Skip to content

Commit 6d60b6e

Browse files
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 <[email protected]>
1 parent 7db91e5 commit 6d60b6e

File tree

9 files changed

+566
-0
lines changed

9 files changed

+566
-0
lines changed

arch/riscv/include/asm/delay.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (C) 2009 Chen Liqin <[email protected]>
3+
* Copyright (C) 2016 Regents of the University of California
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU General Public License
7+
* as published by the Free Software Foundation, version 2.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*/
14+
15+
#ifndef _ASM_RISCV_DELAY_H
16+
#define _ASM_RISCV_DELAY_H
17+
18+
extern unsigned long riscv_timebase;
19+
20+
#define udelay udelay
21+
extern void udelay(unsigned long usecs);
22+
23+
#define ndelay ndelay
24+
extern void ndelay(unsigned long nsecs);
25+
26+
extern void __delay(unsigned long cycles);
27+
28+
#endif /* _ASM_RISCV_DELAY_H */
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (C) 2003-2004 Hewlett-Packard Co
3+
* David Mosberger-Tang <[email protected]>
4+
* Copyright (C) 2012 ARM Ltd.
5+
* Copyright (C) 2016 SiFive, Inc.
6+
*
7+
* This program is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License version 2 as
9+
* published by the Free Software Foundation.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
#ifndef __ASM_RISCV_DMA_MAPPING_H
20+
#define __ASM_RISCV_DMA_MAPPING_H
21+
22+
/* Use ops->dma_mapping_error (if it exists) or assume success */
23+
// #undef DMA_ERROR_CODE
24+
25+
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
26+
{
27+
return &dma_noop_ops;
28+
}
29+
30+
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
31+
{
32+
if (!dev->dma_mask)
33+
return false;
34+
35+
return addr + size - 1 <= *dev->dma_mask;
36+
}
37+
38+
#endif /* __ASM_RISCV_DMA_MAPPING_H */

arch/riscv/include/asm/irq.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (C) 2012 Regents of the University of California
3+
* Copyright (C) 2017 SiFive
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU General Public License
7+
* as published by the Free Software Foundation, version 2.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*/
14+
15+
#ifndef _ASM_RISCV_IRQ_H
16+
#define _ASM_RISCV_IRQ_H
17+
18+
#define NR_IRQS 0
19+
20+
#define INTERRUPT_CAUSE_SOFTWARE 1
21+
#define INTERRUPT_CAUSE_TIMER 5
22+
#define INTERRUPT_CAUSE_EXTERNAL 9
23+
24+
void riscv_timer_interrupt(void);
25+
26+
#include <asm-generic/irq.h>
27+
28+
#endif /* _ASM_RISCV_IRQ_H */

arch/riscv/include/asm/irqflags.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (C) 2012 Regents of the University of California
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, version 2.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*/
13+
14+
15+
#ifndef _ASM_RISCV_IRQFLAGS_H
16+
#define _ASM_RISCV_IRQFLAGS_H
17+
18+
#include <asm/processor.h>
19+
#include <asm/csr.h>
20+
21+
/* read interrupt enabled status */
22+
static inline unsigned long arch_local_save_flags(void)
23+
{
24+
return csr_read(sstatus);
25+
}
26+
27+
/* unconditionally enable interrupts */
28+
static inline void arch_local_irq_enable(void)
29+
{
30+
csr_set(sstatus, SR_IE);
31+
}
32+
33+
/* unconditionally disable interrupts */
34+
static inline void arch_local_irq_disable(void)
35+
{
36+
csr_clear(sstatus, SR_IE);
37+
}
38+
39+
/* get status and disable interrupts */
40+
static inline unsigned long arch_local_irq_save(void)
41+
{
42+
return csr_read_clear(sstatus, SR_IE);
43+
}
44+
45+
/* test flags */
46+
static inline int arch_irqs_disabled_flags(unsigned long flags)
47+
{
48+
return !(flags & SR_IE);
49+
}
50+
51+
/* test hardware interrupt enable bit */
52+
static inline int arch_irqs_disabled(void)
53+
{
54+
return arch_irqs_disabled_flags(arch_local_save_flags());
55+
}
56+
57+
/* set interrupt enabled status */
58+
static inline void arch_local_irq_restore(unsigned long flags)
59+
{
60+
csr_set(sstatus, flags & SR_IE);
61+
}
62+
63+
#endif /* _ASM_RISCV_IRQFLAGS_H */

arch/riscv/include/asm/pci.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (C) 2016 SiFive
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, version 2.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*/
13+
14+
#ifndef __ASM_RISCV_PCI_H
15+
#define __ASM_RISCV_PCI_H
16+
17+
#include <linux/types.h>
18+
#include <linux/slab.h>
19+
#include <linux/dma-mapping.h>
20+
21+
#include <asm/io.h>
22+
23+
#define PCIBIOS_MIN_IO 0
24+
#define PCIBIOS_MIN_MEM 0
25+
26+
/* RISC-V shim does not initialize PCI bus */
27+
#define pcibios_assign_all_busses() 1
28+
29+
/* We do not have an IOMMU */
30+
#define PCI_DMA_BUS_IS_PHYS 1
31+
32+
extern int isa_dma_bridge_buggy;
33+
34+
#ifdef CONFIG_PCI
35+
static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
36+
{
37+
/* no legacy IRQ on risc-v */
38+
return -ENODEV;
39+
}
40+
41+
static inline int pci_proc_domain(struct pci_bus *bus)
42+
{
43+
/* always show the domain in /proc */
44+
return 1;
45+
}
46+
#endif /* CONFIG_PCI */
47+
48+
#endif /* __ASM_PCI_H */

arch/riscv/include/asm/sbi.h

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright (C) 2015 Regents of the University of California
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, version 2.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*/
13+
14+
#ifndef _ASM_RISCV_SBI_H
15+
#define _ASM_RISCV_SBI_H
16+
17+
#include <linux/types.h>
18+
19+
#define SBI_SET_TIMER 0
20+
#define SBI_CONSOLE_PUTCHAR 1
21+
#define SBI_CONSOLE_GETCHAR 2
22+
#define SBI_CLEAR_IPI 3
23+
#define SBI_SEND_IPI 4
24+
#define SBI_REMOTE_FENCE_I 5
25+
#define SBI_REMOTE_SFENCE_VMA 6
26+
#define SBI_REMOTE_SFENCE_VMA_ASID 7
27+
#define SBI_SHUTDOWN 8
28+
29+
#define SBI_CALL(which, arg0, arg1, arg2) ({ \
30+
register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); \
31+
register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); \
32+
register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); \
33+
register uintptr_t a7 asm ("a7") = (uintptr_t)(which); \
34+
asm volatile ("ecall" \
35+
: "+r" (a0) \
36+
: "r" (a1), "r" (a2), "r" (a7) \
37+
: "memory"); \
38+
a0; \
39+
})
40+
41+
/* Lazy implementations until SBI is finalized */
42+
#define SBI_CALL_0(which) SBI_CALL(which, 0, 0, 0)
43+
#define SBI_CALL_1(which, arg0) SBI_CALL(which, arg0, 0, 0)
44+
#define SBI_CALL_2(which, arg0, arg1) SBI_CALL(which, arg0, arg1, 0)
45+
46+
static inline void sbi_console_putchar(int ch)
47+
{
48+
SBI_CALL_1(SBI_CONSOLE_PUTCHAR, ch);
49+
}
50+
51+
static inline int sbi_console_getchar(void)
52+
{
53+
return SBI_CALL_0(SBI_CONSOLE_GETCHAR);
54+
}
55+
56+
static inline void sbi_set_timer(uint64_t stime_value)
57+
{
58+
#if __riscv_xlen == 32
59+
SBI_CALL_2(SBI_SET_TIMER, stime_value, stime_value >> 32);
60+
#else
61+
SBI_CALL_1(SBI_SET_TIMER, stime_value);
62+
#endif
63+
}
64+
65+
static inline void sbi_shutdown(void)
66+
{
67+
SBI_CALL_0(SBI_SHUTDOWN);
68+
}
69+
70+
static inline void sbi_clear_ipi(void)
71+
{
72+
SBI_CALL_0(SBI_CLEAR_IPI);
73+
}
74+
75+
static inline void sbi_send_ipi(const unsigned long *hart_mask)
76+
{
77+
SBI_CALL_1(SBI_SEND_IPI, hart_mask);
78+
}
79+
80+
static inline void sbi_remote_fence_i(const unsigned long *hart_mask)
81+
{
82+
SBI_CALL_1(SBI_REMOTE_FENCE_I, hart_mask);
83+
}
84+
85+
static inline void sbi_remote_sfence_vma(const unsigned long *hart_mask,
86+
unsigned long start,
87+
unsigned long size)
88+
{
89+
SBI_CALL_1(SBI_REMOTE_SFENCE_VMA, hart_mask);
90+
}
91+
92+
static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
93+
unsigned long start,
94+
unsigned long size,
95+
unsigned long asid)
96+
{
97+
SBI_CALL_1(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask);
98+
}
99+
100+
#endif

arch/riscv/include/asm/timex.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (C) 2012 Regents of the University of California
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, version 2.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*/
13+
14+
#ifndef _ASM_RISCV_TIMEX_H
15+
#define _ASM_RISCV_TIMEX_H
16+
17+
#include <asm/param.h>
18+
19+
typedef unsigned long cycles_t;
20+
21+
static inline cycles_t get_cycles(void)
22+
{
23+
cycles_t n;
24+
25+
__asm__ __volatile__ (
26+
"rdtime %0"
27+
: "=r" (n));
28+
return n;
29+
}
30+
31+
#ifdef CONFIG_64BIT
32+
static inline uint64_t get_cycles64(void)
33+
{
34+
return get_cycles();
35+
}
36+
#else
37+
static inline uint64_t get_cycles64(void)
38+
{
39+
u32 lo, hi, tmp;
40+
__asm__ __volatile__ (
41+
"1:\n"
42+
"rdtimeh %0\n"
43+
"rdtime %1\n"
44+
"rdtimeh %2\n"
45+
"bne %0, %2, 1b"
46+
: "=&r" (hi), "=&r" (lo), "=&r" (tmp));
47+
return ((u64)hi << 32) | lo;
48+
}
49+
#endif
50+
51+
#define ARCH_HAS_READ_CURRENT_TIMER
52+
53+
static inline int read_current_timer(unsigned long *timer_val)
54+
{
55+
*timer_val = get_cycles();
56+
return 0;
57+
}
58+
59+
#endif /* _ASM_RISCV_TIMEX_H */

0 commit comments

Comments
 (0)