summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Schwebel <r.schwebel@pengutronix.de>2007-11-08 17:22:51 +0100
committerRobert Schwebel <r.schwebel@pengutronix.de>2007-11-08 17:22:51 +0100
commit0e5848047874c52500ecef0560b4aa5459ddd917 (patch)
tree8810b0701889c78810077a8aeba827f116ff5127
parent175e8438df25835c497025ebece6f5ccd5766b9d (diff)
parente5eba4cf3a9622c53fe3ce8a2b2f6c804088f6eb (diff)
downloadbarebox-0e5848047874c52500ecef0560b4aa5459ddd917.tar.gz
barebox-0e5848047874c52500ecef0560b4aa5459ddd917.tar.xz
Merge branch 'master' of ssh://rsc@octopus/home/git/projects/u-boot-v2
-rw-r--r--.gitignore2
-rw-r--r--arch/arm/configs/phyCORE-pcm038_defconfig160
-rw-r--r--arch/arm/mach-imx/gpio.c29
-rw-r--r--arch/sandbox/Makefile1
-rw-r--r--board/phycore_pcm038/lowlevel_init.S15
-rw-r--r--board/phycore_pcm038/pcm038.c33
-rw-r--r--commands/mount.c2
-rw-r--r--commands/net.c2
-rw-r--r--drivers/net/Kconfig5
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/fec_imx27.c654
-rw-r--r--drivers/net/fec_imx27.h336
-rw-r--r--drivers/net/fec_mpc5200.c549
-rw-r--r--drivers/net/fec_mpc5200.h414
-rw-r--r--include/asm-arm/arch-imx/imx-regs.h80
-rw-r--r--include/asm-ppc/arch-mpc5200/fec.h14
-rw-r--r--include/asm-sandbox/posix_types.h4
-rw-r--r--include/fec.h44
-rw-r--r--net/eth.c2
-rw-r--r--net/net.c2
20 files changed, 1855 insertions, 494 deletions
diff --git a/.gitignore b/.gitignore
index 0eaee334ad..bcf8f98937 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,8 @@ include/linux/autoconf.h
include/linux/compile.h
include/linux/version.h
include/linux/utsrelease.h
+arch/sandbox/lib/u-boot.lds
+include/asm-sandbox/arch
# stgit generated dirs
patches-*
diff --git a/arch/arm/configs/phyCORE-pcm038_defconfig b/arch/arm/configs/phyCORE-pcm038_defconfig
new file mode 100644
index 0000000000..347dbc9832
--- /dev/null
+++ b/arch/arm/configs/phyCORE-pcm038_defconfig
@@ -0,0 +1,160 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.0.0-git
+# Thu Nov 8 16:52:09 2007
+#
+CONFIG_ARCH_TEXT_BASE=0xa0000000
+CONFIG_BOARDINFO="Phytec Phycore MX27"
+# CONFIG_BOARD_LINKER_SCRIPT is not set
+CONFIG_GENERIC_LINKER_SCRIPT=y
+CONFIG_ARM=y
+CONFIG_ARM926EJS=y
+CONFIG_ARCH_IMX=y
+CONFIG_ARCH_IMX27=y
+# CONFIG_MACH_MX1ADS is not set
+# CONFIG_MACH_SCB9328 is not set
+CONFIG_MACH_PCM038=y
+# CONFIG_MACH_ECO920 is not set
+# CONFIG_MACH_NXDB500 is not set
+# CONFIG_MACH_IMX31 is not set
+
+#
+# Arm specific settings
+#
+CONFIG_CMDLINE_TAG=y
+CONFIG_SETUP_MEMORY_TAGS=y
+# CONFIG_INITRD_TAG is not set
+CONFIG_GREGORIAN_CALENDER=y
+CONFIG_HAS_KALLSYMS=y
+CONFIG_HAS_MODULES=y
+
+#
+# General Settings
+#
+CONFIG_TEXT_BASE=0xa7f00000
+# CONFIG_BROKEN is not set
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_PROMPT="uboot:"
+CONFIG_BAUDRATE=115200
+CONFIG_CMDLINE_EDITING=y
+# CONFIG_AUTO_COMPLETE is not set
+CONFIG_LONGHELP=y
+CONFIG_CBSIZE=1024
+CONFIG_MAXARGS=16
+CONFIG_SHELL_HUSH=y
+# CONFIG_SHELL_SIMPLE is not set
+CONFIG_PROMPT_HUSH_PS2="> "
+CONFIG_DYNAMIC_CRC_TABLE=y
+CONFIG_ERRNO_MESSAGES=y
+CONFIG_TIMESTAMP=y
+CONFIG_CONSOLE_ACTIVATE_FIRST=y
+# CONFIG_OF_FLAT_TREE is not set
+CONFIG_DEFAULT_ENVIRONMENT=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH=""
+
+#
+# Debugging
+#
+# CONFIG_SKIP_LOWLEVEL_INIT is not set
+# CONFIG_ENABLE_FLASH_NOISE is not set
+# CONFIG_ENABLE_PARTITION_NOISE is not set
+# CONFIG_ENABLE_DEVICE_NOISE is not set
+
+#
+# Commands
+#
+
+#
+# scripting
+#
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_ENVIRONMENT=y
+CONFIG_CMD_HELP=y
+# CONFIG_CMD_READLINE is not set
+
+#
+# file commands
+#
+CONFIG_CMD_LS=y
+CONFIG_CMD_RM=y
+CONFIG_CMD_CAT=y
+CONFIG_CMD_MKDIR=y
+CONFIG_CMD_RMDIR=y
+CONFIG_CMD_CP=y
+CONFIG_CMD_PWD=y
+CONFIG_CMD_CD=y
+CONFIG_CMD_MOUNT=y
+CONFIG_CMD_UMOUNT=y
+
+#
+# console
+#
+CONFIG_CMD_CLEAR=y
+CONFIG_CMD_ECHO=y
+
+#
+# memory
+#
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_MTEST=y
+# CONFIG_CMD_MTEST_ALTERNATIVE is not set
+
+#
+# flash
+#
+CONFIG_CMD_FLASH=y
+
+#
+# booting
+#
+CONFIG_CMD_BOOTM=y
+# CONFIG_CMD_BOOTM_ZLIB is not set
+# CONFIG_CMD_BOOTM_BZLIB is not set
+# CONFIG_CMD_BOOTM_SHOW_TYPE is not set
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_TEST=y
+CONFIG_NET=y
+CONFIG_NET_BOOTP=y
+CONFIG_NET_DHCP=y
+# CONFIG_NET_RARP is not set
+# CONFIG_NET_SNTP is not set
+# CONFIG_NET_NFS is not set
+CONFIG_NET_PING=y
+CONFIG_NET_TFTP=y
+
+#
+# Drivers
+#
+
+#
+# serial drivers
+#
+CONFIG_DRIVER_SERIAL_IMX=y
+CONFIG_MIIPHY=y
+
+#
+# Network drivers
+#
+# CONFIG_DRIVER_NET_SMC911X is not set
+CONFIG_DRIVER_NET_IMX27=y
+
+#
+# flash drivers
+#
+CONFIG_HAS_CFI=y
+CONFIG_DRIVER_CFI=y
+# CONFIG_DRIVER_CFI_NEW is not set
+CONFIG_CFI_BUFFER_WRITE=y
+# CONFIG_NAND is not set
+
+#
+# Filesystem support
+#
+# CONFIG_FS_CRAMFS is not set
+CONFIG_CRC32=y
diff --git a/arch/arm/mach-imx/gpio.c b/arch/arm/mach-imx/gpio.c
index 9e667e32e5..2d42d3d8f9 100644
--- a/arch/arm/mach-imx/gpio.c
+++ b/arch/arm/mach-imx/gpio.c
@@ -29,10 +29,14 @@
void imx_gpio_mode(int gpio_mode)
{
unsigned int pin = gpio_mode & GPIO_PIN_MASK;
- unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5;
- unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10;
+ unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+ unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
+ unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT;
+ unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT;
unsigned int tmp;
+ printf("gpio_mode: 0x%08x ocr: 0x%08x port: %d pin: %2d aout: %d bout: %d\n", gpio_mode, ocr, port, pin, aout, bout);
+
/* Pullup enable */
if(gpio_mode & GPIO_PUEN)
PUEN(port) |= (1 << pin);
@@ -52,25 +56,22 @@ void imx_gpio_mode(int gpio_mode)
GPR(port) &= ~(1 << pin);
/* use as gpio? */
- if( ocr == 3 )
+ if(!(gpio_mode & (GPIO_PF | GPIO_AF)))
GIUS(port) |= (1 << pin);
else
GIUS(port) &= ~(1 << pin);
/* Output / input configuration */
- /* FIXME: I'm not very sure about OCR and ICONF, someone
- * should have a look over it
- */
if (pin < 16) {
tmp = OCR1(port);
tmp &= ~(3 << (pin * 2));
tmp |= (ocr << (pin * 2));
OCR1(port) = tmp;
- if( gpio_mode & GPIO_AOUT )
- ICONFA1(port) &= ~(3 << (pin * 2));
- if( gpio_mode & GPIO_BOUT )
- ICONFB1(port) &= ~(3 << (pin * 2));
+ ICONFA1(port) &= ~(3 << (pin * 2));
+ ICONFA1(port) |= aout << (pin * 2);
+ ICONFB1(port) &= ~(3 << (pin * 2));
+ ICONFB1(port) |= bout << (pin * 2);
} else {
pin -= 16;
@@ -79,10 +80,10 @@ void imx_gpio_mode(int gpio_mode)
tmp |= (ocr << (pin * 2));
OCR2(port) = tmp;
- if( gpio_mode & GPIO_AOUT )
- ICONFA2(port) &= ~(3 << (pin * 2));
- if( gpio_mode & GPIO_BOUT )
- ICONFB2(port) &= ~(3 << (pin * 2));
+ ICONFA2(port) &= ~(3 << (pin * 2));
+ ICONFA2(port) |= aout << (pin * 2);
+ ICONFB2(port) &= ~(3 << (pin * 2));
+ ICONFB2(port) |= bout << (pin * 2);
}
}
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index 07478c1928..7701c68620 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -9,6 +9,7 @@ machine-y := sandbox
lds-y := arch/sandbox/lib/u-boot.lds
BOARD:= arch/sandbox/lib
board-y := sandbox
+lds-y := arch/sandbox/lib/u-boot.lds
TEXT_BASE = $(CONFIG_TEXT_BASE)
diff --git a/board/phycore_pcm038/lowlevel_init.S b/board/phycore_pcm038/lowlevel_init.S
index 0c47c3a34c..fc65b902b6 100644
--- a/board/phycore_pcm038/lowlevel_init.S
+++ b/board/phycore_pcm038/lowlevel_init.S
@@ -50,6 +50,9 @@ board_init_lowlevel:
writel(0x130410c3, PCDR0)
writel(0x09030913, PCDR1)
+ /* skip sdram setup for debugging */
+ mov pc,r10
+
/* Skip SDRAM initialization if we run from RAM */
cmp pc, #0xa0000000
bls 1f
@@ -69,9 +72,9 @@ board_init_lowlevel:
writel(0x00005005, 0x10027838)
writel(0x15555555, 0x1002783C)
writel(0x00000004, 0xD8001010)
- writel(0x00795729, 0xD8001004)
+ writel(0x006ac73a, 0xD8001004)
writel(0x92100000, 0xD8001000)
- writel(0x00000000, 0xA0000F00)
+ writel(0x00000000, 0xA0000F00)
writel(0xA2100000, 0xD8001000)
writel(0x00000000, 0xA0000F00)
writel(0x00000000, 0xA0000F00)
@@ -82,14 +85,14 @@ board_init_lowlevel:
writel(0x00000000, 0xA0000F00)
writel(0x00000000, 0xA0000F00)
writel(0x00000000, 0xA0000F00)
- writel(0xB2126080, 0xD8001000)
+ writel(0xb2100000, 0xD8001000)
ldr r0, =0xA0000033
- mov r1, #0x0
+ mov r1, #0xda
strb r1, [r0]
ldr r0, =0xA1000000
- mov r1, #0x0
+ mov r1, #0xff
strb r1, [r0]
- writel(0x82126080, 0xD8001000)
+ writel(0x82226080, 0xD8001000)
mov pc,r10
diff --git a/board/phycore_pcm038/pcm038.c b/board/phycore_pcm038/pcm038.c
index 092abd1a7b..99cbc5eec4 100644
--- a/board/phycore_pcm038/pcm038.c
+++ b/board/phycore_pcm038/pcm038.c
@@ -24,6 +24,7 @@
#include <init.h>
#include <environment.h>
#include <asm/arch/imx-regs.h>
+#include <fec.h>
#include <asm/arch/gpio.h>
#include <partition.h>
#include <fs.h>
@@ -42,45 +43,51 @@ static struct device_d sdram_dev = {
.id = "ram0",
.map_base = 0xa0000000,
- .size = 32 * 1024 * 1024,
+ .size = 128 * 1024 * 1024,
.type = DEVICE_TYPE_DRAM,
};
+static struct fec_platform_data fec_info = {
+ .xcv_type = MII100,
+};
+
static struct device_d fec_dev = {
.name = "fec_imx27",
.id = "eth0",
-
+ .map_base = 0x1002b000,
+ .platform_data = &fec_info,
.type = DEVICE_TYPE_ETHER,
};
static int pcm038_devices_init(void)
{
int i;
- unsigned short mode[] = {
- PD12_AOUT_FEC_RXD0,
- PD5_AOUT_FEC_RXD1,
- PD6_AOUT_FEC_RXD2,
- PD7_AOUT_FEC_RXD3,
- PD4_AOUT_FEC_RX_ER,
- PD13_AOUT_FEC_RX_DV,
+ unsigned int mode[] = {
PD0_AIN_FEC_TXD0,
PD1_AIN_FEC_TXD1,
PD2_AIN_FEC_TXD2,
PD3_AIN_FEC_TXD3,
- PD11_AOUT_FEC_TX_CLK,
- PF23_AIN_FEC_TX_EN,
+ PD4_AOUT_FEC_RX_ER,
+ PD5_AOUT_FEC_RXD1,
+ PD6_AOUT_FEC_RXD2,
+ PD7_AOUT_FEC_RXD3,
PD8_AF_FEC_MDIO,
- PD9_AIN_FEC_MDC,
+ PD9_AIN_FEC_MDC | GPIO_PUEN,
+ PD10_AOUT_FEC_CRS,
+ PD11_AOUT_FEC_TX_CLK,
+ PD12_AOUT_FEC_RXD0,
+ PD13_AOUT_FEC_RX_DV,
PD14_AOUT_FEC_CLR,
PD15_AOUT_FEC_COL,
PD16_AIN_FEC_TX_ER,
+ PF23_AIN_FEC_TX_EN,
PE12_PF_UART1_TXD,
PE13_PF_UART1_RXD,
PE14_PF_UART1_CTS,
PE15_PF_UART1_RTS };
- for (i = 0; i < sizeof(mode) / sizeof(short); i ++)
+ for (i = 0; i < sizeof(mode) / sizeof(int); i++)
imx_gpio_mode(mode[i]);
register_device(&cfi_dev);
diff --git a/commands/mount.c b/commands/mount.c
index 22794f0d7e..dd04bdeeb7 100644
--- a/commands/mount.c
+++ b/commands/mount.c
@@ -83,7 +83,7 @@ U_BOOT_CMD_END
* Usage: mount [<device> <fstype> <mountpoint>]
*
* Mounts a filesystem of a given <fstype> on a <device> to a <mountpoint>.
- * <device> can be one of /dev/* or some arbitrary string if no
+ * <device> can be one of /dev/ * or some arbitrary string if no
* device is needed for this driver (for example ramfs).
*
* <fstype> is the filesystem driver to use. Try the 'devinfo' command
diff --git a/commands/net.c b/commands/net.c
index d12559e13f..25115e4f42 100644
--- a/commands/net.c
+++ b/commands/net.c
@@ -54,7 +54,7 @@ static void netboot_update_env (void)
setenv ("rootpath", NetOurRootPath);
if (NetOurIP)
- dev_set_param_ip(eth_current->dev, "ip", NetOurIP);
+ dev_set_param_ip(eth_current->dev, "ipaddr", NetOurIP);
if (NetServerIP)
dev_set_param_ip(eth_current->dev, "serverip", NetServerIP);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6b169dafcc..372f02dc12 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -52,6 +52,11 @@ config DRIVER_NET_MPC5200
depends on ARCH_MPC5200
select MIIPHY
+config DRIVER_NET_IMX27
+ bool "i.MX27 Ethernet driver"
+ depends on ARCH_IMX27
+ select MIIPHY
+
config DRIVER_NET_TAP
bool "tap Ethernet driver"
depends on LINUX
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b5e1b76258..cc48a27e52 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -4,5 +4,6 @@ obj-$(CONFIG_DRIVER_NET_DM9000) += dm9000.o
obj-$(CONFIG_DRIVER_NET_NETX) += netx_eth.o
obj-$(CONFIG_DRIVER_NET_AT91_ETHER) += at91_ether.o
obj-$(CONFIG_DRIVER_NET_MPC5200) += fec_mpc5200.o
+obj-$(CONFIG_DRIVER_NET_IMX27) += fec_imx27.o
obj-$(CONFIG_DRIVER_NET_TAP) += tap.o
obj-$(CONFIG_MIIPHY) += miiphy.o
diff --git a/drivers/net/fec_imx27.c b/drivers/net/fec_imx27.c
new file mode 100644
index 0000000000..2a9368f806
--- /dev/null
+++ b/drivers/net/fec_imx27.c
@@ -0,0 +1,654 @@
+/*
+ * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
+ *
+ * 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
+ */
+
+#define DEBUG
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <init.h>
+#include <miiphy.h>
+#include <driver.h>
+#include <miiphy.h>
+#include <fec.h>
+#include "fec_imx27.h"
+
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <clock.h>
+#include <asm/arch/clock.h>
+#include <xfuncs.h>
+
+#define CONFIG_PHY_ADDR 1 /* FIXME */
+
+typedef struct {
+ uint8_t data[1500]; /* actual data */
+ int length; /* actual length */
+ int used; /* buffer in use or not */
+ uint8_t head[16]; /* MAC header(6 + 6 + 2) + 2(aligned) */
+} NBUF;
+
+/*
+ * MII-interface related functions
+ */
+static int fec_miiphy_read(struct miiphy_device *mdev, uint8_t phyAddr,
+ uint8_t regAddr, uint16_t * retVal)
+{
+ struct eth_device *edev = mdev->edev;
+ fec_priv *fec = (fec_priv *)edev->priv;
+
+ uint32_t reg; /* convenient holder for the PHY register */
+ uint32_t phy; /* convenient holder for the PHY */
+ uint64_t start;
+
+ /*
+ * reading from any PHY's register is done by properly
+ * programming the FEC's MII data register.
+ */
+ writel(FEC_IEVENT_MII, &fec->eth->ievent);
+ reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+ phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+ writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg, &fec->eth->mii_data);
+
+ /*
+ * wait for the related interrupt
+ */
+ start = get_time_ns();
+ while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+ if (is_timeout(start, MSECOND)) {
+ printf("Read MDIO failed...\n");
+ return -1;
+ }
+ }
+
+ /*
+ * clear mii interrupt bit
+ */
+ writel(FEC_IEVENT_MII, &fec->eth->ievent);
+
+ /*
+ * it's now safe to read the PHY's register
+ */
+ *retVal = readl(&fec->eth->mii_data);
+
+ return 0;
+}
+
+static int fec_miiphy_write(struct miiphy_device *mdev, uint8_t phyAddr,
+ uint8_t regAddr, uint16_t data)
+{
+ struct eth_device *edev = mdev->edev;
+ fec_priv *fec = (fec_priv *)edev->priv;
+
+ uint32_t reg; /* convenient holder for the PHY register */
+ uint32_t phy; /* convenient holder for the PHY */
+ uint64_t start;
+
+ reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+ phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+ writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
+ FEC_MII_DATA_TA | phy | reg | data, &fec->eth->mii_data);
+
+ /*
+ * wait for the MII interrupt
+ */
+ start = get_time_ns();
+ while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+ if (is_timeout(start, MSECOND)) {
+ printf("Write MDIO failed...\n");
+ return -1;
+ }
+ }
+
+ /*
+ * clear MII interrupt bit
+ */
+ writel(FEC_IEVENT_MII, &fec->eth->ievent);
+
+ return 0;
+}
+
+static int fec_rx_task_enable(fec_priv *fec)
+{
+ writel(1 << 24, &fec->eth->r_des_active);
+ return 0;
+}
+
+static int fec_rx_task_disable(fec_priv *fec)
+{
+ return 0;
+}
+
+static int fec_tx_task_enable(fec_priv *fec)
+{
+ writel(1 << 24, &fec->eth->x_des_active);
+ return 0;
+}
+
+static int fec_tx_task_disable(fec_priv *fec)
+{
+ return 0;
+}
+
+/**
+ * Initialize receive task's buffer descriptors
+ * @param[in] fec all we know about the device yet
+ * @param[in] count receive buffer count to be allocated
+ * @param[in] size size of each receive buffer
+ * @return 0 on success
+ *
+ * For this task we need additional memory for the data buffers. And each
+ * data buffer requires some alignment. Thy must be aligned to a specific
+ * boundary each (4 byte).
+ */
+static int fec_rbd_init(fec_priv *fec, int count, int size)
+{
+ int ix;
+ static int once = 0;
+ uint32_t p=0;
+
+ if (!once) {
+ /* reserve data memory and consider alignment */
+ p = (uint32_t)xzalloc(size * count + 0x04) + 0x03;
+ p &= ~0x03;
+ }
+
+ for (ix = 0; ix < count; ix++) {
+ if (!once) {
+ writel(p, &fec->rbd_base[ix].data_pointer);
+ p += size;
+ }
+ writew(FEC_RBD_EMPTY, &fec->rbd_base[ix].status);
+ writew(0, &fec->rbd_base[ix].data_length);
+ }
+ once = 1; /* malloc done now (and once) */
+ /*
+ * mark the last RBD to close the ring
+ */
+ writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &fec->rbd_base[ix - 1].status);
+ fec->rbd_index = 0;
+
+ return 0;
+}
+
+/**
+ * Initialize transmit task's buffer descriptors
+ * @param[in] fec all we know about the device yet
+ *
+ * Transmit buffers are created externally. We only have to init the BDs here.
+ * Note: There is a race condition in the hardware. When only one BD is in
+ * use it must be marked with the WRAP bit to use it for every transmitt.
+ * This bit in combination with the READY bit results into double transmit
+ * of each data buffer. It seems the state machine checks READY earlier then
+ * resetting it after the first transfer.
+ * Using two BDs solves this issue.
+ */
+static void fec_tbd_init(fec_priv *fec)
+{
+ writew(0x0000, &fec->tbd_base[0].status);
+ writew(FEC_TBD_WRAP, &fec->tbd_base[1].status);
+ fec->tbd_index = 0;
+}
+
+/**
+ * Mark the given read buffer descriptor as free
+ * @param[in] last 1 if this is the last buffer descriptor in the chain, else 0
+ * @param[in] pRbd buffer descriptor to mark free again
+ */
+static void fec_rbd_clean(int last, FEC_BD *pRbd)
+{
+ /*
+ * Reset buffer descriptor as empty
+ */
+ if (last)
+ writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &pRbd->status);
+ else
+ writew(FEC_RBD_EMPTY, &pRbd->status);
+ /*
+ * no data in it
+ */
+ writew(0, &pRbd->data_length);
+}
+
+static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac)
+{
+ /* no eeprom */
+ return -1;
+}
+
+static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac)
+{
+ fec_priv *fec = (fec_priv *)dev->priv;
+//#define WTF_IS_THIS
+#ifdef WTF_IS_THIS
+ uint32_t crc = 0xffffffff; /* initial value */
+ uint8_t currByte; /* byte for which to compute the CRC */
+ int byte; /* loop - counter */
+ int bit; /* loop - counter */
+
+ /*
+ * The algorithm used is the following:
+ * we loop on each of the six bytes of the provided address,
+ * and we compute the CRC by left-shifting the previous
+ * value by one position, so that each bit in the current
+ * byte of the address may contribute the calculation. If
+ * the latter and the MSB in the CRC are different, then
+ * the CRC value so computed is also ex-ored with the
+ * "polynomium generator". The current byte of the address
+ * is also shifted right by one bit at each iteration.
+ * This is because the CRC generatore in hardware is implemented
+ * as a shift-register with as many ex-ores as the radixes
+ * in the polynomium. This suggests that we represent the
+ * polynomiumm itself as a 32-bit constant.
+ */
+ for (byte = 0; byte < 6; byte++) {
+ currByte = mac[byte];
+ for (bit = 0; bit < 8; bit++) {
+ if ((currByte & 0x01) ^ (crc & 0x01)) {
+ crc >>= 1;
+ crc = crc ^ 0xedb88320;
+ } else {
+ crc >>= 1;
+ }
+ currByte >>= 1;
+ }
+ }
+
+ crc = crc >> 26;
+
+ /*
+ * Set individual hash table register
+ */
+ if (crc >= 32) {
+ fec->eth->iaddr1 = (1 << (crc - 32));
+ fec->eth->iaddr2 = 0;
+ } else {
+ fec->eth->iaddr1 = 0;
+ fec->eth->iaddr2 = (1 << crc);
+ }
+#else
+ writel(0, &fec->eth->iaddr1);
+ writel(0, &fec->eth->iaddr2);
+ writel(0, &fec->eth->gaddr1);
+ writel(0, &fec->eth->gaddr2);
+#endif
+ /*
+ * Set physical address
+ */
+ writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3], &fec->eth->paddr1);
+ writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fec->eth->paddr2);
+
+ return 0;
+}
+
+static int fec_init(struct eth_device *dev)
+{
+ fec_priv *fec = (fec_priv *)dev->priv;
+
+ /*
+ * Initialize RxBD/TxBD rings
+ */
+ fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);
+ fec_tbd_init(fec);
+
+ /*
+ * Clear FEC-Lite interrupt event register(IEVENT)
+ */
+ writel(0xffffffff, &fec->eth->ievent);
+
+ /*
+ * Set interrupt mask register
+ */
+ writel(0x00000000, &fec->eth->imask);
+
+ /*
+ * Set FEC-Lite receive control register(R_CNTRL):
+ */
+ if (fec->xcv_type == SEVENWIRE) {
+ /*
+ * Frame length=1518; 7-wire mode
+ */
+ writel(0x05ee0020, &fec->eth->r_cntrl); /* FIXME 0x05ee0000 */
+ } else {
+ /*
+ * Frame length=1518; MII mode;
+ */
+ writel(0x05ee0024, &fec->eth->r_cntrl); /* FIXME 0x05ee0004 */
+
+ /*
+ * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
+ * and do not drop the Preamble.
+ */
+ writel(((imx_get_ahbclk() >> 20) / 5) << 1, &fec->eth->mii_speed); /* No MII for 7-wire mode */
+ }
+
+ /*
+ * Set Opcode/Pause Duration Register
+ */
+ writel(0x00010020, &fec->eth->op_pause); /* FIXME 0xffff0020; */
+
+ writel(0x2, &fec->eth->x_wmrk);
+
+ /*
+ * Set multicast address filter
+ */
+ writel(0x00000000, &fec->eth->gaddr1);
+ writel(0x00000000, &fec->eth->gaddr2);
+
+ /* size of each buffer */
+ writel(2048-16, &fec->eth->emrbr); /* ???????????????????? */
+
+ if (fec->xcv_type != SEVENWIRE)
+ miiphy_restart_aneg(&fec->miiphy);
+
+ return 0;
+}
+
+/**
+ * Start the FEC engine
+ * @param[in] dev Our device to handle
+ */
+static int fec_open(struct eth_device *edev)
+{
+ fec_priv *fec = (fec_priv *)edev->priv;
+
+ writel(1 << 2, &fec->eth->x_cntrl); /* full-duplex, heartbeat disabled */
+
+ fec->rbd_index = 0;
+
+ /*
+ * Enable FEC-Lite controller
+ */
+ writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl);
+ /*
+ * Enable SmartDMA receive task
+ */
+ fec_rx_task_enable(fec);
+
+ if (fec->xcv_type != SEVENWIRE) {
+ miiphy_wait_aneg(&fec->miiphy);
+ miiphy_print_status(&fec->miiphy);
+ }
+
+ return 0;
+}
+
+/**
+ * Halt the FEC engine
+ * @param[in] dev Our device to handle
+ */
+static void fec_halt(struct eth_device *dev)
+{
+ fec_priv *fec = (fec_priv *)dev->priv;
+ int counter = 0xffff;
+
+ /*
+ * issue graceful stop command to the FEC transmitter if necessary
+ */
+ writel(FEC_ECNTRL_RESET | readl(&fec->eth->x_cntrl), &fec->eth->x_cntrl);
+
+ /*
+ * wait for graceful stop to register
+ */
+ while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
+ ; /* FIXME ensure time */
+
+ /*
+ * Disable SmartDMA tasks
+ */
+ fec_tx_task_disable(fec);
+ fec_rx_task_disable(fec);
+
+ /*
+ * Disable the Ethernet Controller
+ * Note: this will also reset the BD index counter!
+ */
+ writel(0, &fec->eth->ecntrl);
+ fec->rbd_index = 0;
+ fec->tbd_index = 0;
+}
+
+/**
+ * Transmit one frame
+ * @param[in] dev Our ethernet device to handle
+ * @param[in] eth_data Pointer to the data to be transmitted
+ * @param[in] data_length Data count in bytes
+ * @return 0 on success
+ */
+static int fec_send(struct eth_device *dev, void *eth_data, int data_length)
+{
+ unsigned int status;
+
+ /*
+ * This routine transmits one frame. This routine only accepts
+ * 6-byte Ethernet addresses.
+ */
+ fec_priv *fec = (fec_priv *)dev->priv;
+
+ /*
+ * Check for valid length of data.
+ */
+ if ((data_length > 1500) || (data_length <= 0)) {
+ printf("Payload (%d) to large!\n");
+ return -1;
+ }
+
+ if ((uint32_t)eth_data & 0x0F) {
+ printf("%s: Warning: Transmitt data not aligned!\n", __FUNCTION__);
+ }
+ /*
+ * Setup the transmitt buffer
+ * Note: We are always using the first buffer for transmission,
+ * the second will be empty and only used to stop the DMA engine
+ */
+ writew(data_length, &fec->tbd_base[fec->tbd_index].data_length);
+ writel((uint32_t)eth_data, &fec->tbd_base[fec->tbd_index].data_pointer);
+ /*
+ * update BD's status now
+ * This block:
+ * - is always the last in a chain (means no chain)
+ * - should transmitt the CRC
+ * - might be the last BD in the list, so the address counter should
+ * wrap (-> keep the WRAP flag)
+ */
+ status = readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_WRAP;
+ status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
+ writew(status, &fec->tbd_base[fec->tbd_index].status);
+ /*
+ * Enable SmartDMA transmit task
+ */
+ fec_tx_task_enable(fec);
+
+ /*
+ * wait until frame is sent .
+ */
+ while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) {
+ /* FIXME: Timeout */
+ }
+
+ /* for next transmission use the other buffer */
+ if (fec->tbd_index)
+ fec->tbd_index = 0;
+ else
+ fec->tbd_index = 1;
+
+ return 0;
+}
+
+/**
+ * Pull one frame from the card
+ * @param[in] dev Our ethernet device to handle
+ * @return Length of packet read
+ */
+static int fec_recv(struct eth_device *dev)
+{
+ fec_priv *fec = (fec_priv *)dev->priv;
+ FEC_BD *rbd = &fec->rbd_base[fec->rbd_index];
+ unsigned long ievent;
+ int frame_length, len = 0;
+ NBUF *frame;
+ uint16_t bd_status;
+ uchar buff[FEC_MAX_PKT_SIZE];
+
+ /*
+ * Check if any critical events have happened
+ */
+ ievent = readl(&fec->eth->ievent);
+ writel(ievent, &fec->eth->ievent);
+ if (ievent & (FEC_IEVENT_BABT | FEC_IEVENT_XFIFO_ERROR |
+ FEC_IEVENT_RFIFO_ERROR)) {
+ /* BABT, Rx/Tx FIFO errors */
+ fec_halt(dev);
+ fec_init(dev);
+ printf("some error: 0x%08x\n", ievent);
+ return 0;
+ }
+ if (ievent & FEC_IEVENT_HBERR) {
+ /* Heartbeat error */
+ writel(0x00000001 | readl(&fec->eth->x_cntrl), &fec->eth->x_cntrl);
+ }
+ if (ievent & FEC_IEVENT_GRA) {
+ /* Graceful stop complete */
+ if (readl(&fec->eth->x_cntrl) & 0x00000001) {
+ fec_halt(dev);
+ writel(~0x00000001 & readl(&fec->eth->x_cntrl), &fec->eth->x_cntrl);
+ fec_init(dev);
+ }
+ }
+
+ /*
+ * ensure reading the right buffer status
+ */
+ bd_status = readw(&rbd->status);
+
+ if (!(bd_status & FEC_RBD_EMPTY)) {
+ if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
+ ((readw(&rbd->data_length) - 4) > 14)) {
+ /*
+ * Get buffer address and size
+ */
+ frame = (NBUF *)readl(&rbd->data_pointer);
+ frame_length = readw(&rbd->data_length) - 4;
+ /*
+ * Fill the buffer and pass it to upper layers
+ */
+ memcpy(buff, frame->data, frame_length);
+ NetReceive(buff, frame_length);
+ len = frame_length;
+ } else {
+ if (bd_status & FEC_RBD_ERR) {
+ printf("error frame: 0x%08x 0x%08x\n", rbd, bd_status);
+ }
+ }
+ /*
+ * free the current buffer, restart the engine
+ * and move forward to the next buffer
+ */
+ fec_rbd_clean(fec->rbd_index == (FEC_RBD_NUM - 1) ? 1 : 0, rbd);
+ fec_rx_task_enable(fec);
+ fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM;
+ }
+
+ return len;
+}
+
+int fec_probe(struct device_d *dev)
+{
+ struct fec_platform_data *pdata = (struct fec_platform_data *)dev->platform_data;
+ struct eth_device *edev;
+ fec_priv *fec;
+ uint32_t base;
+
+ PCCR0 |= PCCR0_FEC_EN;
+ edev = (struct eth_device *)malloc(sizeof(struct eth_device));
+ dev->type_data = edev;
+ fec = (fec_priv*)malloc(sizeof(*fec));
+ edev->priv = fec;
+ edev->dev = dev;
+ edev->open = fec_open,
+ edev->init = fec_init,
+ edev->send = fec_send,
+ edev->recv = fec_recv,
+ edev->halt = fec_halt,
+ edev->get_ethaddr = fec_get_hwaddr,
+ edev->set_ethaddr = fec_set_hwaddr,
+
+ fec->eth = (ethernet_regs *)dev->map_base;
+
+ /* Reset chip. */
+ writel(FEC_ECNTRL_RESET, &fec->eth->ecntrl);
+ while(readl(&fec->eth->ecntrl) & 1) {
+ udelay(10);
+ }
+
+ /*
+ * reserve memory for both buffer descriptor chains at once
+ * Datasheet forces the startaddress of each chain is 16 byte aligned
+ */
+ base = (uint32_t)xzalloc( (2 + FEC_RBD_NUM) * sizeof(FEC_BD) + 0x20 );
+ base += 0x0f;
+ base &= ~0x0f;
+ fec->rbd_base = (FEC_BD*)base;
+ base += FEC_RBD_NUM * sizeof(FEC_BD) + 0x0f;
+ base &= ~0x0f;
+ fec->tbd_base = (FEC_BD*)base;
+
+ writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
+ writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);
+
+ fec->xcv_type = pdata->xcv_type;
+
+ sprintf(dev->name, "FEC ETHERNET");
+
+ if (fec->xcv_type != SEVENWIRE) {
+ fec->miiphy.read = fec_miiphy_read;
+ fec->miiphy.write = fec_miiphy_write;
+ fec->miiphy.address = CONFIG_PHY_ADDR;
+ fec->miiphy.flags = pdata->xcv_type == MII10 ? MIIPHY_FORCE_10 : 0;
+ fec->miiphy.edev = edev;
+
+ miiphy_register(&fec->miiphy);
+ }
+
+ eth_register(edev);
+ return 0;
+}
+
+static struct driver_d imx27_driver = {
+ .name = "fec_imx27",
+ .probe = fec_probe,
+ .type = DEVICE_TYPE_ETHER,
+};
+
+static int fec_register(void)
+{
+ register_driver(&imx27_driver);
+ return 0;
+}
+
+device_initcall(fec_register);
+
+/**
+ * @file
+ * @brief Network driver for FreeScale's FEC implementation.
+ * This type of hardware can be found on i.MX27 CPUs
+ */
diff --git a/drivers/net/fec_imx27.h b/drivers/net/fec_imx27.h
new file mode 100644
index 0000000000..b2c4436e1f
--- /dev/null
+++ b/drivers/net/fec_imx27.h
@@ -0,0 +1,336 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on mpc4200fec.h
+ * (C) Copyright Motorola, Inc., 2000
+ *
+ * odin ethernet header file
+ */
+
+#ifndef __IMX27_FEC_H
+#define __IMX27_FEC_H
+
+/*
+typedef unsigned long uint32_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+*/
+
+/**
+ * Layout description of the FEC
+ */
+typedef struct ethernet_register_set {
+
+/* [10:2]addr = 00 */
+
+/* Control and status Registers (offset 000-1FF) */
+
+ uint32_t fec_id; /* MBAR_ETH + 0x000 */
+ uint32_t ievent; /* MBAR_ETH + 0x004 */
+ uint32_t imask; /* MBAR_ETH + 0x008 */
+
+ uint32_t RES0[1]; /* MBAR_ETH + 0x00C */
+ uint32_t r_des_active; /* MBAR_ETH + 0x010 */
+ uint32_t x_des_active; /* MBAR_ETH + 0x014 */
+ uint32_t r_des_active_cl; /* MBAR_ETH + 0x018 */
+ uint32_t x_des_active_cl; /* MBAR_ETH + 0x01C */
+ uint32_t ivent_set; /* MBAR_ETH + 0x020 */
+ uint32_t ecntrl; /* MBAR_ETH + 0x024 */
+
+ uint32_t RES1[6]; /* MBAR_ETH + 0x028-03C */
+ uint32_t mii_data; /* MBAR_ETH + 0x040 */
+ uint32_t mii_speed; /* MBAR_ETH + 0x044 */
+ uint32_t mii_status; /* MBAR_ETH + 0x048 */
+
+ uint32_t RES2[5]; /* MBAR_ETH + 0x04C-05C */
+ uint32_t mib_data; /* MBAR_ETH + 0x060 */
+ uint32_t mib_control; /* MBAR_ETH + 0x064 */
+
+ uint32_t RES3[6]; /* MBAR_ETH + 0x068-7C */
+ uint32_t r_activate; /* MBAR_ETH + 0x080 */
+ uint32_t r_cntrl; /* MBAR_ETH + 0x084 */
+ uint32_t r_hash; /* MBAR_ETH + 0x088 */
+ uint32_t r_data; /* MBAR_ETH + 0x08C */
+ uint32_t ar_done; /* MBAR_ETH + 0x090 */
+ uint32_t r_test; /* MBAR_ETH + 0x094 */
+ uint32_t r_mib; /* MBAR_ETH + 0x098 */
+ uint32_t r_da_low; /* MBAR_ETH + 0x09C */
+ uint32_t r_da_high; /* MBAR_ETH + 0x0A0 */
+
+ uint32_t RES4[7]; /* MBAR_ETH + 0x0A4-0BC */
+ uint32_t x_activate; /* MBAR_ETH + 0x0C0 */
+ uint32_t x_cntrl; /* MBAR_ETH + 0x0C4 */
+ uint32_t backoff; /* MBAR_ETH + 0x0C8 */
+ uint32_t x_data; /* MBAR_ETH + 0x0CC */
+ uint32_t x_status; /* MBAR_ETH + 0x0D0 */
+ uint32_t x_mib; /* MBAR_ETH + 0x0D4 */
+ uint32_t x_test; /* MBAR_ETH + 0x0D8 */
+ uint32_t fdxfc_da1; /* MBAR_ETH + 0x0DC */
+ uint32_t fdxfc_da2; /* MBAR_ETH + 0x0E0 */
+ uint32_t paddr1; /* MBAR_ETH + 0x0E4 */
+ uint32_t paddr2; /* MBAR_ETH + 0x0E8 */
+ uint32_t op_pause; /* MBAR_ETH + 0x0EC */
+
+ uint32_t RES5[4]; /* MBAR_ETH + 0x0F0-0FC */
+ uint32_t instr_reg; /* MBAR_ETH + 0x100 */
+ uint32_t context_reg; /* MBAR_ETH + 0x104 */
+ uint32_t test_cntrl; /* MBAR_ETH + 0x108 */
+ uint32_t acc_reg; /* MBAR_ETH + 0x10C */
+ uint32_t ones; /* MBAR_ETH + 0x110 */
+ uint32_t zeros; /* MBAR_ETH + 0x114 */
+ uint32_t iaddr1; /* MBAR_ETH + 0x118 */
+ uint32_t iaddr2; /* MBAR_ETH + 0x11C */
+ uint32_t gaddr1; /* MBAR_ETH + 0x120 */
+ uint32_t gaddr2; /* MBAR_ETH + 0x124 */
+ uint32_t random; /* MBAR_ETH + 0x128 */
+ uint32_t rand1; /* MBAR_ETH + 0x12C */
+ uint32_t tmp; /* MBAR_ETH + 0x130 */
+
+ uint32_t RES6[3]; /* MBAR_ETH + 0x134-13C */
+ uint32_t fifo_id; /* MBAR_ETH + 0x140 */
+ uint32_t x_wmrk; /* MBAR_ETH + 0x144 */
+ uint32_t fcntrl; /* MBAR_ETH + 0x148 */
+ uint32_t r_bound; /* MBAR_ETH + 0x14C */
+ uint32_t r_fstart; /* MBAR_ETH + 0x150 */
+ uint32_t r_count; /* MBAR_ETH + 0x154 */
+ uint32_t r_lag; /* MBAR_ETH + 0x158 */
+ uint32_t r_read; /* MBAR_ETH + 0x15C */
+ uint32_t r_write; /* MBAR_ETH + 0x160 */
+ uint32_t x_count; /* MBAR_ETH + 0x164 */
+ uint32_t x_lag; /* MBAR_ETH + 0x168 */
+ uint32_t x_retry; /* MBAR_ETH + 0x16C */
+ uint32_t x_write; /* MBAR_ETH + 0x170 */
+ uint32_t x_read; /* MBAR_ETH + 0x174 */
+
+ uint32_t RES7[2]; /* MBAR_ETH + 0x178-17C */
+ uint32_t fm_cntrl; /* MBAR_ETH + 0x180 */
+#define erdsr fm_cntrl
+ uint32_t rfifo_data; /* MBAR_ETH + 0x184 */
+#define etdsr rfifo_data
+ uint32_t rfifo_status; /* MBAR_ETH + 0x188 */
+#define emrbr rfifo_status
+ uint32_t rfifo_cntrl; /* MBAR_ETH + 0x18C */
+ uint32_t rfifo_lrf_ptr; /* MBAR_ETH + 0x190 */
+ uint32_t rfifo_lwf_ptr; /* MBAR_ETH + 0x194 */
+ uint32_t rfifo_alarm; /* MBAR_ETH + 0x198 */
+ uint32_t rfifo_rdptr; /* MBAR_ETH + 0x19C */
+ uint32_t rfifo_wrptr; /* MBAR_ETH + 0x1A0 */
+ uint32_t tfifo_data; /* MBAR_ETH + 0x1A4 */
+ uint32_t tfifo_status; /* MBAR_ETH + 0x1A8 */
+ uint32_t tfifo_cntrl; /* MBAR_ETH + 0x1AC */
+ uint32_t tfifo_lrf_ptr; /* MBAR_ETH + 0x1B0 */
+ uint32_t tfifo_lwf_ptr; /* MBAR_ETH + 0x1B4 */
+ uint32_t tfifo_alarm; /* MBAR_ETH + 0x1B8 */
+ uint32_t tfifo_rdptr; /* MBAR_ETH + 0x1BC */
+ uint32_t tfifo_wrptr; /* MBAR_ETH + 0x1C0 */
+
+ uint32_t reset_cntrl; /* MBAR_ETH + 0x1C4 */
+ uint32_t xmit_fsm; /* MBAR_ETH + 0x1C8 */
+
+ uint32_t RES8[3]; /* MBAR_ETH + 0x1CC-1D4 */
+ uint32_t rdes_data0; /* MBAR_ETH + 0x1D8 */
+ uint32_t rdes_data1; /* MBAR_ETH + 0x1DC */
+ uint32_t r_length; /* MBAR_ETH + 0x1E0 */
+ uint32_t x_length; /* MBAR_ETH + 0x1E4 */
+ uint32_t x_addr; /* MBAR_ETH + 0x1E8 */
+ uint32_t cdes_data; /* MBAR_ETH + 0x1EC */
+ uint32_t status; /* MBAR_ETH + 0x1F0 */
+ uint32_t dma_control; /* MBAR_ETH + 0x1F4 */
+ uint32_t des_cmnd; /* MBAR_ETH + 0x1F8 */
+ uint32_t data; /* MBAR_ETH + 0x1FC */
+
+/* MIB COUNTERS (Offset 200-2FF) */
+
+ uint32_t rmon_t_drop; /* MBAR_ETH + 0x200 */
+ uint32_t rmon_t_packets; /* MBAR_ETH + 0x204 */
+ uint32_t rmon_t_bc_pkt; /* MBAR_ETH + 0x208 */
+ uint32_t rmon_t_mc_pkt; /* MBAR_ETH + 0x20C */
+ uint32_t rmon_t_crc_align; /* MBAR_ETH + 0x210 */
+ uint32_t rmon_t_undersize; /* MBAR_ETH + 0x214 */
+ uint32_t rmon_t_oversize; /* MBAR_ETH + 0x218 */
+ uint32_t rmon_t_frag; /* MBAR_ETH + 0x21C */
+ uint32_t rmon_t_jab; /* MBAR_ETH + 0x220 */
+ uint32_t rmon_t_col; /* MBAR_ETH + 0x224 */
+ uint32_t rmon_t_p64; /* MBAR_ETH + 0x228 */
+ uint32_t rmon_t_p65to127; /* MBAR_ETH + 0x22C */
+ uint32_t rmon_t_p128to255; /* MBAR_ETH + 0x230 */
+ uint32_t rmon_t_p256to511; /* MBAR_ETH + 0x234 */
+ uint32_t rmon_t_p512to1023; /* MBAR_ETH + 0x238 */
+ uint32_t rmon_t_p1024to2047; /* MBAR_ETH + 0x23C */
+ uint32_t rmon_t_p_gte2048; /* MBAR_ETH + 0x240 */
+ uint32_t rmon_t_octets; /* MBAR_ETH + 0x244 */
+ uint32_t ieee_t_drop; /* MBAR_ETH + 0x248 */
+ uint32_t ieee_t_frame_ok; /* MBAR_ETH + 0x24C */
+ uint32_t ieee_t_1col; /* MBAR_ETH + 0x250 */
+ uint32_t ieee_t_mcol; /* MBAR_ETH + 0x254 */
+ uint32_t ieee_t_def; /* MBAR_ETH + 0x258 */
+ uint32_t ieee_t_lcol; /* MBAR_ETH + 0x25C */
+ uint32_t ieee_t_excol; /* MBAR_ETH + 0x260 */
+ uint32_t ieee_t_macerr; /* MBAR_ETH + 0x264 */
+ uint32_t ieee_t_cserr; /* MBAR_ETH + 0x268 */
+ uint32_t ieee_t_sqe; /* MBAR_ETH + 0x26C */
+ uint32_t t_fdxfc; /* MBAR_ETH + 0x270 */
+ uint32_t ieee_t_octets_ok; /* MBAR_ETH + 0x274 */
+
+ uint32_t RES9[2]; /* MBAR_ETH + 0x278-27C */
+ uint32_t rmon_r_drop; /* MBAR_ETH + 0x280 */
+ uint32_t rmon_r_packets; /* MBAR_ETH + 0x284 */
+ uint32_t rmon_r_bc_pkt; /* MBAR_ETH + 0x288 */
+ uint32_t rmon_r_mc_pkt; /* MBAR_ETH + 0x28C */
+ uint32_t rmon_r_crc_align; /* MBAR_ETH + 0x290 */
+ uint32_t rmon_r_undersize; /* MBAR_ETH + 0x294 */
+ uint32_t rmon_r_oversize; /* MBAR_ETH + 0x298 */
+ uint32_t rmon_r_frag; /* MBAR_ETH + 0x29C */
+ uint32_t rmon_r_jab; /* MBAR_ETH + 0x2A0 */
+
+ uint32_t rmon_r_resvd_0; /* MBAR_ETH + 0x2A4 */
+
+ uint32_t rmon_r_p64; /* MBAR_ETH + 0x2A8 */
+ uint32_t rmon_r_p65to127; /* MBAR_ETH + 0x2AC */
+ uint32_t rmon_r_p128to255; /* MBAR_ETH + 0x2B0 */
+ uint32_t rmon_r_p256to511; /* MBAR_ETH + 0x2B4 */
+ uint32_t rmon_r_p512to1023; /* MBAR_ETH + 0x2B8 */
+ uint32_t rmon_r_p1024to2047; /* MBAR_ETH + 0x2BC */
+ uint32_t rmon_r_p_gte2048; /* MBAR_ETH + 0x2C0 */
+ uint32_t rmon_r_octets; /* MBAR_ETH + 0x2C4 */
+ uint32_t ieee_r_drop; /* MBAR_ETH + 0x2C8 */
+ uint32_t ieee_r_frame_ok; /* MBAR_ETH + 0x2CC */
+ uint32_t ieee_r_crc; /* MBAR_ETH + 0x2D0 */
+ uint32_t ieee_r_align; /* MBAR_ETH + 0x2D4 */
+ uint32_t r_macerr; /* MBAR_ETH + 0x2D8 */
+ uint32_t r_fdxfc; /* MBAR_ETH + 0x2DC */
+ uint32_t ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
+
+ uint32_t RES10[6]; /* MBAR_ETH + 0x2E4-2FC */
+
+ uint32_t RES11[64]; /* MBAR_ETH + 0x300-3FF */
+} ethernet_regs;
+
+#define FEC_IEVENT_HBERR 0x80000000
+#define FEC_IEVENT_BABR 0x40000000
+#define FEC_IEVENT_BABT 0x20000000
+#define FEC_IEVENT_GRA 0x10000000
+#define FEC_IEVENT_TFINT 0x08000000
+#define FEC_IEVENT_MII 0x00800000
+#define FEC_IEVENT_LATE_COL 0x00200000
+#define FEC_IEVENT_COL_RETRY_LIM 0x00100000
+#define FEC_IEVENT_XFIFO_UN 0x00080000
+#define FEC_IEVENT_XFIFO_ERROR 0x00040000
+#define FEC_IEVENT_RFIFO_ERROR 0x00020000
+
+#define FEC_IMASK_HBERR 0x80000000
+#define FEC_IMASK_BABR 0x40000000
+#define FEC_IMASK_BABT 0x20000000
+#define FEC_IMASK_GRA 0x10000000
+#define FEC_IMASK_MII 0x00800000
+#define FEC_IMASK_LATE_COL 0x00200000
+#define FEC_IMASK_COL_RETRY_LIM 0x00100000
+#define FEC_IMASK_XFIFO_UN 0x00080000
+#define FEC_IMASK_XFIFO_ERROR 0x00040000
+#define FEC_IMASK_RFIFO_ERROR 0x00020000
+
+#define FEC_RCNTRL_MAX_FL_SHIFT 16
+#define FEC_RCNTRL_LOOP 0x01
+#define FEC_RCNTRL_DRT 0x02
+#define FEC_RCNTRL_MII_MODE 0x04
+#define FEC_RCNTRL_PROM 0x08
+#define FEC_RCNTRL_BC_REJ 0x10
+#define FEC_RCNTRL_FCE 0x20
+
+#define FEC_TCNTRL_GTS 0x00000001
+#define FEC_TCNTRL_HBC 0x00000002
+#define FEC_TCNTRL_FDEN 0x00000004
+#define FEC_TCNTRL_TFC_PAUSE 0x00000008
+#define FEC_TCNTRL_RFC_PAUSE 0x00000010
+
+#define FEC_ECNTRL_RESET 0x00000001
+#define FEC_ECNTRL_ETHER_EN 0x00000002
+
+/**
+ * Receive & Transmit Buffer Descriptor definitions
+ * Little endian layout
+ */
+typedef struct buffer_descriptor {
+ uint16_t data_length;
+ uint16_t status;
+ uint32_t data_pointer;
+} FEC_BD;
+
+/**
+ * private structure
+ */
+typedef struct {
+ ethernet_regs *eth;
+ xceiver_type xcv_type; /** transceiver type */
+ FEC_BD *rbd_base; /** RBD ring */
+ int rbd_index; /** next receive BD to read */
+ FEC_BD *tbd_base; /** TBD ring */
+ int tbd_index; /** next transmit BD to write */
+ struct miiphy_device miiphy;
+} fec_priv;
+
+/**
+ * buffer alignment on request
+ */
+#define RDB_ALIGNMENT 16
+
+/* Ethernet parameter area */
+#define FEC_TBD_BASE (FEC_PARAM_BASE + 0x00)
+#define FEC_TBD_NEXT (FEC_PARAM_BASE + 0x04)
+#define FEC_RBD_BASE (FEC_PARAM_BASE + 0x08)
+#define FEC_RBD_NEXT (FEC_PARAM_BASE + 0x0c)
+
+/**
+ * Numbers of buffer descriptos for receiving
+ */
+#define FEC_RBD_NUM 64 /* The user can adjust this value */
+
+/**
+ * define the packet size limit
+ */
+#define FEC_MAX_PKT_SIZE 1536
+
+/* RBD bits definitions */
+#define FEC_RBD_EMPTY 0x8000 /* Buffer is empty */
+#define FEC_RBD_WRAP 0x2000 /* Last BD in ring */
+#define FEC_RBD_INT 0x1000 /* Interrupt */
+#define FEC_RBD_LAST 0x0800 /* Buffer is last in frame(useless) */
+#define FEC_RBD_MISS 0x0100 /* Miss bit for prom mode */
+#define FEC_RBD_BC 0x0080 /* The received frame is broadcast frame */
+#define FEC_RBD_MC 0x0040 /* The received frame is multicast frame */
+#define FEC_RBD_LG 0x0020 /* Frame length violation */
+#define FEC_RBD_NO 0x0010 /* Nonoctet align frame */
+#define FEC_RBD_SH 0x0008 /* Short frame */
+#define FEC_RBD_CR 0x0004 /* CRC error */
+#define FEC_RBD_OV 0x0002 /* Receive FIFO overrun */
+#define FEC_RBD_TR 0x0001 /* Frame is truncated */
+#define FEC_RBD_ERR (FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \
+ FEC_RBD_OV | FEC_RBD_TR)
+
+/* TBD bits definitions */
+#define FEC_TBD_READY 0x8000 /* Buffer is ready */
+#define FEC_TBD_WRAP 0x2000 /* Last BD in ring */
+#define FEC_TBD_INT 0x1000 /* Interrupt */
+#define FEC_TBD_LAST 0x0800 /* Buffer is last in frame */
+#define FEC_TBD_TC 0x0400 /* Transmit the CRC */
+#define FEC_TBD_ABC 0x0200 /* Append bad CRC */
+
+/* MII-related definitios */
+#define FEC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */
+#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */
+#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */
+#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */
+#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */
+#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */
+#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */
+
+#define FEC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */
+#define FEC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */
+
+#endif /* __IMX27_FEC_H */
+
+/**
+ * @file
+ * @brief Definitions for the FEC driver (i.MX27)
+ */
diff --git a/drivers/net/fec_mpc5200.c b/drivers/net/fec_mpc5200.c
index 41c191f812..39c3f132db 100644
--- a/drivers/net/fec_mpc5200.c
+++ b/drivers/net/fec_mpc5200.c
@@ -4,21 +4,53 @@
*
* This file is based on mpc4200fec.c,
* (C) Copyright Motorola, Inc., 2000
+ *
+ * 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
*/
+#define DEBUG
+
#include <common.h>
-#include <asm/arch/mpc5xxx.h>
+//#include <asm/arch/mpc5xxx.h>
#include <malloc.h>
#include <net.h>
#include <init.h>
#include <miiphy.h>
#include <driver.h>
-#include <asm/arch/sdma.h>
-#include <asm/arch/fec.h>
-#include <asm/arch/clocks.h>
+//#include <asm/arch/sdma.h>
+//#include <asm/arch/fec.h>
+#include <asm-ppc/arch-mpc5200/fec.h>
+//#include <asm/arch/clocks.h>
#include <miiphy.h>
#include "fec_mpc5200.h"
+#include <asm/io.h>
+
+#ifdef CONFIG_ARCH_IMX27
+#include <asm/arch/imx-regs.h>
+#include <clock.h>
+#include <asm/arch/clock.h>
+#include <xfuncs.h>
+#endif
+
+extern int memory_display(char *addr, ulong offs, ulong nbytes, int size);
+
#define CONFIG_PHY_ADDR 1 /* FIXME */
typedef struct {
@@ -39,36 +71,38 @@ static int fec5xxx_miiphy_read(struct miiphy_device *mdev, uint8_t phyAddr,
uint32 reg; /* convenient holder for the PHY register */
uint32 phy; /* convenient holder for the PHY */
- int timeout = 0xffff;
+ uint64_t start;
/*
* reading from any PHY's register is done by properly
* programming the FEC's MII data register.
*/
+ writel(FEC_IEVENT_MII, &fec->eth->ievent);
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
- fec->eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg);
+ writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg, &fec->eth->mii_data);
/*
* wait for the related interrupt
*/
- while ((timeout--) && (!(fec->eth->ievent & FEC_IEVENT_MII))) ;
-
- if (timeout == 0) {
- debug("Read MDIO failed...\n");
- return -1;
+ start = get_time_ns();
+ while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+ if (is_timeout(start, MSECOND)) {
+ printf("Read MDIO failed...\n");
+ return -1;
+ }
}
/*
* clear mii interrupt bit
*/
- fec->eth->ievent = FEC_IEVENT_MII;
+ writel(FEC_IEVENT_MII, &fec->eth->ievent);
/*
* it's now safe to read the PHY's register
*/
- *retVal = (uint16) fec->eth->mii_data;
+ *retVal = readl(&fec->eth->mii_data);
return 0;
}
@@ -81,148 +115,171 @@ static int fec5xxx_miiphy_write(struct miiphy_device *mdev, uint8_t phyAddr,
uint32 reg; /* convenient holder for the PHY register */
uint32 phy; /* convenient holder for the PHY */
- int timeout = 0xffff;
+ uint64_t start;
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
- fec->eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
- FEC_MII_DATA_TA | phy | reg | data);
+ writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
+ FEC_MII_DATA_TA | phy | reg | data, &fec->eth->mii_data);
/*
* wait for the MII interrupt
*/
- while ((timeout--) && (!(fec->eth->ievent & FEC_IEVENT_MII))) ;
-
- if (timeout == 0) {
- debug("Write MDIO failed...\n");
- return -1;
+ start = get_time_ns();
+ while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+ if (is_timeout(start, MSECOND)) {
+ printf("Write MDIO failed...\n");
+ return -1;
+ }
}
/*
* clear MII interrupt bit
*/
- fec->eth->ievent = FEC_IEVENT_MII;
+ writel(FEC_IEVENT_MII, &fec->eth->ievent);
+
+ return 0;
+}
+
+#ifdef CONFIG_MPC5200
+static int mpc5xxx_fec_rx_task_enable(mpc5xxx_fec_priv *fec)
+{
+ SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
+ return 0;
+}
+
+static int mpc5xxx_fec_rx_task_disable(mpc5xxx_fec_priv *fec)
+{
+ SDMA_TASK_DISABLE(FEC_RECV_TASK_NO);
+ return 0;
+}
+
+static int mpc5xxx_fec_tx_task_enable(mpc5xxx_fec_priv *fec)
+{
+ SDMA_TASK_ENABLE(FEC_XMIT_TASK_NO);
+ return 0;
+}
+
+static int mpc5xxx_fec_tx_task_disable(mpc5xxx_fec_priv *fec)
+{
+ SDMA_TASK_DISABLE(FEC_XMIT_TASK_NO);
+ return 0;
+}
+#endif
+#ifdef CONFIG_ARCH_IMX27
+static int mpc5xxx_fec_rx_task_enable(mpc5xxx_fec_priv *fec)
+{
+ writel(1 << 24, &fec->eth->r_des_active);
return 0;
}
-static int mpc5xxx_fec_rbd_init(mpc5xxx_fec_priv *fec)
+static int mpc5xxx_fec_rx_task_disable(mpc5xxx_fec_priv *fec)
+{
+ return 0;
+}
+
+static int mpc5xxx_fec_tx_task_enable(mpc5xxx_fec_priv *fec)
+{
+ writel(1 << 24, &fec->eth->x_des_active);
+ return 0;
+}
+
+static int mpc5xxx_fec_tx_task_disable(mpc5xxx_fec_priv *fec)
+{
+ return 0;
+}
+#endif
+
+/**
+ * allocate and link buffers for the receive task
+ * @param[in] fec all we know about the device yet
+ * @param[in] count receive buffer count to be allocated
+ * @param[in] size size of each receive buffer
+ * @return 0 on success
+ *
+ * We need some alignment for the buffers. Thy must be
+ * aligned to a specific boundary each. See RDB_ALIGNMENT
+ */
+static int mpc5xxx_fec_rbd_init(mpc5xxx_fec_priv *fec, int count, int size)
{
int ix;
- char *data;
static int once = 0;
+ uint32 p;
+
+ printf("%s\n", __FUNCTION__);
- for (ix = 0; ix < FEC_RBD_NUM; ix++) {
+ size += RDB_ALIGNMENT; /* enlarge the size for alignment */
+
+ for (ix = 0; ix < count; ix++) {
if (!once) {
- data = (char *)malloc(FEC_MAX_PKT_SIZE);
- if (data == NULL) {
- printf ("RBD INIT FAILED\n");
- return -1;
- }
- fec->rbdBase[ix].dataPointer = (uint32)data;
+ p = (uint32)xzalloc(size);
+ p += RDB_ALIGNMENT - 1;
+ p &= ~(RDB_ALIGNMENT - 1);
+ writel(p, &fec->rbdBase[ix].dataPointer);
}
- fec->rbdBase[ix].status = FEC_RBD_EMPTY;
- fec->rbdBase[ix].dataLength = 0;
+ writew(FEC_RBD_EMPTY, &fec->rbdBase[ix].status);
+ writew(0, &fec->rbdBase[ix].dataLength);
}
once ++;
/*
* have the last RBD to close the ring
*/
- fec->rbdBase[ix - 1].status |= FEC_RBD_WRAP;
+ writew(FEC_RBD_WRAP | readl(&fec->rbdBase[ix - 1].status), &fec->rbdBase[ix - 1].status);
fec->rbdIndex = 0;
return 0;
}
+/**
+ * initialize buffers for the transmit task
+ * @param[in] fec all we know about the device yet
+ *
+ * Nothing special here to do. We ony using one bufffer
+ * for all transmit operations.
+ */
static void mpc5xxx_fec_tbd_init(mpc5xxx_fec_priv *fec)
{
- int ix;
-
- for (ix = 0; ix < FEC_TBD_NUM; ix++) {
- fec->tbdBase[ix].status = 0;
- }
-
- /*
- * Have the last TBD to close the ring
- */
- fec->tbdBase[ix - 1].status |= FEC_TBD_WRAP;
-
- /*
- * Initialize some indices
- */
- fec->tbdIndex = 0;
- fec->usedTbdIndex = 0;
- fec->cleanTbdNum = FEC_TBD_NUM;
+ writew(FEC_TBD_WRAP, &fec->tbdBase[0].status);
}
-static void mpc5xxx_fec_rbd_clean(mpc5xxx_fec_priv *fec, volatile FEC_RBD * pRbd)
+/**
+ * Mark the given read buffer descriptor as free
+ * @param[in] last 1 if this is the last buffer descriptor in the chain, else 0
+ * @param[in] pRbd buffer descriptor to mark free again
+ */
+static void mpc5xxx_fec_rbd_clean(int last, FEC_RBD *pRbd)
{
/*
* Reset buffer descriptor as empty
*/
- if ((fec->rbdIndex) == (FEC_RBD_NUM - 1))
- pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY);
+ if (last)
+ writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &pRbd->status);
else
- pRbd->status = FEC_RBD_EMPTY;
-
- pRbd->dataLength = 0;
-
- /*
- * Now, we have an empty RxBD, restart the SmartDMA receive task
- */
- SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
-
- /*
- * Increment BD count
- */
- fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
-}
-
-static void mpc5xxx_fec_tbd_scrub(mpc5xxx_fec_priv *fec)
-{
- volatile FEC_TBD *pUsedTbd;
-
+ writew(FEC_RBD_EMPTY, &pRbd->status);
/*
- * process all the consumed TBDs
+ * no data in it
*/
- while (fec->cleanTbdNum < FEC_TBD_NUM) {
- pUsedTbd = &fec->tbdBase[fec->usedTbdIndex];
- if (pUsedTbd->status & FEC_TBD_READY) {
- debug("Cannot clean TBD %d, in use\n", fec->cleanTbdNum);
- return;
- }
-
- /*
- * clean this buffer descriptor
- */
- if (fec->usedTbdIndex == (FEC_TBD_NUM - 1))
- pUsedTbd->status = FEC_TBD_WRAP;
- else
- pUsedTbd->status = 0;
-
- /*
- * update some indeces for a correct handling of the TBD ring
- */
- fec->cleanTbdNum++;
- fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM;
- }
+ writew(0, &pRbd->dataLength);
}
-static int mpc5xxx_fec_get_ethaddr(struct eth_device *dev, unsigned char *mac)
+static int mpc5xxx_fec_get_hwaddr(struct eth_device *dev, unsigned char *mac)
{
/* no eeprom */
return -1;
}
-static int mpc5xxx_fec_set_ethaddr(struct eth_device *dev, unsigned char *mac)
+static int mpc5xxx_fec_set_hwaddr(struct eth_device *dev, unsigned char *mac)
{
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
+//#define WTF_IS_THIS
+#ifdef WTF_IS_THIS
+ uint32 crc = 0xffffffff; /* initial value */
uint8 currByte; /* byte for which to compute the CRC */
int byte; /* loop - counter */
int bit; /* loop - counter */
- uint32 crc = 0xffffffff; /* initial value */
/*
* The algorithm used is the following:
@@ -264,12 +321,17 @@ static int mpc5xxx_fec_set_ethaddr(struct eth_device *dev, unsigned char *mac)
fec->eth->iaddr1 = 0;
fec->eth->iaddr2 = (1 << crc);
}
-
+#else
+ writel(0, &fec->eth->iaddr1);
+ writel(0, &fec->eth->iaddr2);
+ writel(0, &fec->eth->gaddr1);
+ writel(0, &fec->eth->gaddr2);
+#endif
/*
* Set physical address
*/
- fec->eth->paddr1 = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
- fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
+ writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3], &fec->eth->paddr1);
+ writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fec->eth->paddr2);
return 0;
}
@@ -277,25 +339,26 @@ static int mpc5xxx_fec_set_ethaddr(struct eth_device *dev, unsigned char *mac)
static int mpc5xxx_fec_init(struct eth_device *dev)
{
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
+#ifdef CONFIG_MPC5200
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
-
+#endif
debug("mpc5xxx_fec_init... Begin\n");
/*
* Initialize RxBD/TxBD rings
*/
- mpc5xxx_fec_rbd_init(fec);
+ mpc5xxx_fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);
mpc5xxx_fec_tbd_init(fec);
/*
* Clear FEC-Lite interrupt event register(IEVENT)
*/
- fec->eth->ievent = 0xffffffff;
+ writel(0xffffffff, &fec->eth->ievent);
/*
* Set interrupt mask register
*/
- fec->eth->imask = 0x00000000;
+ writel(0x00000000, &fec->eth->imask);
/*
* Set FEC-Lite receive control register(R_CNTRL):
@@ -304,84 +367,94 @@ static int mpc5xxx_fec_init(struct eth_device *dev)
/*
* Frame length=1518; 7-wire mode
*/
- fec->eth->r_cntrl = 0x05ee0020; /*0x05ee0000;FIXME */
+ writel(0x05ee0020, &fec->eth->r_cntrl); /* FIXME 0x05ee0000 */
} else {
/*
* Frame length=1518; MII mode;
*/
- fec->eth->r_cntrl = 0x05ee0024; /*0x05ee0004;FIXME */
- }
+ writel(0x05ee0024, &fec->eth->r_cntrl); /* FIXME 0x05ee0004 */
- if (fec->xcv_type != SEVENWIRE) {
/*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
* and do not drop the Preamble.
*/
- fec->eth->mii_speed = (((get_ipb_clock() >> 20) / 5) << 1); /* No MII for 7-wire mode */
+#ifdef CONFIG_MPC5200
+ writel(((get_ipb_clock() >> 20) / 5) << 1, &fec->eth->mii_speed); /* No MII for 7-wire mode */
+#endif
+#ifdef CONFIG_ARCH_IMX27
+ writel(((imx_get_ahbclk() >> 20) / 5) << 1, &fec->eth->mii_speed); /* No MII for 7-wire mode */
+#endif
}
/*
* Set Opcode/Pause Duration Register
*/
- fec->eth->op_pause = 0x00010020; /*FIXME 0xffff0020; */
+ writel(0x00010020, &fec->eth->op_pause); /* FIXME 0xffff0020; */
+#ifdef CONFIG_MPC5200
/*
* Set Rx FIFO alarm and granularity value
*/
- fec->eth->rfifo_cntrl = 0x0c000000
- | (fec->eth->rfifo_cntrl & ~0x0f000000);
- fec->eth->rfifo_alarm = 0x0000030c;
+ writel(0x0c000000 | (readl(&fec->eth->rfifo_cntrl) & ~0x0f000000)), &fec->eth->rfifo_cntrl);
+ writel(0x0000030c, &fec->eth->rfifo_alarm);
- if (fec->eth->rfifo_status & 0x00700000 ) {
+ if (readl(&fec->eth->rfifo_status) & 0x00700000 ) {
debug("mpc5xxx_fec_init() RFIFO error\n");
}
/*
* Set Tx FIFO granularity value
*/
- fec->eth->tfifo_cntrl = 0x0c000000
- | (fec->eth->tfifo_cntrl & ~0x0f000000);
+ writel(0x0c000000 | (readl(&fec->eth->tfifo_cntrl)& ~0x0f000000), &fec->eth->tfifo_cntrl);
- debug("tfifo_status: 0x%08x\n", fec->eth->tfifo_status);
- debug("tfifo_alarm: 0x%08x\n", fec->eth->tfifo_alarm);
+ debug("tfifo_status: 0x%08x\n", readl(&fec->eth->tfifo_status));
+ debug("tfifo_alarm: 0x%08x\n", readl(&fec->eth->tfifo_alarm));
/*
* Set transmit fifo watermark register(X_WMRK), default = 64
*/
- fec->eth->tfifo_alarm = 0x00000080;
- fec->eth->x_wmrk = 0x2;
+ writel(0x00000080, &fec->eth->tfifo_alarm);
/*
- * Set multicast address filter
+ * Turn ON cheater FSM: ????
*/
- fec->eth->gaddr1 = 0x00000000;
- fec->eth->gaddr2 = 0x00000000;
+ writel(0x03000000, &fec->eth->xmit_fsm);
+#endif
+
+ writel(0x2, &fec->eth->x_wmrk);
/*
- * Turn ON cheater FSM: ????
+ * Set multicast address filter
*/
- fec->eth->xmit_fsm = 0x03000000;
+ writel(0x00000000, &fec->eth->gaddr1);
+ writel(0x00000000, &fec->eth->gaddr2);
+#ifdef CONFIG_MPC5200
/*
* Set priority of different initiators
*/
sdma->IPR0 = 7; /* always */
sdma->IPR3 = 6; /* Eth RX */
sdma->IPR4 = 5; /* Eth Tx */
+#endif
+#ifdef CONFIG_ARCH_IMX27
+ writel(2048-16, &fec->eth->emrbr);
+#endif
/*
* Clear SmartDMA task interrupt pending bits
*/
- SDMA_CLEAR_IEVENT(FEC_RECV_TASK_NO);
+// SDMA_CLEAR_IEVENT(FEC_RECV_TASK_NO);
/*
* Initialize SmartDMA parameters stored in SRAM
*/
+#ifdef CONFIG_MPC5200
*(volatile int *)FEC_TBD_BASE = (int)fec->tbdBase;
*(volatile int *)FEC_RBD_BASE = (int)fec->rbdBase;
*(volatile int *)FEC_TBD_NEXT = (int)fec->tbdBase;
*(volatile int *)FEC_RBD_NEXT = (int)fec->rbdBase;
-
+#endif
debug("mpc5xxx_fec_init... Done \n");
if (fec->xcv_type != SEVENWIRE)
@@ -394,6 +467,8 @@ static int mpc5xxx_fec_open(struct eth_device *edev)
{
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)edev->priv;
+ printf("%s\n", __FUNCTION__);
+
#if defined(CONFIG_MPC5200)
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
/*
@@ -403,17 +478,27 @@ static int mpc5xxx_fec_open(struct eth_device *edev)
sdma->PtdCntrl |= 0x00000001;
#endif
- fec->eth->x_cntrl = 0x00000000; /* half-duplex, heartbeat disabled */
+#if 0
+ writel(0x00000000, &fec->eth->x_cntrl); /* half-duplex, heartbeat disabled */
+#else
+ writel(1 << 2, &fec->eth->x_cntrl); /* full-duplex, heartbeat disabled */
+#endif
+
+ fec->rbdIndex = 0;
/*
* Enable FEC-Lite controller
*/
- fec->eth->ecntrl |= 0x00000006;
-
+#if defined(CONFIG_MPC5200)
+ writel(0x00000006 | readl(&fec->eth->ecntrl), &fec->eth->ecntrl);
+#endif
+#if defined(CONFIG_ARCH_IMX27)
+ writel(0x00000002 | readl(&fec->eth->ecntrl), &fec->eth->ecntrl);
+#endif
/*
* Enable SmartDMA receive task
*/
- SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
+ mpc5xxx_fec_rx_task_enable(fec);
if (fec->xcv_type != SEVENWIRE) {
miiphy_wait_aneg(&fec->miiphy);
@@ -434,20 +519,21 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)
/*
* issue graceful stop command to the FEC transmitter if necessary
*/
- fec->eth->x_cntrl |= 0x00000001;
+ writel(0x00000001 | readl(&fec->eth->x_cntrl), &fec->eth->x_cntrl);
/*
* wait for graceful stop to register
*/
- while ((counter--) && (!(fec->eth->ievent & FEC_IEVENT_GRA))) ;
+ while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
+ ;
/*
* Disable SmartDMA tasks
*/
- SDMA_TASK_DISABLE (FEC_XMIT_TASK_NO);
- SDMA_TASK_DISABLE (FEC_RECV_TASK_NO);
+ mpc5xxx_fec_tx_task_disable(fec);
+ mpc5xxx_fec_rx_task_disable(fec);
-#if defined(CONFIG_MPC5200)
+#ifdef CONFIG_MPC5200
/*
* Turn on COMM bus prefetch in the MGT5200 BestComm after we're
* done. It doesn't work w/ the current receive task.
@@ -458,15 +544,17 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)
/*
* Disable the Ethernet Controller
*/
- fec->eth->ecntrl &= 0xfffffffd;
+ writel(0, &fec->eth->ecntrl);
+#ifdef CONFIG_MPC5200
/*
* Clear FIFO status registers
*/
- fec->eth->rfifo_status &= 0x00700000;
- fec->eth->tfifo_status &= 0x00700000;
+ writel(0x00700000 & readl(&fec->eth->rfifo_status), &fec->eth->rfifo_status);
+ writel(0x00700000 & readl(&fec->eth->tfifo_status), &fec->eth->tfifo_status);
+#endif
-// fec->eth->reset_cntrl = 0x01000000;
+// writel(0x01000000, &fec->eth->reset_cntrl);
debug("Ethernet task stopped\n");
}
@@ -474,39 +562,39 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)
#ifdef DEBUG_FIFO
static void tfifo_print(char *devname, mpc5xxx_fec_priv *fec)
{
- if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
- || (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
-
- printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
- printf("ievent: 0x%08x\n", fec->eth->ievent);
- printf("x_status: 0x%08x\n", fec->eth->x_status);
- printf("tfifo: status 0x%08x\n", fec->eth->tfifo_status);
-
- printf(" control 0x%08x\n", fec->eth->tfifo_cntrl);
- printf(" lrfp 0x%08x\n", fec->eth->tfifo_lrf_ptr);
- printf(" lwfp 0x%08x\n", fec->eth->tfifo_lwf_ptr);
- printf(" alarm 0x%08x\n", fec->eth->tfifo_alarm);
- printf(" readptr 0x%08x\n", fec->eth->tfifo_rdptr);
- printf(" writptr 0x%08x\n", fec->eth->tfifo_wrptr);
+ if ((readl(&fec->eth->tfifo_lrf_ptr) != readl(&fec->eth->tfifo_lwf_ptr))
+ || (readl(&fec->eth->tfifo_rdptr) != readl(&fec->eth->tfifo_wrptr))) {
+
+ printf("ecntrl: 0x%08x\n", readl(&fec->eth->ecntrl));
+ printf("ievent: 0x%08x\n", readl(&fec->eth->ievent));
+ printf("x_status: 0x%08x\n", readl(&fec->eth->x_status));
+ printf("tfifo: status 0x%08x\n", readl(&fec->eth->tfifo_status));
+
+ printf(" control 0x%08x\n", readl(&fec->eth->tfifo_cntrl));
+ printf(" lrfp 0x%08x\n", readl(&fec->eth->tfifo_lrf_ptr));
+ printf(" lwfp 0x%08x\n", readl(&fec->eth->tfifo_lwf_ptr));
+ printf(" alarm 0x%08x\n", readl(&fec->eth->tfifo_alarm));
+ printf(" readptr 0x%08x\n", readl(&fec->eth->tfifo_rdptr));
+ printf(" writptr 0x%08x\n", readl(&fec->eth->tfifo_wrptr));
}
}
static void rfifo_print(char *devname, mpc5xxx_fec_priv *fec)
{
- if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
- || (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
-
- printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
- printf("ievent: 0x%08x\n", fec->eth->ievent);
- printf("x_status: 0x%08x\n", fec->eth->x_status);
- printf("rfifo: status 0x%08x\n", fec->eth->rfifo_status);
-
- printf(" control 0x%08x\n", fec->eth->rfifo_cntrl);
- printf(" lrfp 0x%08x\n", fec->eth->rfifo_lrf_ptr);
- printf(" lwfp 0x%08x\n", fec->eth->rfifo_lwf_ptr);
- printf(" alarm 0x%08x\n", fec->eth->rfifo_alarm);
- printf(" readptr 0x%08x\n", fec->eth->rfifo_rdptr);
- printf(" writptr 0x%08x\n", fec->eth->rfifo_wrptr);
+ if ((readl(&fec->eth->rfifo_lrf_ptr) != readl(&fec->eth->rfifo_lwf_ptr))
+ || (readl(&fec->eth->rfifo_rdptr) != readl(&fec->eth->rfifo_wrptr))) {
+
+ printf("ecntrl: 0x%08x\n", readl(&fec->eth->ecntrl));
+ printf("ievent: 0x%08x\n", readl(&fec->eth->ievent));
+ printf("x_status: 0x%08x\n", readl(&fec->eth->x_status));
+ printf("rfifo: status 0x%08x\n", readl(&fec->eth->rfifo_status));
+
+ printf(" control 0x%08x\n", readl(&fec->eth->rfifo_cntrl));
+ printf(" lrfp 0x%08x\n", readl(&fec->eth->rfifo_lrf_ptr));
+ printf(" lwfp 0x%08x\n", readl(&fec->eth->rfifo_lwf_ptr));
+ printf(" alarm 0x%08x\n", readl(&fec->eth->rfifo_alarm));
+ printf(" readptr 0x%08x\n", readl(&fec->eth->rfifo_rdptr));
+ printf(" writptr 0x%08x\n", readl(&fec->eth->rfifo_wrptr));
}
}
#else
@@ -514,7 +602,7 @@ static void tfifo_print(char *devname, mpc5xxx_fec_priv *fec)
{
}
-static void rfifo_print(char *devname, mpc5xxx_fec_priv *fec)
+static void __maybe_unused rfifo_print(char *devname, mpc5xxx_fec_priv *fec)
{
}
#endif /* DEBUG_FIFO */
@@ -529,16 +617,13 @@ static int mpc5xxx_fec_send(struct eth_device *dev, void *eth_data,
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
volatile FEC_TBD *pTbd;
+// printf("%s length=%d data=0x%08x\n", __FUNCTION__, data_length, eth_data);
+
#ifdef DEBUG_FIFO
debug_fifo("tbd status: 0x%04x\n", fec->tbdBase[0].status);
tfifo_print(dev->name, fec);
#endif
/*
- * Clear Tx BD ring at first
- */
- mpc5xxx_fec_tbd_scrub(fec);
-
- /*
* Check for valid length of data.
*/
if ((data_length > 1500) || (data_length <= 0)) {
@@ -546,41 +631,17 @@ static int mpc5xxx_fec_send(struct eth_device *dev, void *eth_data,
}
/*
- * Check the number of vacant TxBDs.
- */
- if (fec->cleanTbdNum < 1) {
- printf("No available TxBDs ...\n");
- return -1;
- }
-
- /*
* Get the first TxBD to send the mac header
*/
- pTbd = &fec->tbdBase[fec->tbdIndex];
+ pTbd = &fec->tbdBase[0];
pTbd->dataLength = data_length;
pTbd->dataPointer = (uint32)eth_data;
- pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
- fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
-
- /*
- * Kick the MII i/f
- */
- if (fec->xcv_type != SEVENWIRE) {
- uint16 phyStatus;
- fec5xxx_miiphy_read(&fec->miiphy, 0, 0x1, &phyStatus);
- }
+ pTbd->status = FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY | FEC_TBD_WRAP;
/*
* Enable SmartDMA transmit task
*/
-
- tfifo_print(dev->name, fec);
-
- SDMA_TASK_ENABLE (FEC_XMIT_TASK_NO);
-
- tfifo_print(dev->name, fec);
-
- fec->cleanTbdNum -= 1;
+ mpc5xxx_fec_tx_task_enable(fec);
/*
* wait until frame is sent .
@@ -598,33 +659,35 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)
* This command pulls one frame from the card
*/
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
- volatile FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
+ FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
unsigned long ievent;
int frame_length, len = 0;
NBUF *frame;
uchar buff[FEC_MAX_PKT_SIZE];
+// printf("%s\n", __FUNCTION__);
/*
* Check if any critical events have happened
*/
- ievent = fec->eth->ievent;
- fec->eth->ievent = ievent;
+ ievent = readl(&fec->eth->ievent);
+ writel(ievent, &fec->eth->ievent);
if (ievent & (FEC_IEVENT_BABT | FEC_IEVENT_XFIFO_ERROR |
FEC_IEVENT_RFIFO_ERROR)) {
/* BABT, Rx/Tx FIFO errors */
mpc5xxx_fec_halt(dev);
mpc5xxx_fec_init(dev);
+ printf("some error: 0x%08x\n", ievent);
return 0;
}
if (ievent & FEC_IEVENT_HBERR) {
/* Heartbeat error */
- fec->eth->x_cntrl |= 0x00000001;
+ writel(0x00000001 | readl(&fec->eth->x_cntrl), &fec->eth->x_cntrl);
}
if (ievent & FEC_IEVENT_GRA) {
/* Graceful stop complete */
- if (fec->eth->x_cntrl & 0x00000001) {
+ if (readl(&fec->eth->x_cntrl) & 0x00000001) {
mpc5xxx_fec_halt(dev);
- fec->eth->x_cntrl &= ~0x00000001;
+ writel(~0x00000001 & readl(&fec->eth->x_cntrl), &fec->eth->x_cntrl);
mpc5xxx_fec_init(dev);
}
}
@@ -632,37 +695,49 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)
if (!(pRbd->status & FEC_RBD_EMPTY)) {
if ((pRbd->status & FEC_RBD_LAST) && !(pRbd->status & FEC_RBD_ERR) &&
((pRbd->dataLength - 4) > 14)) {
+ printf("read from %d (0x%08x) rbd=0x%08x", fec->rbdIndex, pRbd->dataPointer, pRbd);
/*
* Get buffer address and size
*/
frame = (NBUF *)pRbd->dataPointer;
frame_length = pRbd->dataLength - 4;
-
+ printf(" len=%d\n", frame_length);
+#define DEBUG_RX_HEADER
#ifdef DEBUG_RX_HEADER
{
- int i;
- printf("recv data hdr:");
- for (i = 0; i < 14; i++)
- printf("%02x ", *(frame->head + i));
- printf("\n");
+ printf("recv data hdr:\n");
+ memory_display(frame->data, 0, frame_length, 1);
}
#endif
/*
* Fill the buffer and pass it to upper layers
*/
+#ifdef CONFIG_MPC5200
memcpy(buff, frame->head, 14);
memcpy(buff + 14, frame->data, frame_length);
+#endif
+#ifdef CONFIG_ARCH_IMX27
+ memcpy(buff, frame->data, frame_length);
+#endif
NetReceive(buff, frame_length);
len = frame_length;
+ } else {
+ if (pRbd->status & FEC_RBD_ERR) {
+ printf("error frame: 0x%08x 0x%08x\n", pRbd, pRbd->status);
+ }
}
/*
- * Reset buffer descriptor as empty
+ * free the current buffer, restart the engine and move
+ * forward to the next buffer
*/
- mpc5xxx_fec_rbd_clean(fec, pRbd);
+ mpc5xxx_fec_rbd_clean(fec->rbdIndex == (FEC_RBD_NUM - 1) ? 1 : 0, pRbd);
+ mpc5xxx_fec_rx_task_enable(fec);
+ fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
+
}
- SDMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
+// SDMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
return len;
}
@@ -672,6 +747,11 @@ int mpc5xxx_fec_probe(struct device_d *dev)
struct eth_device *edev;
mpc5xxx_fec_priv *fec;
+ printf("%s\n", __FUNCTION__);
+
+#ifdef CONFIG_ARCH_IMX27
+ PCCR0 |= PCCR0_FEC_EN;
+#endif
edev = (struct eth_device *)malloc(sizeof(struct eth_device));
dev->type_data = edev;
fec = (mpc5xxx_fec_priv *)malloc(sizeof(*fec));
@@ -682,24 +762,46 @@ int mpc5xxx_fec_probe(struct device_d *dev)
edev->send = mpc5xxx_fec_send,
edev->recv = mpc5xxx_fec_recv,
edev->halt = mpc5xxx_fec_halt,
- edev->get_ethaddr = mpc5xxx_fec_ethaddr,
- edev->set_ethaddr = mpc5xxx_fec_ethaddr,
+ edev->get_ethaddr = mpc5xxx_fec_get_hwaddr,
+ edev->set_ethaddr = mpc5xxx_fec_set_hwaddr,
fec->eth = (ethernet_regs *)dev->map_base;
+
+#ifdef CONFIG_MPC5200
fec->tbdBase = (FEC_TBD *)FEC_BD_BASE;
fec->rbdBase = (FEC_RBD *)(FEC_BD_BASE + FEC_TBD_NUM * sizeof(FEC_TBD));
+#endif
+#ifdef CONFIG_ARCH_IMX27
+ /* Reset chip. FIXME: shouldn't it be done for mpc5200 aswell? */
+ writel(1, &fec->eth->ecntrl);
+ while(readl(&fec->eth->ecntrl) & 1) {
+ udelay(10);
+ }
+
+ {
+ unsigned long base;
+
+ base = ((unsigned long)xzalloc(sizeof(FEC_TBD) + 32) + 31) & ~0x1f;
+ fec->tbdBase = (FEC_TBD *)base;
+ writel(fec->tbdBase, &fec->eth->etdsr);
+ base = ((unsigned long)xzalloc(FEC_RBD_NUM * sizeof(FEC_RBD) + 32) + 31) & ~0x1f;
+ fec->rbdBase = (FEC_RBD *)base;
+ writel(fec->rbdBase, &fec->eth->erdsr);
+ }
+#endif
fec->xcv_type = pdata->xcv_type;
sprintf(dev->name, "FEC ETHERNET");
-
+#ifdef CONFIG_MPC5200
loadtask(0, 2);
-
+#endif
if (fec->xcv_type != SEVENWIRE) {
fec->miiphy.read = fec5xxx_miiphy_read;
fec->miiphy.write = fec5xxx_miiphy_write;
fec->miiphy.address = CONFIG_PHY_ADDR;
fec->miiphy.flags = pdata->xcv_type == MII10 ? MIIPHY_FORCE_10 : 0;
+ fec->miiphy.edev = edev;
miiphy_register(&fec->miiphy);
}
@@ -722,3 +824,8 @@ static int mpc5xxx_fec_register(void)
device_initcall(mpc5xxx_fec_register);
+/**
+ * @file
+ * @brief Network driver for FreeScale's FEC implementation.
+ * This type of hardware can be found on MPC52xx and i.MX27 CPUs
+ */
diff --git a/drivers/net/fec_mpc5200.h b/drivers/net/fec_mpc5200.h
index 62fb1cf463..39547dcdb7 100644
--- a/drivers/net/fec_mpc5200.h
+++ b/drivers/net/fec_mpc5200.h
@@ -15,188 +15,194 @@ typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
+/**
+ * Layout description of the FEC
+ */
typedef struct ethernet_register_set {
/* [10:2]addr = 00 */
/* Control and status Registers (offset 000-1FF) */
- volatile uint32 fec_id; /* MBAR_ETH + 0x000 */
- volatile uint32 ievent; /* MBAR_ETH + 0x004 */
- volatile uint32 imask; /* MBAR_ETH + 0x008 */
-
- volatile uint32 RES0[1]; /* MBAR_ETH + 0x00C */
- volatile uint32 r_des_active; /* MBAR_ETH + 0x010 */
- volatile uint32 x_des_active; /* MBAR_ETH + 0x014 */
- volatile uint32 r_des_active_cl; /* MBAR_ETH + 0x018 */
- volatile uint32 x_des_active_cl; /* MBAR_ETH + 0x01C */
- volatile uint32 ivent_set; /* MBAR_ETH + 0x020 */
- volatile uint32 ecntrl; /* MBAR_ETH + 0x024 */
-
- volatile uint32 RES1[6]; /* MBAR_ETH + 0x028-03C */
- volatile uint32 mii_data; /* MBAR_ETH + 0x040 */
- volatile uint32 mii_speed; /* MBAR_ETH + 0x044 */
- volatile uint32 mii_status; /* MBAR_ETH + 0x048 */
-
- volatile uint32 RES2[5]; /* MBAR_ETH + 0x04C-05C */
- volatile uint32 mib_data; /* MBAR_ETH + 0x060 */
- volatile uint32 mib_control; /* MBAR_ETH + 0x064 */
-
- volatile uint32 RES3[6]; /* MBAR_ETH + 0x068-7C */
- volatile uint32 r_activate; /* MBAR_ETH + 0x080 */
- volatile uint32 r_cntrl; /* MBAR_ETH + 0x084 */
- volatile uint32 r_hash; /* MBAR_ETH + 0x088 */
- volatile uint32 r_data; /* MBAR_ETH + 0x08C */
- volatile uint32 ar_done; /* MBAR_ETH + 0x090 */
- volatile uint32 r_test; /* MBAR_ETH + 0x094 */
- volatile uint32 r_mib; /* MBAR_ETH + 0x098 */
- volatile uint32 r_da_low; /* MBAR_ETH + 0x09C */
- volatile uint32 r_da_high; /* MBAR_ETH + 0x0A0 */
-
- volatile uint32 RES4[7]; /* MBAR_ETH + 0x0A4-0BC */
- volatile uint32 x_activate; /* MBAR_ETH + 0x0C0 */
- volatile uint32 x_cntrl; /* MBAR_ETH + 0x0C4 */
- volatile uint32 backoff; /* MBAR_ETH + 0x0C8 */
- volatile uint32 x_data; /* MBAR_ETH + 0x0CC */
- volatile uint32 x_status; /* MBAR_ETH + 0x0D0 */
- volatile uint32 x_mib; /* MBAR_ETH + 0x0D4 */
- volatile uint32 x_test; /* MBAR_ETH + 0x0D8 */
- volatile uint32 fdxfc_da1; /* MBAR_ETH + 0x0DC */
- volatile uint32 fdxfc_da2; /* MBAR_ETH + 0x0E0 */
- volatile uint32 paddr1; /* MBAR_ETH + 0x0E4 */
- volatile uint32 paddr2; /* MBAR_ETH + 0x0E8 */
- volatile uint32 op_pause; /* MBAR_ETH + 0x0EC */
-
- volatile uint32 RES5[4]; /* MBAR_ETH + 0x0F0-0FC */
- volatile uint32 instr_reg; /* MBAR_ETH + 0x100 */
- volatile uint32 context_reg; /* MBAR_ETH + 0x104 */
- volatile uint32 test_cntrl; /* MBAR_ETH + 0x108 */
- volatile uint32 acc_reg; /* MBAR_ETH + 0x10C */
- volatile uint32 ones; /* MBAR_ETH + 0x110 */
- volatile uint32 zeros; /* MBAR_ETH + 0x114 */
- volatile uint32 iaddr1; /* MBAR_ETH + 0x118 */
- volatile uint32 iaddr2; /* MBAR_ETH + 0x11C */
- volatile uint32 gaddr1; /* MBAR_ETH + 0x120 */
- volatile uint32 gaddr2; /* MBAR_ETH + 0x124 */
- volatile uint32 random; /* MBAR_ETH + 0x128 */
- volatile uint32 rand1; /* MBAR_ETH + 0x12C */
- volatile uint32 tmp; /* MBAR_ETH + 0x130 */
-
- volatile uint32 RES6[3]; /* MBAR_ETH + 0x134-13C */
- volatile uint32 fifo_id; /* MBAR_ETH + 0x140 */
- volatile uint32 x_wmrk; /* MBAR_ETH + 0x144 */
- volatile uint32 fcntrl; /* MBAR_ETH + 0x148 */
- volatile uint32 r_bound; /* MBAR_ETH + 0x14C */
- volatile uint32 r_fstart; /* MBAR_ETH + 0x150 */
- volatile uint32 r_count; /* MBAR_ETH + 0x154 */
- volatile uint32 r_lag; /* MBAR_ETH + 0x158 */
- volatile uint32 r_read; /* MBAR_ETH + 0x15C */
- volatile uint32 r_write; /* MBAR_ETH + 0x160 */
- volatile uint32 x_count; /* MBAR_ETH + 0x164 */
- volatile uint32 x_lag; /* MBAR_ETH + 0x168 */
- volatile uint32 x_retry; /* MBAR_ETH + 0x16C */
- volatile uint32 x_write; /* MBAR_ETH + 0x170 */
- volatile uint32 x_read; /* MBAR_ETH + 0x174 */
-
- volatile uint32 RES7[2]; /* MBAR_ETH + 0x178-17C */
- volatile uint32 fm_cntrl; /* MBAR_ETH + 0x180 */
- volatile uint32 rfifo_data; /* MBAR_ETH + 0x184 */
- volatile uint32 rfifo_status; /* MBAR_ETH + 0x188 */
- volatile uint32 rfifo_cntrl; /* MBAR_ETH + 0x18C */
- volatile uint32 rfifo_lrf_ptr; /* MBAR_ETH + 0x190 */
- volatile uint32 rfifo_lwf_ptr; /* MBAR_ETH + 0x194 */
- volatile uint32 rfifo_alarm; /* MBAR_ETH + 0x198 */
- volatile uint32 rfifo_rdptr; /* MBAR_ETH + 0x19C */
- volatile uint32 rfifo_wrptr; /* MBAR_ETH + 0x1A0 */
- volatile uint32 tfifo_data; /* MBAR_ETH + 0x1A4 */
- volatile uint32 tfifo_status; /* MBAR_ETH + 0x1A8 */
- volatile uint32 tfifo_cntrl; /* MBAR_ETH + 0x1AC */
- volatile uint32 tfifo_lrf_ptr; /* MBAR_ETH + 0x1B0 */
- volatile uint32 tfifo_lwf_ptr; /* MBAR_ETH + 0x1B4 */
- volatile uint32 tfifo_alarm; /* MBAR_ETH + 0x1B8 */
- volatile uint32 tfifo_rdptr; /* MBAR_ETH + 0x1BC */
- volatile uint32 tfifo_wrptr; /* MBAR_ETH + 0x1C0 */
-
- volatile uint32 reset_cntrl; /* MBAR_ETH + 0x1C4 */
- volatile uint32 xmit_fsm; /* MBAR_ETH + 0x1C8 */
-
- volatile uint32 RES8[3]; /* MBAR_ETH + 0x1CC-1D4 */
- volatile uint32 rdes_data0; /* MBAR_ETH + 0x1D8 */
- volatile uint32 rdes_data1; /* MBAR_ETH + 0x1DC */
- volatile uint32 r_length; /* MBAR_ETH + 0x1E0 */
- volatile uint32 x_length; /* MBAR_ETH + 0x1E4 */
- volatile uint32 x_addr; /* MBAR_ETH + 0x1E8 */
- volatile uint32 cdes_data; /* MBAR_ETH + 0x1EC */
- volatile uint32 status; /* MBAR_ETH + 0x1F0 */
- volatile uint32 dma_control; /* MBAR_ETH + 0x1F4 */
- volatile uint32 des_cmnd; /* MBAR_ETH + 0x1F8 */
- volatile uint32 data; /* MBAR_ETH + 0x1FC */
+ uint32 fec_id; /* MBAR_ETH + 0x000 */
+ uint32 ievent; /* MBAR_ETH + 0x004 */
+ uint32 imask; /* MBAR_ETH + 0x008 */
+
+ uint32 RES0[1]; /* MBAR_ETH + 0x00C */
+ uint32 r_des_active; /* MBAR_ETH + 0x010 */
+ uint32 x_des_active; /* MBAR_ETH + 0x014 */
+ uint32 r_des_active_cl; /* MBAR_ETH + 0x018 */
+ uint32 x_des_active_cl; /* MBAR_ETH + 0x01C */
+ uint32 ivent_set; /* MBAR_ETH + 0x020 */
+ uint32 ecntrl; /* MBAR_ETH + 0x024 */
+
+ uint32 RES1[6]; /* MBAR_ETH + 0x028-03C */
+ uint32 mii_data; /* MBAR_ETH + 0x040 */
+ uint32 mii_speed; /* MBAR_ETH + 0x044 */
+ uint32 mii_status; /* MBAR_ETH + 0x048 */
+
+ uint32 RES2[5]; /* MBAR_ETH + 0x04C-05C */
+ uint32 mib_data; /* MBAR_ETH + 0x060 */
+ uint32 mib_control; /* MBAR_ETH + 0x064 */
+
+ uint32 RES3[6]; /* MBAR_ETH + 0x068-7C */
+ uint32 r_activate; /* MBAR_ETH + 0x080 */
+ uint32 r_cntrl; /* MBAR_ETH + 0x084 */
+ uint32 r_hash; /* MBAR_ETH + 0x088 */
+ uint32 r_data; /* MBAR_ETH + 0x08C */
+ uint32 ar_done; /* MBAR_ETH + 0x090 */
+ uint32 r_test; /* MBAR_ETH + 0x094 */
+ uint32 r_mib; /* MBAR_ETH + 0x098 */
+ uint32 r_da_low; /* MBAR_ETH + 0x09C */
+ uint32 r_da_high; /* MBAR_ETH + 0x0A0 */
+
+ uint32 RES4[7]; /* MBAR_ETH + 0x0A4-0BC */
+ uint32 x_activate; /* MBAR_ETH + 0x0C0 */
+ uint32 x_cntrl; /* MBAR_ETH + 0x0C4 */
+ uint32 backoff; /* MBAR_ETH + 0x0C8 */
+ uint32 x_data; /* MBAR_ETH + 0x0CC */
+ uint32 x_status; /* MBAR_ETH + 0x0D0 */
+ uint32 x_mib; /* MBAR_ETH + 0x0D4 */
+ uint32 x_test; /* MBAR_ETH + 0x0D8 */
+ uint32 fdxfc_da1; /* MBAR_ETH + 0x0DC */
+ uint32 fdxfc_da2; /* MBAR_ETH + 0x0E0 */
+ uint32 paddr1; /* MBAR_ETH + 0x0E4 */
+ uint32 paddr2; /* MBAR_ETH + 0x0E8 */
+ uint32 op_pause; /* MBAR_ETH + 0x0EC */
+
+ uint32 RES5[4]; /* MBAR_ETH + 0x0F0-0FC */
+ uint32 instr_reg; /* MBAR_ETH + 0x100 */
+ uint32 context_reg; /* MBAR_ETH + 0x104 */
+ uint32 test_cntrl; /* MBAR_ETH + 0x108 */
+ uint32 acc_reg; /* MBAR_ETH + 0x10C */
+ uint32 ones; /* MBAR_ETH + 0x110 */
+ uint32 zeros; /* MBAR_ETH + 0x114 */
+ uint32 iaddr1; /* MBAR_ETH + 0x118 */
+ uint32 iaddr2; /* MBAR_ETH + 0x11C */
+ uint32 gaddr1; /* MBAR_ETH + 0x120 */
+ uint32 gaddr2; /* MBAR_ETH + 0x124 */
+ uint32 random; /* MBAR_ETH + 0x128 */
+ uint32 rand1; /* MBAR_ETH + 0x12C */
+ uint32 tmp; /* MBAR_ETH + 0x130 */
+
+ uint32 RES6[3]; /* MBAR_ETH + 0x134-13C */
+ uint32 fifo_id; /* MBAR_ETH + 0x140 */
+ uint32 x_wmrk; /* MBAR_ETH + 0x144 */
+ uint32 fcntrl; /* MBAR_ETH + 0x148 */
+ uint32 r_bound; /* MBAR_ETH + 0x14C */
+ uint32 r_fstart; /* MBAR_ETH + 0x150 */
+ uint32 r_count; /* MBAR_ETH + 0x154 */
+ uint32 r_lag; /* MBAR_ETH + 0x158 */
+ uint32 r_read; /* MBAR_ETH + 0x15C */
+ uint32 r_write; /* MBAR_ETH + 0x160 */
+ uint32 x_count; /* MBAR_ETH + 0x164 */
+ uint32 x_lag; /* MBAR_ETH + 0x168 */
+ uint32 x_retry; /* MBAR_ETH + 0x16C */
+ uint32 x_write; /* MBAR_ETH + 0x170 */
+ uint32 x_read; /* MBAR_ETH + 0x174 */
+
+ uint32 RES7[2]; /* MBAR_ETH + 0x178-17C */
+ uint32 fm_cntrl; /* MBAR_ETH + 0x180 */
+#define erdsr fm_cntrl
+ uint32 rfifo_data; /* MBAR_ETH + 0x184 */
+#define etdsr rfifo_data
+ uint32 rfifo_status; /* MBAR_ETH + 0x188 */
+#define emrbr rfifo_status
+ uint32 rfifo_cntrl; /* MBAR_ETH + 0x18C */
+ uint32 rfifo_lrf_ptr; /* MBAR_ETH + 0x190 */
+ uint32 rfifo_lwf_ptr; /* MBAR_ETH + 0x194 */
+ uint32 rfifo_alarm; /* MBAR_ETH + 0x198 */
+ uint32 rfifo_rdptr; /* MBAR_ETH + 0x19C */
+ uint32 rfifo_wrptr; /* MBAR_ETH + 0x1A0 */
+ uint32 tfifo_data; /* MBAR_ETH + 0x1A4 */
+ uint32 tfifo_status; /* MBAR_ETH + 0x1A8 */
+ uint32 tfifo_cntrl; /* MBAR_ETH + 0x1AC */
+ uint32 tfifo_lrf_ptr; /* MBAR_ETH + 0x1B0 */
+ uint32 tfifo_lwf_ptr; /* MBAR_ETH + 0x1B4 */
+ uint32 tfifo_alarm; /* MBAR_ETH + 0x1B8 */
+ uint32 tfifo_rdptr; /* MBAR_ETH + 0x1BC */
+ uint32 tfifo_wrptr; /* MBAR_ETH + 0x1C0 */
+
+ uint32 reset_cntrl; /* MBAR_ETH + 0x1C4 */
+ uint32 xmit_fsm; /* MBAR_ETH + 0x1C8 */
+
+ uint32 RES8[3]; /* MBAR_ETH + 0x1CC-1D4 */
+ uint32 rdes_data0; /* MBAR_ETH + 0x1D8 */
+ uint32 rdes_data1; /* MBAR_ETH + 0x1DC */
+ uint32 r_length; /* MBAR_ETH + 0x1E0 */
+ uint32 x_length; /* MBAR_ETH + 0x1E4 */
+ uint32 x_addr; /* MBAR_ETH + 0x1E8 */
+ uint32 cdes_data; /* MBAR_ETH + 0x1EC */
+ uint32 status; /* MBAR_ETH + 0x1F0 */
+ uint32 dma_control; /* MBAR_ETH + 0x1F4 */
+ uint32 des_cmnd; /* MBAR_ETH + 0x1F8 */
+ uint32 data; /* MBAR_ETH + 0x1FC */
/* MIB COUNTERS (Offset 200-2FF) */
- volatile uint32 rmon_t_drop; /* MBAR_ETH + 0x200 */
- volatile uint32 rmon_t_packets; /* MBAR_ETH + 0x204 */
- volatile uint32 rmon_t_bc_pkt; /* MBAR_ETH + 0x208 */
- volatile uint32 rmon_t_mc_pkt; /* MBAR_ETH + 0x20C */
- volatile uint32 rmon_t_crc_align; /* MBAR_ETH + 0x210 */
- volatile uint32 rmon_t_undersize; /* MBAR_ETH + 0x214 */
- volatile uint32 rmon_t_oversize; /* MBAR_ETH + 0x218 */
- volatile uint32 rmon_t_frag; /* MBAR_ETH + 0x21C */
- volatile uint32 rmon_t_jab; /* MBAR_ETH + 0x220 */
- volatile uint32 rmon_t_col; /* MBAR_ETH + 0x224 */
- volatile uint32 rmon_t_p64; /* MBAR_ETH + 0x228 */
- volatile uint32 rmon_t_p65to127; /* MBAR_ETH + 0x22C */
- volatile uint32 rmon_t_p128to255; /* MBAR_ETH + 0x230 */
- volatile uint32 rmon_t_p256to511; /* MBAR_ETH + 0x234 */
- volatile uint32 rmon_t_p512to1023; /* MBAR_ETH + 0x238 */
- volatile uint32 rmon_t_p1024to2047; /* MBAR_ETH + 0x23C */
- volatile uint32 rmon_t_p_gte2048; /* MBAR_ETH + 0x240 */
- volatile uint32 rmon_t_octets; /* MBAR_ETH + 0x244 */
- volatile uint32 ieee_t_drop; /* MBAR_ETH + 0x248 */
- volatile uint32 ieee_t_frame_ok; /* MBAR_ETH + 0x24C */
- volatile uint32 ieee_t_1col; /* MBAR_ETH + 0x250 */
- volatile uint32 ieee_t_mcol; /* MBAR_ETH + 0x254 */
- volatile uint32 ieee_t_def; /* MBAR_ETH + 0x258 */
- volatile uint32 ieee_t_lcol; /* MBAR_ETH + 0x25C */
- volatile uint32 ieee_t_excol; /* MBAR_ETH + 0x260 */
- volatile uint32 ieee_t_macerr; /* MBAR_ETH + 0x264 */
- volatile uint32 ieee_t_cserr; /* MBAR_ETH + 0x268 */
- volatile uint32 ieee_t_sqe; /* MBAR_ETH + 0x26C */
- volatile uint32 t_fdxfc; /* MBAR_ETH + 0x270 */
- volatile uint32 ieee_t_octets_ok; /* MBAR_ETH + 0x274 */
-
- volatile uint32 RES9[2]; /* MBAR_ETH + 0x278-27C */
- volatile uint32 rmon_r_drop; /* MBAR_ETH + 0x280 */
- volatile uint32 rmon_r_packets; /* MBAR_ETH + 0x284 */
- volatile uint32 rmon_r_bc_pkt; /* MBAR_ETH + 0x288 */
- volatile uint32 rmon_r_mc_pkt; /* MBAR_ETH + 0x28C */
- volatile uint32 rmon_r_crc_align; /* MBAR_ETH + 0x290 */
- volatile uint32 rmon_r_undersize; /* MBAR_ETH + 0x294 */
- volatile uint32 rmon_r_oversize; /* MBAR_ETH + 0x298 */
- volatile uint32 rmon_r_frag; /* MBAR_ETH + 0x29C */
- volatile uint32 rmon_r_jab; /* MBAR_ETH + 0x2A0 */
-
- volatile uint32 rmon_r_resvd_0; /* MBAR_ETH + 0x2A4 */
-
- volatile uint32 rmon_r_p64; /* MBAR_ETH + 0x2A8 */
- volatile uint32 rmon_r_p65to127; /* MBAR_ETH + 0x2AC */
- volatile uint32 rmon_r_p128to255; /* MBAR_ETH + 0x2B0 */
- volatile uint32 rmon_r_p256to511; /* MBAR_ETH + 0x2B4 */
- volatile uint32 rmon_r_p512to1023; /* MBAR_ETH + 0x2B8 */
- volatile uint32 rmon_r_p1024to2047; /* MBAR_ETH + 0x2BC */
- volatile uint32 rmon_r_p_gte2048; /* MBAR_ETH + 0x2C0 */
- volatile uint32 rmon_r_octets; /* MBAR_ETH + 0x2C4 */
- volatile uint32 ieee_r_drop; /* MBAR_ETH + 0x2C8 */
- volatile uint32 ieee_r_frame_ok; /* MBAR_ETH + 0x2CC */
- volatile uint32 ieee_r_crc; /* MBAR_ETH + 0x2D0 */
- volatile uint32 ieee_r_align; /* MBAR_ETH + 0x2D4 */
- volatile uint32 r_macerr; /* MBAR_ETH + 0x2D8 */
- volatile uint32 r_fdxfc; /* MBAR_ETH + 0x2DC */
- volatile uint32 ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
-
- volatile uint32 RES10[6]; /* MBAR_ETH + 0x2E4-2FC */
-
- volatile uint32 RES11[64]; /* MBAR_ETH + 0x300-3FF */
+ uint32 rmon_t_drop; /* MBAR_ETH + 0x200 */
+ uint32 rmon_t_packets; /* MBAR_ETH + 0x204 */
+ uint32 rmon_t_bc_pkt; /* MBAR_ETH + 0x208 */
+ uint32 rmon_t_mc_pkt; /* MBAR_ETH + 0x20C */
+ uint32 rmon_t_crc_align; /* MBAR_ETH + 0x210 */
+ uint32 rmon_t_undersize; /* MBAR_ETH + 0x214 */
+ uint32 rmon_t_oversize; /* MBAR_ETH + 0x218 */
+ uint32 rmon_t_frag; /* MBAR_ETH + 0x21C */
+ uint32 rmon_t_jab; /* MBAR_ETH + 0x220 */
+ uint32 rmon_t_col; /* MBAR_ETH + 0x224 */
+ uint32 rmon_t_p64; /* MBAR_ETH + 0x228 */
+ uint32 rmon_t_p65to127; /* MBAR_ETH + 0x22C */
+ uint32 rmon_t_p128to255; /* MBAR_ETH + 0x230 */
+ uint32 rmon_t_p256to511; /* MBAR_ETH + 0x234 */
+ uint32 rmon_t_p512to1023; /* MBAR_ETH + 0x238 */
+ uint32 rmon_t_p1024to2047; /* MBAR_ETH + 0x23C */
+ uint32 rmon_t_p_gte2048; /* MBAR_ETH + 0x240 */
+ uint32 rmon_t_octets; /* MBAR_ETH + 0x244 */
+ uint32 ieee_t_drop; /* MBAR_ETH + 0x248 */
+ uint32 ieee_t_frame_ok; /* MBAR_ETH + 0x24C */
+ uint32 ieee_t_1col; /* MBAR_ETH + 0x250 */
+ uint32 ieee_t_mcol; /* MBAR_ETH + 0x254 */
+ uint32 ieee_t_def; /* MBAR_ETH + 0x258 */
+ uint32 ieee_t_lcol; /* MBAR_ETH + 0x25C */
+ uint32 ieee_t_excol; /* MBAR_ETH + 0x260 */
+ uint32 ieee_t_macerr; /* MBAR_ETH + 0x264 */
+ uint32 ieee_t_cserr; /* MBAR_ETH + 0x268 */
+ uint32 ieee_t_sqe; /* MBAR_ETH + 0x26C */
+ uint32 t_fdxfc; /* MBAR_ETH + 0x270 */
+ uint32 ieee_t_octets_ok; /* MBAR_ETH + 0x274 */
+
+ uint32 RES9[2]; /* MBAR_ETH + 0x278-27C */
+ uint32 rmon_r_drop; /* MBAR_ETH + 0x280 */
+ uint32 rmon_r_packets; /* MBAR_ETH + 0x284 */
+ uint32 rmon_r_bc_pkt; /* MBAR_ETH + 0x288 */
+ uint32 rmon_r_mc_pkt; /* MBAR_ETH + 0x28C */
+ uint32 rmon_r_crc_align; /* MBAR_ETH + 0x290 */
+ uint32 rmon_r_undersize; /* MBAR_ETH + 0x294 */
+ uint32 rmon_r_oversize; /* MBAR_ETH + 0x298 */
+ uint32 rmon_r_frag; /* MBAR_ETH + 0x29C */
+ uint32 rmon_r_jab; /* MBAR_ETH + 0x2A0 */
+
+ uint32 rmon_r_resvd_0; /* MBAR_ETH + 0x2A4 */
+
+ uint32 rmon_r_p64; /* MBAR_ETH + 0x2A8 */
+ uint32 rmon_r_p65to127; /* MBAR_ETH + 0x2AC */
+ uint32 rmon_r_p128to255; /* MBAR_ETH + 0x2B0 */
+ uint32 rmon_r_p256to511; /* MBAR_ETH + 0x2B4 */
+ uint32 rmon_r_p512to1023; /* MBAR_ETH + 0x2B8 */
+ uint32 rmon_r_p1024to2047; /* MBAR_ETH + 0x2BC */
+ uint32 rmon_r_p_gte2048; /* MBAR_ETH + 0x2C0 */
+ uint32 rmon_r_octets; /* MBAR_ETH + 0x2C4 */
+ uint32 ieee_r_drop; /* MBAR_ETH + 0x2C8 */
+ uint32 ieee_r_frame_ok; /* MBAR_ETH + 0x2CC */
+ uint32 ieee_r_crc; /* MBAR_ETH + 0x2D0 */
+ uint32 ieee_r_align; /* MBAR_ETH + 0x2D4 */
+ uint32 r_macerr; /* MBAR_ETH + 0x2D8 */
+ uint32 r_fdxfc; /* MBAR_ETH + 0x2DC */
+ uint32 ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
+
+ uint32 RES10[6]; /* MBAR_ETH + 0x2E4-2FC */
+
+ uint32 RES11[64]; /* MBAR_ETH + 0x300-3FF */
} ethernet_regs;
#define FEC_IEVENT_HBERR 0x80000000
@@ -239,8 +245,12 @@ typedef struct ethernet_register_set {
#define FEC_ECNTRL_RESET 0x00000001
#define FEC_ECNTRL_ETHER_EN 0x00000002
-/* Receive & Transmit Buffer Descriptor definitions */
-typedef struct BufferDescriptor {
+#ifdef CONFIG_MPC5200
+/**
+ * Receive & Transmit Buffer Descriptor definitions
+ * Big endian layout
+ */
+typedef struct {
uint16 status;
uint16 dataLength;
uint32 dataPointer;
@@ -251,33 +261,58 @@ typedef struct {
uint16 dataLength;
uint32 dataPointer;
} FEC_TBD;
+#endif
-/* private structure */
+#ifdef CONFIG_ARCH_IMX27
+/**
+ * Receive & Transmit Buffer Descriptor definitions
+ * Little endian layout
+ */
+typedef struct {
+ uint16 dataLength;
+ uint16 status;
+ uint32 dataPointer;
+} FEC_RBD;
+
+typedef struct {
+ uint16 dataLength;
+ uint16 status;
+ uint32 dataPointer;
+} FEC_TBD;
+#endif
+/**
+ * private structure
+ */
typedef struct {
ethernet_regs *eth;
- xceiver_type xcv_type; /* transceiver type */
- FEC_RBD *rbdBase; /* RBD ring */
- FEC_TBD *tbdBase; /* TBD ring */
- uint16 rbdIndex; /* next receive BD to read */
- uint16 tbdIndex; /* next transmit BD to send */
- uint16 usedTbdIndex; /* next transmit BD to clean */
- uint16 cleanTbdNum; /* the number of available transmit BDs */
+ xceiver_type xcv_type; /** transceiver type */
+ FEC_RBD *rbdBase; /** RBD ring */
+ FEC_TBD *tbdBase; /** TBD ring */
+ uint16 rbdIndex; /** next receive BD to read */
struct miiphy_device miiphy;
} mpc5xxx_fec_priv;
+/**
+ * buffer alignment on request
+ */
+#define RDB_ALIGNMENT 16
+
/* Ethernet parameter area */
#define FEC_TBD_BASE (FEC_PARAM_BASE + 0x00)
#define FEC_TBD_NEXT (FEC_PARAM_BASE + 0x04)
#define FEC_RBD_BASE (FEC_PARAM_BASE + 0x08)
#define FEC_RBD_NEXT (FEC_PARAM_BASE + 0x0c)
-/* BD Numer definitions */
-#define FEC_TBD_NUM 48 /* The user can adjust this value */
-#define FEC_RBD_NUM 32 /* The user can adjust this value */
+/**
+ * Numbers of buffer descriptos for receiving
+ */
+#define FEC_RBD_NUM 64 /* The user can adjust this value */
-/* packet size limit */
+/**
+ * define the packet size limit
+ */
#define FEC_MAX_PKT_SIZE 1536
/* RBD bits definitions */
@@ -318,3 +353,8 @@ typedef struct {
#define FEC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */
#endif /* __MPC5XXX_FEC_H */
+
+/**
+ * @file
+ * @brief Definitions for the FEC driver (MPC52xx and i-MX27)
+ */
diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h
index a8ef8b795d..472f74c56b 100644
--- a/include/asm-arm/arch-imx/imx-regs.h
+++ b/include/asm-arm/arch-imx/imx-regs.h
@@ -56,48 +56,62 @@
* i.MX1 and i.MXL: 0 <= x <= 3
* i.MX27 : 0 <= x <= 5
*/
-#define DDIR(x) __REG2(IMX_GPIO_BASE + 0x00, ((x) & 3) << 8)
-#define OCR1(x) __REG2(IMX_GPIO_BASE + 0x04, ((x) & 3) << 8)
-#define OCR2(x) __REG2(IMX_GPIO_BASE + 0x08, ((x) & 3) << 8)
-#define ICONFA1(x) __REG2(IMX_GPIO_BASE + 0x0c, ((x) & 3) << 8)
-#define ICONFA2(x) __REG2(IMX_GPIO_BASE + 0x10, ((x) & 3) << 8)
-#define ICONFB1(x) __REG2(IMX_GPIO_BASE + 0x14, ((x) & 3) << 8)
-#define ICONFB2(x) __REG2(IMX_GPIO_BASE + 0x18, ((x) & 3) << 8)
-#define DR(x) __REG2(IMX_GPIO_BASE + 0x1c, ((x) & 3) << 8)
-#define GIUS(x) __REG2(IMX_GPIO_BASE + 0x20, ((x) & 3) << 8)
-#define SSR(x) __REG2(IMX_GPIO_BASE + 0x24, ((x) & 3) << 8)
-#define ICR1(x) __REG2(IMX_GPIO_BASE + 0x28, ((x) & 3) << 8)
-#define ICR2(x) __REG2(IMX_GPIO_BASE + 0x2c, ((x) & 3) << 8)
-#define IMR(x) __REG2(IMX_GPIO_BASE + 0x30, ((x) & 3) << 8)
-#define ISR(x) __REG2(IMX_GPIO_BASE + 0x34, ((x) & 3) << 8)
-#define GPR(x) __REG2(IMX_GPIO_BASE + 0x38, ((x) & 3) << 8)
-#define SWR(x) __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
-#define PUEN(x) __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
+#define DDIR(x) __REG2(IMX_GPIO_BASE + 0x00, ((x) & 7) << 8)
+#define OCR1(x) __REG2(IMX_GPIO_BASE + 0x04, ((x) & 7) << 8)
+#define OCR2(x) __REG2(IMX_GPIO_BASE + 0x08, ((x) & 7) << 8)
+#define ICONFA1(x) __REG2(IMX_GPIO_BASE + 0x0c, ((x) & 7) << 8)
+#define ICONFA2(x) __REG2(IMX_GPIO_BASE + 0x10, ((x) & 7) << 8)
+#define ICONFB1(x) __REG2(IMX_GPIO_BASE + 0x14, ((x) & 7) << 8)
+#define ICONFB2(x) __REG2(IMX_GPIO_BASE + 0x18, ((x) & 7) << 8)
+#define DR(x) __REG2(IMX_GPIO_BASE + 0x1c, ((x) & 7) << 8)
+#define GIUS(x) __REG2(IMX_GPIO_BASE + 0x20, ((x) & 7) << 8)
+#define SSR(x) __REG2(IMX_GPIO_BASE + 0x24, ((x) & 7) << 8)
+#define ICR1(x) __REG2(IMX_GPIO_BASE + 0x28, ((x) & 7) << 8)
+#define ICR2(x) __REG2(IMX_GPIO_BASE + 0x2c, ((x) & 7) << 8)
+#define IMR(x) __REG2(IMX_GPIO_BASE + 0x30, ((x) & 7) << 8)
+#define ISR(x) __REG2(IMX_GPIO_BASE + 0x34, ((x) & 7) << 8)
+#define GPR(x) __REG2(IMX_GPIO_BASE + 0x38, ((x) & 7) << 8)
+#define SWR(x) __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 7) << 8)
+#define PUEN(x) __REG2(IMX_GPIO_BASE + 0x40, ((x) & 7) << 8)
#define GPIO_PIN_MASK 0x1f
-#define GPIO_PORT_MASK (0x7 << 5)
-#define GPIO_PORTA (0 << 5)
-#define GPIO_PORTB (1 << 5)
-#define GPIO_PORTC (2 << 5)
-#define GPIO_PORTD (3 << 5)
-#define GPIO_PORTE (4 << 5)
-#define GPIO_PORTF (5 << 5)
+#define GPIO_PORT_SHIFT 5
+#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
+
+#define GPIO_PORTA (0 << GPIO_PORT_SHIFT)
+#define GPIO_PORTB (1 << GPIO_PORT_SHIFT)
+#define GPIO_PORTC (2 << GPIO_PORT_SHIFT)
+#define GPIO_PORTD (3 << GPIO_PORT_SHIFT)
+#define GPIO_PORTE (4 << GPIO_PORT_SHIFT)
+#define GPIO_PORTF (5 << GPIO_PORT_SHIFT)
#define GPIO_OUT (1 << 8)
#define GPIO_IN (0 << 8)
#define GPIO_PUEN (1 << 9)
-#define GPIO_PF (0 << 10)
-#define GPIO_AF (1 << 10)
+#define GPIO_PF (1 << 10)
+#define GPIO_AF (1 << 11)
+
+#define GPIO_OCR_SHIFT 12
+#define GPIO_OCR_MASK (3 << GPIO_OCR_SHIFT)
+#define GPIO_AIN (0 << GPIO_OCR_SHIFT)
+#define GPIO_BIN (1 << GPIO_OCR_SHIFT)
+#define GPIO_CIN (2 << GPIO_OCR_SHIFT)
+#define GPIO_GPIO (3 << GPIO_OCR_SHIFT)
-#define GPIO_OCR_MASK (3 << 11)
-#define GPIO_AIN (0 << 11)
-#define GPIO_BIN (1 << 11)
-#define GPIO_CIN (2 << 11)
-#define GPIO_GPIO (3 << 11)
+#define GPIO_AOUT_SHIFT 14
+#define GPIO_AOUT_MASK (3 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT (0 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_ISR (1 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_0 (2 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_1 (3 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT (1 << 13)
-#define GPIO_BOUT (1 << 14)
+#define GPIO_BOUT_SHIFT 16
+#define GPIO_BOUT_MASK (3 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT (0 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_ISR (1 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_0 (2 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_1 (3 << GPIO_BOUT_SHIFT)
#endif /* _IMX_REGS_H */
diff --git a/include/asm-ppc/arch-mpc5200/fec.h b/include/asm-ppc/arch-mpc5200/fec.h
deleted file mode 100644
index a3e04b4e9d..0000000000
--- a/include/asm-ppc/arch-mpc5200/fec.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __INCLUDE_ASM_ARCH_FEC_H
-#define __INCLUDE_ASM_ARCH_FEC_H
-
-struct mpc5xxx_fec_platform_data {
- ulong xcv_type;
-};
-
-typedef enum {
- SEVENWIRE, /* 7-wire */
- MII10, /* MII 10Mbps */
- MII100 /* MII 100Mbps */
-} xceiver_type;
-
-#endif /* __INCLUDE_ASM_ARCH_FEC_H */
diff --git a/include/asm-sandbox/posix_types.h b/include/asm-sandbox/posix_types.h
index 5529f32702..5dcc842ab7 100644
--- a/include/asm-sandbox/posix_types.h
+++ b/include/asm-sandbox/posix_types.h
@@ -16,8 +16,8 @@ typedef int __kernel_pid_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
-typedef unsigned int __kernel_size_t;
-typedef int __kernel_ssize_t;
+typedef unsigned long __kernel_size_t;
+typedef long __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
diff --git a/include/fec.h b/include/fec.h
new file mode 100644
index 0000000000..89f0fba2c1
--- /dev/null
+++ b/include/fec.h
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * @brief Shared structures and constants between i.MX27's and MPC52xx's FEC
+ */
+#ifndef __INCLUDE_NETWORK_FEC_H
+#define __INCLUDE_NETWORK_FEC_H
+
+/**
+ * Define the phy connected externally
+ */
+struct fec_platform_data {
+ ulong xcv_type;
+};
+
+/**
+ * Supported phy types on this platform
+ */
+typedef enum {
+ SEVENWIRE, /** 7-wire */
+ MII10, /** MII 10Mbps */
+ MII100 /** MII 100Mbps */
+} xceiver_type;
+
+#endif /* __INCLUDE_NETWORK_FEC_H */
diff --git a/net/eth.c b/net/eth.c
index 2f7136b324..95c2428ab1 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -95,7 +95,7 @@ int eth_register(struct eth_device *edev)
return -1;
}
- edev->param_ip.name = "ip";
+ edev->param_ip.name = "ipaddr";
edev->param_ethaddr.name = "ethaddr";
edev->param_gateway.name = "gateway";
edev->param_netmask.name = "netmask";
diff --git a/net/net.c b/net/net.c
index fd2effe4c6..e970238603 100644
--- a/net/net.c
+++ b/net/net.c
@@ -264,7 +264,7 @@ NetLoop(proto_t protocol)
return -1;
}
- ip = dev_get_param_ip(eth_current->dev, "ip");
+ ip = dev_get_param_ip(eth_current->dev, "ipaddr");
NetCopyIP(&NetOurIP, &ip);
/* XXX problem with bss workaround */