/*
 * Copyright (C) 2017-2020 Alibaba Group Holding Limited
 */


/******************************************************************************
 * @file     drv_common.h
 * @brief    Header File for Common Driver
 * @version  V1.0
 * @date     31. March 2020
 * @model    common
 ******************************************************************************/

#ifndef _DRV_COMMON_H_
#define _DRV_COMMON_H_

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <drv/list.h>
#include <csi_config.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifdef CONFIG_DEBUG_MODE
#define CSI_ASSERT(expr)                            \
        do {                                        \
            if ((int32_t)expr == (int32_t)NULL) {   \
                printf("PROGRAM ASSERT\n");         \
                while(1);                           \
            }                                       \
        } while(0);
#else
#define CSI_ASSERT(expr)        ((void)0U)
#endif

#ifdef CONFIG_PARAM_NOT_CHECK
#define CSI_PARAM_CHK(para, err)                    \
    do {                                            \
        if ((int32_t)para == (int32_t)NULL) {       \
            return (err);                           \
        }                                           \
    } while (0)

#define CSI_PARAM_CHK_NORETVAL(para)                \
    do {                                            \
        if ((int32_t)para == (int32_t)NULL) {       \
            return;                                 \
        }                                           \
    } while (0)
#else
#define CSI_PARAM_CHK(para, err)
#define CSI_PARAM_CHK_NORETVAL(para)
#endif

typedef enum {
    CSI_OK          =  0,
    CSI_ERROR       = -1,
    CSI_BUSY        = -2,
    CSI_TIMEOUT     = -3,
    CSI_UNSUPPORTED = -4
} csi_error_t;

typedef struct {
   uint8_t    readable;
   uint8_t    writeable;
   uint8_t    error;
} csi_state_t;

typedef struct csi_dev csi_dev_t;

#ifdef CONFIG_PM
typedef enum {
    PM_DEV_SUSPEND,
    PM_DEV_RESUME,
} csi_pm_dev_action_t;

typedef enum {
    PM_MODE_RUN                  = 0,   ///< Running mode
    PM_MODE_SLEEP_1,                    ///< Sleep LV1 mode
    PM_MODE_SLEEP_2,                    ///< Sleep LV2 mode
    PM_MODE_DEEP_SLEEP_1,               ///< Deep sleep LV1 mode
    PM_MODE_DEEP_SLEEP_2,               ///< Deep sleep LV2 mode
} csi_pm_mode_t;

typedef struct {
    slist_t     next;
    csi_error_t (*pm_action)(csi_dev_t *dev, csi_pm_dev_action_t action);
    uint32_t    *reten_mem;
    uint32_t    size;
} csi_pm_dev_t;

#include <drv/pm.h>
#endif

struct csi_dev {
    uint32_t     reg_base;
    uint8_t      irq_num;
    uint8_t      idx;
    uint16_t     dev_tag;
    void         (*irq_handler)(void *);
#ifdef CONFIG_PM
    csi_pm_dev_t pm_dev;
#endif
};

#define HANDLE_REG_BASE(handle)     (handle->dev.reg_base)
#define HANDLE_IRQ_NUM(handle)      (handle->dev.irq_num)
#define HANDLE_DEV_IDX(handle)      (handle->dev.idx)
#define HANDLE_IRQ_HANDLER(handle)  (handle->dev.irq_handler)

typedef struct {
    uint32_t reg_base;
    uint8_t  irq_num;
    uint8_t  idx;
    uint16_t dev_tag;
} csi_perip_info_t;

typedef enum {
    DEV_DW_UART_TAG = 0U,
    DEV_DW_TIMER_TAG,
    DEV_DW_IIC_TAG,
    DEV_DW_GPIO_TAG,
    DEV_DW_WDT_TAG,
    DEV_DW_SPI_TAG,
    DEV_WJ_DMA_TAG,
    DEV_DW_DMA_TAG,
    DEV_WJ_USI_TAG,
    DEV_WJ_PWM_TAG,
    DEV_WJ_RTC_TAG,
    DEV_WJ_EFLASH_TAG,
    DEV_WJ_PMU_TAG,
    DEV_WJ_PINMUX_TAG,
    DEV_WJ_AES_TAG,
    DEV_WJ_SHA_TAG,
    DEV_WJ_RSA_TAG,
    DEV_WJ_CRC_TAG,
    DEV_WJ_ADC_TAG,
    DEV_WJ_RNG_TAG,
    DEV_WJ_I2S_TAG,
    DEV_OSR_RNG_TAG,
    DEV_CD_QSPI_TAG,
    DEV_WJ_MBOX_TAG,
    DEV_RCHBAND_CODEC_TAG,
    DEV_WJ_CODEC_TAG,  //
    DEV_WJ_USB_TAG,    //
    DEV_WJ_SDIO_TAG,   //
    DEV_WJ_FFT_TAG,    //
    DEV_DCD_ISO7816_TAG,//
    DEV_WJ_ETB_TAG,
    DEV_WJ_EFUSE_TAG,
    DEV_WJ_ROM_TAG,
    DEV_WJ_SASC_TAG,
    DEV_WJ_TIPC_TAG,
    DEV_DW_SDMMC_TAG,
    DEV_WJ_SPDIF_TAG,
    DEV_WJ_TDM_TAG,
    DEV_WJ_PDM_TAG,
    DEV_BLANK_TAG
} csi_dev_tag_t;

csi_error_t target_get(csi_dev_tag_t dev_tag, uint32_t idx, csi_dev_t *dev);
csi_error_t target_get_optimal_dma_channel(void *dma_list, uint32_t ctrl_num, csi_dev_t *parent_dev, void *ch_info);
void mdelay(uint32_t ms);
void udelay(uint32_t us);

#ifdef __cplusplus
}
#endif

#endif /* _DRV_COMMON_H_ */

