summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/atmel_usart.c48
-rw-r--r--drivers/atmel_usart.h8
-rw-r--r--drivers/fsl_i2c.c27
-rw-r--r--drivers/macb.c575
-rw-r--r--drivers/macb.h269
-rw-r--r--drivers/qe/qe.h2
-rw-r--r--drivers/qe/uec.c27
-rw-r--r--drivers/tsec.c84
-rw-r--r--drivers/tsec.h5
10 files changed, 999 insertions, 48 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 60ce3b4..df9fbf2 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -32,7 +32,7 @@ COBJS = 3c589.o 5701rls.o ali512x.o atmel_usart.o \
cs8900.o ct69000.o dataflash.o dc2114x.o dm9000x.o \
e1000.o eepro100.o \
i8042.o inca-ip_sw.o keyboard.o \
- lan91c96.o \
+ lan91c96.o macb.o \
natsemi.o ne2000.o netarm_eth.o netconsole.o \
ns16550.o ns8382x.o ns87308.o ns7520_eth.o omap1510_i2c.o \
omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o tsi108_pci.o\
diff --git a/drivers/atmel_usart.c b/drivers/atmel_usart.c
index 41c3768..f35b997 100644
--- a/drivers/atmel_usart.c
+++ b/drivers/atmel_usart.c
@@ -19,7 +19,22 @@
#ifdef CONFIG_ATMEL_USART
#include <asm/io.h>
-#include <asm/arch/platform.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/memory-map.h>
+
+#if defined(CONFIG_USART0)
+# define USART_ID 0
+# define USART_BASE USART0_BASE
+#elif defined(CONFIG_USART1)
+# define USART_ID 1
+# define USART_BASE USART1_BASE
+#elif defined(CONFIG_USART2)
+# define USART_ID 2
+# define USART_BASE USART2_BASE
+#elif defined(CONFIG_USART3)
+# define USART_ID 3
+# define USART_BASE USART3_BASE
+#endif
#include "atmel_usart.h"
@@ -35,26 +50,23 @@ void serial_setbrg(void)
* Baud Rate = --------------
* 16 * CD
*/
- usart_hz = pm_get_clock_freq(gd->console_uart->resource[0].u.clock.id);
+ usart_hz = get_usart_clk_rate(USART_ID);
divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate;
- usart3_writel(gd->console_uart, BRGR, USART3_BF(CD, divisor));
+ usart3_writel(BRGR, USART3_BF(CD, divisor));
}
int serial_init(void)
{
- usart3_writel(gd->console_uart, CR,
- USART3_BIT(RSTRX) | USART3_BIT(RSTTX));
+ usart3_writel(CR, USART3_BIT(RSTRX) | USART3_BIT(RSTTX));
serial_setbrg();
- usart3_writel(gd->console_uart, CR,
- USART3_BIT(RXEN) | USART3_BIT(TXEN));
- usart3_writel(gd->console_uart, MR,
- USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
- | USART3_BF(USCLKS, USART3_USCLKS_MCK)
- | USART3_BF(CHRL, USART3_CHRL_8)
- | USART3_BF(PAR, USART3_PAR_NONE)
- | USART3_BF(NBSTOP, USART3_NBSTOP_1));
+ usart3_writel(CR, USART3_BIT(RXEN) | USART3_BIT(TXEN));
+ usart3_writel(MR, (USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
+ | USART3_BF(USCLKS, USART3_USCLKS_MCK)
+ | USART3_BF(CHRL, USART3_CHRL_8)
+ | USART3_BF(PAR, USART3_PAR_NONE)
+ | USART3_BF(NBSTOP, USART3_NBSTOP_1)));
return 0;
}
@@ -64,8 +76,8 @@ void serial_putc(char c)
if (c == '\n')
serial_putc('\r');
- while (!(usart3_readl(gd->console_uart, CSR) & USART3_BIT(TXRDY))) ;
- usart3_writel(gd->console_uart, THR, c);
+ while (!(usart3_readl(CSR) & USART3_BIT(TXRDY))) ;
+ usart3_writel(THR, c);
}
void serial_puts(const char *s)
@@ -76,13 +88,13 @@ void serial_puts(const char *s)
int serial_getc(void)
{
- while (!(usart3_readl(gd->console_uart, CSR) & USART3_BIT(RXRDY))) ;
- return usart3_readl(gd->console_uart, RHR);
+ while (!(usart3_readl(CSR) & USART3_BIT(RXRDY))) ;
+ return usart3_readl(RHR);
}
int serial_tstc(void)
{
- return (usart3_readl(gd->console_uart, CSR) & USART3_BIT(RXRDY)) != 0;
+ return (usart3_readl(CSR) & USART3_BIT(RXRDY)) != 0;
}
#endif /* CONFIG_ATMEL_USART */
diff --git a/drivers/atmel_usart.h b/drivers/atmel_usart.h
index fad90a8..af3773a 100644
--- a/drivers/atmel_usart.h
+++ b/drivers/atmel_usart.h
@@ -306,9 +306,9 @@
| USART3_BF(name,value))
/* Register access macros */
-#define usart3_readl(port,reg) \
- readl((port)->regs + USART3_##reg)
-#define usart3_writel(port,reg,value) \
- writel((value), (port)->regs + USART3_##reg)
+#define usart3_readl(reg) \
+ readl((void *)USART_BASE + USART3_##reg)
+#define usart3_writel(reg,value) \
+ writel((value), (void *)USART_BASE + USART3_##reg)
#endif /* __DRIVERS_ATMEL_USART_H__ */
diff --git a/drivers/fsl_i2c.c b/drivers/fsl_i2c.c
index c929096..ebae5af 100644
--- a/drivers/fsl_i2c.c
+++ b/drivers/fsl_i2c.c
@@ -58,6 +58,7 @@ i2c_init(int speed, int slaveadd)
dev = (struct fsl_i2c *) (CFG_IMMR + CFG_I2C_OFFSET);
writeb(0, &dev->cr); /* stop I2C controller */
+ udelay(5); /* let it shutdown in peace */
writeb(0x3F, &dev->fdr); /* set bus speed */
writeb(0x3F, &dev->dfsrr); /* set default filter */
writeb(slaveadd << 1, &dev->adr); /* write slave address */
@@ -191,15 +192,17 @@ __i2c_read(u8 *data, int length)
int
i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
{
- int i = 0;
+ int i = -1; /* signal error */
u8 *a = (u8*)&addr;
if (i2c_wait4bus() >= 0
&& i2c_write_addr(dev, I2C_WRITE_BIT, 0) != 0
- && __i2c_write(&a[4 - alen], alen) == alen
- && i2c_write_addr(dev, I2C_READ_BIT, 1) != 0) {
+ && __i2c_write(&a[4 - alen], alen) == alen)
+ i = 0; /* No error so far */
+
+ if (length
+ && i2c_write_addr(dev, I2C_READ_BIT, 1) != 0)
i = __i2c_read(data, length);
- }
writeb(I2C_CR_MEN, &i2c_dev[i2c_bus_num]->cr);
@@ -212,7 +215,7 @@ i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
int
i2c_write(u8 dev, uint addr, int alen, u8 *data, int length)
{
- int i = 0;
+ int i = -1; /* signal error */
u8 *a = (u8*)&addr;
if (i2c_wait4bus() >= 0
@@ -232,16 +235,14 @@ i2c_write(u8 dev, uint addr, int alen, u8 *data, int length)
int
i2c_probe(uchar chip)
{
- int tmp;
-
- /*
- * Try to read the first location of the chip. The underlying
- * driver doesn't appear to support sending just the chip address
- * and looking for an <ACK> back.
+ /* For unknow reason the controller will ACK when
+ * probing for a slave with the same address, so skip
+ * it.
*/
- udelay(10000);
+ if (chip == (readb(&i2c_dev[i2c_bus_num]->adr) >> 1))
+ return -1;
- return i2c_read(chip, 0, 1, (uchar *)&tmp, 1);
+ return i2c_read(chip, 0, 0, NULL, 0);
}
uchar
diff --git a/drivers/macb.c b/drivers/macb.c
new file mode 100644
index 0000000..186ab19
--- /dev/null
+++ b/drivers/macb.c
@@ -0,0 +1,575 @@
+/*
+ * 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>
+
+#if defined(CONFIG_MACB) && (CONFIG_COMMANDS & (CFG_CMD_NET | CFG_CMD_MII))
+
+/*
+ * 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 CFG_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 <malloc.h>
+
+#include <linux/mii.h>
+#include <asm/io.h>
+#include <asm/dma-mapping.h>
+#include <asm/arch/clk.h>
+
+#include "macb.h"
+
+#define CFG_MACB_RX_BUFFER_SIZE 4096
+#define CFG_MACB_RX_RING_SIZE (CFG_MACB_RX_BUFFER_SIZE / 128)
+#define CFG_MACB_TX_RING_SIZE 16
+#define CFG_MACB_TX_TIMEOUT 1000
+#define CFG_MACB_AUTONEG_TIMEOUT 5000000
+
+struct macb_dma_desc {
+ u32 addr;
+ u32 ctrl;
+};
+
+#define RXADDR_USED 0x00000001
+#define RXADDR_WRAP 0x00000002
+
+#define RXBUF_FRMLEN_MASK 0x00000fff
+#define RXBUF_FRAME_START 0x00004000
+#define RXBUF_FRAME_END 0x00008000
+#define RXBUF_TYPEID_MATCH 0x00400000
+#define RXBUF_ADDR4_MATCH 0x00800000
+#define RXBUF_ADDR3_MATCH 0x01000000
+#define RXBUF_ADDR2_MATCH 0x02000000
+#define RXBUF_ADDR1_MATCH 0x04000000
+#define RXBUF_BROADCAST 0x80000000
+
+#define TXBUF_FRMLEN_MASK 0x000007ff
+#define TXBUF_FRAME_END 0x00008000
+#define TXBUF_NOCRC 0x00010000
+#define TXBUF_EXHAUSTED 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(SOF, 1)
+ | MACB_BF(RW, 1)
+ | MACB_BF(PHYA, macb->phy_addr)
+ | MACB_BF(REGA, reg)
+ | MACB_BF(CODE, 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(SOF, 1)
+ | MACB_BF(RW, 2)
+ | MACB_BF(PHYA, macb->phy_addr)
+ | MACB_BF(REGA, reg)
+ | MACB_BF(CODE, 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 (CONFIG_COMMANDS & CFG_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);
+
+ ctrl = length & TXBUF_FRMLEN_MASK;
+ ctrl |= TXBUF_FRAME_END;
+ if (tx_head == (CFG_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;
+ 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...
+ */
+ i = 0;
+ while (!(macb->tx_ring[tx_head].ctrl & TXBUF_USED)) {
+ if (i > CFG_MACB_TX_TIMEOUT) {
+ printf("%s: TX timeout\n", netdev->name);
+ break;
+ }
+ udelay(1);
+ i++;
+ }
+
+ dma_unmap_single(packet, length, paddr);
+
+ if (i <= CFG_MACB_TX_TIMEOUT) {
+ ctrl = macb->tx_ring[tx_head].ctrl;
+ if (ctrl & TXBUF_UNDERRUN)
+ printf("%s: TX underrun\n", netdev->name);
+ if (ctrl & TXBUF_EXHAUSTED)
+ printf("%s: TX buffers exhausted in mid frame\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 > CFG_MACB_RX_RING_SIZE)
+ i = 0;
+ }
+
+ while (i < new_tail) {
+ macb->rx_ring[i].addr &= ~RXADDR_USED;
+ i++;
+ }
+
+ 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 * (CFG_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 >= CFG_MACB_RX_RING_SIZE)
+ rx_tail = 0;
+ reclaim_rx_buffers(macb, rx_tail);
+ } else {
+ if (++rx_tail >= CFG_MACB_RX_RING_SIZE) {
+ wrapped = 1;
+ rx_tail = 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+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;
+
+ /* 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;
+ }
+
+ 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));
+
+#if 0
+ for (i = 0; i < 9; i++)
+ printf("mii%d: 0x%04x\n", i, macb_mdio_read(macb, i));
+#endif
+
+ for (i = 0; i < CFG_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);
+
+ if (!(status & BMSR_LSTATUS)) {
+ for (i = 0; i < CFG_MACB_AUTONEG_TIMEOUT / 100; i++) {
+ udelay(100);
+ status = macb_mdio_read(macb, MII_BMSR);
+ if (status & BMSR_LSTATUS)
+ break;
+ }
+ }
+
+ if (!(status & BMSR_LSTATUS)) {
+ printf("%s: link down (status: 0x%04x)\n",
+ netdev->name, status);
+ return 0;
+ } else {
+ 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(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;
+ u32 hwaddr_bottom;
+ u16 hwaddr_top;
+ 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 < CFG_MACB_RX_RING_SIZE; i++) {
+ if (i == (CFG_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 < CFG_MACB_TX_RING_SIZE; i++) {
+ macb->tx_ring[i].addr = 0;
+ if (i == (CFG_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, RBQP, macb->rx_ring_dma);
+ macb_writel(macb, TBQP, macb->tx_ring_dma);
+
+ /* set hardware address */
+ hwaddr_bottom = cpu_to_le32(*((u32 *)netdev->enetaddr));
+ macb_writel(macb, SA1B, hwaddr_bottom);
+ hwaddr_top = cpu_to_le16(*((u16 *)(netdev->enetaddr + 4)));
+ macb_writel(macb, SA1T, hwaddr_top);
+
+ /* choose RMII or MII mode. This depends on the board */
+#ifdef CONFIG_RMII
+ macb_writel(macb, USRIO, 0);
+#else
+ macb_writel(macb, USRIO, MACB_BIT(MII));
+#endif
+
+ if (!macb_phy_init(macb))
+ return 0;
+
+ /* Enable TX and RX */
+ macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE));
+
+ return 1;
+}
+
+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));
+}
+
+int macb_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(CFG_MACB_RX_BUFFER_SIZE,
+ &macb->rx_buffer_dma);
+ macb->rx_ring = dma_alloc_coherent(CFG_MACB_RX_RING_SIZE
+ * sizeof(struct macb_dma_desc),
+ &macb->rx_ring_dma);
+ macb->tx_ring = dma_alloc_coherent(CFG_MACB_TX_RING_SIZE
+ * sizeof(struct macb_dma_desc),
+ &macb->tx_ring_dma);
+
+ macb->regs = regs;
+ macb->phy_addr = phy_addr;
+
+ sprintf(netdev->name, "macb%d", id);
+ netdev->init = macb_init;
+ netdev->halt = macb_halt;
+ netdev->send = macb_send;
+ netdev->recv = macb_recv;
+
+ /*
+ * 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, MACB_CLK_DIV8);
+ else if (macb_hz < 40000000)
+ ncfgr = MACB_BF(CLK, MACB_CLK_DIV16);
+ else if (macb_hz < 80000000)
+ ncfgr = MACB_BF(CLK, MACB_CLK_DIV32);
+ else
+ ncfgr = MACB_BF(CLK, MACB_CLK_DIV64);
+
+ macb_writel(macb, NCFGR, ncfgr);
+
+ eth_register(netdev);
+
+ return 0;
+}
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_NET) */
+
+#if (CONFIG_COMMANDS & CFG_CMD_MII)
+
+int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
+{
+ unsigned long netctl;
+ unsigned long netstat;
+ unsigned long frame;
+ int iflag;
+
+ iflag = disable_interrupts();
+ netctl = macb_readl(&macb, EMACB_NCR);
+ netctl |= MACB_BIT(MPE);
+ macb_writel(&macb, EMACB_NCR, netctl);
+ if (iflag)
+ enable_interrupts();
+
+ frame = (MACB_BF(SOF, 1)
+ | MACB_BF(RW, 2)
+ | MACB_BF(PHYA, addr)
+ | MACB_BF(REGA, reg)
+ | MACB_BF(CODE, 2));
+ macb_writel(&macb, EMACB_MAN, frame);
+
+ do {
+ netstat = macb_readl(&macb, EMACB_NSR);
+ } while (!(netstat & MACB_BIT(IDLE)));
+
+ frame = macb_readl(&macb, EMACB_MAN);
+ *value = MACB_BFEXT(DATA, frame);
+
+ iflag = disable_interrupts();
+ netctl = macb_readl(&macb, EMACB_NCR);
+ netctl &= ~MACB_BIT(MPE);
+ macb_writel(&macb, EMACB_NCR, netctl);
+ if (iflag)
+ enable_interrupts();
+
+ return 0;
+}
+
+int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
+{
+ unsigned long netctl;
+ unsigned long netstat;
+ unsigned long frame;
+ int iflag;
+
+ iflag = disable_interrupts();
+ netctl = macb_readl(&macb, EMACB_NCR);
+ netctl |= MACB_BIT(MPE);
+ macb_writel(&macb, EMACB_NCR, netctl);
+ if (iflag)
+ enable_interrupts();
+
+ frame = (MACB_BF(SOF, 1)
+ | MACB_BF(RW, 1)
+ | MACB_BF(PHYA, addr)
+ | MACB_BF(REGA, reg)
+ | MACB_BF(CODE, 2)
+ | MACB_BF(DATA, value));
+ macb_writel(&macb, EMACB_MAN, frame);
+
+ do {
+ netstat = macb_readl(&macb, EMACB_NSR);
+ } while (!(netstat & MACB_BIT(IDLE)));
+
+ iflag = disable_interrupts();
+ netctl = macb_readl(&macb, EMACB_NCR);
+ netctl &= ~MACB_BIT(MPE);
+ macb_writel(&macb, EMACB_NCR, netctl);
+ if (iflag)
+ enable_interrupts();
+
+ return 0;
+}
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) */
+
+#endif /* CONFIG_MACB */
diff --git a/drivers/macb.h b/drivers/macb.h
new file mode 100644
index 0000000..c778e4e
--- /dev/null
+++ b/drivers/macb.h
@@ -0,0 +1,269 @@
+/*
+ * 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_MACB_H__
+#define __DRIVERS_MACB_H__
+
+/* MACB register offsets */
+#define MACB_NCR 0x0000
+#define MACB_NCFGR 0x0004
+#define MACB_NSR 0x0008
+#define MACB_TSR 0x0014
+#define MACB_RBQP 0x0018
+#define MACB_TBQP 0x001c
+#define MACB_RSR 0x0020
+#define MACB_ISR 0x0024
+#define MACB_IER 0x0028
+#define MACB_IDR 0x002c
+#define MACB_IMR 0x0030
+#define MACB_MAN 0x0034
+#define MACB_PTR 0x0038
+#define MACB_PFR 0x003c
+#define MACB_FTO 0x0040
+#define MACB_SCF 0x0044
+#define MACB_MCF 0x0048
+#define MACB_FRO 0x004c
+#define MACB_FCSE 0x0050
+#define MACB_ALE 0x0054
+#define MACB_DTF 0x0058
+#define MACB_LCOL 0x005c
+#define MACB_EXCOL 0x0060
+#define MACB_TUND 0x0064
+#define MACB_CSE 0x0068
+#define MACB_RRE 0x006c
+#define MACB_ROVR 0x0070
+#define MACB_RSE 0x0074
+#define MACB_ELE 0x0078
+#define MACB_RJA 0x007c
+#define MACB_USF 0x0080
+#define MACB_STE 0x0084
+#define MACB_RLE 0x0088
+#define MACB_TPF 0x008c
+#define MACB_HRB 0x0090
+#define MACB_HRT 0x0094
+#define MACB_SA1B 0x0098
+#define MACB_SA1T 0x009c
+#define MACB_SA2B 0x00a0
+#define MACB_SA2T 0x00a4
+#define MACB_SA3B 0x00a8
+#define MACB_SA3T 0x00ac
+#define MACB_SA4B 0x00b0
+#define MACB_SA4T 0x00b4
+#define MACB_TID 0x00b8
+#define MACB_TPQ 0x00bc
+#define MACB_USRIO 0x00c0
+#define MACB_WOL 0x00c4
+
+/* Bitfields in NCR */
+#define MACB_LB_OFFSET 0
+#define MACB_LB_SIZE 1
+#define MACB_LLB_OFFSET 1
+#define MACB_LLB_SIZE 1
+#define MACB_RE_OFFSET 2
+#define MACB_RE_SIZE 1
+#define MACB_TE_OFFSET 3
+#define MACB_TE_SIZE 1
+#define MACB_MPE_OFFSET 4
+#define MACB_MPE_SIZE 1
+#define MACB_CLRSTAT_OFFSET 5
+#define MACB_CLRSTAT_SIZE 1
+#define MACB_INCSTAT_OFFSET 6
+#define MACB_INCSTAT_SIZE 1
+#define MACB_WESTAT_OFFSET 7
+#define MACB_WESTAT_SIZE 1
+#define MACB_BP_OFFSET 8
+#define MACB_BP_SIZE 1
+#define MACB_TSTART_OFFSET 9
+#define MACB_TSTART_SIZE 1
+#define MACB_THALT_OFFSET 10
+#define MACB_THALT_SIZE 1
+#define MACB_NCR_TPF_OFFSET 11
+#define MACB_NCR_TPF_SIZE 1
+#define MACB_TZQ_OFFSET 12
+#define MACB_TZQ_SIZE 1
+
+/* Bitfields in NCFGR */
+#define MACB_SPD_OFFSET 0
+#define MACB_SPD_SIZE 1
+#define MACB_FD_OFFSET 1
+#define MACB_FD_SIZE 1
+#define MACB_BIT_RATE_OFFSET 2
+#define MACB_BIT_RATE_SIZE 1
+#define MACB_JFRAME_OFFSET 3
+#define MACB_JFRAME_SIZE 1
+#define MACB_CAF_OFFSET 4
+#define MACB_CAF_SIZE 1
+#define MACB_NBC_OFFSET 5
+#define MACB_NBC_SIZE 1
+#define MACB_NCFGR_MTI_OFFSET 6
+#define MACB_NCFGR_MTI_SIZE 1
+#define MACB_UNI_OFFSET 7
+#define MACB_UNI_SIZE 1
+#define MACB_BIG_OFFSET 8
+#define MACB_BIG_SIZE 1
+#define MACB_EAE_OFFSET 9
+#define MACB_EAE_SIZE 1
+#define MACB_CLK_OFFSET 10
+#define MACB_CLK_SIZE 2
+#define MACB_RTY_OFFSET 12
+#define MACB_RTY_SIZE 1
+#define MACB_PAE_OFFSET 13
+#define MACB_PAE_SIZE 1
+#define MACB_RBOF_OFFSET 14
+#define MACB_RBOF_SIZE 2
+#define MACB_RLCE_OFFSET 16
+#define MACB_RLCE_SIZE 1
+#define MACB_DRFCS_OFFSET 17
+#define MACB_DRFCS_SIZE 1
+#define MACB_EFRHD_OFFSET 18
+#define MACB_EFRHD_SIZE 1
+#define MACB_IRXFCS_OFFSET 19
+#define MACB_IRXFCS_SIZE 1
+
+/* Bitfields in NSR */
+#define MACB_NSR_LINK_OFFSET 0
+#define MACB_NSR_LINK_SIZE 1
+#define MACB_MDIO_OFFSET 1
+#define MACB_MDIO_SIZE 1
+#define MACB_IDLE_OFFSET 2
+#define MACB_IDLE_SIZE 1
+
+/* Bitfields in TSR */
+#define MACB_UBR_OFFSET 0
+#define MACB_UBR_SIZE 1
+#define MACB_COL_OFFSET 1
+#define MACB_COL_SIZE 1
+#define MACB_TSR_RLE_OFFSET 2
+#define MACB_TSR_RLE_SIZE 1
+#define MACB_TGO_OFFSET 3
+#define MACB_TGO_SIZE 1
+#define MACB_BEX_OFFSET 4
+#define MACB_BEX_SIZE 1
+#define MACB_COMP_OFFSET 5
+#define MACB_COMP_SIZE 1
+#define MACB_UND_OFFSET 6
+#define MACB_UND_SIZE 1
+
+/* Bitfields in RSR */
+#define MACB_BNA_OFFSET 0
+#define MACB_BNA_SIZE 1
+#define MACB_REC_OFFSET 1
+#define MACB_REC_SIZE 1
+#define MACB_OVR_OFFSET 2
+#define MACB_OVR_SIZE 1
+
+/* Bitfields in ISR/IER/IDR/IMR */
+#define MACB_MFD_OFFSET 0
+#define MACB_MFD_SIZE 1
+#define MACB_RCOMP_OFFSET 1
+#define MACB_RCOMP_SIZE 1
+#define MACB_RXUBR_OFFSET 2
+#define MACB_RXUBR_SIZE 1
+#define MACB_TXUBR_OFFSET 3
+#define MACB_TXUBR_SIZE 1
+#define MACB_ISR_TUND_OFFSET 4
+#define MACB_ISR_TUND_SIZE 1
+#define MACB_ISR_RLE_OFFSET 5
+#define MACB_ISR_RLE_SIZE 1
+#define MACB_TXERR_OFFSET 6
+#define MACB_TXERR_SIZE 1
+#define MACB_TCOMP_OFFSET 7
+#define MACB_TCOMP_SIZE 1
+#define MACB_ISR_LINK_OFFSET 9
+#define MACB_ISR_LINK_SIZE 1
+#define MACB_ISR_ROVR_OFFSET 10
+#define MACB_ISR_ROVR_SIZE 1
+#define MACB_HRESP_OFFSET 11
+#define MACB_HRESP_SIZE 1
+#define MACB_PFR_OFFSET 12
+#define MACB_PFR_SIZE 1
+#define MACB_PTZ_OFFSET 13
+#define MACB_PTZ_SIZE 1
+
+/* Bitfields in MAN */
+#define MACB_DATA_OFFSET 0
+#define MACB_DATA_SIZE 16
+#define MACB_CODE_OFFSET 16
+#define MACB_CODE_SIZE 2
+#define MACB_REGA_OFFSET 18
+#define MACB_REGA_SIZE 5
+#define MACB_PHYA_OFFSET 23
+#define MACB_PHYA_SIZE 5
+#define MACB_RW_OFFSET 28
+#define MACB_RW_SIZE 2
+#define MACB_SOF_OFFSET 30
+#define MACB_SOF_SIZE 2
+
+/* Bitfields in USRIO */
+#define MACB_MII_OFFSET 0
+#define MACB_MII_SIZE 1
+#define MACB_EAM_OFFSET 1
+#define MACB_EAM_SIZE 1
+#define MACB_TX_PAUSE_OFFSET 2
+#define MACB_TX_PAUSE_SIZE 1
+#define MACB_TX_PAUSE_ZERO_OFFSET 3
+#define MACB_TX_PAUSE_ZERO_SIZE 1
+
+/* Bitfields in WOL */
+#define MACB_IP_OFFSET 0
+#define MACB_IP_SIZE 16
+#define MACB_MAG_OFFSET 16
+#define MACB_MAG_SIZE 1
+#define MACB_ARP_OFFSET 17
+#define MACB_ARP_SIZE 1
+#define MACB_SA1_OFFSET 18
+#define MACB_SA1_SIZE 1
+#define MACB_WOL_MTI_OFFSET 19
+#define MACB_WOL_MTI_SIZE 1
+
+/* Constants for CLK */
+#define MACB_CLK_DIV8 0
+#define MACB_CLK_DIV16 1
+#define MACB_CLK_DIV32 2
+#define MACB_CLK_DIV64 3
+
+/* Constants for MAN register */
+#define MACB_MAN_SOF 1
+#define MACB_MAN_WRITE 1
+#define MACB_MAN_READ 2
+#define MACB_MAN_CODE 2
+
+/* Bit manipulation macros */
+#define MACB_BIT(name) \
+ (1 << MACB_##name##_OFFSET)
+#define MACB_BF(name,value) \
+ (((value) & ((1 << MACB_##name##_SIZE) - 1)) \
+ << MACB_##name##_OFFSET)
+#define MACB_BFEXT(name,value)\
+ (((value) >> MACB_##name##_OFFSET) \
+ & ((1 << MACB_##name##_SIZE) - 1))
+#define MACB_BFINS(name,value,old) \
+ (((old) & ~(((1 << MACB_##name##_SIZE) - 1) \
+ << MACB_##name##_OFFSET)) \
+ | MACB_BF(name,value))
+
+/* Register access macros */
+#define macb_readl(port,reg) \
+ readl((port)->regs + MACB_##reg)
+#define macb_writel(port,reg,value) \
+ writel((value), (port)->regs + MACB_##reg)
+
+#endif /* __DRIVERS_MACB_H__ */
diff --git a/drivers/qe/qe.h b/drivers/qe/qe.h
index f7f8ed0..0bcd0a9 100644
--- a/drivers/qe/qe.h
+++ b/drivers/qe/qe.h
@@ -30,7 +30,7 @@
#define UCC_MAX_NUM 8
#define QE_DATAONLY_BASE (uint)(128)
-#define QE_DATAONLY_SIZE ((uint)(0xc000) - QE_DATAONLY_BASE)
+#define QE_DATAONLY_SIZE (QE_MURAM_SIZE - QE_DATAONLY_BASE)
/* QE threads SNUM
*/
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c
index f640c81..c416a67 100644
--- a/drivers/qe/uec.c
+++ b/drivers/qe/uec.c
@@ -432,7 +432,12 @@ static int init_phy(struct eth_device *dev)
}
memset(mii_info, 0, sizeof(*mii_info));
- mii_info->speed = SPEED_1000;
+ if (uec->uec_info->uf_info.eth_type == GIGA_ETH) {
+ mii_info->speed = SPEED_1000;
+ } else {
+ mii_info->speed = SPEED_100;
+ }
+
mii_info->duplex = DUPLEX_FULL;
mii_info->pause = 0;
mii_info->link = 1;
@@ -508,7 +513,8 @@ static void adjust_link(struct eth_device *dev)
}
if (mii_info->speed != uec->oldspeed) {
- switch (mii_info->speed) {
+ if (uec->uec_info->uf_info.eth_type == GIGA_ETH) {
+ switch (mii_info->speed) {
case 1000:
break;
case 100:
@@ -531,6 +537,7 @@ static void adjust_link(struct eth_device *dev)
printf("%s: Ack,Speed(%d)is illegal\n",
dev->name, mii_info->speed);
break;
+ }
}
printf("%s: Speed %dBT\n", dev->name, mii_info->speed);
@@ -1122,7 +1129,7 @@ static int uec_send(struct eth_device* dev, volatile void *buf, int len)
uec_private_t *uec;
ucc_fast_private_t *uccf;
volatile qe_bd_t *bd;
- volatile u16 status;
+ u16 status;
int i;
int result = 0;
@@ -1131,7 +1138,7 @@ static int uec_send(struct eth_device* dev, volatile void *buf, int len)
bd = uec->txBd;
/* Find an empty TxBD */
- for (i = 0; BD_STATUS(bd) & TxBD_READY; i++) {
+ for (i = 0; bd->status & TxBD_READY; i++) {
if (i > 0x100000) {
printf("%s: tx buffer not ready\n", dev->name);
return result;
@@ -1141,7 +1148,7 @@ static int uec_send(struct eth_device* dev, volatile void *buf, int len)
/* Init TxBD */
BD_DATA_SET(bd, buf);
BD_LENGTH_SET(bd, len);
- status = BD_STATUS(bd);
+ status = bd->status;
status &= BD_WRAP;
status |= (TxBD_READY | TxBD_LAST);
BD_STATUS_SET(bd, status);
@@ -1150,13 +1157,11 @@ static int uec_send(struct eth_device* dev, volatile void *buf, int len)
ucc_fast_transmit_on_demand(uccf);
/* Wait for buffer to be transmitted */
- status = BD_STATUS(bd);
- for (i = 0; status & TxBD_READY; i++) {
+ for (i = 0; bd->status & TxBD_READY; i++) {
if (i > 0x100000) {
printf("%s: tx error\n", dev->name);
return result;
}
- status = BD_STATUS(bd);
}
/* Ok, the buffer be transimitted */
@@ -1171,12 +1176,12 @@ static int uec_recv(struct eth_device* dev)
{
uec_private_t *uec = dev->priv;
volatile qe_bd_t *bd;
- volatile u16 status;
+ u16 status;
u16 len;
u8 *data;
bd = uec->rxBd;
- status = BD_STATUS(bd);
+ status = bd->status;
while (!(status & RxBD_EMPTY)) {
if (!(status & RxBD_ERROR)) {
@@ -1190,7 +1195,7 @@ static int uec_recv(struct eth_device* dev)
BD_LENGTH_SET(bd, 0);
BD_STATUS_SET(bd, status | RxBD_EMPTY);
BD_ADVANCE(bd, status, uec->p_rx_bd_ring);
- status = BD_STATUS(bd);
+ status = bd->status;
}
uec->rxBd = bd;
diff --git a/drivers/tsec.c b/drivers/tsec.c
index 2524e4f..3f11eb0 100644
--- a/drivers/tsec.c
+++ b/drivers/tsec.c
@@ -381,6 +381,61 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
return 0;
}
+/*
+ * Parse the BCM54xx status register for speed and duplex information.
+ * The linux sungem_phy has this information, but in a table format.
+ */
+uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv)
+{
+
+ switch((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >> MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT){
+
+ case 1:
+ printf("Enet starting in 10BT/HD\n");
+ priv->duplexity = 0;
+ priv->speed = 10;
+ break;
+
+ case 2:
+ printf("Enet starting in 10BT/FD\n");
+ priv->duplexity = 1;
+ priv->speed = 10;
+ break;
+
+ case 3:
+ printf("Enet starting in 100BT/HD\n");
+ priv->duplexity = 0;
+ priv->speed = 100;
+ break;
+
+ case 5:
+ printf("Enet starting in 100BT/FD\n");
+ priv->duplexity = 1;
+ priv->speed = 100;
+ break;
+
+ case 6:
+ printf("Enet starting in 1000BT/HD\n");
+ priv->duplexity = 0;
+ priv->speed = 1000;
+ break;
+
+ case 7:
+ printf("Enet starting in 1000BT/FD\n");
+ priv->duplexity = 1;
+ priv->speed = 1000;
+ break;
+
+ default:
+ printf("Auto-neg error, defaulting to 10BT/HD\n");
+ priv->duplexity = 0;
+ priv->speed = 10;
+ break;
+ }
+
+ return 0;
+
+}
/* Parse the 88E1011's status register for speed and duplex
* information
*/
@@ -770,6 +825,34 @@ static void tsec_halt(struct eth_device *dev)
phy_run_commands(priv, priv->phyinfo->shutdown);
}
+/* The 5411 id is 0x206070, the 5421 is 0x2060e0 */
+struct phy_info phy_info_BCM5461S = {
+ 0x02060c1, /* 5461 ID */
+ "Broadcom BCM5461S",
+ 0, /* not clear to me what minor revisions we can shift away */
+ (struct phy_cmd[]) { /* config */
+ /* Reset and configure the PHY */
+ {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+ {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
+ {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
+ {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+ {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
+ {miim_end,}
+ },
+ (struct phy_cmd[]) { /* startup */
+ /* Status is read once to clear old link state */
+ {MIIM_STATUS, miim_read, NULL},
+ /* Auto-negotiate */
+ {MIIM_STATUS, miim_read, &mii_parse_sr},
+ /* Read the status */
+ {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
+ {miim_end,}
+ },
+ (struct phy_cmd[]) { /* shutdown */
+ {miim_end,}
+ },
+};
+
struct phy_info phy_info_M88E1011S = {
0x01410c6,
"Marvell 88E1011S",
@@ -1112,6 +1195,7 @@ struct phy_info phy_info_dp83865 = {
struct phy_info *phy_info[] = {
&phy_info_cis8204,
&phy_info_cis8201,
+ &phy_info_BCM5461S,
&phy_info_M88E1011S,
&phy_info_M88E1111S,
&phy_info_M88E1145,
diff --git a/drivers/tsec.h b/drivers/tsec.h
index cee3003..422bc66 100644
--- a/drivers/tsec.h
+++ b/drivers/tsec.h
@@ -109,6 +109,11 @@
#define MIIM_GBIT_CONTROL 0x9
#define MIIM_GBIT_CONTROL_INIT 0xe00
+/* Broadcom BCM54xx -- taken from linux sungem_phy */
+#define MIIM_BCM54xx_AUXSTATUS 0x19
+#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK 0x0700
+#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT 8
+
/* Cicada Auxiliary Control/Status Register */
#define MIIM_CIS8201_AUX_CONSTAT 0x1c
#define MIIM_CIS8201_AUXCONSTAT_INIT 0x0004