From b258ef99c281aa3d2d220dea43c45984cdb8ac69 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 14 Mar 2025 14:39:17 +0800 Subject: [PATCH] phy: rockchip: mipi csi2 dphy support rv1126b Change-Id: I45365edfa4ffb7363bec13387e9b2b3d2a6a0a0b Signed-off-by: Zefa Chen --- .../rockchip/phy-rockchip-csi2-dphy-common.h | 1 + .../phy/rockchip/phy-rockchip-csi2-dphy-hw.c | 103 +++++++++++++++++- drivers/phy/rockchip/phy-rockchip-csi2-dphy.c | 17 ++- 3 files changed, 117 insertions(+), 4 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h index 97f24c1e2b7f..295974d9bc89 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h @@ -26,6 +26,7 @@ enum csi2_dphy_chip_id { CHIP_ID_RV1106 = 0x3, CHIP_ID_RK3562 = 0x4, CHIP_ID_RK3576 = 0x5, + CHIP_ID_RV1126B = 0x6, }; enum csi2_dphy_rx_pads { diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c index 9ea9e8265f22..f3d317d040c7 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c @@ -44,6 +44,11 @@ /*RK3576 DPHY GRF REG OFFSET */ #define GRF_SOC_CON5_RK3576 (0x14) +/*RV1126B DPHY GRF REG OFFSET */ +#define CSIPHY0_GRF_CON_RV1126B (0x50010) +#define CSIPHY1_GRF_CON_RV1126B (0x50014) +#define MISC_GRF_CON_RV1126B (0x50020) + /*GRF REG BIT DEFINE */ #define GRF_CSI2PHY_LANE_SEL_SPLIT (0x1) #define GRF_CSI2PHY_SEL_SPLIT_0_1 (0x0) @@ -78,6 +83,12 @@ #define CSI2_DPHY_PATH1_MODE_SEL (0x84C) #define CSI2_DPHY_PATH1_LVDS_MODE_SEL (0x880) +/* rv1126b path mode */ +#define RV1126B_CSI2_DPHY_PATH0_MODE_SEL (0x66C) +#define RV1126B_CSI2_DPHY_PATH0_LVDS_MODE_SEL (0x700) +#define RV1126B_CSI2_DPHY_PATH1_MODE_SEL (0xACC) +#define RV1126B_CSI2_DPHY_PATH1_LVDS_MODE_SEL (0xB00) + /* PHY REG BIT DEFINE */ #define CSI2_DPHY_LANE_MODE_FULL (0x4) #define CSI2_DPHY_LANE_MODE_SPLIT (0x2) @@ -525,6 +536,49 @@ static const struct grf_reg rk3576_grf_dphy_regs[] = { [GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(GRF_SOC_CON5_RK3576, 1, 2), }; +static const struct grf_reg rv1126b_grf_dphy_regs[] = { + [GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 4, 0), + [GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 1, 8), + [GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 4, 4), + [GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 2, 4), + [GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 2, 6), + [GRF_DPHY_CLK_INV_SEL] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 1, 9), + [GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 1, 10), + [GRF_DPHY_CLK1_INV_SEL] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 1, 11), + [GRF_DPHY1_CSI2PHY_FORCERXMODE] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 4, 0), + [GRF_DPHY1_CSI2PHY_CLKLANE_EN] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 1, 8), + [GRF_DPHY1_CSI2PHY_DATALANE_EN] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 4, 4), + [GRF_DPHY1_CSI2PHY_DATALANE_EN0] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 2, 4), + [GRF_DPHY1_CSI2PHY_DATALANE_EN1] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 2, 6), + [GRF_DPHY1_CLK_INV_SEL] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 1, 9), + [GRF_DPHY1_CSI2PHY_CLKLANE1_EN] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 1, 10), + [GRF_DPHY1_CLK1_INV_SEL] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 1, 11), + [GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(MISC_GRF_CON_RV1126B, 1, 0), + [GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(MISC_GRF_CON_RV1126B, 1, 1), +}; + +static const struct csi2dphy_reg rv1126b_csi2dphy_regs[] = { + [CSI2PHY_REG_CTRL_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CTRL_LANE_ENABLE), + [CSI2PHY_DUAL_CLK_EN] = CSI2PHY_REG(CSI2_DPHY_DUAL_CAL_EN), + [CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK_WR_THS_SETTLE), + [CSI2PHY_CLK_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK_CALIB_EN), + [CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_WR_THS_SETTLE), + [CSI2PHY_LANE0_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_CALIB_EN), + [CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_WR_THS_SETTLE), + [CSI2PHY_LANE1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_CALIB_EN), + [CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_WR_THS_SETTLE), + [CSI2PHY_LANE2_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_CALIB_EN), + [CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_WR_THS_SETTLE), + [CSI2PHY_LANE3_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_CALIB_EN), + [CSI2PHY_CLK1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_WR_THS_SETTLE), + [CSI2PHY_CLK1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_CALIB_EN), + [CSI2PHY_CLK1_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_LANE_EN), + [CSI2PHY_PATH0_MODEL] = CSI2PHY_REG(RV1126B_CSI2_DPHY_PATH0_MODE_SEL), + [CSI2PHY_PATH0_LVDS_MODEL] = CSI2PHY_REG(RV1126B_CSI2_DPHY_PATH0_LVDS_MODE_SEL), + [CSI2PHY_PATH1_MODEL] = CSI2PHY_REG(RV1126B_CSI2_DPHY_PATH1_MODE_SEL), + [CSI2PHY_PATH1_LVDS_MODEL] = CSI2PHY_REG(RV1126B_CSI2_DPHY_PATH1_LVDS_MODE_SEL), +}; + /* These tables must be sorted by .range_h ascending. */ static const struct hsfreq_range rk3568_csi2_dphy_hw_hsfreq_ranges[] = { { 109, 0x02}, { 149, 0x03}, { 199, 0x06}, { 249, 0x06}, @@ -683,6 +737,8 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); } else if (hw->drv_data->chip_id == CHIP_ID_RK3576) { write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); + } else if (hw->drv_data->chip_id == CHIP_ID_RV1126B) { + write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); } break; case 2: @@ -709,6 +765,8 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); } else if (hw->drv_data->chip_id == CHIP_ID_RK3576) { write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); + } else if (hw->drv_data->chip_id == CHIP_ID_RV1126B) { + write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); } break; case 4: @@ -728,6 +786,11 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN0, GENMASK(sensor->lanes - 1, 0)); write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); + } else if (hw->drv_data->chip_id == CHIP_ID_RV1126B) { + write_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); + write_grf_reg(hw, GRF_DPHY1_CSI2PHY_DATALANE_EN0, + GENMASK(sensor->lanes - 1, 0)); + write_grf_reg(hw, GRF_DPHY1_CSI2PHY_CLKLANE_EN, 0x1); } break; case 5: @@ -747,6 +810,11 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN1, GENMASK(sensor->lanes - 1, 0)); write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE1_EN, 0x1); + } else if (hw->drv_data->chip_id == CHIP_ID_RV1126B) { + write_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); + write_grf_reg(hw, GRF_DPHY1_CSI2PHY_DATALANE_EN1, + GENMASK(sensor->lanes - 1, 0)); + write_grf_reg(hw, GRF_DPHY1_CSI2PHY_CLKLANE1_EN, 0x1); } break; default: @@ -788,6 +856,13 @@ static int csi2_dphy_hw_stream_on(struct csi2_dphy *dphy, } } + if (hw->drv_data->chip_id == CHIP_ID_RV1126B && + dphy->phy_index % 3 == DPHY2) { + read_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, &val); + val |= BIT(7);//split mode lane2_3 reset + write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, val); + } + /* set data lane num and enable clock lane */ /* * for rk356x: dphy0 is used just for full mode, @@ -905,7 +980,8 @@ static int csi2_dphy_hw_stream_on(struct csi2_dphy *dphy, } } - if (hw->drv_data->chip_id == CHIP_ID_RV1106) { + if (hw->drv_data->chip_id == CHIP_ID_RV1106 || + hw->drv_data->chip_id == CHIP_ID_RV1126B) { if (dphy->phy_index % 3 == DPHY0 || dphy->phy_index % 3 == DPHY1) { if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { @@ -924,7 +1000,8 @@ static int csi2_dphy_hw_stream_on(struct csi2_dphy *dphy, write_csi2_dphy_reg(hw, CSI2PHY_PATH1_LVDS_MODEL, (lvds_width << 4) | 0X0f); } } - if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { + if (hw->drv_data->chip_id == CHIP_ID_RV1106 && + sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { if (hw->lane_mode == LANE_MODE_FULL) write_csi2_dphy_reg(hw, CSI2PHY_CLK_INV, 0x04); else @@ -1083,6 +1160,11 @@ static void rk3576_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw) hw->grf_regs = rk3576_grf_dphy_regs; } +static void rv1126b_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw) +{ + hw->grf_regs = rv1126b_grf_dphy_regs; +} + static const struct dphy_hw_drv_data rk3568_csi2_dphy_hw_drv_data = { .hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges, .num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges), @@ -1148,6 +1230,19 @@ static const struct dphy_hw_drv_data rk3576_csi2_dphy_hw_drv_data = { .stream_off = csi2_dphy_hw_stream_off, }; +static const struct dphy_hw_drv_data rv1126b_csi2_dphy_hw_drv_data = { + .hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges, + .num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges), + .csi2dphy_regs = rv1126b_csi2dphy_regs, + .num_csi2dphy_regs = ARRAY_SIZE(rv1126b_csi2dphy_regs), + .grf_regs = rv1126b_grf_dphy_regs, + .num_grf_regs = ARRAY_SIZE(rv1126b_grf_dphy_regs), + .individual_init = rv1126b_csi2_dphy_hw_individual_init, + .chip_id = CHIP_ID_RV1126B, + .stream_on = csi2_dphy_hw_stream_on, + .stream_off = csi2_dphy_hw_stream_off, +}; + static const struct of_device_id rockchip_csi2_dphy_hw_match_id[] = { { .compatible = "rockchip,rk3568-csi2-dphy-hw", @@ -1169,6 +1264,10 @@ static const struct of_device_id rockchip_csi2_dphy_hw_match_id[] = { .compatible = "rockchip,rk3576-csi2-dphy-hw", .data = &rk3576_csi2_dphy_hw_drv_data, }, + { + .compatible = "rockchip,rv1126b-csi2-dphy-hw", + .data = &rv1126b_csi2_dphy_hw_drv_data, + }, {} }; MODULE_DEVICE_TABLE(of, rockchip_csi2_dphy_hw_match_id); diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c index ad589467654b..b4a976e06f18 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c @@ -208,7 +208,8 @@ static int rockchip_csi2_dphy_attach_hw(struct csi2_dphy *dphy, int csi_idx, int dphy->csi_info.dphy_vendor[index] = PHY_VENDOR_INNO; mutex_unlock(&dphy_hw->mutex); } - } else if (dphy->drv_data->chip_id == CHIP_ID_RK3562) { + } else if (dphy->drv_data->chip_id == CHIP_ID_RK3562 || + dphy->drv_data->chip_id == CHIP_ID_RV1126B) { dphy_hw = dphy->dphy_hw_group[csi_idx / 2]; mutex_lock(&dphy_hw->mutex); if (csi_idx == 0 || csi_idx == 2) { @@ -393,7 +394,8 @@ static int rockchip_csi2_dphy_detach_hw(struct csi2_dphy *dphy, int csi_idx, int rockchip_csi2_inno_phy_remove_dphy_dev(dphy, dphy_hw); mutex_unlock(&dphy_hw->mutex); } - } else if (dphy->drv_data->chip_id == CHIP_ID_RK3562) { + } else if (dphy->drv_data->chip_id == CHIP_ID_RK3562 || + dphy->drv_data->chip_id == CHIP_ID_RV1126B) { dphy_hw = (struct csi2_dphy_hw *)dphy->phy_hw[index]; if (!dphy_hw) { dev_err(dphy->dev, "%s csi_idx %d detach hw failed\n", @@ -1070,6 +1072,13 @@ static struct dphy_drv_data rk3576_dphy_drv_data = { .num_samsung_phy = 1, }; +static struct dphy_drv_data rv1126b_dphy_drv_data = { + .dev_name = "csi2dphy", + .chip_id = CHIP_ID_RV1126B, + .num_inno_phy = 2, + .num_samsung_phy = 0, +}; + static const struct of_device_id rockchip_csi2_dphy_match_id[] = { { .compatible = "rockchip,rk3568-csi2-dphy", @@ -1091,6 +1100,10 @@ static const struct of_device_id rockchip_csi2_dphy_match_id[] = { .compatible = "rockchip,rk3576-csi2-dphy", .data = &rk3576_dphy_drv_data, }, + { + .compatible = "rockchip,rv1126b-csi2-dphy", + .data = &rv1126b_dphy_drv_data, + }, {} }; MODULE_DEVICE_TABLE(of, rockchip_csi2_dphy_match_id);