]> Git Repo - J-u-boot.git/blobdiff - drivers/net/ftmac100.c
Subtree merge tag 'v6.11-dts' of dts repo [1] into dts/upstream
[J-u-boot.git] / drivers / net / ftmac100.c
index 7c89d7f67b8daf259938ae8a2d3b4baf1ad75a63..fa0b3dbb6d1787a93e1989b06898f1b3f4487cce 100644 (file)
@@ -7,14 +7,17 @@
  */
 
 #include <config.h>
-#include <common.h>
 #include <cpu_func.h>
 #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 +26,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;
-       phys_addr_t iobase;
+       struct ftmac100 *ftmac100;
+       struct mii_dev *bus;
 };
 
 /*
@@ -36,7 +43,7 @@ struct ftmac100_data {
  */
 static void ftmac100_reset(struct ftmac100_data *priv)
 {
-       struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
+       struct ftmac100 *ftmac100 = priv->ftmac100;
 
        debug ("%s()\n", __func__);
 
@@ -57,7 +64,7 @@ static void ftmac100_reset(struct ftmac100_data *priv)
 static void ftmac100_set_mac(struct ftmac100_data *priv ,
        const unsigned char *mac)
 {
-       struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
+       struct ftmac100 *ftmac100 = priv->ftmac100;
        unsigned int maddr = mac[0] << 8 | mac[1];
        unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
 
@@ -72,7 +79,7 @@ static void ftmac100_set_mac(struct ftmac100_data *priv ,
  */
 static void _ftmac100_halt(struct ftmac100_data *priv)
 {
-       struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
+       struct ftmac100 *ftmac100 = priv->ftmac100;
        debug ("%s()\n", __func__);
        writel (0, &ftmac100->maccr);
 }
@@ -82,7 +89,7 @@ static void _ftmac100_halt(struct ftmac100_data *priv)
  */
 static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6])
 {
-       struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
+       struct ftmac100 *ftmac100 = priv->ftmac100;
        struct ftmac100_txdes *txdes = priv->txdes;
        struct ftmac100_rxdes *rxdes = priv->rxdes;
        unsigned int maccr;
@@ -94,7 +101,6 @@ static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6])
        /* set the ethernet address */
        ftmac100_set_mac(priv, enetaddr);
 
-
        /* disable all interrupts */
 
        writel (0, &ftmac100->imr);
@@ -187,7 +193,7 @@ static int __ftmac100_recv(struct ftmac100_data *priv)
  */
 static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length)
 {
-       struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
+       struct ftmac100 *ftmac100 = priv->ftmac100;
        struct ftmac100_txdes *curr_des = priv->txdes;
        ulong start;
 
@@ -314,7 +320,7 @@ static int ftmac100_of_to_plat(struct udevice *dev)
        struct eth_pdata *pdata = dev_get_plat(dev);
        const char *mac;
        pdata->iobase = dev_read_addr(dev);
-       priv->iobase = pdata->iobase;
+       priv->ftmac100 = phys_to_virt(pdata->iobase);
        mac = dtbmacaddr(0);
        if (mac)
                memcpy(pdata->enetaddr , mac , 6);
@@ -322,10 +328,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 +454,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),
This page took 0.031319 seconds and 4 git commands to generate.