Add Ethernet support for AR934x SoC. Since it uses Atheros generic phy
support, only one Ethernet port is being set up.

Signed-off-by: Nikolaos Pasaloukos <nikolaos.pasalou...@imgtec.com>
Cc: Joe Hershberger <joe.hershber...@gmail.com>
---
 drivers/net/Makefile |   1 +
 drivers/net/ar934x.c | 572 +++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/ar934x.h | 202 ++++++++++++++++++
 include/netdev.h     |   1 +
 4 files changed, 776 insertions(+)
 create mode 100644 drivers/net/ar934x.c
 create mode 100644 drivers/net/ar934x.h

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 7f9ce90..3e8887b 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -7,6 +7,7 @@
 
 obj-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o
 obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
+obj-$(CONFIG_AR934X_ETH) += ar934x.o
 obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
 obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
 obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
diff --git a/drivers/net/ar934x.c b/drivers/net/ar934x.c
new file mode 100644
index 0000000..ce7fd56
--- /dev/null
+++ b/drivers/net/ar934x.c
@@ -0,0 +1,572 @@
+/*
+ *  Copyright (C) 2013 Imagination Technologies
+ *
+ *  Derived from works by OpenWRT
+ *
+ *  SPDX-License-Identifier:   GPL-2.0
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <pci.h>
+#include <phy.h>
+#include <miiphy.h>
+#include <asm/ar7240_addrspace.h>
+#include "ar934x.h"
+
+static struct ar934x_mac ar934x_macs[CONFIG_AR934x_NMACS];
+
+static u32 ioaddr;
+
+const struct {
+       const char *name;
+       u16 version;
+       u32 mask;       /* should clear the bits supported by this chip */
+} ath_chip_info[] = {
+       {"AR7240", 0x00c0, 0x00003300,},
+       {"AR7241", 0x0100, 0x00c03300,},
+       {"AR7242", 0x1100, 0x00c03300,},
+       {"AR9330", 0x0110, 0x00003300,},
+       {"AR9331", 0x1110, 0x00003300,},
+       {"AR9341", 0x0120, 0x00c03300,},
+       {"AR9342", 0x1120, 0x00c03300,},
+       {"AR9344", 0x2120, 0x00c03300,},
+};
+
+const struct pci_device_id supported[] = {
+       {PCI_VENDOR_ID_ATHEROS, 0xa02a},
+       {0, 0}
+};
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+uint16_t ar9344_mdio_read(char *devname, uint32_t phy_addr, uint8_t reg)
+{
+       uint16_t addr  = (phy_addr << AR934x_ADDR_SHIFT) | reg, val;
+       int rddata;
+       uint16_t ii = 0xFFFF;
+       ioaddr = ar_name2mac(devname);
+
+       /*
+        * Check for previous transactions are complete. Added to avoid
+        * race condition while running at higher frequencies.
+        */
+       do {
+               udelay(5);
+               rddata = ATHRS_REG_R32(AR934x_MII_MGMT_IND) & 0x1;
+       } while (rddata && --ii);
+
+       if (ii == 0)
+               printf("ERROR:%s:%d transaction failed\n", __func__, __LINE__);
+
+       ATHRS_REG_W32(AR934x_MII_MGMT_CMD, 0x0);
+       ATHRS_REG_W32(AR934x_MII_MGMT_ADDRESS, addr);
+       ATHRS_REG_W32(AR934x_MII_MGMT_CMD, AR934x_MGMT_CMD_READ);
+
+       do {
+               udelay(5);
+               rddata = ATHRS_REG_R32(AR934x_MII_MGMT_IND) & 0x1;
+       } while (rddata && --ii);
+
+       if (ii == 0)
+               printf("Error!!! mdio_read polling has no correct status!\n");
+
+       val = ATHRS_REG_R32(AR934x_MII_MGMT_STATUS);
+       ATHRS_REG_W32(AR934x_MII_MGMT_CMD, 0x0);
+
+       return val;
+}
+
+void ar9344_mdio_write(char *devname, uint32_t phy_addr, uint8_t reg,
+                      uint16_t data)
+{
+       uint16_t addr  = (phy_addr << AR934x_ADDR_SHIFT) | reg;
+       int rddata;
+       uint16_t ii = 0xFFFF;
+       ioaddr = ar_name2mac(devname);
+
+       /*
+        * Check for previous transactions are complete. Added to avoid
+        * race condition while running at higher frequencies.
+        */
+       do {
+               udelay(5);
+               rddata = ATHRS_REG_R32(AR934x_MII_MGMT_IND) & 0x1;
+       } while (rddata && --ii);
+
+       if (ii == 0)
+               printf("ERROR:%s:%d transaction failed\n", __func__, __LINE__);
+
+       ATHRS_REG_W32(AR934x_MII_MGMT_ADDRESS, addr);
+       ATHRS_REG_W32(AR934x_MII_MGMT_CTRL, data);
+
+       do {
+               rddata = ATHRS_REG_R32(AR934x_MII_MGMT_IND) & 0x1;
+       } while (rddata && --ii);
+
+       if (ii == 0)
+               printf("Error!!! mdio_write polling has no correct status!\n");
+}
+#endif         /* defined(CONFIG_MII) || defined(CONFIG_CMD_MII) */
+
+#if defined(CONFIG_PHYLIB)
+int ar9344_miiphy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
+                      int reg_addr)
+{
+       uint16_t ret;
+       uint32_t addr;
+
+       addr = (dev_addr == 0xffffffff) ? 0x00000001 : dev_addr;
+
+       ret = ar9344_mdio_read(bus->name, addr, reg_addr);
+
+       return ret;
+}
+
+int ar9344_miiphy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
+                      int reg_addr, uint16_t data)
+{
+       uint32_t addr;
+
+       addr = (dev_addr == 0xffffffff) ? 0x00000001 : dev_addr;
+
+       ar9344_mdio_write(bus->name, addr, reg_addr, data);
+
+       return 0;
+}
+#endif         /* defined(CONFIG_PHYLIB) */
+
+static void ar934x_get_ethaddr(struct eth_device *dev)
+{
+       if (!eth_getenv_enetaddr("ethaddr", dev->enetaddr)) {
+               /* Use random address if the above address is invalid */
+               if (!is_valid_ether_addr(dev->enetaddr)) {
+#ifdef CONFIG_RANDOM_MACADDR
+                       eth_random_enetaddr(dev->enetaddr);
+                       debug("Using random MAC address\n");
+#else
+                       printf("WARNING: No valid MAC address!");
+#endif
+               }
+       }
+       printf("%s MAC is: %pM\n", dev->name, dev->enetaddr);
+}
+
+static int ar934x_send(struct eth_device *dev, void *packet, int length)
+{
+       int i;
+
+       struct ar934x_mac *mac = (struct ar934x_mac *)dev->priv;
+       struct ar934x_desc *f = mac->fifo_tx[mac->next_tx];
+       ioaddr = mac->mac_base;
+
+       f->pkt_size = length;
+       f->res1 = 0;
+       f->pkt_start_addr = virt_to_phys(packet);
+
+       ar7240_tx_give_to_dma(f);
+       flush_cache((u32) packet, length);
+       ATHRS_REG_W32(AR934x_DMA_TX_DESC, virt_to_phys(f));
+       ATHRS_REG_W32(AR934x_DMA_TX_CTRL, AR934x_TXE);
+
+       for (i = 0; i < MAX_WAIT; i++) {
+               udelay(10);
+               if (!ar7240_tx_owned_by_dma(f))
+                       break;
+       }
+       if (i == MAX_WAIT)
+               printf("Tx Timed out\n");
+
+       f->pkt_start_addr = 0;
+       f->pkt_size = 0;
+
+       if (++mac->next_tx >= NO_OF_TX_FIFOS)
+               mac->next_tx = 0;
+
+       return 0;
+}
+
+static int ar934x_recv(struct eth_device *dev)
+{
+       int length;
+       struct ar934x_desc *f;
+       struct ar934x_mac *mac;
+
+       mac = (struct ar934x_mac *)dev->priv;
+       ioaddr = mac->mac_base;
+
+       for (;;) {
+               f = mac->fifo_rx[mac->next_rx];
+               if (ar7240_rx_owned_by_dma(f))
+                       break;
+
+               length = f->pkt_size;
+
+               NetReceive(NetRxPackets[mac->next_rx], length-4);
+               flush_cache((u32)NetRxPackets[mac->next_rx], PKTSIZE_ALIGN);
+
+               ar7240_rx_give_to_dma(f);
+
+               if (++mac->next_rx >= NO_OF_RX_FIFOS)
+                       mac->next_rx = 0;
+       }
+
+       if (!(ATHRS_REG_R32(AR934x_DMA_RX_CTRL))) {
+               ATHRS_REG_W32(AR934x_DMA_RX_DESC, virt_to_phys(f));
+               ATHRS_REG_W32(AR934x_DMA_RX_CTRL, 1);
+       }
+
+       return 0;
+}
+
+static int ar934x_alloc_fifo(int ndesc, struct ar934x_desc **fifo)
+{
+       int i;
+       u32 size;
+       uchar *p = NULL;
+
+       size = sizeof(struct ar934x_desc) * ndesc;
+       size += CONFIG_SYS_CACHELINE_SIZE - 1;
+
+       p = malloc(size);
+       if (p == NULL) {
+               printf("Cant allocate fifos\n");
+               return -1;
+       }
+
+       p = (uchar *)(((u32) p + CONFIG_SYS_CACHELINE_SIZE - 1) &
+                    ~(CONFIG_SYS_CACHELINE_SIZE - 1));
+       p = (uchar *)UNCACHED_SDRAM(p);
+
+       for (i = 0; i < ndesc; i++)
+               fifo[i] = (struct ar934x_desc *)p + i;
+
+       return 0;
+}
+
+static int ar934x_setup_fifos(struct ar934x_mac *mac)
+{
+       int i;
+
+       if (ar934x_alloc_fifo(NO_OF_TX_FIFOS, mac->fifo_tx))
+               return 1;
+
+       for (i = 0; i < NO_OF_TX_FIFOS; i++) {
+               mac->fifo_tx[i]->next_desc = (i == NO_OF_TX_FIFOS - 1) ?
+                                            virt_to_phys(mac->fifo_tx[0]) :
+                                            virt_to_phys(mac->fifo_tx[i + 1]);
+               ar7240_tx_own(mac->fifo_tx[i]);
+       }
+
+       if (ar934x_alloc_fifo(NO_OF_RX_FIFOS, mac->fifo_rx))
+               return 1;
+
+       for (i = 0; i < NO_OF_RX_FIFOS; i++) {
+               mac->fifo_rx[i]->next_desc = (i == NO_OF_RX_FIFOS - 1) ?
+                                            virt_to_phys(mac->fifo_rx[0]) :
+                                            virt_to_phys(mac->fifo_rx[i + 1]);
+       }
+
+       return 1;
+}
+
+static void ar934x_set_rx_mode(struct eth_device *dev)
+{
+       u32 mgmt_cfg_val;
+       struct ar934x_mac *mac = (struct ar934x_mac *)dev->priv;
+       ioaddr = mac->mac_base;
+
+       if ((ar_reg_rd(&ar7240_rst2->bootstrap) & WASP_REF_CLK_25) == 0)
+               ar_reg_wr(&ar7240_pll->switch_clk_spare, 0x271);
+       else
+               ar_reg_wr(&ar7240_pll->switch_clk_spare, 0x570);
+
+       if (is_ar934x(&ar7240_rst2) && dev->index == 0) {
+               debug("WASP  ----> S17 PHY *\n");
+               mgmt_cfg_val = 4;
+               if (dev->index == 0)
+                       ar_reg_wr(AR7240_ETH_CFG, AR7240_ETH_CFG_RGMII_GE0);
+
+               udelay(1000);
+
+               ATHRS_REG_W32(AR934x_MAC_MII_MGMT_CFG,
+                             mgmt_cfg_val | (1 << 31));
+               ATHRS_REG_W32(AR934x_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+       }
+}
+
+static void ar934x_hw_start(struct eth_device *dev)
+{
+       struct ar934x_mac *mac = (struct ar934x_mac *)dev->priv;
+       ioaddr = mac->mac_base;
+
+       if (dev->index) {
+               ATHRS_REG_W32(AR934x_MAC_CFG1, (AR934x_MAC_CFG1_RX_EN |
+                                               AR934x_MAC_CFG1_TX_EN));
+               ar_mac_reg_set(AR934x_MAC_CFG2, (AR934x_MAC_CFG2_PAD_CRC_EN |
+                                                AR934x_MAC_CFG2_LEN_CHECK |
+                                                AR934x_MAC_CFG2_IF_1000));
+       } else {
+               ATHRS_REG_W32(AR934x_MAC_CFG1, (AR934x_MAC_CFG1_RX_EN |
+                                               AR934x_MAC_CFG1_TX_EN));
+               ar_mac_reg_set(AR934x_MAC_CFG2, (AR934x_MAC_CFG2_PAD_CRC_EN |
+                                                AR934x_MAC_CFG2_LEN_CHECK |
+                                                AR934x_MAC_CFG2_IF_10_100));
+       }
+       ATHRS_REG_W32(AR934x_MAC_FIFO_CFG_0, 0x1f00);
+
+       ar934x_set_rx_mode(dev);
+
+       ATHRS_REG_W32(AR934x_MAC_FIFO_CFG_1, 0x10ffff);
+       ATHRS_REG_W32(AR934x_MAC_FIFO_CFG_2, 0xAAA0555);
+
+       ar_mac_reg_set(AR934x_MAC_FIFO_CFG_4, 0x3ffff);
+
+       /*
+        * Setting Drop CRC Errors, Pause Frames,Length Error frames
+        * and Multi/Broad cast frames.
+        */
+       ATHRS_REG_W32(AR934x_MAC_FIFO_CFG_5, 0x7eccf);
+
+       ATHRS_REG_W32(AR934x_MAC_FIFO_CFG_3, 0x1f00140);
+
+       debug(" : cfg1 %#x cfg2 %#x\n", ATHRS_REG_R32(AR934x_MAC_CFG1),
+             ATHRS_REG_R32(AR934x_MAC_CFG2));
+}
+
+static int ar9344_init_board(struct eth_device *dev)
+{
+       int i;
+       u32 reg_val;
+
+       struct ar934x_mac *mac = (struct ar934x_mac *)dev->priv;
+       ioaddr = mac->mac_base;
+
+       reg_val = ATHRS_REG_R32(AR934x_MAC_CFG1);
+       ATHRS_REG_W32(AR934x_MAC_CFG1, reg_val | AR934x_MAC_CFG1_SOFT_RST |
+                     AR934x_MAC_CFG1_RX_RST | AR934x_MAC_CFG1_TX_RST);
+
+       reg_val = ar_reg_rd(&ar7240_rst2->rev_id) & AR9344_REV_ID_MASK;
+       for (i = ARRAY_SIZE(ath_chip_info) - 1; i >= 0; i--) {
+               if (reg_val == ath_chip_info[i].version) {
+                       debug("wasp reset mask: %08x\n", ath_chip_info[i].mask);
+                       ar_reg_rd_set(&ar7240_rst1->reset,
+                                     ath_chip_info[i].mask);
+                       udelay(100 * 1000);
+                       ar_reg_rd_clr(&ar7240_rst1->reset,
+                                     ath_chip_info[i].mask);
+                       return 0;
+               }
+       }
+
+       /* if unknown chip, assume array element #0, original AR7240 */
+       printf("PCI device %s: unknown chip version, assuming AR7240\n",
+              dev->name);
+       printf("PCI device: TxConfig = 0x%08X\n",
+              ar_reg_rd(&ar7240_rst2->rev_id));
+
+       return 0;
+}
+
+/*
+ * HALT - Turn off ethernet interface
+ */
+static void ar934x_halt(struct eth_device *dev)
+{
+       struct ar934x_mac *mac = (struct ar934x_mac *)dev->priv;
+       ioaddr = mac->mac_base;
+
+       /* Stop the chip's Tx and Rx DMA processes. */
+       ATHRS_REG_W32(AR934x_DMA_RX_CTRL, 0x00);
+
+       while (ATHRS_REG_R32(AR934x_DMA_RX_CTRL))
+               udelay(10);
+}
+
+static int ar934x_check_link(struct ar934x_mac *mac)
+{
+       struct phy_device *phydev;
+
+       ioaddr = mac->mac_base;
+       phydev = mac->phydev;
+       phy_startup(phydev);
+
+       if (!phydev->link) {
+               printf("%s link down\n", mac->dev->name);
+               return 0;
+       }
+
+       switch (phydev->speed) {
+       case _1000BASET:
+               ar7240_set_mac_if(1);
+               ar_mac_reg_set(AR934x_MAC_FIFO_CFG_5, (1 << 19));
+               if (is_ar7242(&ar7240_rst2) && (mac->dev->index == 0))
+                       ar_reg_wr(&ar7240_pll->eth_xmii_config, 0x1c000000);
+               if (is_ar934x(&ar7240_rst2) && (mac->dev->index == 0))
+                       ar_reg_wr(&ar7240_pll->eth_xmii_config, 0x06000000);
+               break;
+
+       case _100BASET:
+               ar7240_set_mac_if(0);
+               ar_mac_reg_set(AR934x_MAC_IFCTL, AR934x_MAC_IFCTL_SPEED);
+               ar_mac_reg_clr(AR934x_MAC_FIFO_CFG_5, (1 << 19));
+               if ((is_ar7242(&ar7240_rst2) || is_ar934x(&ar7240_rst2)) &&
+                   (mac->dev->index == 0))
+                       ar_reg_wr(&ar7240_pll->eth_xmii_config, 0x0101);
+               break;
+
+       case _10BASET:
+               ar7240_set_mac_if(0);
+               ar_mac_reg_clr(AR934x_MAC_IFCTL, AR934x_MAC_IFCTL_SPEED);
+               ar_mac_reg_clr(AR934x_MAC_FIFO_CFG_5, (1 << 19));
+
+               if ((is_ar7242(&ar7240_rst2) || is_ar934x(&ar7240_rst2)) &&
+                   (mac->dev->index == 0))
+                       ar_reg_wr(&ar7240_pll->eth_xmii_config, 0x1616);
+               break;
+
+       default:
+               printf("Invalid speed detected\n");
+               return 0;
+       }
+
+       if (phydev->link && (phydev->duplex == mac->duplex) &&
+           (phydev->speed == mac->speed))
+               return 1;
+
+       mac->duplex = phydev->duplex;
+       mac->speed = phydev->speed;
+
+       debug("dup %d speed %d\n", phydev->duplex, phydev->speed);
+
+       ar7240_set_mac_duplex(phydev->duplex);
+
+       return 1;
+}
+
+/*
+ * For every command we re-setup the ring and start with clean h/w rx state
+ */
+static int ar934x_init_ring(struct eth_device *dev, bd_t *bis)
+{
+       int i;
+       struct ar934x_desc *fr;
+       struct ar934x_mac *mac = (struct ar934x_mac *)dev->priv;
+       ioaddr = mac->mac_base;
+
+
+       if (!ar934x_check_link(mac))
+               return 0;
+
+       mac->next_rx = 0;
+       for (i = 0; i < NO_OF_RX_FIFOS; i++) {
+               fr = mac->fifo_rx[i];
+               fr->pkt_start_addr = virt_to_phys(NetRxPackets[i]);
+               flush_cache((u32) NetRxPackets[i], PKTSIZE_ALIGN);
+               ar7240_rx_give_to_dma(fr);
+       }
+
+       ATHRS_REG_W32(AR934x_DMA_RX_DESC, virt_to_phys(mac->fifo_rx[0]));
+       ATHRS_REG_W32(AR934x_DMA_RX_CTRL, AR934x_RXE);  /* rx start */
+       udelay(1000 * 1000);
+
+       return 1;
+}
+
+/*
+ *INIT - Finish setting up the ethernet interface
+ */
+static int ar934x_init(struct eth_device *dev, bd_t *bis)
+{
+       struct ar934x_mac *mac = (struct ar934x_mac *)dev->priv;
+       struct mii_dev *bus;
+       struct phy_device *phydev;
+       u32 mac_h, mac_l, supported;
+       int ret;
+       ioaddr = mac->mac_base;
+
+       ret = ar9344_init_board(dev);
+       if (ret)
+               return ret;
+
+       ar934x_hw_start(dev);
+
+       ar934x_setup_fifos(mac);
+       udelay(100 * 1000);
+
+       mac_l = (dev->enetaddr[4] << 8) | (dev->enetaddr[5]);
+       mac_h = (dev->enetaddr[0] << 24) |
+               (dev->enetaddr[1] << 16) |
+               (dev->enetaddr[2] << 8) |
+               (dev->enetaddr[3] << 0);
+
+       ATHRS_REG_W32(AR934x_GE_MAC_ADDR1, mac_l);
+       ATHRS_REG_W32(AR934x_GE_MAC_ADDR2, mac_h);
+
+       bus = mdio_alloc();
+       if (!bus) {
+               printf("Can not allocate memory of bus\n");
+               return 0;
+       }
+
+       bus->read = ar9344_miiphy_read;
+       bus->write = ar9344_miiphy_write;
+       sprintf(bus->name, "%s", dev->name);
+
+       phydev = phy_connect(bus, 0, dev, PHY_INTERFACE_MODE_RGMII);
+       if (!phydev) {
+               printf("phy_connect failed\n");
+               return 0;
+       }
+       mac->phydev = phydev;
+       supported = (PHY_BASIC_FEATURES | SUPPORTED_1000baseT_Full |
+                    SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+       phydev->supported &= supported;
+       phy_config(phydev);
+
+       printf("%s up\n", dev->name);
+
+       return 1;
+}
+
+int ar934x_initialize(bd_t *bis)
+{
+       int card_num;
+       struct eth_device *dev;
+
+       for (card_num = 0; card_num < ARRAY_SIZE(supported) - 1; card_num++) {
+               printf("Atheros AR934x --> eth%d\n", card_num);
+
+               dev = (struct eth_device *)malloc(sizeof(*dev));
+               if (!dev) {
+                       printf("Can not allocate memory of ar9344\n");
+                       break;
+               }
+
+               memset(dev, 0, sizeof(*dev));
+               sprintf(dev->name, "eth%d", card_num);
+
+               ar934x_macs[card_num].mac_base = card_num ? AR7240_GE1_BASE :
+                                                            AR7240_GE0_BASE;
+               ar934x_macs[card_num].dev = dev;
+
+               dev->priv = (void *)&ar934x_macs[card_num];
+               dev->iobase = 0;
+               dev->init = ar934x_init_ring;
+               dev->halt = ar934x_halt;
+               dev->send = ar934x_send;
+               dev->recv = ar934x_recv;
+               dev->index = card_num;
+
+               ar934x_get_ethaddr(dev);
+
+               eth_register(dev);
+
+               ar934x_init(dev, bis);
+       }
+       return card_num;
+}
diff --git a/drivers/net/ar934x.h b/drivers/net/ar934x.h
new file mode 100644
index 0000000..66781a0
--- /dev/null
+++ b/drivers/net/ar934x.h
@@ -0,0 +1,202 @@
+/*
+ *  Copyright (C) 2013 Imagination Technologies
+ *
+ *  Derived from works by OpenWRT
+ *
+ *  SPDX-License-Identifier:   GPL-2.0
+ */
+
+#ifndef _AR934x_H
+#define _AR934x_H
+
+#include <linux/types.h>
+
+/*
+ *  h/w descriptor
+ */
+#define CONFIG_AR934x_NMACS    1
+
+#define NO_OF_TX_FIFOS  8
+#define NO_OF_RX_FIFOS  8
+
+struct ar934x_desc {
+       uint32_t pkt_start_addr;
+       uint32_t is_empty:1;
+       uint32_t res1:10;
+       uint32_t ftpp_override:5;
+       uint32_t res2:4;
+       uint32_t pkt_size:12;
+       uint32_t next_desc;
+};
+
+struct ar934x_mac {
+       struct ar934x_desc *fifo_tx[NO_OF_TX_FIFOS];
+       struct ar934x_desc *fifo_rx[NO_OF_RX_FIFOS];
+       struct eth_device *dev;
+       struct phy_device *phydev;
+       u32 next_tx;
+       u32 next_rx;
+       u32 link;
+       u32 duplex;
+       u32 speed;
+       u32 mac_base;
+};
+
+#define MAX_WAIT        1000
+
+/*
+ *  Config/Mac Register definitions
+ */
+#define AR934x_MAC_CFG1             0x00
+#define AR934x_MAC_CFG2             0x04
+#define AR934x_MAC_IFCTL            0x38
+
+/*
+ *  fifo control registers
+ */
+#define AR934x_MAC_FIFO_CFG_0      0x48
+#define AR934x_MAC_FIFO_CFG_1      0x4c
+#define AR934x_MAC_FIFO_CFG_2      0x50
+#define AR934x_MAC_FIFO_CFG_3      0x54
+#define AR934x_MAC_FIFO_CFG_4      0x58
+
+#define AR934x_MAC_FIFO_CFG_5      0x5c
+#define AR934x_BYTE_PER_CLK_EN     (1 << 19)
+
+#define AR934x_MAC_FIFO_RAM_0      0x60
+#define AR934x_MAC_FIFO_RAM_1      0x64
+#define AR934x_MAC_FIFO_RAM_2      0x68
+#define AR934x_MAC_FIFO_RAM_3      0x6c
+#define AR934x_MAC_FIFO_RAM_4      0x70
+#define AR934x_MAC_FIFO_RAM_5      0x74
+#define AR934x_MAC_FIFO_RAM_6      0x78
+#define AR934x_MAC_FIFO_RAM_7      0x7c
+
+/*
+ *  fields
+ */
+#define AR934x_MAC_CFG1_SOFT_RST       (1 << 31)
+#define AR934x_MAC_CFG1_RX_RST         (1 << 19)
+#define AR934x_MAC_CFG1_TX_RST         (1 << 18)
+#define AR934x_MAC_CFG1_LOOPBACK       (1 << 8)
+#define AR934x_MAC_CFG1_RX_EN          (1 << 2)
+#define AR934x_MAC_CFG1_TX_EN          (1 << 0)
+
+#define AR934x_MAC_CFG2_FDX            (1 << 0)
+#define AR934x_MAC_CFG2_PAD_CRC_EN     (1 << 2)
+#define AR934x_MAC_CFG2_LEN_CHECK      (1 << 4)
+#define AR934x_MAC_CFG2_HUGE_FRAME_EN  (1 << 5)
+#define AR934x_MAC_CFG2_IF_1000                (1 << 9)
+#define AR934x_MAC_CFG2_IF_10_100      (1 << 8)
+
+#define AR934x_MAC_IFCTL_SPEED         (1 << 16)
+
+/* 0 - 25MHz   1 - 40 MHz */
+#define WASP_REF_CLK_25                        (1 << 4)
+
+/*
+ *  DMA (tx/rx) register defines
+ */
+#define AR934x_DMA_TX_CTRL              0x180
+#define AR934x_DMA_TX_DESC              0x184
+#define AR934x_DMA_TX_STATUS            0x188
+#define AR934x_DMA_RX_CTRL              0x18c
+#define AR934x_DMA_RX_DESC              0x190
+#define AR934x_DMA_RX_STATUS            0x194
+#define AR934x_DMA_INTR_MASK            0x198
+#define AR934x_DMA_INTR                 0x19c
+
+/*
+ *  tx/rx ctrl and status bits
+ */
+#define AR934x_TXE                      (1 << 0)
+#define AR934x_TX_STATUS_PKTCNT_SHIFT   16
+#define AR934x_TX_STATUS_PKT_SENT       0x1
+#define AR934x_TX_STATUS_URN            0x2
+#define AR934x_TX_STATUS_BUS_ERROR      0x8
+
+#define AR934x_RXE                      (1 << 0)
+
+#define AR934x_RX_STATUS_PKTCNT_MASK    0xff0000
+#define AR934x_RX_STATUS_PKT_RCVD       (1 << 0)
+#define AR934x_RX_STATUS_OVF            (1 << 2)
+#define AR934x_RX_STATUS_BUS_ERROR      (1 << 3)
+
+/*
+ *  MII registers
+ */
+#define AR934x_MAC_MII_MGMT_CFG         0x20
+#define AR934x_MGMT_CFG_CLK_DIV_20      0x07
+
+#define AR934x_MII_MGMT_CMD             0x24
+#define AR934x_MGMT_CMD_READ            0x1
+
+#define AR934x_MII_MGMT_ADDRESS         0x28
+#define AR934x_ADDR_SHIFT               8
+
+#define AR934x_MII_MGMT_CTRL            0x2c
+#define AR934x_MII_MGMT_STATUS          0x30
+
+#define AR934x_MII_MGMT_IND             0x34
+#define AR934x_MGMT_IND_BUSY            (1 << 0)
+#define AR934x_MGMT_IND_INVALID         (1 << 2)
+
+#define AR934x_GE_MAC_ADDR1             0x40
+#define AR934x_GE_MAC_ADDR2             0x44
+
+/*
+ *  Ownership of descriptors between DMA and cpu
+ */
+#define ar7240_rx_owned_by_dma(_ds)     ((_ds)->is_empty == 1)
+#define ar7240_rx_give_to_dma(_ds)      ((_ds)->is_empty = 1)
+#define ar7240_tx_owned_by_dma(_ds)     ((_ds)->is_empty == 0)
+#define ar7240_tx_give_to_dma(_ds)      ((_ds)->is_empty = 0)
+#define ar7240_tx_own(_ds)              ((_ds)->is_empty = 1)
+
+/*
+ *  Primitives
+ */
+
+#define ar_name2mac(name)              strcmp(name, "eth0") ? \
+                                               KSEG1ADDR(AR7240_GE1_BASE) : \
+                                               KSEG1ADDR(AR7240_GE0_BASE)
+
+#define ar_reg_rd(_addr)               readl(KSEG1ADDR((_addr)))
+#define ar_reg_wr(_addr, _val)         writel((_val), KSEG1ADDR((_addr)))
+
+#define ATHRS_REG_W32(reg, val32)      ar_reg_wr(ioaddr + (reg), (val32))
+#define ATHRS_REG_R32(reg)             readl(KSEG1ADDR(ioaddr + (reg)))
+
+#define ar_reg_rd_set(_reg, _mask)                                            \
+       ar_reg_wr((_reg), (ar_reg_rd((_reg)) | (_mask)))
+
+#define ar_reg_rd_clr(_reg, _mask)                                            \
+       ar_reg_wr((_reg), (ar_reg_rd((_reg)) & ~(_mask)))
+
+#define ar_mac_reg_set(_x, _y)         ar_reg_rd_set(((_x) + ioaddr), (_y))
+#define ar_mac_reg_clr(_x, _y)         ar_reg_rd_clr(((_x) + ioaddr), (_y))
+
+/*
+ *  Link settings
+ */
+
+#define ar7240_set_mac_duplex(_fdx)    do {                                   \
+       if ((_fdx))                                                            \
+               ar_mac_reg_set(AR934x_MAC_CFG2, AR934x_MAC_CFG2_FDX);          \
+       else                                                                   \
+               ar_mac_reg_clr(AR934x_MAC_CFG2, AR934x_MAC_CFG2_FDX);          \
+} while (0)
+
+#define ar7240_set_mac_if(_is_xgmii)    do {                                  \
+       ar_mac_reg_clr(AR934x_MAC_CFG2, AR934x_MAC_CFG2_IF_1000 |              \
+                                       AR934x_MAC_CFG2_IF_10_100);\
+       if ((_is_xgmii)) {                                                     \
+               ar_mac_reg_set(AR934x_MAC_CFG2, AR934x_MAC_CFG2_IF_1000);      \
+               ar_mac_reg_set(AR934x_MAC_FIFO_CFG_5, AR934x_BYTE_PER_CLK_EN); \
+       } else {                                                               \
+               ar_mac_reg_set(AR934x_MAC_CFG2, AR934x_MAC_CFG2_IF_10_100);    \
+               ar_mac_reg_clr(AR934x_MAC_FIFO_CFG_5, AR934x_BYTE_PER_CLK_EN); \
+       }                                                                      \
+} while (0)
+
+#endif
diff --git a/include/netdev.h b/include/netdev.h
index 47fa80d..b235c9f 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -28,6 +28,7 @@ int cpu_eth_init(bd_t *bis);
 int altera_tse_initialize(u8 dev_num, int mac_base,
                          int sgdma_rx_base, int sgdma_tx_base,
                          u32 sgdma_desc_base, u32 sgdma_desc_size);
+int ar934x_initialize(bd_t *bis);
 int at91emac_register(bd_t *bis, unsigned long iobase);
 int au1x00_enet_initialize(bd_t*);
 int ax88180_initialize(bd_t *bis);
-- 
1.8.3.2


_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to