[U-Boot] [PATCH RFC 7/7] NET: AR934x: Ethernet drivers for SoC AR934x
Nikolaos Pasaloukos
Nikolaos.Pasaloukos at imgtec.com
Fri Nov 29 10:48:08 CET 2013
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.Pasaloukos at imgtec.com>
Cc: Joe Hershberger <joe.hershberger at 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
More information about the U-Boot
mailing list