[PATCH 08/25] phy: cadence: Sierra: Add a UCLASS_PHY device for links

Aswath Govindraju a-govindraju at ti.com
Thu Jan 27 10:12:51 CET 2022


Add a driver of type UCLASS_PHY for each of the link nodes in the serdes
instance.

Signed-off-by: Aswath Govindraju <a-govindraju at ti.com>
---
 drivers/phy/cadence/phy-cadence-sierra.c | 116 +++++++++++++++--------
 1 file changed, 75 insertions(+), 41 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index 90699f2fa653..af67df6d06cb 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -203,7 +203,7 @@ struct cdns_sierra_phy {
 	size_t size;
 	struct regmap *regmap;
 	struct cdns_sierra_data *init_data;
-	struct cdns_sierra_inst phys[SIERRA_MAX_LANES];
+	struct cdns_sierra_inst *phys[SIERRA_MAX_LANES];
 	struct reset_control *phy_rst;
 	struct regmap *regmap_lane_cdb[SIERRA_MAX_LANES];
 	struct regmap *regmap_phy_config_ctrl;
@@ -242,8 +242,8 @@ static inline struct cdns_sierra_inst *phy_get_drvdata(struct phy *phy)
 		return NULL;
 
 	for (index = 0; index < sp->nsubnodes; index++) {
-		if (phy->id == sp->phys[index].mlane)
-			return &sp->phys[index];
+		if (phy->id == sp->phys[index]->mlane)
+			return sp->phys[index];
 	}
 
 	return NULL;
@@ -500,13 +500,79 @@ static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp,
 	return 0;
 }
 
+static int cdns_sierra_bind_link_nodes(struct  cdns_sierra_phy *sp)
+{
+	struct udevice *dev = sp->dev;
+	struct driver *link_drv;
+	ofnode child;
+	int rc;
+
+	link_drv = lists_driver_lookup_name("sierra_phy_link");
+	if (!link_drv) {
+		dev_err(dev, "Cannot find driver 'sierra_phy_link'\n");
+		return -ENOENT;
+	}
+
+	ofnode_for_each_subnode(child, dev_ofnode(dev)) {
+		if (!(ofnode_name_eq(child, "phy") ||
+		      ofnode_name_eq(child, "link")))
+			continue;
+
+		rc = device_bind(dev, link_drv, "link", NULL, child, NULL);
+		if (rc) {
+			dev_err(dev, "cannot bind driver for link\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+static int cdns_sierra_link_probe(struct udevice *dev)
+{
+	struct cdns_sierra_inst *inst = dev_get_priv(dev);
+	struct cdns_sierra_phy *sp = dev_get_priv(dev->parent);
+	struct reset_ctl_bulk *rst;
+	int ret, node;
+
+	rst = devm_reset_bulk_get_by_node(dev, dev_ofnode(dev));
+	if (IS_ERR(rst)) {
+		ret = PTR_ERR(rst);
+		dev_err(dev, "failed to get reset\n");
+		return ret;
+	}
+	inst->lnk_rst = rst;
+
+	ret = cdns_sierra_get_optional(inst, dev_ofnode(dev));
+	if (ret) {
+		dev_err(dev, "missing property in node\n");
+		return ret;
+	}
+	node = sp->nsubnodes;
+	sp->phys[node] = inst;
+	sp->nsubnodes += 1;
+	sp->num_lanes += inst->num_lanes;
+
+	/* If more than one subnode, configure the PHY as multilink */
+	if (!sp->autoconf && sp->nsubnodes > 1)
+		regmap_field_write(sp->phy_pll_cfg_1, 0x1);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(sierra_phy_link) = {
+	.name		= "sierra_phy_link",
+	.id		= UCLASS_PHY,
+	.probe		= cdns_sierra_link_probe,
+	.priv_auto	= sizeof(struct cdns_sierra_inst),
+};
+
 static int cdns_sierra_phy_probe(struct udevice *dev)
 {
 	struct cdns_sierra_phy *sp = dev_get_priv(dev);
 	struct cdns_sierra_data *data;
 	unsigned int id_value;
 	int ret, node = 0;
-	ofnode child;
 
 	sp->dev = dev;
 
@@ -558,46 +624,14 @@ static int cdns_sierra_phy_probe(struct udevice *dev)
 	}
 
 	sp->autoconf = dev_read_bool(dev, "cdns,autoconf");
-
-	ofnode_for_each_subnode(child, dev_ofnode(dev)) {
-		if (!(ofnode_name_eq(child, "phy") ||
-		      ofnode_name_eq(child, "link")))
-			continue;
-
-		sp->phys[node].lnk_rst = devm_reset_bulk_get_by_node(dev,
-								     child);
-		if (IS_ERR(sp->phys[node].lnk_rst)) {
-			ret = PTR_ERR(sp->phys[node].lnk_rst);
-			dev_err(dev, "failed to get reset %s\n",
-				ofnode_get_name(child));
-			goto put_child2;
-		}
-
-		if (!sp->autoconf) {
-			ret = cdns_sierra_get_optional(&sp->phys[node], child);
-			if (ret) {
-				dev_err(dev, "missing property in node %s\n",
-					ofnode_get_name(child));
-				goto put_child;
-			}
-		}
-		sp->num_lanes += sp->phys[node].num_lanes;
-
-		node++;
-	}
-	sp->nsubnodes = node;
-
-	/* If more than one subnode, configure the PHY as multilink */
-	if (!sp->autoconf && sp->nsubnodes > 1)
-		regmap_field_write(sp->phy_pll_cfg_1, 0x1);
+	/* Binding link nodes as children to serdes */
+	ret = cdns_sierra_bind_link_nodes(sp);
+	if (ret)
+		goto clk_disable;
 
 	dev_info(dev, "sierra probed\n");
 	return 0;
 
-put_child:
-	node++;
-put_child2:
-
 clk_disable:
 	clk_disable_unprepare(sp->input_clks[PHY_CLK]);
 	return ret;
@@ -615,7 +649,7 @@ static int cdns_sierra_phy_remove(struct udevice *dev)
 	 * Need to put the subnode resets here though.
 	 */
 	for (i = 0; i < phy->nsubnodes; i++)
-		reset_assert_bulk(phy->phys[i].lnk_rst);
+		reset_assert_bulk(phy->phys[i]->lnk_rst);
 
 	clk_disable_unprepare(phy->input_clks[PHY_CLK]);
 
-- 
2.17.1



More information about the U-Boot mailing list