diff options
author | Palmer Dabbelt <palmer@dabbelt.com> | 2017-07-10 18:05:09 -0700 |
---|---|---|
committer | Palmer Dabbelt <palmer@dabbelt.com> | 2017-09-26 15:26:47 -0700 |
commit | 6d60b6ee0c9777b92c47f6dc8aad1dd90612e4fa (patch) | |
tree | 759b45dbcebd1700f2f9df4deb0513ba54da36c7 /arch/riscv/include | |
parent | 7db91e57a0acde126a162ababfb1e0ab190130cb (diff) |
RISC-V: Device, timer, IRQs, and the SBI
This patch contains code that interfaces with devices that are mandated
by the RISC-V supervisor specification and that don't have explicit
drivers anywhere else in the tree. This includes the staticly defined
interrupts, the CSR-mapped timer, and virtualized SBI devices.
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
Diffstat (limited to 'arch/riscv/include')
-rw-r--r-- | arch/riscv/include/asm/delay.h | 28 | ||||
-rw-r--r-- | arch/riscv/include/asm/dma-mapping.h | 38 | ||||
-rw-r--r-- | arch/riscv/include/asm/irq.h | 28 | ||||
-rw-r--r-- | arch/riscv/include/asm/irqflags.h | 63 | ||||
-rw-r--r-- | arch/riscv/include/asm/pci.h | 48 | ||||
-rw-r--r-- | arch/riscv/include/asm/sbi.h | 100 | ||||
-rw-r--r-- | arch/riscv/include/asm/timex.h | 59 |
7 files changed, 364 insertions, 0 deletions
diff --git a/arch/riscv/include/asm/delay.h b/arch/riscv/include/asm/delay.h new file mode 100644 index 000000000000..cbb0c9eb96cb --- /dev/null +++ b/arch/riscv/include/asm/delay.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 Chen Liqin <liqin.chen@sunplusct.com> + * Copyright (C) 2016 Regents of the University of California + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _ASM_RISCV_DELAY_H +#define _ASM_RISCV_DELAY_H + +extern unsigned long riscv_timebase; + +#define udelay udelay +extern void udelay(unsigned long usecs); + +#define ndelay ndelay +extern void ndelay(unsigned long nsecs); + +extern void __delay(unsigned long cycles); + +#endif /* _ASM_RISCV_DELAY_H */ diff --git a/arch/riscv/include/asm/dma-mapping.h b/arch/riscv/include/asm/dma-mapping.h new file mode 100644 index 000000000000..3eec1000196d --- /dev/null +++ b/arch/riscv/include/asm/dma-mapping.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2003-2004 Hewlett-Packard Co + * David Mosberger-Tang <davidm@hpl.hp.com> + * Copyright (C) 2012 ARM Ltd. + * Copyright (C) 2016 SiFive, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef __ASM_RISCV_DMA_MAPPING_H +#define __ASM_RISCV_DMA_MAPPING_H + +/* Use ops->dma_mapping_error (if it exists) or assume success */ +// #undef DMA_ERROR_CODE + +static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) +{ + return &dma_noop_ops; +} + +static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) +{ + if (!dev->dma_mask) + return false; + + return addr + size - 1 <= *dev->dma_mask; +} + +#endif /* __ASM_RISCV_DMA_MAPPING_H */ diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h new file mode 100644 index 000000000000..4dee9d4c13c0 --- /dev/null +++ b/arch/riscv/include/asm/irq.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 Regents of the University of California + * Copyright (C) 2017 SiFive + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _ASM_RISCV_IRQ_H +#define _ASM_RISCV_IRQ_H + +#define NR_IRQS 0 + +#define INTERRUPT_CAUSE_SOFTWARE 1 +#define INTERRUPT_CAUSE_TIMER 5 +#define INTERRUPT_CAUSE_EXTERNAL 9 + +void riscv_timer_interrupt(void); + +#include <asm-generic/irq.h> + +#endif /* _ASM_RISCV_IRQ_H */ diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h new file mode 100644 index 000000000000..6fdc860d7f84 --- /dev/null +++ b/arch/riscv/include/asm/irqflags.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2012 Regents of the University of California + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#ifndef _ASM_RISCV_IRQFLAGS_H +#define _ASM_RISCV_IRQFLAGS_H + +#include <asm/processor.h> +#include <asm/csr.h> + +/* read interrupt enabled status */ +static inline unsigned long arch_local_save_flags(void) +{ + return csr_read(sstatus); +} + +/* unconditionally enable interrupts */ +static inline void arch_local_irq_enable(void) +{ + csr_set(sstatus, SR_IE); +} + +/* unconditionally disable interrupts */ +static inline void arch_local_irq_disable(void) +{ + csr_clear(sstatus, SR_IE); +} + +/* get status and disable interrupts */ +static inline unsigned long arch_local_irq_save(void) +{ + return csr_read_clear(sstatus, SR_IE); +} + +/* test flags */ +static inline int arch_irqs_disabled_flags(unsigned long flags) +{ + return !(flags & SR_IE); +} + +/* test hardware interrupt enable bit */ +static inline int arch_irqs_disabled(void) +{ + return arch_irqs_disabled_flags(arch_local_save_flags()); +} + +/* set interrupt enabled status */ +static inline void arch_local_irq_restore(unsigned long flags) +{ + csr_set(sstatus, flags & SR_IE); +} + +#endif /* _ASM_RISCV_IRQFLAGS_H */ diff --git a/arch/riscv/include/asm/pci.h b/arch/riscv/include/asm/pci.h new file mode 100644 index 000000000000..0f2fc9ef20fc --- /dev/null +++ b/arch/riscv/include/asm/pci.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016 SiFive + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ASM_RISCV_PCI_H +#define __ASM_RISCV_PCI_H + +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> + +#include <asm/io.h> + +#define PCIBIOS_MIN_IO 0 +#define PCIBIOS_MIN_MEM 0 + +/* RISC-V shim does not initialize PCI bus */ +#define pcibios_assign_all_busses() 1 + +/* We do not have an IOMMU */ +#define PCI_DMA_BUS_IS_PHYS 1 + +extern int isa_dma_bridge_buggy; + +#ifdef CONFIG_PCI +static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) +{ + /* no legacy IRQ on risc-v */ + return -ENODEV; +} + +static inline int pci_proc_domain(struct pci_bus *bus) +{ + /* always show the domain in /proc */ + return 1; +} +#endif /* CONFIG_PCI */ + +#endif /* __ASM_PCI_H */ diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h new file mode 100644 index 000000000000..b6bb10b92fe2 --- /dev/null +++ b/arch/riscv/include/asm/sbi.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2015 Regents of the University of California + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _ASM_RISCV_SBI_H +#define _ASM_RISCV_SBI_H + +#include <linux/types.h> + +#define SBI_SET_TIMER 0 +#define SBI_CONSOLE_PUTCHAR 1 +#define SBI_CONSOLE_GETCHAR 2 +#define SBI_CLEAR_IPI 3 +#define SBI_SEND_IPI 4 +#define SBI_REMOTE_FENCE_I 5 +#define SBI_REMOTE_SFENCE_VMA 6 +#define SBI_REMOTE_SFENCE_VMA_ASID 7 +#define SBI_SHUTDOWN 8 + +#define SBI_CALL(which, arg0, arg1, arg2) ({ \ + register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); \ + register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); \ + register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); \ + register uintptr_t a7 asm ("a7") = (uintptr_t)(which); \ + asm volatile ("ecall" \ + : "+r" (a0) \ + : "r" (a1), "r" (a2), "r" (a7) \ + : "memory"); \ + a0; \ +}) + +/* Lazy implementations until SBI is finalized */ +#define SBI_CALL_0(which) SBI_CALL(which, 0, 0, 0) +#define SBI_CALL_1(which, arg0) SBI_CALL(which, arg0, 0, 0) +#define SBI_CALL_2(which, arg0, arg1) SBI_CALL(which, arg0, arg1, 0) + +static inline void sbi_console_putchar(int ch) +{ + SBI_CALL_1(SBI_CONSOLE_PUTCHAR, ch); +} + +static inline int sbi_console_getchar(void) +{ + return SBI_CALL_0(SBI_CONSOLE_GETCHAR); +} + +static inline void sbi_set_timer(uint64_t stime_value) +{ +#if __riscv_xlen == 32 + SBI_CALL_2(SBI_SET_TIMER, stime_value, stime_value >> 32); +#else + SBI_CALL_1(SBI_SET_TIMER, stime_value); +#endif +} + +static inline void sbi_shutdown(void) +{ + SBI_CALL_0(SBI_SHUTDOWN); +} + +static inline void sbi_clear_ipi(void) +{ + SBI_CALL_0(SBI_CLEAR_IPI); +} + +static inline void sbi_send_ipi(const unsigned long *hart_mask) +{ + SBI_CALL_1(SBI_SEND_IPI, hart_mask); +} + +static inline void sbi_remote_fence_i(const unsigned long *hart_mask) +{ + SBI_CALL_1(SBI_REMOTE_FENCE_I, hart_mask); +} + +static inline void sbi_remote_sfence_vma(const unsigned long *hart_mask, + unsigned long start, + unsigned long size) +{ + SBI_CALL_1(SBI_REMOTE_SFENCE_VMA, hart_mask); +} + +static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, + unsigned long start, + unsigned long size, + unsigned long asid) +{ + SBI_CALL_1(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask); +} + +#endif diff --git a/arch/riscv/include/asm/timex.h b/arch/riscv/include/asm/timex.h new file mode 100644 index 000000000000..3df4932d8964 --- /dev/null +++ b/arch/riscv/include/asm/timex.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2012 Regents of the University of California + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _ASM_RISCV_TIMEX_H +#define _ASM_RISCV_TIMEX_H + +#include <asm/param.h> + +typedef unsigned long cycles_t; + +static inline cycles_t get_cycles(void) +{ + cycles_t n; + + __asm__ __volatile__ ( + "rdtime %0" + : "=r" (n)); + return n; +} + +#ifdef CONFIG_64BIT +static inline uint64_t get_cycles64(void) +{ + return get_cycles(); +} +#else +static inline uint64_t get_cycles64(void) +{ + u32 lo, hi, tmp; + __asm__ __volatile__ ( + "1:\n" + "rdtimeh %0\n" + "rdtime %1\n" + "rdtimeh %2\n" + "bne %0, %2, 1b" + : "=&r" (hi), "=&r" (lo), "=&r" (tmp)); + return ((u64)hi << 32) | lo; +} +#endif + +#define ARCH_HAS_READ_CURRENT_TIMER + +static inline int read_current_timer(unsigned long *timer_val) +{ + *timer_val = get_cycles(); + return 0; +} + +#endif /* _ASM_RISCV_TIMEX_H */ |