1 /* Copyright 2018 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
4 #include <metal/machine/platform.h>
6 #ifdef METAL_SIFIVE_CLIC0
10 #include <metal/shutdown.h>
11 #include <metal/drivers/sifive_clic0.h>
12 #include <metal/machine.h>
14 typedef enum metal_clic_vector_{
15 METAL_CLIC_NONVECTOR = 0,
16 METAL_CLIC_VECTORED = 1
19 struct __metal_clic_cfg {
26 const struct __metal_clic_cfg __metal_clic_defaultcfg = {
27 .nmbits = METAL_INTR_PRIV_M_MODE,
29 .nvbit = METAL_CLIC_NONVECTOR
32 void __metal_clic0_handler(int id, void *priv) __attribute__((aligned(64)));
34 void __metal_clic0_default_vector_handler (void) __attribute__((interrupt, aligned(64)));
36 struct __metal_clic_cfg __metal_clic0_configuration (struct __metal_driver_sifive_clic0 *clic,
37 struct __metal_clic_cfg *cfg)
39 volatile unsigned char val;
40 struct __metal_clic_cfg cliccfg;
41 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
44 val = cfg->nmbits << 5 | cfg->nlbits << 1 | cfg->nvbit;
45 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
46 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
47 METAL_SIFIVE_CLIC0_CLICCFG)) = val;
49 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
50 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
51 METAL_SIFIVE_CLIC0_CLICCFG));
52 cliccfg.nmbits = (val & METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MASK) >> 5;
53 cliccfg.nlbits = (val & METAL_SIFIVE_CLIC0_CLICCFG_NLBITS_MASK) >> 1;
54 cliccfg.nvbit = val & METAL_SIFIVE_CLIC0_CLICCFG_NVBIT_MASK;
58 int __metal_clic0_interrupt_set_mode (struct __metal_driver_sifive_clic0 *clic, int id, int mode)
61 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
62 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
64 if (mode >= (cfg.nmbits << 1)) {
65 /* Do nothing, mode request same or exceed what configured in CLIC */
69 /* Mask out nmbits and retain other values */
70 mask = ((uint8_t)(-1)) >> cfg.nmbits;
71 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
72 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
73 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) & mask;
74 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
75 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
76 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = val | (mode << (8 - cfg.nmbits));
80 int __metal_clic0_interrupt_set_level (struct __metal_driver_sifive_clic0 *clic, int id, unsigned int level)
82 uint8_t mask, nmmask, nlmask, val;
83 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
84 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
86 /* Drop the LSBs that don't fit in nlbits */
87 level = level >> (METAL_CLIC_MAX_NLBITS - cfg.nlbits);
89 nmmask = ~( ((uint8_t)(-1)) >> (cfg.nmbits) );
90 nlmask = ((uint8_t)(-1)) >> (cfg.nmbits + cfg.nlbits);
91 mask = ~(nlmask | nmmask);
93 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
94 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
95 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
96 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
97 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
98 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = __METAL_SET_FIELD(val, mask, level);
102 unsigned int __metal_clic0_interrupt_get_level (struct __metal_driver_sifive_clic0 *clic, int id)
105 uint8_t mask, val, freebits, nlbits;
106 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
107 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
108 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
110 if ((cfg.nmbits + cfg.nlbits) >= num_intbits) {
111 nlbits = num_intbits - cfg.nmbits;
116 mask = ((1 << nlbits) - 1) << (8 - (cfg.nmbits + nlbits));
117 freebits = ((1 << METAL_CLIC_MAX_NLBITS) - 1) >> nlbits;
120 level = (1 << METAL_CLIC_MAX_NLBITS) - 1;
122 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
123 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
124 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
125 val = __METAL_GET_FIELD(val, mask);
126 level = (val << (METAL_CLIC_MAX_NLBITS - nlbits)) | freebits;
132 int __metal_clic0_interrupt_set_priority (struct __metal_driver_sifive_clic0 *clic, int id, int priority)
134 uint8_t mask, npmask, val, npbits;
135 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
136 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
137 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
139 if ((cfg.nmbits + cfg.nlbits) < num_intbits) {
140 npbits = num_intbits - (cfg.nmbits + cfg.nlbits);
141 priority = priority >> (8 - npbits);
143 mask = ((uint8_t)(-1)) >> (cfg.nmbits + cfg.nlbits + npbits);
144 npmask = ~(((uint8_t)(-1)) >> (cfg.nmbits + cfg.nlbits));
145 mask = ~(mask | npmask);
147 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
148 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
149 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
150 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
151 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
152 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = __METAL_SET_FIELD(val, mask, priority);
157 int __metal_clic0_interrupt_get_priority (struct __metal_driver_sifive_clic0 *clic, int id)
160 uint8_t mask, val, freebits, nlbits;
161 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
162 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
163 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
165 if ((cfg.nmbits + cfg.nlbits) >= num_intbits) {
166 nlbits = num_intbits - cfg.nmbits;
171 mask = ((1 << nlbits) - 1) << (8 - (cfg.nmbits + nlbits));
172 freebits = ((1 << METAL_CLIC_MAX_NLBITS) - 1) >> nlbits;
175 priority = (1 << METAL_CLIC_MAX_NLBITS) - 1;
177 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
178 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
179 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
180 priority = __METAL_GET_FIELD(val, freebits);
185 int __metal_clic0_interrupt_set_vector_mode (struct __metal_driver_sifive_clic0 *clic, int id, int enable)
188 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
189 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
191 mask = 1 << (8 - num_intbits);
192 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
193 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
194 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
195 /* Ensure its value is 1 bit wide */
197 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
198 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
199 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = __METAL_SET_FIELD(val, mask, enable);
203 int __metal_clic0_interrupt_is_vectored (struct __metal_driver_sifive_clic0 *clic, int id)
206 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
207 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
209 mask = 1 << (8 - num_intbits);
210 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
211 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
212 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
213 return __METAL_GET_FIELD(val, mask);
216 int __metal_clic0_interrupt_enable (struct __metal_driver_sifive_clic0 *clic, int id)
218 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
219 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
221 if (id >= num_subinterrupts) {
224 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
225 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
226 METAL_SIFIVE_CLIC0_CLICINTIE_BASE + id)) = METAL_ENABLE;
230 int __metal_clic0_interrupt_disable (struct __metal_driver_sifive_clic0 *clic, int id)
232 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
233 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
235 if (id >= num_subinterrupts) {
238 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
239 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
240 METAL_SIFIVE_CLIC0_CLICINTIE_BASE + id)) = METAL_DISABLE;
244 int __metal_clic0_interrupt_is_enabled (struct __metal_driver_sifive_clic0 *clic, int id)
246 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
247 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
249 if (id >= num_subinterrupts) {
252 return __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
253 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
254 METAL_SIFIVE_CLIC0_CLICINTIE_BASE + id));
257 int __metal_clic0_interrupt_is_pending (struct __metal_driver_sifive_clic0 *clic, int id)
259 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
260 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
262 if (id >= num_subinterrupts) {
265 return __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
266 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
267 METAL_SIFIVE_CLIC0_CLICINTIP_BASE + id));
270 int __metal_clic0_interrupt_set (struct __metal_driver_sifive_clic0 *clic, int id)
272 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
273 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
275 if (id < num_subinterrupts) {
276 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
277 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
278 METAL_SIFIVE_CLIC0_CLICINTIP_BASE + id)) = METAL_ENABLE;
284 int __metal_clic0_interrupt_clear (struct __metal_driver_sifive_clic0 *clic, int id)
286 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
287 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
289 if (id < num_subinterrupts) {
290 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
291 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
292 METAL_SIFIVE_CLIC0_CLICINTIP_BASE + id)) = METAL_DISABLE;
298 int __metal_clic0_configure_set_vector_mode (struct __metal_driver_sifive_clic0 *clic, metal_vector_mode mode)
300 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
303 case METAL_SELECTIVE_NONVECTOR_MODE:
304 cfg.nvbit = METAL_CLIC_NONVECTOR;
305 __metal_controller_interrupt_vector(mode, &clic->metal_mtvt_table);
307 case METAL_SELECTIVE_VECTOR_MODE:
308 cfg.nvbit = METAL_CLIC_VECTORED;
309 __metal_controller_interrupt_vector(mode, &clic->metal_mtvt_table);
311 case METAL_HARDWARE_VECTOR_MODE:
312 cfg.nvbit = METAL_CLIC_VECTORED;
313 __metal_controller_interrupt_vector(mode, &clic->metal_mtvt_table);
318 __metal_clic0_configuration(clic, &cfg);
322 metal_vector_mode __metal_clic0_configure_get_vector_mode (struct __metal_driver_sifive_clic0 *clic)
324 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
325 metal_vector_mode mode = __metal_controller_interrupt_vector_mode();
327 if (mode == METAL_SELECTIVE_VECTOR_MODE) {
329 return METAL_SELECTIVE_VECTOR_MODE;
331 return METAL_SELECTIVE_NONVECTOR_MODE;
338 int __metal_clic0_configure_set_privilege (struct __metal_driver_sifive_clic0 *clic, metal_intr_priv_mode priv)
340 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
343 __metal_clic0_configuration(clic, &cfg);
347 metal_intr_priv_mode __metal_clic0_configure_get_privilege (struct __metal_driver_sifive_clic0 *clic)
349 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
354 int __metal_clic0_configure_set_level (struct __metal_driver_sifive_clic0 *clic, int level)
356 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
358 cfg.nlbits = level & 0xF;
359 __metal_clic0_configuration(clic, &cfg);
363 int __metal_clic0_configure_get_level (struct __metal_driver_sifive_clic0 *clic)
365 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
370 unsigned long long __metal_clic0_mtime_get (struct __metal_driver_sifive_clic0 *clic)
372 __metal_io_u32 lo, hi;
373 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
375 /* Guard against rollover when reading */
377 hi = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CLIC0_MTIME + 4));
378 lo = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CLIC0_MTIME));
379 } while (__METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CLIC0_MTIME + 4)) != hi);
381 return (((unsigned long long)hi) << 32) | lo;
384 int __metal_driver_sifive_clic0_mtimecmp_set(struct metal_interrupt *controller,
386 unsigned long long time)
388 struct __metal_driver_sifive_clic0 *clic =
389 (struct __metal_driver_sifive_clic0 *)(controller);
391 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
392 /* Per spec, the RISC-V MTIME/MTIMECMP registers are 64 bit,
393 * and are NOT internally latched for multiword transfers.
394 * Need to be careful about sequencing to avoid triggering
395 * spurious interrupts: For that set the high word to a max
398 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_SIFIVE_CLIC0_MTIMECMP_BASE + 4)) = 0xFFFFFFFF;
399 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_SIFIVE_CLIC0_MTIMECMP_BASE)) = (__metal_io_u32)time;
400 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_SIFIVE_CLIC0_MTIMECMP_BASE + 4)) = (__metal_io_u32)(time >> 32);
404 void __metal_clic0_handler (int id, void *priv)
406 struct __metal_driver_sifive_clic0 *clic = priv;
407 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
409 if ( (id < num_subinterrupts) && (clic->metal_exint_table[id].handler) ) {
410 clic->metal_exint_table[id].handler(id, clic->metal_exint_table[id].exint_data);
414 void __metal_clic0_default_handler (int id, void *priv) {
418 void __metal_clic0_default_vector_handler (void) {
422 void __metal_driver_sifive_clic0_init (struct metal_interrupt *controller)
424 struct __metal_driver_sifive_clic0 *clic =
425 (struct __metal_driver_sifive_clic0 *)(controller);
427 if ( !clic->init_done ) {
428 int level, max_levels, line, num_interrupts, num_subinterrupts;
429 struct __metal_clic_cfg cfg = __metal_clic_defaultcfg;
430 struct metal_interrupt *intc =
431 __metal_driver_sifive_clic0_interrupt_parent(controller);
433 /* Initialize ist parent controller, aka cpu_intc. */
434 intc->vtable->interrupt_init(intc);
435 __metal_controller_interrupt_vector(METAL_SELECTIVE_NONVECTOR_MODE,
436 &clic->metal_mtvt_table);
439 * Register its interrupts with with parent controller,
440 * aka sw, timer and ext to its default isr
442 num_interrupts = __metal_driver_sifive_clic0_num_interrupts(controller);
443 for (int i = 0; i < num_interrupts; i++) {
444 line = __metal_driver_sifive_clic0_interrupt_lines(controller, i);
445 intc->vtable->interrupt_register(intc, line, NULL, clic);
448 /* Default CLIC mode to per dts */
449 max_levels = __metal_driver_sifive_clic0_max_levels(controller);
450 cfg.nlbits = (max_levels > METAL_CLIC_MAX_NLBITS) ?
451 METAL_CLIC_MAX_NLBITS : max_levels;
452 __metal_clic0_configuration(clic, &cfg);
454 level = (1 << cfg.nlbits) - 1;
455 num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
456 clic->metal_mtvt_table[0] = &__metal_clic0_handler;
457 for (int i = 1; i < num_subinterrupts; i++) {
458 clic->metal_mtvt_table[i] = NULL;
459 clic->metal_exint_table[i].handler = NULL;
460 clic->metal_exint_table[i].sub_int = NULL;
461 clic->metal_exint_table[i].exint_data = NULL;
462 __metal_clic0_interrupt_disable(clic, i);
463 __metal_clic0_interrupt_set_level(clic, i, level);
469 int __metal_driver_sifive_clic0_register (struct metal_interrupt *controller,
470 int id, metal_interrupt_handler_t isr,
474 int num_subinterrupts;
475 struct __metal_driver_sifive_clic0 *clic =
476 (struct __metal_driver_sifive_clic0 *)(controller);
477 struct metal_interrupt *intc =
478 __metal_driver_sifive_clic0_interrupt_parent(controller);
479 metal_vector_mode mode = __metal_clic0_configure_get_vector_mode(clic);
481 if ( ( (mode == METAL_SELECTIVE_VECTOR_MODE) &&
482 (__metal_clic0_interrupt_is_vectored(clic, id)) ) ||
483 (mode == METAL_HARDWARE_VECTOR_MODE) ||
484 (mode == METAL_VECTOR_MODE) ||
485 (mode == METAL_DIRECT_MODE) ) {
489 /* Register its interrupts with parent controller */
490 if (id < METAL_INTERRUPT_ID_CSW) {
491 return intc->vtable->interrupt_register(intc, id, isr, priv);
495 * CLIC (sub-interrupts) devices interrupts start at 16 but offset from 0
496 * Reset the IDs to reflects this.
498 num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
499 if (id < num_subinterrupts) {
501 clic->metal_exint_table[id].handler = isr;
502 clic->metal_exint_table[id].exint_data = priv;
504 clic->metal_exint_table[id].handler = __metal_clic0_default_handler;
505 clic->metal_exint_table[id].sub_int = priv;
512 int __metal_driver_sifive_clic0_vector_register (struct metal_interrupt *controller,
513 int id, metal_interrupt_vector_handler_t isr,
517 struct __metal_driver_sifive_clic0 *clic =
518 (struct __metal_driver_sifive_clic0 *)(controller);
519 struct metal_interrupt *intc =
520 __metal_driver_sifive_clic0_interrupt_parent(controller);
521 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
522 metal_vector_mode mode = __metal_clic0_configure_get_vector_mode(clic);
524 if ((mode != METAL_SELECTIVE_VECTOR_MODE) && (mode != METAL_HARDWARE_VECTOR_MODE)) {
527 if ((mode == METAL_SELECTIVE_VECTOR_MODE) &&
528 (__metal_clic0_interrupt_is_vectored(clic, id) == 0) ) {
531 if (id < num_subinterrupts) {
533 clic->metal_mtvt_table[id] = isr;
534 clic->metal_exint_table[id].exint_data = priv;
536 clic->metal_mtvt_table[id] = __metal_clic0_default_vector_handler;
537 clic->metal_exint_table[id].sub_int = priv;
544 int __metal_driver_sifive_clic0_enable (struct metal_interrupt *controller, int id)
546 struct __metal_driver_sifive_clic0 *clic =
547 (struct __metal_driver_sifive_clic0 *)(controller);
548 return __metal_clic0_interrupt_enable(clic, id);
551 int __metal_driver_sifive_clic0_disable (struct metal_interrupt *controller, int id)
553 struct __metal_driver_sifive_clic0 *clic =
554 (struct __metal_driver_sifive_clic0 *)(controller);
555 return __metal_clic0_interrupt_disable(clic, id);
558 int __metal_driver_sifive_clic0_enable_interrupt_vector(struct metal_interrupt *controller, int id)
561 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
562 struct __metal_driver_sifive_clic0 *clic =
563 (struct __metal_driver_sifive_clic0 *)(controller);
564 metal_vector_mode mode = __metal_clic0_configure_get_vector_mode(clic);
566 if ((mode != METAL_SELECTIVE_VECTOR_MODE) && (mode != METAL_HARDWARE_VECTOR_MODE)) {
569 if (id < num_subinterrupts) {
570 __metal_clic0_interrupt_set_vector_mode(clic, id, METAL_ENABLE);
576 int __metal_driver_sifive_clic0_disable_interrupt_vector(struct metal_interrupt *controller, int id)
578 int num_subinterrupts;
579 struct __metal_driver_sifive_clic0 *clic =
580 (struct __metal_driver_sifive_clic0 *)(controller);
582 num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
583 if (id < num_subinterrupts) {
584 __metal_clic0_interrupt_set_vector_mode(clic, id, METAL_DISABLE);
590 metal_vector_mode __metal_driver_sifive_clic0_get_vector_mode (struct metal_interrupt *controller)
592 struct __metal_driver_sifive_clic0 *clic =
593 (struct __metal_driver_sifive_clic0 *)(controller);
594 return __metal_clic0_configure_get_vector_mode(clic);
597 int __metal_driver_sifive_clic0_set_vector_mode (struct metal_interrupt *controller, metal_vector_mode mode)
599 struct __metal_driver_sifive_clic0 *clic =
600 (struct __metal_driver_sifive_clic0 *)(controller);
601 return __metal_clic0_configure_set_vector_mode(clic, mode);
604 metal_intr_priv_mode __metal_driver_sifive_clic0_get_privilege (struct metal_interrupt *controller)
606 struct __metal_driver_sifive_clic0 *clic =
607 (struct __metal_driver_sifive_clic0 *)(controller);
608 return __metal_clic0_configure_get_privilege(clic);
611 int __metal_driver_sifive_clic0_set_privilege (struct metal_interrupt *controller, metal_intr_priv_mode priv)
613 struct __metal_driver_sifive_clic0 *clic =
614 (struct __metal_driver_sifive_clic0 *)(controller);
615 return __metal_clic0_configure_set_privilege(clic, priv);
618 unsigned int __metal_driver_sifive_clic0_get_threshold (struct metal_interrupt *controller)
620 struct __metal_driver_sifive_clic0 *clic =
621 (struct __metal_driver_sifive_clic0 *)(controller);
622 return __metal_clic0_configure_get_level(clic);
625 int __metal_driver_sifive_clic0_set_threshold (struct metal_interrupt *controller, unsigned int level)
627 struct __metal_driver_sifive_clic0 *clic =
628 (struct __metal_driver_sifive_clic0 *)(controller);
629 return __metal_clic0_configure_set_level(clic, level);
632 unsigned int __metal_driver_sifive_clic0_get_priority (struct metal_interrupt *controller, int id)
634 struct __metal_driver_sifive_clic0 *clic =
635 (struct __metal_driver_sifive_clic0 *)(controller);
636 return __metal_clic0_interrupt_get_priority(clic, id);
639 int __metal_driver_sifive_clic0_set_priority (struct metal_interrupt *controller, int id, unsigned int priority)
641 struct __metal_driver_sifive_clic0 *clic =
642 (struct __metal_driver_sifive_clic0 *)(controller);
643 return __metal_clic0_interrupt_set_priority(clic, id, priority);
646 int __metal_driver_sifive_clic0_clear_interrupt (struct metal_interrupt *controller, int id)
648 struct __metal_driver_sifive_clic0 *clic =
649 (struct __metal_driver_sifive_clic0 *)(controller);
650 return __metal_clic0_interrupt_clear(clic, id);
653 int __metal_driver_sifive_clic0_set_interrupt (struct metal_interrupt *controller, int id)
655 struct __metal_driver_sifive_clic0 *clic =
656 (struct __metal_driver_sifive_clic0 *)(controller);
657 return __metal_clic0_interrupt_set(clic, id);
660 int __metal_driver_sifive_clic0_command_request (struct metal_interrupt *controller,
661 int command, void *data)
665 struct __metal_driver_sifive_clic0 *clic =
666 (struct __metal_driver_sifive_clic0 *)(controller);
667 unsigned long control_base = __metal_driver_sifive_clic0_control_base(controller);
670 case METAL_TIMER_MTIME_GET:
672 *(unsigned long long *)data = __metal_clic0_mtime_get(clic);
676 case METAL_SOFTWARE_IPI_CLEAR:
678 hartid = *(int *)data;
679 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
680 (hartid * 4))) = METAL_DISABLE;
681 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
682 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
683 METAL_SIFIVE_CLIC0_CLICINTIP_BASE)) = METAL_DISABLE;
687 case METAL_SOFTWARE_IPI_SET:
689 hartid = *(int *)data;
690 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
691 (hartid * 4))) = METAL_ENABLE;
692 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
693 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
694 METAL_SIFIVE_CLIC0_CLICINTIP_BASE)) = METAL_ENABLE;
698 case METAL_SOFTWARE_MSIP_GET:
701 hartid = *(int *)data;
702 rc = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
712 __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_clic0) = {
713 .clic_vtable.interrupt_init = __metal_driver_sifive_clic0_init,
714 .clic_vtable.interrupt_register = __metal_driver_sifive_clic0_register,
715 .clic_vtable.interrupt_vector_register = __metal_driver_sifive_clic0_vector_register,
716 .clic_vtable.interrupt_enable = __metal_driver_sifive_clic0_enable,
717 .clic_vtable.interrupt_disable = __metal_driver_sifive_clic0_disable,
718 .clic_vtable.interrupt_vector_enable = __metal_driver_sifive_clic0_enable_interrupt_vector,
719 .clic_vtable.interrupt_vector_disable = __metal_driver_sifive_clic0_disable_interrupt_vector,
720 .clic_vtable.interrupt_get_vector_mode = __metal_driver_sifive_clic0_get_vector_mode,
721 .clic_vtable.interrupt_set_vector_mode = __metal_driver_sifive_clic0_set_vector_mode,
722 .clic_vtable.interrupt_get_privilege = __metal_driver_sifive_clic0_get_privilege,
723 .clic_vtable.interrupt_set_privilege = __metal_driver_sifive_clic0_set_privilege,
724 .clic_vtable.interrupt_get_threshold = __metal_driver_sifive_clic0_get_threshold,
725 .clic_vtable.interrupt_set_threshold = __metal_driver_sifive_clic0_set_threshold,
726 .clic_vtable.interrupt_get_priority = __metal_driver_sifive_clic0_get_priority,
727 .clic_vtable.interrupt_set_priority = __metal_driver_sifive_clic0_set_priority,
728 .clic_vtable.interrupt_clear = __metal_driver_sifive_clic0_clear_interrupt,
729 .clic_vtable.interrupt_set = __metal_driver_sifive_clic0_set_interrupt,
730 .clic_vtable.command_request = __metal_driver_sifive_clic0_command_request,
731 .clic_vtable.mtimecmp_set = __metal_driver_sifive_clic0_mtimecmp_set,
734 #endif /* METAL_SIFIVE_CLIC0 */
736 typedef int no_empty_translation_units;