@@ -32,16 +32,95 @@ struct clic_config {
3232 mem_addr_t base ;
3333};
3434
35+ struct pmp_stack_guard_key_t {
36+ unsigned long mstatus ;
37+ unsigned int irq_key ;
38+ };
39+
40+ /*
41+ * M-mode CLIC memory-mapped registers are accessible only in M-mode.
42+ * Temporarily disable the PMP stack guard (set mstatus.MPRV = 0) to configure
43+ * CLIC registers, then restore the PMP stack guard using these functions.
44+ */
45+ static ALWAYS_INLINE void disable_pmp_stack_guard (struct pmp_stack_guard_key_t * key )
46+ {
47+ if (IS_ENABLED (CONFIG_PMP_STACK_GUARD )) {
48+ key -> irq_key = irq_lock ();
49+ key -> mstatus = csr_read_clear (mstatus , MSTATUS_MPRV );
50+ } else {
51+ ARG_UNUSED (key );
52+ }
53+ }
54+
55+ static ALWAYS_INLINE void restore_pmp_stack_guard (struct pmp_stack_guard_key_t key )
56+ {
57+ if (IS_ENABLED (CONFIG_PMP_STACK_GUARD )) {
58+ csr_write (mstatus , key .mstatus );
59+ irq_unlock (key .irq_key );
60+ } else {
61+ ARG_UNUSED (key );
62+ }
63+ }
64+
65+ static ALWAYS_INLINE void write_clic32 (const struct device * dev , uint32_t offset , uint32_t value )
66+ {
67+ const struct clic_config * config = dev -> config ;
68+ mem_addr_t reg_addr = config -> base + offset ;
69+ struct pmp_stack_guard_key_t key ;
70+
71+ disable_pmp_stack_guard (& key );
72+ sys_write32 (value , reg_addr );
73+ restore_pmp_stack_guard (key );
74+ }
75+
76+ static ALWAYS_INLINE uint32_t read_clic32 (const struct device * dev , uint32_t offset )
77+ {
78+ const struct clic_config * config = dev -> config ;
79+ mem_addr_t reg_addr = config -> base + offset ;
80+ struct pmp_stack_guard_key_t key ;
81+ uint32_t reg ;
82+
83+ disable_pmp_stack_guard (& key );
84+ reg = sys_read32 (reg_addr );
85+ restore_pmp_stack_guard (key );
86+
87+ return reg ;
88+ }
89+
90+ static ALWAYS_INLINE void write_clic8 (const struct device * dev , uint32_t offset , uint8_t value )
91+ {
92+ const struct clic_config * config = dev -> config ;
93+ mem_addr_t reg_addr = config -> base + offset ;
94+ struct pmp_stack_guard_key_t key ;
95+
96+ disable_pmp_stack_guard (& key );
97+ sys_write8 (value , reg_addr );
98+ restore_pmp_stack_guard (key );
99+ }
100+
101+ static ALWAYS_INLINE uint8_t read_clic8 (const struct device * dev , uint32_t offset )
102+ {
103+ const struct clic_config * config = dev -> config ;
104+ mem_addr_t reg_addr = config -> base + offset ;
105+ struct pmp_stack_guard_key_t key ;
106+ uint32_t reg ;
107+
108+ disable_pmp_stack_guard (& key );
109+ reg = sys_read8 (reg_addr );
110+ restore_pmp_stack_guard (key );
111+
112+ return reg ;
113+ }
114+
35115/**
36116 * @brief Enable interrupt
37117 */
38118void riscv_clic_irq_enable (uint32_t irq )
39119{
40120 const struct device * dev = DEVICE_DT_INST_GET (0 );
41- const struct clic_config * config = dev -> config ;
42121 union CLICINTIE clicintie = {.b = {.IE = 0x1 }};
43122
44- sys_write8 ( clicintie . w , config -> base + CLIC_INTIE (irq ));
123+ write_clic8 ( dev , CLIC_INTIE (irq ), clicintie . w );
45124}
46125
47126/**
@@ -50,10 +129,9 @@ void riscv_clic_irq_enable(uint32_t irq)
50129void riscv_clic_irq_disable (uint32_t irq )
51130{
52131 const struct device * dev = DEVICE_DT_INST_GET (0 );
53- const struct clic_config * config = dev -> config ;
54132 union CLICINTIE clicintie = {.b = {.IE = 0x0 }};
55133
56- sys_write8 ( clicintie . w , config -> base + CLIC_INTIE (irq ));
134+ write_clic8 ( dev , CLIC_INTIE (irq ), clicintie . w );
57135}
58136
59137/**
@@ -62,8 +140,7 @@ void riscv_clic_irq_disable(uint32_t irq)
62140int riscv_clic_irq_is_enabled (uint32_t irq )
63141{
64142 const struct device * dev = DEVICE_DT_INST_GET (0 );
65- const struct clic_config * config = dev -> config ;
66- union CLICINTIE clicintie = {.w = sys_read8 (config -> base + CLIC_INTIE (irq ))};
143+ union CLICINTIE clicintie = {.w = read_clic8 (dev , CLIC_INTIE (irq ))};
67144
68145 return clicintie .b .IE ;
69146}
@@ -74,7 +151,6 @@ int riscv_clic_irq_is_enabled(uint32_t irq)
74151void riscv_clic_irq_priority_set (uint32_t irq , uint32_t pri , uint32_t flags )
75152{
76153 const struct device * dev = DEVICE_DT_INST_GET (0 );
77- const struct clic_config * config = dev -> config ;
78154 const struct clic_data * data = dev -> data ;
79155
80156 /*
@@ -96,12 +172,12 @@ void riscv_clic_irq_priority_set(uint32_t irq, uint32_t pri, uint32_t flags)
96172 (MIN (pri , max_level ) << (8U - data -> nlbits )) |
97173 BIT_MASK (8U - data -> intctlbits );
98174
99- sys_write8 ( intctrl , config -> base + CLIC_INTCTRL (irq ));
175+ write_clic8 ( dev , CLIC_INTCTRL (irq ), intctrl );
100176
101177 /* Set the IRQ operates in machine mode, non-vectoring and the trigger type. */
102178 union CLICINTATTR clicattr = {.b = {.mode = 0x3 , .shv = 0x0 , .trg = flags & BIT_MASK (3 )}};
103179
104- sys_write8 ( clicattr . w , config -> base + CLIC_INTATTR (irq ));
180+ write_clic8 ( dev , CLIC_INTATTR (irq ), clicattr . w );
105181}
106182
107183/**
@@ -110,12 +186,11 @@ void riscv_clic_irq_priority_set(uint32_t irq, uint32_t pri, uint32_t flags)
110186void riscv_clic_irq_vector_set (uint32_t irq )
111187{
112188 const struct device * dev = DEVICE_DT_INST_GET (0 );
113- const struct clic_config * config = dev -> config ;
114- union CLICINTATTR clicattr = {.w = sys_read8 (config -> base + CLIC_INTATTR (irq ))};
189+ union CLICINTATTR clicattr = {.w = read_clic8 (dev , CLIC_INTATTR (irq ))};
115190
116191 /* Set Selective Hardware Vectoring. */
117192 clicattr .b .shv = 1 ;
118- sys_write8 ( clicattr . w , config -> base + CLIC_INTATTR (irq ));
193+ write_clic8 ( dev , CLIC_INTATTR (irq ), clicattr . w );
119194}
120195
121196/**
@@ -124,25 +199,23 @@ void riscv_clic_irq_vector_set(uint32_t irq)
124199void riscv_clic_irq_set_pending (uint32_t irq )
125200{
126201 const struct device * dev = DEVICE_DT_INST_GET (0 );
127- const struct clic_config * config = dev -> config ;
128202 union CLICINTIP clicintip = {.b = {.IP = 0x1 }};
129203
130- sys_write8 ( clicintip . w , config -> base + CLIC_INTIP (irq ));
204+ write_clic8 ( dev , CLIC_INTIP (irq ), clicintip . w );
131205}
132206
133207static int clic_init (const struct device * dev )
134208{
135- const struct clic_config * config = dev -> config ;
136209 struct clic_data * data = dev -> data ;
137210
138211 if (IS_ENABLED (CONFIG_NUCLEI_ECLIC )) {
139212 /* Configure the interrupt level threshold. */
140213 union CLICMTH clicmth = {.b = {.mth = 0x0 }};
141214
142- sys_write32 ( clicmth . qw , config -> base + CLIC_MTH );
215+ write_clic32 ( dev , CLIC_MTH , clicmth . qw );
143216
144217 /* Detect the number of bits for the clicintctl register. */
145- union CLICINFO clicinfo = {.qw = sys_read32 ( config -> base + CLIC_INFO )};
218+ union CLICINFO clicinfo = {.qw = read_clic32 ( dev , CLIC_INFO )};
146219
147220 data -> intctlbits = clicinfo .b .intctlbits ;
148221
@@ -151,18 +224,18 @@ static int clic_init(const struct device *dev)
151224 }
152225
153226 /* Configure the number of bits assigned to interrupt levels. */
154- union CLICCFG cliccfg = {.qw = sys_read32 ( config -> base + CLIC_CFG )};
227+ union CLICCFG cliccfg = {.qw = read_clic32 ( dev , CLIC_CFG )};
155228
156229 cliccfg .w .nlbits = data -> nlbits ;
157- sys_write32 ( cliccfg . qw , config -> base + CLIC_CFG );
230+ write_clic32 ( dev , CLIC_CFG , cliccfg . qw );
158231 } else {
159232 /* Configure the interrupt level threshold by CSR mintthresh. */
160233 csr_write (CSR_MINTTHRESH , 0x0 );
161234 }
162235
163236 /* Reset all interrupt control register */
164237 for (int i = 0 ; i < CONFIG_NUM_IRQS ; i ++ ) {
165- sys_write32 ( 0 , config -> base + CLIC_CTRL (i ));
238+ write_clic32 ( dev , CLIC_CTRL (i ), 0 );
166239 }
167240
168241 return 0 ;
0 commit comments