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