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 ca5934b4f3f..1bca6345384 100644 --- a/libcpu/risc-v/SConscript +++ b/libcpu/risc-v/SConscript @@ -13,6 +13,7 @@ list = os.listdir(cwd) # add common code files if rtconfig.CPU in common64_arch : group += SConscript(os.path.join('common64', 'SConscript')) + group += SConscript(os.path.join('plic', 'SConscript')) else : group += SConscript(os.path.join('common', 'SConscript')) diff --git a/libcpu/risc-v/common64/interrupt.c b/libcpu/risc-v/common64/interrupt.c new file mode 100644 index 00000000000..06c7a123ac6 --- /dev/null +++ b/libcpu/risc-v/common64/interrupt.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/01 Bernard The first version + * 2018/12/27 Jesven Change irq enable/disable to cpu0 + */ +#include +#include +#include +#include "encoding.h" +#include "riscv.h" +#include "interrupt.h" + +#ifdef RT_USING_SMART +#include +#endif + +/* TODO define PLIC_PHY_ADDR in BSP and remove me */ +#ifdef C908_PLIC_PHY_ADDR +#define PLIC_PHY_ADDR C908_PLIC_PHY_ADDR +#elif defined(C906_PLIC_PHY_ADDR) +#define PLIC_PHY_ADDR C906_PLIC_PHY_ADDR +#elif !defined(PLIC_PHY_ADDR) +#define PLIC_PHY_ADDR 0x0c000000L +#endif + +static struct rt_irq_desc isr_table[INTERRUPTS_MAX]; +static struct plic_handler plic_handlers[1]; + +rt_inline struct plic_handler *plic_handler_get(void) +{ + return &plic_handlers[0]; +} + +static void plic_init(void) +{ + void *plic_base = (void *)PLIC_PHY_ADDR; + +#ifdef RT_USING_SMART + // PLIC takes up 64 MB space + plic_base = rt_ioremap(plic_base, 64 * 1024 * 1024); +#endif + /* skip contexts other than supervisor external interrupt */ + plic_handler_init(plic_handler_get(), plic_base, 1); + + plic_set_threshold(plic_handler_get(), 0); +} + +static void rt_hw_interrupt_handle(int vector, void *param) +{ + rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector); +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + if ((vector < 0) || (vector > IRQ_MAX_NR)) + { + return; + } + + plic_irq_disable(plic_handler_get(), vector); +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + if ((vector < 0) || (vector > IRQ_MAX_NR)) + { + return; + } + + plic_set_priority(plic_handler_get(), vector, 1); + + plic_irq_enable(plic_handler_get(), vector); +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +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)) + { + return old_handler; + } + + old_handler = isr_table[IRQ_OFFSET + vector].handler; + + isr_table[IRQ_OFFSET + vector].handler = handler; + isr_table[IRQ_OFFSET + vector].param = param; + + return old_handler; +} + +void rt_hw_interrupt_init(void) +{ + /* init exceptions table */ + for (int idx = 0; idx < INTERRUPTS_MAX; idx++) + { + isr_table[idx].handler = rt_hw_interrupt_handle; + isr_table[idx].param = RT_NULL; + } + + plic_init(); + + /* Enable supervisor external interrupts. */ + set_csr(sie, SIE_SEIE); +} + +/* + * 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) +{ + struct plic_handler *plic; + rt_isr_handler_t isr; + void *param; + int irq; + + plic = plic_handler_get(); + + while ((irq = plic_claim(plic))) + { + isr = isr_table[IRQ_OFFSET + irq].handler; + param = isr_table[IRQ_OFFSET + irq].param; + if (isr) + { + isr(irq, param); + } + + plic_complete(plic, irq); + } +} diff --git a/libcpu/risc-v/virt64/interrupt.h b/libcpu/risc-v/common64/interrupt.h similarity index 76% rename from libcpu/risc-v/virt64/interrupt.h rename to libcpu/risc-v/common64/interrupt.h index 5b7ff57a476..08ce1c1d9a6 100644 --- a/libcpu/risc-v/virt64/interrupt.h +++ b/libcpu/risc-v/common64/interrupt.h @@ -11,10 +11,11 @@ #ifndef INTERRUPT_H__ #define INTERRUPT_H__ -#define MAX_HANDLERS 128 - -#include -#include "stack.h" +#define IRQ_OFFSET 16 +#ifndef IRQ_MAX_NR +#define IRQ_MAX_NR 200 +#endif +#define INTERRUPTS_MAX (IRQ_OFFSET + IRQ_MAX_NR) enum { @@ -33,14 +34,14 @@ enum EP_INSTRUCTION_PAGE_FAULT, /* page attr */ EP_LOAD_PAGE_FAULT, /* read data */ EP_RESERVED14, - EP_STORE_PAGE_FAULT, /* write data */ + EP_STORE_PAGE_FAULT, /* write data */ }; -int rt_hw_plic_irq_enable(int irq_number); -int rt_hw_plic_irq_disable(int irq_number); void rt_hw_interrupt_init(void); void rt_hw_interrupt_mask(int vector); +void rt_hw_interrupt_umask(int vector); rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name); -void handle_trap(rt_ubase_t xcause, rt_ubase_t xtval, rt_ubase_t xepc, struct rt_hw_stack_frame *sp); + +void plic_handle_irq(void); #endif diff --git a/libcpu/risc-v/plic/SConscript b/libcpu/risc-v/plic/SConscript new file mode 100644 index 00000000000..10630c92f70 --- /dev/null +++ b/libcpu/risc-v/plic/SConscript @@ -0,0 +1,12 @@ +# RT-Thread building script for component + +from building import * +cwd = GetCurrentDir() +src = [] +CPPPATH = [] + +src += Glob('*.c') +CPPPATH += [cwd] + +group = DefineGroup('libcpu', src, depend = [], CPPPATH = CPPPATH) +Return('group') diff --git a/libcpu/risc-v/plic/plic.c b/libcpu/risc-v/plic/plic.c new file mode 100644 index 00000000000..8da0aa744bb --- /dev/null +++ b/libcpu/risc-v/plic/plic.c @@ -0,0 +1,133 @@ +/* + * 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 "plic.h" +#include + +/* + * Each interrupt source has a priority register associated with it. + * We always hardwire it to one in Linux. + */ +#define PRIORITY_BASE 0 +#define PRIORITY_PER_ID 4 + +/* + * Each hart context has a vector of interrupt enable bits associated with it. + * There's one bit for each interrupt source. + */ +#define CONTEXT_ENABLE_BASE 0x2000 +#define CONTEXT_ENABLE_SIZE 0x80 + +/* + * Each hart context has a set of control registers associated with it. Right + * now there's only two: a source priority threshold over which the hart will + * take an interrupt, and a register to claim interrupts. + */ +#define CONTEXT_BASE 0x200000 +#define CONTEXT_SIZE 0x1000 +#define CONTEXT_THRESHOLD 0x00 +#define CONTEXT_CLAIM 0x04 + +static void plic_toggle(struct plic_handler *handler, unsigned int irq, int enable) +{ + void *reg = handler->enable_base + (irq / 32) * sizeof(unsigned int); + unsigned int hwirq_mask = 1 << (irq % 32); + + if (enable) + writel(readl(reg) | hwirq_mask, reg); + else + writel(readl(reg) & ~hwirq_mask, reg); +} + +/* + * 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(struct plic_handler *handler, int irq, int priority) +{ + writel(priority, handler->base + PRIORITY_BASE + irq * PRIORITY_PER_ID); +} + +/* + * Each global interrupt can be enabled by setting the corresponding + * bit in the enables registers. + */ +void plic_irq_enable(struct plic_handler *handler, int irq) +{ + plic_toggle(handler, irq, 1); +} + +void plic_irq_disable(struct plic_handler *handler, int irq) +{ + plic_toggle(handler, irq, 1); +} + +/* + * 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(struct plic_handler *handler, int threshold) +{ + writel(threshold, handler->hart_base + CONTEXT_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(struct plic_handler *handler) +{ + void *claim = handler->hart_base + CONTEXT_CLAIM; + + return readl(claim); +} + +/* + * 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(struct plic_handler *handler, int irq) +{ + void *claim = handler->hart_base + CONTEXT_CLAIM; + + writel(irq, claim); +} + +void plic_handler_init(struct plic_handler *handler, void *base, unsigned int context_id) +{ + handler->base = base; + handler->hart_base = base + CONTEXT_BASE + context_id * CONTEXT_SIZE; + handler->enable_base = base + CONTEXT_ENABLE_BASE + context_id * CONTEXT_ENABLE_SIZE; +} diff --git a/libcpu/risc-v/plic/plic.h b/libcpu/risc-v/plic/plic.h new file mode 100644 index 00000000000..b4189251f17 --- /dev/null +++ b/libcpu/risc-v/plic/plic.h @@ -0,0 +1,30 @@ +/* + * 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__ + +struct plic_handler +{ + void *base; + void *hart_base; + void *enable_base; +}; + +void plic_set_priority(struct plic_handler *handler, int irq, int priority); +void plic_irq_enable(struct plic_handler *handler, int irq); +void plic_irq_disable(struct plic_handler *handler, int irq); +void plic_set_threshold(struct plic_handler *handler, int mthreshold); +int plic_claim(struct plic_handler *handler); +void plic_complete(struct plic_handler *handler, int irq); +void plic_handler_init(struct plic_handler *handler, void *base, unsigned int context_id); + +#endif diff --git a/libcpu/risc-v/t-head/c906/interrupt.c b/libcpu/risc-v/t-head/c906/interrupt.c deleted file mode 100644 index 2f7a86e6802..00000000000 --- a/libcpu/risc-v/t-head/c906/interrupt.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - */ - -#include -#include - -#include "interrupt.h" -#include "riscv.h" -#include "plic.h" - -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; - -struct rt_irq_desc isr_table[INTERRUPTS_MAX]; - -static void rt_hw_interrupt_handler(int vector, void *param) -{ - rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); -} - -/** - * This function will initialize hardware interrupt - */ -void rt_hw_interrupt_init(void) -{ - /* init interrupt controller */ - plic_init(); - - rt_int32_t idx; - - rt_memset(isr_table, 0x00, sizeof(isr_table)); - for (idx = 0; idx < INTERRUPTS_MAX; idx++) - { - isr_table[idx].handler = rt_hw_interrupt_handler; - } - - /* init interrupt nest, and context in thread sp */ - rt_interrupt_nest = 0; - rt_interrupt_from_thread = 0; - rt_interrupt_to_thread = 0; - rt_thread_switch_interrupt_flag = 0; -} - -/** - * This function will mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_mask(int vector) -{ - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return; - } - plic_disable_irq(vector); -} - -/** - - * This function will un-mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_umask(int vector) -{ - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return; - } - plic_enable_irq(vector); -} - -/** - * This function will install a interrupt service routine to a interrupt. - * @param vector the interrupt number - * @param handler the interrupt service routine to be installed - * @param param the interrupt service function parameter - * @param name the interrupt name - * @return old handler - */ -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)) - { - return old_handler; - } - - old_handler = isr_table[IRQ_OFFSET + vector].handler; - -#ifdef RT_USING_INTERRUPT_INFO - rt_strncpy(isr_table[IRQ_OFFSET + vector].name, name, RT_NAME_MAX); -#endif /* RT_USING_INTERRUPT_INFO */ - isr_table[IRQ_OFFSET + vector].handler = handler; - isr_table[IRQ_OFFSET + vector].param = param; - - return old_handler; -} diff --git a/libcpu/risc-v/t-head/c906/interrupt.h b/libcpu/risc-v/t-head/c906/interrupt.h deleted file mode 100644 index bdc98972b2c..00000000000 --- a/libcpu/risc-v/t-head/c906/interrupt.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - */ - -#ifndef __INTERRUPT_H__ -#define __INTERRUPT_H__ - -#include - -#define NR_CPUS 1 - -#define IRQ_OFFSET 16 -#ifndef IRQ_MAX_NR -#define IRQ_MAX_NR 207 -#endif -#define INTERRUPTS_MAX (IRQ_OFFSET + IRQ_MAX_NR) - -enum { - EP_INSTRUCTION_ADDRESS_MISALIGNED = 0, - EP_INSTRUCTION_ACCESS_FAULT, - EP_ILLEGAL_INSTRUCTION, - EP_BREAKPOINT, - EP_LOAD_ADDRESS_MISALIGNED, - EP_LOAD_ACCESS_FAULT, - EP_STORE_ADDRESS_MISALIGNED, - EP_STORE_ACCESS_FAULT, - EP_ENVIRONMENT_CALL_U_MODE, - EP_ENVIRONMENT_CALL_S_MODE, - EP_RESERVED10, - EP_ENVIRONMENT_CALL_M_MODE, - EP_INSTRUCTION_PAGE_FAULT, /* page attr */ - EP_LOAD_PAGE_FAULT, /* read data */ - EP_RESERVED14, - EP_STORE_PAGE_FAULT, /* write data */ -}; - -void rt_hw_interrupt_init(void); -void rt_hw_interrupt_mask(int vector); -void rt_hw_interrupt_umask(int vector); -rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name); - -#endif diff --git a/libcpu/risc-v/t-head/c906/plic.c b/libcpu/risc-v/t-head/c906/plic.c deleted file mode 100644 index 829ee9e4fd4..00000000000 --- a/libcpu/risc-v/t-head/c906/plic.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - * 2021-11-12 JasonHu fix bug that not intr on f133 - * 2023-04-22 flyingcys add plic register ioremap - */ - -#include - -#include - -#include "plic.h" -#include "interrupt.h" -#include "io.h" -#include "encoding.h" -#include "ioremap.h" - -static void *c906_plic_regs = RT_NULL; -extern struct rt_irq_desc isr_table[]; - -struct plic_handler -{ - rt_bool_t present; - void *hart_base; - void *enable_base; -}; - -rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable); -struct plic_handler c906_plic_handlers[C906_NR_CPUS]; -static void *c906_irq_priority[INTERRUPTS_MAX] = {RT_NULL}; - -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)c906_plic_regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID); -#ifdef RT_USING_SMART - if (c906_irq_priority[hwirq] == RT_NULL) - { - c906_irq_priority[hwirq] = (void *)rt_ioremap(priority_addr, 0x1000); - } - priority_addr = c906_irq_priority[hwirq]; -#endif - writel(enable, priority_addr); - struct plic_handler *handler = &c906_plic_handlers[cpu]; - - if (handler->present) - { - plic_toggle(handler, hwirq, 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 - { - LOG_W("no irq!\n"); - return; - } - isr = isr_table[IRQ_OFFSET + irq].handler; - param = isr_table[IRQ_OFFSET + irq].param; - if (isr != RT_NULL) - { - isr(irq, param); - } - /* complete irq. */ - plic_complete(irq); -} - -void plic_complete(int irqno) -{ - int cpu = 0; - struct plic_handler *handler = &c906_plic_handlers[cpu]; - - writel(irqno, (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM)); -} - -void plic_disable_irq(int irqno) -{ - plic_irq_toggle(irqno, 0); -} - -void plic_enable_irq(int irqno) -{ - plic_irq_toggle(irqno, 1); -} - -/* - * 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 cpu = 0; - unsigned int irq; - - struct plic_handler *handler = &c906_plic_handlers[cpu]; - void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM); - - if (c906_plic_regs == RT_NULL || !handler->present) - { - LOG_E("plic state not initialized."); - return; - } - - clear_csr(sie, SIE_SEIE); - - while ((irq = readl(claim))) - { - /* ID0 is diabled permantually from spec. */ - if (irq == 0) - { - LOG_E("irq no is zero."); - } - else - { - generic_handle_irq(irq); - } - } - set_csr(sie, SIE_SEIE); -} - -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); - - if (enable) - { - writel(readl(reg) | hwirq_mask, reg); - } - else - { - writel(readl(reg) & ~hwirq_mask, reg); - } -} - -void plic_init(void) -{ - int nr_irqs; - int nr_context; - int i; - unsigned long hwirq; - int cpu = 0; - - if (c906_plic_regs) - { - LOG_E("plic already initialized!"); - return; - } - - nr_context = C906_NR_CONTEXT; - - c906_plic_regs = (void *)C906_PLIC_PHY_ADDR; - if (!c906_plic_regs) - { - LOG_E("fatal error, plic is reg space is null."); - return; - } - - nr_irqs = C906_PLIC_NR_EXT_IRQS; - - for (i = 0; i < nr_context; i ++) - { - struct plic_handler *handler; - uint32_t threshold = 0; - - cpu = 0; - - /* skip contexts other than supervisor external interrupt */ - if (i == 0) - { - continue; - } - - // we always use CPU0 M-mode target register. - handler = &c906_plic_handlers[cpu]; - if (handler->present) - { - threshold = 0xffffffff; - goto done; - } - - handler->present = RT_TRUE; - handler->hart_base = (void *)((rt_size_t)c906_plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART); - handler->enable_base = (void *)((rt_size_t)c906_plic_regs + ENABLE_BASE + i * ENABLE_PER_HART); -#ifdef RT_USING_SMART - handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000); - handler->enable_base = (void *)rt_ioremap(handler->enable_base, 0x1000); -#endif -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++) - { - plic_toggle(handler, hwirq, 0); - } - } - - /* Enable supervisor external interrupts. */ - set_csr(sie, SIE_SEIE); -} diff --git a/libcpu/risc-v/t-head/c906/plic.h b/libcpu/risc-v/t-head/c906/plic.h deleted file mode 100644 index 93235279e2c..00000000000 --- a/libcpu/risc-v/t-head/c906/plic.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - * 2023-04-22 flyingcys add C906_PLIC_PHY_ADDR macro judge - */ - -#ifndef __RISCV64_PLIC_H__ -#define __RISCV64_PLIC_H__ - -#include - -#ifndef C906_PLIC_PHY_ADDR -#define C906_PLIC_PHY_ADDR (0x10000000) -#endif -#define C906_PLIC_NR_EXT_IRQS (IRQ_MAX_NR) -#define C906_NR_CPUS (NR_CPUS) - -/* M and S mode context. */ -#define C906_NR_CONTEXT (2) - -#define MAX_DEVICES 1024 -#define MAX_CONTEXTS 15872 - -/* - * Each interrupt source has a priority register associated with it. - * We always hardwire it to one in Linux. - */ -#define PRIORITY_BASE 0 -#define PRIORITY_PER_ID 4 - -/* - * Each hart context has a vector of interrupt enable bits associated with it. - * There's one bit for each interrupt source. - */ -#define ENABLE_BASE 0x2000 -#define ENABLE_PER_HART 0x80 - -/* - * Each hart context has a set of control registers associated with it. Right - * now there's only two: a source priority threshold over which the hart will - * take an interrupt, and a register to claim interrupts. - */ -#define CONTEXT_BASE 0x200000 -#define CONTEXT_PER_HART 0x1000 -#define CONTEXT_THRESHOLD 0x00 -#define CONTEXT_CLAIM 0x04 - -void plic_init(void); -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); - -#endif diff --git a/libcpu/risc-v/t-head/c908/interrupt.c b/libcpu/risc-v/t-head/c908/interrupt.c deleted file mode 100644 index 2f7a86e6802..00000000000 --- a/libcpu/risc-v/t-head/c908/interrupt.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - */ - -#include -#include - -#include "interrupt.h" -#include "riscv.h" -#include "plic.h" - -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; - -struct rt_irq_desc isr_table[INTERRUPTS_MAX]; - -static void rt_hw_interrupt_handler(int vector, void *param) -{ - rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); -} - -/** - * This function will initialize hardware interrupt - */ -void rt_hw_interrupt_init(void) -{ - /* init interrupt controller */ - plic_init(); - - rt_int32_t idx; - - rt_memset(isr_table, 0x00, sizeof(isr_table)); - for (idx = 0; idx < INTERRUPTS_MAX; idx++) - { - isr_table[idx].handler = rt_hw_interrupt_handler; - } - - /* init interrupt nest, and context in thread sp */ - rt_interrupt_nest = 0; - rt_interrupt_from_thread = 0; - rt_interrupt_to_thread = 0; - rt_thread_switch_interrupt_flag = 0; -} - -/** - * This function will mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_mask(int vector) -{ - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return; - } - plic_disable_irq(vector); -} - -/** - - * This function will un-mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_umask(int vector) -{ - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return; - } - plic_enable_irq(vector); -} - -/** - * This function will install a interrupt service routine to a interrupt. - * @param vector the interrupt number - * @param handler the interrupt service routine to be installed - * @param param the interrupt service function parameter - * @param name the interrupt name - * @return old handler - */ -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)) - { - return old_handler; - } - - old_handler = isr_table[IRQ_OFFSET + vector].handler; - -#ifdef RT_USING_INTERRUPT_INFO - rt_strncpy(isr_table[IRQ_OFFSET + vector].name, name, RT_NAME_MAX); -#endif /* RT_USING_INTERRUPT_INFO */ - isr_table[IRQ_OFFSET + vector].handler = handler; - isr_table[IRQ_OFFSET + vector].param = param; - - return old_handler; -} diff --git a/libcpu/risc-v/t-head/c908/interrupt.h b/libcpu/risc-v/t-head/c908/interrupt.h deleted file mode 100644 index 2ee08248375..00000000000 --- a/libcpu/risc-v/t-head/c908/interrupt.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - */ - -#ifndef __INTERRUPT_H__ -#define __INTERRUPT_H__ - -#include - -#define NR_CPUS 1 - -#define IRQ_OFFSET 16 -#ifndef IRQ_MAX_NR -#define IRQ_MAX_NR 200 -#endif -#define INTERRUPTS_MAX (IRQ_OFFSET + IRQ_MAX_NR) - -enum { - EP_INSTRUCTION_ADDRESS_MISALIGNED = 0, - EP_INSTRUCTION_ACCESS_FAULT, - EP_ILLEGAL_INSTRUCTION, - EP_BREAKPOINT, - EP_LOAD_ADDRESS_MISALIGNED, - EP_LOAD_ACCESS_FAULT, - EP_STORE_ADDRESS_MISALIGNED, - EP_STORE_ACCESS_FAULT, - EP_ENVIRONMENT_CALL_U_MODE, - EP_ENVIRONMENT_CALL_S_MODE, - EP_RESERVED10, - EP_ENVIRONMENT_CALL_M_MODE, - EP_INSTRUCTION_PAGE_FAULT, /* page attr */ - EP_LOAD_PAGE_FAULT, /* read data */ - EP_RESERVED14, - EP_STORE_PAGE_FAULT, /* write data */ -}; - -void rt_hw_interrupt_init(void); -void rt_hw_interrupt_mask(int vector); -void rt_hw_interrupt_umask(int vector); -rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name); - -#endif diff --git a/libcpu/risc-v/t-head/c908/plic.c b/libcpu/risc-v/t-head/c908/plic.c deleted file mode 100644 index 08cb6c18d2f..00000000000 --- a/libcpu/risc-v/t-head/c908/plic.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - * 2021-11-12 JasonHu fix bug that not intr on f133 - * 2023-04-22 flyingcys add plic register ioremap - */ - -#include - -#include - -#include "plic.h" -#include "interrupt.h" -#include "io.h" -#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; -}; - -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 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]; - - if (handler->present) - { - plic_toggle(handler, hwirq, 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 - { - LOG_W("no irq!\n"); - return; - } - isr = isr_table[IRQ_OFFSET + irq].handler; - param = isr_table[IRQ_OFFSET + irq].param; - if (isr != RT_NULL) - { - isr(irq, param); - } - /* complete irq. */ - plic_complete(irq); -} - -void plic_complete(int irqno) -{ - int cpu = 0; - struct plic_handler *handler = &plic_handlers[cpu]; - - writel(irqno, (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM)); -} - -void plic_disable_irq(int irqno) -{ - plic_irq_toggle(irqno, 0); -} - -void plic_enable_irq(int irqno) -{ - plic_irq_toggle(irqno, 1); -} - -/* - * 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 cpu = 0; - unsigned int irq; - - struct plic_handler *handler = &plic_handlers[cpu]; - void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM); - - if (plic_regs == RT_NULL || !handler->present) - { - LOG_E("plic state not initialized."); - return; - } - - clear_csr(sie, SIE_SEIE); - - while ((irq = readl(claim))) - { - /* ID0 is diabled permantually from spec. */ - if (irq == 0) - { - LOG_E("irq no is zero."); - } - else - { - generic_handle_irq(irq); - } - } - set_csr(sie, SIE_SEIE); -} - -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); - - if (enable) - { - writel(readl(reg) | hwirq_mask, reg); - } - else - { - writel(readl(reg) & ~hwirq_mask, reg); - } -} - -void plic_init(void) -{ - int nr_irqs; - int nr_context; - int i; - unsigned long hwirq; - int cpu = 0; - - if (plic_regs) - { - LOG_E("plic already initialized!"); - return; - } - - nr_context = C908_NR_CONTEXT; - - plic_regs = (void *)C908_PLIC_PHY_ADDR; - if (!plic_regs) - { - LOG_E("fatal error, plic is reg space is null."); - return; - } - - nr_irqs = C908_PLIC_NR_EXT_IRQS; - - for (i = 0; i < nr_context; i ++) - { - struct plic_handler *handler; - uint32_t threshold = 0; - - cpu = 0; - - /* skip contexts other than supervisor external interrupt */ - if (i == 0) - { - continue; - } - - // we always use CPU0 M-mode target register. - handler = &plic_handlers[cpu]; - if (handler->present) - { - 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); -#ifdef RT_USING_SMART - handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000); - handler->enable_base = (void *)rt_ioremap(handler->enable_base, 0x1000); -#endif -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++) - { - plic_toggle(handler, hwirq, 0); - } - } - - /* Enable supervisor external interrupts. */ - set_csr(sie, SIE_SEIE); -} diff --git a/libcpu/risc-v/t-head/c908/plic.h b/libcpu/risc-v/t-head/c908/plic.h deleted file mode 100644 index 94f00eacdb8..00000000000 --- a/libcpu/risc-v/t-head/c908/plic.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - * 2023-04-22 flyingcys add C906_PLIC_PHY_ADDR macro judge - */ - -#ifndef __RISCV64_PLIC_H__ -#define __RISCV64_PLIC_H__ - -#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 MAX_DEVICES 1024 -#define MAX_CONTEXTS 15872 - -/* - * Each interrupt source has a priority register associated with it. - * We always hardwire it to one in Linux. - */ -#define PRIORITY_BASE 0 -#define PRIORITY_PER_ID 4 - -/* - * Each hart context has a vector of interrupt enable bits associated with it. - * There's one bit for each interrupt source. - */ -#define ENABLE_BASE 0x2000 -#define ENABLE_PER_HART 0x80 - -/* - * Each hart context has a set of control registers associated with it. Right - * now there's only two: a source priority threshold over which the hart will - * take an interrupt, and a register to claim interrupts. - */ -#define CONTEXT_BASE 0x200000 -#define CONTEXT_PER_HART 0x1000 -#define CONTEXT_THRESHOLD 0x00 -#define CONTEXT_CLAIM 0x04 - -void plic_init(void); -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); - -#endif diff --git a/libcpu/risc-v/virt64/interrupt.c b/libcpu/risc-v/virt64/interrupt.c deleted file mode 100644 index f627210dac2..00000000000 --- a/libcpu/risc-v/virt64/interrupt.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018/10/01 Bernard The first version - * 2018/12/27 Jesven Change irq enable/disable to cpu0 - */ -#include -#include -#include "tick.h" -#include "encoding.h" -#include "riscv.h" -#include "interrupt.h" - -struct rt_irq_desc irq_desc[MAX_HANDLERS]; - -static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param) -{ - rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector); - return RT_NULL; -} - -int rt_hw_plic_irq_enable(int irq_number) -{ - plic_irq_enable(irq_number); - return 0; -} - -int rt_hw_plic_irq_disable(int irq_number) -{ - plic_irq_disable(irq_number); - return 0; -} - -/** - * This function will un-mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_umask(int vector) -{ - plic_set_priority(vector, 1); - - rt_hw_plic_irq_enable(vector); -} - -/** - * This function will install a interrupt service routine to a interrupt. - * @param vector the interrupt number - * @param new_handler the interrupt service routine to be installed - * @param old_handler the old interrupt service routine - */ -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 < MAX_HANDLERS) - { - old_handler = irq_desc[vector].handler; - if (handler != RT_NULL) - { - irq_desc[vector].handler = (rt_isr_handler_t)handler; - irq_desc[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; -#endif - } - } - - return old_handler; -} - -void rt_hw_interrupt_init() -{ - /* Enable machine external interrupts. */ - // set_csr(sie, SIP_SEIP); - int idx = 0; - /* init exceptions table */ - for (idx = 0; idx < MAX_HANDLERS; idx++) - { - irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; - irq_desc[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; -#endif - } - - plic_set_threshold(0); -} diff --git a/libcpu/risc-v/virt64/plic.c b/libcpu/risc-v/virt64/plic.c deleted file mode 100644 index 8aab8b1292b..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_VIRT64_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 a13b6d96222..00000000000 --- a/libcpu/risc-v/virt64/plic.h +++ /dev/null @@ -1,80 +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 - -/* RT-Thread runs in S-mode on virt64 by default */ -#define RISCV_VIRT64_S_MODE - -#ifndef RISCV_VIRT64_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