Merge branch 'master' of git://git.denx.de/u-boot-net
authorTom Rini <trini@konsulko.com>
Thu, 28 Jan 2016 23:42:10 +0000 (18:42 -0500)
committerTom Rini <trini@konsulko.com>
Thu, 28 Jan 2016 23:42:10 +0000 (18:42 -0500)
1  2 
board/freescale/ls1021atwr/ls1021atwr.c
cmd/ethsw.c
drivers/net/designware.c
drivers/net/fsl_mdio.c
drivers/net/phy/cortina.c
drivers/net/tsec.c
include/net.h

@@@ -30,7 -30,6 +30,7 @@@
  #ifdef CONFIG_U_QE
  #include "../../../drivers/qe/qe.h"
  #endif
 +#include <fsl_validate.h>
  
  
  DECLARE_GLOBAL_DATA_PTR;
@@@ -244,9 -243,9 +244,9 @@@ int board_mmc_init(bd_t *bis
  }
  #endif
  
- #ifdef CONFIG_TSEC_ENET
  int board_eth_init(bd_t *bis)
  {
+ #ifdef CONFIG_TSEC_ENET
        struct fsl_pq_mdio_info mdio_info;
        struct tsec_info_struct tsec_info[4];
        int num = 0;
        fsl_pq_mdio_init(bis, &mdio_info);
  
        tsec_eth_init(bis, tsec_info, num);
+ #endif
  
        return pci_eth_init(bis);
  }
- #endif
  
  #if !defined(CONFIG_QSPI_BOOT) && !defined(CONFIG_SD_BOOT_QSPI)
  int config_serdes_mux(void)
@@@ -550,9 -549,6 +550,9 @@@ int board_late_init(void
  #ifdef CONFIG_SCSI_AHCI_PLAT
        ls1021a_sata_init();
  #endif
 +#ifdef CONFIG_CHAIN_OF_TRUST
 +      fsl_setenv_chain_of_trust();
 +#endif
  
        return 0;
  }
diff --combined cmd/ethsw.c
@@@ -71,7 -71,7 +71,7 @@@ static int ethsw_vlan_help_key_func(str
  
  #define ETHSW_PORT_UNTAG_HELP "ethsw [port <port_no>] untagged " \
  "{ [help] | show | all | none | pvid } " \
- " - set egress tagging mod for a port"
+ " - set egress tagging mode for a port"
  
  static int ethsw_port_untag_help_key_func(struct ethsw_command_def *parsed_cmd)
  {
@@@ -114,6 -114,17 +114,17 @@@ static int ethsw_ingr_fltr_help_key_fun
        return CMD_RET_SUCCESS;
  }
  
+ #define ETHSW_PORT_AGGR_HELP "ethsw [port <port_no>] aggr" \
+ " { [help] | show | <lag_group_no> } " \
+ "- get/set LAG group for a port"
+ static int ethsw_port_aggr_help_key_func(struct ethsw_command_def *parsed_cmd)
+ {
+       printf(ETHSW_PORT_AGGR_HELP"\n");
+       return CMD_RET_SUCCESS;
+ }
  static struct keywords_to_function {
        enum ethsw_keyword_id cmd_keyword[ETHSW_MAX_CMD_PARAMS];
        int cmd_func_offset;
                        .cmd_func_offset = offsetof(struct ethsw_command_func,
                                                    port_ingr_filt_set),
                        .keyword_function = NULL,
+               }, {
+                       .cmd_keyword = {
+                                       ethsw_id_aggr,
+                                       ethsw_id_key_end,
+                       },
+                       .cmd_func_offset = -1,
+                       .keyword_function = &ethsw_port_aggr_help_key_func,
+               }, {
+                       .cmd_keyword = {
+                                       ethsw_id_aggr,
+                                       ethsw_id_help,
+                                       ethsw_id_key_end,
+                       },
+                       .cmd_func_offset = -1,
+                       .keyword_function = &ethsw_port_aggr_help_key_func,
+               }, {
+                       .cmd_keyword = {
+                                       ethsw_id_aggr,
+                                       ethsw_id_show,
+                                       ethsw_id_key_end,
+                       },
+                       .cmd_func_offset = offsetof(struct ethsw_command_func,
+                                                   port_aggr_show),
+                       .keyword_function = NULL,
+               }, {
+                       .cmd_keyword = {
+                                       ethsw_id_aggr,
+                                       ethsw_id_aggr_no,
+                                       ethsw_id_key_end,
+                       },
+                       .cmd_func_offset = offsetof(struct ethsw_command_func,
+                                                   port_aggr_set),
+                       .keyword_function = NULL,
                },
  };
  
@@@ -576,6 -620,9 +620,9 @@@ static int keyword_match_pvid(enum eths
  static int keyword_match_mac_addr(enum ethsw_keyword_id key_id, int argc,
                                  char *const argv[], int *argc_nr,
                                  struct ethsw_command_def *parsed_cmd);
+ static int keyword_match_aggr(enum ethsw_keyword_id key_id, int argc,
+                             char *const argv[], int *argc_nr,
+                             struct ethsw_command_def *parsed_cmd);
  
  /*
   * Define properties for each keyword;
@@@ -661,6 -708,9 +708,9 @@@ struct keyword_def 
                }, {
                                .keyword_name = "filtering",
                                .match = &keyword_match_gen,
+               }, {
+                               .keyword_name = "aggr",
+                               .match = &keyword_match_aggr,
                },
  };
  
@@@ -826,6 -876,28 +876,28 @@@ static int keyword_match_mac_addr(enum 
        return 1;
  }
  
+ /* Function used to match the command's aggregation number */
+ static int keyword_match_aggr(enum ethsw_keyword_id key_id, int argc,
+                             char *const argv[], int *argc_nr,
+                             struct ethsw_command_def *parsed_cmd)
+ {
+       unsigned long val;
+       if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd))
+               return 0;
+       if (*argc_nr + 1 >= argc)
+               return 1;
+       if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) {
+               parsed_cmd->aggr_grp = val;
+               (*argc_nr)++;
+               parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_aggr_no;
+       }
+       return 1;
+ }
  /* Finds optional keywords and modifies *argc_va to skip them */
  static void cmd_keywords_opt_check(const struct ethsw_command_def *parsed_cmd,
                                   int *argc_val)
@@@ -984,6 -1056,7 +1056,7 @@@ static void command_def_init(struct eth
  
        parsed_cmd->port = ETHSW_CMD_PORT_ALL;
        parsed_cmd->vid = ETHSW_CMD_VLAN_ALL;
+       parsed_cmd->aggr_grp = ETHSW_CMD_AGGR_GRP_NONE;
        parsed_cmd->cmd_function = NULL;
  
        /* We initialize the MAC address with the Broadcast address */
@@@ -1010,7 -1083,7 +1083,7 @@@ static int do_ethsw(cmd_tbl_t *cmdtp, i
  }
  
  #define ETHSW_PORT_CONF_HELP "[port <port_no>] { enable | disable | show } " \
- "- enable/disable a port; show shows a port's configuration"
+ "- enable/disable a port; show a port's configuration"
  
  U_BOOT_CMD(ethsw, ETHSW_MAX_CMD_PARAMS, 0, do_ethsw,
           "Ethernet l2 switch commands",
           ETHSW_EGR_VLAN_TAG_HELP"\n"
           ETHSW_VLAN_FDB_HELP"\n"
           ETHSW_PORT_INGR_FLTR_HELP"\n"
+          ETHSW_PORT_AGGR_HELP"\n"
  );
diff --combined drivers/net/designware.c
@@@ -81,7 -81,7 +81,7 @@@ static int dw_mdio_init(const char *nam
  
        bus->read = dw_mdio_read;
        bus->write = dw_mdio_write;
 -      snprintf(bus->name, sizeof(bus->name), name);
 +      snprintf(bus->name, sizeof(bus->name), "%s", name);
  
        bus->priv = (void *)mac_regs_p;
  
@@@ -196,6 -196,8 +196,8 @@@ static void dw_adjust_link(struct eth_m
  
        if (phydev->speed != 1000)
                conf |= MII_PORTSELECT;
+       else
+               conf &= ~MII_PORTSELECT;
  
        if (phydev->speed == 100)
                conf |= FES_100;
@@@ -404,7 -406,7 +406,7 @@@ static int _dw_free_pkt(struct dw_eth_d
  static int dw_phy_init(struct dw_eth_dev *priv, void *dev)
  {
        struct phy_device *phydev;
-       int mask = 0xffffffff;
+       int mask = 0xffffffff, ret;
  
  #ifdef CONFIG_PHY_ADDR
        mask = 1 << CONFIG_PHY_ADDR;
        phy_connect_dev(phydev, dev);
  
        phydev->supported &= PHY_GBIT_FEATURES;
+       if (priv->max_speed) {
+               ret = phy_set_supported(phydev, priv->max_speed);
+               if (ret)
+                       return ret;
+       }
        phydev->advertising = phydev->supported;
  
        priv->phydev = phydev;
@@@ -599,6 -606,7 +606,7 @@@ static int designware_eth_probe(struct 
        priv->mac_regs_p = (struct eth_mac_regs *)iobase;
        priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
        priv->interface = pdata->phy_interface;
+       priv->max_speed = pdata->max_speed;
  
        dw_mdio_init(dev->name, priv->mac_regs_p);
        priv->bus = miiphy_get_dev_by_name(dev->name);
@@@ -633,6 -641,7 +641,7 @@@ static int designware_eth_ofdata_to_pla
  {
        struct eth_pdata *pdata = dev_get_platdata(dev);
        const char *phy_mode;
+       const fdt32_t *cell;
  
        pdata->iobase = dev_get_addr(dev);
        pdata->phy_interface = -1;
                return -EINVAL;
        }
  
+       pdata->max_speed = 0;
+       cell = fdt_getprop(gd->fdt_blob, dev->of_offset, "max-speed", NULL);
+       if (cell)
+               pdata->max_speed = fdt32_to_cpu(*cell);
        return 0;
  }
  
diff --combined drivers/net/fsl_mdio.c
@@@ -5,6 -5,7 +5,7 @@@
   *
   * SPDX-License-Identifier:   GPL-2.0+
   */
  #include <common.h>
  #include <miiphy.h>
  #include <phy.h>
@@@ -32,8 -33,7 +33,7 @@@ int tsec_local_mdio_read(struct tsec_mi
        int value;
        int timeout = 1000000;
  
-       /* Put the address of the phy, and the register
-        * number into MIIMADD */
+       /* Put the address of the phy, and the register number into MIIMADD */
        out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
  
        /* Clear the command register, and wait */
@@@ -104,7 -104,7 +104,7 @@@ int fsl_pq_mdio_init(bd_t *bis, struct 
        bus->read = tsec_phy_read;
        bus->write = tsec_phy_write;
        bus->reset = fsl_pq_mdio_reset;
 -      sprintf(bus->name, info->name);
 +      strcpy(bus->name, info->name);
  
        bus->priv = (void *)info->regs;
  
@@@ -174,8 -174,7 +174,8 @@@ void cs4340_upload_firmware(struct phy_
                printf("MMC read: dev # %u, block # %u, count %u ...\n",
                       dev, blk, cnt);
                mmc_init(mmc);
 -              (void)mmc->block_dev.block_read(dev, blk, cnt, addr);
 +              (void)mmc->block_dev.block_read(&mmc->block_dev, blk, cnt,
 +                                              addr);
                /* flush cache after read */
                flush_cache((ulong)addr, cnt * 512);
        }
@@@ -257,6 -256,12 +257,12 @@@ int cs4340_config(struct phy_device *ph
        return 0;
  }
  
+ int cs4340_probe(struct phy_device *phydev)
+ {
+       phydev->flags = PHY_FLAG_BROKEN_RESET;
+       return 0;
+ }
  int cs4340_startup(struct phy_device *phydev)
  {
        phydev->link = 1;
@@@ -276,6 -281,7 +282,7 @@@ struct phy_driver cs4340_driver = 
                 MDIO_DEVS_PHYXS | MDIO_DEVS_AN |
                 MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2),
        .config = &cs4340_config,
+       .probe  = &cs4340_probe,
        .startup = &cs4340_startup,
        .shutdown = &gen10g_shutdown,
  };
diff --combined drivers/net/tsec.c
@@@ -1,18 -1,16 +1,16 @@@
  /*
   * Freescale Three Speed Ethernet Controller driver
   *
-  * This software may be used and distributed according to the
-  * terms of the GNU Public License, Version 2, incorporated
-  * herein by reference.
-  *
   * Copyright 2004-2011, 2013 Freescale Semiconductor, Inc.
   * (C) Copyright 2003, Motorola, Inc.
   * author Andy Fleming
   *
+  * SPDX-License-Identifier:   GPL-2.0+
   */
  
  #include <config.h>
  #include <common.h>
+ #include <dm.h>
  #include <malloc.h>
  #include <net.h>
  #include <command.h>
  
  DECLARE_GLOBAL_DATA_PTR;
  
- #define TX_BUF_CNT            2
- static uint rx_idx;           /* index of the current RX buffer */
- static uint tx_idx;           /* index of the current TX buffer */
- #ifdef __GNUC__
- static struct txbd8 __iomem txbd[TX_BUF_CNT] __aligned(8);
- static struct rxbd8 __iomem rxbd[PKTBUFSRX] __aligned(8);
- #else
- #error "rtx must be 64-bit aligned"
- #endif
- static int tsec_send(struct eth_device *dev, void *packet, int length);
+ #ifndef CONFIG_DM_ETH
  /* Default initializations for TSEC controllers. */
  
  static struct tsec_info_struct tsec_info[] = {
@@@ -64,6 -48,7 +48,7 @@@
        STD_TSEC_INFO(4),       /* TSEC4 */
  #endif
  };
+ #endif /* CONFIG_DM_ETH */
  
  #define TBIANA_SETTINGS ( \
                TBIANA_ASYMMETRIC_PAUSE \
  /* Configure the TBI for SGMII operation */
  static void tsec_configure_serdes(struct tsec_private *priv)
  {
-       /* Access TBI PHY registers at given TSEC register offset as opposed
-        * to the register offset used for external PHY accesses */
+       /*
+        * Access TBI PHY registers at given TSEC register offset as opposed
+        * to the register offset used for external PHY accesses
+        */
        tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
                        0, TBI_ANA, TBIANA_SETTINGS);
        tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
  
  /* Set the appropriate hash bit for the given addr */
  
- /* The algorithm works like so:
+ /*
+  * The algorithm works like so:
   * 1) Take the Destination Address (ie the multicast address), and
   * do a CRC on it (little endian), and reverse the bits of the
   * result.
   * hash index which gaddr register to use, and the 5 other bits
   * indicate which bit (assuming an IBM numbering scheme, which
   * for PowerPC (tm) is usually the case) in the register holds
-  * the entry. */
- static int
- tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set)
+  * the entry.
+  */
+ #ifndef CONFIG_DM_ETH
+ static int tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set)
+ #else
+ static int tsec_mcast_addr(struct udevice *dev, const u8 *mcast_mac, int set)
+ #endif
  {
        struct tsec_private *priv = (struct tsec_private *)dev->priv;
        struct tsec __iomem *regs = priv->regs;
  }
  #endif /* Multicast TFTP ? */
  
- /* Initialized required registers to appropriate values, zeroing
+ /*
+  * Initialized required registers to appropriate values, zeroing
   * those we don't care about (unless zero is bad, in which case,
   * choose a more appropriate value)
   */
@@@ -181,7 -174,8 +174,8 @@@ static void init_registers(struct tsec 
  
  }
  
- /* Configure maccfg2 based on negotiated speed and duplex
+ /*
+  * Configure maccfg2 based on negotiated speed and duplex
   * reported by PHY handling code
   */
  static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
        case 10:
                maccfg2 |= MACCFG2_MII;
  
-               /* Set R100 bit in all modes although
+               /*
+                * Set R100 bit in all modes although
                 * it is only used in RGMII mode
                 */
                if (phydev->speed == 100)
                        (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
  }
  
+ /*
+  * This returns the status bits of the device. The return value
+  * is never checked, and this is what the 8260 driver did, so we
+  * do the same. Presumably, this would be zero if there were no
+  * errors
+  */
+ #ifndef CONFIG_DM_ETH
+ static int tsec_send(struct eth_device *dev, void *packet, int length)
+ #else
+ static int tsec_send(struct udevice *dev, void *packet, int length)
+ #endif
+ {
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       struct tsec __iomem *regs = priv->regs;
+       uint16_t status;
+       int result = 0;
+       int i;
+       /* Find an empty buffer descriptor */
+       for (i = 0;
+            in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_READY;
+            i++) {
+               if (i >= TOUT_LOOP) {
+                       debug("%s: tsec: tx buffers full\n", dev->name);
+                       return result;
+               }
+       }
+       out_be32(&priv->txbd[priv->tx_idx].bufptr, (u32)packet);
+       out_be16(&priv->txbd[priv->tx_idx].length, length);
+       status = in_be16(&priv->txbd[priv->tx_idx].status);
+       out_be16(&priv->txbd[priv->tx_idx].status, status |
+               (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT));
+       /* Tell the DMA to go */
+       out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
+       /* Wait for buffer to be transmitted */
+       for (i = 0;
+            in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_READY;
+            i++) {
+               if (i >= TOUT_LOOP) {
+                       debug("%s: tsec: tx error\n", dev->name);
+                       return result;
+               }
+       }
+       priv->tx_idx = (priv->tx_idx + 1) % TX_BUF_CNT;
+       result = in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_STATS;
+       return result;
+ }
+ #ifndef CONFIG_DM_ETH
+ static int tsec_recv(struct eth_device *dev)
+ {
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       struct tsec __iomem *regs = priv->regs;
+       while (!(in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY)) {
+               int length = in_be16(&priv->rxbd[priv->rx_idx].length);
+               uint16_t status = in_be16(&priv->rxbd[priv->rx_idx].status);
+               uchar *packet = net_rx_packets[priv->rx_idx];
+               /* Send the packet up if there were no errors */
+               if (!(status & RXBD_STATS))
+                       net_process_received_packet(packet, length - 4);
+               else
+                       printf("Got error %x\n", (status & RXBD_STATS));
+               out_be16(&priv->rxbd[priv->rx_idx].length, 0);
+               status = RXBD_EMPTY;
+               /* Set the wrap bit if this is the last element in the list */
+               if ((priv->rx_idx + 1) == PKTBUFSRX)
+                       status |= RXBD_WRAP;
+               out_be16(&priv->rxbd[priv->rx_idx].status, status);
+               priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
+       }
+       if (in_be32(&regs->ievent) & IEVENT_BSY) {
+               out_be32(&regs->ievent, IEVENT_BSY);
+               out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
+       }
+       return -1;
+ }
+ #else
+ static int tsec_recv(struct udevice *dev, int flags, uchar **packetp)
+ {
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       struct tsec __iomem *regs = priv->regs;
+       int ret = -1;
+       if (!(in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY)) {
+               int length = in_be16(&priv->rxbd[priv->rx_idx].length);
+               uint16_t status = in_be16(&priv->rxbd[priv->rx_idx].status);
+               uint32_t buf;
+               /* Send the packet up if there were no errors */
+               if (!(status & RXBD_STATS)) {
+                       buf = in_be32(&priv->rxbd[priv->rx_idx].bufptr);
+                       *packetp = (uchar *)buf;
+                       ret = length - 4;
+               } else {
+                       printf("Got error %x\n", (status & RXBD_STATS));
+               }
+       }
+       if (in_be32(&regs->ievent) & IEVENT_BSY) {
+               out_be32(&regs->ievent, IEVENT_BSY);
+               out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
+       }
+       return ret;
+ }
+ static int tsec_free_pkt(struct udevice *dev, uchar *packet, int length)
+ {
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       uint16_t status;
+       out_be16(&priv->rxbd[priv->rx_idx].length, 0);
+       status = RXBD_EMPTY;
+       /* Set the wrap bit if this is the last element in the list */
+       if ((priv->rx_idx + 1) == PKTBUFSRX)
+               status |= RXBD_WRAP;
+       out_be16(&priv->rxbd[priv->rx_idx].status, status);
+       priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
+       return 0;
+ }
+ #endif
+ /* Stop the interface */
+ #ifndef CONFIG_DM_ETH
+ static void tsec_halt(struct eth_device *dev)
+ #else
+ static void tsec_halt(struct udevice *dev)
+ #endif
+ {
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       struct tsec __iomem *regs = priv->regs;
+       clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+       setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+       while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
+                       != (IEVENT_GRSC | IEVENT_GTSC))
+               ;
+       clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
+       /* Shut down the PHY, as needed */
+       phy_shutdown(priv->phydev);
+ }
  #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
  /*
   * When MACCFG1[Rx_EN] is enabled during system boot as part
   * of the eTSEC port initialization sequence,
   * the eTSEC Rx logic may not be properly initialized.
   */
- void redundant_init(struct eth_device *dev)
+ void redundant_init(struct tsec_private *priv)
  {
-       struct tsec_private *priv = dev->priv;
        struct tsec __iomem *regs = priv->regs;
        uint t, count = 0;
        int fail = 1;
  
        do {
                uint16_t status;
-               tsec_send(dev, (void *)pkt, sizeof(pkt));
+               tsec_send(priv->dev, (void *)pkt, sizeof(pkt));
  
                /* Wait for buffer to be received */
-               for (t = 0; in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY; t++) {
+               for (t = 0;
+                    in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY;
+                    t++) {
                        if (t >= 10 * TOUT_LOOP) {
-                               printf("%s: tsec: rx error\n", dev->name);
+                               printf("%s: tsec: rx error\n", priv->dev->name);
                                break;
                        }
                }
  
-               if (!memcmp(pkt, (void *)net_rx_packets[rx_idx], sizeof(pkt)))
+               if (!memcmp(pkt, net_rx_packets[priv->rx_idx], sizeof(pkt)))
                        fail = 0;
  
-               out_be16(&rxbd[rx_idx].length, 0);
+               out_be16(&priv->rxbd[priv->rx_idx].length, 0);
                status = RXBD_EMPTY;
-               if ((rx_idx + 1) == PKTBUFSRX)
+               if ((priv->rx_idx + 1) == PKTBUFSRX)
                        status |= RXBD_WRAP;
-               out_be16(&rxbd[rx_idx].status, status);
-               rx_idx = (rx_idx + 1) % PKTBUFSRX;
+               out_be16(&priv->rxbd[priv->rx_idx].status, status);
+               priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
  
                if (in_be32(&regs->ievent) & IEVENT_BSY) {
                        out_be32(&regs->ievent, IEVENT_BSY);
  }
  #endif
  
- /* Set up the buffers and their descriptors, and bring up the
+ /*
+  * Set up the buffers and their descriptors, and bring up the
   * interface
   */
- static void startup_tsec(struct eth_device *dev)
+ static void startup_tsec(struct tsec_private *priv)
  {
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
        struct tsec __iomem *regs = priv->regs;
        uint16_t status;
        int i;
  
        /* reset the indices to zero */
-       rx_idx = 0;
-       tx_idx = 0;
+       priv->rx_idx = 0;
+       priv->tx_idx = 0;
  #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
        uint svr;
  #endif
  
        /* Point to the buffer descriptors */
-       out_be32(&regs->tbase, (u32)&txbd[0]);
-       out_be32(&regs->rbase, (u32)&rxbd[0]);
+       out_be32(&regs->tbase, (u32)&priv->txbd[0]);
+       out_be32(&regs->rbase, (u32)&priv->rxbd[0]);
  
        /* Initialize the Rx Buffer descriptors */
        for (i = 0; i < PKTBUFSRX; i++) {
-               out_be16(&rxbd[i].status, RXBD_EMPTY);
-               out_be16(&rxbd[i].length, 0);
-               out_be32(&rxbd[i].bufptr, (u32)net_rx_packets[i]);
+               out_be16(&priv->rxbd[i].status, RXBD_EMPTY);
+               out_be16(&priv->rxbd[i].length, 0);
+               out_be32(&priv->rxbd[i].bufptr, (u32)net_rx_packets[i]);
        }
-       status = in_be16(&rxbd[PKTBUFSRX - 1].status);
-       out_be16(&rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP);
+       status = in_be16(&priv->rxbd[PKTBUFSRX - 1].status);
+       out_be16(&priv->rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP);
  
        /* Initialize the TX Buffer Descriptors */
        for (i = 0; i < TX_BUF_CNT; i++) {
-               out_be16(&txbd[i].status, 0);
-               out_be16(&txbd[i].length, 0);
-               out_be32(&txbd[i].bufptr, 0);
+               out_be16(&priv->txbd[i].status, 0);
+               out_be16(&priv->txbd[i].length, 0);
+               out_be32(&priv->txbd[i].bufptr, 0);
        }
-       status = in_be16(&txbd[TX_BUF_CNT - 1].status);
-       out_be16(&txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP);
+       status = in_be16(&priv->txbd[TX_BUF_CNT - 1].status);
+       out_be16(&priv->txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP);
  
  #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
        svr = get_svr();
        if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
-               redundant_init(dev);
+               redundant_init(priv);
  #endif
        /* Enable Transmit and Receive */
        setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
        clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
  }
  
- /* This returns the status bits of the device.        The return value
-  * is never checked, and this is what the 8260 driver did, so we
-  * do the same.        Presumably, this would be zero if there were no
-  * errors
-  */
- static int tsec_send(struct eth_device *dev, void *packet, int length)
- {
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       struct tsec __iomem *regs = priv->regs;
-       uint16_t status;
-       int result = 0;
-       int i;
-       /* Find an empty buffer descriptor */
-       for (i = 0; in_be16(&txbd[tx_idx].status) & TXBD_READY; i++) {
-               if (i >= TOUT_LOOP) {
-                       debug("%s: tsec: tx buffers full\n", dev->name);
-                       return result;
-               }
-       }
-       out_be32(&txbd[tx_idx].bufptr, (u32)packet);
-       out_be16(&txbd[tx_idx].length, length);
-       status = in_be16(&txbd[tx_idx].status);
-       out_be16(&txbd[tx_idx].status, status |
-               (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT));
-       /* Tell the DMA to go */
-       out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
-       /* Wait for buffer to be transmitted */
-       for (i = 0; in_be16(&txbd[tx_idx].status) & TXBD_READY; i++) {
-               if (i >= TOUT_LOOP) {
-                       debug("%s: tsec: tx error\n", dev->name);
-                       return result;
-               }
-       }
-       tx_idx = (tx_idx + 1) % TX_BUF_CNT;
-       result = in_be16(&txbd[tx_idx].status) & TXBD_STATS;
-       return result;
- }
- static int tsec_recv(struct eth_device *dev)
- {
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       struct tsec __iomem *regs = priv->regs;
-       while (!(in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY)) {
-               int length = in_be16(&rxbd[rx_idx].length);
-               uint16_t status = in_be16(&rxbd[rx_idx].status);
-               /* Send the packet up if there were no errors */
-               if (!(status & RXBD_STATS))
-                       net_process_received_packet(net_rx_packets[rx_idx],
-                                                   length - 4);
-               else
-                       printf("Got error %x\n", (status & RXBD_STATS));
-               out_be16(&rxbd[rx_idx].length, 0);
-               status = RXBD_EMPTY;
-               /* Set the wrap bit if this is the last element in the list */
-               if ((rx_idx + 1) == PKTBUFSRX)
-                       status |= RXBD_WRAP;
-               out_be16(&rxbd[rx_idx].status, status);
-               rx_idx = (rx_idx + 1) % PKTBUFSRX;
-       }
-       if (in_be32(&regs->ievent) & IEVENT_BSY) {
-               out_be32(&regs->ievent, IEVENT_BSY);
-               out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
-       }
-       return -1;
- }
- /* Stop the interface */
- static void tsec_halt(struct eth_device *dev)
- {
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       struct tsec __iomem *regs = priv->regs;
-       clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
-       setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
-       while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
-                       != (IEVENT_GRSC | IEVENT_GTSC))
-               ;
-       clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
-       /* Shut down the PHY, as needed */
-       phy_shutdown(priv->phydev);
- }
- /* Initializes data structures and registers for the controller,
-  * and brings the interface up.        Returns the link status, meaning
+ /*
+  * Initializes data structures and registers for the controller,
+  * and brings the interface up. Returns the link status, meaning
   * that it returns success if the link is up, failure otherwise.
-  * This allows u-boot to find the first active controller.
+  * This allows U-Boot to find the first active controller.
   */
+ #ifndef CONFIG_DM_ETH
  static int tsec_init(struct eth_device *dev, bd_t * bd)
+ #else
+ static int tsec_init(struct udevice *dev)
+ #endif
  {
        struct tsec_private *priv = (struct tsec_private *)dev->priv;
+ #ifdef CONFIG_DM_ETH
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+ #endif
        struct tsec __iomem *regs = priv->regs;
        u32 tempval;
        int ret;
        /* Init ECNTRL */
        out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
  
-       /* Copy the station address into the address registers.
+       /*
+        * Copy the station address into the address registers.
         * For a station address of 0x12345678ABCD in transmission
         * order (BE), MACnADDR1 is set to 0xCDAB7856 and
         * MACnADDR2 is set to 0x34120000.
         */
+ #ifndef CONFIG_DM_ETH
        tempval = (dev->enetaddr[5] << 24) | (dev->enetaddr[4] << 16) |
                  (dev->enetaddr[3] << 8)  |  dev->enetaddr[2];
+ #else
+       tempval = (pdata->enetaddr[5] << 24) | (pdata->enetaddr[4] << 16) |
+                 (pdata->enetaddr[3] << 8)  |  pdata->enetaddr[2];
+ #endif
  
        out_be32(&regs->macstnaddr1, tempval);
  
+ #ifndef CONFIG_DM_ETH
        tempval = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16);
+ #else
+       tempval = (pdata->enetaddr[1] << 24) | (pdata->enetaddr[0] << 16);
+ #endif
  
        out_be32(&regs->macstnaddr2, tempval);
  
        init_registers(regs);
  
        /* Ready the device for tx/rx */
-       startup_tsec(dev);
+       startup_tsec(priv);
  
        /* Start up the PHY */
        ret = phy_startup(priv->phydev);
@@@ -551,8 -626,8 +626,8 @@@ static phy_interface_t tsec_get_interfa
                         * be set by the platform code.
                         */
                        if ((interface == PHY_INTERFACE_MODE_RGMII_ID) ||
-                                (interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
-                                (interface == PHY_INTERFACE_MODE_RGMII_RXID))
+                           (interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
+                           (interface == PHY_INTERFACE_MODE_RGMII_RXID))
                                return interface;
  
                        return PHY_INTERFACE_MODE_RGMII;
        return PHY_INTERFACE_MODE_MII;
  }
  
/* Discover which PHY is attached to the device, and configure it
+ /*
 * Discover which PHY is attached to the device, and configure it
   * properly.  If the PHY is not recognized, then return 0
   * (failure).  Otherwise, return 1
   */
- static int init_phy(struct eth_device *dev)
+ static int init_phy(struct tsec_private *priv)
  {
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
        struct phy_device *phydev;
        struct tsec __iomem *regs = priv->regs;
        u32 supported = (SUPPORTED_10baseT_Half |
                supported |= SUPPORTED_1000baseT_Full;
  
        /* Assign a Physical address to the TBI */
-       out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
+       out_be32(&regs->tbipa, priv->tbiaddr);
  
        priv->interface = tsec_get_interface(priv);
  
        if (priv->interface == PHY_INTERFACE_MODE_SGMII)
                tsec_configure_serdes(priv);
  
-       phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
+       phydev = phy_connect(priv->bus, priv->phyaddr, priv->dev,
+                            priv->interface);
        if (!phydev)
                return 0;
  
        return 1;
  }
  
- /* Initialize device structure. Returns success if PHY
+ #ifndef CONFIG_DM_ETH
+ /*
+  * Initialize device structure. Returns success if PHY
   * initialization succeeded (i.e. if it recognizes the PHY)
   */
  static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
        priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
  
        priv->phyaddr = tsec_info->phyaddr;
+       priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE;
        priv->flags = tsec_info->flags;
  
 -      sprintf(dev->name, tsec_info->devname);
 +      strcpy(dev->name, tsec_info->devname);
        priv->interface = tsec_info->interface;
        priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
+       priv->dev = dev;
        dev->iobase = 0;
        dev->priv = priv;
        dev->init = tsec_init;
        dev->mcast = tsec_mcast_addr;
  #endif
  
-       /* Tell u-boot to get the addr from the env */
+       /* Tell U-Boot to get the addr from the env */
        for (i = 0; i < 6; i++)
                dev->enetaddr[i] = 0;
  
        clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
  
        /* Try to initialize PHY here, and return */
-       return init_phy(dev);
+       return init_phy(priv);
  }
  
  /*
@@@ -690,3 -769,118 +769,118 @@@ int tsec_standard_init(bd_t *bis
  
        return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
  }
+ #else /* CONFIG_DM_ETH */
+ int tsec_probe(struct udevice *dev)
+ {
+       struct tsec_private *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct fsl_pq_mdio_info mdio_info;
+       int offset = 0;
+       int reg;
+       const char *phy_mode;
+       int ret;
+       pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+       priv->regs = (struct tsec *)pdata->iobase;
+       offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+                                      "phy-handle");
+       if (offset > 0) {
+               reg = fdtdec_get_int(gd->fdt_blob, offset, "reg", 0);
+               priv->phyaddr = reg;
+       } else {
+               debug("phy-handle does not exist under tsec %s\n", dev->name);
+               return -ENOENT;
+       }
+       offset = fdt_parent_offset(gd->fdt_blob, offset);
+       if (offset > 0) {
+               reg = fdtdec_get_int(gd->fdt_blob, offset, "reg", 0);
+               priv->phyregs_sgmii = (struct tsec_mii_mng *)(reg + 0x520);
+       } else {
+               debug("No parent node for PHY?\n");
+               return -ENOENT;
+       }
+       offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+                                      "tbi-handle");
+       if (offset > 0) {
+               reg = fdtdec_get_int(gd->fdt_blob, offset, "reg",
+                                    CONFIG_SYS_TBIPA_VALUE);
+               priv->tbiaddr = reg;
+       } else {
+               priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE;
+       }
+       phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset,
+                              "phy-connection-type", NULL);
+       if (phy_mode)
+               pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+       if (pdata->phy_interface == -1) {
+               debug("Invalid PHY interface '%s'\n", phy_mode);
+               return -EINVAL;
+       }
+       priv->interface = pdata->phy_interface;
+       /* Initialize flags */
+       priv->flags = TSEC_GIGABIT;
+       if (priv->interface == PHY_INTERFACE_MODE_SGMII)
+               priv->flags |= TSEC_SGMII;
+       mdio_info.regs = priv->phyregs_sgmii;
+       mdio_info.name = (char *)dev->name;
+       ret = fsl_pq_mdio_init(NULL, &mdio_info);
+       if (ret)
+               return ret;
+       /* Reset the MAC */
+       setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
+       udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
+       clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
+       priv->dev = dev;
+       priv->bus = miiphy_get_dev_by_name(dev->name);
+       /* Try to initialize PHY here, and return */
+       return !init_phy(priv);
+ }
+ int tsec_remove(struct udevice *dev)
+ {
+       struct tsec_private *priv = dev->priv;
+       free(priv->phydev);
+       mdio_unregister(priv->bus);
+       mdio_free(priv->bus);
+       return 0;
+ }
+ static const struct eth_ops tsec_ops = {
+       .start = tsec_init,
+       .send = tsec_send,
+       .recv = tsec_recv,
+       .free_pkt = tsec_free_pkt,
+       .stop = tsec_halt,
+ #ifdef CONFIG_MCAST_TFTP
+       .mcast = tsec_mcast_addr,
+ #endif
+ };
+ static const struct udevice_id tsec_ids[] = {
+       { .compatible = "fsl,tsec" },
+       { }
+ };
+ U_BOOT_DRIVER(eth_tsec) = {
+       .name = "tsec",
+       .id = UCLASS_ETH,
+       .of_match = tsec_ids,
+       .probe = tsec_probe,
+       .remove = tsec_remove,
+       .ops = &tsec_ops,
+       .priv_auto_alloc_size = sizeof(struct tsec_private),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .flags = DM_FLAG_ALLOC_PRIV_DMA,
+ };
+ #endif /* CONFIG_DM_ETH */
diff --combined include/net.h
@@@ -86,11 -86,13 +86,13 @@@ enum eth_state_t 
   * @iobase: The base address of the hardware registers
   * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env
   * @phy_interface: PHY interface to use - see PHY_INTERFACE_MODE_...
+  * @max_speed: Maximum speed of Ethernet connection supported by MAC
   */
  struct eth_pdata {
        phys_addr_t iobase;
        unsigned char enetaddr[6];
        int phy_interface;
+       int max_speed;
  };
  
  enum eth_recv_flags {
@@@ -181,7 -183,8 +183,7 @@@ int eth_unregister(struct eth_device *d
  
  extern struct eth_device *eth_current;
  
 -static inline __attribute__((always_inline))
 -struct eth_device *eth_get_dev(void)
 +static __always_inline struct eth_device *eth_get_dev(void)
  {
        return eth_current;
  }
@@@ -199,14 -202,14 +201,14 @@@ static inline unsigned char *eth_get_et
  /* Used only when NetConsole is enabled */
  int eth_is_active(struct eth_device *dev); /* Test device for active state */
  /* Set active state */
 -static inline __attribute__((always_inline)) int eth_init_state_only(void)
 +static __always_inline int eth_init_state_only(void)
  {
        eth_get_dev()->state = ETH_STATE_ACTIVE;
  
        return 0;
  }
  /* Set passive state */
 -static inline __attribute__((always_inline)) void eth_halt_state_only(void)
 +static __always_inline void eth_halt_state_only(void)
  {
        eth_get_dev()->state = ETH_STATE_PASSIVE;
  }
@@@ -656,7 -659,7 +658,7 @@@ int nc_input_packet(uchar *pkt, struct 
        unsigned src_port, unsigned len);
  #endif
  
 -static inline __attribute__((always_inline)) int eth_is_on_demand_init(void)
 +static __always_inline int eth_is_on_demand_init(void)
  {
  #ifdef CONFIG_NETCONSOLE
        extern enum proto_t net_loop_last_protocol;