diff options
Diffstat (limited to 'drivers/phy/rockchip/phy-rockchip-inno-csidphy.c')
-rw-r--r-- | drivers/phy/rockchip/phy-rockchip-inno-csidphy.c | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c index 2ab99e1d47eb..c79fb53d8ee5 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c @@ -30,6 +30,8 @@ #define RK3568_GRF_VI_CON0 0x0340 #define RK3568_GRF_VI_CON1 0x0344 +#define RK3588_CSIDPHY_GRF_CON0 0x0000 + /* PHY */ #define CSIDPHY_CTRL_LANE_ENABLE 0x00 #define CSIDPHY_CTRL_LANE_ENABLE_CK BIT(6) @@ -67,6 +69,8 @@ #define RK1808_CSIDPHY_CLK_CALIB_EN 0x168 #define RK3568_CSIDPHY_CLK_CALIB_EN 0x168 +#define RESETS_MAX 2 + /* * The higher 16-bit of this register is used for write protection * only if BIT(x + 16) set to 1 the BIT(x) can be written. @@ -87,10 +91,11 @@ struct dphy_reg { u32 offset; u32 mask; u32 shift; + u8 valid; }; #define PHY_REG(_offset, _width, _shift) \ - { .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, } + { .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, .valid = 1, } static const struct dphy_reg rk1808_grf_dphy_regs[] = { [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 0), @@ -114,6 +119,12 @@ static const struct dphy_reg rk3568_grf_dphy_regs[] = { [GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3568_GRF_VI_CON0, 1, 8), }; +static const struct dphy_reg rk3588_grf_dphy_regs[] = { + [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3588_CSIDPHY_GRF_CON0, 4, 0), + [GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK3588_CSIDPHY_GRF_CON0, 4, 4), + [GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3588_CSIDPHY_GRF_CON0, 1, 8), +}; + struct hsfreq_range { u32 range_h; u8 cfg_bit; @@ -126,6 +137,8 @@ struct dphy_drv_data { const struct hsfreq_range *hsfreq_ranges; int num_hsfreq_ranges; const struct dphy_reg *grf_regs; + const char *const *resets; + unsigned int resets_num; }; struct rockchip_inno_csidphy { @@ -133,7 +146,8 @@ struct rockchip_inno_csidphy { void __iomem *phy_base; struct clk *pclk; struct regmap *grf; - struct reset_control *rst; + struct reset_control_bulk_data resets[RESETS_MAX]; + unsigned int resets_num; const struct dphy_drv_data *drv_data; struct phy_configure_opts_mipi_dphy config; u8 hsfreq; @@ -145,7 +159,7 @@ static inline void write_grf_reg(struct rockchip_inno_csidphy *priv, const struct dphy_drv_data *drv_data = priv->drv_data; const struct dphy_reg *reg = &drv_data->grf_regs[index]; - if (reg->offset) + if (reg->valid) regmap_write(priv->grf, reg->offset, HIWORD_UPDATE(value, reg->mask, reg->shift)); } @@ -173,6 +187,15 @@ static const struct hsfreq_range rk3368_mipidphy_hsfreq_ranges[] = { {1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e} }; +static const char *const rk3368_reset_names[] = { + "apb" +}; + +static const char *const rk3588_reset_names[] = { + "apb", + "phy" +}; + static void rockchip_inno_csidphy_ths_settle(struct rockchip_inno_csidphy *priv, int hsfreq, int offset) { @@ -343,6 +366,8 @@ static const struct dphy_drv_data rk1808_mipidphy_drv_data = { .hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges, .num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges), .grf_regs = rk1808_grf_dphy_regs, + .resets = rk3368_reset_names, + .resets_num = ARRAY_SIZE(rk3368_reset_names), }; static const struct dphy_drv_data rk3326_mipidphy_drv_data = { @@ -352,6 +377,8 @@ static const struct dphy_drv_data rk3326_mipidphy_drv_data = { .hsfreq_ranges = rk3326_mipidphy_hsfreq_ranges, .num_hsfreq_ranges = ARRAY_SIZE(rk3326_mipidphy_hsfreq_ranges), .grf_regs = rk3326_grf_dphy_regs, + .resets = rk3368_reset_names, + .resets_num = ARRAY_SIZE(rk3368_reset_names), }; static const struct dphy_drv_data rk3368_mipidphy_drv_data = { @@ -361,6 +388,8 @@ static const struct dphy_drv_data rk3368_mipidphy_drv_data = { .hsfreq_ranges = rk3368_mipidphy_hsfreq_ranges, .num_hsfreq_ranges = ARRAY_SIZE(rk3368_mipidphy_hsfreq_ranges), .grf_regs = rk3368_grf_dphy_regs, + .resets = rk3368_reset_names, + .resets_num = ARRAY_SIZE(rk3368_reset_names), }; static const struct dphy_drv_data rk3568_mipidphy_drv_data = { @@ -370,6 +399,19 @@ static const struct dphy_drv_data rk3568_mipidphy_drv_data = { .hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges, .num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges), .grf_regs = rk3568_grf_dphy_regs, + .resets = rk3368_reset_names, + .resets_num = ARRAY_SIZE(rk3368_reset_names), +}; + +static const struct dphy_drv_data rk3588_mipidphy_drv_data = { + .pwrctl_offset = -1, + .ths_settle_offset = RK3568_CSIDPHY_CLK_WR_THS_SETTLE, + .calib_offset = RK3568_CSIDPHY_CLK_CALIB_EN, + .hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges, + .num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges), + .grf_regs = rk3588_grf_dphy_regs, + .resets = rk3588_reset_names, + .resets_num = ARRAY_SIZE(rk3588_reset_names), }; static const struct of_device_id rockchip_inno_csidphy_match_id[] = { @@ -393,6 +435,10 @@ static const struct of_device_id rockchip_inno_csidphy_match_id[] = { .compatible = "rockchip,rk3568-csi-dphy", .data = &rk3568_mipidphy_drv_data, }, + { + .compatible = "rockchip,rk3588-csi-dphy", + .data = &rk3588_mipidphy_drv_data, + }, {} }; MODULE_DEVICE_TABLE(of, rockchip_inno_csidphy_match_id); @@ -403,6 +449,7 @@ static int rockchip_inno_csidphy_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct phy_provider *phy_provider; struct phy *phy; + int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -434,10 +481,18 @@ static int rockchip_inno_csidphy_probe(struct platform_device *pdev) return PTR_ERR(priv->pclk); } - priv->rst = devm_reset_control_get(dev, "apb"); - if (IS_ERR(priv->rst)) { + if (priv->drv_data->resets_num > RESETS_MAX) { + dev_err(dev, "invalid number of resets\n"); + return -EINVAL; + } + priv->resets_num = priv->drv_data->resets_num; + for (unsigned int i = 0; i < priv->resets_num; i++) + priv->resets[i].id = priv->drv_data->resets[i]; + ret = devm_reset_control_bulk_get_exclusive(dev, priv->resets_num, + priv->resets); + if (ret) { dev_err(dev, "failed to get system reset control\n"); - return PTR_ERR(priv->rst); + return ret; } phy = devm_phy_create(dev, NULL, &rockchip_inno_csidphy_ops); |