/* Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd. */ #include "mipi_rx_hal.h" #include #include "ot_osal.h" #include "ot_mipi_rx.h" #include "mipi_rx_reg.h" #include "sys_config.h" static unsigned long g_mipi_rx_core_reset_addr; static unsigned long g_mipi_sys_ctrl_addr; typedef struct { bool phy_rg_faclk0_en; bool phy_rg_lp_clk_en; bool phy_rg_lp_mode_en; } phy_mode_link_t; typedef enum { MIPI_ESC_D0 = 0x1 << 0, MIPI_ESC_D1 = 0x1 << 1, MIPI_ESC_D2 = 0x1 << 2, MIPI_ESC_D3 = 0x1 << 3, MIPI_ESC_CLK0 = 0x1 << 4, MIPI_ESC_CLK1 = 0x1 << 5, MIPI_TIMEOUT_D0 = 0x1 << 8, MIPI_TIMEOUT_D1 = 0x1 << 9, MIPI_TIMEOUT_D2 = 0x1 << 10, MIPI_TIMEOUT_D3 = 0x1 << 11, MIPI_TIMEOUT_CLK0 = 0x1 << 12, MIPI_TIMEOUT_CLK1 = 0x1 << 13, } phy_err_int_state; typedef enum { MIPI_VC0_FRAME_CRC = 0x1 << 0, /* in the last frame, VC0'S data has a CRC ERROR at least */ MIPI_VC1_FRAME_CRC = 0x1 << 1, /* in the last frame, VC1'S data has a CRC ERROR at least */ MIPI_VC2_FRAME_CRC = 0x1 << 2, /* in the last frame, VC2'S data has a CRC ERROR at least */ MIPI_VC3_FRAME_CRC = 0x1 << 3, /* in the last frame, VC3'S data has a CRC ERROR at least */ MIPI_VC0_PKT_HEADER_ECC = 0x1 << 4, MIPI_VC1_PKT_HEADER_ECC = 0x1 << 5, MIPI_VC2_PKT_HEADER_ECC = 0x1 << 6, MIPI_VC3_PKT_HEADER_ECC = 0x1 << 7, MIPI_PKT_HEADER_ERR = 0x1 << 8, MIPI_VC0_ORDER_ERR = 0x1 << 16, MIPI_VC1_ORDER_ERR = 0x1 << 17, MIPI_VC2_ORDER_ERR = 0x1 << 18, MIPI_VC3_ORDER_ERR = 0x1 << 19, MIPI_VC0_NO_MATCH = 0x1 << 20, MIPI_VC1_NO_MATCH = 0x1 << 21, MIPI_VC2_NO_MATCH = 0x1 << 22, MIPI_VC3_NO_MATCH = 0x1 << 23, } mipi_csi_int_state; typedef enum { CMD_FIFO_WRITE_ERR = 0x1 << 0, /* MIPI_CTRL write command FIFO error */ DATA_FIFO_WRITE_ERR = 0x1 << 1, CMD_FIFO_READ_ERR = 0x1 << 16, DATA_FIFO_READ_ERR = 0x1 << 17, } mipi_ctrl_int_state; typedef enum { ALIGN_FIFO_FULL_ERR = 0x1 << 0, ALIGN_LANE0_ERR = 0x1 << 1, ALIGN_LANE1_ERR = 0x1 << 2, ALIGN_LANE2_ERR = 0x1 << 3, ALIGN_LANE3_ERR = 0x1 << 4, } align_int_state; /* *************************************************************************** * macro definition * * ************************************************************************** */ #define MIPI_RX_REGS_ADDR 0x173C0000 #define MIPI_RX_REGS_SIZE 0x10000 #define MIPI_RX_CRG_ADDR 0x11018540 #define MIPI_RX_CRG_SIZE 0x120 #define MIPI_RX_CRG_OFFSET 0x20 #define MIPI_RX_SYS_CTRL_ADDR 0x11020EE0 #define MIPI_RX_SYS_CTRL_SIZE 0x10 #define MIPI_RX_SYS_CTRL_OFFSET 0x10 #define MIPI_RX_PIX0_RST_BIT 0 #define MIPI_RX_PIX0_CLK_BIT 4 #define MIPI_RX_CIL_CLK_BIT 4 #define MIPI_RX_BUS_CLK_BIT 5 #define MIPI_RX_BUS_RST_BIT 0 #define MIPI_RX_IRQ 189 #define is_valid_id(id) ((id) != -1) #define SKEW_LINK 0x0 #define MIPI_FSMO_VALUE 0x000d1d0c /**************************************************************************** * global variables definition * * ************************************************************************** */ mipi_rx_regs_type_t *g_mipi_rx_regs_type = NULL; unsigned int g_mipi_rx_irq_num = MIPI_RX_IRQ; static const phy_mode_link_t g_phy_mode[][MIPI_RX_MAX_PHY_NUM] = { {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}} }; phy_err_int_cnt_t g_phy_err_int_cnt[MIPI_RX_MAX_PHY_NUM]; mipi_err_int_cnt_t g_mipi_err_int_cnt[MIPI_RX_MAX_DEV_NUM]; align_err_int_cnt_t g_align_err_int_cnt[MIPI_RX_MAX_DEV_NUM]; mipi_lane_mode_t g_lane_mode[MIPI_RX_MAX_DEV_NUM]; phy_err_int_cnt_t *mipi_hal_get_phy_err_int(int phy_id) { return &g_phy_err_int_cnt[phy_id]; } mipi_err_int_cnt_t *mipi_hal_get_mipi_err_int(int phy_id) { return &g_mipi_err_int_cnt[phy_id]; } align_err_int_cnt_t *mipi_hal_get_align_err_int(int phy_id) { return &g_align_err_int_cnt[phy_id]; } void mipi_rx_set_regs(mipi_rx_regs_type_t *regs) { g_mipi_rx_regs_type = regs; } void mipi_rx_set_irq(unsigned int mipi_rx_irq) { g_mipi_rx_irq_num = mipi_rx_irq; } /* function definition */ static void set_bit(unsigned long value, unsigned long offset, unsigned long addr) { unsigned long t, mask; mask = 1 << offset; t = osal_readl((const volatile void *)(uintptr_t)addr); t &= ~mask; t |= (value << offset) & mask; osal_writel(t, (volatile void *)(uintptr_t)addr); } static void write_reg32(unsigned long addr, unsigned int value, unsigned int mask) { unsigned int t; t = osal_readl((void *)(uintptr_t)addr); t &= ~mask; t |= value & mask; osal_writel(t, (void *)(uintptr_t)addr); } static mipi_rx_phy_cfg_t *get_mipi_rx_phy_regs(unsigned int phy_id) { return &g_mipi_rx_regs_type->mipi_rx_phy_cfg[phy_id]; } static mipi_rx_sys_regs_t *get_mipi_rx_sys_regs(void) { return &g_mipi_rx_regs_type->mipi_rx_chn_regs[0].mipi_rx_sys_regs; } static mipi_rx_chn_regs_t1 *get_mipi_ctrl_regs(combo_dev_t devno) { return &g_mipi_rx_regs_type->mipi_rx_chn_regs[devno].mipi_chn_regs_1; } static mipi_rx_chn_regs_t2 *get_mipi_ctrl_regs_2(combo_dev_t devno) { return &g_mipi_rx_regs_type->mipi_rx_chn_regs[devno].mipi_chn_regs_2; } unsigned int mipi_rx_get_chip_id(void) { return CHIP_SS524V100; } static void mipi_rx_set_cil_int_mask(unsigned int phy_id, unsigned int mask) { reg_mipi_int_msk mipi_int_msk; volatile mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; volatile mipi_rx_sys_regs_t *mipi_rx_sys_regs = get_mipi_rx_sys_regs(); mipi_int_msk.u32 = mipi_rx_sys_regs->mipi_int_msk.u32; switch (phy_id) { case MIPI_RX_PHY_ID_0: mipi_int_msk.bits.int_phycil0_mask = 0x0; break; case MIPI_RX_PHY_ID_1: mipi_int_msk.bits.int_phycil1_mask = 0x0; break; case MIPI_RX_PHY_ID_2: mipi_int_msk.bits.int_phycil2_mask = 0x0; break; case MIPI_RX_PHY_ID_3: mipi_int_msk.bits.int_phycil3_mask = 0x0; break; default: break; } mipi_rx_sys_regs->mipi_int_msk.u32 = mipi_int_msk.u32; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); mipi_rx_phy_cfg->mipi_cil_int_msk_link.u32 = mask; } void mipi_rx_unlock_config(void) { volatile mipi_rx_sys_regs_t *mipi_rx_sys_regs = get_mipi_rx_sys_regs(); mipi_rx_sys_regs->phy_cmos_lock.u32 = 0x5AF03869; /* ulock,mipi phy can set by driver */ } static void mipi_rx_set_phy_skew_link(unsigned int phy_id, unsigned int value) { volatile reg_phy_skew_link phy_skew_link; volatile mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_skew_link.u32 = value; mipi_rx_phy_cfg->phy_skew_link.u32 = phy_skew_link.u32; } static void mipi_rx_set_phy_fsmo_link(unsigned int phy_id, unsigned int value) { volatile mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); mipi_rx_phy_cfg->cil_fsm0_link.u32 = value; } static void mipi_rx_set_phy_rg_faclk0_en(unsigned int phy_id, bool enable) { volatile reg_phy_mode_link phy_mode_link; mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_mode_link.u32 = mipi_rx_phy_cfg->phy_mode_link.u32; phy_mode_link.bits.phy0_rg_faclk0_en = enable; mipi_rx_phy_cfg->phy_mode_link.u32 = phy_mode_link.u32; } static void mipi_rx_set_phy_rg_lp_clk_en(unsigned int phy_id, bool enable) { volatile reg_phy_mode_link phy_mode_link; mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_mode_link.u32 = mipi_rx_phy_cfg->phy_mode_link.u32; phy_mode_link.bits.phy0_rg_en_lp_clk = enable; mipi_rx_phy_cfg->phy_mode_link.u32 = phy_mode_link.u32; } static void mipi_rx_set_phy_rg_lp_mode_en(unsigned int phy_id, bool enable) { volatile reg_phy_mode_link phy_mode_link; mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_mode_link.u32 = mipi_rx_phy_cfg->phy_mode_link.u32; phy_mode_link.bits.phy0_rg_en_lp = enable; mipi_rx_phy_cfg->phy_mode_link.u32 = phy_mode_link.u32; } void mipi_rx_drv_set_mipi_crop_en(combo_dev_t devno, bool enable) { reg_mipi_ctrl_mode_pixel mipi_ctrl_mode_pixel; volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); mipi_ctrl_mode_pixel.u32 = mipi_ctrl_regs->mipi_ctrl_mode_pixel.u32; mipi_ctrl_mode_pixel.bits.crop_en = enable; mipi_ctrl_regs->mipi_ctrl_mode_pixel.u32 = mipi_ctrl_mode_pixel.u32; } void mipi_rx_drv_set_mipi_yuv_dt(combo_dev_t devno, data_type_t input_data_type) { reg_mipi_userdef_dt user_def_dt; reg_mipi_user_def user_def; reg_mipi_ctrl_mode_hs mipi_ctrl_mode_hs; reg_mipi_ctrl_mode_pixel mipi_ctrl_mode_pixel; volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); unsigned char bit_width = 0; bool user_def_en = 0; unsigned int temp_data_type = 0; if (input_data_type == DATA_TYPE_YUV422_8BIT) { bit_width = 0; temp_data_type = 0x1e; user_def_en = 1; } user_def_dt.u32 = mipi_ctrl_regs->mipi_userdef_dt.u32; user_def.u32 = mipi_ctrl_regs->mipi_user_def.u32; mipi_ctrl_mode_hs.u32 = mipi_ctrl_regs->mipi_ctrl_mode_hs.u32; mipi_ctrl_mode_pixel.u32 = mipi_ctrl_regs->mipi_ctrl_mode_pixel.u32; user_def_dt.bits.user_def0_dt = bit_width & 0x3; user_def_dt.bits.user_def1_dt = bit_width & 0x3; user_def_dt.bits.user_def2_dt = bit_width & 0x3; user_def_dt.bits.user_def3_dt = bit_width & 0x3; user_def.bits.user_def0 = temp_data_type & 0x3f; user_def.bits.user_def1 = temp_data_type & 0x3f; user_def.bits.user_def2 = temp_data_type & 0x3f; user_def.bits.user_def3 = temp_data_type & 0x3f; mipi_ctrl_mode_hs.bits.user_def_en = user_def_en; if (input_data_type == DATA_TYPE_YUV422_8BIT) { mipi_ctrl_mode_pixel.bits.mipi_yuv_420_nolegacy_en = 0; mipi_ctrl_mode_pixel.bits.mipi_yuv_420_legacy_en = 0; mipi_ctrl_mode_pixel.bits.mipi_yuv_422_en = 1; } mipi_ctrl_regs->mipi_userdef_dt.u32 = user_def_dt.u32; mipi_ctrl_regs->mipi_user_def.u32 = user_def.u32; mipi_ctrl_regs->mipi_ctrl_mode_hs.u32 = mipi_ctrl_mode_hs.u32; mipi_ctrl_regs->mipi_ctrl_mode_pixel.u32 = mipi_ctrl_mode_pixel.u32; } unsigned int mipi_rx_drv_get_phy_data(int phy_id, short lane_id) { volatile reg_phy_data_link phy_data_link; mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; unsigned int lane_data = 0x0; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_data_link.u32 = mipi_rx_phy_cfg->phy_data_link.u32; if (lane_id == MIPI_RX_LANE_ID_0) { lane_data = phy_data_link.bits.phy_data0_mipi; } else if (lane_id == MIPI_RX_LANE_ID_1) { lane_data = phy_data_link.bits.phy_data1_mipi; } else if (lane_id == MIPI_RX_LANE_ID_2) { lane_data = phy_data_link.bits.phy_data2_mipi; } else if (lane_id == MIPI_RX_LANE_ID_3) { lane_data = phy_data_link.bits.phy_data3_mipi; } return lane_data; } unsigned int mipi_rx_drv_get_phy_mipi_link_data(int phy_id, short lane_id) { volatile reg_phy_data_mipi_link phy_data_mipi_link; mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; unsigned int lane_data = 0x0; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_data_mipi_link.u32 = mipi_rx_phy_cfg->phy_data_mipi_link.u32; if (lane_id == MIPI_RX_LANE_ID_0) { lane_data = phy_data_mipi_link.bits.phy_data0_mipi_hs; } else if (lane_id == MIPI_RX_LANE_ID_1) { lane_data = phy_data_mipi_link.bits.phy_data1_mipi_hs; } else if (lane_id == MIPI_RX_LANE_ID_2) { lane_data = phy_data_mipi_link.bits.phy_data2_mipi_hs; } else if (lane_id == MIPI_RX_LANE_ID_3) { lane_data = phy_data_mipi_link.bits.phy_data3_mipi_hs; } return lane_data; } void mipi_rx_drv_set_clear_en(combo_dev_t devno) { reg_mipi_ctrl_mode_pixel mipi_ctrl_mode_pixel; volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); mipi_ctrl_mode_pixel.u32 = mipi_ctrl_regs->mipi_ctrl_mode_pixel.u32; mipi_ctrl_mode_pixel.bits.sync_clear_en = 0x0; mipi_ctrl_regs->mipi_ctrl_mode_pixel.u32 = mipi_ctrl_mode_pixel.u32; } void mipi_rx_drv_set_scan_mode(combo_dev_t devno, mipi_scan_mode_t scan_mode) { reg_mipi_interlaced mipi_interlaced; bool interlaced_en = FALSE; volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); if (scan_mode == MIPI_SCAN_INTERLACED) { interlaced_en = TRUE; } else if (scan_mode == MIPI_SCAN_PROGRESSIVE) { interlaced_en = FALSE; } else { interlaced_en = TRUE; } mipi_interlaced.u32 = mipi_ctrl_regs->mipi_interlaced.u32; mipi_interlaced.bits.mipi_csi_interlaced = interlaced_en; mipi_ctrl_regs->mipi_interlaced.u32 = mipi_interlaced.u32; } static void mipi_rx_set_lane_id(combo_dev_t devno, unsigned int lane_idx, short lane_id) { reg_lane_id0_chn lane_id0_chn0; volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); lane_id0_chn0.u32 = mipi_ctrl_regs->lane_id0_chn.u32; lane_id = (lane_id - MIPI_RX_LANE_NUM * devno); switch (lane_id) { case MIPI_RX_LANE_ID_0: lane_id0_chn0.bits.lane0_id = lane_idx & 0xf; break; case MIPI_RX_LANE_ID_1: lane_id0_chn0.bits.lane1_id = lane_idx & 0xf; break; case MIPI_RX_LANE_ID_2: lane_id0_chn0.bits.lane2_id = lane_idx & 0xf; break; case MIPI_RX_LANE_ID_3: lane_id0_chn0.bits.lane3_id = lane_idx & 0xf; break; default: break; } mipi_ctrl_regs->lane_id0_chn.u32 = lane_id0_chn0.u32; } void mipi_rx_drv_set_link_lane_id(combo_dev_t devno, input_mode_t input_mode, const short *lane_id) { unsigned int i; unsigned int lane_num = 0; if (input_mode == INPUT_MODE_MIPI) { lane_num = MIPI_LANE_NUM_PRE_DEV; } for (i = 0; i < lane_num; i++) { if (is_valid_id(lane_id[i])) { mipi_rx_set_lane_id(devno, i, lane_id[i]); } } } static void mipi_rx_drv_dev0_set_pn_swap(const unsigned char *pn_swap) { reg_d_p_swap_phy0123 dp_swap0; unsigned char lane0_swap = pn_swap[MIPI_LANE_ID_0]; unsigned char lane1_swap = pn_swap[MIPI_LANE_ID_1]; unsigned char lane2_swap = pn_swap[MIPI_LANE_ID_2]; unsigned char lane3_swap = pn_swap[MIPI_LANE_ID_3]; volatile mipi_rx_sys_regs_t *mipi_rx_sys_regs = get_mipi_rx_sys_regs(); dp_swap0.u32 = mipi_rx_sys_regs->d_p_swap_phy0123.u32; dp_swap0.bits.phy0_d0_swap = lane0_swap & 0x1; dp_swap0.bits.phy0_d1_swap = lane1_swap & 0x1; dp_swap0.bits.phy0_d2_swap = lane2_swap & 0x1; dp_swap0.bits.phy0_d3_swap = lane3_swap & 0x1; mipi_rx_sys_regs->d_p_swap_phy0123.u32 = dp_swap0.u32; } static void mipi_rx_drv_dev1_set_pn_swap(const unsigned char *pn_reverse) { reg_d_p_swap_phy0123 dp_swap0; unsigned char lane0_swap = pn_reverse[MIPI_LANE_ID_0]; unsigned char lane1_swap = pn_reverse[MIPI_LANE_ID_1]; unsigned char lane2_swap = pn_reverse[MIPI_LANE_ID_2]; unsigned char lane3_swap = pn_reverse[MIPI_LANE_ID_3]; volatile mipi_rx_sys_regs_t *mipi_rx_sys_regs = get_mipi_rx_sys_regs(); dp_swap0.u32 = mipi_rx_sys_regs->d_p_swap_phy0123.u32; dp_swap0.bits.phy1_d0_swap = lane0_swap & 0x1; dp_swap0.bits.phy1_d1_swap = lane1_swap & 0x1; dp_swap0.bits.phy1_d2_swap = lane2_swap & 0x1; dp_swap0.bits.phy1_d3_swap = lane3_swap & 0x1; mipi_rx_sys_regs->d_p_swap_phy0123.u32 = dp_swap0.u32; } static void mipi_rx_drv_dev2_set_pn_swap(const unsigned char *pn_reverse) { reg_d_p_swap_phy0123 dp_swap0; unsigned char lane0_swap = pn_reverse[MIPI_LANE_ID_0]; unsigned char lane1_swap = pn_reverse[MIPI_LANE_ID_1]; unsigned char lane2_swap = pn_reverse[MIPI_LANE_ID_2]; unsigned char lane3_swap = pn_reverse[MIPI_LANE_ID_3]; volatile mipi_rx_sys_regs_t *mipi_rx_sys_regs = get_mipi_rx_sys_regs(); dp_swap0.u32 = mipi_rx_sys_regs->d_p_swap_phy0123.u32; dp_swap0.bits.phy2_d0_swap = lane0_swap & 0x1; dp_swap0.bits.phy2_d1_swap = lane1_swap & 0x1; dp_swap0.bits.phy2_d2_swap = lane2_swap & 0x1; dp_swap0.bits.phy2_d3_swap = lane3_swap & 0x1; mipi_rx_sys_regs->d_p_swap_phy0123.u32 = dp_swap0.u32; } static void mipi_rx_drv_dev3_set_pn_swap(const unsigned char *pn_reverse) { reg_d_p_swap_phy0123 dp_swap0; unsigned char lane0_swap = pn_reverse[MIPI_LANE_ID_0]; unsigned char lane1_swap = pn_reverse[MIPI_LANE_ID_1]; unsigned char lane2_swap = pn_reverse[MIPI_LANE_ID_2]; unsigned char lane3_swap = pn_reverse[MIPI_LANE_ID_3]; volatile mipi_rx_sys_regs_t *mipi_rx_sys_regs = get_mipi_rx_sys_regs(); dp_swap0.u32 = mipi_rx_sys_regs->d_p_swap_phy0123.u32; dp_swap0.bits.phy3_d0_swap = lane0_swap & 0x1; dp_swap0.bits.phy3_d1_swap = lane1_swap & 0x1; dp_swap0.bits.phy3_d2_swap = lane2_swap & 0x1; dp_swap0.bits.phy3_d3_swap = lane3_swap & 0x1; mipi_rx_sys_regs->d_p_swap_phy0123.u32 = dp_swap0.u32; } void mipi_rx_drv_set_pn_swap(combo_dev_t devno, const unsigned char *pn_swap) { switch (devno) { case MIPI_RX_PHY_ID_0: mipi_rx_drv_dev0_set_pn_swap(pn_swap); break; case MIPI_RX_PHY_ID_1: mipi_rx_drv_dev1_set_pn_swap(pn_swap); break; case MIPI_RX_PHY_ID_2: mipi_rx_drv_dev2_set_pn_swap(pn_swap); break; case MIPI_RX_PHY_ID_3: mipi_rx_drv_dev3_set_pn_swap(pn_swap); break; default: break; } } static void mipi_rx_drv_set_chn0_mem_ctrl(bool enable) { reg_chn0_mem_ctrl chn0_mem_ctrl; mipi_rx_sys_regs_t *mipi_rx_sys_regs = NULL; mipi_rx_sys_regs = get_mipi_rx_sys_regs(); chn0_mem_ctrl.u32 = mipi_rx_sys_regs->chn0_mem_ctrl.u32; chn0_mem_ctrl.bits.chn0_mem_ck_gt = enable; mipi_rx_sys_regs->chn0_mem_ctrl.u32 = chn0_mem_ctrl.u32; } static void mipi_rx_drv_set_chn1_mem_ctrl(bool enable) { reg_chn1_mem_ctrl chn1_mem_ctrl; mipi_rx_sys_regs_t *mipi_rx_sys_regs = NULL; mipi_rx_sys_regs = get_mipi_rx_sys_regs(); chn1_mem_ctrl.u32 = mipi_rx_sys_regs->chn1_mem_ctrl.u32; chn1_mem_ctrl.bits.chn1_mem_ck_gt = enable; mipi_rx_sys_regs->chn1_mem_ctrl.u32 = chn1_mem_ctrl.u32; } static void mipi_rx_drv_set_chn2_mem_ctrl(bool enable) { reg_chn2_mem_ctrl chn2_mem_ctrl; mipi_rx_sys_regs_t *mipi_rx_sys_regs = NULL; mipi_rx_sys_regs = get_mipi_rx_sys_regs(); chn2_mem_ctrl.u32 = mipi_rx_sys_regs->chn2_mem_ctrl.u32; chn2_mem_ctrl.bits.chn2_mem_ck_gt = enable; mipi_rx_sys_regs->chn2_mem_ctrl.u32 = chn2_mem_ctrl.u32; } static void mipi_rx_drv_set_chn3_mem_ctrl(bool enable) { reg_chn3_mem_ctrl chn3_mem_ctrl; mipi_rx_sys_regs_t *mipi_rx_sys_regs = NULL; mipi_rx_sys_regs = get_mipi_rx_sys_regs(); chn3_mem_ctrl.u32 = mipi_rx_sys_regs->chn3_mem_ctrl.u32; chn3_mem_ctrl.bits.chn3_mem_ck_gt = enable; mipi_rx_sys_regs->chn3_mem_ctrl.u32 = chn3_mem_ctrl.u32; } void mipi_rx_drv_set_mem_cken(combo_dev_t devno, bool enable) { switch (devno) { case MIPI_RX_PHY_ID_0: mipi_rx_drv_set_chn0_mem_ctrl(enable); break; case MIPI_RX_PHY_ID_1: mipi_rx_drv_set_chn1_mem_ctrl(enable); break; case MIPI_RX_PHY_ID_2: mipi_rx_drv_set_chn2_mem_ctrl(enable); break; case MIPI_RX_PHY_ID_3: mipi_rx_drv_set_chn3_mem_ctrl(enable); break; default: break; } } static void mipi_rx_drv_set_phy_en_link(unsigned int phy_id, unsigned int lane_bitmap) { reg_phy_en_link phy_en_link; mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_en_link.u32 = mipi_rx_phy_cfg->phy_en_link.u32; if (lane_bitmap & 0x5) { phy_en_link.bits.phy_da_d0_valid = lane_bitmap & 0x1; phy_en_link.bits.phy_da_d2_valid = (lane_bitmap & 0x4) >> 2; /* 2 : bit 2 */ phy_en_link.bits.phy_d0_term_en = lane_bitmap & 0x1; phy_en_link.bits.phy_d2_term_en = (lane_bitmap & 0x4) >> 2; /* 2 : bit 2 */ phy_en_link.bits.phy_clk0_term_en = 1; } if (lane_bitmap & 0xa) { phy_en_link.bits.phy_da_d1_valid = (lane_bitmap & 0x2) >> 1; phy_en_link.bits.phy_da_d3_valid = (lane_bitmap & 0x8) >> 3; /* 3 : bit 3 */ phy_en_link.bits.phy_d1_term_en = (lane_bitmap & 0x2) >> 1; phy_en_link.bits.phy_d3_term_en = (lane_bitmap & 0x8) >> 3; /* 3 : bit 3 */ } if (lane_bitmap & 0xc) { phy_en_link.bits.phy_da_d2_valid = (lane_bitmap & 0x4) >> 2; /* 2 : bit 2 */ phy_en_link.bits.phy_da_d3_valid = (lane_bitmap & 0x8) >> 3; /* 3 : bit 3 */ phy_en_link.bits.phy_d2_term_en = (lane_bitmap & 0x4) >> 2; /* 2 : bit 2 */ phy_en_link.bits.phy_d3_term_en = (lane_bitmap & 0x8) >> 3; /* 3 : bit 3 */ } mipi_rx_phy_cfg->phy_en_link.u32 = phy_en_link.u32; } static void mipi_rx_drv_set_phy_mode(unsigned int phy_id, unsigned int lane_bitmap) { reg_phy_mode_link phy_mode_link; mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_mode_link.u32 = mipi_rx_phy_cfg->phy_mode_link.u32; phy_mode_link.bits.phy0_rg_en_d = lane_bitmap & 0xf; phy_mode_link.bits.phy0_rg_en_clk0 = 1; phy_mode_link.bits.phy0_rg_mipi_mode0 = 1; phy_mode_link.bits.phy0_rg_en_lp = lane_bitmap & 0xf; phy_mode_link.bits.phy0_rg_en_lp_clk = 1; mipi_rx_phy_cfg->phy_mode_link.u32 = phy_mode_link.u32; } static void mipi_rx_drv_set_phy_en(unsigned int lane_bitmap) { reg_phy_en phy_en; mipi_rx_sys_regs_t *mipi_rx_sys_regs = NULL; mipi_rx_sys_regs = get_mipi_rx_sys_regs(); phy_en.u32 = mipi_rx_sys_regs->phy_en.u32; if (lane_bitmap & 0xf) { phy_en.bits.phy0_en = 1; } if (lane_bitmap & 0xf0) { phy_en.bits.phy1_en = 1; } if (lane_bitmap & 0xf00) { phy_en.bits.phy2_en = 1; } if (lane_bitmap & 0xf000) { phy_en.bits.phy3_en = 1; } mipi_rx_sys_regs->phy_en.u32 = phy_en.u32; } static void mipi_rx_drv_set_lane_en(combo_dev_t devno, unsigned int lane_bitmap) { reg_lane_en lane_en; mipi_rx_sys_regs_t *mipi_rx_sys_regs = NULL; mipi_rx_sys_regs = get_mipi_rx_sys_regs(); lane_en.u32 = mipi_rx_sys_regs->lane_en.u32; lane_en.u32 = (lane_en.u32 & (~(0xf << (devno * MIPI_RX_LANE_NUM)))) | (lane_bitmap & 0xffffffff); mipi_rx_sys_regs->lane_en.u32 = lane_en.u32; } static void mipi_rx_drv_set_phy_cil_en(unsigned int lane_bitmap, bool enable) { reg_phy_cil_ctrl phy_cil_ctrl; mipi_rx_sys_regs_t *mipi_rx_sys_regs = NULL; mipi_rx_sys_regs = get_mipi_rx_sys_regs(); phy_cil_ctrl.u32 = mipi_rx_sys_regs->phy_cil_ctrl.u32; if (lane_bitmap & 0xf) { phy_cil_ctrl.bits.phycil0_cken = enable; } if (lane_bitmap & 0xf0) { phy_cil_ctrl.bits.phycil1_cken = 1; } if (lane_bitmap & 0xf00) { phy_cil_ctrl.bits.phycil2_cken = 1; } if (lane_bitmap & 0xf000) { phy_cil_ctrl.bits.phycil3_cken = 1; } mipi_rx_sys_regs->phy_cil_ctrl.u32 = phy_cil_ctrl.u32; } static void mipi_rx_drv_set_phy_cfg_mode(input_mode_t input_mode, unsigned int lane_bitmap) { reg_phycfg_mode phycfg_mode; mipi_rx_sys_regs_t *mipi_rx_sys_regs = NULL; unsigned int cfg_mode = 0; unsigned int cfg_mode_sel = 0; mipi_rx_sys_regs = get_mipi_rx_sys_regs(); phycfg_mode.u32 = mipi_rx_sys_regs->phycfg_mode.u32; if (input_mode == INPUT_MODE_MIPI) { cfg_mode = 0; cfg_mode_sel = 0; } if (lane_bitmap & 0xf) { phycfg_mode.bits.phycil0_cfg_mode = cfg_mode & 0x7; /* 0x7:mask */ phycfg_mode.bits.phycil0_cfg_mode_sel = cfg_mode_sel & 0x1; } if (lane_bitmap & 0xf0) { phycfg_mode.bits.phycil1_cfg_mode = cfg_mode & 0x7; /* 0x7:mask */ phycfg_mode.bits.phycil1_cfg_mode_sel = cfg_mode_sel & 0x1; } if (lane_bitmap & 0xf00) { phycfg_mode.bits.phycil2_cfg_mode = cfg_mode & 0x7; /* 0x7:mask */ phycfg_mode.bits.phycil2_cfg_mode_sel = cfg_mode_sel & 0x1; } if (lane_bitmap & 0xf000) { phycfg_mode.bits.phycil3_cfg_mode = cfg_mode & 0x7; /* 0x7:mask */ phycfg_mode.bits.phycil3_cfg_mode_sel = cfg_mode_sel & 0x1; } mipi_rx_sys_regs->phycfg_mode.u32 = phycfg_mode.u32; } static void mipi_rx_drv_set_phy_cfg_en(unsigned int lane_bitmap, bool enable) { reg_phycfg_en phycfg_en; mipi_rx_sys_regs_t *mipi_rx_sys_regs = NULL; mipi_rx_sys_regs = get_mipi_rx_sys_regs(); phycfg_en.u32 = mipi_rx_sys_regs->phycfg_en.u32; if (lane_bitmap & 0xf) { phycfg_en.bits.phycil0_cfg_en = enable; } if (lane_bitmap & 0xf0) { phycfg_en.bits.phycil1_cfg_en = enable; } if (lane_bitmap & 0xf00) { phycfg_en.bits.phycil2_cfg_en = enable; } if (lane_bitmap & 0xf000) { phycfg_en.bits.phycil3_cfg_en = enable; } mipi_rx_sys_regs->phycfg_en.u32 = phycfg_en.u32; } void mipi_rx_drv_set_phy_config(combo_dev_t devno, input_mode_t input_mode, unsigned int lane_bitmap) { unsigned int i; unsigned int mask; unsigned int phy_lane_bitmap; for (i = 0; i < MIPI_RX_MAX_PHY_NUM; i++) { mask = 0xf << (MIPI_RX_LANE_NUM * i); if (lane_bitmap & mask) { phy_lane_bitmap = (lane_bitmap & mask) >> (MIPI_RX_LANE_NUM * i); mipi_rx_drv_set_phy_en_link(i, phy_lane_bitmap); mipi_rx_drv_set_phy_mode(i, phy_lane_bitmap); } } mipi_rx_drv_set_phy_en(lane_bitmap); mipi_rx_drv_set_lane_en(devno, lane_bitmap); mipi_rx_drv_set_phy_cil_en(lane_bitmap, 1); mipi_rx_drv_set_phy_cfg_mode(input_mode, lane_bitmap); mipi_rx_drv_set_phy_cfg_en(lane_bitmap, 1); } static void mipi_rx_drv_set_phy_cmv(unsigned int phy_id, phy_cmv_mode_t cmv_mode, unsigned int lane_bitmap) { unsigned int mipi_cmv_mode = 0; reg_phy_mode_link phy_mode_link; mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; if (cmv_mode == PHY_CMV_GE1200MV) { mipi_cmv_mode = 0; } else if (cmv_mode == PHY_CMV_LT1200MV) { mipi_cmv_mode = 1; } mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_mode_link.u32 = mipi_rx_phy_cfg->phy_mode_link.u32; if (lane_bitmap & 0x5) { phy_mode_link.bits.phy0_rg_mipi_mode0 = mipi_cmv_mode & 0x1; } mipi_rx_phy_cfg->phy_mode_link.u32 = phy_mode_link.u32; } void mipi_rx_drv_set_phy_cmvmode(input_mode_t input_mode, phy_cmv_mode_t cmv_mode, unsigned int lane_bitmap) { unsigned int i; unsigned int mask; unsigned int phy_lane_bitmap; for (i = 0; i < MIPI_RX_MAX_PHY_NUM; i++) { mask = 0xf << (MIPI_RX_LANE_NUM * i); if (lane_bitmap & mask) { phy_lane_bitmap = (lane_bitmap & mask) >> (MIPI_RX_LANE_NUM * i); mipi_rx_drv_set_phy_cmv(i, cmv_mode, phy_lane_bitmap); } } mipi_rx_drv_set_phy_cfg_mode(input_mode, lane_bitmap); mipi_rx_drv_set_phy_cfg_en(lane_bitmap, 1); } int check_lane_can_used(combo_dev_t devno, const short lane_id[], int lane_num) { if (lane_num > MIPI_LANE_NUM_PRE_DEV) { return TD_FAILURE; } if (mipi_rx_get_chip_id() == CHIP_SS522V100) { if ((devno == 1) && ((lane_id[2] != -1) || (lane_id[3] != -1))) { /* 2/3:lane 2~3 */ ot_err("devno[%d] use lane_id[2]:%d or lane_id[3]:%d.\n", devno, lane_id[2], lane_id[3]); return TD_FAILURE; } } else { if (((devno == 2) || (devno == 3)) && /* 2/3:dev 2~3 */ ((lane_id[2] != -1) || (lane_id[3] != -1))) { /* 2/3:lane 2~3 */ ot_err("devno[%d] use lane_id[2]:%d or lane_id[3]:%d.\n", devno, lane_id[2], lane_id[3]); return TD_FAILURE; } } return TD_SUCCESS; } int mipi_rx_drv_is_lane_valid(combo_dev_t devno, short lane_id, lane_divide_mode_t mode) { int lane_valid = 0; switch (mode) { case LANE_DIVIDE_MODE_0: if ((lane_id >= (short)(MIPI_RX_LANE_NUM * devno)) && (lane_id < (short)(MIPI_RX_LANE_NUM * (devno + 1)))) { lane_valid = 1; } break; default: break; } return lane_valid; } void mipi_init_lane_mode(void) { int i; for (i = 0; i < MIPI_RX_MAX_DEV_NUM; i++) { g_lane_mode[i] = WORK_0LANE_MODE; } } static mipi_lane_mode_t mipi_rx_get_lane_work_mode(const short lane_id[], int lane_num) { int i; mipi_lane_mode_t lane_mode; int lane_used = 0; if (lane_num > MIPI_LANE_NUM_PRE_DEV) { osal_printk("lane_num err!\n"); return WORK_LANE_MODE_BUTT; } for (i = 0; i < lane_num; i++) { if (lane_id[i] != -1) { lane_used++; } } if (lane_used == 2) { /* 2:used 2lane */ lane_mode = WORK_2LANE_MODE; } else if (lane_used == 4) { /* 4:used 4lane */ lane_mode = WORK_4LANE_MODE; } else if (lane_used == 0) { /* 0:used 0lane */ lane_mode = WORK_0LANE_MODE; } else { osal_printk("lane_num err!\n"); lane_mode = WORK_LANE_MODE_BUTT; } return lane_mode; } int mipi_check_lane_mode(combo_dev_t devno, const short lane_id[], int lane_num) { mipi_lane_mode_t lane_mode; mipi_lane_mode_t lane_mode_last; lane_mode = mipi_rx_get_lane_work_mode(lane_id, lane_num); if (lane_mode == WORK_LANE_MODE_BUTT) { ot_err("invalid lane_mode!\n"); return TD_FAILURE; } lane_mode_last = g_lane_mode[devno]; g_lane_mode[devno] = lane_mode; if (mipi_rx_get_chip_id() == CHIP_SS522V100) { if ((g_lane_mode[0] == WORK_4LANE_MODE) && (g_lane_mode[1] != WORK_0LANE_MODE)) { /* 0/1: dev 0~1 */ ot_err("lane_mode not supoort!\n"); goto fail; } } else { if (((g_lane_mode[0] == WORK_4LANE_MODE) || (g_lane_mode[1] == WORK_4LANE_MODE)) && /* 0/1: dev 0~1 */ ((g_lane_mode[2] != WORK_0LANE_MODE) || (g_lane_mode[3] != WORK_0LANE_MODE))) { /* 2/3: dev 2~3 */ ot_err("lane_mode not supoort!\n"); goto fail; } } return TD_SUCCESS; fail: g_lane_mode[devno] = lane_mode_last; return TD_FAILURE; } static void mipi_rx_drv_hw_init(void); void mipi_rx_drv_set_hs_mode(lane_divide_mode_t mode) { int i; mipi_rx_drv_hw_init(); for (i = 0; i < MIPI_RX_MAX_PHY_NUM; i++) { mipi_rx_set_phy_rg_faclk0_en(i, g_phy_mode[mode][i].phy_rg_faclk0_en); mipi_rx_set_phy_rg_lp_clk_en(i, g_phy_mode[mode][i].phy_rg_lp_clk_en); mipi_rx_set_phy_rg_lp_mode_en(i, g_phy_mode[mode][i].phy_rg_lp_mode_en); } } static void mipi_rx_enable_disable_clock(combo_dev_t combo_dev, int enable) { set_bit((unsigned long)enable, MIPI_RX_PIX0_CLK_BIT, g_mipi_rx_core_reset_addr + MIPI_RX_CRG_OFFSET * (combo_dev + 1)); } void mipi_rx_drv_enable_clock(combo_dev_t combo_dev) { mipi_rx_enable_disable_clock(combo_dev, 1); } void mipi_rx_drv_disable_clock(combo_dev_t combo_dev) { mipi_rx_enable_disable_clock(combo_dev, 0); } static void mipi_rx_core_reset_unreset(combo_dev_t combo_dev, int reset) { set_bit((unsigned long)reset, MIPI_RX_PIX0_RST_BIT, g_mipi_rx_core_reset_addr + MIPI_RX_CRG_OFFSET * (combo_dev + 1)); } void mipi_rx_drv_core_reset(combo_dev_t combo_dev) { mipi_rx_core_reset_unreset(combo_dev, 1); } void mipi_rx_drv_core_unreset(combo_dev_t combo_dev) { mipi_rx_core_reset_unreset(combo_dev, 0); } void mipi_rx_drv_get_mipi_imgsize_statis(combo_dev_t devno, short vc, img_size_t *size) { reg_mipi_imgsize0_statis mipi_imgsize0_statis; reg_mipi_imgsize1_statis mipi_imgsize1_statis; reg_mipi_imgsize2_statis mipi_imgsize2_statis; reg_mipi_imgsize3_statis mipi_imgsize3_statis; volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); if (vc == MIPI_RX_VC_0) { mipi_imgsize0_statis.u32 = mipi_ctrl_regs->mipi_imgsize0_statis.u32; size->width = mipi_imgsize0_statis.bits.imgwidth_statis_vc0; size->height = mipi_imgsize0_statis.bits.imgheight_statis_vc0; } else if (vc == MIPI_RX_VC_1) { mipi_imgsize1_statis.u32 = mipi_ctrl_regs->mipi_imgsize1_statis.u32; size->width = mipi_imgsize1_statis.bits.imgwidth_statis_vc1; size->height = mipi_imgsize1_statis.bits.imgheight_statis_vc1; } else if (vc == MIPI_RX_VC_2) { mipi_imgsize2_statis.u32 = mipi_ctrl_regs->mipi_imgsize2_statis.u32; size->width = mipi_imgsize2_statis.bits.imgwidth_statis_vc2; size->height = mipi_imgsize2_statis.bits.imgheight_statis_vc2; } else if (vc == MIPI_RX_VC_3) { mipi_imgsize3_statis.u32 = mipi_ctrl_regs->mipi_imgsize3_statis.u32; size->width = mipi_imgsize3_statis.bits.imgwidth_statis_vc3; size->height = mipi_imgsize3_statis.bits.imgheight_statis_vc3; } else { size->width = 0; size->height = 0; } } static void mipi_rx_phy_cil_int_statis(int phy_id) { unsigned int phy_int_status; mipi_rx_phy_cfg_t *mipi_rx_phy_cfg = NULL; mipi_rx_phy_cfg = get_mipi_rx_phy_regs(phy_id); phy_int_status = mipi_rx_phy_cfg->mipi_cil_int_link.u32; if (phy_int_status) { mipi_rx_phy_cfg->mipi_cil_int_raw_link.u32 = 0xffffffff; if (phy_int_status & MIPI_ESC_CLK1) { g_phy_err_int_cnt[phy_id].clk1_fsm_escape_err_cnt++; } if (phy_int_status & MIPI_ESC_CLK0) { g_phy_err_int_cnt[phy_id].clk0_fsm_escape_err_cnt++; } if (phy_int_status & MIPI_ESC_D0) { g_phy_err_int_cnt[phy_id].d0_fsm_escape_err_cnt++; } if (phy_int_status & MIPI_ESC_D1) { g_phy_err_int_cnt[phy_id].d1_fsm_escape_err_cnt++; } if (phy_int_status & MIPI_ESC_D2) { g_phy_err_int_cnt[phy_id].d2_fsm_escape_err_cnt++; } if (phy_int_status & MIPI_ESC_D3) { g_phy_err_int_cnt[phy_id].d3_fsm_escape_err_cnt++; } if (phy_int_status & MIPI_TIMEOUT_CLK1) { g_phy_err_int_cnt[phy_id].clk1_fsm_timeout_err_cnt++; } if (phy_int_status & MIPI_TIMEOUT_CLK0) { g_phy_err_int_cnt[phy_id].clk0_fsm_timeout_err_cnt++; } if (phy_int_status & MIPI_TIMEOUT_D0) { g_phy_err_int_cnt[phy_id].d0_fsm_timeout_err_cnt++; } if (phy_int_status & MIPI_TIMEOUT_D1) { g_phy_err_int_cnt[phy_id].d1_fsm_timeout_err_cnt++; } if (phy_int_status & MIPI_TIMEOUT_D2) { g_phy_err_int_cnt[phy_id].d2_fsm_timeout_err_cnt++; } if (phy_int_status & MIPI_TIMEOUT_D3) { g_phy_err_int_cnt[phy_id].d3_fsm_timeout_err_cnt++; } } } static void mipi_int_statics(combo_dev_t devno) { unsigned int mipi_ctrl_int; mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); mipi_ctrl_int = mipi_ctrl_regs->mipi_ctrl_int.u32; /* Need read mipi_main_int and line_int, to clear MIPI_MAIN_INT_ST and MIPI_LINE_INTR_ST interrupt. */ if (mipi_ctrl_int) { mipi_ctrl_regs->mipi_ctrl_int_raw.u32 = 0xffffffff; } if (mipi_ctrl_int) { if (mipi_ctrl_int & CMD_FIFO_READ_ERR) { g_mipi_err_int_cnt[devno].cmd_fifo_rderr_cnt++; } if (mipi_ctrl_int & DATA_FIFO_READ_ERR) { g_mipi_err_int_cnt[devno].data_fifo_rderr_cnt++; } if (mipi_ctrl_int & CMD_FIFO_WRITE_ERR) { g_mipi_err_int_cnt[devno].cmd_fifo_wrerr_cnt++; } if (mipi_ctrl_int & DATA_FIFO_WRITE_ERR) { g_mipi_err_int_cnt[devno].data_fifo_wrerr_cnt++; } } } static void csi_frame_crc_int_statis(combo_dev_t devno, unsigned int mipi_crc_intr_st) { if (mipi_crc_intr_st & MIPI_VC0_FRAME_CRC) { g_mipi_err_int_cnt[devno].vc0_err_crc_cnt++; } if (mipi_crc_intr_st & MIPI_VC1_FRAME_CRC) { g_mipi_err_int_cnt[devno].vc1_err_crc_cnt++; } if (mipi_crc_intr_st & MIPI_VC2_FRAME_CRC) { g_mipi_err_int_cnt[devno].vc2_err_crc_cnt++; } if (mipi_crc_intr_st & MIPI_VC3_FRAME_CRC) { g_mipi_err_int_cnt[devno].vc3_err_crc_cnt++; } } static void csi_header_ecc_int_statis(combo_dev_t devno, unsigned int mipi_crc_intr_st) { if (mipi_crc_intr_st & MIPI_VC0_PKT_HEADER_ECC) { g_mipi_err_int_cnt[devno].vc0_err_ecc_corrected_cnt++; } if (mipi_crc_intr_st & MIPI_VC1_PKT_HEADER_ECC) { g_mipi_err_int_cnt[devno].vc1_err_ecc_corrected_cnt++; } if (mipi_crc_intr_st & MIPI_VC2_PKT_HEADER_ECC) { g_mipi_err_int_cnt[devno].vc2_err_ecc_corrected_cnt++; } if (mipi_crc_intr_st & MIPI_VC3_PKT_HEADER_ECC) { g_mipi_err_int_cnt[devno].vc3_err_ecc_corrected_cnt++; } if (mipi_crc_intr_st & MIPI_PKT_HEADER_ERR) { g_mipi_err_int_cnt[devno].err_ecc_double_cnt++; } } static void csi_order_err_int_statis(combo_dev_t devno, unsigned int mipi_crc_intr_st) { if (mipi_crc_intr_st & MIPI_VC0_ORDER_ERR) { g_mipi_err_int_cnt[devno].err_f_seq_vc0_cnt++; } if (mipi_crc_intr_st & MIPI_VC1_ORDER_ERR) { g_mipi_err_int_cnt[devno].err_f_seq_vc1_cnt++; } if (mipi_crc_intr_st & MIPI_VC2_ORDER_ERR) { g_mipi_err_int_cnt[devno].err_f_seq_vc2_cnt++; } if (mipi_crc_intr_st & MIPI_VC3_ORDER_ERR) { g_mipi_err_int_cnt[devno].err_f_seq_vc3_cnt++; } } static void csi_no_match_err_int_statis(combo_dev_t devno, unsigned int mipi_crc_intr_st) { if (mipi_crc_intr_st & MIPI_VC0_NO_MATCH) { g_mipi_err_int_cnt[devno].err_f_bndry_match_vc0_cnt++; } if (mipi_crc_intr_st & MIPI_VC1_NO_MATCH) { g_mipi_err_int_cnt[devno].err_f_bndry_match_vc1_cnt++; } if (mipi_crc_intr_st & MIPI_VC2_NO_MATCH) { g_mipi_err_int_cnt[devno].err_f_bndry_match_vc2_cnt++; } if (mipi_crc_intr_st & MIPI_VC3_NO_MATCH) { g_mipi_err_int_cnt[devno].err_f_bndry_match_vc3_cnt++; } } static void csi_int_statis(combo_dev_t devno) { unsigned int mipi_crc_intr_st; volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); mipi_crc_intr_st = mipi_ctrl_regs->mipi_crc_intr_st.u32; if (mipi_crc_intr_st) { mipi_ctrl_regs->mipi_crc_intr_raw.u32 = 0xffffffff; } csi_frame_crc_int_statis(devno, mipi_crc_intr_st); csi_header_ecc_int_statis(devno, mipi_crc_intr_st); csi_order_err_int_statis(devno, mipi_crc_intr_st); csi_no_match_err_int_statis(devno, mipi_crc_intr_st); } static void align_int_statis(combo_dev_t devno) { unsigned int align_int; volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); align_int = mipi_ctrl_regs->align_int.u32; if (align_int) { mipi_ctrl_regs->align_int_raw.u32 = 0xffffffff; } if (align_int & ALIGN_FIFO_FULL_ERR) { g_align_err_int_cnt[devno].fifo_full_err_cnt++; } if (align_int & ALIGN_LANE0_ERR) { g_align_err_int_cnt[devno].lane0_align_err_cnt++; } if (align_int & ALIGN_LANE1_ERR) { g_align_err_int_cnt[devno].lane1_align_err_cnt++; } if (align_int & ALIGN_LANE2_ERR) { g_align_err_int_cnt[devno].lane2_align_err_cnt++; } if (align_int & ALIGN_LANE3_ERR) { g_align_err_int_cnt[devno].lane3_align_err_cnt++; } } static int mipi_rx_interrupt_route(int irq, void *dev_id) { volatile mipi_rx_sys_regs_t *mipi_rx_sys_regs = get_mipi_rx_sys_regs(); volatile mipi_rx_chn_regs_t2 *mipi_ctrl_regs2 = NULL; int i; ot_mipi_rx_unused(irq); ot_mipi_rx_unused(dev_id); for (i = 0; i < MIPI_RX_MAX_PHY_NUM; i++) { mipi_rx_phy_cil_int_statis(i); } for (i = 0; i < MIPI_RX_MAX_DEV_NUM; i++) { mipi_ctrl_regs2 = get_mipi_ctrl_regs_2(i); if (mipi_ctrl_regs2->chn_int_raw.u32) { mipi_rx_drv_core_reset(i); mipi_rx_drv_core_unreset(i); } else { continue; } mipi_int_statics(i); csi_int_statis(i); align_int_statis(i); mipi_ctrl_regs2->chn_int_raw.u32 = 0xf; } mipi_rx_sys_regs->mipi_int_raw.u32 = 0xffffffff; return OSAL_IRQ_HANDLED; } static int mipi_rx_drv_reg_init(void) { if (g_mipi_rx_regs_type == NULL) { g_mipi_rx_regs_type = (mipi_rx_regs_type_t *)osal_ioremap(MIPI_RX_REGS_ADDR, (unsigned int)MIPI_RX_REGS_SIZE); if (g_mipi_rx_regs_type == NULL) { ot_err("remap mipi_rx reg addr fail\n"); return -1; } } return 0; } static int mipi_rx_register_irq(void) { int ret; ret = osal_request_irq(g_mipi_rx_irq_num, mipi_rx_interrupt_route, NULL, "MIPI_RX", mipi_rx_interrupt_route); if (ret < 0) { ot_err("mipi_rx: failed to register irq.\n"); return -1; } return 0; } static void mipi_rx_unregister_irq(void) { osal_free_irq(g_mipi_rx_irq_num, mipi_rx_interrupt_route); } static void mipi_rx_drv_hw_init(void) { unsigned long mipi_rx_crg_addr; int i; mipi_rx_crg_addr = g_mipi_rx_core_reset_addr; /* cil clk & bus clk */ write_reg32(mipi_rx_crg_addr, 1 << MIPI_RX_BUS_CLK_BIT, 0x1 << MIPI_RX_BUS_CLK_BIT); write_reg32(mipi_rx_crg_addr, 1 << MIPI_RX_CIL_CLK_BIT, 0x1 << MIPI_RX_CIL_CLK_BIT); /* bus reset */ write_reg32(mipi_rx_crg_addr, 1 << MIPI_RX_BUS_RST_BIT, 0x1 << MIPI_RX_BUS_RST_BIT); osal_udelay(10); /* 10 : wait reset ok */ write_reg32(mipi_rx_crg_addr, 0, 0x1 << MIPI_RX_BUS_RST_BIT); for (i = 0; i < MIPI_RX_MAX_PHY_NUM; ++i) { mipi_rx_set_cil_int_mask(i, MIPI_CIL_INT_MASK); mipi_rx_set_phy_skew_link(i, SKEW_LINK); mipi_rx_set_phy_fsmo_link(i, MIPI_FSMO_VALUE); } } static void mipi_rx_drv_hw_exit(void) { unsigned long mipi_rx_crg_addr; mipi_rx_crg_addr = g_mipi_rx_core_reset_addr; /* reset */ write_reg32(mipi_rx_crg_addr, 1 << MIPI_RX_BUS_RST_BIT, 0x1 << MIPI_RX_BUS_RST_BIT); /* cil clk & bus clk */ write_reg32(mipi_rx_crg_addr, 0, 0x1 << MIPI_RX_CIL_CLK_BIT); write_reg32(mipi_rx_crg_addr, 0, 0x1 << MIPI_RX_BUS_CLK_BIT); } int mipi_rx_drv_init(void) { int ret; ret = mipi_rx_drv_reg_init(); if (ret < 0) { ot_err("mipi_rx_drv_reg_init fail!\n"); goto fail0; } ret = mipi_rx_register_irq(); if (ret < 0) { ot_err("mipi_rx_register_irq fail!\n"); goto fail0; } g_mipi_rx_core_reset_addr = (unsigned long)(uintptr_t)osal_ioremap(MIPI_RX_CRG_ADDR, (unsigned long)MIPI_RX_CRG_SIZE); if (g_mipi_rx_core_reset_addr == (unsigned long)NULL) { ot_err("mipi_rx reset ioremap failed!\n"); goto fail1; } g_mipi_sys_ctrl_addr = (unsigned long)(uintptr_t)osal_ioremap(MIPI_RX_SYS_CTRL_ADDR, (unsigned long)MIPI_RX_SYS_CTRL_SIZE); if (g_mipi_sys_ctrl_addr == (unsigned long)NULL) { ot_err("mipi_rx sys_strl ioremap failed!\n"); goto fail2; } mipi_rx_drv_hw_init(); return 0; fail2: osal_iounmap((void *)(uintptr_t)g_mipi_rx_core_reset_addr); fail1: mipi_rx_unregister_irq(); fail0: return -1; } void mipi_rx_drv_exit(void) { mipi_rx_unregister_irq(); mipi_rx_drv_hw_exit(); osal_iounmap((void *)(uintptr_t)g_mipi_rx_core_reset_addr); osal_iounmap((void *)(uintptr_t)g_mipi_sys_ctrl_addr); } void mipi_rx_drv_set_chn_int_mask(combo_dev_t devno) { reg_mipi_int_msk mipi_int_msk; volatile mipi_rx_sys_regs_t *mipi_rx_sys_regs = get_mipi_rx_sys_regs(); mipi_int_msk.u32 = mipi_rx_sys_regs->mipi_int_msk.u32; if (devno == 0) { mipi_int_msk.bits.int_chn0_mask = 0x1; } else if (devno == 1) { mipi_int_msk.bits.int_chn1_mask = 0x1; } else if (devno == 2) { /* 2:dev index */ mipi_int_msk.bits.int_chn2_mask = 0x1; } else if (devno == 3) { /* 3:dev index */ mipi_int_msk.bits.int_chn3_mask = 0x1; } mipi_rx_sys_regs->mipi_int_msk.u32 = mipi_int_msk.u32; } void mipi_rx_drv_set_mipi_ctrl_int_mask(combo_dev_t devno, unsigned int mask) { volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); mipi_ctrl_regs->mipi_ctrl_int_msk.u32 = mask; } void mipi_rx_drv_set_mipi_csi_int_mask(combo_dev_t devno, unsigned int mask) { volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); mipi_ctrl_regs->mipi_crc_intr_msk.u32 = mask; } void mipi_rx_drv_set_align_int_mask(combo_dev_t devno, unsigned int mask) { volatile mipi_rx_chn_regs_t1 *mipi_ctrl_regs = get_mipi_ctrl_regs(devno); mipi_ctrl_regs->align_int_msk.u32 = mask; } void mipi_rx_drv_set_chn_int_category_mask(combo_dev_t devno, unsigned int mask) { volatile mipi_rx_chn_regs_t2 *mipi_ctrl_regs2 = get_mipi_ctrl_regs_2(devno); mipi_ctrl_regs2->chn_int_mask.u32 = mask; }