From 01ba1db73c0623714e9119d2ea753aa5e4dbdebb Mon Sep 17 00:00:00 2001 From: Florian Sylvestre Date: Fri, 5 May 2023 18:48:37 +0200 Subject: [PATCH 11/20] CR52: add interrupts support --- machines/cortex-a/armv8/spider/tpl_irq.c | 26 +++---- .../armv8/spider/tpl_machine_spider.c | 20 ++--- machines/cortex-a/armv8/spider/tpl_stubs.c | 76 +++++++++++++++++-- 3 files changed, 89 insertions(+), 33 deletions(-) diff --git a/machines/cortex-a/armv8/spider/tpl_irq.c b/machines/cortex-a/armv8/spider/tpl_irq.c index 122faec5..f98b6bfd 100644 --- a/machines/cortex-a/armv8/spider/tpl_irq.c +++ b/machines/cortex-a/armv8/spider/tpl_irq.c @@ -27,18 +27,6 @@ extern CONST(tpl_it_vector_entry, OS_CONST) tpl_it_vector[31]; -static inline uint32 cp15_read_irq_id(void) -{ - uint32 irq_id; - __asm__ volatile - ( - "mrc p15, 0, %[result], c12, c8, 0;" - :[result] "=r" (irq_id)::"memory" - ); - - return irq_id; -} - void tpl_arm_subarch_irq_handler () { @@ -46,11 +34,19 @@ void tpl_arm_subarch_irq_handler () VAR(tpl_it_handler, AUTOMATIC) isr_vector; /* - * get interrupt id + * Get group0 interrupt id + * Use 'cp15_read32(0, 12, 8, 0, isr_id_dec);' for group1 */ - isr_id_dec = cp15_read_irq_id(); + cp15_read32(0, 12, 12, 0, isr_id_dec); - /* launch interrupt fonction */ + /* + * Launch interrupt function + */ isr_vector = tpl_it_vector[isr_id_dec].func; isr_vector(tpl_it_vector[isr_id_dec].args); + + /* + * Clear interrupt + */ + cp15_write32(0, 12, 12, 1, isr_id_dec); } diff --git a/machines/cortex-a/armv8/spider/tpl_machine_spider.c b/machines/cortex-a/armv8/spider/tpl_machine_spider.c index 602e071b..0d4f7060 100644 --- a/machines/cortex-a/armv8/spider/tpl_machine_spider.c +++ b/machines/cortex-a/armv8/spider/tpl_machine_spider.c @@ -36,6 +36,8 @@ #define NB_TICK ((uint64)12500000 / (uint64)100) // systick 100 times per seconds (every 10ms) +#define GICR_ISENABLER0 (0xf0110100) + inline uint32 __attribute__((always_inline)) CNTV_CTL_read(void) { uint32 val; cp15_read32(0, 14, 3, 1, val); @@ -57,7 +59,7 @@ inline void __attribute__((always_inline)) CNTV_VAL_write(uint64 val) { } inline uint64 __attribute__((always_inline)) CNTVCT_read(void) { - uint32 val; + uint64 val; cp15_read64(1, 14, val); return val; } @@ -87,24 +89,18 @@ get_systick_timer() { //interrupt id #27 FUNC(void, OS_CODE) tpl_set_systick_timer(void) { + enable_systick_timer(0); - writeToAddress(0xf0110180, 0xffffffff); // Clear pending interrupts - writeToAddress(0xf0110080, 0xffffffff); // GICR_IGROUPR0: set to group 1=IRQ (group0=FIQ) - writeToAddress(0xf0110100, 0xffffffff); // GICR_ISENABLER0: enable forwarding int to cpu - writeToAddress(0xf0000000, 0x53); //GICD_CTLR: enable interrupts distribution to CPU - - cp15_write32(0, 12, 12, 6, 1); // Write 1 to ICC_IGRPEN0 - cp15_write32(0, 12, 12, 7, 1); // Write 1 to ICC_IGRPEN1 - - __asm__ volatile ("CPSIE IF"); - CNTV_VAL_write(get_systick_timer() + NB_TICK); // can set CNTV_TVAL + enable_systick_timer(1); + /* Enable forwarding int to cpu */ + writeToAddress(GICR_ISENABLER0, 0x08000000); + /* Unmask interrupt */ CNTV_CTL_write(CNTV_CTL_read() & ~CNTV_CTL_IMASK); - } #define OS_STOP_SEC_CODE #include "tpl_memmap.h" diff --git a/machines/cortex-a/armv8/spider/tpl_stubs.c b/machines/cortex-a/armv8/spider/tpl_stubs.c index af060b22..9e41ddbb 100644 --- a/machines/cortex-a/armv8/spider/tpl_stubs.c +++ b/machines/cortex-a/armv8/spider/tpl_stubs.c @@ -29,23 +29,87 @@ #include "tpl_os_kernel.h" #include "emblib.h" -extern unsigned int GETISR ( void ); - -// #include "init.h" -extern void enable_irq ( void ); #define OS_START_SEC_CODE #include "tpl_memmap.h" extern uint32 vectors; +/* GICD */ +#define GICD_CTLR (0xf0000000) +#define GICD_TYPER (0xf0000004) +#define GICD_IGROUPR (0xf0000080) +#define GICD_ICENABLER (0xf0000180) +#define GICD_ICPENDR (0xf0000280) +#define GICD_ICFGR (0xf0000c00) + +/* GICR */ +#define GICR_CTLR (0xf0100000) +#define GICR_WAKER (0xf0100014) +#define GICR_IGROUPR0 (0xf0110080) +#define GICR_ICENABLER0 (0xf0110180) +#define GICR_ICPENDR0 (0xf0110280) + +FUNC(void, OS_CODE) wait_rwp(void) { + + /* Wait for rwp cleared */ + while (readFromAddress(GICD_CTLR) & 0x80000000) + ; + +} + +FUNC(void, OS_CODE) wait_uwp(void) { + + /* Wait for uwp cleared */ + while (readFromAddress(GICR_CTLR) & 0x80000000) + ; + +} + +FUNC(void, OS_CODE) init_irq(void) { + + __asm__ volatile ("CPSID IF"); /* Disable interrupts */ + + uint16 nb_int_reg = (readFromAddress(GICD_TYPER) & 0x1f) + 1; /* GICD_TYPER.ITLinesNumber */ + writeToAddress(GICD_CTLR, 0x0); /* Disable interrupts distribution to CPU */ + wait_rwp(); + + /* Starting from 1, because first 32 interrupts are located in an other bank of registers */ + for(uint8 int_id = 1; int_id < nb_int_reg; int_id++) { + writeToAddress(GICD_ICENABLER + int_id * 4, 0xffffffff); /* Disable interrupts */ + writeToAddress(GICD_ICPENDR + int_id * 4, 0xffffffff); /* Clear pending interrupts */ + writeToAddress(GICD_IGROUPR + int_id * 4, 0xffffffff); /* Use group 1 for all interrupts */ + + writeToAddress(GICD_ICFGR + int_id * 8, 0x0); /* Set interrupts as level sensitive */ + writeToAddress(GICD_ICFGR + int_id * 8 + 4, 0x0); + } + wait_rwp(); + + writeToAddress(GICR_WAKER, 0x4); /* Set CPU as awake */ + + writeToAddress(GICR_ICENABLER0, 0xffffffff); /* Disable forwarding int to cpu */ + writeToAddress(GICR_ICPENDR0, 0xffffffff); /* Clear pending interrupts */ + writeToAddress(GICR_IGROUPR0, 0xffffffff); /* Use group1=IRQ (group0=FIQ) */ + wait_uwp(); + + writeToAddress(GICD_CTLR, 0x2); /* Enable interrupts distribution to CPU */ + wait_rwp(); + + cp15_write32(0, 4, 6, 0, 0xff); /* Write 0xff to ICC_PMR_EL1: allow all priority levels */ + + cp15_write32(0, 12, 12, 6, 1); /* Write 1 to ICC_IGRPEN0 */ + cp15_write32(0, 12, 12, 7, 1); /* Write 1 to ICC_IGRPEN1 */ + + __asm__ volatile ("CPSIE IF"); /* Enable interrupts */ +} + FUNC(void, OS_CODE) tpl_init_machine(void) { - cp15_write32(0, 12, 0, 0, &vectors); // write VBAR + cp15_write32(0, 12, 0, 0, &vectors); /* write VBAR */ tpl_init_machine_generic (); - //enable_irq(); + init_irq(); } FUNC(void, OS_CODE) tpl_shutdown(void) -- 2.34.1