Files
hisi_SS524V100_SDK/interdrv/mipi_rx/mipi_rx_hal.c
T

1468 lines
44 KiB
C

/*
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
*/
#include "mipi_rx_hal.h"
#include <linux/types.h>
#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;
}