From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:45:28 +0000 Subject: [PATCH] add boot partition size --- kernel/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c | 595 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 518 insertions(+), 77 deletions(-) diff --git a/kernel/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c b/kernel/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c index 0755823..e0a9fd6 100644 --- a/kernel/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c +++ b/kernel/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c @@ -21,11 +21,24 @@ #include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> #include <media/v4l2-device.h> +#include <linux/reset.h> #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) + +/*RK3588 DPHY GRF REG OFFSET */ +#define GRF_DPHY_CON0 (0x0) +#define GRF_SOC_CON2 (0x0308) + +/*RV1106 DPHY GRF REG OFFSET */ +#define GRF_VI_MISC_CON0 (0x50000) +#define GRF_VI_CSIPHY_CON5 (0x50014) /*GRF REG BIT DEFINE */ #define GRF_CSI2PHY_LANE_SEL_SPLIT (0x1) @@ -37,7 +50,10 @@ #define CSI2_DPHY_CTRL_PWRCTL \ CSI2_DPHY_CTRL_INVALID_OFFSET #define CSI2_DPHY_CTRL_LANE_ENABLE (0x00) +#define CSI2_DPHY_CLK1_LANE_EN (0x2C) #define CSI2_DPHY_DUAL_CAL_EN (0x80) +#define CSI2_DPHY_CLK_INV (0X84) + #define CSI2_DPHY_CLK_WR_THS_SETTLE (0x160) #define CSI2_DPHY_CLK_CALIB_EN (0x168) #define CSI2_DPHY_LANE0_WR_THS_SETTLE (0x1e0) @@ -50,6 +66,11 @@ #define CSI2_DPHY_LANE3_CALIB_EN (0x368) #define CSI2_DPHY_CLK1_WR_THS_SETTLE (0x3e0) #define CSI2_DPHY_CLK1_CALIB_EN (0x3e8) + +#define CSI2_DPHY_PATH0_MODE_SEL (0x44C) +#define CSI2_DPHY_PATH0_LVDS_MODE_SEL (0x480) +#define CSI2_DPHY_PATH1_MODE_SEL (0x84C) +#define CSI2_DPHY_PATH1_LVDS_MODE_SEL (0x880) /* PHY REG BIT DEFINE */ #define CSI2_DPHY_LANE_MODE_FULL (0x4) @@ -128,8 +149,26 @@ GRF_DPHY_ISP_CSI2PHY_SEL, GRF_DPHY_CIF_CSI2PHY_SEL, GRF_DPHY_CSI2PHY_LANE_SEL, + GRF_DPHY_CSI2PHY1_LANE_SEL, GRF_DPHY_CSI2PHY_DATALANE_EN0, GRF_DPHY_CSI2PHY_DATALANE_EN1, + GRF_CPHY_MODE, + GRF_DPHY_CSIHOST2_SEL, + GRF_DPHY_CSIHOST3_SEL, + GRF_DPHY_CSIHOST4_SEL, + GRF_DPHY_CSIHOST5_SEL, + /* 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 { @@ -152,7 +191,28 @@ //rk3568 only CSI2PHY_DUAL_CLK_EN, CSI2PHY_CLK1_THS_SETTLE, - CSI2PHY_CLK1_CALIB_ENABLE + CSI2PHY_CLK1_CALIB_ENABLE, + //rk3588 + CSI2PHY_CLK_LANE_ENABLE, + CSI2PHY_CLK1_LANE_ENABLE, + CSI2PHY_DATA_LANE0_ENABLE, + CSI2PHY_DATA_LANE1_ENABLE, + CSI2PHY_DATA_LANE2_ENABLE, + CSI2PHY_DATA_LANE3_ENABLE, + CSI2PHY_LANE0_ERR_SOT_SYNC, + CSI2PHY_LANE1_ERR_SOT_SYNC, + CSI2PHY_LANE2_ERR_SOT_SYNC, + CSI2PHY_LANE3_ERR_SOT_SYNC, + CSI2PHY_S0C_GNR_CON1, + CSI2PHY_COMBO_S0D0_GNR_CON1, + CSI2PHY_COMBO_S0D1_GNR_CON1, + CSI2PHY_COMBO_S0D2_GNR_CON1, + CSI2PHY_S0D3_GNR_CON1, + CSI2PHY_PATH0_MODEL, + CSI2PHY_PATH0_LVDS_MODEL, + CSI2PHY_PATH1_MODEL, + CSI2PHY_PATH1_LVDS_MODEL, + CSI2PHY_CLK_INV, }; #define HIWORD_UPDATE(val, mask, shift) \ @@ -166,8 +226,18 @@ struct hsfreq_range { u32 range_h; - u8 cfg_bit; + u16 cfg_bit; }; + +static inline void write_sys_grf_reg(struct csi2_dphy_hw *hw, + int index, u8 value) +{ + const struct grf_reg *reg = &hw->grf_regs[index]; + unsigned int val = HIWORD_UPDATE(value, reg->mask, reg->shift); + + if (reg->mask) + regmap_write(hw->regmap_sys_grf, reg->offset, val); +} static inline void write_grf_reg(struct csi2_dphy_hw *hw, int index, u8 value) @@ -175,7 +245,7 @@ const struct grf_reg *reg = &hw->grf_regs[index]; unsigned int val = HIWORD_UPDATE(value, reg->mask, reg->shift); - if (reg->offset) + if (reg->mask) regmap_write(hw->regmap_grf, reg->offset, val); } @@ -184,7 +254,7 @@ const struct grf_reg *reg = &hw->grf_regs[index]; unsigned int val = 0; - if (reg->offset) { + if (reg->mask) { regmap_read(hw->regmap_grf, reg->offset, &val); val = (val >> reg->shift) & reg->mask; } @@ -198,9 +268,22 @@ const struct csi2dphy_reg *reg = &hw->csi2dphy_regs[index]; if ((index == CSI2PHY_REG_CTRL_LANE_ENABLE) || + (index == CSI2PHY_CLK_LANE_ENABLE) || (index != CSI2PHY_REG_CTRL_LANE_ENABLE && reg->offset != 0x0)) writel(value, hw->hw_base_addr + reg->offset); +} + +static inline void write_csi2_dphy_reg_mask(struct csi2_dphy_hw *hw, + int index, u32 value, u32 mask) +{ + const struct csi2dphy_reg *reg = &hw->csi2dphy_regs[index]; + u32 read_val = 0; + + read_val = readl(hw->hw_base_addr + reg->offset); + read_val &= ~mask; + read_val |= value; + writel(read_val, hw->hw_base_addr + reg->offset); } static inline void read_csi2_dphy_reg(struct csi2_dphy_hw *hw, @@ -209,6 +292,7 @@ const struct csi2dphy_reg *reg = &hw->csi2dphy_regs[index]; if ((index == CSI2PHY_REG_CTRL_LANE_ENABLE) || + (index == CSI2PHY_CLK_LANE_ENABLE) || (index != CSI2PHY_REG_CTRL_LANE_ENABLE && reg->offset != 0x0)) *value = readl(hw->hw_base_addr + reg->offset); @@ -280,8 +364,114 @@ [CSI2PHY_CLK1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_CALIB_EN), }; -static const struct clk_bulk_data rk3568_csi2_dphy_hw_clks[] = { - { .id = "pclk" }, +static const struct grf_reg rk3588_grf_dphy_regs[] = { + [GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(GRF_DPHY_CON0, 4, 0), + [GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(GRF_DPHY_CON0, 4, 4), + [GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(GRF_DPHY_CON0, 2, 4), + [GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(GRF_DPHY_CON0, 2, 6), + [GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(GRF_DPHY_CON0, 1, 8), + [GRF_DPHY_CLK_INV_SEL] = GRF_REG(GRF_DPHY_CON0, 1, 9), + [GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(GRF_DPHY_CON0, 1, 10), + [GRF_DPHY_CLK1_INV_SEL] = GRF_REG(GRF_DPHY_CON0, 1, 11), + [GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(GRF_SOC_CON2, 1, 6), + [GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(GRF_SOC_CON2, 1, 7), + [GRF_DPHY_CSIHOST2_SEL] = GRF_REG(GRF_SOC_CON2, 1, 8), + [GRF_DPHY_CSIHOST3_SEL] = GRF_REG(GRF_SOC_CON2, 1, 9), + [GRF_DPHY_CSIHOST4_SEL] = GRF_REG(GRF_SOC_CON2, 1, 10), + [GRF_DPHY_CSIHOST5_SEL] = GRF_REG(GRF_SOC_CON2, 1, 11), +}; + +static const struct csi2dphy_reg rk3588_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), +}; + +static const struct grf_reg rv1106_grf_dphy_regs[] = { + [GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(GRF_VI_CSIPHY_CON5, 4, 0), + [GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(GRF_VI_CSIPHY_CON5, 1, 8), + [GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(GRF_VI_CSIPHY_CON5, 4, 4), + [GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(GRF_VI_CSIPHY_CON5, 2, 4), + [GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(GRF_VI_CSIPHY_CON5, 2, 6), + [GRF_DPHY_CLK_INV_SEL] = GRF_REG(GRF_VI_CSIPHY_CON5, 1, 9), + [GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(GRF_VI_CSIPHY_CON5, 1, 10), + [GRF_DPHY_CLK1_INV_SEL] = GRF_REG(GRF_VI_CSIPHY_CON5, 1, 11), + [GRF_MIPI_HOST0_SEL] = GRF_REG(GRF_VI_MISC_CON0, 1, 0), + [GRF_LVDS_HOST0_SEL] = GRF_REG(GRF_VI_MISC_CON0, 1, 2), +}; + +static const struct csi2dphy_reg rv1106_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(CSI2_DPHY_PATH0_MODE_SEL), + [CSI2PHY_PATH0_LVDS_MODEL] = CSI2PHY_REG(CSI2_DPHY_PATH0_LVDS_MODE_SEL), + [CSI2PHY_PATH1_MODEL] = CSI2PHY_REG(CSI2_DPHY_PATH1_MODE_SEL), + [CSI2PHY_PATH1_LVDS_MODEL] = CSI2PHY_REG(CSI2_DPHY_PATH1_LVDS_MODE_SEL), + [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. */ @@ -321,6 +511,51 @@ return NULL; } +static unsigned char get_lvds_data_width(u32 pixelformat) +{ + switch (pixelformat) { + /* csi raw8 */ + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SGBRG8_1X8: + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: + return 0x2; + /* csi raw10 */ + case MEDIA_BUS_FMT_SBGGR10_1X10: + case MEDIA_BUS_FMT_SGBRG10_1X10: + case MEDIA_BUS_FMT_SGRBG10_1X10: + case MEDIA_BUS_FMT_SRGGB10_1X10: + return 0x0; + /* csi raw12 */ + case MEDIA_BUS_FMT_SBGGR12_1X12: + case MEDIA_BUS_FMT_SGBRG12_1X12: + case MEDIA_BUS_FMT_SGRBG12_1X12: + case MEDIA_BUS_FMT_SRGGB12_1X12: + return 0x1; + /* csi uyvy 422 */ + case MEDIA_BUS_FMT_UYVY8_2X8: + case MEDIA_BUS_FMT_VYUY8_2X8: + case MEDIA_BUS_FMT_YUYV8_2X8: + case MEDIA_BUS_FMT_YVYU8_2X8: + case MEDIA_BUS_FMT_RGB888_1X24: + return 0x2; + + default: + return 0x2; + } +} + +static void csi2_dphy_hw_do_reset(struct csi2_dphy_hw *hw) +{ + if (hw->rsts_bulk) + reset_control_assert(hw->rsts_bulk); + + udelay(5); + + if (hw->rsts_bulk) + reset_control_deassert(hw->rsts_bulk); +} + static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, struct csi2_sensor *sensor) { @@ -337,38 +572,108 @@ is_cif = false; if (hw->lane_mode == LANE_MODE_FULL) { - val = ~GRF_CSI2PHY_LANE_SEL_SPLIT; - write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); - write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN, - GENMASK(sensor->lanes - 1, 0)); - write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); + val = !GRF_CSI2PHY_LANE_SEL_SPLIT; + if (dphy->phy_index < 3) { + 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) + write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); + else + write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); + } else { + 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); + } } else { val = GRF_CSI2PHY_LANE_SEL_SPLIT; - write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); - if (dphy->phy_index == DPHY1) { + switch (dphy->phy_index) { + case 1: 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 (is_cif) - write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, - GRF_CSI2PHY_SEL_SPLIT_0_1); - else - write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, - GRF_CSI2PHY_SEL_SPLIT_0_1); - } - - if (dphy->phy_index == DPHY2) { + if (hw->drv_data->chip_id < CHIP_ID_RK3588) { + write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); + if (is_cif) + write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, + GRF_CSI2PHY_SEL_SPLIT_0_1); + else + write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, + GRF_CSI2PHY_SEL_SPLIT_0_1); + } else if (hw->drv_data->chip_id == CHIP_ID_RK3588) { + write_sys_grf_reg(hw, GRF_DPHY_CSIHOST2_SEL, 0x0); + write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); + } else if (hw->drv_data->chip_id == CHIP_ID_RV1106) { + if (sensor->mbus.type == V4L2_MBUS_CSI2_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: 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 (is_cif) - write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, - GRF_CSI2PHY_SEL_SPLIT_2_3); - else - write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, - GRF_CSI2PHY_SEL_SPLIT_2_3); - } + if (hw->drv_data->chip_id < CHIP_ID_RK3588) { + write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); + if (is_cif) + write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, + GRF_CSI2PHY_SEL_SPLIT_2_3); + else + write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, + GRF_CSI2PHY_SEL_SPLIT_2_3); + } 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: + 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: + 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; + }; } } @@ -376,13 +681,20 @@ struct v4l2_subdev *sd) { struct v4l2_subdev *sensor_sd = get_remote_sensor(sd); - struct csi2_sensor *sensor = sd_to_sensor(dphy, sensor_sd); + struct csi2_sensor *sensor; struct csi2_dphy_hw *hw = dphy->dphy_hw; const struct dphy_hw_drv_data *drv_data = hw->drv_data; const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges; int num_hsfreq_ranges = drv_data->num_hsfreq_ranges; int i, hsfreq = 0; u32 val = 0, pre_val; + u8 lvds_width = 0; + + if (!sensor_sd) + return -ENODEV; + sensor = sd_to_sensor(dphy, sensor_sd); + if (!sensor) + return -ENODEV; mutex_lock(&hw->mutex); @@ -401,31 +713,32 @@ if (!(pre_val & (0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT))) val |= (0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT); - if (dphy->phy_index == DPHY1) + if (dphy->phy_index % 3 == DPHY1) val |= (GENMASK(sensor->lanes - 1, 0) << CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT); - if (dphy->phy_index == DPHY2) + if (dphy->phy_index % 3 == DPHY2) { val |= (GENMASK(sensor->lanes - 1, 0) << CSI2_DPHY_CTRL_DATALANE_SPLIT_LANE2_3_OFFSET_BIT); + if (hw->drv_data->chip_id >= CHIP_ID_RK3588) + write_csi2_dphy_reg(hw, CSI2PHY_CLK1_LANE_ENABLE, BIT(6)); + } } val |= pre_val; write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, val); - if (sensor->mbus.type == V4L2_MBUS_CSI2) { - /* Reset dphy digital part */ - if (hw->lane_mode == LANE_MODE_FULL) { - write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x1e); - write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x1f); - } else { - read_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, &val); - if (!(val & CSI2_DPHY_LANE_DUAL_MODE_EN)) { - write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x5e); - write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x5f); - } + /* Reset dphy digital part */ + if (hw->lane_mode == LANE_MODE_FULL) { + write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x1e); + write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x1f); + } else { + read_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, &val); + if (!(val & CSI2_DPHY_LANE_DUAL_MODE_EN)) { + write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x5e); + write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x5f); } - csi2_dphy_config_dual_mode(dphy, sensor); } + csi2_dphy_config_dual_mode(dphy, sensor); /* not into receive mode/wait stopstate */ write_grf_reg(hw, GRF_DPHY_CSI2PHY_FORCERXMODE, 0x0); @@ -443,7 +756,7 @@ if (sensor->lanes > 0x03) write_csi2_dphy_reg(hw, CSI2PHY_LANE3_CALIB_ENABLE, 0x80); } else { - if (dphy->phy_index == DPHY1) { + if (dphy->phy_index % 3 == DPHY1) { write_csi2_dphy_reg(hw, CSI2PHY_CLK_CALIB_ENABLE, 0x80); if (sensor->lanes > 0x00) write_csi2_dphy_reg(hw, CSI2PHY_LANE0_CALIB_ENABLE, 0x80); @@ -451,7 +764,7 @@ write_csi2_dphy_reg(hw, CSI2PHY_LANE1_CALIB_ENABLE, 0x80); } - if (dphy->phy_index == DPHY2) { + if (dphy->phy_index % 3 == DPHY2) { write_csi2_dphy_reg(hw, CSI2PHY_CLK1_CALIB_ENABLE, 0x80); if (sensor->lanes > 0x00) write_csi2_dphy_reg(hw, CSI2PHY_LANE2_CALIB_ENABLE, 0x80); @@ -487,16 +800,43 @@ if (sensor->lanes > 0x03) csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA3); } else { - if (dphy->phy_index == DPHY1) { + if (dphy->phy_index % 3 == DPHY1) { csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_CLOCK); csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA0); csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA1); } - if (dphy->phy_index == DPHY2) { + if (dphy->phy_index % 3 == DPHY2) { csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_CLOCK1); csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA2); csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA3); + } + } + + if (hw->drv_data->chip_id == CHIP_ID_RV1106) { + if (dphy->phy_index % 3 == DPHY0 || + dphy->phy_index % 3 == DPHY1) { + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { + write_csi2_dphy_reg(hw, CSI2PHY_PATH0_MODEL, 0x2); + } else { + write_csi2_dphy_reg(hw, CSI2PHY_PATH0_MODEL, 0x4); + lvds_width = get_lvds_data_width(sensor->format.code); + write_csi2_dphy_reg(hw, CSI2PHY_PATH0_LVDS_MODEL, (lvds_width << 4) | 0X0f); + } + } else { + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { + write_csi2_dphy_reg(hw, CSI2PHY_PATH1_MODEL, 0x2); + } else { + write_csi2_dphy_reg(hw, CSI2PHY_PATH1_MODEL, 0x4); + lvds_width = get_lvds_data_width(sensor->format.code); + write_csi2_dphy_reg(hw, CSI2PHY_PATH1_LVDS_MODEL, (lvds_width << 4) | 0X0f); + } + } + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { + if (hw->lane_mode == LANE_MODE_FULL) + write_csi2_dphy_reg(hw, CSI2PHY_CLK_INV, 0x04); + else + write_csi2_dphy_reg(hw, CSI2PHY_CLK_INV, 0x14); } } @@ -518,6 +858,7 @@ mutex_lock(&hw->mutex); write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, 0x01); + csi2_dphy_hw_do_reset(hw); usleep_range(500, 1000); mutex_unlock(&hw->mutex); @@ -525,26 +866,109 @@ return 0; } +static int csi2_dphy_hw_ttl_mode_enable(struct csi2_dphy_hw *hw) +{ + int ret = 0; + + ret = clk_bulk_prepare_enable(hw->num_clks, hw->clks_bulk); + if (ret) { + dev_err(hw->dev, "failed to enable clks\n"); + return ret; + } + + write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, 0x7d); + write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x5f); + write_csi2_dphy_reg(hw, CSI2PHY_PATH0_MODEL, 0x1); + write_csi2_dphy_reg(hw, CSI2PHY_PATH1_MODEL, 0x1); + return ret; +} + +static void csi2_dphy_hw_ttl_mode_disable(struct csi2_dphy_hw *hw) +{ + write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, 0x01); + clk_bulk_disable_unprepare(hw->num_clks, hw->clks_bulk); +} + static void rk3568_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw) { hw->grf_regs = rk3568_grf_dphy_regs; } +static void rk3588_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw) +{ + hw->grf_regs = rk3588_grf_dphy_regs; +} + +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 = { - .clks = rk3568_csi2_dphy_hw_clks, - .num_clks = ARRAY_SIZE(rk3568_csi2_dphy_hw_clks), .hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges, .num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges), .csi2dphy_regs = rk3568_csi2dphy_regs, .grf_regs = rk3568_grf_dphy_regs, .individual_init = rk3568_csi2_dphy_hw_individual_init, .chip_id = CHIP_ID_RK3568, + .stream_on = csi2_dphy_hw_stream_on, + .stream_off = csi2_dphy_hw_stream_off, +}; + +static const struct dphy_hw_drv_data rk3588_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 = rk3588_csi2dphy_regs, + .grf_regs = rk3588_grf_dphy_regs, + .individual_init = rk3588_csi2_dphy_hw_individual_init, + .chip_id = CHIP_ID_RK3588, + .stream_on = csi2_dphy_hw_stream_on, + .stream_off = csi2_dphy_hw_stream_off, +}; + +static const struct dphy_hw_drv_data rv1106_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 = rv1106_csi2dphy_regs, + .grf_regs = rv1106_grf_dphy_regs, + .individual_init = rv1106_csi2_dphy_hw_individual_init, + .chip_id = CHIP_ID_RV1106, + .stream_on = csi2_dphy_hw_stream_on, + .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", .data = &rk3568_csi2_dphy_hw_drv_data, + }, + { + .compatible = "rockchip,rk3588-csi2-dphy-hw", + .data = &rk3588_csi2_dphy_hw_drv_data, + }, + { + .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, }, {} }; @@ -558,7 +982,6 @@ struct resource *res; const struct of_device_id *of_id; const struct dphy_hw_drv_data *drv_data; - int ret; dphy_hw = devm_kzalloc(dev, sizeof(*dphy_hw), GFP_KERNEL); if (!dphy_hw) @@ -569,33 +992,33 @@ if (!of_id) return -EINVAL; - grf = syscon_node_to_regmap(dev->parent->of_node); + drv_data = of_id->data; + + grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,grf"); if (IS_ERR(grf)) { - grf = syscon_regmap_lookup_by_phandle(dev->of_node, - "rockchip,grf"); - if (IS_ERR(grf)) { - dev_err(dev, "Can't find GRF syscon\n"); - return -ENODEV; - } + dev_err(dev, "Can't find GRF syscon\n"); + return -ENODEV; } dphy_hw->regmap_grf = grf; - drv_data = of_id->data; - dphy_hw->num_clks = drv_data->num_clks; - dphy_hw->clks = devm_kmemdup(dev, drv_data->clks, - drv_data->num_clks * sizeof(struct clk_bulk_data), - GFP_KERNEL); - if (!dphy_hw->clks) { - dev_err(dev, "failed to acquire csi2 dphy clks mem\n"); - return -ENOMEM; + if (drv_data->chip_id == CHIP_ID_RK3588) { + grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,sys_grf"); + if (IS_ERR(grf)) { + dev_err(dev, "Can't find SYS GRF syscon\n"); + return -ENODEV; + } + dphy_hw->regmap_sys_grf = grf; } - ret = devm_clk_bulk_get(dev, dphy_hw->num_clks, dphy_hw->clks); - if (ret == -EPROBE_DEFER) { - dev_err(dev, "get csi2 dphy clks failed\n"); - return -EPROBE_DEFER; - } - if (ret) - dphy_hw->num_clks = 0; + + dphy_hw->num_clks = devm_clk_bulk_get_all(dev, &dphy_hw->clks_bulk); + if (dphy_hw->num_clks < 0) + dev_err(dev, "failed to get csi2 clks\n"); + + dphy_hw->rsts_bulk = devm_reset_control_array_get_optional_exclusive(dev); + if (IS_ERR(dphy_hw->rsts_bulk)) + dev_err_probe(dev, PTR_ERR(dphy_hw->rsts_bulk), "failed to get dphy reset\n"); dphy_hw->dphy_dev_num = 0; dphy_hw->drv_data = drv_data; @@ -616,8 +1039,16 @@ return -ENODEV; } } - dphy_hw->stream_on = csi2_dphy_hw_stream_on; - dphy_hw->stream_off = csi2_dphy_hw_stream_off; + dphy_hw->stream_on = drv_data->stream_on; + dphy_hw->stream_off = drv_data->stream_off; + + if (drv_data->chip_id == CHIP_ID_RV1106) { + dphy_hw->ttl_mode_enable = csi2_dphy_hw_ttl_mode_enable; + dphy_hw->ttl_mode_disable = csi2_dphy_hw_ttl_mode_disable; + } else { + dphy_hw->ttl_mode_enable = NULL; + dphy_hw->ttl_mode_disable = NULL; + } atomic_set(&dphy_hw->stream_cnt, 0); @@ -626,8 +1057,6 @@ platform_set_drvdata(pdev, dphy_hw); pm_runtime_enable(&pdev->dev); - - platform_driver_register(&rockchip_csi2_dphy_driver); dev_info(dev, "csi2 dphy hw probe successfully!\n"); @@ -652,7 +1081,19 @@ .of_match_table = rockchip_csi2_dphy_hw_match_id, }, }; + +int rockchip_csi2_dphy_hw_init(void) +{ + return platform_driver_register(&rockchip_csi2_dphy_hw_driver); +} + +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +subsys_initcall(rockchip_csi2_dphy_hw_init); +#else +#if !defined(CONFIG_VIDEO_REVERSE_IMAGE) module_platform_driver(rockchip_csi2_dphy_hw_driver); +#endif +#endif MODULE_AUTHOR("Rockchip Camera/ISP team"); MODULE_DESCRIPTION("Rockchip MIPI CSI2 DPHY HW driver"); -- Gitblit v1.6.2