/**
 * \file    drv_interrupt.h
 * \brief   Interrupt definitions
 * 
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-03-12
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-03-12  Original Creation
 * 
 */
 
#ifndef __DRV_INTERRUPT_H_
#define __DRV_INTERRUPT_H_

#include "arch.h"
#include "types.h"


#pragma pack(1)

/**
 * Interrupt priority definitions, The lowest priority number has 
 * the highest priority. 
 */
#define IPIC_INTR_PRI_7                     7
#define IPIC_INTR_PRI_6                     6
#define IPIC_INTR_PRI_5                     5
#define IPIC_INTR_PRI_4                     4
#define IPIC_INTR_PRI_3                     3
#define IPIC_INTR_PRI_2                     2
#define IPIC_INTR_PRI_1                     1
#define IPIC_INTR_PRI_0                     0


/** Default Interrupt Vector Table
   Index        Name                Priority
   IRQ[15:8]    reserved            reserved
   IRQ[7]       GPIO_INT            7
   IRQ[6]       SPI_INT             6
   IRQ[5]       SEC_UART_INT        5
   IRQ[4]       UART_INT            4
   IRQ[3]       SEC_I2C_INT         3
   IRQ[2]       I2C_INT             2
   IRQ[1]       DMA_INT             1
   IRQ[0]       PD_INT              0
 */
#define IPIC_MAX_INTR_VEC                   (16)
#define IPIC_CFG_INTR_VEC_NUM               (8)

#define IPIC_CFG_INTR_IDX_GPIO_INT          7
#define IPIC_CFG_INTR_IDX_SPI_INT           6
#define IPIC_CFG_INTR_IDX_SEC_UART_INT      5
#define IPIC_CFG_INTR_IDX_UART_INT          4
#define IPIC_CFG_INTR_IDX_SEC_I2C_INT       3
#define IPIC_CFG_INTR_IDX_I2C_INT           2
#define IPIC_CFG_INTR_IDX_DMA_INT           1
#define IPIC_CFG_INTR_IDX_PD_INT            0

#pragma pack()


#if 1
#if 1
#define DRV_INTR_GLOBAL_GET()          		read_csr(mie)
#define DRV_INTR_GLOBAL_SET(val)        	asm volatile ("csrw mie, %0" :: "r"(val))
#define DRV_INTR_GLOBAL_DISABLE()      		write_csr(mie,0)
#else
#define DRV_INTR_GLOBAL_GET()
#define DRV_INTR_GLOBAL_SET(en)
#define DRV_INTR_GLOBAL_DISABLE()
#endif
#else
#define DRV_INTR_GLOBAL_ENABLE()            asm volatile 	( "csrs mstatus,8" )
#define DRV_INTR_GLOBAL_DISABLE()           asm volatile 	( "csrc mstatus,8" )
#endif


/** \brief Interrupt initialization
 *
 */
void drv_intr_init(void);

/** \brief Get external interrupt state
 *
 * \param idx       Interrupt vector index
 * \return          0:disable, 1:enable
 */
bool_t drv_intr_ext_en_get(int idx);

/** \brief Enable/disable external interrupt only
 *
 * \param idx       Interrupt vector index
 * \param state     0:disable, 1:enable
 */
void drv_intr_ext_en_set(int idx, bool_t state);

/** \brief Enable/disable external interrupt and set handlers
 *
 * \param idx       Interrupt vector index
 * \param state     0:disable, 1:enable
 * \param pri       interrupt priority, range: 0~7
 * \param isr_func  interrupt handler
 */
void drv_intr_ext_set(int idx, bool_t state, int pri, v_func_ptr_t isr_func);

#if SYS_DRIVER_M_TIMER_ENABLED
/**
 *  RISC-V Machine timer interrupt handler
 *  If user need continuous timer, the handler need to re-enable the mtimer
 */
extern v_func_v_ptr_t g_mtimer_interrupt_handler;

#define drv_intr_mtimer_handler_set(func) \
    do { \
        g_mtimer_interrupt_handler = func; \
    } while(0)

#else
#define drv_intr_mtimer_handler_set(func)
#endif /* SYS_DRIVER_M_TIMER_ENABLED */


#define DRV_MSW_INTR_ENABLE()      set_csr(mie,MIP_MSIP)
#define DRV_MSW_INTR_DISABLE()     clear_csr(mie,MIP_MSIP)

/**
 * The default external interrupt service
 *
 * \param pri       interrupt priority, range: 0~7
 */
void drv_intr_mext_default_handler(u32_t pri);


#endif /* #ifndef __DRV_INTERRUPT_H_ */

