#include <ucps2-intrin.h>
#include "alg.h"
#include "inter_vector.h"
#include "csu.h"
#include "pet_ctrl.h"
#include "ucp_sfr_c.h"
#include "ucp_js_ctrl.h"
#include "dw_apb_timers.h"
#include "type_define.h"
#include "dw_apb_timers.h"
#include "ucp_param.h"
#include "gs_que.h"
#include "error.h"
#include "debug.h"
#include "smartos.h"
/*
	函数名：ape_request_irq
*/

#define DEBUG_OFF 0
#define bit_32  32
#define bit_64  64
#define MAX_IRQ_NUM  512
#define IRQ_TRACPOINT_SIZE  0x92c


int entry_cnt = 0;
int smart_fun_cnt_s_c = 0;
int smart_fun_cnt_e_c = 0;

unsigned int smart_irq_check_cnt = 0;
unsigned int smart_irq_clear_cnt = 0;

volatile  unsigned int g_mask;

char mask_array[16] = {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60};
int  apcid_ad_val[] = {0,64,128,192};
uint32_t global_int_cnt[512] = {0};


vec_desc g_vec_val;

int debug_enable = 0;
int debug_addr = 0;

uint32_t reg_cnt = 0;


irq_debug_t *debug_info;
#if DEBUG_OFF
#define irq_debug(add,b) (0)
#else
static void irq_debug(void * addr, uint32_t v)
{
    if(debug_enable == 1)
    {
        do_write(addr, v);
        __ucps2_synch(0);
    }
}

#endif

vec_desc *get_vec_desc()
{
    return &g_vec_val;
}


static uint32_t get_int_status_reg(uint32_t vector,int apcid)
{
    int mask_val;
//  int bit_val;
    int load_val;

    mask_val = vector>>5;
//  bit_val = (vector)&(bit_32 -1);
    if((apcid >= 0)&&(apcid < 4))
    {
        load_val =  do_read((SYSCFG_BASE_ADDR + 1248 + mask_array[mask_val] + apcid_ad_val[apcid]));
        return load_val;
    }
    else if(apcid == 4)
    {
        load_val =	do_read((PET_CTRL_BASE + 100*4 + mask_val*4 ));
        return load_val;
    }
    else if(apcid == 5)
    {
        load_val =	do_read((JECS_CTRL_BASE + 40*4 + mask_val*4 ));
        return load_val;
    }
    
    return 0;
}


void isr_entry()
{
    vec_desc * vec_val = &g_vec_val;
    unsigned int val;
    int k;
    int irq_num_bit;
    uint32_t sys_status;
    int bit_val;
  	++entry_cnt;
    g_mask = APC_CSU_INTMASKL;
    APC_CSU_INTMASKL = 0;
    __ucps2_synch(0);
    irq_debug(&(debug_info->irq_cnt), entry_cnt);
    irq_debug(&(debug_info->apc_csu_allpendevent0), APC_CSU_ALLPENDEVENT0);
    irq_debug(&(debug_info->event_mask_l), APC_CSU_EVENTMASKL);
//  val = APC_CSU_ALLPENDEVENT0 & APC_CSU_INTMASKL;
    val = APC_CSU_ALLPENDEVENT0 & g_mask;
    while(val != 0)
    {
        bit_val = find_lsb(val);
        for(k = 0; k < (vec_val->reg_vec_count); k++)
        {
            irq_num_bit =(vec_val->reg_vec_buf[k])&(bit_32 -1);
            sys_status = get_int_status_reg(vec_val->reg_vec_buf[k],apcid_buf[cur_apeid]);
            irq_debug(&(debug_info->irq_sys_status[vec_val->reg_vec_buf[k]>>5]), sys_status);
            if((bit_val == irq_num_bit) && (sys_status  & (1 << irq_num_bit)))
            {
                if(vec_val->pfun[k] != NULL)
                {
                    smart_fun_cnt_s_c++;
                    irq_debug(&(debug_info->fun_start_cnt_all), smart_fun_cnt_s_c);
                    irq_debug(&(debug_info->cur_irq_num),vec_val->reg_vec_buf[k]);
                    vec_val->pfun[k]();
                    __ucps2_synch(0);
                    vec_val->irq_count[k]++;
                    global_int_cnt[vec_val->reg_vec_buf[k]]++;
                    irq_debug(&(debug_info->fun_run_cnt[vec_val->reg_vec_buf[k]]),global_int_cnt[vec_val->reg_vec_buf[k]]);
                    APC_CSU_EVENTINTCLEAR = (vec_val->reg_vec_buf[k] & 31);
                    __ucps2_synch(0);
                    smart_fun_cnt_e_c++;
                    irq_debug(&(debug_info->fun_end_cnt_all), smart_fun_cnt_e_c);

                }
            }
        }
        
        val &= ~(1 << bit_val);
    }

    APC_CSU_INTMASKL = g_mask;
    __ucps2_synch(0);
}



void enable_interrupt()
{
    int32_t addr = (int32_t)__ucps2_interrupt5;
    __ucps2_IntAddr(addr);
    __ucps2_IntEn(f_Enable);
}


int smart_irq_request(uint32_t vector,irq_handler func)
{
    int mask_val;
    int i= 0;
    int bit_val;
    int apcid;
#if ON_DEBUG
    int load_val;
#endif
    int cpuid = get_cur_cpuid();
    if((cpuid < 0)||(cpuid > 11))
    {
        return -EINVAL;
    }
    if(vector > FUN_IRQ_MAX_NUM - 1)
    {
        return -EINVAL;
    }
    __ucps2_IntEn(f_Disable);
	for(i = 0; i < g_vec_val.reg_vec_count;i++)
    {
        if(vector == g_vec_val.reg_vec_buf[i])
        {
            return -EREREG; 
        }
    }
    mask_val = vector>>5;
    bit_val = (vector)&(bit_32 -1);
    apcid = apcid_buf[cpuid];

    if(apcid ==4)
    {
        load_val =  do_read((PET_CTRL_BASE + 280 + mask_val*4 ));
        load_val |= (1<<bit_val);
        do_write((PET_CTRL_BASE + 280 + mask_val*4 ),load_val);
        __ucps2_synch(0);
        load_val =  do_read((PET_CTRL_BASE + 280 + mask_val*4 ));
    }
    else if(apcid == 5)
    {
        load_val =  do_read((JECS_CTRL_BASE + 40 + mask_val*4 ));
        load_val |= (1<<bit_val);
        do_write((JECS_CTRL_BASE + 40 + mask_val*4 ),load_val);
        __ucps2_synch(0);
        load_val =  do_read((JECS_CTRL_BASE + 40 + mask_val*4 ));
    }
    else
    {
        load_val =  do_read((SYSCFG_BASE_ADDR + 720 + mask_val*4 + apcid*bit_64));
        load_val |= (1<<bit_val);
        do_write((SYSCFG_BASE_ADDR + 720 + mask_val*4 + apcid*bit_64),load_val);
        __ucps2_synch(0);
        load_val =  do_read((SYSCFG_BASE_ADDR + 720 + mask_val*4 + apcid*bit_64));
    }
    reg_cnt++;
    irq_debug(&(debug_info->irq_sys_mask[mask_val]), load_val);
    irq_debug(&(debug_info->reg_irq_val[reg_cnt]), vector);
    irq_debug(&(debug_info->reg_irq_cnt), reg_cnt);
    irq_debug(&(debug_info->reg_irq_cpu_id), cpuid);
    
    APC_CSU_INTMASKL |= (1 << bit_val);
    __ucps2_synch(0);
    g_vec_val.reg_vec_buf[g_vec_val.reg_vec_count] = vector;
    g_vec_val.pfun[g_vec_val.reg_vec_count] = func;
    g_vec_val.reg_vec_count++;
    __ucps2_IntEn(f_Enable);
    
    return 0;

}


int smart_irq_free(uint32_t vector)
{
    int mask_val;
    int i= 0;
    int bit_val;
    int apcid;
    int load_val;
    int cpuid = get_cur_cpuid();
    if(vector > FUN_IRQ_MAX_NUM - 1)
    {
        return -EINVAL;
    }
    mask_val = vector>>5;
    bit_val = (vector)&(bit_32 -1);
    apcid = apcid_buf[cpuid];
    __ucps2_IntEn(f_Disable);
    if(apcid ==4){
        load_val =  do_read((PET_CTRL_BASE + 70*4 + mask_val*4 ));
        load_val &= ~(1<<bit_val);
        do_write((PET_CTRL_BASE + 70*4 + mask_val*4 ),load_val);

    }else if(apcid == 5){
        load_val =  do_read((JECS_CTRL_BASE + 10*4 + mask_val*4 ));
        load_val &= ~(1<<bit_val);
        do_write((JECS_CTRL_BASE + 10*4 + mask_val*4),load_val);
    }else{
        load_val =  do_read((SYSCFG_BASE_ADDR + 180*4 + mask_val*4 + apcid*bit_64));
        load_val &= ~(1<<bit_val);
        do_write((SYSCFG_BASE_ADDR + 180*4 + mask_val*4 + apcid*bit_64),load_val);
    }
    __ucps2_synch(0);
//  APC_CSU_EVENTMASKL &= ~(1 << bit_val);   //enable
    APC_CSU_INTMASKL &= ~(1 << bit_val);
    __ucps2_synch(0);
    __ucps2_IntEn(f_Enable);
    for(i = 0; i < g_vec_val.reg_vec_count;i++)
     {
       if(vector == g_vec_val.reg_vec_buf[i])
       {
            g_vec_val.reg_vec_buf[i] = 0;
            g_vec_val.pfun[i] = NULL;
            g_vec_val.reg_vec_count--;

            return 0;
       }
     }
     
     return -1;
}

int smart_irq_enable(uint32_t vector)
{
    int mask_val;
    int bit_val;
    int apcid;
    int load_val;
    int cpuid = get_cur_cpuid();

    if (vector > (MAX_IRQ_NUM-1))
    {
    return -EINVAL;		
    }
    mask_val = vector>>5;
    bit_val = (vector)&(bit_32 -1);
    apcid = apcid_buf[cpuid];
    __ucps2_IntEn(f_Disable);
    if(apcid ==4)
    {
        load_val =  do_read((PET_CTRL_BASE + 280 + mask_val*4 ));
        load_val |= (1<<bit_val);
        do_write((PET_CTRL_BASE + 280 + mask_val*4 ),load_val);
         __ucps2_synch(0);
    }
    else if(apcid == 5)
    {
        load_val =  do_read((JECS_CTRL_BASE + 40 + mask_val*4 ));
        load_val |= (1<<bit_val);
        do_write((JECS_CTRL_BASE + 40 + mask_val*4 ),load_val);
         __ucps2_synch(0);
    }
    else
    {
        load_val =  do_read((SYSCFG_BASE_ADDR + 720 + mask_val*4 + apcid*bit_64));
        load_val |= (1<<bit_val);
        do_write((SYSCFG_BASE_ADDR + 720 + mask_val*4 + apcid*bit_64),load_val);
         __ucps2_synch(0);
    }
    __ucps2_IntEn(f_Enable);
    return 0;
}



int smart_irq_disable(uint32_t vector)
{
    int mask_val;
    int i= 0;
    int bit_val;
    int apcid;
    int load_val;
    int cpuid = get_cur_cpuid();

    if (vector > (MAX_IRQ_NUM-1))
    {
        return -EINVAL;		
    }

    mask_val = vector>>5;
    bit_val = (vector)&(bit_32 -1);
    apcid = apcid_buf[cpuid];
    __ucps2_IntEn(f_Disable);
    if(apcid ==4)
    {
        load_val =  do_read((PET_CTRL_BASE + 70*4 + mask_val*4 ));
        load_val &= ~(1<<bit_val);
        do_write((PET_CTRL_BASE + 70*4 + mask_val*4 ),load_val);
        __ucps2_synch(0);
    }
    else if(apcid == 5)
    {
        load_val =  do_read((JECS_CTRL_BASE + 10*4 + mask_val*4 ));
        load_val &= ~(1<<bit_val);
        do_write((JECS_CTRL_BASE + 10*4 + mask_val*4),load_val);
         __ucps2_synch(0);
    }
    else
    {
        load_val =  do_read((SYSCFG_BASE_ADDR + 180*4 + mask_val*4 + apcid*bit_64));
        load_val &= ~(1<<bit_val);
        do_write((SYSCFG_BASE_ADDR + 180*4 + mask_val*4 + apcid*bit_64),load_val);
         __ucps2_synch(0);
    }
    __ucps2_IntEn(f_Enable);
     return 0;
}



int smart_irq_debug_init(uint32_t debug_base_addr, uint32_t len_bytes)
{
    if (debug_base_addr <= 0x10000000)
    {
        return -1;
    }
    if (len_bytes < IRQ_TRACPOINT_SIZE)
    {
        return -2;
    }
    debug_enable = 1;
    debug_addr = debug_base_addr;

    debug_info = (irq_debug_t *)debug_addr;

	return 0;
}

uint32_t smart_irq_get_type_cnt(smart_irq_cnt_type_t num_type)
{
    uint32_t val = 0;

    switch (num_type)
    {
        case smart_all_irq:
            val = entry_cnt;
        break;

        case smart_fun_s:
            val = smart_fun_cnt_s_c;
        break;

        case smart_fun_e:
            val =  smart_fun_cnt_e_c;
        break;
        /*
        case smart_clear_cnt_error:
        val =  smart_irq_clear_cnt;
        break;
        case smart_irq_check_error:
        val =  smart_irq_check_cnt;
        break;
        */
        default:
        break;
    }

    return val;
}

int smart_irq_get_run_cnt(uint32_t irqnum)
{
    int i;

    if (irqnum > (MAX_IRQ_NUM-1))
    {
        return -EINVAL;
    }
    vec_desc * vec_val = get_vec_desc();
    for(i = 0; i < vec_val->reg_vec_count;i++)
    {
        if(irqnum == vec_val->reg_vec_buf[i])
        {
            break;
        }
    }
    if(i != vec_val->reg_vec_count)
    {
        return vec_val->irq_count[i];
    }
    return 0;
}



