1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Rockchip MIPI RX Innosilicon DPHY driver 4 * 5 * Copyright (C) 2021 Fuzhou Rockchip Electronics Co., Ltd. 6 */ 7 8 #include <linux/bitfield.h> 9 #include <linux/clk.h> 10 #include <linux/delay.h> 11 #include <linux/io.h> 12 #include <linux/mfd/syscon.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/of_platform.h> 16 #include <linux/phy/phy.h> 17 #include <linux/phy/phy-mipi-dphy.h> 18 #include <linux/platform_device.h> 19 #include <linux/pm_runtime.h> 20 #include <linux/regmap.h> 21 #include <linux/reset.h> 22 23 /* GRF */ 24 #define RK1808_GRF_PD_VI_CON_OFFSET 0x0430 25 26 #define RK3326_GRF_PD_VI_CON_OFFSET 0x0430 27 28 #define RK3368_GRF_SOC_CON6_OFFSET 0x0418 29 30 #define RK3568_GRF_VI_CON0 0x0340 31 #define RK3568_GRF_VI_CON1 0x0344 32 33 /* PHY */ 34 #define CSIDPHY_CTRL_LANE_ENABLE 0x00 35 #define CSIDPHY_CTRL_LANE_ENABLE_CK BIT(6) 36 #define CSIDPHY_CTRL_LANE_ENABLE_MASK GENMASK(5, 2) 37 #define CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED BIT(0) 38 39 /* not present on all variants */ 40 #define CSIDPHY_CTRL_PWRCTL 0x04 41 #define CSIDPHY_CTRL_PWRCTL_UNDEFINED GENMASK(7, 5) 42 #define CSIDPHY_CTRL_PWRCTL_SYNCRST BIT(2) 43 #define CSIDPHY_CTRL_PWRCTL_LDO_PD BIT(1) 44 #define CSIDPHY_CTRL_PWRCTL_PLL_PD BIT(0) 45 46 #define CSIDPHY_CTRL_DIG_RST 0x80 47 #define CSIDPHY_CTRL_DIG_RST_UNDEFINED 0x1e 48 #define CSIDPHY_CTRL_DIG_RST_RESET BIT(0) 49 50 /* offset after ths_settle_offset */ 51 #define CSIDPHY_CLK_THS_SETTLE 0 52 #define CSIDPHY_LANE_THS_SETTLE(n) (((n) + 1) * 0x80) 53 #define CSIDPHY_THS_SETTLE_MASK GENMASK(6, 0) 54 55 /* offset after calib_offset */ 56 #define CSIDPHY_CLK_CALIB_EN 0 57 #define CSIDPHY_LANE_CALIB_EN(n) (((n) + 1) * 0x80) 58 #define CSIDPHY_CALIB_EN BIT(7) 59 60 /* Configure the count time of the THS-SETTLE by protocol. */ 61 #define RK1808_CSIDPHY_CLK_WR_THS_SETTLE 0x160 62 #define RK3326_CSIDPHY_CLK_WR_THS_SETTLE 0x100 63 #define RK3368_CSIDPHY_CLK_WR_THS_SETTLE 0x100 64 #define RK3568_CSIDPHY_CLK_WR_THS_SETTLE 0x160 65 66 /* Calibration reception enable */ 67 #define RK1808_CSIDPHY_CLK_CALIB_EN 0x168 68 #define RK3568_CSIDPHY_CLK_CALIB_EN 0x168 69 70 /* 71 * The higher 16-bit of this register is used for write protection 72 * only if BIT(x + 16) set to 1 the BIT(x) can be written. 73 */ 74 #define HIWORD_UPDATE(val, mask, shift) \ 75 ((val) << (shift) | (mask) << ((shift) + 16)) 76 77 #define HZ_TO_MHZ(freq) div_u64(freq, 1000 * 1000) 78 79 enum dphy_reg_id { 80 /* rk1808 & rk3326 */ 81 GRF_DPHY_CSIPHY_FORCERXMODE, 82 GRF_DPHY_CSIPHY_CLKLANE_EN, 83 GRF_DPHY_CSIPHY_DATALANE_EN, 84 }; 85 86 struct dphy_reg { 87 u32 offset; 88 u32 mask; 89 u32 shift; 90 }; 91 92 #define PHY_REG(_offset, _width, _shift) \ 93 { .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, } 94 95 static const struct dphy_reg rk1808_grf_dphy_regs[] = { 96 [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 0), 97 [GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 1, 8), 98 [GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 4), 99 }; 100 101 static const struct dphy_reg rk3326_grf_dphy_regs[] = { 102 [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 0), 103 [GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 1, 8), 104 [GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 4), 105 }; 106 107 static const struct dphy_reg rk3368_grf_dphy_regs[] = { 108 [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3368_GRF_SOC_CON6_OFFSET, 4, 8), 109 }; 110 111 static const struct dphy_reg rk3568_grf_dphy_regs[] = { 112 [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3568_GRF_VI_CON0, 4, 0), 113 [GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK3568_GRF_VI_CON0, 4, 4), 114 [GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3568_GRF_VI_CON0, 1, 8), 115 }; 116 117 struct hsfreq_range { 118 u32 range_h; 119 u8 cfg_bit; 120 }; 121 122 struct dphy_drv_data { 123 int pwrctl_offset; 124 int ths_settle_offset; 125 int calib_offset; 126 const struct hsfreq_range *hsfreq_ranges; 127 int num_hsfreq_ranges; 128 const struct dphy_reg *grf_regs; 129 }; 130 131 struct rockchip_inno_csidphy { 132 struct device *dev; 133 void __iomem *phy_base; 134 struct clk *pclk; 135 struct regmap *grf; 136 struct reset_control *rst; 137 const struct dphy_drv_data *drv_data; 138 struct phy_configure_opts_mipi_dphy config; 139 u8 hsfreq; 140 }; 141 142 static inline void write_grf_reg(struct rockchip_inno_csidphy *priv, 143 int index, u8 value) 144 { 145 const struct dphy_drv_data *drv_data = priv->drv_data; 146 const struct dphy_reg *reg = &drv_data->grf_regs[index]; 147 148 if (reg->offset) 149 regmap_write(priv->grf, reg->offset, 150 HIWORD_UPDATE(value, reg->mask, reg->shift)); 151 } 152 153 /* These tables must be sorted by .range_h ascending. */ 154 static const struct hsfreq_range rk1808_mipidphy_hsfreq_ranges[] = { 155 { 109, 0x02}, { 149, 0x03}, { 199, 0x06}, { 249, 0x06}, 156 { 299, 0x06}, { 399, 0x08}, { 499, 0x0b}, { 599, 0x0e}, 157 { 699, 0x10}, { 799, 0x12}, { 999, 0x16}, {1199, 0x1e}, 158 {1399, 0x23}, {1599, 0x2d}, {1799, 0x32}, {1999, 0x37}, 159 {2199, 0x3c}, {2399, 0x41}, {2499, 0x46} 160 }; 161 162 static const struct hsfreq_range rk3326_mipidphy_hsfreq_ranges[] = { 163 { 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03}, 164 { 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07}, 165 { 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b}, 166 {1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e} 167 }; 168 169 static const struct hsfreq_range rk3368_mipidphy_hsfreq_ranges[] = { 170 { 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03}, 171 { 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07}, 172 { 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b}, 173 {1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e} 174 }; 175 176 static void rockchip_inno_csidphy_ths_settle(struct rockchip_inno_csidphy *priv, 177 int hsfreq, int offset) 178 { 179 const struct dphy_drv_data *drv_data = priv->drv_data; 180 u32 val; 181 182 val = readl(priv->phy_base + drv_data->ths_settle_offset + offset); 183 val &= ~CSIDPHY_THS_SETTLE_MASK; 184 val |= hsfreq; 185 writel(val, priv->phy_base + drv_data->ths_settle_offset + offset); 186 } 187 188 static int rockchip_inno_csidphy_configure(struct phy *phy, 189 union phy_configure_opts *opts) 190 { 191 struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); 192 const struct dphy_drv_data *drv_data = priv->drv_data; 193 struct phy_configure_opts_mipi_dphy *config = &opts->mipi_dphy; 194 unsigned int hsfreq = 0; 195 unsigned int i; 196 u64 data_rate_mbps; 197 int ret; 198 199 /* pass with phy_mipi_dphy_get_default_config (with pixel rate?) */ 200 ret = phy_mipi_dphy_config_validate(config); 201 if (ret) 202 return ret; 203 204 data_rate_mbps = HZ_TO_MHZ(config->hs_clk_rate); 205 206 dev_dbg(priv->dev, "lanes %d - data_rate_mbps %llu\n", 207 config->lanes, data_rate_mbps); 208 for (i = 0; i < drv_data->num_hsfreq_ranges; i++) { 209 if (drv_data->hsfreq_ranges[i].range_h >= data_rate_mbps) { 210 hsfreq = drv_data->hsfreq_ranges[i].cfg_bit; 211 break; 212 } 213 } 214 if (!hsfreq) 215 return -EINVAL; 216 217 priv->hsfreq = hsfreq; 218 priv->config = *config; 219 return 0; 220 } 221 222 static int rockchip_inno_csidphy_power_on(struct phy *phy) 223 { 224 struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); 225 const struct dphy_drv_data *drv_data = priv->drv_data; 226 u64 data_rate_mbps = HZ_TO_MHZ(priv->config.hs_clk_rate); 227 u32 val; 228 int ret, i; 229 230 ret = clk_enable(priv->pclk); 231 if (ret < 0) 232 return ret; 233 234 ret = pm_runtime_resume_and_get(priv->dev); 235 if (ret < 0) { 236 clk_disable(priv->pclk); 237 return ret; 238 } 239 240 /* phy start */ 241 if (drv_data->pwrctl_offset >= 0) 242 writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED | 243 CSIDPHY_CTRL_PWRCTL_SYNCRST, 244 priv->phy_base + drv_data->pwrctl_offset); 245 246 /* set data lane num and enable clock lane */ 247 val = FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_MASK, GENMASK(priv->config.lanes - 1, 0)) | 248 FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_CK, 1) | 249 FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED, 1); 250 writel(val, priv->phy_base + CSIDPHY_CTRL_LANE_ENABLE); 251 252 /* Reset dphy analog part */ 253 if (drv_data->pwrctl_offset >= 0) 254 writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED, 255 priv->phy_base + drv_data->pwrctl_offset); 256 usleep_range(500, 1000); 257 258 /* Reset dphy digital part */ 259 writel(CSIDPHY_CTRL_DIG_RST_UNDEFINED, 260 priv->phy_base + CSIDPHY_CTRL_DIG_RST); 261 writel(CSIDPHY_CTRL_DIG_RST_UNDEFINED + CSIDPHY_CTRL_DIG_RST_RESET, 262 priv->phy_base + CSIDPHY_CTRL_DIG_RST); 263 264 /* not into receive mode/wait stopstate */ 265 write_grf_reg(priv, GRF_DPHY_CSIPHY_FORCERXMODE, 0x0); 266 267 /* enable calibration */ 268 if (data_rate_mbps > 1500 && drv_data->calib_offset >= 0) { 269 writel(CSIDPHY_CALIB_EN, 270 priv->phy_base + drv_data->calib_offset + 271 CSIDPHY_CLK_CALIB_EN); 272 for (i = 0; i < priv->config.lanes; i++) 273 writel(CSIDPHY_CALIB_EN, 274 priv->phy_base + drv_data->calib_offset + 275 CSIDPHY_LANE_CALIB_EN(i)); 276 } 277 278 rockchip_inno_csidphy_ths_settle(priv, priv->hsfreq, 279 CSIDPHY_CLK_THS_SETTLE); 280 for (i = 0; i < priv->config.lanes; i++) 281 rockchip_inno_csidphy_ths_settle(priv, priv->hsfreq, 282 CSIDPHY_LANE_THS_SETTLE(i)); 283 284 write_grf_reg(priv, GRF_DPHY_CSIPHY_CLKLANE_EN, 0x1); 285 write_grf_reg(priv, GRF_DPHY_CSIPHY_DATALANE_EN, 286 GENMASK(priv->config.lanes - 1, 0)); 287 288 return 0; 289 } 290 291 static int rockchip_inno_csidphy_power_off(struct phy *phy) 292 { 293 struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); 294 const struct dphy_drv_data *drv_data = priv->drv_data; 295 296 /* disable all lanes */ 297 writel(CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED, 298 priv->phy_base + CSIDPHY_CTRL_LANE_ENABLE); 299 300 /* disable pll and ldo */ 301 if (drv_data->pwrctl_offset >= 0) 302 writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED | 303 CSIDPHY_CTRL_PWRCTL_LDO_PD | 304 CSIDPHY_CTRL_PWRCTL_PLL_PD, 305 priv->phy_base + drv_data->pwrctl_offset); 306 usleep_range(500, 1000); 307 308 pm_runtime_put(priv->dev); 309 clk_disable(priv->pclk); 310 311 return 0; 312 } 313 314 static int rockchip_inno_csidphy_init(struct phy *phy) 315 { 316 struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); 317 318 return clk_prepare(priv->pclk); 319 } 320 321 static int rockchip_inno_csidphy_exit(struct phy *phy) 322 { 323 struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); 324 325 clk_unprepare(priv->pclk); 326 327 return 0; 328 } 329 330 static const struct phy_ops rockchip_inno_csidphy_ops = { 331 .power_on = rockchip_inno_csidphy_power_on, 332 .power_off = rockchip_inno_csidphy_power_off, 333 .init = rockchip_inno_csidphy_init, 334 .exit = rockchip_inno_csidphy_exit, 335 .configure = rockchip_inno_csidphy_configure, 336 .owner = THIS_MODULE, 337 }; 338 339 static const struct dphy_drv_data rk1808_mipidphy_drv_data = { 340 .pwrctl_offset = -1, 341 .ths_settle_offset = RK1808_CSIDPHY_CLK_WR_THS_SETTLE, 342 .calib_offset = RK1808_CSIDPHY_CLK_CALIB_EN, 343 .hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges, 344 .num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges), 345 .grf_regs = rk1808_grf_dphy_regs, 346 }; 347 348 static const struct dphy_drv_data rk3326_mipidphy_drv_data = { 349 .pwrctl_offset = CSIDPHY_CTRL_PWRCTL, 350 .ths_settle_offset = RK3326_CSIDPHY_CLK_WR_THS_SETTLE, 351 .calib_offset = -1, 352 .hsfreq_ranges = rk3326_mipidphy_hsfreq_ranges, 353 .num_hsfreq_ranges = ARRAY_SIZE(rk3326_mipidphy_hsfreq_ranges), 354 .grf_regs = rk3326_grf_dphy_regs, 355 }; 356 357 static const struct dphy_drv_data rk3368_mipidphy_drv_data = { 358 .pwrctl_offset = CSIDPHY_CTRL_PWRCTL, 359 .ths_settle_offset = RK3368_CSIDPHY_CLK_WR_THS_SETTLE, 360 .calib_offset = -1, 361 .hsfreq_ranges = rk3368_mipidphy_hsfreq_ranges, 362 .num_hsfreq_ranges = ARRAY_SIZE(rk3368_mipidphy_hsfreq_ranges), 363 .grf_regs = rk3368_grf_dphy_regs, 364 }; 365 366 static const struct dphy_drv_data rk3568_mipidphy_drv_data = { 367 .pwrctl_offset = -1, 368 .ths_settle_offset = RK3568_CSIDPHY_CLK_WR_THS_SETTLE, 369 .calib_offset = RK3568_CSIDPHY_CLK_CALIB_EN, 370 .hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges, 371 .num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges), 372 .grf_regs = rk3568_grf_dphy_regs, 373 }; 374 375 static const struct of_device_id rockchip_inno_csidphy_match_id[] = { 376 { 377 .compatible = "rockchip,px30-csi-dphy", 378 .data = &rk3326_mipidphy_drv_data, 379 }, 380 { 381 .compatible = "rockchip,rk1808-csi-dphy", 382 .data = &rk1808_mipidphy_drv_data, 383 }, 384 { 385 .compatible = "rockchip,rk3326-csi-dphy", 386 .data = &rk3326_mipidphy_drv_data, 387 }, 388 { 389 .compatible = "rockchip,rk3368-csi-dphy", 390 .data = &rk3368_mipidphy_drv_data, 391 }, 392 { 393 .compatible = "rockchip,rk3568-csi-dphy", 394 .data = &rk3568_mipidphy_drv_data, 395 }, 396 {} 397 }; 398 MODULE_DEVICE_TABLE(of, rockchip_inno_csidphy_match_id); 399 400 static int rockchip_inno_csidphy_probe(struct platform_device *pdev) 401 { 402 struct rockchip_inno_csidphy *priv; 403 struct device *dev = &pdev->dev; 404 struct phy_provider *phy_provider; 405 struct phy *phy; 406 407 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 408 if (!priv) 409 return -ENOMEM; 410 411 priv->dev = dev; 412 platform_set_drvdata(pdev, priv); 413 414 priv->drv_data = of_device_get_match_data(dev); 415 if (!priv->drv_data) { 416 dev_err(dev, "Can't find device data\n"); 417 return -ENODEV; 418 } 419 420 priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, 421 "rockchip,grf"); 422 if (IS_ERR(priv->grf)) { 423 dev_err(dev, "Can't find GRF syscon\n"); 424 return PTR_ERR(priv->grf); 425 } 426 427 priv->phy_base = devm_platform_ioremap_resource(pdev, 0); 428 if (IS_ERR(priv->phy_base)) 429 return PTR_ERR(priv->phy_base); 430 431 priv->pclk = devm_clk_get(dev, "pclk"); 432 if (IS_ERR(priv->pclk)) { 433 dev_err(dev, "failed to get pclk\n"); 434 return PTR_ERR(priv->pclk); 435 } 436 437 priv->rst = devm_reset_control_get(dev, "apb"); 438 if (IS_ERR(priv->rst)) { 439 dev_err(dev, "failed to get system reset control\n"); 440 return PTR_ERR(priv->rst); 441 } 442 443 phy = devm_phy_create(dev, NULL, &rockchip_inno_csidphy_ops); 444 if (IS_ERR(phy)) { 445 dev_err(dev, "failed to create phy\n"); 446 return PTR_ERR(phy); 447 } 448 449 phy_set_drvdata(phy, priv); 450 451 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 452 if (IS_ERR(phy_provider)) { 453 dev_err(dev, "failed to register phy provider\n"); 454 return PTR_ERR(phy_provider); 455 } 456 457 pm_runtime_enable(dev); 458 459 return 0; 460 } 461 462 static void rockchip_inno_csidphy_remove(struct platform_device *pdev) 463 { 464 struct rockchip_inno_csidphy *priv = platform_get_drvdata(pdev); 465 466 pm_runtime_disable(priv->dev); 467 } 468 469 static struct platform_driver rockchip_inno_csidphy_driver = { 470 .driver = { 471 .name = "rockchip-inno-csidphy", 472 .of_match_table = rockchip_inno_csidphy_match_id, 473 }, 474 .probe = rockchip_inno_csidphy_probe, 475 .remove_new = rockchip_inno_csidphy_remove, 476 }; 477 478 module_platform_driver(rockchip_inno_csidphy_driver); 479 MODULE_AUTHOR("Heiko Stuebner <heiko.stuebner@theobroma-systems.com>"); 480 MODULE_DESCRIPTION("Rockchip MIPI Innosilicon CSI-DPHY driver"); 481 MODULE_LICENSE("GPL v2"); 482