diff options
Diffstat (limited to 'drivers/phy/qualcomm/phy-qcom-qmp.c')
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp.c | 78 |
1 files changed, 21 insertions, 57 deletions
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index a808887ab4e2..3b01ebf76f66 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -1339,8 +1339,7 @@ static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp) return 0; } -/* PHY Initialization */ -static int qcom_qmp_phy_init(struct phy *phy) +static int qcom_qmp_phy_enable(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; @@ -1419,14 +1418,6 @@ static int qcom_qmp_phy_init(struct phy *phy) goto err_lane_rst; /* - * UFS PHY requires the deassert of software reset before serdes start. - * For UFS PHYs that do not have software reset control bits, defer - * starting serdes until the power on callback. - */ - if ((cfg->type == PHY_TYPE_UFS) && cfg->no_pcs_sw_reset) - goto out; - - /* * Pull out PHY from POWER DOWN state. * This is active low enable signal to power-down PHY. */ @@ -1437,7 +1428,9 @@ static int qcom_qmp_phy_init(struct phy *phy) usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); /* Pull PHY out of reset state */ - qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); + if (!cfg->no_pcs_sw_reset) + qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); + if (cfg->has_phy_dp_com_ctrl) qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); @@ -1454,11 +1447,10 @@ static int qcom_qmp_phy_init(struct phy *phy) goto err_pcs_ready; } qmp->phy_initialized = true; - -out: - return ret; + return 0; err_pcs_ready: + reset_control_assert(qmp->ufs_reset); clk_disable_unprepare(qphy->pipe_clk); err_clk_enable: if (cfg->has_lane_rst) @@ -1469,7 +1461,7 @@ err_lane_rst: return ret; } -static int qcom_qmp_phy_exit(struct phy *phy) +static int qcom_qmp_phy_disable(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; @@ -1497,44 +1489,6 @@ static int qcom_qmp_phy_exit(struct phy *phy) return 0; } -static int qcom_qmp_phy_poweron(struct phy *phy) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - struct qcom_qmp *qmp = qphy->qmp; - const struct qmp_phy_cfg *cfg = qmp->cfg; - void __iomem *pcs = qphy->pcs; - void __iomem *status; - unsigned int mask, val; - int ret = 0; - - if (cfg->type != PHY_TYPE_UFS) - return 0; - - /* - * For UFS PHY that has not software reset control, serdes start - * should only happen when UFS driver explicitly calls phy_power_on - * after it deasserts software reset. - */ - if (cfg->no_pcs_sw_reset && !qmp->phy_initialized && - (qmp->init_count != 0)) { - /* start SerDes and Phy-Coding-Sublayer */ - qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); - - status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; - mask = cfg->mask_pcs_ready; - - ret = readl_poll_timeout(status, val, !(val & mask), 1, - PHY_INIT_COMPLETE_TIMEOUT); - if (ret) { - dev_err(qmp->dev, "phy initialization timed-out\n"); - return ret; - } - qmp->phy_initialized = true; - } - - return ret; -} - static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) { @@ -1784,9 +1738,15 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) } static const struct phy_ops qcom_qmp_phy_gen_ops = { - .init = qcom_qmp_phy_init, - .exit = qcom_qmp_phy_exit, - .power_on = qcom_qmp_phy_poweron, + .init = qcom_qmp_phy_enable, + .exit = qcom_qmp_phy_disable, + .set_mode = qcom_qmp_phy_set_mode, + .owner = THIS_MODULE, +}; + +static const struct phy_ops qcom_qmp_ufs_ops = { + .power_on = qcom_qmp_phy_enable, + .power_off = qcom_qmp_phy_disable, .set_mode = qcom_qmp_phy_set_mode, .owner = THIS_MODULE, }; @@ -1797,6 +1757,7 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) struct qcom_qmp *qmp = dev_get_drvdata(dev); struct phy *generic_phy; struct qmp_phy *qphy; + const struct phy_ops *ops = &qcom_qmp_phy_gen_ops; char prop_name[MAX_PROP_NAME]; int ret; @@ -1883,7 +1844,10 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) } } - generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_gen_ops); + if (qmp->cfg->type == PHY_TYPE_UFS) + ops = &qcom_qmp_ufs_ops; + + generic_phy = devm_phy_create(dev, np, ops); if (IS_ERR(generic_phy)) { ret = PTR_ERR(generic_phy); dev_err(dev, "failed to create qphy %d\n", ret); |