]> git.baikalelectronics.ru Git - uboot.git/commitdiff
net: ftmac100: add mii read and write callbacks
authorSergei Antonov <saproj@gmail.com>
Fri, 3 Feb 2023 19:09:04 +0000 (22:09 +0300)
committerTom Rini <trini@konsulko.com>
Fri, 10 Feb 2023 18:41:07 +0000 (13:41 -0500)
Register mii_bus with read and write callbacks to allow the 'mii'
command to work. Use a timeout of 10 ms to wait for the R/W
operations to complete.

Signed-off-by: Sergei Antonov <saproj@gmail.com>
Reviewed-by: Rick Chen <rick@andestech.com>
Tested-by: Rick Chen <rick@andestech.com>
drivers/net/Kconfig
drivers/net/ftmac100.c
drivers/net/ftmac100.h

index 3816d05525cd7e16c2db1107fecdfea601fb74eb..ceadee98a1e8f0bd24774fe7c3980e0773525e71 100644 (file)
@@ -413,6 +413,7 @@ config FSL_FM_10GEC_REGULAR_NOTATION
 
 config FTMAC100
        bool "Ftmac100 Ethernet Support"
+       select MII
        help
          This MAC is present in Andestech SoCs.
 
index e7b9d88ea9cd36bb5009f224bf5e60d2e5f55406..fae3adc3de347dcb2f3425ee6bfe0c08f80c68cc 100644 (file)
 #include <env.h>
 #include <malloc.h>
 #include <net.h>
+#include <phy.h>
+#include <miiphy.h>
+#include <dm/device_compat.h>
 #include <asm/global_data.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 
 #include "ftmac100.h"
 #include <dm.h>
@@ -23,12 +27,16 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define ETH_ZLEN       60
 
+/* Timeout for a mdio read/write operation */
+#define FTMAC100_MDIO_TIMEOUT_USEC     10000
+
 struct ftmac100_data {
        struct ftmac100_txdes txdes[1];
        struct ftmac100_rxdes rxdes[PKTBUFSRX];
        int rx_index;
        const char *name;
        struct ftmac100 *ftmac100;
+       struct mii_dev *bus;
 };
 
 /*
@@ -322,10 +330,104 @@ static int ftmac100_of_to_plat(struct udevice *dev)
        return 0;
 }
 
+/*
+ * struct mii_bus functions
+ */
+static int ftmac100_mdio_read(struct mii_dev *bus, int addr, int devad,
+                             int reg)
+{
+       struct ftmac100_data *priv = bus->priv;
+       struct ftmac100 *ftmac100 = priv->ftmac100;
+       int phycr = FTMAC100_PHYCR_PHYAD(addr) |
+                   FTMAC100_PHYCR_REGAD(reg) |
+                   FTMAC100_PHYCR_MIIRD;
+       int ret;
+
+       writel(phycr, &ftmac100->phycr);
+
+       ret = readl_poll_timeout(&ftmac100->phycr, phycr,
+                                !(phycr & FTMAC100_PHYCR_MIIRD),
+                                FTMAC100_MDIO_TIMEOUT_USEC);
+       if (ret)
+               pr_err("%s: mdio read failed (addr=0x%x reg=0x%x)\n",
+                      bus->name, addr, reg);
+       else
+               ret = phycr & FTMAC100_PHYCR_MIIRDATA;
+
+       return ret;
+}
+
+static int ftmac100_mdio_write(struct mii_dev *bus, int addr, int devad,
+                              int reg, u16 value)
+{
+       struct ftmac100_data *priv = bus->priv;
+       struct ftmac100 *ftmac100 = priv->ftmac100;
+       int phycr = FTMAC100_PHYCR_PHYAD(addr) |
+                   FTMAC100_PHYCR_REGAD(reg) |
+                   FTMAC100_PHYCR_MIIWR;
+       int ret;
+
+       writel(value, &ftmac100->phywdata);
+       writel(phycr, &ftmac100->phycr);
+
+       ret = readl_poll_timeout(&ftmac100->phycr, phycr,
+                                !(phycr & FTMAC100_PHYCR_MIIWR),
+                                FTMAC100_MDIO_TIMEOUT_USEC);
+       if (ret)
+               pr_err("%s: mdio write failed (addr=0x%x reg=0x%x)\n",
+                      bus->name, addr, reg);
+
+       return ret;
+}
+
+static int ftmac100_mdio_init(struct udevice *dev)
+{
+       struct ftmac100_data *priv = dev_get_priv(dev);
+       struct mii_dev *bus;
+       int ret;
+
+       bus = mdio_alloc();
+       if (!bus)
+               return -ENOMEM;
+
+       bus->read  = ftmac100_mdio_read;
+       bus->write = ftmac100_mdio_write;
+       bus->priv  = priv;
+
+       ret = mdio_register_seq(bus, dev_seq(dev));
+       if (ret) {
+               mdio_free(bus);
+               return ret;
+       }
+
+       priv->bus = bus;
+
+       return 0;
+}
+
 static int ftmac100_probe(struct udevice *dev)
 {
        struct ftmac100_data *priv = dev_get_priv(dev);
        priv->name = dev->name;
+       int ret = 0;
+
+       ret = ftmac100_mdio_init(dev);
+       if (ret) {
+               dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
+               goto out;
+       }
+
+out:
+       return ret;
+}
+
+static int ftmac100_remove(struct udevice *dev)
+{
+       struct ftmac100_data *priv = dev_get_priv(dev);
+
+       mdio_unregister(priv->bus);
+       mdio_free(priv->bus);
+
        return 0;
 }
 
@@ -354,6 +456,7 @@ U_BOOT_DRIVER(ftmac100) = {
        .bind   = ftmac100_bind,
        .of_to_plat = ftmac100_of_to_plat,
        .probe  = ftmac100_probe,
+       .remove = ftmac100_remove,
        .ops    = &ftmac100_ops,
        .priv_auto      = sizeof(struct ftmac100_data),
        .plat_auto      = sizeof(struct eth_pdata),
index 75a49f628a69a0316deb0d0204bfad339d70ebaf..21d339f835bf604ff6f8243ca2a212ae4e2163e8 100644 (file)
@@ -92,6 +92,15 @@ struct ftmac100 {
 #define FTMAC100_MACCR_RX_MULTIPKT     (1 << 16)
 #define FTMAC100_MACCR_RX_BROADPKT     (1 << 17)
 
+/*
+ * PHY control register
+ */
+#define FTMAC100_PHYCR_MIIRDATA                0xffff
+#define FTMAC100_PHYCR_PHYAD(x)                (((x) & 0x1f) << 16)
+#define FTMAC100_PHYCR_REGAD(x)                (((x) & 0x1f) << 21)
+#define FTMAC100_PHYCR_MIIWR           BIT(27)
+#define FTMAC100_PHYCR_MIIRD           BIT(26)
+
 /*
  * Transmit descriptor, aligned to 16 bytes
  */