diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/mxc_enet.c | 742 | ||||
-rw-r--r-- | drivers/net/mxc_fec.c | 29 |
3 files changed, 29 insertions, 743 deletions
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 9318015..6ba00be 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -50,7 +50,6 @@ COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o COBJS-$(CONFIG_MXC_FEC) += mxc_fec.o -COBJS-$(CONFIG_MXC_ENET) += mxc_enet.o COBJS-$(CONFIG_NATSEMI) += natsemi.o COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o diff --git a/drivers/net/mxc_enet.c b/drivers/net/mxc_enet.c deleted file mode 100644 index edfbc1a..0000000 --- a/drivers/net/mxc_enet.c +++ /dev/null @@ -1,742 +0,0 @@ -/* - * (C) Copyright 2000-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2008-2010 Freescale Semiconductor, Inc. - * - * 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 - */ - -#include <common.h> -#include <malloc.h> -#include <net.h> -#include <miiphy.h> -#include <asm/arch/mx28.h> -#include <asm/arch/regs-enet.h> -#include <asm/arch/regs-clkctrl.h> - -/* - * Debug message switch - */ -#undef MXC_ENET_DEBUG - -/* - * Buffer descriptor control/status used by Ethernet receive. - */ -#define BD_ENET_RX_EMPTY ((ushort)0x8000) -#define BD_ENET_RX_RO1 ((ushort)0x4000) -#define BD_ENET_RX_WRAP ((ushort)0x2000) -#define BD_ENET_RX_INTR ((ushort)0x1000) -#define BD_ENET_RX_RO2 BD_ENET_RX_INTR -#define BD_ENET_RX_LAST ((ushort)0x0800) -#define BD_ENET_RX_FIRST ((ushort)0x0400) -#define BD_ENET_RX_MISS ((ushort)0x0100) -#define BD_ENET_RX_BC ((ushort)0x0080) -#define BD_ENET_RX_MC ((ushort)0x0040) -#define BD_ENET_RX_LG ((ushort)0x0020) -#define BD_ENET_RX_NO ((ushort)0x0010) -#define BD_ENET_RX_SH ((ushort)0x0008) -#define BD_ENET_RX_CR ((ushort)0x0004) -#define BD_ENET_RX_OV ((ushort)0x0002) -#define BD_ENET_RX_CL ((ushort)0x0001) -#define BD_ENET_RX_TR BD_ENET_RX_CL -#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */ - -/* - * Buffer descriptor control/status used by Ethernet transmit. - */ -#define BD_ENET_TX_READY ((ushort)0x8000) -#define BD_ENET_TX_PAD ((ushort)0x4000) -#define BD_ENET_TX_TO1 BD_ENET_TX_PAD -#define BD_ENET_TX_WRAP ((ushort)0x2000) -#define BD_ENET_TX_INTR ((ushort)0x1000) -#define BD_ENET_TX_TO2 BD_ENET_TX_INTR_ -#define BD_ENET_TX_LAST ((ushort)0x0800) -#define BD_ENET_TX_TC ((ushort)0x0400) -#define BD_ENET_TX_DEF ((ushort)0x0200) -#define BD_ENET_TX_ABC BD_ENET_TX_DEF -#define BD_ENET_TX_HB ((ushort)0x0100) -#define BD_ENET_TX_LC ((ushort)0x0080) -#define BD_ENET_TX_RL ((ushort)0x0040) -#define BD_ENET_TX_RCMASK ((ushort)0x003c) -#define BD_ENET_TX_UN ((ushort)0x0002) -#define BD_ENET_TX_CSL ((ushort)0x0001) -#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */ - -/* - * Buffer descriptors - */ -typedef struct cpm_buf_desc { - ushort cbd_datlen; /* Data length in buffer */ - ushort cbd_sc; /* Status and Control */ - uint cbd_bufaddr; /* Buffer address in host memory */ -} cbd_t; - -/* ENET private information */ -struct enet_info_s { - int index; - u32 iobase; - int phy_addr; - int dup_spd; - char *phy_name; - int phyname_init; - cbd_t *rxbd; /* Rx BD */ - cbd_t *txbd; /* Tx BD */ - uint rxIdx; - uint txIdx; - char *rxbuf; - char *txbuf; - int initialized; - struct enet_info_s *next; -}; - -/* Register read/write struct */ -typedef struct enet { - u32 resv0; /* 0x0000 */ - u32 eir; /* 0x0004 */ - u32 eimr; /* 0x0008 */ - u32 resv1; /* 0x000c */ - u32 rdar; /* 0x0010 */ - u32 tdar; /* 0x0014 */ - u32 resv2[3]; /* 0x0018 */ - u32 ecr; /* 0x0024 */ - u32 resv3[6]; /* 0x0028 */ - u32 mmfr; /* 0x0040 */ - u32 mscr; /* 0x0044 */ - u32 resv4[7]; /* 0x0048 */ - u32 mibc; /* 0x0064 */ - u32 resv5[7]; /* 0x0068 */ - u32 rcr; /* 0x0084 */ - u32 resv6[15]; /* 0x0088 */ - u32 tcr; /* 0x00c4 */ - u32 resv7[7]; /* 0x00c8 */ - u32 palr; /* 0x00e4 */ - u32 paur; /* 0x00e8 */ - u32 opd; /* 0x00ec */ - u32 resv8[10]; /* 0x00f0 */ - u32 iaur; /* 0x0118 */ - u32 ialr; /* 0x011c */ - u32 gaur; /* 0x0120 */ - u32 galr; /* 0x0124 */ - u32 resv9[7]; /* 0x0128 */ - u32 tfwr; /* 0x0144 */ - u32 resv10; /* 0x0148 */ - u32 frbr; /* 0x014c */ - u32 frsr; /* 0x0150 */ - u32 resv11[11]; /* 0x0154 */ - u32 erdsr; /* 0x0180 */ - u32 etdsr; /* 0x0184 */ - u32 emrbr; /* 0x0188 */ - /* Unused registers ... */ -} enet_t; - -/* - * Ethernet Transmit and Receive Buffers - */ -#define DBUF_LENGTH 1520 -#define RX_BUF_CNT (PKTBUFSRX) -#define TX_BUF_CNT (RX_BUF_CNT) -#define PKT_MINBUF_SIZE 64 -#define PKT_MAXBLR_SIZE 1520 -#define LAST_RX_BUF (RX_BUF_CNT - 1) -#define BD_ENET_RX_W_E (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY) -#define BD_ENET_TX_RDY_LST (BD_ENET_TX_READY | BD_ENET_TX_LAST) - -/* - * MII definitions - */ -#define ENET_MII_ST 0x40000000 -#define ENET_MII_OP_OFF 28 -#define ENET_MII_OP_MASK 0x03 -#define ENET_MII_OP_RD 0x02 -#define ENET_MII_OP_WR 0x01 -#define ENET_MII_PA_OFF 23 -#define ENET_MII_PA_MASK 0xFF -#define ENET_MII_RA_OFF 18 -#define ENET_MII_RA_MASK 0xFF -#define ENET_MII_TA 0x00020000 -#define ENET_MII_DATA_OFF 0 -#define ENET_MII_DATA_MASK 0x0000FFFF - -#define ENET_MII_FRAME \ - (ENET_MII_ST | ENET_MII_TA) - -#define ENET_MII_OP(x) \ - (((x) & ENET_MII_OP_MASK) << ENET_MII_OP_OFF) - -#define ENET_MII_PA(pa) \ - (((pa) & ENET_MII_PA_MASK) << ENET_MII_PA_OFF) - -#define ENET_MII_RA(ra) \ - (((ra) & ENET_MII_RA_MASK) << ENET_MII_RA_OFF) - -#define ENET_MII_SET_DATA(v) \ - (((v) & ENET_MII_DATA_MASK) << ENET_MII_DATA_OFF) - -#define ENET_MII_GET_DATA(v) \ - (((v) >> ENET_MII_DATA_OFF) & ENET_MII_DATA_MASK) - -#define ENET_MII_READ(pa, ra) \ - ((ENET_MII_FRAME | ENET_MII_OP(ENET_MII_OP_RD)) | \ - ENET_MII_PA(pa) | ENET_MII_RA(ra)) - -#define ENET_MII_WRITE(pa, ra, v) \ - (ENET_MII_FRAME | ENET_MII_OP(ENET_MII_OP_WR) | \ - ENET_MII_PA(pa) | ENET_MII_RA(ra) | ENET_MII_SET_DATA(v)) - -#define ENET_MII_TIMEOUT 50000 -#define ENET_MII_TICK 2 -#define ENET_MII_PHYADDR 0x0 - -/* - * Misc definitions - */ -#ifndef CONFIG_SYS_CACHELINE_SIZE -#define CONFIG_SYS_CACHELINE_SIZE 32 -#endif - -#define ENET_RESET_DELAY 100 -#define ENET_MAX_TIMEOUT 50000 -#define ENET_TIMEOUT_TICKET 2 - -#define __swap_32(x) ((((unsigned long)x) << 24) | \ - ((0x0000FF00UL & ((unsigned long)x)) << 8) | \ - ((0x00FF0000UL & ((unsigned long)x)) >> 8) | \ - (((unsigned long)x) >> 24)) - -/* - * Functions - */ -extern void enet_board_init(void); - -#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) -static struct enet_info_s enet_info[] = { - { - 0, /* index */ - REGS_ENET_BASE, /* io base */ -#ifdef CONFIG_DISCOVER_PHY - -1, /* discover phy_addr */ -#else - ENET_MII_PHYADDR, /* phy_addr for MAC0 */ -#endif - 0, /* duplex and speed */ - 0, /* phy name */ - 0, /* phyname init */ - 0, /* RX BD */ - 0, /* TX BD */ - 0, /* rx Index */ - 0, /* tx Index */ - 0, /* tx buffer */ - 0 /* initialized flag */ - } -}; - -static inline int __enet_mii_read(volatile enet_t *enetp, unsigned char addr, - unsigned char reg, unsigned short *value) -{ - int waiting = ENET_MII_TIMEOUT; - if (enetp->eir & BM_ENET_MAC0_EIR_MII) - enetp->eir |= BM_ENET_MAC0_EIR_MII; - - enetp->mmfr = ENET_MII_READ(addr, reg); - while (1) { - if (enetp->eir & BM_ENET_MAC0_EIR_MII) { - enetp->eir |= BM_ENET_MAC0_EIR_MII; - break; - } - if ((waiting--) <= 0) - return -1; - udelay(ENET_MII_TICK); - } - *value = ENET_MII_GET_DATA(enetp->mmfr); - return 0; -} - -static inline int __enet_mii_write(volatile enet_t *enetp, unsigned char addr, - unsigned char reg, unsigned short value) -{ - int waiting = ENET_MII_TIMEOUT; - if (enetp->eir & BM_ENET_MAC0_EIR_MII) - enetp->eir |= BM_ENET_MAC0_EIR_MII; - - enetp->mmfr = ENET_MII_WRITE(addr, reg, value); - while (1) { - if (enetp->eir & BM_ENET_MAC0_EIR_MII) { - enetp->eir |= BM_ENET_MAC0_EIR_MII; - break; - } - if ((waiting--) <= 0) - return -1; - udelay(ENET_MII_TICK); - } - return 0; -} - -static int mxc_enet_mii_read(char *devname, unsigned char addr, - unsigned char reg, unsigned short *value) -{ - struct eth_device *dev = eth_get_dev_by_name(devname); - struct enet_info_s *info; - volatile enet_t *enetp; - - if (!dev) - return -1; - info = dev->priv; - enetp = (enet_t *) (info->iobase); - return __enet_mii_read(enetp, addr, reg, value); -} - -static int mxc_enet_mii_write(char *devname, unsigned char addr, - unsigned char reg, unsigned short value) -{ - struct eth_device *dev = eth_get_dev_by_name(devname); - struct enet_info_s *info; - volatile enet_t *enetp; - if (!dev) - return -1; - info = dev->priv; - enetp = (enet_t *) (info->iobase); - return __enet_mii_write(enetp, addr, reg, value); -} - -static void mxc_enet_mii_init(volatile enet_t *enetp) -{ - /* Set RMII mode */ - enetp->rcr |= BM_ENET_MAC0_RCR_RMII_MODE; - - /* The phy requires MDC clock below 2.5 MHz */ - enetp->mscr |= (enetp->mscr & ~BM_ENET_MAC0_MSCR_MII_SPEED) | - (40 << BP_ENET_MAC0_MSCR_MII_SPEED); -} - -#ifdef CONFIG_DISCOVER_PHY -static inline int __enet_mii_info(volatile enet_t *enetp, unsigned char addr) -{ - unsigned int id = 0; - unsigned short val; - - if (__enet_mii_read(enetp, addr, PHY_PHYIDR2, &val) != 0) - return -1; - id = val; - if (id == 0xffff) - return -1; - - if (__enet_mii_read(enetp, addr, PHY_PHYIDR1, &val) != 0) - return -1; - - if (val == 0xffff) - return -1; - - id |= val << 16; - -#ifdef MXC_ENMXC_ENET_DEBUG - printf("PHY indentify @ 0x%x = 0x%08x\n", addr, id); -#endif - return 0; -} - -static int mxc_enet_mii_discover_phy(struct eth_device *dev) -{ - unsigned short addr, val; - struct enet_info_s *info = dev->priv; - volatile enet_t *enetp = (enet_t *) (info->iobase); - - /* Dummy read with delay to get phy start working */ - do { - __enet_mii_read(enetp, ENET_MII_PHYADDR, PHY_PHYIDR1, &val); - udelay(10000); -#ifdef MXC_ENET_DEBUG - printf("Dummy read on phy\n"); -#endif - } while (val == 0 || val == 0xffff); - - /* Read phy ID */ - for (addr = 0; addr < 0x20; addr++) { - if (!__enet_mii_info(enetp, addr)) - return addr; - } - - return -1; -} -#endif - -static void set_duplex_speed(volatile enet_t *enetp, unsigned char addr, - int dup_spd) -{ - unsigned short val; - int ret; - - ret = __enet_mii_read(enetp, addr, PHY_BMCR, &val); - switch (dup_spd >> 16) { - case HALF: - val &= (~PHY_BMCR_DPLX); - break; - case FULL: - val |= PHY_BMCR_DPLX; - break; - default: - val |= PHY_BMCR_AUTON | PHY_BMCR_RST_NEG; - } - ret |= __enet_mii_write(enetp, addr, PHY_BMCR, val); - - if (!ret && (val & PHY_BMCR_AUTON)) { - ret = 0; - while (ret++ < ENET_MII_TIMEOUT) { - if (__enet_mii_read(enetp, addr, PHY_BMSR, &val)) - break; - if (!(val & PHY_BMSR_AUTN_ABLE)) - break; - if (val & PHY_BMSR_AUTN_COMP) - break; - } - } - - if (__enet_mii_read(enetp, addr, PHY_BMSR, &val)) { - dup_spd = _100BASET | (FULL << 16); - } else { - if (val & (PHY_BMSR_100TXF | PHY_BMSR_100TXH | PHY_BMSR_100T4)) - dup_spd = _100BASET; - else - dup_spd = _10BASET; - if (val & (PHY_BMSR_100TXF | PHY_BMSR_10TF)) - dup_spd |= (FULL << 16); - else - dup_spd |= (HALF << 16); - } - - if ((dup_spd >> 16) == FULL) { - enetp->tcr |= BM_ENET_MAC0_TCR_FEDN; -#ifdef MXC_ENET_DEBUG - printf("full duplex, "); -#endif - } else { - enetp->rcr |= BM_ENET_MAC0_RCR_DRT; - enetp->tcr &= ~BM_ENET_MAC0_TCR_FEDN; -#ifdef MXC_ENET_DEBUG - printf("half duplex, "); -#endif - } -#ifdef MXC_ENET_DEBUG - if ((dup_spd & 0xffff) == _100BASET) - printf("100 Mbps\n"); - else - printf("10 Mbps\n"); -#endif -} - -static void copy_packet(char *pdst, char *psrc, int length) -{ - long *pldst = (long *)pdst; - long *plsrc = (long *)psrc; - - length /= sizeof(long); - while (length--) { - *pldst = __swap_32(*plsrc); - pldst++; - plsrc++; - } -} - -static int enet_send(struct eth_device *dev, volatile void *packet, int length) -{ - struct enet_info_s *info = dev->priv; - volatile enet_t *enetp = (enet_t *) (info->iobase); - int i; - u16 phyStatus; - - __enet_mii_read(enetp, info->phy_addr, PHY_BMSR, &phyStatus); - - if (!(phyStatus & PHY_BMSR_LS)) { - printf("ENET: Link is down %x\n", phyStatus); - return -1; - } - - /* Wait for ready */ - i = 0; - while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) && - (i < ENET_MAX_TIMEOUT)) { - udelay(ENET_TIMEOUT_TICKET); - i++; - } - if (i >= ENET_MAX_TIMEOUT) - printf("TX buffer is NOT ready\n"); - - /* Manipulate the packet buffer */ - copy_packet((char *)info->txbd[info->txIdx].cbd_bufaddr, - (char *)packet, length + (4 - length % 4)); - - /* Set up transmit Buffer Descriptor */ - info->txbd[info->txIdx].cbd_datlen = length; - info->txbd[info->txIdx].cbd_sc = - (info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_WRAP) | - BD_ENET_TX_TC | BD_ENET_TX_RDY_LST; - - /* Activate transmit Buffer Descriptor polling */ - enetp->tdar = 0x01000000; - - /* Move Buffer Descriptor to the next */ - info->txIdx = (info->txIdx + 1) % TX_BUF_CNT; - - return length; -} - -static int enet_recv(struct eth_device *dev) -{ - struct enet_info_s *info = dev->priv; - volatile enet_t *enetp = (enet_t *) (info->iobase); - int length; - - for (;;) { - if (info->rxbd[info->rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { - length = -1; - break; /* nothing received - leave for() loop */ - } - - length = info->rxbd[info->rxIdx].cbd_datlen; - - if (info->rxbd[info->rxIdx].cbd_sc & 0x003f) { -#ifdef MXC_ENET_DEBUG - printf("%s[%d] err: %x\n", - __func__, __LINE__, - info->rxbd[info->rxIdx].cbd_sc); -#endif - } else { - length -= 4; - - /* Manipulate the packet buffer */ - copy_packet((char *)NetRxPackets[info->rxIdx], - (char *)info->rxbd[info->rxIdx].cbd_bufaddr, - length + (4 - length % 4)); - - /* Pass the packet up to the protocol layers. */ - NetReceive(NetRxPackets[info->rxIdx], length); - } - - /* Give the buffer back to the ENET */ - info->rxbd[info->rxIdx].cbd_datlen = 0; - - /* Wrap around buffer index when necessary */ - if (info->rxIdx == LAST_RX_BUF) { - info->rxbd[RX_BUF_CNT - 1].cbd_sc = BD_ENET_RX_W_E; - info->rxIdx = 0; - } else { - info->rxbd[info->rxIdx].cbd_sc = BD_ENET_RX_EMPTY; - info->rxIdx++; - } - - /* Try to fill Buffer Descriptors */ - enetp->rdar = 0x01000000; - } - - return length; -} - -static void enet_reset(struct eth_device *dev) -{ - int i; - struct enet_info_s *info = dev->priv; - volatile enet_t *enetp = (enet_t *) (info->iobase); - - enetp->ecr |= BM_ENET_MAC0_ECR_RESET; - for (i = 0; (enetp->ecr & BM_ENET_MAC0_ECR_RESET) && (i < ENET_RESET_DELAY); ++i) - udelay(1); - - if (i == ENET_RESET_DELAY) - printf("ENET reset timeout\n"); -} - -static void enet_halt(struct eth_device *dev) -{ - struct enet_info_s *info = dev->priv; - - /* Reset ENET controller to stop transmit and receive */ - enet_reset(dev); - - /* Clear buffers */ - info->rxIdx = info->txIdx = 0; - memset(info->rxbd, 0, RX_BUF_CNT * sizeof(cbd_t)); - memset(info->txbd, 0, TX_BUF_CNT * sizeof(cbd_t)); - memset(info->rxbuf, 0, RX_BUF_CNT * DBUF_LENGTH); - memset(info->txbuf, 0, TX_BUF_CNT * DBUF_LENGTH); -} - -static int enet_init(struct eth_device *dev, bd_t *bd) -{ - struct enet_info_s *info = dev->priv; - volatile enet_t *enetp = (enet_t *) (info->iobase); - int i; - u8 *ea = NULL; - - /* Turn on ENET clocks */ - REG_WR(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET, - REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET) & - ~(BM_CLKCTRL_ENET_SLEEP | BM_CLKCTRL_ENET_DISABLE)); - - /* Set up ENET PLL for 50 MHz */ - REG_SET(REGS_CLKCTRL_BASE, HW_CLKCTRL_PLL2CTRL0, - BM_CLKCTRL_PLL2CTRL0_POWER); /* Power on ENET PLL */ - udelay(10); /* Wait 10 us */ - REG_CLR(REGS_CLKCTRL_BASE, HW_CLKCTRL_PLL2CTRL0, - BM_CLKCTRL_PLL2CTRL0_CLKGATE); /* Gate on ENET PLL */ - REG_WR(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET, - REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET) | - BM_CLKCTRL_ENET_CLK_OUT_EN); /* Enable pad output */ - - /* Board level init */ - enet_board_init(); - - /* Reset ENET controller */ - enet_reset(dev); - -#if defined(CONFIG_CMD_MII) || defined(CONFIG_MII) || \ - defined(CONFIG_DISCOVER_PHY) - mxc_enet_mii_init(enetp); -#ifdef CONFIG_DISCOVER_PHY - if (info->phy_addr < 0 || info->phy_addr > 0x1f) - info->phy_addr = mxc_enet_mii_discover_phy(dev); -#endif - set_duplex_speed(enetp, (unsigned char)info->phy_addr, info->dup_spd); -#else -#ifndef CONFIG_DISCOVER_PHY - set_duplex_speed(enetp, (unsigned char)info->phy_addr, - (ENETDUPLEX << 16) | ENETSPEED); -#endif -#endif - /* We use strictly polling mode only */ - enetp->eimr = 0; - - /* Clear any pending interrupt */ - enetp->eir = 0xffffffff; - - /* Disable loopback mode */ - enetp->rcr &= ~BM_ENET_MAC0_RCR_LOOP; - - /* Enable RX flow control */ - enetp->rcr |= BM_ENET_MAC0_RCR_FCE; - - /* Set station address and enable it for TX */ - ea = dev->enetaddr; - enetp->palr = (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); - enetp->paur = (ea[4] << 24) | (ea[5] << 16); - enetp->tcr |= BM_ENET_MAC0_TCR_TX_ADDR_INS; - - /* Clear unicast address hash table */ - enetp->iaur = 0; - enetp->ialr = 0; - - /* Clear multicast address hash table */ - enetp->gaur = 0; - enetp->galr = 0; - - /* Set maximum receive buffer size. */ - enetp->emrbr = PKT_MAXBLR_SIZE; - - /* Setup Buffers and Buffer Desriptors */ - info->rxIdx = 0; - info->txIdx = 0; - - /* - * Setup Receiver Buffer Descriptors - * Settings: - * Empty, Wrap - */ - for (i = 0; i < RX_BUF_CNT; i++) { - info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; - info->rxbd[i].cbd_datlen = 0; /* Reset */ - info->rxbd[i].cbd_bufaddr = - (uint) (&info->rxbuf[0] + i * DBUF_LENGTH); - } - info->rxbd[RX_BUF_CNT - 1].cbd_sc |= BD_ENET_RX_WRAP; - - /* - * Setup Transmitter Buffer Descriptors - * Settings: - * Last, Tx CRC - */ - for (i = 0; i < TX_BUF_CNT; i++) { - info->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC; - info->txbd[i].cbd_datlen = 0; /* Reset */ - info->txbd[i].cbd_bufaddr = - (uint) (&info->txbuf[0] + i * DBUF_LENGTH); - } - info->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; - - /* Set receive and transmit descriptor base */ - enetp->erdsr = (unsigned int)(&info->rxbd[0]); - enetp->etdsr = (unsigned int)(&info->txbd[0]); - - /* Now enable the transmit and receive processing */ - enetp->ecr |= BM_ENET_MAC0_ECR_ETHER_EN; - - /* And last, try to fill Rx Buffer Descriptors */ - enetp->rdar = 0x01000000; - - return 0; -} - -int mxc_enet_initialize(bd_t *bis) -{ - struct eth_device *dev; - int i; - - for (i = 0; i < sizeof(enet_info) / sizeof(enet_info[0]); i++) { - dev = (struct eth_device *) memalign(CONFIG_SYS_CACHELINE_SIZE, - sizeof(*dev)); - if (dev == NULL) - hang(); - - memset(dev, 0, sizeof(*dev)); - - /* Regiester device */ - sprintf(dev->name, "ENET%d", enet_info[i].index); - dev->priv = &enet_info[i]; - dev->init = enet_init; - dev->halt = enet_halt; - dev->send = enet_send; - dev->recv = enet_recv; - eth_register(dev); -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) - miiphy_register(dev->name, mxc_enet_mii_read, mxc_enet_mii_write); -#endif - /* Setup Receive and Transmit buffer descriptor */ - enet_info[i].rxbd = - (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE, - RX_BUF_CNT * sizeof(cbd_t)); - enet_info[i].rxbuf = - (char *) memalign(CONFIG_SYS_CACHELINE_SIZE, - RX_BUF_CNT * DBUF_LENGTH); - enet_info[i].txbd = - (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE, - TX_BUF_CNT * sizeof(cbd_t)); - enet_info[i].txbuf = - (char *) memalign(CONFIG_SYS_CACHELINE_SIZE, - TX_BUF_CNT * DBUF_LENGTH); - enet_info[i].phy_name = - (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, 32); -#ifdef MXC_ENET_DEBUG - printf("%s: rxbd %x txbd %x ->%x\n", dev->name, - (int)enet_info[i].rxbd, (int)enet_info[i].txbd, - (int)enet_info[i].txbuf); -#endif - } - - return 1; -} - -#endif /* defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) */ diff --git a/drivers/net/mxc_fec.c b/drivers/net/mxc_fec.c index ba60d03..1a9f53f 100644 --- a/drivers/net/mxc_fec.c +++ b/drivers/net/mxc_fec.c @@ -285,6 +285,17 @@ static void setFecDuplexSpeed(volatile fec_t *fecp, unsigned char addr, unsigned short val = 0; int ret; +#ifdef CONFIG_MX28 + /* Dummy read with delay to get phy start working */ + do { + __fec_mii_read(fecp, CONFIG_FEC0_PHY_ADDR, PHY_PHYIDR1, &val); + udelay(10000); +#ifdef MII_DEBUG + printf("Dummy read on phy\n"); +#endif + } while (val == 0 || val == 0xffff); +#endif + ret = __fec_mii_read(fecp, addr, PHY_BMCR, &val); switch (dup_spd >> 16) { case HALF: @@ -343,6 +354,17 @@ static void setFecDuplexSpeed(volatile fec_t *fecp, unsigned char addr, #endif } +#ifdef CONFIG_MX28 +static void swap_packet(void *packet, int length) +{ + int i; + unsigned int *buf = packet; + + for (i = 0; i < (length + 3) / 4; i++, buf++) + *buf = __swab32(*buf); +} +#endif + int fec_send(struct eth_device *dev, volatile void *packet, int length) { struct fec_info_s *info = dev->priv; @@ -369,6 +391,10 @@ int fec_send(struct eth_device *dev, volatile void *packet, int length) if (j >= FEC_MAX_TIMEOUT) printf("TX not ready\n"); +#ifdef CONFIG_MX28 + swap_packet((void *)packet, length); +#endif + #ifdef CONFIG_ARCH_MMU memcpy(ioremap_nocache(info->txbd[info->txIdx].cbd_bufaddr, length), packet, length); @@ -440,6 +466,9 @@ int fec_recv(struct eth_device *dev) #endif } else { length -= 4; +#ifdef CONFIG_MX28 + swap_packet((void *)NetRxPackets[info->rxIdx], length); +#endif /* Pass the packet up to the protocol layers. */ #ifdef CONFIG_ARCH_MMU memcpy(NetRxPackets[info->rxIdx], |