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_priv_mode_ {
15 METAL_PRIV_M_MODE = 0,
16 METAL_PRIV_MU_MODE = 1,
17 METAL_PRIV_MSU_MODE = 2
20 typedef enum metal_clic_vector_{
21 METAL_CLIC_NONVECTOR = 0,
22 METAL_CLIC_VECTORED = 1
25 struct __metal_clic_cfg {
32 const struct __metal_clic_cfg __metal_clic_defaultcfg = {
33 .nmbits = METAL_PRIV_M_MODE,
35 .nvbit = METAL_CLIC_NONVECTOR
38 struct __metal_clic_cfg __metal_clic0_configuration (struct __metal_driver_sifive_clic0 *clic,
39 struct __metal_clic_cfg *cfg)
41 volatile unsigned char val;
42 struct __metal_clic_cfg cliccfg;
43 uintptr_t hartid = __metal_myhart_id();
44 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
47 val = cfg->nmbits << 5 | cfg->nlbits << 1 | cfg->nvbit;
48 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
49 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
50 METAL_SIFIVE_CLIC0_CLICCFG)) = val;
52 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
53 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
54 METAL_SIFIVE_CLIC0_CLICCFG));
55 cliccfg.nmbits = (val & METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MASK) >> 5;
56 cliccfg.nlbits = (val & METAL_SIFIVE_CLIC0_CLICCFG_NLBITS_MASK) >> 1;
57 cliccfg.nvbit = val & METAL_SIFIVE_CLIC0_CLICCFG_NVBIT_MASK;
61 int __metal_clic0_interrupt_set_mode (struct __metal_driver_sifive_clic0 *clic, int id, int mode)
64 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
65 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
67 if (mode >= (cfg.nmbits << 1)) {
68 /* Do nothing, mode request same or exceed what configured in CLIC */
72 /* Mask out nmbits and retain other values */
73 mask = ((uint8_t)(-1)) >> cfg.nmbits;
74 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
75 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
76 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) & mask;
77 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
78 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
79 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = val | (mode << (8 - cfg.nmbits));
83 int __metal_clic0_interrupt_set_level (struct __metal_driver_sifive_clic0 *clic, int id, int level)
85 uint8_t mask, nmmask, nlmask, val;
86 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
87 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
89 /* Drop the LSBs that don't fit in nlbits */
90 level = level >> (METAL_CLIC_MAX_NLBITS - cfg.nlbits);
92 nmmask = ~( ((uint8_t)(-1)) >> (cfg.nmbits) );
93 nlmask = ((uint8_t)(-1)) >> (cfg.nmbits + cfg.nlbits);
94 mask = ~(nlmask | nmmask);
96 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
97 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
98 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
99 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
100 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
101 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = __METAL_SET_FIELD(val, mask, level);
105 int __metal_clic0_interrupt_get_level (struct __metal_driver_sifive_clic0 *clic, int id)
108 uint8_t mask, val, freebits, nlbits;
109 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
110 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
111 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
113 if ((cfg.nmbits + cfg.nlbits) >= num_intbits) {
114 nlbits = num_intbits - cfg.nmbits;
119 mask = ((1 << nlbits) - 1) << (8 - (cfg.nmbits + nlbits));
120 freebits = ((1 << METAL_CLIC_MAX_NLBITS) - 1) >> nlbits;
123 level = (1 << METAL_CLIC_MAX_NLBITS) - 1;
125 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
126 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
127 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
128 val = __METAL_GET_FIELD(val, mask);
129 level = (val << (METAL_CLIC_MAX_NLBITS - nlbits)) | freebits;
135 int __metal_clic0_interrupt_set_priority (struct __metal_driver_sifive_clic0 *clic, int id, int priority)
137 uint8_t mask, npmask, val, npbits;
138 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
139 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
140 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
142 if ((cfg.nmbits + cfg.nlbits) < num_intbits) {
143 npbits = num_intbits - (cfg.nmbits + cfg.nlbits);
144 priority = priority >> (8 - npbits);
146 mask = ((uint8_t)(-1)) >> (cfg.nmbits + cfg.nlbits + npbits);
147 npmask = ~(((uint8_t)(-1)) >> (cfg.nmbits + cfg.nlbits));
148 mask = ~(mask | npmask);
150 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
151 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
152 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
153 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
154 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
155 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = __METAL_SET_FIELD(val, mask, priority);
160 int __metal_clic0_interrupt_get_priority (struct __metal_driver_sifive_clic0 *clic, int id)
163 uint8_t mask, val, freebits, nlbits;
164 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
165 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
166 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
168 if ((cfg.nmbits + cfg.nlbits) >= num_intbits) {
169 nlbits = num_intbits - cfg.nmbits;
174 mask = ((1 << nlbits) - 1) << (8 - (cfg.nmbits + nlbits));
175 freebits = ((1 << METAL_CLIC_MAX_NLBITS) - 1) >> nlbits;
178 priority = (1 << METAL_CLIC_MAX_NLBITS) - 1;
180 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
181 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
182 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
183 priority = __METAL_GET_FIELD(val, freebits);
188 int __metal_clic0_interrupt_set_vector (struct __metal_driver_sifive_clic0 *clic, int id, int enable)
191 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
192 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
194 mask = 1 << (8 - num_intbits);
195 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
196 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
197 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
198 /* Ensure its value is 1 bit wide */
200 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
201 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
202 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = __METAL_SET_FIELD(val, mask, enable);
206 int __metal_clic0_interrupt_is_vectored (struct __metal_driver_sifive_clic0 *clic, int id)
209 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
210 int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
212 mask = 1 << (8 - num_intbits);
213 val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
214 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
215 METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
216 return __METAL_GET_FIELD(val, mask);
219 int __metal_clic0_interrupt_enable (struct __metal_driver_sifive_clic0 *clic, int id)
221 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
222 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
224 if (id >= num_subinterrupts) {
227 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
228 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
229 METAL_SIFIVE_CLIC0_CLICINTIE_BASE + id)) = METAL_ENABLE;
233 int __metal_clic0_interrupt_disable (struct __metal_driver_sifive_clic0 *clic, int id)
235 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
236 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
238 if (id >= num_subinterrupts) {
241 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
242 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
243 METAL_SIFIVE_CLIC0_CLICINTIE_BASE + id)) = METAL_DISABLE;
247 int __metal_clic0_interrupt_is_enabled (struct __metal_driver_sifive_clic0 *clic, int id)
249 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
250 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
252 if (id >= num_subinterrupts) {
255 return __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
256 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
257 METAL_SIFIVE_CLIC0_CLICINTIE_BASE + id));
260 int __metal_clic0_interrupt_is_pending (struct __metal_driver_sifive_clic0 *clic, int id)
262 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
263 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
265 if (id >= num_subinterrupts) {
268 return __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
269 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
270 METAL_SIFIVE_CLIC0_CLICINTIP_BASE + id));
273 int __metal_clic0_interrupt_set (struct __metal_driver_sifive_clic0 *clic, int id)
275 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
277 if ((id >= METAL_INTERRUPT_ID_LC0) && (id < num_subinterrupts)) {
282 int __metal_clic0_interrupt_clear (struct __metal_driver_sifive_clic0 *clic, int id)
284 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
286 if ((id >= METAL_INTERRUPT_ID_LC0) && (id < num_subinterrupts)) {
291 void __metal_clic0_configure_privilege (struct __metal_driver_sifive_clic0 *clic, metal_priv_mode priv)
293 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
296 __metal_clic0_configuration(clic, &cfg);
299 void __metal_clic0_configure_level (struct __metal_driver_sifive_clic0 *clic, int level)
301 struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
304 __metal_clic0_configuration(clic, &cfg);
307 unsigned long long __metal_clic0_mtime_get (struct __metal_driver_sifive_clic0 *clic)
309 __metal_io_u32 lo, hi;
310 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
312 /* Guard against rollover when reading */
314 hi = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CLIC0_MTIME + 4));
315 lo = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CLIC0_MTIME));
316 } while (__METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CLIC0_MTIME + 4)) != hi);
318 return (((unsigned long long)hi) << 32) | lo;
321 int __metal_driver_sifive_clic0_mtimecmp_set(struct metal_interrupt *controller,
323 unsigned long long time)
325 struct __metal_driver_sifive_clic0 *clic =
326 (struct __metal_driver_sifive_clic0 *)(controller);
328 unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
329 /* Per spec, the RISC-V MTIME/MTIMECMP registers are 64 bit,
330 * and are NOT internally latched for multiword transfers.
331 * Need to be careful about sequencing to avoid triggering
332 * spurious interrupts: For that set the high word to a max
335 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_SIFIVE_CLIC0_MTIMECMP_BASE + 4)) = 0xFFFFFFFF;
336 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_SIFIVE_CLIC0_MTIMECMP_BASE)) = (__metal_io_u32)time;
337 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_SIFIVE_CLIC0_MTIMECMP_BASE + 4)) = (__metal_io_u32)(time >> 32);
341 void __metal_clic0_handler(int id, void *priv) __attribute__((aligned(64)));
342 void __metal_clic0_handler (int id, void *priv)
345 struct __metal_driver_sifive_clic0 *clic = priv;
346 int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
348 idx = id - METAL_INTERRUPT_ID_LC0;
349 if ( (idx < num_subinterrupts) && (clic->metal_mtvt_table[idx]) ) {
350 clic->metal_mtvt_table[idx](id, clic->metal_exint_table[idx].exint_data);
354 void __metal_clic0_default_handler (int id, void *priv) {
358 void __metal_driver_sifive_clic0_init (struct metal_interrupt *controller)
360 struct __metal_driver_sifive_clic0 *clic =
361 (struct __metal_driver_sifive_clic0 *)(controller);
363 if ( !clic->init_done ) {
364 int level, max_levels, line, num_interrupts, num_subinterrupts;
365 struct __metal_clic_cfg cfg = __metal_clic_defaultcfg;
366 struct metal_interrupt *intc =
367 __metal_driver_sifive_clic0_interrupt_parent(controller);
369 /* Initialize ist parent controller, aka cpu_intc. */
370 intc->vtable->interrupt_init(intc);
371 __metal_controller_interrupt_vector(METAL_SELECTIVE_VECTOR_MODE,
372 &__metal_clic0_handler);
375 * Register its interrupts with with parent controller,
376 * aka sw, timer and ext to its default isr
378 num_interrupts = __metal_driver_sifive_clic0_num_interrupts(controller);
379 for (int i = 0; i < num_interrupts; i++) {
380 line = __metal_driver_sifive_clic0_interrupt_lines(controller, i);
381 intc->vtable->interrupt_register(intc, line, NULL, clic);
384 /* Default CLIC mode to per dts */
385 max_levels = __metal_driver_sifive_clic0_max_levels(controller);
386 cfg.nlbits = (max_levels > METAL_CLIC_MAX_NLBITS) ?
387 METAL_CLIC_MAX_NLBITS : max_levels;
388 __metal_clic0_configuration(clic, &cfg);
390 level = (1 << cfg.nlbits) - 1;
391 num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
392 for (int i = 0; i < num_subinterrupts; i++) {
393 clic->metal_mtvt_table[i] = NULL;
394 clic->metal_exint_table[i].sub_int = NULL;
395 clic->metal_exint_table[i].exint_data = NULL;
396 __metal_clic0_interrupt_disable(clic, i);
397 __metal_clic0_interrupt_set_level(clic, i, level);
403 int __metal_driver_sifive_clic0_register (struct metal_interrupt *controller,
404 int id, metal_interrupt_handler_t isr,
408 int num_subinterrupts;
409 struct __metal_driver_sifive_clic0 *clic =
410 (struct __metal_driver_sifive_clic0 *)(controller);
411 struct metal_interrupt *intc =
412 __metal_driver_sifive_clic0_interrupt_parent(controller);
414 /* Register its interrupts with parent controller */
415 if ( id < METAL_INTERRUPT_ID_LC0) {
416 return intc->vtable->interrupt_register(intc, id, isr, priv);
420 * CLIC (sub-interrupts) devices interrupts start at 16 but offset from 0
421 * Reset the IDs to reflects this.
423 id -= METAL_INTERRUPT_ID_LC0;
424 num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
425 if (id < num_subinterrupts) {
427 clic->metal_mtvt_table[id] = isr;
428 clic->metal_exint_table[id].exint_data = priv;
430 clic->metal_mtvt_table[id] = __metal_clic0_default_handler;
431 clic->metal_exint_table[id].sub_int = priv;
438 int __metal_driver_sifive_clic0_enable (struct metal_interrupt *controller, int id)
440 struct __metal_driver_sifive_clic0 *clic =
441 (struct __metal_driver_sifive_clic0 *)(controller);
442 return __metal_clic0_interrupt_enable(clic, id);
445 int __metal_driver_sifive_clic0_disable (struct metal_interrupt *controller, int id)
447 struct __metal_driver_sifive_clic0 *clic =
448 (struct __metal_driver_sifive_clic0 *)(controller);
449 return __metal_clic0_interrupt_disable(clic, id);
452 int __metal_driver_sifive_clic0_enable_interrupt_vector(struct metal_interrupt *controller,
453 int id, metal_vector_mode mode)
455 int num_subinterrupts;
456 struct __metal_driver_sifive_clic0 *clic =
457 (struct __metal_driver_sifive_clic0 *)(controller);
459 if (id == METAL_INTERRUPT_ID_BASE) {
460 if (mode == METAL_SELECTIVE_VECTOR_MODE) {
461 __metal_controller_interrupt_vector(mode, &__metal_clic0_handler);
464 if (mode == METAL_HARDWARE_VECTOR_MODE) {
465 __metal_controller_interrupt_vector(mode, &clic->metal_mtvt_table);
469 num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
470 if ((id >= METAL_INTERRUPT_ID_LC0) && (id < num_subinterrupts)) {
471 if ((mode == METAL_SELECTIVE_VECTOR_MODE) &&
472 __metal_controller_interrupt_is_selective_vectored()) {
473 __metal_clic0_interrupt_set_vector(clic, id, METAL_ENABLE);
481 int __metal_driver_sifive_clic0_disable_interrupt_vector(struct metal_interrupt *controller, int id)
483 int num_subinterrupts;
484 struct __metal_driver_sifive_clic0 *clic =
485 (struct __metal_driver_sifive_clic0 *)(controller);
487 if (id == METAL_INTERRUPT_ID_BASE) {
488 __metal_controller_interrupt_vector(METAL_SELECTIVE_VECTOR_MODE, &__metal_clic0_handler);
491 num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
492 if ((id >= METAL_INTERRUPT_ID_LC0) && (id < num_subinterrupts)) {
493 if (__metal_controller_interrupt_is_selective_vectored()) {
494 __metal_clic0_interrupt_set_vector(clic, id, METAL_DISABLE);
501 int __metal_driver_sifive_clic0_command_request (struct metal_interrupt *controller,
502 int command, void *data)
506 struct __metal_driver_sifive_clic0 *clic =
507 (struct __metal_driver_sifive_clic0 *)(controller);
508 unsigned long control_base = __metal_driver_sifive_clic0_control_base(controller);
511 case METAL_TIMER_MTIME_GET:
513 *(unsigned long long *)data = __metal_clic0_mtime_get(clic);
517 case METAL_SOFTWARE_IPI_CLEAR:
519 hartid = *(int *)data;
520 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
521 (hartid * 4))) = METAL_DISABLE;
522 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
523 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
524 METAL_SIFIVE_CLIC0_CLICINTIP_BASE)) = METAL_DISABLE;
528 case METAL_SOFTWARE_IPI_SET:
530 hartid = *(int *)data;
531 __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
532 (hartid * 4))) = METAL_ENABLE;
533 __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
534 METAL_SIFIVE_CLIC0_MMODE_APERTURE +
535 METAL_SIFIVE_CLIC0_CLICINTIP_BASE)) = METAL_ENABLE;
539 case METAL_SOFTWARE_MSIP_GET:
542 hartid = *(int *)data;
543 rc = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
553 __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_clic0) = {
554 .clic_vtable.interrupt_init = __metal_driver_sifive_clic0_init,
555 .clic_vtable.interrupt_register = __metal_driver_sifive_clic0_register,
556 .clic_vtable.interrupt_enable = __metal_driver_sifive_clic0_enable,
557 .clic_vtable.interrupt_disable = __metal_driver_sifive_clic0_disable,
558 .clic_vtable.interrupt_vector_enable = __metal_driver_sifive_clic0_enable_interrupt_vector,
559 .clic_vtable.interrupt_vector_disable = __metal_driver_sifive_clic0_disable_interrupt_vector,
560 .clic_vtable.command_request = __metal_driver_sifive_clic0_command_request,
561 .clic_vtable.mtimecmp_set = __metal_driver_sifive_clic0_mtimecmp_set,
564 #endif /* METAL_SIFIVE_CLIC0 */