driver: net: consolidate ti's code in separate folder
authorGrygorii Strashko <grygorii.strashko@ti.com>
Wed, 31 Oct 2018 21:21:39 +0000 (16:21 -0500)
committerJoe Hershberger <joe.hershberger@ni.com>
Mon, 5 Nov 2018 16:41:59 +0000 (10:41 -0600)
Add drivers/net/ti/ folder and move all TI's code in this folder for better
maintenance.

Reviewed-by: Tom Rini <trini@konsulko.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
18 files changed:
arch/arm/mach-davinci/dp83848.c
arch/arm/mach-davinci/et1011c.c
arch/arm/mach-davinci/ksz8873.c
arch/arm/mach-davinci/lxt972.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/cpsw-common.c [deleted file]
drivers/net/cpsw.c [deleted file]
drivers/net/davinci_emac.c [deleted file]
drivers/net/davinci_emac.h [deleted file]
drivers/net/keystone_net.c [deleted file]
drivers/net/ti/Kconfig [new file with mode: 0644]
drivers/net/ti/Makefile [new file with mode: 0644]
drivers/net/ti/cpsw-common.c [new file with mode: 0644]
drivers/net/ti/cpsw.c [new file with mode: 0644]
drivers/net/ti/davinci_emac.c [new file with mode: 0644]
drivers/net/ti/davinci_emac.h [new file with mode: 0644]
drivers/net/ti/keystone_net.c [new file with mode: 0644]

index 595e3ca149bd39875b973b683fe75687a26bf14e..7115d7bad24f4939ffde1f49f5188095ce65eeb8 100644 (file)
@@ -12,7 +12,7 @@
 #include <net.h>
 #include <dp83848.h>
 #include <asm/arch/emac_defs.h>
-#include "../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/ti/davinci_emac.h"
 
 #ifdef CONFIG_DRIVER_TI_EMAC
 
index 3d02274810748a973688eb31460663de6ac9b347..bfb7ff26894e3cb149766d141ee86e153e7eb966 100644 (file)
@@ -9,7 +9,7 @@
 #include <net.h>
 #include <miiphy.h>
 #include <asm/arch/emac_defs.h>
-#include "../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/ti/davinci_emac.h"
 
 #ifdef CONFIG_DRIVER_TI_EMAC
 
index 899cff0169a955e9c878714931017137cb14b82c..85b0c2620c9ed9543ae53bb1304e844683652768 100644 (file)
@@ -19,7 +19,7 @@
 #include <net.h>
 #include <asm/arch/emac_defs.h>
 #include <asm/io.h>
-#include "../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/ti/davinci_emac.h"
 
 int ksz8873_is_phy_connected(int phy_addr)
 {
index 170e4a57830243e0ff8b3578a0b14aaeb3c0efbb..b54f67dbfedbc57f030d355b05e2d1fdaecef1fa 100644 (file)
@@ -13,7 +13,7 @@
 #include <miiphy.h>
 #include <lxt971a.h>
 #include <asm/arch/emac_defs.h>
-#include "../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/ti/davinci_emac.h"
 
 #ifdef CONFIG_DRIVER_TI_EMAC
 
index fd1c48049a9bde51d3c8df18e9a2ab2951da8ee9..8fb365fc5d2a64165dff2a4f003499f73759e68a 100644 (file)
@@ -11,13 +11,6 @@ config DM_ETH
          This is currently implemented in net/eth-uclass.c
          Look in include/net.h for details.
 
-config DRIVER_TI_CPSW
-       bool "TI Common Platform Ethernet Switch"
-       select PHYLIB
-       help
-         This driver supports the TI three port switch gigabit ethernet
-         subsystem found in the TI SoCs.
-
 menuconfig NETDEVICES
        bool "Network device support"
        depends on NET
@@ -355,10 +348,7 @@ config SH_ETHER
        help
          This driver supports the Ethernet for Renesas SH and ARM SoCs.
 
-config DRIVER_TI_EMAC
-       bool "TI Davinci EMAC"
-       help
-          Support for davinci emac
+source "drivers/net/ti/Kconfig"
 
 config XILINX_AXIEMAC
        depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
index cc0971c614f40b31528ed69ad0cdf8c20ecef9bc..99056aa041d08e3fd959d5bdcfbf6a713a7cb795 100644 (file)
@@ -30,7 +30,6 @@ obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 obj-$(CONFIG_FTMAC110) += ftmac110.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
-obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 obj-$(CONFIG_LAN91C96) += lan91c96.o
 obj-$(CONFIG_LPC32XX_ETH) += lpc32xx_eth.o
@@ -57,9 +56,7 @@ obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_RENESAS_RAVB) += ravb.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
-obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
 obj-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
-obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o
 obj-$(CONFIG_FMAN_ENET) += fsl_mdio.o
 obj-$(CONFIG_ULI526X) += uli526x.o
 obj-$(CONFIG_VSC7385_ENET) += vsc7385.o
@@ -74,3 +71,4 @@ obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
 obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
 obj-$(CONFIG_FSL_PFE) += pfe_eth/
 obj-$(CONFIG_SNI_AVE) += sni_ave.o
+obj-y += ti/
diff --git a/drivers/net/cpsw-common.c b/drivers/net/cpsw-common.c
deleted file mode 100644 (file)
index 6c8ddbd..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * CPSW common - libs used across TI ethernet devices.
- *
- * Copyright (C) 2016, Texas Instruments, Incorporated
- */
-
-#include <common.h>
-#include <dm.h>
-#include <environment.h>
-#include <fdt_support.h>
-#include <asm/io.h>
-#include <cpsw.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define CTRL_MAC_REG(offset, id) ((offset) + 0x8 * (id))
-
-static int davinci_emac_3517_get_macid(struct udevice *dev, u16 offset,
-                                      int slave, u8 *mac_addr)
-{
-       void *fdt = (void *)gd->fdt_blob;
-       int node = dev_of_offset(dev);
-       u32 macid_lsb;
-       u32 macid_msb;
-       fdt32_t gmii = 0;
-       int syscon;
-       u32 addr;
-
-       syscon = fdtdec_lookup_phandle(fdt, node, "syscon");
-       if (syscon < 0) {
-               pr_err("Syscon offset not found\n");
-               return -ENOENT;
-       }
-
-       addr = (u32)map_physmem(fdt_translate_address(fdt, syscon, &gmii),
-                               sizeof(u32), MAP_NOCACHE);
-       if (addr == FDT_ADDR_T_NONE) {
-               pr_err("Not able to get syscon address to get mac efuse address\n");
-               return -ENOENT;
-       }
-
-       addr += CTRL_MAC_REG(offset, slave);
-
-       /* try reading mac address from efuse */
-       macid_lsb = readl(addr);
-       macid_msb = readl(addr + 4);
-
-       mac_addr[0] = (macid_msb >> 16) & 0xff;
-       mac_addr[1] = (macid_msb >> 8)  & 0xff;
-       mac_addr[2] = macid_msb & 0xff;
-       mac_addr[3] = (macid_lsb >> 16) & 0xff;
-       mac_addr[4] = (macid_lsb >> 8)  & 0xff;
-       mac_addr[5] = macid_lsb & 0xff;
-
-       return 0;
-}
-
-static int cpsw_am33xx_cm_get_macid(struct udevice *dev, u16 offset, int slave,
-                                   u8 *mac_addr)
-{
-       void *fdt = (void *)gd->fdt_blob;
-       int node = dev_of_offset(dev);
-       u32 macid_lo;
-       u32 macid_hi;
-       fdt32_t gmii = 0;
-       int syscon;
-       u32 addr;
-
-       syscon = fdtdec_lookup_phandle(fdt, node, "syscon");
-       if (syscon < 0) {
-               pr_err("Syscon offset not found\n");
-               return -ENOENT;
-       }
-
-       addr = (u32)map_physmem(fdt_translate_address(fdt, syscon, &gmii),
-                               sizeof(u32), MAP_NOCACHE);
-       if (addr == FDT_ADDR_T_NONE) {
-               pr_err("Not able to get syscon address to get mac efuse address\n");
-               return -ENOENT;
-       }
-
-       addr += CTRL_MAC_REG(offset, slave);
-
-       /* try reading mac address from efuse */
-       macid_lo = readl(addr);
-       macid_hi = readl(addr + 4);
-
-       mac_addr[5] = (macid_lo >> 8) & 0xff;
-       mac_addr[4] = macid_lo & 0xff;
-       mac_addr[3] = (macid_hi >> 24) & 0xff;
-       mac_addr[2] = (macid_hi >> 16) & 0xff;
-       mac_addr[1] = (macid_hi >> 8) & 0xff;
-       mac_addr[0] = macid_hi & 0xff;
-
-       return 0;
-}
-
-int ti_cm_get_macid(struct udevice *dev, int slave, u8 *mac_addr)
-{
-       if (of_machine_is_compatible("ti,dm8148"))
-               return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
-
-       if (of_machine_is_compatible("ti,am33xx"))
-               return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
-
-       if (device_is_compatible(dev, "ti,am3517-emac"))
-               return davinci_emac_3517_get_macid(dev, 0x110, slave, mac_addr);
-
-       if (device_is_compatible(dev, "ti,dm816-emac"))
-               return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr);
-
-       if (of_machine_is_compatible("ti,am43"))
-               return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
-
-       if (of_machine_is_compatible("ti,dra7"))
-               return davinci_emac_3517_get_macid(dev, 0x514, slave, mac_addr);
-
-       dev_err(dev, "incompatible machine/device type for reading mac address\n");
-       return -ENOENT;
-}
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
deleted file mode 100644 (file)
index 8e2a48c..0000000
+++ /dev/null
@@ -1,1508 +0,0 @@
-/*
- * CPSW Ethernet Switch Driver
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.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 version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <common.h>
-#include <command.h>
-#include <net.h>
-#include <miiphy.h>
-#include <malloc.h>
-#include <net.h>
-#include <netdev.h>
-#include <cpsw.h>
-#include <linux/errno.h>
-#include <asm/gpio.h>
-#include <asm/io.h>
-#include <phy.h>
-#include <asm/arch/cpu.h>
-#include <dm.h>
-#include <fdt_support.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define BITMASK(bits)          (BIT(bits) - 1)
-#define PHY_REG_MASK           0x1f
-#define PHY_ID_MASK            0x1f
-#define NUM_DESCS              (PKTBUFSRX * 2)
-#define PKT_MIN                        60
-#define PKT_MAX                        (1500 + 14 + 4 + 4)
-#define CLEAR_BIT              1
-#define GIGABITEN              BIT(7)
-#define FULLDUPLEXEN           BIT(0)
-#define MIIEN                  BIT(15)
-
-/* reg offset */
-#define CPSW_HOST_PORT_OFFSET  0x108
-#define CPSW_SLAVE0_OFFSET     0x208
-#define CPSW_SLAVE1_OFFSET     0x308
-#define CPSW_SLAVE_SIZE                0x100
-#define CPSW_CPDMA_OFFSET      0x800
-#define CPSW_HW_STATS          0x900
-#define CPSW_STATERAM_OFFSET   0xa00
-#define CPSW_CPTS_OFFSET       0xc00
-#define CPSW_ALE_OFFSET                0xd00
-#define CPSW_SLIVER0_OFFSET    0xd80
-#define CPSW_SLIVER1_OFFSET    0xdc0
-#define CPSW_BD_OFFSET         0x2000
-#define CPSW_MDIO_DIV          0xff
-
-#define AM335X_GMII_SEL_OFFSET 0x630
-
-/* DMA Registers */
-#define CPDMA_TXCONTROL                0x004
-#define CPDMA_RXCONTROL                0x014
-#define CPDMA_SOFTRESET                0x01c
-#define CPDMA_RXFREE           0x0e0
-#define CPDMA_TXHDP_VER1       0x100
-#define CPDMA_TXHDP_VER2       0x200
-#define CPDMA_RXHDP_VER1       0x120
-#define CPDMA_RXHDP_VER2       0x220
-#define CPDMA_TXCP_VER1                0x140
-#define CPDMA_TXCP_VER2                0x240
-#define CPDMA_RXCP_VER1                0x160
-#define CPDMA_RXCP_VER2                0x260
-
-/* Descriptor mode bits */
-#define CPDMA_DESC_SOP         BIT(31)
-#define CPDMA_DESC_EOP         BIT(30)
-#define CPDMA_DESC_OWNER       BIT(29)
-#define CPDMA_DESC_EOQ         BIT(28)
-
-/*
- * This timeout definition is a worst-case ultra defensive measure against
- * unexpected controller lock ups.  Ideally, we should never ever hit this
- * scenario in practice.
- */
-#define MDIO_TIMEOUT            100 /* msecs */
-#define CPDMA_TIMEOUT          100 /* msecs */
-
-struct cpsw_mdio_regs {
-       u32     version;
-       u32     control;
-#define CONTROL_IDLE           BIT(31)
-#define CONTROL_ENABLE         BIT(30)
-
-       u32     alive;
-       u32     link;
-       u32     linkintraw;
-       u32     linkintmasked;
-       u32     __reserved_0[2];
-       u32     userintraw;
-       u32     userintmasked;
-       u32     userintmaskset;
-       u32     userintmaskclr;
-       u32     __reserved_1[20];
-
-       struct {
-               u32             access;
-               u32             physel;
-#define USERACCESS_GO          BIT(31)
-#define USERACCESS_WRITE       BIT(30)
-#define USERACCESS_ACK         BIT(29)
-#define USERACCESS_READ                (0)
-#define USERACCESS_DATA                (0xffff)
-       } user[0];
-};
-
-struct cpsw_regs {
-       u32     id_ver;
-       u32     control;
-       u32     soft_reset;
-       u32     stat_port_en;
-       u32     ptype;
-};
-
-struct cpsw_slave_regs {
-       u32     max_blks;
-       u32     blk_cnt;
-       u32     flow_thresh;
-       u32     port_vlan;
-       u32     tx_pri_map;
-#ifdef CONFIG_AM33XX
-       u32     gap_thresh;
-#elif defined(CONFIG_TI814X)
-       u32     ts_ctl;
-       u32     ts_seq_ltype;
-       u32     ts_vlan;
-#endif
-       u32     sa_lo;
-       u32     sa_hi;
-};
-
-struct cpsw_host_regs {
-       u32     max_blks;
-       u32     blk_cnt;
-       u32     flow_thresh;
-       u32     port_vlan;
-       u32     tx_pri_map;
-       u32     cpdma_tx_pri_map;
-       u32     cpdma_rx_chan_map;
-};
-
-struct cpsw_sliver_regs {
-       u32     id_ver;
-       u32     mac_control;
-       u32     mac_status;
-       u32     soft_reset;
-       u32     rx_maxlen;
-       u32     __reserved_0;
-       u32     rx_pause;
-       u32     tx_pause;
-       u32     __reserved_1;
-       u32     rx_pri_map;
-};
-
-#define ALE_ENTRY_BITS         68
-#define ALE_ENTRY_WORDS                DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
-
-/* ALE Registers */
-#define ALE_CONTROL            0x08
-#define ALE_UNKNOWNVLAN                0x18
-#define ALE_TABLE_CONTROL      0x20
-#define ALE_TABLE              0x34
-#define ALE_PORTCTL            0x40
-
-#define ALE_TABLE_WRITE                BIT(31)
-
-#define ALE_TYPE_FREE                  0
-#define ALE_TYPE_ADDR                  1
-#define ALE_TYPE_VLAN                  2
-#define ALE_TYPE_VLAN_ADDR             3
-
-#define ALE_UCAST_PERSISTANT           0
-#define ALE_UCAST_UNTOUCHED            1
-#define ALE_UCAST_OUI                  2
-#define ALE_UCAST_TOUCHED              3
-
-#define ALE_MCAST_FWD                  0
-#define ALE_MCAST_BLOCK_LEARN_FWD      1
-#define ALE_MCAST_FWD_LEARN            2
-#define ALE_MCAST_FWD_2                        3
-
-enum cpsw_ale_port_state {
-       ALE_PORT_STATE_DISABLE  = 0x00,
-       ALE_PORT_STATE_BLOCK    = 0x01,
-       ALE_PORT_STATE_LEARN    = 0x02,
-       ALE_PORT_STATE_FORWARD  = 0x03,
-};
-
-/* ALE unicast entry flags - passed into cpsw_ale_add_ucast() */
-#define ALE_SECURE     1
-#define ALE_BLOCKED    2
-
-struct cpsw_slave {
-       struct cpsw_slave_regs          *regs;
-       struct cpsw_sliver_regs         *sliver;
-       int                             slave_num;
-       u32                             mac_control;
-       struct cpsw_slave_data          *data;
-};
-
-struct cpdma_desc {
-       /* hardware fields */
-       u32                     hw_next;
-       u32                     hw_buffer;
-       u32                     hw_len;
-       u32                     hw_mode;
-       /* software fields */
-       u32                     sw_buffer;
-       u32                     sw_len;
-};
-
-struct cpdma_chan {
-       struct cpdma_desc       *head, *tail;
-       void                    *hdp, *cp, *rxfree;
-};
-
-/* AM33xx SoC specific definitions for the CONTROL port */
-#define AM33XX_GMII_SEL_MODE_MII       0
-#define AM33XX_GMII_SEL_MODE_RMII      1
-#define AM33XX_GMII_SEL_MODE_RGMII     2
-
-#define AM33XX_GMII_SEL_RGMII1_IDMODE  BIT(4)
-#define AM33XX_GMII_SEL_RGMII2_IDMODE  BIT(5)
-#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN        BIT(6)
-#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN        BIT(7)
-
-#define GMII_SEL_MODE_MASK             0x3
-
-#define desc_write(desc, fld, val)     __raw_writel((u32)(val), &(desc)->fld)
-#define desc_read(desc, fld)           __raw_readl(&(desc)->fld)
-#define desc_read_ptr(desc, fld)       ((void *)__raw_readl(&(desc)->fld))
-
-#define chan_write(chan, fld, val)     __raw_writel((u32)(val), (chan)->fld)
-#define chan_read(chan, fld)           __raw_readl((chan)->fld)
-#define chan_read_ptr(chan, fld)       ((void *)__raw_readl((chan)->fld))
-
-#define for_active_slave(slave, priv) \
-       slave = (priv)->slaves + (priv)->data.active_slave; if (slave)
-#define for_each_slave(slave, priv) \
-       for (slave = (priv)->slaves; slave != (priv)->slaves + \
-                               (priv)->data.slaves; slave++)
-
-struct cpsw_priv {
-#ifdef CONFIG_DM_ETH
-       struct udevice                  *dev;
-#else
-       struct eth_device               *dev;
-#endif
-       struct cpsw_platform_data       data;
-       int                             host_port;
-
-       struct cpsw_regs                *regs;
-       void                            *dma_regs;
-       struct cpsw_host_regs           *host_port_regs;
-       void                            *ale_regs;
-
-       struct cpdma_desc               *descs;
-       struct cpdma_desc               *desc_free;
-       struct cpdma_chan               rx_chan, tx_chan;
-
-       struct cpsw_slave               *slaves;
-       struct phy_device               *phydev;
-       struct mii_dev                  *bus;
-
-       u32                             phy_mask;
-};
-
-static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
-{
-       int idx;
-
-       idx    = start / 32;
-       start -= idx * 32;
-       idx    = 2 - idx; /* flip */
-       return (ale_entry[idx] >> start) & BITMASK(bits);
-}
-
-static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
-                                     u32 value)
-{
-       int idx;
-
-       value &= BITMASK(bits);
-       idx    = start / 32;
-       start -= idx * 32;
-       idx    = 2 - idx; /* flip */
-       ale_entry[idx] &= ~(BITMASK(bits) << start);
-       ale_entry[idx] |=  (value << start);
-}
-
-#define DEFINE_ALE_FIELD(name, start, bits)                            \
-static inline int cpsw_ale_get_##name(u32 *ale_entry)                  \
-{                                                                      \
-       return cpsw_ale_get_field(ale_entry, start, bits);              \
-}                                                                      \
-static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value)      \
-{                                                                      \
-       cpsw_ale_set_field(ale_entry, start, bits, value);              \
-}
-
-DEFINE_ALE_FIELD(entry_type,           60,     2)
-DEFINE_ALE_FIELD(mcast_state,          62,     2)
-DEFINE_ALE_FIELD(port_mask,            66,     3)
-DEFINE_ALE_FIELD(ucast_type,           62,     2)
-DEFINE_ALE_FIELD(port_num,             66,     2)
-DEFINE_ALE_FIELD(blocked,              65,     1)
-DEFINE_ALE_FIELD(secure,               64,     1)
-DEFINE_ALE_FIELD(mcast,                        40,     1)
-
-/* The MAC address field in the ALE entry cannot be macroized as above */
-static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
-{
-       int i;
-
-       for (i = 0; i < 6; i++)
-               addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
-}
-
-static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
-{
-       int i;
-
-       for (i = 0; i < 6; i++)
-               cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
-}
-
-static int cpsw_ale_read(struct cpsw_priv *priv, int idx, u32 *ale_entry)
-{
-       int i;
-
-       __raw_writel(idx, priv->ale_regs + ALE_TABLE_CONTROL);
-
-       for (i = 0; i < ALE_ENTRY_WORDS; i++)
-               ale_entry[i] = __raw_readl(priv->ale_regs + ALE_TABLE + 4 * i);
-
-       return idx;
-}
-
-static int cpsw_ale_write(struct cpsw_priv *priv, int idx, u32 *ale_entry)
-{
-       int i;
-
-       for (i = 0; i < ALE_ENTRY_WORDS; i++)
-               __raw_writel(ale_entry[i], priv->ale_regs + ALE_TABLE + 4 * i);
-
-       __raw_writel(idx | ALE_TABLE_WRITE, priv->ale_regs + ALE_TABLE_CONTROL);
-
-       return idx;
-}
-
-static int cpsw_ale_match_addr(struct cpsw_priv *priv, const u8 *addr)
-{
-       u32 ale_entry[ALE_ENTRY_WORDS];
-       int type, idx;
-
-       for (idx = 0; idx < priv->data.ale_entries; idx++) {
-               u8 entry_addr[6];
-
-               cpsw_ale_read(priv, idx, ale_entry);
-               type = cpsw_ale_get_entry_type(ale_entry);
-               if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
-                       continue;
-               cpsw_ale_get_addr(ale_entry, entry_addr);
-               if (memcmp(entry_addr, addr, 6) == 0)
-                       return idx;
-       }
-       return -ENOENT;
-}
-
-static int cpsw_ale_match_free(struct cpsw_priv *priv)
-{
-       u32 ale_entry[ALE_ENTRY_WORDS];
-       int type, idx;
-
-       for (idx = 0; idx < priv->data.ale_entries; idx++) {
-               cpsw_ale_read(priv, idx, ale_entry);
-               type = cpsw_ale_get_entry_type(ale_entry);
-               if (type == ALE_TYPE_FREE)
-                       return idx;
-       }
-       return -ENOENT;
-}
-
-static int cpsw_ale_find_ageable(struct cpsw_priv *priv)
-{
-       u32 ale_entry[ALE_ENTRY_WORDS];
-       int type, idx;
-
-       for (idx = 0; idx < priv->data.ale_entries; idx++) {
-               cpsw_ale_read(priv, idx, ale_entry);
-               type = cpsw_ale_get_entry_type(ale_entry);
-               if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
-                       continue;
-               if (cpsw_ale_get_mcast(ale_entry))
-                       continue;
-               type = cpsw_ale_get_ucast_type(ale_entry);
-               if (type != ALE_UCAST_PERSISTANT &&
-                   type != ALE_UCAST_OUI)
-                       return idx;
-       }
-       return -ENOENT;
-}
-
-static int cpsw_ale_add_ucast(struct cpsw_priv *priv, const u8 *addr,
-                             int port, int flags)
-{
-       u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
-       int idx;
-
-       cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
-       cpsw_ale_set_addr(ale_entry, addr);
-       cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
-       cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
-       cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
-       cpsw_ale_set_port_num(ale_entry, port);
-
-       idx = cpsw_ale_match_addr(priv, addr);
-       if (idx < 0)
-               idx = cpsw_ale_match_free(priv);
-       if (idx < 0)
-               idx = cpsw_ale_find_ageable(priv);
-       if (idx < 0)
-               return -ENOMEM;
-
-       cpsw_ale_write(priv, idx, ale_entry);
-       return 0;
-}
-
-static int cpsw_ale_add_mcast(struct cpsw_priv *priv, const u8 *addr,
-                             int port_mask)
-{
-       u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
-       int idx, mask;
-
-       idx = cpsw_ale_match_addr(priv, addr);
-       if (idx >= 0)
-               cpsw_ale_read(priv, idx, ale_entry);
-
-       cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
-       cpsw_ale_set_addr(ale_entry, addr);
-       cpsw_ale_set_mcast_state(ale_entry, ALE_MCAST_FWD_2);
-
-       mask = cpsw_ale_get_port_mask(ale_entry);
-       port_mask |= mask;
-       cpsw_ale_set_port_mask(ale_entry, port_mask);
-
-       if (idx < 0)
-               idx = cpsw_ale_match_free(priv);
-       if (idx < 0)
-               idx = cpsw_ale_find_ageable(priv);
-       if (idx < 0)
-               return -ENOMEM;
-
-       cpsw_ale_write(priv, idx, ale_entry);
-       return 0;
-}
-
-static inline void cpsw_ale_control(struct cpsw_priv *priv, int bit, int val)
-{
-       u32 tmp, mask = BIT(bit);
-
-       tmp  = __raw_readl(priv->ale_regs + ALE_CONTROL);
-       tmp &= ~mask;
-       tmp |= val ? mask : 0;
-       __raw_writel(tmp, priv->ale_regs + ALE_CONTROL);
-}
-
-#define cpsw_ale_enable(priv, val)     cpsw_ale_control(priv, 31, val)
-#define cpsw_ale_clear(priv, val)      cpsw_ale_control(priv, 30, val)
-#define cpsw_ale_vlan_aware(priv, val) cpsw_ale_control(priv,  2, val)
-
-static inline void cpsw_ale_port_state(struct cpsw_priv *priv, int port,
-                                      int val)
-{
-       int offset = ALE_PORTCTL + 4 * port;
-       u32 tmp, mask = 0x3;
-
-       tmp  = __raw_readl(priv->ale_regs + offset);
-       tmp &= ~mask;
-       tmp |= val & mask;
-       __raw_writel(tmp, priv->ale_regs + offset);
-}
-
-static struct cpsw_mdio_regs *mdio_regs;
-
-/* wait until hardware is ready for another user access */
-static inline u32 wait_for_user_access(void)
-{
-       u32 reg = 0;
-       int timeout = MDIO_TIMEOUT;
-
-       while (timeout-- &&
-       ((reg = __raw_readl(&mdio_regs->user[0].access)) & USERACCESS_GO))
-               udelay(10);
-
-       if (timeout == -1) {
-               printf("wait_for_user_access Timeout\n");
-               return -ETIMEDOUT;
-       }
-       return reg;
-}
-
-/* wait until hardware state machine is idle */
-static inline void wait_for_idle(void)
-{
-       int timeout = MDIO_TIMEOUT;
-
-       while (timeout-- &&
-               ((__raw_readl(&mdio_regs->control) & CONTROL_IDLE) == 0))
-               udelay(10);
-
-       if (timeout == -1)
-               printf("wait_for_idle Timeout\n");
-}
-
-static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
-                               int dev_addr, int phy_reg)
-{
-       int data;
-       u32 reg;
-
-       if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
-               return -EINVAL;
-
-       wait_for_user_access();
-       reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
-              (phy_id << 16));
-       __raw_writel(reg, &mdio_regs->user[0].access);
-       reg = wait_for_user_access();
-
-       data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
-       return data;
-}
-
-static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
-                               int phy_reg, u16 data)
-{
-       u32 reg;
-
-       if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
-               return -EINVAL;
-
-       wait_for_user_access();
-       reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
-                  (phy_id << 16) | (data & USERACCESS_DATA));
-       __raw_writel(reg, &mdio_regs->user[0].access);
-       wait_for_user_access();
-
-       return 0;
-}
-
-static void cpsw_mdio_init(const char *name, u32 mdio_base, u32 div)
-{
-       struct mii_dev *bus = mdio_alloc();
-
-       mdio_regs = (struct cpsw_mdio_regs *)mdio_base;
-
-       /* set enable and clock divider */
-       __raw_writel(div | CONTROL_ENABLE, &mdio_regs->control);
-
-       /*
-        * wait for scan logic to settle:
-        * the scan time consists of (a) a large fixed component, and (b) a
-        * small component that varies with the mii bus frequency.  These
-        * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
-        * silicon.  Since the effect of (b) was found to be largely
-        * negligible, we keep things simple here.
-        */
-       udelay(1000);
-
-       bus->read = cpsw_mdio_read;
-       bus->write = cpsw_mdio_write;
-       strcpy(bus->name, name);
-
-       mdio_register(bus);
-}
-
-/* Set a self-clearing bit in a register, and wait for it to clear */
-static inline void setbit_and_wait_for_clear32(void *addr)
-{
-       __raw_writel(CLEAR_BIT, addr);
-       while (__raw_readl(addr) & CLEAR_BIT)
-               ;
-}
-
-#define mac_hi(mac)    (((mac)[0] << 0) | ((mac)[1] << 8) |    \
-                        ((mac)[2] << 16) | ((mac)[3] << 24))
-#define mac_lo(mac)    (((mac)[4] << 0) | ((mac)[5] << 8))
-
-static void cpsw_set_slave_mac(struct cpsw_slave *slave,
-                              struct cpsw_priv *priv)
-{
-#ifdef CONFIG_DM_ETH
-       struct eth_pdata *pdata = dev_get_platdata(priv->dev);
-
-       writel(mac_hi(pdata->enetaddr), &slave->regs->sa_hi);
-       writel(mac_lo(pdata->enetaddr), &slave->regs->sa_lo);
-#else
-       __raw_writel(mac_hi(priv->dev->enetaddr), &slave->regs->sa_hi);
-       __raw_writel(mac_lo(priv->dev->enetaddr), &slave->regs->sa_lo);
-#endif
-}
-
-static int cpsw_slave_update_link(struct cpsw_slave *slave,
-                                  struct cpsw_priv *priv, int *link)
-{
-       struct phy_device *phy;
-       u32 mac_control = 0;
-       int ret = -ENODEV;
-
-       phy = priv->phydev;
-       if (!phy)
-               goto out;
-
-       ret = phy_startup(phy);
-       if (ret)
-               goto out;
-
-       if (link)
-               *link = phy->link;
-
-       if (phy->link) { /* link up */
-               mac_control = priv->data.mac_control;
-               if (phy->speed == 1000)
-                       mac_control |= GIGABITEN;
-               if (phy->duplex == DUPLEX_FULL)
-                       mac_control |= FULLDUPLEXEN;
-               if (phy->speed == 100)
-                       mac_control |= MIIEN;
-       }
-
-       if (mac_control == slave->mac_control)
-               goto out;
-
-       if (mac_control) {
-               printf("link up on port %d, speed %d, %s duplex\n",
-                               slave->slave_num, phy->speed,
-                               (phy->duplex == DUPLEX_FULL) ? "full" : "half");
-       } else {
-               printf("link down on port %d\n", slave->slave_num);
-       }
-
-       __raw_writel(mac_control, &slave->sliver->mac_control);
-       slave->mac_control = mac_control;
-
-out:
-       return ret;
-}
-
-static int cpsw_update_link(struct cpsw_priv *priv)
-{
-       int ret = -ENODEV;
-       struct cpsw_slave *slave;
-
-       for_active_slave(slave, priv)
-               ret = cpsw_slave_update_link(slave, priv, NULL);
-
-       return ret;
-}
-
-static inline u32  cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
-{
-       if (priv->host_port == 0)
-               return slave_num + 1;
-       else
-               return slave_num;
-}
-
-static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
-{
-       u32     slave_port;
-
-       setbit_and_wait_for_clear32(&slave->sliver->soft_reset);
-
-       /* setup priority mapping */
-       __raw_writel(0x76543210, &slave->sliver->rx_pri_map);
-       __raw_writel(0x33221100, &slave->regs->tx_pri_map);
-
-       /* setup max packet size, and mac address */
-       __raw_writel(PKT_MAX, &slave->sliver->rx_maxlen);
-       cpsw_set_slave_mac(slave, priv);
-
-       slave->mac_control = 0; /* no link yet */
-
-       /* enable forwarding */
-       slave_port = cpsw_get_slave_port(priv, slave->slave_num);
-       cpsw_ale_port_state(priv, slave_port, ALE_PORT_STATE_FORWARD);
-
-       cpsw_ale_add_mcast(priv, net_bcast_ethaddr, 1 << slave_port);
-
-       priv->phy_mask |= 1 << slave->data->phy_addr;
-}
-
-static struct cpdma_desc *cpdma_desc_alloc(struct cpsw_priv *priv)
-{
-       struct cpdma_desc *desc = priv->desc_free;
-
-       if (desc)
-               priv->desc_free = desc_read_ptr(desc, hw_next);
-       return desc;
-}
-
-static void cpdma_desc_free(struct cpsw_priv *priv, struct cpdma_desc *desc)
-{
-       if (desc) {
-               desc_write(desc, hw_next, priv->desc_free);
-               priv->desc_free = desc;
-       }
-}
-
-static int cpdma_submit(struct cpsw_priv *priv, struct cpdma_chan *chan,
-                       void *buffer, int len)
-{
-       struct cpdma_desc *desc, *prev;
-       u32 mode;
-
-       desc = cpdma_desc_alloc(priv);
-       if (!desc)
-               return -ENOMEM;
-
-       if (len < PKT_MIN)
-               len = PKT_MIN;
-
-       mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
-
-       desc_write(desc, hw_next,   0);
-       desc_write(desc, hw_buffer, buffer);
-       desc_write(desc, hw_len,    len);
-       desc_write(desc, hw_mode,   mode | len);
-       desc_write(desc, sw_buffer, buffer);
-       desc_write(desc, sw_len,    len);
-
-       if (!chan->head) {
-               /* simple case - first packet enqueued */
-               chan->head = desc;
-               chan->tail = desc;
-               chan_write(chan, hdp, desc);
-               goto done;
-       }
-
-       /* not the first packet - enqueue at the tail */
-       prev = chan->tail;
-       desc_write(prev, hw_next, desc);
-       chan->tail = desc;
-
-       /* next check if EOQ has been triggered already */
-       if (desc_read(prev, hw_mode) & CPDMA_DESC_EOQ)
-               chan_write(chan, hdp, desc);
-
-done:
-       if (chan->rxfree)
-               chan_write(chan, rxfree, 1);
-       return 0;
-}
-
-static int cpdma_process(struct cpsw_priv *priv, struct cpdma_chan *chan,
-                        void **buffer, int *len)
-{
-       struct cpdma_desc *desc = chan->head;
-       u32 status;
-
-       if (!desc)
-               return -ENOENT;
-
-       status = desc_read(desc, hw_mode);
-
-       if (len)
-               *len = status & 0x7ff;
-
-       if (buffer)
-               *buffer = desc_read_ptr(desc, sw_buffer);
-
-       if (status & CPDMA_DESC_OWNER) {
-               if (chan_read(chan, hdp) == 0) {
-                       if (desc_read(desc, hw_mode) & CPDMA_DESC_OWNER)
-                               chan_write(chan, hdp, desc);
-               }
-
-               return -EBUSY;
-       }
-
-       chan->head = desc_read_ptr(desc, hw_next);
-       chan_write(chan, cp, desc);
-
-       cpdma_desc_free(priv, desc);
-       return 0;
-}
-
-static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr)
-{
-       struct cpsw_slave       *slave;
-       int i, ret;
-
-       /* soft reset the controller and initialize priv */
-       setbit_and_wait_for_clear32(&priv->regs->soft_reset);
-
-       /* initialize and reset the address lookup engine */
-       cpsw_ale_enable(priv, 1);
-       cpsw_ale_clear(priv, 1);
-       cpsw_ale_vlan_aware(priv, 0); /* vlan unaware mode */
-
-       /* setup host port priority mapping */
-       __raw_writel(0x76543210, &priv->host_port_regs->cpdma_tx_pri_map);
-       __raw_writel(0, &priv->host_port_regs->cpdma_rx_chan_map);
-
-       /* disable priority elevation and enable statistics on all ports */
-       __raw_writel(0, &priv->regs->ptype);
-
-       /* enable statistics collection only on the host port */
-       __raw_writel(BIT(priv->host_port), &priv->regs->stat_port_en);
-       __raw_writel(0x7, &priv->regs->stat_port_en);
-
-       cpsw_ale_port_state(priv, priv->host_port, ALE_PORT_STATE_FORWARD);
-
-       cpsw_ale_add_ucast(priv, enetaddr, priv->host_port, ALE_SECURE);
-       cpsw_ale_add_mcast(priv, net_bcast_ethaddr, 1 << priv->host_port);
-
-       for_active_slave(slave, priv)
-               cpsw_slave_init(slave, priv);
-
-       ret = cpsw_update_link(priv);
-       if (ret)
-               goto out;
-
-       /* init descriptor pool */
-       for (i = 0; i < NUM_DESCS; i++) {
-               desc_write(&priv->descs[i], hw_next,
-                          (i == (NUM_DESCS - 1)) ? 0 : &priv->descs[i+1]);
-       }
-       priv->desc_free = &priv->descs[0];
-
-       /* initialize channels */
-       if (priv->data.version == CPSW_CTRL_VERSION_2) {
-               memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
-               priv->rx_chan.hdp       = priv->dma_regs + CPDMA_RXHDP_VER2;
-               priv->rx_chan.cp        = priv->dma_regs + CPDMA_RXCP_VER2;
-               priv->rx_chan.rxfree    = priv->dma_regs + CPDMA_RXFREE;
-
-               memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
-               priv->tx_chan.hdp       = priv->dma_regs + CPDMA_TXHDP_VER2;
-               priv->tx_chan.cp        = priv->dma_regs + CPDMA_TXCP_VER2;
-       } else {
-               memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
-               priv->rx_chan.hdp       = priv->dma_regs + CPDMA_RXHDP_VER1;
-               priv->rx_chan.cp        = priv->dma_regs + CPDMA_RXCP_VER1;
-               priv->rx_chan.rxfree    = priv->dma_regs + CPDMA_RXFREE;
-
-               memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
-               priv->tx_chan.hdp       = priv->dma_regs + CPDMA_TXHDP_VER1;
-               priv->tx_chan.cp        = priv->dma_regs + CPDMA_TXCP_VER1;
-       }
-
-       /* clear dma state */
-       setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET);
-
-       if (priv->data.version == CPSW_CTRL_VERSION_2) {
-               for (i = 0; i < priv->data.channels; i++) {
-                       __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER2 + 4
-                                       * i);
-                       __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
-                                       * i);
-                       __raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER2 + 4
-                                       * i);
-                       __raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER2 + 4
-                                       * i);
-                       __raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER2 + 4
-                                       * i);
-               }
-       } else {
-               for (i = 0; i < priv->data.channels; i++) {
-                       __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER1 + 4
-                                       * i);
-                       __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
-                                       * i);
-                       __raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER1 + 4
-                                       * i);
-                       __raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER1 + 4
-                                       * i);
-                       __raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER1 + 4
-                                       * i);
-
-               }
-       }
-
-       __raw_writel(1, priv->dma_regs + CPDMA_TXCONTROL);
-       __raw_writel(1, priv->dma_regs + CPDMA_RXCONTROL);
-
-       /* submit rx descs */
-       for (i = 0; i < PKTBUFSRX; i++) {
-               ret = cpdma_submit(priv, &priv->rx_chan, net_rx_packets[i],
-                                  PKTSIZE);
-               if (ret < 0) {
-                       printf("error %d submitting rx desc\n", ret);
-                       break;
-               }
-       }
-
-out:
-       return ret;
-}
-
-static int cpsw_reap_completed_packets(struct cpsw_priv *priv)
-{
-       int timeout = CPDMA_TIMEOUT;
-
-       /* reap completed packets */
-       while (timeout-- &&
-              (cpdma_process(priv, &priv->tx_chan, NULL, NULL) >= 0))
-               ;
-
-       return timeout;
-}
-
-static void _cpsw_halt(struct cpsw_priv *priv)
-{
-       cpsw_reap_completed_packets(priv);
-
-       writel(0, priv->dma_regs + CPDMA_TXCONTROL);
-       writel(0, priv->dma_regs + CPDMA_RXCONTROL);
-
-       /* soft reset the controller and initialize priv */
-       setbit_and_wait_for_clear32(&priv->regs->soft_reset);
-
-       /* clear dma state */
-       setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET);
-
-}
-
-static int _cpsw_send(struct cpsw_priv *priv, void *packet, int length)
-{
-       int timeout;
-
-       flush_dcache_range((unsigned long)packet,
-                          (unsigned long)packet + ALIGN(length, PKTALIGN));
-
-       timeout = cpsw_reap_completed_packets(priv);
-       if (timeout == -1) {
-               printf("cpdma_process timeout\n");
-               return -ETIMEDOUT;
-       }
-
-       return cpdma_submit(priv, &priv->tx_chan, packet, length);
-}
-
-static int _cpsw_recv(struct cpsw_priv *priv, uchar **pkt)
-{
-       void *buffer;
-       int len;
-       int ret;
-
-       ret = cpdma_process(priv, &priv->rx_chan, &buffer, &len);
-       if (ret < 0)
-               return ret;
-
-       invalidate_dcache_range((unsigned long)buffer,
-                               (unsigned long)buffer + PKTSIZE_ALIGN);
-       *pkt = buffer;
-
-       return len;
-}
-
-static void cpsw_slave_setup(struct cpsw_slave *slave, int slave_num,
-                           struct cpsw_priv *priv)
-{
-       void                    *regs = priv->regs;
-       struct cpsw_slave_data  *data = priv->data.slave_data + slave_num;
-       slave->slave_num = slave_num;
-       slave->data     = data;
-       slave->regs     = regs + data->slave_reg_ofs;
-       slave->sliver   = regs + data->sliver_reg_ofs;
-}
-
-static int cpsw_phy_init(struct cpsw_priv *priv, struct cpsw_slave *slave)
-{
-       struct phy_device *phydev;
-       u32 supported = PHY_GBIT_FEATURES;
-
-       phydev = phy_connect(priv->bus,
-                       slave->data->phy_addr,
-                       priv->dev,
-                       slave->data->phy_if);
-
-       if (!phydev)
-               return -1;
-
-       phydev->supported &= supported;
-       phydev->advertising = phydev->supported;
-
-#ifdef CONFIG_DM_ETH
-       if (slave->data->phy_of_handle)
-               phydev->node = offset_to_ofnode(slave->data->phy_of_handle);
-#endif
-
-       priv->phydev = phydev;
-       phy_config(phydev);
-
-       return 1;
-}
-
-static void cpsw_phy_addr_update(struct cpsw_priv *priv)
-{
-       struct cpsw_platform_data *data = &priv->data;
-       u16 alive = mdio_regs->alive & GENMASK(15, 0);
-       int active = data->active_slave;
-       int new_addr = ffs(alive) - 1;
-
-       /*
-        * If there is only one phy alive and its address does not match
-        * that of active slave, then phy address can safely be updated.
-        */
-       if (hweight16(alive) == 1 &&
-           data->slave_data[active].phy_addr != new_addr) {
-               printf("Updated phy address for CPSW#%d, old: %d, new: %d\n",
-                      active, data->slave_data[active].phy_addr, new_addr);
-               data->slave_data[active].phy_addr = new_addr;
-       }
-}
-
-int _cpsw_register(struct cpsw_priv *priv)
-{
-       struct cpsw_slave       *slave;
-       struct cpsw_platform_data *data = &priv->data;
-       void                    *regs = (void *)data->cpsw_base;
-
-       priv->slaves = malloc(sizeof(struct cpsw_slave) * data->slaves);
-       if (!priv->slaves) {
-               return -ENOMEM;
-       }
-
-       priv->host_port         = data->host_port_num;
-       priv->regs              = regs;
-       priv->host_port_regs    = regs + data->host_port_reg_ofs;
-       priv->dma_regs          = regs + data->cpdma_reg_ofs;
-       priv->ale_regs          = regs + data->ale_reg_ofs;
-       priv->descs             = (void *)regs + data->bd_ram_ofs;
-
-       int idx = 0;
-
-       for_each_slave(slave, priv) {
-               cpsw_slave_setup(slave, idx, priv);
-               idx = idx + 1;
-       }
-
-       cpsw_mdio_init(priv->dev->name, data->mdio_base, data->mdio_div);
-
-       cpsw_phy_addr_update(priv);
-
-       priv->bus = miiphy_get_dev_by_name(priv->dev->name);
-       for_active_slave(slave, priv)
-               cpsw_phy_init(priv, slave);
-
-       return 0;
-}
-
-#ifndef CONFIG_DM_ETH
-static int cpsw_init(struct eth_device *dev, bd_t *bis)
-{
-       struct cpsw_priv        *priv = dev->priv;
-
-       return _cpsw_init(priv, dev->enetaddr);
-}
-
-static void cpsw_halt(struct eth_device *dev)
-{
-       struct cpsw_priv *priv = dev->priv;
-
-       return _cpsw_halt(priv);
-}
-
-static int cpsw_send(struct eth_device *dev, void *packet, int length)
-{
-       struct cpsw_priv        *priv = dev->priv;
-
-       return _cpsw_send(priv, packet, length);
-}
-
-static int cpsw_recv(struct eth_device *dev)
-{
-       struct cpsw_priv *priv = dev->priv;
-       uchar *pkt = NULL;
-       int len;
-
-       len = _cpsw_recv(priv, &pkt);
-
-       if (len > 0) {
-               net_process_received_packet(pkt, len);
-               cpdma_submit(priv, &priv->rx_chan, pkt, PKTSIZE);
-       }
-
-       return len;
-}
-
-int cpsw_register(struct cpsw_platform_data *data)
-{
-       struct cpsw_priv        *priv;
-       struct eth_device       *dev;
-       int ret;
-
-       dev = calloc(sizeof(*dev), 1);
-       if (!dev)
-               return -ENOMEM;
-
-       priv = calloc(sizeof(*priv), 1);
-       if (!priv) {
-               free(dev);
-               return -ENOMEM;
-       }
-
-       priv->dev = dev;
-       priv->data = *data;
-
-       strcpy(dev->name, "cpsw");
-       dev->iobase     = 0;
-       dev->init       = cpsw_init;
-       dev->halt       = cpsw_halt;
-       dev->send       = cpsw_send;
-       dev->recv       = cpsw_recv;
-       dev->priv       = priv;
-
-       eth_register(dev);
-
-       ret = _cpsw_register(priv);
-       if (ret < 0) {
-               eth_unregister(dev);
-               free(dev);
-               free(priv);
-               return ret;
-       }
-
-       return 1;
-}
-#else
-static int cpsw_eth_start(struct udevice *dev)
-{
-       struct eth_pdata *pdata = dev_get_platdata(dev);
-       struct cpsw_priv *priv = dev_get_priv(dev);
-
-       return _cpsw_init(priv, pdata->enetaddr);
-}
-
-static int cpsw_eth_send(struct udevice *dev, void *packet, int length)
-{
-       struct cpsw_priv *priv = dev_get_priv(dev);
-
-       return _cpsw_send(priv, packet, length);
-}
-
-static int cpsw_eth_recv(struct udevice *dev, int flags, uchar **packetp)
-{
-       struct cpsw_priv *priv = dev_get_priv(dev);
-
-       return _cpsw_recv(priv, packetp);
-}
-
-static int cpsw_eth_free_pkt(struct udevice *dev, uchar *packet,
-                                  int length)
-{
-       struct cpsw_priv *priv = dev_get_priv(dev);
-
-       return cpdma_submit(priv, &priv->rx_chan, packet, PKTSIZE);
-}
-
-static void cpsw_eth_stop(struct udevice *dev)
-{
-       struct cpsw_priv *priv = dev_get_priv(dev);
-
-       return _cpsw_halt(priv);
-}
-
-
-static int cpsw_eth_probe(struct udevice *dev)
-{
-       struct cpsw_priv *priv = dev_get_priv(dev);
-
-       priv->dev = dev;
-
-       return _cpsw_register(priv);
-}
-
-static const struct eth_ops cpsw_eth_ops = {
-       .start          = cpsw_eth_start,
-       .send           = cpsw_eth_send,
-       .recv           = cpsw_eth_recv,
-       .free_pkt       = cpsw_eth_free_pkt,
-       .stop           = cpsw_eth_stop,
-};
-
-static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node)
-{
-       return fdtdec_get_addr_size_auto_noparent(fdt, node, "reg", 0, NULL,
-                                                 false);
-}
-
-static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv,
-                                phy_interface_t phy_mode)
-{
-       u32 reg;
-       u32 mask;
-       u32 mode = 0;
-       bool rgmii_id = false;
-       int slave = priv->data.active_slave;
-
-       reg = readl(priv->data.gmii_sel);
-
-       switch (phy_mode) {
-       case PHY_INTERFACE_MODE_RMII:
-               mode = AM33XX_GMII_SEL_MODE_RMII;
-               break;
-
-       case PHY_INTERFACE_MODE_RGMII:
-               mode = AM33XX_GMII_SEL_MODE_RGMII;
-               break;
-       case PHY_INTERFACE_MODE_RGMII_ID:
-       case PHY_INTERFACE_MODE_RGMII_RXID:
-       case PHY_INTERFACE_MODE_RGMII_TXID:
-               mode = AM33XX_GMII_SEL_MODE_RGMII;
-               rgmii_id = true;
-               break;
-
-       case PHY_INTERFACE_MODE_MII:
-       default:
-               mode = AM33XX_GMII_SEL_MODE_MII;
-               break;
-       };
-
-       mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6);
-       mode <<= slave * 2;
-
-       if (priv->data.rmii_clock_external) {
-               if (slave == 0)
-                       mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
-               else
-                       mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
-       }
-
-       if (rgmii_id) {
-               if (slave == 0)
-                       mode |= AM33XX_GMII_SEL_RGMII1_IDMODE;
-               else
-                       mode |= AM33XX_GMII_SEL_RGMII2_IDMODE;
-       }
-
-       reg &= ~mask;
-       reg |= mode;
-
-       writel(reg, priv->data.gmii_sel);
-}
-
-static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv,
-                                phy_interface_t phy_mode)
-{
-       u32 reg;
-       u32 mask;
-       u32 mode = 0;
-       int slave = priv->data.active_slave;
-
-       reg = readl(priv->data.gmii_sel);
-
-       switch (phy_mode) {
-       case PHY_INTERFACE_MODE_RMII:
-               mode = AM33XX_GMII_SEL_MODE_RMII;
-               break;
-
-       case PHY_INTERFACE_MODE_RGMII:
-       case PHY_INTERFACE_MODE_RGMII_ID:
-       case PHY_INTERFACE_MODE_RGMII_RXID:
-       case PHY_INTERFACE_MODE_RGMII_TXID:
-               mode = AM33XX_GMII_SEL_MODE_RGMII;
-               break;
-
-       case PHY_INTERFACE_MODE_MII:
-       default:
-               mode = AM33XX_GMII_SEL_MODE_MII;
-               break;
-       };
-
-       switch (slave) {
-       case 0:
-               mask = GMII_SEL_MODE_MASK;
-               break;
-       case 1:
-               mask = GMII_SEL_MODE_MASK << 4;
-               mode <<= 4;
-               break;
-       default:
-               dev_err(priv->dev, "invalid slave number...\n");
-               return;
-       }
-
-       if (priv->data.rmii_clock_external)
-               dev_err(priv->dev, "RMII External clock is not supported\n");
-
-       reg &= ~mask;
-       reg |= mode;
-
-       writel(reg, priv->data.gmii_sel);
-}
-
-static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat,
-                        phy_interface_t phy_mode)
-{
-       if (!strcmp(compat, "ti,am3352-cpsw-phy-sel"))
-               cpsw_gmii_sel_am3352(priv, phy_mode);
-       if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel"))
-               cpsw_gmii_sel_am3352(priv, phy_mode);
-       else if (!strcmp(compat, "ti,dra7xx-cpsw-phy-sel"))
-               cpsw_gmii_sel_dra7xx(priv, phy_mode);
-}
-
-static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
-{
-       struct eth_pdata *pdata = dev_get_platdata(dev);
-       struct cpsw_priv *priv = dev_get_priv(dev);
-       struct gpio_desc *mode_gpios;
-       const char *phy_mode;
-       const char *phy_sel_compat = NULL;
-       const void *fdt = gd->fdt_blob;
-       int node = dev_of_offset(dev);
-       int subnode;
-       int slave_index = 0;
-       int active_slave;
-       int num_mode_gpios;
-       int ret;
-
-       pdata->iobase = devfdt_get_addr(dev);
-       priv->data.version = CPSW_CTRL_VERSION_2;
-       priv->data.bd_ram_ofs = CPSW_BD_OFFSET;
-       priv->data.ale_reg_ofs = CPSW_ALE_OFFSET;
-       priv->data.cpdma_reg_ofs = CPSW_CPDMA_OFFSET;
-       priv->data.mdio_div = CPSW_MDIO_DIV;
-       priv->data.host_port_reg_ofs = CPSW_HOST_PORT_OFFSET,
-
-       pdata->phy_interface = -1;
-
-       priv->data.cpsw_base = pdata->iobase;
-       priv->data.channels = fdtdec_get_int(fdt, node, "cpdma_channels", -1);
-       if (priv->data.channels <= 0) {
-               printf("error: cpdma_channels not found in dt\n");
-               return -ENOENT;
-       }
-
-       priv->data.slaves = fdtdec_get_int(fdt, node, "slaves", -1);
-       if (priv->data.slaves <= 0) {
-               printf("error: slaves not found in dt\n");
-               return -ENOENT;
-       }
-       priv->data.slave_data = malloc(sizeof(struct cpsw_slave_data) *
-                                      priv->data.slaves);
-
-       priv->data.ale_entries = fdtdec_get_int(fdt, node, "ale_entries", -1);
-       if (priv->data.ale_entries <= 0) {
-               printf("error: ale_entries not found in dt\n");
-               return -ENOENT;
-       }
-
-       priv->data.bd_ram_ofs = fdtdec_get_int(fdt, node, "bd_ram_size", -1);
-       if (priv->data.bd_ram_ofs <= 0) {
-               printf("error: bd_ram_size not found in dt\n");
-               return -ENOENT;
-       }
-
-       priv->data.mac_control = fdtdec_get_int(fdt, node, "mac_control", -1);
-       if (priv->data.mac_control <= 0) {
-               printf("error: ale_entries not found in dt\n");
-               return -ENOENT;
-       }
-
-       num_mode_gpios = gpio_get_list_count(dev, "mode-gpios");
-       if (num_mode_gpios > 0) {
-               mode_gpios = malloc(sizeof(struct gpio_desc) *
-                                   num_mode_gpios);
-               gpio_request_list_by_name(dev, "mode-gpios", mode_gpios,
-                                         num_mode_gpios, GPIOD_IS_OUT);
-               free(mode_gpios);
-       }
-
-       active_slave = fdtdec_get_int(fdt, node, "active_slave", 0);
-       priv->data.active_slave = active_slave;
-
-       fdt_for_each_subnode(subnode, fdt, node) {
-               int len;
-               const char *name;
-
-               name = fdt_get_name(fdt, subnode, &len);
-               if (!strncmp(name, "mdio", 4)) {
-                       u32 mdio_base;
-
-                       mdio_base = cpsw_get_addr_by_node(fdt, subnode);
-                       if (mdio_base == FDT_ADDR_T_NONE) {
-                               pr_err("Not able to get MDIO address space\n");
-                               return -ENOENT;
-                       }
-                       priv->data.mdio_base = mdio_base;
-               }
-
-               if (!strncmp(name, "slave", 5)) {
-                       u32 phy_id[2];
-
-                       if (slave_index >= priv->data.slaves)
-                               continue;
-                       phy_mode = fdt_getprop(fdt, subnode, "phy-mode", NULL);
-                       if (phy_mode)
-                               priv->data.slave_data[slave_index].phy_if =
-                                       phy_get_interface_by_name(phy_mode);
-
-                       priv->data.slave_data[slave_index].phy_of_handle =
-                               fdtdec_lookup_phandle(fdt, subnode,
-                                                     "phy-handle");
-
-                       if (priv->data.slave_data[slave_index].phy_of_handle >= 0) {
-                               priv->data.slave_data[slave_index].phy_addr =
-                                               fdtdec_get_int(gd->fdt_blob,
-                                                              priv->data.slave_data[slave_index].phy_of_handle,
-                                                              "reg", -1);
-                       } else {
-                               fdtdec_get_int_array(fdt, subnode, "phy_id",
-                                                    phy_id, 2);
-                               priv->data.slave_data[slave_index].phy_addr =
-                                               phy_id[1];
-                       }
-                       slave_index++;
-               }
-
-               if (!strncmp(name, "cpsw-phy-sel", 12)) {
-                       priv->data.gmii_sel = cpsw_get_addr_by_node(fdt,
-                                                                   subnode);
-
-                       if (priv->data.gmii_sel == FDT_ADDR_T_NONE) {
-                               pr_err("Not able to get gmii_sel reg address\n");
-                               return -ENOENT;
-                       }
-
-                       if (fdt_get_property(fdt, subnode, "rmii-clock-ext",
-                                            NULL))
-                               priv->data.rmii_clock_external = true;
-
-                       phy_sel_compat = fdt_getprop(fdt, subnode, "compatible",
-                                                    NULL);
-                       if (!phy_sel_compat) {
-                               pr_err("Not able to get gmii_sel compatible\n");
-                               return -ENOENT;
-                       }
-               }
-       }
-
-       priv->data.slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET;
-       priv->data.slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET;
-
-       if (priv->data.slaves == 2) {
-               priv->data.slave_data[1].slave_reg_ofs = CPSW_SLAVE1_OFFSET;
-               priv->data.slave_data[1].sliver_reg_ofs = CPSW_SLIVER1_OFFSET;
-       }
-
-       ret = ti_cm_get_macid(dev, active_slave, pdata->enetaddr);
-       if (ret < 0) {
-               pr_err("cpsw read efuse mac failed\n");
-               return ret;
-       }
-
-       pdata->phy_interface = priv->data.slave_data[active_slave].phy_if;
-       if (pdata->phy_interface == -1) {
-               debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
-               return -EINVAL;
-       }
-
-       /* Select phy interface in control module */
-       cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface);
-
-       return 0;
-}
-
-int cpsw_get_slave_phy_addr(struct udevice *dev, int slave)
-{
-       struct cpsw_priv *priv = dev_get_priv(dev);
-       struct cpsw_platform_data *data = &priv->data;
-
-       return data->slave_data[slave].phy_addr;
-}
-
-static const struct udevice_id cpsw_eth_ids[] = {
-       { .compatible = "ti,cpsw" },
-       { .compatible = "ti,am335x-cpsw" },
-       { }
-};
-
-U_BOOT_DRIVER(eth_cpsw) = {
-       .name   = "eth_cpsw",
-       .id     = UCLASS_ETH,
-       .of_match = cpsw_eth_ids,
-       .ofdata_to_platdata = cpsw_eth_ofdata_to_platdata,
-       .probe  = cpsw_eth_probe,
-       .ops    = &cpsw_eth_ops,
-       .priv_auto_alloc_size = sizeof(struct cpsw_priv),
-       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
-       .flags = DM_FLAG_ALLOC_PRIV_DMA,
-};
-#endif /* CONFIG_DM_ETH */
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
deleted file mode 100644 (file)
index bb879d8..0000000
+++ /dev/null
@@ -1,901 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Ethernet driver for TI TMS320DM644x (DaVinci) chips.
- *
- * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
- *
- * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright
- * follows:
- *
- * ----------------------------------------------------------------------------
- *
- * dm644x_emac.c
- *
- * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM
- *
- * Copyright (C) 2005 Texas Instruments.
- *
- * ----------------------------------------------------------------------------
- *
- * Modifications:
- * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot.
- * ver  1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors
- */
-#include <common.h>
-#include <command.h>
-#include <net.h>
-#include <miiphy.h>
-#include <malloc.h>
-#include <netdev.h>
-#include <linux/compiler.h>
-#include <asm/arch/emac_defs.h>
-#include <asm/io.h>
-#include "davinci_emac.h"
-
-unsigned int   emac_dbg = 0;
-#define debug_emac(fmt,args...)        if (emac_dbg) printf(fmt,##args)
-
-#ifdef EMAC_HW_RAM_ADDR
-static inline unsigned long BD_TO_HW(unsigned long x)
-{
-       if (x == 0)
-               return 0;
-
-       return x - EMAC_WRAPPER_RAM_ADDR + EMAC_HW_RAM_ADDR;
-}
-
-static inline unsigned long HW_TO_BD(unsigned long x)
-{
-       if (x == 0)
-               return 0;
-
-       return x - EMAC_HW_RAM_ADDR + EMAC_WRAPPER_RAM_ADDR;
-}
-#else
-#define BD_TO_HW(x)    (x)
-#define HW_TO_BD(x)    (x)
-#endif
-
-#ifdef DAVINCI_EMAC_GIG_ENABLE
-#define emac_gigabit_enable(phy_addr)  davinci_eth_gigabit_enable(phy_addr)
-#else
-#define emac_gigabit_enable(phy_addr)  /* no gigabit to enable */
-#endif
-
-#if !defined(CONFIG_SYS_EMAC_TI_CLKDIV)
-#define CONFIG_SYS_EMAC_TI_CLKDIV      ((EMAC_MDIO_BUS_FREQ / \
-               EMAC_MDIO_CLOCK_FREQ) - 1)
-#endif
-
-static void davinci_eth_mdio_enable(void);
-
-static int gen_init_phy(int phy_addr);
-static int gen_is_phy_connected(int phy_addr);
-static int gen_get_link_speed(int phy_addr);
-static int gen_auto_negotiate(int phy_addr);
-
-void eth_mdio_enable(void)
-{
-       davinci_eth_mdio_enable();
-}
-
-/* EMAC Addresses */
-static volatile emac_regs      *adap_emac = (emac_regs *)EMAC_BASE_ADDR;
-static volatile ewrap_regs     *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
-static volatile mdio_regs      *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR;
-
-/* EMAC descriptors */
-static volatile emac_desc      *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE);
-static volatile emac_desc      *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
-static volatile emac_desc      *emac_rx_active_head = 0;
-static volatile emac_desc      *emac_rx_active_tail = 0;
-static int                     emac_rx_queue_active = 0;
-
-/* Receive packet buffers */
-static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * EMAC_RXBUF_SIZE]
-                               __aligned(ARCH_DMA_MINALIGN);
-
-#ifndef CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT
-#define CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT      3
-#endif
-
-/* PHY address for a discovered PHY (0xff - not found) */
-static u_int8_t        active_phy_addr[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT];
-
-/* number of PHY found active */
-static u_int8_t        num_phy;
-
-phy_t                          phy[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT];
-
-static int davinci_eth_set_mac_addr(struct eth_device *dev)
-{
-       unsigned long           mac_hi;
-       unsigned long           mac_lo;
-
-       /*
-        * Set MAC Addresses & Init multicast Hash to 0 (disable any multicast
-        * receive)
-        *  Using channel 0 only - other channels are disabled
-        *  */
-       writel(0, &adap_emac->MACINDEX);
-       mac_hi = (dev->enetaddr[3] << 24) |
-                (dev->enetaddr[2] << 16) |
-                (dev->enetaddr[1] << 8)  |
-                (dev->enetaddr[0]);
-       mac_lo = (dev->enetaddr[5] << 8) |
-                (dev->enetaddr[4]);
-
-       writel(mac_hi, &adap_emac->MACADDRHI);
-#if defined(DAVINCI_EMAC_VERSION2)
-       writel(mac_lo | EMAC_MAC_ADDR_IS_VALID | EMAC_MAC_ADDR_MATCH,
-              &adap_emac->MACADDRLO);
-#else
-       writel(mac_lo, &adap_emac->MACADDRLO);
-#endif
-
-       writel(0, &adap_emac->MACHASH1);
-       writel(0, &adap_emac->MACHASH2);
-
-       /* Set source MAC address - REQUIRED */
-       writel(mac_hi, &adap_emac->MACSRCADDRHI);
-       writel(mac_lo, &adap_emac->MACSRCADDRLO);
-
-
-       return 0;
-}
-
-static void davinci_eth_mdio_enable(void)
-{
-       u_int32_t       clkdiv;
-
-       clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV;
-
-       writel((clkdiv & 0xff) |
-              MDIO_CONTROL_ENABLE |
-              MDIO_CONTROL_FAULT |
-              MDIO_CONTROL_FAULT_ENABLE,
-              &adap_mdio->CONTROL);
-
-       while (readl(&adap_mdio->CONTROL) & MDIO_CONTROL_IDLE)
-               ;
-}
-
-/*
- * Tries to find an active connected PHY. Returns 1 if address if found.
- * If no active PHY (or more than one PHY) found returns 0.
- * Sets active_phy_addr variable.
- */
-static int davinci_eth_phy_detect(void)
-{
-       u_int32_t       phy_act_state;
-       int             i;
-       int             j;
-       unsigned int    count = 0;
-
-       for (i = 0; i < CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT; i++)
-               active_phy_addr[i] = 0xff;
-
-       udelay(1000);
-       phy_act_state = readl(&adap_mdio->ALIVE);
-
-       if (phy_act_state == 0)
-               return 0;               /* No active PHYs */
-
-       debug_emac("davinci_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state);
-
-       for (i = 0, j = 0; i < 32; i++)
-               if (phy_act_state & (1 << i)) {
-                       count++;
-                       if (count <= CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT) {
-                               active_phy_addr[j++] = i;
-                       } else {
-                               printf("%s: to many PHYs detected.\n",
-                                       __func__);
-                               count = 0;
-                               break;
-                       }
-               }
-
-       num_phy = count;
-
-       return count;
-}
-
-
-/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
-int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
-{
-       int     tmp;
-
-       while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
-               ;
-
-       writel(MDIO_USERACCESS0_GO |
-              MDIO_USERACCESS0_WRITE_READ |
-              ((reg_num & 0x1f) << 21) |
-              ((phy_addr & 0x1f) << 16),
-              &adap_mdio->USERACCESS0);
-
-       /* Wait for command to complete */
-       while ((tmp = readl(&adap_mdio->USERACCESS0)) & MDIO_USERACCESS0_GO)
-               ;
-
-       if (tmp & MDIO_USERACCESS0_ACK) {
-               *data = tmp & 0xffff;
-               return 1;
-       }
-
-       return 0;
-}
-
-/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
-int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
-{
-
-       while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
-               ;
-
-       writel(MDIO_USERACCESS0_GO |
-              MDIO_USERACCESS0_WRITE_WRITE |
-              ((reg_num & 0x1f) << 21) |
-              ((phy_addr & 0x1f) << 16) |
-              (data & 0xffff),
-              &adap_mdio->USERACCESS0);
-
-       /* Wait for command to complete */
-       while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
-               ;
-
-       return 1;
-}
-
-/* PHY functions for a generic PHY */
-static int gen_init_phy(int phy_addr)
-{
-       int     ret = 1;
-
-       if (gen_get_link_speed(phy_addr)) {
-               /* Try another time */
-               ret = gen_get_link_speed(phy_addr);
-       }
-
-       return(ret);
-}
-
-static int gen_is_phy_connected(int phy_addr)
-{
-       u_int16_t       dummy;
-
-       return davinci_eth_phy_read(phy_addr, MII_PHYSID1, &dummy);
-}
-
-static int get_active_phy(void)
-{
-       int i;
-
-       for (i = 0; i < num_phy; i++)
-               if (phy[i].get_link_speed(active_phy_addr[i]))
-                       return i;
-
-       return -1;      /* Return error if no link */
-}
-
-static int gen_get_link_speed(int phy_addr)
-{
-       u_int16_t       tmp;
-
-       if (davinci_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) &&
-                       (tmp & 0x04)) {
-#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
-               defined(CONFIG_MACH_DAVINCI_DA850_EVM)
-               davinci_eth_phy_read(phy_addr, MII_LPA, &tmp);
-
-               /* Speed doesn't matter, there is no setting for it in EMAC. */
-               if (tmp & (LPA_100FULL | LPA_10FULL)) {
-                       /* set EMAC for Full Duplex  */
-                       writel(EMAC_MACCONTROL_MIIEN_ENABLE |
-                                       EMAC_MACCONTROL_FULLDUPLEX_ENABLE,
-                                       &adap_emac->MACCONTROL);
-               } else {
-                       /*set EMAC for Half Duplex  */
-                       writel(EMAC_MACCONTROL_MIIEN_ENABLE,
-                                       &adap_emac->MACCONTROL);
-               }
-
-               if (tmp & (LPA_100FULL | LPA_100HALF))
-                       writel(readl(&adap_emac->MACCONTROL) |
-                                       EMAC_MACCONTROL_RMIISPEED_100,
-                                        &adap_emac->MACCONTROL);
-               else
-                       writel(readl(&adap_emac->MACCONTROL) &
-                                       ~EMAC_MACCONTROL_RMIISPEED_100,
-                                        &adap_emac->MACCONTROL);
-#endif
-               return(1);
-       }
-
-       return(0);
-}
-
-static int gen_auto_negotiate(int phy_addr)
-{
-       u_int16_t       tmp;
-       u_int16_t       val;
-       unsigned long   cntr = 0;
-
-       if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp))
-               return 0;
-
-       val = tmp | BMCR_FULLDPLX | BMCR_ANENABLE |
-                                               BMCR_SPEED100;
-       davinci_eth_phy_write(phy_addr, MII_BMCR, val);
-
-       if (!davinci_eth_phy_read(phy_addr, MII_ADVERTISE, &val))
-               return 0;
-
-       val |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL |
-                                                       ADVERTISE_10HALF);
-       davinci_eth_phy_write(phy_addr, MII_ADVERTISE, val);
-
-       if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp))
-               return(0);
-
-#ifdef DAVINCI_EMAC_GIG_ENABLE
-       davinci_eth_phy_read(phy_addr, MII_CTRL1000, &val);
-       val |= PHY_1000BTCR_1000FD;
-       val &= ~PHY_1000BTCR_1000HD;
-       davinci_eth_phy_write(phy_addr, MII_CTRL1000, val);
-       davinci_eth_phy_read(phy_addr, MII_CTRL1000, &val);
-#endif
-
-       /* Restart Auto_negotiation  */
-       tmp |= BMCR_ANRESTART;
-       davinci_eth_phy_write(phy_addr, MII_BMCR, tmp);
-
-       /*check AutoNegotiate complete */
-       do {
-               udelay(40000);
-               if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp))
-                       return 0;
-
-               if (tmp & BMSR_ANEGCOMPLETE)
-                       break;
-
-               cntr++;
-       } while (cntr < 200);
-
-       if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp))
-               return(0);
-
-       if (!(tmp & BMSR_ANEGCOMPLETE))
-               return(0);
-
-       return(gen_get_link_speed(phy_addr));
-}
-/* End of generic PHY functions */
-
-
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-static int davinci_mii_phy_read(struct mii_dev *bus, int addr, int devad,
-                               int reg)
-{
-       unsigned short value = 0;
-       int retval = davinci_eth_phy_read(addr, reg, &value);
-
-       return retval ? value : -EIO;
-}
-
-static int davinci_mii_phy_write(struct mii_dev *bus, int addr, int devad,
-                                int reg, u16 value)
-{
-       return davinci_eth_phy_write(addr, reg, value) ? 0 : 1;
-}
-#endif
-
-static void  __attribute__((unused)) davinci_eth_gigabit_enable(int phy_addr)
-{
-       u_int16_t data;
-
-       if (davinci_eth_phy_read(phy_addr, 0, &data)) {
-               if (data & (1 << 6)) { /* speed selection MSB */
-                       /*
-                        * Check if link detected is giga-bit
-                        * If Gigabit mode detected, enable gigbit in MAC
-                        */
-                       writel(readl(&adap_emac->MACCONTROL) |
-                               EMAC_MACCONTROL_GIGFORCE |
-                               EMAC_MACCONTROL_GIGABIT_ENABLE,
-                               &adap_emac->MACCONTROL);
-               }
-       }
-}
-
-/* Eth device open */
-static int davinci_eth_open(struct eth_device *dev, bd_t *bis)
-{
-       dv_reg_p                addr;
-       u_int32_t               clkdiv, cnt, mac_control;
-       uint16_t                __maybe_unused lpa_val;
-       volatile emac_desc      *rx_desc;
-       int                     index;
-
-       debug_emac("+ emac_open\n");
-
-       /* Reset EMAC module and disable interrupts in wrapper */
-       writel(1, &adap_emac->SOFTRESET);
-       while (readl(&adap_emac->SOFTRESET) != 0)
-               ;
-#if defined(DAVINCI_EMAC_VERSION2)
-       writel(1, &adap_ewrap->softrst);
-       while (readl(&adap_ewrap->softrst) != 0)
-               ;
-#else
-       writel(0, &adap_ewrap->EWCTL);
-       for (cnt = 0; cnt < 5; cnt++) {
-               clkdiv = readl(&adap_ewrap->EWCTL);
-       }
-#endif
-
-#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
-       defined(CONFIG_MACH_DAVINCI_DA850_EVM)
-       adap_ewrap->c0rxen = adap_ewrap->c1rxen = adap_ewrap->c2rxen = 0;
-       adap_ewrap->c0txen = adap_ewrap->c1txen = adap_ewrap->c2txen = 0;
-       adap_ewrap->c0miscen = adap_ewrap->c1miscen = adap_ewrap->c2miscen = 0;
-#endif
-       rx_desc = emac_rx_desc;
-
-       writel(1, &adap_emac->TXCONTROL);
-       writel(1, &adap_emac->RXCONTROL);
-
-       davinci_eth_set_mac_addr(dev);
-
-       /* Set DMA 8 TX / 8 RX Head pointers to 0 */
-       addr = &adap_emac->TX0HDP;
-       for (cnt = 0; cnt < 8; cnt++)
-               writel(0, addr++);
-
-       addr = &adap_emac->RX0HDP;
-       for (cnt = 0; cnt < 8; cnt++)
-               writel(0, addr++);
-
-       /* Clear Statistics (do this before setting MacControl register) */
-       addr = &adap_emac->RXGOODFRAMES;
-       for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++)
-               writel(0, addr++);
-
-       /* No multicast addressing */
-       writel(0, &adap_emac->MACHASH1);
-       writel(0, &adap_emac->MACHASH2);
-
-       /* Create RX queue and set receive process in place */
-       emac_rx_active_head = emac_rx_desc;
-       for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) {
-               rx_desc->next = BD_TO_HW((u_int32_t)(rx_desc + 1));
-               rx_desc->buffer = &emac_rx_buffers[cnt * EMAC_RXBUF_SIZE];
-               rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
-               rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
-               rx_desc++;
-       }
-
-       /* Finalize the rx desc list */
-       rx_desc--;
-       rx_desc->next = 0;
-       emac_rx_active_tail = rx_desc;
-       emac_rx_queue_active = 1;
-
-       /* Enable TX/RX */
-       writel(EMAC_MAX_ETHERNET_PKT_SIZE, &adap_emac->RXMAXLEN);
-       writel(0, &adap_emac->RXBUFFEROFFSET);
-
-       /*
-        * No fancy configs - Use this for promiscous debug
-        *   - EMAC_RXMBPENABLE_RXCAFEN_ENABLE
-        */
-       writel(EMAC_RXMBPENABLE_RXBROADEN, &adap_emac->RXMBPENABLE);
-
-       /* Enable ch 0 only */
-       writel(1, &adap_emac->RXUNICASTSET);
-
-       /* Init MDIO & get link state */
-       clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV;
-       writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT,
-              &adap_mdio->CONTROL);
-
-       /* We need to wait for MDIO to start */
-       udelay(1000);
-
-       index = get_active_phy();
-       if (index == -1)
-               return(0);
-
-       /* Enable MII interface */
-       mac_control = EMAC_MACCONTROL_MIIEN_ENABLE;
-#ifdef DAVINCI_EMAC_GIG_ENABLE
-       davinci_eth_phy_read(active_phy_addr[index], MII_STAT1000, &lpa_val);
-       if (lpa_val & PHY_1000BTSR_1000FD) {
-               debug_emac("eth_open : gigabit negotiated\n");
-               mac_control |= EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
-               mac_control |= EMAC_MACCONTROL_GIGABIT_ENABLE;
-       }
-#endif
-
-       davinci_eth_phy_read(active_phy_addr[index], MII_LPA, &lpa_val);
-       if (lpa_val & (LPA_100FULL | LPA_10FULL))
-               /* set EMAC for Full Duplex  */
-               mac_control |= EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
-#if defined(CONFIG_SOC_DA8XX) || \
-       (defined(CONFIG_OMAP34XX) && defined(CONFIG_DRIVER_TI_EMAC_USE_RMII))
-       mac_control |= EMAC_MACCONTROL_RMIISPEED_100;
-#endif
-       writel(mac_control, &adap_emac->MACCONTROL);
-       /* Start receive process */
-       writel(BD_TO_HW((u_int32_t)emac_rx_desc), &adap_emac->RX0HDP);
-
-       debug_emac("- emac_open\n");
-
-       return(1);
-}
-
-/* EMAC Channel Teardown */
-static void davinci_eth_ch_teardown(int ch)
-{
-       dv_reg          dly = 0xff;
-       dv_reg          cnt;
-
-       debug_emac("+ emac_ch_teardown\n");
-
-       if (ch == EMAC_CH_TX) {
-               /* Init TX channel teardown */
-               writel(0, &adap_emac->TXTEARDOWN);
-               do {
-                       /*
-                        * Wait here for Tx teardown completion interrupt to
-                        * occur. Note: A task delay can be called here to pend
-                        * rather than occupying CPU cycles - anyway it has
-                        * been found that teardown takes very few cpu cycles
-                        * and does not affect functionality
-                        */
-                       dly--;
-                       udelay(1);
-                       if (dly == 0)
-                               break;
-                       cnt = readl(&adap_emac->TX0CP);
-               } while (cnt != 0xfffffffc);
-               writel(cnt, &adap_emac->TX0CP);
-               writel(0, &adap_emac->TX0HDP);
-       } else {
-               /* Init RX channel teardown */
-               writel(0, &adap_emac->RXTEARDOWN);
-               do {
-                       /*
-                        * Wait here for Rx teardown completion interrupt to
-                        * occur. Note: A task delay can be called here to pend
-                        * rather than occupying CPU cycles - anyway it has
-                        * been found that teardown takes very few cpu cycles
-                        * and does not affect functionality
-                        */
-                       dly--;
-                       udelay(1);
-                       if (dly == 0)
-                               break;
-                       cnt = readl(&adap_emac->RX0CP);
-               } while (cnt != 0xfffffffc);
-               writel(cnt, &adap_emac->RX0CP);
-               writel(0, &adap_emac->RX0HDP);
-       }
-
-       debug_emac("- emac_ch_teardown\n");
-}
-
-/* Eth device close */
-static void davinci_eth_close(struct eth_device *dev)
-{
-       debug_emac("+ emac_close\n");
-
-       davinci_eth_ch_teardown(EMAC_CH_TX);    /* TX Channel teardown */
-       if (readl(&adap_emac->RXCONTROL) & 1)
-               davinci_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */
-
-       /* Reset EMAC module and disable interrupts in wrapper */
-       writel(1, &adap_emac->SOFTRESET);
-#if defined(DAVINCI_EMAC_VERSION2)
-       writel(1, &adap_ewrap->softrst);
-#else
-       writel(0, &adap_ewrap->EWCTL);
-#endif
-
-#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
-       defined(CONFIG_MACH_DAVINCI_DA850_EVM)
-       adap_ewrap->c0rxen = adap_ewrap->c1rxen = adap_ewrap->c2rxen = 0;
-       adap_ewrap->c0txen = adap_ewrap->c1txen = adap_ewrap->c2txen = 0;
-       adap_ewrap->c0miscen = adap_ewrap->c1miscen = adap_ewrap->c2miscen = 0;
-#endif
-       debug_emac("- emac_close\n");
-}
-
-static int tx_send_loop = 0;
-
-/*
- * This function sends a single packet on the network and returns
- * positive number (number of bytes transmitted) or negative for error
- */
-static int davinci_eth_send_packet (struct eth_device *dev,
-                                       void *packet, int length)
-{
-       int ret_status = -1;
-       int index;
-       tx_send_loop = 0;
-
-       index = get_active_phy();
-       if (index == -1) {
-               printf(" WARN: emac_send_packet: No link\n");
-               return (ret_status);
-       }
-
-       /* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */
-       if (length < EMAC_MIN_ETHERNET_PKT_SIZE) {
-               length = EMAC_MIN_ETHERNET_PKT_SIZE;
-       }
-
-       /* Populate the TX descriptor */
-       emac_tx_desc->next = 0;
-       emac_tx_desc->buffer = (u_int8_t *) packet;
-       emac_tx_desc->buff_off_len = (length & 0xffff);
-       emac_tx_desc->pkt_flag_len = ((length & 0xffff) |
-                                     EMAC_CPPI_SOP_BIT |
-                                     EMAC_CPPI_OWNERSHIP_BIT |
-                                     EMAC_CPPI_EOP_BIT);
-
-       flush_dcache_range((unsigned long)packet,
-                          (unsigned long)packet + ALIGN(length, PKTALIGN));
-
-       /* Send the packet */
-       writel(BD_TO_HW((unsigned long)emac_tx_desc), &adap_emac->TX0HDP);
-
-       /* Wait for packet to complete or link down */
-       while (1) {
-               if (!phy[index].get_link_speed(active_phy_addr[index])) {
-                       davinci_eth_ch_teardown (EMAC_CH_TX);
-                       return (ret_status);
-               }
-
-               if (readl(&adap_emac->TXINTSTATRAW) & 0x01) {
-                       ret_status = length;
-                       break;
-               }
-               tx_send_loop++;
-       }
-
-       return (ret_status);
-}
-
-/*
- * This function handles receipt of a packet from the network
- */
-static int davinci_eth_rcv_packet (struct eth_device *dev)
-{
-       volatile emac_desc *rx_curr_desc;
-       volatile emac_desc *curr_desc;
-       volatile emac_desc *tail_desc;
-       int status, ret = -1;
-
-       rx_curr_desc = emac_rx_active_head;
-       if (!rx_curr_desc)
-               return 0;
-       status = rx_curr_desc->pkt_flag_len;
-       if ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0) {
-               if (status & EMAC_CPPI_RX_ERROR_FRAME) {
-                       /* Error in packet - discard it and requeue desc */
-                       printf ("WARN: emac_rcv_pkt: Error in packet\n");
-               } else {
-                       unsigned long tmp = (unsigned long)rx_curr_desc->buffer;
-                       unsigned short len =
-                               rx_curr_desc->buff_off_len & 0xffff;
-
-                       invalidate_dcache_range(tmp, tmp + ALIGN(len, PKTALIGN));
-                       net_process_received_packet(rx_curr_desc->buffer, len);
-                       ret = len;
-               }
-
-               /* Ack received packet descriptor */
-               writel(BD_TO_HW((ulong)rx_curr_desc), &adap_emac->RX0CP);
-               curr_desc = rx_curr_desc;
-               emac_rx_active_head =
-                       (volatile emac_desc *) (HW_TO_BD(rx_curr_desc->next));
-
-               if (status & EMAC_CPPI_EOQ_BIT) {
-                       if (emac_rx_active_head) {
-                               writel(BD_TO_HW((ulong)emac_rx_active_head),
-                                      &adap_emac->RX0HDP);
-                       } else {
-                               emac_rx_queue_active = 0;
-                               printf ("INFO:emac_rcv_packet: RX Queue not active\n");
-                       }
-               }
-
-               /* Recycle RX descriptor */
-               rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
-               rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
-               rx_curr_desc->next = 0;
-
-               if (emac_rx_active_head == 0) {
-                       printf ("INFO: emac_rcv_pkt: active queue head = 0\n");
-                       emac_rx_active_head = curr_desc;
-                       emac_rx_active_tail = curr_desc;
-                       if (emac_rx_queue_active != 0) {
-                               writel(BD_TO_HW((ulong)emac_rx_active_head),
-                                      &adap_emac->RX0HDP);
-                               printf ("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n");
-                               emac_rx_queue_active = 1;
-                       }
-               } else {
-                       tail_desc = emac_rx_active_tail;
-                       emac_rx_active_tail = curr_desc;
-                       tail_desc->next = BD_TO_HW((ulong) curr_desc);
-                       status = tail_desc->pkt_flag_len;
-                       if (status & EMAC_CPPI_EOQ_BIT) {
-                               writel(BD_TO_HW((ulong)curr_desc),
-                                      &adap_emac->RX0HDP);
-                               status &= ~EMAC_CPPI_EOQ_BIT;
-                               tail_desc->pkt_flag_len = status;
-                       }
-               }
-               return (ret);
-       }
-       return (0);
-}
-
-/*
- * This function initializes the emac hardware. It does NOT initialize
- * EMAC modules power or pin multiplexors, that is done by board_init()
- * much earlier in bootup process. Returns 1 on success, 0 otherwise.
- */
-int davinci_emac_initialize(void)
-{
-       u_int32_t       phy_id;
-       u_int16_t       tmp;
-       int             i;
-       int             ret;
-       struct eth_device *dev;
-
-       dev = malloc(sizeof *dev);
-
-       if (dev == NULL)
-               return -1;
-
-       memset(dev, 0, sizeof *dev);
-       strcpy(dev->name, "DaVinci-EMAC");
-
-       dev->iobase = 0;
-       dev->init = davinci_eth_open;
-       dev->halt = davinci_eth_close;
-       dev->send = davinci_eth_send_packet;
-       dev->recv = davinci_eth_rcv_packet;
-       dev->write_hwaddr = davinci_eth_set_mac_addr;
-
-       eth_register(dev);
-
-       davinci_eth_mdio_enable();
-
-       /* let the EMAC detect the PHYs */
-       udelay(5000);
-
-       for (i = 0; i < 256; i++) {
-               if (readl(&adap_mdio->ALIVE))
-                       break;
-               udelay(1000);
-       }
-
-       if (i >= 256) {
-               printf("No ETH PHY detected!!!\n");
-               return(0);
-       }
-
-       /* Find if PHY(s) is/are connected */
-       ret = davinci_eth_phy_detect();
-       if (!ret)
-               return(0);
-       else
-               debug_emac(" %d ETH PHY detected\n", ret);
-
-       /* Get PHY ID and initialize phy_ops for a detected PHY */
-       for (i = 0; i < num_phy; i++) {
-               if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID1,
-                                                       &tmp)) {
-                       active_phy_addr[i] = 0xff;
-                       continue;
-               }
-
-               phy_id = (tmp << 16) & 0xffff0000;
-
-               if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID2,
-                                                       &tmp)) {
-                       active_phy_addr[i] = 0xff;
-                       continue;
-               }
-
-               phy_id |= tmp & 0x0000ffff;
-
-               switch (phy_id) {
-#ifdef PHY_KSZ8873
-               case PHY_KSZ8873:
-                       sprintf(phy[i].name, "KSZ8873 @ 0x%02x",
-                                               active_phy_addr[i]);
-                       phy[i].init = ksz8873_init_phy;
-                       phy[i].is_phy_connected = ksz8873_is_phy_connected;
-                       phy[i].get_link_speed = ksz8873_get_link_speed;
-                       phy[i].auto_negotiate = ksz8873_auto_negotiate;
-                       break;
-#endif
-#ifdef PHY_LXT972
-               case PHY_LXT972:
-                       sprintf(phy[i].name, "LXT972 @ 0x%02x",
-                                               active_phy_addr[i]);
-                       phy[i].init = lxt972_init_phy;
-                       phy[i].is_phy_connected = lxt972_is_phy_connected;
-                       phy[i].get_link_speed = lxt972_get_link_speed;
-                       phy[i].auto_negotiate = lxt972_auto_negotiate;
-                       break;
-#endif
-#ifdef PHY_DP83848
-               case PHY_DP83848:
-                       sprintf(phy[i].name, "DP83848 @ 0x%02x",
-                                               active_phy_addr[i]);
-                       phy[i].init = dp83848_init_phy;
-                       phy[i].is_phy_connected = dp83848_is_phy_connected;
-                       phy[i].get_link_speed = dp83848_get_link_speed;
-                       phy[i].auto_negotiate = dp83848_auto_negotiate;
-                       break;
-#endif
-#ifdef PHY_ET1011C
-               case PHY_ET1011C:
-                       sprintf(phy[i].name, "ET1011C @ 0x%02x",
-                                               active_phy_addr[i]);
-                       phy[i].init = gen_init_phy;
-                       phy[i].is_phy_connected = gen_is_phy_connected;
-                       phy[i].get_link_speed = et1011c_get_link_speed;
-                       phy[i].auto_negotiate = gen_auto_negotiate;
-                       break;
-#endif
-               default:
-                       sprintf(phy[i].name, "GENERIC @ 0x%02x",
-                                               active_phy_addr[i]);
-                       phy[i].init = gen_init_phy;
-                       phy[i].is_phy_connected = gen_is_phy_connected;
-                       phy[i].get_link_speed = gen_get_link_speed;
-                       phy[i].auto_negotiate = gen_auto_negotiate;
-               }
-
-               debug("Ethernet PHY: %s\n", phy[i].name);
-
-               int retval;
-               struct mii_dev *mdiodev = mdio_alloc();
-               if (!mdiodev)
-                       return -ENOMEM;
-               strncpy(mdiodev->name, phy[i].name, MDIO_NAME_LEN);
-               mdiodev->read = davinci_mii_phy_read;
-               mdiodev->write = davinci_mii_phy_write;
-
-               retval = mdio_register(mdiodev);
-               if (retval < 0)
-                       return retval;
-#ifdef DAVINCI_EMAC_GIG_ENABLE
-#define PHY_CONF_REG   22
-               /* Enable PHY to clock out TX_CLK */
-               davinci_eth_phy_read(active_phy_addr[i], PHY_CONF_REG, &tmp);
-               tmp |= PHY_CONF_TXCLKEN;
-               davinci_eth_phy_write(active_phy_addr[i], PHY_CONF_REG, tmp);
-               davinci_eth_phy_read(active_phy_addr[i], PHY_CONF_REG, &tmp);
-#endif
-       }
-
-#if defined(CONFIG_TI816X) || (defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
-               defined(CONFIG_MACH_DAVINCI_DA850_EVM) && \
-                       !defined(CONFIG_DRIVER_TI_EMAC_RMII_NO_NEGOTIATE))
-       for (i = 0; i < num_phy; i++) {
-               if (phy[i].is_phy_connected(i))
-                       phy[i].auto_negotiate(i);
-       }
-#endif
-       return(1);
-}
diff --git a/drivers/net/davinci_emac.h b/drivers/net/davinci_emac.h
deleted file mode 100644 (file)
index 695855b..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2011 Ilya Yanok, Emcraft Systems
- *
- * Based on: mach-davinci/emac_defs.h
- * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
- */
-
-#ifndef _DAVINCI_EMAC_H_
-#define _DAVINCI_EMAC_H_
-/* Ethernet Min/Max packet size */
-#define EMAC_MIN_ETHERNET_PKT_SIZE     60
-#define EMAC_MAX_ETHERNET_PKT_SIZE     1518
-/* Buffer size (should be aligned on 32 byte and cache line) */
-#define EMAC_RXBUF_SIZE        ALIGN(ALIGN(EMAC_MAX_ETHERNET_PKT_SIZE, 32),\
-                               ARCH_DMA_MINALIGN)
-
-/* Number of RX packet buffers
- * NOTE: Only 1 buffer supported as of now
- */
-#define EMAC_MAX_RX_BUFFERS            10
-
-
-/***********************************************
- ******** Internally used macros ***************
- ***********************************************/
-
-#define EMAC_CH_TX                     1
-#define EMAC_CH_RX                     0
-
-/* Each descriptor occupies 4 words, lets start RX desc's at 0 and
- * reserve space for 64 descriptors max
- */
-#define EMAC_RX_DESC_BASE              0x0
-#define EMAC_TX_DESC_BASE              0x1000
-
-/* EMAC Teardown value */
-#define EMAC_TEARDOWN_VALUE            0xfffffffc
-
-/* MII Status Register */
-#define MII_STATUS_REG                 1
-/* PHY Configuration register */
-#define PHY_CONF_TXCLKEN               (1 << 5)
-
-/* Number of statistics registers */
-#define EMAC_NUM_STATS                 36
-
-
-/* EMAC Descriptor */
-typedef volatile struct _emac_desc
-{
-       u_int32_t       next;           /* Pointer to next descriptor
-                                          in chain */
-       u_int8_t        *buffer;        /* Pointer to data buffer */
-       u_int32_t       buff_off_len;   /* Buffer Offset(MSW) and Length(LSW) */
-       u_int32_t       pkt_flag_len;   /* Packet Flags(MSW) and Length(LSW) */
-} emac_desc;
-
-/* CPPI bit positions */
-#define EMAC_CPPI_SOP_BIT              (0x80000000)
-#define EMAC_CPPI_EOP_BIT              (0x40000000)
-#define EMAC_CPPI_OWNERSHIP_BIT                (0x20000000)
-#define EMAC_CPPI_EOQ_BIT              (0x10000000)
-#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT        (0x08000000)
-#define EMAC_CPPI_PASS_CRC_BIT         (0x04000000)
-
-#define EMAC_CPPI_RX_ERROR_FRAME       (0x03fc0000)
-
-#define EMAC_MACCONTROL_MIIEN_ENABLE           (0x20)
-#define EMAC_MACCONTROL_FULLDUPLEX_ENABLE      (0x1)
-#define EMAC_MACCONTROL_GIGABIT_ENABLE         (1 << 7)
-#define EMAC_MACCONTROL_GIGFORCE               (1 << 17)
-#define EMAC_MACCONTROL_RMIISPEED_100          (1 << 15)
-
-#define EMAC_MAC_ADDR_MATCH            (1 << 19)
-#define EMAC_MAC_ADDR_IS_VALID         (1 << 20)
-
-#define EMAC_RXMBPENABLE_RXCAFEN_ENABLE        (0x200000)
-#define EMAC_RXMBPENABLE_RXBROADEN     (0x2000)
-
-
-#define MDIO_CONTROL_IDLE              (0x80000000)
-#define MDIO_CONTROL_ENABLE            (0x40000000)
-#define MDIO_CONTROL_FAULT_ENABLE      (0x40000)
-#define MDIO_CONTROL_FAULT             (0x80000)
-#define MDIO_USERACCESS0_GO            (0x80000000)
-#define MDIO_USERACCESS0_WRITE_READ    (0x0)
-#define MDIO_USERACCESS0_WRITE_WRITE   (0x40000000)
-#define MDIO_USERACCESS0_ACK           (0x20000000)
-
-/* Ethernet MAC Registers Structure */
-typedef struct  {
-       dv_reg          TXIDVER;
-       dv_reg          TXCONTROL;
-       dv_reg          TXTEARDOWN;
-       u_int8_t        RSVD0[4];
-       dv_reg          RXIDVER;
-       dv_reg          RXCONTROL;
-       dv_reg          RXTEARDOWN;
-       u_int8_t        RSVD1[100];
-       dv_reg          TXINTSTATRAW;
-       dv_reg          TXINTSTATMASKED;
-       dv_reg          TXINTMASKSET;
-       dv_reg          TXINTMASKCLEAR;
-       dv_reg          MACINVECTOR;
-       u_int8_t        RSVD2[12];
-       dv_reg          RXINTSTATRAW;
-       dv_reg          RXINTSTATMASKED;
-       dv_reg          RXINTMASKSET;
-       dv_reg          RXINTMASKCLEAR;
-       dv_reg          MACINTSTATRAW;
-       dv_reg          MACINTSTATMASKED;
-       dv_reg          MACINTMASKSET;
-       dv_reg          MACINTMASKCLEAR;
-       u_int8_t        RSVD3[64];
-       dv_reg          RXMBPENABLE;
-       dv_reg          RXUNICASTSET;
-       dv_reg          RXUNICASTCLEAR;
-       dv_reg          RXMAXLEN;
-       dv_reg          RXBUFFEROFFSET;
-       dv_reg          RXFILTERLOWTHRESH;
-       u_int8_t        RSVD4[8];
-       dv_reg          RX0FLOWTHRESH;
-       dv_reg          RX1FLOWTHRESH;
-       dv_reg          RX2FLOWTHRESH;
-       dv_reg          RX3FLOWTHRESH;
-       dv_reg          RX4FLOWTHRESH;
-       dv_reg          RX5FLOWTHRESH;
-       dv_reg          RX6FLOWTHRESH;
-       dv_reg          RX7FLOWTHRESH;
-       dv_reg          RX0FREEBUFFER;
-       dv_reg          RX1FREEBUFFER;
-       dv_reg          RX2FREEBUFFER;
-       dv_reg          RX3FREEBUFFER;
-       dv_reg          RX4FREEBUFFER;
-       dv_reg          RX5FREEBUFFER;
-       dv_reg          RX6FREEBUFFER;
-       dv_reg          RX7FREEBUFFER;
-       dv_reg          MACCONTROL;
-       dv_reg          MACSTATUS;
-       dv_reg          EMCONTROL;
-       dv_reg          FIFOCONTROL;
-       dv_reg          MACCONFIG;
-       dv_reg          SOFTRESET;
-       u_int8_t        RSVD5[88];
-       dv_reg          MACSRCADDRLO;
-       dv_reg          MACSRCADDRHI;
-       dv_reg          MACHASH1;
-       dv_reg          MACHASH2;
-       dv_reg          BOFFTEST;
-       dv_reg          TPACETEST;
-       dv_reg          RXPAUSE;
-       dv_reg          TXPAUSE;
-       u_int8_t        RSVD6[16];
-       dv_reg          RXGOODFRAMES;
-       dv_reg          RXBCASTFRAMES;
-       dv_reg          RXMCASTFRAMES;
-       dv_reg          RXPAUSEFRAMES;
-       dv_reg          RXCRCERRORS;
-       dv_reg          RXALIGNCODEERRORS;
-       dv_reg          RXOVERSIZED;
-       dv_reg          RXJABBER;
-       dv_reg          RXUNDERSIZED;
-       dv_reg          RXFRAGMENTS;
-       dv_reg          RXFILTERED;
-       dv_reg          RXQOSFILTERED;
-       dv_reg          RXOCTETS;
-       dv_reg          TXGOODFRAMES;
-       dv_reg          TXBCASTFRAMES;
-       dv_reg          TXMCASTFRAMES;
-       dv_reg          TXPAUSEFRAMES;
-       dv_reg          TXDEFERRED;
-       dv_reg          TXCOLLISION;
-       dv_reg          TXSINGLECOLL;
-       dv_reg          TXMULTICOLL;
-       dv_reg          TXEXCESSIVECOLL;
-       dv_reg          TXLATECOLL;
-       dv_reg          TXUNDERRUN;
-       dv_reg          TXCARRIERSENSE;
-       dv_reg          TXOCTETS;
-       dv_reg          FRAME64;
-       dv_reg          FRAME65T127;
-       dv_reg          FRAME128T255;
-       dv_reg          FRAME256T511;
-       dv_reg          FRAME512T1023;
-       dv_reg          FRAME1024TUP;
-       dv_reg          NETOCTETS;
-       dv_reg          RXSOFOVERRUNS;
-       dv_reg          RXMOFOVERRUNS;
-       dv_reg          RXDMAOVERRUNS;
-       u_int8_t        RSVD7[624];
-       dv_reg          MACADDRLO;
-       dv_reg          MACADDRHI;
-       dv_reg          MACINDEX;
-       u_int8_t        RSVD8[244];
-       dv_reg          TX0HDP;
-       dv_reg          TX1HDP;
-       dv_reg          TX2HDP;
-       dv_reg          TX3HDP;
-       dv_reg          TX4HDP;
-       dv_reg          TX5HDP;
-       dv_reg          TX6HDP;
-       dv_reg          TX7HDP;
-       dv_reg          RX0HDP;
-       dv_reg          RX1HDP;
-       dv_reg          RX2HDP;
-       dv_reg          RX3HDP;
-       dv_reg          RX4HDP;
-       dv_reg          RX5HDP;
-       dv_reg          RX6HDP;
-       dv_reg          RX7HDP;
-       dv_reg          TX0CP;
-       dv_reg          TX1CP;
-       dv_reg          TX2CP;
-       dv_reg          TX3CP;
-       dv_reg          TX4CP;
-       dv_reg          TX5CP;
-       dv_reg          TX6CP;
-       dv_reg          TX7CP;
-       dv_reg          RX0CP;
-       dv_reg          RX1CP;
-       dv_reg          RX2CP;
-       dv_reg          RX3CP;
-       dv_reg          RX4CP;
-       dv_reg          RX5CP;
-       dv_reg          RX6CP;
-       dv_reg          RX7CP;
-} emac_regs;
-
-/* EMAC Wrapper Registers Structure */
-typedef struct  {
-#ifdef DAVINCI_EMAC_VERSION2
-       dv_reg          idver;
-       dv_reg          softrst;
-       dv_reg          emctrl;
-       dv_reg          c0rxthreshen;
-       dv_reg          c0rxen;
-       dv_reg          c0txen;
-       dv_reg          c0miscen;
-       dv_reg          c1rxthreshen;
-       dv_reg          c1rxen;
-       dv_reg          c1txen;
-       dv_reg          c1miscen;
-       dv_reg          c2rxthreshen;
-       dv_reg          c2rxen;
-       dv_reg          c2txen;
-       dv_reg          c2miscen;
-       dv_reg          c0rxthreshstat;
-       dv_reg          c0rxstat;
-       dv_reg          c0txstat;
-       dv_reg          c0miscstat;
-       dv_reg          c1rxthreshstat;
-       dv_reg          c1rxstat;
-       dv_reg          c1txstat;
-       dv_reg          c1miscstat;
-       dv_reg          c2rxthreshstat;
-       dv_reg          c2rxstat;
-       dv_reg          c2txstat;
-       dv_reg          c2miscstat;
-       dv_reg          c0rximax;
-       dv_reg          c0tximax;
-       dv_reg          c1rximax;
-       dv_reg          c1tximax;
-       dv_reg          c2rximax;
-       dv_reg          c2tximax;
-#else
-       u_int8_t        RSVD0[4100];
-       dv_reg          EWCTL;
-       dv_reg          EWINTTCNT;
-#endif
-} ewrap_regs;
-
-/* EMAC MDIO Registers Structure */
-typedef struct  {
-       dv_reg          VERSION;
-       dv_reg          CONTROL;
-       dv_reg          ALIVE;
-       dv_reg          LINK;
-       dv_reg          LINKINTRAW;
-       dv_reg          LINKINTMASKED;
-       u_int8_t        RSVD0[8];
-       dv_reg          USERINTRAW;
-       dv_reg          USERINTMASKED;
-       dv_reg          USERINTMASKSET;
-       dv_reg          USERINTMASKCLEAR;
-       u_int8_t        RSVD1[80];
-       dv_reg          USERACCESS0;
-       dv_reg          USERPHYSEL0;
-       dv_reg          USERACCESS1;
-       dv_reg          USERPHYSEL1;
-} mdio_regs;
-
-int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data);
-int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data);
-
-typedef struct {
-       char    name[64];
-       int     (*init)(int phy_addr);
-       int     (*is_phy_connected)(int phy_addr);
-       int     (*get_link_speed)(int phy_addr);
-       int     (*auto_negotiate)(int phy_addr);
-} phy_t;
-
-#endif /* _DAVINCI_EMAC_H_ */
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
deleted file mode 100644 (file)
index d4d909b..0000000
+++ /dev/null
@@ -1,1170 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Ethernet driver for TI K2HK EVM.
- *
- * (C) Copyright 2012-2014
- *     Texas Instruments Incorporated, <www.ti.com>
- */
-#include <common.h>
-#include <command.h>
-#include <console.h>
-
-#include <dm.h>
-#include <dm/lists.h>
-
-#include <net.h>
-#include <phy.h>
-#include <errno.h>
-#include <miiphy.h>
-#include <malloc.h>
-#include <asm/ti-common/keystone_nav.h>
-#include <asm/ti-common/keystone_net.h>
-#include <asm/ti-common/keystone_serdes.h>
-#include <asm/arch/psc_defs.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#ifndef CONFIG_DM_ETH
-unsigned int emac_open;
-static struct mii_dev *mdio_bus;
-static unsigned int sys_has_mdio = 1;
-#endif
-
-#ifdef KEYSTONE2_EMAC_GIG_ENABLE
-#define emac_gigabit_enable(x) keystone2_eth_gigabit_enable(x)
-#else
-#define emac_gigabit_enable(x) /* no gigabit to enable */
-#endif
-
-#define RX_BUFF_NUMS   24
-#define RX_BUFF_LEN    1520
-#define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN
-#define SGMII_ANEG_TIMEOUT             4000
-
-static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16);
-
-#ifndef CONFIG_DM_ETH
-struct rx_buff_desc net_rx_buffs = {
-       .buff_ptr       = rx_buffs,
-       .num_buffs      = RX_BUFF_NUMS,
-       .buff_len       = RX_BUFF_LEN,
-       .rx_flow        = 22,
-};
-#endif
-
-#ifdef CONFIG_DM_ETH
-
-enum link_type {
-       LINK_TYPE_SGMII_MAC_TO_MAC_AUTO         = 0,
-       LINK_TYPE_SGMII_MAC_TO_PHY_MODE         = 1,
-       LINK_TYPE_SGMII_MAC_TO_MAC_FORCED_MODE  = 2,
-       LINK_TYPE_SGMII_MAC_TO_FIBRE_MODE       = 3,
-       LINK_TYPE_SGMII_MAC_TO_PHY_NO_MDIO_MODE = 4,
-       LINK_TYPE_RGMII_LINK_MAC_PHY            = 5,
-       LINK_TYPE_RGMII_LINK_MAC_MAC_FORCED     = 6,
-       LINK_TYPE_RGMII_LINK_MAC_PHY_NO_MDIO    = 7,
-       LINK_TYPE_10G_MAC_TO_PHY_MODE           = 10,
-       LINK_TYPE_10G_MAC_TO_MAC_FORCED_MODE    = 11,
-};
-
-#define mac_hi(mac)     (((mac)[0] << 0) | ((mac)[1] << 8) |    \
-                        ((mac)[2] << 16) | ((mac)[3] << 24))
-#define mac_lo(mac)     (((mac)[4] << 0) | ((mac)[5] << 8))
-
-#ifdef CONFIG_KSNET_NETCP_V1_0
-
-#define EMAC_EMACSW_BASE_OFS           0x90800
-#define EMAC_EMACSW_PORT_BASE_OFS      (EMAC_EMACSW_BASE_OFS + 0x60)
-
-/* CPSW Switch slave registers */
-#define CPGMACSL_REG_SA_LO             0x10
-#define CPGMACSL_REG_SA_HI             0x14
-
-#define DEVICE_EMACSW_BASE(base, x)    ((base) + EMAC_EMACSW_PORT_BASE_OFS +  \
-                                        (x) * 0x30)
-
-#elif defined CONFIG_KSNET_NETCP_V1_5
-
-#define EMAC_EMACSW_PORT_BASE_OFS      0x222000
-
-/* CPSW Switch slave registers */
-#define CPGMACSL_REG_SA_LO             0x308
-#define CPGMACSL_REG_SA_HI             0x30c
-
-#define DEVICE_EMACSW_BASE(base, x)    ((base) + EMAC_EMACSW_PORT_BASE_OFS +  \
-                                        (x) * 0x1000)
-
-#endif
-
-
-struct ks2_eth_priv {
-       struct udevice                  *dev;
-       struct phy_device               *phydev;
-       struct mii_dev                  *mdio_bus;
-       int                             phy_addr;
-       phy_interface_t                 phy_if;
-       int                             sgmii_link_type;
-       void                            *mdio_base;
-       struct rx_buff_desc             net_rx_buffs;
-       struct pktdma_cfg               *netcp_pktdma;
-       void                            *hd;
-       int                             slave_port;
-       enum link_type                  link_type;
-       bool                            emac_open;
-       bool                            has_mdio;
-};
-#endif
-
-/* MDIO */
-
-static int keystone2_mdio_reset(struct mii_dev *bus)
-{
-       u_int32_t clkdiv;
-       struct mdio_regs *adap_mdio = bus->priv;
-
-       clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
-
-       writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE |
-              MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE,
-              &adap_mdio->control);
-
-       while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE)
-               ;
-
-       return 0;
-}
-
-/**
- * keystone2_mdio_read - read a PHY register via MDIO interface.
- * Blocks until operation is complete.
- */
-static int keystone2_mdio_read(struct mii_dev *bus,
-                              int addr, int devad, int reg)
-{
-       int tmp;
-       struct mdio_regs *adap_mdio = bus->priv;
-
-       while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
-               ;
-
-       writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ |
-              ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16),
-              &adap_mdio->useraccess0);
-
-       /* Wait for command to complete */
-       while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO)
-               ;
-
-       if (tmp & MDIO_USERACCESS0_ACK)
-               return tmp & 0xffff;
-
-       return -1;
-}
-
-/**
- * keystone2_mdio_write - write to a PHY register via MDIO interface.
- * Blocks until operation is complete.
- */
-static int keystone2_mdio_write(struct mii_dev *bus,
-                               int addr, int devad, int reg, u16 val)
-{
-       struct mdio_regs *adap_mdio = bus->priv;
-
-       while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
-               ;
-
-       writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE |
-              ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) |
-              (val & 0xffff), &adap_mdio->useraccess0);
-
-       /* Wait for command to complete */
-       while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
-               ;
-
-       return 0;
-}
-
-#ifndef CONFIG_DM_ETH
-static void  __attribute__((unused))
-       keystone2_eth_gigabit_enable(struct eth_device *dev)
-{
-       u_int16_t data;
-       struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
-
-       if (sys_has_mdio) {
-               data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr,
-                                          MDIO_DEVAD_NONE, 0);
-               /* speed selection MSB */
-               if (!(data & (1 << 6)))
-                       return;
-       }
-
-       /*
-        * Check if link detected is giga-bit
-        * If Gigabit mode detected, enable gigbit in MAC
-        */
-       writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) +
-                    CPGMACSL_REG_CTL) |
-              EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
-              DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL);
-}
-#else
-static void  __attribute__((unused))
-       keystone2_eth_gigabit_enable(struct udevice *dev)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-       u_int16_t data;
-
-       if (priv->has_mdio) {
-               data = keystone2_mdio_read(priv->mdio_bus, priv->phy_addr,
-                                          MDIO_DEVAD_NONE, 0);
-               /* speed selection MSB */
-               if (!(data & (1 << 6)))
-                       return;
-       }
-
-       /*
-        * Check if link detected is giga-bit
-        * If Gigabit mode detected, enable gigbit in MAC
-        */
-       writel(readl(DEVICE_EMACSL_BASE(priv->slave_port - 1) +
-                    CPGMACSL_REG_CTL) |
-              EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
-              DEVICE_EMACSL_BASE(priv->slave_port - 1) + CPGMACSL_REG_CTL);
-}
-#endif
-
-#ifdef CONFIG_SOC_K2G
-int keystone_rgmii_config(struct phy_device *phy_dev)
-{
-       unsigned int i, status;
-
-       i = 0;
-       do {
-               if (i > SGMII_ANEG_TIMEOUT) {
-                       puts(" TIMEOUT !\n");
-                       phy_dev->link = 0;
-                       return 0;
-               }
-
-               if (ctrlc()) {
-                       puts("user interrupt!\n");
-                       phy_dev->link = 0;
-                       return -EINTR;
-               }
-
-               if ((i++ % 500) == 0)
-                       printf(".");
-
-               udelay(1000);   /* 1 ms */
-               status = readl(RGMII_STATUS_REG);
-       } while (!(status & RGMII_REG_STATUS_LINK));
-
-       puts(" done\n");
-
-       return 0;
-}
-#else
-int keystone_sgmii_config(struct phy_device *phy_dev, int port, int interface)
-{
-       unsigned int i, status, mask;
-       unsigned int mr_adv_ability, control;
-
-       switch (interface) {
-       case SGMII_LINK_MAC_MAC_AUTONEG:
-               mr_adv_ability  = (SGMII_REG_MR_ADV_ENABLE |
-                                  SGMII_REG_MR_ADV_LINK |
-                                  SGMII_REG_MR_ADV_FULL_DUPLEX |
-                                  SGMII_REG_MR_ADV_GIG_MODE);
-               control         = (SGMII_REG_CONTROL_MASTER |
-                                  SGMII_REG_CONTROL_AUTONEG);
-
-               break;
-       case SGMII_LINK_MAC_PHY:
-       case SGMII_LINK_MAC_PHY_FORCED:
-               mr_adv_ability  = SGMII_REG_MR_ADV_ENABLE;
-               control         = SGMII_REG_CONTROL_AUTONEG;
-
-               break;
-       case SGMII_LINK_MAC_MAC_FORCED:
-               mr_adv_ability  = (SGMII_REG_MR_ADV_ENABLE |
-                                  SGMII_REG_MR_ADV_LINK |
-                                  SGMII_REG_MR_ADV_FULL_DUPLEX |
-                                  SGMII_REG_MR_ADV_GIG_MODE);
-               control         = SGMII_REG_CONTROL_MASTER;
-
-               break;
-       case SGMII_LINK_MAC_FIBER:
-               mr_adv_ability  = 0x20;
-               control         = SGMII_REG_CONTROL_AUTONEG;
-
-               break;
-       default:
-               mr_adv_ability  = SGMII_REG_MR_ADV_ENABLE;
-               control         = SGMII_REG_CONTROL_AUTONEG;
-       }
-
-       __raw_writel(0, SGMII_CTL_REG(port));
-
-       /*
-        * Wait for the SerDes pll to lock,
-        * but don't trap if lock is never read
-        */
-       for (i = 0; i < 1000; i++)  {
-               udelay(2000);
-               status = __raw_readl(SGMII_STATUS_REG(port));
-               if ((status & SGMII_REG_STATUS_LOCK) != 0)
-                       break;
-       }
-
-       __raw_writel(mr_adv_ability, SGMII_MRADV_REG(port));
-       __raw_writel(control, SGMII_CTL_REG(port));
-
-
-       mask = SGMII_REG_STATUS_LINK;
-
-       if (control & SGMII_REG_CONTROL_AUTONEG)
-               mask |= SGMII_REG_STATUS_AUTONEG;
-
-       status = __raw_readl(SGMII_STATUS_REG(port));
-       if ((status & mask) == mask)
-               return 0;
-
-       printf("\n%s Waiting for SGMII auto negotiation to complete",
-              phy_dev->dev->name);
-       while ((status & mask) != mask) {
-               /*
-                * Timeout reached ?
-                */
-               if (i > SGMII_ANEG_TIMEOUT) {
-                       puts(" TIMEOUT !\n");
-                       phy_dev->link = 0;
-                       return 0;
-               }
-
-               if (ctrlc()) {
-                       puts("user interrupt!\n");
-                       phy_dev->link = 0;
-                       return -EINTR;
-               }
-
-               if ((i++ % 500) == 0)
-                       printf(".");
-
-               udelay(1000);   /* 1 ms */
-               status = __raw_readl(SGMII_STATUS_REG(port));
-       }
-       puts(" done\n");
-
-       return 0;
-}
-#endif
-
-int mac_sl_reset(u32 port)
-{
-       u32 i, v;
-
-       if (port >= DEVICE_N_GMACSL_PORTS)
-               return GMACSL_RET_INVALID_PORT;
-
-       /* Set the soft reset bit */
-       writel(CPGMAC_REG_RESET_VAL_RESET,
-              DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET);
-
-       /* Wait for the bit to clear */
-       for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
-               v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET);
-               if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
-                   CPGMAC_REG_RESET_VAL_RESET)
-                       return GMACSL_RET_OK;
-       }
-
-       /* Timeout on the reset */
-       return GMACSL_RET_WARN_RESET_INCOMPLETE;
-}
-
-int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg)
-{
-       u32 v, i;
-       int ret = GMACSL_RET_OK;
-
-       if (port >= DEVICE_N_GMACSL_PORTS)
-               return GMACSL_RET_INVALID_PORT;
-
-       if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) {
-               cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN;
-               ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG;
-       }
-
-       /* Must wait if the device is undergoing reset */
-       for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
-               v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET);
-               if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
-                   CPGMAC_REG_RESET_VAL_RESET)
-                       break;
-       }
-
-       if (i == DEVICE_EMACSL_RESET_POLL_COUNT)
-               return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE;
-
-       writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN);
-       writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL);
-
-#ifndef CONFIG_SOC_K2HK
-       /* Map RX packet flow priority to 0 */
-       writel(0, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RX_PRI_MAP);
-#endif
-
-       return ret;
-}
-
-int ethss_config(u32 ctl, u32 max_pkt_size)
-{
-       u32 i;
-
-       /* Max length register */
-       writel(max_pkt_size, DEVICE_CPSW_BASE + CPSW_REG_MAXLEN);
-
-       /* Control register */
-       writel(ctl, DEVICE_CPSW_BASE + CPSW_REG_CTL);
-
-       /* All statistics enabled by default */
-       writel(CPSW_REG_VAL_STAT_ENABLE_ALL,
-              DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN);
-
-       /* Reset and enable the ALE */
-       writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE |
-              CPSW_REG_VAL_ALE_CTL_BYPASS,
-              DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL);
-
-       /* All ports put into forward mode */
-       for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++)
-               writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE,
-                      DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i));
-
-       return 0;
-}
-
-int ethss_start(void)
-{
-       int i;
-       struct mac_sl_cfg cfg;
-
-       cfg.max_rx_len  = MAX_SIZE_STREAM_BUFFER;
-       cfg.ctl         = GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL;
-
-       for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) {
-               mac_sl_reset(i);
-               mac_sl_config(i, &cfg);
-       }
-
-       return 0;
-}
-
-int ethss_stop(void)
-{
-       int i;
-
-       for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++)
-               mac_sl_reset(i);
-
-       return 0;
-}
-
-struct ks2_serdes ks2_serdes_sgmii_156p25mhz = {
-       .clk = SERDES_CLOCK_156P25M,
-       .rate = SERDES_RATE_5G,
-       .rate_mode = SERDES_QUARTER_RATE,
-       .intf = SERDES_PHY_SGMII,
-       .loopback = 0,
-};
-
-#ifndef CONFIG_SOC_K2G
-static void keystone2_net_serdes_setup(void)
-{
-       ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE,
-                       &ks2_serdes_sgmii_156p25mhz,
-                       CONFIG_KSNET_SERDES_LANES_PER_SGMII);
-
-#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L)
-       ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE,
-                       &ks2_serdes_sgmii_156p25mhz,
-                       CONFIG_KSNET_SERDES_LANES_PER_SGMII);
-#endif
-
-       /* wait till setup */
-       udelay(5000);
-}
-#endif
-
-#ifndef CONFIG_DM_ETH
-
-int keystone2_eth_read_mac_addr(struct eth_device *dev)
-{
-       struct eth_priv_t *eth_priv;
-       u32 maca = 0;
-       u32 macb = 0;
-
-       eth_priv = (struct eth_priv_t *)dev->priv;
-
-       /* Read the e-fuse mac address */
-       if (eth_priv->slave_port == 1) {
-               maca = __raw_readl(MAC_ID_BASE_ADDR);
-               macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
-       }
-
-       dev->enetaddr[0] = (macb >>  8) & 0xff;
-       dev->enetaddr[1] = (macb >>  0) & 0xff;
-       dev->enetaddr[2] = (maca >> 24) & 0xff;
-       dev->enetaddr[3] = (maca >> 16) & 0xff;
-       dev->enetaddr[4] = (maca >>  8) & 0xff;
-       dev->enetaddr[5] = (maca >>  0) & 0xff;
-
-       return 0;
-}
-
-int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num)
-{
-       if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE)
-               num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE;
-
-       return ksnav_send(&netcp_pktdma, buffer,
-                         num_bytes, (slave_port_num) << 16);
-}
-
-/* Eth device open */
-static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
-{
-       struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
-       struct phy_device *phy_dev = eth_priv->phy_dev;
-
-       debug("+ emac_open\n");
-
-       net_rx_buffs.rx_flow    = eth_priv->rx_flow;
-
-       sys_has_mdio =
-               (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
-
-       if (sys_has_mdio)
-               keystone2_mdio_reset(mdio_bus);
-
-#ifdef CONFIG_SOC_K2G
-       keystone_rgmii_config(phy_dev);
-#else
-       keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1,
-                             eth_priv->sgmii_link_type);
-#endif
-
-       udelay(10000);
-
-       /* On chip switch configuration */
-       ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE);
-
-       /* TODO: add error handling code */
-       if (qm_init()) {
-               printf("ERROR: qm_init()\n");
-               return -1;
-       }
-       if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) {
-               qm_close();
-               printf("ERROR: netcp_init()\n");
-               return -1;
-       }
-
-       /*
-        * Streaming switch configuration. If not present this
-        * statement is defined to void in target.h.
-        * If present this is usually defined to a series of register writes
-        */
-       hw_config_streaming_switch();
-
-       if (sys_has_mdio) {
-               keystone2_mdio_reset(mdio_bus);
-
-               phy_startup(phy_dev);
-               if (phy_dev->link == 0) {
-                       ksnav_close(&netcp_pktdma);
-                       qm_close();
-                       return -1;
-               }
-       }
-
-       emac_gigabit_enable(dev);
-
-       ethss_start();
-
-       debug("- emac_open\n");
-
-       emac_open = 1;
-
-       return 0;
-}
-
-/* Eth device close */
-void keystone2_eth_close(struct eth_device *dev)
-{
-       struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
-       struct phy_device *phy_dev = eth_priv->phy_dev;
-
-       debug("+ emac_close\n");
-
-       if (!emac_open)
-               return;
-
-       ethss_stop();
-
-       ksnav_close(&netcp_pktdma);
-       qm_close();
-       phy_shutdown(phy_dev);
-
-       emac_open = 0;
-
-       debug("- emac_close\n");
-}
-
-/*
- * This function sends a single packet on the network and returns
- * positive number (number of bytes transmitted) or negative for error
- */
-static int keystone2_eth_send_packet(struct eth_device *dev,
-                                       void *packet, int length)
-{
-       int ret_status = -1;
-       struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
-       struct phy_device *phy_dev = eth_priv->phy_dev;
-
-       genphy_update_link(phy_dev);
-       if (phy_dev->link == 0)
-               return -1;
-
-       if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0)
-               return ret_status;
-
-       return length;
-}
-
-/*
- * This function handles receipt of a packet from the network
- */
-static int keystone2_eth_rcv_packet(struct eth_device *dev)
-{
-       void *hd;
-       int  pkt_size;
-       u32  *pkt;
-
-       hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size);
-       if (hd == NULL)
-               return 0;
-
-       net_process_received_packet((uchar *)pkt, pkt_size);
-
-       ksnav_release_rxhd(&netcp_pktdma, hd);
-
-       return pkt_size;
-}
-
-#ifdef CONFIG_MCAST_TFTP
-static int keystone2_eth_bcast_addr(struct eth_device *dev, u32 ip, u8 set)
-{
-       return 0;
-}
-#endif
-
-/*
- * This function initializes the EMAC hardware.
- */
-int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
-{
-       int res;
-       struct eth_device *dev;
-       struct phy_device *phy_dev;
-       struct mdio_regs *adap_mdio = (struct mdio_regs *)EMAC_MDIO_BASE_ADDR;
-
-       dev = malloc(sizeof(struct eth_device));
-       if (dev == NULL)
-               return -1;
-
-       memset(dev, 0, sizeof(struct eth_device));
-
-       strcpy(dev->name, eth_priv->int_name);
-       dev->priv = eth_priv;
-
-       keystone2_eth_read_mac_addr(dev);
-
-       dev->iobase             = 0;
-       dev->init               = keystone2_eth_open;
-       dev->halt               = keystone2_eth_close;
-       dev->send               = keystone2_eth_send_packet;
-       dev->recv               = keystone2_eth_rcv_packet;
-#ifdef CONFIG_MCAST_TFTP
-       dev->mcast              = keystone2_eth_bcast_addr;
-#endif
-
-       eth_register(dev);
-
-       /* Register MDIO bus if it's not registered yet */
-       if (!mdio_bus) {
-               mdio_bus        = mdio_alloc();
-               mdio_bus->read  = keystone2_mdio_read;
-               mdio_bus->write = keystone2_mdio_write;
-               mdio_bus->reset = keystone2_mdio_reset;
-               mdio_bus->priv  = (void *)EMAC_MDIO_BASE_ADDR;
-               strcpy(mdio_bus->name, "ethernet-mdio");
-
-               res = mdio_register(mdio_bus);
-               if (res)
-                       return res;
-       }
-
-#ifndef CONFIG_SOC_K2G
-       keystone2_net_serdes_setup();
-#endif
-
-       /* Create phy device and bind it with driver */
-#ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE
-       phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr,
-                             dev, eth_priv->phy_if);
-       phy_config(phy_dev);
-#else
-       phy_dev = phy_find_by_mask(mdio_bus, 1 << eth_priv->phy_addr,
-                                  eth_priv->phy_if);
-       phy_dev->dev = dev;
-#endif
-       eth_priv->phy_dev = phy_dev;
-
-       return 0;
-}
-
-#else
-
-static int ks2_eth_start(struct udevice *dev)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-
-#ifdef CONFIG_SOC_K2G
-       keystone_rgmii_config(priv->phydev);
-#else
-       keystone_sgmii_config(priv->phydev, priv->slave_port - 1,
-                             priv->sgmii_link_type);
-#endif
-
-       udelay(10000);
-
-       /* On chip switch configuration */
-       ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE);
-
-       qm_init();
-
-       if (ksnav_init(priv->netcp_pktdma, &priv->net_rx_buffs)) {
-               pr_err("ksnav_init failed\n");
-               goto err_knav_init;
-       }
-
-       /*
-        * Streaming switch configuration. If not present this
-        * statement is defined to void in target.h.
-        * If present this is usually defined to a series of register writes
-        */
-       hw_config_streaming_switch();
-
-       if (priv->has_mdio) {
-               keystone2_mdio_reset(priv->mdio_bus);
-
-               phy_startup(priv->phydev);
-               if (priv->phydev->link == 0) {
-                       pr_err("phy startup failed\n");
-                       goto err_phy_start;
-               }
-       }
-
-       emac_gigabit_enable(dev);
-
-       ethss_start();
-
-       priv->emac_open = true;
-
-       return 0;
-
-err_phy_start:
-       ksnav_close(priv->netcp_pktdma);
-err_knav_init:
-       qm_close();
-
-       return -EFAULT;
-}
-
-static int ks2_eth_send(struct udevice *dev, void *packet, int length)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-
-       genphy_update_link(priv->phydev);
-       if (priv->phydev->link == 0)
-               return -1;
-
-       if (length < EMAC_MIN_ETHERNET_PKT_SIZE)
-               length = EMAC_MIN_ETHERNET_PKT_SIZE;
-
-       return ksnav_send(priv->netcp_pktdma, (u32 *)packet,
-                         length, (priv->slave_port) << 16);
-}
-
-static int ks2_eth_recv(struct udevice *dev, int flags, uchar **packetp)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-       int  pkt_size;
-       u32 *pkt = NULL;
-
-       priv->hd = ksnav_recv(priv->netcp_pktdma, &pkt, &pkt_size);
-       if (priv->hd == NULL)
-               return -EAGAIN;
-
-       *packetp = (uchar *)pkt;
-
-       return pkt_size;
-}
-
-static int ks2_eth_free_pkt(struct udevice *dev, uchar *packet,
-                                  int length)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-
-       ksnav_release_rxhd(priv->netcp_pktdma, priv->hd);
-
-       return 0;
-}
-
-static void ks2_eth_stop(struct udevice *dev)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-
-       if (!priv->emac_open)
-               return;
-       ethss_stop();
-
-       ksnav_close(priv->netcp_pktdma);
-       qm_close();
-       phy_shutdown(priv->phydev);
-       priv->emac_open = false;
-}
-
-int ks2_eth_read_rom_hwaddr(struct udevice *dev)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-       struct eth_pdata *pdata = dev_get_platdata(dev);
-       u32 maca = 0;
-       u32 macb = 0;
-
-       /* Read the e-fuse mac address */
-       if (priv->slave_port == 1) {
-               maca = __raw_readl(MAC_ID_BASE_ADDR);
-               macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
-       }
-
-       pdata->enetaddr[0] = (macb >>  8) & 0xff;
-       pdata->enetaddr[1] = (macb >>  0) & 0xff;
-       pdata->enetaddr[2] = (maca >> 24) & 0xff;
-       pdata->enetaddr[3] = (maca >> 16) & 0xff;
-       pdata->enetaddr[4] = (maca >>  8) & 0xff;
-       pdata->enetaddr[5] = (maca >>  0) & 0xff;
-
-       return 0;
-}
-
-int ks2_eth_write_hwaddr(struct udevice *dev)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-       struct eth_pdata *pdata = dev_get_platdata(dev);
-
-       writel(mac_hi(pdata->enetaddr),
-              DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) +
-                                 CPGMACSL_REG_SA_HI);
-       writel(mac_lo(pdata->enetaddr),
-              DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) +
-                                 CPGMACSL_REG_SA_LO);
-
-       return 0;
-}
-
-static int ks2_eth_probe(struct udevice *dev)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-       struct mii_dev *mdio_bus;
-       int ret;
-
-       priv->dev = dev;
-
-       /* These clock enables has to be moved to common location */
-       if (cpu_is_k2g())
-               writel(KS2_ETHERNET_RGMII, KS2_ETHERNET_CFG);
-
-       /* By default, select PA PLL clock as PA clock source */
-#ifndef CONFIG_SOC_K2G
-       if (psc_enable_module(KS2_LPSC_PA))
-               return -EACCES;
-#endif
-       if (psc_enable_module(KS2_LPSC_CPGMAC))
-               return -EACCES;
-       if (psc_enable_module(KS2_LPSC_CRYPTO))
-               return -EACCES;
-
-       if (cpu_is_k2e() || cpu_is_k2l())
-               pll_pa_clk_sel();
-
-
-       priv->net_rx_buffs.buff_ptr = rx_buffs;
-       priv->net_rx_buffs.num_buffs = RX_BUFF_NUMS;
-       priv->net_rx_buffs.buff_len = RX_BUFF_LEN;
-
-       if (priv->slave_port == 1) {
-               /*
-                * Register MDIO bus for slave 0 only, other slave have
-                * to re-use the same
-                */
-               mdio_bus = mdio_alloc();
-               if (!mdio_bus) {
-                       pr_err("MDIO alloc failed\n");
-                       return -ENOMEM;
-               }
-               priv->mdio_bus = mdio_bus;
-               mdio_bus->read  = keystone2_mdio_read;
-               mdio_bus->write = keystone2_mdio_write;
-               mdio_bus->reset = keystone2_mdio_reset;
-               mdio_bus->priv  = priv->mdio_base;
-               sprintf(mdio_bus->name, "ethernet-mdio");
-
-               ret = mdio_register(mdio_bus);
-               if (ret) {
-                       pr_err("MDIO bus register failed\n");
-                       return ret;
-               }
-       } else {
-               /* Get the MDIO bus from slave 0 device */
-               struct ks2_eth_priv *parent_priv;
-
-               parent_priv = dev_get_priv(dev->parent);
-               priv->mdio_bus = parent_priv->mdio_bus;
-       }
-
-#ifndef CONFIG_SOC_K2G
-       keystone2_net_serdes_setup();
-#endif
-
-       priv->netcp_pktdma = &netcp_pktdma;
-
-       if (priv->has_mdio) {
-               priv->phydev = phy_connect(priv->mdio_bus, priv->phy_addr,
-                                          dev, priv->phy_if);
-               phy_config(priv->phydev);
-       }
-
-       return 0;
-}
-
-int ks2_eth_remove(struct udevice *dev)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-
-       free(priv->phydev);
-       mdio_unregister(priv->mdio_bus);
-       mdio_free(priv->mdio_bus);
-
-       return 0;
-}
-
-static const struct eth_ops ks2_eth_ops = {
-       .start                  = ks2_eth_start,
-       .send                   = ks2_eth_send,
-       .recv                   = ks2_eth_recv,
-       .free_pkt               = ks2_eth_free_pkt,
-       .stop                   = ks2_eth_stop,
-       .read_rom_hwaddr        = ks2_eth_read_rom_hwaddr,
-       .write_hwaddr           = ks2_eth_write_hwaddr,
-};
-
-static int ks2_eth_bind_slaves(struct udevice *dev, int gbe, int *gbe_0)
-{
-       const void *fdt = gd->fdt_blob;
-       struct udevice *sl_dev;
-       int interfaces;
-       int sec_slave;
-       int slave;
-       int ret;
-       char *slave_name;
-
-       interfaces = fdt_subnode_offset(fdt, gbe, "interfaces");
-       fdt_for_each_subnode(slave, fdt, interfaces) {
-               int slave_no;
-
-               slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT);
-               if (slave_no == -ENOENT)
-                       continue;
-
-               if (slave_no == 0) {
-                       /* This is the current eth device */
-                       *gbe_0 = slave;
-               } else {
-                       /* Slave devices to be registered */
-                       slave_name = malloc(20);
-                       snprintf(slave_name, 20, "netcp@slave-%d", slave_no);
-                       ret = device_bind_driver_to_node(dev, "eth_ks2_sl",
-                                       slave_name, offset_to_ofnode(slave),
-                                       &sl_dev);
-                       if (ret) {
-                               pr_err("ks2_net - not able to bind slave interfaces\n");
-                               return ret;
-                       }
-               }
-       }
-
-       sec_slave = fdt_subnode_offset(fdt, gbe, "secondary-slave-ports");
-       fdt_for_each_subnode(slave, fdt, sec_slave) {
-               int slave_no;
-
-               slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT);
-               if (slave_no == -ENOENT)
-                       continue;
-
-               /* Slave devices to be registered */
-               slave_name = malloc(20);
-               snprintf(slave_name, 20, "netcp@slave-%d", slave_no);
-               ret = device_bind_driver_to_node(dev, "eth_ks2_sl", slave_name,
-                                       offset_to_ofnode(slave), &sl_dev);
-               if (ret) {
-                       pr_err("ks2_net - not able to bind slave interfaces\n");
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static int ks2_eth_parse_slave_interface(int netcp, int slave,
-                                        struct ks2_eth_priv *priv,
-                                        struct eth_pdata *pdata)
-{
-       const void *fdt = gd->fdt_blob;
-       int mdio;
-       int phy;
-       int dma_count;
-       u32 dma_channel[8];
-
-       priv->slave_port = fdtdec_get_int(fdt, slave, "slave-port", -1);
-       priv->net_rx_buffs.rx_flow = priv->slave_port * 8;
-
-       /* U-Boot slave port number starts with 1 instead of 0 */
-       priv->slave_port += 1;
-
-       dma_count = fdtdec_get_int_array_count(fdt, netcp,
-                                              "ti,navigator-dmas",
-                                              dma_channel, 8);
-
-       if (dma_count > (2 * priv->slave_port)) {
-               int dma_idx;
-
-               dma_idx = priv->slave_port * 2 - 1;
-               priv->net_rx_buffs.rx_flow = dma_channel[dma_idx];
-       }
-
-       priv->link_type = fdtdec_get_int(fdt, slave, "link-interface", -1);
-
-       phy = fdtdec_lookup_phandle(fdt, slave, "phy-handle");
-       if (phy >= 0) {
-               priv->phy_addr = fdtdec_get_int(fdt, phy, "reg", -1);
-
-               mdio = fdt_parent_offset(fdt, phy);
-               if (mdio < 0) {
-                       pr_err("mdio dt not found\n");
-                       return -ENODEV;
-               }
-               priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg");
-       }
-
-       if (priv->link_type == LINK_TYPE_SGMII_MAC_TO_PHY_MODE) {
-               priv->phy_if = PHY_INTERFACE_MODE_SGMII;
-               pdata->phy_interface = priv->phy_if;
-               priv->sgmii_link_type = SGMII_LINK_MAC_PHY;
-               priv->has_mdio = true;
-       } else if (priv->link_type == LINK_TYPE_RGMII_LINK_MAC_PHY) {
-               priv->phy_if = PHY_INTERFACE_MODE_RGMII;
-               pdata->phy_interface = priv->phy_if;
-               priv->has_mdio = true;
-       }
-
-       return 0;
-}
-
-static int ks2_sl_eth_ofdata_to_platdata(struct udevice *dev)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-       struct eth_pdata *pdata = dev_get_platdata(dev);
-       const void *fdt = gd->fdt_blob;
-       int slave = dev_of_offset(dev);
-       int interfaces;
-       int gbe;
-       int netcp_devices;
-       int netcp;
-
-       interfaces = fdt_parent_offset(fdt, slave);
-       gbe = fdt_parent_offset(fdt, interfaces);
-       netcp_devices = fdt_parent_offset(fdt, gbe);
-       netcp = fdt_parent_offset(fdt, netcp_devices);
-
-       ks2_eth_parse_slave_interface(netcp, slave, priv, pdata);
-
-       pdata->iobase = fdtdec_get_addr(fdt, netcp, "reg");
-
-       return 0;
-}
-
-static int ks2_eth_ofdata_to_platdata(struct udevice *dev)
-{
-       struct ks2_eth_priv *priv = dev_get_priv(dev);
-       struct eth_pdata *pdata = dev_get_platdata(dev);
-       const void *fdt = gd->fdt_blob;
-       int gbe_0 = -ENODEV;
-       int netcp_devices;
-       int gbe;
-
-       netcp_devices = fdt_subnode_offset(fdt, dev_of_offset(dev),
-                                          "netcp-devices");
-       gbe = fdt_subnode_offset(fdt, netcp_devices, "gbe");
-
-       ks2_eth_bind_slaves(dev, gbe, &gbe_0);
-
-       ks2_eth_parse_slave_interface(dev_of_offset(dev), gbe_0, priv, pdata);
-
-       pdata->iobase = devfdt_get_addr(dev);
-
-       return 0;
-}
-
-static const struct udevice_id ks2_eth_ids[] = {
-       { .compatible = "ti,netcp-1.0" },
-       { }
-};
-
-U_BOOT_DRIVER(eth_ks2_slave) = {
-       .name   = "eth_ks2_sl",
-       .id     = UCLASS_ETH,
-       .ofdata_to_platdata = ks2_sl_eth_ofdata_to_platdata,
-       .probe  = ks2_eth_probe,
-       .remove = ks2_eth_remove,
-       .ops    = &ks2_eth_ops,
-       .priv_auto_alloc_size = sizeof(struct ks2_eth_priv),
-       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
-       .flags = DM_FLAG_ALLOC_PRIV_DMA,
-};
-
-U_BOOT_DRIVER(eth_ks2) = {
-       .name   = "eth_ks2",
-       .id     = UCLASS_ETH,
-       .of_match = ks2_eth_ids,
-       .ofdata_to_platdata = ks2_eth_ofdata_to_platdata,
-       .probe  = ks2_eth_probe,
-       .remove = ks2_eth_remove,
-       .ops    = &ks2_eth_ops,
-       .priv_auto_alloc_size = sizeof(struct ks2_eth_priv),
-       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
-       .flags = DM_FLAG_ALLOC_PRIV_DMA,
-};
-#endif
diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig
new file mode 100644 (file)
index 0000000..35a6b5d
--- /dev/null
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+
+config DRIVER_TI_CPSW
+       bool "TI Common Platform Ethernet Switch"
+       select PHYLIB
+       help
+         This driver supports the TI three port switch gigabit ethernet
+         subsystem found in the TI SoCs.
+
+config DRIVER_TI_EMAC
+       bool "TI Davinci EMAC"
+       help
+          Support for davinci emac
diff --git a/drivers/net/ti/Makefile b/drivers/net/ti/Makefile
new file mode 100644 (file)
index 0000000..4ab4a27
--- /dev/null
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+
+obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o
+obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
+obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o
diff --git a/drivers/net/ti/cpsw-common.c b/drivers/net/ti/cpsw-common.c
new file mode 100644 (file)
index 0000000..6c8ddbd
--- /dev/null
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CPSW common - libs used across TI ethernet devices.
+ *
+ * Copyright (C) 2016, Texas Instruments, Incorporated
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <environment.h>
+#include <fdt_support.h>
+#include <asm/io.h>
+#include <cpsw.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CTRL_MAC_REG(offset, id) ((offset) + 0x8 * (id))
+
+static int davinci_emac_3517_get_macid(struct udevice *dev, u16 offset,
+                                      int slave, u8 *mac_addr)
+{
+       void *fdt = (void *)gd->fdt_blob;
+       int node = dev_of_offset(dev);
+       u32 macid_lsb;
+       u32 macid_msb;
+       fdt32_t gmii = 0;
+       int syscon;
+       u32 addr;
+
+       syscon = fdtdec_lookup_phandle(fdt, node, "syscon");
+       if (syscon < 0) {
+               pr_err("Syscon offset not found\n");
+               return -ENOENT;
+       }
+
+       addr = (u32)map_physmem(fdt_translate_address(fdt, syscon, &gmii),
+                               sizeof(u32), MAP_NOCACHE);
+       if (addr == FDT_ADDR_T_NONE) {
+               pr_err("Not able to get syscon address to get mac efuse address\n");
+               return -ENOENT;
+       }
+
+       addr += CTRL_MAC_REG(offset, slave);
+
+       /* try reading mac address from efuse */
+       macid_lsb = readl(addr);
+       macid_msb = readl(addr + 4);
+
+       mac_addr[0] = (macid_msb >> 16) & 0xff;
+       mac_addr[1] = (macid_msb >> 8)  & 0xff;
+       mac_addr[2] = macid_msb & 0xff;
+       mac_addr[3] = (macid_lsb >> 16) & 0xff;
+       mac_addr[4] = (macid_lsb >> 8)  & 0xff;
+       mac_addr[5] = macid_lsb & 0xff;
+
+       return 0;
+}
+
+static int cpsw_am33xx_cm_get_macid(struct udevice *dev, u16 offset, int slave,
+                                   u8 *mac_addr)
+{
+       void *fdt = (void *)gd->fdt_blob;
+       int node = dev_of_offset(dev);
+       u32 macid_lo;
+       u32 macid_hi;
+       fdt32_t gmii = 0;
+       int syscon;
+       u32 addr;
+
+       syscon = fdtdec_lookup_phandle(fdt, node, "syscon");
+       if (syscon < 0) {
+               pr_err("Syscon offset not found\n");
+               return -ENOENT;
+       }
+
+       addr = (u32)map_physmem(fdt_translate_address(fdt, syscon, &gmii),
+                               sizeof(u32), MAP_NOCACHE);
+       if (addr == FDT_ADDR_T_NONE) {
+               pr_err("Not able to get syscon address to get mac efuse address\n");
+               return -ENOENT;
+       }
+
+       addr += CTRL_MAC_REG(offset, slave);
+
+       /* try reading mac address from efuse */
+       macid_lo = readl(addr);
+       macid_hi = readl(addr + 4);
+
+       mac_addr[5] = (macid_lo >> 8) & 0xff;
+       mac_addr[4] = macid_lo & 0xff;
+       mac_addr[3] = (macid_hi >> 24) & 0xff;
+       mac_addr[2] = (macid_hi >> 16) & 0xff;
+       mac_addr[1] = (macid_hi >> 8) & 0xff;
+       mac_addr[0] = macid_hi & 0xff;
+
+       return 0;
+}
+
+int ti_cm_get_macid(struct udevice *dev, int slave, u8 *mac_addr)
+{
+       if (of_machine_is_compatible("ti,dm8148"))
+               return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
+
+       if (of_machine_is_compatible("ti,am33xx"))
+               return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
+
+       if (device_is_compatible(dev, "ti,am3517-emac"))
+               return davinci_emac_3517_get_macid(dev, 0x110, slave, mac_addr);
+
+       if (device_is_compatible(dev, "ti,dm816-emac"))
+               return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr);
+
+       if (of_machine_is_compatible("ti,am43"))
+               return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
+
+       if (of_machine_is_compatible("ti,dra7"))
+               return davinci_emac_3517_get_macid(dev, 0x514, slave, mac_addr);
+
+       dev_err(dev, "incompatible machine/device type for reading mac address\n");
+       return -ENOENT;
+}
diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c
new file mode 100644 (file)
index 0000000..8e2a48c
--- /dev/null
@@ -0,0 +1,1508 @@
+/*
+ * CPSW Ethernet Switch Driver
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <miiphy.h>
+#include <malloc.h>
+#include <net.h>
+#include <netdev.h>
+#include <cpsw.h>
+#include <linux/errno.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <phy.h>
+#include <asm/arch/cpu.h>
+#include <dm.h>
+#include <fdt_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define BITMASK(bits)          (BIT(bits) - 1)
+#define PHY_REG_MASK           0x1f
+#define PHY_ID_MASK            0x1f
+#define NUM_DESCS              (PKTBUFSRX * 2)
+#define PKT_MIN                        60
+#define PKT_MAX                        (1500 + 14 + 4 + 4)
+#define CLEAR_BIT              1
+#define GIGABITEN              BIT(7)
+#define FULLDUPLEXEN           BIT(0)
+#define MIIEN                  BIT(15)
+
+/* reg offset */
+#define CPSW_HOST_PORT_OFFSET  0x108
+#define CPSW_SLAVE0_OFFSET     0x208
+#define CPSW_SLAVE1_OFFSET     0x308
+#define CPSW_SLAVE_SIZE                0x100
+#define CPSW_CPDMA_OFFSET      0x800
+#define CPSW_HW_STATS          0x900
+#define CPSW_STATERAM_OFFSET   0xa00
+#define CPSW_CPTS_OFFSET       0xc00
+#define CPSW_ALE_OFFSET                0xd00
+#define CPSW_SLIVER0_OFFSET    0xd80
+#define CPSW_SLIVER1_OFFSET    0xdc0
+#define CPSW_BD_OFFSET         0x2000
+#define CPSW_MDIO_DIV          0xff
+
+#define AM335X_GMII_SEL_OFFSET 0x630
+
+/* DMA Registers */
+#define CPDMA_TXCONTROL                0x004
+#define CPDMA_RXCONTROL                0x014
+#define CPDMA_SOFTRESET                0x01c
+#define CPDMA_RXFREE           0x0e0
+#define CPDMA_TXHDP_VER1       0x100
+#define CPDMA_TXHDP_VER2       0x200
+#define CPDMA_RXHDP_VER1       0x120
+#define CPDMA_RXHDP_VER2       0x220
+#define CPDMA_TXCP_VER1                0x140
+#define CPDMA_TXCP_VER2                0x240
+#define CPDMA_RXCP_VER1                0x160
+#define CPDMA_RXCP_VER2                0x260
+
+/* Descriptor mode bits */
+#define CPDMA_DESC_SOP         BIT(31)
+#define CPDMA_DESC_EOP         BIT(30)
+#define CPDMA_DESC_OWNER       BIT(29)
+#define CPDMA_DESC_EOQ         BIT(28)
+
+/*
+ * This timeout definition is a worst-case ultra defensive measure against
+ * unexpected controller lock ups.  Ideally, we should never ever hit this
+ * scenario in practice.
+ */
+#define MDIO_TIMEOUT            100 /* msecs */
+#define CPDMA_TIMEOUT          100 /* msecs */
+
+struct cpsw_mdio_regs {
+       u32     version;
+       u32     control;
+#define CONTROL_IDLE           BIT(31)
+#define CONTROL_ENABLE         BIT(30)
+
+       u32     alive;
+       u32     link;
+       u32     linkintraw;
+       u32     linkintmasked;
+       u32     __reserved_0[2];
+       u32     userintraw;
+       u32     userintmasked;
+       u32     userintmaskset;
+       u32     userintmaskclr;
+       u32     __reserved_1[20];
+
+       struct {
+               u32             access;
+               u32             physel;
+#define USERACCESS_GO          BIT(31)
+#define USERACCESS_WRITE       BIT(30)
+#define USERACCESS_ACK         BIT(29)
+#define USERACCESS_READ                (0)
+#define USERACCESS_DATA                (0xffff)
+       } user[0];
+};
+
+struct cpsw_regs {
+       u32     id_ver;
+       u32     control;
+       u32     soft_reset;
+       u32     stat_port_en;
+       u32     ptype;
+};
+
+struct cpsw_slave_regs {
+       u32     max_blks;
+       u32     blk_cnt;
+       u32     flow_thresh;
+       u32     port_vlan;
+       u32     tx_pri_map;
+#ifdef CONFIG_AM33XX
+       u32     gap_thresh;
+#elif defined(CONFIG_TI814X)
+       u32     ts_ctl;
+       u32     ts_seq_ltype;
+       u32     ts_vlan;
+#endif
+       u32     sa_lo;
+       u32     sa_hi;
+};
+
+struct cpsw_host_regs {
+       u32     max_blks;
+       u32     blk_cnt;
+       u32     flow_thresh;
+       u32     port_vlan;
+       u32     tx_pri_map;
+       u32     cpdma_tx_pri_map;
+       u32     cpdma_rx_chan_map;
+};
+
+struct cpsw_sliver_regs {
+       u32     id_ver;
+       u32     mac_control;
+       u32     mac_status;
+       u32     soft_reset;
+       u32     rx_maxlen;
+       u32     __reserved_0;
+       u32     rx_pause;
+       u32     tx_pause;
+       u32     __reserved_1;
+       u32     rx_pri_map;
+};
+
+#define ALE_ENTRY_BITS         68
+#define ALE_ENTRY_WORDS                DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
+
+/* ALE Registers */
+#define ALE_CONTROL            0x08
+#define ALE_UNKNOWNVLAN                0x18
+#define ALE_TABLE_CONTROL      0x20
+#define ALE_TABLE              0x34
+#define ALE_PORTCTL            0x40
+
+#define ALE_TABLE_WRITE                BIT(31)
+
+#define ALE_TYPE_FREE                  0
+#define ALE_TYPE_ADDR                  1
+#define ALE_TYPE_VLAN                  2
+#define ALE_TYPE_VLAN_ADDR             3
+
+#define ALE_UCAST_PERSISTANT           0
+#define ALE_UCAST_UNTOUCHED            1
+#define ALE_UCAST_OUI                  2
+#define ALE_UCAST_TOUCHED              3
+
+#define ALE_MCAST_FWD                  0
+#define ALE_MCAST_BLOCK_LEARN_FWD      1
+#define ALE_MCAST_FWD_LEARN            2
+#define ALE_MCAST_FWD_2                        3
+
+enum cpsw_ale_port_state {
+       ALE_PORT_STATE_DISABLE  = 0x00,
+       ALE_PORT_STATE_BLOCK    = 0x01,
+       ALE_PORT_STATE_LEARN    = 0x02,
+       ALE_PORT_STATE_FORWARD  = 0x03,
+};
+
+/* ALE unicast entry flags - passed into cpsw_ale_add_ucast() */
+#define ALE_SECURE     1
+#define ALE_BLOCKED    2
+
+struct cpsw_slave {
+       struct cpsw_slave_regs          *regs;
+       struct cpsw_sliver_regs         *sliver;
+       int                             slave_num;
+       u32                             mac_control;
+       struct cpsw_slave_data          *data;
+};
+
+struct cpdma_desc {
+       /* hardware fields */
+       u32                     hw_next;
+       u32                     hw_buffer;
+       u32                     hw_len;
+       u32                     hw_mode;
+       /* software fields */
+       u32                     sw_buffer;
+       u32                     sw_len;
+};
+
+struct cpdma_chan {
+       struct cpdma_desc       *head, *tail;
+       void                    *hdp, *cp, *rxfree;
+};
+
+/* AM33xx SoC specific definitions for the CONTROL port */
+#define AM33XX_GMII_SEL_MODE_MII       0
+#define AM33XX_GMII_SEL_MODE_RMII      1
+#define AM33XX_GMII_SEL_MODE_RGMII     2
+
+#define AM33XX_GMII_SEL_RGMII1_IDMODE  BIT(4)
+#define AM33XX_GMII_SEL_RGMII2_IDMODE  BIT(5)
+#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN        BIT(6)
+#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN        BIT(7)
+
+#define GMII_SEL_MODE_MASK             0x3
+
+#define desc_write(desc, fld, val)     __raw_writel((u32)(val), &(desc)->fld)
+#define desc_read(desc, fld)           __raw_readl(&(desc)->fld)
+#define desc_read_ptr(desc, fld)       ((void *)__raw_readl(&(desc)->fld))
+
+#define chan_write(chan, fld, val)     __raw_writel((u32)(val), (chan)->fld)
+#define chan_read(chan, fld)           __raw_readl((chan)->fld)
+#define chan_read_ptr(chan, fld)       ((void *)__raw_readl((chan)->fld))
+
+#define for_active_slave(slave, priv) \
+       slave = (priv)->slaves + (priv)->data.active_slave; if (slave)
+#define for_each_slave(slave, priv) \
+       for (slave = (priv)->slaves; slave != (priv)->slaves + \
+                               (priv)->data.slaves; slave++)
+
+struct cpsw_priv {
+#ifdef CONFIG_DM_ETH
+       struct udevice                  *dev;
+#else
+       struct eth_device               *dev;
+#endif
+       struct cpsw_platform_data       data;
+       int                             host_port;
+
+       struct cpsw_regs                *regs;
+       void                            *dma_regs;
+       struct cpsw_host_regs           *host_port_regs;
+       void                            *ale_regs;
+
+       struct cpdma_desc               *descs;
+       struct cpdma_desc               *desc_free;
+       struct cpdma_chan               rx_chan, tx_chan;
+
+       struct cpsw_slave               *slaves;
+       struct phy_device               *phydev;
+       struct mii_dev                  *bus;
+
+       u32                             phy_mask;
+};
+
+static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
+{
+       int idx;
+
+       idx    = start / 32;
+       start -= idx * 32;
+       idx    = 2 - idx; /* flip */
+       return (ale_entry[idx] >> start) & BITMASK(bits);
+}
+
+static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
+                                     u32 value)
+{
+       int idx;
+
+       value &= BITMASK(bits);
+       idx    = start / 32;
+       start -= idx * 32;
+       idx    = 2 - idx; /* flip */
+       ale_entry[idx] &= ~(BITMASK(bits) << start);
+       ale_entry[idx] |=  (value << start);
+}
+
+#define DEFINE_ALE_FIELD(name, start, bits)                            \
+static inline int cpsw_ale_get_##name(u32 *ale_entry)                  \
+{                                                                      \
+       return cpsw_ale_get_field(ale_entry, start, bits);              \
+}                                                                      \
+static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value)      \
+{                                                                      \
+       cpsw_ale_set_field(ale_entry, start, bits, value);              \
+}
+
+DEFINE_ALE_FIELD(entry_type,           60,     2)
+DEFINE_ALE_FIELD(mcast_state,          62,     2)
+DEFINE_ALE_FIELD(port_mask,            66,     3)
+DEFINE_ALE_FIELD(ucast_type,           62,     2)
+DEFINE_ALE_FIELD(port_num,             66,     2)
+DEFINE_ALE_FIELD(blocked,              65,     1)
+DEFINE_ALE_FIELD(secure,               64,     1)
+DEFINE_ALE_FIELD(mcast,                        40,     1)
+
+/* The MAC address field in the ALE entry cannot be macroized as above */
+static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
+{
+       int i;
+
+       for (i = 0; i < 6; i++)
+               addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
+}
+
+static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
+{
+       int i;
+
+       for (i = 0; i < 6; i++)
+               cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
+}
+
+static int cpsw_ale_read(struct cpsw_priv *priv, int idx, u32 *ale_entry)
+{
+       int i;
+
+       __raw_writel(idx, priv->ale_regs + ALE_TABLE_CONTROL);
+
+       for (i = 0; i < ALE_ENTRY_WORDS; i++)
+               ale_entry[i] = __raw_readl(priv->ale_regs + ALE_TABLE + 4 * i);
+
+       return idx;
+}
+
+static int cpsw_ale_write(struct cpsw_priv *priv, int idx, u32 *ale_entry)
+{
+       int i;
+
+       for (i = 0; i < ALE_ENTRY_WORDS; i++)
+               __raw_writel(ale_entry[i], priv->ale_regs + ALE_TABLE + 4 * i);
+
+       __raw_writel(idx | ALE_TABLE_WRITE, priv->ale_regs + ALE_TABLE_CONTROL);
+
+       return idx;
+}
+
+static int cpsw_ale_match_addr(struct cpsw_priv *priv, const u8 *addr)
+{
+       u32 ale_entry[ALE_ENTRY_WORDS];
+       int type, idx;
+
+       for (idx = 0; idx < priv->data.ale_entries; idx++) {
+               u8 entry_addr[6];
+
+               cpsw_ale_read(priv, idx, ale_entry);
+               type = cpsw_ale_get_entry_type(ale_entry);
+               if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
+                       continue;
+               cpsw_ale_get_addr(ale_entry, entry_addr);
+               if (memcmp(entry_addr, addr, 6) == 0)
+                       return idx;
+       }
+       return -ENOENT;
+}
+
+static int cpsw_ale_match_free(struct cpsw_priv *priv)
+{
+       u32 ale_entry[ALE_ENTRY_WORDS];
+       int type, idx;
+
+       for (idx = 0; idx < priv->data.ale_entries; idx++) {
+               cpsw_ale_read(priv, idx, ale_entry);
+               type = cpsw_ale_get_entry_type(ale_entry);
+               if (type == ALE_TYPE_FREE)
+                       return idx;
+       }
+       return -ENOENT;
+}
+
+static int cpsw_ale_find_ageable(struct cpsw_priv *priv)
+{
+       u32 ale_entry[ALE_ENTRY_WORDS];
+       int type, idx;
+
+       for (idx = 0; idx < priv->data.ale_entries; idx++) {
+               cpsw_ale_read(priv, idx, ale_entry);
+               type = cpsw_ale_get_entry_type(ale_entry);
+               if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
+                       continue;
+               if (cpsw_ale_get_mcast(ale_entry))
+                       continue;
+               type = cpsw_ale_get_ucast_type(ale_entry);
+               if (type != ALE_UCAST_PERSISTANT &&
+                   type != ALE_UCAST_OUI)
+                       return idx;
+       }
+       return -ENOENT;
+}
+
+static int cpsw_ale_add_ucast(struct cpsw_priv *priv, const u8 *addr,
+                             int port, int flags)
+{
+       u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+       int idx;
+
+       cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+       cpsw_ale_set_addr(ale_entry, addr);
+       cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
+       cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
+       cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
+       cpsw_ale_set_port_num(ale_entry, port);
+
+       idx = cpsw_ale_match_addr(priv, addr);
+       if (idx < 0)
+               idx = cpsw_ale_match_free(priv);
+       if (idx < 0)
+               idx = cpsw_ale_find_ageable(priv);
+       if (idx < 0)
+               return -ENOMEM;
+
+       cpsw_ale_write(priv, idx, ale_entry);
+       return 0;
+}
+
+static int cpsw_ale_add_mcast(struct cpsw_priv *priv, const u8 *addr,
+                             int port_mask)
+{
+       u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+       int idx, mask;
+
+       idx = cpsw_ale_match_addr(priv, addr);
+       if (idx >= 0)
+               cpsw_ale_read(priv, idx, ale_entry);
+
+       cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+       cpsw_ale_set_addr(ale_entry, addr);
+       cpsw_ale_set_mcast_state(ale_entry, ALE_MCAST_FWD_2);
+
+       mask = cpsw_ale_get_port_mask(ale_entry);
+       port_mask |= mask;
+       cpsw_ale_set_port_mask(ale_entry, port_mask);
+
+       if (idx < 0)
+               idx = cpsw_ale_match_free(priv);
+       if (idx < 0)
+               idx = cpsw_ale_find_ageable(priv);
+       if (idx < 0)
+               return -ENOMEM;
+
+       cpsw_ale_write(priv, idx, ale_entry);
+       return 0;
+}
+
+static inline void cpsw_ale_control(struct cpsw_priv *priv, int bit, int val)
+{
+       u32 tmp, mask = BIT(bit);
+
+       tmp  = __raw_readl(priv->ale_regs + ALE_CONTROL);
+       tmp &= ~mask;
+       tmp |= val ? mask : 0;
+       __raw_writel(tmp, priv->ale_regs + ALE_CONTROL);
+}
+
+#define cpsw_ale_enable(priv, val)     cpsw_ale_control(priv, 31, val)
+#define cpsw_ale_clear(priv, val)      cpsw_ale_control(priv, 30, val)
+#define cpsw_ale_vlan_aware(priv, val) cpsw_ale_control(priv,  2, val)
+
+static inline void cpsw_ale_port_state(struct cpsw_priv *priv, int port,
+                                      int val)
+{
+       int offset = ALE_PORTCTL + 4 * port;
+       u32 tmp, mask = 0x3;
+
+       tmp  = __raw_readl(priv->ale_regs + offset);
+       tmp &= ~mask;
+       tmp |= val & mask;
+       __raw_writel(tmp, priv->ale_regs + offset);
+}
+
+static struct cpsw_mdio_regs *mdio_regs;
+
+/* wait until hardware is ready for another user access */
+static inline u32 wait_for_user_access(void)
+{
+       u32 reg = 0;
+       int timeout = MDIO_TIMEOUT;
+
+       while (timeout-- &&
+       ((reg = __raw_readl(&mdio_regs->user[0].access)) & USERACCESS_GO))
+               udelay(10);
+
+       if (timeout == -1) {
+               printf("wait_for_user_access Timeout\n");
+               return -ETIMEDOUT;
+       }
+       return reg;
+}
+
+/* wait until hardware state machine is idle */
+static inline void wait_for_idle(void)
+{
+       int timeout = MDIO_TIMEOUT;
+
+       while (timeout-- &&
+               ((__raw_readl(&mdio_regs->control) & CONTROL_IDLE) == 0))
+               udelay(10);
+
+       if (timeout == -1)
+               printf("wait_for_idle Timeout\n");
+}
+
+static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
+                               int dev_addr, int phy_reg)
+{
+       int data;
+       u32 reg;
+
+       if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+               return -EINVAL;
+
+       wait_for_user_access();
+       reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
+              (phy_id << 16));
+       __raw_writel(reg, &mdio_regs->user[0].access);
+       reg = wait_for_user_access();
+
+       data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
+       return data;
+}
+
+static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
+                               int phy_reg, u16 data)
+{
+       u32 reg;
+
+       if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+               return -EINVAL;
+
+       wait_for_user_access();
+       reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
+                  (phy_id << 16) | (data & USERACCESS_DATA));
+       __raw_writel(reg, &mdio_regs->user[0].access);
+       wait_for_user_access();
+
+       return 0;
+}
+
+static void cpsw_mdio_init(const char *name, u32 mdio_base, u32 div)
+{
+       struct mii_dev *bus = mdio_alloc();
+
+       mdio_regs = (struct cpsw_mdio_regs *)mdio_base;
+
+       /* set enable and clock divider */
+       __raw_writel(div | CONTROL_ENABLE, &mdio_regs->control);
+
+       /*
+        * wait for scan logic to settle:
+        * the scan time consists of (a) a large fixed component, and (b) a
+        * small component that varies with the mii bus frequency.  These
+        * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
+        * silicon.  Since the effect of (b) was found to be largely
+        * negligible, we keep things simple here.
+        */
+       udelay(1000);
+
+       bus->read = cpsw_mdio_read;
+       bus->write = cpsw_mdio_write;
+       strcpy(bus->name, name);
+
+       mdio_register(bus);
+}
+
+/* Set a self-clearing bit in a register, and wait for it to clear */
+static inline void setbit_and_wait_for_clear32(void *addr)
+{
+       __raw_writel(CLEAR_BIT, addr);
+       while (__raw_readl(addr) & CLEAR_BIT)
+               ;
+}
+
+#define mac_hi(mac)    (((mac)[0] << 0) | ((mac)[1] << 8) |    \
+                        ((mac)[2] << 16) | ((mac)[3] << 24))
+#define mac_lo(mac)    (((mac)[4] << 0) | ((mac)[5] << 8))
+
+static void cpsw_set_slave_mac(struct cpsw_slave *slave,
+                              struct cpsw_priv *priv)
+{
+#ifdef CONFIG_DM_ETH
+       struct eth_pdata *pdata = dev_get_platdata(priv->dev);
+
+       writel(mac_hi(pdata->enetaddr), &slave->regs->sa_hi);
+       writel(mac_lo(pdata->enetaddr), &slave->regs->sa_lo);
+#else
+       __raw_writel(mac_hi(priv->dev->enetaddr), &slave->regs->sa_hi);
+       __raw_writel(mac_lo(priv->dev->enetaddr), &slave->regs->sa_lo);
+#endif
+}
+
+static int cpsw_slave_update_link(struct cpsw_slave *slave,
+                                  struct cpsw_priv *priv, int *link)
+{
+       struct phy_device *phy;
+       u32 mac_control = 0;
+       int ret = -ENODEV;
+
+       phy = priv->phydev;
+       if (!phy)
+               goto out;
+
+       ret = phy_startup(phy);
+       if (ret)
+               goto out;
+
+       if (link)
+               *link = phy->link;
+
+       if (phy->link) { /* link up */
+               mac_control = priv->data.mac_control;
+               if (phy->speed == 1000)
+                       mac_control |= GIGABITEN;
+               if (phy->duplex == DUPLEX_FULL)
+                       mac_control |= FULLDUPLEXEN;
+               if (phy->speed == 100)
+                       mac_control |= MIIEN;
+       }
+
+       if (mac_control == slave->mac_control)
+               goto out;
+
+       if (mac_control) {
+               printf("link up on port %d, speed %d, %s duplex\n",
+                               slave->slave_num, phy->speed,
+                               (phy->duplex == DUPLEX_FULL) ? "full" : "half");
+       } else {
+               printf("link down on port %d\n", slave->slave_num);
+       }
+
+       __raw_writel(mac_control, &slave->sliver->mac_control);
+       slave->mac_control = mac_control;
+
+out:
+       return ret;
+}
+
+static int cpsw_update_link(struct cpsw_priv *priv)
+{
+       int ret = -ENODEV;
+       struct cpsw_slave *slave;
+
+       for_active_slave(slave, priv)
+               ret = cpsw_slave_update_link(slave, priv, NULL);
+
+       return ret;
+}
+
+static inline u32  cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
+{
+       if (priv->host_port == 0)
+               return slave_num + 1;
+       else
+               return slave_num;
+}
+
+static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
+{
+       u32     slave_port;
+
+       setbit_and_wait_for_clear32(&slave->sliver->soft_reset);
+
+       /* setup priority mapping */
+       __raw_writel(0x76543210, &slave->sliver->rx_pri_map);
+       __raw_writel(0x33221100, &slave->regs->tx_pri_map);
+
+       /* setup max packet size, and mac address */
+       __raw_writel(PKT_MAX, &slave->sliver->rx_maxlen);
+       cpsw_set_slave_mac(slave, priv);
+
+       slave->mac_control = 0; /* no link yet */
+
+       /* enable forwarding */
+       slave_port = cpsw_get_slave_port(priv, slave->slave_num);
+       cpsw_ale_port_state(priv, slave_port, ALE_PORT_STATE_FORWARD);
+
+       cpsw_ale_add_mcast(priv, net_bcast_ethaddr, 1 << slave_port);
+
+       priv->phy_mask |= 1 << slave->data->phy_addr;
+}
+
+static struct cpdma_desc *cpdma_desc_alloc(struct cpsw_priv *priv)
+{
+       struct cpdma_desc *desc = priv->desc_free;
+
+       if (desc)
+               priv->desc_free = desc_read_ptr(desc, hw_next);
+       return desc;
+}
+
+static void cpdma_desc_free(struct cpsw_priv *priv, struct cpdma_desc *desc)
+{
+       if (desc) {
+               desc_write(desc, hw_next, priv->desc_free);
+               priv->desc_free = desc;
+       }
+}
+
+static int cpdma_submit(struct cpsw_priv *priv, struct cpdma_chan *chan,
+                       void *buffer, int len)
+{
+       struct cpdma_desc *desc, *prev;
+       u32 mode;
+
+       desc = cpdma_desc_alloc(priv);
+       if (!desc)
+               return -ENOMEM;
+
+       if (len < PKT_MIN)
+               len = PKT_MIN;
+
+       mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
+
+       desc_write(desc, hw_next,   0);
+       desc_write(desc, hw_buffer, buffer);
+       desc_write(desc, hw_len,    len);
+       desc_write(desc, hw_mode,   mode | len);
+       desc_write(desc, sw_buffer, buffer);
+       desc_write(desc, sw_len,    len);
+
+       if (!chan->head) {
+               /* simple case - first packet enqueued */
+               chan->head = desc;
+               chan->tail = desc;
+               chan_write(chan, hdp, desc);
+               goto done;
+       }
+
+       /* not the first packet - enqueue at the tail */
+       prev = chan->tail;
+       desc_write(prev, hw_next, desc);
+       chan->tail = desc;
+
+       /* next check if EOQ has been triggered already */
+       if (desc_read(prev, hw_mode) & CPDMA_DESC_EOQ)
+               chan_write(chan, hdp, desc);
+
+done:
+       if (chan->rxfree)
+               chan_write(chan, rxfree, 1);
+       return 0;
+}
+
+static int cpdma_process(struct cpsw_priv *priv, struct cpdma_chan *chan,
+                        void **buffer, int *len)
+{
+       struct cpdma_desc *desc = chan->head;
+       u32 status;
+
+       if (!desc)
+               return -ENOENT;
+
+       status = desc_read(desc, hw_mode);
+
+       if (len)
+               *len = status & 0x7ff;
+
+       if (buffer)
+               *buffer = desc_read_ptr(desc, sw_buffer);
+
+       if (status & CPDMA_DESC_OWNER) {
+               if (chan_read(chan, hdp) == 0) {
+                       if (desc_read(desc, hw_mode) & CPDMA_DESC_OWNER)
+                               chan_write(chan, hdp, desc);
+               }
+
+               return -EBUSY;
+       }
+
+       chan->head = desc_read_ptr(desc, hw_next);
+       chan_write(chan, cp, desc);
+
+       cpdma_desc_free(priv, desc);
+       return 0;
+}
+
+static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr)
+{
+       struct cpsw_slave       *slave;
+       int i, ret;
+
+       /* soft reset the controller and initialize priv */
+       setbit_and_wait_for_clear32(&priv->regs->soft_reset);
+
+       /* initialize and reset the address lookup engine */
+       cpsw_ale_enable(priv, 1);
+       cpsw_ale_clear(priv, 1);
+       cpsw_ale_vlan_aware(priv, 0); /* vlan unaware mode */
+
+       /* setup host port priority mapping */
+       __raw_writel(0x76543210, &priv->host_port_regs->cpdma_tx_pri_map);
+       __raw_writel(0, &priv->host_port_regs->cpdma_rx_chan_map);
+
+       /* disable priority elevation and enable statistics on all ports */
+       __raw_writel(0, &priv->regs->ptype);
+
+       /* enable statistics collection only on the host port */
+       __raw_writel(BIT(priv->host_port), &priv->regs->stat_port_en);
+       __raw_writel(0x7, &priv->regs->stat_port_en);
+
+       cpsw_ale_port_state(priv, priv->host_port, ALE_PORT_STATE_FORWARD);
+
+       cpsw_ale_add_ucast(priv, enetaddr, priv->host_port, ALE_SECURE);
+       cpsw_ale_add_mcast(priv, net_bcast_ethaddr, 1 << priv->host_port);
+
+       for_active_slave(slave, priv)
+               cpsw_slave_init(slave, priv);
+
+       ret = cpsw_update_link(priv);
+       if (ret)
+               goto out;
+
+       /* init descriptor pool */
+       for (i = 0; i < NUM_DESCS; i++) {
+               desc_write(&priv->descs[i], hw_next,
+                          (i == (NUM_DESCS - 1)) ? 0 : &priv->descs[i+1]);
+       }
+       priv->desc_free = &priv->descs[0];
+
+       /* initialize channels */
+       if (priv->data.version == CPSW_CTRL_VERSION_2) {
+               memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
+               priv->rx_chan.hdp       = priv->dma_regs + CPDMA_RXHDP_VER2;
+               priv->rx_chan.cp        = priv->dma_regs + CPDMA_RXCP_VER2;
+               priv->rx_chan.rxfree    = priv->dma_regs + CPDMA_RXFREE;
+
+               memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
+               priv->tx_chan.hdp       = priv->dma_regs + CPDMA_TXHDP_VER2;
+               priv->tx_chan.cp        = priv->dma_regs + CPDMA_TXCP_VER2;
+       } else {
+               memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
+               priv->rx_chan.hdp       = priv->dma_regs + CPDMA_RXHDP_VER1;
+               priv->rx_chan.cp        = priv->dma_regs + CPDMA_RXCP_VER1;
+               priv->rx_chan.rxfree    = priv->dma_regs + CPDMA_RXFREE;
+
+               memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
+               priv->tx_chan.hdp       = priv->dma_regs + CPDMA_TXHDP_VER1;
+               priv->tx_chan.cp        = priv->dma_regs + CPDMA_TXCP_VER1;
+       }
+
+       /* clear dma state */
+       setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET);
+
+       if (priv->data.version == CPSW_CTRL_VERSION_2) {
+               for (i = 0; i < priv->data.channels; i++) {
+                       __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER2 + 4
+                                       * i);
+                       __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
+                                       * i);
+                       __raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER2 + 4
+                                       * i);
+                       __raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER2 + 4
+                                       * i);
+                       __raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER2 + 4
+                                       * i);
+               }
+       } else {
+               for (i = 0; i < priv->data.channels; i++) {
+                       __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER1 + 4
+                                       * i);
+                       __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
+                                       * i);
+                       __raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER1 + 4
+                                       * i);
+                       __raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER1 + 4
+                                       * i);
+                       __raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER1 + 4
+                                       * i);
+
+               }
+       }
+
+       __raw_writel(1, priv->dma_regs + CPDMA_TXCONTROL);
+       __raw_writel(1, priv->dma_regs + CPDMA_RXCONTROL);
+
+       /* submit rx descs */
+       for (i = 0; i < PKTBUFSRX; i++) {
+               ret = cpdma_submit(priv, &priv->rx_chan, net_rx_packets[i],
+                                  PKTSIZE);
+               if (ret < 0) {
+                       printf("error %d submitting rx desc\n", ret);
+                       break;
+               }
+       }
+
+out:
+       return ret;
+}
+
+static int cpsw_reap_completed_packets(struct cpsw_priv *priv)
+{
+       int timeout = CPDMA_TIMEOUT;
+
+       /* reap completed packets */
+       while (timeout-- &&
+              (cpdma_process(priv, &priv->tx_chan, NULL, NULL) >= 0))
+               ;
+
+       return timeout;
+}
+
+static void _cpsw_halt(struct cpsw_priv *priv)
+{
+       cpsw_reap_completed_packets(priv);
+
+       writel(0, priv->dma_regs + CPDMA_TXCONTROL);
+       writel(0, priv->dma_regs + CPDMA_RXCONTROL);
+
+       /* soft reset the controller and initialize priv */
+       setbit_and_wait_for_clear32(&priv->regs->soft_reset);
+
+       /* clear dma state */
+       setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET);
+
+}
+
+static int _cpsw_send(struct cpsw_priv *priv, void *packet, int length)
+{
+       int timeout;
+
+       flush_dcache_range((unsigned long)packet,
+                          (unsigned long)packet + ALIGN(length, PKTALIGN));
+
+       timeout = cpsw_reap_completed_packets(priv);
+       if (timeout == -1) {
+               printf("cpdma_process timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       return cpdma_submit(priv, &priv->tx_chan, packet, length);
+}
+
+static int _cpsw_recv(struct cpsw_priv *priv, uchar **pkt)
+{
+       void *buffer;
+       int len;
+       int ret;
+
+       ret = cpdma_process(priv, &priv->rx_chan, &buffer, &len);
+       if (ret < 0)
+               return ret;
+
+       invalidate_dcache_range((unsigned long)buffer,
+                               (unsigned long)buffer + PKTSIZE_ALIGN);
+       *pkt = buffer;
+
+       return len;
+}
+
+static void cpsw_slave_setup(struct cpsw_slave *slave, int slave_num,
+                           struct cpsw_priv *priv)
+{
+       void                    *regs = priv->regs;
+       struct cpsw_slave_data  *data = priv->data.slave_data + slave_num;
+       slave->slave_num = slave_num;
+       slave->data     = data;
+       slave->regs     = regs + data->slave_reg_ofs;
+       slave->sliver   = regs + data->sliver_reg_ofs;
+}
+
+static int cpsw_phy_init(struct cpsw_priv *priv, struct cpsw_slave *slave)
+{
+       struct phy_device *phydev;
+       u32 supported = PHY_GBIT_FEATURES;
+
+       phydev = phy_connect(priv->bus,
+                       slave->data->phy_addr,
+                       priv->dev,
+                       slave->data->phy_if);
+
+       if (!phydev)
+               return -1;
+
+       phydev->supported &= supported;
+       phydev->advertising = phydev->supported;
+
+#ifdef CONFIG_DM_ETH
+       if (slave->data->phy_of_handle)
+               phydev->node = offset_to_ofnode(slave->data->phy_of_handle);
+#endif
+
+       priv->phydev = phydev;
+       phy_config(phydev);
+
+       return 1;
+}
+
+static void cpsw_phy_addr_update(struct cpsw_priv *priv)
+{
+       struct cpsw_platform_data *data = &priv->data;
+       u16 alive = mdio_regs->alive & GENMASK(15, 0);
+       int active = data->active_slave;
+       int new_addr = ffs(alive) - 1;
+
+       /*
+        * If there is only one phy alive and its address does not match
+        * that of active slave, then phy address can safely be updated.
+        */
+       if (hweight16(alive) == 1 &&
+           data->slave_data[active].phy_addr != new_addr) {
+               printf("Updated phy address for CPSW#%d, old: %d, new: %d\n",
+                      active, data->slave_data[active].phy_addr, new_addr);
+               data->slave_data[active].phy_addr = new_addr;
+       }
+}
+
+int _cpsw_register(struct cpsw_priv *priv)
+{
+       struct cpsw_slave       *slave;
+       struct cpsw_platform_data *data = &priv->data;
+       void                    *regs = (void *)data->cpsw_base;
+
+       priv->slaves = malloc(sizeof(struct cpsw_slave) * data->slaves);
+       if (!priv->slaves) {
+               return -ENOMEM;
+       }
+
+       priv->host_port         = data->host_port_num;
+       priv->regs              = regs;
+       priv->host_port_regs    = regs + data->host_port_reg_ofs;
+       priv->dma_regs          = regs + data->cpdma_reg_ofs;
+       priv->ale_regs          = regs + data->ale_reg_ofs;
+       priv->descs             = (void *)regs + data->bd_ram_ofs;
+
+       int idx = 0;
+
+       for_each_slave(slave, priv) {
+               cpsw_slave_setup(slave, idx, priv);
+               idx = idx + 1;
+       }
+
+       cpsw_mdio_init(priv->dev->name, data->mdio_base, data->mdio_div);
+
+       cpsw_phy_addr_update(priv);
+
+       priv->bus = miiphy_get_dev_by_name(priv->dev->name);
+       for_active_slave(slave, priv)
+               cpsw_phy_init(priv, slave);
+
+       return 0;
+}
+
+#ifndef CONFIG_DM_ETH
+static int cpsw_init(struct eth_device *dev, bd_t *bis)
+{
+       struct cpsw_priv        *priv = dev->priv;
+
+       return _cpsw_init(priv, dev->enetaddr);
+}
+
+static void cpsw_halt(struct eth_device *dev)
+{
+       struct cpsw_priv *priv = dev->priv;
+
+       return _cpsw_halt(priv);
+}
+
+static int cpsw_send(struct eth_device *dev, void *packet, int length)
+{
+       struct cpsw_priv        *priv = dev->priv;
+
+       return _cpsw_send(priv, packet, length);
+}
+
+static int cpsw_recv(struct eth_device *dev)
+{
+       struct cpsw_priv *priv = dev->priv;
+       uchar *pkt = NULL;
+       int len;
+
+       len = _cpsw_recv(priv, &pkt);
+
+       if (len > 0) {
+               net_process_received_packet(pkt, len);
+               cpdma_submit(priv, &priv->rx_chan, pkt, PKTSIZE);
+       }
+
+       return len;
+}
+
+int cpsw_register(struct cpsw_platform_data *data)
+{
+       struct cpsw_priv        *priv;
+       struct eth_device       *dev;
+       int ret;
+
+       dev = calloc(sizeof(*dev), 1);
+       if (!dev)
+               return -ENOMEM;
+
+       priv = calloc(sizeof(*priv), 1);
+       if (!priv) {
+               free(dev);
+               return -ENOMEM;
+       }
+
+       priv->dev = dev;
+       priv->data = *data;
+
+       strcpy(dev->name, "cpsw");
+       dev->iobase     = 0;
+       dev->init       = cpsw_init;
+       dev->halt       = cpsw_halt;
+       dev->send       = cpsw_send;
+       dev->recv       = cpsw_recv;
+       dev->priv       = priv;
+
+       eth_register(dev);
+
+       ret = _cpsw_register(priv);
+       if (ret < 0) {
+               eth_unregister(dev);
+               free(dev);
+               free(priv);
+               return ret;
+       }
+
+       return 1;
+}
+#else
+static int cpsw_eth_start(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct cpsw_priv *priv = dev_get_priv(dev);
+
+       return _cpsw_init(priv, pdata->enetaddr);
+}
+
+static int cpsw_eth_send(struct udevice *dev, void *packet, int length)
+{
+       struct cpsw_priv *priv = dev_get_priv(dev);
+
+       return _cpsw_send(priv, packet, length);
+}
+
+static int cpsw_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+       struct cpsw_priv *priv = dev_get_priv(dev);
+
+       return _cpsw_recv(priv, packetp);
+}
+
+static int cpsw_eth_free_pkt(struct udevice *dev, uchar *packet,
+                                  int length)
+{
+       struct cpsw_priv *priv = dev_get_priv(dev);
+
+       return cpdma_submit(priv, &priv->rx_chan, packet, PKTSIZE);
+}
+
+static void cpsw_eth_stop(struct udevice *dev)
+{
+       struct cpsw_priv *priv = dev_get_priv(dev);
+
+       return _cpsw_halt(priv);
+}
+
+
+static int cpsw_eth_probe(struct udevice *dev)
+{
+       struct cpsw_priv *priv = dev_get_priv(dev);
+
+       priv->dev = dev;
+
+       return _cpsw_register(priv);
+}
+
+static const struct eth_ops cpsw_eth_ops = {
+       .start          = cpsw_eth_start,
+       .send           = cpsw_eth_send,
+       .recv           = cpsw_eth_recv,
+       .free_pkt       = cpsw_eth_free_pkt,
+       .stop           = cpsw_eth_stop,
+};
+
+static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node)
+{
+       return fdtdec_get_addr_size_auto_noparent(fdt, node, "reg", 0, NULL,
+                                                 false);
+}
+
+static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv,
+                                phy_interface_t phy_mode)
+{
+       u32 reg;
+       u32 mask;
+       u32 mode = 0;
+       bool rgmii_id = false;
+       int slave = priv->data.active_slave;
+
+       reg = readl(priv->data.gmii_sel);
+
+       switch (phy_mode) {
+       case PHY_INTERFACE_MODE_RMII:
+               mode = AM33XX_GMII_SEL_MODE_RMII;
+               break;
+
+       case PHY_INTERFACE_MODE_RGMII:
+               mode = AM33XX_GMII_SEL_MODE_RGMII;
+               break;
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+               mode = AM33XX_GMII_SEL_MODE_RGMII;
+               rgmii_id = true;
+               break;
+
+       case PHY_INTERFACE_MODE_MII:
+       default:
+               mode = AM33XX_GMII_SEL_MODE_MII;
+               break;
+       };
+
+       mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6);
+       mode <<= slave * 2;
+
+       if (priv->data.rmii_clock_external) {
+               if (slave == 0)
+                       mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
+               else
+                       mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
+       }
+
+       if (rgmii_id) {
+               if (slave == 0)
+                       mode |= AM33XX_GMII_SEL_RGMII1_IDMODE;
+               else
+                       mode |= AM33XX_GMII_SEL_RGMII2_IDMODE;
+       }
+
+       reg &= ~mask;
+       reg |= mode;
+
+       writel(reg, priv->data.gmii_sel);
+}
+
+static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv,
+                                phy_interface_t phy_mode)
+{
+       u32 reg;
+       u32 mask;
+       u32 mode = 0;
+       int slave = priv->data.active_slave;
+
+       reg = readl(priv->data.gmii_sel);
+
+       switch (phy_mode) {
+       case PHY_INTERFACE_MODE_RMII:
+               mode = AM33XX_GMII_SEL_MODE_RMII;
+               break;
+
+       case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+               mode = AM33XX_GMII_SEL_MODE_RGMII;
+               break;
+
+       case PHY_INTERFACE_MODE_MII:
+       default:
+               mode = AM33XX_GMII_SEL_MODE_MII;
+               break;
+       };
+
+       switch (slave) {
+       case 0:
+               mask = GMII_SEL_MODE_MASK;
+               break;
+       case 1:
+               mask = GMII_SEL_MODE_MASK << 4;
+               mode <<= 4;
+               break;
+       default:
+               dev_err(priv->dev, "invalid slave number...\n");
+               return;
+       }
+
+       if (priv->data.rmii_clock_external)
+               dev_err(priv->dev, "RMII External clock is not supported\n");
+
+       reg &= ~mask;
+       reg |= mode;
+
+       writel(reg, priv->data.gmii_sel);
+}
+
+static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat,
+                        phy_interface_t phy_mode)
+{
+       if (!strcmp(compat, "ti,am3352-cpsw-phy-sel"))
+               cpsw_gmii_sel_am3352(priv, phy_mode);
+       if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel"))
+               cpsw_gmii_sel_am3352(priv, phy_mode);
+       else if (!strcmp(compat, "ti,dra7xx-cpsw-phy-sel"))
+               cpsw_gmii_sel_dra7xx(priv, phy_mode);
+}
+
+static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct cpsw_priv *priv = dev_get_priv(dev);
+       struct gpio_desc *mode_gpios;
+       const char *phy_mode;
+       const char *phy_sel_compat = NULL;
+       const void *fdt = gd->fdt_blob;
+       int node = dev_of_offset(dev);
+       int subnode;
+       int slave_index = 0;
+       int active_slave;
+       int num_mode_gpios;
+       int ret;
+
+       pdata->iobase = devfdt_get_addr(dev);
+       priv->data.version = CPSW_CTRL_VERSION_2;
+       priv->data.bd_ram_ofs = CPSW_BD_OFFSET;
+       priv->data.ale_reg_ofs = CPSW_ALE_OFFSET;
+       priv->data.cpdma_reg_ofs = CPSW_CPDMA_OFFSET;
+       priv->data.mdio_div = CPSW_MDIO_DIV;
+       priv->data.host_port_reg_ofs = CPSW_HOST_PORT_OFFSET,
+
+       pdata->phy_interface = -1;
+
+       priv->data.cpsw_base = pdata->iobase;
+       priv->data.channels = fdtdec_get_int(fdt, node, "cpdma_channels", -1);
+       if (priv->data.channels <= 0) {
+               printf("error: cpdma_channels not found in dt\n");
+               return -ENOENT;
+       }
+
+       priv->data.slaves = fdtdec_get_int(fdt, node, "slaves", -1);
+       if (priv->data.slaves <= 0) {
+               printf("error: slaves not found in dt\n");
+               return -ENOENT;
+       }
+       priv->data.slave_data = malloc(sizeof(struct cpsw_slave_data) *
+                                      priv->data.slaves);
+
+       priv->data.ale_entries = fdtdec_get_int(fdt, node, "ale_entries", -1);
+       if (priv->data.ale_entries <= 0) {
+               printf("error: ale_entries not found in dt\n");
+               return -ENOENT;
+       }
+
+       priv->data.bd_ram_ofs = fdtdec_get_int(fdt, node, "bd_ram_size", -1);
+       if (priv->data.bd_ram_ofs <= 0) {
+               printf("error: bd_ram_size not found in dt\n");
+               return -ENOENT;
+       }
+
+       priv->data.mac_control = fdtdec_get_int(fdt, node, "mac_control", -1);
+       if (priv->data.mac_control <= 0) {
+               printf("error: ale_entries not found in dt\n");
+               return -ENOENT;
+       }
+
+       num_mode_gpios = gpio_get_list_count(dev, "mode-gpios");
+       if (num_mode_gpios > 0) {
+               mode_gpios = malloc(sizeof(struct gpio_desc) *
+                                   num_mode_gpios);
+               gpio_request_list_by_name(dev, "mode-gpios", mode_gpios,
+                                         num_mode_gpios, GPIOD_IS_OUT);
+               free(mode_gpios);
+       }
+
+       active_slave = fdtdec_get_int(fdt, node, "active_slave", 0);
+       priv->data.active_slave = active_slave;
+
+       fdt_for_each_subnode(subnode, fdt, node) {
+               int len;
+               const char *name;
+
+               name = fdt_get_name(fdt, subnode, &len);
+               if (!strncmp(name, "mdio", 4)) {
+                       u32 mdio_base;
+
+                       mdio_base = cpsw_get_addr_by_node(fdt, subnode);
+                       if (mdio_base == FDT_ADDR_T_NONE) {
+                               pr_err("Not able to get MDIO address space\n");
+                               return -ENOENT;
+                       }
+                       priv->data.mdio_base = mdio_base;
+               }
+
+               if (!strncmp(name, "slave", 5)) {
+                       u32 phy_id[2];
+
+                       if (slave_index >= priv->data.slaves)
+                               continue;
+                       phy_mode = fdt_getprop(fdt, subnode, "phy-mode", NULL);
+                       if (phy_mode)
+                               priv->data.slave_data[slave_index].phy_if =
+                                       phy_get_interface_by_name(phy_mode);
+
+                       priv->data.slave_data[slave_index].phy_of_handle =
+                               fdtdec_lookup_phandle(fdt, subnode,
+                                                     "phy-handle");
+
+                       if (priv->data.slave_data[slave_index].phy_of_handle >= 0) {
+                               priv->data.slave_data[slave_index].phy_addr =
+                                               fdtdec_get_int(gd->fdt_blob,
+                                                              priv->data.slave_data[slave_index].phy_of_handle,
+                                                              "reg", -1);
+                       } else {
+                               fdtdec_get_int_array(fdt, subnode, "phy_id",
+                                                    phy_id, 2);
+                               priv->data.slave_data[slave_index].phy_addr =
+                                               phy_id[1];
+                       }
+                       slave_index++;
+               }
+
+               if (!strncmp(name, "cpsw-phy-sel", 12)) {
+                       priv->data.gmii_sel = cpsw_get_addr_by_node(fdt,
+                                                                   subnode);
+
+                       if (priv->data.gmii_sel == FDT_ADDR_T_NONE) {
+                               pr_err("Not able to get gmii_sel reg address\n");
+                               return -ENOENT;
+                       }
+
+                       if (fdt_get_property(fdt, subnode, "rmii-clock-ext",
+                                            NULL))
+                               priv->data.rmii_clock_external = true;
+
+                       phy_sel_compat = fdt_getprop(fdt, subnode, "compatible",
+                                                    NULL);
+                       if (!phy_sel_compat) {
+                               pr_err("Not able to get gmii_sel compatible\n");
+                               return -ENOENT;
+                       }
+               }
+       }
+
+       priv->data.slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET;
+       priv->data.slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET;
+
+       if (priv->data.slaves == 2) {
+               priv->data.slave_data[1].slave_reg_ofs = CPSW_SLAVE1_OFFSET;
+               priv->data.slave_data[1].sliver_reg_ofs = CPSW_SLIVER1_OFFSET;
+       }
+
+       ret = ti_cm_get_macid(dev, active_slave, pdata->enetaddr);
+       if (ret < 0) {
+               pr_err("cpsw read efuse mac failed\n");
+               return ret;
+       }
+
+       pdata->phy_interface = priv->data.slave_data[active_slave].phy_if;
+       if (pdata->phy_interface == -1) {
+               debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+               return -EINVAL;
+       }
+
+       /* Select phy interface in control module */
+       cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface);
+
+       return 0;
+}
+
+int cpsw_get_slave_phy_addr(struct udevice *dev, int slave)
+{
+       struct cpsw_priv *priv = dev_get_priv(dev);
+       struct cpsw_platform_data *data = &priv->data;
+
+       return data->slave_data[slave].phy_addr;
+}
+
+static const struct udevice_id cpsw_eth_ids[] = {
+       { .compatible = "ti,cpsw" },
+       { .compatible = "ti,am335x-cpsw" },
+       { }
+};
+
+U_BOOT_DRIVER(eth_cpsw) = {
+       .name   = "eth_cpsw",
+       .id     = UCLASS_ETH,
+       .of_match = cpsw_eth_ids,
+       .ofdata_to_platdata = cpsw_eth_ofdata_to_platdata,
+       .probe  = cpsw_eth_probe,
+       .ops    = &cpsw_eth_ops,
+       .priv_auto_alloc_size = sizeof(struct cpsw_priv),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif /* CONFIG_DM_ETH */
diff --git a/drivers/net/ti/davinci_emac.c b/drivers/net/ti/davinci_emac.c
new file mode 100644 (file)
index 0000000..bb879d8
--- /dev/null
@@ -0,0 +1,901 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Ethernet driver for TI TMS320DM644x (DaVinci) chips.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright
+ * follows:
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * dm644x_emac.c
+ *
+ * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM
+ *
+ * Copyright (C) 2005 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * Modifications:
+ * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot.
+ * ver  1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <miiphy.h>
+#include <malloc.h>
+#include <netdev.h>
+#include <linux/compiler.h>
+#include <asm/arch/emac_defs.h>
+#include <asm/io.h>
+#include "davinci_emac.h"
+
+unsigned int   emac_dbg = 0;
+#define debug_emac(fmt,args...)        if (emac_dbg) printf(fmt,##args)
+
+#ifdef EMAC_HW_RAM_ADDR
+static inline unsigned long BD_TO_HW(unsigned long x)
+{
+       if (x == 0)
+               return 0;
+
+       return x - EMAC_WRAPPER_RAM_ADDR + EMAC_HW_RAM_ADDR;
+}
+
+static inline unsigned long HW_TO_BD(unsigned long x)
+{
+       if (x == 0)
+               return 0;
+
+       return x - EMAC_HW_RAM_ADDR + EMAC_WRAPPER_RAM_ADDR;
+}
+#else
+#define BD_TO_HW(x)    (x)
+#define HW_TO_BD(x)    (x)
+#endif
+
+#ifdef DAVINCI_EMAC_GIG_ENABLE
+#define emac_gigabit_enable(phy_addr)  davinci_eth_gigabit_enable(phy_addr)
+#else
+#define emac_gigabit_enable(phy_addr)  /* no gigabit to enable */
+#endif
+
+#if !defined(CONFIG_SYS_EMAC_TI_CLKDIV)
+#define CONFIG_SYS_EMAC_TI_CLKDIV      ((EMAC_MDIO_BUS_FREQ / \
+               EMAC_MDIO_CLOCK_FREQ) - 1)
+#endif
+
+static void davinci_eth_mdio_enable(void);
+
+static int gen_init_phy(int phy_addr);
+static int gen_is_phy_connected(int phy_addr);
+static int gen_get_link_speed(int phy_addr);
+static int gen_auto_negotiate(int phy_addr);
+
+void eth_mdio_enable(void)
+{
+       davinci_eth_mdio_enable();
+}
+
+/* EMAC Addresses */
+static volatile emac_regs      *adap_emac = (emac_regs *)EMAC_BASE_ADDR;
+static volatile ewrap_regs     *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
+static volatile mdio_regs      *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR;
+
+/* EMAC descriptors */
+static volatile emac_desc      *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE);
+static volatile emac_desc      *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
+static volatile emac_desc      *emac_rx_active_head = 0;
+static volatile emac_desc      *emac_rx_active_tail = 0;
+static int                     emac_rx_queue_active = 0;
+
+/* Receive packet buffers */
+static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * EMAC_RXBUF_SIZE]
+                               __aligned(ARCH_DMA_MINALIGN);
+
+#ifndef CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT
+#define CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT      3
+#endif
+
+/* PHY address for a discovered PHY (0xff - not found) */
+static u_int8_t        active_phy_addr[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT];
+
+/* number of PHY found active */
+static u_int8_t        num_phy;
+
+phy_t                          phy[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT];
+
+static int davinci_eth_set_mac_addr(struct eth_device *dev)
+{
+       unsigned long           mac_hi;
+       unsigned long           mac_lo;
+
+       /*
+        * Set MAC Addresses & Init multicast Hash to 0 (disable any multicast
+        * receive)
+        *  Using channel 0 only - other channels are disabled
+        *  */
+       writel(0, &adap_emac->MACINDEX);
+       mac_hi = (dev->enetaddr[3] << 24) |
+                (dev->enetaddr[2] << 16) |
+                (dev->enetaddr[1] << 8)  |
+                (dev->enetaddr[0]);
+       mac_lo = (dev->enetaddr[5] << 8) |
+                (dev->enetaddr[4]);
+
+       writel(mac_hi, &adap_emac->MACADDRHI);
+#if defined(DAVINCI_EMAC_VERSION2)
+       writel(mac_lo | EMAC_MAC_ADDR_IS_VALID | EMAC_MAC_ADDR_MATCH,
+              &adap_emac->MACADDRLO);
+#else
+       writel(mac_lo, &adap_emac->MACADDRLO);
+#endif
+
+       writel(0, &adap_emac->MACHASH1);
+       writel(0, &adap_emac->MACHASH2);
+
+       /* Set source MAC address - REQUIRED */
+       writel(mac_hi, &adap_emac->MACSRCADDRHI);
+       writel(mac_lo, &adap_emac->MACSRCADDRLO);
+
+
+       return 0;
+}
+
+static void davinci_eth_mdio_enable(void)
+{
+       u_int32_t       clkdiv;
+
+       clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV;
+
+       writel((clkdiv & 0xff) |
+              MDIO_CONTROL_ENABLE |
+              MDIO_CONTROL_FAULT |
+              MDIO_CONTROL_FAULT_ENABLE,
+              &adap_mdio->CONTROL);
+
+       while (readl(&adap_mdio->CONTROL) & MDIO_CONTROL_IDLE)
+               ;
+}
+
+/*
+ * Tries to find an active connected PHY. Returns 1 if address if found.
+ * If no active PHY (or more than one PHY) found returns 0.
+ * Sets active_phy_addr variable.
+ */
+static int davinci_eth_phy_detect(void)
+{
+       u_int32_t       phy_act_state;
+       int             i;
+       int             j;
+       unsigned int    count = 0;
+
+       for (i = 0; i < CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT; i++)
+               active_phy_addr[i] = 0xff;
+
+       udelay(1000);
+       phy_act_state = readl(&adap_mdio->ALIVE);
+
+       if (phy_act_state == 0)
+               return 0;               /* No active PHYs */
+
+       debug_emac("davinci_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state);
+
+       for (i = 0, j = 0; i < 32; i++)
+               if (phy_act_state & (1 << i)) {
+                       count++;
+                       if (count <= CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT) {
+                               active_phy_addr[j++] = i;
+                       } else {
+                               printf("%s: to many PHYs detected.\n",
+                                       __func__);
+                               count = 0;
+                               break;
+                       }
+               }
+
+       num_phy = count;
+
+       return count;
+}
+
+
+/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
+int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
+{
+       int     tmp;
+
+       while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
+               ;
+
+       writel(MDIO_USERACCESS0_GO |
+              MDIO_USERACCESS0_WRITE_READ |
+              ((reg_num & 0x1f) << 21) |
+              ((phy_addr & 0x1f) << 16),
+              &adap_mdio->USERACCESS0);
+
+       /* Wait for command to complete */
+       while ((tmp = readl(&adap_mdio->USERACCESS0)) & MDIO_USERACCESS0_GO)
+               ;
+
+       if (tmp & MDIO_USERACCESS0_ACK) {
+               *data = tmp & 0xffff;
+               return 1;
+       }
+
+       return 0;
+}
+
+/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
+int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
+{
+
+       while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
+               ;
+
+       writel(MDIO_USERACCESS0_GO |
+              MDIO_USERACCESS0_WRITE_WRITE |
+              ((reg_num & 0x1f) << 21) |
+              ((phy_addr & 0x1f) << 16) |
+              (data & 0xffff),
+              &adap_mdio->USERACCESS0);
+
+       /* Wait for command to complete */
+       while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
+               ;
+
+       return 1;
+}
+
+/* PHY functions for a generic PHY */
+static int gen_init_phy(int phy_addr)
+{
+       int     ret = 1;
+
+       if (gen_get_link_speed(phy_addr)) {
+               /* Try another time */
+               ret = gen_get_link_speed(phy_addr);
+       }
+
+       return(ret);
+}
+
+static int gen_is_phy_connected(int phy_addr)
+{
+       u_int16_t       dummy;
+
+       return davinci_eth_phy_read(phy_addr, MII_PHYSID1, &dummy);
+}
+
+static int get_active_phy(void)
+{
+       int i;
+
+       for (i = 0; i < num_phy; i++)
+               if (phy[i].get_link_speed(active_phy_addr[i]))
+                       return i;
+
+       return -1;      /* Return error if no link */
+}
+
+static int gen_get_link_speed(int phy_addr)
+{
+       u_int16_t       tmp;
+
+       if (davinci_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) &&
+                       (tmp & 0x04)) {
+#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
+               defined(CONFIG_MACH_DAVINCI_DA850_EVM)
+               davinci_eth_phy_read(phy_addr, MII_LPA, &tmp);
+
+               /* Speed doesn't matter, there is no setting for it in EMAC. */
+               if (tmp & (LPA_100FULL | LPA_10FULL)) {
+                       /* set EMAC for Full Duplex  */
+                       writel(EMAC_MACCONTROL_MIIEN_ENABLE |
+                                       EMAC_MACCONTROL_FULLDUPLEX_ENABLE,
+                                       &adap_emac->MACCONTROL);
+               } else {
+                       /*set EMAC for Half Duplex  */
+                       writel(EMAC_MACCONTROL_MIIEN_ENABLE,
+                                       &adap_emac->MACCONTROL);
+               }
+
+               if (tmp & (LPA_100FULL | LPA_100HALF))
+                       writel(readl(&adap_emac->MACCONTROL) |
+                                       EMAC_MACCONTROL_RMIISPEED_100,
+                                        &adap_emac->MACCONTROL);
+               else
+                       writel(readl(&adap_emac->MACCONTROL) &
+                                       ~EMAC_MACCONTROL_RMIISPEED_100,
+                                        &adap_emac->MACCONTROL);
+#endif
+               return(1);
+       }
+
+       return(0);
+}
+
+static int gen_auto_negotiate(int phy_addr)
+{
+       u_int16_t       tmp;
+       u_int16_t       val;
+       unsigned long   cntr = 0;
+
+       if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp))
+               return 0;
+
+       val = tmp | BMCR_FULLDPLX | BMCR_ANENABLE |
+                                               BMCR_SPEED100;
+       davinci_eth_phy_write(phy_addr, MII_BMCR, val);
+
+       if (!davinci_eth_phy_read(phy_addr, MII_ADVERTISE, &val))
+               return 0;
+
+       val |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL |
+                                                       ADVERTISE_10HALF);
+       davinci_eth_phy_write(phy_addr, MII_ADVERTISE, val);
+
+       if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp))
+               return(0);
+
+#ifdef DAVINCI_EMAC_GIG_ENABLE
+       davinci_eth_phy_read(phy_addr, MII_CTRL1000, &val);
+       val |= PHY_1000BTCR_1000FD;
+       val &= ~PHY_1000BTCR_1000HD;
+       davinci_eth_phy_write(phy_addr, MII_CTRL1000, val);
+       davinci_eth_phy_read(phy_addr, MII_CTRL1000, &val);
+#endif
+
+       /* Restart Auto_negotiation  */
+       tmp |= BMCR_ANRESTART;
+       davinci_eth_phy_write(phy_addr, MII_BMCR, tmp);
+
+       /*check AutoNegotiate complete */
+       do {
+               udelay(40000);
+               if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp))
+                       return 0;
+
+               if (tmp & BMSR_ANEGCOMPLETE)
+                       break;
+
+               cntr++;
+       } while (cntr < 200);
+
+       if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp))
+               return(0);
+
+       if (!(tmp & BMSR_ANEGCOMPLETE))
+               return(0);
+
+       return(gen_get_link_speed(phy_addr));
+}
+/* End of generic PHY functions */
+
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+static int davinci_mii_phy_read(struct mii_dev *bus, int addr, int devad,
+                               int reg)
+{
+       unsigned short value = 0;
+       int retval = davinci_eth_phy_read(addr, reg, &value);
+
+       return retval ? value : -EIO;
+}
+
+static int davinci_mii_phy_write(struct mii_dev *bus, int addr, int devad,
+                                int reg, u16 value)
+{
+       return davinci_eth_phy_write(addr, reg, value) ? 0 : 1;
+}
+#endif
+
+static void  __attribute__((unused)) davinci_eth_gigabit_enable(int phy_addr)
+{
+       u_int16_t data;
+
+       if (davinci_eth_phy_read(phy_addr, 0, &data)) {
+               if (data & (1 << 6)) { /* speed selection MSB */
+                       /*
+                        * Check if link detected is giga-bit
+                        * If Gigabit mode detected, enable gigbit in MAC
+                        */
+                       writel(readl(&adap_emac->MACCONTROL) |
+                               EMAC_MACCONTROL_GIGFORCE |
+                               EMAC_MACCONTROL_GIGABIT_ENABLE,
+                               &adap_emac->MACCONTROL);
+               }
+       }
+}
+
+/* Eth device open */
+static int davinci_eth_open(struct eth_device *dev, bd_t *bis)
+{
+       dv_reg_p                addr;
+       u_int32_t               clkdiv, cnt, mac_control;
+       uint16_t                __maybe_unused lpa_val;
+       volatile emac_desc      *rx_desc;
+       int                     index;
+
+       debug_emac("+ emac_open\n");
+
+       /* Reset EMAC module and disable interrupts in wrapper */
+       writel(1, &adap_emac->SOFTRESET);
+       while (readl(&adap_emac->SOFTRESET) != 0)
+               ;
+#if defined(DAVINCI_EMAC_VERSION2)
+       writel(1, &adap_ewrap->softrst);
+       while (readl(&adap_ewrap->softrst) != 0)
+               ;
+#else
+       writel(0, &adap_ewrap->EWCTL);
+       for (cnt = 0; cnt < 5; cnt++) {
+               clkdiv = readl(&adap_ewrap->EWCTL);
+       }
+#endif
+
+#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
+       defined(CONFIG_MACH_DAVINCI_DA850_EVM)
+       adap_ewrap->c0rxen = adap_ewrap->c1rxen = adap_ewrap->c2rxen = 0;
+       adap_ewrap->c0txen = adap_ewrap->c1txen = adap_ewrap->c2txen = 0;
+       adap_ewrap->c0miscen = adap_ewrap->c1miscen = adap_ewrap->c2miscen = 0;
+#endif
+       rx_desc = emac_rx_desc;
+
+       writel(1, &adap_emac->TXCONTROL);
+       writel(1, &adap_emac->RXCONTROL);
+
+       davinci_eth_set_mac_addr(dev);
+
+       /* Set DMA 8 TX / 8 RX Head pointers to 0 */
+       addr = &adap_emac->TX0HDP;
+       for (cnt = 0; cnt < 8; cnt++)
+               writel(0, addr++);
+
+       addr = &adap_emac->RX0HDP;
+       for (cnt = 0; cnt < 8; cnt++)
+               writel(0, addr++);
+
+       /* Clear Statistics (do this before setting MacControl register) */
+       addr = &adap_emac->RXGOODFRAMES;
+       for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++)
+               writel(0, addr++);
+
+       /* No multicast addressing */
+       writel(0, &adap_emac->MACHASH1);
+       writel(0, &adap_emac->MACHASH2);
+
+       /* Create RX queue and set receive process in place */
+       emac_rx_active_head = emac_rx_desc;
+       for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) {
+               rx_desc->next = BD_TO_HW((u_int32_t)(rx_desc + 1));
+               rx_desc->buffer = &emac_rx_buffers[cnt * EMAC_RXBUF_SIZE];
+               rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
+               rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
+               rx_desc++;
+       }
+
+       /* Finalize the rx desc list */
+       rx_desc--;
+       rx_desc->next = 0;
+       emac_rx_active_tail = rx_desc;
+       emac_rx_queue_active = 1;
+
+       /* Enable TX/RX */
+       writel(EMAC_MAX_ETHERNET_PKT_SIZE, &adap_emac->RXMAXLEN);
+       writel(0, &adap_emac->RXBUFFEROFFSET);
+
+       /*
+        * No fancy configs - Use this for promiscous debug
+        *   - EMAC_RXMBPENABLE_RXCAFEN_ENABLE
+        */
+       writel(EMAC_RXMBPENABLE_RXBROADEN, &adap_emac->RXMBPENABLE);
+
+       /* Enable ch 0 only */
+       writel(1, &adap_emac->RXUNICASTSET);
+
+       /* Init MDIO & get link state */
+       clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV;
+       writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT,
+              &adap_mdio->CONTROL);
+
+       /* We need to wait for MDIO to start */
+       udelay(1000);
+
+       index = get_active_phy();
+       if (index == -1)
+               return(0);
+
+       /* Enable MII interface */
+       mac_control = EMAC_MACCONTROL_MIIEN_ENABLE;
+#ifdef DAVINCI_EMAC_GIG_ENABLE
+       davinci_eth_phy_read(active_phy_addr[index], MII_STAT1000, &lpa_val);
+       if (lpa_val & PHY_1000BTSR_1000FD) {
+               debug_emac("eth_open : gigabit negotiated\n");
+               mac_control |= EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+               mac_control |= EMAC_MACCONTROL_GIGABIT_ENABLE;
+       }
+#endif
+
+       davinci_eth_phy_read(active_phy_addr[index], MII_LPA, &lpa_val);
+       if (lpa_val & (LPA_100FULL | LPA_10FULL))
+               /* set EMAC for Full Duplex  */
+               mac_control |= EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+#if defined(CONFIG_SOC_DA8XX) || \
+       (defined(CONFIG_OMAP34XX) && defined(CONFIG_DRIVER_TI_EMAC_USE_RMII))
+       mac_control |= EMAC_MACCONTROL_RMIISPEED_100;
+#endif
+       writel(mac_control, &adap_emac->MACCONTROL);
+       /* Start receive process */
+       writel(BD_TO_HW((u_int32_t)emac_rx_desc), &adap_emac->RX0HDP);
+
+       debug_emac("- emac_open\n");
+
+       return(1);
+}
+
+/* EMAC Channel Teardown */
+static void davinci_eth_ch_teardown(int ch)
+{
+       dv_reg          dly = 0xff;
+       dv_reg          cnt;
+
+       debug_emac("+ emac_ch_teardown\n");
+
+       if (ch == EMAC_CH_TX) {
+               /* Init TX channel teardown */
+               writel(0, &adap_emac->TXTEARDOWN);
+               do {
+                       /*
+                        * Wait here for Tx teardown completion interrupt to
+                        * occur. Note: A task delay can be called here to pend
+                        * rather than occupying CPU cycles - anyway it has
+                        * been found that teardown takes very few cpu cycles
+                        * and does not affect functionality
+                        */
+                       dly--;
+                       udelay(1);
+                       if (dly == 0)
+                               break;
+                       cnt = readl(&adap_emac->TX0CP);
+               } while (cnt != 0xfffffffc);
+               writel(cnt, &adap_emac->TX0CP);
+               writel(0, &adap_emac->TX0HDP);
+       } else {
+               /* Init RX channel teardown */
+               writel(0, &adap_emac->RXTEARDOWN);
+               do {
+                       /*
+                        * Wait here for Rx teardown completion interrupt to
+                        * occur. Note: A task delay can be called here to pend
+                        * rather than occupying CPU cycles - anyway it has
+                        * been found that teardown takes very few cpu cycles
+                        * and does not affect functionality
+                        */
+                       dly--;
+                       udelay(1);
+                       if (dly == 0)
+                               break;
+                       cnt = readl(&adap_emac->RX0CP);
+               } while (cnt != 0xfffffffc);
+               writel(cnt, &adap_emac->RX0CP);
+               writel(0, &adap_emac->RX0HDP);
+       }
+
+       debug_emac("- emac_ch_teardown\n");
+}
+
+/* Eth device close */
+static void davinci_eth_close(struct eth_device *dev)
+{
+       debug_emac("+ emac_close\n");
+
+       davinci_eth_ch_teardown(EMAC_CH_TX);    /* TX Channel teardown */
+       if (readl(&adap_emac->RXCONTROL) & 1)
+               davinci_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */
+
+       /* Reset EMAC module and disable interrupts in wrapper */
+       writel(1, &adap_emac->SOFTRESET);
+#if defined(DAVINCI_EMAC_VERSION2)
+       writel(1, &adap_ewrap->softrst);
+#else
+       writel(0, &adap_ewrap->EWCTL);
+#endif
+
+#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
+       defined(CONFIG_MACH_DAVINCI_DA850_EVM)
+       adap_ewrap->c0rxen = adap_ewrap->c1rxen = adap_ewrap->c2rxen = 0;
+       adap_ewrap->c0txen = adap_ewrap->c1txen = adap_ewrap->c2txen = 0;
+       adap_ewrap->c0miscen = adap_ewrap->c1miscen = adap_ewrap->c2miscen = 0;
+#endif
+       debug_emac("- emac_close\n");
+}
+
+static int tx_send_loop = 0;
+
+/*
+ * This function sends a single packet on the network and returns
+ * positive number (number of bytes transmitted) or negative for error
+ */
+static int davinci_eth_send_packet (struct eth_device *dev,
+                                       void *packet, int length)
+{
+       int ret_status = -1;
+       int index;
+       tx_send_loop = 0;
+
+       index = get_active_phy();
+       if (index == -1) {
+               printf(" WARN: emac_send_packet: No link\n");
+               return (ret_status);
+       }
+
+       /* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */
+       if (length < EMAC_MIN_ETHERNET_PKT_SIZE) {
+               length = EMAC_MIN_ETHERNET_PKT_SIZE;
+       }
+
+       /* Populate the TX descriptor */
+       emac_tx_desc->next = 0;
+       emac_tx_desc->buffer = (u_int8_t *) packet;
+       emac_tx_desc->buff_off_len = (length & 0xffff);
+       emac_tx_desc->pkt_flag_len = ((length & 0xffff) |
+                                     EMAC_CPPI_SOP_BIT |
+                                     EMAC_CPPI_OWNERSHIP_BIT |
+                                     EMAC_CPPI_EOP_BIT);
+
+       flush_dcache_range((unsigned long)packet,
+                          (unsigned long)packet + ALIGN(length, PKTALIGN));
+
+       /* Send the packet */
+       writel(BD_TO_HW((unsigned long)emac_tx_desc), &adap_emac->TX0HDP);
+
+       /* Wait for packet to complete or link down */
+       while (1) {
+               if (!phy[index].get_link_speed(active_phy_addr[index])) {
+                       davinci_eth_ch_teardown (EMAC_CH_TX);
+                       return (ret_status);
+               }
+
+               if (readl(&adap_emac->TXINTSTATRAW) & 0x01) {
+                       ret_status = length;
+                       break;
+               }
+               tx_send_loop++;
+       }
+
+       return (ret_status);
+}
+
+/*
+ * This function handles receipt of a packet from the network
+ */
+static int davinci_eth_rcv_packet (struct eth_device *dev)
+{
+       volatile emac_desc *rx_curr_desc;
+       volatile emac_desc *curr_desc;
+       volatile emac_desc *tail_desc;
+       int status, ret = -1;
+
+       rx_curr_desc = emac_rx_active_head;
+       if (!rx_curr_desc)
+               return 0;
+       status = rx_curr_desc->pkt_flag_len;
+       if ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0) {
+               if (status & EMAC_CPPI_RX_ERROR_FRAME) {
+                       /* Error in packet - discard it and requeue desc */
+                       printf ("WARN: emac_rcv_pkt: Error in packet\n");
+               } else {
+                       unsigned long tmp = (unsigned long)rx_curr_desc->buffer;
+                       unsigned short len =
+                               rx_curr_desc->buff_off_len & 0xffff;
+
+                       invalidate_dcache_range(tmp, tmp + ALIGN(len, PKTALIGN));
+                       net_process_received_packet(rx_curr_desc->buffer, len);
+                       ret = len;
+               }
+
+               /* Ack received packet descriptor */
+               writel(BD_TO_HW((ulong)rx_curr_desc), &adap_emac->RX0CP);
+               curr_desc = rx_curr_desc;
+               emac_rx_active_head =
+                       (volatile emac_desc *) (HW_TO_BD(rx_curr_desc->next));
+
+               if (status & EMAC_CPPI_EOQ_BIT) {
+                       if (emac_rx_active_head) {
+                               writel(BD_TO_HW((ulong)emac_rx_active_head),
+                                      &adap_emac->RX0HDP);
+                       } else {
+                               emac_rx_queue_active = 0;
+                               printf ("INFO:emac_rcv_packet: RX Queue not active\n");
+                       }
+               }
+
+               /* Recycle RX descriptor */
+               rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
+               rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
+               rx_curr_desc->next = 0;
+
+               if (emac_rx_active_head == 0) {
+                       printf ("INFO: emac_rcv_pkt: active queue head = 0\n");
+                       emac_rx_active_head = curr_desc;
+                       emac_rx_active_tail = curr_desc;
+                       if (emac_rx_queue_active != 0) {
+                               writel(BD_TO_HW((ulong)emac_rx_active_head),
+                                      &adap_emac->RX0HDP);
+                               printf ("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n");
+                               emac_rx_queue_active = 1;
+                       }
+               } else {
+                       tail_desc = emac_rx_active_tail;
+                       emac_rx_active_tail = curr_desc;
+                       tail_desc->next = BD_TO_HW((ulong) curr_desc);
+                       status = tail_desc->pkt_flag_len;
+                       if (status & EMAC_CPPI_EOQ_BIT) {
+                               writel(BD_TO_HW((ulong)curr_desc),
+                                      &adap_emac->RX0HDP);
+                               status &= ~EMAC_CPPI_EOQ_BIT;
+                               tail_desc->pkt_flag_len = status;
+                       }
+               }
+               return (ret);
+       }
+       return (0);
+}
+
+/*
+ * This function initializes the emac hardware. It does NOT initialize
+ * EMAC modules power or pin multiplexors, that is done by board_init()
+ * much earlier in bootup process. Returns 1 on success, 0 otherwise.
+ */
+int davinci_emac_initialize(void)
+{
+       u_int32_t       phy_id;
+       u_int16_t       tmp;
+       int             i;
+       int             ret;
+       struct eth_device *dev;
+
+       dev = malloc(sizeof *dev);
+
+       if (dev == NULL)
+               return -1;
+
+       memset(dev, 0, sizeof *dev);
+       strcpy(dev->name, "DaVinci-EMAC");
+
+       dev->iobase = 0;
+       dev->init = davinci_eth_open;
+       dev->halt = davinci_eth_close;
+       dev->send = davinci_eth_send_packet;
+       dev->recv = davinci_eth_rcv_packet;
+       dev->write_hwaddr = davinci_eth_set_mac_addr;
+
+       eth_register(dev);
+
+       davinci_eth_mdio_enable();
+
+       /* let the EMAC detect the PHYs */
+       udelay(5000);
+
+       for (i = 0; i < 256; i++) {
+               if (readl(&adap_mdio->ALIVE))
+                       break;
+               udelay(1000);
+       }
+
+       if (i >= 256) {
+               printf("No ETH PHY detected!!!\n");
+               return(0);
+       }
+
+       /* Find if PHY(s) is/are connected */
+       ret = davinci_eth_phy_detect();
+       if (!ret)
+               return(0);
+       else
+               debug_emac(" %d ETH PHY detected\n", ret);
+
+       /* Get PHY ID and initialize phy_ops for a detected PHY */
+       for (i = 0; i < num_phy; i++) {
+               if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID1,
+                                                       &tmp)) {
+                       active_phy_addr[i] = 0xff;
+                       continue;
+               }
+
+               phy_id = (tmp << 16) & 0xffff0000;
+
+               if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID2,
+                                                       &tmp)) {
+                       active_phy_addr[i] = 0xff;
+                       continue;
+               }
+
+               phy_id |= tmp & 0x0000ffff;
+
+               switch (phy_id) {
+#ifdef PHY_KSZ8873
+               case PHY_KSZ8873:
+                       sprintf(phy[i].name, "KSZ8873 @ 0x%02x",
+                                               active_phy_addr[i]);
+                       phy[i].init = ksz8873_init_phy;
+                       phy[i].is_phy_connected = ksz8873_is_phy_connected;
+                       phy[i].get_link_speed = ksz8873_get_link_speed;
+                       phy[i].auto_negotiate = ksz8873_auto_negotiate;
+                       break;
+#endif
+#ifdef PHY_LXT972
+               case PHY_LXT972:
+                       sprintf(phy[i].name, "LXT972 @ 0x%02x",
+                                               active_phy_addr[i]);
+                       phy[i].init = lxt972_init_phy;
+                       phy[i].is_phy_connected = lxt972_is_phy_connected;
+                       phy[i].get_link_speed = lxt972_get_link_speed;
+                       phy[i].auto_negotiate = lxt972_auto_negotiate;
+                       break;
+#endif
+#ifdef PHY_DP83848
+               case PHY_DP83848:
+                       sprintf(phy[i].name, "DP83848 @ 0x%02x",
+                                               active_phy_addr[i]);
+                       phy[i].init = dp83848_init_phy;
+                       phy[i].is_phy_connected = dp83848_is_phy_connected;
+                       phy[i].get_link_speed = dp83848_get_link_speed;
+                       phy[i].auto_negotiate = dp83848_auto_negotiate;
+                       break;
+#endif
+#ifdef PHY_ET1011C
+               case PHY_ET1011C:
+                       sprintf(phy[i].name, "ET1011C @ 0x%02x",
+                                               active_phy_addr[i]);
+                       phy[i].init = gen_init_phy;
+                       phy[i].is_phy_connected = gen_is_phy_connected;
+                       phy[i].get_link_speed = et1011c_get_link_speed;
+                       phy[i].auto_negotiate = gen_auto_negotiate;
+                       break;
+#endif
+               default:
+                       sprintf(phy[i].name, "GENERIC @ 0x%02x",
+                                               active_phy_addr[i]);
+                       phy[i].init = gen_init_phy;
+                       phy[i].is_phy_connected = gen_is_phy_connected;
+                       phy[i].get_link_speed = gen_get_link_speed;
+                       phy[i].auto_negotiate = gen_auto_negotiate;
+               }
+
+               debug("Ethernet PHY: %s\n", phy[i].name);
+
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, phy[i].name, MDIO_NAME_LEN);
+               mdiodev->read = davinci_mii_phy_read;
+               mdiodev->write = davinci_mii_phy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
+#ifdef DAVINCI_EMAC_GIG_ENABLE
+#define PHY_CONF_REG   22
+               /* Enable PHY to clock out TX_CLK */
+               davinci_eth_phy_read(active_phy_addr[i], PHY_CONF_REG, &tmp);
+               tmp |= PHY_CONF_TXCLKEN;
+               davinci_eth_phy_write(active_phy_addr[i], PHY_CONF_REG, tmp);
+               davinci_eth_phy_read(active_phy_addr[i], PHY_CONF_REG, &tmp);
+#endif
+       }
+
+#if defined(CONFIG_TI816X) || (defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
+               defined(CONFIG_MACH_DAVINCI_DA850_EVM) && \
+                       !defined(CONFIG_DRIVER_TI_EMAC_RMII_NO_NEGOTIATE))
+       for (i = 0; i < num_phy; i++) {
+               if (phy[i].is_phy_connected(i))
+                       phy[i].auto_negotiate(i);
+       }
+#endif
+       return(1);
+}
diff --git a/drivers/net/ti/davinci_emac.h b/drivers/net/ti/davinci_emac.h
new file mode 100644 (file)
index 0000000..695855b
--- /dev/null
@@ -0,0 +1,304 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2011 Ilya Yanok, Emcraft Systems
+ *
+ * Based on: mach-davinci/emac_defs.h
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ */
+
+#ifndef _DAVINCI_EMAC_H_
+#define _DAVINCI_EMAC_H_
+/* Ethernet Min/Max packet size */
+#define EMAC_MIN_ETHERNET_PKT_SIZE     60
+#define EMAC_MAX_ETHERNET_PKT_SIZE     1518
+/* Buffer size (should be aligned on 32 byte and cache line) */
+#define EMAC_RXBUF_SIZE        ALIGN(ALIGN(EMAC_MAX_ETHERNET_PKT_SIZE, 32),\
+                               ARCH_DMA_MINALIGN)
+
+/* Number of RX packet buffers
+ * NOTE: Only 1 buffer supported as of now
+ */
+#define EMAC_MAX_RX_BUFFERS            10
+
+
+/***********************************************
+ ******** Internally used macros ***************
+ ***********************************************/
+
+#define EMAC_CH_TX                     1
+#define EMAC_CH_RX                     0
+
+/* Each descriptor occupies 4 words, lets start RX desc's at 0 and
+ * reserve space for 64 descriptors max
+ */
+#define EMAC_RX_DESC_BASE              0x0
+#define EMAC_TX_DESC_BASE              0x1000
+
+/* EMAC Teardown value */
+#define EMAC_TEARDOWN_VALUE            0xfffffffc
+
+/* MII Status Register */
+#define MII_STATUS_REG                 1
+/* PHY Configuration register */
+#define PHY_CONF_TXCLKEN               (1 << 5)
+
+/* Number of statistics registers */
+#define EMAC_NUM_STATS                 36
+
+
+/* EMAC Descriptor */
+typedef volatile struct _emac_desc
+{
+       u_int32_t       next;           /* Pointer to next descriptor
+                                          in chain */
+       u_int8_t        *buffer;        /* Pointer to data buffer */
+       u_int32_t       buff_off_len;   /* Buffer Offset(MSW) and Length(LSW) */
+       u_int32_t       pkt_flag_len;   /* Packet Flags(MSW) and Length(LSW) */
+} emac_desc;
+
+/* CPPI bit positions */
+#define EMAC_CPPI_SOP_BIT              (0x80000000)
+#define EMAC_CPPI_EOP_BIT              (0x40000000)
+#define EMAC_CPPI_OWNERSHIP_BIT                (0x20000000)
+#define EMAC_CPPI_EOQ_BIT              (0x10000000)
+#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT        (0x08000000)
+#define EMAC_CPPI_PASS_CRC_BIT         (0x04000000)
+
+#define EMAC_CPPI_RX_ERROR_FRAME       (0x03fc0000)
+
+#define EMAC_MACCONTROL_MIIEN_ENABLE           (0x20)
+#define EMAC_MACCONTROL_FULLDUPLEX_ENABLE      (0x1)
+#define EMAC_MACCONTROL_GIGABIT_ENABLE         (1 << 7)
+#define EMAC_MACCONTROL_GIGFORCE               (1 << 17)
+#define EMAC_MACCONTROL_RMIISPEED_100          (1 << 15)
+
+#define EMAC_MAC_ADDR_MATCH            (1 << 19)
+#define EMAC_MAC_ADDR_IS_VALID         (1 << 20)
+
+#define EMAC_RXMBPENABLE_RXCAFEN_ENABLE        (0x200000)
+#define EMAC_RXMBPENABLE_RXBROADEN     (0x2000)
+
+
+#define MDIO_CONTROL_IDLE              (0x80000000)
+#define MDIO_CONTROL_ENABLE            (0x40000000)
+#define MDIO_CONTROL_FAULT_ENABLE      (0x40000)
+#define MDIO_CONTROL_FAULT             (0x80000)
+#define MDIO_USERACCESS0_GO            (0x80000000)
+#define MDIO_USERACCESS0_WRITE_READ    (0x0)
+#define MDIO_USERACCESS0_WRITE_WRITE   (0x40000000)
+#define MDIO_USERACCESS0_ACK           (0x20000000)
+
+/* Ethernet MAC Registers Structure */
+typedef struct  {
+       dv_reg          TXIDVER;
+       dv_reg          TXCONTROL;
+       dv_reg          TXTEARDOWN;
+       u_int8_t        RSVD0[4];
+       dv_reg          RXIDVER;
+       dv_reg          RXCONTROL;
+       dv_reg          RXTEARDOWN;
+       u_int8_t        RSVD1[100];
+       dv_reg          TXINTSTATRAW;
+       dv_reg          TXINTSTATMASKED;
+       dv_reg          TXINTMASKSET;
+       dv_reg          TXINTMASKCLEAR;
+       dv_reg          MACINVECTOR;
+       u_int8_t        RSVD2[12];
+       dv_reg          RXINTSTATRAW;
+       dv_reg          RXINTSTATMASKED;
+       dv_reg          RXINTMASKSET;
+       dv_reg          RXINTMASKCLEAR;
+       dv_reg          MACINTSTATRAW;
+       dv_reg          MACINTSTATMASKED;
+       dv_reg          MACINTMASKSET;
+       dv_reg          MACINTMASKCLEAR;
+       u_int8_t        RSVD3[64];
+       dv_reg          RXMBPENABLE;
+       dv_reg          RXUNICASTSET;
+       dv_reg          RXUNICASTCLEAR;
+       dv_reg          RXMAXLEN;
+       dv_reg          RXBUFFEROFFSET;
+       dv_reg          RXFILTERLOWTHRESH;
+       u_int8_t        RSVD4[8];
+       dv_reg          RX0FLOWTHRESH;
+       dv_reg          RX1FLOWTHRESH;
+       dv_reg          RX2FLOWTHRESH;
+       dv_reg          RX3FLOWTHRESH;
+       dv_reg          RX4FLOWTHRESH;
+       dv_reg          RX5FLOWTHRESH;
+       dv_reg          RX6FLOWTHRESH;
+       dv_reg          RX7FLOWTHRESH;
+       dv_reg          RX0FREEBUFFER;
+       dv_reg          RX1FREEBUFFER;
+       dv_reg          RX2FREEBUFFER;
+       dv_reg          RX3FREEBUFFER;
+       dv_reg          RX4FREEBUFFER;
+       dv_reg          RX5FREEBUFFER;
+       dv_reg          RX6FREEBUFFER;
+       dv_reg          RX7FREEBUFFER;
+       dv_reg          MACCONTROL;
+       dv_reg          MACSTATUS;
+       dv_reg          EMCONTROL;
+       dv_reg          FIFOCONTROL;
+       dv_reg          MACCONFIG;
+       dv_reg          SOFTRESET;
+       u_int8_t        RSVD5[88];
+       dv_reg          MACSRCADDRLO;
+       dv_reg          MACSRCADDRHI;
+       dv_reg          MACHASH1;
+       dv_reg          MACHASH2;
+       dv_reg          BOFFTEST;
+       dv_reg          TPACETEST;
+       dv_reg          RXPAUSE;
+       dv_reg          TXPAUSE;
+       u_int8_t        RSVD6[16];
+       dv_reg          RXGOODFRAMES;
+       dv_reg          RXBCASTFRAMES;
+       dv_reg          RXMCASTFRAMES;
+       dv_reg          RXPAUSEFRAMES;
+       dv_reg          RXCRCERRORS;
+       dv_reg          RXALIGNCODEERRORS;
+       dv_reg          RXOVERSIZED;
+       dv_reg          RXJABBER;
+       dv_reg          RXUNDERSIZED;
+       dv_reg          RXFRAGMENTS;
+       dv_reg          RXFILTERED;
+       dv_reg          RXQOSFILTERED;
+       dv_reg          RXOCTETS;
+       dv_reg          TXGOODFRAMES;
+       dv_reg          TXBCASTFRAMES;
+       dv_reg          TXMCASTFRAMES;
+       dv_reg          TXPAUSEFRAMES;
+       dv_reg          TXDEFERRED;
+       dv_reg          TXCOLLISION;
+       dv_reg          TXSINGLECOLL;
+       dv_reg          TXMULTICOLL;
+       dv_reg          TXEXCESSIVECOLL;
+       dv_reg          TXLATECOLL;
+       dv_reg          TXUNDERRUN;
+       dv_reg          TXCARRIERSENSE;
+       dv_reg          TXOCTETS;
+       dv_reg          FRAME64;
+       dv_reg          FRAME65T127;
+       dv_reg          FRAME128T255;
+       dv_reg          FRAME256T511;
+       dv_reg          FRAME512T1023;
+       dv_reg          FRAME1024TUP;
+       dv_reg          NETOCTETS;
+       dv_reg          RXSOFOVERRUNS;
+       dv_reg          RXMOFOVERRUNS;
+       dv_reg          RXDMAOVERRUNS;
+       u_int8_t        RSVD7[624];
+       dv_reg          MACADDRLO;
+       dv_reg          MACADDRHI;
+       dv_reg          MACINDEX;
+       u_int8_t        RSVD8[244];
+       dv_reg          TX0HDP;
+       dv_reg          TX1HDP;
+       dv_reg          TX2HDP;
+       dv_reg          TX3HDP;
+       dv_reg          TX4HDP;
+       dv_reg          TX5HDP;
+       dv_reg          TX6HDP;
+       dv_reg          TX7HDP;
+       dv_reg          RX0HDP;
+       dv_reg          RX1HDP;
+       dv_reg          RX2HDP;
+       dv_reg          RX3HDP;
+       dv_reg          RX4HDP;
+       dv_reg          RX5HDP;
+       dv_reg          RX6HDP;
+       dv_reg          RX7HDP;
+       dv_reg          TX0CP;
+       dv_reg          TX1CP;
+       dv_reg          TX2CP;
+       dv_reg          TX3CP;
+       dv_reg          TX4CP;
+       dv_reg          TX5CP;
+       dv_reg          TX6CP;
+       dv_reg          TX7CP;
+       dv_reg          RX0CP;
+       dv_reg          RX1CP;
+       dv_reg          RX2CP;
+       dv_reg          RX3CP;
+       dv_reg          RX4CP;
+       dv_reg          RX5CP;
+       dv_reg          RX6CP;
+       dv_reg          RX7CP;
+} emac_regs;
+
+/* EMAC Wrapper Registers Structure */
+typedef struct  {
+#ifdef DAVINCI_EMAC_VERSION2
+       dv_reg          idver;
+       dv_reg          softrst;
+       dv_reg          emctrl;
+       dv_reg          c0rxthreshen;
+       dv_reg          c0rxen;
+       dv_reg          c0txen;
+       dv_reg          c0miscen;
+       dv_reg          c1rxthreshen;
+       dv_reg          c1rxen;
+       dv_reg          c1txen;
+       dv_reg          c1miscen;
+       dv_reg          c2rxthreshen;
+       dv_reg          c2rxen;
+       dv_reg          c2txen;
+       dv_reg          c2miscen;
+       dv_reg          c0rxthreshstat;
+       dv_reg          c0rxstat;
+       dv_reg          c0txstat;
+       dv_reg          c0miscstat;
+       dv_reg          c1rxthreshstat;
+       dv_reg          c1rxstat;
+       dv_reg          c1txstat;
+       dv_reg          c1miscstat;
+       dv_reg          c2rxthreshstat;
+       dv_reg          c2rxstat;
+       dv_reg          c2txstat;
+       dv_reg          c2miscstat;
+       dv_reg          c0rximax;
+       dv_reg          c0tximax;
+       dv_reg          c1rximax;
+       dv_reg          c1tximax;
+       dv_reg          c2rximax;
+       dv_reg          c2tximax;
+#else
+       u_int8_t        RSVD0[4100];
+       dv_reg          EWCTL;
+       dv_reg          EWINTTCNT;
+#endif
+} ewrap_regs;
+
+/* EMAC MDIO Registers Structure */
+typedef struct  {
+       dv_reg          VERSION;
+       dv_reg          CONTROL;
+       dv_reg          ALIVE;
+       dv_reg          LINK;
+       dv_reg          LINKINTRAW;
+       dv_reg          LINKINTMASKED;
+       u_int8_t        RSVD0[8];
+       dv_reg          USERINTRAW;
+       dv_reg          USERINTMASKED;
+       dv_reg          USERINTMASKSET;
+       dv_reg          USERINTMASKCLEAR;
+       u_int8_t        RSVD1[80];
+       dv_reg          USERACCESS0;
+       dv_reg          USERPHYSEL0;
+       dv_reg          USERACCESS1;
+       dv_reg          USERPHYSEL1;
+} mdio_regs;
+
+int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data);
+int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data);
+
+typedef struct {
+       char    name[64];
+       int     (*init)(int phy_addr);
+       int     (*is_phy_connected)(int phy_addr);
+       int     (*get_link_speed)(int phy_addr);
+       int     (*auto_negotiate)(int phy_addr);
+} phy_t;
+
+#endif /* _DAVINCI_EMAC_H_ */
diff --git a/drivers/net/ti/keystone_net.c b/drivers/net/ti/keystone_net.c
new file mode 100644 (file)
index 0000000..d4d909b
--- /dev/null
@@ -0,0 +1,1170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Ethernet driver for TI K2HK EVM.
+ *
+ * (C) Copyright 2012-2014
+ *     Texas Instruments Incorporated, <www.ti.com>
+ */
+#include <common.h>
+#include <command.h>
+#include <console.h>
+
+#include <dm.h>
+#include <dm/lists.h>
+
+#include <net.h>
+#include <phy.h>
+#include <errno.h>
+#include <miiphy.h>
+#include <malloc.h>
+#include <asm/ti-common/keystone_nav.h>
+#include <asm/ti-common/keystone_net.h>
+#include <asm/ti-common/keystone_serdes.h>
+#include <asm/arch/psc_defs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_DM_ETH
+unsigned int emac_open;
+static struct mii_dev *mdio_bus;
+static unsigned int sys_has_mdio = 1;
+#endif
+
+#ifdef KEYSTONE2_EMAC_GIG_ENABLE
+#define emac_gigabit_enable(x) keystone2_eth_gigabit_enable(x)
+#else
+#define emac_gigabit_enable(x) /* no gigabit to enable */
+#endif
+
+#define RX_BUFF_NUMS   24
+#define RX_BUFF_LEN    1520
+#define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN
+#define SGMII_ANEG_TIMEOUT             4000
+
+static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16);
+
+#ifndef CONFIG_DM_ETH
+struct rx_buff_desc net_rx_buffs = {
+       .buff_ptr       = rx_buffs,
+       .num_buffs      = RX_BUFF_NUMS,
+       .buff_len       = RX_BUFF_LEN,
+       .rx_flow        = 22,
+};
+#endif
+
+#ifdef CONFIG_DM_ETH
+
+enum link_type {
+       LINK_TYPE_SGMII_MAC_TO_MAC_AUTO         = 0,
+       LINK_TYPE_SGMII_MAC_TO_PHY_MODE         = 1,
+       LINK_TYPE_SGMII_MAC_TO_MAC_FORCED_MODE  = 2,
+       LINK_TYPE_SGMII_MAC_TO_FIBRE_MODE       = 3,
+       LINK_TYPE_SGMII_MAC_TO_PHY_NO_MDIO_MODE = 4,
+       LINK_TYPE_RGMII_LINK_MAC_PHY            = 5,
+       LINK_TYPE_RGMII_LINK_MAC_MAC_FORCED     = 6,
+       LINK_TYPE_RGMII_LINK_MAC_PHY_NO_MDIO    = 7,
+       LINK_TYPE_10G_MAC_TO_PHY_MODE           = 10,
+       LINK_TYPE_10G_MAC_TO_MAC_FORCED_MODE    = 11,
+};
+
+#define mac_hi(mac)     (((mac)[0] << 0) | ((mac)[1] << 8) |    \
+                        ((mac)[2] << 16) | ((mac)[3] << 24))
+#define mac_lo(mac)     (((mac)[4] << 0) | ((mac)[5] << 8))
+
+#ifdef CONFIG_KSNET_NETCP_V1_0
+
+#define EMAC_EMACSW_BASE_OFS           0x90800
+#define EMAC_EMACSW_PORT_BASE_OFS      (EMAC_EMACSW_BASE_OFS + 0x60)
+
+/* CPSW Switch slave registers */
+#define CPGMACSL_REG_SA_LO             0x10
+#define CPGMACSL_REG_SA_HI             0x14
+
+#define DEVICE_EMACSW_BASE(base, x)    ((base) + EMAC_EMACSW_PORT_BASE_OFS +  \
+                                        (x) * 0x30)
+
+#elif defined CONFIG_KSNET_NETCP_V1_5
+
+#define EMAC_EMACSW_PORT_BASE_OFS      0x222000
+
+/* CPSW Switch slave registers */
+#define CPGMACSL_REG_SA_LO             0x308
+#define CPGMACSL_REG_SA_HI             0x30c
+
+#define DEVICE_EMACSW_BASE(base, x)    ((base) + EMAC_EMACSW_PORT_BASE_OFS +  \
+                                        (x) * 0x1000)
+
+#endif
+
+
+struct ks2_eth_priv {
+       struct udevice                  *dev;
+       struct phy_device               *phydev;
+       struct mii_dev                  *mdio_bus;
+       int                             phy_addr;
+       phy_interface_t                 phy_if;
+       int                             sgmii_link_type;
+       void                            *mdio_base;
+       struct rx_buff_desc             net_rx_buffs;
+       struct pktdma_cfg               *netcp_pktdma;
+       void                            *hd;
+       int                             slave_port;
+       enum link_type                  link_type;
+       bool                            emac_open;
+       bool                            has_mdio;
+};
+#endif
+
+/* MDIO */
+
+static int keystone2_mdio_reset(struct mii_dev *bus)
+{
+       u_int32_t clkdiv;
+       struct mdio_regs *adap_mdio = bus->priv;
+
+       clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
+
+       writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE |
+              MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE,
+              &adap_mdio->control);
+
+       while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE)
+               ;
+
+       return 0;
+}
+
+/**
+ * keystone2_mdio_read - read a PHY register via MDIO interface.
+ * Blocks until operation is complete.
+ */
+static int keystone2_mdio_read(struct mii_dev *bus,
+                              int addr, int devad, int reg)
+{
+       int tmp;
+       struct mdio_regs *adap_mdio = bus->priv;
+
+       while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
+               ;
+
+       writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ |
+              ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16),
+              &adap_mdio->useraccess0);
+
+       /* Wait for command to complete */
+       while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO)
+               ;
+
+       if (tmp & MDIO_USERACCESS0_ACK)
+               return tmp & 0xffff;
+
+       return -1;
+}
+
+/**
+ * keystone2_mdio_write - write to a PHY register via MDIO interface.
+ * Blocks until operation is complete.
+ */
+static int keystone2_mdio_write(struct mii_dev *bus,
+                               int addr, int devad, int reg, u16 val)
+{
+       struct mdio_regs *adap_mdio = bus->priv;
+
+       while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
+               ;
+
+       writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE |
+              ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) |
+              (val & 0xffff), &adap_mdio->useraccess0);
+
+       /* Wait for command to complete */
+       while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
+               ;
+
+       return 0;
+}
+
+#ifndef CONFIG_DM_ETH
+static void  __attribute__((unused))
+       keystone2_eth_gigabit_enable(struct eth_device *dev)
+{
+       u_int16_t data;
+       struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+
+       if (sys_has_mdio) {
+               data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr,
+                                          MDIO_DEVAD_NONE, 0);
+               /* speed selection MSB */
+               if (!(data & (1 << 6)))
+                       return;
+       }
+
+       /*
+        * Check if link detected is giga-bit
+        * If Gigabit mode detected, enable gigbit in MAC
+        */
+       writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) +
+                    CPGMACSL_REG_CTL) |
+              EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
+              DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL);
+}
+#else
+static void  __attribute__((unused))
+       keystone2_eth_gigabit_enable(struct udevice *dev)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+       u_int16_t data;
+
+       if (priv->has_mdio) {
+               data = keystone2_mdio_read(priv->mdio_bus, priv->phy_addr,
+                                          MDIO_DEVAD_NONE, 0);
+               /* speed selection MSB */
+               if (!(data & (1 << 6)))
+                       return;
+       }
+
+       /*
+        * Check if link detected is giga-bit
+        * If Gigabit mode detected, enable gigbit in MAC
+        */
+       writel(readl(DEVICE_EMACSL_BASE(priv->slave_port - 1) +
+                    CPGMACSL_REG_CTL) |
+              EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
+              DEVICE_EMACSL_BASE(priv->slave_port - 1) + CPGMACSL_REG_CTL);
+}
+#endif
+
+#ifdef CONFIG_SOC_K2G
+int keystone_rgmii_config(struct phy_device *phy_dev)
+{
+       unsigned int i, status;
+
+       i = 0;
+       do {
+               if (i > SGMII_ANEG_TIMEOUT) {
+                       puts(" TIMEOUT !\n");
+                       phy_dev->link = 0;
+                       return 0;
+               }
+
+               if (ctrlc()) {
+                       puts("user interrupt!\n");
+                       phy_dev->link = 0;
+                       return -EINTR;
+               }
+
+               if ((i++ % 500) == 0)
+                       printf(".");
+
+               udelay(1000);   /* 1 ms */
+               status = readl(RGMII_STATUS_REG);
+       } while (!(status & RGMII_REG_STATUS_LINK));
+
+       puts(" done\n");
+
+       return 0;
+}
+#else
+int keystone_sgmii_config(struct phy_device *phy_dev, int port, int interface)
+{
+       unsigned int i, status, mask;
+       unsigned int mr_adv_ability, control;
+
+       switch (interface) {
+       case SGMII_LINK_MAC_MAC_AUTONEG:
+               mr_adv_ability  = (SGMII_REG_MR_ADV_ENABLE |
+                                  SGMII_REG_MR_ADV_LINK |
+                                  SGMII_REG_MR_ADV_FULL_DUPLEX |
+                                  SGMII_REG_MR_ADV_GIG_MODE);
+               control         = (SGMII_REG_CONTROL_MASTER |
+                                  SGMII_REG_CONTROL_AUTONEG);
+
+               break;
+       case SGMII_LINK_MAC_PHY:
+       case SGMII_LINK_MAC_PHY_FORCED:
+               mr_adv_ability  = SGMII_REG_MR_ADV_ENABLE;
+               control         = SGMII_REG_CONTROL_AUTONEG;
+
+               break;
+       case SGMII_LINK_MAC_MAC_FORCED:
+               mr_adv_ability  = (SGMII_REG_MR_ADV_ENABLE |
+                                  SGMII_REG_MR_ADV_LINK |
+                                  SGMII_REG_MR_ADV_FULL_DUPLEX |
+                                  SGMII_REG_MR_ADV_GIG_MODE);
+               control         = SGMII_REG_CONTROL_MASTER;
+
+               break;
+       case SGMII_LINK_MAC_FIBER:
+               mr_adv_ability  = 0x20;
+               control         = SGMII_REG_CONTROL_AUTONEG;
+
+               break;
+       default:
+               mr_adv_ability  = SGMII_REG_MR_ADV_ENABLE;
+               control         = SGMII_REG_CONTROL_AUTONEG;
+       }
+
+       __raw_writel(0, SGMII_CTL_REG(port));
+
+       /*
+        * Wait for the SerDes pll to lock,
+        * but don't trap if lock is never read
+        */
+       for (i = 0; i < 1000; i++)  {
+               udelay(2000);
+               status = __raw_readl(SGMII_STATUS_REG(port));
+               if ((status & SGMII_REG_STATUS_LOCK) != 0)
+                       break;
+       }
+
+       __raw_writel(mr_adv_ability, SGMII_MRADV_REG(port));
+       __raw_writel(control, SGMII_CTL_REG(port));
+
+
+       mask = SGMII_REG_STATUS_LINK;
+
+       if (control & SGMII_REG_CONTROL_AUTONEG)
+               mask |= SGMII_REG_STATUS_AUTONEG;
+
+       status = __raw_readl(SGMII_STATUS_REG(port));
+       if ((status & mask) == mask)
+               return 0;
+
+       printf("\n%s Waiting for SGMII auto negotiation to complete",
+              phy_dev->dev->name);
+       while ((status & mask) != mask) {
+               /*
+                * Timeout reached ?
+                */
+               if (i > SGMII_ANEG_TIMEOUT) {
+                       puts(" TIMEOUT !\n");
+                       phy_dev->link = 0;
+                       return 0;
+               }
+
+               if (ctrlc()) {
+                       puts("user interrupt!\n");
+                       phy_dev->link = 0;
+                       return -EINTR;
+               }
+
+               if ((i++ % 500) == 0)
+                       printf(".");
+
+               udelay(1000);   /* 1 ms */
+               status = __raw_readl(SGMII_STATUS_REG(port));
+       }
+       puts(" done\n");
+
+       return 0;
+}
+#endif
+
+int mac_sl_reset(u32 port)
+{
+       u32 i, v;
+
+       if (port >= DEVICE_N_GMACSL_PORTS)
+               return GMACSL_RET_INVALID_PORT;
+
+       /* Set the soft reset bit */
+       writel(CPGMAC_REG_RESET_VAL_RESET,
+              DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET);
+
+       /* Wait for the bit to clear */
+       for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
+               v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET);
+               if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
+                   CPGMAC_REG_RESET_VAL_RESET)
+                       return GMACSL_RET_OK;
+       }
+
+       /* Timeout on the reset */
+       return GMACSL_RET_WARN_RESET_INCOMPLETE;
+}
+
+int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg)
+{
+       u32 v, i;
+       int ret = GMACSL_RET_OK;
+
+       if (port >= DEVICE_N_GMACSL_PORTS)
+               return GMACSL_RET_INVALID_PORT;
+
+       if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) {
+               cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN;
+               ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG;
+       }
+
+       /* Must wait if the device is undergoing reset */
+       for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
+               v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET);
+               if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
+                   CPGMAC_REG_RESET_VAL_RESET)
+                       break;
+       }
+
+       if (i == DEVICE_EMACSL_RESET_POLL_COUNT)
+               return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE;
+
+       writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN);
+       writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL);
+
+#ifndef CONFIG_SOC_K2HK
+       /* Map RX packet flow priority to 0 */
+       writel(0, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RX_PRI_MAP);
+#endif
+
+       return ret;
+}
+
+int ethss_config(u32 ctl, u32 max_pkt_size)
+{
+       u32 i;
+
+       /* Max length register */
+       writel(max_pkt_size, DEVICE_CPSW_BASE + CPSW_REG_MAXLEN);
+
+       /* Control register */
+       writel(ctl, DEVICE_CPSW_BASE + CPSW_REG_CTL);
+
+       /* All statistics enabled by default */
+       writel(CPSW_REG_VAL_STAT_ENABLE_ALL,
+              DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN);
+
+       /* Reset and enable the ALE */
+       writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE |
+              CPSW_REG_VAL_ALE_CTL_BYPASS,
+              DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL);
+
+       /* All ports put into forward mode */
+       for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++)
+               writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE,
+                      DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i));
+
+       return 0;
+}
+
+int ethss_start(void)
+{
+       int i;
+       struct mac_sl_cfg cfg;
+
+       cfg.max_rx_len  = MAX_SIZE_STREAM_BUFFER;
+       cfg.ctl         = GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL;
+
+       for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) {
+               mac_sl_reset(i);
+               mac_sl_config(i, &cfg);
+       }
+
+       return 0;
+}
+
+int ethss_stop(void)
+{
+       int i;
+
+       for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++)
+               mac_sl_reset(i);
+
+       return 0;
+}
+
+struct ks2_serdes ks2_serdes_sgmii_156p25mhz = {
+       .clk = SERDES_CLOCK_156P25M,
+       .rate = SERDES_RATE_5G,
+       .rate_mode = SERDES_QUARTER_RATE,
+       .intf = SERDES_PHY_SGMII,
+       .loopback = 0,
+};
+
+#ifndef CONFIG_SOC_K2G
+static void keystone2_net_serdes_setup(void)
+{
+       ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE,
+                       &ks2_serdes_sgmii_156p25mhz,
+                       CONFIG_KSNET_SERDES_LANES_PER_SGMII);
+
+#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L)
+       ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE,
+                       &ks2_serdes_sgmii_156p25mhz,
+                       CONFIG_KSNET_SERDES_LANES_PER_SGMII);
+#endif
+
+       /* wait till setup */
+       udelay(5000);
+}
+#endif
+
+#ifndef CONFIG_DM_ETH
+
+int keystone2_eth_read_mac_addr(struct eth_device *dev)
+{
+       struct eth_priv_t *eth_priv;
+       u32 maca = 0;
+       u32 macb = 0;
+
+       eth_priv = (struct eth_priv_t *)dev->priv;
+
+       /* Read the e-fuse mac address */
+       if (eth_priv->slave_port == 1) {
+               maca = __raw_readl(MAC_ID_BASE_ADDR);
+               macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
+       }
+
+       dev->enetaddr[0] = (macb >>  8) & 0xff;
+       dev->enetaddr[1] = (macb >>  0) & 0xff;
+       dev->enetaddr[2] = (maca >> 24) & 0xff;
+       dev->enetaddr[3] = (maca >> 16) & 0xff;
+       dev->enetaddr[4] = (maca >>  8) & 0xff;
+       dev->enetaddr[5] = (maca >>  0) & 0xff;
+
+       return 0;
+}
+
+int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num)
+{
+       if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE)
+               num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE;
+
+       return ksnav_send(&netcp_pktdma, buffer,
+                         num_bytes, (slave_port_num) << 16);
+}
+
+/* Eth device open */
+static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
+{
+       struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+       struct phy_device *phy_dev = eth_priv->phy_dev;
+
+       debug("+ emac_open\n");
+
+       net_rx_buffs.rx_flow    = eth_priv->rx_flow;
+
+       sys_has_mdio =
+               (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
+
+       if (sys_has_mdio)
+               keystone2_mdio_reset(mdio_bus);
+
+#ifdef CONFIG_SOC_K2G
+       keystone_rgmii_config(phy_dev);
+#else
+       keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1,
+                             eth_priv->sgmii_link_type);
+#endif
+
+       udelay(10000);
+
+       /* On chip switch configuration */
+       ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE);
+
+       /* TODO: add error handling code */
+       if (qm_init()) {
+               printf("ERROR: qm_init()\n");
+               return -1;
+       }
+       if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) {
+               qm_close();
+               printf("ERROR: netcp_init()\n");
+               return -1;
+       }
+
+       /*
+        * Streaming switch configuration. If not present this
+        * statement is defined to void in target.h.
+        * If present this is usually defined to a series of register writes
+        */
+       hw_config_streaming_switch();
+
+       if (sys_has_mdio) {
+               keystone2_mdio_reset(mdio_bus);
+
+               phy_startup(phy_dev);
+               if (phy_dev->link == 0) {
+                       ksnav_close(&netcp_pktdma);
+                       qm_close();
+                       return -1;
+               }
+       }
+
+       emac_gigabit_enable(dev);
+
+       ethss_start();
+
+       debug("- emac_open\n");
+
+       emac_open = 1;
+
+       return 0;
+}
+
+/* Eth device close */
+void keystone2_eth_close(struct eth_device *dev)
+{
+       struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+       struct phy_device *phy_dev = eth_priv->phy_dev;
+
+       debug("+ emac_close\n");
+
+       if (!emac_open)
+               return;
+
+       ethss_stop();
+
+       ksnav_close(&netcp_pktdma);
+       qm_close();
+       phy_shutdown(phy_dev);
+
+       emac_open = 0;
+
+       debug("- emac_close\n");
+}
+
+/*
+ * This function sends a single packet on the network and returns
+ * positive number (number of bytes transmitted) or negative for error
+ */
+static int keystone2_eth_send_packet(struct eth_device *dev,
+                                       void *packet, int length)
+{
+       int ret_status = -1;
+       struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+       struct phy_device *phy_dev = eth_priv->phy_dev;
+
+       genphy_update_link(phy_dev);
+       if (phy_dev->link == 0)
+               return -1;
+
+       if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0)
+               return ret_status;
+
+       return length;
+}
+
+/*
+ * This function handles receipt of a packet from the network
+ */
+static int keystone2_eth_rcv_packet(struct eth_device *dev)
+{
+       void *hd;
+       int  pkt_size;
+       u32  *pkt;
+
+       hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size);
+       if (hd == NULL)
+               return 0;
+
+       net_process_received_packet((uchar *)pkt, pkt_size);
+
+       ksnav_release_rxhd(&netcp_pktdma, hd);
+
+       return pkt_size;
+}
+
+#ifdef CONFIG_MCAST_TFTP
+static int keystone2_eth_bcast_addr(struct eth_device *dev, u32 ip, u8 set)
+{
+       return 0;
+}
+#endif
+
+/*
+ * This function initializes the EMAC hardware.
+ */
+int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
+{
+       int res;
+       struct eth_device *dev;
+       struct phy_device *phy_dev;
+       struct mdio_regs *adap_mdio = (struct mdio_regs *)EMAC_MDIO_BASE_ADDR;
+
+       dev = malloc(sizeof(struct eth_device));
+       if (dev == NULL)
+               return -1;
+
+       memset(dev, 0, sizeof(struct eth_device));
+
+       strcpy(dev->name, eth_priv->int_name);
+       dev->priv = eth_priv;
+
+       keystone2_eth_read_mac_addr(dev);
+
+       dev->iobase             = 0;
+       dev->init               = keystone2_eth_open;
+       dev->halt               = keystone2_eth_close;
+       dev->send               = keystone2_eth_send_packet;
+       dev->recv               = keystone2_eth_rcv_packet;
+#ifdef CONFIG_MCAST_TFTP
+       dev->mcast              = keystone2_eth_bcast_addr;
+#endif
+
+       eth_register(dev);
+
+       /* Register MDIO bus if it's not registered yet */
+       if (!mdio_bus) {
+               mdio_bus        = mdio_alloc();
+               mdio_bus->read  = keystone2_mdio_read;
+               mdio_bus->write = keystone2_mdio_write;
+               mdio_bus->reset = keystone2_mdio_reset;
+               mdio_bus->priv  = (void *)EMAC_MDIO_BASE_ADDR;
+               strcpy(mdio_bus->name, "ethernet-mdio");
+
+               res = mdio_register(mdio_bus);
+               if (res)
+                       return res;
+       }
+
+#ifndef CONFIG_SOC_K2G
+       keystone2_net_serdes_setup();
+#endif
+
+       /* Create phy device and bind it with driver */
+#ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE
+       phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr,
+                             dev, eth_priv->phy_if);
+       phy_config(phy_dev);
+#else
+       phy_dev = phy_find_by_mask(mdio_bus, 1 << eth_priv->phy_addr,
+                                  eth_priv->phy_if);
+       phy_dev->dev = dev;
+#endif
+       eth_priv->phy_dev = phy_dev;
+
+       return 0;
+}
+
+#else
+
+static int ks2_eth_start(struct udevice *dev)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+
+#ifdef CONFIG_SOC_K2G
+       keystone_rgmii_config(priv->phydev);
+#else
+       keystone_sgmii_config(priv->phydev, priv->slave_port - 1,
+                             priv->sgmii_link_type);
+#endif
+
+       udelay(10000);
+
+       /* On chip switch configuration */
+       ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE);
+
+       qm_init();
+
+       if (ksnav_init(priv->netcp_pktdma, &priv->net_rx_buffs)) {
+               pr_err("ksnav_init failed\n");
+               goto err_knav_init;
+       }
+
+       /*
+        * Streaming switch configuration. If not present this
+        * statement is defined to void in target.h.
+        * If present this is usually defined to a series of register writes
+        */
+       hw_config_streaming_switch();
+
+       if (priv->has_mdio) {
+               keystone2_mdio_reset(priv->mdio_bus);
+
+               phy_startup(priv->phydev);
+               if (priv->phydev->link == 0) {
+                       pr_err("phy startup failed\n");
+                       goto err_phy_start;
+               }
+       }
+
+       emac_gigabit_enable(dev);
+
+       ethss_start();
+
+       priv->emac_open = true;
+
+       return 0;
+
+err_phy_start:
+       ksnav_close(priv->netcp_pktdma);
+err_knav_init:
+       qm_close();
+
+       return -EFAULT;
+}
+
+static int ks2_eth_send(struct udevice *dev, void *packet, int length)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+
+       genphy_update_link(priv->phydev);
+       if (priv->phydev->link == 0)
+               return -1;
+
+       if (length < EMAC_MIN_ETHERNET_PKT_SIZE)
+               length = EMAC_MIN_ETHERNET_PKT_SIZE;
+
+       return ksnav_send(priv->netcp_pktdma, (u32 *)packet,
+                         length, (priv->slave_port) << 16);
+}
+
+static int ks2_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+       int  pkt_size;
+       u32 *pkt = NULL;
+
+       priv->hd = ksnav_recv(priv->netcp_pktdma, &pkt, &pkt_size);
+       if (priv->hd == NULL)
+               return -EAGAIN;
+
+       *packetp = (uchar *)pkt;
+
+       return pkt_size;
+}
+
+static int ks2_eth_free_pkt(struct udevice *dev, uchar *packet,
+                                  int length)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+
+       ksnav_release_rxhd(priv->netcp_pktdma, priv->hd);
+
+       return 0;
+}
+
+static void ks2_eth_stop(struct udevice *dev)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+
+       if (!priv->emac_open)
+               return;
+       ethss_stop();
+
+       ksnav_close(priv->netcp_pktdma);
+       qm_close();
+       phy_shutdown(priv->phydev);
+       priv->emac_open = false;
+}
+
+int ks2_eth_read_rom_hwaddr(struct udevice *dev)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       u32 maca = 0;
+       u32 macb = 0;
+
+       /* Read the e-fuse mac address */
+       if (priv->slave_port == 1) {
+               maca = __raw_readl(MAC_ID_BASE_ADDR);
+               macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
+       }
+
+       pdata->enetaddr[0] = (macb >>  8) & 0xff;
+       pdata->enetaddr[1] = (macb >>  0) & 0xff;
+       pdata->enetaddr[2] = (maca >> 24) & 0xff;
+       pdata->enetaddr[3] = (maca >> 16) & 0xff;
+       pdata->enetaddr[4] = (maca >>  8) & 0xff;
+       pdata->enetaddr[5] = (maca >>  0) & 0xff;
+
+       return 0;
+}
+
+int ks2_eth_write_hwaddr(struct udevice *dev)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+
+       writel(mac_hi(pdata->enetaddr),
+              DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) +
+                                 CPGMACSL_REG_SA_HI);
+       writel(mac_lo(pdata->enetaddr),
+              DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) +
+                                 CPGMACSL_REG_SA_LO);
+
+       return 0;
+}
+
+static int ks2_eth_probe(struct udevice *dev)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+       struct mii_dev *mdio_bus;
+       int ret;
+
+       priv->dev = dev;
+
+       /* These clock enables has to be moved to common location */
+       if (cpu_is_k2g())
+               writel(KS2_ETHERNET_RGMII, KS2_ETHERNET_CFG);
+
+       /* By default, select PA PLL clock as PA clock source */
+#ifndef CONFIG_SOC_K2G
+       if (psc_enable_module(KS2_LPSC_PA))
+               return -EACCES;
+#endif
+       if (psc_enable_module(KS2_LPSC_CPGMAC))
+               return -EACCES;
+       if (psc_enable_module(KS2_LPSC_CRYPTO))
+               return -EACCES;
+
+       if (cpu_is_k2e() || cpu_is_k2l())
+               pll_pa_clk_sel();
+
+
+       priv->net_rx_buffs.buff_ptr = rx_buffs;
+       priv->net_rx_buffs.num_buffs = RX_BUFF_NUMS;
+       priv->net_rx_buffs.buff_len = RX_BUFF_LEN;
+
+       if (priv->slave_port == 1) {
+               /*
+                * Register MDIO bus for slave 0 only, other slave have
+                * to re-use the same
+                */
+               mdio_bus = mdio_alloc();
+               if (!mdio_bus) {
+                       pr_err("MDIO alloc failed\n");
+                       return -ENOMEM;
+               }
+               priv->mdio_bus = mdio_bus;
+               mdio_bus->read  = keystone2_mdio_read;
+               mdio_bus->write = keystone2_mdio_write;
+               mdio_bus->reset = keystone2_mdio_reset;
+               mdio_bus->priv  = priv->mdio_base;
+               sprintf(mdio_bus->name, "ethernet-mdio");
+
+               ret = mdio_register(mdio_bus);
+               if (ret) {
+                       pr_err("MDIO bus register failed\n");
+                       return ret;
+               }
+       } else {
+               /* Get the MDIO bus from slave 0 device */
+               struct ks2_eth_priv *parent_priv;
+
+               parent_priv = dev_get_priv(dev->parent);
+               priv->mdio_bus = parent_priv->mdio_bus;
+       }
+
+#ifndef CONFIG_SOC_K2G
+       keystone2_net_serdes_setup();
+#endif
+
+       priv->netcp_pktdma = &netcp_pktdma;
+
+       if (priv->has_mdio) {
+               priv->phydev = phy_connect(priv->mdio_bus, priv->phy_addr,
+                                          dev, priv->phy_if);
+               phy_config(priv->phydev);
+       }
+
+       return 0;
+}
+
+int ks2_eth_remove(struct udevice *dev)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+
+       free(priv->phydev);
+       mdio_unregister(priv->mdio_bus);
+       mdio_free(priv->mdio_bus);
+
+       return 0;
+}
+
+static const struct eth_ops ks2_eth_ops = {
+       .start                  = ks2_eth_start,
+       .send                   = ks2_eth_send,
+       .recv                   = ks2_eth_recv,
+       .free_pkt               = ks2_eth_free_pkt,
+       .stop                   = ks2_eth_stop,
+       .read_rom_hwaddr        = ks2_eth_read_rom_hwaddr,
+       .write_hwaddr           = ks2_eth_write_hwaddr,
+};
+
+static int ks2_eth_bind_slaves(struct udevice *dev, int gbe, int *gbe_0)
+{
+       const void *fdt = gd->fdt_blob;
+       struct udevice *sl_dev;
+       int interfaces;
+       int sec_slave;
+       int slave;
+       int ret;
+       char *slave_name;
+
+       interfaces = fdt_subnode_offset(fdt, gbe, "interfaces");
+       fdt_for_each_subnode(slave, fdt, interfaces) {
+               int slave_no;
+
+               slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT);
+               if (slave_no == -ENOENT)
+                       continue;
+
+               if (slave_no == 0) {
+                       /* This is the current eth device */
+                       *gbe_0 = slave;
+               } else {
+                       /* Slave devices to be registered */
+                       slave_name = malloc(20);
+                       snprintf(slave_name, 20, "netcp@slave-%d", slave_no);
+                       ret = device_bind_driver_to_node(dev, "eth_ks2_sl",
+                                       slave_name, offset_to_ofnode(slave),
+                                       &sl_dev);
+                       if (ret) {
+                               pr_err("ks2_net - not able to bind slave interfaces\n");
+                               return ret;
+                       }
+               }
+       }
+
+       sec_slave = fdt_subnode_offset(fdt, gbe, "secondary-slave-ports");
+       fdt_for_each_subnode(slave, fdt, sec_slave) {
+               int slave_no;
+
+               slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT);
+               if (slave_no == -ENOENT)
+                       continue;
+
+               /* Slave devices to be registered */
+               slave_name = malloc(20);
+               snprintf(slave_name, 20, "netcp@slave-%d", slave_no);
+               ret = device_bind_driver_to_node(dev, "eth_ks2_sl", slave_name,
+                                       offset_to_ofnode(slave), &sl_dev);
+               if (ret) {
+                       pr_err("ks2_net - not able to bind slave interfaces\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int ks2_eth_parse_slave_interface(int netcp, int slave,
+                                        struct ks2_eth_priv *priv,
+                                        struct eth_pdata *pdata)
+{
+       const void *fdt = gd->fdt_blob;
+       int mdio;
+       int phy;
+       int dma_count;
+       u32 dma_channel[8];
+
+       priv->slave_port = fdtdec_get_int(fdt, slave, "slave-port", -1);
+       priv->net_rx_buffs.rx_flow = priv->slave_port * 8;
+
+       /* U-Boot slave port number starts with 1 instead of 0 */
+       priv->slave_port += 1;
+
+       dma_count = fdtdec_get_int_array_count(fdt, netcp,
+                                              "ti,navigator-dmas",
+                                              dma_channel, 8);
+
+       if (dma_count > (2 * priv->slave_port)) {
+               int dma_idx;
+
+               dma_idx = priv->slave_port * 2 - 1;
+               priv->net_rx_buffs.rx_flow = dma_channel[dma_idx];
+       }
+
+       priv->link_type = fdtdec_get_int(fdt, slave, "link-interface", -1);
+
+       phy = fdtdec_lookup_phandle(fdt, slave, "phy-handle");
+       if (phy >= 0) {
+               priv->phy_addr = fdtdec_get_int(fdt, phy, "reg", -1);
+
+               mdio = fdt_parent_offset(fdt, phy);
+               if (mdio < 0) {
+                       pr_err("mdio dt not found\n");
+                       return -ENODEV;
+               }
+               priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg");
+       }
+
+       if (priv->link_type == LINK_TYPE_SGMII_MAC_TO_PHY_MODE) {
+               priv->phy_if = PHY_INTERFACE_MODE_SGMII;
+               pdata->phy_interface = priv->phy_if;
+               priv->sgmii_link_type = SGMII_LINK_MAC_PHY;
+               priv->has_mdio = true;
+       } else if (priv->link_type == LINK_TYPE_RGMII_LINK_MAC_PHY) {
+               priv->phy_if = PHY_INTERFACE_MODE_RGMII;
+               pdata->phy_interface = priv->phy_if;
+               priv->has_mdio = true;
+       }
+
+       return 0;
+}
+
+static int ks2_sl_eth_ofdata_to_platdata(struct udevice *dev)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       const void *fdt = gd->fdt_blob;
+       int slave = dev_of_offset(dev);
+       int interfaces;
+       int gbe;
+       int netcp_devices;
+       int netcp;
+
+       interfaces = fdt_parent_offset(fdt, slave);
+       gbe = fdt_parent_offset(fdt, interfaces);
+       netcp_devices = fdt_parent_offset(fdt, gbe);
+       netcp = fdt_parent_offset(fdt, netcp_devices);
+
+       ks2_eth_parse_slave_interface(netcp, slave, priv, pdata);
+
+       pdata->iobase = fdtdec_get_addr(fdt, netcp, "reg");
+
+       return 0;
+}
+
+static int ks2_eth_ofdata_to_platdata(struct udevice *dev)
+{
+       struct ks2_eth_priv *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       const void *fdt = gd->fdt_blob;
+       int gbe_0 = -ENODEV;
+       int netcp_devices;
+       int gbe;
+
+       netcp_devices = fdt_subnode_offset(fdt, dev_of_offset(dev),
+                                          "netcp-devices");
+       gbe = fdt_subnode_offset(fdt, netcp_devices, "gbe");
+
+       ks2_eth_bind_slaves(dev, gbe, &gbe_0);
+
+       ks2_eth_parse_slave_interface(dev_of_offset(dev), gbe_0, priv, pdata);
+
+       pdata->iobase = devfdt_get_addr(dev);
+
+       return 0;
+}
+
+static const struct udevice_id ks2_eth_ids[] = {
+       { .compatible = "ti,netcp-1.0" },
+       { }
+};
+
+U_BOOT_DRIVER(eth_ks2_slave) = {
+       .name   = "eth_ks2_sl",
+       .id     = UCLASS_ETH,
+       .ofdata_to_platdata = ks2_sl_eth_ofdata_to_platdata,
+       .probe  = ks2_eth_probe,
+       .remove = ks2_eth_remove,
+       .ops    = &ks2_eth_ops,
+       .priv_auto_alloc_size = sizeof(struct ks2_eth_priv),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+
+U_BOOT_DRIVER(eth_ks2) = {
+       .name   = "eth_ks2",
+       .id     = UCLASS_ETH,
+       .of_match = ks2_eth_ids,
+       .ofdata_to_platdata = ks2_eth_ofdata_to_platdata,
+       .probe  = ks2_eth_probe,
+       .remove = ks2_eth_remove,
+       .ops    = &ks2_eth_ops,
+       .priv_auto_alloc_size = sizeof(struct ks2_eth_priv),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif