/*---------------------------------------------------------------------------- * Tencent is pleased to support the open source community by making TencentOS * available. * * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. * If you have downloaded a copy of the TencentOS binary from Tencent, please * note that the TencentOS binary is licensed under the BSD 3-Clause License. * * If you have downloaded a copy of the TencentOS source code from Tencent, * please note that TencentOS source code is licensed under the BSD 3-Clause * License, except for the third-party components listed below which are * subject to different license terms. Your integration of TencentOS into your * own projects may require compliance with the BSD 3-Clause License, as well * as the other licenses applicable to the third-party components included * within TencentOS. *---------------------------------------------------------------------------*/ #include #include #define ECLIC_ADDR_BASE 0xD2000000 #define CLIC_INT_TMR 0x07 #define ECLIC_CFG_OFFSET 0x00 #define ECLIC_INFO_OFFSET 0x04 #define ECLIC_MTH_OFFSET 0x0B #define ECLIC_INT_IP_OFFSET 0x1000 #define ECLIC_INT_IE_OFFSET 0x1001 #define ECLIC_INT_ATTR_OFFSET 0x1002 #define ECLIC_INT_CTRL_OFFSET 0x1003 #define ECLIC_CFG_NLBITS_MASK 0x1E #define ECLIC_CFG_NLBITS_LSB 1 static uint8_t eclic_get_clic_int_ctl_bits() { uint32_t bits = *(volatile uint32_t*)(ECLIC_ADDR_BASE+ECLIC_INFO_OFFSET); bits >>= 21; return (uint8_t) bits; } static uint8_t eclic_get_nlbits() { uint8_t nlbits = *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET); nlbits = (nlbits & ECLIC_CFG_NLBITS_MASK) >> ECLIC_CFG_NLBITS_LSB; uint8_t cicbits = eclic_get_clic_int_ctl_bits(); if(nlbits > cicbits) { nlbits = cicbits; } return nlbits; } static uint8_t eclic_get_intctrl(uint32_t source) { return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_CTRL_OFFSET+source*4); } static void eclic_set_intctrl(uint32_t source, uint8_t v) { *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_CTRL_OFFSET+source*4) = v; } static void eclic_enable_interrupt(uint32_t source) { *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IE_OFFSET+source*4) = 1; } static void eclic_set_irq_level(uint32_t source, uint8_t level) { uint8_t nlbits = eclic_get_nlbits(); if (nlbits == 0) { return ; } uint8_t intctrl_val = eclic_get_intctrl(source); intctrl_val <<= nlbits; intctrl_val >>= nlbits; intctrl_val |= (level << (8- nlbits)); eclic_set_intctrl(source, intctrl_val); } static void eclic_set_irq_priority(uint32_t source, uint8_t priority) { uint8_t nlbits = eclic_get_nlbits(); uint8_t cicbits= eclic_get_clic_int_ctl_bits(); if (nlbits >= cicbits) { return ; } uint8_t pad = ~0; pad <<= cicbits; pad >>= cicbits; uint8_t intctrl_val = eclic_get_intctrl(source); intctrl_val >>= (8 - nlbits); intctrl_val <<= (8 - nlbits); intctrl_val |= (priority << (8 - cicbits)); intctrl_val |= pad; eclic_set_intctrl(source, intctrl_val); } #define USE_DEFAULT_IRQ_ENTRY 1 __PORT__ void port_cpu_init() { void rv32_exception_entry(); uint32_t entry = (uint32_t) rv32_exception_entry; // 0x03 means use eclic __ASM__ __VOLATILE__("csrw mtvec, %0"::"r"(entry | 0x03)); // MTVT2: 0x7EC // set mtvt2.MTVT2EN = 0 needs to clear bit 0 // use mtvec as entry of irq and other trap __ASM__ __VOLATILE__("csrc 0x7EC, 0x1"); eclic_enable_interrupt(CLIC_INT_TMR); eclic_set_irq_level(CLIC_INT_TMR, 0); } __PORT__ void port_systick_priority_set(uint32_t priority) { eclic_set_irq_priority(CLIC_INT_TMR, priority); } __PORT__ void *port_get_irq_vector_table() { unsigned int *base = 0; // MTVT: 0x307 __ASM__ __VOLATILE__("csrr %0, 0x307":"=r"(base)); return base; }