From 6d31ebb3ecd0e5d8774596479c1fd87bd2aa74fa Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 3 Jan 2023 15:45:13 +0800 Subject: [PATCH] phy: rockchip: csi2-dphy: support rk3562 Signed-off-by: Zefa Chen Change-Id: I938047b37e2feba021a19f953f859679468fee1a --- .../rockchip/phy-rockchip-csi2-dphy-common.h | 1 + .../phy/rockchip/phy-rockchip-csi2-dphy-hw.c | 126 +++++++++++++++--- drivers/phy/rockchip/phy-rockchip-csi2-dphy.c | 9 ++ 3 files changed, 121 insertions(+), 15 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h index 9d4ea147c9c3..0ec812bcb014 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h @@ -19,6 +19,7 @@ enum csi2_dphy_chip_id { CHIP_ID_RK3588 = 0x1, CHIP_ID_RK3588_DCPHY = 0x2, CHIP_ID_RV1106 = 0x3, + CHIP_ID_RK3562 = 0x4, }; 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 527962352337..1440844f0185 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c @@ -24,6 +24,10 @@ #include #include "phy-rockchip-csi2-dphy-common.h" +/* RK3562 DPHY GRF REG OFFSET */ +#define RK3562_GRF_VI_CON0 (0x0520) +#define RK3562_GRF_VI_CON1 (0x0524) + /* GRF REG OFFSET */ #define GRF_VI_CON0 (0x0340) #define GRF_VI_CON1 (0x0344) @@ -156,6 +160,15 @@ enum grf_reg_id { /* below is for rv1106 only */ GRF_MIPI_HOST0_SEL, GRF_LVDS_HOST0_SEL, + /* below is for rk3562 */ + GRF_DPHY1_CLK_INV_SEL, + GRF_DPHY1_CLK1_INV_SEL, + GRF_DPHY1_CSI2PHY_CLKLANE1_EN, + GRF_DPHY1_CSI2PHY_FORCERXMODE, + GRF_DPHY1_CSI2PHY_CLKLANE_EN, + GRF_DPHY1_CSI2PHY_DATALANE_EN, + GRF_DPHY1_CSI2PHY_DATALANE_EN0, + GRF_DPHY1_CSI2PHY_DATALANE_EN1, }; enum csi2dphy_reg_id { @@ -422,6 +435,45 @@ static const struct csi2dphy_reg rv1106_csi2dphy_regs[] = { [CSI2PHY_CLK_INV] = CSI2PHY_REG(CSI2_DPHY_CLK_INV), }; +static const struct grf_reg rk3562_grf_dphy_regs[] = { + [GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(RK3562_GRF_VI_CON0, 4, 0), + [GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(RK3562_GRF_VI_CON0, 4, 4), + [GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(RK3562_GRF_VI_CON0, 2, 4), + [GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(RK3562_GRF_VI_CON0, 2, 6), + [GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(RK3562_GRF_VI_CON0, 1, 8), + [GRF_DPHY_CLK_INV_SEL] = GRF_REG(RK3562_GRF_VI_CON0, 1, 9), + [GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(RK3562_GRF_VI_CON0, 1, 10), + [GRF_DPHY_CLK1_INV_SEL] = GRF_REG(RK3562_GRF_VI_CON0, 1, 11), + [GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(RK3562_GRF_VI_CON0, 1, 12), + [GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(RK3562_GRF_VI_CON0, 1, 13), + [GRF_DPHY1_CSI2PHY_FORCERXMODE] = GRF_REG(RK3562_GRF_VI_CON1, 4, 0), + [GRF_DPHY1_CSI2PHY_DATALANE_EN] = GRF_REG(RK3562_GRF_VI_CON1, 4, 4), + [GRF_DPHY1_CSI2PHY_DATALANE_EN0] = GRF_REG(RK3562_GRF_VI_CON1, 2, 4), + [GRF_DPHY1_CSI2PHY_DATALANE_EN1] = GRF_REG(RK3562_GRF_VI_CON1, 2, 6), + [GRF_DPHY1_CSI2PHY_CLKLANE_EN] = GRF_REG(RK3562_GRF_VI_CON1, 1, 8), + [GRF_DPHY1_CLK_INV_SEL] = GRF_REG(RK3562_GRF_VI_CON1, 1, 9), + [GRF_DPHY1_CSI2PHY_CLKLANE1_EN] = GRF_REG(RK3562_GRF_VI_CON1, 1, 10), + [GRF_DPHY1_CLK1_INV_SEL] = GRF_REG(RK3562_GRF_VI_CON1, 1, 11), +}; + +static const struct csi2dphy_reg rk3562_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), +}; + /* 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}, @@ -525,15 +577,21 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN, GENMASK(sensor->lanes - 1, 0)); write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); - if (hw->drv_data->chip_id < CHIP_ID_RK3588) + if (hw->drv_data->chip_id != CHIP_ID_RK3588) write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); else write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); } else { - write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN, - GENMASK(sensor->lanes - 1, 0)); - write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); - if (hw->drv_data->chip_id < CHIP_ID_RK3588) + if (hw->drv_data->chip_id <= CHIP_ID_RK3588) { + write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN, + GENMASK(sensor->lanes - 1, 0)); + write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); + } else { + write_grf_reg(hw, GRF_DPHY1_CSI2PHY_DATALANE_EN, + GENMASK(sensor->lanes - 1, 0)); + write_grf_reg(hw, GRF_DPHY1_CSI2PHY_CLKLANE_EN, 0x1); + } + if (hw->drv_data->chip_id != CHIP_ID_RK3588) write_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); else write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); @@ -562,6 +620,8 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, write_grf_reg(hw, GRF_MIPI_HOST0_SEL, 0x1); else write_grf_reg(hw, GRF_LVDS_HOST0_SEL, 0x1); + } else if (hw->drv_data->chip_id == CHIP_ID_RK3562) { + write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); } break; case 2: @@ -579,21 +639,37 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, } else if (hw->drv_data->chip_id == CHIP_ID_RK3588) { write_sys_grf_reg(hw, GRF_DPHY_CSIHOST3_SEL, 0x1); write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); + } else if (hw->drv_data->chip_id == CHIP_ID_RK3562) { + write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); } break; case 4: - write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); - write_sys_grf_reg(hw, GRF_DPHY_CSIHOST4_SEL, 0x0); - write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN0, - GENMASK(sensor->lanes - 1, 0)); - write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); + if (hw->drv_data->chip_id == CHIP_ID_RK3588) { + write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); + write_sys_grf_reg(hw, GRF_DPHY_CSIHOST4_SEL, 0x0); + 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_RK3562) { + 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: - write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); - write_sys_grf_reg(hw, GRF_DPHY_CSIHOST5_SEL, 0x1); - write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN1, - GENMASK(sensor->lanes - 1, 0)); - write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE1_EN, 0x1); + if (hw->drv_data->chip_id == CHIP_ID_RK3588) { + write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); + write_sys_grf_reg(hw, GRF_DPHY_CSIHOST5_SEL, 0x1); + 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_RK3562) { + 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: break; @@ -822,6 +898,11 @@ static void rv1106_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw) hw->grf_regs = rv1106_grf_dphy_regs; } +static void rk3562_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw) +{ + hw->grf_regs = rk3562_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), @@ -855,6 +936,17 @@ static const struct dphy_hw_drv_data rv1106_csi2_dphy_hw_drv_data = { .stream_off = csi2_dphy_hw_stream_off, }; +static const struct dphy_hw_drv_data rk3562_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 = rk3562_csi2dphy_regs, + .grf_regs = rk3562_grf_dphy_regs, + .individual_init = rk3562_csi2_dphy_hw_individual_init, + .chip_id = CHIP_ID_RK3562, + .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", @@ -868,6 +960,10 @@ static const struct of_device_id rockchip_csi2_dphy_hw_match_id[] = { .compatible = "rockchip,rv1106-csi2-dphy-hw", .data = &rv1106_csi2_dphy_hw_drv_data, }, + { + .compatible = "rockchip,rk3562-csi2-dphy-hw", + .data = &rk3562_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 d6980d49787d..7e53e599314a 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c @@ -697,6 +697,11 @@ static struct dphy_drv_data rv1106_dphy_drv_data = { .vendor = PHY_VENDOR_INNO, }; +static struct dphy_drv_data rk3562_dphy_drv_data = { + .dev_name = "csi2dphy", + .vendor = PHY_VENDOR_INNO, +}; + static const struct of_device_id rockchip_csi2_dphy_match_id[] = { { .compatible = "rockchip,rk3568-csi2-dphy", @@ -710,6 +715,10 @@ static const struct of_device_id rockchip_csi2_dphy_match_id[] = { .compatible = "rockchip,rv1106-csi2-dphy", .data = &rv1106_dphy_drv_data, }, + { + .compatible = "rockchip,rk3562-csi2-dphy", + .data = &rk3562_dphy_drv_data, + }, {} }; MODULE_DEVICE_TABLE(of, rockchip_csi2_dphy_match_id);