528 lines
12 KiB
C
528 lines
12 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
/* os shim includes */
|
|
#include "os_types.h"
|
|
#include "iot_config.h"
|
|
#include "irq.h"
|
|
|
|
#include "apb.h"
|
|
#include "ahb.h"
|
|
#include "cpu.h"
|
|
#include "intc.h"
|
|
#include "intc_reg.h"
|
|
#include "hw_reg_api.h"
|
|
|
|
/* systick timer frq */
|
|
#define SYSTICK_FRQ (1 * 1000 * 1000)
|
|
#define INT_ID_READ_TIMES (128)
|
|
|
|
static uint32_t intc_systick_rate = 0;
|
|
|
|
void IRAM_ATTR intc_write(uint32_t cpu, uint32_t reg, uint32_t data)
|
|
{
|
|
if(HAL_INTR_CPU_0 == cpu){
|
|
INTC0_WRITE_REG(reg, data);
|
|
}else if(HAL_INTR_CPU_1 == cpu){
|
|
INTC1_WRITE_REG(reg, data);
|
|
}else if(HAL_INTR_CPU_2 == cpu){
|
|
INTC2_WRITE_REG(reg, data);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
uint32_t IRAM_ATTR intc_read(uint32_t cpu, uint32_t reg)
|
|
{
|
|
uint32_t data;
|
|
|
|
if(HAL_INTR_CPU_0 == cpu){
|
|
data = INTC0_READ_REG(reg);
|
|
}else if(HAL_INTR_CPU_1 == cpu){
|
|
data = INTC1_READ_REG(reg);
|
|
}else if(HAL_INTR_CPU_2 == cpu){
|
|
data = INTC2_READ_REG(reg);
|
|
}else{
|
|
data = 0;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
void intc_init(uint32_t cpu)
|
|
{
|
|
if(cpu == HAL_INTR_CPU_0){
|
|
apb_enable(APB_INTC0);
|
|
} else if(cpu == HAL_INTR_CPU_1){
|
|
apb_enable(APB_INTC1);
|
|
} else if(cpu == HAL_INTR_CPU_2){
|
|
apb_enable(APB_INTC2);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
intc_write(cpu, CFG_INT_ENA0_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_ENA1_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_ENA2_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_ENA3_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_SEL_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG0_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG1_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG2_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG3_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG4_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG5_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG6_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG7_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG8_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG9_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG10_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG11_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG12_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG13_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG14_ADDR, 0x0);
|
|
intc_write(cpu, CFG_INT_PRI_CFG15_ADDR, 0x0);
|
|
|
|
return;
|
|
}
|
|
|
|
void intc_set_priority(uint32_t cpu, uint32_t vector, uint32_t priority)
|
|
{
|
|
uint32_t tmp, addr;
|
|
uint32_t group = 0;
|
|
(void)cpu;
|
|
|
|
group = vector>>3;
|
|
|
|
if(group == 0) {
|
|
addr = CFG_INT_PRI_CFG0_ADDR;
|
|
}
|
|
else if(group == 1) {
|
|
addr = CFG_INT_PRI_CFG1_ADDR;
|
|
}
|
|
else if(group == 2) {
|
|
addr = CFG_INT_PRI_CFG2_ADDR;
|
|
}
|
|
else if(group == 3) {
|
|
addr = CFG_INT_PRI_CFG3_ADDR;
|
|
}
|
|
else if(group == 4) {
|
|
addr = CFG_INT_PRI_CFG4_ADDR;
|
|
}
|
|
else if(group == 5) {
|
|
addr = CFG_INT_PRI_CFG5_ADDR;
|
|
}
|
|
else if(group == 6) {
|
|
addr = CFG_INT_PRI_CFG6_ADDR;
|
|
}
|
|
else if(group == 7) {
|
|
addr = CFG_INT_PRI_CFG7_ADDR;
|
|
}
|
|
else if(group == 8) {
|
|
addr = CFG_INT_PRI_CFG8_ADDR;
|
|
}
|
|
else if(group == 9) {
|
|
addr = CFG_INT_PRI_CFG9_ADDR;
|
|
}
|
|
else if(group == 10) {
|
|
addr = CFG_INT_PRI_CFG10_ADDR;
|
|
}
|
|
else if(group == 11) {
|
|
addr = CFG_INT_PRI_CFG11_ADDR;
|
|
}
|
|
else if(group == 12) {
|
|
addr = CFG_INT_PRI_CFG12_ADDR;
|
|
}
|
|
else if(group == 13) {
|
|
addr = CFG_INT_PRI_CFG13_ADDR;
|
|
}
|
|
else if(group == 14) {
|
|
addr = CFG_INT_PRI_CFG14_ADDR;
|
|
}
|
|
else if(group == 15) {
|
|
addr = CFG_INT_PRI_CFG15_ADDR;
|
|
}else{
|
|
return;
|
|
}
|
|
|
|
tmp = intc_read(cpu, addr);
|
|
tmp |= priority << ((vector%8)*4);
|
|
intc_write(cpu, addr, tmp);
|
|
|
|
return;
|
|
}
|
|
|
|
void IRAM_ATTR intc_mask(uint32_t cpu, uint32_t vector)
|
|
{
|
|
uint32_t tmp, addr;
|
|
|
|
if(vector < 32){
|
|
addr = CFG_INT_ENA0_ADDR;
|
|
}else if(vector < 64){
|
|
addr = CFG_INT_ENA1_ADDR;
|
|
vector -= 32;
|
|
}else if(vector < 96){
|
|
addr = CFG_INT_ENA2_ADDR;
|
|
vector -= 64;
|
|
}else if(vector < 128){
|
|
addr = CFG_INT_ENA3_ADDR;
|
|
vector -= 96;
|
|
}
|
|
else{
|
|
return;
|
|
}
|
|
|
|
tmp = intc_read(cpu, addr);
|
|
tmp &= ~(1 << vector);
|
|
intc_write(cpu, addr, tmp);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void IRAM_ATTR intc_unmask(uint32_t cpu, uint32_t vector)
|
|
{
|
|
uint32_t tmp, addr;
|
|
|
|
if(vector < 32){
|
|
addr = CFG_INT_ENA0_ADDR;
|
|
}else if(vector < 64){
|
|
addr = CFG_INT_ENA1_ADDR;
|
|
vector -= 32;
|
|
}else if(vector < 96){
|
|
addr = CFG_INT_ENA2_ADDR;
|
|
vector -= 64;
|
|
}else if(vector < 128){
|
|
addr = CFG_INT_ENA3_ADDR;
|
|
vector -= 96;
|
|
}
|
|
else{
|
|
return;
|
|
}
|
|
|
|
tmp = intc_read(cpu, addr);
|
|
tmp |= (1 << vector);
|
|
intc_write(cpu, addr, tmp);
|
|
|
|
return;
|
|
}
|
|
|
|
void intc_config(uint32_t cpu, uint32_t vector, uint32_t level, uint32_t up)
|
|
{
|
|
(void)cpu;
|
|
(void)vector;
|
|
(void)level;
|
|
(void)up;
|
|
return;
|
|
}
|
|
|
|
void intc_ack(uint32_t cpu, uint32_t vector)
|
|
{
|
|
(void)cpu;
|
|
(void)vector;
|
|
return;
|
|
}
|
|
|
|
uint32_t g_snapshot_triggered = 0;
|
|
|
|
uint32_t IRAM_ATTR intc_get_vector(uint32_t cpu)
|
|
{
|
|
uint32_t status;
|
|
uint32_t vector = 0;
|
|
|
|
status = intc_read(cpu, CFG_INT_PRI_STS_ADDR);
|
|
vector = REG_FIELD_GET(INT_ID, status);
|
|
|
|
return vector;
|
|
}
|
|
|
|
void IRAM_ATTR intc_handler(uint32_t cpu)
|
|
{
|
|
volatile uint32_t status;
|
|
volatile uint32_t vector1, vector2;
|
|
uint32_t read_cnt = INT_ID_READ_TIMES;
|
|
|
|
do {
|
|
status = intc_read(cpu, CFG_INT_PRI_STS_ADDR);
|
|
vector1 = REG_FIELD_GET(INT_ID, status);
|
|
status = intc_read(cpu, CFG_INT_PRI_STS_ADDR);
|
|
vector2 = REG_FIELD_GET(INT_ID, status);
|
|
if (vector1 == vector2) {
|
|
break;
|
|
}
|
|
} while (--read_cnt);
|
|
|
|
if (0 == read_cnt || vector1 >= HAL_VECTOR_MAX) {
|
|
return;
|
|
} else {
|
|
hal_deliver_interrupt(vector1);
|
|
}
|
|
}
|
|
|
|
void IRAM_ATTR intc_force_mtip(uint32_t cpu)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INTER_MTIP_CTL1_ADDR);
|
|
REG_FIELD_SET(MTIP_INT_FORCE, tmp, 1);
|
|
intc_write(cpu, CFG_INTER_MTIP_CTL1_ADDR, tmp);
|
|
|
|
return;
|
|
}
|
|
|
|
int IRAM_ATTR intc_get_force_mtip(uint32_t cpu)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INTER_MTIP_CTL1_ADDR);
|
|
|
|
return REG_FIELD_GET(MTIP_INT_FORCE, tmp);
|
|
}
|
|
|
|
void IRAM_ATTR intc_clear_force_mtip(uint32_t cpu)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INTER_MTIP_CTL1_ADDR);
|
|
REG_FIELD_SET(MTIP_INT_FORCE, tmp, 0);
|
|
intc_write(cpu, CFG_INTER_MTIP_CTL1_ADDR, tmp);
|
|
|
|
return;
|
|
}
|
|
|
|
void IRAM_ATTR systick_clear(uint32_t cpu)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INTER_MTIP_CTL2_ADDR);
|
|
REG_FIELD_SET(MTIP_CNT_INT_CLR, tmp, 1);
|
|
intc_write(cpu, CFG_INTER_MTIP_CTL2_ADDR, tmp);
|
|
|
|
return;
|
|
}
|
|
|
|
void IRAM_ATTR systick_config(uint32_t cpu, uint32_t clock, uint32_t rate)
|
|
{
|
|
uint32_t tmp;
|
|
uint32_t tick = SYSTICK_FRQ / rate - 1UL;
|
|
|
|
(void)clock;
|
|
tmp = intc_read(cpu, CFG_INTER_MTIP_CMP_ADDR);
|
|
REG_FIELD_SET(MTIP_CMP, tmp, tick);
|
|
intc_write(cpu, CFG_INTER_MTIP_CMP_ADDR, tmp);
|
|
|
|
intc_systick_rate = rate;
|
|
|
|
return;
|
|
}
|
|
|
|
void IRAM_ATTR systick_enable(uint32_t cpu)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INTER_MTIP_CTL1_ADDR);
|
|
REG_FIELD_SET(MTIP_CNT_EN, tmp, 1);
|
|
REG_FIELD_SET(MTIP_INT_EN, tmp, 1);
|
|
intc_write(cpu, CFG_INTER_MTIP_CTL1_ADDR, tmp);
|
|
|
|
return;
|
|
}
|
|
|
|
void systick_update(uint32_t cpu, uint32_t clock)
|
|
{
|
|
uint32_t tick = (clock / intc_systick_rate) - 1UL;
|
|
|
|
intc_write(cpu, CFG_INTER_MTIP_CMP_ADDR, tick);
|
|
}
|
|
|
|
uint32_t intc_get_software_int_status(uint32_t cpu)
|
|
{
|
|
return intc_read(cpu, CFG_INTER_MSIP_ADDR);
|
|
}
|
|
|
|
void intc_send_software_int(uint32_t dst_cpu)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid(), tmp;
|
|
|
|
tmp = intc_read(dst_cpu, CFG_INTER_MSIP_ADDR);
|
|
tmp |= (1 << cpu);
|
|
intc_write(dst_cpu, CFG_INTER_MSIP_ADDR, tmp);
|
|
}
|
|
|
|
void intc_clear_software_int(uint32_t dst_cpu)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid(), tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INTER_MSIP_CLR_ADDR);
|
|
tmp |= (1 << dst_cpu);
|
|
intc_write(cpu, CFG_INTER_MSIP_CLR_ADDR, tmp);
|
|
}
|
|
|
|
void intc_clear_all_software_int(void)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid();
|
|
|
|
intc_write(cpu, CFG_INTER_MSIP_CLR_ADDR, 0xFFFFFFFF);
|
|
}
|
|
|
|
void intc_set_wakeup_enable(intc_wakeup_src_e wakeup_src)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid(), tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INT_WAKEUP_ENA0_ADDR);
|
|
tmp |= (1 << wakeup_src);
|
|
intc_write(cpu, CFG_INT_WAKEUP_ENA0_ADDR, tmp);
|
|
}
|
|
|
|
void intc_set_wakeup_disable(intc_wakeup_src_e wakeup_src)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid(), tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INT_WAKEUP_ENA0_ADDR);
|
|
tmp &= ~(1 << wakeup_src);
|
|
intc_write(cpu, CFG_INT_WAKEUP_ENA0_ADDR, tmp);
|
|
}
|
|
|
|
uint32_t intc_get_wakeup_state(void)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid();
|
|
|
|
return intc_read(cpu, CFG_INT_WAKEUP_STS0_ADDR);;
|
|
}
|
|
|
|
uint32_t intc_get_wakeup_source(void)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid();
|
|
|
|
return intc_read(cpu, CFG_INT_WAKEUP_SRC0_ADDR);;
|
|
}
|
|
|
|
void intc_mon_cnt_ena(uint8_t ch, uint8_t ena)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid(), tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INT_MON_CFG0_ADDR);
|
|
switch(ch) {
|
|
case 0: {
|
|
REG_FIELD_SET(INT_MON_SIG0_CNT_EN, tmp, ena);
|
|
break;
|
|
}
|
|
case 1: {
|
|
REG_FIELD_SET(INT_MON_SIG1_CNT_EN, tmp, ena);
|
|
break;
|
|
}
|
|
case 2: {
|
|
REG_FIELD_SET(INT_MON_SIG2_CNT_EN, tmp, ena);
|
|
break;
|
|
}
|
|
case 3: {
|
|
REG_FIELD_SET(INT_MON_SIG3_CNT_EN, tmp, ena);
|
|
break;
|
|
}
|
|
default :{
|
|
return ;
|
|
}
|
|
}
|
|
intc_write(cpu, CFG_INT_MON_CFG0_ADDR, tmp);
|
|
}
|
|
|
|
void intc_mon_cnt_clear(uint8_t ch)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid(), tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INT_MON_CFG0_ADDR);
|
|
switch(ch) {
|
|
case 0: {
|
|
REG_FIELD_SET(INT_MON_SIG0_CNT_CLR, tmp, 1);
|
|
break;
|
|
}
|
|
case 1: {
|
|
REG_FIELD_SET(INT_MON_SIG1_CNT_CLR, tmp, 1);
|
|
break;
|
|
}
|
|
case 2: {
|
|
REG_FIELD_SET(INT_MON_SIG2_CNT_CLR, tmp, 1);
|
|
break;
|
|
}
|
|
case 3: {
|
|
REG_FIELD_SET(INT_MON_SIG3_CNT_CLR, tmp, 1);
|
|
break;
|
|
}
|
|
default :{
|
|
return ;
|
|
}
|
|
}
|
|
intc_write(cpu, CFG_INT_MON_CFG0_ADDR, tmp);
|
|
}
|
|
|
|
void intc_mon_sig_sel(uint8_t ch, uint8_t sig)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid(), tmp;
|
|
|
|
tmp = intc_read(cpu, CFG_INT_MON_CFG1_ADDR);
|
|
switch(ch) {
|
|
case 0: {
|
|
REG_FIELD_SET(INT_MON_SIG0_SEL, tmp, sig);
|
|
break;
|
|
}
|
|
case 1: {
|
|
REG_FIELD_SET(INT_MON_SIG1_SEL, tmp, sig);
|
|
break;
|
|
}
|
|
case 2: {
|
|
REG_FIELD_SET(INT_MON_SIG2_SEL, tmp, sig);
|
|
break;
|
|
}
|
|
case 3: {
|
|
REG_FIELD_SET(INT_MON_SIG3_SEL, tmp, sig);
|
|
break;
|
|
}
|
|
default :{
|
|
return ;
|
|
}
|
|
}
|
|
intc_write(cpu, CFG_INT_MON_CFG1_ADDR, tmp);
|
|
}
|
|
|
|
uint32_t intc_get_mon_cnt(uint8_t ch)
|
|
{
|
|
uint32_t cpu = cpu_get_mhartid(), tmp;
|
|
|
|
switch(ch) {
|
|
case 0: {
|
|
tmp = intc_read(cpu, CFG_INT_MON_SIG0_CNT_ADDR);
|
|
break;
|
|
}
|
|
case 1: {
|
|
tmp = intc_read(cpu, CFG_INT_MON_SIG1_CNT_ADDR);
|
|
break;
|
|
}
|
|
case 2: {
|
|
tmp = intc_read(cpu, CFG_INT_MON_SIG2_CNT_ADDR);
|
|
break;
|
|
}
|
|
case 3: {
|
|
tmp = intc_read(cpu, CFG_INT_MON_SIG3_CNT_ADDR);
|
|
break;
|
|
}
|
|
default :{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return tmp;
|
|
}
|
|
|
|
|