From: John Jacques <john.jacq...@intel.com>

Removes unused code and adds the second MDIO bus
available on 6700.

Signed-off-by: John Jacques <john.jacq...@intel.com>
---
 arch/arm64/boot/dts/intel/axc6732-waco.dts |    7 +
 arch/arm64/boot/dts/intel/axc67xx.dtsi     |    4 +-
 arch/arm64/boot/dts/intel/axm56xx.dtsi     |    2 +-
 drivers/misc/Kconfig                       |    6 +
 drivers/misc/Makefile                      |    1 +
 drivers/misc/axxia-mdio.c                  |  228 ++++++
 drivers/net/ethernet/lsi/Kconfig           |   34 -
 drivers/net/ethernet/lsi/Makefile          |    2 -
 drivers/net/ethernet/lsi/lsi-femac.c       | 1198 ----------------------------
 drivers/net/ethernet/lsi/lsi-mdio.c        |  205 -----
 include/linux/axxia-mdio.h                 |   21 +
 11 files changed, 266 insertions(+), 1442 deletions(-)
 create mode 100644 drivers/misc/axxia-mdio.c
 delete mode 100644 drivers/net/ethernet/lsi/lsi-femac.c
 delete mode 100644 drivers/net/ethernet/lsi/lsi-mdio.c
 create mode 100644 include/linux/axxia-mdio.h

diff --git a/arch/arm64/boot/dts/intel/axc6732-waco.dts 
b/arch/arm64/boot/dts/intel/axc6732-waco.dts
index 056efc4..c600dbe 100644
--- a/arch/arm64/boot/dts/intel/axc6732-waco.dts
+++ b/arch/arm64/boot/dts/intel/axc6732-waco.dts
@@ -55,6 +55,13 @@
        };
 };
 
+&mdio1 {
+       status = "okay";
+       lsi,mdio-clk-offset = <0x1c>;
+       lsi,mdio-clk-period = <0xf0>;
+       max-speed = <10>;
+};
+
 &spi0 {
        status = "okay";
 
diff --git a/arch/arm64/boot/dts/intel/axc67xx.dtsi 
b/arch/arm64/boot/dts/intel/axc67xx.dtsi
index 3554dd5..f6712fb 100644
--- a/arch/arm64/boot/dts/intel/axc67xx.dtsi
+++ b/arch/arm64/boot/dts/intel/axc67xx.dtsi
@@ -120,7 +120,7 @@
                };
 
                mdio0: mdio@8080260000 {
-                       compatible = "lsi,axm-mdio";
+                       compatible = "lsi,axm-mdio", "intel,axxia-mdio0";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <0x80 0x80260000 0 0x1000>;
@@ -128,7 +128,7 @@
                };
 
                mdio1: mdio@8080270000 {
-                       compatible = "lsi,axm-mdio";
+                       compatible = "intel,axxia-mdio1";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <0x80 0x80270000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/intel/axm56xx.dtsi 
b/arch/arm64/boot/dts/intel/axm56xx.dtsi
index ff140b7..08ebbe9 100644
--- a/arch/arm64/boot/dts/intel/axm56xx.dtsi
+++ b/arch/arm64/boot/dts/intel/axm56xx.dtsi
@@ -130,7 +130,7 @@
                };
 
                mdio: mdio@8080200000 {
-                       compatible = "lsi,axm-mdio";
+                       compatible = "lsi,axm-mdio", "intel,axxia-mdio0";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <0x80 0x80200000 0 0x1000>;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c7be89f..13f8e17 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -530,6 +530,12 @@ config AXXIA_PEI
        help
         Set up the PEI controllers in Linux instead of the boot loader.
 
+config AXXIA_MDIO
+       bool "Axxia MDIO Driver"
+       depends on ARCH_AXXIA
+       help
+        Provide access to the Axxia MDIO bus.
+
 config VEXPRESS_SYSCFG
        bool "Versatile Express System Configuration driver"
        depends on VEXPRESS_CONFIG
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 00cdb96..438adf2 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_LSI_MTC)         += lsi-mtc.o
 obj-$(CONFIG_LSI_SMMON)         += lsi-smmon.o
 obj-$(CONFIG_AXXIA_OEM)         += axxia-oem.o
 obj-$(CONFIG_AXXIA_PEI)         += axxia-pei.o
+obj-$(CONFIG_AXXIA_MDIO)        += axxia-mdio.o
 obj-$(CONFIG_ECHO)             += echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)  += vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)         += cxl/
diff --git a/drivers/misc/axxia-mdio.c b/drivers/misc/axxia-mdio.c
new file mode 100644
index 0000000..acaca53
--- /dev/null
+++ b/drivers/misc/axxia-mdio.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2017 Intel <john.jacq...@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ */
+
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+
+/* MDIO Registers */
+#define MDIO_CONTROL           0x00
+#define   CONTROL_BUSY         (1<<31) /* MDIO cycle in progress (RO) */
+#define   CONTROL_NOPRE                (1<<30) /* Suppress preamble */
+#define   CONTROL_CL22         (0<<29) /* Clause-22 */
+#define   CONTROL_CL45         (1<<29) /* Clause-45 */
+#define   CONTROL_READ         (2<<27) /* Read operation */
+#define   CONTROL_WRITE                (1<<27) /* Write operation */
+#define   CONTROL_IFSEL                (1<<26) /* Interface select */
+#define   CONTROL_PHYREG(_n)   (((_n) & 0x1F) << 21)
+#define   CONTROL_PHYID(_n)    (((_n) & 0x1F) << 16)
+#define   CONTROL_DATA(_n)     (((_n) & 0xFFFF) << 0)
+#define MDIO_STATUS            0x04
+#define   STATUS_BUSY          (1<<31)
+#define   STATUS_DONE          (1<<30)
+#define MDIO_CLK_OFFSET                0x08
+#define MDIO_CLK_PERIOD                0x0c
+
+/* MDIO bus driver private data */
+struct axxia_mdio_priv {
+       void __iomem *base;
+       struct mii_bus *bus;
+};
+
+static inline void __iomem *
+bus_to_regs(struct mii_bus *bus)
+{
+       return ((struct axxia_mdio_priv *)bus->priv)->base;
+}
+
+static int
+axxia_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+       void __iomem *base = bus_to_regs(bus);
+       u32 ctrl;
+       u32 data;
+
+       /* Set the mdio_done (status) bit. */
+       writel(STATUS_DONE | readl(base + MDIO_STATUS), base + MDIO_STATUS);
+
+       /* Write the command. */
+       ctrl = (CONTROL_READ |
+               CONTROL_PHYID(mii_id) |
+               CONTROL_PHYREG(regnum));
+
+       if (regnum & MII_ADDR_C45)
+               ctrl |= CONTROL_CL45;
+
+       writel(ctrl, base + MDIO_CONTROL);
+
+       /* Wait for the mdio_done (status) bit to clear. */
+       while ((readl(base + MDIO_STATUS) & STATUS_DONE) != 0)
+               cpu_relax();
+
+       /* Wait for the mdio_busy (control) bit to clear. */
+       do {
+               data = readl(base + MDIO_CONTROL);
+       } while ((data & CONTROL_BUSY) != 0);
+
+       return data & 0xFFFF;
+}
+
+static int
+axxia_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+       void __iomem *base = bus_to_regs(bus);
+       u32 ctrl;
+
+       printk("%s:%d - base=0x%p\n", __FILE__, __LINE__, base);
+
+       /* Wait for mdio_busy (control) to be clear. */
+       while ((readl(base + MDIO_CONTROL) & CONTROL_BUSY) != 0)
+               cpu_relax();
+
+       /* Set the mdio_busy (status) bit. */
+       writel(STATUS_DONE | readl(base + MDIO_STATUS), base + MDIO_STATUS);
+
+       /* Write the command. */
+       ctrl = (CONTROL_WRITE |
+               CONTROL_PHYID(mii_id) |
+               CONTROL_PHYREG(regnum) |
+               CONTROL_DATA(value));
+
+       if (regnum & MII_ADDR_C45)
+               ctrl |= CONTROL_CL45;
+
+       writel(ctrl, base + MDIO_CONTROL);
+
+       /* Wait for the mdio_done (status) bit to clear. */
+       while ((readl(base + MDIO_STATUS) & STATUS_DONE) != 0)
+               cpu_relax();
+
+       /* Wait for the mdio_busy (control) bit to clear. */
+       while ((readl(base + MDIO_CONTROL) & CONTROL_BUSY) != 0)
+               cpu_relax();
+
+       return 0;
+}
+
+static int
+axxia_mdio_probe(struct platform_device *pdev)
+{
+       struct device_node     *np = pdev->dev.of_node;
+       struct axxia_mdio_priv *priv = NULL;
+       struct resource        *res;
+       int                     err;
+       u32                     clk_offset = 0x10;
+       u32                     clk_period = 0x2c;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+
+       if (!priv)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       if (!res)
+               return -ENODEV;
+
+       priv->bus = mdiobus_alloc();
+
+       if (!priv->bus)
+               return -ENOMEM;
+
+       priv->bus->name  = "Axxia MDIO",
+       priv->bus->read  = axxia_mdio_read,
+       priv->bus->write = axxia_mdio_write,
+       priv->bus->priv  = priv;
+       snprintf(priv->bus->id, MII_BUS_ID_SIZE, pdev->name);
+       printk("%s:%d - pdev->name=%s\n", __FILE__, __LINE__, pdev->name);
+
+       priv->base = devm_ioremap_resource(&pdev->dev, res);
+
+       if (!priv->base) {
+               dev_err(&pdev->dev, "Failed to map registers\n");
+               err = -ENODEV;
+               goto err_ret;
+       }
+
+       priv->bus->parent = &pdev->dev;
+       dev_set_drvdata(&pdev->dev, priv->bus);
+
+       of_property_read_u32(np, "lsi,mdio-clk-offset", &clk_offset);
+       of_property_read_u32(np, "lsi,mdio-clk-period", &clk_period);
+
+       writel(clk_offset, priv->base + MDIO_CLK_OFFSET);
+       writel(clk_period, priv->base + MDIO_CLK_PERIOD);
+       writel(0, priv->base + MDIO_CONTROL);
+
+       err = of_mdiobus_register(priv->bus, np);
+
+       if (err) {
+               dev_err(&pdev->dev, "Failed to register MDIO bus\n");
+               goto err_ret;
+       }
+
+       return 0;
+
+err_ret:
+
+       if (priv && priv->bus)
+               kfree(priv->bus);
+
+       return err;
+}
+
+static int
+axxia_mdio_remove(struct platform_device *pdev)
+{
+       struct mii_bus *bus = dev_get_drvdata(&pdev->dev);
+
+       mdiobus_unregister(bus);
+       dev_set_drvdata(&pdev->dev, NULL);
+       mdiobus_free(bus);
+
+       return 0;
+}
+
+static struct of_device_id axxia_mdio_match[] = {
+       { .compatible = "lsi,axm-mdio", },
+       { .compatible = "intel,axxia-mdio0", },
+       { .compatible = "intel,axxia-mdio1", },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, axxia_mdio_match);
+
+static struct platform_driver axxia_mdio_driver = {
+       .driver = {
+               .name           = "axxia-mdio",
+               .owner          = THIS_MODULE,
+               .of_match_table = axxia_mdio_match,
+       },
+       .probe  = axxia_mdio_probe,
+       .remove = axxia_mdio_remove,
+};
+
+module_platform_driver(axxia_mdio_driver);
+
+MODULE_AUTHOR("John Jacques");
+MODULE_DESCRIPTION("Axxia MDIO Bus Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/lsi/Kconfig b/drivers/net/ethernet/lsi/Kconfig
index 408e643..a78867d 100644
--- a/drivers/net/ethernet/lsi/Kconfig
+++ b/drivers/net/ethernet/lsi/Kconfig
@@ -1,37 +1,3 @@
-config NET_VENDOR_LSI
-       bool "LSI AXM55xx Ethernet support"
-       select MII
-       select PHYLIB
-       default y if ARCH_AXXIA
-       ---help---
-       If you have a network interface driver for LSI AXXIA series, say Y
-
-       Note that the answer to this question doesn't directly affect the
-       kernel: saying N will just cause the configurator to skip all
-       the questions about LSI devices. If you say Y, you will be
-       asked for your specific card in the following questions.
-
-if NET_VENDOR_LSI
-
-config NET_LSI_MDIO
-       bool "LSI AXM55xx MDIO bus driver"
-       default y
-       ---help---
-         The MDIO controller in AXM55xx devices.
-
-         If your board uses an external PHY connected to FEMAC, say Y.
-
-config NET_LSI_FEMAC
-       tristate "LSI FEMAC Ethernet controller"
-       select LSI_MDIO
-       default y
-       ---help---
-         Say Y here if you want to use the built-in 10/100 Fast ethernet
-         controller (FEMAC) on the AXM55xx devices.
-
-endif # NET_VENDOR_LSI
-
-
 config LSI_NET
        bool "LSI ACP34XX Ethernet support"
        select MII
diff --git a/drivers/net/ethernet/lsi/Makefile 
b/drivers/net/ethernet/lsi/Makefile
index 5ebc246..a48a239 100644
--- a/drivers/net/ethernet/lsi/Makefile
+++ b/drivers/net/ethernet/lsi/Makefile
@@ -1,6 +1,4 @@
 # Makefile for the LSI FEMAC network interface.
 
-obj-$(CONFIG_NET_LSI_MDIO) += lsi-mdio.o
-obj-$(CONFIG_NET_LSI_FEMAC) += lsi-femac.o
 obj-$(CONFIG_LSI_NET) += lsi_acp_mdio.o
 obj-$(CONFIG_LSI_NET) += lsi_acp_net.o
diff --git a/drivers/net/ethernet/lsi/lsi-femac.c 
b/drivers/net/ethernet/lsi/lsi-femac.c
deleted file mode 100644
index 734ea03..0000000
--- a/drivers/net/ethernet/lsi/lsi-femac.c
+++ /dev/null
@@ -1,1198 +0,0 @@
-/* drivers/net/ethernet/lsi/lsi-femac.c
- *
- * Network device driver for LSI Fast-Ethernet controller (FEMAC).
- *
- * Copyright (C) 2013 LSI
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/version.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_mdio.h>
-#include <linux/dmapool.h>
-
-#define DRVNAME          "lsi-femac"
-#define DESCRIPTOR_GRANULARITY   64
-#define MAX_FRAME_SIZE         1600
-#define NAPI_WEIGHT              64
-
-static unsigned char macaddr[ETH_ALEN];
-module_param_array(macaddr, byte, NULL, S_IRUSR);
-MODULE_PARM_DESC(macaddr, "Ethernet address");
-
-static int rx_num_desc = 128; /* Must be multiple of DESCRIPTOR_GRANULARITY */
-module_param(rx_num_desc, int, S_IRUSR);
-MODULE_PARM_DESC(rx_num_desc, "Number of receive descriptors");
-
-static int tx_num_desc = 128; /* Must be multiple of DESCRIPTOR_GRANULARITY */
-module_param(tx_num_desc, int, S_IRUSR);
-MODULE_PARM_DESC(tx_num_desc, "Number of transmit descriptors");
-
-/**
- * struct dma_desc - Hardware DMA descriptor
- */
-struct dma_desc {
-       __le32 flags;
-#define DMADESC_FILL    (0 << 0)
-#define DMADESC_BLOCK   (1 << 0)
-#define DMADESC_SCATTER (2 << 0)
-#define DMADESC_READ    (0 << 2)
-#define DMADESC_WRITE   (1 << 2)
-#define DMADESC_SOP     (1 << 3)
-#define DMADESC_EOP     (1 << 4)
-#define DMADESC_INTR    (1 << 5)
-#define DMADESC_ERROR   (1 << 6)
-#define DMADESC_SWAP    (1 << 7)
-       __le16 pdu_len;
-       __le16 buf_len;
-       __le32 cookie;
-       __le32 buf_ptr;
-};
-
-/**
- * struct queue_ptr - Holds the state of the RX or TX queue
- * @hw_tail: Tail pointer (written by hardware, pointer to this field is
- *           programmed into the DMAREG_(RX|TX)_TAIL_ADDR). Points to the next
- *           descriptor to be used for reception or transmission.
- * @tail:    Driver tail pointer. Follows hw_tail and points to next descriptor
- *           to be completed.
- * @head:    Head pointer where the drivers puts the new buffers queued for
- *           transmission, and the where fresh RX buffers are added.
- * @size:    Size in bytes of the descriptor ring.
- * @phys:    Physical address of descriptor ring.
- */
-struct queue_ptr {
-       __le32      hw_tail;
-       u32         tail;
-       u32         head;
-       size_t      size;
-       dma_addr_t  phys;
-};
-
-struct dbg_counters {
-       unsigned long tx_interrupt;
-       unsigned long rx_interrupt;
-       unsigned long tx_nodesc;
-       unsigned long tx_nobuf;
-};
-
-#define DBG_INC(_priv, _member) (++(_priv)->counters._member)
-
-/* Device private data */
-struct femac_dev {
-       struct net_device      *ndev;
-       struct device          *dev;
-       struct napi_struct      napi;
-       void __iomem            *base;
-       /* MAC address (from parameter, device-tree or randomized) */
-       unsigned char           mac_addr[ETH_ALEN] __aligned(2);
-       /* PHY */
-       struct phy_device       *phy_dev;
-       int                     link;
-       int                     speed;
-       int                     duplex;
-       /* RX/TX ring */
-       size_t                  rx_ring_size;
-       dma_addr_t              rx_ring_phys;
-       unsigned                rx_num_desc;
-       struct dma_desc         *rx_ring;
-       struct queue_ptr       *rxq;
-       /* TX ring */
-       size_t                  tx_ring_size;
-       dma_addr_t              tx_ring_phys;
-       unsigned                tx_num_desc;
-       struct dma_desc         *tx_ring;
-       struct queue_ptr       *txq;
-       /* Lock protecting the TX ring */
-       spinlock_t              lock;
-       /* DMA pool for tx buffers */
-       struct dma_pool        *tx_pool;
-       /* Debug counters */
-       struct dbg_counters     counters;
-};
-
-#define napi_to_priv(_napi) container_of(napi, struct femac_dev, napi)
-
-/* FEMAC Registers
- */
-
-/* SMII Status */
-#define RXREG_SMII_STATUS              0x0010
-#define   RX_SMII_STATUS_SPEED         0x01
-#define   RX_SMII_STATUS_DUPLEX                0x02
-#define   RX_SMII_STATUS_LINK          0x04
-#define   RX_SMII_STATUS_JABBER                0x08
-#define   RX_SMII_STATUS_FCD           0x10 /* False Carrier Detect */
-/* Receive Configuration */
-#define RXREG_CONF                     0x004c
-#define   RX_CONF_ENABLE               0x0001
-#define   RX_CONF_PAP                  0x0002 /* Pass Any Packet */
-#define   RX_CONF_JUMBO9K              0x0008
-#define   RX_CONF_STRIPCRC             0x0010
-#define   RX_CONF_AMT                  0x0020 /* Accept All MAC Types */
-#define   RX_CONF_AFC                  0x0040 /* Accept Flow Control */
-#define   RX_CONF_VLAN                 0x0200 /* Enable VLAN */
-#define   RX_CONF_SPEED                        0x0800 /* RX MAC Speed, 0=10M, 
1=100M */
-#define   RX_CONF_DUPLEX               0x1000 /* 1=Full-duplex */
-#define   RX_CONF_LINK                 0x2000 /* 1=Enable */
-#define   RX_CONF_RXFCE                        0x4000 /* RX flow-control */
-#define   RX_CONF_TXFCE                        0x8000 /* TX flow-control */
-/* Receive Statistics */
-#define RXREG_STAT_OVERFLOW            0x0278
-#define RXREG_STAT_UNDERSIZE           0x00280
-#define RXREG_STAT_OVERSIZE            0x002b8
-#define RXREG_STAT_PACKET_OK           0x002c0
-#define RXREG_STAT_CRC_ERR             0x002c8
-#define RXREG_STAT_MULTICAST           0x002d0
-#define RXREG_STAT_BROADCAST           0x002d8
-#define RXREG_STAT_MACTYPE             0x002e0
-#define RXREG_STAT_ALIGN_ERR           0x002e8
-#define RXREG_STAT_BYTES_LO            0x002f0
-#define RXREG_STAT_BYTES_HI            0x002f8
-/* Receive Ethernet Mode */
-#define RXREG_MODE                     0x0800
-#define   RX_MODE_ETHERNET_ENABLE      0x01
-/* Receive Soft Reset */
-#define RXREG_SOFT_RESET               0x0808
-#define   RX_SOFT_RESET_MAC_0          0x01
-/* Transmit Watermark */
-#define TXREG_WATERMARK                        0x1018
-#define   TX_WATERMARK_DTPA_ASSERT     0x8000
-#define   TX_WATERMARK_DTPA_DISABLE    0x4000
-#define   TX_WATERMARK_DTPA_HIGH(_x)   (((_x) & 0x7f) << 7)
-#define   TX_WATERMARK_DTPA_LOW(_x)    (((_x) & 0x7f) << 0)
-/* Swap Source Address Registers */
-#define TXREG_SOURCE_ADDRESS_2         0x1020
-#define TXREG_SOURCE_ADDRESS_1         0x1024
-#define TXREG_SOURCE_ADDRESS_0         0x1028
-/* Transmit Extended Configuration */
-#define TXREG_EXTENDED_CONF            0x1030
-#define   TX_EXTCONF_TXCOLL_WATERMARK  0xe000
-#define   TX_EXTCONF_EX_DEFFERED_DROP  0x0200
-#define   TX_EXTCONF_JUMBO9K           0x0100
-#define   TX_EXTCONF_LATE_COLL_WDW     0x00ff
-/* Transmit Configuration */
-#define TXREG_CONF                     0x1050
-#define   TX_CONF_ENABLE_SWAP_SA       0x8000
-#define   TX_CONF_LINK                 0x2000
-#define   TX_CONF_DUPLEX               0x1000
-#define   TX_CONF_SPEED                        0x0800
-#define   TX_CONF_XBK_RST_RX_NTX       0x0600
-#define   TX_CONF_IFG_MASK             0x01f0
-#define   TX_CONF_IFG(_x)              (((_x) & 0x1f) << 4)
-#define   TX_CONF_APP_CRC_ENABLE       0x0004
-#define   TX_CONF_PAD_ENABLE           0x0002
-#define   TX_CONF_ENABLE               0x0001
-/* Transmit Statistics */
-#define TXREG_STAT_UNDERRUN            0x1300
-#define TXREG_STAT_DEFERRED            0x1308
-#define TXREG_STAT_PAUSE               0x1310
-#define TXREG_STAT_PACKET_OK           0x1318
-#define TXREG_STAT_UNDERSIZE           0x1350
-#define TXREG_STAT_BYTES_LO            0x1358
-#define TXREG_STAT_BYTES_HI            0x1360
-#define TXREG_STAT_LATECOLL            0x1368
-#define TXREG_STAT_EXCECOLL            0x1370
-#define TXREG_STAT_EXCEDEFERRED                0x1378
-#define TXREG_STAT_COLLISION_LIMIT     0x1380
-/* Transmit Mode */
-#define TXREG_MODE                     0x1800
-#define   TX_MODE_ETHERNET_ENABLE      0x01
-/* Transmit Soft Reset */
-#define TXREG_SOFT_RESET               0x1808
-#define   TX_SOFT_RESET_MAC_0          0x01
-/* DMA Control */
-#define DMAREG_CONTROL                 0x2000
-#define   DMA_CTRL_RST                 0x80000000
-#define   DMA_CTRL_ERR_CLEAR           0x40000000
-#define   DMA_CTRL_ENABLE              0x00010000
-/* DMA Enable */
-#define DMAREG_ENABLE                  0x2008
-#define   DMA_TX_ENABLE                        0x00010000
-#define   DMA_RX_ENABLE                        0x00020000
-/* DMA Interrupt Enable/Status */
-#define DMAREG_INT_STATUS              0x2018
-#define DMAREG_INT_ENABLE              0x201c
-#define   DMA_INT_TX                   0x01
-#define   DMA_INT_RX                   0x02
-/* DMA RX/TX Queue Base/Size */
-#define DMAREG_RX_QUEUE_BASE           0x2030
-#define DMAREG_RX_QUEUE_SIZE           0x2034
-#define DMAREG_TX_QUEUE_BASE           0x2038
-#define DMAREG_TX_QUEUE_SIZE           0x203c
-/* DMA Tail Pointer Address */
-#define DMAREG_RX_TAIL_ADDR            0x2048
-#define DMAREG_TX_TAIL_ADDR            0x204c
-/* DMA Head/Tail Pointers */
-#define DMAREG_RX_HEAD                 0x2050
-#define DMAREG_RX_TAIL                 0x2054
-#define DMAREG_TX_HEAD                 0x2058
-#define DMAREG_TX_TAIL                 0x205c
-#define   DMA_POINTER_GEN              0x100000
-#define   DMA_POINTER_MASK             0x0fffff
-#define DMAREG_DTPA_LOW                        0x2060
-#define   DTPA_LOW_MARK(_x)            (((_x) & 0x1ff) << 0)
-#define   DTPA_BP_COUNT(_x)            (((_x) & 0xff) << 16)
-#define DMAREG_DTPA_HIGH               0x2064
-#define   DTPA_HIGH_MARK(_x)           (((_x) & 0x1ff) << 0)
-#define   DTPA_START_THRES(_x)         (((_x) & 0x3) << 16)
-
-#define dmaptr_idx(_val) (((_val) & DMA_POINTER_MASK) / sizeof(struct 
dma_desc))
-#define dmaptr_gen(_val) (!!((_val) & DMA_POINTER_GEN))
-
-/* RX/TX-ring
- *
- * tail - Oldest descriptor, i.e. the next descriptor to be processed by RX/TX
- * interrupt. This pointer is only used by the driver (no corresponding
- * hardware register). The interrupt handler will process descriptors from tail
- * to hw_tail.
- *
- * hw_tail - Next descriptor to be processed by hardware. The memory location
- * is updated by the hardware when it switches descriptor (via DMA). A copy of
- * this value is also available in the DMAREG_[RX|TX]_TAIL register.
- *
- * head - Newest descriptor. This is where the driver adds new descriptors
- * (either fresh rx buffers or tx buffers queued for transmission) and the
- * pointer is updated in hardware via the DMAREG_[RX|TX]_HEAD register. The
- * hardware will process descriptors from hw_tail to head. When hw_tail ==
- * head, the ring is empty.
- *
- *             tail    hw_tail         head
- *             |       |               |
- *             V       V               V
- *      +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
- *      |     | |     | |     | |     | |     | |     |
- *      +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
- *
- */
-
-/**
- * queue_get_head - Return next DMA descriptor from head of queue.
- */
-static inline struct dma_desc *
-queue_get_head(struct dma_desc *ring, const struct queue_ptr *q)
-{
-       if ((q->head ^ q->tail) == DMA_POINTER_GEN)
-               return NULL;
-       return &ring[dmaptr_idx(q->head)];
-}
-
-/**
- * queue_get_tail - Return next DMA descriptor from tail of queue.
- */
-static inline struct dma_desc *
-queue_get_tail(struct dma_desc *ring, const struct queue_ptr *q)
-{
-       if (q->tail == le32_to_cpu(q->hw_tail))
-               return NULL;
-       return &ring[dmaptr_idx(q->tail)];
-}
-
-/**
- * inc_pointer - Helper function to increment a DMA pointer. The counter is in
- * the lower bits and is incremented modulo the size of the ring. The bit
- * DMA_POINTER_GEN is toggled when the counter wraps.
- */
-static inline u32
-inc_pointer(u32 ptr, u32 size)
-{
-       u32 newptr = (ptr & DMA_POINTER_MASK) + sizeof(struct dma_desc);
-
-       /* When counter wraps (on size), reset and toggle generation bit.
-        * Otherwise preserve generation bit
-        */
-       if (newptr >= size)
-               newptr = (ptr & DMA_POINTER_GEN) ^ DMA_POINTER_GEN;
-       else
-               newptr |= ptr & DMA_POINTER_GEN;
-
-       return newptr;
-}
-
-static inline u32
-queue_inc_head(struct queue_ptr *q)
-{
-       q->head = inc_pointer(q->head, q->size);
-       return q->head;
-}
-
-static inline u32
-queue_inc_tail(struct queue_ptr *q)
-{
-       q->tail = inc_pointer(q->tail, q->size);
-       return q->tail;
-}
-
-static inline void
-pr_queue(const char *tag, const struct queue_ptr *q)
-{
-       pr_debug("%s tail=%d.%d hw_tail=%d.%d head=%d.%d\n",
-                tag,
-                dmaptr_gen(q->tail), dmaptr_idx(q->tail),
-                dmaptr_gen(q->hw_tail), dmaptr_idx(q->hw_tail),
-                dmaptr_gen(q->head), dmaptr_idx(q->head));
-}
-
-/**
- * clear_statistics - Counters are cleared on read.
- */
-static void
-clear_statistics(const struct femac_dev *priv)
-{
-       int waste;
-
-       waste = readl(priv->base + RXREG_STAT_OVERFLOW);
-       waste = readl(priv->base + RXREG_STAT_UNDERSIZE);
-       waste = readl(priv->base + RXREG_STAT_OVERSIZE);
-       waste = readl(priv->base + RXREG_STAT_PACKET_OK);
-       waste = readl(priv->base + RXREG_STAT_CRC_ERR);
-       waste = readl(priv->base + RXREG_STAT_MULTICAST);
-       waste = readl(priv->base + RXREG_STAT_BROADCAST);
-       waste = readl(priv->base + RXREG_STAT_MACTYPE);
-       waste = readl(priv->base + RXREG_STAT_ALIGN_ERR);
-       waste = readl(priv->base + RXREG_STAT_BYTES_LO);
-       waste = readl(priv->base + RXREG_STAT_BYTES_HI);
-
-       waste = readl(priv->base + TXREG_STAT_UNDERRUN);
-       waste = readl(priv->base + TXREG_STAT_DEFERRED);
-       waste = readl(priv->base + TXREG_STAT_PAUSE);
-       waste = readl(priv->base + TXREG_STAT_PACKET_OK);
-       waste = readl(priv->base + TXREG_STAT_UNDERSIZE);
-       waste = readl(priv->base + TXREG_STAT_BYTES_LO);
-       waste = readl(priv->base + TXREG_STAT_BYTES_HI);
-       waste = readl(priv->base + TXREG_STAT_LATECOLL);
-       waste = readl(priv->base + TXREG_STAT_EXCECOLL);
-       waste = readl(priv->base + TXREG_STAT_EXCEDEFERRED);
-       waste = readl(priv->base + TXREG_STAT_COLLISION_LIMIT);
-}
-
-static int
-enable_rx_tx(struct net_device *device)
-{
-       struct femac_dev *priv = netdev_priv(device);
-       unsigned long rxcfg;
-       unsigned long txcfg;
-
-       rxcfg = (RX_CONF_STRIPCRC |
-                RX_CONF_RXFCE    |
-                RX_CONF_TXFCE);
-
-       txcfg = (TX_CONF_ENABLE_SWAP_SA |
-                TX_CONF_APP_CRC_ENABLE |
-                TX_CONF_IFG(0xf)       |
-                TX_CONF_PAD_ENABLE);
-
-       /* Setup the receive and transmit configuration registers according to
-        * status from PHY.
-        */
-       if (priv->phy_dev->speed == SPEED_100) {
-               rxcfg |= RX_CONF_SPEED;
-               txcfg |= TX_CONF_SPEED;
-       }
-       if (priv->phy_dev->duplex == DUPLEX_FULL) {
-               rxcfg |= RX_CONF_DUPLEX;
-               txcfg |= TX_CONF_DUPLEX;
-       }
-       if (priv->phy_dev->link) {
-               rxcfg |= (RX_CONF_ENABLE | RX_CONF_LINK);
-               txcfg |= (TX_CONF_LINK | TX_CONF_ENABLE);
-       }
-
-       writel(rxcfg, priv->base + RXREG_CONF);
-       writel(txcfg, priv->base + TXREG_CONF);
-
-       if (priv->phy_dev->link) {
-               netif_start_queue(device);
-               netif_carrier_on(device);
-       } else {
-               netif_carrier_off(device);
-               netif_stop_queue(device);
-       }
-
-       return 0;
-}
-
-static void
-disable_rx_tx(struct femac_dev *priv)
-{
-       unsigned long txcfg;
-       unsigned long rxcfg;
-
-       rxcfg = readl(priv->base + RXREG_CONF);
-       rxcfg &= ~RX_CONF_ENABLE;
-       writel(rxcfg, priv->base + RXREG_CONF);
-
-       txcfg = readl(priv->base + TXREG_CONF);
-       txcfg &= ~TX_CONF_ENABLE;
-       writel(txcfg, priv->base + TXREG_CONF);
-}
-
-static ssize_t
-femac_show_counters(struct device *dev,
-                   struct device_attribute *attr,
-                   char *buf)
-{
-       struct net_device *ndev = container_of(dev, struct net_device, dev);
-       struct femac_dev *priv = netdev_priv(ndev);
-       ssize_t n = 0;
-
-       n += snprintf(&buf[n], PAGE_SIZE,
-                       "tx_interrupt: %lu\n"
-                       "rx_interrupt: %lu\n"
-                       "tx_nodesc: %lu\n"
-                       "tx_nobuf: %lu\n",
-                       priv->counters.tx_interrupt,
-                       priv->counters.rx_interrupt,
-                       priv->counters.tx_nodesc,
-                       priv->counters.tx_nobuf);
-
-       n += snprintf(&buf[n], PAGE_SIZE,
-                     "rx_queue: %u.%u / %u.%u / %u.%u\n",
-                     dmaptr_gen(priv->rxq->tail),
-                     dmaptr_idx(priv->rxq->tail),
-                     dmaptr_gen(le32_to_cpu(priv->rxq->hw_tail)),
-                     dmaptr_idx(le32_to_cpu(priv->rxq->hw_tail)),
-                     dmaptr_gen(priv->rxq->head),
-                     dmaptr_idx(priv->rxq->head));
-
-       n += snprintf(&buf[n], PAGE_SIZE,
-                     "tx_queue: %u.%u / %u.%u / %u.%u\n",
-                     dmaptr_gen(priv->txq->tail),
-                     dmaptr_idx(priv->txq->tail),
-                     dmaptr_gen(le32_to_cpu(priv->txq->hw_tail)),
-                     dmaptr_idx(le32_to_cpu(priv->txq->hw_tail)),
-                     dmaptr_gen(priv->txq->head),
-                     dmaptr_idx(priv->txq->head));
-
-       return n;
-}
-static DEVICE_ATTR(counters, S_IRUSR, femac_show_counters, NULL);
-
-static void
-set_macaddr(struct femac_dev *priv, u8 *addr)
-{
-       writel((addr[4] << 8) | addr[5], priv->base + TXREG_SOURCE_ADDRESS_2);
-       writel((addr[2] << 8) | addr[3], priv->base + TXREG_SOURCE_ADDRESS_1);
-       writel((addr[0] << 8) | addr[1], priv->base + TXREG_SOURCE_ADDRESS_0);
-}
-
-/**
- * femac_adjust_link - Called by the PHY driver to update MAC with changes in
- * link state.
- */
-static void
-femac_adjust_link(struct net_device *ndev)
-{
-       struct femac_dev *priv = netdev_priv(ndev);
-       struct phy_device *phy_dev = priv->phy_dev;
-       int status_change = 0;
-
-       /* Link on or off change */
-       if (phy_dev->link != priv->link) {
-               priv->link = phy_dev->link;
-               if (phy_dev->link)
-                       enable_rx_tx(ndev);
-               else
-                       disable_rx_tx(priv);
-               status_change = 1;
-       }
-
-       if (status_change)
-               phy_print_status(phy_dev);
-}
-
-/**
- * alloc_rx_buf - Initialize a dma descritor with a new rx buffer.
- */
-static int
-alloc_rx_buf(struct femac_dev *priv, struct dma_desc *d)
-{
-       struct sk_buff *skb;
-       dma_addr_t dma_addr;
-
-       skb = netdev_alloc_skb(priv->ndev, MAX_FRAME_SIZE);
-       if (!skb)
-               return -ENOMEM;
-       dma_addr = dma_map_single(priv->dev, skb->data,
-                                 MAX_FRAME_SIZE, DMA_FROM_DEVICE);
-       if (dma_mapping_error(priv->dev, dma_addr)) {
-               dev_kfree_skb_any(skb);
-               return -ENOMEM;
-       }
-       d->flags   = cpu_to_le32(DMADESC_WRITE | DMADESC_INTR);
-       d->buf_len = cpu_to_le16(MAX_FRAME_SIZE);
-       d->pdu_len = d->buf_len;
-       d->buf_ptr = cpu_to_le32((u32)dma_addr);
-       d->cookie  = (u32)skb;
-       return 0;
-}
-
-static void
-femac_tx_complete(struct femac_dev *priv)
-{
-       struct dma_desc *desc;
-       int complete = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       while ((desc = queue_get_tail(priv->tx_ring, priv->txq)) != NULL) {
-               void *buf = (void *)desc->cookie;
-
-               dma_pool_free(priv->tx_pool, buf, le32_to_cpu(desc->buf_ptr));
-               queue_inc_tail(priv->txq);
-               pr_queue("femac: TX complete", priv->txq);
-               ++complete;
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (complete)
-               netif_wake_queue(priv->ndev);
-}
-
-static inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2)
-{
-       const u16 *a = (const u16 *)addr1;
-       const u16 *b = (const u16 *)addr2;
-
-       BUILD_BUG_ON(ETH_ALEN != 6);
-       return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
-}
-
-static int
-femac_rx_packets(struct femac_dev *priv, int max)
-{
-       struct sk_buff *skb;
-       struct dma_desc *desc;
-       int num_rx = 0;
-
-       while (num_rx < max) {
-               desc = queue_get_tail(priv->rx_ring, priv->rxq);
-               if (!desc)
-                       break;
-               queue_inc_tail(priv->rxq);
-
-               pr_debug(DRVNAME " (RX) desc=%p flags=%#x len=%u/%u buf=%#x 
cookie=%#x\n",
-                        desc,
-                        le32_to_cpu(desc->flags),
-                        le16_to_cpu(desc->buf_len),
-                        le16_to_cpu(desc->pdu_len),
-                        le32_to_cpu(desc->buf_ptr),
-                        desc->cookie);
-
-               dma_unmap_single(priv->dev, le32_to_cpu(desc->buf_ptr),
-                                MAX_FRAME_SIZE, DMA_FROM_DEVICE);
-               skb = (struct sk_buff *)desc->cookie;
-
-               if (!(le32_to_cpu(desc->flags) & DMADESC_ERROR)) {
-                       struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
-
-                       if (is_multicast_ether_addr(&ethhdr->h_dest[0]) ||
-                           is_broadcast_ether_addr(&ethhdr->h_dest[0]) ||
-                           compare_ether_addr(&ethhdr->h_dest[0],
-                                              &priv->mac_addr[0]) == 0) {
-                               /* No error, pass sk_buff to upper layer */
-                               skb_put(skb, le16_to_cpu(desc->buf_len));
-                               skb->protocol = eth_type_trans(skb, priv->ndev);
-                               netif_receive_skb(skb);
-                       } else {
-                               dev_kfree_skb_any(skb);
-                       }
-               } else {
-                       struct net_device_stats *s = &priv->ndev->stats;
-
-                       /* Error, free skb and update counters */
-                       dev_kfree_skb_any(skb);
-
-                       s->rx_fifo_errors +=
-                               readl(priv->base + RXREG_STAT_OVERFLOW);
-                       s->rx_crc_errors +=
-                               readl(priv->base + RXREG_STAT_CRC_ERR);
-                       s->rx_frame_errors +=
-                               readl(priv->base + RXREG_STAT_ALIGN_ERR);
-               }
-
-               /* Add new RX buffers */
-               desc = queue_get_head(priv->rx_ring, priv->rxq);
-               if (alloc_rx_buf(priv, desc)) {
-                       dev_warn(priv->dev, "femac: Failed to alloc RX 
buffer\n");
-                       break;
-               }
-               /* Writes to desc must complete before head is advanced */
-               wmb();
-               writel(queue_inc_head(priv->rxq), priv->base + DMAREG_RX_HEAD);
-
-               ++num_rx;
-       }
-
-       return num_rx;
-}
-
-static irqreturn_t
-femac_isr(int irq, void *device_id)
-{
-       struct femac_dev *priv = (struct femac_dev *)device_id;
-       u32 int_status, int_enable;
-
-       /* Read interrupt status */
-       int_status = readl(priv->base + DMAREG_INT_STATUS);
-       int_enable = readl(priv->base + DMAREG_INT_ENABLE);
-       int_status &= int_enable;
-
-       if ((int_status & (DMA_INT_TX | DMA_INT_RX)) == 0)
-               return IRQ_NONE;
-
-       if (int_status & DMA_INT_TX)
-               DBG_INC(priv, tx_interrupt);
-       else
-               DBG_INC(priv, rx_interrupt);
-
-       if (napi_schedule_prep(&priv->napi)) {
-               /* Disable interrupts */
-               writel(0, priv->base + DMAREG_INT_ENABLE);
-               __napi_schedule(&priv->napi);
-       } else {
-               /* Clear interrupt status */
-               writel(0, priv->base + DMAREG_INT_STATUS);
-       }
-
-       return IRQ_HANDLED;
-}
-
-static int
-femac_poll(struct napi_struct *napi, int budget)
-{
-       struct femac_dev *priv = napi_to_priv(napi);
-       int rcvd;
-
-       /* Clear interrupt status */
-       writel(0, priv->base + DMAREG_INT_STATUS);
-
-       WARN_ON(priv->rxq->head != readl(priv->base + DMAREG_RX_HEAD));
-
-       /* Clean TX ring */
-       femac_tx_complete(priv);
-
-       /* Process rx_ring */
-       rcvd = femac_rx_packets(priv, budget);
-       if (rcvd < budget) {
-               /* Exit polling mode */
-               napi_complete(napi);
-               /* Re-enable receive interrupts */
-               writel(DMA_INT_RX | DMA_INT_TX, priv->base + DMAREG_INT_ENABLE);
-       }
-
-       return rcvd;
-}
-
-/**
- * femac_open - Opens the interface.
- *
- * The interface is opened whenever ifconfig activates it.  The open method
- * should register any system resource it needs (I/O ports, IRQ, DMA, etc.)
- * turn on the hardware, and increment the module usage count.
- */
-static int
-femac_open(struct net_device *ndev)
-{
-       struct femac_dev *priv = netdev_priv(ndev);
-       struct device_node *phy_np;
-       struct phy_device *phy_dev;
-       int rc;
-
-       phy_np = of_parse_phandle(priv->dev->of_node, "phy-handle", 0);
-       if (!phy_np) {
-               dev_err(&ndev->dev, "Missing phy-handle\n");
-               return -ENODEV;
-       }
-
-       phy_dev = of_phy_connect(ndev, phy_np, femac_adjust_link,
-                                0, PHY_INTERFACE_MODE_MII);
-       if (IS_ERR_OR_NULL(phy_dev)) {
-               dev_err(&ndev->dev, "Could not attach to PHY\n");
-               return -ENODEV;
-       }
-
-       phy_dev->advertising = phy_dev->supported;
-       priv->link = 0;
-       priv->phy_dev = phy_dev;
-
-       phy_attached_info(phy_dev);
-
-       napi_enable(&priv->napi);
-
-       /* Install the interrupt handlers. */
-       rc = request_irq(ndev->irq, femac_isr, 0, DRVNAME, priv);
-       if (rc) {
-               dev_err(&ndev->dev, "Request IRQ%d failed\n", ndev->irq);
-               return rc;
-       }
-
-       /* enable interrupts */
-       writel(DMA_INT_RX | DMA_INT_TX, priv->base + DMAREG_INT_ENABLE);
-
-       phy_start(priv->phy_dev);
-
-       return 0;
-}
-
-/**
- * femac_stop - Stops the interface.
- *
- * The interface is stopped when it is brought down; operations performed at
- * open time should be reversed.
- */
-static int
-femac_stop(struct net_device *device)
-{
-       struct femac_dev *priv = netdev_priv(device);
-
-       /* Indicate to the OS that no more packets should be sent.  */
-       netif_stop_queue(device);
-
-       phy_disconnect(priv->phy_dev);
-
-       /* Stop the receiver and transmitter.  */
-       disable_rx_tx(priv);
-
-       /* Disable NAPI. */
-       napi_disable(&priv->napi);
-
-       /* Free the interrupts.  */
-       free_irq(device->irq, priv);
-
-       return 0;
-}
-
-/**
- * femac_hard_start_xmit - The method initiates the transmission of a packet.
- *
- * The full packet (protocol headers and all) is contained in a socket buffer
- * (sk_buff) structure.
- *
- * Since the FEMAC DMA engine needs 32-bit aligned data, we allocate a new TX
- * buffer from a dma_pool and copy the payload before passing it on to the
- * hardware.
- */
-static int
-femac_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-       struct femac_dev *priv = netdev_priv(ndev);
-       struct dma_desc *desc;
-       void *tx_buf;
-       dma_addr_t dma_addr;
-       unsigned long flags;
-       int length;
-
-       if (skb->len > MAX_FRAME_SIZE) {
-               ++ndev->stats.tx_dropped;
-               goto drop;
-       }
-
-       tx_buf = dma_pool_alloc(priv->tx_pool, GFP_ATOMIC, &dma_addr);
-       if (!tx_buf) {
-               netif_stop_queue(ndev);
-               DBG_INC(priv, tx_nobuf);
-               ++ndev->stats.tx_dropped;
-               dev_err_ratelimited(&ndev->dev, "No TX buffers!\n");
-               goto drop;
-       }
-
-       length = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
-       skb_copy_from_linear_data(skb, tx_buf, length);
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       desc = queue_get_head(priv->tx_ring, priv->txq);
-       pr_debug(DRVNAME " (TX) desc=%p len=%u\n", desc, length);
-       if (!desc) {
-               DBG_INC(priv, tx_nodesc);
-               spin_unlock_irqrestore(&priv->lock, flags);
-               dma_pool_free(priv->tx_pool, tx_buf, dma_addr);
-               netif_stop_queue(ndev);
-               dev_kfree_skb_any(skb);
-               ++ndev->stats.tx_dropped;
-               dev_err_ratelimited(&ndev->dev, "No TX descriptors!\n");
-               return NETDEV_TX_BUSY;
-       }
-
-       desc->flags = cpu_to_le32(DMADESC_WRITE | DMADESC_INTR |
-                                 DMADESC_SOP | DMADESC_EOP);
-       desc->buf_ptr = cpu_to_le32((u32)dma_addr);
-       desc->buf_len = cpu_to_le16(length);
-       desc->pdu_len = desc->buf_len;
-       desc->cookie  = (u32)tx_buf;
-       /* Make sure writes to descriptor completed before starting TX */
-       wmb();
-       WARN_ON(priv->txq->head != readl(priv->base + DMAREG_TX_HEAD));
-       writel(queue_inc_head(priv->txq), priv->base + DMAREG_TX_HEAD);
-       netif_trans_update(ndev);       /* prevent tx timeout */
-       pr_queue("XMIT", priv->txq);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-drop:
-       dev_kfree_skb_any(skb);
-       return NETDEV_TX_OK;
-}
-
-/**
- * femac_get_stats - Read hardware counters.
- *
- * Whenever an application needs to get statistics for the interface, this
- * method is called.
- */
-static struct net_device_stats *
-femac_get_stats(struct net_device *ndev)
-{
-       struct femac_dev *priv = netdev_priv(ndev);
-       struct net_device_stats *s = &ndev->stats;
-
-       s->rx_packets       += readl(priv->base + RXREG_STAT_PACKET_OK);
-       s->tx_packets       += readl(priv->base + TXREG_STAT_PACKET_OK);
-       s->rx_bytes         += readl(priv->base + RXREG_STAT_BYTES_LO);
-       s->tx_bytes         += readl(priv->base + TXREG_STAT_BYTES_LO);
-       s->multicast        += readl(priv->base + RXREG_STAT_MULTICAST);
-       s->multicast        += readl(priv->base + RXREG_STAT_BROADCAST);
-       s->collisions       += readl(priv->base + TXREG_STAT_LATECOLL);
-       s->collisions       += readl(priv->base + TXREG_STAT_EXCECOLL);
-       s->rx_length_errors += readl(priv->base + RXREG_STAT_UNDERSIZE);
-       s->rx_length_errors += readl(priv->base + RXREG_STAT_OVERSIZE);
-       s->tx_fifo_errors   += readl(priv->base + TXREG_STAT_UNDERRUN);
-
-       s->rx_errors =
-               (s->rx_length_errors +
-                s->rx_fifo_errors +
-                s->rx_crc_errors +
-                s->rx_frame_errors);
-
-       s->tx_errors =
-               (s->tx_fifo_errors +
-                s->tx_aborted_errors);
-
-       return &ndev->stats;
-}
-
-/**
- * femac_set_mac_address
- */
-static int
-femac_set_mac_address(struct net_device *ndev, void *data)
-{
-       struct femac_dev *priv = netdev_priv(ndev);
-       struct sockaddr *addr = data;
-
-       if (netif_running(ndev))
-               return -EBUSY;
-
-       memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
-       set_macaddr(priv, addr->sa_data);
-
-       return 0;
-}
-
-static const struct net_device_ops femac_netdev_ops = {
-       .ndo_open            = femac_open,
-       .ndo_stop            = femac_stop,
-       .ndo_get_stats       = femac_get_stats,
-       .ndo_set_mac_address = femac_set_mac_address,
-       .ndo_start_xmit      = femac_hard_start_xmit,
-};
-
-/* Ethtool operations */
-
-static int
-femac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
-{
-       struct femac_dev *priv = netdev_priv(ndev);
-
-       if (!priv->phy_dev)
-               return -ENODEV;
-
-       return phy_ethtool_gset(priv->phy_dev, cmd);
-}
-
-static int
-femac_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
-{
-       struct femac_dev *priv = netdev_priv(ndev);
-
-       if (!priv->phy_dev)
-               return -ENODEV;
-
-       return phy_ethtool_sset(priv->phy_dev, cmd);
-}
-
-static const struct ethtool_ops femac_ethtool_ops = {
-       .get_settings = femac_get_settings,
-       .set_settings = femac_set_settings
-};
-
-/**
- * femac_init - Allocate memory and initialize the hardware
- */
-static int
-femac_init(struct net_device *ndev)
-{
-       struct femac_dev *priv = netdev_priv(ndev);
-       dma_addr_t dma_phys;
-       int i;
-
-       /* Reset the MAC */
-       writel(0x80000000, priv->base + DMAREG_CONTROL);
-
-       /* The number of rx and tx descriptors must be an even multiple of
-        * DESCRIPTOR_GRANULARITY.
-        */
-       priv->rx_num_desc = ALIGN(rx_num_desc, DESCRIPTOR_GRANULARITY);
-       priv->tx_num_desc = ALIGN(tx_num_desc, DESCRIPTOR_GRANULARITY);
-
-       /* This needs to be set to something sane for dma_alloc_coherent() */
-       ndev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       ndev->dev.dma_mask = &ndev->dev.coherent_dma_mask;
-
-       priv->tx_pool = dma_pool_create("femac_dma", priv->dev,
-                                          MAX_FRAME_SIZE, 4, 0);
-       if (!priv->tx_pool) {
-               dev_err(&ndev->dev, "Failed to allocate DMA buffer pool\n");
-               return -ENOMEM;
-       }
-
-       spin_lock_init(&priv->lock);
-
-       /* Take MAC out of reset */
-       writel(0x0, priv->base + RXREG_SOFT_RESET);
-       writel(RX_MODE_ETHERNET_ENABLE, priv->base + RXREG_MODE);
-       writel(0x0, priv->base + TXREG_SOFT_RESET);
-       writel(TX_MODE_ETHERNET_ENABLE, priv->base + TXREG_MODE);
-       writel(TX_WATERMARK_DTPA_HIGH(96) | TX_WATERMARK_DTPA_LOW(10),
-              priv->base + TXREG_WATERMARK);
-
-       writel(DMA_CTRL_ERR_CLEAR | DMA_CTRL_ENABLE,
-              priv->base + DMAREG_CONTROL);
-       writel(DMA_TX_ENABLE | DMA_RX_ENABLE, priv->base + DMAREG_ENABLE);
-       writel(DTPA_BP_COUNT(0x28) | DTPA_LOW_MARK(0x44),
-              priv->base + DMAREG_DTPA_LOW);
-       writel(DTPA_HIGH_MARK(0xc0) | DTPA_START_THRES(0),
-              priv->base + DMAREG_DTPA_HIGH);
-
-       set_macaddr(priv, ndev->dev_addr);
-
-       /* Initialize RX queue */
-       priv->rx_ring_size = priv->rx_num_desc * sizeof(struct dma_desc);
-       priv->rx_ring = dma_alloc_coherent(&ndev->dev, priv->rx_ring_size,
-                                          &priv->rx_ring_phys, GFP_KERNEL);
-       priv->rxq = dma_alloc_coherent(&ndev->dev, 2 * sizeof(struct queue_ptr),
-                                      &dma_phys, GFP_KERNEL);
-       priv->rxq->phys = dma_phys;
-       writel(priv->rx_ring_phys, priv->base + DMAREG_RX_QUEUE_BASE);
-       writel(priv->rx_ring_size / 1024, priv->base + DMAREG_RX_QUEUE_SIZE);
-       writel(priv->rxq->phys, priv->base + DMAREG_RX_TAIL_ADDR);
-       priv->rxq->size = priv->rx_ring_size;
-       priv->rxq->hw_tail = readl(priv->base + DMAREG_RX_TAIL);
-       priv->rxq->tail    = priv->rxq->hw_tail;
-       priv->rxq->head    = priv->rxq->hw_tail;
-       writel(priv->rxq->head, priv->base + DMAREG_RX_HEAD);
-       pr_debug("femac: rx_ring %p rxq %p\n", priv->rx_ring, priv->rxq);
-
-       /* Initialize the descriptors */
-       for (i = 0; i < priv->rx_num_desc - 1; ++i) {
-               struct dma_desc *desc  = &priv->rx_ring[i];
-
-               alloc_rx_buf(priv, desc);
-               writel(queue_inc_head(priv->rxq), priv->base + DMAREG_RX_HEAD);
-       }
-
-       /* Initialize TX queue */
-       priv->tx_ring_size = priv->tx_num_desc * sizeof(struct dma_desc);
-       priv->tx_ring = dma_alloc_coherent(&ndev->dev, priv->tx_ring_size,
-                                          &priv->tx_ring_phys, GFP_KERNEL);
-       priv->txq = &priv->rxq[1];
-       priv->txq->phys = dma_phys + sizeof(struct queue_ptr);
-       writel(priv->tx_ring_phys, priv->base + DMAREG_TX_QUEUE_BASE);
-       writel(priv->tx_ring_size / 1024, priv->base + DMAREG_TX_QUEUE_SIZE);
-       writel(priv->txq->phys, priv->base + DMAREG_TX_TAIL_ADDR);
-       priv->txq->size    = priv->tx_ring_size;
-       priv->txq->hw_tail = readl(priv->base + DMAREG_RX_TAIL);
-       priv->txq->head    = priv->txq->hw_tail;
-       priv->txq->tail    = priv->txq->hw_tail;
-       writel(priv->txq->head, priv->base + DMAREG_TX_HEAD);
-       pr_debug("femac: tx_ring %p txq %p\n", priv->tx_ring, priv->txq);
-
-       /* Clear statistics */
-       clear_statistics(priv);
-
-       ether_setup(ndev);
-       ndev->netdev_ops = &femac_netdev_ops;
-       ndev->ethtool_ops = &femac_ethtool_ops;
-       ndev->watchdog_timeo = msecs_to_jiffies(1000);
-       memset(&priv->napi, 0, sizeof(struct napi_struct));
-       netif_napi_add(ndev, &priv->napi, femac_poll, NAPI_WEIGHT);
-
-       return 0;
-}
-
-/**
- * femac_probe - Create, initialize and register the net_device.
- */
-static int
-femac_probe(struct platform_device *pdev)
-{
-       struct device_node *np = pdev->dev.of_node;
-       struct net_device *ndev = NULL;
-       struct femac_dev *priv = NULL;
-       struct resource *res;
-       const u32 *field;
-       int length;
-       int rc = 0;
-
-       /* Allocate space for the net_device. */
-       ndev = alloc_etherdev(sizeof(*priv));
-       if (!ndev) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       priv = netdev_priv(ndev);
-       priv->ndev = ndev;
-       priv->dev = &pdev->dev;
-       strcpy(ndev->name, "eth%d");
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       priv->base  = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(priv->base)) {
-               rc = PTR_ERR(priv->base);
-               goto out;
-       }
-
-       ndev->irq = platform_get_irq(pdev, 0);
-       if (ndev->irq < 0) {
-               rc = ndev->irq;
-               goto out;
-       }
-
-       /* Check for mac address property in device-tree */
-       field = of_get_property(np, "mac-address", &length);
-       if (!field)
-               field = of_get_property(np, "local-mac-address", &length);
-       if (field && length == ETH_ALEN)
-               ether_addr_copy(priv->mac_addr, (const u8 *)field);
-       /* MAC address may be overridden via module/cmdline parameter */
-       if (is_valid_ether_addr(macaddr))
-               ether_addr_copy(priv->mac_addr, macaddr);
-       /* Still no valid MAC address, randomize it */
-       if (!is_valid_ether_addr(priv->mac_addr))
-               random_ether_addr(priv->mac_addr);
-
-       ether_addr_copy(ndev->dev_addr, &priv->mac_addr[0]);
-       ether_addr_copy(ndev->perm_addr, &priv->mac_addr[0]);
-       ndev->addr_len = ETH_ALEN;
-
-       /* Initialize the device. */
-       rc = femac_init(ndev);
-       if (rc != 0)
-               goto out;
-
-       /* Register the device. */
-       rc = register_netdev(ndev);
-       if (rc != 0)
-               goto out;
-
-       device_create_file(&ndev->dev, &dev_attr_counters);
-
-       netif_carrier_off(ndev);
-
-out:
-       if (rc) {
-               dev_err(&pdev->dev, "Failed to initialize, error %d\n", rc);
-               if (ndev)
-                       free_netdev(ndev);
-       }
-       return rc;
-}
-
-/**
- * femac_remove - Handle device removal.
- */
-static int
-femac_remove(struct platform_device *pdev)
-{
-       struct net_device *ndev = platform_get_drvdata(pdev);
-       struct femac_dev *priv = netdev_priv(ndev);
-
-       device_remove_file(&ndev->dev, &dev_attr_counters);
-       dma_pool_destroy(priv->tx_pool);
-       dma_free_coherent(&ndev->dev,
-                         priv->rx_ring_size,
-                         priv->rx_ring,
-                         priv->rx_ring_phys);
-       dma_free_coherent(&ndev->dev,
-                         priv->tx_ring_size,
-                         priv->tx_ring,
-                         priv->tx_ring_phys);
-       dma_free_coherent(&ndev->dev,
-                         2 * sizeof(struct queue_ptr),
-                         priv->rxq,
-                         priv->rxq->phys);
-       unregister_netdev(ndev);
-       free_netdev(ndev);
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-femac_suspend(struct device *dev)
-{
-       return -ENOSYS;
-}
-
-static int
-femac_resume(struct device *dev)
-{
-       return -ENOSYS;
-}
-
-static const struct dev_pm_ops femac_pm_ops = {
-       .suspend = femac_suspend,
-       .resume  = femac_resume,
-};
-#endif
-
-static const struct of_device_id femac_id_table[] = {
-       { .compatible = "lsi,femac" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, femac_id_table);
-
-static struct platform_driver femac_driver = {
-       .driver = {
-               .name  = DRVNAME,
-               .owner = THIS_MODULE,
-#ifdef CONFIG_PM
-               .pm = &femac_pm_ops,
-#endif
-               .of_match_table = femac_id_table,
-       },
-       .probe = femac_probe,
-       .remove = femac_remove,
-};
-
-module_platform_driver(femac_driver);
-
-MODULE_AUTHOR("LSI Corporation");
-MODULE_DESCRIPTION("LSI FEMAC Ethernet Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/lsi/lsi-mdio.c 
b/drivers/net/ethernet/lsi/lsi-mdio.c
deleted file mode 100644
index 56decf6..0000000
--- a/drivers/net/ethernet/lsi/lsi-mdio.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Driver for MDIO controller found in LSI Axxia devices.
- *
- * Copyright (C) 2013 LSI Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/mii.h>
-#include <linux/phy.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_mdio.h>
-#include <linux/of_platform.h>
-#include <linux/io.h>
-
-/* MDIO Registers */
-#define MDIO_CONTROL           0x00
-#define   CONTROL_BUSY         (1<<31) /* MDIO cycle in progress (RO) */
-#define   CONTROL_NOPRE                (1<<30) /* Suppress preamble */
-#define   CONTROL_CL22         (0<<29) /* Clause-22 */
-#define   CONTROL_CL45         (1<<29) /* Clause-45 */
-#define   CONTROL_READ         (2<<27) /* Read operation */
-#define   CONTROL_WRITE                (1<<27) /* Write operation */
-#define   CONTROL_IFSEL                (1<<26) /* Interface select */
-#define   CONTROL_PHYREG(_n)   (((_n) & 0x1F) << 21)
-#define   CONTROL_PHYID(_n)    (((_n) & 0x1F) << 16)
-#define   CONTROL_DATA(_n)     (((_n) & 0xFFFF) << 0)
-#define MDIO_STATUS            0x04
-#define   STATUS_BUSY          (1<<31)
-#define   STATUS_DONE          (1<<30)
-#define MDIO_CLK_OFFSET                0x08
-#define MDIO_CLK_PERIOD                0x0c
-
-/* MDIO bus driver private data */
-struct lsi_mdio_priv {
-       void __iomem *base;
-       struct mii_bus *bus;
-};
-
-static inline void __iomem *
-bus_to_regs(struct mii_bus *bus)
-{
-       return ((struct lsi_mdio_priv *)bus->priv)->base;
-}
-
-static int
-lsi_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
-{
-       void __iomem *base = bus_to_regs(bus);
-       u32 ctrl;
-       u32 data;
-
-       /* Set the mdio_done (status) bit. */
-       writel(STATUS_DONE | readl(base + MDIO_STATUS), base + MDIO_STATUS);
-
-       /* Write the command. */
-       ctrl = (CONTROL_READ |
-               CONTROL_PHYID(mii_id) |
-               CONTROL_PHYREG(regnum));
-       if (regnum & MII_ADDR_C45)
-               ctrl |= CONTROL_CL45;
-       writel(ctrl, base + MDIO_CONTROL);
-
-       /* Wait for the mdio_done (status) bit to clear. */
-       while ((readl(base + MDIO_STATUS) & STATUS_DONE) != 0)
-               cpu_relax();
-
-       /* Wait for the mdio_busy (control) bit to clear. */
-       do {
-               data = readl(base + MDIO_CONTROL);
-       } while ((data & CONTROL_BUSY) != 0);
-
-       return data & 0xFFFF;
-}
-
-static int
-lsi_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
-{
-       void __iomem *base = bus_to_regs(bus);
-       u32 ctrl;
-
-       /* Wait for mdio_busy (control) to be clear. */
-       while ((readl(base + MDIO_CONTROL) & CONTROL_BUSY) != 0)
-               cpu_relax();
-
-       /* Set the mdio_busy (status) bit. */
-       writel(STATUS_DONE | readl(base + MDIO_STATUS), base + MDIO_STATUS);
-
-       /* Write the command. */
-       ctrl = (CONTROL_WRITE |
-               CONTROL_PHYID(mii_id) |
-               CONTROL_PHYREG(regnum) |
-               CONTROL_DATA(value));
-       if (regnum & MII_ADDR_C45)
-               ctrl |= CONTROL_CL45;
-       writel(ctrl, base + MDIO_CONTROL);
-
-       /* Wait for the mdio_done (status) bit to clear. */
-       while ((readl(base + MDIO_STATUS) & STATUS_DONE) != 0)
-               cpu_relax();
-
-       /* Wait for the mdio_busy (control) bit to clear. */
-       while ((readl(base + MDIO_CONTROL) & CONTROL_BUSY) != 0)
-               cpu_relax();
-
-       return 0;
-}
-
-static int
-lsi_mdio_probe(struct platform_device *pdev)
-{
-       struct device_node   *np = pdev->dev.of_node;
-       struct lsi_mdio_priv *priv = NULL;
-       struct resource      *res;
-       int                   err;
-       u32                   clk_offset = 0x10;
-       u32                   clk_period = 0x2c;
-
-       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENODEV;
-
-       priv->bus = mdiobus_alloc();
-       if (!priv->bus)
-               return -ENOMEM;
-
-       priv->bus->name  = "Axxia MDIO",
-       priv->bus->read  = lsi_mdio_read,
-       priv->bus->write = lsi_mdio_write,
-       priv->bus->priv  = priv;
-       snprintf(priv->bus->id, MII_BUS_ID_SIZE, pdev->name);
-
-       priv->base = devm_ioremap_resource(&pdev->dev, res);
-       if (!priv->base) {
-               dev_err(&pdev->dev, "Failed to map registers\n");
-               err = -ENODEV;
-               goto err_ret;
-       }
-
-       priv->bus->parent = &pdev->dev;
-       dev_set_drvdata(&pdev->dev, priv->bus);
-
-       of_property_read_u32(np, "lsi,mdio-clk-offset", &clk_offset);
-       of_property_read_u32(np, "lsi,mdio-clk-period", &clk_period);
-
-       writel(clk_offset, priv->base + MDIO_CLK_OFFSET);
-       writel(clk_period, priv->base + MDIO_CLK_PERIOD);
-       writel(0, priv->base + MDIO_CONTROL);
-
-       err = of_mdiobus_register(priv->bus, np);
-       if (err) {
-               dev_err(&pdev->dev, "Failed to register MDIO bus\n");
-               goto err_ret;
-       }
-
-       return 0;
-
-err_ret:
-       if (priv && priv->bus)
-               kfree(priv->bus);
-       return err;
-}
-
-static int
-lsi_mdio_remove(struct platform_device *pdev)
-{
-       struct mii_bus *bus = dev_get_drvdata(&pdev->dev);
-
-       mdiobus_unregister(bus);
-       dev_set_drvdata(&pdev->dev, NULL);
-       mdiobus_free(bus);
-
-       return 0;
-}
-
-static struct of_device_id lsi_mdio_match[] = {
-       { .compatible = "lsi,axm-mdio", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, lsi_mdio_match);
-
-static struct platform_driver lsi_mdio_driver = {
-       .driver = {
-               .name           = "lsi-mdio",
-               .owner          = THIS_MODULE,
-               .of_match_table = lsi_mdio_match,
-       },
-       .probe  = lsi_mdio_probe,
-       .remove = lsi_mdio_remove,
-};
-
-module_platform_driver(lsi_mdio_driver);
-
-MODULE_AUTHOR("LSI Corporation");
-MODULE_DESCRIPTION("LSI MDIO Bus Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/include/linux/axxia-mdio.h b/include/linux/axxia-mdio.h
new file mode 100644
index 0000000..3550349
--- /dev/null
+++ b/include/linux/axxia-mdio.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 Intel <john.jacq...@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ */
+
+#ifndef __DRIVERS_MISC_AXXIA_MDIO_H
+#define __DRIVERS_MISC_AXXIA_MDIO_H
+
+#endif /* __DRIVERS_MISC_AXXIA_MDIO_H */
-- 
2.7.4

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to