Lines Matching +full:sc7180 +full:- +full:dp
1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/clk-provider.h>
25 #include <drm/bridge/aux-bridge.h>
27 #include <dt-bindings/phy/phy-qcom-qmp.h>
29 #include "phy-qcom-qmp-common.h"
31 #include "phy-qcom-qmp.h"
32 #include "phy-qcom-qmp-pcs-misc-v3.h"
33 #include "phy-qcom-qmp-pcs-usb-v4.h"
34 #include "phy-qcom-qmp-pcs-usb-v5.h"
35 #include "phy-qcom-qmp-pcs-usb-v6.h"
36 #include "phy-qcom-qmp-pcs-usb-v8.h"
38 #include "phy-qcom-qmp-dp-com-v3.h"
40 #include "phy-qcom-qmp-dp-phy.h"
41 #include "phy-qcom-qmp-dp-phy-v3.h"
42 #include "phy-qcom-qmp-dp-phy-v4.h"
43 #include "phy-qcom-qmp-dp-phy-v5.h"
44 #include "phy-qcom-qmp-dp-phy-v6.h"
47 /* DP PHY soft reset */
49 /* mux to select DP PHY reset control, 0:HW control, 1: software reset */
58 #define DP_MODE BIT(1) /* enables DP mode */
72 /* set of registers with offsets different per-PHY */
1652 { .name = "vdda-phy", .enable_load = 21800 },
1653 { .name = "vdda-pll", .enable_load = 36000 },
1768 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
1785 /* Init sequence for DP PHY block link rates */
1795 /* DP PHY swing and pre_emphasis tables */
1801 /* DP PHY callbacks */
2516 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_dp_serdes_init()
2517 void __iomem *serdes = qmp->dp_serdes; in qmp_combo_dp_serdes_init()
2518 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; in qmp_combo_dp_serdes_init()
2520 qmp_configure(qmp->dev, serdes, cfg->dp_serdes_tbl, in qmp_combo_dp_serdes_init()
2521 cfg->dp_serdes_tbl_num); in qmp_combo_dp_serdes_init()
2523 switch (dp_opts->link_rate) { in qmp_combo_dp_serdes_init()
2525 qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_rbr, in qmp_combo_dp_serdes_init()
2526 cfg->serdes_tbl_rbr_num); in qmp_combo_dp_serdes_init()
2529 qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_hbr, in qmp_combo_dp_serdes_init()
2530 cfg->serdes_tbl_hbr_num); in qmp_combo_dp_serdes_init()
2533 qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_hbr2, in qmp_combo_dp_serdes_init()
2534 cfg->serdes_tbl_hbr2_num); in qmp_combo_dp_serdes_init()
2537 qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_hbr3, in qmp_combo_dp_serdes_init()
2538 cfg->serdes_tbl_hbr3_num); in qmp_combo_dp_serdes_init()
2542 return -EINVAL; in qmp_combo_dp_serdes_init()
2550 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_v3_dp_aux_init()
2554 qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); in qmp_v3_dp_aux_init()
2559 qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]); in qmp_v3_dp_aux_init()
2561 writel(DP_PHY_PD_CTL_PSR_PWRDN, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); in qmp_v3_dp_aux_init()
2567 qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); in qmp_v3_dp_aux_init()
2573 qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]); in qmp_v3_dp_aux_init()
2575 writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG0); in qmp_v3_dp_aux_init()
2576 writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); in qmp_v3_dp_aux_init()
2577 writel(0x24, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2); in qmp_v3_dp_aux_init()
2578 writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG3); in qmp_v3_dp_aux_init()
2579 writel(0x0a, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG4); in qmp_v3_dp_aux_init()
2580 writel(0x26, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG5); in qmp_v3_dp_aux_init()
2581 writel(0x0a, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG6); in qmp_v3_dp_aux_init()
2582 writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG7); in qmp_v3_dp_aux_init()
2583 writel(0xbb, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG8); in qmp_v3_dp_aux_init()
2584 writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG9); in qmp_v3_dp_aux_init()
2585 qmp->dp_aux_cfg = 0; in qmp_v3_dp_aux_init()
2590 qmp->dp_dp_phy + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); in qmp_v3_dp_aux_init()
2595 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; in qmp_combo_configure_dp_swing()
2596 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_configure_dp_swing()
2601 for (i = 0; i < dp_opts->lanes; i++) { in qmp_combo_configure_dp_swing()
2602 v_level = max(v_level, dp_opts->voltage[i]); in qmp_combo_configure_dp_swing()
2603 p_level = max(p_level, dp_opts->pre[i]); in qmp_combo_configure_dp_swing()
2606 if (dp_opts->link_rate <= 2700) { in qmp_combo_configure_dp_swing()
2607 voltage_swing_cfg = (*cfg->swing_hbr_rbr)[v_level][p_level]; in qmp_combo_configure_dp_swing()
2608 pre_emphasis_cfg = (*cfg->pre_emphasis_hbr_rbr)[v_level][p_level]; in qmp_combo_configure_dp_swing()
2610 voltage_swing_cfg = (*cfg->swing_hbr3_hbr2)[v_level][p_level]; in qmp_combo_configure_dp_swing()
2611 pre_emphasis_cfg = (*cfg->pre_emphasis_hbr3_hbr2)[v_level][p_level]; in qmp_combo_configure_dp_swing()
2616 return -EINVAL; in qmp_combo_configure_dp_swing()
2622 writel(voltage_swing_cfg, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]); in qmp_combo_configure_dp_swing()
2623 writel(pre_emphasis_cfg, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); in qmp_combo_configure_dp_swing()
2624 writel(voltage_swing_cfg, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]); in qmp_combo_configure_dp_swing()
2625 writel(pre_emphasis_cfg, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); in qmp_combo_configure_dp_swing()
2632 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; in qmp_v3_configure_dp_tx()
2638 if (dp_opts->lanes == 1) { in qmp_v3_configure_dp_tx()
2646 writel(drvr_en, qmp->dp_tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); in qmp_v3_configure_dp_tx()
2647 writel(bias_en, qmp->dp_tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); in qmp_v3_configure_dp_tx()
2648 writel(drvr_en, qmp->dp_tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); in qmp_v3_configure_dp_tx()
2649 writel(bias_en, qmp->dp_tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); in qmp_v3_configure_dp_tx()
2654 bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); in qmp_combo_configure_dp_mode()
2655 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; in qmp_combo_configure_dp_mode()
2661 if (dp_opts->lanes == 4 || reverse) in qmp_combo_configure_dp_mode()
2663 if (dp_opts->lanes == 4 || !reverse) in qmp_combo_configure_dp_mode()
2666 writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); in qmp_combo_configure_dp_mode()
2669 writel(0x4c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); in qmp_combo_configure_dp_mode()
2671 writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); in qmp_combo_configure_dp_mode()
2678 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; in qmp_combo_configure_dp_clocks()
2681 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_configure_dp_clocks()
2683 switch (dp_opts->link_rate) { in qmp_combo_configure_dp_clocks()
2702 return -EINVAL; in qmp_combo_configure_dp_clocks()
2704 writel(phy_vco_div, qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_VCO_DIV]); in qmp_combo_configure_dp_clocks()
2706 clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000); in qmp_combo_configure_dp_clocks()
2707 clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq); in qmp_combo_configure_dp_clocks()
2714 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_v3_configure_dp_phy()
2720 writel(0x05, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); in qmp_v3_configure_dp_phy()
2721 writel(0x05, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); in qmp_v3_configure_dp_phy()
2727 writel(0x04, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2); in qmp_v3_configure_dp_phy()
2728 writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v3_configure_dp_phy()
2729 writel(0x05, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v3_configure_dp_phy()
2730 writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v3_configure_dp_phy()
2731 writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v3_configure_dp_phy()
2733 writel(0x20, qmp->dp_serdes + cfg->regs[QPHY_COM_RESETSM_CNTRL]); in qmp_v3_configure_dp_phy()
2735 if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_C_READY_STATUS], in qmp_v3_configure_dp_phy()
2740 return -ETIMEDOUT; in qmp_v3_configure_dp_phy()
2742 writel(0x19, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v3_configure_dp_phy()
2744 if (readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS], in qmp_v3_configure_dp_phy()
2749 return -ETIMEDOUT; in qmp_v3_configure_dp_phy()
2751 writel(0x18, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v3_configure_dp_phy()
2753 writel(0x19, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v3_configure_dp_phy()
2755 return readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS], in qmp_v3_configure_dp_phy()
2771 qmp->dp_aux_cfg++; in qmp_v3_calibrate_dp_phy()
2772 qmp->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); in qmp_v3_calibrate_dp_phy()
2773 val = cfg1_settings[qmp->dp_aux_cfg]; in qmp_v3_calibrate_dp_phy()
2775 writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); in qmp_v3_calibrate_dp_phy()
2782 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_v4_dp_aux_init()
2786 qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); in qmp_v4_dp_aux_init()
2789 writel(0x17, qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]); in qmp_v4_dp_aux_init()
2791 writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG0); in qmp_v4_dp_aux_init()
2792 writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); in qmp_v4_dp_aux_init()
2793 writel(0xa4, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2); in qmp_v4_dp_aux_init()
2794 writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG3); in qmp_v4_dp_aux_init()
2795 writel(0x0a, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG4); in qmp_v4_dp_aux_init()
2796 writel(0x26, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG5); in qmp_v4_dp_aux_init()
2797 writel(0x0a, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG6); in qmp_v4_dp_aux_init()
2798 writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG7); in qmp_v4_dp_aux_init()
2799 writel(0xb7, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG8); in qmp_v4_dp_aux_init()
2800 writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG9); in qmp_v4_dp_aux_init()
2801 qmp->dp_aux_cfg = 0; in qmp_v4_dp_aux_init()
2806 qmp->dp_dp_phy + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); in qmp_v4_dp_aux_init()
2811 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_v4_configure_dp_tx()
2814 writel(0x27, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]); in qmp_v4_configure_dp_tx()
2815 writel(0x27, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]); in qmp_v4_configure_dp_tx()
2817 writel(0x20, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); in qmp_v4_configure_dp_tx()
2818 writel(0x20, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); in qmp_v4_configure_dp_tx()
2825 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_v456_configure_dp_phy()
2829 writel(0x0f, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG_1); in qmp_v456_configure_dp_phy()
2833 writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); in qmp_v456_configure_dp_phy()
2834 writel(0xa4, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2); in qmp_v456_configure_dp_phy()
2836 writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); in qmp_v456_configure_dp_phy()
2837 writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); in qmp_v456_configure_dp_phy()
2843 writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v456_configure_dp_phy()
2844 writel(0x05, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v456_configure_dp_phy()
2845 writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v456_configure_dp_phy()
2846 writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v456_configure_dp_phy()
2848 writel(0x20, qmp->dp_serdes + cfg->regs[QPHY_COM_RESETSM_CNTRL]); in qmp_v456_configure_dp_phy()
2850 if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_C_READY_STATUS], in qmp_v456_configure_dp_phy()
2855 return -ETIMEDOUT; in qmp_v456_configure_dp_phy()
2857 if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], in qmp_v456_configure_dp_phy()
2862 return -ETIMEDOUT; in qmp_v456_configure_dp_phy()
2864 if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], in qmp_v456_configure_dp_phy()
2869 return -ETIMEDOUT; in qmp_v456_configure_dp_phy()
2871 writel(0x19, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v456_configure_dp_phy()
2873 if (readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS], in qmp_v456_configure_dp_phy()
2878 return -ETIMEDOUT; in qmp_v456_configure_dp_phy()
2880 if (readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS], in qmp_v456_configure_dp_phy()
2885 return -ETIMEDOUT; in qmp_v456_configure_dp_phy()
2892 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_v4_configure_dp_phy()
2893 bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); in qmp_v4_configure_dp_phy()
2894 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; in qmp_v4_configure_dp_phy()
2904 * At least for 7nm DP PHY this has to be done after enabling link in qmp_v4_configure_dp_phy()
2908 if (dp_opts->lanes == 1) { in qmp_v4_configure_dp_phy()
2913 } else if (dp_opts->lanes == 2) { in qmp_v4_configure_dp_phy()
2925 writel(drvr0_en, qmp->dp_tx + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]); in qmp_v4_configure_dp_phy()
2926 writel(bias0_en, qmp->dp_tx + cfg->regs[QPHY_TX_TRANSCEIVER_BIAS_EN]); in qmp_v4_configure_dp_phy()
2927 writel(drvr1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]); in qmp_v4_configure_dp_phy()
2928 writel(bias1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_TRANSCEIVER_BIAS_EN]); in qmp_v4_configure_dp_phy()
2930 writel(0x18, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v4_configure_dp_phy()
2932 writel(0x19, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); in qmp_v4_configure_dp_phy()
2934 if (readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS], in qmp_v4_configure_dp_phy()
2939 return -ETIMEDOUT; in qmp_v4_configure_dp_phy()
2941 writel(0x0a, qmp->dp_tx + cfg->regs[QPHY_TX_TX_POL_INV]); in qmp_v4_configure_dp_phy()
2942 writel(0x0a, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_POL_INV]); in qmp_v4_configure_dp_phy()
2944 writel(0x27, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]); in qmp_v4_configure_dp_phy()
2945 writel(0x27, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]); in qmp_v4_configure_dp_phy()
2947 writel(0x20, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); in qmp_v4_configure_dp_phy()
2948 writel(0x20, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); in qmp_v4_configure_dp_phy()
2962 qmp->dp_aux_cfg++; in qmp_v4_calibrate_dp_phy()
2963 qmp->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); in qmp_v4_calibrate_dp_phy()
2964 val = cfg1_settings[qmp->dp_aux_cfg]; in qmp_v4_calibrate_dp_phy()
2966 writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); in qmp_v4_calibrate_dp_phy()
2973 const struct phy_configure_opts_dp *dp_opts = &opts->dp; in qmp_combo_dp_configure()
2975 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_dp_configure()
2977 mutex_lock(&qmp->phy_mutex); in qmp_combo_dp_configure()
2979 memcpy(&qmp->dp_opts, dp_opts, sizeof(*dp_opts)); in qmp_combo_dp_configure()
2980 if (qmp->dp_opts.set_voltages) { in qmp_combo_dp_configure()
2981 cfg->configure_dp_tx(qmp); in qmp_combo_dp_configure()
2982 qmp->dp_opts.set_voltages = 0; in qmp_combo_dp_configure()
2985 mutex_unlock(&qmp->phy_mutex); in qmp_combo_dp_configure()
2993 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_dp_calibrate()
2996 mutex_lock(&qmp->phy_mutex); in qmp_combo_dp_calibrate()
2998 if (cfg->calibrate_dp_phy) in qmp_combo_dp_calibrate()
2999 ret = cfg->calibrate_dp_phy(qmp); in qmp_combo_dp_calibrate()
3001 mutex_unlock(&qmp->phy_mutex); in qmp_combo_dp_calibrate()
3008 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_com_init()
3009 void __iomem *com = qmp->com; in qmp_combo_com_init()
3013 if (!force && qmp->init_count++) in qmp_combo_com_init()
3016 ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); in qmp_combo_com_init()
3018 dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); in qmp_combo_com_init()
3022 ret = reset_control_bulk_assert(cfg->num_resets, qmp->resets); in qmp_combo_com_init()
3024 dev_err(qmp->dev, "reset assert failed\n"); in qmp_combo_com_init()
3028 ret = reset_control_bulk_deassert(cfg->num_resets, qmp->resets); in qmp_combo_com_init()
3030 dev_err(qmp->dev, "reset deassert failed\n"); in qmp_combo_com_init()
3034 ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks); in qmp_combo_com_init()
3047 if (qmp->orientation == TYPEC_ORIENTATION_REVERSE) in qmp_combo_com_init()
3051 switch (qmp->qmpphy_mode) { in qmp_combo_com_init()
3055 /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ in qmp_combo_com_init()
3064 /* bring QMP DP PHY PCS block out of reset */ in qmp_combo_com_init()
3081 qphy_setbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qmp_combo_com_init()
3087 reset_control_bulk_assert(cfg->num_resets, qmp->resets); in qmp_combo_com_init()
3089 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qmp_combo_com_init()
3091 qmp->init_count--; in qmp_combo_com_init()
3098 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_com_exit()
3100 if (!force && --qmp->init_count) in qmp_combo_com_exit()
3103 reset_control_bulk_assert(cfg->num_resets, qmp->resets); in qmp_combo_com_exit()
3105 clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); in qmp_combo_com_exit()
3107 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qmp_combo_com_exit()
3115 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_dp_init()
3118 mutex_lock(&qmp->phy_mutex); in qmp_combo_dp_init()
3124 cfg->dp_aux_init(qmp); in qmp_combo_dp_init()
3126 qmp->dp_init_count++; in qmp_combo_dp_init()
3129 mutex_unlock(&qmp->phy_mutex); in qmp_combo_dp_init()
3137 mutex_lock(&qmp->phy_mutex); in qmp_combo_dp_exit()
3141 qmp->dp_init_count--; in qmp_combo_dp_exit()
3143 mutex_unlock(&qmp->phy_mutex); in qmp_combo_dp_exit()
3151 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_dp_power_on()
3152 void __iomem *tx = qmp->dp_tx; in qmp_combo_dp_power_on()
3153 void __iomem *tx2 = qmp->dp_tx2; in qmp_combo_dp_power_on()
3155 mutex_lock(&qmp->phy_mutex); in qmp_combo_dp_power_on()
3159 qmp_configure_lane(qmp->dev, tx, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 1); in qmp_combo_dp_power_on()
3160 qmp_configure_lane(qmp->dev, tx2, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 2); in qmp_combo_dp_power_on()
3162 /* Configure special DP tx tunings */ in qmp_combo_dp_power_on()
3163 cfg->configure_dp_tx(qmp); in qmp_combo_dp_power_on()
3166 cfg->configure_dp_phy(qmp); in qmp_combo_dp_power_on()
3168 qmp->dp_powered_on = true; in qmp_combo_dp_power_on()
3170 mutex_unlock(&qmp->phy_mutex); in qmp_combo_dp_power_on()
3179 mutex_lock(&qmp->phy_mutex); in qmp_combo_dp_power_off()
3181 /* Assert DP PHY power down */ in qmp_combo_dp_power_off()
3182 writel(DP_PHY_PD_CTL_PSR_PWRDN, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); in qmp_combo_dp_power_off()
3184 qmp->dp_powered_on = false; in qmp_combo_dp_power_off()
3186 mutex_unlock(&qmp->phy_mutex); in qmp_combo_dp_power_off()
3194 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_usb_power_on()
3195 void __iomem *serdes = qmp->serdes; in qmp_combo_usb_power_on()
3196 void __iomem *tx = qmp->tx; in qmp_combo_usb_power_on()
3197 void __iomem *rx = qmp->rx; in qmp_combo_usb_power_on()
3198 void __iomem *tx2 = qmp->tx2; in qmp_combo_usb_power_on()
3199 void __iomem *rx2 = qmp->rx2; in qmp_combo_usb_power_on()
3200 void __iomem *pcs = qmp->pcs; in qmp_combo_usb_power_on()
3201 void __iomem *pcs_usb = qmp->pcs_usb; in qmp_combo_usb_power_on()
3206 qmp_configure(qmp->dev, serdes, cfg->serdes_tbl, cfg->serdes_tbl_num); in qmp_combo_usb_power_on()
3208 ret = clk_prepare_enable(qmp->pipe_clk); in qmp_combo_usb_power_on()
3210 dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); in qmp_combo_usb_power_on()
3215 qmp_configure_lane(qmp->dev, tx, cfg->tx_tbl, cfg->tx_tbl_num, 1); in qmp_combo_usb_power_on()
3216 qmp_configure_lane(qmp->dev, tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2); in qmp_combo_usb_power_on()
3218 qmp_configure_lane(qmp->dev, rx, cfg->rx_tbl, cfg->rx_tbl_num, 1); in qmp_combo_usb_power_on()
3219 qmp_configure_lane(qmp->dev, rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2); in qmp_combo_usb_power_on()
3221 qmp_configure(qmp->dev, pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); in qmp_combo_usb_power_on()
3224 qmp_configure(qmp->dev, pcs_usb, cfg->pcs_usb_tbl, in qmp_combo_usb_power_on()
3225 cfg->pcs_usb_tbl_num); in qmp_combo_usb_power_on()
3227 if (cfg->has_pwrdn_delay) in qmp_combo_usb_power_on()
3231 qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qmp_combo_usb_power_on()
3233 /* start SerDes and Phy-Coding-Sublayer */ in qmp_combo_usb_power_on()
3234 qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START); in qmp_combo_usb_power_on()
3236 status = pcs + cfg->regs[QPHY_PCS_STATUS]; in qmp_combo_usb_power_on()
3240 dev_err(qmp->dev, "phy initialization timed-out\n"); in qmp_combo_usb_power_on()
3247 clk_disable_unprepare(qmp->pipe_clk); in qmp_combo_usb_power_on()
3255 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_usb_power_off()
3257 clk_disable_unprepare(qmp->pipe_clk); in qmp_combo_usb_power_off()
3260 qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qmp_combo_usb_power_off()
3262 /* stop SerDes and Phy-Coding-Sublayer */ in qmp_combo_usb_power_off()
3263 qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL], in qmp_combo_usb_power_off()
3267 qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qmp_combo_usb_power_off()
3278 mutex_lock(&qmp->phy_mutex); in qmp_combo_usb_init()
3289 qmp->usb_init_count++; in qmp_combo_usb_init()
3292 mutex_unlock(&qmp->phy_mutex); in qmp_combo_usb_init()
3301 mutex_lock(&qmp->phy_mutex); in qmp_combo_usb_exit()
3310 qmp->usb_init_count--; in qmp_combo_usb_exit()
3313 mutex_unlock(&qmp->phy_mutex); in qmp_combo_usb_exit()
3321 qmp->phy_mode = mode; in qmp_combo_usb_set_mode()
3345 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_enable_autonomous_mode()
3346 void __iomem *pcs_usb = qmp->pcs_usb ?: qmp->pcs; in qmp_combo_enable_autonomous_mode()
3347 void __iomem *pcs_misc = qmp->pcs_misc; in qmp_combo_enable_autonomous_mode()
3350 if (qmp->phy_mode == PHY_MODE_USB_HOST_SS || in qmp_combo_enable_autonomous_mode()
3351 qmp->phy_mode == PHY_MODE_USB_DEVICE_SS) in qmp_combo_enable_autonomous_mode()
3357 qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_combo_enable_autonomous_mode()
3359 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_combo_enable_autonomous_mode()
3361 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qmp_combo_enable_autonomous_mode()
3365 qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); in qmp_combo_enable_autonomous_mode()
3374 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_disable_autonomous_mode()
3375 void __iomem *pcs_usb = qmp->pcs_usb ?: qmp->pcs; in qmp_combo_disable_autonomous_mode()
3376 void __iomem *pcs_misc = qmp->pcs_misc; in qmp_combo_disable_autonomous_mode()
3382 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qmp_combo_disable_autonomous_mode()
3385 qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_combo_disable_autonomous_mode()
3387 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_combo_disable_autonomous_mode()
3394 dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->phy_mode); in qmp_combo_runtime_suspend()
3396 if (!qmp->init_count) { in qmp_combo_runtime_suspend()
3403 clk_disable_unprepare(qmp->pipe_clk); in qmp_combo_runtime_suspend()
3404 clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); in qmp_combo_runtime_suspend()
3414 dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->phy_mode); in qmp_combo_runtime_resume()
3416 if (!qmp->init_count) { in qmp_combo_runtime_resume()
3421 ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks); in qmp_combo_runtime_resume()
3425 ret = clk_prepare_enable(qmp->pipe_clk); in qmp_combo_runtime_resume()
3428 clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); in qmp_combo_runtime_resume()
3444 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_vreg_init()
3445 struct device *dev = qmp->dev; in qmp_combo_vreg_init()
3446 int num = cfg->num_vregs; in qmp_combo_vreg_init()
3449 qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); in qmp_combo_vreg_init()
3450 if (!qmp->vregs) in qmp_combo_vreg_init()
3451 return -ENOMEM; in qmp_combo_vreg_init()
3454 qmp->vregs[i].supply = cfg->vreg_list[i].name; in qmp_combo_vreg_init()
3456 ret = devm_regulator_bulk_get(dev, num, qmp->vregs); in qmp_combo_vreg_init()
3463 ret = regulator_set_load(qmp->vregs[i].consumer, in qmp_combo_vreg_init()
3464 cfg->vreg_list[i].enable_load); in qmp_combo_vreg_init()
3467 qmp->vregs[i].supply); in qmp_combo_vreg_init()
3477 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_reset_init()
3478 struct device *dev = qmp->dev; in qmp_combo_reset_init()
3482 qmp->resets = devm_kcalloc(dev, cfg->num_resets, in qmp_combo_reset_init()
3483 sizeof(*qmp->resets), GFP_KERNEL); in qmp_combo_reset_init()
3484 if (!qmp->resets) in qmp_combo_reset_init()
3485 return -ENOMEM; in qmp_combo_reset_init()
3487 for (i = 0; i < cfg->num_resets; i++) in qmp_combo_reset_init()
3488 qmp->resets[i].id = cfg->reset_list[i]; in qmp_combo_reset_init()
3490 ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, qmp->resets); in qmp_combo_reset_init()
3499 struct device *dev = qmp->dev; in qmp_combo_clk_init()
3503 qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); in qmp_combo_clk_init()
3504 if (!qmp->clks) in qmp_combo_clk_init()
3505 return -ENOMEM; in qmp_combo_clk_init()
3508 qmp->clks[i].id = qmp_combo_phy_clk_l[i]; in qmp_combo_clk_init()
3510 qmp->num_clks = num; in qmp_combo_clk_init()
3512 return devm_clk_bulk_get_optional(dev, num, qmp->clks); in qmp_combo_clk_init()
3530 * +---------------+
3531 * | PHY block |<<---------------------------------------+
3533 * | +-------+ | +-----+ |
3534 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
3535 * clk | +-------+ | +-----+
3536 * +---------------+
3540 struct clk_fixed_rate *fixed = &qmp->pipe_clk_fixed; in phy_pipe_clk_register()
3544 snprintf(name, sizeof(name), "%s::pipe_clk", dev_name(qmp->dev)); in phy_pipe_clk_register()
3549 fixed->fixed_rate = 125000000; in phy_pipe_clk_register()
3550 fixed->hw.init = &init; in phy_pipe_clk_register()
3552 return devm_clk_hw_register(qmp->dev, &fixed->hw); in phy_pipe_clk_register()
3558 * +------------------------------+
3561 * | +-------------------+ |
3562 * | | (DP PLL/VCO) | |
3563 * | +---------+---------+ |
3565 * | +----------+-----------+ |
3567 * | +----------+-----------+ |
3568 * +------------------------------+
3570 * +---------<---------v------------>----------+
3572 * +--------v----------------+ |
3575 * +--------+----------------+ |
3584 * +--------<------------+-----------------+---<---+
3586 * +----v---------+ +--------v-----+ +--------v------+
3591 * +-------+------+ +-----+--------+ +--------+------+
3593 * v---->----------v-------------<------v
3595 * +----------+-----------------+
3597 * +---------+------------------+
3601 * for DP pixel clock
3606 switch (req->rate) { in qmp_dp_pixel_clk_determine_rate()
3612 return -EINVAL; in qmp_dp_pixel_clk_determine_rate()
3622 dp_opts = &qmp->dp_opts; in qmp_dp_pixel_clk_recalc_rate()
3624 switch (dp_opts->link_rate) { in qmp_dp_pixel_clk_recalc_rate()
3645 switch (req->rate) { in qmp_dp_link_clk_determine_rate()
3652 return -EINVAL; in qmp_dp_link_clk_determine_rate()
3662 dp_opts = &qmp->dp_opts; in qmp_dp_link_clk_recalc_rate()
3664 switch (dp_opts->link_rate) { in qmp_dp_link_clk_recalc_rate()
3669 return dp_opts->link_rate * 100000; in qmp_dp_link_clk_recalc_rate()
3683 unsigned int idx = clkspec->args[0]; in qmp_dp_clks_hw_get()
3687 return ERR_PTR(-EINVAL); in qmp_dp_clks_hw_get()
3691 return &qmp->dp_link_hw; in qmp_dp_clks_hw_get()
3693 return &qmp->dp_pixel_hw; in qmp_dp_clks_hw_get()
3702 snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev)); in phy_dp_clks_register()
3705 qmp->dp_link_hw.init = &init; in phy_dp_clks_register()
3706 ret = devm_clk_hw_register(qmp->dev, &qmp->dp_link_hw); in phy_dp_clks_register()
3710 snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev)); in phy_dp_clks_register()
3713 qmp->dp_pixel_hw.init = &init; in phy_dp_clks_register()
3714 ret = devm_clk_hw_register(qmp->dev, &qmp->dp_pixel_hw); in phy_dp_clks_register()
3725 switch (clkspec->args[0]) { in qmp_combo_clk_hw_get()
3727 return &qmp->pipe_clk_fixed.hw; in qmp_combo_clk_hw_get()
3729 return &qmp->dp_link_hw; in qmp_combo_clk_hw_get()
3731 return &qmp->dp_pixel_hw; in qmp_combo_clk_hw_get()
3734 return ERR_PTR(-EINVAL); in qmp_combo_clk_hw_get()
3753 if (usb_np == qmp->dev->of_node) in qmp_combo_register_clocks()
3754 return devm_of_clk_add_hw_provider(qmp->dev, qmp_combo_clk_hw_get, qmp); in qmp_combo_register_clocks()
3760 &qmp->pipe_clk_fixed.hw); in qmp_combo_register_clocks()
3768 ret = devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, usb_np); in qmp_combo_register_clocks()
3776 return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); in qmp_combo_register_clocks()
3784 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_typec_switch_set()
3786 if (orientation == qmp->orientation || orientation == TYPEC_ORIENTATION_NONE) in qmp_combo_typec_switch_set()
3789 mutex_lock(&qmp->phy_mutex); in qmp_combo_typec_switch_set()
3790 qmp->orientation = orientation; in qmp_combo_typec_switch_set()
3792 if (qmp->init_count) { in qmp_combo_typec_switch_set()
3793 if (qmp->usb_init_count) in qmp_combo_typec_switch_set()
3794 qmp_combo_usb_power_off(qmp->usb_phy); in qmp_combo_typec_switch_set()
3798 if (qmp->usb_init_count) in qmp_combo_typec_switch_set()
3799 qmp_combo_usb_power_on(qmp->usb_phy); in qmp_combo_typec_switch_set()
3800 if (qmp->dp_init_count) in qmp_combo_typec_switch_set()
3801 cfg->dp_aux_init(qmp); in qmp_combo_typec_switch_set()
3803 mutex_unlock(&qmp->phy_mutex); in qmp_combo_typec_switch_set()
3811 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_typec_mux_set()
3815 guard(mutex)(&qmp->phy_mutex); in qmp_combo_typec_mux_set()
3817 if (state->alt) in qmp_combo_typec_mux_set()
3818 svid = state->alt->svid; in qmp_combo_typec_mux_set()
3823 switch (state->mode) { in qmp_combo_typec_mux_set()
3824 /* DP Only */ in qmp_combo_typec_mux_set()
3830 /* DP + USB */ in qmp_combo_typec_mux_set()
3840 /* No DP SVID => don't care, assume it's just USB3 */ in qmp_combo_typec_mux_set()
3844 if (new_mode == qmp->qmpphy_mode) { in qmp_combo_typec_mux_set()
3845 dev_dbg(qmp->dev, "typec_mux_set: same qmpphy mode, bail out\n"); in qmp_combo_typec_mux_set()
3849 if (qmp->qmpphy_mode != QMPPHY_MODE_USB3_ONLY && qmp->dp_powered_on) { in qmp_combo_typec_mux_set()
3850 dev_dbg(qmp->dev, "typec_mux_set: DP PHY is still in use, delaying switch\n"); in qmp_combo_typec_mux_set()
3854 dev_dbg(qmp->dev, "typec_mux_set: switching from qmpphy mode %d to %d\n", in qmp_combo_typec_mux_set()
3855 qmp->qmpphy_mode, new_mode); in qmp_combo_typec_mux_set()
3857 qmp->qmpphy_mode = new_mode; in qmp_combo_typec_mux_set()
3859 if (qmp->init_count) { in qmp_combo_typec_mux_set()
3860 if (qmp->usb_init_count) in qmp_combo_typec_mux_set()
3861 qmp_combo_usb_power_off(qmp->usb_phy); in qmp_combo_typec_mux_set()
3863 if (qmp->dp_init_count) in qmp_combo_typec_mux_set()
3864 writel(DP_PHY_PD_CTL_PSR_PWRDN, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); in qmp_combo_typec_mux_set()
3872 if (qmp->usb_init_count) in qmp_combo_typec_mux_set()
3873 qmp->usb_init_count--; in qmp_combo_typec_mux_set()
3877 qmp_combo_usb_power_on(qmp->usb_phy); in qmp_combo_typec_mux_set()
3878 if (!qmp->usb_init_count) in qmp_combo_typec_mux_set()
3879 qmp->usb_init_count++; in qmp_combo_typec_mux_set()
3883 if (qmp->dp_init_count) in qmp_combo_typec_mux_set()
3884 cfg->dp_aux_init(qmp); in qmp_combo_typec_mux_set()
3895 typec_switch_unregister(qmp->sw); in qmp_combo_typec_switch_unregister()
3902 typec_mux_unregister(qmp->mux); in qmp_combo_typec_mux_unregister()
3909 struct device *dev = qmp->dev; in qmp_combo_typec_register()
3913 sw_desc.fwnode = dev->fwnode; in qmp_combo_typec_register()
3915 qmp->sw = typec_switch_register(dev, &sw_desc); in qmp_combo_typec_register()
3916 if (IS_ERR(qmp->sw)) { in qmp_combo_typec_register()
3917 dev_err(dev, "Unable to register typec switch: %pe\n", qmp->sw); in qmp_combo_typec_register()
3918 return PTR_ERR(qmp->sw); in qmp_combo_typec_register()
3926 mux_desc.fwnode = dev->fwnode; in qmp_combo_typec_register()
3928 qmp->mux = typec_mux_register(dev, &mux_desc); in qmp_combo_typec_register()
3929 if (IS_ERR(qmp->mux)) { in qmp_combo_typec_register()
3930 dev_err(dev, "Unable to register typec mux: %pe\n", qmp->mux); in qmp_combo_typec_register()
3931 return PTR_ERR(qmp->mux); in qmp_combo_typec_register()
3945 struct device *dev = qmp->dev; in qmp_combo_parse_dt_legacy_dp()
3948 * Get memory resources from the DP child node: in qmp_combo_parse_dt_legacy_dp()
3949 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2; in qmp_combo_parse_dt_legacy_dp()
3950 * tx2 -> 3; rx2 -> 4 in qmp_combo_parse_dt_legacy_dp()
3952 * Note that only tx/tx2 and pcs (dp_phy) are used by the DP in qmp_combo_parse_dt_legacy_dp()
3955 qmp->dp_tx = devm_of_iomap(dev, np, 0, NULL); in qmp_combo_parse_dt_legacy_dp()
3956 if (IS_ERR(qmp->dp_tx)) in qmp_combo_parse_dt_legacy_dp()
3957 return PTR_ERR(qmp->dp_tx); in qmp_combo_parse_dt_legacy_dp()
3959 qmp->dp_dp_phy = devm_of_iomap(dev, np, 2, NULL); in qmp_combo_parse_dt_legacy_dp()
3960 if (IS_ERR(qmp->dp_dp_phy)) in qmp_combo_parse_dt_legacy_dp()
3961 return PTR_ERR(qmp->dp_dp_phy); in qmp_combo_parse_dt_legacy_dp()
3963 qmp->dp_tx2 = devm_of_iomap(dev, np, 3, NULL); in qmp_combo_parse_dt_legacy_dp()
3964 if (IS_ERR(qmp->dp_tx2)) in qmp_combo_parse_dt_legacy_dp()
3965 return PTR_ERR(qmp->dp_tx2); in qmp_combo_parse_dt_legacy_dp()
3972 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_parse_dt_legacy_usb()
3973 struct device *dev = qmp->dev; in qmp_combo_parse_dt_legacy_usb()
3977 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2; in qmp_combo_parse_dt_legacy_usb()
3978 * tx2 -> 3; rx2 -> 4; pcs_misc (optional) -> 5 in qmp_combo_parse_dt_legacy_usb()
3980 qmp->tx = devm_of_iomap(dev, np, 0, NULL); in qmp_combo_parse_dt_legacy_usb()
3981 if (IS_ERR(qmp->tx)) in qmp_combo_parse_dt_legacy_usb()
3982 return PTR_ERR(qmp->tx); in qmp_combo_parse_dt_legacy_usb()
3984 qmp->rx = devm_of_iomap(dev, np, 1, NULL); in qmp_combo_parse_dt_legacy_usb()
3985 if (IS_ERR(qmp->rx)) in qmp_combo_parse_dt_legacy_usb()
3986 return PTR_ERR(qmp->rx); in qmp_combo_parse_dt_legacy_usb()
3988 qmp->pcs = devm_of_iomap(dev, np, 2, NULL); in qmp_combo_parse_dt_legacy_usb()
3989 if (IS_ERR(qmp->pcs)) in qmp_combo_parse_dt_legacy_usb()
3990 return PTR_ERR(qmp->pcs); in qmp_combo_parse_dt_legacy_usb()
3992 if (cfg->pcs_usb_offset) in qmp_combo_parse_dt_legacy_usb()
3993 qmp->pcs_usb = qmp->pcs + cfg->pcs_usb_offset; in qmp_combo_parse_dt_legacy_usb()
3995 qmp->tx2 = devm_of_iomap(dev, np, 3, NULL); in qmp_combo_parse_dt_legacy_usb()
3996 if (IS_ERR(qmp->tx2)) in qmp_combo_parse_dt_legacy_usb()
3997 return PTR_ERR(qmp->tx2); in qmp_combo_parse_dt_legacy_usb()
3999 qmp->rx2 = devm_of_iomap(dev, np, 4, NULL); in qmp_combo_parse_dt_legacy_usb()
4000 if (IS_ERR(qmp->rx2)) in qmp_combo_parse_dt_legacy_usb()
4001 return PTR_ERR(qmp->rx2); in qmp_combo_parse_dt_legacy_usb()
4003 qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL); in qmp_combo_parse_dt_legacy_usb()
4004 if (IS_ERR(qmp->pcs_misc)) { in qmp_combo_parse_dt_legacy_usb()
4005 dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); in qmp_combo_parse_dt_legacy_usb()
4006 qmp->pcs_misc = NULL; in qmp_combo_parse_dt_legacy_usb()
4009 qmp->pipe_clk = devm_get_clk_from_child(dev, np, NULL); in qmp_combo_parse_dt_legacy_usb()
4010 if (IS_ERR(qmp->pipe_clk)) { in qmp_combo_parse_dt_legacy_usb()
4011 return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk), in qmp_combo_parse_dt_legacy_usb()
4021 struct platform_device *pdev = to_platform_device(qmp->dev); in qmp_combo_parse_dt_legacy()
4024 qmp->serdes = devm_platform_ioremap_resource(pdev, 0); in qmp_combo_parse_dt_legacy()
4025 if (IS_ERR(qmp->serdes)) in qmp_combo_parse_dt_legacy()
4026 return PTR_ERR(qmp->serdes); in qmp_combo_parse_dt_legacy()
4028 qmp->com = devm_platform_ioremap_resource(pdev, 1); in qmp_combo_parse_dt_legacy()
4029 if (IS_ERR(qmp->com)) in qmp_combo_parse_dt_legacy()
4030 return PTR_ERR(qmp->com); in qmp_combo_parse_dt_legacy()
4032 qmp->dp_serdes = devm_platform_ioremap_resource(pdev, 2); in qmp_combo_parse_dt_legacy()
4033 if (IS_ERR(qmp->dp_serdes)) in qmp_combo_parse_dt_legacy()
4034 return PTR_ERR(qmp->dp_serdes); in qmp_combo_parse_dt_legacy()
4044 ret = devm_clk_bulk_get_all(qmp->dev, &qmp->clks); in qmp_combo_parse_dt_legacy()
4048 qmp->num_clks = ret; in qmp_combo_parse_dt_legacy()
4055 struct platform_device *pdev = to_platform_device(qmp->dev); in qmp_combo_parse_dt()
4056 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_combo_parse_dt()
4057 const struct qmp_combo_offsets *offs = cfg->offsets; in qmp_combo_parse_dt()
4058 struct device *dev = qmp->dev; in qmp_combo_parse_dt()
4063 return -EINVAL; in qmp_combo_parse_dt()
4069 qmp->com = base + offs->com; in qmp_combo_parse_dt()
4070 qmp->tx = base + offs->txa; in qmp_combo_parse_dt()
4071 qmp->rx = base + offs->rxa; in qmp_combo_parse_dt()
4072 qmp->tx2 = base + offs->txb; in qmp_combo_parse_dt()
4073 qmp->rx2 = base + offs->rxb; in qmp_combo_parse_dt()
4075 qmp->serdes = base + offs->usb3_serdes; in qmp_combo_parse_dt()
4076 qmp->pcs_misc = base + offs->usb3_pcs_misc; in qmp_combo_parse_dt()
4077 qmp->pcs = base + offs->usb3_pcs; in qmp_combo_parse_dt()
4078 qmp->pcs_usb = base + offs->usb3_pcs_usb; in qmp_combo_parse_dt()
4080 qmp->dp_serdes = base + offs->dp_serdes; in qmp_combo_parse_dt()
4081 if (offs->dp_txa) { in qmp_combo_parse_dt()
4082 qmp->dp_tx = base + offs->dp_txa; in qmp_combo_parse_dt()
4083 qmp->dp_tx2 = base + offs->dp_txb; in qmp_combo_parse_dt()
4085 qmp->dp_tx = base + offs->txa; in qmp_combo_parse_dt()
4086 qmp->dp_tx2 = base + offs->txb; in qmp_combo_parse_dt()
4088 qmp->dp_dp_phy = base + offs->dp_dp_phy; in qmp_combo_parse_dt()
4094 qmp->pipe_clk = devm_clk_get(dev, "usb3_pipe"); in qmp_combo_parse_dt()
4095 if (IS_ERR(qmp->pipe_clk)) { in qmp_combo_parse_dt()
4096 return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk), in qmp_combo_parse_dt()
4107 if (args->args_count == 0) in qmp_combo_phy_xlate()
4108 return ERR_PTR(-EINVAL); in qmp_combo_phy_xlate()
4110 switch (args->args[0]) { in qmp_combo_phy_xlate()
4112 return qmp->usb_phy; in qmp_combo_phy_xlate()
4114 return qmp->dp_phy; in qmp_combo_phy_xlate()
4117 return ERR_PTR(-EINVAL); in qmp_combo_phy_xlate()
4123 struct device *dev = &pdev->dev; in qmp_combo_probe()
4130 return -ENOMEM; in qmp_combo_probe()
4132 qmp->dev = dev; in qmp_combo_probe()
4135 qmp->orientation = TYPEC_ORIENTATION_NORMAL; in qmp_combo_probe()
4137 qmp->cfg = of_device_get_match_data(dev); in qmp_combo_probe()
4138 if (!qmp->cfg) in qmp_combo_probe()
4139 return -EINVAL; in qmp_combo_probe()
4141 mutex_init(&qmp->phy_mutex); in qmp_combo_probe()
4152 usb_np = of_get_child_by_name(dev->of_node, "usb3-phy"); in qmp_combo_probe()
4154 dp_np = of_get_child_by_name(dev->of_node, "dp-phy"); in qmp_combo_probe()
4157 return -EINVAL; in qmp_combo_probe()
4162 usb_np = of_node_get(dev->of_node); in qmp_combo_probe()
4163 dp_np = of_node_get(dev->of_node); in qmp_combo_probe()
4193 * The hw default is USB3_ONLY, but USB3+DP mode lets us more easily in qmp_combo_probe()
4194 * check both sub-blocks' init tables for blunders at probe time. in qmp_combo_probe()
4196 qmp->qmpphy_mode = QMPPHY_MODE_USB3DP; in qmp_combo_probe()
4198 qmp->usb_phy = devm_phy_create(dev, usb_np, &qmp_combo_usb_phy_ops); in qmp_combo_probe()
4199 if (IS_ERR(qmp->usb_phy)) { in qmp_combo_probe()
4200 ret = PTR_ERR(qmp->usb_phy); in qmp_combo_probe()
4205 phy_set_drvdata(qmp->usb_phy, qmp); in qmp_combo_probe()
4207 qmp->dp_phy = devm_phy_create(dev, dp_np, &qmp_combo_dp_phy_ops); in qmp_combo_probe()
4208 if (IS_ERR(qmp->dp_phy)) { in qmp_combo_probe()
4209 ret = PTR_ERR(qmp->dp_phy); in qmp_combo_probe()
4210 dev_err(dev, "failed to create DP PHY: %d\n", ret); in qmp_combo_probe()
4214 phy_set_drvdata(qmp->dp_phy, qmp); in qmp_combo_probe()
4216 if (usb_np == dev->of_node) in qmp_combo_probe()
4234 .compatible = "qcom,sar2130p-qmp-usb3-dp-phy",
4238 .compatible = "qcom,sc7180-qmp-usb3-dp-phy",
4242 .compatible = "qcom,sc7280-qmp-usb3-dp-phy",
4246 .compatible = "qcom,sc8180x-qmp-usb3-dp-phy",
4250 .compatible = "qcom,sc8280xp-qmp-usb43dp-phy",
4254 .compatible = "qcom,sdm845-qmp-usb3-dp-phy",
4258 .compatible = "qcom,sm6350-qmp-usb3-dp-phy",
4262 .compatible = "qcom,sm8150-qmp-usb3-dp-phy",
4266 .compatible = "qcom,sm8250-qmp-usb3-dp-phy",
4270 .compatible = "qcom,sm8350-qmp-usb3-dp-phy",
4274 .compatible = "qcom,sm8450-qmp-usb3-dp-phy",
4278 .compatible = "qcom,sm8550-qmp-usb3-dp-phy",
4282 .compatible = "qcom,sm8650-qmp-usb3-dp-phy",
4286 .compatible = "qcom,sm8750-qmp-usb3-dp-phy",
4290 .compatible = "qcom,x1e80100-qmp-usb3-dp-phy",
4300 .name = "qcom-qmp-combo-phy",
4309 MODULE_DESCRIPTION("Qualcomm QMP USB+DP combo PHY driver");