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 <irq.h>
13 
arch_irq_enable(unsigned int irq)14 void arch_irq_enable(unsigned int irq)
15 {
16 	uint32_t mie;
17 
18 #if defined(CONFIG_RISCV_HAS_PLIC)
19 	unsigned int level = irq_get_level(irq);
20 
21 	if (level == 2) {
22 		irq = irq_from_level_2(irq);
23 		riscv_plic_irq_enable(irq);
24 		return;
25 	}
26 #endif
27 
28 	/*
29 	 * CSR mie register is updated using atomic instruction csrrs
30 	 * (atomic read and set bits in CSR register)
31 	 */
32 	__asm__ volatile ("csrrs %0, mie, %1\n"
33 			  : "=r" (mie)
34 			  : "r" (1 << irq));
35 }
36 
arch_irq_disable(unsigned int irq)37 void arch_irq_disable(unsigned int irq)
38 {
39 	uint32_t mie;
40 
41 #if defined(CONFIG_RISCV_HAS_PLIC)
42 	unsigned int level = irq_get_level(irq);
43 
44 	if (level == 2) {
45 		irq = irq_from_level_2(irq);
46 		riscv_plic_irq_disable(irq);
47 		return;
48 	}
49 #endif
50 
51 	/*
52 	 * Use atomic instruction csrrc to disable device interrupt in mie CSR.
53 	 * (atomic read and clear bits in CSR register)
54 	 */
55 	__asm__ volatile ("csrrc %0, mie, %1\n"
56 			  : "=r" (mie)
57 			  : "r" (1 << irq));
58 };
59 
arch_irq_priority_set(unsigned int irq,unsigned int prio)60 void arch_irq_priority_set(unsigned int irq, unsigned int prio)
61 {
62 #if defined(CONFIG_RISCV_HAS_PLIC)
63 	unsigned int level = irq_get_level(irq);
64 
65 	if (level == 2) {
66 		irq = irq_from_level_2(irq);
67 		riscv_plic_set_priority(irq, prio);
68 	}
69 #endif
70 
71 	return ;
72 }
73 
arch_irq_is_enabled(unsigned int irq)74 int arch_irq_is_enabled(unsigned int irq)
75 {
76 	uint32_t mie;
77 
78 #if defined(CONFIG_RISCV_HAS_PLIC)
79 	unsigned int level = irq_get_level(irq);
80 
81 	if (level == 2) {
82 		irq = irq_from_level_2(irq);
83 		return riscv_plic_irq_is_enabled(irq);
84 	}
85 #endif
86 
87 	__asm__ volatile ("csrr %0, mie" : "=r" (mie));
88 
89 	return !!(mie & (1 << irq));
90 }
91 
92 #if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
soc_interrupt_init(void)93 __weak void soc_interrupt_init(void)
94 {
95 	/* ensure that all interrupts are disabled */
96 	(void)irq_lock();
97 
98 	__asm__ volatile ("csrwi mie, 0\n"
99 			  "csrwi mip, 0\n");
100 }
101 #endif
102