Lines Matching +full:gcc +full:- +full:sc8180x
1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/clk-provider.h>
23 #include <dt-bindings/phy/phy.h>
25 #include "phy-qcom-qmp.h"
84 * if yes, then offset gives index in the reg-layout
116 /* set of registers with offsets different per-PHY */
2766 /* struct qmp_phy_cfg - per-PHY initialization config */
2768 /* phy-type - PCIE/UFS/USB */
2773 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
2855 * struct qmp_phy - per-lane phy descriptor
2899 * struct qcom_qmp - structure holding QMP phy block attributes
2908 * @phys: array of per-lane phy descriptors
3017 "vdda-phy", "vdda-pll",
3990 if (!(t->lane_mask & lane_mask)) in qcom_qmp_phy_configure_lane()
3993 if (t->in_layout) in qcom_qmp_phy_configure_lane()
3994 writel(t->val, base + regs[t->offset]); in qcom_qmp_phy_configure_lane()
3996 writel(t->val, base + t->offset); in qcom_qmp_phy_configure_lane()
4010 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_serdes_init()
4011 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_serdes_init()
4012 void __iomem *serdes = qphy->serdes; in qcom_qmp_phy_serdes_init()
4013 const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; in qcom_qmp_phy_serdes_init()
4014 const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; in qcom_qmp_phy_serdes_init()
4015 int serdes_tbl_num = cfg->serdes_tbl_num; in qcom_qmp_phy_serdes_init()
4018 qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); in qcom_qmp_phy_serdes_init()
4019 if (cfg->serdes_tbl_sec) in qcom_qmp_phy_serdes_init()
4020 qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, in qcom_qmp_phy_serdes_init()
4021 cfg->serdes_tbl_num_sec); in qcom_qmp_phy_serdes_init()
4023 if (cfg->type == PHY_TYPE_DP) { in qcom_qmp_phy_serdes_init()
4024 switch (dp_opts->link_rate) { in qcom_qmp_phy_serdes_init()
4026 qcom_qmp_phy_configure(serdes, cfg->regs, in qcom_qmp_phy_serdes_init()
4027 cfg->serdes_tbl_rbr, in qcom_qmp_phy_serdes_init()
4028 cfg->serdes_tbl_rbr_num); in qcom_qmp_phy_serdes_init()
4031 qcom_qmp_phy_configure(serdes, cfg->regs, in qcom_qmp_phy_serdes_init()
4032 cfg->serdes_tbl_hbr, in qcom_qmp_phy_serdes_init()
4033 cfg->serdes_tbl_hbr_num); in qcom_qmp_phy_serdes_init()
4036 qcom_qmp_phy_configure(serdes, cfg->regs, in qcom_qmp_phy_serdes_init()
4037 cfg->serdes_tbl_hbr2, in qcom_qmp_phy_serdes_init()
4038 cfg->serdes_tbl_hbr2_num); in qcom_qmp_phy_serdes_init()
4041 qcom_qmp_phy_configure(serdes, cfg->regs, in qcom_qmp_phy_serdes_init()
4042 cfg->serdes_tbl_hbr3, in qcom_qmp_phy_serdes_init()
4043 cfg->serdes_tbl_hbr3_num); in qcom_qmp_phy_serdes_init()
4047 return -EINVAL; in qcom_qmp_phy_serdes_init()
4052 if (cfg->has_phy_com_ctrl) { in qcom_qmp_phy_serdes_init()
4056 qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); in qcom_qmp_phy_serdes_init()
4057 qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], in qcom_qmp_phy_serdes_init()
4060 status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; in qcom_qmp_phy_serdes_init()
4061 mask = cfg->mask_com_pcs_ready; in qcom_qmp_phy_serdes_init()
4066 dev_err(qmp->dev, in qcom_qmp_phy_serdes_init()
4067 "phy common block init timed-out\n"); in qcom_qmp_phy_serdes_init()
4079 qphy->pcs + QSERDES_DP_PHY_PD_CTL); in qcom_qmp_v3_phy_dp_aux_init()
4084 qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); in qcom_qmp_v3_phy_dp_aux_init()
4086 writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); in qcom_qmp_v3_phy_dp_aux_init()
4092 qphy->pcs + QSERDES_DP_PHY_PD_CTL); in qcom_qmp_v3_phy_dp_aux_init()
4098 qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); in qcom_qmp_v3_phy_dp_aux_init()
4100 writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); in qcom_qmp_v3_phy_dp_aux_init()
4101 writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); in qcom_qmp_v3_phy_dp_aux_init()
4102 writel(0x24, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); in qcom_qmp_v3_phy_dp_aux_init()
4103 writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); in qcom_qmp_v3_phy_dp_aux_init()
4104 writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); in qcom_qmp_v3_phy_dp_aux_init()
4105 writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); in qcom_qmp_v3_phy_dp_aux_init()
4106 writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); in qcom_qmp_v3_phy_dp_aux_init()
4107 writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); in qcom_qmp_v3_phy_dp_aux_init()
4108 writel(0xbb, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); in qcom_qmp_v3_phy_dp_aux_init()
4109 writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); in qcom_qmp_v3_phy_dp_aux_init()
4110 qphy->dp_aux_cfg = 0; in qcom_qmp_v3_phy_dp_aux_init()
4115 qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); in qcom_qmp_v3_phy_dp_aux_init()
4149 const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; in qcom_qmp_phy_configure_dp_swing()
4154 for (i = 0; i < dp_opts->lanes; i++) { in qcom_qmp_phy_configure_dp_swing()
4155 v_level = max(v_level, dp_opts->voltage[i]); in qcom_qmp_phy_configure_dp_swing()
4156 p_level = max(p_level, dp_opts->pre[i]); in qcom_qmp_phy_configure_dp_swing()
4159 if (dp_opts->link_rate <= 2700) { in qcom_qmp_phy_configure_dp_swing()
4169 return -EINVAL; in qcom_qmp_phy_configure_dp_swing()
4175 writel(voltage_swing_cfg, qphy->tx + drv_lvl_reg); in qcom_qmp_phy_configure_dp_swing()
4176 writel(pre_emphasis_cfg, qphy->tx + emp_post_reg); in qcom_qmp_phy_configure_dp_swing()
4177 writel(voltage_swing_cfg, qphy->tx2 + drv_lvl_reg); in qcom_qmp_phy_configure_dp_swing()
4178 writel(pre_emphasis_cfg, qphy->tx2 + emp_post_reg); in qcom_qmp_phy_configure_dp_swing()
4185 const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; in qcom_qmp_v3_phy_configure_dp_tx()
4193 if (dp_opts->lanes == 1) { in qcom_qmp_v3_phy_configure_dp_tx()
4201 writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); in qcom_qmp_v3_phy_configure_dp_tx()
4202 writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); in qcom_qmp_v3_phy_configure_dp_tx()
4203 writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); in qcom_qmp_v3_phy_configure_dp_tx()
4204 writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); in qcom_qmp_v3_phy_configure_dp_tx()
4217 * use type-c connector to understand orientation and lanes. in qcom_qmp_phy_configure_dp_mode()
4220 * the orientation of the type-c cable. in qcom_qmp_phy_configure_dp_mode()
4227 * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); in qcom_qmp_phy_configure_dp_mode()
4230 writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL); in qcom_qmp_phy_configure_dp_mode()
4232 writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE); in qcom_qmp_phy_configure_dp_mode()
4239 const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; in qcom_qmp_v3_phy_configure_dp_phy()
4240 const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; in qcom_qmp_v3_phy_configure_dp_phy()
4246 writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); in qcom_qmp_v3_phy_configure_dp_phy()
4247 writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); in qcom_qmp_v3_phy_configure_dp_phy()
4249 switch (dp_opts->link_rate) { in qcom_qmp_v3_phy_configure_dp_phy()
4268 return -EINVAL; in qcom_qmp_v3_phy_configure_dp_phy()
4270 writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV); in qcom_qmp_v3_phy_configure_dp_phy()
4272 clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); in qcom_qmp_v3_phy_configure_dp_phy()
4273 clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); in qcom_qmp_v3_phy_configure_dp_phy()
4275 writel(0x04, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); in qcom_qmp_v3_phy_configure_dp_phy()
4276 writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v3_phy_configure_dp_phy()
4277 writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v3_phy_configure_dp_phy()
4278 writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v3_phy_configure_dp_phy()
4279 writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v3_phy_configure_dp_phy()
4281 writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL); in qcom_qmp_v3_phy_configure_dp_phy()
4283 if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS, in qcom_qmp_v3_phy_configure_dp_phy()
4288 return -ETIMEDOUT; in qcom_qmp_v3_phy_configure_dp_phy()
4290 writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v3_phy_configure_dp_phy()
4292 if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, in qcom_qmp_v3_phy_configure_dp_phy()
4297 return -ETIMEDOUT; in qcom_qmp_v3_phy_configure_dp_phy()
4299 writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v3_phy_configure_dp_phy()
4301 writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v3_phy_configure_dp_phy()
4303 return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, in qcom_qmp_v3_phy_configure_dp_phy()
4319 qphy->dp_aux_cfg++; in qcom_qmp_v3_dp_phy_calibrate()
4320 qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); in qcom_qmp_v3_dp_phy_calibrate()
4321 val = cfg1_settings[qphy->dp_aux_cfg]; in qcom_qmp_v3_dp_phy_calibrate()
4323 writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); in qcom_qmp_v3_dp_phy_calibrate()
4332 qphy->pcs + QSERDES_DP_PHY_PD_CTL); in qcom_qmp_v4_phy_dp_aux_init()
4335 writel(0x17, qphy->serdes + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN); in qcom_qmp_v4_phy_dp_aux_init()
4337 writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); in qcom_qmp_v4_phy_dp_aux_init()
4338 writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); in qcom_qmp_v4_phy_dp_aux_init()
4339 writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); in qcom_qmp_v4_phy_dp_aux_init()
4340 writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); in qcom_qmp_v4_phy_dp_aux_init()
4341 writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); in qcom_qmp_v4_phy_dp_aux_init()
4342 writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); in qcom_qmp_v4_phy_dp_aux_init()
4343 writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); in qcom_qmp_v4_phy_dp_aux_init()
4344 writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); in qcom_qmp_v4_phy_dp_aux_init()
4345 writel(0xb7, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); in qcom_qmp_v4_phy_dp_aux_init()
4346 writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); in qcom_qmp_v4_phy_dp_aux_init()
4347 qphy->dp_aux_cfg = 0; in qcom_qmp_v4_phy_dp_aux_init()
4352 qphy->pcs + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); in qcom_qmp_v4_phy_dp_aux_init()
4358 writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); in qcom_qmp_v4_phy_configure_dp_tx()
4359 writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); in qcom_qmp_v4_phy_configure_dp_tx()
4361 writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); in qcom_qmp_v4_phy_configure_dp_tx()
4362 writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); in qcom_qmp_v4_phy_configure_dp_tx()
4371 const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; in qcom_qmp_v4_phy_configure_dp_phy()
4372 const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; in qcom_qmp_v4_phy_configure_dp_phy()
4378 writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1); in qcom_qmp_v4_phy_configure_dp_phy()
4382 writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); in qcom_qmp_v4_phy_configure_dp_phy()
4383 writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); in qcom_qmp_v4_phy_configure_dp_phy()
4385 writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); in qcom_qmp_v4_phy_configure_dp_phy()
4386 writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); in qcom_qmp_v4_phy_configure_dp_phy()
4388 switch (dp_opts->link_rate) { in qcom_qmp_v4_phy_configure_dp_phy()
4407 return -EINVAL; in qcom_qmp_v4_phy_configure_dp_phy()
4409 writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV); in qcom_qmp_v4_phy_configure_dp_phy()
4411 clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); in qcom_qmp_v4_phy_configure_dp_phy()
4412 clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); in qcom_qmp_v4_phy_configure_dp_phy()
4414 writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v4_phy_configure_dp_phy()
4415 writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v4_phy_configure_dp_phy()
4416 writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v4_phy_configure_dp_phy()
4417 writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v4_phy_configure_dp_phy()
4419 writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL); in qcom_qmp_v4_phy_configure_dp_phy()
4421 if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS, in qcom_qmp_v4_phy_configure_dp_phy()
4426 return -ETIMEDOUT; in qcom_qmp_v4_phy_configure_dp_phy()
4428 if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, in qcom_qmp_v4_phy_configure_dp_phy()
4433 return -ETIMEDOUT; in qcom_qmp_v4_phy_configure_dp_phy()
4435 if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, in qcom_qmp_v4_phy_configure_dp_phy()
4440 return -ETIMEDOUT; in qcom_qmp_v4_phy_configure_dp_phy()
4442 writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v4_phy_configure_dp_phy()
4444 if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, in qcom_qmp_v4_phy_configure_dp_phy()
4449 return -ETIMEDOUT; in qcom_qmp_v4_phy_configure_dp_phy()
4451 if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, in qcom_qmp_v4_phy_configure_dp_phy()
4456 return -ETIMEDOUT; in qcom_qmp_v4_phy_configure_dp_phy()
4463 if (dp_opts->lanes == 1) { in qcom_qmp_v4_phy_configure_dp_phy()
4468 } else if (dp_opts->lanes == 2) { in qcom_qmp_v4_phy_configure_dp_phy()
4480 writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN); in qcom_qmp_v4_phy_configure_dp_phy()
4481 writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); in qcom_qmp_v4_phy_configure_dp_phy()
4482 writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN); in qcom_qmp_v4_phy_configure_dp_phy()
4483 writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); in qcom_qmp_v4_phy_configure_dp_phy()
4485 writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v4_phy_configure_dp_phy()
4487 writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); in qcom_qmp_v4_phy_configure_dp_phy()
4489 if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, in qcom_qmp_v4_phy_configure_dp_phy()
4494 return -ETIMEDOUT; in qcom_qmp_v4_phy_configure_dp_phy()
4496 writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV); in qcom_qmp_v4_phy_configure_dp_phy()
4497 writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV); in qcom_qmp_v4_phy_configure_dp_phy()
4499 writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); in qcom_qmp_v4_phy_configure_dp_phy()
4500 writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); in qcom_qmp_v4_phy_configure_dp_phy()
4502 writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); in qcom_qmp_v4_phy_configure_dp_phy()
4503 writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); in qcom_qmp_v4_phy_configure_dp_phy()
4517 qphy->dp_aux_cfg++; in qcom_qmp_v4_dp_phy_calibrate()
4518 qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); in qcom_qmp_v4_dp_phy_calibrate()
4519 val = cfg1_settings[qphy->dp_aux_cfg]; in qcom_qmp_v4_dp_phy_calibrate()
4521 writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); in qcom_qmp_v4_dp_phy_calibrate()
4528 const struct phy_configure_opts_dp *dp_opts = &opts->dp; in qcom_qmp_dp_phy_configure()
4530 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_dp_phy_configure()
4532 memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts)); in qcom_qmp_dp_phy_configure()
4533 if (qphy->dp_opts.set_voltages) { in qcom_qmp_dp_phy_configure()
4534 cfg->configure_dp_tx(qphy); in qcom_qmp_dp_phy_configure()
4535 qphy->dp_opts.set_voltages = 0; in qcom_qmp_dp_phy_configure()
4544 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_dp_phy_calibrate()
4546 if (cfg->calibrate_dp_phy) in qcom_qmp_dp_phy_calibrate()
4547 return cfg->calibrate_dp_phy(qphy); in qcom_qmp_dp_phy_calibrate()
4554 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_com_init()
4555 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_com_init()
4556 void __iomem *serdes = qphy->serdes; in qcom_qmp_phy_com_init()
4557 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_com_init()
4558 void __iomem *dp_com = qmp->dp_com; in qcom_qmp_phy_com_init()
4561 mutex_lock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
4562 if (qmp->init_count++) { in qcom_qmp_phy_com_init()
4563 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
4568 ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); in qcom_qmp_phy_com_init()
4570 dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); in qcom_qmp_phy_com_init()
4574 for (i = 0; i < cfg->num_resets; i++) { in qcom_qmp_phy_com_init()
4575 ret = reset_control_assert(qmp->resets[i]); in qcom_qmp_phy_com_init()
4577 dev_err(qmp->dev, "%s reset assert failed\n", in qcom_qmp_phy_com_init()
4578 cfg->reset_list[i]); in qcom_qmp_phy_com_init()
4583 for (i = cfg->num_resets - 1; i >= 0; i--) { in qcom_qmp_phy_com_init()
4584 ret = reset_control_deassert(qmp->resets[i]); in qcom_qmp_phy_com_init()
4586 dev_err(qmp->dev, "%s reset deassert failed\n", in qcom_qmp_phy_com_init()
4587 qphy->cfg->reset_list[i]); in qcom_qmp_phy_com_init()
4592 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qcom_qmp_phy_com_init()
4596 if (cfg->has_phy_dp_com_ctrl) { in qcom_qmp_phy_com_init()
4604 /* Default type-c orientation, i.e CC1 */ in qcom_qmp_phy_com_init()
4619 if (cfg->has_phy_com_ctrl) { in qcom_qmp_phy_com_init()
4620 qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], in qcom_qmp_phy_com_init()
4623 if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) in qcom_qmp_phy_com_init()
4625 cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qcom_qmp_phy_com_init()
4626 cfg->pwrdn_ctrl); in qcom_qmp_phy_com_init()
4629 cfg->pwrdn_ctrl); in qcom_qmp_phy_com_init()
4632 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
4637 while (++i < cfg->num_resets) in qcom_qmp_phy_com_init()
4638 reset_control_assert(qmp->resets[i]); in qcom_qmp_phy_com_init()
4640 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qcom_qmp_phy_com_init()
4642 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
4649 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_com_exit()
4650 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_com_exit()
4651 void __iomem *serdes = qphy->serdes; in qcom_qmp_phy_com_exit()
4652 int i = cfg->num_resets; in qcom_qmp_phy_com_exit()
4654 mutex_lock(&qmp->phy_mutex); in qcom_qmp_phy_com_exit()
4655 if (--qmp->init_count) { in qcom_qmp_phy_com_exit()
4656 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_exit()
4660 reset_control_assert(qmp->ufs_reset); in qcom_qmp_phy_com_exit()
4661 if (cfg->has_phy_com_ctrl) { in qcom_qmp_phy_com_exit()
4662 qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], in qcom_qmp_phy_com_exit()
4664 qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], in qcom_qmp_phy_com_exit()
4666 qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], in qcom_qmp_phy_com_exit()
4670 while (--i >= 0) in qcom_qmp_phy_com_exit()
4671 reset_control_assert(qmp->resets[i]); in qcom_qmp_phy_com_exit()
4673 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_com_exit()
4675 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qcom_qmp_phy_com_exit()
4677 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_exit()
4685 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_init()
4686 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_init()
4688 dev_vdbg(qmp->dev, "Initializing QMP phy\n"); in qcom_qmp_phy_init()
4690 if (cfg->no_pcs_sw_reset) { in qcom_qmp_phy_init()
4696 if (!qmp->ufs_reset) { in qcom_qmp_phy_init()
4697 qmp->ufs_reset = in qcom_qmp_phy_init()
4698 devm_reset_control_get_exclusive(qmp->dev, in qcom_qmp_phy_init()
4701 if (IS_ERR(qmp->ufs_reset)) { in qcom_qmp_phy_init()
4702 ret = PTR_ERR(qmp->ufs_reset); in qcom_qmp_phy_init()
4703 dev_err(qmp->dev, in qcom_qmp_phy_init()
4707 qmp->ufs_reset = NULL; in qcom_qmp_phy_init()
4712 ret = reset_control_assert(qmp->ufs_reset); in qcom_qmp_phy_init()
4721 if (cfg->type == PHY_TYPE_DP) in qcom_qmp_phy_init()
4722 cfg->dp_aux_init(qphy); in qcom_qmp_phy_init()
4730 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_power_on()
4731 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_power_on()
4732 void __iomem *tx = qphy->tx; in qcom_qmp_phy_power_on()
4733 void __iomem *rx = qphy->rx; in qcom_qmp_phy_power_on()
4734 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_power_on()
4735 void __iomem *pcs_misc = qphy->pcs_misc; in qcom_qmp_phy_power_on()
4742 if (cfg->has_lane_rst) { in qcom_qmp_phy_power_on()
4743 ret = reset_control_deassert(qphy->lane_rst); in qcom_qmp_phy_power_on()
4745 dev_err(qmp->dev, "lane%d reset deassert failed\n", in qcom_qmp_phy_power_on()
4746 qphy->index); in qcom_qmp_phy_power_on()
4751 ret = clk_prepare_enable(qphy->pipe_clk); in qcom_qmp_phy_power_on()
4753 dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); in qcom_qmp_phy_power_on()
4758 qcom_qmp_phy_configure_lane(tx, cfg->regs, in qcom_qmp_phy_power_on()
4759 cfg->tx_tbl, cfg->tx_tbl_num, 1); in qcom_qmp_phy_power_on()
4760 if (cfg->tx_tbl_sec) in qcom_qmp_phy_power_on()
4761 qcom_qmp_phy_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, in qcom_qmp_phy_power_on()
4762 cfg->tx_tbl_num_sec, 1); in qcom_qmp_phy_power_on()
4764 /* Configuration for other LANE for USB-DP combo PHY */ in qcom_qmp_phy_power_on()
4765 if (cfg->is_dual_lane_phy) { in qcom_qmp_phy_power_on()
4766 qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, in qcom_qmp_phy_power_on()
4767 cfg->tx_tbl, cfg->tx_tbl_num, 2); in qcom_qmp_phy_power_on()
4768 if (cfg->tx_tbl_sec) in qcom_qmp_phy_power_on()
4769 qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, in qcom_qmp_phy_power_on()
4770 cfg->tx_tbl_sec, in qcom_qmp_phy_power_on()
4771 cfg->tx_tbl_num_sec, 2); in qcom_qmp_phy_power_on()
4775 if (cfg->type == PHY_TYPE_DP) in qcom_qmp_phy_power_on()
4776 cfg->configure_dp_tx(qphy); in qcom_qmp_phy_power_on()
4778 qcom_qmp_phy_configure_lane(rx, cfg->regs, in qcom_qmp_phy_power_on()
4779 cfg->rx_tbl, cfg->rx_tbl_num, 1); in qcom_qmp_phy_power_on()
4780 if (cfg->rx_tbl_sec) in qcom_qmp_phy_power_on()
4781 qcom_qmp_phy_configure_lane(rx, cfg->regs, in qcom_qmp_phy_power_on()
4782 cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); in qcom_qmp_phy_power_on()
4784 if (cfg->is_dual_lane_phy) { in qcom_qmp_phy_power_on()
4785 qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, in qcom_qmp_phy_power_on()
4786 cfg->rx_tbl, cfg->rx_tbl_num, 2); in qcom_qmp_phy_power_on()
4787 if (cfg->rx_tbl_sec) in qcom_qmp_phy_power_on()
4788 qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, in qcom_qmp_phy_power_on()
4789 cfg->rx_tbl_sec, in qcom_qmp_phy_power_on()
4790 cfg->rx_tbl_num_sec, 2); in qcom_qmp_phy_power_on()
4794 if (cfg->type == PHY_TYPE_DP) { in qcom_qmp_phy_power_on()
4795 cfg->configure_dp_phy(qphy); in qcom_qmp_phy_power_on()
4797 qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); in qcom_qmp_phy_power_on()
4798 if (cfg->pcs_tbl_sec) in qcom_qmp_phy_power_on()
4799 qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, in qcom_qmp_phy_power_on()
4800 cfg->pcs_tbl_num_sec); in qcom_qmp_phy_power_on()
4803 ret = reset_control_deassert(qmp->ufs_reset); in qcom_qmp_phy_power_on()
4807 qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, in qcom_qmp_phy_power_on()
4808 cfg->pcs_misc_tbl_num); in qcom_qmp_phy_power_on()
4809 if (cfg->pcs_misc_tbl_sec) in qcom_qmp_phy_power_on()
4810 qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, in qcom_qmp_phy_power_on()
4811 cfg->pcs_misc_tbl_num_sec); in qcom_qmp_phy_power_on()
4815 * This is active low enable signal to power-down PHY. in qcom_qmp_phy_power_on()
4817 if(cfg->type == PHY_TYPE_PCIE) in qcom_qmp_phy_power_on()
4818 qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); in qcom_qmp_phy_power_on()
4820 if (cfg->has_pwrdn_delay) in qcom_qmp_phy_power_on()
4821 usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); in qcom_qmp_phy_power_on()
4823 if (cfg->type != PHY_TYPE_DP) { in qcom_qmp_phy_power_on()
4825 if (!cfg->no_pcs_sw_reset) in qcom_qmp_phy_power_on()
4826 qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qcom_qmp_phy_power_on()
4827 /* start SerDes and Phy-Coding-Sublayer */ in qcom_qmp_phy_power_on()
4828 qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qcom_qmp_phy_power_on()
4830 if (cfg->type == PHY_TYPE_UFS) { in qcom_qmp_phy_power_on()
4831 status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; in qcom_qmp_phy_power_on()
4835 status = pcs + cfg->regs[QPHY_PCS_STATUS]; in qcom_qmp_phy_power_on()
4836 mask = cfg->phy_status; in qcom_qmp_phy_power_on()
4843 dev_err(qmp->dev, "phy initialization timed-out\n"); in qcom_qmp_phy_power_on()
4850 clk_disable_unprepare(qphy->pipe_clk); in qcom_qmp_phy_power_on()
4852 if (cfg->has_lane_rst) in qcom_qmp_phy_power_on()
4853 reset_control_assert(qphy->lane_rst); in qcom_qmp_phy_power_on()
4861 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_power_off()
4863 clk_disable_unprepare(qphy->pipe_clk); in qcom_qmp_phy_power_off()
4865 if (cfg->type == PHY_TYPE_DP) { in qcom_qmp_phy_power_off()
4867 writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); in qcom_qmp_phy_power_off()
4870 if (!cfg->no_pcs_sw_reset) in qcom_qmp_phy_power_off()
4871 qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qcom_qmp_phy_power_off()
4873 /* stop SerDes and Phy-Coding-Sublayer */ in qcom_qmp_phy_power_off()
4874 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qcom_qmp_phy_power_off()
4877 if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { in qcom_qmp_phy_power_off()
4878 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qcom_qmp_phy_power_off()
4879 cfg->pwrdn_ctrl); in qcom_qmp_phy_power_off()
4881 qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, in qcom_qmp_phy_power_off()
4882 cfg->pwrdn_ctrl); in qcom_qmp_phy_power_off()
4892 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_exit()
4894 if (cfg->has_lane_rst) in qcom_qmp_phy_exit()
4895 reset_control_assert(qphy->lane_rst); in qcom_qmp_phy_exit()
4932 qphy->mode = mode; in qcom_qmp_phy_set_mode()
4939 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_enable_autonomous_mode()
4940 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_enable_autonomous_mode()
4941 void __iomem *pcs_misc = qphy->pcs_misc; in qcom_qmp_phy_enable_autonomous_mode()
4944 if (qphy->mode == PHY_MODE_USB_HOST_SS || in qcom_qmp_phy_enable_autonomous_mode()
4945 qphy->mode == PHY_MODE_USB_DEVICE_SS) in qcom_qmp_phy_enable_autonomous_mode()
4951 qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_enable_autonomous_mode()
4953 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_enable_autonomous_mode()
4955 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qcom_qmp_phy_enable_autonomous_mode()
4959 qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); in qcom_qmp_phy_enable_autonomous_mode()
4968 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_disable_autonomous_mode()
4969 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_disable_autonomous_mode()
4970 void __iomem *pcs_misc = qphy->pcs_misc; in qcom_qmp_phy_disable_autonomous_mode()
4976 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qcom_qmp_phy_disable_autonomous_mode()
4979 qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_disable_autonomous_mode()
4981 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_disable_autonomous_mode()
4987 struct qmp_phy *qphy = qmp->phys[0]; in qcom_qmp_phy_runtime_suspend()
4988 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_runtime_suspend()
4990 dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); in qcom_qmp_phy_runtime_suspend()
4993 if (cfg->type != PHY_TYPE_USB3) in qcom_qmp_phy_runtime_suspend()
4996 if (!qmp->init_count) { in qcom_qmp_phy_runtime_suspend()
5003 clk_disable_unprepare(qphy->pipe_clk); in qcom_qmp_phy_runtime_suspend()
5004 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_runtime_suspend()
5012 struct qmp_phy *qphy = qmp->phys[0]; in qcom_qmp_phy_runtime_resume()
5013 const struct qmp_phy_cfg *cfg = qphy->cfg; in qcom_qmp_phy_runtime_resume()
5016 dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); in qcom_qmp_phy_runtime_resume()
5019 if (cfg->type != PHY_TYPE_USB3) in qcom_qmp_phy_runtime_resume()
5022 if (!qmp->init_count) { in qcom_qmp_phy_runtime_resume()
5027 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qcom_qmp_phy_runtime_resume()
5031 ret = clk_prepare_enable(qphy->pipe_clk); in qcom_qmp_phy_runtime_resume()
5034 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_runtime_resume()
5046 int num = cfg->num_vregs; in qcom_qmp_phy_vreg_init()
5049 qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); in qcom_qmp_phy_vreg_init()
5050 if (!qmp->vregs) in qcom_qmp_phy_vreg_init()
5051 return -ENOMEM; in qcom_qmp_phy_vreg_init()
5054 qmp->vregs[i].supply = cfg->vreg_list[i]; in qcom_qmp_phy_vreg_init()
5056 return devm_regulator_bulk_get(dev, num, qmp->vregs); in qcom_qmp_phy_vreg_init()
5064 qmp->resets = devm_kcalloc(dev, cfg->num_resets, in qcom_qmp_phy_reset_init()
5065 sizeof(*qmp->resets), GFP_KERNEL); in qcom_qmp_phy_reset_init()
5066 if (!qmp->resets) in qcom_qmp_phy_reset_init()
5067 return -ENOMEM; in qcom_qmp_phy_reset_init()
5069 for (i = 0; i < cfg->num_resets; i++) { in qcom_qmp_phy_reset_init()
5071 const char *name = cfg->reset_list[i]; in qcom_qmp_phy_reset_init()
5078 qmp->resets[i] = rst; in qcom_qmp_phy_reset_init()
5087 int num = cfg->num_clks; in qcom_qmp_phy_clk_init()
5090 qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); in qcom_qmp_phy_clk_init()
5091 if (!qmp->clks) in qcom_qmp_phy_clk_init()
5092 return -ENOMEM; in qcom_qmp_phy_clk_init()
5095 qmp->clks[i].id = cfg->clk_list[i]; in qcom_qmp_phy_clk_init()
5097 return devm_clk_bulk_get(dev, num, qmp->clks); in qcom_qmp_phy_clk_init()
5108 * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
5109 * controls it. The <s>_pipe_clk coming out of the GCC is requested
5111 * We register the <s>_pipe_clksrc here. The gcc driver takes care
5115 * +---------------+
5116 * | PHY block |<<---------------------------------------+
5118 * | +-------+ | +-----+ |
5119 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
5120 * clk | +-------+ | +-----+
5121 * +---------------+
5129 ret = of_property_read_string(np, "clock-output-names", &init.name); in phy_pipe_clk_register()
5131 dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); in phy_pipe_clk_register()
5135 fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); in phy_pipe_clk_register()
5137 return -ENOMEM; in phy_pipe_clk_register()
5142 fixed->fixed_rate = 125000000; in phy_pipe_clk_register()
5143 fixed->hw.init = &init; in phy_pipe_clk_register()
5145 ret = devm_clk_hw_register(qmp->dev, &fixed->hw); in phy_pipe_clk_register()
5149 ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); in phy_pipe_clk_register()
5157 ret = devm_add_action(qmp->dev, phy_clk_release_provider, np); in phy_pipe_clk_register()
5167 * +------------------------------+
5170 * | +-------------------+ |
5172 * | +---------+---------+ |
5174 * | +----------+-----------+ |
5176 * | +----------+-----------+ |
5177 * +------------------------------+
5179 * +---------<---------v------------>----------+
5181 * +--------v----------------+ |
5184 * +--------+----------------+ |
5193 * +--------<------------+-----------------+---<---+
5195 * +----v---------+ +--------v-----+ +--------v------+
5200 * +-------+------+ +-----+--------+ +--------+------+
5202 * v---->----------v-------------<------v
5204 * +----------+-----------------+
5206 * +---------+------------------+
5216 switch (req->rate) { in qcom_qmp_dp_pixel_clk_determine_rate()
5222 return -EINVAL; in qcom_qmp_dp_pixel_clk_determine_rate()
5234 qphy = dp_clks->qphy; in qcom_qmp_dp_pixel_clk_recalc_rate()
5235 dp_opts = &qphy->dp_opts; in qcom_qmp_dp_pixel_clk_recalc_rate()
5237 switch (dp_opts->link_rate) { in qcom_qmp_dp_pixel_clk_recalc_rate()
5259 switch (req->rate) { in qcom_qmp_dp_link_clk_determine_rate()
5266 return -EINVAL; in qcom_qmp_dp_link_clk_determine_rate()
5278 qphy = dp_clks->qphy; in qcom_qmp_dp_link_clk_recalc_rate()
5279 dp_opts = &qphy->dp_opts; in qcom_qmp_dp_link_clk_recalc_rate()
5281 switch (dp_opts->link_rate) { in qcom_qmp_dp_link_clk_recalc_rate()
5286 return dp_opts->link_rate * 100000; in qcom_qmp_dp_link_clk_recalc_rate()
5301 unsigned int idx = clkspec->args[0]; in qcom_qmp_dp_clks_hw_get()
5305 return ERR_PTR(-EINVAL); in qcom_qmp_dp_clks_hw_get()
5309 return &dp_clks->dp_link_hw; in qcom_qmp_dp_clks_hw_get()
5311 return &dp_clks->dp_pixel_hw; in qcom_qmp_dp_clks_hw_get()
5322 dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL); in phy_dp_clks_register()
5324 return -ENOMEM; in phy_dp_clks_register()
5326 dp_clks->qphy = qphy; in phy_dp_clks_register()
5327 qphy->dp_clks = dp_clks; in phy_dp_clks_register()
5329 snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev)); in phy_dp_clks_register()
5332 dp_clks->dp_link_hw.init = &init; in phy_dp_clks_register()
5333 ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw); in phy_dp_clks_register()
5337 snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev)); in phy_dp_clks_register()
5340 dp_clks->dp_pixel_hw.init = &init; in phy_dp_clks_register()
5341 ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw); in phy_dp_clks_register()
5353 ret = devm_add_action(qmp->dev, phy_clk_release_provider, np); in phy_dp_clks_register()
5398 return -ENOMEM; in qcom_qmp_phy_create()
5400 qphy->cfg = cfg; in qcom_qmp_phy_create()
5401 qphy->serdes = serdes; in qcom_qmp_phy_create()
5404 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. in qcom_qmp_phy_create()
5405 * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 in qcom_qmp_phy_create()
5406 * For single lane PHYs: pcs_misc (optional) -> 3. in qcom_qmp_phy_create()
5408 qphy->tx = of_iomap(np, 0); in qcom_qmp_phy_create()
5409 if (!qphy->tx) in qcom_qmp_phy_create()
5410 return -ENOMEM; in qcom_qmp_phy_create()
5412 qphy->rx = of_iomap(np, 1); in qcom_qmp_phy_create()
5413 if (!qphy->rx) in qcom_qmp_phy_create()
5414 return -ENOMEM; in qcom_qmp_phy_create()
5416 qphy->pcs = of_iomap(np, 2); in qcom_qmp_phy_create()
5417 if (!qphy->pcs) in qcom_qmp_phy_create()
5418 return -ENOMEM; in qcom_qmp_phy_create()
5421 * If this is a dual-lane PHY, then there should be registers for the in qcom_qmp_phy_create()
5426 if (cfg->is_dual_lane_phy) { in qcom_qmp_phy_create()
5427 qphy->tx2 = of_iomap(np, 3); in qcom_qmp_phy_create()
5428 qphy->rx2 = of_iomap(np, 4); in qcom_qmp_phy_create()
5429 if (!qphy->tx2 || !qphy->rx2) { in qcom_qmp_phy_create()
5434 qphy->pcs_misc = qphy->tx2; in qcom_qmp_phy_create()
5435 qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; in qcom_qmp_phy_create()
5436 qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; in qcom_qmp_phy_create()
5439 qphy->pcs_misc = of_iomap(np, 5); in qcom_qmp_phy_create()
5443 qphy->pcs_misc = of_iomap(np, 3); in qcom_qmp_phy_create()
5446 if (!qphy->pcs_misc) in qcom_qmp_phy_create()
5447 dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); in qcom_qmp_phy_create()
5457 qphy->pipe_clk = of_clk_get_by_name(np, prop_name); in qcom_qmp_phy_create()
5458 if (IS_ERR(qphy->pipe_clk)) { in qcom_qmp_phy_create()
5459 if (cfg->type == PHY_TYPE_PCIE || in qcom_qmp_phy_create()
5460 cfg->type == PHY_TYPE_USB3) { in qcom_qmp_phy_create()
5461 ret = PTR_ERR(qphy->pipe_clk); in qcom_qmp_phy_create()
5462 if (ret != -EPROBE_DEFER) in qcom_qmp_phy_create()
5468 qphy->pipe_clk = NULL; in qcom_qmp_phy_create()
5472 if (cfg->has_lane_rst) { in qcom_qmp_phy_create()
5474 qphy->lane_rst = of_reset_control_get(np, prop_name); in qcom_qmp_phy_create()
5475 if (IS_ERR(qphy->lane_rst)) { in qcom_qmp_phy_create()
5477 return PTR_ERR(qphy->lane_rst); in qcom_qmp_phy_create()
5481 if (cfg->type == PHY_TYPE_UFS || cfg->type == PHY_TYPE_PCIE) in qcom_qmp_phy_create()
5483 else if (cfg->type == PHY_TYPE_DP) in qcom_qmp_phy_create()
5495 qphy->phy = generic_phy; in qcom_qmp_phy_create()
5496 qphy->index = id; in qcom_qmp_phy_create()
5497 qphy->qmp = qmp; in qcom_qmp_phy_create()
5498 qmp->phys[id] = qphy; in qcom_qmp_phy_create()
5506 .compatible = "qcom,ipq8074-qmp-usb3-phy",
5509 .compatible = "qcom,msm8996-qmp-pcie-phy",
5512 .compatible = "qcom,msm8996-qmp-ufs-phy",
5515 .compatible = "qcom,msm8996-qmp-usb3-phy",
5518 .compatible = "qcom,msm8998-qmp-pcie-phy",
5521 .compatible = "qcom,msm8998-qmp-ufs-phy",
5524 .compatible = "qcom,ipq8074-qmp-pcie-phy",
5527 .compatible = "qcom,ipq6018-qmp-pcie-phy",
5530 .compatible = "qcom,ipq6018-qmp-usb3-phy",
5533 .compatible = "qcom,sc7180-qmp-usb3-phy",
5536 .compatible = "qcom,sc7180-qmp-usb3-dp-phy",
5539 .compatible = "qcom,sc8180x-qmp-pcie-phy",
5542 .compatible = "qcom,sc8180x-qmp-ufs-phy",
5545 .compatible = "qcom,sc8180x-qmp-usb3-phy",
5548 .compatible = "qcom,sc8180x-qmp-usb3-dp-phy",
5551 .compatible = "qcom,sdm845-qhp-pcie-phy",
5554 .compatible = "qcom,sdm845-qmp-pcie-phy",
5557 .compatible = "qcom,sdm845-qmp-usb3-phy",
5560 .compatible = "qcom,sdm845-qmp-usb3-uni-phy",
5563 .compatible = "qcom,sdm845-qmp-ufs-phy",
5566 .compatible = "qcom,msm8998-qmp-usb3-phy",
5569 .compatible = "qcom,sm6115-qmp-ufs-phy",
5572 .compatible = "qcom,sm8150-qmp-ufs-phy",
5575 .compatible = "qcom,sm8250-qmp-ufs-phy",
5578 .compatible = "qcom,sm8150-qmp-usb3-phy",
5581 .compatible = "qcom,sm8150-qmp-usb3-uni-phy",
5584 .compatible = "qcom,sm8250-qmp-usb3-phy",
5587 .compatible = "qcom,sm8250-qmp-usb3-dp-phy",
5590 .compatible = "qcom,sm8250-qmp-usb3-uni-phy",
5593 .compatible = "qcom,sm8250-qmp-gen3x1-pcie-phy",
5596 .compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy",
5599 .compatible = "qcom,sm8350-qmp-ufs-phy",
5602 .compatible = "qcom,sm8250-qmp-modem-pcie-phy",
5605 .compatible = "qcom,sdx55-qmp-pcie-phy",
5608 .compatible = "qcom,sdx55-qmp-usb3-uni-phy",
5611 .compatible = "qcom,sm8350-qmp-usb3-phy",
5614 .compatible = "qcom,sm8350-qmp-usb3-uni-phy",
5623 .compatible = "qcom,sc7180-qmp-usb3-dp-phy",
5627 .compatible = "qcom,sm8250-qmp-usb3-dp-phy",
5631 .compatible = "qcom,sc8180x-qmp-usb3-dp-phy",
5645 struct device *dev = &pdev->dev; in qcom_qmp_phy_probe()
5660 return -ENOMEM; in qcom_qmp_phy_probe()
5662 qmp->dev = dev; in qcom_qmp_phy_probe()
5672 return -EINVAL; in qcom_qmp_phy_probe()
5674 combo_cfg = match->data; in qcom_qmp_phy_probe()
5676 return -EINVAL; in qcom_qmp_phy_probe()
5678 usb_cfg = combo_cfg->usb_cfg; in qcom_qmp_phy_probe()
5688 if (combo_cfg || cfg->has_phy_dp_com_ctrl) { in qcom_qmp_phy_probe()
5689 qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); in qcom_qmp_phy_probe()
5690 if (IS_ERR(qmp->dp_com)) in qcom_qmp_phy_probe()
5691 return PTR_ERR(qmp->dp_com); in qcom_qmp_phy_probe()
5700 dp_cfg = combo_cfg->dp_cfg; in qcom_qmp_phy_probe()
5703 expected_phys = cfg->nlanes; in qcom_qmp_phy_probe()
5706 mutex_init(&qmp->phy_mutex); in qcom_qmp_phy_probe()
5718 if (ret != -EPROBE_DEFER) in qcom_qmp_phy_probe()
5724 num = of_get_available_child_count(dev->of_node); in qcom_qmp_phy_probe()
5727 return -EINVAL; in qcom_qmp_phy_probe()
5729 qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); in qcom_qmp_phy_probe()
5730 if (!qmp->phys) in qcom_qmp_phy_probe()
5731 return -ENOMEM; in qcom_qmp_phy_probe()
5742 for_each_available_child_of_node(dev->of_node, child) { in qcom_qmp_phy_probe()
5743 if (of_node_name_eq(child, "dp-phy")) { in qcom_qmp_phy_probe()
5746 } else if (of_node_name_eq(child, "usb3-phy")) { in qcom_qmp_phy_probe()
5751 /* Create per-lane phy */ in qcom_qmp_phy_probe()
5763 if (cfg->type == PHY_TYPE_USB3 || cfg->type == PHY_TYPE_PCIE) { in qcom_qmp_phy_probe()
5766 dev_err(qmp->dev, in qcom_qmp_phy_probe()
5770 } else if (cfg->type == PHY_TYPE_DP) { in qcom_qmp_phy_probe()
5771 ret = phy_dp_clks_register(qmp, qmp->phys[id], child); in qcom_qmp_phy_probe()
5773 dev_err(qmp->dev, in qcom_qmp_phy_probe()
5783 dev_info(dev, "Registered Qcom-QMP phy\n"); in qcom_qmp_phy_probe()
5798 .name = "qcom-qmp-phy",