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