diff --git a/board/avaota-f1/cdk/avaota_f1.cdkproj b/board/avaota-f1/cdk/avaota_f1.cdkproj index 9f8ae57d..3c34cccd 100644 --- a/board/avaota-f1/cdk/avaota_f1.cdkproj +++ b/board/avaota-f1/cdk/avaota_f1.cdkproj @@ -238,6 +238,7 @@ + @@ -276,6 +277,9 @@ + + + @@ -507,6 +511,9 @@ + + + @@ -534,6 +541,17 @@ + + + 0x20181C8;;; + ;;32;;MHZ;;up + + 1 + 1 + + 100:4;100:8;100:8;100:8; + 1 + @@ -637,7 +655,7 @@ None (-O0) Maximum (-g3) - $(ProjectPath);../../../include/;../../../include/arch/riscv/;../../../include/cli/;../../../include/drivers/chips/sun300iw1/;../../../include/drivers/mmc/;../../../include/drivers/pmu/reg/;../../../include/drivers/pmu/;../../../include/drivers/reg/;../../../include/drivers/usb/;../../../include/image/;../../../include/lib/elf/;../../../include/lib/fatfs/;../../../include/lib/fdt/;../../../include/drivers/;../../../include/drivers/chips/;../../../include/drivers/mtd + $(ProjectPath);../../../include/;../../../include/arch/riscv/;../../../include/cli/;../../../include/drivers/chips/sun300iw1/;../../../include/drivers/mmc/;../../../include/drivers/pmu/reg/;../../../include/drivers/pmu/;../../../include/drivers/reg/;../../../include/drivers/usb/;../../../include/image/;../../../include/lib/elf/;../../../include/lib/fatfs/;../../../include/lib/fdt/;../../../include/drivers/;../../../include/drivers/chips/;../../../include/drivers/mtd/;../../../include/drivers/intc/ -nostdlib -nostdinc -march=rv32imafcxthead -mabi=ilp32f -Wno-int-to-pointer-cast -Wno-int-to-pointer-cast -Wno-shift-count-overflow -Wno-builtin-declaration-mismatch -Wno-pointer-to-int-cast -Wno-implicit-function-declaration -Wno-discarded-qualifiers -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wno-parentheses no no @@ -654,7 +672,7 @@ - $(ProjectPath);../../../include/;../../../include/arch/riscv/;../../../include/cli/;../../../include/drivers/chips/sun300iw1/;../../../include/drivers/mmc/;../../../include/drivers/pmu/reg/;../../../include/drivers/pmu/;../../../include/drivers/reg/;../../../include/drivers/usb/;../../../include/image/;../../../include/lib/elf/;../../../include/lib/fatfs/;../../../include/lib/fdt/;../../../include/drivers/;../../../include/drivers/chips/ + $(ProjectPath);../../../include/;../../../include/arch/riscv/;../../../include/cli/;../../../include/drivers/chips/sun300iw1/;../../../include/drivers/mmc/;../../../include/drivers/pmu/reg/;../../../include/drivers/pmu/;../../../include/drivers/reg/;../../../include/drivers/usb/;../../../include/image/;../../../include/lib/elf/;../../../include/lib/fatfs/;../../../include/lib/fdt/;../../../include/drivers/;../../../include/drivers/chips/;../../../include/drivers/intc/ none @@ -668,6 +686,8 @@ no start-group no + none + no yes @@ -723,12 +743,15 @@ + yes no 4444 no 6666 5000 + localhost + 3333 openocd-sifive latest @@ -751,15 +774,4 @@ - - - 0x20181C8;;; - ;;32;;MHZ;;up - - 1 - 1 - - 100:4;100:8;100:8;100:8; - 1 - diff --git a/board/avaota-f1/cdk/config.h b/board/avaota-f1/cdk/config.h index a53a0d5c..1af4787a 100644 --- a/board/avaota-f1/cdk/config.h +++ b/board/avaota-f1/cdk/config.h @@ -5,7 +5,7 @@ // Project Info #define PROJECT_NAME "SyterKit" -#define PROJECT_VERSION "0.3.0" +#define PROJECT_VERSION "0.4.0.2" #define PROJECT_GIT_HASH "58dcc02e" #define PROJECT_C_COMPILER "riscv64-unknown-elf-gcc" #define PROJECT_C_COMPILER_VERSION "10.4.0" diff --git a/board/avaota-f1/start.S b/board/avaota-f1/start.S index 209bfd3d..450170b6 100644 --- a/board/avaota-f1/start.S +++ b/board/avaota-f1/start.S @@ -179,87 +179,87 @@ vectors: mret /* - * IRQ vectors. - */ - .align 6 - .globl irq_handler + * IRQ vectors. + */ + .align 6 + .globl irq_handler irq_handler: - csrw mscratch, sp - addi sp, sp, -(37 * REGSZ) - SREG x1, 1 * REGSZ(x2) - SREG x3, 3 * REGSZ(x2) - SREG x4, 4 * REGSZ(x2) - SREG x5, 5 * REGSZ(x2) - SREG x6, 6 * REGSZ(x2) - SREG x7, 7 * REGSZ(x2) - SREG x8, 8 * REGSZ(x2) - SREG x9, 9 * REGSZ(x2) - SREG x10, 10 * REGSZ(x2) - SREG x11, 11 * REGSZ(x2) - SREG x12, 12 * REGSZ(x2) - SREG x13, 13 * REGSZ(x2) - SREG x14, 14 * REGSZ(x2) - SREG x15, 15 * REGSZ(x2) - SREG x16, 16 * REGSZ(x2) - SREG x17, 17 * REGSZ(x2) - SREG x18, 18 * REGSZ(x2) - SREG x19, 19 * REGSZ(x2) - SREG x20, 20 * REGSZ(x2) - SREG x21, 21 * REGSZ(x2) - SREG x22, 22 * REGSZ(x2) - SREG x23, 23 * REGSZ(x2) - SREG x24, 24 * REGSZ(x2) - SREG x25, 25 * REGSZ(x2) - SREG x26, 26 * REGSZ(x2) - SREG x27, 27 * REGSZ(x2) - SREG x28, 28 * REGSZ(x2) - SREG x29, 29 * REGSZ(x2) - SREG x30, 30 * REGSZ(x2) - SREG x31, 31 * REGSZ(x2) - csrrw t0, mscratch, x0 - csrr s0, mstatus - csrr t1, mepc - csrr t2, mbadaddr - csrr t3, mcause - SREG t0, 2 * REGSZ(x2) - SREG s0, 32 * REGSZ(x2) - SREG t1, 33 * REGSZ(x2) - SREG t2, 34 * REGSZ(x2) - SREG t3, 35 * REGSZ(x2) - li x5, -1 - SREG x5, 36 * REGSZ(x2) - move a0, sp - jal riscv_handle_exception - csrr a0, mscratch - LREG x1, 1 * REGSZ(a0) - LREG x2, 2 * REGSZ(a0) - LREG x3, 3 * REGSZ(a0) - LREG x4, 4 * REGSZ(a0) - LREG x5, 5 * REGSZ(a0) - LREG x6, 6 * REGSZ(a0) - LREG x7, 7 * REGSZ(a0) - LREG x8, 8 * REGSZ(a0) - LREG x9, 9 * REGSZ(a0) - LREG x11, 11 * REGSZ(a0) - LREG x12, 12 * REGSZ(a0) - LREG x13, 13 * REGSZ(a0) - LREG x14, 14 * REGSZ(a0) - LREG x15, 15 * REGSZ(a0) - LREG x16, 16 * REGSZ(a0) - LREG x17, 17 * REGSZ(a0) - LREG x18, 18 * REGSZ(a0) - LREG x19, 19 * REGSZ(a0) - LREG x20, 20 * REGSZ(a0) - LREG x21, 21 * REGSZ(a0) - LREG x22, 22 * REGSZ(a0) - LREG x23, 23 * REGSZ(a0) - LREG x24, 24 * REGSZ(a0) - LREG x25, 25 * REGSZ(a0) - LREG x26, 26 * REGSZ(a0) - LREG x27, 27 * REGSZ(a0) - LREG x28, 28 * REGSZ(a0) - LREG x29, 29 * REGSZ(a0) - LREG x30, 30 * REGSZ(a0) - LREG x31, 31 * REGSZ(a0) - LREG x10, 10 * REGSZ(a0) - mret + csrw mscratch, sp + addi sp, sp, -(37 * REGSZ) + SREG x1, 1 * REGSZ(x2) + SREG x3, 3 * REGSZ(x2) + SREG x4, 4 * REGSZ(x2) + SREG x5, 5 * REGSZ(x2) + SREG x6, 6 * REGSZ(x2) + SREG x7, 7 * REGSZ(x2) + SREG x8, 8 * REGSZ(x2) + SREG x9, 9 * REGSZ(x2) + SREG x10, 10 * REGSZ(x2) + SREG x11, 11 * REGSZ(x2) + SREG x12, 12 * REGSZ(x2) + SREG x13, 13 * REGSZ(x2) + SREG x14, 14 * REGSZ(x2) + SREG x15, 15 * REGSZ(x2) + SREG x16, 16 * REGSZ(x2) + SREG x17, 17 * REGSZ(x2) + SREG x18, 18 * REGSZ(x2) + SREG x19, 19 * REGSZ(x2) + SREG x20, 20 * REGSZ(x2) + SREG x21, 21 * REGSZ(x2) + SREG x22, 22 * REGSZ(x2) + SREG x23, 23 * REGSZ(x2) + SREG x24, 24 * REGSZ(x2) + SREG x25, 25 * REGSZ(x2) + SREG x26, 26 * REGSZ(x2) + SREG x27, 27 * REGSZ(x2) + SREG x28, 28 * REGSZ(x2) + SREG x29, 29 * REGSZ(x2) + SREG x30, 30 * REGSZ(x2) + SREG x31, 31 * REGSZ(x2) + csrrw t0, mscratch, x0 + csrr s0, mstatus + csrr t1, mepc + csrr t2, mbadaddr + csrr t3, mcause + SREG t0, 2 * REGSZ(x2) + SREG s0, 32 * REGSZ(x2) + SREG t1, 33 * REGSZ(x2) + SREG t2, 34 * REGSZ(x2) + SREG t3, 35 * REGSZ(x2) + li x5, -1 + SREG x5, 36 * REGSZ(x2) + move a0, sp + jal riscv_handle_exception + csrr a0, mscratch + LREG x1, 1 * REGSZ(a0) + LREG x2, 2 * REGSZ(a0) + LREG x3, 3 * REGSZ(a0) + LREG x4, 4 * REGSZ(a0) + LREG x5, 5 * REGSZ(a0) + LREG x6, 6 * REGSZ(a0) + LREG x7, 7 * REGSZ(a0) + LREG x8, 8 * REGSZ(a0) + LREG x9, 9 * REGSZ(a0) + LREG x11, 11 * REGSZ(a0) + LREG x12, 12 * REGSZ(a0) + LREG x13, 13 * REGSZ(a0) + LREG x14, 14 * REGSZ(a0) + LREG x15, 15 * REGSZ(a0) + LREG x16, 16 * REGSZ(a0) + LREG x17, 17 * REGSZ(a0) + LREG x18, 18 * REGSZ(a0) + LREG x19, 19 * REGSZ(a0) + LREG x20, 20 * REGSZ(a0) + LREG x21, 21 * REGSZ(a0) + LREG x22, 22 * REGSZ(a0) + LREG x23, 23 * REGSZ(a0) + LREG x24, 24 * REGSZ(a0) + LREG x25, 25 * REGSZ(a0) + LREG x26, 26 * REGSZ(a0) + LREG x27, 27 * REGSZ(a0) + LREG x28, 28 * REGSZ(a0) + LREG x29, 29 * REGSZ(a0) + LREG x30, 30 * REGSZ(a0) + LREG x31, 31 * REGSZ(a0) + LREG x10, 10 * REGSZ(a0) + mret diff --git a/include/arch/riscv/csr.h b/include/arch/riscv/csr.h index e7553f4d..bfb8d2b7 100644 --- a/include/arch/riscv/csr.h +++ b/include/arch/riscv/csr.h @@ -74,6 +74,12 @@ extern "C" { #define MIE_SEIE (1 << 9) /**< Supervisor External Interrupt Enable */ #define MIE_MEIE (1 << 11) /**< Machine External Interrupt Enable */ +/* RISC-V Privilege */ +#define PRV_U (0) +#define PRV_S (1) +#define PRV_H (2) +#define PRV_M (3) + /** * @brief Swap the value of a CSR with a new value. * diff --git a/include/drivers/intc/sys-clic.h b/include/drivers/intc/sys-clic.h new file mode 100644 index 00000000..87d55f7a --- /dev/null +++ b/include/drivers/intc/sys-clic.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _SYS_CLIC_H_ +#define _SYS_CLIC_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif// __cplusplus + +#define CLIC_IRQ_NUM (186) + +typedef enum irq_trigger_type { + IRQ_TRIGGER_TYPE_LEVEL, + IRQ_TRIGGER_TYPE_EDGE_RISING, + IRQ_TRIGGER_TYPE_EDGE_FALLING, + IRQ_TRIGGER_TYPE_EDGE_BOTH +} irq_trigger_type_t; + +typedef struct irq_controller { + uint16_t id; + uint16_t irq_cnt; + uint16_t parent_id; + uint16_t irq_id; + uint64_t reg_base_addr; +} irq_controller_t; + +/** + * @brief Handles the IRQ + * + */ +void do_irq(); + +/** + * @brief Initializes the interrupt mechanism + * + * @return 0 on success, or an error code + */ +int arch_interrupt_init(void); + +/** + * @brief Exits the interrupt mechanism + * + * @return 0 on success, or an error code + */ +int arch_interrupt_exit(void); + +#ifdef __cplusplus +} +#endif// __cplusplus + +#endif// _SYS_CLIC_H_ \ No newline at end of file diff --git a/include/drivers/reg/reg-clic.h b/include/drivers/reg/reg-clic.h new file mode 100644 index 00000000..67267453 --- /dev/null +++ b/include/drivers/reg/reg-clic.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __REG_CLIC_H__ +#define __REG_CLIC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif// __cplusplus + +/* RISC-V CLIC register offset */ +#define CLIC_CFG_REG_OFF 0x00 +#define CLIC_INFO_REG_OFF 0x04 + +#define CLIC_MINTTHRESH_REG_OFF 0x08 + +#define CLIC_INT_IP_REG_OFF 0x1000 +#define CLIC_INT_IE_REG_OFF 0x1001 +#define CLIC_INT_ATTR_REG_OFF 0x1002 +#define CLIC_INT_CTRL_REG_OFF 0x1003 + +#define CLIC_INT_REG_ADDR_INTERVAL 0x4 + +#define CLIC_INT_X_IP_REG_OFF(id) (0x1000 + ((id) *CLIC_INT_REG_ADDR_INTERVAL)) +#define CLIC_INT_X_IE_REG_OFF(id) (0x1001 + ((id) *CLIC_INT_REG_ADDR_INTERVAL)) +#define CLIC_INT_X_ATTR_REG_OFF(id) (0x1002 + ((id) *CLIC_INT_REG_ADDR_INTERVAL)) +#define CLIC_INT_X_CTRL_REG_OFF(id) (0x1003 + ((id) *CLIC_INT_REG_ADDR_INTERVAL)) + +#define CLIC_INX_X_32BIT_REG_OFF(id) \ + (0x1000 + ((id) *CLIC_INT_REG_ADDR_INTERVAL)) + +/* CLIC_CFG_REG */ +#define PREEMPTION_PRIORITY_BITS_SHIFT 1 +#define PREEMPTION_PRIORITY_BITS_MASK (0xF << PREEMPTION_PRIORITY_BITS_SHIFT) + +/* CLIC_INFO_REG */ +#define IRQ_CNT_SHIFT 0 +#define IRQ_CNT_MASK (0x1FFF << IRQ_CNT_SHIFT) + +#define HW_VERSION_SHIFT 13 +#define HW_VERSION_MASK (0xF << HW_VERSION_SHIFT) + +#define HW_IMPL_VERSION_SHIFT 17 +#define HW_IMPL_VERSION_MASK (0xF << HW_IMPL_VERSION_SHIFT) + +#define CTRL_REG_BITS_SHIFT 21 +#define CTRL_REG_BITS_MASK (0xF << CTRL_REG_BITS_SHIFT) + +/* CLIC_INT_IP_REG */ +#define IP_SHIFT 0 +#define IP_BIT_MASK (0x1 << IP_SHIFT) + +/* CLIC_INT_IE_REG */ +#define IE_SHIFT 0 +#define IE_BIT_MASK (0x1 << IE_SHIFT) + +/* CLIC_INT_ATTR_REG */ +#define HW_VECTOR_IRQ_SHIFT 0 +#define HW_VECTOR_IRQ_BIT_MASK (0x1 << HW_VECTOR_IRQ_SHIFT) + +#define TRIGGER_TYPE_SHIFT 1 +#define TRIGGER_TYPE_BIT_MASK (0x3 << TRIGGER_TYPE_SHIFT) + +#ifdef __cplusplus +} +#endif// __cplusplus + +#endif// __REG_CLIC_H__ \ No newline at end of file diff --git a/src/arch/riscv/riscv32_e907/exception.c b/src/arch/riscv/riscv32_e907/exception.c index 659b78b1..3d6cea42 100644 --- a/src/arch/riscv/riscv32_e907/exception.c +++ b/src/arch/riscv/riscv32_e907/exception.c @@ -14,6 +14,8 @@ #include #include +#include + #if defined(__riscv_flen) #if __riscv_flen >= 32 extern void f32_read(int n, uint32_t *v); @@ -115,19 +117,6 @@ struct instruction_info_t { unsigned int sign_extend : 1; }; -/** - * @brief Structure for IRQ handler - * - * @param data Pointer to data associated with the IRQ handler - * @param func Function pointer to the IRQ handler function - */ -typedef struct _irq_handler { - void *data; - void (*func)(void *data); -} irq_handler_t; - -static irq_handler_t core_interrupt_handler[8] = {0}; - static struct instruction_info_t insn_info[] = { #if __riscv_xlen == 128 {0x00002000, 0x0000e003, 2, 7, 8, 0, 1, 16, 1}, /* C.LQ */ @@ -274,9 +263,9 @@ static void show_regs(struct pt_regs_t *regs) { printk_error("Bad address: 0x%08x\r\n", regs->badvaddr); printk_error("Stored ra: 0x%08x\r\n", regs->x[1]); printk_error("Stored sp: 0x%08x\r\n", regs->x[2]); - printk_error("========== backtrace ==========\n"); - dump_stack(); - backtrace((char *)regs->epc, (long *)regs->x[2], (char *)regs->x[1]); + printk_error("========== backtrace ==========\n"); + dump_stack(); + backtrace((char *) regs->epc, (long *) regs->x[2], (char *) regs->x[1]); } static struct instruction_info_t *match_instruction(unsigned long insn) { @@ -429,7 +418,7 @@ void riscv_handle_exception(struct pt_regs_t *regs) { case 6: /* Hypervisor timer interrupt */ case 7: /* Machine timer interrupt */ csr_clear(mip, pending); - (core_interrupt_handler[cause].func)(core_interrupt_handler[cause].data); + do_irq(); break; case 8: /* User external interrupt */ case 9: /* Supervisor external interrupt */ @@ -472,6 +461,3 @@ void riscv_handle_exception(struct pt_regs_t *regs) { } abort(); } - -static void dummy_interrupt_function(void *data) { -} diff --git a/src/drivers/intc/sys-clic.c b/src/drivers/intc/sys-clic.c new file mode 100644 index 00000000..e5ce4cc2 --- /dev/null +++ b/src/drivers/intc/sys-clic.c @@ -0,0 +1,232 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +static irq_handler_t sunxi_int_handlers[CLIC_IRQ_NUM]; +static irq_controller_t sunxi_clic_controller; + +static int sunxi_plat_irq_init(void) { + uint32_t i; + irq_controller_t *ic; + ic = &sunxi_clic_controller; + ic->reg_base_addr = (SUNXI_RISCV_CLINT_BASE + 0x800000); + ic->irq_cnt = 208; + ic->parent_id = 0; + ic->irq_id = 0; + return 0; +} + +static inline void sunxi_clic_set_irq_ctrl_bit(uint32_t reg_addr, uint8_t mask, int is_set) { + uint8_t reg_data = readb(reg_addr); + if (is_set) + reg_data |= mask; + else + reg_data &= ~mask; + writeb(reg_data, reg_addr); +} + +static inline void sunxi_clic_set_enable(uint32_t reg_addr, int enabled) { + sunxi_clic_set_irq_ctrl_bit(reg_addr, IE_BIT_MASK, enabled); +} + +static inline void sunxi_clic_set_pending(uint32_t reg_addr, int pending) { + sunxi_clic_set_irq_ctrl_bit(reg_addr, IP_BIT_MASK, pending); +} + +static inline void sunxi_clic_set_vec_mode(uint32_t reg_addr, int vec_mode) { + sunxi_clic_set_irq_ctrl_bit(reg_addr, HW_VECTOR_IRQ_BIT_MASK, vec_mode); +} + +static inline void sunxi_clic_set_trigger_type(uint32_t reg_addr, irq_trigger_type_t type) { + uint8_t reg_data, field_value; + if (type == IRQ_TRIGGER_TYPE_LEVEL) { + field_value = 0; + } else if (type == IRQ_TRIGGER_TYPE_EDGE_RISING) { + field_value = 1; + } else if (type == IRQ_TRIGGER_TYPE_EDGE_FALLING) { + field_value = 3; + } else { + return; + } + reg_data = readb(reg_addr); + reg_data &= ~TRIGGER_TYPE_BIT_MASK; + reg_data |= field_value << TRIGGER_TYPE_SHIFT; + writeb(reg_data, reg_addr); +} + +static int sunxi_clic_init(const struct irq_controller *ic) { + uint32_t i, reg_data, irq_cnt, preemption_bits; + uint32_t reg_addr; + + sunxi_plat_irq_init(); + reg_addr = ic->reg_base_addr + CLIC_INFO_REG_OFF; + reg_data = readl(reg_addr); + + irq_cnt = (reg_data & IRQ_CNT_MASK) >> IRQ_CNT_SHIFT; + printk_trace("CLIC: irq_cnt:%d ic->irq_cnt:%d\n", irq_cnt, ic->irq_cnt); + if (ic->irq_cnt != irq_cnt) + return -1; + preemption_bits = (reg_data & CTRL_REG_BITS_MASK) >> CTRL_REG_BITS_SHIFT; + preemption_bits <<= PREEMPTION_PRIORITY_BITS_SHIFT; + preemption_bits &= PREEMPTION_PRIORITY_BITS_MASK; + reg_addr = ic->reg_base_addr + CLIC_CFG_REG_OFF; + + writel(preemption_bits, reg_addr); + for (i = 0; i < irq_cnt; i++) { + //disable all interrupt + reg_addr = ic->reg_base_addr + CLIC_INT_X_IE_REG_OFF(i); + sunxi_clic_set_enable(reg_addr, 0); + reg_addr = ic->reg_base_addr + CLIC_INT_X_ATTR_REG_OFF(i); + sunxi_clic_set_vec_mode(reg_addr, 0); + //clear pending + reg_addr = ic->reg_base_addr + CLIC_INT_X_IP_REG_OFF(i); + sunxi_clic_set_pending(reg_addr, 1); + } + reg_addr = ic->reg_base_addr + CLIC_INT_X_IE_REG_OFF(i); + printk_trace("CLIC: addr 0x%x(0x%x)set_enable 0\n", reg_addr, readb(reg_addr)); + reg_addr = ic->reg_base_addr + CLIC_INT_X_ATTR_REG_OFF(i); + printk_trace("CLIC: addr 0x%x(0x%x) set_vec 1\n", reg_addr, readb(reg_addr)); + reg_addr = ic->reg_base_addr + CLIC_INT_X_IP_REG_OFF(i); + printk_trace("CLIC: addr 0x%x(0x%x) clear pending 1\n", reg_addr, readb(reg_addr)); + return 0; +} + +static int sunxi_clic_irq_enable(const struct irq_controller *ic, uint32_t irq_id) { + uint32_t reg_addr; + reg_addr = ic->reg_base_addr + CLIC_INT_X_IE_REG_OFF(irq_id); + sunxi_clic_set_enable(reg_addr, 1); + return 0; +} + +static int sunxi_clic_irq_disable(const struct irq_controller *ic, uint32_t irq_id) { + uint32_t reg_addr; + reg_addr = ic->reg_base_addr + CLIC_INT_X_IE_REG_OFF(irq_id); + sunxi_clic_set_enable(reg_addr, 0); + return 0; +} + +static int sunxi_clic_irq_is_enabled(const struct irq_controller *ic, uint32_t irq_id) { + if (readb((ic->reg_base_addr + CLIC_INT_X_IE_REG_OFF(irq_id))) & IE_BIT_MASK) + return 1; + return 0; +} + +static int sunxi_clic_irq_is_pending(const struct irq_controller *ic, uint32_t irq_id) { + if (readb((ic->reg_base_addr + CLIC_INT_X_IP_REG_OFF(irq_id))) & IP_BIT_MASK) + return 1; + return 0; +} + +static int sunxi_clic_irq_set_pending(const struct irq_controller *ic, uint32_t irq_id, + int pending) { + uint32_t reg_addr; + reg_addr = ic->reg_base_addr + CLIC_INT_X_IP_REG_OFF(irq_id); + sunxi_clic_set_pending(reg_addr, pending); + return 0; +} + +static int sunxi_clic_irq_set_trigger_type(const struct irq_controller *ic, uint32_t irq_id, irq_trigger_type_t type) { + uint32_t reg_addr; + if (type == IRQ_TRIGGER_TYPE_EDGE_BOTH) + return -1; + reg_addr = ic->reg_base_addr + CLIC_INT_X_ATTR_REG_OFF(irq_id); + sunxi_clic_set_trigger_type(reg_addr, type); + return 0; +} + +static void default_isr(void *data) { + printk_debug("default_isr(): called from IRQ %d\n", (uint32_t) data); + while (1) + ; +} + +static void sunxi_clic_spi_handler(int irq_no) { + if (sunxi_int_handlers[irq_no].func != default_isr) { + sunxi_int_handlers[irq_no].func( + sunxi_int_handlers[irq_no].data); + } +} + +void irq_free_handler(int irq) { + if (irq >= CLIC_IRQ_NUM) { + return; + } + sunxi_int_handlers[irq].data = NULL; + sunxi_int_handlers[irq].func = default_isr; +} + +int irq_enable(int irq_no) { + if (irq_no >= CLIC_IRQ_NUM) { + printf("CLIC: irq NO.(%d) > CLIC_IRQ_NUM(%d)\n", irq_no, CLIC_IRQ_NUM); + return -1; + } + sunxi_clic_irq_enable(&sunxi_clic_controller, irq_no); + return 0; +} + +int irq_disable(int irq_no) { + if (irq_no >= CLIC_IRQ_NUM) { + printf("CLIC: irq NO.(%d) > CLIC_IRQ_NUM(%d) !!\n", irq_no, CLIC_IRQ_NUM); + return -1; + } + sunxi_clic_irq_disable(&sunxi_clic_controller, irq_no); + return 0; +} + +void irq_install_handler(int irq, interrupt_handler_t handle_irq, void *data) { + if (irq >= CLIC_IRQ_NUM || !handle_irq) { + return; + } + sunxi_int_handlers[irq].data = data; + sunxi_int_handlers[irq].func = handle_irq; +} + +void do_irq() { + uint32_t idnum = 0; + uint32_t rv_mcause = 0; + + asm volatile("csrr %0, mcause" + : "=r"(rv_mcause)); + printk_trace("CLIC: rv_mcause:0x%x riscv_mode:0x%lx\n", rv_mcause, riscv_mode); + csr_clear(mie, MIE_MSIE); + + do { + idnum = (rv_mcause & 0xFFF); + if (idnum != 0) { + sunxi_clic_spi_handler(idnum); + irq_enable(idnum); + return; + } + } while (idnum != 0); + + csr_set(mie, MIE_MSIE); + return; +} + +int arch_interrupt_init(void) { + sunxi_clic_init(&sunxi_clic_controller); + csr_set(mstatus, MSTATUS_MIE); + csr_set(mie, MIE_MEIE); + return 0; +} + +int arch_interrupt_exit(void) { + csr_clear(mstatus, MSTATUS_MIE); + csr_clear(mie, MIE_MEIE); + /* reinit to clear pending */ + sunxi_clic_init(&sunxi_clic_controller); + return 0; +} \ No newline at end of file diff --git a/src/drivers/intc/sys-gic.c b/src/drivers/intc/sys-gic.c index e3004572..2e4205c7 100644 --- a/src/drivers/intc/sys-gic.c +++ b/src/drivers/intc/sys-gic.c @@ -133,6 +133,7 @@ static void default_isr(void *data) { while (1) ; } + static void gic_sgi_handler(uint32_t irq_no) { printk_debug("GIC: SGI irq %d coming... \n", irq_no); } @@ -185,7 +186,7 @@ int sunxi_gic_cpu_interface_exit(void) { void do_irq(struct arm_regs_t *regs) { uint32_t idnum = readl(GIC_INT_ACK_REG); - + if ((idnum == 1022) || (idnum == 1023)) { printk_error("GIC: spurious irq !!\n"); return;