diff --git a/bsp/qemu-virt64-riscv/driver/board.c b/bsp/qemu-virt64-riscv/driver/board.c index c5116aad0c5..35ea0fa7fb2 100644 --- a/bsp/qemu-virt64-riscv/driver/board.c +++ b/bsp/qemu-virt64-riscv/driver/board.c @@ -76,8 +76,6 @@ void rt_hw_board_init(void) rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); #endif - plic_init(); - rt_hw_interrupt_init(); rt_hw_uart_init(); diff --git a/libcpu/risc-v/SConscript b/libcpu/risc-v/SConscript index 273c997e8eb..d8e80adfe25 100644 --- a/libcpu/risc-v/SConscript +++ b/libcpu/risc-v/SConscript @@ -16,6 +16,10 @@ if rtconfig.CPU in common64_arch : else : group += SConscript(os.path.join('common', 'SConscript')) +# FIXME: remove implementation of plic in BSP +if rtconfig.CPU in common64_arch: + group += SConscript(os.path.join('plic', 'SConscript')) + # cpu porting code files if 'VENDOR' in vars(rtconfig) and rtconfig.VENDOR != '': group = group + SConscript(os.path.join(rtconfig.VENDOR, rtconfig.CPU, 'SConscript')) diff --git a/libcpu/risc-v/plic/SConscript b/libcpu/risc-v/plic/SConscript new file mode 100644 index 00000000000..d6bcf2cee20 --- /dev/null +++ b/libcpu/risc-v/plic/SConscript @@ -0,0 +1,10 @@ +# RT-Thread building script for component + +from building import * +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/risc-v/t-head/c908/plic.c b/libcpu/risc-v/plic/plic.c similarity index 58% rename from libcpu/risc-v/t-head/c908/plic.c rename to libcpu/risc-v/plic/plic.c index 08cb6c18d2f..faed9b6861d 100644 --- a/libcpu/risc-v/t-head/c908/plic.c +++ b/libcpu/risc-v/plic/plic.c @@ -20,36 +20,44 @@ #include "encoding.h" #include "ioremap.h" -static void *plic_regs = RT_NULL; extern struct rt_irq_desc isr_table[]; struct plic_handler { rt_bool_t present; - void *hart_base; - void *enable_base; + void *hart_base; + void *enable_base; }; +struct plic +{ + void *base_pa; + volatile rt_uint32_t *priority_base; + + void (*irq_handler)(int irq); + + struct plic_handler handlers[NR_CPUS]; +}; + +static struct plic _plic = {}; + rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable); -struct plic_handler plic_handlers[C908_NR_CPUS]; -static void *plic_irq_priority[INTERRUPTS_MAX] = {RT_NULL}; + +rt_inline struct plic_handler *plic_get_handler(int cpu) +{ + return &_plic.handlers[cpu]; +} + +rt_inline struct plic *plic_get(void) +{ + return &_plic; +} rt_inline void plic_irq_toggle(int hwirq, int enable) { int cpu = 0; - void *priority_addr; - /* set priority of interrupt, interrupt 0 is zero. */ - priority_addr = (void *)((rt_size_t)plic_regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID); -#ifdef RT_USING_SMART - if (plic_irq_priority[hwirq] == RT_NULL) - { - plic_irq_priority[hwirq] = (void *)rt_ioremap(priority_addr, 0x1000); - } - priority_addr = plic_irq_priority[hwirq]; -#endif - writel(enable, priority_addr); - struct plic_handler *handler = &plic_handlers[cpu]; + struct plic_handler *handler = plic_get_handler(cpu); if (handler->present) { @@ -59,25 +67,21 @@ rt_inline void plic_irq_toggle(int hwirq, int enable) static void generic_handle_irq(int irq) { - rt_isr_handler_t isr; - void *param; - if (irq < 0 || irq >= IRQ_MAX_NR) { LOG_E("bad irq number %d!\n", irq); return; } - if (!irq) // irq = 0 => no irq + if (!irq) // irq = 0 => no irq { LOG_W("no irq!\n"); return; } - isr = isr_table[IRQ_OFFSET + irq].handler; - param = isr_table[IRQ_OFFSET + irq].param; - if (isr != RT_NULL) + + if (plic_get()->irq_handler != RT_NULL) { - isr(irq, param); + plic_get()->irq_handler(irq); } /* complete irq. */ plic_complete(irq); @@ -86,7 +90,7 @@ static void generic_handle_irq(int irq) void plic_complete(int irqno) { int cpu = 0; - struct plic_handler *handler = &plic_handlers[cpu]; + struct plic_handler *handler = plic_get_handler(cpu); writel(irqno, (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM)); } @@ -109,13 +113,13 @@ void plic_enable_irq(int irqno) */ void plic_handle_irq(void) { - int cpu = 0; + int cpu = 0; unsigned int irq; - struct plic_handler *handler = &plic_handlers[cpu]; - void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM); + struct plic_handler *handler = plic_get_handler(cpu); + void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM); - if (plic_regs == RT_NULL || !handler->present) + if (!handler->present) { LOG_E("plic state not initialized."); return; @@ -140,8 +144,8 @@ void plic_handle_irq(void) rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable) { - uint32_t *reg = (uint32_t *)((rt_size_t)handler->enable_base + (hwirq / 32) * sizeof(uint32_t)); - uint32_t hwirq_mask = 1 << (hwirq % 32); + uint32_t *reg = (uint32_t *)((rt_size_t)handler->enable_base + (hwirq / 32) * sizeof(uint32_t)); + uint32_t hwirq_mask = 1 << (hwirq % 32); if (enable) { @@ -153,32 +157,33 @@ rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable) } } -void plic_init(void) +void plic_init(unsigned long base_pa, void (*irq_handler)(int irq)) { - int nr_irqs; - int nr_context; - int i; + int nr_irqs; + int nr_context; + int i; unsigned long hwirq; - int cpu = 0; + int cpu = 0; + struct plic *plic = plic_get(); - if (plic_regs) + if (plic->base_pa) { LOG_E("plic already initialized!"); return; } - nr_context = C908_NR_CONTEXT; - - plic_regs = (void *)C908_PLIC_PHY_ADDR; - if (!plic_regs) + if (!base_pa || !irq_handler) { - LOG_E("fatal error, plic is reg space is null."); + LOG_E("fatal error, plic init params is null."); return; } + plic->base_pa = (void*)base_pa; + plic->irq_handler = irq_handler; - nr_irqs = C908_PLIC_NR_EXT_IRQS; + nr_context = PLIC_NR_CONTEXT; + nr_irqs = IRQ_MAX_NR; - for (i = 0; i < nr_context; i ++) + for (i = 0; i < nr_context; i++) { struct plic_handler *handler; uint32_t threshold = 0; @@ -192,21 +197,21 @@ void plic_init(void) } // we always use CPU0 M-mode target register. - handler = &plic_handlers[cpu]; + handler = plic_get_handler(cpu); if (handler->present) { - threshold = 0xffffffff; + threshold = 0xffffffff; goto done; } - handler->present = RT_TRUE; - handler->hart_base = (void *)((rt_size_t)plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART); - handler->enable_base = (void *)((rt_size_t)plic_regs + ENABLE_BASE + i * ENABLE_PER_HART); + handler->present = RT_TRUE; + handler->hart_base = (void *)(plic->base_pa + CONTEXT_BASE + i * CONTEXT_PER_HART); + handler->enable_base = (void *)(plic->base_pa + ENABLE_BASE + i * ENABLE_PER_HART); #ifdef RT_USING_SMART - handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000); + handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000); handler->enable_base = (void *)rt_ioremap(handler->enable_base, 0x1000); #endif -done: + done: /* priority must be > threshold to trigger an interrupt */ writel(threshold, (void *)((rt_size_t)handler->hart_base + CONTEXT_THRESHOLD)); for (hwirq = 1; hwirq <= nr_irqs; hwirq++) @@ -218,3 +223,30 @@ void plic_init(void) /* Enable supervisor external interrupts. */ set_csr(sie, SIE_SEIE); } + +void plic_set_threshold(int threshold) +{ + int hart = 0; + struct plic_handler *handler; + + handler = plic_get_handler(hart); + + writel(threshold, (void *)((rt_size_t)handler->hart_base + CONTEXT_THRESHOLD)); +} + +void plic_set_priority(int irq, int priority) +{ + struct plic *plic = plic_get(); + + /* set priority of interrupt, interrupt 0 is zero. */ + if (plic->priority_base == RT_NULL) + { +#ifdef RT_USING_SMART + plic->priority_base = (rt_uint32_t *)rt_ioremap(plic->base_pa, 0x1000); +#else + plic->priority_base = (rt_uint32_t *)plic->base_pa; +#endif + } + + plic->priority_base[irq] = priority; +} diff --git a/libcpu/risc-v/t-head/c908/plic.h b/libcpu/risc-v/plic/plic.h similarity index 85% rename from libcpu/risc-v/t-head/c908/plic.h rename to libcpu/risc-v/plic/plic.h index 94f00eacdb8..3175f28351c 100644 --- a/libcpu/risc-v/t-head/c908/plic.h +++ b/libcpu/risc-v/plic/plic.h @@ -14,14 +14,8 @@ #include -#ifndef C908_PLIC_PHY_ADDR -#define C908_PLIC_PHY_ADDR (0xF00000000UL) -#endif -#define C908_PLIC_NR_EXT_IRQS (IRQ_MAX_NR) -#define C908_NR_CPUS (NR_CPUS) - /* M and S mode context. */ -#define C908_NR_CONTEXT (2) +#define PLIC_NR_CONTEXT (2) #define MAX_DEVICES 1024 #define MAX_CONTEXTS 15872 @@ -50,11 +44,13 @@ #define CONTEXT_THRESHOLD 0x00 #define CONTEXT_CLAIM 0x04 -void plic_init(void); +void plic_init(unsigned long base_pa, void (*irq_handler)(int irq)); void plic_enable_irq(int irqno); void plic_disable_irq(int irqno); // tell PLIC that we've served this IRQ void plic_complete(int irq); void plic_handle_irq(void); +void plic_set_threshold(int mthreshold); +void plic_set_priority(int irq, int priority); #endif diff --git a/libcpu/risc-v/t-head/c906/interrupt.c b/libcpu/risc-v/t-head/c906/interrupt.c index 2f7a86e6802..c7e85250d36 100644 --- a/libcpu/risc-v/t-head/c906/interrupt.c +++ b/libcpu/risc-v/t-head/c906/interrupt.c @@ -15,6 +15,10 @@ #include "riscv.h" #include "plic.h" +#ifndef C906_PLIC_PHY_ADDR +#define C906_PLIC_PHY_ADDR (0x10000000) +#endif + extern rt_atomic_t rt_interrupt_nest; extern rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; extern rt_uint32_t rt_thread_switch_interrupt_flag; @@ -26,13 +30,26 @@ static void rt_hw_interrupt_handler(int vector, void *param) rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); } +static void __isr(int irq) +{ + rt_isr_handler_t isr; + void *param; + + isr = isr_table[IRQ_OFFSET + irq].handler; + param = isr_table[IRQ_OFFSET + irq].param; + if (isr != RT_NULL) + { + isr(irq, param); + } +} + /** * This function will initialize hardware interrupt */ void rt_hw_interrupt_init(void) { /* init interrupt controller */ - plic_init(); + plic_init(C906_PLIC_PHY_ADDR, __isr); rt_int32_t idx; @@ -88,7 +105,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name) { rt_isr_handler_t old_handler = RT_NULL; - if ((vector < 0) || (vector > IRQ_MAX_NR)) + if ((vector < 0) || (vector >= IRQ_MAX_NR)) { return old_handler; } diff --git a/libcpu/risc-v/t-head/c908/interrupt.c b/libcpu/risc-v/t-head/c908/interrupt.c index 2f7a86e6802..9d7eaf1afa1 100644 --- a/libcpu/risc-v/t-head/c908/interrupt.c +++ b/libcpu/risc-v/t-head/c908/interrupt.c @@ -15,6 +15,10 @@ #include "riscv.h" #include "plic.h" +#ifndef C908_PLIC_PHY_ADDR +#define C908_PLIC_PHY_ADDR (0xF00000000UL) +#endif + extern rt_atomic_t rt_interrupt_nest; extern rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; extern rt_uint32_t rt_thread_switch_interrupt_flag; @@ -26,13 +30,26 @@ static void rt_hw_interrupt_handler(int vector, void *param) rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); } +static void __isr(int irq) +{ + rt_isr_handler_t isr; + void *param; + + isr = isr_table[IRQ_OFFSET + irq].handler; + param = isr_table[IRQ_OFFSET + irq].param; + if (isr != RT_NULL) + { + isr(irq, param); + } +} + /** * This function will initialize hardware interrupt */ void rt_hw_interrupt_init(void) { /* init interrupt controller */ - plic_init(); + plic_init(C908_PLIC_PHY_ADDR, __isr); rt_int32_t idx; @@ -88,7 +105,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name) { rt_isr_handler_t old_handler = RT_NULL; - if ((vector < 0) || (vector > IRQ_MAX_NR)) + if ((vector < 0) || (vector >= IRQ_MAX_NR)) { return old_handler; } diff --git a/libcpu/risc-v/virt64/interrupt.c b/libcpu/risc-v/virt64/interrupt.c index f627210dac2..bf4471da8ac 100644 --- a/libcpu/risc-v/virt64/interrupt.c +++ b/libcpu/risc-v/virt64/interrupt.c @@ -15,7 +15,11 @@ #include "riscv.h" #include "interrupt.h" -struct rt_irq_desc irq_desc[MAX_HANDLERS]; +#ifndef PLIC_BASE_ADDR +#define PLIC_BASE_ADDR 0x0c000000 +#endif + +struct rt_irq_desc isr_table[INTERRUPTS_MAX]; static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param) { @@ -25,13 +29,13 @@ static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param) int rt_hw_plic_irq_enable(int irq_number) { - plic_irq_enable(irq_number); + plic_enable_irq(irq_number); return 0; } int rt_hw_plic_irq_disable(int irq_number) { - plic_irq_disable(irq_number); + plic_disable_irq(irq_number); return 0; } @@ -57,16 +61,16 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, { rt_isr_handler_t old_handler = RT_NULL; - if(vector < MAX_HANDLERS) + if(vector < INTERRUPTS_MAX) { - old_handler = irq_desc[vector].handler; + old_handler = isr_table[vector].handler; if (handler != RT_NULL) { - irq_desc[vector].handler = (rt_isr_handler_t)handler; - irq_desc[vector].param = param; + isr_table[vector].handler = (rt_isr_handler_t)handler; + isr_table[vector].param = param; #ifdef RT_USING_INTERRUPT_INFO - rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name); - irq_desc[vector].counter = 0; + rt_snprintf(isr_table[vector].name, RT_NAME_MAX - 1, "%s", name); + isr_table[vector].counter = 0; #endif } } @@ -74,19 +78,35 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, return old_handler; } -void rt_hw_interrupt_init() +static void __isr(int irq) +{ + rt_isr_handler_t isr; + void *param; + + isr = isr_table[IRQ_OFFSET + irq].handler; + param = isr_table[IRQ_OFFSET + irq].param; + if (isr != RT_NULL) + { + isr(irq, param); + } +} + +void rt_hw_interrupt_init(void) { /* Enable machine external interrupts. */ // set_csr(sie, SIP_SEIP); int idx = 0; + + plic_init(PLIC_BASE_ADDR, __isr); + /* init exceptions table */ - for (idx = 0; idx < MAX_HANDLERS; idx++) + for (idx = 0; idx < INTERRUPTS_MAX; idx++) { - irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; - irq_desc[idx].param = RT_NULL; + isr_table[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; + isr_table[idx].param = RT_NULL; #ifdef RT_USING_INTERRUPT_INFO - rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default"); - irq_desc[idx].counter = 0; + rt_snprintf(isr_table[idx].name, RT_NAME_MAX - 1, "default"); + isr_table[idx].counter = 0; #endif } diff --git a/libcpu/risc-v/virt64/interrupt.h b/libcpu/risc-v/virt64/interrupt.h index 5b7ff57a476..f4d057a31d0 100644 --- a/libcpu/risc-v/virt64/interrupt.h +++ b/libcpu/risc-v/virt64/interrupt.h @@ -11,11 +11,17 @@ #ifndef INTERRUPT_H__ #define INTERRUPT_H__ -#define MAX_HANDLERS 128 - #include #include "stack.h" +#define NR_CPUS 1 + +#define IRQ_OFFSET 0 +#ifndef IRQ_MAX_NR +#define IRQ_MAX_NR 128 +#endif +#define INTERRUPTS_MAX (IRQ_OFFSET + IRQ_MAX_NR) + enum { EP_INSTRUCTION_ADDRESS_MISALIGNED = 0, diff --git a/libcpu/risc-v/virt64/plic.c b/libcpu/risc-v/virt64/plic.c deleted file mode 100644 index f222146f34d..00000000000 --- a/libcpu/risc-v/virt64/plic.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-20 bigmagic first version - * 2022-09-16 WangXiaoyao Porting to rv64 - */ -#include -#include -#include -#include "plic.h" -#include -#include "encoding.h" -#include - -#include -#include -#include - -#ifdef RT_USING_SMART -#include -#else -#define rt_ioremap(addr, ...) (addr) -#endif - -size_t plic_base = 0x0c000000L; - -/* - * Each PLIC interrupt source can be assigned a priority by writing - * to its 32-bit memory-mapped priority register. - * The QEMU-virt (the same as FU540-C000) supports 7 levels of priority. - * A priority value of 0 is reserved to mean "never interrupt" and - * effectively disables the interrupt. - * Priority 1 is the lowest active priority, and priority 7 is the highest. - * Ties between global interrupts of the same priority are broken by - * the Interrupt ID; interrupts with the lowest ID have the highest - * effective priority. - */ -void plic_set_priority(int irq, int priority) -{ - *(uint32_t *)PLIC_PRIORITY(irq) = priority; -} - -/* - * Each global interrupt can be enabled by setting the corresponding - * bit in the enables registers. - */ -void plic_irq_enable(int irq) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_ENABLE(hart) = ((*(uint32_t *)PLIC_ENABLE(hart)) | (1 << irq)); -#ifdef RISCV_S_MODE - set_csr(sie, read_csr(sie) | MIP_SEIP); -#else - set_csr(mie, read_csr(mie) | MIP_MEIP); -#endif -} - -void plic_irq_disable(int irq) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_ENABLE(hart) = (((*(uint32_t *)PLIC_ENABLE(hart)) & (~(1 << irq)))); -} - -/* - * PLIC will mask all interrupts of a priority less than or equal to threshold. - * Maximum threshold is 7. - * For example, a threshold value of zero permits all interrupts with - * non-zero priority, whereas a value of 7 masks all interrupts. - * Notice, the threshold is global for PLIC, not for each interrupt source. - */ -void plic_set_threshold(int threshold) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_THRESHOLD(hart) = threshold; -} - -/* - * DESCRIPTION: - * Query the PLIC what interrupt we should serve. - * Perform an interrupt claim by reading the claim register, which - * returns the ID of the highest-priority pending interrupt or zero if there - * is no pending interrupt. - * A successful claim also atomically clears the corresponding pending bit - * on the interrupt source. - * RETURN VALUE: - * the ID of the highest-priority pending interrupt or zero if there - * is no pending interrupt. - */ -int plic_claim(void) -{ - int hart = __raw_hartid(); - int irq = *(uint32_t *)PLIC_CLAIM(hart); - return irq; -} - -/* - * DESCRIPTION: - * Writing the interrupt ID it received from the claim (irq) to the - * complete register would signal the PLIC we've served this IRQ. - * The PLIC does not check whether the completion ID is the same as the - * last claim ID for that target. If the completion ID does not match an - * interrupt source that is currently enabled for the target, the completion - * is silently ignored. - * RETURN VALUE: none - */ -void plic_complete(int irq) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_COMPLETE(hart) = irq; -} - -void plic_set_ie(rt_uint32_t word_index, rt_uint32_t val) -{ - volatile void *plic_ie = (void *)(rt_ubase_t)(plic_base + PLIC_ENABLE_BASE + 0x80 + word_index * 4); - writel(val, plic_ie); -} - -static void _set_sie(int hartid) -{ - for (size_t i = hartid * WORD_CNT_BYTE; i < 32; i++) - plic_set_ie(i, 0xffffffff); -} - -void plic_init() -{ - // PLIC takes up 64 MB space - plic_base = (size_t)rt_ioremap((void *)plic_base, 64 * 1024 * 1024); - - plic_set_threshold(0); - - for (int i = 0; i < CONFIG_IRQ_NR; i++) - { - plic_set_priority(i, 1); - } - - // in a single core system, only current context was set - _set_sie(__raw_hartid()); -} - -extern struct rt_irq_desc irq_desc[MAX_HANDLERS]; -/* - * Handling an interrupt is a two-step process: first you claim the interrupt - * by reading the claim register, then you complete the interrupt by writing - * that source ID back to the same claim register. This automatically enables - * and disables the interrupt, so there's nothing else to do. - */ -void plic_handle_irq(void) -{ - int plic_irq = plic_claim(); - plic_complete(plic_irq); - irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param); -} diff --git a/libcpu/risc-v/virt64/plic.h b/libcpu/risc-v/virt64/plic.h deleted file mode 100644 index 314210c66b5..00000000000 --- a/libcpu/risc-v/virt64/plic.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-20 bigmagic first version - * 2021-10-20 bernard fix s-mode issue - */ - -#ifndef __PLIC_H__ -#define __PLIC_H__ - -#include -#include - -#define PLIC_PRIORITY_BASE 0x0 -#define PLIC_PENDING_BASE 0x1000 -#define PLIC_ENABLE_BASE 0x2000 -#define PLIC_CONTEXT_BASE 0x200000 - -extern size_t plic_base; - -#define VIRT_PLIC_BASE (plic_base) - -#define PLIC_PRIORITY_OFFSET (0x0) -#define PLIC_PENDING_OFFSET (0x1000) - -#define PLIC_ENABLE_STRIDE 0x80 -#define PLIC_CONTEXT_STRIDE 0x1000 - -#ifndef RISCV_S_MODE -#define PLIC_MENABLE_OFFSET (0x2000) -#define PLIC_MTHRESHOLD_OFFSET (0x200000) -#define PLIC_MCLAIM_OFFSET (0x200004) -#define PLIC_MCOMPLETE_OFFSET (0x200004) - -#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_MENABLE_OFFSET + (hart * 2) * PLIC_ENABLE_STRIDE) -#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_MTHRESHOLD_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_MCLAIM_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_MCOMPLETE_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) - -#else -#define PLIC_SENABLE_OFFSET (0x2000 + PLIC_ENABLE_STRIDE) -#define PLIC_STHRESHOLD_OFFSET (0x200000 + PLIC_CONTEXT_STRIDE) -#define PLIC_SCLAIM_OFFSET (0x200004 + PLIC_CONTEXT_STRIDE) -#define PLIC_SCOMPLETE_OFFSET (0x200004 + PLIC_CONTEXT_STRIDE) - -#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_SENABLE_OFFSET + (hart * 2) * PLIC_ENABLE_STRIDE) -#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_STHRESHOLD_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_SCLAIM_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_SCOMPLETE_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#endif - -#define PLIC_PRIORITY(id) (VIRT_PLIC_BASE + PLIC_PRIORITY_OFFSET + (id) * 4) -#define PLIC_PENDING(id) (VIRT_PLIC_BASE + PLIC_PENDING_OFFSET + ((id) / 32)) - -#define WORD_CNT_BYTE (1024 / 8) - -/* IRQ config in system, max 1024 (from 0 to 1023) */ -#define CONFIG_IRQ_NR (128) -#define CONFIG_IRQ_WORD (CONFIG_IRQ_NR / 32) - -void plic_set_priority(int irq, int priority); -void plic_irq_enable(int irq); -void plic_irq_disable(int irq); -void plic_set_threshold(int mthreshold); -int plic_claim(void); -void plic_complete(int irq); - -void plic_set_thresh(rt_uint32_t val); -void plic_set_ie(rt_uint32_t word_index,rt_uint32_t val); -void plic_init(); -void plic_handle_irq(void); - -#endif