diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h index c7c886589338..bd1195e9eb3a 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h @@ -8,9 +8,14 @@ #ifndef _PHY_ROCKCHIP_CSI2_DPHY_COMMON_H_ #define _PHY_ROCKCHIP_CSI2_DPHY_COMMON_H_ +#define PHY_MAX 16 +#define MAX_DEV_NAME_LEN 32 + /* add new chip id in tail by time order */ enum csi2_dphy_chip_id { CHIP_ID_RK3568 = 0x0, + CHIP_ID_RK3588 = 0x1, + CHIP_ID_RK3588_DCPHY = 0x2, }; enum csi2_dphy_rx_pads { @@ -47,6 +52,10 @@ struct csi2_sensor { struct csi2_dphy_hw; +struct dphy_drv_data { + const char dev_name[MAX_DEV_NAME_LEN]; +}; + struct csi2_dphy { struct device *dev; struct list_head list; @@ -61,17 +70,20 @@ struct csi2_dphy { int phy_index; bool is_streaming; enum csi2_dphy_lane_mode lane_mode; + const struct dphy_drv_data *drv_data; }; struct dphy_hw_drv_data { - const struct clk_bulk_data *clks; - int num_clks; const struct hsfreq_range *hsfreq_ranges; int num_hsfreq_ranges; + const struct hsfreq_range *hsfreq_ranges_cphy; + int num_hsfreq_ranges_cphy; const struct grf_reg *grf_regs; const struct txrx_reg *txrx_regs; const struct csi2dphy_reg *csi2dphy_regs; void (*individual_init)(struct csi2_dphy_hw *hw); + int (*stream_on)(struct csi2_dphy *dphy, struct v4l2_subdev *sd); + int (*stream_off)(struct csi2_dphy *dphy, struct v4l2_subdev *sd); enum csi2_dphy_chip_id chip_id; }; @@ -83,7 +95,8 @@ struct csi2_dphy_hw { const struct csi2dphy_reg *csi2dphy_regs; const struct dphy_hw_drv_data *drv_data; void __iomem *hw_base_addr; - struct clk_bulk_data *clks; + struct clk_bulk_data *clks_bulk; + struct reset_control *rsts_bulk; struct csi2_dphy *dphy_dev[MAX_NUM_CSI2_DPHY]; struct v4l2_subdev sd; struct mutex mutex; /* lock for updating protection */ diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c index cb8482c67d49..8e252babf0ca 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "phy-rockchip-csi2-dphy-common.h" /* GRF REG OFFSET */ @@ -32,6 +33,8 @@ #define GRF_CSI2PHY_SEL_SPLIT_0_1 (0x0) #define GRF_CSI2PHY_SEL_SPLIT_2_3 BIT(0) +#define GRF_DCPHY_CON0 (0x0) + /* PHY REG OFFSET */ #define CSI2_DPHY_CTRL_INVALID_OFFSET (0xffff) #define CSI2_DPHY_CTRL_PWRCTL \ @@ -51,6 +54,21 @@ #define CSI2_DPHY_CLK1_WR_THS_SETTLE (0x3e0) #define CSI2_DPHY_CLK1_CALIB_EN (0x3e8) +#define CSI2_DCPHY_CLK_WR_THS_SETTLE (0xB20) +#define CSI2_DCPHY_LANE0_WR_THS_SETTLE (0xC30) +#define CSI2_DCPHY_LANE0_WR_ERR_SOT_SYNC (0xC34) +#define CSI2_DCPHY_LANE1_WR_THS_SETTLE (0xD30) +#define CSI2_DCPHY_LANE1_WR_ERR_SOT_SYNC (0xD34) +#define CSI2_DCPHY_LANE2_WR_THS_SETTLE (0xE30) +#define CSI2_DCPHY_LANE2_WR_ERR_SOT_SYNC (0xE34) +#define CSI2_DCPHY_LANE3_WR_THS_SETTLE (0xF30) +#define CSI2_DCPHY_LANE3_WR_ERR_SOT_SYNC (0xF34) +#define CSI2_DCPHY_CLK_LANE_ENABLE (0xB00) +#define CSI2_DCPHY_DATA_LANE0_ENABLE (0xC00) +#define CSI2_DCPHY_DATA_LANE1_ENABLE (0xD00) +#define CSI2_DCPHY_DATA_LANE2_ENABLE (0xE00) +#define CSI2_DCPHY_DATA_LANE3_ENABLE (0xF00) + /* PHY REG BIT DEFINE */ #define CSI2_DPHY_LANE_MODE_FULL (0x4) #define CSI2_DPHY_LANE_MODE_SPLIT (0x2) @@ -130,6 +148,7 @@ enum grf_reg_id { GRF_DPHY_CSI2PHY_LANE_SEL, GRF_DPHY_CSI2PHY_DATALANE_EN0, GRF_DPHY_CSI2PHY_DATALANE_EN1, + GRF_CPHY_MODE, }; enum csi2dphy_reg_id { @@ -152,7 +171,17 @@ enum csi2dphy_reg_id { //rk3568 only CSI2PHY_DUAL_CLK_EN, CSI2PHY_CLK1_THS_SETTLE, - CSI2PHY_CLK1_CALIB_ENABLE + CSI2PHY_CLK1_CALIB_ENABLE, + //rk3588 + CSI2PHY_CLK_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, }; #define HIWORD_UPDATE(val, mask, shift) \ @@ -166,7 +195,7 @@ enum csi2dphy_reg_id { struct hsfreq_range { u32 range_h; - u8 cfg_bit; + u16 cfg_bit; }; static inline void write_grf_reg(struct csi2_dphy_hw *hw, @@ -203,6 +232,18 @@ static inline void write_csi2_dphy_reg(struct csi2_dphy_hw *hw, 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, int index, u32 *value) { @@ -280,8 +321,25 @@ static const struct csi2dphy_reg rk3568_csi2dphy_regs[] = { [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_dcphy_regs[] = { + [GRF_CPHY_MODE] = GRF_REG(GRF_DCPHY_CON0, 9, 0), +}; + +static const struct csi2dphy_reg rk3588_csi2dcphy_regs[] = { + [CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_CLK_WR_THS_SETTLE), + [CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE0_WR_THS_SETTLE), + [CSI2PHY_LANE0_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE0_WR_ERR_SOT_SYNC), + [CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE1_WR_THS_SETTLE), + [CSI2PHY_LANE1_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE1_WR_ERR_SOT_SYNC), + [CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE2_WR_THS_SETTLE), + [CSI2PHY_LANE2_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE2_WR_ERR_SOT_SYNC), + [CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE3_WR_THS_SETTLE), + [CSI2PHY_LANE3_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE3_WR_ERR_SOT_SYNC), + [CSI2PHY_CLK_LANE_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_CLK_LANE_ENABLE), + [CSI2PHY_DATA_LANE0_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE0_ENABLE), + [CSI2PHY_DATA_LANE1_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE1_ENABLE), + [CSI2PHY_DATA_LANE2_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE2_ENABLE), + [CSI2PHY_DATA_LANE3_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE3_ENABLE), }; /* These tables must be sorted by .range_h ascending. */ @@ -293,6 +351,37 @@ static const struct hsfreq_range rk3568_csi2_dphy_hw_hsfreq_ranges[] = { {2199, 0x3c}, {2399, 0x41}, {2499, 0x46} }; +/* These tables must be sorted by .range_h ascending. */ +static const struct hsfreq_range rk3588_csi2_dcphy_d_hw_hsfreq_ranges[] = { + { 80, 0x105}, { 100, 0x106}, { 120, 0x107}, { 140, 0x108}, + { 160, 0x109}, { 180, 0x10a}, { 200, 0x10b}, { 220, 0x10c}, + { 240, 0x10d}, { 270, 0x10e}, { 290, 0x10f}, { 310, 0x110}, + { 330, 0x111}, { 350, 0x112}, { 370, 0x113}, { 390, 0x114}, + { 410, 0x115}, { 430, 0x116}, { 450, 0x117}, { 470, 0x118}, + { 490, 0x119}, { 510, 0x11a}, { 540, 0x11b}, { 560, 0x11c}, + { 580, 0x11d}, { 600, 0x11e}, { 620, 0x11f}, { 640, 0x120}, + { 660, 0x121}, { 680, 0x122}, { 700, 0x123}, { 720, 0x124}, + { 740, 0x125}, { 760, 0x126}, { 790, 0x127}, { 810, 0x128}, + { 830, 0x129}, { 850, 0x12a}, { 870, 0x12b}, { 890, 0x12c}, + { 910, 0x12d}, { 930, 0x12e}, { 950, 0x12f}, { 970, 0x130}, + { 990, 0x131}, {1010, 0x132}, {1030, 0x133}, {1060, 0x134}, + {1080, 0x135}, {1100, 0x136}, {1120, 0x137}, {1140, 0x138}, + {1160, 0x139}, {1180, 0x13a}, {1200, 0x13b}, {1220, 0x13c}, + {1240, 0x13d}, {1260, 0x13e}, {1280, 0x13f}, {1310, 0x140}, + {1330, 0x141}, {1350, 0x142}, {1370, 0x143}, {1390, 0x144}, + {1410, 0x145}, {1430, 0x146}, {1450, 0x147}, {1470, 0x148}, + {1490, 0x149}, {1580, 0x007}, {1740, 0x008}, {1910, 0x009}, + {2070, 0x00a}, {2240, 0x00b}, {2410, 0x00c}, {2570, 0x00d}, + {2740, 0x00e}, {2910, 0x00f}, {3070, 0x010}, {3240, 0x011}, + {3410, 0x012}, {3570, 0x013}, {3740, 0x014}, {3890, 0x015}, + {4070, 0x016}, {4240, 0x017}, {4400, 0x018}, {4500, 0x019}, +}; + +/* These tables must be sorted by .range_h ascending. */ +static const struct hsfreq_range rk3588_csi2_dcphy_c_hw_hsfreq_ranges[] = { + { 500, 0x102}, { 990, 0x002}, { 2500, 0x001}, +}; + static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd) { struct media_pad *local, *remote; @@ -525,20 +614,193 @@ static int csi2_dphy_hw_stream_off(struct csi2_dphy *dphy, return 0; } +static int csi_dcphy_wait_lane_prepare(struct csi2_dphy_hw *hw, int index) +{ + int count = 0; + u32 val = 0; + + read_csi2_dphy_reg(hw, index, &val); + while (!(val & BIT(1))) { + usleep_range(10, 20); + read_csi2_dphy_reg(hw, index, &val); + count++; + if (count > 2000) + return -EINVAL; + } + return 0; +} + +static int csi2_dcphy_hw_stream_on(struct csi2_dphy *dphy, + 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_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 sot_sync = 0; + + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { + hsfreq_ranges = drv_data->hsfreq_ranges; + num_hsfreq_ranges = drv_data->num_hsfreq_ranges; + sot_sync = 0x03; + } else if (sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) { + hsfreq_ranges = drv_data->hsfreq_ranges_cphy; + num_hsfreq_ranges = drv_data->num_hsfreq_ranges_cphy; + sot_sync = 0x32; + } + + mutex_lock(&hw->mutex); + if (sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) + write_grf_reg(hw, GRF_CPHY_MODE, 0x9); + + if (hw->rsts_bulk) + reset_control_assert(hw->rsts_bulk); + + /*clk settle fix to 0x301*/ + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) + write_csi2_dphy_reg(hw, CSI2PHY_CLK_THS_SETTLE, 0x301); + /* set data lane */ + for (i = 0; i < num_hsfreq_ranges; i++) { + if (hsfreq_ranges[i].range_h >= dphy->data_rate_mbps) { + hsfreq = hsfreq_ranges[i].cfg_bit; + break; + } + } + + if (i == num_hsfreq_ranges) { + i = num_hsfreq_ranges - 1; + dev_warn(dphy->dev, "data rate: %lld mbps, max support %d mbps", + dphy->data_rate_mbps, hsfreq_ranges[i].range_h + 1); + hsfreq = hsfreq_ranges[i].cfg_bit; + } + if (sensor->lanes > 0x00) { + write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE0_THS_SETTLE, hsfreq, 0x1ff); + write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE0_ERR_SOT_SYNC, sot_sync, 0xff); + } + if (sensor->lanes > 0x01) { + write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE1_THS_SETTLE, hsfreq, 0x1ff); + write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE1_ERR_SOT_SYNC, sot_sync, 0xff); + } + if (sensor->lanes > 0x02) { + write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE2_THS_SETTLE, hsfreq, 0x1ff); + write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE2_ERR_SOT_SYNC, sot_sync, 0xff); + } + if (sensor->lanes > 0x03) { + write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE3_THS_SETTLE, hsfreq, 0x1ff); + write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE3_ERR_SOT_SYNC, sot_sync, 0xff); + } + + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) + write_csi2_dphy_reg(hw, CSI2PHY_CLK_LANE_ENABLE, BIT(0)); + + if (sensor->lanes > 0x00) + write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE0_ENABLE, BIT(0)); + if (sensor->lanes > 0x01) + write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE1_ENABLE, BIT(0)); + if (sensor->lanes > 0x02) + write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE2_ENABLE, BIT(0)); + if (sensor->lanes > 0x03) + write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE3_ENABLE, BIT(0)); + + /*wait for clk lane ready*/ + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) + if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_CLK_LANE_ENABLE)) + goto out_streamon; + + /*wait for data lane ready*/ + if (sensor->lanes > 0x00) + if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_DATA_LANE0_ENABLE)) + goto out_streamon; + if (sensor->lanes > 0x01) + if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_DATA_LANE1_ENABLE)) + goto out_streamon; + if (sensor->lanes > 0x02) + if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_DATA_LANE2_ENABLE)) + goto out_streamon; + if (sensor->lanes > 0x03) + if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_DATA_LANE3_ENABLE)) + goto out_streamon; + + if (hw->rsts_bulk) + reset_control_deassert(hw->rsts_bulk); + atomic_inc(&hw->stream_cnt); + + mutex_unlock(&hw->mutex); + + return 0; +out_streamon: + if (hw->rsts_bulk) + reset_control_deassert(hw->rsts_bulk); + mutex_unlock(&hw->mutex); + dev_err(dphy->dev, "stream on error\n"); + return -EINVAL; + +} + +static int csi2_dcphy_hw_stream_off(struct csi2_dphy *dphy, + struct v4l2_subdev *sd) +{ + struct csi2_dphy_hw *hw = dphy->dphy_hw; + struct v4l2_subdev *sensor_sd = get_remote_sensor(sd); + struct csi2_sensor *sensor = sd_to_sensor(dphy, sensor_sd); + + if (atomic_dec_return(&hw->stream_cnt)) + return 0; + + mutex_lock(&hw->mutex); + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) + write_csi2_dphy_reg(hw, CSI2PHY_CLK_LANE_ENABLE, 0); + if (sensor->lanes > 0x00) + write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE0_ENABLE, 0); + if (sensor->lanes > 0x01) + write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE1_ENABLE, 0); + if (sensor->lanes > 0x02) + write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE2_ENABLE, 0); + if (sensor->lanes > 0x03) + write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE3_ENABLE, 0); + + usleep_range(500, 1000); + + mutex_unlock(&hw->mutex); + + return 0; +} + static void rk3568_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw) { hw->grf_regs = rk3568_grf_dphy_regs; } +static void rk3588_csi2_dcphy_hw_individual_init(struct csi2_dphy_hw *hw) +{ + hw->grf_regs = rk3588_grf_dcphy_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_dcphy_hw_drv_data = { + .hsfreq_ranges = rk3588_csi2_dcphy_d_hw_hsfreq_ranges, + .num_hsfreq_ranges = ARRAY_SIZE(rk3588_csi2_dcphy_d_hw_hsfreq_ranges), + .hsfreq_ranges_cphy = rk3588_csi2_dcphy_c_hw_hsfreq_ranges, + .num_hsfreq_ranges_cphy = ARRAY_SIZE(rk3588_csi2_dcphy_c_hw_hsfreq_ranges), + .csi2dphy_regs = rk3588_csi2dcphy_regs, + .grf_regs = rk3588_grf_dcphy_regs, + .individual_init = rk3588_csi2_dcphy_hw_individual_init, + .chip_id = CHIP_ID_RK3588_DCPHY, + .stream_on = csi2_dcphy_hw_stream_on, + .stream_off = csi2_dcphy_hw_stream_off, }; static const struct of_device_id rockchip_csi2_dphy_hw_match_id[] = { @@ -546,6 +808,10 @@ 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-dcphy-hw", + .data = &rk3588_csi2_dcphy_hw_drv_data, + }, {} }; MODULE_DEVICE_TABLE(of, rockchip_csi2_dphy_hw_match_id); @@ -558,7 +824,6 @@ static int rockchip_csi2_dphy_hw_probe(struct platform_device *pdev) 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,6 +834,8 @@ static int rockchip_csi2_dphy_hw_probe(struct platform_device *pdev) if (!of_id) return -EINVAL; + drv_data = of_id->data; + grf = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(grf)) { grf = syscon_regmap_lookup_by_phandle(dev->of_node, @@ -580,22 +847,13 @@ static int rockchip_csi2_dphy_hw_probe(struct platform_device *pdev) } 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; - } - 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 +874,8 @@ static int rockchip_csi2_dphy_hw_probe(struct platform_device *pdev) 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; atomic_set(&dphy_hw->stream_cnt, 0); @@ -627,8 +885,6 @@ static int rockchip_csi2_dphy_hw_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - platform_driver_register(&rockchip_csi2_dphy_driver); - dev_info(dev, "csi2 dphy hw probe successfully!\n"); return 0; diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c index 56410bb69da5..8e3d72abb2b0 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c @@ -236,7 +236,7 @@ static __maybe_unused int csi2_dphy_runtime_suspend(struct device *dev) struct csi2_dphy_hw *hw = dphy->dphy_hw; if (hw) - clk_bulk_disable_unprepare(hw->num_clks, hw->clks); + clk_bulk_disable_unprepare(hw->num_clks, hw->clks_bulk); return 0; } @@ -250,7 +250,7 @@ static __maybe_unused int csi2_dphy_runtime_resume(struct device *dev) int ret; if (hw) { - ret = clk_bulk_prepare_enable(hw->num_clks, hw->clks); + ret = clk_bulk_prepare_enable(hw->num_clks, hw->clks_bulk); if (ret) { dev_err(hw->dev, "failed to enable clks\n"); return ret; @@ -547,9 +547,22 @@ static int rockchip_csi2_dphy_detach_hw(struct csi2_dphy *dphy) return 0; } +static struct dphy_drv_data r3568_dphy_drv_data = { + .dev_name = "csi2dphy", +}; + +static struct dphy_drv_data r3588_dcphy_drv_data = { + .dev_name = "csi2dcphy", +}; + static const struct of_device_id rockchip_csi2_dphy_match_id[] = { { .compatible = "rockchip,rk3568-csi2-dphy", + .data = &r3568_dphy_drv_data, + }, + { + .compatible = "rockchip,rk3588-csi2-dcphy", + .data = &r3588_dcphy_drv_data, }, {} }; @@ -561,6 +574,7 @@ static int rockchip_csi2_dphy_probe(struct platform_device *pdev) const struct of_device_id *of_id; struct csi2_dphy *csi2dphy; struct v4l2_subdev *sd; + const struct dphy_drv_data *drv_data; int ret; csi2dphy = devm_kzalloc(dev, sizeof(*csi2dphy), GFP_KERNEL); @@ -571,11 +585,11 @@ static int rockchip_csi2_dphy_probe(struct platform_device *pdev) of_id = of_match_device(rockchip_csi2_dphy_match_id, dev); if (!of_id) return -EINVAL; - - csi2dphy->phy_index = of_alias_get_id(dev->of_node, "csi2dphy"); - if (csi2dphy->phy_index < 0 || csi2dphy->phy_index > 2) + drv_data = of_id->data; + csi2dphy->drv_data = drv_data; + csi2dphy->phy_index = of_alias_get_id(dev->of_node, drv_data->dev_name); + if (csi2dphy->phy_index < 0 || csi2dphy->phy_index >= PHY_MAX) csi2dphy->phy_index = 0; - ret = rockchip_csi2_dphy_attach_hw(csi2dphy); if (ret) { dev_err(dev, @@ -638,7 +652,7 @@ struct platform_driver rockchip_csi2_dphy_driver = { .of_match_table = rockchip_csi2_dphy_match_id, }, }; -EXPORT_SYMBOL(rockchip_csi2_dphy_driver); +module_platform_driver(rockchip_csi2_dphy_driver); MODULE_AUTHOR("Rockchip Camera/ISP team"); MODULE_DESCRIPTION("Rockchip MIPI CSI2 DPHY driver");