Skip to content

Commit dbd0ac4

Browse files
jimmyzhekartben
authored andcommitted
drivers: interrupt_controller: intc_clic: add indirect access clic reg
Add indirect CSR access to access CLIC register to satisfy the current CLIC spec (Version v0.9, 2024-06-28: Draf). Add CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS for legacy CLIC implementation with memory-mapped CLIC register. Signed-off-by: Jimmy Zheng <[email protected]>
1 parent 46a828e commit dbd0ac4

File tree

3 files changed

+127
-28
lines changed

3 files changed

+127
-28
lines changed

drivers/interrupt_controller/Kconfig.clic

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ config NUCLEI_ECLIC
1717
select CLIC
1818
select CLIC_SMCLICSHV_EXT if RISCV_VECTORED_MODE
1919
select CLIC_SMCLICCONFIG_EXT
20+
select LEGACY_CLIC_MEMORYMAP_ACCESS
2021
help
2122
Interrupt controller for Nuclei SoC core.
2223

@@ -59,6 +60,12 @@ config CLIC_PARAMETER_MNLBITS
5960
This option specifies the number of bits in CLICINTCTLBITS assigned to
6061
encode the interrupt level at machine mode.
6162

63+
config LEGACY_CLIC_MEMORYMAP_ACCESS
64+
bool
65+
help
66+
Enables legacy CLIC, allowing access to CLIC registers through
67+
memory-mapped access instead of indirect CSR access.
68+
6269
config LEGACY_CLIC
6370
bool "Use the legacy clic specification"
6471
depends on RISCV_HAS_CLIC

drivers/interrupt_controller/intc_clic.c

Lines changed: 107 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -117,32 +117,51 @@ static ALWAYS_INLINE uint8_t read_clic8(const struct device *dev, uint32_t offse
117117
*/
118118
void riscv_clic_irq_enable(uint32_t irq)
119119
{
120-
const struct device *dev = DEVICE_DT_INST_GET(0);
121-
union CLICINTIE clicintie = {.b = {.IE = 0x1}};
120+
if (IS_ENABLED(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS)) {
121+
const struct device *dev = DEVICE_DT_INST_GET(0);
122+
union CLICINTIE clicintie = {.b = {.IE = 0x1}};
122123

123-
write_clic8(dev, CLIC_INTIE(irq), clicintie.w);
124+
write_clic8(dev, CLIC_INTIE(irq), clicintie.w);
125+
} else {
126+
csr_write(CSR_MISELECT, CLIC_INTIE(irq));
127+
csr_set(CSR_MIREG2, BIT(irq % 32));
128+
}
124129
}
125130

126131
/**
127132
* @brief Disable interrupt
128133
*/
129134
void riscv_clic_irq_disable(uint32_t irq)
130135
{
131-
const struct device *dev = DEVICE_DT_INST_GET(0);
132-
union CLICINTIE clicintie = {.b = {.IE = 0x0}};
136+
if (IS_ENABLED(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS)) {
137+
const struct device *dev = DEVICE_DT_INST_GET(0);
138+
union CLICINTIE clicintie = {.b = {.IE = 0x0}};
133139

134-
write_clic8(dev, CLIC_INTIE(irq), clicintie.w);
140+
write_clic8(dev, CLIC_INTIE(irq), clicintie.w);
141+
} else {
142+
csr_write(CSR_MISELECT, CLIC_INTIE(irq));
143+
csr_clear(CSR_MIREG2, BIT(irq % 32));
144+
}
135145
}
136146

137147
/**
138148
* @brief Get enable status of interrupt
139149
*/
140150
int riscv_clic_irq_is_enabled(uint32_t irq)
141151
{
142-
const struct device *dev = DEVICE_DT_INST_GET(0);
143-
union CLICINTIE clicintie = {.w = read_clic8(dev, CLIC_INTIE(irq))};
152+
int is_enabled = 0;
153+
154+
if (IS_ENABLED(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS)) {
155+
const struct device *dev = DEVICE_DT_INST_GET(0);
156+
union CLICINTIE clicintie = {.w = read_clic8(dev, CLIC_INTIE(irq))};
144157

145-
return clicintie.b.IE;
158+
is_enabled = clicintie.b.IE;
159+
} else {
160+
csr_write(CSR_MISELECT, CLIC_INTIE(irq));
161+
is_enabled = csr_read(CSR_MIREG2) & BIT(irq % 32);
162+
}
163+
164+
return !!is_enabled;
146165
}
147166

148167
/**
@@ -172,36 +191,71 @@ void riscv_clic_irq_priority_set(uint32_t irq, uint32_t pri, uint32_t flags)
172191
(MIN(pri, max_level) << (8U - data->nlbits)) |
173192
BIT_MASK(8U - data->intctlbits);
174193

175-
write_clic8(dev, CLIC_INTCTRL(irq), intctrl);
194+
if (IS_ENABLED(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS)) {
195+
write_clic8(dev, CLIC_INTCTRL(irq), intctrl);
196+
} else {
197+
uint32_t clicintctl, bit_offset = 8 * (irq % 4);
198+
199+
csr_write(CSR_MISELECT, CLIC_INTCTRL(irq));
200+
clicintctl = csr_read(CSR_MIREG);
201+
clicintctl &= ~GENMASK(bit_offset + 7, bit_offset);
202+
clicintctl |= intctrl << bit_offset;
203+
csr_write(CSR_MIREG, clicintctl);
204+
}
176205

177206
/* Set the IRQ operates in machine mode, non-vectoring and the trigger type. */
178207
union CLICINTATTR clicattr = {.b = {.mode = 0x3, .shv = 0x0, .trg = flags & BIT_MASK(3)}};
179208

180-
write_clic8(dev, CLIC_INTATTR(irq), clicattr.w);
209+
if (IS_ENABLED(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS)) {
210+
write_clic8(dev, CLIC_INTATTR(irq), clicattr.w);
211+
} else {
212+
uint32_t clicintattr, bit_offset = 8 * (irq % 4);
213+
214+
csr_write(CSR_MISELECT, CLIC_INTATTR(irq));
215+
clicintattr = csr_read(CSR_MIREG2);
216+
clicintattr &= ~GENMASK(bit_offset + 7, bit_offset);
217+
clicintattr |= clicattr.w << bit_offset;
218+
csr_write(CSR_MIREG2, clicintattr);
219+
}
181220
}
182221

183222
/**
184223
* @brief Set vector mode of interrupt
185224
*/
186225
void riscv_clic_irq_vector_set(uint32_t irq)
187226
{
188-
const struct device *dev = DEVICE_DT_INST_GET(0);
189-
union CLICINTATTR clicattr = {.w = read_clic8(dev, CLIC_INTATTR(irq))};
227+
if (IS_ENABLED(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS)) {
228+
const struct device *dev = DEVICE_DT_INST_GET(0);
229+
union CLICINTATTR clicattr = {.w = read_clic8(dev, CLIC_INTATTR(irq))};
230+
231+
/* Set Selective Hardware Vectoring. */
232+
clicattr.b.shv = 1;
233+
write_clic8(dev, CLIC_INTATTR(irq), clicattr.w);
234+
} else {
235+
uint32_t clicintattr, bit_offset = 8 * (irq % 4);
236+
union CLICINTATTR clicattr = {.b = {.shv = 1}};
190237

191-
/* Set Selective Hardware Vectoring. */
192-
clicattr.b.shv = 1;
193-
write_clic8(dev, CLIC_INTATTR(irq), clicattr.w);
238+
csr_write(CSR_MISELECT, CLIC_INTATTR(irq));
239+
clicintattr = csr_read(CSR_MIREG2);
240+
clicintattr |= clicattr.w << bit_offset;
241+
csr_write(CSR_MIREG2, clicintattr);
242+
}
194243
}
195244

196245
/**
197246
* @brief Set pending bit of an interrupt
198247
*/
199248
void riscv_clic_irq_set_pending(uint32_t irq)
200249
{
201-
const struct device *dev = DEVICE_DT_INST_GET(0);
202-
union CLICINTIP clicintip = {.b = {.IP = 0x1}};
250+
if (IS_ENABLED(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS)) {
251+
const struct device *dev = DEVICE_DT_INST_GET(0);
252+
union CLICINTIP clicintip = {.b = {.IP = 0x1}};
203253

204-
write_clic8(dev, CLIC_INTIP(irq), clicintip.w);
254+
write_clic8(dev, CLIC_INTIP(irq), clicintip.w);
255+
} else {
256+
csr_write(CSR_MISELECT, CLIC_INTIP(irq));
257+
csr_set(CSR_MIREG, BIT(irq % 32));
258+
}
205259
}
206260

207261
static int clic_init(const struct device *dev)
@@ -228,16 +282,40 @@ static int clic_init(const struct device *dev)
228282
}
229283

230284
if (IS_ENABLED(CONFIG_CLIC_SMCLICCONFIG_EXT)) {
231-
/* Configure the number of bits assigned to interrupt levels. */
232-
union CLICCFG cliccfg = {.qw = read_clic32(dev, CLIC_CFG)};
233-
234-
cliccfg.w.nlbits = data->nlbits;
235-
write_clic32(dev, CLIC_CFG, cliccfg.qw);
285+
if (IS_ENABLED(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS)) {
286+
/* Configure the number of bits assigned to interrupt levels. */
287+
union CLICCFG cliccfg = {.qw = read_clic32(dev, CLIC_CFG)};
288+
289+
cliccfg.w.nlbits = data->nlbits;
290+
write_clic32(dev, CLIC_CFG, cliccfg.qw);
291+
} else {
292+
csr_write(CSR_MISELECT, CLIC_CFG);
293+
union CLICCFG cliccfg = {.qw = csr_read(CSR_MIREG)};
294+
295+
cliccfg.w.nlbits = data->nlbits;
296+
csr_write(CSR_MIREG, cliccfg.qw);
297+
}
236298
}
237299

238-
/* Reset all interrupt control register */
239-
for (int i = 0; i < CONFIG_NUM_IRQS; i++) {
240-
write_clic32(dev, CLIC_CTRL(i), 0);
300+
if (IS_ENABLED(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS)) {
301+
/* Reset all interrupt control register. */
302+
for (int i = 0; i < CONFIG_NUM_IRQS; i++) {
303+
write_clic32(dev, CLIC_CTRL(i), 0);
304+
}
305+
} else {
306+
/* Reset all clicintip, clicintie register. */
307+
for (int i = 0; i < CONFIG_NUM_IRQS; i += 32) {
308+
csr_write(CSR_MISELECT, CLIC_INTIP(i));
309+
csr_write(CSR_MIREG, 0);
310+
csr_write(CSR_MIREG2, 0);
311+
}
312+
313+
/* Reset all clicintctl, clicintattr register. */
314+
for (int i = 0; i < CONFIG_NUM_IRQS; i += 4) {
315+
csr_write(CSR_MISELECT, CLIC_INTCTRL(i));
316+
csr_write(CSR_MIREG, 0);
317+
csr_write(CSR_MIREG2, 0);
318+
}
241319
}
242320

243321
return 0;
@@ -250,7 +328,8 @@ static int clic_init(const struct device *dev)
250328
};
251329
#define CLIC_INTC_CONFIG_INIT(n) \
252330
const static struct clic_config clic_config_##n = { \
253-
.base = DT_REG_ADDR(DT_DRV_INST(n)), \
331+
.base = COND_CODE_1(CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS, \
332+
(DT_REG_ADDR(DT_DRV_INST(n))), (0)), \
254333
};
255334
#define CLIC_INTC_DEVICE_INIT(n) \
256335
CLIC_INTC_DATA_INIT(n) \

drivers/interrupt_controller/intc_clic.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,31 @@
1212
#define CSR_MTVT (0x307)
1313
#define CSR_MNXTI (0x345)
1414
#define CSR_MINTTHRESH (0x347)
15+
#define CSR_MISELECT (0x350)
16+
#define CSR_MIREG (0x351)
17+
#define CSR_MIREG2 (0x352)
1518

1619
#ifndef __ASSEMBLER__
1720

1821
#include <stddef.h>
1922

23+
#ifdef CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS
2024
/* CLIC Memory mapped register offset */
2125
#define CLIC_CFG (0x0)
2226
#define CLIC_CTRL(irq) (0x1000 + 4 * (irq))
2327
#define CLIC_INTIP(irq) (CLIC_CTRL(irq) + offsetof(union CLICCTRL, w.INTIP))
2428
#define CLIC_INTIE(irq) (CLIC_CTRL(irq) + offsetof(union CLICCTRL, w.INTIE))
2529
#define CLIC_INTATTR(irq) (CLIC_CTRL(irq) + offsetof(union CLICCTRL, w.INTATTR))
2630
#define CLIC_INTCTRL(irq) (CLIC_CTRL(irq) + offsetof(union CLICCTRL, w.INTCTRL))
31+
#else
32+
/* Indirect CSR Access miselect offset */
33+
#define CLIC_CFG (0x14A0)
34+
#define CLIC_CTRL(irq) (0x0) /* Dummy value for driver compatibility */
35+
#define CLIC_INTIP(irq) (0x1400 + (irq) / 32)
36+
#define CLIC_INTIE(irq) (0x1400 + (irq) / 32)
37+
#define CLIC_INTATTR(irq) (0x1000 + (irq) / 4)
38+
#define CLIC_INTCTRL(irq) (0x1000 + (irq) / 4)
39+
#endif /* !CONFIG_LEGACY_CLIC_MEMORYMAP_ACCESS */
2740

2841
/* Nuclei ECLIC memory mapped register offset */
2942
#define CLIC_INFO (0x4)

0 commit comments

Comments
 (0)