@@ -2576,13 +2576,63 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy,
return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np);
}
-static int qmp_combo_create(struct device *dev, struct device_node *np, int id,
+static int qmp_combo_create_dp(struct device *dev, struct device_node *np, int id,
+ void __iomem *serdes, const struct qmp_phy_cfg *cfg)
+{
+ struct qcom_qmp *qmp = dev_get_drvdata(dev);
+ struct phy *generic_phy;
+ struct qmp_phy *qphy;
+ int ret;
+
+ qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
+ if (!qphy)
+ return -ENOMEM;
+
+ qphy->cfg = cfg;
+ qphy->serdes = serdes;
+ /*
+ * Get memory resources for each PHY:
+ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
+ * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
+ * For single lane PHYs: pcs_misc (optional) -> 3.
+ *
+ * Note that only tx/tx2 and pcs are used by the DP implementation.
+ */
+ qphy->tx = devm_of_iomap(dev, np, 0, NULL);
+ if (IS_ERR(qphy->tx))
+ return PTR_ERR(qphy->tx);
+
+ qphy->pcs = devm_of_iomap(dev, np, 2, NULL);
+ if (IS_ERR(qphy->pcs))
+ return PTR_ERR(qphy->pcs);
+
+ if (cfg->lanes >= 2) {
+ qphy->tx2 = devm_of_iomap(dev, np, 3, NULL);
+ if (IS_ERR(qphy->tx2))
+ return PTR_ERR(qphy->tx2);
+ }
+
+ generic_phy = devm_phy_create(dev, np, &qmp_combo_dp_phy_ops);
+ if (IS_ERR(generic_phy)) {
+ ret = PTR_ERR(generic_phy);
+ dev_err(dev, "failed to create DP PHY: %d\n", ret);
+ return ret;
+ }
+
+ qphy->phy = generic_phy;
+ qphy->qmp = qmp;
+ qmp->phys[id] = qphy;
+ phy_set_drvdata(generic_phy, qphy);
+
+ return 0;
+}
+
+static int qmp_combo_create_usb(struct device *dev, struct device_node *np, int id,
void __iomem *serdes, const struct qmp_phy_cfg *cfg)
{
struct qcom_qmp *qmp = dev_get_drvdata(dev);
struct phy *generic_phy;
struct qmp_phy *qphy;
- const struct phy_ops *ops;
int ret;
qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
@@ -2631,31 +2681,16 @@ static int qmp_combo_create(struct device *dev, struct device_node *np, int id,
qphy->pcs_misc = NULL;
}
- /*
- * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3
- * based phys, so they essentially have pipe clock. So,
- * we return error in case phy is USB3 or PIPE type.
- * Otherwise, we initialize pipe clock to NULL for
- * all phys that don't need this.
- */
qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL);
if (IS_ERR(qphy->pipe_clk)) {
- if (cfg->type == PHY_TYPE_USB3)
- return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk),
- "failed to get lane%d pipe_clk\n",
- id);
- qphy->pipe_clk = NULL;
+ return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk),
+ "failed to get lane%d pipe_clk\n", id);
}
- if (cfg->type == PHY_TYPE_DP)
- ops = &qmp_combo_dp_phy_ops;
- else
- ops = &qmp_combo_usb_phy_ops;
-
- generic_phy = devm_phy_create(dev, np, ops);
+ generic_phy = devm_phy_create(dev, np, &qmp_combo_usb_phy_ops);
if (IS_ERR(generic_phy)) {
ret = PTR_ERR(generic_phy);
- dev_err(dev, "failed to create qphy %d\n", ret);
+ dev_err(dev, "failed to create USB PHY: %d\n", ret);
return ret;
}
@@ -2752,7 +2787,7 @@ static int qmp_combo_probe(struct platform_device *pdev)
serdes = dp_serdes;
/* Create per-lane phy */
- ret = qmp_combo_create(dev, child, id, serdes, cfg);
+ ret = qmp_combo_create_dp(dev, child, id, serdes, cfg);
if (ret) {
dev_err(dev, "failed to create lane%d phy, %d\n",
id, ret);
@@ -2770,7 +2805,7 @@ static int qmp_combo_probe(struct platform_device *pdev)
serdes = usb_serdes;
/* Create per-lane phy */
- ret = qmp_combo_create(dev, child, id, serdes, cfg);
+ ret = qmp_combo_create_usb(dev, child, id, serdes, cfg);
if (ret) {
dev_err(dev, "failed to create lane%d phy, %d\n",
id, ret);