net: ftgmac100: convert to driver model
authorCédric Le Goater <clg@kaod.org>
Mon, 29 Oct 2018 06:06:31 +0000 (07:06 +0100)
committerJoe Hershberger <joe.hershberger@ni.com>
Mon, 5 Nov 2018 16:41:56 +0000 (10:41 -0600)
The driver is based on the previous one and the code is only adapted
to fit the driver model. The support for the Faraday ftgmac100
controller is the same with MAC and MDIO bus support for RGMII/RMII
modes.

Configuration is updated to enable compile again. At this stage, the
driver compiles but is not yet functional.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
drivers/net/Kconfig
drivers/net/ftgmac100.c
include/netdev.h

index 3ce46c84907668293034ba76d1955c085adbf15a..fd1c48049a9bde51d3c8df18e9a2ab2951da8ee9 100644 (file)
@@ -186,6 +186,32 @@ config FTMAC100
        help
          This MAC is present in Andestech SoCs.
 
+config FTGMAC100
+       bool "Ftgmac100 Ethernet Support"
+       depends on DM_ETH
+       select PHYLIB
+       help
+         This driver supports the Faraday's FTGMAC100 Gigabit SoC
+         Ethernet controller that can be found on Aspeed SoCs (which
+         include NCSI).
+
+         It is fully compliant with IEEE 802.3 specification for
+         10/100 Mbps Ethernet and IEEE 802.3z specification for 1000
+         Mbps Ethernet and includes Reduced Media Independent
+         Interface (RMII) and Reduced Gigabit Media Independent
+         Interface (RGMII) interfaces. It adopts an AHB bus interface
+         and integrates a link list DMA engine with direct M-Bus
+         accesses for transmitting and receiving packets. It has
+         independent TX/RX fifos, supports half and full duplex (1000
+         Mbps mode only supports full duplex), flow control for full
+         duplex and backpressure for half duplex.
+
+         The FTGMAC100 also implements IP, TCP, UDP checksum offloads
+         and supports IEEE 802.1Q VLAN tag insertion and removal. It
+         offers high-priority transmit queue for QoS and CoS
+         applications.
+
+
 config MVGBE
        bool "Marvell Orion5x/Kirkwood network interface support"
        depends on KIRKWOOD || ORION5X
index c996f5f4a16762001ac26ff92ff5e547d6e5f06f..67a7c73503c59158b9dacda0b2619436128e6d59 100644 (file)
@@ -7,15 +7,16 @@
  *
  * (C) Copyright 2010 Andes Technology
  * Macpaul Lin <macpaul@andestech.com>
+ *
+ * Copyright (C) 2018, IBM Corporation.
  */
 
-#include <config.h>
-#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
 #include <malloc.h>
 #include <net.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/dma-mapping.h>
-#include <linux/mii.h>
 
 #include "ftgmac100.h"
 
 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
 #define PKTBUFSTX      4       /* must be power of 2 */
 
+/**
+ * struct ftgmac100_data - private data for the FTGMAC100 driver
+ *
+ * @iobase: The base address of the hardware registers
+ * @txdes: The array of transmit descriptors
+ * @rxdes: The array of receive descriptors
+ * @tx_index: Transmit descriptor index in @txdes
+ * @rx_index: Receive descriptor index in @rxdes
+ * @phy_addr: The PHY interface address to use
+ */
 struct ftgmac100_data {
+       struct ftgmac100 *iobase;
+
        ulong txdes_dma;
        struct ftgmac100_txdes *txdes;
        ulong rxdes_dma;
@@ -41,10 +54,10 @@ struct ftgmac100_data {
 /*
  * struct mii_bus functions
  */
-static int ftgmac100_mdiobus_read(struct eth_device *dev, int phy_addr,
-       int regnum)
+static int ftgmac100_mdiobus_read(struct ftgmac100_data *priv, int phy_addr,
+                                 int regnum)
 {
-       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
+       struct ftgmac100 *ftgmac100 = priv->iobase;
        int phycr;
        int i;
 
@@ -76,10 +89,10 @@ static int ftgmac100_mdiobus_read(struct eth_device *dev, int phy_addr,
        return -1;
 }
 
-static int ftgmac100_mdiobus_write(struct eth_device *dev, int phy_addr,
-       int regnum, u16 value)
+static int ftgmac100_mdiobus_write(struct ftgmac100_data *priv, int phy_addr,
+                                  int regnum, u16 value)
 {
-       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
+       struct ftgmac100 *ftgmac100 = priv->iobase;
        int phycr;
        int data;
        int i;
@@ -114,9 +127,10 @@ static int ftgmac100_mdiobus_write(struct eth_device *dev, int phy_addr,
        return -1;
 }
 
-int ftgmac100_phy_read(struct eth_device *dev, int addr, int reg, u16 *value)
+int ftgmac100_phy_read(struct ftgmac100_data *priv, int addr, int reg,
+                      u16 *value)
 {
-       *value = ftgmac100_mdiobus_read(dev , addr, reg);
+       *value = ftgmac100_mdiobus_read(priv, addr, reg);
 
        if (*value == -1)
                return -1;
@@ -124,31 +138,31 @@ int ftgmac100_phy_read(struct eth_device *dev, int addr, int reg, u16 *value)
        return 0;
 }
 
-int  ftgmac100_phy_write(struct eth_device *dev, int addr, int reg, u16 value)
+int ftgmac100_phy_write(struct ftgmac100_data *priv, int addr, int reg,
+                       u16 value)
 {
-       if (ftgmac100_mdiobus_write(dev, addr, reg, value) == -1)
+       if (ftgmac100_mdiobus_write(priv, addr, reg, value) == -1)
                return -1;
 
        return 0;
 }
 
-static int ftgmac100_phy_reset(struct eth_device *dev)
+static int ftgmac100_phy_reset(struct ftgmac100_data *priv, struct udevice *dev)
 {
-       struct ftgmac100_data *priv = dev->priv;
        int i;
        u16 status, adv;
 
        adv = ADVERTISE_CSMA | ADVERTISE_ALL;
 
-       ftgmac100_phy_write(dev, priv->phy_addr, MII_ADVERTISE, adv);
+       ftgmac100_phy_write(priv, priv->phy_addr, MII_ADVERTISE, adv);
 
        printf("%s: Starting autonegotiation...\n", dev->name);
 
-       ftgmac100_phy_write(dev, priv->phy_addr,
-               MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART));
+       ftgmac100_phy_write(priv, priv->phy_addr,
+                           MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART));
 
        for (i = 0; i < 100000 / 100; i++) {
-               ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &status);
+               ftgmac100_phy_read(priv, priv->phy_addr, MII_BMSR, &status);
 
                if (status & BMSR_ANEGCOMPLETE)
                        break;
@@ -166,19 +180,17 @@ static int ftgmac100_phy_reset(struct eth_device *dev)
        return 1;
 }
 
-static int ftgmac100_phy_init(struct eth_device *dev)
+static int ftgmac100_phy_init(struct ftgmac100_data *priv, struct udevice *dev)
 {
-       struct ftgmac100_data *priv = dev->priv;
-
        int phy_addr;
        u16 phy_id, status, adv, lpa, stat_ge;
        int media, speed, duplex;
        int i;
 
        /* Check if the PHY is up to snuff... */
-       for (phy_addr = 0; phy_addr < CONFIG_PHY_MAX_ADDR; phy_addr++) {
+       for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
 
-               ftgmac100_phy_read(dev, phy_addr, MII_PHYSID1, &phy_id);
+               ftgmac100_phy_read(priv, phy_addr, MII_PHYSID1, &phy_id);
 
                /*
                 * When it is unable to found PHY,
@@ -197,15 +209,15 @@ static int ftgmac100_phy_init(struct eth_device *dev)
                return 0;
        }
 
-       ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &status);
+       ftgmac100_phy_read(priv, priv->phy_addr, MII_BMSR, &status);
 
        if (!(status & BMSR_LSTATUS)) {
                /* Try to re-negotiate if we don't have link already. */
-               ftgmac100_phy_reset(dev);
+               ftgmac100_phy_reset(priv, dev);
 
                for (i = 0; i < 100000 / 100; i++) {
-                       ftgmac100_phy_read(dev, priv->phy_addr,
-                               MII_BMSR, &status);
+                       ftgmac100_phy_read(priv, priv->phy_addr,
+                                          MII_BMSR, &status);
                        if (status & BMSR_LSTATUS)
                                break;
                        udelay(100);
@@ -235,8 +247,8 @@ static int ftgmac100_phy_init(struct eth_device *dev)
        }
 #endif
 
-       ftgmac100_phy_read(dev, priv->phy_addr, MII_ADVERTISE, &adv);
-       ftgmac100_phy_read(dev, priv->phy_addr, MII_LPA, &lpa);
+       ftgmac100_phy_read(priv, priv->phy_addr, MII_ADVERTISE, &adv);
+       ftgmac100_phy_read(priv, priv->phy_addr, MII_LPA, &lpa);
 
        media = mii_nway_result(lpa & adv);
        speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 1 : 0);
@@ -248,21 +260,19 @@ static int ftgmac100_phy_init(struct eth_device *dev)
        return 1;
 }
 
-static int ftgmac100_update_link_speed(struct eth_device *dev)
+static int ftgmac100_update_link_speed(struct ftgmac100_data *priv)
 {
-       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
-       struct ftgmac100_data *priv = dev->priv;
-
+       struct ftgmac100 *ftgmac100 = priv->iobase;
        unsigned short stat_fe;
        unsigned short stat_ge;
        unsigned int maccr;
 
 #ifdef CONFIG_FTGMAC100_EGIGA
        /* 1000 Base-T Status Register */
-       ftgmac100_phy_read(dev, priv->phy_addr, MII_STAT1000, &stat_ge);
+       ftgmac100_phy_read(priv, priv->phy_addr, MII_STAT1000, &stat_ge);
 #endif
 
-       ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &stat_fe);
+       ftgmac100_phy_read(priv, priv->phy_addr, MII_BMSR, &stat_fe);
 
        if (!(stat_fe & BMSR_LSTATUS))  /* link status up? */
                return 0;
@@ -315,9 +325,9 @@ static int ftgmac100_update_link_speed(struct eth_device *dev)
 /*
  * Reset MAC
  */
-static void ftgmac100_reset(struct eth_device *dev)
+static void ftgmac100_reset(struct ftgmac100_data *priv)
 {
-       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
+       struct ftgmac100 *ftgmac100 = priv->iobase;
 
        debug("%s()\n", __func__);
 
@@ -330,10 +340,10 @@ static void ftgmac100_reset(struct eth_device *dev)
 /*
  * Set MAC address
  */
-static void ftgmac100_set_mac(struct eth_device *dev,
-       const unsigned char *mac)
+static int ftgmac100_set_mac(struct ftgmac100_data *priv,
+                            const unsigned char *mac)
 {
-       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
+       struct ftgmac100 *ftgmac100 = priv->iobase;
        unsigned int maddr = mac[0] << 8 | mac[1];
        unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
 
@@ -341,31 +351,28 @@ static void ftgmac100_set_mac(struct eth_device *dev,
 
        writel(maddr, &ftgmac100->mac_madr);
        writel(laddr, &ftgmac100->mac_ladr);
-}
 
-static void ftgmac100_set_mac_from_env(struct eth_device *dev)
-{
-       eth_env_get_enetaddr("ethaddr", dev->enetaddr);
-
-       ftgmac100_set_mac(dev, dev->enetaddr);
+       return 0;
 }
 
 /*
  * disable transmitter, receiver
  */
-static void ftgmac100_halt(struct eth_device *dev)
+static void ftgmac100_stop(struct udevice *dev)
 {
-       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
+       struct ftgmac100_data *priv = dev_get_priv(dev);
+       struct ftgmac100 *ftgmac100 = priv->iobase;
 
        debug("%s()\n", __func__);
 
        writel(0, &ftgmac100->maccr);
 }
 
-static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
+static int ftgmac100_start(struct udevice *dev)
 {
-       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
-       struct ftgmac100_data *priv = dev->priv;
+       struct eth_pdata *plat = dev_get_platdata(dev);
+       struct ftgmac100_data *priv = dev_get_priv(dev);
+       struct ftgmac100 *ftgmac100 = priv->iobase;
        struct ftgmac100_txdes *txdes;
        struct ftgmac100_rxdes *rxdes;
        unsigned int maccr;
@@ -374,6 +381,8 @@ static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
 
        debug("%s()\n", __func__);
 
+       ftgmac100_reset(priv);
+
        if (!priv->txdes) {
                txdes = dma_alloc_coherent(
                        sizeof(*txdes) * PKTBUFSTX, &priv->txdes_dma);
@@ -395,7 +404,7 @@ static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
        rxdes = priv->rxdes;
 
        /* set the ethernet address */
-       ftgmac100_set_mac_from_env(dev);
+       ftgmac100_set_mac(priv, plat->enetaddr);
 
        /* disable all interrupts */
        writel(0, &ftgmac100->ier);
@@ -453,20 +462,34 @@ static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
 
        writel(maccr, &ftgmac100->maccr);
 
-       if (!ftgmac100_phy_init(dev)) {
-               if (!ftgmac100_update_link_speed(dev))
+       if (!ftgmac100_phy_init(priv, dev)) {
+               if (!ftgmac100_update_link_speed(priv))
                        return -1;
        }
 
        return 0;
 }
 
+static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+       struct ftgmac100_data *priv = dev_get_priv(dev);
+       struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
+
+       /* Release buffer to DMA */
+       curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
+
+       /* Move to next descriptor */
+       priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
+
+       return 0;
+}
+
 /*
  * Get a data block via Ethernet
  */
-static int ftgmac100_recv(struct eth_device *dev)
+static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
 {
-       struct ftgmac100_data *priv = dev->priv;
+       struct ftgmac100_data *priv = dev_get_priv(dev);
        struct ftgmac100_rxdes *curr_des;
        unsigned short rxlen;
 
@@ -505,10 +528,10 @@ static int ftgmac100_recv(struct eth_device *dev)
 /*
  * Send a data block via Ethernet
  */
-static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
+static int ftgmac100_send(struct udevice *dev, void *packet, int length)
 {
-       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
-       struct ftgmac100_data *priv = dev->priv;
+       struct ftgmac100_data *priv = dev_get_priv(dev);
+       struct ftgmac100 *ftgmac100 = priv->iobase;
        struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
 
        if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
@@ -540,43 +563,59 @@ static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
        return 0;
 }
 
-int ftgmac100_initialize(bd_t *bd)
+static int ftgmac100_write_hwaddr(struct udevice *dev)
 {
-       struct eth_device *dev;
-       struct ftgmac100_data *priv;
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct ftgmac100_data *priv = dev_get_priv(dev);
 
-       dev = malloc(sizeof *dev);
-       if (!dev) {
-               printf("%s(): failed to allocate dev\n", __func__);
-               goto out;
-       }
-
-       /* Transmit and receive descriptors should align to 16 bytes */
-       priv = memalign(16, sizeof(struct ftgmac100_data));
-       if (!priv) {
-               printf("%s(): failed to allocate priv\n", __func__);
-               goto free_dev;
-       }
-
-       memset(dev, 0, sizeof(*dev));
-       memset(priv, 0, sizeof(*priv));
+       return ftgmac100_set_mac(priv, pdata->enetaddr);
+}
 
-       strcpy(dev->name, "FTGMAC100");
-       dev->iobase     = CONFIG_FTGMAC100_BASE;
-       dev->init       = ftgmac100_init;
-       dev->halt       = ftgmac100_halt;
-       dev->send       = ftgmac100_send;
-       dev->recv       = ftgmac100_recv;
-       dev->priv       = priv;
+static int ftgmac100_ofdata_to_platdata(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev_get_platdata(dev);
 
-       eth_register(dev);
+       pdata->iobase = devfdt_get_addr(dev);
+       return 0;
+}
 
-       ftgmac100_reset(dev);
+static int ftgmac100_probe(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct ftgmac100_data *priv = dev_get_priv(dev);
 
-       return 1;
+       priv->iobase = (struct ftgmac100 *)pdata->iobase;
+       return 0;
+}
 
-free_dev:
-       free(dev);
-out:
+static int ftgmac100_remove(struct udevice *dev)
+{
        return 0;
 }
+
+static const struct eth_ops ftgmac100_ops = {
+       .start  = ftgmac100_start,
+       .send   = ftgmac100_send,
+       .recv   = ftgmac100_recv,
+       .stop   = ftgmac100_stop,
+       .free_pkt = ftgmac100_free_pkt,
+       .write_hwaddr = ftgmac100_write_hwaddr,
+};
+
+static const struct udevice_id ftgmac100_ids[] = {
+       { .compatible = "faraday,ftgmac100" },
+       { }
+};
+
+U_BOOT_DRIVER(ftgmac100) = {
+       .name   = "ftgmac100",
+       .id     = UCLASS_ETH,
+       .of_match = ftgmac100_ids,
+       .ofdata_to_platdata = ftgmac100_ofdata_to_platdata,
+       .probe  = ftgmac100_probe,
+       .remove = ftgmac100_remove,
+       .ops    = &ftgmac100_ops,
+       .priv_auto_alloc_size = sizeof(struct ftgmac100_data),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+};
index 55001625fb923a86868d224d4fdcb03c2cb8da56..0a1a3a2d8da25ae96a9dc538b25eb62b1ffc46bd 100644 (file)
@@ -43,7 +43,6 @@ int ethoc_initialize(u8 dev_num, int base_addr);
 int fec_initialize (bd_t *bis);
 int fecmxc_initialize(bd_t *bis);
 int fecmxc_initialize_multi(bd_t *bis, int dev_id, int phy_id, uint32_t addr);
-int ftgmac100_initialize(bd_t *bits);
 int ftmac100_initialize(bd_t *bits);
 int ftmac110_initialize(bd_t *bits);
 void gt6426x_eth_initialize(bd_t *bis);