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: qcom: qmp-usbc: Add QCS615 USB/DP PHY config and DP mode support

Add QCS615-specific configuration for USB/DP PHY, including DP init
routines, voltage swing tables, and platform data. Add compatible
"qcs615-qmp-usb3-dp-phy".

Note: SW_PORTSELECT handling for orientation flip is not implemented
due to QCS615 fixed-orientation design and non-standard lane mapping.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Xiangxu Yin <xiangxu.yin@oss.qualcomm.com>
Link: https://patch.msgid.link/20251215-add-displayport-support-for-qcs615-platform-v8-12-cbc72c88a44e@oss.qualcomm.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Xiangxu Yin and committed by
Vinod Koul
81791c45 c1282d5f

+413
+413
drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
··· 30 30 #include "phy-qcom-qmp-pcs-misc-v3.h" 31 31 32 32 #include "phy-qcom-qmp-dp-phy.h" 33 + #include "phy-qcom-qmp-dp-phy-v2.h" 33 34 34 35 #define PHY_INIT_COMPLETE_TIMEOUT 10000 35 36 #define SW_PORTSELECT_VAL BIT(0) ··· 290 289 QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), 291 290 }; 292 291 292 + static const struct qmp_phy_init_tbl qmp_v2_dp_serdes_tbl[] = { 293 + QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), 294 + QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x37), 295 + QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x00), 296 + QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), 297 + QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3f), 298 + QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x0e), 299 + QMP_PHY_INIT_CFG(QSERDES_COM_BG_CTRL, 0x0f), 300 + QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x06), 301 + QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), 302 + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), 303 + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), 304 + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), 305 + QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), 306 + QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x40), 307 + QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), 308 + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), 309 + QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x08), 310 + QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x05), 311 + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), 312 + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x00), 313 + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x00), 314 + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), 315 + QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x0f), 316 + QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x02), 317 + }; 318 + 319 + static const struct qmp_phy_init_tbl qmp_v2_dp_serdes_tbl_rbr[] = { 320 + QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x2c), 321 + QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x69), 322 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), 323 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80), 324 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07), 325 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xbf), 326 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x21), 327 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), 328 + }; 329 + 330 + static const struct qmp_phy_init_tbl qmp_v2_dp_serdes_tbl_hbr[] = { 331 + QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x24), 332 + QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x69), 333 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), 334 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80), 335 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07), 336 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x3f), 337 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x38), 338 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), 339 + }; 340 + 341 + static const struct qmp_phy_init_tbl qmp_v2_dp_serdes_tbl_hbr2[] = { 342 + QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x20), 343 + QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x8c), 344 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), 345 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), 346 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x0a), 347 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x7f), 348 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x70), 349 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), 350 + }; 351 + 352 + static const struct qmp_phy_init_tbl qmp_v2_dp_tx_tbl[] = { 353 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_TRANSCEIVER_BIAS_EN, 0x1a), 354 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_VMODE_CTRL1, 0x40), 355 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_PRE_STALL_LDO_BOOST_EN, 0x30), 356 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_INTERFACE_SELECT, 0x3d), 357 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_CLKBUF_ENABLE, 0x0f), 358 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_RESET_TSYNC_EN, 0x03), 359 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_TRAN_DRVR_EMP_EN, 0x03), 360 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), 361 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_TX_INTERFACE_MODE, 0x00), 362 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_TX_EMP_POST1_LVL, 0x2b), 363 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_TX_DRV_LVL, 0x2f), 364 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_TX_BAND, 0x4), 365 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_RES_CODE_LANE_OFFSET_TX, 0x12), 366 + QMP_PHY_INIT_CFG(QSERDES_V2_TX_RES_CODE_LANE_OFFSET_RX, 0x12), 367 + }; 368 + 293 369 struct qmp_usbc_offsets { 294 370 u16 serdes; 295 371 u16 pcs; ··· 512 434 "phy_phy", "phy", 513 435 }; 514 436 437 + static const char * const usb3dpphy_reset_l[] = { 438 + "phy_phy", "dp_phy", 439 + }; 440 + 515 441 static const struct regulator_bulk_data qmp_phy_msm8998_vreg_l[] = { 516 442 { .supply = "vdda-phy", .init_load_uA = 68600 }, 517 443 { .supply = "vdda-pll", .init_load_uA = 14200 }, ··· 539 457 .rx = 0x400, 540 458 .tx2 = 0x600, 541 459 .rx2 = 0x800, 460 + }; 461 + 462 + static const struct qmp_usbc_offsets qmp_usbc_usb3dp_offsets_qcs615 = { 463 + .serdes = 0x0, 464 + .pcs = 0xc00, 465 + .pcs_misc = 0xa00, 466 + .tx = 0x200, 467 + .rx = 0x400, 468 + .tx2 = 0x600, 469 + .rx2 = 0x800, 470 + .dp_serdes = 0x1c00, 471 + .dp_txa = 0x1400, 472 + .dp_txb = 0x1800, 473 + .dp_dp_phy = 0x1000, 474 + }; 475 + 476 + static const u8 qmp_v2_dp_pre_emphasis_hbr2_rbr[4][4] = { 477 + {0x00, 0x0b, 0x12, 0xff}, 478 + {0x00, 0x0a, 0x12, 0xff}, 479 + {0x00, 0x0c, 0xff, 0xff}, 480 + {0xff, 0xff, 0xff, 0xff} 481 + }; 482 + 483 + static const u8 qmp_v2_dp_voltage_swing_hbr2_rbr[4][4] = { 484 + {0x07, 0x0f, 0x14, 0xff}, 485 + {0x11, 0x1d, 0x1f, 0xff}, 486 + {0x18, 0x1f, 0xff, 0xff}, 487 + {0xff, 0xff, 0xff, 0xff} 542 488 }; 543 489 544 490 static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { ··· 641 531 .regs = qmp_v3_usb3phy_regs_layout_qcm2290, 642 532 }; 643 533 534 + static void qmp_v2_dp_aux_init(struct qmp_usbc *qmp); 535 + static void qmp_v2_configure_dp_tx(struct qmp_usbc *qmp); 536 + static int qmp_v2_configure_dp_phy(struct qmp_usbc *qmp); 537 + static int qmp_v2_calibrate_dp_phy(struct qmp_usbc *qmp); 538 + 539 + static const struct qmp_phy_cfg qcs615_usb3dp_phy_cfg = { 540 + .offsets = &qmp_usbc_usb3dp_offsets_qcs615, 541 + 542 + .serdes_tbl = qcm2290_usb3_serdes_tbl, 543 + .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), 544 + .tx_tbl = qcm2290_usb3_tx_tbl, 545 + .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl), 546 + .rx_tbl = qcm2290_usb3_rx_tbl, 547 + .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl), 548 + .pcs_tbl = qcm2290_usb3_pcs_tbl, 549 + .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl), 550 + 551 + .regs = qmp_v3_usb3phy_regs_layout_qcm2290, 552 + 553 + .dp_serdes_tbl = qmp_v2_dp_serdes_tbl, 554 + .dp_serdes_tbl_num = ARRAY_SIZE(qmp_v2_dp_serdes_tbl), 555 + .dp_tx_tbl = qmp_v2_dp_tx_tbl, 556 + .dp_tx_tbl_num = ARRAY_SIZE(qmp_v2_dp_tx_tbl), 557 + 558 + .serdes_tbl_rbr = qmp_v2_dp_serdes_tbl_rbr, 559 + .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v2_dp_serdes_tbl_rbr), 560 + .serdes_tbl_hbr = qmp_v2_dp_serdes_tbl_hbr, 561 + .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v2_dp_serdes_tbl_hbr), 562 + .serdes_tbl_hbr2 = qmp_v2_dp_serdes_tbl_hbr2, 563 + .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v2_dp_serdes_tbl_hbr2), 564 + 565 + .swing_tbl = &qmp_v2_dp_voltage_swing_hbr2_rbr, 566 + .pre_emphasis_tbl = &qmp_v2_dp_pre_emphasis_hbr2_rbr, 567 + 568 + .dp_aux_init = qmp_v2_dp_aux_init, 569 + .configure_dp_tx = qmp_v2_configure_dp_tx, 570 + .configure_dp_phy = qmp_v2_configure_dp_phy, 571 + .calibrate_dp_phy = qmp_v2_calibrate_dp_phy, 572 + 573 + .reset_list = usb3dpphy_reset_l, 574 + .num_resets = ARRAY_SIZE(usb3dpphy_reset_l), 575 + .vreg_list = qmp_phy_qcs615_vreg_l, 576 + .num_vregs = ARRAY_SIZE(qmp_phy_qcs615_vreg_l), 577 + }; 578 + 644 579 static void qmp_usbc_set_phy_mode(struct qmp_usbc *qmp, bool is_dp) 645 580 { 646 581 if (qmp->tcsr_map && qmp->dp_phy_mode_reg) ··· 740 585 clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); 741 586 742 587 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); 588 + 589 + return 0; 590 + } 591 + 592 + static void qmp_v2_dp_aux_init(struct qmp_usbc *qmp) 593 + { 594 + writel(DP_PHY_PD_CTL_AUX_PWRDN | 595 + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | 596 + DP_PHY_PD_CTL_PLL_PWRDN, 597 + qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); 598 + 599 + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | 600 + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | 601 + DP_PHY_PD_CTL_PLL_PWRDN, 602 + qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); 603 + 604 + writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG0); 605 + writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); 606 + writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2); 607 + writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG3); 608 + writel(0x0a, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG4); 609 + writel(0x26, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG5); 610 + writel(0x0a, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG6); 611 + writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG7); 612 + writel(0xbb, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG8); 613 + writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG9); 614 + qmp->dp_aux_cfg = 0; 615 + 616 + writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | 617 + PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | 618 + PHY_AUX_REQ_ERR_MASK, 619 + qmp->dp_dp_phy + QSERDES_V2_DP_PHY_AUX_INTERRUPT_MASK); 620 + } 621 + 622 + static int qmp_v2_configure_dp_swing(struct qmp_usbc *qmp) 623 + { 624 + const struct qmp_phy_cfg *cfg = qmp->cfg; 625 + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; 626 + void __iomem *tx = qmp->dp_tx; 627 + void __iomem *tx2 = qmp->dp_tx2; 628 + unsigned int v_level = 0, p_level = 0; 629 + u8 voltage_swing_cfg, pre_emphasis_cfg; 630 + int i; 631 + 632 + if (dp_opts->lanes > 4) { 633 + dev_err(qmp->dev, "Invalid lane_num(%d)\n", dp_opts->lanes); 634 + return -EINVAL; 635 + } 636 + 637 + for (i = 0; i < dp_opts->lanes; i++) { 638 + v_level = max(v_level, dp_opts->voltage[i]); 639 + p_level = max(p_level, dp_opts->pre[i]); 640 + } 641 + 642 + if (v_level > 4 || p_level > 4) { 643 + dev_err(qmp->dev, "Invalid v(%d) | p(%d) level)\n", 644 + v_level, p_level); 645 + return -EINVAL; 646 + } 647 + 648 + voltage_swing_cfg = (*cfg->swing_tbl)[v_level][p_level]; 649 + pre_emphasis_cfg = (*cfg->pre_emphasis_tbl)[v_level][p_level]; 650 + 651 + voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; 652 + pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; 653 + 654 + if (voltage_swing_cfg == 0xff && pre_emphasis_cfg == 0xff) 655 + return -EINVAL; 656 + 657 + writel(voltage_swing_cfg, tx + QSERDES_V2_TX_TX_DRV_LVL); 658 + writel(pre_emphasis_cfg, tx + QSERDES_V2_TX_TX_EMP_POST1_LVL); 659 + writel(voltage_swing_cfg, tx2 + QSERDES_V2_TX_TX_DRV_LVL); 660 + writel(pre_emphasis_cfg, tx2 + QSERDES_V2_TX_TX_EMP_POST1_LVL); 661 + 662 + return 0; 663 + } 664 + 665 + static void qmp_usbc_configure_dp_mode(struct qmp_usbc *qmp) 666 + { 667 + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); 668 + u32 val; 669 + 670 + val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | 671 + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN; 672 + 673 + writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); 674 + 675 + if (reverse) 676 + writel(0xc9, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); 677 + else 678 + writel(0xd9, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); 679 + } 680 + 681 + static int qmp_usbc_configure_dp_clocks(struct qmp_usbc *qmp) 682 + { 683 + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; 684 + u32 phy_vco_div; 685 + unsigned long pixel_freq; 686 + 687 + switch (dp_opts->link_rate) { 688 + case 1620: 689 + phy_vco_div = 0x1; 690 + pixel_freq = 1620000000UL / 2; 691 + break; 692 + case 2700: 693 + phy_vco_div = 0x1; 694 + pixel_freq = 2700000000UL / 2; 695 + break; 696 + case 5400: 697 + phy_vco_div = 0x2; 698 + pixel_freq = 5400000000UL / 4; 699 + break; 700 + default: 701 + dev_err(qmp->dev, "link rate:%d not supported\n", dp_opts->link_rate); 702 + return -EINVAL; 703 + } 704 + writel(phy_vco_div, qmp->dp_dp_phy + QSERDES_V2_DP_PHY_VCO_DIV); 705 + 706 + clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000); 707 + clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq); 708 + 709 + return 0; 710 + } 711 + 712 + static void qmp_v2_configure_dp_tx(struct qmp_usbc *qmp) 713 + { 714 + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; 715 + void __iomem *tx = qmp->dp_tx; 716 + void __iomem *tx2 = qmp->dp_tx2; 717 + 718 + /* program default setting first */ 719 + writel(0x2a, tx + QSERDES_V2_TX_TX_DRV_LVL); 720 + writel(0x20, tx + QSERDES_V2_TX_TX_EMP_POST1_LVL); 721 + writel(0x2a, tx2 + QSERDES_V2_TX_TX_DRV_LVL); 722 + writel(0x20, tx2 + QSERDES_V2_TX_TX_EMP_POST1_LVL); 723 + 724 + if (dp_opts->link_rate >= 2700) { 725 + writel(0xc4, tx + QSERDES_V2_TX_LANE_MODE_1); 726 + writel(0xc4, tx2 + QSERDES_V2_TX_LANE_MODE_1); 727 + } else { 728 + writel(0xc6, tx + QSERDES_V2_TX_LANE_MODE_1); 729 + writel(0xc6, tx2 + QSERDES_V2_TX_LANE_MODE_1); 730 + } 731 + 732 + qmp_v2_configure_dp_swing(qmp); 733 + } 734 + 735 + static int qmp_v2_configure_dp_phy(struct qmp_usbc *qmp) 736 + { 737 + u32 status; 738 + int ret; 739 + 740 + qmp_usbc_configure_dp_mode(qmp); 741 + 742 + writel(0x05, qmp->dp_dp_phy + QSERDES_V2_DP_PHY_TX0_TX1_LANE_CTL); 743 + writel(0x05, qmp->dp_dp_phy + QSERDES_V2_DP_PHY_TX2_TX3_LANE_CTL); 744 + 745 + ret = qmp_usbc_configure_dp_clocks(qmp); 746 + if (ret) 747 + return ret; 748 + 749 + writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); 750 + writel(0x05, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); 751 + writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); 752 + writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); 753 + 754 + writel(0x20, qmp->dp_serdes + QSERDES_COM_RESETSM_CNTRL); 755 + 756 + if (readl_poll_timeout(qmp->dp_serdes + QSERDES_COM_C_READY_STATUS, 757 + status, 758 + ((status & BIT(0)) > 0), 759 + 500, 760 + 10000)) { 761 + dev_err(qmp->dev, "C_READY not ready\n"); 762 + return -ETIMEDOUT; 763 + } 764 + 765 + if (readl_poll_timeout(qmp->dp_serdes + QSERDES_COM_CMN_STATUS, 766 + status, 767 + ((status & BIT(0)) > 0), 768 + 500, 769 + 10000)){ 770 + dev_err(qmp->dev, "FREQ_DONE not ready\n"); 771 + return -ETIMEDOUT; 772 + } 773 + 774 + if (readl_poll_timeout(qmp->dp_serdes + QSERDES_COM_CMN_STATUS, 775 + status, 776 + ((status & BIT(1)) > 0), 777 + 500, 778 + 10000)){ 779 + dev_err(qmp->dev, "PLL_LOCKED not ready\n"); 780 + return -ETIMEDOUT; 781 + } 782 + 783 + writel(0x19, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); 784 + 785 + if (readl_poll_timeout(qmp->dp_dp_phy + QSERDES_V2_DP_PHY_STATUS, 786 + status, 787 + ((status & BIT(0)) > 0), 788 + 500, 789 + 10000)){ 790 + dev_err(qmp->dev, "TSYNC_DONE not ready\n"); 791 + return -ETIMEDOUT; 792 + } 793 + 794 + if (readl_poll_timeout(qmp->dp_dp_phy + QSERDES_V2_DP_PHY_STATUS, 795 + status, 796 + ((status & BIT(1)) > 0), 797 + 500, 798 + 10000)){ 799 + dev_err(qmp->dev, "PHY_READY not ready\n"); 800 + return -ETIMEDOUT; 801 + } 802 + 803 + writel(0x3f, qmp->dp_tx + QSERDES_V2_TX_TRANSCEIVER_BIAS_EN); 804 + writel(0x10, qmp->dp_tx + QSERDES_V2_TX_HIGHZ_DRVR_EN); 805 + writel(0x0a, qmp->dp_tx + QSERDES_V2_TX_TX_POL_INV); 806 + writel(0x3f, qmp->dp_tx2 + QSERDES_V2_TX_TRANSCEIVER_BIAS_EN); 807 + writel(0x10, qmp->dp_tx2 + QSERDES_V2_TX_HIGHZ_DRVR_EN); 808 + writel(0x0a, qmp->dp_tx2 + QSERDES_V2_TX_TX_POL_INV); 809 + 810 + writel(0x18, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); 811 + writel(0x19, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); 812 + 813 + if (readl_poll_timeout(qmp->dp_dp_phy + QSERDES_V2_DP_PHY_STATUS, 814 + status, 815 + ((status & BIT(1)) > 0), 816 + 500, 817 + 10000)){ 818 + dev_err(qmp->dev, "PHY_READY not ready\n"); 819 + return -ETIMEDOUT; 820 + } 821 + 822 + return 0; 823 + } 824 + 825 + static int qmp_v2_calibrate_dp_phy(struct qmp_usbc *qmp) 826 + { 827 + static const u8 cfg1_settings[] = {0x13, 0x23, 0x1d}; 828 + u8 val; 829 + 830 + qmp->dp_aux_cfg++; 831 + qmp->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); 832 + val = cfg1_settings[qmp->dp_aux_cfg]; 833 + 834 + writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); 743 835 744 836 return 0; 745 837 } ··· 1256 854 1257 855 void __iomem *tx = qmp->dp_tx; 1258 856 void __iomem *tx2 = qmp->dp_tx2; 857 + 858 + /* 859 + * FIXME: SW_PORTSELECT handling for DP orientation flip is not implemented. 860 + * Expected: 861 + * - For standard lane mapping: configure SW_PORTSELECT in QSERDES_DP_PHY_CFG_1. 862 + * - For non-standard mapping: pass orientation to dp_ctrl and handle flip 863 + * via logical2physical lane remapping. 864 + */ 1259 865 1260 866 mutex_lock(&qmp->phy_mutex); 1261 867 ··· 2010 1600 }, { 2011 1601 .compatible = "qcom,qcm2290-qmp-usb3-phy", 2012 1602 .data = &qcm2290_usb3phy_cfg, 1603 + }, { 1604 + .compatible = "qcom,qcs615-qmp-usb3-dp-phy", 1605 + .data = &qcs615_usb3dp_phy_cfg, 2013 1606 }, { 2014 1607 .compatible = "qcom,qcs615-qmp-usb3-phy", 2015 1608 .data = &qcs615_usb3phy_cfg,