Lines Matching +full:sdm845 +full:- +full:qmp +full:- +full:usb3 +full:- +full:uni +full:- +full:phy

1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/clk-provider.h>
17 #include <linux/phy/phy.h>
23 #include <dt-bindings/phy/phy.h>
25 #include "phy-qcom-qmp.h"
42 /* DP PHY soft reset */
44 /* mux to select DP PHY reset control, 0:HW control, 1: software reset */
46 /* USB3 PHY soft reset */
48 /* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */
52 #define USB3_MODE BIT(0) /* enables USB3 mode */
83 * if yes, then offset gives index in the reg-layout
115 /* set of registers with offsets different per-PHY */
1827 /* struct qmp_phy_cfg - per-PHY initialization config */
1829 /* phy-type - PCIE/UFS/USB */
1831 /* number of lanes provided by phy */
1834 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
1846 /* Init sequence for DP PHY block link rates */
1873 /* true, if PHY has a separate PHY_COM control block */
1875 /* true, if PHY has a reset for individual lanes */
1877 /* true, if PHY needs delay after POWER_DOWN */
1883 /* true, if PHY has a separate DP_COM control block */
1885 /* true, if PHY has secondary tx/rx lanes to be configured */
1898 * struct qmp_phy - per-lane phy descriptor
1900 * @phy: generic phy
1901 * @cfg: phy specific configuration
1902 * @serdes: iomapped memory space for phy's serdes (i.e. PLL)
1911 * @qmp: QMP phy to which this lane belongs
1913 * @mode: current PHY mode
1916 struct phy *phy; member
1927 struct qcom_qmp *qmp; member
1942 * struct qcom_qmp - structure holding QMP phy block attributes
1945 * @dp_com: iomapped memory space for phy's dp_com control block
1947 * @clks: array of clocks required by phy
1948 * @resets: array of resets required by phy
1951 * @phys: array of per-lane phy descriptors
1952 * @phy_mutex: mutex lock for PHY common block initialization
1953 * @init_count: phy common block initialization count
1954 * @ufs_reset: optional UFS PHY reset handle
1996 /* list of clocks required by phy */
2017 /* the primary usb3 phy on sm8250 doesn't have a ref clock */
2028 "phy", "common", "cfg",
2032 "phy", "common",
2036 "phy",
2040 "phy",
2045 "vdda-phy", "vdda-pll",
2157 "phy", "common",
2603 if (!(t->lane_mask & lane_mask)) in qcom_qmp_phy_configure_lane()
2606 if (t->in_layout) in qcom_qmp_phy_configure_lane()
2607 writel(t->val, base + regs[t->offset]); in qcom_qmp_phy_configure_lane()
2609 writel(t->val, base + t->offset); in qcom_qmp_phy_configure_lane()
2623 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_serdes_init() local
2624 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_serdes_init()
2625 void __iomem *serdes = qphy->serdes; in qcom_qmp_phy_serdes_init()
2626 const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; in qcom_qmp_phy_serdes_init()
2627 const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; in qcom_qmp_phy_serdes_init()
2628 int serdes_tbl_num = cfg->serdes_tbl_num; in qcom_qmp_phy_serdes_init()
2631 qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); in qcom_qmp_phy_serdes_init()
2633 if (cfg->type == PHY_TYPE_DP) { in qcom_qmp_phy_serdes_init()
2634 switch (dp_opts->link_rate) { in qcom_qmp_phy_serdes_init()
2636 qcom_qmp_phy_configure(serdes, cfg->regs, in qcom_qmp_phy_serdes_init()
2637 cfg->serdes_tbl_rbr, in qcom_qmp_phy_serdes_init()
2638 cfg->serdes_tbl_rbr_num); in qcom_qmp_phy_serdes_init()
2641 qcom_qmp_phy_configure(serdes, cfg->regs, in qcom_qmp_phy_serdes_init()
2642 cfg->serdes_tbl_hbr, in qcom_qmp_phy_serdes_init()
2643 cfg->serdes_tbl_hbr_num); in qcom_qmp_phy_serdes_init()
2646 qcom_qmp_phy_configure(serdes, cfg->regs, in qcom_qmp_phy_serdes_init()
2647 cfg->serdes_tbl_hbr2, in qcom_qmp_phy_serdes_init()
2648 cfg->serdes_tbl_hbr2_num); in qcom_qmp_phy_serdes_init()
2651 qcom_qmp_phy_configure(serdes, cfg->regs, in qcom_qmp_phy_serdes_init()
2652 cfg->serdes_tbl_hbr3, in qcom_qmp_phy_serdes_init()
2653 cfg->serdes_tbl_hbr3_num); in qcom_qmp_phy_serdes_init()
2657 return -EINVAL; in qcom_qmp_phy_serdes_init()
2662 if (cfg->has_phy_com_ctrl) { in qcom_qmp_phy_serdes_init()
2666 qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); in qcom_qmp_phy_serdes_init()
2667 qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], in qcom_qmp_phy_serdes_init()
2670 status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; in qcom_qmp_phy_serdes_init()
2671 mask = cfg->mask_com_pcs_ready; in qcom_qmp_phy_serdes_init()
2676 dev_err(qmp->dev, in qcom_qmp_phy_serdes_init()
2677 "phy common block init timed-out\n"); in qcom_qmp_phy_serdes_init()
2689 qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); in qcom_qmp_phy_dp_aux_init()
2691 /* Turn on BIAS current for PHY/PLL */ in qcom_qmp_phy_dp_aux_init()
2694 qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); in qcom_qmp_phy_dp_aux_init()
2696 writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); in qcom_qmp_phy_dp_aux_init()
2702 qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); in qcom_qmp_phy_dp_aux_init()
2708 qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); in qcom_qmp_phy_dp_aux_init()
2710 writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG0); in qcom_qmp_phy_dp_aux_init()
2711 writel(0x13, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1); in qcom_qmp_phy_dp_aux_init()
2712 writel(0x24, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2); in qcom_qmp_phy_dp_aux_init()
2713 writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG3); in qcom_qmp_phy_dp_aux_init()
2714 writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG4); in qcom_qmp_phy_dp_aux_init()
2715 writel(0x26, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG5); in qcom_qmp_phy_dp_aux_init()
2716 writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG6); in qcom_qmp_phy_dp_aux_init()
2717 writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG7); in qcom_qmp_phy_dp_aux_init()
2718 writel(0xbb, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG8); in qcom_qmp_phy_dp_aux_init()
2719 writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG9); in qcom_qmp_phy_dp_aux_init()
2720 qphy->dp_aux_cfg = 0; in qcom_qmp_phy_dp_aux_init()
2725 qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); in qcom_qmp_phy_dp_aux_init()
2744 const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; in qcom_qmp_phy_configure_dp_tx()
2750 for (i = 0; i < dp_opts->lanes; i++) { in qcom_qmp_phy_configure_dp_tx()
2751 v_level = max(v_level, dp_opts->voltage[i]); in qcom_qmp_phy_configure_dp_tx()
2752 p_level = max(p_level, dp_opts->pre[i]); in qcom_qmp_phy_configure_dp_tx()
2755 if (dp_opts->lanes == 1) { in qcom_qmp_phy_configure_dp_tx()
2774 writel(voltage_swing_cfg, qphy->tx + QSERDES_V3_TX_TX_DRV_LVL); in qcom_qmp_phy_configure_dp_tx()
2775 writel(pre_emphasis_cfg, qphy->tx + QSERDES_V3_TX_TX_EMP_POST1_LVL); in qcom_qmp_phy_configure_dp_tx()
2776 writel(voltage_swing_cfg, qphy->tx2 + QSERDES_V3_TX_TX_DRV_LVL); in qcom_qmp_phy_configure_dp_tx()
2777 writel(pre_emphasis_cfg, qphy->tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL); in qcom_qmp_phy_configure_dp_tx()
2779 writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); in qcom_qmp_phy_configure_dp_tx()
2780 writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); in qcom_qmp_phy_configure_dp_tx()
2781 writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); in qcom_qmp_phy_configure_dp_tx()
2782 writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); in qcom_qmp_phy_configure_dp_tx()
2785 static int qcom_qmp_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) in qcom_qmp_dp_phy_configure() argument
2787 const struct phy_configure_opts_dp *dp_opts = &opts->dp; in qcom_qmp_dp_phy_configure()
2788 struct qmp_phy *qphy = phy_get_drvdata(phy); in qcom_qmp_dp_phy_configure()
2790 memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts)); in qcom_qmp_dp_phy_configure()
2791 if (qphy->dp_opts.set_voltages) { in qcom_qmp_dp_phy_configure()
2793 qphy->dp_opts.set_voltages = 0; in qcom_qmp_dp_phy_configure()
2801 const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; in qcom_qmp_phy_configure_dp_phy()
2802 const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; in qcom_qmp_phy_configure_dp_phy()
2811 * use type-c connector to understand orientation and lanes. in qcom_qmp_phy_configure_dp_phy()
2814 * the orientation of the type-c cable. in qcom_qmp_phy_configure_dp_phy()
2821 * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); in qcom_qmp_phy_configure_dp_phy()
2824 writel(val, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); in qcom_qmp_phy_configure_dp_phy()
2826 writel(0x5c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); in qcom_qmp_phy_configure_dp_phy()
2827 writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); in qcom_qmp_phy_configure_dp_phy()
2828 writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); in qcom_qmp_phy_configure_dp_phy()
2830 switch (dp_opts->link_rate) { in qcom_qmp_phy_configure_dp_phy()
2849 return -EINVAL; in qcom_qmp_phy_configure_dp_phy()
2851 writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV); in qcom_qmp_phy_configure_dp_phy()
2853 clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); in qcom_qmp_phy_configure_dp_phy()
2854 clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); in qcom_qmp_phy_configure_dp_phy()
2856 writel(0x04, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2); in qcom_qmp_phy_configure_dp_phy()
2857 writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG); in qcom_qmp_phy_configure_dp_phy()
2858 writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_CFG); in qcom_qmp_phy_configure_dp_phy()
2859 writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG); in qcom_qmp_phy_configure_dp_phy()
2860 writel(0x09, qphy->pcs + QSERDES_V3_DP_PHY_CFG); in qcom_qmp_phy_configure_dp_phy()
2862 writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL); in qcom_qmp_phy_configure_dp_phy()
2864 if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS, in qcom_qmp_phy_configure_dp_phy()
2869 return -ETIMEDOUT; in qcom_qmp_phy_configure_dp_phy()
2871 writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG); in qcom_qmp_phy_configure_dp_phy()
2873 if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, in qcom_qmp_phy_configure_dp_phy()
2878 return -ETIMEDOUT; in qcom_qmp_phy_configure_dp_phy()
2880 writel(0x18, qphy->pcs + QSERDES_V3_DP_PHY_CFG); in qcom_qmp_phy_configure_dp_phy()
2882 writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG); in qcom_qmp_phy_configure_dp_phy()
2884 return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, in qcom_qmp_phy_configure_dp_phy()
2895 static int qcom_qmp_dp_phy_calibrate(struct phy *phy) in qcom_qmp_dp_phy_calibrate() argument
2897 struct qmp_phy *qphy = phy_get_drvdata(phy); in qcom_qmp_dp_phy_calibrate()
2901 qphy->dp_aux_cfg++; in qcom_qmp_dp_phy_calibrate()
2902 qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); in qcom_qmp_dp_phy_calibrate()
2903 val = cfg1_settings[qphy->dp_aux_cfg]; in qcom_qmp_dp_phy_calibrate()
2905 writel(val, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1); in qcom_qmp_dp_phy_calibrate()
2912 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_com_init() local
2913 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_com_init()
2914 void __iomem *serdes = qphy->serdes; in qcom_qmp_phy_com_init()
2915 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_com_init()
2916 void __iomem *dp_com = qmp->dp_com; in qcom_qmp_phy_com_init()
2919 mutex_lock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
2920 if (qmp->init_count++) { in qcom_qmp_phy_com_init()
2921 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
2926 ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); in qcom_qmp_phy_com_init()
2928 dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); in qcom_qmp_phy_com_init()
2932 for (i = 0; i < cfg->num_resets; i++) { in qcom_qmp_phy_com_init()
2933 ret = reset_control_assert(qmp->resets[i]); in qcom_qmp_phy_com_init()
2935 dev_err(qmp->dev, "%s reset assert failed\n", in qcom_qmp_phy_com_init()
2936 cfg->reset_list[i]); in qcom_qmp_phy_com_init()
2941 for (i = cfg->num_resets - 1; i >= 0; i--) { in qcom_qmp_phy_com_init()
2942 ret = reset_control_deassert(qmp->resets[i]); in qcom_qmp_phy_com_init()
2944 dev_err(qmp->dev, "%s reset deassert failed\n", in qcom_qmp_phy_com_init()
2945 qphy->cfg->reset_list[i]); in qcom_qmp_phy_com_init()
2950 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qcom_qmp_phy_com_init()
2952 dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); in qcom_qmp_phy_com_init()
2956 if (cfg->has_phy_dp_com_ctrl) { in qcom_qmp_phy_com_init()
2959 /* override hardware control for reset of qmp phy */ in qcom_qmp_phy_com_init()
2964 /* Default type-c orientation, i.e CC1 */ in qcom_qmp_phy_com_init()
2970 /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ in qcom_qmp_phy_com_init()
2979 if (cfg->has_phy_com_ctrl) { in qcom_qmp_phy_com_init()
2980 qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], in qcom_qmp_phy_com_init()
2983 if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) in qcom_qmp_phy_com_init()
2985 cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qcom_qmp_phy_com_init()
2986 cfg->pwrdn_ctrl); in qcom_qmp_phy_com_init()
2989 cfg->pwrdn_ctrl); in qcom_qmp_phy_com_init()
2992 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
2997 while (++i < cfg->num_resets) in qcom_qmp_phy_com_init()
2998 reset_control_assert(qmp->resets[i]); in qcom_qmp_phy_com_init()
3000 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qcom_qmp_phy_com_init()
3002 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
3009 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_com_exit() local
3010 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_com_exit()
3011 void __iomem *serdes = qphy->serdes; in qcom_qmp_phy_com_exit()
3012 int i = cfg->num_resets; in qcom_qmp_phy_com_exit()
3014 mutex_lock(&qmp->phy_mutex); in qcom_qmp_phy_com_exit()
3015 if (--qmp->init_count) { in qcom_qmp_phy_com_exit()
3016 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_exit()
3020 reset_control_assert(qmp->ufs_reset); in qcom_qmp_phy_com_exit()
3021 if (cfg->has_phy_com_ctrl) { in qcom_qmp_phy_com_exit()
3022 qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], in qcom_qmp_phy_com_exit()
3024 qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], in qcom_qmp_phy_com_exit()
3026 qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], in qcom_qmp_phy_com_exit()
3030 while (--i >= 0) in qcom_qmp_phy_com_exit()
3031 reset_control_assert(qmp->resets[i]); in qcom_qmp_phy_com_exit()
3033 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_com_exit()
3035 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qcom_qmp_phy_com_exit()
3037 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_exit()
3042 static int qcom_qmp_phy_init(struct phy *phy) in qcom_qmp_phy_init() argument
3044 struct qmp_phy *qphy = phy_get_drvdata(phy); in qcom_qmp_phy_init()
3045 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_init() local
3046 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_init()
3048 dev_vdbg(qmp->dev, "Initializing QMP phy\n"); in qcom_qmp_phy_init()
3050 if (cfg->no_pcs_sw_reset) { in qcom_qmp_phy_init()
3053 * circular dependency where UFS needs its PHY, but the PHY in qcom_qmp_phy_init()
3056 if (!qmp->ufs_reset) { in qcom_qmp_phy_init()
3057 qmp->ufs_reset = in qcom_qmp_phy_init()
3058 devm_reset_control_get_exclusive(qmp->dev, in qcom_qmp_phy_init()
3061 if (IS_ERR(qmp->ufs_reset)) { in qcom_qmp_phy_init()
3062 ret = PTR_ERR(qmp->ufs_reset); in qcom_qmp_phy_init()
3063 dev_err(qmp->dev, in qcom_qmp_phy_init()
3067 qmp->ufs_reset = NULL; in qcom_qmp_phy_init()
3072 ret = reset_control_assert(qmp->ufs_reset); in qcom_qmp_phy_init()
3081 if (cfg->type == PHY_TYPE_DP) in qcom_qmp_phy_init()
3087 static int qcom_qmp_phy_power_on(struct phy *phy) in qcom_qmp_phy_power_on() argument
3089 struct qmp_phy *qphy = phy_get_drvdata(phy); in qcom_qmp_phy_power_on()
3090 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_power_on() local
3091 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_power_on()
3092 void __iomem *tx = qphy->tx; in qcom_qmp_phy_power_on()
3093 void __iomem *rx = qphy->rx; in qcom_qmp_phy_power_on()
3094 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_power_on()
3095 void __iomem *pcs_misc = qphy->pcs_misc; in qcom_qmp_phy_power_on()
3102 if (cfg->has_lane_rst) { in qcom_qmp_phy_power_on()
3103 ret = reset_control_deassert(qphy->lane_rst); in qcom_qmp_phy_power_on()
3105 dev_err(qmp->dev, "lane%d reset deassert failed\n", in qcom_qmp_phy_power_on()
3106 qphy->index); in qcom_qmp_phy_power_on()
3111 ret = clk_prepare_enable(qphy->pipe_clk); in qcom_qmp_phy_power_on()
3113 dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); in qcom_qmp_phy_power_on()
3118 qcom_qmp_phy_configure_lane(tx, cfg->regs, in qcom_qmp_phy_power_on()
3119 cfg->tx_tbl, cfg->tx_tbl_num, 1); in qcom_qmp_phy_power_on()
3120 /* Configuration for other LANE for USB-DP combo PHY */ in qcom_qmp_phy_power_on()
3121 if (cfg->is_dual_lane_phy) in qcom_qmp_phy_power_on()
3122 qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, in qcom_qmp_phy_power_on()
3123 cfg->tx_tbl, cfg->tx_tbl_num, 2); in qcom_qmp_phy_power_on()
3126 if (cfg->type == PHY_TYPE_DP) in qcom_qmp_phy_power_on()
3129 qcom_qmp_phy_configure_lane(rx, cfg->regs, in qcom_qmp_phy_power_on()
3130 cfg->rx_tbl, cfg->rx_tbl_num, 1); in qcom_qmp_phy_power_on()
3132 if (cfg->is_dual_lane_phy) in qcom_qmp_phy_power_on()
3133 qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, in qcom_qmp_phy_power_on()
3134 cfg->rx_tbl, cfg->rx_tbl_num, 2); in qcom_qmp_phy_power_on()
3137 if (cfg->type == PHY_TYPE_DP) in qcom_qmp_phy_power_on()
3140 qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); in qcom_qmp_phy_power_on()
3142 ret = reset_control_deassert(qmp->ufs_reset); in qcom_qmp_phy_power_on()
3146 qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, in qcom_qmp_phy_power_on()
3147 cfg->pcs_misc_tbl_num); in qcom_qmp_phy_power_on()
3150 * Pull out PHY from POWER DOWN state. in qcom_qmp_phy_power_on()
3151 * This is active low enable signal to power-down PHY. in qcom_qmp_phy_power_on()
3153 if(cfg->type == PHY_TYPE_PCIE) in qcom_qmp_phy_power_on()
3154 qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); in qcom_qmp_phy_power_on()
3156 if (cfg->has_pwrdn_delay) in qcom_qmp_phy_power_on()
3157 usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); in qcom_qmp_phy_power_on()
3159 if (cfg->type != PHY_TYPE_DP) { in qcom_qmp_phy_power_on()
3160 /* Pull PHY out of reset state */ in qcom_qmp_phy_power_on()
3161 if (!cfg->no_pcs_sw_reset) in qcom_qmp_phy_power_on()
3162 qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qcom_qmp_phy_power_on()
3163 /* start SerDes and Phy-Coding-Sublayer */ in qcom_qmp_phy_power_on()
3164 qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qcom_qmp_phy_power_on()
3166 if (cfg->type == PHY_TYPE_UFS) { in qcom_qmp_phy_power_on()
3167 status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; in qcom_qmp_phy_power_on()
3171 status = pcs + cfg->regs[QPHY_PCS_STATUS]; in qcom_qmp_phy_power_on()
3179 dev_err(qmp->dev, "phy initialization timed-out\n"); in qcom_qmp_phy_power_on()
3186 clk_disable_unprepare(qphy->pipe_clk); in qcom_qmp_phy_power_on()
3188 if (cfg->has_lane_rst) in qcom_qmp_phy_power_on()
3189 reset_control_assert(qphy->lane_rst); in qcom_qmp_phy_power_on()
3194 static int qcom_qmp_phy_power_off(struct phy *phy) in qcom_qmp_phy_power_off() argument
3196 struct qmp_phy *qphy = phy_get_drvdata(phy); in qcom_qmp_phy_power_off()
3197 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_power_off()
3199 clk_disable_unprepare(qphy->pipe_clk); in qcom_qmp_phy_power_off()
3201 if (cfg->type == PHY_TYPE_DP) { in qcom_qmp_phy_power_off()
3202 /* Assert DP PHY power down */ in qcom_qmp_phy_power_off()
3203 writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); in qcom_qmp_phy_power_off()
3205 /* PHY reset */ in qcom_qmp_phy_power_off()
3206 if (!cfg->no_pcs_sw_reset) in qcom_qmp_phy_power_off()
3207 qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qcom_qmp_phy_power_off()
3209 /* stop SerDes and Phy-Coding-Sublayer */ in qcom_qmp_phy_power_off()
3210 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qcom_qmp_phy_power_off()
3212 /* Put PHY into POWER DOWN state: active low */ in qcom_qmp_phy_power_off()
3213 if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { in qcom_qmp_phy_power_off()
3214 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qcom_qmp_phy_power_off()
3215 cfg->pwrdn_ctrl); in qcom_qmp_phy_power_off()
3217 qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, in qcom_qmp_phy_power_off()
3218 cfg->pwrdn_ctrl); in qcom_qmp_phy_power_off()
3225 static int qcom_qmp_phy_exit(struct phy *phy) in qcom_qmp_phy_exit() argument
3227 struct qmp_phy *qphy = phy_get_drvdata(phy); in qcom_qmp_phy_exit()
3228 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_exit()
3230 if (cfg->has_lane_rst) in qcom_qmp_phy_exit()
3231 reset_control_assert(qphy->lane_rst); in qcom_qmp_phy_exit()
3238 static int qcom_qmp_phy_enable(struct phy *phy) in qcom_qmp_phy_enable() argument
3242 ret = qcom_qmp_phy_init(phy); in qcom_qmp_phy_enable()
3246 ret = qcom_qmp_phy_power_on(phy); in qcom_qmp_phy_enable()
3248 qcom_qmp_phy_exit(phy); in qcom_qmp_phy_enable()
3253 static int qcom_qmp_phy_disable(struct phy *phy) in qcom_qmp_phy_disable() argument
3257 ret = qcom_qmp_phy_power_off(phy); in qcom_qmp_phy_disable()
3260 return qcom_qmp_phy_exit(phy); in qcom_qmp_phy_disable()
3263 static int qcom_qmp_phy_set_mode(struct phy *phy, in qcom_qmp_phy_set_mode() argument
3266 struct qmp_phy *qphy = phy_get_drvdata(phy); in qcom_qmp_phy_set_mode()
3268 qphy->mode = mode; in qcom_qmp_phy_set_mode()
3275 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_enable_autonomous_mode()
3276 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_enable_autonomous_mode()
3277 void __iomem *pcs_misc = qphy->pcs_misc; in qcom_qmp_phy_enable_autonomous_mode()
3280 if (qphy->mode == PHY_MODE_USB_HOST_SS || in qcom_qmp_phy_enable_autonomous_mode()
3281 qphy->mode == PHY_MODE_USB_DEVICE_SS) in qcom_qmp_phy_enable_autonomous_mode()
3287 qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_enable_autonomous_mode()
3289 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_enable_autonomous_mode()
3291 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qcom_qmp_phy_enable_autonomous_mode()
3294 /* Enable required PHY autonomous mode interrupts */ in qcom_qmp_phy_enable_autonomous_mode()
3295 qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); in qcom_qmp_phy_enable_autonomous_mode()
3304 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_disable_autonomous_mode()
3305 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_disable_autonomous_mode()
3306 void __iomem *pcs_misc = qphy->pcs_misc; in qcom_qmp_phy_disable_autonomous_mode()
3312 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qcom_qmp_phy_disable_autonomous_mode()
3315 qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_disable_autonomous_mode()
3317 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_disable_autonomous_mode()
3322 struct qcom_qmp *qmp = dev_get_drvdata(dev); in qcom_qmp_phy_runtime_suspend() local
3323 struct qmp_phy *qphy = qmp->phys[0]; in qcom_qmp_phy_runtime_suspend()
3324 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_runtime_suspend()
3326 dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); in qcom_qmp_phy_runtime_suspend()
3328 /* Supported only for USB3 PHY and luckily USB3 is the first phy */ in qcom_qmp_phy_runtime_suspend()
3329 if (cfg->type != PHY_TYPE_USB3) in qcom_qmp_phy_runtime_suspend()
3332 if (!qmp->init_count) { in qcom_qmp_phy_runtime_suspend()
3333 dev_vdbg(dev, "PHY not initialized, bailing out\n"); in qcom_qmp_phy_runtime_suspend()
3339 clk_disable_unprepare(qphy->pipe_clk); in qcom_qmp_phy_runtime_suspend()
3340 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_runtime_suspend()
3347 struct qcom_qmp *qmp = dev_get_drvdata(dev); in qcom_qmp_phy_runtime_resume() local
3348 struct qmp_phy *qphy = qmp->phys[0]; in qcom_qmp_phy_runtime_resume()
3349 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_runtime_resume()
3352 dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); in qcom_qmp_phy_runtime_resume()
3354 /* Supported only for USB3 PHY and luckily USB3 is the first phy */ in qcom_qmp_phy_runtime_resume()
3355 if (cfg->type != PHY_TYPE_USB3) in qcom_qmp_phy_runtime_resume()
3358 if (!qmp->init_count) { in qcom_qmp_phy_runtime_resume()
3359 dev_vdbg(dev, "PHY not initialized, bailing out\n"); in qcom_qmp_phy_runtime_resume()
3363 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qcom_qmp_phy_runtime_resume()
3365 dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); in qcom_qmp_phy_runtime_resume()
3369 ret = clk_prepare_enable(qphy->pipe_clk); in qcom_qmp_phy_runtime_resume()
3372 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_runtime_resume()
3383 struct qcom_qmp *qmp = dev_get_drvdata(dev); in qcom_qmp_phy_vreg_init() local
3384 int num = cfg->num_vregs; in qcom_qmp_phy_vreg_init()
3387 qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); in qcom_qmp_phy_vreg_init()
3388 if (!qmp->vregs) in qcom_qmp_phy_vreg_init()
3389 return -ENOMEM; in qcom_qmp_phy_vreg_init()
3392 qmp->vregs[i].supply = cfg->vreg_list[i]; in qcom_qmp_phy_vreg_init()
3394 return devm_regulator_bulk_get(dev, num, qmp->vregs); in qcom_qmp_phy_vreg_init()
3399 struct qcom_qmp *qmp = dev_get_drvdata(dev); in qcom_qmp_phy_reset_init() local
3402 qmp->resets = devm_kcalloc(dev, cfg->num_resets, in qcom_qmp_phy_reset_init()
3403 sizeof(*qmp->resets), GFP_KERNEL); in qcom_qmp_phy_reset_init()
3404 if (!qmp->resets) in qcom_qmp_phy_reset_init()
3405 return -ENOMEM; in qcom_qmp_phy_reset_init()
3407 for (i = 0; i < cfg->num_resets; i++) { in qcom_qmp_phy_reset_init()
3409 const char *name = cfg->reset_list[i]; in qcom_qmp_phy_reset_init()
3416 qmp->resets[i] = rst; in qcom_qmp_phy_reset_init()
3424 struct qcom_qmp *qmp = dev_get_drvdata(dev); in qcom_qmp_phy_clk_init() local
3425 int num = cfg->num_clks; in qcom_qmp_phy_clk_init()
3428 qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); in qcom_qmp_phy_clk_init()
3429 if (!qmp->clks) in qcom_qmp_phy_clk_init()
3430 return -ENOMEM; in qcom_qmp_phy_clk_init()
3433 qmp->clks[i].id = cfg->clk_list[i]; in qcom_qmp_phy_clk_init()
3435 return devm_clk_bulk_get(dev, num, qmp->clks); in qcom_qmp_phy_clk_init()
3446 * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
3448 * by the PHY driver for its operations.
3453 * +---------------+
3454 * | PHY block |<<---------------------------------------+
3456 * | +-------+ | +-----+ |
3457 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
3458 * clk | +-------+ | +-----+
3459 * +---------------+
3461 static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) in phy_pipe_clk_register() argument
3467 ret = of_property_read_string(np, "clock-output-names", &init.name); in phy_pipe_clk_register()
3469 dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); in phy_pipe_clk_register()
3473 fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); in phy_pipe_clk_register()
3475 return -ENOMEM; in phy_pipe_clk_register()
3479 /* controllers using QMP phys use 125MHz pipe clock interface */ in phy_pipe_clk_register()
3480 fixed->fixed_rate = 125000000; in phy_pipe_clk_register()
3481 fixed->hw.init = &init; in phy_pipe_clk_register()
3483 ret = devm_clk_hw_register(qmp->dev, &fixed->hw); in phy_pipe_clk_register()
3487 ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); in phy_pipe_clk_register()
3495 ret = devm_add_action(qmp->dev, phy_clk_release_provider, np); in phy_pipe_clk_register()
3505 * +------------------------------+
3508 * | +-------------------+ |
3510 * | +---------+---------+ |
3512 * | +----------+-----------+ |
3514 * | +----------+-----------+ |
3515 * +------------------------------+
3517 * +---------<---------v------------>----------+
3519 * +--------v----------------+ |
3522 * +--------+----------------+ |
3531 * +--------<------------+-----------------+---<---+
3533 * +----v---------+ +--------v-----+ +--------v------+
3538 * +-------+------+ +-----+--------+ +--------+------+
3540 * v---->----------v-------------<------v
3542 * +----------+-----------------+
3544 * +---------+------------------+
3554 switch (req->rate) { in qcom_qmp_dp_pixel_clk_determine_rate()
3560 return -EINVAL; in qcom_qmp_dp_pixel_clk_determine_rate()
3572 qphy = dp_clks->qphy; in qcom_qmp_dp_pixel_clk_recalc_rate()
3573 dp_opts = &qphy->dp_opts; in qcom_qmp_dp_pixel_clk_recalc_rate()
3575 switch (dp_opts->link_rate) { in qcom_qmp_dp_pixel_clk_recalc_rate()
3597 switch (req->rate) { in qcom_qmp_dp_link_clk_determine_rate()
3604 return -EINVAL; in qcom_qmp_dp_link_clk_determine_rate()
3616 qphy = dp_clks->qphy; in qcom_qmp_dp_link_clk_recalc_rate()
3617 dp_opts = &qphy->dp_opts; in qcom_qmp_dp_link_clk_recalc_rate()
3619 switch (dp_opts->link_rate) { in qcom_qmp_dp_link_clk_recalc_rate()
3624 return dp_opts->link_rate * 100000; in qcom_qmp_dp_link_clk_recalc_rate()
3639 unsigned int idx = clkspec->args[0]; in qcom_qmp_dp_clks_hw_get()
3643 return ERR_PTR(-EINVAL); in qcom_qmp_dp_clks_hw_get()
3647 return &dp_clks->dp_link_hw; in qcom_qmp_dp_clks_hw_get()
3649 return &dp_clks->dp_pixel_hw; in qcom_qmp_dp_clks_hw_get()
3652 static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, in phy_dp_clks_register() argument
3659 dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL); in phy_dp_clks_register()
3661 return -ENOMEM; in phy_dp_clks_register()
3663 dp_clks->qphy = qphy; in phy_dp_clks_register()
3664 qphy->dp_clks = dp_clks; in phy_dp_clks_register()
3668 dp_clks->dp_link_hw.init = &init; in phy_dp_clks_register()
3669 ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw); in phy_dp_clks_register()
3675 dp_clks->dp_pixel_hw.init = &init; in phy_dp_clks_register()
3676 ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw); in phy_dp_clks_register()
3688 ret = devm_add_action(qmp->dev, phy_clk_release_provider, np); in phy_dp_clks_register()
3724 struct qcom_qmp *qmp = dev_get_drvdata(dev); in qcom_qmp_phy_create() local
3725 struct phy *generic_phy; in qcom_qmp_phy_create()
3733 return -ENOMEM; in qcom_qmp_phy_create()
3735 qphy->cfg = cfg; in qcom_qmp_phy_create()
3736 qphy->serdes = serdes; in qcom_qmp_phy_create()
3738 * Get memory resources for each phy lane: in qcom_qmp_phy_create()
3739 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. in qcom_qmp_phy_create()
3740 * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 in qcom_qmp_phy_create()
3741 * For single lane PHYs: pcs_misc (optional) -> 3. in qcom_qmp_phy_create()
3743 qphy->tx = of_iomap(np, 0); in qcom_qmp_phy_create()
3744 if (!qphy->tx) in qcom_qmp_phy_create()
3745 return -ENOMEM; in qcom_qmp_phy_create()
3747 qphy->rx = of_iomap(np, 1); in qcom_qmp_phy_create()
3748 if (!qphy->rx) in qcom_qmp_phy_create()
3749 return -ENOMEM; in qcom_qmp_phy_create()
3751 qphy->pcs = of_iomap(np, 2); in qcom_qmp_phy_create()
3752 if (!qphy->pcs) in qcom_qmp_phy_create()
3753 return -ENOMEM; in qcom_qmp_phy_create()
3756 * If this is a dual-lane PHY, then there should be registers for the in qcom_qmp_phy_create()
3761 if (cfg->is_dual_lane_phy) { in qcom_qmp_phy_create()
3762 qphy->tx2 = of_iomap(np, 3); in qcom_qmp_phy_create()
3763 qphy->rx2 = of_iomap(np, 4); in qcom_qmp_phy_create()
3764 if (!qphy->tx2 || !qphy->rx2) { in qcom_qmp_phy_create()
3769 qphy->pcs_misc = qphy->tx2; in qcom_qmp_phy_create()
3770 qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; in qcom_qmp_phy_create()
3771 qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; in qcom_qmp_phy_create()
3774 qphy->pcs_misc = of_iomap(np, 5); in qcom_qmp_phy_create()
3778 qphy->pcs_misc = of_iomap(np, 3); in qcom_qmp_phy_create()
3781 if (!qphy->pcs_misc) in qcom_qmp_phy_create()
3782 dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); in qcom_qmp_phy_create()
3785 * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 in qcom_qmp_phy_create()
3787 * we return error in case phy is USB3 or PIPE type. in qcom_qmp_phy_create()
3792 qphy->pipe_clk = of_clk_get_by_name(np, prop_name); in qcom_qmp_phy_create()
3793 if (IS_ERR(qphy->pipe_clk)) { in qcom_qmp_phy_create()
3794 if (cfg->type == PHY_TYPE_PCIE || in qcom_qmp_phy_create()
3795 cfg->type == PHY_TYPE_USB3) { in qcom_qmp_phy_create()
3796 ret = PTR_ERR(qphy->pipe_clk); in qcom_qmp_phy_create()
3797 if (ret != -EPROBE_DEFER) in qcom_qmp_phy_create()
3803 qphy->pipe_clk = NULL; in qcom_qmp_phy_create()
3807 if (cfg->has_lane_rst) { in qcom_qmp_phy_create()
3809 qphy->lane_rst = of_reset_control_get(np, prop_name); in qcom_qmp_phy_create()
3810 if (IS_ERR(qphy->lane_rst)) { in qcom_qmp_phy_create()
3812 return PTR_ERR(qphy->lane_rst); in qcom_qmp_phy_create()
3816 if (cfg->type == PHY_TYPE_UFS || cfg->type == PHY_TYPE_PCIE) in qcom_qmp_phy_create()
3818 else if (cfg->type == PHY_TYPE_DP) in qcom_qmp_phy_create()
3830 qphy->phy = generic_phy; in qcom_qmp_phy_create()
3831 qphy->index = id; in qcom_qmp_phy_create()
3832 qphy->qmp = qmp; in qcom_qmp_phy_create()
3833 qmp->phys[id] = qphy; in qcom_qmp_phy_create()
3841 .compatible = "qcom,ipq8074-qmp-usb3-phy",
3844 .compatible = "qcom,msm8996-qmp-pcie-phy",
3847 .compatible = "qcom,msm8996-qmp-ufs-phy",
3850 .compatible = "qcom,msm8996-qmp-usb3-phy",
3853 .compatible = "qcom,msm8998-qmp-pcie-phy",
3856 .compatible = "qcom,msm8998-qmp-ufs-phy",
3859 .compatible = "qcom,ipq8074-qmp-pcie-phy",
3862 .compatible = "qcom,sc7180-qmp-usb3-phy",
3865 .compatible = "qcom,sc7180-qmp-usb3-dp-phy",
3866 /* It's a combo phy */
3868 .compatible = "qcom,sdm845-qhp-pcie-phy",
3871 .compatible = "qcom,sdm845-qmp-pcie-phy",
3874 .compatible = "qcom,sdm845-qmp-usb3-phy",
3877 .compatible = "qcom,sdm845-qmp-usb3-uni-phy",
3880 .compatible = "qcom,sdm845-qmp-ufs-phy",
3883 .compatible = "qcom,msm8998-qmp-usb3-phy",
3886 .compatible = "qcom,sm8150-qmp-ufs-phy",
3889 .compatible = "qcom,sm8250-qmp-ufs-phy",
3892 .compatible = "qcom,sm8150-qmp-usb3-phy",
3895 .compatible = "qcom,sm8150-qmp-usb3-uni-phy",
3898 .compatible = "qcom,sm8250-qmp-usb3-phy",
3901 .compatible = "qcom,sm8250-qmp-usb3-uni-phy",
3910 .compatible = "qcom,sc7180-qmp-usb3-dp-phy",
3923 struct qcom_qmp *qmp; in qcom_qmp_phy_probe() local
3924 struct device *dev = &pdev->dev; in qcom_qmp_phy_probe()
3937 qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); in qcom_qmp_phy_probe()
3938 if (!qmp) in qcom_qmp_phy_probe()
3939 return -ENOMEM; in qcom_qmp_phy_probe()
3941 qmp->dev = dev; in qcom_qmp_phy_probe()
3942 dev_set_drvdata(dev, qmp); in qcom_qmp_phy_probe()
3944 /* Get the specific init parameters of QMP phy */ in qcom_qmp_phy_probe()
3951 return -EINVAL; in qcom_qmp_phy_probe()
3953 combo_cfg = match->data; in qcom_qmp_phy_probe()
3955 return -EINVAL; in qcom_qmp_phy_probe()
3957 usb_cfg = combo_cfg->usb_cfg; in qcom_qmp_phy_probe()
3961 /* per PHY serdes; usually located at base address */ in qcom_qmp_phy_probe()
3966 /* per PHY dp_com; if PHY has dp_com control block */ in qcom_qmp_phy_probe()
3967 if (combo_cfg || cfg->has_phy_dp_com_ctrl) { in qcom_qmp_phy_probe()
3968 qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); in qcom_qmp_phy_probe()
3969 if (IS_ERR(qmp->dp_com)) in qcom_qmp_phy_probe()
3970 return PTR_ERR(qmp->dp_com); in qcom_qmp_phy_probe()
3974 /* Only two serdes for combo PHY */ in qcom_qmp_phy_probe()
3979 dp_cfg = combo_cfg->dp_cfg; in qcom_qmp_phy_probe()
3982 expected_phys = cfg->nlanes; in qcom_qmp_phy_probe()
3985 mutex_init(&qmp->phy_mutex); in qcom_qmp_phy_probe()
3997 if (ret != -EPROBE_DEFER) in qcom_qmp_phy_probe()
4003 num = of_get_available_child_count(dev->of_node); in qcom_qmp_phy_probe()
4006 return -EINVAL; in qcom_qmp_phy_probe()
4008 qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); in qcom_qmp_phy_probe()
4009 if (!qmp->phys) in qcom_qmp_phy_probe()
4010 return -ENOMEM; in qcom_qmp_phy_probe()
4021 for_each_available_child_of_node(dev->of_node, child) { in qcom_qmp_phy_probe()
4022 if (of_node_name_eq(child, "dp-phy")) { in qcom_qmp_phy_probe()
4025 } else if (of_node_name_eq(child, "usb3-phy")) { in qcom_qmp_phy_probe()
4030 /* Create per-lane phy */ in qcom_qmp_phy_probe()
4033 dev_err(dev, "failed to create lane%d phy, %d\n", in qcom_qmp_phy_probe()
4039 * Register the pipe clock provided by phy. in qcom_qmp_phy_probe()
4042 if (cfg->type == PHY_TYPE_USB3 || cfg->type == PHY_TYPE_PCIE) { in qcom_qmp_phy_probe()
4043 ret = phy_pipe_clk_register(qmp, child); in qcom_qmp_phy_probe()
4045 dev_err(qmp->dev, in qcom_qmp_phy_probe()
4049 } else if (cfg->type == PHY_TYPE_DP) { in qcom_qmp_phy_probe()
4050 ret = phy_dp_clks_register(qmp, qmp->phys[id], child); in qcom_qmp_phy_probe()
4052 dev_err(qmp->dev, in qcom_qmp_phy_probe()
4062 dev_info(dev, "Registered Qcom-QMP phy\n"); in qcom_qmp_phy_probe()
4077 .name = "qcom-qmp-phy",
4086 MODULE_DESCRIPTION("Qualcomm QMP PHY driver");