diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/gmacb.c | 622 | ||||
-rw-r--r-- | drivers/net/gmacb.h | 266 | ||||
-rw-r--r-- | drivers/net/macb.c | 6 |
4 files changed, 893 insertions, 2 deletions
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index e4abac7c8f..b1da93f8f2 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -52,6 +52,7 @@ COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o COBJS-$(CONFIG_LAN91C96) += lan91c96.o COBJS-$(CONFIG_MACB) += macb.o +COBJS-$(CONFIG_GMACB) += gmacb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o diff --git a/drivers/net/gmacb.c b/drivers/net/gmacb.c new file mode 100644 index 0000000000..af1f552ab0 --- /dev/null +++ b/drivers/net/gmacb.c @@ -0,0 +1,622 @@ +/* + * Copyright (C) 2005-2006 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <common.h> + +/* + * The u-boot networking stack is a little weird. It seems like the + * networking core allocates receive buffers up front without any + * regard to the hardware that's supposed to actually receive those + * packets. + * + * The MACB receives packets into 128-byte receive buffers, so the + * buffers allocated by the core isn't very practical to use. We'll + * allocate our own, but we need one such buffer in case a packet + * wraps around the DMA ring so that we have to copy it. + * + * Therefore, define CONFIG_SYS_RX_ETH_BUFFER to 1 in the board-specific + * configuration header. This way, the core allocates one RX buffer + * and one TX buffer, each of which can hold a ethernet packet of + * maximum size. + * + * For some reason, the networking core unconditionally specifies a + * 32-byte packet "alignment" (which really should be called + * "padding"). MACB shouldn't need that, but we'll refrain from any + * core modifications here... + */ + +#include <net.h> +#include <netdev.h> +#include <malloc.h> +#include <miiphy.h> + +#include <linux/mii.h> +#include <asm/io.h> +#include <asm/dma-mapping.h> +#include <asm/arch/clk.h> + +#include "gmacb.h" + +#define barrier() asm volatile("" ::: "memory") + +#define CONFIG_SYS_MACB_RX_BUFFER_SIZE 4096 +#define CONFIG_SYS_MACB_RX_RING_SIZE (CONFIG_SYS_MACB_RX_BUFFER_SIZE / 128) +#define CONFIG_SYS_MACB_TX_RING_SIZE 16 +#define CONFIG_SYS_MACB_TX_TIMEOUT 1000 +#define CONFIG_SYS_MACB_AUTONEG_TIMEOUT 5000000 + +struct macb_dma_desc { + u32 addr; + u32 ctrl; +} __attribute__ ((packed, aligned(8))); + +#define RXADDR_USED 0x00000001 +#define RXADDR_WRAP 0x00000002 + +#define RXBUF_FRMLEN_MASK 0x00001fff +#define RXBUF_FRAME_START 0x00004000 +#define RXBUF_FRAME_END 0x00008000 +#define RXBUF_TYPEID_MATCH 0x00400000 +#define RXBUF_ADDR4_MATCH 0x06000000 +#define RXBUF_ADDR3_MATCH 0x04000000 +#define RXBUF_ADDR2_MATCH 0x02000000 +#define RXBUF_ADDR1_MATCH 0x00000000 +#define RXBUF_BROADCAST 0x80000000 + +#define TXBUF_FRMLEN_MASK 0x00003fff +#define TXBUF_FRAME_END 0x00008000 +#define TXBUF_NOCRC 0x00010000 +#define TXBUF_FCS_ERR 0x00700000 +#define TXBUF_COL 0x04000000 +#define TXBUF_FRAME_COR 0x08000000 +#define TXBUF_UNDERRUN 0x10000000 +#define TXBUF_MAXRETRY 0x20000000 +#define TXBUF_WRAP 0x40000000 +#define TXBUF_USED 0x80000000 + +struct macb_device { + void *regs; + + unsigned int rx_tail; + unsigned int tx_head; + unsigned int tx_tail; + + void *rx_buffer; + void *tx_buffer; + struct macb_dma_desc *rx_ring; + struct macb_dma_desc *tx_ring; + + unsigned long rx_buffer_dma; + unsigned long rx_ring_dma; + unsigned long tx_ring_dma; + + const struct device *dev; + struct eth_device netdev; + unsigned short phy_addr; +}; +#define to_macb(_nd) container_of(_nd, struct macb_device, netdev) + +static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + + netctl = macb_readl(macb, NCR); + netctl |= MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); + + frame = (MACB_BF(CLTTO, 1) + | MACB_BF(OP, 1) + | MACB_BF(PHYA, macb->phy_addr) + | MACB_BF(REGA, reg) + | MACB_BF(WTN, 2) + | MACB_BF(DATA, value)); + macb_writel(macb, MAN, frame); + + do { + netstat = macb_readl(macb, NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + netctl = macb_readl(macb, NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); +} + +static u16 macb_mdio_read(struct macb_device *macb, u8 reg) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + + netctl = macb_readl(macb, NCR); + netctl |= MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); + + frame = (MACB_BF(CLTTO, 1) + | MACB_BF(OP, 2) + | MACB_BF(PHYA, macb->phy_addr) + | MACB_BF(REGA, reg) + | MACB_BF(WTN, 2)); + macb_writel(macb, MAN, frame); + + do { + netstat = macb_readl(macb, NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + frame = macb_readl(macb, MAN); + + netctl = macb_readl(macb, NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); + + return MACB_BFEXT(DATA, frame); +} + +#if defined(CONFIG_CMD_MII) + +int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value) +{ + struct eth_device *dev = eth_get_dev_by_name(devname); + struct macb_device *macb = to_macb(dev); + + if ( macb->phy_addr != phy_adr ) + return -1; + + *value = macb_mdio_read(macb, reg); + + return 0; +} + +int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value) +{ + struct eth_device *dev = eth_get_dev_by_name(devname); + struct macb_device *macb = to_macb(dev); + + if ( macb->phy_addr != phy_adr ) + return -1; + + macb_mdio_write(macb, reg, value); + + return 0; +} +#endif + + +#if defined(CONFIG_CMD_NET) + +static int macb_send(struct eth_device *netdev, volatile void *packet, + int length) +{ + struct macb_device *macb = to_macb(netdev); + unsigned long paddr, ctrl; + unsigned int tx_head = macb->tx_head; + int i; + + paddr = dma_map_single(packet, length, DMA_TO_DEVICE); + + macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | macb_readl(macb, NCR)); + ctrl = length & TXBUF_FRMLEN_MASK; + ctrl |= TXBUF_FRAME_END; + if (tx_head == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) { + ctrl |= TXBUF_WRAP; + macb->tx_head = 0; + } else + macb->tx_head++; + + macb->tx_ring[tx_head].ctrl = ctrl; + macb->tx_ring[tx_head].addr = paddr; + barrier(); + + macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); + + /* + * I guess this is necessary because the networking core may + * re-use the transmit buffer as soon as we return... + */ + for (i = 0; i <= CONFIG_SYS_MACB_TX_TIMEOUT; i++) { + barrier(); + ctrl = macb->tx_ring[tx_head].ctrl; + if (ctrl & TXBUF_USED) + break; + udelay(1); + } + + dma_unmap_single(packet, length, paddr); + + if (i <= CONFIG_SYS_MACB_TX_TIMEOUT) { + if (ctrl & TXBUF_UNDERRUN) + printf("%s: TX underrun\n", netdev->name); + } else { + printf("%s: TX timeout\n", netdev->name); + } + + /* No one cares anyway */ + return 0; +} + +static void reclaim_rx_buffers(struct macb_device *macb, + unsigned int new_tail) +{ + unsigned int i; + + i = macb->rx_tail; + while (i > new_tail) { + macb->rx_ring[i].addr &= ~RXADDR_USED; + i++; + if (i > CONFIG_SYS_MACB_RX_RING_SIZE) + i = 0; + } + + while (i < new_tail) { + macb->rx_ring[i].addr &= ~RXADDR_USED; + i++; + } + + barrier(); + macb->rx_tail = new_tail; +} + +static int macb_recv(struct eth_device *netdev) +{ + struct macb_device *macb = to_macb(netdev); + unsigned int rx_tail = macb->rx_tail; + void *buffer; + int length; + int wrapped = 0; + u32 status; + + for (;;) { + if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED)) + return -1; + + status = macb->rx_ring[rx_tail].ctrl; + if (status & RXBUF_FRAME_START) { + if (rx_tail != macb->rx_tail) + reclaim_rx_buffers(macb, rx_tail); + wrapped = 0; + } + + if (status & RXBUF_FRAME_END) { + buffer = macb->rx_buffer + 128 * macb->rx_tail; + length = status & RXBUF_FRMLEN_MASK; + if (wrapped) { + unsigned int headlen, taillen; + + headlen = 128 * (CONFIG_SYS_MACB_RX_RING_SIZE + - macb->rx_tail); + taillen = length - headlen; + memcpy((void *)NetRxPackets[0], + buffer, headlen); + memcpy((void *)NetRxPackets[0] + headlen, + macb->rx_buffer, taillen); + buffer = (void *)NetRxPackets[0]; + } + + NetReceive(buffer, length); + if (++rx_tail >= CONFIG_SYS_MACB_RX_RING_SIZE) + rx_tail = 0; + reclaim_rx_buffers(macb, rx_tail); + } else { + if (++rx_tail >= CONFIG_SYS_MACB_RX_RING_SIZE) { + wrapped = 1; + rx_tail = 0; + } + } + barrier(); + } + + return 0; +} + +static void macb_phy_reset(struct macb_device *macb) +{ + struct eth_device *netdev = &macb->netdev; + int i; + u16 status, adv; + + adv = ADVERTISE_CSMA | ADVERTISE_ALL; + macb_mdio_write(macb, MII_ADVERTISE, adv); + printf("%s: Starting autonegotiation...\n", netdev->name); + macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE + | BMCR_ANRESTART)); + + for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) { + status = macb_mdio_read(macb, MII_BMSR); + if (status & BMSR_ANEGCOMPLETE) + break; + udelay(100); + } + + if (status & BMSR_ANEGCOMPLETE) + printf("%s: Autonegotiation complete\n", netdev->name); + else + printf("%s: Autonegotiation timed out (status=0x%04x)\n", + netdev->name, status); +} + +#ifdef CONFIG_MACB_SEARCH_PHY +static int macb_phy_find(struct macb_device *macb) +{ + int i; + u16 phy_id; + + /* Search for PHY... */ + for (i = 0; i < 32; i++) { + macb->phy_addr = i; + phy_id = macb_mdio_read(macb, MII_PHYSID1); + if (phy_id != 0xffff) { + printf("%s: PHY present at %d\n", macb->netdev.name, i); + return 1; + } + } + + /* PHY isn't up to snuff */ + printf("%s: PHY not found", macb->netdev.name); + + return 0; +} +#endif /* CONFIG_MACB_SEARCH_PHY */ + + +static int macb_phy_init(struct macb_device *macb) +{ + struct eth_device *netdev = &macb->netdev; + u32 ncfgr; + u16 phy_id, status, adv, lpa; + int media, speed, duplex; + int i; + +#ifdef CONFIG_MACB_SEARCH_PHY + /* Auto-detect phy_addr */ + if (!macb_phy_find(macb)) { + return 0; + } +#endif /* CONFIG_MACB_SEARCH_PHY */ + + /* Check if the PHY is up to snuff... */ + phy_id = macb_mdio_read(macb, MII_PHYSID1); + if (phy_id == 0xffff) { + printf("%s: No PHY present\n", netdev->name); + return 0; + } + + /* Timing configuration for KSZ9021RN PHY */ + macb_mdio_write(macb, 11, 260 | 0x8000); + macb_mdio_write(macb, 12, 0xF2F4); + macb_mdio_write(macb, 11, 261 | 0x8000); + macb_mdio_write(macb, 12, 0x2222); + + status = macb_mdio_read(macb, MII_BMSR); + if (!(status & BMSR_LSTATUS)) { + /* Try to re-negotiate if we don't have link already. */ + macb_phy_reset(macb); + for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) { + status = macb_mdio_read(macb, MII_BMSR); + if (status & BMSR_LSTATUS) + break; + udelay(100); + } + } + + if (!(status & BMSR_LSTATUS)) { + printf("%s: link down (status: 0x%04x)\n", + netdev->name, status); + return 0; + } else { + /* Judge whether work in 1000Base-T mode */ + adv = macb_mdio_read(macb, MII_STAT1000); + lpa = macb_mdio_read(macb, MII_CTRL1000); + if (adv & (1 << 11)) { + speed = 1000; + + if (lpa & (1 << 9)) { + duplex = 1; + } else { + duplex = 0; + } + + printf("%s: link up, %dMbps %s-duplex (lpa: 0x%04x)\n", + netdev->name, + speed, + duplex ? "full" : "half", + lpa); + + ncfgr = macb_readl(macb, NCFGR); + ncfgr &= ~(MACB_BIT(GBE) | MACB_BIT (SPD) | MACB_BIT(FD)); + if (speed) + ncfgr |= MACB_BIT(GBE); + if (duplex) + ncfgr |= MACB_BIT(FD); + macb_writel(macb, NCFGR, ncfgr); + } else { + /* Judge whether work in 100Base-T mode */ + adv = macb_mdio_read(macb, MII_ADVERTISE); + lpa = macb_mdio_read(macb, MII_LPA); + media = mii_nway_result(lpa & adv); + speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) + ? 1 : 0); + duplex = (media & ADVERTISE_FULL) ? 1 : 0; + + printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", + netdev->name, + speed? "100" : "10", + duplex ? "full" : "half", + lpa); + + ncfgr = macb_readl(macb, NCFGR); + ncfgr &= ~(MACB_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD)); + if (speed) + ncfgr |= MACB_BIT(SPD); + if (duplex) + ncfgr |= MACB_BIT(FD); + macb_writel(macb, NCFGR, ncfgr); + } + } + + return 1; +} + +static int macb_init(struct eth_device *netdev, bd_t *bd) +{ + struct macb_device *macb = to_macb(netdev); + unsigned long paddr; + int i; + + /* + * macb_halt should have been called at some point before now, + * so we'll assume the controller is idle. + */ + + /* initialize DMA descriptors */ + paddr = macb->rx_buffer_dma; + for (i = 0; i < CONFIG_SYS_MACB_RX_RING_SIZE; i++) { + if (i == (CONFIG_SYS_MACB_RX_RING_SIZE - 1)) + paddr |= RXADDR_WRAP; + macb->rx_ring[i].addr = paddr; + macb->rx_ring[i].ctrl = 0; + paddr += 128; + } + for (i = 0; i < CONFIG_SYS_MACB_TX_RING_SIZE; i++) { + macb->tx_ring[i].addr = 0; + if (i == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) + macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; + else + macb->tx_ring[i].ctrl = TXBUF_USED; + } + macb->rx_tail = macb->tx_head = macb->tx_tail = 0; + + macb_writel(macb, RBQB, macb->rx_ring_dma); + macb_writel(macb, TBQB, macb->tx_ring_dma); + + /* choose RMII or MII mode. This depends on the board */ +#ifdef CONFIG_RGMII +#if defined(CONFIG_AT91SAMA5) + macb_writel(macb, UR, MACB_BIT(RGMII)); +#else + macb_writel(macb, UR, 0); +#endif +#endif /* CONFIG_RGMII */ + + if (!macb_phy_init(macb)) + return -1; + + /* Enable TX and RX */ + macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); + + return 0; +} + +static void macb_halt(struct eth_device *netdev) +{ + struct macb_device *macb = to_macb(netdev); + u32 ncr, tsr; + + /* Halt the controller and wait for any ongoing transmission to end. */ + ncr = macb_readl(macb, NCR); + ncr |= MACB_BIT(THALT); + macb_writel(macb, NCR, ncr); + + do { + tsr = macb_readl(macb, TSR); + } while (tsr & MACB_BIT(TGO)); + + /* Disable TX and RX, and clear statistics */ + macb_writel(macb, NCR, MACB_BIT(CLRSTAT)); +} + +static int macb_write_hwaddr(struct eth_device *dev) +{ + struct macb_device *macb = to_macb(dev); + u32 hwaddr_bottom; + u16 hwaddr_top; + + /* set hardware address */ + hwaddr_bottom = dev->enetaddr[0] | dev->enetaddr[1] << 8 | + dev->enetaddr[2] << 16 | dev->enetaddr[3] << 24; + macb_writel(macb, SA1B, hwaddr_bottom); + hwaddr_top = dev->enetaddr[4] | dev->enetaddr[5] << 8; + macb_writel(macb, SA1T, hwaddr_top); + return 0; +} + +int gmacb_eth_initialize(int id, void *regs, unsigned int phy_addr) +{ + struct macb_device *macb; + struct eth_device *netdev; + unsigned long macb_hz; + u32 ncfgr; + + macb = malloc(sizeof(struct macb_device)); + if (!macb) { + printf("Error: Failed to allocate memory for MACB%d\n", id); + return -1; + } + memset(macb, 0, sizeof(struct macb_device)); + + netdev = &macb->netdev; + + macb->rx_buffer = dma_alloc_coherent(CONFIG_SYS_MACB_RX_BUFFER_SIZE, + &macb->rx_buffer_dma); + + macb->rx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_RX_RING_SIZE + * sizeof(struct macb_dma_desc), + &macb->rx_ring_dma); + macb->tx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_TX_RING_SIZE + * sizeof(struct macb_dma_desc), + &macb->tx_ring_dma); + + macb->regs = regs; + macb->phy_addr = phy_addr; + + sprintf(netdev->name, "gmacb%d", id); + netdev->init = macb_init; + netdev->halt = macb_halt; + netdev->send = macb_send; + netdev->recv = macb_recv; + netdev->write_hwaddr = macb_write_hwaddr; + + /* + * Do some basic initialization so that we at least can talk + * to the PHY + */ + macb_hz = get_macb_pclk_rate(id); + if (macb_hz < 20000000) + ncfgr = MACB_BF(CLK, GMACB_CLK_DIV8); + else if (macb_hz < 40000000) + ncfgr = MACB_BF(CLK, GMACB_CLK_DIV16); + else if (macb_hz < 80000000) + ncfgr = MACB_BF(CLK, GMACB_CLK_DIV32); + else if (macb_hz < 120000000) + ncfgr = MACB_BF(CLK, GMACB_CLK_DIV48); + else + ncfgr = MACB_BF(CLK, GMACB_CLK_DIV64); + + macb_writel(macb, NCFGR, ncfgr); + + /* Configuration the Datapath 64 bit */ + macb_writel(macb, NCFGR, MACB_BF(DBW, 1) | macb_readl(macb, NCFGR)); + + eth_register(netdev); + +#if defined(CONFIG_CMD_MII) + miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write); +#endif + return 0; +} + +#endif diff --git a/drivers/net/gmacb.h b/drivers/net/gmacb.h new file mode 100644 index 0000000000..cd755bccc3 --- /dev/null +++ b/drivers/net/gmacb.h @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2005-2006 Atmel Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef __DRIVERS_GMACB_H__ +#define __DRIVERS_GMACB_H__ + +/* MACB register offsets */ +#define GMACB_NCR 0x0000 +#define GMACB_NCFGR 0x0004 +#define GMACB_NSR 0x0008 +#define GMACB_UR 0x000c +#define GMACB_DCFGR 0x0010 +#define GMACB_TSR 0x0014 +#define GMACB_RBQB 0x0018 +#define GMACB_TBQB 0x001c +#define GMACB_RSR 0x0020 +#define GMACB_ISR 0x0024 +#define GMACB_IER 0x0028 +#define GMACB_IDR 0x002c +#define GMACB_IMR 0x0030 +#define GMACB_MAN 0x0034 +#define GMACB_RPQ 0x0038 +#define GMACB_TPQ 0x003c +#define GMACB_TPSF 0x0040 +#define GMACB_RPSF 0x0044 +#define GMACB_HRB 0x0080 +#define GMACB_HRT 0x0084 +#define GMACB_SA1B 0x0088 +#define GMACB_SA1T 0x008c +#define GMACB_SA2B 0x0090 +#define GMACB_SA2T 0x0094 +#define GMACB_SA3B 0x0098 +#define GMACB_SA3T 0x009c +#define GMACB_SA4B 0x00a0 +#define GMACB_SA4T 0x00a4 +#define GMACB_TIDM1 0x00a8 +#define GMACB_TIDM2 0x00ac +#define GMACB_TIDM3 0x00b0 +#define GMACB_TIDM4 0x00b4 +#define GMACB_WOL 0x00b8 +#define GMACB_IPGS 0x00bc +#define GMACB_SVLAN 0x00c0 +#define GMACB_TPFCP 0x00c4 +#define GMACB_SAMB1 0x00c8 +#define GMACB_SAMT1 0x00cc + +#define GMACB_FT 0x0108 +#define GMACB_BCFT 0x010c + + + + + /* Bitfields in NCR */ +#define GMACB_LB_OFFSET 0 +#define GMACB_LB_SIZE 1 +#define GMACB_LBL_OFFSET 1 +#define GMACB_LBL_SIZE 1 +#define GMACB_RE_OFFSET 2 +#define GMACB_RE_SIZE 1 +#define GMACB_TE_OFFSET 3 +#define GMACB_TE_SIZE 1 +#define GMACB_MPE_OFFSET 4 +#define GMACB_MPE_SIZE 1 +#define GMACB_CLRSTAT_OFFSET 5 +#define GMACB_CLRSTAT_SIZE 1 +#define GMACB_INCSTAT_OFFSET 6 +#define GMACB_INCSTAT_SIZE 1 +#define GMACB_WESTAT_OFFSET 7 +#define GMACB_WESTAT_SIZE 1 +#define GMACB_BP_OFFSET 8 +#define GMACB_BP_SIZE 1 +#define GMACB_TSTART_OFFSET 9 +#define GMACB_TSTART_SIZE 1 +#define GMACB_THALT_OFFSET 10 +#define GMACB_THALT_SIZE 1 +#define GMACB_NCR_TPF_OFFSET 11 +#define GMACB_NCR_TPF_SIZE 1 +#define GMACB_TZQ_OFFSET 12 +#define GMACB_TZQ_SIZE 1 + + /* Bitfields in NCFGR */ +#define GMACB_SPD_OFFSET 0 +#define GMACB_SPD_SIZE 1 +#define GMACB_FD_OFFSET 1 +#define GMACB_FD_SIZE 1 +#define GMACB_DNVLAN_OFFSET 2 +#define GMACB_DNVLAN_SIZE 1 +#define GMACB_JFRAME_OFFSET 3 +#define GMACB_JFRAME_SIZE 1 +#define GMACB_CAF_OFFSET 4 +#define GMACB_CAF_SIZE 1 +#define GMACB_NBC_OFFSET 5 +#define GMACB_NBC_SIZE 1 +#define GMACB_NCFGR_MTI_OFFSET 6 +#define GMACB_NCFGR_MTI_SIZE 1 +#define GMACB_UNI_OFFSET 7 +#define GMACB_UNI_SIZE 1 +#define MACB_MAXFS_OFFSET 8 +#define MACB_MAXFS_SIZE 1 +#define GMACB_GBE_OFFSET 10 +#define GMACB_GBE_SIZE 1 +#define GMACB_PIS_OFFSET 11 +#define GMACB_PIS_SIZE 1 +#define GMACB_RTY_OFFSET 12 +#define GMACB_RTY_SIZE 1 +#define GMACB_PEN_OFFSET 13 +#define GMACB_PEN_SIZE 1 +#define GMACB_RXBUFO_OFFSET 14 +#define GMACB_RXBUFO_SIZE 2 +#define GMACB_LFERD_OFFSET 16 +#define GMACB_LFERD_SIZE 1 +#define GMACB_RFCS_OFFSET 17 +#define GMACB_RFCS_SIZE 1 +#define GMACB_CLK_OFFSET 18 +#define GMACB_CLK_SIZE 3 +#define GMACB_DBW_OFFSET 21 +#define GMACB_DBW_SIZE 2 + + /* Bitfields in NSR */ +#define GMACB_NSR_LINK_OFFSET 0 +#define GMACB_NSR_LINK_SIZE 1 +#define GMACB_MDIO_OFFSET 1 +#define GMACB_MDIO_SIZE 1 +#define GMACB_IDLE_OFFSET 2 +#define GMACB_IDLE_SIZE 1 + + /* Bitfields in TSR */ +#define GMACB_UBR_OFFSET 0 +#define GMACB_UBR_SIZE 1 +#define GMACB_COL_OFFSET 1 +#define GMACB_COL_SIZE 1 +#define GMACB_TSR_RLE_OFFSET 2 +#define GMACB_TSR_RLE_SIZE 1 +#define GMACB_TGO_OFFSET 3 +#define GMACB_TGO_SIZE 1 +#define GMACB_BEX_OFFSET 4 +#define GMACB_BEX_SIZE 1 +#define GMACB_COMP_OFFSET 5 +#define GMACB_COMP_SIZE 1 +#define GMACB_UND_OFFSET 6 +#define GMACB_UND_SIZE 1 + + /* Bitfields in RSR */ +#define GMACB_BNA_OFFSET 0 +#define GMACB_BNA_SIZE 1 +#define GMACB_REC_OFFSET 1 +#define GMACB_REC_SIZE 1 +#define GMACB_OVR_OFFSET 2 +#define GMACB_OVR_SIZE 1 + + /* Bitfields in ISR/IER/IDR/IMR */ +#define GMACB_MFD_OFFSET 0 +#define GMACB_MFD_SIZE 1 +#define GMACB_RCOMP_OFFSET 1 +#define GMACB_RCOMP_SIZE 1 +#define GMACB_RXUBR_OFFSET 2 +#define GMACB_RXUBR_SIZE 1 +#define GMACB_TXUBR_OFFSET 3 +#define GMACB_TXUBR_SIZE 1 +#define GMACB_ISR_TUND_OFFSET 4 +#define GMACB_ISR_TUND_SIZE 1 +#define GMACB_ISR_RLE_OFFSET 5 +#define GMACB_ISR_RLE_SIZE 1 +#define GMACB_TXERR_OFFSET 6 +#define GMACB_TXERR_SIZE 1 +#define GMACB_TCOMP_OFFSET 7 +#define GMACB_TCOMP_SIZE 1 +#define GMACB_ISR_LINK_OFFSET 9 +#define GMACB_ISR_LINK_SIZE 1 +#define GMACB_ISR_ROVR_OFFSET 10 +#define GMACB_ISR_ROVR_SIZE 1 +#define GMACB_HRESP_OFFSET 11 +#define GMACB_HRESP_SIZE 1 +#define GMACB_PFR_OFFSET 12 +#define GMACB_PFR_SIZE 1 +#define GMACB_PTZ_OFFSET 13 +#define GMACB_PTZ_SIZE 1 + + /* Bitfields in MAN */ +#define GMACB_DATA_OFFSET 0 +#define GMACB_DATA_SIZE 16 +#define GMACB_WTN_OFFSET 16 +#define GMACB_WTN_SIZE 2 +#define GMACB_REGA_OFFSET 18 +#define GMACB_REGA_SIZE 5 +#define GMACB_PHYA_OFFSET 23 +#define GMACB_PHYA_SIZE 5 +#define GMACB_OP_OFFSET 28 +#define GMACB_OP_SIZE 2 +#define GMACB_CLTTO_OFFSET 30 +#define GMACB_CLTTO_SIZE 1 +#define GMACB_WZO_OFFSET 31 +#define GMACB_WZO_SIZE 1 + + /* Bitfields in US */ +#define GMACB_GMII_OFFSET 0 +#define GMACB_GMII_SIZE 1 + + /* Bitfields in USRIO (AT91) */ +#define GMACB_RGMII_OFFSET 0 +#define GMACB_RGMII_SIZE 1 + + /* Bitfields in WOL */ +#define GMACB_IP_OFFSET 0 +#define GMACB_IP_SIZE 16 +#define GMACB_MAG_OFFSET 16 +#define GMACB_MAG_SIZE 1 +#define GMACB_ARP_OFFSET 17 +#define GMACB_ARP_SIZE 1 +#define GMACB_SA1_OFFSET 18 +#define GMACB_SA1_SIZE 1 +#define GMACB_WOL_MTI_OFFSET 19 +#define GMACB_WOL_MTI_SIZE 1 + + /* Constants for CLK */ +#define GMACB_CLK_DIV8 0 +#define GMACB_CLK_DIV16 1 +#define GMACB_CLK_DIV32 2 +#define GMACB_CLK_DIV48 3 +#define GMACB_CLK_DIV64 4 + +/* Constants for MAN register */ +#define GMACB_MAN_SOF 1 +#define GMACB_MAN_WRITE 1 +#define GMACB_MAN_READ 2 +#define GMACB_MAN_CODE 2 + +/* Bit manipulation macros */ +#define MACB_BIT(name) \ + (1 << GMACB_##name##_OFFSET) +#define MACB_BF(name,value) \ + (((value) & ((1 << GMACB_##name##_SIZE) - 1)) \ + << GMACB_##name##_OFFSET) +#define MACB_BFEXT(name,value)\ + (((value) >> GMACB_##name##_OFFSET) \ + & ((1 << GMACB_##name##_SIZE) - 1)) +#define MACB_BFINS(name,value,old) \ + (((old) & ~(((1 << GMACB_##name##_SIZE) - 1) \ + << GMACB_##name##_OFFSET)) \ + | MACB_BF(name,value)) + +/* Register access macros */ +#define macb_readl(port,reg) \ + readl((port)->regs + GMACB_##reg) +#define macb_writel(port,reg,value) \ + writel((value), (port)->regs + GMACB_##reg) + +#endif /* __DRIVERS_MACB_H__ */ diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 0e1ced71c5..f05a566521 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -471,7 +471,8 @@ static int macb_init(struct eth_device *netdev, bd_t *bd) #if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \ defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \ - defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5) + defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5) || \ + defined(CONFIG_AT91SAMA5) macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN)); #else macb_writel(macb, USRIO, 0); @@ -480,7 +481,8 @@ static int macb_init(struct eth_device *netdev, bd_t *bd) #if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \ defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \ - defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5) + defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5) || \ + defined(CONFIG_AT91SAMA5) macb_writel(macb, USRIO, MACB_BIT(CLKEN)); #else macb_writel(macb, USRIO, MACB_BIT(MII)); |