[U-Boot] [PATCH] net: introduce MDIO DM class for MDIO devices
Alex Marginean
alexm.osslist at gmail.com
Fri May 31 16:27:09 UTC 2019
Adds UCLASS_MDIO DM class supporting MDIO buses that are probed as
stand-alone devices. Useful in particular for systems that support
DM_ETH and have a stand-alone MDIO hardware block shared by multiple
Ethernet interfaces.
Signed-off-by: Alex Marginean <alexm.osslist at gmail.com>
---
cmd/mdio.c | 5 ++
drivers/net/Kconfig | 13 +++++
include/dm/uclass-id.h | 1 +
include/miiphy.h | 50 ++++++++++++++++++++
net/Makefile | 1 +
net/mdio-uclass.c | 105 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 175 insertions(+)
create mode 100644 net/mdio-uclass.c
diff --git a/cmd/mdio.c b/cmd/mdio.c
index 5e219f699d..a6fa9266d0 100644
--- a/cmd/mdio.c
+++ b/cmd/mdio.c
@@ -203,6 +203,11 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (argc < 2)
return CMD_RET_USAGE;
+#ifdef CONFIG_DM_MDIO
+ /* probe DM MII device before any operation so they are all accesible */
+ dm_mdio_probe_devices();
+#endif
+
/*
* We use the last specified parameters, unless new ones are
* entered.
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e6a4fdf30e..6fba5a84dd 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -11,6 +11,19 @@ config DM_ETH
This is currently implemented in net/eth-uclass.c
Look in include/net.h for details.
+config DM_MDIO
+ bool "Enable Driver Model for MDIO devices"
+ depends on DM_ETH && PHYLIB
+ help
+ Enable driver model for MDIO devices
+
+ Adds UCLASS_MDIO DM class supporting MDIO buses that are probed as
+ stand-alone devices. Useful in particular for systems that support
+ DM_ETH and have a stand-alone MDIO hardware block shared by multiple
+ Ethernet interfaces.
+ This is currently implemented in net/mdio-uclass.c
+ Look in include/miiphy.h for details.
+
menuconfig NETDEVICES
bool "Network device support"
depends on NET
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 09e0ad5391..90667e62cf 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -58,6 +58,7 @@ enum uclass_id {
UCLASS_LPC, /* x86 'low pin count' interface */
UCLASS_MAILBOX, /* Mailbox controller */
UCLASS_MASS_STORAGE, /* Mass storage device */
+ UCLASS_MDIO, /* MDIO bus */
UCLASS_MISC, /* Miscellaneous device */
UCLASS_MMC, /* SD / MMC card or chip */
UCLASS_MOD_EXP, /* RSA Mod Exp device */
diff --git a/include/miiphy.h b/include/miiphy.h
index f11763affd..455feacd33 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -118,4 +118,54 @@ int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
#define ESTATUS_1000XF 0x8000
#define ESTATUS_1000XH 0x4000
+#ifdef CONFIG_DM_MDIO
+
+/**
+ * struct mii_pdata - Platform data for MDIO buses
+ *
+ * @mii_bus: Supporting MII legacy bus
+ * @priv_pdata: device specific platdata
+ */
+struct mdio_perdev_priv {
+ struct mii_dev *mii_bus;
+};
+
+/**
+ * struct mii_ops - MDIO bus operations
+ *
+ * @read: Read from a PHY register
+ * @write: Write to a PHY register
+ * @reset: Reset the MDIO bus, NULL if not supported
+ */
+struct mdio_ops {
+ int (*read)(struct udevice *mdio_dev, int addr, int devad, int reg);
+ int (*write)(struct udevice *mdio_dev, int addr, int devad, int reg,
+ u16 val);
+ int (*reset)(struct udevice *mdio_dev);
+};
+
+#define mdio_get_ops(dev) ((struct mdio_ops *)(dev)->driver->ops)
+
+/**
+ * mii_dm_probe_devices - Call probe on all MII devices, currently used for
+ * MDIO console commands.
+ */
+void dm_mdio_probe_devices(void);
+
+/**
+ * dm_mdio_phy_connect - Wrapper over phy_connect for DM MDIO
+ *
+ * @dev: mdio dev
+ * @addr: PHY address on MDIO bus
+ * @ethdev: ethernet device to connect to the PHY
+ * @interface: MAC-PHY protocol
+ *
+ * @return pointer to phy_device, or 0 on error
+ */
+struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
+ struct udevice *ethdev,
+ phy_interface_t interface);
+
+#endif
+
#endif
diff --git a/net/Makefile b/net/Makefile
index ce36362168..6251ff3991 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_NET) += eth-uclass.o
else
obj-$(CONFIG_NET) += eth_legacy.o
endif
+obj-$(CONFIG_DM_MDIO) += mdio-uclass.o
obj-$(CONFIG_NET) += eth_common.o
obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
obj-$(CONFIG_NET) += net.o
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c
new file mode 100644
index 0000000000..6ae7b4ecfd
--- /dev/null
+++ b/net/mdio-uclass.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+void dm_mdio_probe_devices(void)
+{
+ struct udevice *it;
+ struct uclass *uc;
+
+ uclass_get(UCLASS_MDIO, &uc);
+ uclass_foreach_dev(it, uc) {
+ device_probe(it);
+ }
+}
+
+static int dm_mdio_post_bind(struct udevice *dev)
+{
+ if (strchr(dev->name, ' ')) {
+ debug("\nError: MDIO device name \"%s\" has a space!\n",
+ dev->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int dm_mdio_read(struct mii_dev *mii_bus, int addr, int devad, int reg)
+{
+ struct udevice *dev = mii_bus->priv;
+
+ return mdio_get_ops(dev)->read(dev, addr, devad, reg);
+}
+
+static int dm_mdio_write(struct mii_dev *mii_bus, int addr, int devad, int reg,
+ u16 val)
+{
+ struct udevice *dev = mii_bus->priv;
+
+ return mdio_get_ops(dev)->write(dev, addr, devad, reg, val);
+}
+
+static int dm_mdio_reset(struct mii_dev *mii_bus)
+{
+ struct udevice *dev = mii_bus->priv;
+
+ if (mdio_get_ops(dev)->reset)
+ return mdio_get_ops(dev)->reset(dev);
+ else
+ return 0;
+}
+
+static int dm_mdio_post_probe(struct udevice *dev)
+{
+ struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
+
+ pdata->mii_bus = mdio_alloc();
+ pdata->mii_bus->read = dm_mdio_read;
+ pdata->mii_bus->write = dm_mdio_write;
+ pdata->mii_bus->reset = dm_mdio_reset;
+ pdata->mii_bus->priv = dev;
+ strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN);
+
+ return mdio_register(pdata->mii_bus);
+}
+
+static int dm_mdio_pre_remove(struct udevice *dev)
+{
+ struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
+ struct mdio_ops *ops = mdio_get_ops(dev);
+
+ if (ops->reset)
+ ops->reset(dev);
+ mdio_free(pdata->mii_bus);
+
+ return 0;
+}
+
+struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
+ struct udevice *ethdev,
+ phy_interface_t interface)
+{
+ struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
+
+ if (device_probe(dev))
+ return 0;
+
+ return phy_connect(pdata->mii_bus, addr, ethdev, interface);
+}
+
+UCLASS_DRIVER(mii) = {
+ .id = UCLASS_MDIO,
+ .name = "mii",
+ .post_bind = dm_mdio_post_bind,
+ .post_probe = dm_mdio_post_probe,
+ .pre_remove = dm_mdio_pre_remove,
+ .per_device_auto_alloc_size = sizeof(struct mdio_perdev_priv),
+};
--
2.17.1
More information about the U-Boot
mailing list