@@ -32,16 +32,95 @@ struct clic_config {
32
32
mem_addr_t base ;
33
33
};
34
34
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
+
35
115
/**
36
116
* @brief Enable interrupt
37
117
*/
38
118
void riscv_clic_irq_enable (uint32_t irq )
39
119
{
40
120
const struct device * dev = DEVICE_DT_INST_GET (0 );
41
- const struct clic_config * config = dev -> config ;
42
121
union CLICINTIE clicintie = {.b = {.IE = 0x1 }};
43
122
44
- sys_write8 ( clicintie . w , config -> base + CLIC_INTIE (irq ));
123
+ write_clic8 ( dev , CLIC_INTIE (irq ), clicintie . w );
45
124
}
46
125
47
126
/**
@@ -50,10 +129,9 @@ void riscv_clic_irq_enable(uint32_t irq)
50
129
void riscv_clic_irq_disable (uint32_t irq )
51
130
{
52
131
const struct device * dev = DEVICE_DT_INST_GET (0 );
53
- const struct clic_config * config = dev -> config ;
54
132
union CLICINTIE clicintie = {.b = {.IE = 0x0 }};
55
133
56
- sys_write8 ( clicintie . w , config -> base + CLIC_INTIE (irq ));
134
+ write_clic8 ( dev , CLIC_INTIE (irq ), clicintie . w );
57
135
}
58
136
59
137
/**
@@ -62,8 +140,7 @@ void riscv_clic_irq_disable(uint32_t irq)
62
140
int riscv_clic_irq_is_enabled (uint32_t irq )
63
141
{
64
142
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 ))};
67
144
68
145
return clicintie .b .IE ;
69
146
}
@@ -74,7 +151,6 @@ int riscv_clic_irq_is_enabled(uint32_t irq)
74
151
void riscv_clic_irq_priority_set (uint32_t irq , uint32_t pri , uint32_t flags )
75
152
{
76
153
const struct device * dev = DEVICE_DT_INST_GET (0 );
77
- const struct clic_config * config = dev -> config ;
78
154
const struct clic_data * data = dev -> data ;
79
155
80
156
/*
@@ -96,12 +172,12 @@ void riscv_clic_irq_priority_set(uint32_t irq, uint32_t pri, uint32_t flags)
96
172
(MIN (pri , max_level ) << (8U - data -> nlbits )) |
97
173
BIT_MASK (8U - data -> intctlbits );
98
174
99
- sys_write8 ( intctrl , config -> base + CLIC_INTCTRL (irq ));
175
+ write_clic8 ( dev , CLIC_INTCTRL (irq ), intctrl );
100
176
101
177
/* Set the IRQ operates in machine mode, non-vectoring and the trigger type. */
102
178
union CLICINTATTR clicattr = {.b = {.mode = 0x3 , .shv = 0x0 , .trg = flags & BIT_MASK (3 )}};
103
179
104
- sys_write8 ( clicattr . w , config -> base + CLIC_INTATTR (irq ));
180
+ write_clic8 ( dev , CLIC_INTATTR (irq ), clicattr . w );
105
181
}
106
182
107
183
/**
@@ -110,12 +186,11 @@ void riscv_clic_irq_priority_set(uint32_t irq, uint32_t pri, uint32_t flags)
110
186
void riscv_clic_irq_vector_set (uint32_t irq )
111
187
{
112
188
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 ))};
115
190
116
191
/* Set Selective Hardware Vectoring. */
117
192
clicattr .b .shv = 1 ;
118
- sys_write8 ( clicattr . w , config -> base + CLIC_INTATTR (irq ));
193
+ write_clic8 ( dev , CLIC_INTATTR (irq ), clicattr . w );
119
194
}
120
195
121
196
/**
@@ -124,25 +199,23 @@ void riscv_clic_irq_vector_set(uint32_t irq)
124
199
void riscv_clic_irq_set_pending (uint32_t irq )
125
200
{
126
201
const struct device * dev = DEVICE_DT_INST_GET (0 );
127
- const struct clic_config * config = dev -> config ;
128
202
union CLICINTIP clicintip = {.b = {.IP = 0x1 }};
129
203
130
- sys_write8 ( clicintip . w , config -> base + CLIC_INTIP (irq ));
204
+ write_clic8 ( dev , CLIC_INTIP (irq ), clicintip . w );
131
205
}
132
206
133
207
static int clic_init (const struct device * dev )
134
208
{
135
- const struct clic_config * config = dev -> config ;
136
209
struct clic_data * data = dev -> data ;
137
210
138
211
if (IS_ENABLED (CONFIG_NUCLEI_ECLIC )) {
139
212
/* Configure the interrupt level threshold. */
140
213
union CLICMTH clicmth = {.b = {.mth = 0x0 }};
141
214
142
- sys_write32 ( clicmth . qw , config -> base + CLIC_MTH );
215
+ write_clic32 ( dev , CLIC_MTH , clicmth . qw );
143
216
144
217
/* 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 )};
146
219
147
220
data -> intctlbits = clicinfo .b .intctlbits ;
148
221
@@ -151,18 +224,18 @@ static int clic_init(const struct device *dev)
151
224
}
152
225
153
226
/* 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 )};
155
228
156
229
cliccfg .w .nlbits = data -> nlbits ;
157
- sys_write32 ( cliccfg . qw , config -> base + CLIC_CFG );
230
+ write_clic32 ( dev , CLIC_CFG , cliccfg . qw );
158
231
} else {
159
232
/* Configure the interrupt level threshold by CSR mintthresh. */
160
233
csr_write (CSR_MINTTHRESH , 0x0 );
161
234
}
162
235
163
236
/* Reset all interrupt control register */
164
237
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 );
166
239
}
167
240
168
241
return 0 ;
0 commit comments