/**
 * \file    drv_pd_isr.c
 * \brief   PD interrupt service request interface definition
 *
 * \par     Copyright (c) 2019 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2019-08-01
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2019-08-01  Original Creation
 * 
 */

#include "libc.h"
#include "drivers.h"


#define DPM_INT_EN_REG                                  (0x4000000C)

/**
INT_ENA, RW, reset value(0x0)
Global Interrupt Disable/Enable
1: Enable
0: Disable
*/
#ifndef INT_ENA
#define INT_ENA
#endif
#define DPM_INT_EN_REG_INT_ENA                          (0x00)
#define DPM_INT_EN_REG_INT_ENA_WTH                      (0x01)
#define DPM_INT_EN_REG_INT_ENA_FLDSET                   (0x00000001)
#define DPM_INT_EN_REG_INT_ENA_FLDMSK                   (0xFFFFFFFE)


#define DPM_INT_STATUS_REG                              (0x40000010)

/**
HW_TIMER3_TIMEOUT, RC, reset value(0x0)
*/
#ifndef HW_TIMER3_TIMEOUT
#define HW_TIMER3_TIMEOUT
#endif
#define DPM_INT_STATUS_REG_HW_TIMER3_TIMEOUT            (0x0C)
#define DPM_INT_STATUS_REG_HW_TIMER3_TIMEOUT_WTH        (0x01)
#define DPM_INT_STATUS_REG_HW_TIMER3_TIMEOUT_FLDSET     (0x00001000)
#define DPM_INT_STATUS_REG_HW_TIMER3_TIMEOUT_FLDMSK     (0xFFFFEFFF)

/**
HW_TIMER2_TIMEOUT, RC, reset value(0x0)
*/
#ifndef HW_TIMER2_TIMEOUT
#define HW_TIMER2_TIMEOUT
#endif
#define DPM_INT_STATUS_REG_HW_TIMER2_TIMEOUT            (0x0B)
#define DPM_INT_STATUS_REG_HW_TIMER2_TIMEOUT_WTH        (0x01)
#define DPM_INT_STATUS_REG_HW_TIMER2_TIMEOUT_FLDSET     (0x00000800)
#define DPM_INT_STATUS_REG_HW_TIMER2_TIMEOUT_FLDMSK     (0xFFFFF7FF)

/**
HW_TIMER1_TIMEOUT, RC, reset value(0x0)
*/
#ifndef HW_TIMER1_TIMEOUT
#define HW_TIMER1_TIMEOUT
#endif
#define DPM_INT_STATUS_REG_HW_TIMER1_TIMEOUT            (0x0A)
#define DPM_INT_STATUS_REG_HW_TIMER1_TIMEOUT_WTH        (0x01)
#define DPM_INT_STATUS_REG_HW_TIMER1_TIMEOUT_FLDSET     (0x00000400)
#define DPM_INT_STATUS_REG_HW_TIMER1_TIMEOUT_FLDMSK     (0xFFFFFBFF)


/** Other PD field sets */
#define DPM_INT_STATUS_REG_PD_FLDSETS                   (0xFFFFE3FF)


/**
 * array of function pointers which contains the IPIC
 * interrupt handlers
 */
static v_func_ptr_t g_pd_interrupt_handlers[DRV_PD_INTR_TYPE_MAX];

bool_t drv_pd_intr_en_get(void)
{
    return DRV_REG_FIELD_GET(DPM_INT_EN_REG, INT_ENA);
}

void drv_pd_intr_en_set(int flg)
{
    DRV_REG_FIELD_SET(DPM_INT_EN_REG,INT_ENA,(flg));
}

void drv_pd_isr(u32_t arg)
{
    u32_t int_status = DRV_REG_GET(DPM_INT_STATUS_REG);

    if (int_status > 0) 
    {
        if (int_status & DPM_INT_STATUS_REG_HW_TIMER1_TIMEOUT_FLDSET)
        {
            if (g_pd_interrupt_handlers[DRV_PD_INTR_TYPE_HW_TIMER1_OR_GPIO_CAP0])
            {
                g_pd_interrupt_handlers[DRV_PD_INTR_TYPE_HW_TIMER1_OR_GPIO_CAP0](int_status);
            }
        }

        if (int_status & DPM_INT_STATUS_REG_HW_TIMER2_TIMEOUT_FLDSET)
        {
            if (g_pd_interrupt_handlers[DRV_PD_INTR_TYPE_HW_TIMER2_OR_GPIO_CAP1])
            {
                g_pd_interrupt_handlers[DRV_PD_INTR_TYPE_HW_TIMER2_OR_GPIO_CAP1](int_status);
            }
        }

        if (int_status & DPM_INT_STATUS_REG_HW_TIMER3_TIMEOUT_FLDSET)
        {
            if (g_pd_interrupt_handlers[DRV_PD_INTR_TYPE_HW_TIMER3])
            {
                g_pd_interrupt_handlers[DRV_PD_INTR_TYPE_HW_TIMER3](int_status);
            }
        }

        if (int_status & DPM_INT_STATUS_REG_PD_FLDSETS)
        {
            if (g_pd_interrupt_handlers[DRV_PD_INTR_TYPE_PD])
            {
                g_pd_interrupt_handlers[DRV_PD_INTR_TYPE_PD](int_status);
            }
        }
    }
}

void drv_pd_intr_handler_init(void)
{
    int i;
    drv_pd_intr_en_set(FALSE);
    for (i = 0; i < DRV_PD_INTR_TYPE_MAX; i++)
    {
        g_pd_interrupt_handlers[i] = NULL;
    }
}

void drv_pd_intr_init(bool_t en)
{
    drv_pd_intr_handler_init();
    drv_intr_ext_set(IPIC_CFG_INTR_IDX_PD_INT, en, IPIC_INTR_PRI_1, drv_pd_isr);
}

void drv_pd_intr_handler_set(DRV_PD_INTR_TYPE_t type, v_func_ptr_t intr_func)
{
    if (type >= DRV_PD_INTR_TYPE_MAX)
        return;
    g_pd_interrupt_handlers[type] = intr_func;
}


