summaryrefslogtreecommitdiff
path: root/drivers/net/ti/am65-cpsw-nuss.c
diff options
context:
space:
mode:
authorMaxime Ripard <mripard@kernel.org>2023-07-24 15:57:30 +0200
committerTom Rini <trini@konsulko.com>2023-07-27 17:10:46 -0400
commit9b33be392b30deeda242212a0a7b09adc9f91b26 (patch)
treeb3e92f15461f3bfb833dd75ac7c75ff1a57ef6ca /drivers/net/ti/am65-cpsw-nuss.c
parent67957176a258d4288740acd2a18097d5b4ecf080 (diff)
downloadu-boot-9b33be392b30deeda242212a0a7b09adc9f91b26.tar.gz
u-boot-9b33be392b30deeda242212a0a7b09adc9f91b26.tar.bz2
u-boot-9b33be392b30deeda242212a0a7b09adc9f91b26.zip
net: ti: am65-cpsw-nuss: Enforce pinctrl state on the MDIO child node
The binding represents the MDIO controller as a child device tree node of the MAC device tree node. The U-Boot driver mostly ignores that child device tree node and just hardcodes the resources it uses to support both the MAC and MDIO in a single driver. However, some resources like pinctrl muxing states are thus ignored. This has been a problem with some device trees that will put some pinctrl states on the MDIO device tree node, like the SK-AM62 Device Tree does. Let's rework the driver a bit to create a dummy MDIO driver that we will then get during our initialization to force the core to select the right muxing. Signed-off-by: Maxime Ripard <mripard@kernel.org> Reviewed-by: Siddharth Vadapalli <s-vadapalli@ti.com> Acked-by: Roger Quadros <rogerq@kernel.org> Acked-by: Nishanth Menon <nm@ti.com>
Diffstat (limited to 'drivers/net/ti/am65-cpsw-nuss.c')
-rw-r--r--drivers/net/ti/am65-cpsw-nuss.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
index 523a4c9f91..b0dd1b9bd3 100644
--- a/drivers/net/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -15,6 +15,7 @@
#include <dm.h>
#include <dm/device_compat.h>
#include <dm/lists.h>
+#include <dm/pinctrl.h>
#include <dma-uclass.h>
#include <dm/of_access.h>
#include <miiphy.h>
@@ -561,14 +562,62 @@ static const struct soc_attr k3_mdio_soc_data[] = {
{ /* sentinel */ },
};
+static ofnode am65_cpsw_find_mdio(ofnode parent)
+{
+ ofnode node;
+
+ ofnode_for_each_subnode(node, parent)
+ if (ofnode_device_is_compatible(node, "ti,cpsw-mdio"))
+ return node;
+
+ return ofnode_null();
+}
+
+static int am65_cpsw_mdio_setup(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
+ struct udevice *mdio_dev;
+ ofnode mdio;
+ int ret;
+
+ mdio = am65_cpsw_find_mdio(dev_ofnode(cpsw_common->dev));
+ if (!ofnode_valid(mdio))
+ return 0;
+
+ /*
+ * The MDIO controller is represented in the DT binding by a
+ * subnode of the MAC controller.
+ *
+ * We don't have a DM driver for the MDIO device yet, and thus any
+ * pinctrl setting on its node will be ignored.
+ *
+ * However, we do need to make sure the pins states tied to the
+ * MDIO node are configured properly. Fortunately, the core DM
+ * does that for use when we get a device, so we can work around
+ * that whole issue by just requesting a dummy MDIO driver to
+ * probe, and our pins will get muxed.
+ */
+ ret = uclass_get_device_by_ofnode(UCLASS_MDIO, mdio, &mdio_dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int am65_cpsw_mdio_init(struct udevice *dev)
{
struct am65_cpsw_priv *priv = dev_get_priv(dev);
struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
+ int ret;
if (!priv->has_phy || cpsw_common->bus)
return 0;
+ ret = am65_cpsw_mdio_setup(dev);
+ if (ret)
+ return ret;
+
cpsw_common->bus = cpsw_mdio_init(dev->name,
cpsw_common->mdio_base,
cpsw_common->bus_freq,
@@ -837,3 +886,14 @@ U_BOOT_DRIVER(am65_cpsw_nuss_port) = {
.plat_auto = sizeof(struct eth_pdata),
.flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_OS_PREPARE,
};
+
+static const struct udevice_id am65_cpsw_mdio_ids[] = {
+ { .compatible = "ti,cpsw-mdio" },
+ { }
+};
+
+U_BOOT_DRIVER(am65_cpsw_mdio) = {
+ .name = "am65_cpsw_mdio",
+ .id = UCLASS_MDIO,
+ .of_match = am65_cpsw_mdio_ids,
+};