Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

phy: rockchip: inno-dsidphy: Add support for rk3568

Add support for the Rockchip RK3568 DSI-DPHY. Registers were taken from
the BSP kernel driver and wherever possible cross referenced with the
TRM.

Refactor the code to allow the different compatible strings to set
either a max 1GHz timing table (all existing hardware) or a max 2.5GHz
timing table (the new RK356x). This works (for me) on both an RK3326
(PX30) and a new RK3566 device.

Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
Link: https://lore.kernel.org/r/20220919164616.12492-3-macroalpha82@gmail.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Chris Morgan and committed by
Vinod Koul
b8ecfbaf 4b507195

+158 -46
+158 -46
drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
··· 84 84 #define DATA_LANE_0_SKEW_PHASE_MASK GENMASK(2, 0) 85 85 #define DATA_LANE_0_SKEW_PHASE(x) UPDATE(x, 2, 0) 86 86 /* Analog Register Part: reg08 */ 87 + #define PLL_POST_DIV_ENABLE_MASK BIT(5) 88 + #define PLL_POST_DIV_ENABLE BIT(5) 87 89 #define SAMPLE_CLOCK_DIRECTION_MASK BIT(4) 88 90 #define SAMPLE_CLOCK_DIRECTION_REVERSE BIT(4) 89 91 #define SAMPLE_CLOCK_DIRECTION_FORWARD 0 92 + #define LOWFRE_EN_MASK BIT(5) 93 + #define PLL_OUTPUT_FREQUENCY_DIV_BY_1 0 94 + #define PLL_OUTPUT_FREQUENCY_DIV_BY_2 1 95 + /* Analog Register Part: reg0b */ 96 + #define CLOCK_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0) 97 + #define CLOCK_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0) 98 + #define VOD_MIN_RANGE 0x1 99 + #define VOD_MID_RANGE 0x3 100 + #define VOD_BIG_RANGE 0x7 101 + #define VOD_MAX_RANGE 0xf 102 + /* Analog Register Part: reg1E */ 103 + #define PLL_MODE_SEL_MASK GENMASK(6, 5) 104 + #define PLL_MODE_SEL_LVDS_MODE 0 105 + #define PLL_MODE_SEL_MIPI_MODE BIT(5) 90 106 /* Digital Register Part: reg00 */ 91 107 #define REG_DIG_RSTN_MASK BIT(0) 92 108 #define REG_DIG_RSTN_NORMAL BIT(0) ··· 118 102 #define T_LPX_CNT_MASK GENMASK(5, 0) 119 103 #define T_LPX_CNT(x) UPDATE(x, 5, 0) 120 104 /* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg06 */ 105 + #define T_HS_ZERO_CNT_HI_MASK BIT(7) 106 + #define T_HS_ZERO_CNT_HI(x) UPDATE(x, 7, 7) 121 107 #define T_HS_PREPARE_CNT_MASK GENMASK(6, 0) 122 108 #define T_HS_PREPARE_CNT(x) UPDATE(x, 6, 0) 123 109 /* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg07 */ 124 - #define T_HS_ZERO_CNT_MASK GENMASK(5, 0) 125 - #define T_HS_ZERO_CNT(x) UPDATE(x, 5, 0) 110 + #define T_HS_ZERO_CNT_LO_MASK GENMASK(5, 0) 111 + #define T_HS_ZERO_CNT_LO(x) UPDATE(x, 5, 0) 126 112 /* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg08 */ 127 113 #define T_HS_TRAIL_CNT_MASK GENMASK(6, 0) 128 114 #define T_HS_TRAIL_CNT(x) UPDATE(x, 6, 0) 129 115 /* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg09 */ 130 - #define T_HS_EXIT_CNT_MASK GENMASK(4, 0) 131 - #define T_HS_EXIT_CNT(x) UPDATE(x, 4, 0) 116 + #define T_HS_EXIT_CNT_LO_MASK GENMASK(4, 0) 117 + #define T_HS_EXIT_CNT_LO(x) UPDATE(x, 4, 0) 132 118 /* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0a */ 133 - #define T_CLK_POST_CNT_MASK GENMASK(3, 0) 134 - #define T_CLK_POST_CNT(x) UPDATE(x, 3, 0) 119 + #define T_CLK_POST_CNT_LO_MASK GENMASK(3, 0) 120 + #define T_CLK_POST_CNT_LO(x) UPDATE(x, 3, 0) 135 121 /* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0c */ 136 122 #define LPDT_TX_PPI_SYNC_MASK BIT(2) 137 123 #define LPDT_TX_PPI_SYNC_ENABLE BIT(2) ··· 147 129 #define T_CLK_PRE_CNT_MASK GENMASK(3, 0) 148 130 #define T_CLK_PRE_CNT(x) UPDATE(x, 3, 0) 149 131 /* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg10 */ 132 + #define T_CLK_POST_CNT_HI_MASK GENMASK(7, 6) 133 + #define T_CLK_POST_CNT_HI(x) UPDATE(x, 7, 6) 150 134 #define T_TA_GO_CNT_MASK GENMASK(5, 0) 151 135 #define T_TA_GO_CNT(x) UPDATE(x, 5, 0) 152 136 /* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg11 */ 137 + #define T_HS_EXIT_CNT_HI_MASK BIT(6) 138 + #define T_HS_EXIT_CNT_HI(x) UPDATE(x, 6, 6) 153 139 #define T_TA_SURE_CNT_MASK GENMASK(5, 0) 154 140 #define T_TA_SURE_CNT(x) UPDATE(x, 5, 0) 155 141 /* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg12 */ ··· 191 169 #define DSI_PHY_STATUS 0xb0 192 170 #define PHY_LOCK BIT(0) 193 171 172 + enum phy_max_rate { 173 + MAX_1GHZ, 174 + MAX_2_5GHZ, 175 + }; 176 + 177 + struct inno_video_phy_plat_data { 178 + const struct inno_mipi_dphy_timing *inno_mipi_dphy_timing_table; 179 + const unsigned int num_timings; 180 + enum phy_max_rate max_rate; 181 + }; 182 + 194 183 struct inno_dsidphy { 195 184 struct device *dev; 196 185 struct clk *ref_clk; 197 186 struct clk *pclk_phy; 198 187 struct clk *pclk_host; 188 + const struct inno_video_phy_plat_data *pdata; 199 189 void __iomem *phy_base; 200 190 void __iomem *host_base; 201 191 struct reset_control *rst; ··· 232 198 REGISTER_PART_DATA2_LANE, 233 199 REGISTER_PART_DATA3_LANE, 234 200 REGISTER_PART_LVDS, 201 + }; 202 + 203 + struct inno_mipi_dphy_timing { 204 + unsigned long rate; 205 + u8 lpx; 206 + u8 hs_prepare; 207 + u8 clk_lane_hs_zero; 208 + u8 data_lane_hs_zero; 209 + u8 hs_trail; 210 + }; 211 + 212 + static const 213 + struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_1ghz[] = { 214 + { 110000000, 0x0, 0x20, 0x16, 0x02, 0x22}, 215 + { 150000000, 0x0, 0x06, 0x16, 0x03, 0x45}, 216 + { 200000000, 0x0, 0x18, 0x17, 0x04, 0x0b}, 217 + { 250000000, 0x0, 0x05, 0x17, 0x05, 0x16}, 218 + { 300000000, 0x0, 0x51, 0x18, 0x06, 0x2c}, 219 + { 400000000, 0x0, 0x64, 0x19, 0x07, 0x33}, 220 + { 500000000, 0x0, 0x20, 0x1b, 0x07, 0x4e}, 221 + { 600000000, 0x0, 0x6a, 0x1d, 0x08, 0x3a}, 222 + { 700000000, 0x0, 0x3e, 0x1e, 0x08, 0x6a}, 223 + { 800000000, 0x0, 0x21, 0x1f, 0x09, 0x29}, 224 + {1000000000, 0x0, 0x09, 0x20, 0x09, 0x27}, 225 + }; 226 + 227 + static const 228 + struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_2_5ghz[] = { 229 + { 110000000, 0x02, 0x7f, 0x16, 0x02, 0x02}, 230 + { 150000000, 0x02, 0x7f, 0x16, 0x03, 0x02}, 231 + { 200000000, 0x02, 0x7f, 0x17, 0x04, 0x02}, 232 + { 250000000, 0x02, 0x7f, 0x17, 0x05, 0x04}, 233 + { 300000000, 0x02, 0x7f, 0x18, 0x06, 0x04}, 234 + { 400000000, 0x03, 0x7e, 0x19, 0x07, 0x04}, 235 + { 500000000, 0x03, 0x7c, 0x1b, 0x07, 0x08}, 236 + { 600000000, 0x03, 0x70, 0x1d, 0x08, 0x10}, 237 + { 700000000, 0x05, 0x40, 0x1e, 0x08, 0x30}, 238 + { 800000000, 0x05, 0x02, 0x1f, 0x09, 0x30}, 239 + {1000000000, 0x05, 0x08, 0x20, 0x09, 0x30}, 240 + {1200000000, 0x06, 0x03, 0x32, 0x14, 0x0f}, 241 + {1400000000, 0x09, 0x03, 0x32, 0x14, 0x0f}, 242 + {1600000000, 0x0d, 0x42, 0x36, 0x0e, 0x0f}, 243 + {1800000000, 0x0e, 0x47, 0x7a, 0x0e, 0x0f}, 244 + {2000000000, 0x11, 0x64, 0x7a, 0x0e, 0x0b}, 245 + {2200000000, 0x13, 0x64, 0x7e, 0x15, 0x0b}, 246 + {2400000000, 0x13, 0x33, 0x7f, 0x15, 0x6a}, 247 + {2500000000, 0x15, 0x54, 0x7f, 0x15, 0x6a}, 235 248 }; 236 249 237 250 static inline struct inno_dsidphy *hw_to_inno(struct clk_hw *hw) ··· 371 290 static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno) 372 291 { 373 292 struct phy_configure_opts_mipi_dphy *cfg = &inno->dphy_cfg; 374 - const struct { 375 - unsigned long rate; 376 - u8 hs_prepare; 377 - u8 clk_lane_hs_zero; 378 - u8 data_lane_hs_zero; 379 - u8 hs_trail; 380 - } timings[] = { 381 - { 110000000, 0x20, 0x16, 0x02, 0x22}, 382 - { 150000000, 0x06, 0x16, 0x03, 0x45}, 383 - { 200000000, 0x18, 0x17, 0x04, 0x0b}, 384 - { 250000000, 0x05, 0x17, 0x05, 0x16}, 385 - { 300000000, 0x51, 0x18, 0x06, 0x2c}, 386 - { 400000000, 0x64, 0x19, 0x07, 0x33}, 387 - { 500000000, 0x20, 0x1b, 0x07, 0x4e}, 388 - { 600000000, 0x6a, 0x1d, 0x08, 0x3a}, 389 - { 700000000, 0x3e, 0x1e, 0x08, 0x6a}, 390 - { 800000000, 0x21, 0x1f, 0x09, 0x29}, 391 - {1000000000, 0x09, 0x20, 0x09, 0x27}, 392 - }; 293 + const struct inno_mipi_dphy_timing *timings; 393 294 u32 t_txbyteclkhs, t_txclkesc; 394 295 u32 txbyteclkhs, txclkesc, esc_clk_div; 395 296 u32 hs_exit, clk_post, clk_pre, wakeup, lpx, ta_go, ta_sure, ta_wait; 396 297 u32 hs_prepare, hs_trail, hs_zero, clk_lane_hs_zero, data_lane_hs_zero; 397 298 unsigned int i; 299 + 300 + timings = inno->pdata->inno_mipi_dphy_timing_table; 398 301 399 302 inno_dsidphy_pll_calc_rate(inno, cfg->hs_clk_rate); 400 303 ··· 392 327 REG_FBDIV_HI_MASK, REG_FBDIV_HI(inno->pll.fbdiv)); 393 328 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x04, 394 329 REG_FBDIV_LO_MASK, REG_FBDIV_LO(inno->pll.fbdiv)); 330 + if (inno->pdata->max_rate == MAX_2_5GHZ) { 331 + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08, 332 + PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE); 333 + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x0b, 334 + CLOCK_LANE_VOD_RANGE_SET_MASK, 335 + CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE)); 336 + } 395 337 /* Enable PLL and LDO */ 396 338 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01, 397 339 REG_LDOPD_MASK | REG_PLLPD_MASK, ··· 440 368 clk_pre = DIV_ROUND_UP(cfg->clk_pre, BITS_PER_BYTE); 441 369 442 370 /* 443 - * The value of counter for HS Tlpx Time 444 - * Tlpx = Tpin_txbyteclkhs * (2 + value) 445 - */ 446 - lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs); 447 - if (lpx >= 2) 448 - lpx -= 2; 449 - 450 - /* 451 371 * The value of counter for HS Tta-go 452 372 * Tta-go for turnaround 453 373 * Tta-go = Ttxclkesc * value ··· 458 394 */ 459 395 ta_wait = DIV_ROUND_UP(cfg->ta_get, t_txclkesc); 460 396 461 - for (i = 0; i < ARRAY_SIZE(timings); i++) 397 + for (i = 0; i < inno->pdata->num_timings; i++) 462 398 if (inno->pll.rate <= timings[i].rate) 463 399 break; 464 400 465 - if (i == ARRAY_SIZE(timings)) 401 + if (i == inno->pdata->num_timings) 466 402 --i; 403 + 404 + /* 405 + * The value of counter for HS Tlpx Time 406 + * Tlpx = Tpin_txbyteclkhs * (2 + value) 407 + */ 408 + if (inno->pdata->max_rate == MAX_1GHZ) { 409 + lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs); 410 + if (lpx >= 2) 411 + lpx -= 2; 412 + } else 413 + lpx = timings[i].lpx; 467 414 468 415 hs_prepare = timings[i].hs_prepare; 469 416 hs_trail = timings[i].hs_trail; ··· 492 417 T_LPX_CNT(lpx)); 493 418 phy_update_bits(inno, i, 0x06, T_HS_PREPARE_CNT_MASK, 494 419 T_HS_PREPARE_CNT(hs_prepare)); 495 - phy_update_bits(inno, i, 0x07, T_HS_ZERO_CNT_MASK, 496 - T_HS_ZERO_CNT(hs_zero)); 420 + if (inno->pdata->max_rate == MAX_2_5GHZ) 421 + phy_update_bits(inno, i, 0x06, T_HS_ZERO_CNT_HI_MASK, 422 + T_HS_ZERO_CNT_HI(hs_zero >> 6)); 423 + phy_update_bits(inno, i, 0x07, T_HS_ZERO_CNT_LO_MASK, 424 + T_HS_ZERO_CNT_LO(hs_zero)); 497 425 phy_update_bits(inno, i, 0x08, T_HS_TRAIL_CNT_MASK, 498 426 T_HS_TRAIL_CNT(hs_trail)); 499 - phy_update_bits(inno, i, 0x09, T_HS_EXIT_CNT_MASK, 500 - T_HS_EXIT_CNT(hs_exit)); 501 - phy_update_bits(inno, i, 0x0a, T_CLK_POST_CNT_MASK, 502 - T_CLK_POST_CNT(clk_post)); 427 + if (inno->pdata->max_rate == MAX_2_5GHZ) 428 + phy_update_bits(inno, i, 0x11, T_HS_EXIT_CNT_HI_MASK, 429 + T_HS_EXIT_CNT_HI(hs_exit >> 5)); 430 + phy_update_bits(inno, i, 0x09, T_HS_EXIT_CNT_LO_MASK, 431 + T_HS_EXIT_CNT_LO(hs_exit)); 432 + if (inno->pdata->max_rate == MAX_2_5GHZ) 433 + phy_update_bits(inno, i, 0x10, T_CLK_POST_CNT_HI_MASK, 434 + T_CLK_POST_CNT_HI(clk_post >> 4)); 435 + phy_update_bits(inno, i, 0x0a, T_CLK_POST_CNT_LO_MASK, 436 + T_CLK_POST_CNT_LO(clk_post)); 503 437 phy_update_bits(inno, i, 0x0e, T_CLK_PRE_CNT_MASK, 504 438 T_CLK_PRE_CNT(clk_pre)); 505 439 phy_update_bits(inno, i, 0x0c, T_WAKEUP_CNT_HI_MASK, ··· 536 452 537 453 /* Sample clock reverse direction */ 538 454 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08, 539 - SAMPLE_CLOCK_DIRECTION_MASK, 540 - SAMPLE_CLOCK_DIRECTION_REVERSE); 455 + SAMPLE_CLOCK_DIRECTION_MASK | LOWFRE_EN_MASK, 456 + SAMPLE_CLOCK_DIRECTION_REVERSE | 457 + PLL_OUTPUT_FREQUENCY_DIV_BY_1); 541 458 542 459 /* Select LVDS mode */ 543 460 phy_update_bits(inno, REGISTER_PART_LVDS, 0x03, ··· 557 472 LVDS_PLL_POWER_ON | LVDS_BANDGAP_POWER_ON); 558 473 559 474 msleep(20); 475 + 476 + /* Select PLL mode */ 477 + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x1e, 478 + PLL_MODE_SEL_MASK, PLL_MODE_SEL_LVDS_MODE); 560 479 561 480 /* Reset LVDS digital logic */ 562 481 phy_update_bits(inno, REGISTER_PART_LVDS, 0x00, ··· 681 592 .owner = THIS_MODULE, 682 593 }; 683 594 595 + static const struct inno_video_phy_plat_data max_1ghz_video_phy_plat_data = { 596 + .inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_1ghz, 597 + .num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_1ghz), 598 + .max_rate = MAX_1GHZ, 599 + }; 600 + 601 + static const struct inno_video_phy_plat_data max_2_5ghz_video_phy_plat_data = { 602 + .inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_2_5ghz, 603 + .num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_2_5ghz), 604 + .max_rate = MAX_2_5GHZ, 605 + }; 606 + 684 607 static int inno_dsidphy_probe(struct platform_device *pdev) 685 608 { 686 609 struct device *dev = &pdev->dev; ··· 706 605 return -ENOMEM; 707 606 708 607 inno->dev = dev; 608 + inno->pdata = of_device_get_match_data(inno->dev); 709 609 platform_set_drvdata(pdev, inno); 710 610 711 611 inno->phy_base = devm_platform_ioremap_resource(pdev, 0); ··· 765 663 } 766 664 767 665 static const struct of_device_id inno_dsidphy_of_match[] = { 768 - { .compatible = "rockchip,px30-dsi-dphy", }, 769 - { .compatible = "rockchip,rk3128-dsi-dphy", }, 770 - { .compatible = "rockchip,rk3368-dsi-dphy", }, 666 + { 667 + .compatible = "rockchip,px30-dsi-dphy", 668 + .data = &max_1ghz_video_phy_plat_data, 669 + }, { 670 + .compatible = "rockchip,rk3128-dsi-dphy", 671 + .data = &max_1ghz_video_phy_plat_data, 672 + }, { 673 + .compatible = "rockchip,rk3368-dsi-dphy", 674 + .data = &max_1ghz_video_phy_plat_data, 675 + }, { 676 + .compatible = "rockchip,rk3568-dsi-dphy", 677 + .data = &max_2_5ghz_video_phy_plat_data, 678 + }, 771 679 {} 772 680 }; 773 681 MODULE_DEVICE_TABLE(of, inno_dsidphy_of_match);