1 /*
2 * Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief interrupt management code for riscv SOCs supporting the riscv
10 privileged architecture specification
11 */
12 #include <zephyr/irq.h>
13 #include <zephyr/irq_multilevel.h>
14
15 #include <zephyr/drivers/interrupt_controller/riscv_clic.h>
16 #include <zephyr/drivers/interrupt_controller/riscv_plic.h>
17
18 #if defined(CONFIG_RISCV_HAS_CLIC)
19
arch_irq_enable(unsigned int irq)20 void arch_irq_enable(unsigned int irq)
21 {
22 riscv_clic_irq_enable(irq);
23 }
24
arch_irq_disable(unsigned int irq)25 void arch_irq_disable(unsigned int irq)
26 {
27 riscv_clic_irq_disable(irq);
28 }
29
arch_irq_is_enabled(unsigned int irq)30 int arch_irq_is_enabled(unsigned int irq)
31 {
32 return riscv_clic_irq_is_enabled(irq);
33 }
34
z_riscv_irq_priority_set(unsigned int irq,unsigned int prio,uint32_t flags)35 void z_riscv_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
36 {
37 riscv_clic_irq_priority_set(irq, prio, flags);
38 }
39
z_riscv_irq_vector_set(unsigned int irq)40 void z_riscv_irq_vector_set(unsigned int irq)
41 {
42 #if defined(CONFIG_CLIC_SMCLICSHV_EXT)
43 riscv_clic_irq_vector_set(irq);
44 #else
45 ARG_UNUSED(irq);
46 #endif
47 }
48
49 #else /* PLIC + HLINT/CLINT or HLINT/CLINT only */
50
arch_irq_enable(unsigned int irq)51 void arch_irq_enable(unsigned int irq)
52 {
53 uint32_t mie;
54
55 #if defined(CONFIG_RISCV_HAS_PLIC)
56 unsigned int level = irq_get_level(irq);
57
58 if (level == 2) {
59 riscv_plic_irq_enable(irq);
60 return;
61 }
62 #endif
63
64 /*
65 * CSR mie register is updated using atomic instruction csrrs
66 * (atomic read and set bits in CSR register)
67 */
68 mie = csr_read_set(mie, 1 << irq);
69 }
70
arch_irq_disable(unsigned int irq)71 void arch_irq_disable(unsigned int irq)
72 {
73 uint32_t mie;
74
75 #if defined(CONFIG_RISCV_HAS_PLIC)
76 unsigned int level = irq_get_level(irq);
77
78 if (level == 2) {
79 riscv_plic_irq_disable(irq);
80 return;
81 }
82 #endif
83
84 /*
85 * Use atomic instruction csrrc to disable device interrupt in mie CSR.
86 * (atomic read and clear bits in CSR register)
87 */
88 mie = csr_read_clear(mie, 1 << irq);
89 }
90
arch_irq_is_enabled(unsigned int irq)91 int arch_irq_is_enabled(unsigned int irq)
92 {
93 uint32_t mie;
94
95 #if defined(CONFIG_RISCV_HAS_PLIC)
96 unsigned int level = irq_get_level(irq);
97
98 if (level == 2) {
99 return riscv_plic_irq_is_enabled(irq);
100 }
101 #endif
102
103 mie = csr_read(mie);
104
105 return !!(mie & (1 << irq));
106 }
107
108 #if defined(CONFIG_RISCV_HAS_PLIC)
z_riscv_irq_priority_set(unsigned int irq,unsigned int prio,uint32_t flags)109 void z_riscv_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
110 {
111 unsigned int level = irq_get_level(irq);
112
113 if (level == 2) {
114 riscv_plic_set_priority(irq, prio);
115 }
116 }
117 #endif /* CONFIG_RISCV_HAS_PLIC */
118 #endif /* CONFIG_RISCV_HAS_CLIC */
119
120 #if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
soc_interrupt_init(void)121 __weak void soc_interrupt_init(void)
122 {
123 /* ensure that all interrupts are disabled */
124 (void)arch_irq_lock();
125
126 csr_write(mie, 0);
127 csr_write(mip, 0);
128 }
129 #endif
130