]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-arm
authorWolfgang Denk <wd@denx.de>
Wed, 13 Oct 2010 18:59:47 +0000 (20:59 +0200)
committerWolfgang Denk <wd@denx.de>
Wed, 13 Oct 2010 18:59:47 +0000 (20:59 +0200)
94 files changed:
MAINTAINERS
README
arch/arm/include/asm/arch-davinci/emac_defs.h
arch/arm/lib/board.c
arch/microblaze/cpu/start.S
arch/microblaze/include/asm/byteorder.h
arch/microblaze/lib/board.c
arch/powerpc/cpu/74xx_7xx/start.S
arch/powerpc/cpu/mpc512x/start.S
arch/powerpc/cpu/mpc5xx/start.S
arch/powerpc/cpu/mpc5xxx/start.S
arch/powerpc/cpu/mpc8220/start.S
arch/powerpc/cpu/mpc824x/start.S
arch/powerpc/cpu/mpc8260/start.S
arch/powerpc/cpu/mpc83xx/start.S
arch/powerpc/cpu/mpc85xx/start.S
arch/powerpc/cpu/mpc86xx/start.S
arch/powerpc/cpu/mpc8xx/start.S
arch/powerpc/cpu/ppc4xx/start.S
arch/powerpc/lib/board.c
board/a4m072/Makefile [new file with mode: 0644]
board/a4m072/a4m072.c [new file with mode: 0644]
board/a4m072/config.mk [new file with mode: 0644]
board/a4m072/mt46v32m16.h [new file with mode: 0644]
board/davinci/common/misc.c
board/davinci/common/misc.h
board/davinci/da8xxevm/da830evm.c
board/davinci/dm365evm/dm365evm.c
board/davinci/dvevm/dvevm.c
board/davinci/sffsdr/sffsdr.c
board/davinci/sonata/sonata.c
board/pdm360ng/pdm360ng.c
board/ppmc7xx/ppmc7xx.c
board/xilinx/microblaze-generic/microblaze-generic.c
boards.cfg
common/cmd_display.c
common/cmd_flash.c
common/cmd_mem.c
common/cmd_mtdparts.c
common/cmd_nand.c
common/cmd_net.c
common/cmd_tsi148.c
common/env_common.c
common/fdt_support.c
common/usb_storage.c
doc/README.LED_display [new file with mode: 0644]
drivers/misc/Makefile
drivers/misc/pdsp188x.c [new file with mode: 0644]
drivers/mtd/cfi_flash.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_bbt.c
drivers/mtd/nand/nand_ecc.c
drivers/mtd/nand/nand_util.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/spi/spi_flash.c
drivers/net/Makefile
drivers/net/at91_emac.c
drivers/net/davinci_emac.c
drivers/net/enc28j60.c
drivers/net/enc28j60.h [new file with mode: 0644]
drivers/net/enc28j60_lpc2292.c [new file with mode: 0644]
drivers/net/mpc5xxx_fec.c
drivers/net/smc91111.c
drivers/net/xilinx_emaclite.c
drivers/qe/uec.c
drivers/qe/uec_phy.c
drivers/usb/gadget/ether.c
drivers/usb/host/ohci-hcd.c
drivers/usb/musb/musb_hcd.c
examples/standalone/Makefile
fs/fat/fat.c
include/config_cmd_all.h
include/configs/SMN42.h
include/configs/a4m072.h [new file with mode: 0644]
include/configs/hmi1001.h
include/configs/lpc2292sodimm.h
include/configs/manroland/common.h
include/configs/microblaze-generic.h
include/fat.h
include/fdt_support.h
include/led-display.h [new file with mode: 0644]
include/linux/mtd/mtd.h
include/linux/mtd/onenand.h
include/mpc5xxx.h
include/nand.h
include/netdev.h
lib/gunzip.c
lib/zlib.c
net/Makefile
net/eth.c
net/net.c
tools/imls/Makefile

index a394ac942308c3731d509e42ec29569c743351ed..aabd87134861141e3314b3d36db6793166fcbc22 100644 (file)
@@ -305,6 +305,10 @@ Andrea "llandre" Marson <andrea.marson@dave-tech.it>
 
        PPChameleonEVB  PPC405EP
 
+Tirumala Marri <tmarri@apm.com>
+
+       bluestone       APM821XX
+
 Reinhard Meyer <r.meyer@emk-elektronik.de>
 
        TOP860          MPC860T
@@ -343,6 +347,10 @@ Daniel Poirot <dan.poirot@windriver.com>
        sbc8240         MPC8240
        sbc405          PPC405GP
 
+Sergei Poselenov <sposelenov@emcraft.com>
+
+       a4m072          MPC5200
+
 Sudhakar Rajashekhara <sudhakar.raj@ti.com>
 
        da850evm        ARM926EJS (DA850/OMAP-L138)
@@ -498,10 +506,6 @@ Detlev Zundel <dzu@denx.de>
 
        inka4x0         MPC5200
 
-Tirumala Marri <tmarri@apm.com>
-
-       bluestone       APM821XX
-
 -------------------------------------------------------------------------
 
 Unknown / orphaned boards:
diff --git a/README b/README
index f997a5d8605e91ff085da24eeaceac926cf9f194..197804e354e1bb36268f7fa56780141b3ecd0714 100644 (file)
--- a/README
+++ b/README
@@ -2534,18 +2534,32 @@ to save the current settings.
        - CONFIG_ENV_SIZE:
 
          These two #defines specify the offset and size of the environment
-         area within the first NAND device.
+         area within the first NAND device.  CONFIG_ENV_OFFSET must be
+         aligned to an erase block boundary.
 
-       - CONFIG_ENV_OFFSET_REDUND
+       - CONFIG_ENV_OFFSET_REDUND (optional):
 
          This setting describes a second storage area of CONFIG_ENV_SIZE
-         size used to hold a redundant copy of the environment data,
-         so that there is a valid backup copy in case there is a
-         power failure during a "saveenv" operation.
-
-       Note: CONFIG_ENV_OFFSET and CONFIG_ENV_OFFSET_REDUND must be aligned
-       to a block boundary, and CONFIG_ENV_SIZE must be a multiple of
-       the NAND devices block size.
+         size used to hold a redundant copy of the environment data, so
+         that there is a valid backup copy in case there is a power failure
+         during a "saveenv" operation.  CONFIG_ENV_OFFSET_RENDUND must be
+         aligned to an erase block boundary.
+
+       - CONFIG_ENV_RANGE (optional):
+
+         Specifies the length of the region in which the environment
+         can be written.  This should be a multiple of the NAND device's
+         block size.  Specifying a range with more erase blocks than
+         are needed to hold CONFIG_ENV_SIZE allows bad blocks within
+         the range to be avoided.
+
+       - CONFIG_ENV_OFFSET_OOB (optional):
+
+         Enables support for dynamically retrieving the offset of the
+         environment from block zero's out-of-band data.  The
+         "nand env.oob" command can be used to record this offset.
+         Currently, CONFIG_ENV_OFFSET_REDUND is not supported when
+         using CONFIG_ENV_OFFSET_OOB.
 
 - CONFIG_NAND_ENV_DST
 
index 35a1585d17baf1a43459869edbbda419b1bac75c..76493a138a40fc3af69f6ac2f8c89da35d7b150d 100644 (file)
@@ -367,7 +367,6 @@ typedef struct  {
 
 int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data);
 int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data);
-void davinci_eth_set_mac_addr(const u_int8_t *addr);
 
 typedef struct
 {
index 5f2dfd08acf9f083056d790a5cd87bf159a2de6b..22bd2c9b0e2e9bc81e6fee8969356a48ee990382 100644 (file)
@@ -409,15 +409,6 @@ void start_armboot (void)
        enable_interrupts ();
 
        /* Perform network card initialisation if necessary */
-#ifdef CONFIG_DRIVER_TI_EMAC
-       /* XXX: this needs to be moved to board init */
-extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
-       if (getenv ("ethaddr")) {
-               uchar enetaddr[6];
-               eth_getenv_enetaddr("ethaddr", enetaddr);
-               davinci_eth_set_mac_addr(enetaddr);
-       }
-#endif
 
 #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
        /* XXX: this needs to be moved to board init */
@@ -821,16 +812,6 @@ void board_init_r (gd_t *id, ulong dest_addr)
        enable_interrupts ();
 
        /* Perform network card initialisation if necessary */
-#ifdef CONFIG_DRIVER_TI_EMAC
-       /* XXX: this needs to be moved to board init */
-extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
-       if (getenv ("ethaddr")) {
-               uchar enetaddr[6];
-               eth_getenv_enetaddr("ethaddr", enetaddr);
-               davinci_eth_set_mac_addr(enetaddr);
-       }
-#endif
-
 #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
        /* XXX: this needs to be moved to board init */
        if (getenv ("ethaddr")) {
index 2e9a08dc54d39422ca21ec6045f5ba4c14e36161..7f6043413e30ef220f42436833c73c97d77ba530 100644 (file)
@@ -32,6 +32,22 @@ _start:
        mts     rmsr, r0        /* disable cache */
        addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET
        addi    r1, r1, -4      /* Decrement SP to top of memory */
+
+       /* Find-out if u-boot is running on BIG/LITTLE endian platform
+        * There are some steps which is necessary to keep in mind:
+        * 1. Setup offset value to r6
+        * 2. Store word offset value to address 0x0
+        * 3. Load just byte from address 0x0
+        * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
+        *     value that's why is on address 0x0
+        * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
+        */
+       addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
+       swi     r6, r0, 0
+       lbui    r10, r0, 0
+       swi     r6, r0, 0x40
+       swi     r10, r0, 0x50
+
        /* add opcode instruction for 32bit jump - 2 instruction imm & brai*/
        addi    r6, r0, 0xb0000000      /* hex b000 opcode imm */
        swi     r6, r0, 0x0     /* reset address */
@@ -75,26 +91,52 @@ _start:
        /* user_vector_exception */
        addik   r6, r0, _exception_handler
        sw      r6, r1, r0
-       lhu     r7, r1, r0
-       shi     r7, r0, 0xa
-       shi     r6, r0, 0xe
+       /*
+        * BIG ENDIAN memory map for user exception
+        * 0x8: 0xB000XXXX
+        * 0xC: 0xB808XXXX
+        *
+        * then it is necessary to count address for storing the most significant
+        * 16bits from _exception_handler address and copy it to 
+        * 0xa address. Big endian use offset in r10=0 that's why is it just
+        * 0xa address. The same is done for the least significant 16 bits
+        * for 0xe address.
+        *
+        * LITTLE ENDIAN memory map for user exception
+        * 0x8: 0xXXXX00B0
+        * 0xC: 0xXXXX08B8
+        *
+        * Offset is for little endian setup to 0x2. rsubi instruction decrease
+        * address value to ensure that points to proper place which is
+        * 0x8 for the most significant 16 bits and
+        * 0xC for the least significant 16 bits
+        */
+       lhu     r7, r1, r10
+       rsubi   r8, r10, 0xa
+       sh      r7, r0, r8
+       rsubi   r8, r10, 0xe
+       sh      r6, r0, r8
 #endif
 
 #ifdef CONFIG_SYS_INTC_0
        /* interrupt_handler */
        addik   r6, r0, _interrupt_handler
        sw      r6, r1, r0
-       lhu     r7, r1, r0
-       shi     r7, r0, 0x12
-       shi     r6, r0, 0x16
+       lhu     r7, r1, r10
+       rsubi   r8, r10, 0x12
+       sh      r7, r0, r8
+       rsubi   r8, r10, 0x16
+       sh      r6, r0, r8
 #endif
 
        /* hardware exception */
        addik   r6, r0, _hw_exception_handler
        sw      r6, r1, r0
-       lhu     r7, r1, r0
-       shi     r7, r0, 0x22
-       shi     r6, r0, 0x26
+       lhu     r7, r1, r10
+       rsubi   r8, r10, 0x22
+       sh      r7, r0, r8
+       rsubi   r8, r10, 0x26
+       sh      r6, r0, r8
 
        /* enable instruction and data cache */
        mfs     r12, rmsr
index a4a75b7a6dc78d3aa850ceff6ecadd55899349d7..b2757a41f8a43205d33abe10d7d3db7ad36ccf96 100644 (file)
@@ -50,6 +50,10 @@ static __inline__ __u16 ___arch__swab16 (__u16 half_word)
 
 #endif /* __GNUC__ */
 
+#ifdef __MICROBLAZEEL__
+#include <linux/byteorder/little_endian.h>
+#else
 #include <linux/byteorder/big_endian.h>
+#endif
 
 #endif /* __MICROBLAZE_BYTEORDER_H__ */
index 3ff5c17d244c6e04f2db06a11e50a3a3c8d4dc41..0ce040e9efc1bebbe351189c526d31679424a36f 100644 (file)
@@ -31,6 +31,7 @@
 #include <version.h>
 #include <watchdog.h>
 #include <stdio_dev.h>
+#include <net.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -42,6 +43,7 @@ extern int gpio_init (void);
 #ifdef CONFIG_SYS_INTC_0
 extern int interrupts_init (void);
 #endif
+
 #if defined(CONFIG_CMD_NET)
 extern int eth_init (bd_t * bis);
 #endif
@@ -165,8 +167,14 @@ void board_init (void)
 
 #if defined(CONFIG_CMD_NET)
        /* IP Address */
-       bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
-       eth_init (bd);
+       bd->bi_ip_addr = getenv_IPaddr("ipaddr");
+
+       printf("Net:   ");
+       eth_initialize(gd->bd);
+
+       uchar enetaddr[6];
+       eth_getenv_enetaddr("ethaddr", enetaddr);
+       printf("MAC:   %pM\n", enetaddr);
 #endif
 
        /* main_loop */
index a36af5a83fd4967e747e3d36cbaf000966e8a57e..47694aa1f29d28891ed85d87894f0f7c7f142011 100644 (file)
@@ -94,17 +94,7 @@ version_string:
        . = EXC_OFF_SYS_RESET
        .globl  _start
 _start:
-       li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH */
        b       boot_cold
-       sync
-
-       . = EXC_OFF_SYS_RESET + 0x10
-
-       .globl  _start_warm
-_start_warm:
-       li      r21, BOOTFLAG_WARM      /* Software reboot              */
-       b       boot_warm
-       sync
 
        /* the boot code is located below the exception table */
 
@@ -188,7 +178,6 @@ _end_of_vectors:
        . = 0x2000
 
 boot_cold:
-boot_warm:
        /* disable everything */
        li      r0, 0
        mtspr   HID0, r0
@@ -288,14 +277,11 @@ in_flash:
        bl      cpu_init_f
        sync
 
-       mr      r3, r21
-
-       /* r3: BOOTFLAG */
        /* run 1st part of board init code (from Flash)   */
        bl      board_init_f
        sync
 
-       /* NOTREACHED */
+       /* NOTREACHED - board_init_f() does not return */
 
        .globl  invalidate_bats
 invalidate_bats:
index d26b61707e07057c8d82c74af0579b3150d10490..1047c513f9d3dee71948d883a053789d413160e7 100644 (file)
@@ -100,7 +100,6 @@ version_string:
        .globl  _start
        /* Start from here after reset/power on */
 _start:
-       li      r21, BOOTFLAG_COLD  /* Normal Power-On: Boot from FLASH */
        b       boot_cold
 
        .globl  _start_of_vectors
@@ -260,8 +259,6 @@ in_flash:
        /* run low-level CPU init code (in Flash) */
        bl      cpu_init_f
 
-       /* r3: BOOTFLAG */
-       mr      r3, r21
        /* run 1st part of board init code (in Flash) */
        bl      board_init_f
 
index 0af879e39130577fa757ab065f0acd28f327f472..4fd9b63e5abe864994a7db286c54982c92eae8db 100644 (file)
@@ -91,18 +91,6 @@ _start:
        li      r4, CONFIG_SYS_ISB                      /* Set ISB bit */
        or      r3, r3, r4
        mtspr   638, r3
-       li      r21, BOOTFLAG_COLD              /* Normal Power-On: Boot from FLASH     */
-       b       boot_cold
-
-       . = EXC_OFF_SYS_RESET + 0x20
-
-       .globl  _start_warm
-_start_warm:
-       li      r21, BOOTFLAG_WARM              /* Software reboot */
-       b       boot_warm
-
-boot_cold:
-boot_warm:
 
        /* Initialize machine status; enable machine check interrupt            */
        /*----------------------------------------------------------------------*/
@@ -188,10 +176,10 @@ in_flash:
        /* r3: IMMR */
        bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
 
-       mr      r3, r21
-       /* r3: BOOTFLAG */
        bl      board_init_f    /* run 1st part of board init code (from Flash) */
 
+       /* NOTREACHED - board_init_f() does not return */
+
 
        .globl  _start_of_vectors
 _start_of_vectors:
index 8b9f09b39d3ce6eabd3f529bae23803be0858391..1385869e759bb1165a978c3c633c33c309583194 100644 (file)
@@ -89,19 +89,6 @@ version_string:
        . = EXC_OFF_SYS_RESET
        .globl  _start
 _start:
-       li      r21, BOOTFLAG_COLD      /* Normal Power-On              */
-       nop
-       b       boot_cold
-
-       . = EXC_OFF_SYS_RESET + 0x10
-
-       .globl  _start_warm
-_start_warm:
-       li      r21, BOOTFLAG_WARM      /* Software reboot              */
-       b       boot_warm
-
-boot_cold:
-boot_warm:
        mfmsr   r5                      /* save msr contents            */
 
        /* Move CSBoot and adjust instruction pointer                   */
@@ -175,10 +162,10 @@ lowboot_reentry:
        /* r3: IMMR */
        bl      cpu_init_f      /* run low-level CPU init code (in Flash)*/
 
-       mr      r3, r21
-       /* r3: BOOTFLAG */
        bl      board_init_f    /* run 1st part of board init code (in Flash)*/
 
+       /* NOTREACHED - board_init_f() does not return */
+
 /*
  * Vector Table
  */
index 3d79d8ec0d29b7240db4f87c4d9286ddc1a2e0eb..c156e25747bd50be2df91e36621953a2ea86501e 100644 (file)
@@ -88,19 +88,6 @@ version_string:
        . = EXC_OFF_SYS_RESET
        .globl  _start
 _start:
-       li      r21, BOOTFLAG_COLD  /* Normal Power-On      */
-       nop
-       b       boot_cold
-
-       . = EXC_OFF_SYS_RESET + 0x10
-
-       .globl  _start_warm
-_start_warm:
-       li      r21, BOOTFLAG_WARM  /* Software reboot      */
-       b       boot_warm
-
-boot_cold:
-boot_warm:
        mfmsr   r5                  /* save msr contents    */
 
        /* replace default MBAR base address from 0x80000000
@@ -144,10 +131,10 @@ boot_warm:
        /* r3: IMMR */
        bl      cpu_init_f      /* run low-level CPU init code (in Flash)*/
 
-       mr      r3, r21
-       /* r3: BOOTFLAG */
        bl      board_init_f    /* run 1st part of board init code (in Flash)*/
 
+       /* NOTREACHED - board_init_f() does not return */
+
 /*
  * Vector Table
  */
index f3f595af25d9ae190d7e277bd517a04aa906b44d..5b126bb9a24f238651b9923a2ddde58a6ae07d50 100644 (file)
@@ -97,19 +97,6 @@ version_string:
        . = EXC_OFF_SYS_RESET
        .globl  _start
 _start:
-       li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH     */
-       b       boot_cold
-
-       . = EXC_OFF_SYS_RESET + 0x10
-
-       .globl  _start_warm
-_start_warm:
-       li      r21, BOOTFLAG_WARM      /* Software reboot                      */
-       b       boot_warm
-
-boot_cold:
-boot_warm:
-
        /* Initialize machine status; enable machine check interrupt            */
        /*----------------------------------------------------------------------*/
        li      r3, MSR_KERNEL          /* Set FP, ME, RI flags */
@@ -198,10 +185,10 @@ in_flash:
        /* r3: IMMR */
        bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
 
-       mr      r3, r21
-       /* r3: BOOTFLAG */
        bl      board_init_f    /* run 1st part of board init code (from Flash) */
 
+       /* NOTREACHED - board_init_f() does not return */
+
 
        .globl  _start_of_vectors
 _start_of_vectors:
index a43504276b0c3086733ad4eaaed78de6fe6e6019..9485afa9c94cac97f91c4717c129be9c69b97672 100644 (file)
@@ -161,18 +161,6 @@ _hrcw_table:
 
        .globl  _start
 _start:
-       li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH*/
-       nop
-       b       boot_cold
-
-       . = EXC_OFF_SYS_RESET + 0x10
-
-       .globl  _start_warm
-_start_warm:
-       li      r21, BOOTFLAG_WARM      /* Software reboot              */
-       b       boot_warm
-
-boot_cold:
 #if defined(CONFIG_MPC8260ADS) && defined(CONFIG_SYS_DEFAULT_IMMR)
        lis     r3, CONFIG_SYS_DEFAULT_IMMR@h
        nop
@@ -185,7 +173,7 @@ boot_cold:
        stw     r4, 0(r3)
        nop
 #endif /* CONFIG_MPC8260ADS && CONFIG_SYS_DEFAULT_IMMR */
-boot_warm:
+
        mfmsr   r5                      /* save msr contents            */
 
 #if defined(CONFIG_COGENT)
@@ -254,10 +242,10 @@ in_flash:
        bl      init_debug      /* set up debugging stuff               */
 #endif
 
-       mr      r3, r21
-       /* r3: BOOTFLAG */
        bl      board_init_f    /* run 1st part of board init code (in Flash)*/
 
+       /* NOTREACHED - board_init_f() does not return */
+
 /*
  * Vector Table
  */
index c7d85a878ec547c6bf3e08a7b16c4fa244a5fb5c..bdce91581cd8664e65212b6248aa65d9fdccbc71 100644 (file)
@@ -183,22 +183,9 @@ ppcDWload:
 
        .globl  _start
 _start: /* time t 0 */
-       li      r21, BOOTFLAG_COLD  /* Normal Power-On: Boot from FLASH*/
-       nop
-       b       boot_cold
-
-       . = EXC_OFF_SYS_RESET + 0x10
-
-       .globl  _start_warm
-_start_warm:
-       li      r21, BOOTFLAG_WARM      /* Software reboot      */
-       b       boot_warm
-
-
-boot_cold: /* time t 3 */
        lis     r4, CONFIG_DEFAULT_IMMR@h
        nop
-boot_warm: /* time t 5 */
+
        mfmsr   r5                      /* save msr contents    */
 
        /* 83xx manuals prescribe a specific sequence for updating IMMRBAR. */
@@ -302,11 +289,11 @@ in_flash:
        /* run low-level CPU init code (in Flash)*/
        bl      cpu_init_f
 
-       /* r3: BOOTFLAG */
-       mr      r3, r21
        /* run 1st part of board init code (in Flash)*/
        bl      board_init_f
 
+       /* NOTREACHED - board_init_f() does not return */
+
 #ifndef CONFIG_NAND_SPL
 /*
  * Vector Table
index 3278b109feb56626ddbbf311025a4dfbc524bc5b..91096ad588d6c56cdb1c9bb834c988d653c1c472 100644 (file)
@@ -432,6 +432,8 @@ _start_cont:
        bl      board_init_f
        isync
 
+       /* NOTREACHED - board_init_f() does not return */
+
 #ifndef CONFIG_NAND_SPL
        . = EXC_OFF_SYS_RESET
        .globl  _start_of_vectors
index ed1e4ca6681e729f148644e0af3d0e5fa2e86fd9..596053f8857e5bf6a306cdf11b0c86685bc2a200 100644 (file)
@@ -83,17 +83,7 @@ version_string:
        . = EXC_OFF_SYS_RESET
        .globl  _start
 _start:
-       li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH */
        b       boot_cold
-       sync
-
-       . = EXC_OFF_SYS_RESET + 0x10
-
-       .globl  _start_warm
-_start_warm:
-       li      r21, BOOTFLAG_WARM      /* Software reboot */
-       b       boot_warm
-       sync
 
        /* the boot code is located below the exception table */
 
@@ -166,7 +156,6 @@ _end_of_vectors:
        . = 0x2000
 
 boot_cold:
-boot_warm:
        /*
         * NOTE: Only Cpu 0 will ever come here.  Other cores go to an
         * address specified by the BPTR
@@ -303,14 +292,12 @@ diag_done:
 #endif
 
 /*     bl      l2cache_enable */
-       mr      r3, r21
 
-       /* r3: BOOTFLAG */
        /* run 1st part of board init code (from Flash)   */
        bl      board_init_f
        sync
 
-       /* NOTREACHED */
+       /* NOTREACHED - board_init_f() does not return */
 
        .globl  invalidate_bats
 invalidate_bats:
index 7cf602fd4b8e9bc28233735332314a3d760b5417..d6100ec14ea15a4b4dd53273a2703dfe7b9edb16 100644 (file)
@@ -96,18 +96,6 @@ version_string:
 _start:
        lis     r3, CONFIG_SYS_IMMR@h           /* position IMMR */
        mtspr   638, r3
-       li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH     */
-       b       boot_cold
-
-       . = EXC_OFF_SYS_RESET + 0x10
-
-       .globl  _start_warm
-_start_warm:
-       li      r21, BOOTFLAG_WARM      /* Software reboot                      */
-       b       boot_warm
-
-boot_cold:
-boot_warm:
 
        /* Initialize machine status; enable machine check interrupt            */
        /*----------------------------------------------------------------------*/
@@ -202,10 +190,10 @@ in_flash:
        /* r3: IMMR */
        bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
 
-       mr      r3, r21
-       /* r3: BOOTFLAG */
        bl      board_init_f    /* run 1st part of board init code (from Flash) */
 
+       /* NOTREACHED - board_init_f() does not return */
+
 
        .globl  _start_of_vectors
 _start_of_vectors:
index c2d52bfb9f173b86679302742d869087e7ca5c31..03bde4d401c78c654e6839a69d56c7ee9d04f45b 100644 (file)
        GET_GOT
        bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
        bl      board_init_f
+       /* NOTREACHED - board_init_f() does not return */
 #endif
 
 #if defined(CONFIG_SYS_RAMBOOT)
@@ -803,6 +804,7 @@ _start:
 
        bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
        bl      board_init_f
+       /* NOTREACHED - board_init_f() does not return */
 #endif
 
 #endif /* CONFIG_440 */
@@ -911,6 +913,7 @@ _start:
        GET_GOT                 /* initialize GOT access                        */
 
        bl      board_init_f    /* run first part of init code (from Flash)     */
+       /* NOTREACHED - board_init_f() does not return */
 
 #endif /* CONFIG_IOP480 */
 
@@ -1180,8 +1183,9 @@ _start:
 
        bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
 
-       /* NEVER RETURNS! */
        bl      board_init_f    /* run first part of init code (from Flash)     */
+       /* NOTREACHED - board_init_f() does not return */
+
 #endif /* CONFIG_NAND_SPL */
 
 #endif /* CONFIG_405GP || CONFIG_405CR || CONFIG_405 || CONFIG_405EP */
index bfdfa86249642f159aecd04710babfe671394887..529f71960d7ce62dfbfbc897ebe86443d23f8fda 100644 (file)
@@ -480,6 +480,7 @@ void board_init_f (ulong bootflag)
         */
        addr_sp -= sizeof (bd_t);
        bd = (bd_t *) addr_sp;
+       memset(bd, 0, sizeof(bd_t));
        gd->bd = bd;
        debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
                        sizeof (bd_t), addr_sp);
@@ -512,9 +513,6 @@ void board_init_f (ulong bootflag)
 #ifdef CONFIG_SYS_SRAM_BASE
        bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;        /* start of  SRAM memory        */
        bd->bi_sramsize  = CONFIG_SYS_SRAM_SIZE;        /* size  of  SRAM memory        */
-#else
-       bd->bi_sramstart = 0;
-       bd->bi_sramsize  = 0;
 #endif
 
 #if defined(CONFIG_8xx) || defined(CONFIG_8260) || defined(CONFIG_5xx) || \
@@ -739,14 +737,7 @@ void board_init_r (gd_t *id, ulong dest_addr)
        bd->bi_flashoffset = TEXT_BASE + flash_size;
 # elif CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
        bd->bi_flashoffset = monitor_flash_len; /* reserved area for startup monitor  */
-# else
-       bd->bi_flashoffset = 0;
 # endif
-#else  /* CONFIG_SYS_NO_FLASH */
-
-       bd->bi_flashsize = 0;
-       bd->bi_flashstart = 0;
-       bd->bi_flashoffset = 0;
 #endif /* !CONFIG_SYS_NO_FLASH */
 
        WATCHDOG_RESET ();
@@ -803,14 +794,8 @@ void board_init_r (gd_t *id, ulong dest_addr)
                if (s && ((*s == 'y') || (*s == 'Y'))) {
                        bd->bi_iic_fast[0] = 1;
                        bd->bi_iic_fast[1] = 1;
-               } else {
-                       bd->bi_iic_fast[0] = 0;
-                       bd->bi_iic_fast[1] = 0;
                }
        }
-#else
-       bd->bi_iic_fast[0] = 0;
-       bd->bi_iic_fast[1] = 0;
 #endif /* CONFIG_I2CFAST */
 #endif /* CONFIG_405GP, CONFIG_405EP */
 #endif /* CONFIG_SYS_EXTBDINFO */
diff --git a/board/a4m072/Makefile b/board/a4m072/Makefile
new file mode 100644 (file)
index 0000000..442e2d0
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(BOARD).a
+
+COBJS  := $(BOARD).o
+
+SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+SOBJS  := $(addprefix $(obj),$(SOBJS))
+
+$(LIB):        $(obj).depend $(OBJS)
+       $(AR) $(ARFLAGS) $@ $(OBJS)
+
+clean:
+       rm -f $(SOBJS) $(OBJS)
+
+distclean:     clean
+       rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/a4m072/a4m072.c b/board/a4m072/a4m072.c
new file mode 100644 (file)
index 0000000..ae7ccbb
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2004
+ * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
+ *
+ * (C) Copyright 2010
+ * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <libfdt.h>
+#include <netdev.h>
+#include <led-display.h>
+#include <linux/err.h>
+
+#include "mt46v32m16.h"
+
+#ifndef CONFIG_SYS_RAMBOOT
+static void sdram_start (int hi_addr)
+{
+       long hi_addr_bit = hi_addr ? 0x01000000 : 0;
+       long control = SDRAM_CONTROL | hi_addr_bit;
+
+       /* unlock mode register */
+       out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000000);
+       __asm__ volatile ("sync");
+
+       /* precharge all banks */
+       out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000002);
+       __asm__ volatile ("sync");
+
+#if SDRAM_DDR
+       /* set mode register: extended mode */
+       out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_EMODE);
+       __asm__ volatile ("sync");
+
+       /* set mode register: reset DLL */
+       out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_MODE | 0x04000000);
+       __asm__ volatile ("sync");
+#endif
+
+       /* precharge all banks */
+       out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000002);
+       __asm__ volatile ("sync");
+
+       /* auto refresh */
+       out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000004);
+       __asm__ volatile ("sync");
+
+       /* set mode register */
+       out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_MODE);
+       __asm__ volatile ("sync");
+
+       /* normal operation */
+       out_be32((void *)MPC5XXX_SDRAM_CTRL, control);
+       __asm__ volatile ("sync");
+}
+#endif
+
+/*
+ * ATTENTION: Although partially referenced initdram does NOT make real use
+ *            use of CONFIG_SYS_SDRAM_BASE. The code does not work if CONFIG_SYS_SDRAM_BASE
+ *            is something else than 0x00000000.
+ */
+
+phys_size_t initdram (int board_type)
+{
+       ulong dramsize = 0;
+       uint svr, pvr;
+
+#ifndef CONFIG_SYS_RAMBOOT
+       ulong test1, test2;
+
+       /* setup SDRAM chip selects */
+       out_be32((void *)MPC5XXX_SDRAM_CS0CFG, 0x0000001e); /* 2GB at 0x0 */
+       out_be32((void *)MPC5XXX_SDRAM_CS1CFG, 0x80000000); /* disabled */
+       __asm__ volatile ("sync");
+
+       /* setup config registers */
+       out_be32((void *)MPC5XXX_SDRAM_CONFIG1, SDRAM_CONFIG1);
+       out_be32((void *)MPC5XXX_SDRAM_CONFIG2, SDRAM_CONFIG2);
+       __asm__ volatile ("sync");
+
+#if SDRAM_DDR
+       /* set tap delay */
+       out_be32((void *)MPC5XXX_CDM_PORCFG, SDRAM_TAPDELAY);
+       __asm__ volatile ("sync");
+#endif
+
+       /* find RAM size using SDRAM CS0 only */
+       sdram_start(0);
+       test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
+       sdram_start(1);
+       test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
+       if (test1 > test2) {
+               sdram_start(0);
+               dramsize = test1;
+       } else {
+               dramsize = test2;
+       }
+
+       /* memory smaller than 1MB is impossible */
+       if (dramsize < (1 << 20)) {
+               dramsize = 0;
+       }
+
+       /* set SDRAM CS0 size according to the amount of RAM found */
+       if (dramsize > 0) {
+               out_be32((void *)MPC5XXX_SDRAM_CS0CFG,
+                                0x13 + __builtin_ffs(dramsize >> 20) - 1);
+       } else {
+               out_be32((void *)MPC5XXX_SDRAM_CS0CFG, 0); /* disabled */
+       }
+
+#else /* CONFIG_SYS_RAMBOOT */
+
+       /* retrieve size of memory connected to SDRAM CS0 */
+       dramsize = in_be32((void *)MPC5XXX_SDRAM_CS0CFG) & 0xFF;
+       if (dramsize >= 0x13) {
+               dramsize = (1 << (dramsize - 0x13)) << 20;
+       } else {
+               dramsize = 0;
+       }
+
+#endif /* CONFIG_SYS_RAMBOOT */
+
+       /*
+        * On MPC5200B we need to set the special configuration delay in the
+        * DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM
+        * Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190:
+        *
+        * "The SDelay should be written to a value of 0x00000004. It is
+        * required to account for changes caused by normal wafer processing
+        * parameters."
+        */
+       svr = get_svr();
+       pvr = get_pvr();
+       if ((SVR_MJREV(svr) >= 2) &&
+           (PVR_MAJ(pvr) == 1) && (PVR_MIN(pvr) == 4)) {
+
+               out_be32((void *)MPC5XXX_SDRAM_SDELAY, 0x04);
+               __asm__ volatile ("sync");
+       }
+
+       return dramsize;
+}
+
+int checkboard (void)
+{
+       puts ("Board: A4M072\n");
+       return 0;
+}
+
+#ifdef CONFIG_PCI
+static struct pci_controller hose;
+
+extern void pci_mpc5xxx_init(struct pci_controller *);
+
+void pci_init_board(void)
+{
+       pci_mpc5xxx_init(&hose);
+}
+#endif
+
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+void
+ft_board_setup(void *blob, bd_t *bd)
+{
+       ft_cpu_setup(blob, bd);
+}
+#endif
+
+int board_eth_init(bd_t *bis)
+{
+       int rv, num_if = 0;
+
+       /* Initialize TSECs first */
+       if ((rv = cpu_eth_init(bis)) >= 0)
+               num_if += rv;
+       else
+               printf("ERROR: failed to initialize FEC.\n");
+
+       if ((rv = pci_eth_init(bis)) >= 0)
+               num_if += rv;
+       else
+               printf("ERROR: failed to initialize PCI Ethernet.\n");
+
+       return num_if;
+}
+/*
+ * Miscellaneous late-boot configurations
+ *
+ * Initialize EEPROM write-protect GPIO pin.
+ */
+int misc_init_r(void)
+{
+#if defined(CONFIG_SYS_EEPROM_WREN)
+       /* Enable GPIO pin */
+       setbits_be32((void *)MPC5XXX_WU_GPIO_ENABLE, CONFIG_SYS_EEPROM_WP);
+       /* Set direction, output */
+       setbits_be32((void *)MPC5XXX_WU_GPIO_DIR, CONFIG_SYS_EEPROM_WP);
+       /* De-assert write enable */
+       setbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O, CONFIG_SYS_EEPROM_WP);
+#endif
+       return 0;
+}
+#if defined(CONFIG_SYS_EEPROM_WREN)
+/* Input: <dev_addr>  I2C address of EEPROM device to enable.
+ *         <state>     -1: deliver current state
+ *                    0: disable write
+ *                    1: enable write
+ *  Returns:           -1: wrong device address
+ *                      0: dis-/en- able done
+ *                  0/1: current state if <state> was -1.
+ */
+int eeprom_write_enable (unsigned dev_addr, int state)
+{
+       if (CONFIG_SYS_I2C_EEPROM_ADDR != dev_addr) {
+               return -1;
+       } else {
+               switch (state) {
+               case 1:
+                       /* Enable write access */
+                       clrbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O, CONFIG_SYS_EEPROM_WP);
+                       state = 0;
+                       break;
+               case 0:
+                       /* Disable write access */
+                       setbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O, CONFIG_SYS_EEPROM_WP);
+                       state = 0;
+                       break;
+               default:
+                       /* Read current status back. */
+                       state = (0 == (in_be32((void *)MPC5XXX_WU_GPIO_DATA_O) &
+                                                  CONFIG_SYS_EEPROM_WP));
+                       break;
+               }
+       }
+       return state;
+}
+#endif
+
+#ifdef CONFIG_CMD_DISPLAY
+#define DISPLAY_BUF_SIZE       2
+static u8 display_buf[DISPLAY_BUF_SIZE];
+static u8 display_putc_pos;
+static u8 display_out_pos;
+
+static u8 display_dot_enable;
+
+void display_set(int cmd) {
+
+       if (cmd & DISPLAY_CLEAR) {
+               display_buf[0] = display_buf[1] = 0;
+       }
+
+       if (cmd & DISPLAY_HOME) {
+               display_putc_pos = 0;
+       }
+
+       if (cmd & DISPLAY_MARK) {
+               display_dot_enable = 1;
+       } else {
+               display_dot_enable = 0;
+       }
+}
+
+#define SEG_A    (1<<0)
+#define SEG_B    (1<<1)
+#define SEG_C    (1<<2)
+#define SEG_D    (1<<3)
+#define SEG_E    (1<<4)
+#define SEG_F    (1<<5)
+#define SEG_G    (1<<6)
+#define SEG_P    (1<<7)
+#define SEG__    0
+
+/*
+ * +- A -+
+ * |     |
+ * F     B
+ * |     |
+ * +- G -+
+ * |     |
+ * E     C
+ * |     |
+ * +- D -+  P
+ *
+ * 0..9                index 0..9
+ * A..Z                index 10..35
+ * -           index 36
+ * _           index 37
+ */
+
+#define SYMBOL_DASH            (36)
+#define SYMBOL_UNDERLINE       (37)
+
+static u8 display_char2seg7_tbl[]=
+{
+       SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,          /* 0 */
+       SEG_B | SEG_C,                                          /* 1 */
+       SEG_A | SEG_B | SEG_D | SEG_E | SEG_G,                  /* 2 */
+       SEG_A | SEG_B | SEG_C | SEG_D | SEG_G,                  /* 3 */
+       SEG_B | SEG_C | SEG_F | SEG_G,                          /* 4 */
+       SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,                  /* 5 */
+       SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,          /* 6 */
+       SEG_A | SEG_B | SEG_C,                                  /* 7 */
+       SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,  /* 8 */
+       SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,          /* 9 */
+       SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,          /* A */
+       SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,                  /* b */
+       SEG_A | SEG_D | SEG_E | SEG_F,                          /* C */
+       SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,                  /* d */
+       SEG_A | SEG_D | SEG_E | SEG_F | SEG_G,                  /* E */
+       SEG_A | SEG_E | SEG_F | SEG_G,                          /* F */
+       SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,          /* g */
+       SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,                  /* H */
+       SEG_E | SEG_F,                                          /* I */
+       SEG_B | SEG_C | SEG_D | SEG_E,                          /* J */
+       SEG_A,                                          /* K - special 1 */
+       SEG_D | SEG_E | SEG_F,                                  /* L */
+       SEG_B,                                          /* m - special 2 */
+       SEG_C | SEG_E | SEG_G,                                  /* n */
+       SEG_C | SEG_D | SEG_E | SEG_G,                          /* o */
+       SEG_A | SEG_B | SEG_E | SEG_F | SEG_G,                  /* P */
+       SEG_A | SEG_B | SEG_C | SEG_F | SEG_G,                  /* q */
+       SEG_E | SEG_G,                                          /* r */
+       SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,                  /* S */
+       SEG_D | SEG_E | SEG_F | SEG_G,                          /* t */
+       SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,                  /* U */
+       SEG_C | SEG_D | SEG_E | SEG_F,                          /* V */
+       SEG_C,                                          /* w - special 3 */
+       SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,                  /* X */
+       SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,                  /* Y */
+       SEG_A | SEG_B | SEG_D | SEG_E | SEG_G,                  /* Z */
+       SEG_G,                                                  /* - */
+       SEG_D                                                   /* _ */
+};
+
+/* Convert char to the LED segments representation */
+static u8 display_char2seg7(char c)
+{
+       u8 val = 0;
+
+       if (c >= '0' && c <= '9')
+               c -= '0';
+       else if (c >= 'a' && c <= 'z')
+               c -= 'a' - 10;
+       else if (c >= 'A' && c <= 'Z')
+               c -= 'A' - 10;
+       else if (c == '-')
+               c = SYMBOL_DASH;
+       else if ((c == '_') || (c == '.'))
+               c = SYMBOL_UNDERLINE;
+       else
+               c = ' ';        /* display unsupported symbols as space */
+
+       if (c != ' ')
+               val = display_char2seg7_tbl[(int)c];
+
+       /* Handle DP LED here */
+       if (display_dot_enable) {
+               val |= SEG_P;
+       }
+
+       return val;
+}
+
+static inline int display_putc_nomark(char c)
+{
+       if (display_putc_pos >= DISPLAY_BUF_SIZE)
+               return -1;
+
+       display_buf[display_putc_pos++] = display_char2seg7(c);
+       /* one-symbol message should be steady */
+       if (display_putc_pos == 1)
+               display_buf[display_putc_pos] = display_char2seg7(c);
+
+       return c;
+}
+
+int display_putc(char c)
+{
+       /* Mark the codes from the "display" command with the DP LED */
+       display_set(DISPLAY_MARK);
+       return display_putc_nomark(c);
+}
+
+/*
+ * Flush current symbol to the LED display hardware
+ */
+static inline void display_flush(void)
+{
+       u32 val = display_buf[display_out_pos];
+
+       val |= (val << 8) | (val << 16) | (val << 24);
+       out_be32((void *)CONFIG_SYS_DISP_CHR_RAM, val);
+}
+
+/*
+ * Output contents of the software display buffer to the LED display every 0.5s
+ */
+void board_show_activity(ulong timestamp)
+{
+       static ulong last;
+       static u8 once;
+
+       if (!once || (timestamp - last >= (CONFIG_SYS_HZ / 2))) {
+               display_flush();
+               display_out_pos ^= 1;
+               last = timestamp;
+               once = 1;
+       }
+}
+
+/*
+ * Empty fake function
+ */
+void show_activity(int arg)
+{
+}
+#endif
+#if defined (CONFIG_SHOW_BOOT_PROGRESS)
+static int a4m072_status2code(int status, char *buf)
+{
+       char c = 0;
+
+       if (((status > 0) && (status <= 8)) ||
+                               ((status >= 100) && (status <= 108)) ||
+                               ((status < 0) && (status >= -9)) ||
+                               (status == -100) || (status == -101) ||
+                               ((status <= -103) && (status >= -113))) {
+               c = '5';
+       } else if (((status >= 9) && (status <= 14)) ||
+                       ((status >= 120) && (status <= 123)) ||
+                       ((status >= 125) && (status <= 129)) ||
+                       ((status >= -13) && (status <= -10)) ||
+                       (status == -120) || (status == -122) ||
+                       ((status <= -124) && (status >= -127)) ||
+                       (status == -129)) {
+               c = '8';
+       } else if (status == 15) {
+               c = '9';
+       } else if ((status <= -30) && (status >= -32)) {
+               c = 'A';
+       } else if (((status <= -35) && (status >= -40)) ||
+                       ((status <= -42) && (status >= -51)) ||
+                       ((status <= -53) && (status >= -58)) ||
+                       (status == -64) ||
+                       ((status <= -80) && (status >= -83)) ||
+                       (status == -130) || (status == -140) ||
+                       (status == -150)) {
+               c = 'B';
+       }
+
+       if (c == 0)
+               return -EINVAL;
+
+       buf[0] = (status < 0) ? '-' : c;
+       buf[1] = c;
+
+       return 0;
+}
+
+void show_boot_progress(int status)
+{
+       char buf[2];
+
+       if (a4m072_status2code(status, buf) < 0)
+               return;
+
+       display_set(0); /* Clear DP Led */
+       display_putc_nomark(buf[0]);
+       display_putc_nomark(buf[1]);
+       display_set(DISPLAY_HOME);
+       display_out_pos = 0;    /* reset output position */
+
+       /* we want to flush status 15 now */
+       if (status == 15)
+               display_flush();
+}
+#endif
diff --git a/board/a4m072/config.mk b/board/a4m072/config.mk
new file mode 100644 (file)
index 0000000..c6ba51d
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# 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
+#
+
+#
+# a4m072 board:
+#
+#      Valid values for TEXT_BASE is:
+#
+#      0xFE000000   boot low
+#
+
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+
+ifndef TEXT_BASE
+## Standard: boot low
+TEXT_BASE = 0xFE000000
+endif
+
+PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board
diff --git a/board/a4m072/mt46v32m16.h b/board/a4m072/mt46v32m16.h
new file mode 100644 (file)
index 0000000..d7561fb
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2004
+ * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
+ *
+ * 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 SDRAM_DDR      1               /* is DDR */
+
+#if defined(CONFIG_MPC5200)
+/* Settings for XLB = 132 MHz */
+#define SDRAM_MODE     0x018D0000
+#define SDRAM_EMODE    0x40010000
+#define SDRAM_CONTROL  0x704f0f00
+#define SDRAM_CONFIG1  0x73722930
+#define SDRAM_CONFIG2  0x47770000
+#define SDRAM_TAPDELAY 0x10000000
+
+#else
+#error CONFIG_MPC5200 not defined
+#endif
index 86a875eeaa02089bfcdb4cf5267f314d08fe3eb1..b60a46e96d2d60b5612f0ef6426420ca8ba84196 100644 (file)
@@ -85,45 +85,22 @@ err:
        return 0;
 }
 
-/* If there is a MAC address in the environment, and if it is not identical to
- * the MAC address in the EEPROM, then a warning is printed and the MAC address
- * from the environment is used.
- *
+/*
  * If there is no MAC address in the environment, then it will be initialized
  * (silently) from the value in the EEPROM.
  */
-void dv_configure_mac_address(uint8_t *rom_enetaddr)
+void davinci_sync_env_enetaddr(uint8_t *rom_enetaddr)
 {
-       int i;
-       u_int8_t env_enetaddr[6];
-       char *tmp = getenv("ethaddr");
-       char *end;
-
-       /* Read Ethernet MAC address from the U-Boot environment.
-        * If it is not defined, env_enetaddr[] will be cleared. */
-       for (i = 0; i < 6; i++) {
-               env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
-               if (tmp)
-                       tmp = (*end) ? end+1 : end;
-       }
-
-       /* Check if EEPROM and U-Boot environment MAC addresses match. */
-       if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6) != 0 &&
-           memcmp(env_enetaddr, rom_enetaddr, 6) != 0) {
-               printf("Warning: MAC addresses don't match:\n");
-               printf("  EEPROM MAC address: %pM\n", rom_enetaddr);
-               printf("     \"ethaddr\" value: %pM\n", env_enetaddr) ;
-               debug("### Using MAC address from environment\n");
-       }
-       if (!tmp) {
-               char ethaddr[20];
+       uint8_t env_enetaddr[6];
 
+       eth_getenv_enetaddr_by_index(0, env_enetaddr);
+       if (!memcmp(env_enetaddr, "\0\0\0\0\0\0", 6)) {
                /* There is no MAC address in the environment, so we initialize
                 * it from the value in the EEPROM. */
-               sprintf(ethaddr, "%pM", rom_enetaddr) ;
-               debug("### Setting environment from EEPROM MAC address = \"%s\"\n",
-                     ethaddr);
-               setenv("ethaddr", ethaddr);
+               debug("### Setting environment from EEPROM MAC address = "
+                       "\"%pM\"\n",
+                       env_enetaddr);
+               eth_setenv_enetaddr("ethaddr", rom_enetaddr);
        }
 }
 
index 329c369763fa28e58eec391fc82fcc930595f167..a6ac3b9a56836c862f0b7510b372523c3e141de1 100644 (file)
@@ -46,7 +46,7 @@ struct pinmux_resource {
                          }
 
 int dvevm_read_mac_address(uint8_t *buf);
-void dv_configure_mac_address(uint8_t *rom_enetaddr);
+void davinci_sync_env_enetaddr(uint8_t *rom_enetaddr);
 int davinci_configure_pin_mux(const struct pinmux_config *pins, int n_pins);
 int davinci_configure_pin_mux_items(const struct pinmux_resource *item,
                                    int n_items);
index 6baa8603f1758d7baed009a25af04b49be19a4c7..8a9f9884d62e547f120d06b9965059f5b130ac89 100644 (file)
@@ -196,19 +196,17 @@ int board_eth_init(bd_t *bis)
 {
        u_int8_t mac_addr[6];
        u_int8_t switch_start_cmd[2] = { 0x01, 0x23 };
+       struct eth_device *dev;
 
        /* Read Ethernet MAC address from EEPROM */
        if (dvevm_read_mac_address(mac_addr))
                /* set address env if not already set */
-               dv_configure_mac_address(mac_addr);
+               davinci_sync_env_enetaddr(mac_addr);
 
        /* read the address back from env */
        if (!eth_getenv_enetaddr("ethaddr", mac_addr))
                return -1;
 
-       /* provide the resulting addr to the driver */
-       davinci_eth_set_mac_addr(mac_addr);
-
        /* enable the Ethernet switch in the 3 port PHY */
        if (i2c_write(PHY_SW_I2C_ADDR, 0, 0,
                        switch_start_cmd, sizeof(switch_start_cmd))) {
@@ -222,6 +220,12 @@ int board_eth_init(bd_t *bis)
                return -1;
        }
 
+       dev = eth_get_dev();
+
+       /* provide the resulting addr to the driver */
+       memcpy(dev->enetaddr, mac_addr, 6);
+       dev->write_hwaddr(dev);
+
        return 0;
 }
 #endif /* CONFIG_DRIVER_TI_EMAC */
index 290eb99749739c6d2a1a746bda0a9cac5affdc37..85dbe2a9c3271012692e6671786e08282fb68cc4 100644 (file)
@@ -68,7 +68,7 @@ int board_eth_init(bd_t *bis)
 
        /* Read Ethernet MAC address from EEPROM */
        if (dvevm_read_mac_address(eeprom_enetaddr))
-               dv_configure_mac_address(eeprom_enetaddr);
+               davinci_sync_env_enetaddr(eeprom_enetaddr);
 
        davinci_emac_initialize();
 
index 98937a9620ca1ee0fd55d39b50fde7f9f86141fe..073c21a8cca85de86b09b6ad5b6ef6550e128f97 100644 (file)
@@ -71,7 +71,7 @@ int misc_init_r(void)
 
        /* Read Ethernet MAC address from EEPROM if available. */
        if (dvevm_read_mac_address(eeprom_enetaddr))
-               dv_configure_mac_address(eeprom_enetaddr);
+               davinci_sync_env_enetaddr(eeprom_enetaddr);
 
        i2c_read(0x39, 0x00, 1, &video_mode, 1);
 
index c24b9e188c9db81482628cbdbf723bdc1aadc662..657cf2b0d90d5f6e28678ab8c3686bfa3a6afdb1 100644 (file)
@@ -141,7 +141,7 @@ int misc_init_r(void)
 
        /* Read Ethernet MAC address from EEPROM if available. */
        if (sffsdr_read_mac_address(eeprom_enetaddr))
-               dv_configure_mac_address(eeprom_enetaddr);
+               davinci_sync_env_enetaddr(eeprom_enetaddr);
 
        return(0);
 }
index 817970aeaa8f3a4f2a2a0cc30c88f759ad41f2bb..1dc42c4087e238cf72bb947d7f646b8b4506c204 100644 (file)
@@ -70,7 +70,7 @@ int misc_init_r(void)
 
        /* Read Ethernet MAC address from EEPROM if available. */
        if (dvevm_read_mac_address(eeprom_enetaddr))
-               dv_configure_mac_address(eeprom_enetaddr);
+               davinci_sync_env_enetaddr(eeprom_enetaddr);
 
        return(0);
 }
index e8714e3a796063dc0d093bc5e82845c31f659d41..2082ad48a273bc77c6352437456b172aad2ef8e3 100644 (file)
@@ -515,6 +515,46 @@ struct node_info nodes[] = {
 };
 #endif
 
+#if defined(CONFIG_VIDEO)
+/*
+ * EDID block has been generated using Phoenix EDID Designer 1.3.
+ * This tool creates a text file containing:
+ *
+ * EDID BYTES:
+ * 0x   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ *     ------------------------------------------------
+ * 00 | 00 FF FF FF FF FF FF 00 42 C9 34 12 01 00 00 00
+ * 10 | 0A 0C 01 03 80 98 5B 78 CA 7E 50 A0 58 4E 96 25
+ * 20 | 1E 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
+ * 30 | 01 01 01 01 01 01 80 0C 20 00 31 E0 2D 10 2A 80
+ * 40 | 12 08 30 E4 10 00 00 18 00 00 00 FD 00 38 3C 1F
+ * 50 | 3C 04 0A 20 20 20 20 20 20 20 00 00 00 FF 00 50
+ * 60 | 4D 30 37 30 57 4C 33 0A 0A 0A 0A 0A 00 00 00 FF
+ * 70 | 00 41 30 30 30 30 30 30 30 30 30 30 30 31 00 D4
+ *
+ * Then this data has been manually converted to the char
+ * array below.
+ */
+static unsigned char edid_buf[128] = {
+       0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+       0x42, 0xC9, 0x34, 0x12, 0x01, 0x00, 0x00, 0x00,
+       0x0A, 0x0C, 0x01, 0x03, 0x80, 0x98, 0x5B, 0x78,
+       0xCA, 0x7E, 0x50, 0xA0, 0x58, 0x4E, 0x96, 0x25,
+       0x1E, 0x50, 0x54, 0x00, 0x00, 0x00, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x0C,
+       0x20, 0x00, 0x31, 0xE0, 0x2D, 0x10, 0x2A, 0x80,
+       0x12, 0x08, 0x30, 0xE4, 0x10, 0x00, 0x00, 0x18,
+       0x00, 0x00, 0x00, 0xFD, 0x00, 0x38, 0x3C, 0x1F,
+       0x3C, 0x04, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+       0x20, 0x20, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x50,
+       0x4D, 0x30, 0x37, 0x30, 0x57, 0x4C, 0x33, 0x0A,
+       0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0xFF,
+       0x00, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+       0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x00, 0xD4,
+};
+#endif
+
 void ft_board_setup(void *blob, bd_t *bd)
 {
        u32 val[8];
@@ -525,6 +565,9 @@ void ft_board_setup(void *blob, bd_t *bd)
 #ifdef CONFIG_FDT_FIXUP_PARTITIONS
        fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
 #endif
+#if defined(CONFIG_VIDEO)
+       fdt_add_edid(blob, "fsl,mpc5121-diu", edid_buf);
+#endif
 
        /* Fixup NOR FLASH mapping */
        val[i++] = 0;                           /* chip select number */
index 0cad897349279d1582ed245e840f3849f762cc2c..5e7427f370f02f45bbf280a12927f6c719612e8b 100644 (file)
@@ -19,8 +19,7 @@
 
 
 /* Function prototypes */
-extern void unlock_ram_in_cache( void );
-extern void _start_warm(void);
+extern void _start(void);
 
 
 /*
@@ -97,8 +96,8 @@ void do_reset( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] )
        icache_disable();
        dcache_disable();
 
-       /* Jump to warm start (in RAM) */
-       _start_warm();
+       /* Jump to cold reset point (in RAM) */
+       _start();
 
        /* Should never get here */
        while(1);
index 838f1315b3fd5d905997499c5bb5cabf0ac39f1f..744384c1d3a2d5efb33f21ab04c898a66ad6c584 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <common.h>
 #include <config.h>
+#include <netdev.h>
 #include <asm/microblaze_intc.h>
 #include <asm/asm.h>
 
@@ -66,3 +67,15 @@ int fsl_init2 (void) {
        return 0;
 }
 #endif
+
+int board_eth_init(bd_t *bis)
+{
+       /*
+        * This board either has PCI NICs or uses the CPU's TSECs
+        * pci_eth_init() will return 0 if no NICs found, so in that case
+        * returning -1 will force cpu_eth_init() to be called.
+        */
+#ifdef CONFIG_XILINX_EMACLITE
+       return xilinx_emaclite_initialize(bis, XILINX_EMACLITE_BASEADDR);
+#endif
+}
index 38fa5703092df11a0723ce4c860e825a5e54c209..132d178830a60c5158ec084cf1e6bfc2b3b6f8d4 100644 (file)
@@ -91,6 +91,7 @@ DB64360               powerpc 74xx_7xx        db64360         Marvell
 DB64460                powerpc 74xx_7xx        db64460         Marvell
 aria           powerpc mpc512x         -               davedenx
 PATI           powerpc mpc5xx          pati            mpl
+a4m072         powerpc mpc5xxx         a4m072
 BC3450         powerpc mpc5xxx         bc3450
 canmb          powerpc mpc5xxx
 cm5200         powerpc mpc5xxx
index 6c11aa6e3e0e209d560a157d39e8dfe1d9081037..d5d5d8c31d73854b2aa054582f482804abc550d9 100644 (file)
 
 #include <common.h>
 #include <command.h>
+#include <led-display.h>
 
 #undef DEBUG_DISP
 
-#define DISP_SIZE      8
-#define CWORD_CLEAR    0x80
-#define CLEAR_DELAY    (110 * 2)
-
 int do_display (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        int i;
-       int pos;
 
        /* Clear display */
-       *((volatile char*)(CONFIG_SYS_DISP_CWORD)) = CWORD_CLEAR;
-       udelay(1000 * CLEAR_DELAY);
+       display_set(DISPLAY_CLEAR | DISPLAY_HOME);
 
        if (argc < 2)
                return (0);
 
-       for (pos = 0, i = 1; i < argc && pos < DISP_SIZE; i++) {
-               char *p = argv[i], c;
+       for (i = 1; i < argc; i++) {
+               char *p = argv[i];
 
-               if (i > 1) {
-                       *((volatile uchar *) (CONFIG_SYS_DISP_CHR_RAM + pos++)) = ' ';
-#ifdef DEBUG_DISP
-                       putc(' ');
-#endif
+               if (i > 1) { /* Insert a space between strings */
+                       display_putc(' ');
                }
 
-               while ((c = *p++) != '\0' && pos < DISP_SIZE) {
-                       *((volatile uchar *) (CONFIG_SYS_DISP_CHR_RAM + pos++)) = c;
+               while ((*p)) {
 #ifdef DEBUG_DISP
-                       putc(c);
+                       putc(*p);
 #endif
+                       display_putc(*p++);
                }
        }
 
index 2a02eb90d4c0160c3faeb13084ceeb1f67a2fc91..4493948ec4ecbcce6fb1e5e12d427e30064dcd29 100644 (file)
@@ -31,7 +31,7 @@
 #include <dataflash.h>
 #endif
 
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
 #include <jffs2/jffs2.h>
 
 /* partition handling routines */
@@ -327,7 +327,7 @@ int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        flash_info_t *info;
        ulong bank, addr_first, addr_last;
        int n, sect_first, sect_last;
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
        struct mtd_device *dev;
        struct part_info *part;
        u8 dev_type, dev_num, pnum;
@@ -357,7 +357,7 @@ int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                return rcode;
        }
 
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
        /* erase <part-id> - erase partition */
        if ((argc == 2) && (mtd_id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
                mtdparts_init();
@@ -463,7 +463,7 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #if !defined(CONFIG_SYS_NO_FLASH) || defined(CONFIG_HAS_DATAFLASH)
        ulong addr_first, addr_last;
 #endif
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
        struct mtd_device *dev;
        struct part_info *part;
        u8 dev_type, dev_num, pnum;
@@ -553,7 +553,7 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                return rcode;
        }
 
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
        /* protect on/off <part-id> */
        if ((argc == 3) && (mtd_id_parse(argv[2], NULL, &dev_type, &dev_num) == 0)) {
                mtdparts_init();
@@ -681,7 +681,7 @@ int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
 
 
 /**************************************************/
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
 # define TMP_ERASE     "erase <part-id>\n    - erase partition\n"
 # define TMP_PROT_ON   "protect on <part-id>\n    - protect partition\n"
 # define TMP_PROT_OFF  "protect off <part-id>\n    - make partition writable\n"
index 44834ea7514fccb2765d008ed57a83497e9bd4e7..f7a442a88e65234384d33039ad3e02ca23c5c32a 100644 (file)
@@ -337,6 +337,10 @@ int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                ngood++;
                addr1 += size;
                addr2 += size;
+
+               /* reset watchdog from time to time */
+               if ((count % (64 << 10)) == 0)
+                       WATCHDOG_RESET();
        }
 
        printf("Total of %ld %s%s were the same\n",
@@ -447,6 +451,10 @@ int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        *((u_char *)dest) = *((u_char *)addr);
                addr += size;
                dest += size;
+
+               /* reset watchdog from time to time */
+               if ((count % (64 << 10)) == 0)
+                       WATCHDOG_RESET();
        }
        return 0;
 }
index ceec5a97511f1ff3f6cc65458d73178cfc06171d..5481c885d3ea1bb92303d5396d5f626d7c5337e2 100644 (file)
@@ -15,6 +15,9 @@
  *   Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4
  *   kernel tree.
  *
+ * (C) Copyright 2008
+ * Harald Welte, OpenMoko, Inc., Harald Welte <laforge@openmoko.org>
+ *
  *   $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $
  *   Copyright 2002 SYSGO Real-Time Solutions GmbH
  *
@@ -286,6 +289,29 @@ static void current_save(void)
        index_partitions();
 }
 
+
+/**
+ * Produce a mtd_info given a type and num.
+ *
+ * @param type mtd type
+ * @param num mtd number
+ * @param mtd a pointer to an mtd_info instance (output)
+ * @return 0 if device is valid, 1 otherwise
+ */
+static int get_mtd_info(u8 type, u8 num, struct mtd_info **mtd)
+{
+       char mtd_dev[16];
+
+       sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(type), num);
+       *mtd = get_mtd_device_nm(mtd_dev);
+       if (IS_ERR(*mtd)) {
+               printf("Device %s not found!\n", mtd_dev);
+               return 1;
+       }
+
+       return 0;
+}
+
 /**
  * Performs sanity check for supplied flash partition.
  * Table of existing MTD flash devices is searched and partition device
@@ -297,17 +323,12 @@ static void current_save(void)
  */
 static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
 {
-       struct mtd_info *mtd;
-       char mtd_dev[16];
+       struct mtd_info *mtd = NULL;
        int i, j;
        ulong start;
 
-       sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(id->type), id->num);
-       mtd = get_mtd_device_nm(mtd_dev);
-       if (IS_ERR(mtd)) {
-               printf("Partition %s not found on device %s!\n", part->name, mtd_dev);
+       if (get_mtd_info(id->type, id->num, &mtd))
                return 1;
-       }
 
        part->sector_size = mtd->erasesize;
 
@@ -684,20 +705,17 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
 /**
  * Check device number to be within valid range for given device type.
  *
- * @param dev device to validate
+ * @param type mtd type
+ * @param num mtd number
+ * @param size a pointer to the size of the mtd device (output)
  * @return 0 if device is valid, 1 otherwise
  */
 int mtd_device_validate(u8 type, u8 num, u32 *size)
 {
-       struct mtd_info *mtd;
-       char mtd_dev[16];
+       struct mtd_info *mtd = NULL;
 
-       sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(type), num);
-       mtd = get_mtd_device_nm(mtd_dev);
-       if (IS_ERR(mtd)) {
-               printf("Device %s not found!\n", mtd_dev);
+       if (get_mtd_info(type, num, &mtd))
                return 1;
-       }
 
        *size = mtd->size;
 
@@ -1200,38 +1218,93 @@ static int generate_mtdparts_save(char *buf, u32 buflen)
        return ret;
 }
 
+#if defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES)
 /**
- * Format and print out a partition list for each device from global device
- * list.
+ * Get the net size (w/o bad blocks) of the given partition.
+ *
+ * @param mtd the mtd info
+ * @param part the partition
+ * @return the calculated net size of this partition
  */
-static void list_partitions(void)
+static uint64_t net_part_size(struct mtd_info *mtd, struct part_info *part)
+{
+       uint64_t i, net_size = 0;
+
+       if (!mtd->block_isbad)
+               return part->size;
+
+       for (i = 0; i < part->size; i += mtd->erasesize) {
+               if (!mtd->block_isbad(mtd, part->offset + i))
+                       net_size += mtd->erasesize;
+       }
+
+       return net_size;
+}
+#endif
+
+static void print_partition_table(void)
 {
        struct list_head *dentry, *pentry;
        struct part_info *part;
        struct mtd_device *dev;
        int part_num;
 
-       debug("\n---list_partitions---\n");
        list_for_each(dentry, &devices) {
                dev = list_entry(dentry, struct mtd_device, link);
+               /* list partitions for given device */
+               part_num = 0;
+#if defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES)
+               struct mtd_info *mtd;
+
+               if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+                       return;
+
+               printf("\ndevice %s%d <%s>, # parts = %d\n",
+                               MTD_DEV_TYPE(dev->id->type), dev->id->num,
+                               dev->id->mtd_id, dev->num_parts);
+               printf(" #: name\t\tsize\t\tnet size\toffset\t\tmask_flags\n");
+
+               list_for_each(pentry, &dev->parts) {
+                       u32 net_size;
+                       char *size_note;
+
+                       part = list_entry(pentry, struct part_info, link);
+                       net_size = net_part_size(mtd, part);
+                       size_note = part->size == net_size ? " " : " (!)";
+                       printf("%2d: %-20s0x%08x\t0x%08x%s\t0x%08x\t%d\n",
+                                       part_num, part->name, part->size,
+                                       net_size, size_note, part->offset,
+                                       part->mask_flags);
+#else /* !defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
                printf("\ndevice %s%d <%s>, # parts = %d\n",
                                MTD_DEV_TYPE(dev->id->type), dev->id->num,
                                dev->id->mtd_id, dev->num_parts);
                printf(" #: name\t\tsize\t\toffset\t\tmask_flags\n");
 
-               /* list partitions for given device */
-               part_num = 0;
                list_for_each(pentry, &dev->parts) {
                        part = list_entry(pentry, struct part_info, link);
                        printf("%2d: %-20s0x%08x\t0x%08x\t%d\n",
                                        part_num, part->name, part->size,
                                        part->offset, part->mask_flags);
-
+#endif /* defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
                        part_num++;
                }
        }
+
        if (list_empty(&devices))
                printf("no partitions defined\n");
+}
+
+/**
+ * Format and print out a partition list for each device from global device
+ * list.
+ */
+static void list_partitions(void)
+{
+       struct part_info *part;
+
+       debug("\n---list_partitions---\n");
+       print_partition_table();
 
        /* current_mtd_dev is not NULL only when we have non empty device list */
        if (current_mtd_dev) {
@@ -1355,6 +1428,101 @@ static int delete_partition(const char *id)
        return 1;
 }
 
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+/**
+ * Increase the size of the given partition so that it's net size is at least
+ * as large as the size member and such that the next partition would start on a
+ * good block if it were adjacent to this partition.
+ *
+ * @param mtd the mtd device
+ * @param part the partition
+ * @param next_offset pointer to the offset of the next partition after this
+ *                    partition's size has been modified (output)
+ */
+static void spread_partition(struct mtd_info *mtd, struct part_info *part,
+                            uint64_t *next_offset)
+{
+       uint64_t net_size, padding_size = 0;
+       int truncated;
+
+       mtd_get_len_incl_bad(mtd, part->offset, part->size, &net_size,
+                            &truncated);
+
+       /*
+        * Absorb bad blocks immediately following this
+        * partition also into the partition, such that
+        * the next partition starts with a good block.
+        */
+       if (!truncated) {
+               mtd_get_len_incl_bad(mtd, part->offset + net_size,
+                                    mtd->erasesize, &padding_size, &truncated);
+               if (truncated)
+                       padding_size = 0;
+               else
+                       padding_size -= mtd->erasesize;
+       }
+
+       if (truncated) {
+               printf("truncated partition %s to %lld bytes\n", part->name,
+                      (uint64_t) net_size + padding_size);
+       }
+
+       part->size = net_size + padding_size;
+       *next_offset = part->offset + part->size;
+}
+
+/**
+ * Adjust all of the partition sizes, such that all partitions are at least
+ * as big as their mtdparts environment variable sizes and they each start
+ * on a good block.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+static int spread_partitions(void)
+{
+       struct list_head *dentry, *pentry;
+       struct mtd_device *dev;
+       struct part_info *part;
+       struct mtd_info *mtd;
+       int part_num;
+       uint64_t cur_offs;
+
+       list_for_each(dentry, &devices) {
+               dev = list_entry(dentry, struct mtd_device, link);
+
+               if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+                       return 1;
+
+               part_num = 0;
+               cur_offs = 0;
+               list_for_each(pentry, &dev->parts) {
+                       part = list_entry(pentry, struct part_info, link);
+
+                       debug("spread_partitions: device = %s%d, partition %d ="
+                               " (%s) 0x%08x@0x%08x\n",
+                               MTD_DEV_TYPE(dev->id->type), dev->id->num,
+                               part_num, part->name, part->size,
+                               part->offset);
+
+                       if (cur_offs > part->offset)
+                               part->offset = cur_offs;
+
+                       spread_partition(mtd, part, &cur_offs);
+
+                       part_num++;
+               }
+       }
+
+       index_partitions();
+
+       if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+               printf("generated mtdparts too long, reseting to null\n");
+               return 1;
+       }
+       return 0;
+}
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
+
 /**
  * Accept character string describing mtd partitions and call device_parse()
  * for each entry. Add created devices to the global devices list.
@@ -1782,9 +1950,13 @@ int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        }
 
        /* mtdparts add <mtd-dev> <size>[@<offset>] <name> [ro] */
-       if (((argc == 5) || (argc == 6)) && (strcmp(argv[1], "add") == 0)) {
+       if (((argc == 5) || (argc == 6)) && (strncmp(argv[1], "add", 3) == 0)) {
 #define PART_ADD_DESC_MAXLEN 64
                char tmpbuf[PART_ADD_DESC_MAXLEN];
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+               struct mtd_info *mtd;
+               uint64_t next_offset;
+#endif
                u8 type, num, len;
                struct mtd_device *dev;
                struct mtd_device *dev_tmp;
@@ -1819,15 +1991,25 @@ int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                debug("+ %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type),
                                dev->id->num, dev->id->mtd_id);
 
-               if ((dev_tmp = device_find(dev->id->type, dev->id->num)) == NULL) {
+               p = list_entry(dev->parts.next, struct part_info, link);
+
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+               if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+                       return 1;
+
+               if (!strcmp(&argv[1][3], ".spread")) {
+                       spread_partition(mtd, p, &next_offset);
+                       debug("increased %s to %d bytes\n", p->name, p->size);
+               }
+#endif
+
+               dev_tmp = device_find(dev->id->type, dev->id->num);
+               if (dev_tmp == NULL) {
                        device_add(dev);
-               } else {
+               } else if (part_add(dev_tmp, p) != 0) {
                        /* merge new partition with existing ones*/
-                       p = list_entry(dev->parts.next, struct part_info, link);
-                       if (part_add(dev_tmp, p) != 0) {
-                               device_del(dev);
-                               return 1;
-                       }
+                       device_del(dev);
+                       return 1;
                }
 
                if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
@@ -1845,6 +2027,11 @@ int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                return delete_partition(argv[2]);
        }
 
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+       if ((argc == 2) && (strcmp(argv[1], "spread") == 0))
+               return spread_partitions();
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
+
        return cmd_usage(cmdtp);
 }
 
@@ -1867,8 +2054,20 @@ U_BOOT_CMD(
        "    - delete partition (e.g. part-id = nand0,1)\n"
        "mtdparts add <mtd-dev> <size>[@<offset>] [<name>] [ro]\n"
        "    - add partition\n"
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+       "mtdparts add.spread <mtd-dev> <size>[@<offset>] [<name>] [ro]\n"
+       "    - add partition, padding size by skipping bad blocks\n"
+#endif
        "mtdparts default\n"
-       "    - reset partition table to defaults\n\n"
+       "    - reset partition table to defaults\n"
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+       "mtdparts spread\n"
+       "    - adjust the sizes of the partitions so they are\n"
+       "      at least as big as the mtdparts variable specifies\n"
+       "      and they each start on a good block\n\n"
+#else
+       "\n"
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
        "-----\n\n"
        "this command uses three environment variables:\n\n"
        "'partition' - keeps current partition identifier\n\n"
index 3f1d077ff737cae9938475db03d1820c31da0505..8a812379a6e3295ba5765c0c7dfbf146aa006bc0 100644 (file)
  * (C) Copyright 2006-2007 OpenMoko, Inc.
  * Added 16-bit nand support
  * (C) 2004 Texas Instruments
+ *
+ * Copyright 2010 Freescale Semiconductor
+ * The portions of this file whose copyright is held by Freescale and which
+ * are not considered a derived work of GPL v2-only code may be distributed
+ * and/or modified 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.
  */
 
 #include <common.h>
@@ -30,10 +37,16 @@ int find_dev_and_part(const char *id, struct mtd_device **dev,
                      u8 *part_num, struct part_info **part);
 #endif
 
-static int nand_dump(nand_info_t *nand, ulong off, int only_oob)
+static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
 {
        int i;
        u_char *datbuf, *oobbuf, *p;
+       static loff_t last;
+
+       if (repeat)
+               off = last + nand->writesize;
+
+       last = off;
 
        datbuf = malloc(nand->writesize + nand->oobsize);
        oobbuf = malloc(nand->oobsize);
@@ -85,74 +98,132 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob)
 
 /* ------------------------------------------------------------------------- */
 
-static inline int str2long(char *p, ulong *num)
+static int set_dev(int dev)
+{
+       if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+           !nand_info[dev].name) {
+               puts("No such device\n");
+               return -1;
+       }
+
+       if (nand_curr_device == dev)
+               return 0;
+
+       printf("Device %d: %s", dev, nand_info[dev].name);
+       puts("... is now current device\n");
+       nand_curr_device = dev;
+
+#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
+       board_nand_select_device(nand_info[dev].priv, dev);
+#endif
+
+       return 0;
+}
+
+static inline int str2off(const char *p, loff_t *num)
+{
+       char *endptr;
+
+       *num = simple_strtoull(p, &endptr, 16);
+       return *p != '\0' && *endptr == '\0';
+}
+
+static inline int str2long(const char *p, ulong *num)
 {
        char *endptr;
 
        *num = simple_strtoul(p, &endptr, 16);
-       return (*p != '\0' && *endptr == '\0') ? 1 : 0;
+       return *p != '\0' && *endptr == '\0';
 }
 
-static int
-arg_off_size(int argc, char * const argv[], nand_info_t *nand, ulong *off, size_t *size)
+static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)
 {
-       int idx = nand_curr_device;
-#if defined(CONFIG_CMD_MTDPARTS)
+#ifdef CONFIG_CMD_MTDPARTS
        struct mtd_device *dev;
        struct part_info *part;
        u8 pnum;
+       int ret;
 
-       if (argc >= 1 && !(str2long(argv[0], off))) {
-               if ((mtdparts_init() == 0) &&
-                   (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) {
-                       if (dev->id->type != MTD_DEV_TYPE_NAND) {
-                               puts("not a NAND device\n");
-                               return -1;
-                       }
-                       *off = part->offset;
-                       if (argc >= 2) {
-                               if (!(str2long(argv[1], (ulong *)size))) {
-                                       printf("'%s' is not a number\n", argv[1]);
-                                       return -1;
-                               }
-                               if (*size > part->size)
-                                       *size = part->size;
-                       } else {
-                               *size = part->size;
-                       }
-                       idx = dev->id->num;
-                       *nand = nand_info[idx];
-                       goto out;
-               }
+       ret = mtdparts_init();
+       if (ret)
+               return ret;
+
+       ret = find_dev_and_part(partname, &dev, &pnum, &part);
+       if (ret)
+               return ret;
+
+       if (dev->id->type != MTD_DEV_TYPE_NAND) {
+               puts("not a NAND device\n");
+               return -1;
        }
+
+       *off = part->offset;
+       *size = part->size;
+       *idx = dev->id->num;
+
+       ret = set_dev(*idx);
+       if (ret)
+               return ret;
+
+       return 0;
+#else
+       puts("offset is not a number\n");
+       return -1;
 #endif
+}
 
-       if (argc >= 1) {
-               if (!(str2long(argv[0], off))) {
-                       printf("'%s' is not a number\n", argv[0]);
-                       return -1;
-               }
-       } else {
+static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize)
+{
+       if (!str2off(arg, off))
+               return get_part(arg, idx, off, maxsize);
+
+       if (*off >= nand_info[*idx].size) {
+               puts("Offset exceeds device limit\n");
+               return -1;
+       }
+
+       *maxsize = nand_info[*idx].size - *off;
+       return 0;
+}
+
+static int arg_off_size(int argc, char *const argv[], int *idx,
+                       loff_t *off, loff_t *size)
+{
+       int ret;
+       loff_t maxsize;
+
+       if (argc == 0) {
                *off = 0;
+               *size = nand_info[*idx].size;
+               goto print;
        }
 
-       if (argc >= 2) {
-               if (!(str2long(argv[1], (ulong *)size))) {
-                       printf("'%s' is not a number\n", argv[1]);
-                       return -1;
-               }
-       } else {
-               *size = nand->size - *off;
+       ret = arg_off(argv[0], idx, off, &maxsize);
+       if (ret)
+               return ret;
+
+       if (argc == 1) {
+               *size = maxsize;
+               goto print;
        }
 
-#if defined(CONFIG_CMD_MTDPARTS)
-out:
-#endif
-       printf("device %d ", idx);
-       if (*size == nand->size)
+       if (!str2off(argv[1], size)) {
+               printf("'%s' is not a number\n", argv[1]);
+               return -1;
+       }
+
+       if (*size > maxsize) {
+               puts("Size exceeds partition or device limit\n");
+               return -1;
+       }
+
+print:
+       printf("device %d ", *idx);
+       if (*size == nand_info[*idx].size)
                puts("whole chip\n");
        else
-               printf("offset 0x%lx, size 0x%zx\n", *off, *size);
+               printf("offset 0x%llx, size 0x%llx\n",
+                      (unsigned long long)*off, (unsigned long long)*size);
        return 0;
 }
 
@@ -200,14 +271,20 @@ static void do_nand_status(nand_info_t *nand)
 #ifdef CONFIG_ENV_OFFSET_OOB
 unsigned long nand_env_oob_offset;
 
-int do_nand_env_oob(cmd_tbl_t *cmdtp, nand_info_t *nand,
-                   int argc, char * const argv[])
+int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
 {
        int ret;
        uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
-
+       nand_info_t *nand = &nand_info[0];
        char *cmd = argv[1];
 
+       if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
+               puts("no devices available\n");
+               return 1;
+       }
+
+       set_dev(0);
+
        if (!strcmp(cmd, "get")) {
                ret = get_nand_env_oob(nand, &nand_env_oob_offset);
                if (ret)
@@ -215,16 +292,21 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, nand_info_t *nand,
 
                printf("0x%08lx\n", nand_env_oob_offset);
        } else if (!strcmp(cmd, "set")) {
-               ulong addr;
-               size_t dummy_size;
+               loff_t addr;
+               loff_t maxsize;
                struct mtd_oob_ops ops;
+               int idx = 0;
 
                if (argc < 3)
                        goto usage;
 
-               if (arg_off_size(argc - 2, argv + 2, nand, &addr,
-                                &dummy_size) < 0) {
-                       printf("Offset or partition name expected\n");
+               if (arg_off(argv[2], &idx, &addr, &maxsize)) {
+                       puts("Offset or partition name expected\n");
+                       return 1;
+               }
+
+               if (idx != 0) {
+                       puts("Partition not on first NAND device\n");
                        return 1;
                }
 
@@ -264,8 +346,8 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, nand_info_t *nand,
 
                if (addr != nand_env_oob_offset) {
                        printf("Verification of env offset in OOB failed: "
-                              "0x%08lx expected but got 0x%08lx\n",
-                              addr, nand_env_oob_offset);
+                              "0x%08llx expected but got 0x%08lx\n",
+                              (unsigned long long)addr, nand_env_oob_offset);
                        return 1;
                }
        } else {
@@ -293,9 +375,9 @@ static void nand_print_info(int idx)
 
 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
-       int i, dev, ret = 0;
-       ulong addr, off;
-       size_t size;
+       int i, ret = 0;
+       ulong addr;
+       loff_t off, size;
        char *cmd, *s;
        nand_info_t *nand;
 #ifdef CONFIG_SYS_NAND_QUIET
@@ -304,6 +386,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
        int quiet = 0;
 #endif
        const char *quiet_str = getenv("quiet");
+       int dev = nand_curr_device;
+       int repeat = flag & CMD_FLAG_REPEAT;
 
        /* at least two arguments please */
        if (argc < 2)
@@ -314,6 +398,10 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 
        cmd = argv[1];
 
+       /* Only "dump" is repeatable. */
+       if (repeat && strcmp(cmd, "dump"))
+               return 0;
+
        if (strcmp(cmd, "info") == 0) {
 
                putc('\n');
@@ -325,68 +413,45 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
        }
 
        if (strcmp(cmd, "device") == 0) {
-
                if (argc < 3) {
                        putc('\n');
-                       if ((nand_curr_device < 0) ||
-                           (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE))
+                       if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
                                puts("no devices available\n");
                        else
-                               nand_print_info(nand_curr_device);
+                               nand_print_info(dev);
                        return 0;
                }
-               dev = (int)simple_strtoul(argv[2], NULL, 10);
-               if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev].name) {
-                       puts("No such device\n");
-                       return 1;
-               }
-               printf("Device %d: %s", dev, nand_info[dev].name);
-               puts("... is now current device\n");
-               nand_curr_device = dev;
 
-#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
-               /*
-                * Select the chip in the board/cpu specific driver
-                */
-               board_nand_select_device(nand_info[dev].priv, dev);
-#endif
+               dev = (int)simple_strtoul(argv[2], NULL, 10);
+               set_dev(dev);
 
                return 0;
        }
 
-       if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
-           strncmp(cmd, "dump", 4) != 0 &&
-           strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
-           strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
-           strcmp(cmd, "biterr") != 0 &&
-           strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0
-#ifdef CONFIG_ENV_OFFSET_OOB
-           && strcmp(cmd, "env.oob") != 0
-#endif
-           )
-               goto usage;
-
 #ifdef CONFIG_ENV_OFFSET_OOB
        /* this command operates only on the first nand device */
-       if (strcmp(cmd, "env.oob") == 0) {
-               return do_nand_env_oob(cmdtp, &nand_info[0],
-                                      argc - 1, argv + 1);
-       }
+       if (strcmp(cmd, "env.oob") == 0)
+               return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
 #endif
 
-       /* the following commands operate on the current device */
-       if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
-           !nand_info[nand_curr_device].name) {
+       /* The following commands operate on the current device, unless
+        * overridden by a partition specifier.  Note that if somehow the
+        * current device is invalid, it will have to be changed to a valid
+        * one before these commands can run, even if a partition specifier
+        * for another device is to be used.
+        */
+       if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+           !nand_info[dev].name) {
                puts("\nno devices available\n");
                return 1;
        }
-       nand = &nand_info[nand_curr_device];
+       nand = &nand_info[dev];
 
        if (strcmp(cmd, "bad") == 0) {
-               printf("\nDevice %d bad blocks:\n", nand_curr_device);
+               printf("\nDevice %d bad blocks:\n", dev);
                for (off = 0; off < nand->size; off += nand->erasesize)
                        if (nand_block_isbad(nand, off))
-                               printf("  %08lx\n", off);
+                               printf("  %08llx\n", (unsigned long long)off);
                return 0;
        }
 
@@ -395,23 +460,52 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
         *   0    1     2       3    4
         *   nand erase [clean] [off size]
         */
-       if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
+       if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
                nand_erase_options_t opts;
                /* "clean" at index 2 means request to write cleanmarker */
                int clean = argc > 2 && !strcmp("clean", argv[2]);
                int o = clean ? 3 : 2;
-               int scrub = !strcmp(cmd, "scrub");
+               int scrub = !strncmp(cmd, "scrub", 5);
+               int part = 0;
+               int chip = 0;
+               int spread = 0;
+               int args = 2;
+
+               if (cmd[5] != 0) {
+                       if (!strcmp(&cmd[5], ".spread")) {
+                               spread = 1;
+                       } else if (!strcmp(&cmd[5], ".part")) {
+                               part = 1;
+                               args = 1;
+                       } else if (!strcmp(&cmd[5], ".chip")) {
+                               chip = 1;
+                               args = 0;
+                       } else {
+                               goto usage;
+                       }
+               }
+
+               /*
+                * Don't allow missing arguments to cause full chip/partition
+                * erases -- easy to do accidentally, e.g. with a misspelled
+                * variable name.
+                */
+               if (argc != o + args)
+                       goto usage;
 
-               printf("\nNAND %s: ", scrub ? "scrub" : "erase");
+               printf("\nNAND %s: ", cmd);
                /* skip first two or three arguments, look for offset and size */
-               if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)
+               if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0)
                        return 1;
 
+               nand = &nand_info[dev];
+
                memset(&opts, 0, sizeof(opts));
                opts.offset = off;
                opts.length = size;
                opts.jffs2  = clean;
                opts.quiet  = quiet;
+               opts.spread = spread;
 
                if (scrub) {
                        puts("Warning: "
@@ -449,19 +543,14 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                if (argc < 3)
                        goto usage;
 
-               s = strchr(cmd, '.');
                off = (int)simple_strtoul(argv[2], NULL, 16);
-
-               if (s != NULL && strcmp(s, ".oob") == 0)
-                       ret = nand_dump(nand, off, 1);
-               else
-                       ret = nand_dump(nand, off, 0);
+               ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
 
                return ret == 0 ? 1 : 0;
-
        }
 
        if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
+               size_t rwsize;
                int read;
 
                if (argc < 4)
@@ -471,23 +560,26 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 
                read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
                printf("\nNAND %s: ", read ? "read" : "write");
-               if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
+               if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0)
                        return 1;
 
+               nand = &nand_info[dev];
+               rwsize = size;
+
                s = strchr(cmd, '.');
                if (!s || !strcmp(s, ".jffs2") ||
                    !strcmp(s, ".e") || !strcmp(s, ".i")) {
                        if (read)
-                               ret = nand_read_skip_bad(nand, off, &size,
+                               ret = nand_read_skip_bad(nand, off, &rwsize,
                                                         (u_char *)addr);
                        else
-                               ret = nand_write_skip_bad(nand, off, &size,
+                               ret = nand_write_skip_bad(nand, off, &rwsize,
                                                          (u_char *)addr);
                } else if (!strcmp(s, ".oob")) {
                        /* out-of-band data */
                        mtd_oob_ops_t ops = {
                                .oobbuf = (u8 *)addr,
-                               .ooblen = size,
+                               .ooblen = rwsize,
                                .mode = MTD_OOB_RAW
                        };
 
@@ -500,7 +592,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                        return 1;
                }
 
-               printf(" %zu bytes %s: %s\n", size,
+               printf(" %zu bytes %s: %s\n", rwsize,
                       read ? "read" : "written", ret ? "ERROR" : "OK");
 
                return ret == 0 ? 0 : 1;
@@ -564,7 +656,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0)
                        return 1;
 
-               if (!nand_unlock(nand, off, size)) {
+               if (!nand_unlock(&nand_info[dev], off, size)) {
                        puts("NAND flash successfully unlocked\n");
                } else {
                        puts("Error unlocking NAND flash, "
@@ -588,11 +680,16 @@ U_BOOT_CMD(
        "nand write - addr off|partition size\n"
        "    read/write 'size' bytes starting at offset 'off'\n"
        "    to/from memory address 'addr', skipping bad blocks.\n"
-       "nand erase [clean] [off size] - erase 'size' bytes from\n"
-       "    offset 'off' (entire device if not specified)\n"
+       "nand erase[.spread] [clean] [off [size]] - erase 'size' bytes "
+       "from offset 'off'\n"
+       "    With '.spread', erase enough for given file size, otherwise,\n"
+       "    'size' includes skipped bad blocks.\n"
+       "nand erase.part [clean] partition - erase entire mtd partition'\n"
+       "nand erase.chip [clean] - erase entire chip'\n"
        "nand bad - show bad blocks\n"
        "nand dump[.oob] off - dump page\n"
-       "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
+       "nand scrub off size | scrub.part partition | scrub.chip\n"
+       "    really clean NAND erasing bad blocks (UNSAFE)\n"
        "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
        "nand biterr off - make a bit error at offset (UNSAFE)"
 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
index 3ffb9df1de096d4138e36f9cb4ae3e294ffb5f47..44d17db19c5fd28dae8e8771a8eb64f1181f303c 100644 (file)
@@ -54,6 +54,7 @@ U_BOOT_CMD(
        "[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 
+#ifdef CONFIG_CMD_RARP
 int do_rarpb (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        return netboot_common (RARP, cmdtp, argc, argv);
@@ -64,6 +65,7 @@ U_BOOT_CMD(
        "boot image via network using RARP/TFTP protocol",
        "[loadAddress] [[hostIPaddr:]bootfilename]"
 );
+#endif
 
 #if defined(CONFIG_CMD_DHCP)
 int do_dhcp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
index 1e83c886e55fccfbf9de9c8a64463b8db3e81757..6dc9dab36899c10035af72ea4059043bfa0f376a 100644 (file)
@@ -419,7 +419,7 @@ int do_tsi148(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        if (argc > 5)
                vam = simple_strtoul(argv[5], NULL, 16);
        if (argc > 6)
-               vdw = simple_strtoul(argv[7], NULL, 16);
+               vdw = simple_strtoul(argv[6], NULL, 16);
 
        switch (cmd) {
        case 'c':
@@ -465,7 +465,7 @@ int do_tsi148(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 }
 
 U_BOOT_CMD(
-       tsi148, 8,      1,      do_tsi148,
+       tsi148, 7,      1,      do_tsi148,
        "initialize and configure Turndra Tsi148\n",
        "init\n"
        "    - initialize tsi148\n"
index 88f068cc38b8e9785569d87c328ae70034a4d395..5acda4d49ed66225889aa7e9e409652c9ad03cce 100644 (file)
@@ -237,8 +237,8 @@ void env_relocate (void)
                set_default_env(NULL);
 #else
                show_boot_progress (-60);
-#endif
                set_default_env("!bad CRC");
+#endif
        } else {
                env_relocate_spec ();
        }
index 0ed6e77292df179b953f6d1ad760bd9e4a236ac5..b8a3dc969b6e8a7f90e8da642596b7dd19f9e20c 100644 (file)
@@ -667,6 +667,16 @@ int fdt_fixup_nor_flash_size(void *blob)
 }
 #endif
 
+int fdt_increase_size(void *fdt, int add_len)
+{
+       int newlen;
+
+       newlen = fdt_totalsize(fdt) + add_len;
+
+       /* Open in place with a new len */
+       return fdt_open_into(fdt, fdt, newlen);
+}
+
 #ifdef CONFIG_FDT_FIXUP_PARTITIONS
 #include <jffs2/load_kernel.h>
 #include <mtd_node.h>
@@ -701,16 +711,6 @@ int fdt_del_subnodes(const void *blob, int parent_offset)
        return 0;
 }
 
-int fdt_increase_size(void *fdt, int add_len)
-{
-       int newlen;
-
-       newlen = fdt_totalsize(fdt) + add_len;
-
-       /* Open in place with a new len */
-       return fdt_open_into(fdt, fdt, newlen);
-}
-
 int fdt_del_partitions(void *blob, int parent_offset)
 {
        const void *prop;
@@ -1189,3 +1189,32 @@ int fdt_alloc_phandle(void *blob)
 
        return phandle + 1;
 }
+
+#if defined(CONFIG_VIDEO)
+int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf)
+{
+       int noff;
+       int ret;
+
+       noff = fdt_node_offset_by_compatible(blob, -1, compat);
+       if (noff != -FDT_ERR_NOTFOUND) {
+               debug("%s: %s\n", fdt_get_name(blob, noff, 0), compat);
+add_edid:
+               ret = fdt_setprop(blob, noff, "edid", edid_buf, 128);
+               if (ret == -FDT_ERR_NOSPACE) {
+                       ret = fdt_increase_size(blob, 512);
+                       if (!ret)
+                               goto add_edid;
+                       else
+                               goto err_size;
+               } else if (ret < 0) {
+                       printf("Can't add property: %s\n", fdt_strerror(ret));
+                       return ret;
+               }
+       }
+       return 0;
+err_size:
+       printf("Can't increase blob size: %s\n", fdt_strerror(ret));
+       return ret;
+}
+#endif
index 76949b85c0f2793e4bccb4f1dbb63a04b259aed8..613c4f0f1f7e79a653ad6267a8341e7c30207f80 100644 (file)
@@ -204,6 +204,22 @@ int usb_stor_info(void)
        return 1;
 }
 
+static unsigned int usb_get_max_lun(struct us_data *us)
+{
+       int len;
+       unsigned char result;
+       len = usb_control_msg(us->pusb_dev,
+                             usb_rcvctrlpipe(us->pusb_dev, 0),
+                             US_BBB_GET_MAX_LUN,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             0, us->ifnum,
+                             &result, sizeof(result),
+                             USB_CNTL_TIMEOUT * 5);
+       USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
+                       len, (int) result);
+       return (len > 0) ? result : 0;
+}
+
 /*******************************************************************************
  * scan the usb and reports device info
  * to the user if mode = 1
@@ -241,12 +257,21 @@ int usb_stor_scan(int mode)
                        break; /* no more devices avaiable */
 
                if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
-                       /* ok, it is a storage devices
-                        * get info and fill it in
+                       /* OK, it's a storage device.  Iterate over its LUNs
+                        * and populate `usb_dev_desc'.
                         */
-                       if (usb_stor_get_info(dev, &usb_stor[usb_max_devs],
-                                               &usb_dev_desc[usb_max_devs]) == 1)
+                       int lun, max_lun, start = usb_max_devs;
+
+                       max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
+                       for (lun = 0;
+                            lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
+                            lun++) {
+                               usb_dev_desc[usb_max_devs].lun = lun;
+                               if (usb_stor_get_info(dev, &usb_stor[start],
+                                                     &usb_dev_desc[usb_max_devs]) == 1) {
                                usb_max_devs++;
+               }
+                       }
                }
                /* if storage device */
                if (usb_max_devs == USB_MAX_STOR_DEV) {
@@ -882,6 +907,7 @@ static int usb_inquiry(ccb *srb, struct us_data *ss)
        do {
                memset(&srb->cmd[0], 0, 12);
                srb->cmd[0] = SCSI_INQUIRY;
+               srb->cmd[1] = srb->lun << 5;
                srb->cmd[4] = 36;
                srb->datalen = 36;
                srb->cmdlen = 12;
@@ -905,6 +931,7 @@ static int usb_request_sense(ccb *srb, struct us_data *ss)
        ptr = (char *)srb->pdata;
        memset(&srb->cmd[0], 0, 12);
        srb->cmd[0] = SCSI_REQ_SENSE;
+       srb->cmd[1] = srb->lun << 5;
        srb->cmd[4] = 18;
        srb->datalen = 18;
        srb->pdata = &srb->sense_buf[0];
@@ -924,6 +951,7 @@ static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
        do {
                memset(&srb->cmd[0], 0, 12);
                srb->cmd[0] = SCSI_TST_U_RDY;
+               srb->cmd[1] = srb->lun << 5;
                srb->datalen = 0;
                srb->cmdlen = 12;
                if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
@@ -943,6 +971,7 @@ static int usb_read_capacity(ccb *srb, struct us_data *ss)
        do {
                memset(&srb->cmd[0], 0, 12);
                srb->cmd[0] = SCSI_RD_CAPAC;
+               srb->cmd[1] = srb->lun << 5;
                srb->datalen = 8;
                srb->cmdlen = 12;
                if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
@@ -957,6 +986,7 @@ static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
 {
        memset(&srb->cmd[0], 0, 12);
        srb->cmd[0] = SCSI_READ10;
+       srb->cmd[1] = srb->lun << 5;
        srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
        srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
        srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
@@ -973,6 +1003,7 @@ static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
 {
        memset(&srb->cmd[0], 0, 12);
        srb->cmd[0] = SCSI_WRITE10;
+       srb->cmd[1] = srb->lun << 5;
        srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
        srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
        srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
diff --git a/doc/README.LED_display b/doc/README.LED_display
new file mode 100644 (file)
index 0000000..521746e
--- /dev/null
@@ -0,0 +1,27 @@
+LED display internal API
+=======================================
+
+This README describes the LED display API.
+
+The API is defined by the include file include/led-display.h
+
+The first step in to define CONFIG_CMD_DISPLAY in the board config file.
+Then you need to provide the following functions to access LED display:
+
+void display_set(int cmd);
+
+This function should control the state of the LED display. Argument is
+an ORed combination of the following values:
+ DISPLAY_CLEAR -- clear the display
+ DISPLAY_HOME  -- set the position to the beginning of display
+ DISPLAY_MARK  -- enable mark (decimal point), if implemented
+
+int display_putc(char c);
+
+This function should display it's parameter on the LED display in the
+current position. Returns the displayed character on success or -1 in
+case of failure.
+
+With this functions defined 'display' command will display it's
+arguments on the LED display (or clear the display if called without
+arguments).
index 4f15db95a651f3cb5eb3431c96198520b0d2e837..5d668f8222b10379a898c911445f6c05f2ca5e4b 100644 (file)
@@ -33,6 +33,7 @@ COBJS-$(CONFIG_NS87308) += ns87308.o
 COBJS-$(CONFIG_STATUS_LED) += status_led.o
 COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o
 COBJS-$(CONFIG_FSL_PMIC) += fsl_pmic.o
+COBJS-$(CONFIG_PDSP188x) += pdsp188x.o
 
 COBJS  := $(COBJS-y)
 SRCS   := $(COBJS:.o=.c)
diff --git a/drivers/misc/pdsp188x.c b/drivers/misc/pdsp188x.c
new file mode 100644 (file)
index 0000000..656b6ee
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010 Sergey Poselenov, Emcraft Systems, <sposelenov@emcraft.com>
+ * Copyright 2010 Ilya Yanok, Emcraft Systems, <yanok@emcraft.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <led-display.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CMD_DISPLAY
+#define CWORD_CLEAR    0x80
+#define CLEAR_DELAY    (110 * 2)
+#define DISPLAY_SIZE   8
+
+static int pos; /* Current display position */
+
+/* Handle different display commands */
+void display_set(int cmd)
+{
+       if (cmd & DISPLAY_CLEAR) {
+               out_8((unsigned char *)CONFIG_SYS_DISP_CWORD, CWORD_CLEAR);
+               udelay(1000 * CLEAR_DELAY);
+       }
+
+       if (cmd & DISPLAY_HOME) {
+               pos = 0;
+       }
+}
+
+/*
+ * Display a character at the current display position.
+ * Characters beyond the display size are ignored.
+ */
+int display_putc(char c)
+{
+       if (pos >= DISPLAY_SIZE)
+               return -1;
+
+       out_8((unsigned char *)CONFIG_SYS_DISP_CHR_RAM + pos++, c);
+
+       return c;
+}
+#endif
index 02dd27ffb1f9154305bae578682cb08af4f26925..798902f337698d9e54dad633dcc134481fa2069e 100644 (file)
@@ -2033,7 +2033,7 @@ unsigned long flash_init (void)
                        printf ("## Unknown FLASH on Bank %d "
                                "- Size = 0x%08lx = %ld MB\n",
                                i+1, flash_info[i].size,
-                               flash_info[i].size << 20);
+                               flash_info[i].size >> 20);
 #endif /* CONFIG_SYS_FLASH_QUIET_TEST */
                }
 #ifdef CONFIG_SYS_FLASH_PROTECTION
index 6eb52ed50c6a8eef289327e63c84e8238f2562c9..a195ddab35774a9044f0446e8e0d66d880636c3a 100644 (file)
@@ -142,3 +142,47 @@ void put_mtd_device(struct mtd_info *mtd)
        c = --mtd->usecount;
        BUG_ON(c < 0);
 }
+
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+/**
+ * mtd_get_len_incl_bad
+ *
+ * Check if length including bad blocks fits into device.
+ *
+ * @param mtd an MTD device
+ * @param offset offset in flash
+ * @param length image length
+ * @return image length including bad blocks in *len_incl_bad and whether or not
+ *         the length returned was truncated in *truncated
+ */
+void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
+                         const uint64_t length, uint64_t *len_incl_bad,
+                         int *truncated)
+{
+       *truncated = 0;
+       *len_incl_bad = 0;
+
+       if (!mtd->block_isbad) {
+               *len_incl_bad = length;
+               return;
+       }
+
+       uint64_t len_excl_bad = 0;
+       uint64_t block_len;
+
+       while (len_excl_bad < length) {
+               if (offset >= mtd->size) {
+                       *truncated = 1;
+                       return;
+               }
+
+               block_len = mtd->erasesize - (offset & (mtd->erasesize - 1));
+
+               if (!mtd->block_isbad(mtd, offset & ~(mtd->erasesize - 1)))
+                       len_excl_bad += block_len;
+
+               *len_incl_bad += block_len;
+               offset       += block_len;
+       }
+}
+#endif /* defined(CONFIG_CMD_MTDPARTS_SPREAD) */
index e2e43eaec4a5d49605da063d1d5ba598ae8245f3..f647e436681b1e1c255503152b9d6379753e6bef 100644 (file)
@@ -230,18 +230,6 @@ static void part_sync(struct mtd_info *mtd)
        part->master->sync(part->master);
 }
 
-static int part_suspend(struct mtd_info *mtd)
-{
-       struct mtd_part *part = PART(mtd);
-       return part->master->suspend(part->master);
-}
-
-static void part_resume(struct mtd_info *mtd)
-{
-       struct mtd_part *part = PART(mtd);
-       part->master->resume(part->master);
-}
-
 static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
        struct mtd_part *part = PART(mtd);
@@ -339,10 +327,6 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
                slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
        if (master->sync)
                slave->mtd.sync = part_sync;
-       if (!partno && master->suspend && master->resume) {
-                       slave->mtd.suspend = part_suspend;
-                       slave->mtd.resume = part_resume;
-       }
        if (master->lock)
                slave->mtd.lock = part_lock;
        if (master->unlock)
index 7d178468adbe4fa0954b1d5f932a35c1f0deafdf..21cc5a39407d29f74ddb987f6d0373632fa6afba 100644 (file)
  *
  */
 
-/* XXX U-BOOT XXX */
-#if 0
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/compatmac.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-#include <linux/leds.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_MTD_PARTITIONS
-#include <linux/mtd/partitions.h>
-#endif
-
-#endif
-
 #include <common.h>
 
 #define ENOTSUPP       524     /* Operation is not supported */
 #include <asm/io.h>
 #include <asm/errno.h>
 
-#ifdef CONFIG_JFFS2_NAND
-#include <jffs2/jffs2.h>
-#endif
-
 /*
  * CONFIG_SYS_NAND_RESET_CNT is used as a timeout mechanism when resetting
  * a flash.  NAND flash is initialized prior to interrupts so standard timers
@@ -143,44 +115,17 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 
 static int nand_wait(struct mtd_info *mtd, struct nand_chip *this);
 
-/*
- * For devices which display every fart in the system on a separate LED. Is
- * compiled away when LED support is disabled.
- */
-/* XXX U-BOOT XXX */
-#if 0
-DEFINE_LED_TRIGGER(nand_led_trigger);
-#endif
-
 /**
  * nand_release_device - [GENERIC] release chip
  * @mtd:       MTD device structure
  *
  * Deselect, release chip lock and wake up anyone waiting on the device
  */
-/* XXX U-BOOT XXX */
-#if 0
-static void nand_release_device(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd->priv;
-
-       /* De-select the NAND device */
-       chip->select_chip(mtd, -1);
-
-       /* Release the controller and the chip */
-       spin_lock(&chip->controller->lock);
-       chip->controller->active = NULL;
-       chip->state = FL_READY;
-       wake_up(&chip->controller->wq);
-       spin_unlock(&chip->controller->lock);
-}
-#else
 static void nand_release_device (struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        this->select_chip(mtd, -1);     /* De-select the NAND device */
 }
-#endif
 
 /**
  * nand_read_byte - [DEFAULT] read one byte from the chip
@@ -490,24 +435,6 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
  * Wait for the ready pin, after a command
  * The timeout is catched later.
  */
-/* XXX U-BOOT XXX */
-#if 0
-void nand_wait_ready(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd->priv;
-       unsigned long timeo = jiffies + 2;
-
-       led_trigger_event(nand_led_trigger, LED_FULL);
-       /* wait until command is processed or timeout occures */
-       do {
-               if (chip->dev_ready(mtd))
-                       break;
-               touch_softlockup_watchdog();
-       } while (time_before(jiffies, timeo));
-       led_trigger_event(nand_led_trigger, LED_OFF);
-}
-EXPORT_SYMBOL_GPL(nand_wait_ready);
-#else
 void nand_wait_ready(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd->priv;
@@ -522,7 +449,6 @@ void nand_wait_ready(struct mtd_info *mtd)
                                break;
        }
 }
-#endif
 
 /**
  * nand_command - [DEFAULT] Send command to NAND device
@@ -759,45 +685,11 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
  *
  * Get the device and lock it for exclusive access
  */
-/* XXX U-BOOT XXX */
-#if 0
-static int
-nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
-{
-       spinlock_t *lock = &chip->controller->lock;
-       wait_queue_head_t *wq = &chip->controller->wq;
-       DECLARE_WAITQUEUE(wait, current);
- retry:
-       spin_lock(lock);
-
-       /* Hardware controller shared among independend devices */
-       /* Hardware controller shared among independend devices */
-       if (!chip->controller->active)
-               chip->controller->active = chip;
-
-       if (chip->controller->active == chip && chip->state == FL_READY) {
-               chip->state = new_state;
-               spin_unlock(lock);
-               return 0;
-       }
-       if (new_state == FL_PM_SUSPENDED) {
-               spin_unlock(lock);
-               return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
-       }
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       add_wait_queue(wq, &wait);
-       spin_unlock(lock);
-       schedule();
-       remove_wait_queue(wq, &wait);
-       goto retry;
-}
-#else
 static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state)
 {
        this->state = new_state;
        return 0;
 }
-#endif
 
 /**
  * nand_wait - [DEFAULT]  wait until the command is done
@@ -808,46 +700,6 @@ static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int ne
  * Erase can take up to 400ms and program up to 20ms according to
  * general NAND and SmartMedia specs
  */
-/* XXX U-BOOT XXX */
-#if 0
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
-{
-
-       unsigned long timeo = jiffies;
-       int status, state = chip->state;
-
-       if (state == FL_ERASING)
-               timeo += (HZ * 400) / 1000;
-       else
-               timeo += (HZ * 20) / 1000;
-
-       led_trigger_event(nand_led_trigger, LED_FULL);
-
-       /* Apply this short delay always to ensure that we do wait tWB in
-        * any case on any machine. */
-       ndelay(100);
-
-       if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
-               chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
-       else
-               chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
-
-       while (time_before(jiffies, timeo)) {
-               if (chip->dev_ready) {
-                       if (chip->dev_ready(mtd))
-                               break;
-               } else {
-                       if (chip->read_byte(mtd) & NAND_STATUS_READY)
-                               break;
-               }
-               cond_resched();
-       }
-       led_trigger_event(nand_led_trigger, LED_OFF);
-
-       status = (int)chip->read_byte(mtd);
-       return status;
-}
-#else
 static int nand_wait(struct mtd_info *mtd, struct nand_chip *this)
 {
        unsigned long   timeo;
@@ -886,7 +738,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this)
 
        return this->read_byte(mtd);
 }
-#endif
 
 /**
  * nand_read_page_raw - [Intern] read raw page data without ecc
@@ -2001,13 +1852,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
        if (!writelen)
                return 0;
 
-       /* reject writes, which are not page aligned */
-       if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
-               printk(KERN_NOTICE "nand_write: "
-                      "Attempt to write not page aligned data\n");
-               return -EINVAL;
-       }
-
        column = to & (mtd->writesize - 1);
        subpage = column || (writelen & (mtd->writesize - 1));
 
@@ -2523,32 +2367,6 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
        return chip->block_markbad(mtd, ofs);
 }
 
-/**
- * nand_suspend - [MTD Interface] Suspend the NAND flash
- * @mtd:       MTD device structure
- */
-static int nand_suspend(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd->priv;
-
-       return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
-}
-
-/**
- * nand_resume - [MTD Interface] Resume the NAND flash
- * @mtd:       MTD device structure
- */
-static void nand_resume(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd->priv;
-
-       if (chip->state == FL_PM_SUSPENDED)
-               nand_release_device(mtd);
-       else
-               printk(KERN_ERR "nand_resume() called for a chip which is not "
-                      "in suspended state\n");
-}
-
 /*
  * Set default functions
  */
@@ -2584,17 +2402,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
                chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
        if (!chip->scan_bbt)
                chip->scan_bbt = nand_default_bbt;
-
-       if (!chip->controller) {
+       if (!chip->controller)
                chip->controller = &chip->hwcontrol;
-
-               /* XXX U-BOOT XXX */
-#if 0
-               spin_lock_init(&chip->controller->lock);
-               init_waitqueue_head(&chip->controller->wq);
-#endif
-       }
-
 }
 
 /*
@@ -3028,8 +2837,6 @@ int nand_scan_tail(struct mtd_info *mtd)
        mtd->sync = nand_sync;
        mtd->lock = NULL;
        mtd->unlock = NULL;
-       mtd->suspend = nand_suspend;
-       mtd->resume = nand_resume;
        mtd->block_isbad = nand_block_isbad;
        mtd->block_markbad = nand_block_markbad;
 
@@ -3043,16 +2850,6 @@ int nand_scan_tail(struct mtd_info *mtd)
        return 0;
 }
 
-/* module_text_address() isn't exported, and it's mostly a pointless
-   test if this is a module _anyway_ -- they'd have to try _really_ hard
-   to call us from in-kernel code if the core NAND support is modular. */
-#ifdef MODULE
-#define caller_is_module() (1)
-#else
-#define caller_is_module() \
-       module_text_address((unsigned long)__builtin_return_address(0))
-#endif
-
 /**
  * nand_scan - [NAND Interface] Scan for the NAND device
  * @mtd:       MTD device structure
@@ -3069,15 +2866,6 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
 {
        int ret;
 
-       /* Many callers got this wrong, so check for it for a while... */
-       /* XXX U-BOOT XXX */
-#if 0
-       if (!mtd->owner && caller_is_module()) {
-               printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
-               BUG();
-       }
-#endif
-
        ret = nand_scan_ident(mtd, maxchips);
        if (!ret)
                ret = nand_scan_tail(mtd);
@@ -3096,40 +2884,9 @@ void nand_release(struct mtd_info *mtd)
        /* Deregister partitions */
        del_mtd_partitions(mtd);
 #endif
-       /* Deregister the device */
-       /* XXX U-BOOT XXX */
-#if 0
-       del_mtd_device(mtd);
-#endif
 
        /* Free bad block table memory */
        kfree(chip->bbt);
        if (!(chip->options & NAND_OWN_BUFFERS))
                kfree(chip->buffers);
 }
-
-/* XXX U-BOOT XXX */
-#if 0
-EXPORT_SYMBOL_GPL(nand_scan);
-EXPORT_SYMBOL_GPL(nand_scan_ident);
-EXPORT_SYMBOL_GPL(nand_scan_tail);
-EXPORT_SYMBOL_GPL(nand_release);
-
-static int __init nand_base_init(void)
-{
-       led_trigger_register_simple("nand-disk", &nand_led_trigger);
-       return 0;
-}
-
-static void __exit nand_base_exit(void)
-{
-       led_trigger_unregister_simple(nand_led_trigger);
-}
-
-module_init(nand_base_init);
-module_exit(nand_base_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("Generic NAND flash driver code");
-#endif
index 2fe68abe1df8c05255dc5589fc35cc6e6998bbd9..521dddec2784202568b45f7b8a02fc20fcfd8338 100644 (file)
 
 #include <asm/errno.h>
 
-/* XXX U-BOOT XXX */
-#if 0
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/compatmac.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/vmalloc.h>
-#endif
-
 /**
  * check_pattern - [GENERIC] check if a pattern is in the buffer
  * @buf:       the buffer to search
@@ -1231,9 +1218,3 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
        }
        return 1;
 }
-
-/* XXX U-BOOT XXX */
-#if 0
-EXPORT_SYMBOL(nand_scan_bbt);
-EXPORT_SYMBOL(nand_default_bbt);
-#endif
index 463f9cb4d412eef12fa512f36ba7cb65f9fafee7..52bc916afb7370b30763b776a86f10b8d31c5861 100644 (file)
 
 #include <common.h>
 
-/* XXX U-BOOT XXX */
-#if 0
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mtd/nand_ecc.h>
-#endif
-
 #include <asm/errno.h>
 #include <linux/mtd/mtd.h>
 
@@ -140,10 +132,6 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 
        return 0;
 }
-/* XXX U-BOOT XXX */
-#if 0
-EXPORT_SYMBOL(nand_calculate_ecc);
-#endif
 #endif /* CONFIG_NAND_SPL */
 
 static inline int countbits(uint32_t byte)
@@ -212,8 +200,3 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat,
 
        return -EBADMSG;
 }
-
-/* XXX U-BOOT XXX */
-#if 0
-EXPORT_SYMBOL(nand_correct_data);
-#endif
index 29c42f73b1cc4c3c2131a332e68763937ed49585..22c741169476269d167d42b8207da08f500768ae 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
  *
+ * Copyright 2010 Freescale Semiconductor
+ * The portions of this file whose copyright is held by Freescale and which
+ * are not considered a derived work of GPL v2-only code may be distributed
+ * and/or modified 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.
  */
 
 #include <common.h>
@@ -69,7 +75,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
 {
        struct jffs2_unknown_node cleanmarker;
        erase_info_t erase;
-       ulong erase_length;
+       unsigned long erase_length, erased_length; /* in blocks */
        int bbtest = 1;
        int result;
        int percent_complete = -1;
@@ -78,13 +84,19 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
        struct mtd_oob_ops oob_opts;
        struct nand_chip *chip = meminfo->priv;
 
+       if ((opts->offset & (meminfo->writesize - 1)) != 0) {
+               printf("Attempt to erase non page aligned data\n");
+               return -1;
+       }
+
        memset(&erase, 0, sizeof(erase));
        memset(&oob_opts, 0, sizeof(oob_opts));
 
        erase.mtd = meminfo;
        erase.len  = meminfo->erasesize;
        erase.addr = opts->offset;
-       erase_length = opts->length;
+       erase_length = lldiv(opts->length + meminfo->erasesize - 1,
+                            meminfo->erasesize);
 
        cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
        cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
@@ -108,15 +120,8 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
                priv_nand->bbt = NULL;
        }
 
-       if (erase_length < meminfo->erasesize) {
-               printf("Warning: Erase size 0x%08lx smaller than one "  \
-                      "erase block 0x%08x\n",erase_length, meminfo->erasesize);
-               printf("         Erasing 0x%08x instead\n", meminfo->erasesize);
-               erase_length = meminfo->erasesize;
-       }
-
-       for (;
-            erase.addr < opts->offset + erase_length;
+       for (erased_length = 0;
+            erased_length < erase_length;
             erase.addr += meminfo->erasesize) {
 
                WATCHDOG_RESET ();
@@ -129,6 +134,10 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
                                               "0x%08llx                 "
                                               "                         \n",
                                               erase.addr);
+
+                               if (!opts->spread)
+                                       erased_length++;
+
                                continue;
 
                        } else if (ret < 0) {
@@ -139,6 +148,8 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
                        }
                }
 
+               erased_length++;
+
                result = meminfo->erase(meminfo, &erase);
                if (result != 0) {
                        printf("\n%s: MTD Erase failure: %d\n",
@@ -165,9 +176,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
                }
 
                if (!opts->quiet) {
-                       unsigned long long n =(unsigned long long)
-                               (erase.addr + meminfo->erasesize - opts->offset)
-                               * 100;
+                       unsigned long long n = erased_length * 100ULL;
                        int percent;
 
                        do_div(n, erase_length);
@@ -202,41 +211,6 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
        return 0;
 }
 
-/* XXX U-BOOT XXX */
-#if 0
-
-#define MAX_PAGE_SIZE  2048
-#define MAX_OOB_SIZE   64
-
-/*
- * buffer array used for writing data
- */
-static unsigned char data_buf[MAX_PAGE_SIZE];
-static unsigned char oob_buf[MAX_OOB_SIZE];
-
-/* OOB layouts to pass into the kernel as default */
-static struct nand_ecclayout none_ecclayout = {
-       .useecc = MTD_NANDECC_OFF,
-};
-
-static struct nand_ecclayout jffs2_ecclayout = {
-       .useecc = MTD_NANDECC_PLACE,
-       .eccbytes = 6,
-       .eccpos = { 0, 1, 2, 3, 6, 7 }
-};
-
-static struct nand_ecclayout yaffs_ecclayout = {
-       .useecc = MTD_NANDECC_PLACE,
-       .eccbytes = 6,
-       .eccpos = { 8, 9, 10, 13, 14, 15}
-};
-
-static struct nand_ecclayout autoplace_ecclayout = {
-       .useecc = MTD_NANDECC_AUTOPLACE
-};
-#endif
-
-/* XXX U-BOOT XXX */
 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 
 /******************************************************************************
@@ -423,36 +397,43 @@ int nand_unlock(struct mtd_info *mtd, ulong start, ulong length)
 #endif
 
 /**
- * get_len_incl_bad
+ * check_skip_len
  *
- * Check if length including bad blocks fits into device.
+ * Check if there are any bad blocks, and whether length including bad
+ * blocks fits into device
  *
  * @param nand NAND device
  * @param offset offset in flash
  * @param length image length
- * @return image length including bad blocks
+ * @return 0 if the image fits and there are no bad blocks
+ *         1 if the image fits, but there are bad blocks
+ *        -1 if the image does not fit
  */
-static size_t get_len_incl_bad (nand_info_t *nand, loff_t offset,
-                               const size_t length)
+static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
 {
-       size_t len_incl_bad = 0;
        size_t len_excl_bad = 0;
-       size_t block_len;
+       int ret = 0;
 
        while (len_excl_bad < length) {
-               block_len = nand->erasesize - (offset & (nand->erasesize - 1));
+               size_t block_len, block_off;
+               loff_t block_start;
 
-               if (!nand_block_isbad (nand, offset & ~(nand->erasesize - 1)))
-                       len_excl_bad += block_len;
+               if (offset >= nand->size)
+                       return -1;
 
-               len_incl_bad += block_len;
-               offset       += block_len;
+               block_start = offset & ~(loff_t)(nand->erasesize - 1);
+               block_off = offset & (nand->erasesize - 1);
+               block_len = nand->erasesize - block_off;
 
-               if (offset >= nand->size)
-                       break;
+               if (!nand_block_isbad(nand, block_start))
+                       len_excl_bad += block_len;
+               else
+                       ret = 1;
+
+               offset += block_len;
        }
 
-       return len_incl_bad;
+       return ret;
 }
 
 /**
@@ -474,29 +455,41 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 {
        int rval;
        size_t left_to_write = *length;
-       size_t len_incl_bad;
        u_char *p_buffer = buffer;
+       int need_skip;
 
-       /* Reject writes, which are not page aligned */
-       if ((offset & (nand->writesize - 1)) != 0 ||
-           (*length & (nand->writesize - 1)) != 0) {
+       /*
+        * nand_write() handles unaligned, partial page writes.
+        *
+        * We allow length to be unaligned, for convenience in
+        * using the $filesize variable.
+        *
+        * However, starting at an unaligned offset makes the
+        * semantics of bad block skipping ambiguous (really,
+        * you should only start a block skipping access at a
+        * partition boundary).  So don't try to handle that.
+        */
+       if ((offset & (nand->writesize - 1)) != 0) {
                printf ("Attempt to write non page aligned data\n");
+               *length = 0;
                return -EINVAL;
        }
 
-       len_incl_bad = get_len_incl_bad (nand, offset, *length);
-
-       if ((offset + len_incl_bad) > nand->size) {
+       need_skip = check_skip_len(nand, offset, *length);
+       if (need_skip < 0) {
                printf ("Attempt to write outside the flash area\n");
+               *length = 0;
                return -EINVAL;
        }
 
-       if (len_incl_bad == *length) {
+       if (!need_skip) {
                rval = nand_write (nand, offset, length, buffer);
-               if (rval != 0)
-                       printf ("NAND write to offset %llx failed %d\n",
-                               offset, rval);
+               if (rval == 0)
+                       return 0;
 
+               *length = 0;
+               printf ("NAND write to offset %llx failed %d\n",
+                       offset, rval);
                return rval;
        }
 
@@ -553,20 +546,28 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 {
        int rval;
        size_t left_to_read = *length;
-       size_t len_incl_bad;
        u_char *p_buffer = buffer;
+       int need_skip;
 
-       len_incl_bad = get_len_incl_bad (nand, offset, *length);
+       if ((offset & (nand->writesize - 1)) != 0) {
+               printf ("Attempt to read non page aligned data\n");
+               *length = 0;
+               return -EINVAL;
+       }
 
-       if ((offset + len_incl_bad) > nand->size) {
+       need_skip = check_skip_len(nand, offset, *length);
+       if (need_skip < 0) {
                printf ("Attempt to read outside the flash area\n");
+               *length = 0;
                return -EINVAL;
        }
 
-       if (len_incl_bad == *length) {
+       if (!need_skip) {
                rval = nand_read (nand, offset, length, buffer);
                if (!rval || rval == -EUCLEAN)
                        return 0;
+
+               *length = 0;
                printf ("NAND read from offset %llx failed %d\n",
                        offset, rval);
                return rval;
index f9273ab970489fda54ad8faa1c50e51aad8da887..24e02c2840b6c30f84b80d03be01e5af778e7a80 100644 (file)
@@ -2213,6 +2213,7 @@ char *onenand_print_device_info(int device, int version)
 }
 
 static const struct onenand_manufacturers onenand_manuf_ids[] = {
+       {ONENAND_MFR_NUMONYX, "Numonyx"},
        {ONENAND_MFR_SAMSUNG, "Samsung"},
 };
 
index ea875dc812b4bcf34e41af00072ff3c8004207c0..b4ba1dda51dc4fee48116841f702d17787e11787 100644 (file)
@@ -2,6 +2,8 @@
  * SPI flash interface
  *
  * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
+ *
  * Licensed under the GPL-2 or later.
  */
 
@@ -96,13 +98,68 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
        return ret;
 }
 
+/*
+ * The following table holds all device probe functions
+ *
+ * shift:  number of continuation bytes before the ID
+ * idcode: the expected IDCODE or 0xff for non JEDEC devices
+ * probe:  the function to call
+ *
+ * Non JEDEC devices should be ordered in the table such that
+ * the probe functions with best detection algorithms come first.
+ *
+ * Several matching entries are permitted, they will be tried
+ * in sequence until a probe function returns non NULL.
+ *
+ * IDCODE_CONT_LEN may be redefined if a device needs to declare a
+ * larger "shift" value.  IDCODE_PART_LEN generally shouldn't be
+ * changed.  This is the max number of bytes probe functions may
+ * examine when looking up part-specific identification info.
+ *
+ * Probe functions will be given the idcode buffer starting at their
+ * manu id byte (the "idcode" in the table below).  In other words,
+ * all of the continuation bytes will be skipped (the "shift" below).
+ */
+#define IDCODE_CONT_LEN 0
+#define IDCODE_PART_LEN 5
+static const struct {
+       const u8 shift;
+       const u8 idcode;
+       struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
+} flashes[] = {
+       /* Keep it sorted by define name */
+#ifdef CONFIG_SPI_FLASH_ATMEL
+       { 0, 0x1f, spi_flash_probe_atmel, },
+#endif
+#ifdef CONFIG_SPI_FLASH_MACRONIX
+       { 0, 0xc2, spi_flash_probe_macronix, },
+#endif
+#ifdef CONFIG_SPI_FLASH_SPANSION
+       { 0, 0x01, spi_flash_probe_spansion, },
+#endif
+#ifdef CONFIG_SPI_FLASH_SST
+       { 0, 0xbf, spi_flash_probe_sst, },
+#endif
+#ifdef CONFIG_SPI_FLASH_STMICRO
+       { 0, 0x20, spi_flash_probe_stmicro, },
+#endif
+#ifdef CONFIG_SPI_FLASH_WINBOND
+       { 0, 0xef, spi_flash_probe_winbond, },
+#endif
+       /* Keep it sorted by best detection */
+#ifdef CONFIG_SPI_FLASH_STMICRO
+       { 0, 0xff, spi_flash_probe_stmicro, },
+#endif
+};
+#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
+
 struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
                unsigned int max_hz, unsigned int spi_mode)
 {
        struct spi_slave *spi;
-       struct spi_flash *flash;
-       int ret;
-       u8 idcode[5];
+       struct spi_flash *flash = NULL;
+       int ret, i, shift;
+       u8 idcode[IDCODE_LEN], *idp;
 
        spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
        if (!spi) {
@@ -117,53 +174,34 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
        }
 
        /* Read the ID codes */
-       ret = spi_flash_cmd(spi, CMD_READ_ID, &idcode, sizeof(idcode));
+       ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
        if (ret)
                goto err_read_id;
 
-       debug("SF: Got idcode %02x %02x %02x %02x %02x\n", idcode[0],
-                       idcode[1], idcode[2], idcode[3], idcode[4]);
-
-       switch (idcode[0]) {
-#ifdef CONFIG_SPI_FLASH_SPANSION
-       case 0x01:
-               flash = spi_flash_probe_spansion(spi, idcode);
-               break;
+#ifdef DEBUG
+       printf("SF: Got idcodes\n");
+       print_buffer(0, idcode, 1, sizeof(idcode), 0);
 #endif
-#ifdef CONFIG_SPI_FLASH_ATMEL
-       case 0x1F:
-               flash = spi_flash_probe_atmel(spi, idcode);
-               break;
-#endif
-#ifdef CONFIG_SPI_FLASH_MACRONIX
-       case 0xc2:
-               flash = spi_flash_probe_macronix(spi, idcode);
-               break;
-#endif
-#ifdef CONFIG_SPI_FLASH_WINBOND
-       case 0xef:
-               flash = spi_flash_probe_winbond(spi, idcode);
-               break;
-#endif
-#ifdef CONFIG_SPI_FLASH_STMICRO
-       case 0x20:
-       case 0xff: /* Let the stmicro func handle non-JEDEC ids */
-               flash = spi_flash_probe_stmicro(spi, idcode);
-               break;
-#endif
-#ifdef CONFIG_SPI_FLASH_SST
-       case 0xBF:
-               flash = spi_flash_probe_sst(spi, idcode);
-               break;
-#endif
-       default:
-               printf("SF: Unsupported manufacturer %02X\n", idcode[0]);
-               flash = NULL;
-               break;
-       }
 
-       if (!flash)
+       /* count the number of continuation bytes */
+       for (shift = 0, idp = idcode;
+            shift < IDCODE_CONT_LEN && *idp == 0x7f;
+            ++shift, ++idp)
+               continue;
+
+       /* search the table for matches in shift and id */
+       for (i = 0; i < ARRAY_SIZE(flashes); ++i)
+               if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
+                       /* we have a match, call probe */
+                       flash = flashes[i].probe(spi, idp);
+                       if (flash)
+                               break;
+               }
+
+       if (!flash) {
+               printf("SF: Unsupported manufacturer %02x\n", *idp);
                goto err_manufacturer_probe;
+       }
 
        spi_release_bus(spi);
 
index 218eeff86e6ece0d10fc7dff8078cc51f3f9d505..79eb66b26748f6b0bdcb51807e978321b6eecf04 100644 (file)
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_DNET) += dnet.o
 COBJS-$(CONFIG_E1000) += e1000.o
 COBJS-$(CONFIG_EEPRO100) += eepro100.o
 COBJS-$(CONFIG_ENC28J60) += enc28j60.o
+COBJS-$(CONFIG_ENC28J60_LPC2292) += enc28j60_lpc2292.o
 COBJS-$(CONFIG_EP93XX) += ep93xx_eth.o
 COBJS-$(CONFIG_ETHOC) += ethoc.o
 COBJS-$(CONFIG_FEC_MXC) += fec_mxc.o
index ca2b16bf8f3af310cc5fb7550e21178f68518ba2..4e5685c0c32b83fae2a46be6e6c33c43e9f4eacb 100644 (file)
@@ -220,7 +220,7 @@ static int at91emac_phy_reset(struct eth_device *netdev)
        at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMCR,
                (BMCR_ANENABLE | BMCR_ANRESTART));
 
-       for (i = 0; i < 100000 / 100; i++) {
+       for (i = 0; i < 30000; i++) {
                at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
                        MII_BMSR, &status);
                if (status & BMSR_ANEGCOMPLETE)
@@ -233,7 +233,7 @@ static int at91emac_phy_reset(struct eth_device *netdev)
        } else {
                printf("%s: Autonegotiation timed out (status=0x%04x)\n",
                       netdev->name, status);
-               return 1;
+               return -1;
        }
        return 0;
 }
@@ -252,7 +252,7 @@ static int at91emac_phy_init(struct eth_device *netdev)
                MII_PHYSID1, &phy_id);
        if (phy_id == 0xffff) {
                printf("%s: No PHY present\n", netdev->name);
-               return 1;
+               return -1;
        }
 
        at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
@@ -261,7 +261,7 @@ static int at91emac_phy_init(struct eth_device *netdev)
        if (!(status & BMSR_LSTATUS)) {
                /* Try to re-negotiate if we don't have link already. */
                if (at91emac_phy_reset(netdev))
-                       return 2;
+                       return -2;
 
                for (i = 0; i < 100000 / 100; i++) {
                        at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
@@ -273,7 +273,7 @@ static int at91emac_phy_init(struct eth_device *netdev)
        }
        if (!(status & BMSR_LSTATUS)) {
                VERBOSEP("%s: link down\n", netdev->name);
-               return 3;
+               return -3;
        } else {
                at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
                        MII_ADVERTISE, &adv);
@@ -298,7 +298,7 @@ int at91emac_UpdateLinkSpeed(at91_emac_t *emac)
        at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMSR, &stat1);
 
        if (!(stat1 & BMSR_LSTATUS))    /* link status up? */
-               return 1;
+               return -1;
 
        if (stat1 & BMSR_100FULL) {
                /*set Emac for 100BaseTX and Full Duplex  */
@@ -333,7 +333,7 @@ int at91emac_UpdateLinkSpeed(at91_emac_t *emac)
                        &emac->cfg);
                return 0;
        }
-       return 1;
+       return 0;
 }
 
 static int at91emac_init(struct eth_device *netdev, bd_t *bd)
@@ -399,7 +399,7 @@ static int at91emac_init(struct eth_device *netdev, bd_t *bd)
                at91emac_UpdateLinkSpeed(emac);
                return 0;
        }
-       return 1;
+       return -1;
 }
 
 static void at91emac_halt(struct eth_device *netdev)
@@ -501,11 +501,11 @@ int at91emac_register(bd_t *bis, unsigned long iobase)
                iobase = AT91_EMAC_BASE;
        emac = malloc(sizeof(*emac)+512);
        if (emac == NULL)
-               return 1;
+               return -1;
        dev = malloc(sizeof(*dev));
        if (dev == NULL) {
                free(emac);
-               return 1;
+               return -1;
        }
        /* alignment as per Errata (64 bytes) is insufficient! */
        emacfix = (emac_device *) (((unsigned long) emac + 0x1ff) & 0xFFFFFE00);
index 41a9910919666bef8757fd64166b44d2c19cd5b3..e06896fea710fa8141a03f74adb8d03bbd89ef06 100644 (file)
@@ -65,21 +65,6 @@ void eth_mdio_enable(void)
        davinci_eth_mdio_enable();
 }
 
-static u_int8_t davinci_eth_mac_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-/*
- * This function must be called before emac_open() if you want to override
- * the default mac address.
- */
-void davinci_eth_set_mac_addr(const u_int8_t *addr)
-{
-       int i;
-
-       for (i = 0; i < sizeof (davinci_eth_mac_addr); i++) {
-               davinci_eth_mac_addr[i] = addr[i];
-       }
-}
-
 /* EMAC Addresses */
 static volatile emac_regs      *adap_emac = (emac_regs *)EMAC_BASE_ADDR;
 static volatile ewrap_regs     *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
@@ -100,6 +85,43 @@ static volatile u_int8_t    active_phy_addr = 0xff;
 
 phy_t                          phy;
 
+static int davinci_eth_set_mac_addr(struct eth_device *dev)
+{
+       unsigned long           mac_hi;
+       unsigned long           mac_lo;
+
+       /*
+        * Set MAC Addresses & Init multicast Hash to 0 (disable any multicast
+        * receive)
+        *  Using channel 0 only - other channels are disabled
+        *  */
+       writel(0, &adap_emac->MACINDEX);
+       mac_hi = (dev->enetaddr[3] << 24) |
+                (dev->enetaddr[2] << 16) |
+                (dev->enetaddr[1] << 8)  |
+                (dev->enetaddr[0]);
+       mac_lo = (dev->enetaddr[5] << 8) |
+                (dev->enetaddr[4]);
+
+       writel(mac_hi, &adap_emac->MACADDRHI);
+#if defined(DAVINCI_EMAC_VERSION2)
+       writel(mac_lo | EMAC_MAC_ADDR_IS_VALID | EMAC_MAC_ADDR_MATCH,
+              &adap_emac->MACADDRLO);
+#else
+       writel(mac_lo, &adap_emac->MACADDRLO);
+#endif
+
+       writel(0, &adap_emac->MACHASH1);
+       writel(0, &adap_emac->MACHASH2);
+
+       /* Set source MAC address - REQUIRED */
+       writel(mac_hi, &adap_emac->MACSRCADDRHI);
+       writel(mac_lo, &adap_emac->MACSRCADDRLO);
+
+
+       return 0;
+}
+
 static void davinci_eth_mdio_enable(void)
 {
        u_int32_t       clkdiv;
@@ -286,8 +308,6 @@ static int davinci_eth_open(struct eth_device *dev, bd_t *bis)
        dv_reg_p                addr;
        u_int32_t               clkdiv, cnt;
        volatile emac_desc      *rx_desc;
-       unsigned long           mac_hi;
-       unsigned long           mac_lo;
 
        debug_emac("+ emac_open\n");
 
@@ -311,30 +331,7 @@ static int davinci_eth_open(struct eth_device *dev, bd_t *bis)
        writel(1, &adap_emac->TXCONTROL);
        writel(1, &adap_emac->RXCONTROL);
 
-       /* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */
-       /* Using channel 0 only - other channels are disabled */
-       writel(0, &adap_emac->MACINDEX);
-       mac_hi = (davinci_eth_mac_addr[3] << 24) |
-                (davinci_eth_mac_addr[2] << 16) |
-                (davinci_eth_mac_addr[1] << 8)  |
-                (davinci_eth_mac_addr[0]);
-       mac_lo = (davinci_eth_mac_addr[5] << 8) |
-                (davinci_eth_mac_addr[4]);
-
-       writel(mac_hi, &adap_emac->MACADDRHI);
-#if defined(DAVINCI_EMAC_VERSION2)
-       writel(mac_lo | EMAC_MAC_ADDR_IS_VALID | EMAC_MAC_ADDR_MATCH,
-              &adap_emac->MACADDRLO);
-#else
-       writel(mac_lo, &adap_emac->MACADDRLO);
-#endif
-
-       writel(0, &adap_emac->MACHASH1);
-       writel(0, &adap_emac->MACHASH2);
-
-       /* Set source MAC address - REQUIRED */
-       writel(mac_hi, &adap_emac->MACSRCADDRHI);
-       writel(mac_lo, &adap_emac->MACSRCADDRLO);
+       davinci_eth_set_mac_addr(dev);
 
        /* Set DMA 8 TX / 8 RX Head pointers to 0 */
        addr = &adap_emac->TX0HDP;
@@ -636,6 +633,7 @@ int davinci_emac_initialize(void)
        dev->halt = davinci_eth_close;
        dev->send = davinci_eth_send_packet;
        dev->recv = davinci_eth_rcv_packet;
+       dev->write_hwaddr = davinci_eth_set_mac_addr;
 
        eth_register(dev);
 
index 3238a502ca75029d19d2d6bf30f0195b7e19d0b1..6c161b632f4165b87e7939c5ae494f736d72e855 100644 (file)
@@ -1,4 +1,9 @@
 /*
+ * (C) Copyright 2010
+ * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de
+ * Martin Krause, Martin.Krause@tqs.de
+ * reworked original enc28j60.c
+ *
  * 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
@@ -6,7 +11,7 @@
  *
  * 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
+ * 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
  * MA 02111-1307 USA
  */
 
-#include <config.h>
 #include <common.h>
 #include <net.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/spi.h>
-
-/*
- * Control Registers in Bank 0
- */
-
-#define CTL_REG_ERDPTL  0x00
-#define CTL_REG_ERDPTH  0x01
-#define CTL_REG_EWRPTL  0x02
-#define CTL_REG_EWRPTH  0x03
-#define CTL_REG_ETXSTL  0x04
-#define CTL_REG_ETXSTH  0x05
-#define CTL_REG_ETXNDL  0x06
-#define CTL_REG_ETXNDH  0x07
-#define CTL_REG_ERXSTL  0x08
-#define CTL_REG_ERXSTH  0x09
-#define CTL_REG_ERXNDL  0x0A
-#define CTL_REG_ERXNDH  0x0B
-#define CTL_REG_ERXRDPTL 0x0C
-#define CTL_REG_ERXRDPTH 0x0D
-#define CTL_REG_ERXWRPTL 0x0E
-#define CTL_REG_ERXWRPTH 0x0F
-#define CTL_REG_EDMASTL  0x10
-#define CTL_REG_EDMASTH  0x11
-#define CTL_REG_EDMANDL  0x12
-#define CTL_REG_EDMANDH  0x13
-#define CTL_REG_EDMADSTL 0x14
-#define CTL_REG_EDMADSTH 0x15
-#define CTL_REG_EDMACSL  0x16
-#define CTL_REG_EDMACSH  0x17
-/* these are common in all banks */
-#define CTL_REG_EIE     0x1B
-#define CTL_REG_EIR     0x1C
-#define CTL_REG_ESTAT   0x1D
-#define CTL_REG_ECON2   0x1E
-#define CTL_REG_ECON1   0x1F
-
-/*
- * Control Registers in Bank 1
- */
-
-#define CTL_REG_EHT0   0x00
-#define CTL_REG_EHT1   0x01
-#define CTL_REG_EHT2   0x02
-#define CTL_REG_EHT3   0x03
-#define CTL_REG_EHT4   0x04
-#define CTL_REG_EHT5   0x05
-#define CTL_REG_EHT6   0x06
-#define CTL_REG_EHT7   0x07
-#define CTL_REG_EPMM0  0x08
-#define CTL_REG_EPMM1  0x09
-#define CTL_REG_EPMM2  0x0A
-#define CTL_REG_EPMM3  0x0B
-#define CTL_REG_EPMM4  0x0C
-#define CTL_REG_EPMM5  0x0D
-#define CTL_REG_EPMM6  0x0E
-#define CTL_REG_EPMM7  0x0F
-#define CTL_REG_EPMCSL 0x10
-#define CTL_REG_EPMCSH 0x11
-#define CTL_REG_EPMOL  0x14
-#define CTL_REG_EPMOH  0x15
-#define CTL_REG_EWOLIE 0x16
-#define CTL_REG_EWOLIR 0x17
-#define CTL_REG_ERXFCON 0x18
-#define CTL_REG_EPKTCNT 0x19
-
-/*
- * Control Registers in Bank 2
- */
-
-#define CTL_REG_MACON1  0x00
-#define CTL_REG_MACON2  0x01
-#define CTL_REG_MACON3  0x02
-#define CTL_REG_MACON4  0x03
-#define CTL_REG_MABBIPG  0x04
-#define CTL_REG_MAIPGL  0x06
-#define CTL_REG_MAIPGH  0x07
-#define CTL_REG_MACLCON1 0x08
-#define CTL_REG_MACLCON2 0x09
-#define CTL_REG_MAMXFLL  0x0A
-#define CTL_REG_MAMXFLH  0x0B
-#define CTL_REG_MAPHSUP  0x0D
-#define CTL_REG_MICON   0x11
-#define CTL_REG_MICMD   0x12
-#define CTL_REG_MIREGADR 0x14
-#define CTL_REG_MIWRL   0x16
-#define CTL_REG_MIWRH   0x17
-#define CTL_REG_MIRDL   0x18
-#define CTL_REG_MIRDH   0x19
-
-/*
- * Control Registers in Bank 3
- */
-
-#define CTL_REG_MAADR1 0x00
-#define CTL_REG_MAADR0 0x01
-#define CTL_REG_MAADR3 0x02
-#define CTL_REG_MAADR2 0x03
-#define CTL_REG_MAADR5 0x04
-#define CTL_REG_MAADR4 0x05
-#define CTL_REG_EBSTSD 0x06
-#define CTL_REG_EBSTCON 0x07
-#define CTL_REG_EBSTCSL 0x08
-#define CTL_REG_EBSTCSH 0x09
-#define CTL_REG_MISTAT 0x0A
-#define CTL_REG_EREVID 0x12
-#define CTL_REG_ECOCON 0x15
-#define CTL_REG_EFLOCON 0x17
-#define CTL_REG_EPAUSL 0x18
-#define CTL_REG_EPAUSH 0x19
-
-
-/*
- * PHY Register
- */
-
-#define PHY_REG_PHID1 0x02
-#define PHY_REG_PHID2 0x03
-/* taken from the Linux driver */
-#define PHY_REG_PHCON1 0x00
-#define PHY_REG_PHCON2 0x10
-#define PHY_REG_PHLCON 0x14
-
-/*
- * Receive Filter Register (ERXFCON) bits
- */
-
-#define ENC_RFR_UCEN  0x80
-#define ENC_RFR_ANDOR 0x40
-#define ENC_RFR_CRCEN 0x20
-#define ENC_RFR_PMEN  0x10
-#define ENC_RFR_MPEN  0x08
-#define ENC_RFR_HTEN  0x04
-#define ENC_RFR_MCEN  0x02
-#define ENC_RFR_BCEN  0x01
+#include <spi.h>
+#include <malloc.h>
+#include <netdev.h>
+#include <miiphy.h>
+#include "enc28j60.h"
 
 /*
- * ECON1 Register Bits
+ * IMPORTANT: spi_claim_bus() and spi_release_bus()
+ * are called at begin and end of each of the following functions:
+ * enc_miiphy_read(), enc_miiphy_write(), enc_write_hwaddr(),
+ * enc_init(), enc_recv(), enc_send(), enc_halt()
+ * ALL other functions assume that the bus has already been claimed!
+ * Since NetReceive() might call enc_send() in return, the bus must be
+ * released, NetReceive() called and claimed again.
  */
 
-#define ENC_ECON1_TXRST  0x80
-#define ENC_ECON1_RXRST  0x40
-#define ENC_ECON1_DMAST  0x20
-#define ENC_ECON1_CSUMEN 0x10
-#define ENC_ECON1_TXRTS  0x08
-#define ENC_ECON1_RXEN  0x04
-#define ENC_ECON1_BSEL1  0x02
-#define ENC_ECON1_BSEL0  0x01
-
 /*
- * ECON2 Register Bits
+ * Controller memory layout.
+ * We only allow 1 frame for transmission and reserve the rest
+ * for reception to handle as many broadcast packets as possible.
+ * Also use the memory from 0x0000 for receiver buffer. See errata pt. 5
+ * 0x0000 - 0x19ff 6656 bytes receive buffer
+ * 0x1a00 - 0x1fff 1536 bytes transmit buffer =
+ * control(1)+frame(1518)+status(7)+reserve(10).
  */
-#define ENC_ECON2_AUTOINC 0x80
-#define ENC_ECON2_PKTDEC  0x40
-#define ENC_ECON2_PWRSV   0x20
-#define ENC_ECON2_VRPS   0x08
+#define ENC_RX_BUF_START       0x0000
+#define ENC_RX_BUF_END         0x19ff
+#define ENC_TX_BUF_START       0x1a00
+#define ENC_TX_BUF_END         0x1fff
+#define ENC_MAX_FRM_LEN                1518
+#define RX_RESET_COUNTER       1000
 
 /*
- * EIR Register Bits
+ * For non data transfer functions, like phy read/write, set hwaddr, init
+ * we do not need a full, time consuming init including link ready wait.
+ * This enum helps to bring the chip through the minimum necessary inits.
  */
-#define ENC_EIR_PKTIF  0x40
-#define ENC_EIR_DMAIF  0x20
-#define ENC_EIR_LINKIF 0x10
-#define ENC_EIR_TXIF   0x08
-#define ENC_EIR_WOLIF  0x04
-#define ENC_EIR_TXERIF 0x02
-#define ENC_EIR_RXERIF 0x01
+enum enc_initstate {none=0, setupdone, linkready};
+typedef struct enc_device {
+       struct eth_device       *dev;   /* back pointer */
+       struct spi_slave        *slave;
+       int                     rx_reset_counter;
+       u16                     next_pointer;
+       u8                      bank;   /* current bank in enc28j60 */
+       enum enc_initstate      initstate;
+} enc_dev_t;
 
 /*
- * ESTAT Register Bits
+ * enc_bset:           set bits in a common register
+ * enc_bclr:           clear bits in a common register
+ *
+ * making the reg parameter u8 will give a compile time warning if the
+ * functions are called with a register not accessible in all Banks
  */
+static void enc_bset(enc_dev_t *enc, const u8 reg, const u8 data)
+{
+       u8 dout[2];
 
-#define ENC_ESTAT_INT    0x80
-#define ENC_ESTAT_LATECOL 0x10
-#define ENC_ESTAT_RXBUSY  0x04
-#define ENC_ESTAT_TXABRT  0x02
-#define ENC_ESTAT_CLKRDY  0x01
+       dout[0] = CMD_BFS(reg);
+       dout[1] = data;
+       spi_xfer(enc->slave, 2 * 8, dout, NULL,
+               SPI_XFER_BEGIN | SPI_XFER_END);
+}
 
-/*
- * EIE Register Bits
- */
+static void enc_bclr(enc_dev_t *enc, const u8 reg, const u8 data)
+{
+       u8 dout[2];
 
-#define ENC_EIE_INTIE  0x80
-#define ENC_EIE_PKTIE  0x40
-#define ENC_EIE_DMAIE  0x20
-#define ENC_EIE_LINKIE 0x10
-#define ENC_EIE_TXIE   0x08
-#define ENC_EIE_WOLIE  0x04
-#define ENC_EIE_TXERIE 0x02
-#define ENC_EIE_RXERIE 0x01
+       dout[0] = CMD_BFC(reg);
+       dout[1] = data;
+       spi_xfer(enc->slave, 2 * 8, dout, NULL,
+               SPI_XFER_BEGIN | SPI_XFER_END);
+}
 
 /*
- * MACON1 Register Bits
+ * high byte of the register contains bank number:
+ * 0: no bank switch necessary
+ * 1: switch to bank 0
+ * 2: switch to bank 1
+ * 3: switch to bank 2
+ * 4: switch to bank 3
  */
-#define ENC_MACON1_LOOPBK  0x10
-#define ENC_MACON1_TXPAUS  0x08
-#define ENC_MACON1_RXPAUS  0x04
-#define ENC_MACON1_PASSALL 0x02
-#define ENC_MACON1_MARXEN  0x01
-
+static void enc_set_bank(enc_dev_t *enc, const u16 reg)
+{
+       u8 newbank = reg >> 8;
+
+       if (newbank == 0 || newbank == enc->bank)
+               return;
+       switch (newbank) {
+       case 1:
+               enc_bclr(enc, CTL_REG_ECON1,
+                       ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1);
+               break;
+       case 2:
+               enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_BSEL0);
+               enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_BSEL1);
+               break;
+       case 3:
+               enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_BSEL0);
+               enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_BSEL1);
+               break;
+       case 4:
+               enc_bset(enc, CTL_REG_ECON1,
+                       ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1);
+               break;
+       }
+       enc->bank = newbank;
+}
 
 /*
- * MACON2 Register Bits
+ * local functions to access SPI
+ *
+ * reg: register inside ENC28J60
+ * data: 8/16 bits to write
+ * c: number of retries
+ *
+ * enc_r8:             read 8 bits
+ * enc_r16:            read 16 bits
+ * enc_w8:             write 8 bits
+ * enc_w16:            write 16 bits
+ * enc_w8_retry:       write 8 bits, verify and retry
+ * enc_rbuf:           read from ENC28J60 into buffer
+ * enc_wbuf:           write from buffer into ENC28J60
  */
-#define ENC_MACON2_MARST   0x80
-#define ENC_MACON2_RNDRST  0x40
-#define ENC_MACON2_MARXRST 0x08
-#define ENC_MACON2_RFUNRST 0x04
-#define ENC_MACON2_MATXRST 0x02
-#define ENC_MACON2_TFUNRST 0x01
 
 /*
- * MACON3 Register Bits
+ * MAC and MII registers need a 3 byte SPI transfer to read,
+ * all other registers need a 2 byte SPI transfer.
  */
-#define ENC_MACON3_PADCFG2 0x80
-#define ENC_MACON3_PADCFG1 0x40
-#define ENC_MACON3_PADCFG0 0x20
-#define ENC_MACON3_TXCRCEN 0x10
-#define ENC_MACON3_PHDRLEN 0x08
-#define ENC_MACON3_HFRMEN  0x04
-#define ENC_MACON3_FRMLNEN 0x02
-#define ENC_MACON3_FULDPX  0x01
+static int enc_reg2nbytes(const u16 reg)
+{
+       /* check if MAC or MII register */
+       return ((reg >= CTL_REG_MACON1 && reg <= CTL_REG_MIRDH) ||
+               (reg >= CTL_REG_MAADR1 && reg <= CTL_REG_MAADR4) ||
+               (reg == CTL_REG_MISTAT)) ? 3 : 2;
+}
 
 /*
- * MICMD Register Bits
+ * Read a byte register
  */
-#define ENC_MICMD_MIISCAN 0x02
-#define ENC_MICMD_MIIRD   0x01
+static u8 enc_r8(enc_dev_t *enc, const u16 reg)
+{
+       u8 dout[3];
+       u8 din[3];
+       int nbytes = enc_reg2nbytes(reg);
+
+       enc_set_bank(enc, reg);
+       dout[0] = CMD_RCR(reg);
+       spi_xfer(enc->slave, nbytes * 8, dout, din,
+               SPI_XFER_BEGIN | SPI_XFER_END);
+       return din[nbytes-1];
+}
 
 /*
- * MISTAT Register Bits
+ * Read a L/H register pair and return a word.
+ * Must be called with the L register's address.
  */
-#define ENC_MISTAT_NVALID 0x04
-#define ENC_MISTAT_SCAN   0x02
-#define ENC_MISTAT_BUSY   0x01
+static u16 enc_r16(enc_dev_t *enc, const u16 reg)
+{
+       u8 dout[3];
+       u8 din[3];
+       u16 result;
+       int nbytes = enc_reg2nbytes(reg);
+
+       enc_set_bank(enc, reg);
+       dout[0] = CMD_RCR(reg);
+       spi_xfer(enc->slave, nbytes * 8, dout, din,
+               SPI_XFER_BEGIN | SPI_XFER_END);
+       result = din[nbytes-1];
+       dout[0]++; /* next register */
+       spi_xfer(enc->slave, nbytes * 8, dout, din,
+               SPI_XFER_BEGIN | SPI_XFER_END);
+       result |= din[nbytes-1] << 8;
+       return result;
+}
 
 /*
- * PHID1 and PHID2 values
+ * Write a byte register
  */
-#define ENC_PHID1_VALUE 0x0083
-#define ENC_PHID2_VALUE 0x1400
-#define ENC_PHID2_MASK 0xFC00
-
-
-#define ENC_SPI_SLAVE_CS 0x00010000    /* pin P1.16 */
-#define ENC_RESET       0x00020000     /* pin P1.17 */
+static void enc_w8(enc_dev_t *enc, const u16 reg, const u8 data)
+{
+       u8 dout[2];
 
-#define FAILSAFE_VALUE 5000
+       enc_set_bank(enc, reg);
+       dout[0] = CMD_WCR(reg);
+       dout[1] = data;
+       spi_xfer(enc->slave, 2 * 8, dout, NULL,
+               SPI_XFER_BEGIN | SPI_XFER_END);
+}
 
 /*
- * Controller memory layout:
- *
- * 0x0000 - 0x17ff  6k bytes receive buffer
- * 0x1800 - 0x1fff  2k bytes transmit buffer
- */
-/* Use the lower memory for receiver buffer. See errata pt. 5 */
-#define ENC_RX_BUF_START 0x0000
-#define ENC_TX_BUF_START 0x1800
-/* taken from the Linux driver */
-#define ENC_RX_BUF_END   0x17ff
-#define ENC_TX_BUF_END   0x1fff
-
-/* maximum frame length */
-#define ENC_MAX_FRM_LEN 1518
-
-#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS)
-#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS)
-#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8);
-
-
-static unsigned char encReadReg (unsigned char regNo);
-static void encWriteReg (unsigned char regNo, unsigned char data);
-static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c);
-static void encReadBuff (unsigned short length, unsigned char *pBuff);
-static void encWriteBuff (unsigned short length, unsigned char *pBuff);
-static void encBitSet (unsigned char regNo, unsigned char data);
-static void encBitClr (unsigned char regNo, unsigned char data);
-static void encReset (void);
-static void encInit (unsigned char *pEthAddr);
-static unsigned short phyRead (unsigned char addr);
-static void phyWrite(unsigned char, unsigned short);
-static void encPoll (void);
-static void encRx (void);
-
-#define m_nic_read(reg) encReadReg(reg)
-#define m_nic_write(reg, data) encWriteReg(reg, data)
-#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count)
-#define m_nic_read_data(len, buf) encReadBuff((len), (buf))
-#define m_nic_write_data(len, buf) encWriteBuff((len), (buf))
-
-/* bit field set */
-#define m_nic_bfs(reg, data) encBitSet(reg, data)
-
-/* bit field clear */
-#define m_nic_bfc(reg, data) encBitClr(reg, data)
-
-static unsigned char bank = 0; /* current bank in enc28j60 */
-static unsigned char next_pointer_lsb;
-static unsigned char next_pointer_msb;
-
-static unsigned char buffer[ENC_MAX_FRM_LEN];
-static int rxResetCounter = 0;
-
-#define RX_RESET_COUNTER 1000;
-
-/*-----------------------------------------------------------------------------
- * Always returns 0
+ * Write a L/H register pair.
+ * Must be called with the L register's address.
  */
-int eth_init (bd_t * bis)
+static void enc_w16(enc_dev_t *enc, const u16 reg, const u16 data)
 {
-       unsigned char estatVal;
-       uchar enetaddr[6];
-
-       /* configure GPIO */
-       (*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS;
-       (*((volatile unsigned long *) IO1DIR)) |= ENC_RESET;
-
-       /* CS and RESET active low */
-       PUT32 (IO1SET, ENC_SPI_SLAVE_CS);
-       PUT32 (IO1SET, ENC_RESET);
-
-       spi_init ();
-
-       /* taken from the Linux driver - dangerous stuff here! */
-       /* Wait for CLKRDY to become set (i.e., check that we can communicate with
-          the ENC) */
-       do
-       {
-               estatVal = m_nic_read(CTL_REG_ESTAT);
-       } while ((estatVal & 0x08) || (~estatVal & ENC_ESTAT_CLKRDY));
-
-       /* initialize controller */
-       encReset ();
-       eth_getenv_enetaddr("ethaddr", enetaddr);
-       encInit (enetaddr);
-
-       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN);      /* enable receive */
-
-       return 0;
+       u8 dout[2];
+
+       enc_set_bank(enc, reg);
+       dout[0] = CMD_WCR(reg);
+       dout[1] = data;
+       spi_xfer(enc->slave, 2 * 8, dout, NULL,
+               SPI_XFER_BEGIN | SPI_XFER_END);
+       dout[0]++; /* next register */
+       dout[1] = data >> 8;
+       spi_xfer(enc->slave, 2 * 8, dout, NULL,
+               SPI_XFER_BEGIN | SPI_XFER_END);
 }
 
-int eth_send (volatile void *packet, int length)
+/*
+ * Write a byte register, verify and retry
+ */
+static void enc_w8_retry(enc_dev_t *enc, const u16 reg, const u8 data, const int c)
 {
-       /* check frame length, etc. */
-       /* TODO: */
-
-       /* switch to bank 0 */
-       m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
-
-       /* set EWRPT */
-       m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff));
-       m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8));
-
-       /* set ETXND */
-       m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF);
-       m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8);
-
-       /* set ETXST */
-       m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF);
-       m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8);
-
-       /* write packet */
-       m_nic_write_data (length, (unsigned char *) packet);
+       u8 dout[2];
+       u8 readback;
+       int i;
 
-       /* taken from the Linux driver */
-       /* Verify that the internal transmit logic has not been altered by excessive
-          collisions.  See Errata B4 12 and 14.
-        */
-       if (m_nic_read(CTL_REG_EIR) & ENC_EIR_TXERIF) {
-               m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_TXRST);
-               m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_TXRST);
+       enc_set_bank(enc, reg);
+       for (i = 0; i < c; i++) {
+               dout[0] = CMD_WCR(reg);
+               dout[1] = data;
+               spi_xfer(enc->slave, 2 * 8, dout, NULL,
+                       SPI_XFER_BEGIN | SPI_XFER_END);
+               readback = enc_r8(enc, reg);
+               if (readback == data)
+                       break;
+               /* wait 1ms */
+               udelay(1000);
+       }
+       if (i == c) {
+               printf("%s: write reg 0x%03x failed\n", enc->dev->name, reg);
        }
-       m_nic_bfc(CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF));
-
-       /* set ECON1.TXRTS */
-       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS);
-
-       return 0;
 }
 
-
-/*****************************************************************************
- * This function resets the receiver only. This function may be called from
- * interrupt-context.
+/*
+ * Read ENC RAM into buffer
  */
-static void encReceiverReset (void)
+static void enc_rbuf(enc_dev_t *enc, const u16 length, u8 *buf)
 {
-       unsigned char econ1;
-
-       econ1 = m_nic_read (CTL_REG_ECON1);
-       if ((econ1 & ENC_ECON1_RXRST) == 0) {
-               m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST);
-               rxResetCounter = RX_RESET_COUNTER;
-       }
+       u8 dout[1];
+
+       dout[0] = CMD_RBM;
+       spi_xfer(enc->slave, 8, dout, NULL, SPI_XFER_BEGIN);
+       spi_xfer(enc->slave, length * 8, NULL, buf, SPI_XFER_END);
+#ifdef DEBUG
+       puts("Rx:\n");
+       print_buffer(0, buf, 1, length, 0);
+#endif
 }
 
-/*****************************************************************************
- * receiver reset timer
+/*
+ * Write buffer into ENC RAM
  */
-static void encReceiverResetCallback (void)
+static void enc_wbuf(enc_dev_t *enc, const u16 length, const u8 *buf, const u8 control)
 {
-       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST);
-       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN);      /* enable receive */
+       u8 dout[2];
+       dout[0] = CMD_WBM;
+       dout[1] = control;
+       spi_xfer(enc->slave, 2 * 8, dout, NULL, SPI_XFER_BEGIN);
+       spi_xfer(enc->slave, length * 8, buf, NULL, SPI_XFER_END);
+#ifdef DEBUG
+       puts("Tx:\n");
+       print_buffer(0, buf, 1, length, 0);
+#endif
 }
 
-/*-----------------------------------------------------------------------------
- * Check for received packets. Call NetReceive for each packet. The return
- * value is ignored by the caller.
+/*
+ * Try to claim the SPI bus.
+ * Print error message on failure.
  */
-int eth_rx (void)
+static int enc_claim_bus(enc_dev_t *enc)
 {
-       if (rxResetCounter > 0 && --rxResetCounter == 0) {
-               encReceiverResetCallback ();
-       }
-
-       encPoll ();
-
-       return 0;
+       int rc = spi_claim_bus(enc->slave);
+       if (rc)
+               printf("%s: failed to claim SPI bus\n", enc->dev->name);
+       return rc;
 }
 
-void eth_halt (void)
+/*
+ * Release previously claimed SPI bus.
+ * This function is mainly for symmetry to enc_claim_bus().
+ * Let the toolchain decide to inline it...
+ */
+static void enc_release_bus(enc_dev_t *enc)
 {
-       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN);      /* disable receive */
+       spi_release_bus(enc->slave);
 }
 
-/*****************************************************************************/
-
-static void encPoll (void)
+/*
+ * Read PHY register
+ */
+static u16 phy_read(enc_dev_t *enc, const u8 addr)
 {
-       unsigned char eir_reg;
-       volatile unsigned char estat_reg;
-       unsigned char pkt_cnt;
+       uint64_t etime;
+       u8 status;
 
-#ifdef CONFIG_USE_IRQ
-       /* clear global interrupt enable bit in enc28j60 */
-       m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE);
-#endif
-       estat_reg = m_nic_read (CTL_REG_ESTAT);
-
-       eir_reg = m_nic_read (CTL_REG_EIR);
-
-       if (eir_reg & ENC_EIR_TXIF) {
-               /* clear TXIF bit in EIR */
-               m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF);
+       enc_w8(enc, CTL_REG_MIREGADR, addr);
+       enc_w8(enc, CTL_REG_MICMD, ENC_MICMD_MIIRD);
+       /* 1 second timeout - only happens on hardware problem */
+       etime = get_ticks() + get_tbclk();
+       /* poll MISTAT.BUSY bit until operation is complete */
+       do
+       {
+               status = enc_r8(enc, CTL_REG_MISTAT);
+       } while (get_ticks() <= etime && (status & ENC_MISTAT_BUSY));
+       if (status & ENC_MISTAT_BUSY) {
+               printf("%s: timeout reading phy\n", enc->dev->name);
+               return 0;
        }
+       enc_w8(enc, CTL_REG_MICMD, 0);
+       return enc_r16(enc, CTL_REG_MIRDL);
+}
 
-       /* We have to use pktcnt and not pktif bit, see errata pt. 6 */
+/*
+ * Write PHY register
+ */
+static void phy_write(enc_dev_t *enc, const u8 addr, const u16 data)
+{
+       uint64_t etime;
+       u8 status;
 
-       /* move to bank 1 */
-       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
-       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+       enc_w8(enc, CTL_REG_MIREGADR, addr);
+       enc_w16(enc, CTL_REG_MIWRL, data);
+       /* 1 second timeout - only happens on hardware problem */
+       etime = get_ticks() + get_tbclk();
+       /* poll MISTAT.BUSY bit until operation is complete */
+       do
+       {
+               status = enc_r8(enc, CTL_REG_MISTAT);
+       } while (get_ticks() <= etime && (status & ENC_MISTAT_BUSY));
+       if (status & ENC_MISTAT_BUSY) {
+               printf("%s: timeout writing phy\n", enc->dev->name);
+               return;
+       }
+}
 
-       /* read pktcnt */
-       pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
+/*
+ * Verify link status, wait if necessary
+ *
+ * Note: with a 10 MBit/s only PHY there is no autonegotiation possible,
+ * half/full duplex is a pure setup matter. For the time being, this driver
+ * will setup in half duplex mode only.
+ */
+static int enc_phy_link_wait(enc_dev_t *enc)
+{
+       u16 status;
+       int duplex;
+       uint64_t etime;
+
+#ifdef CONFIG_ENC_SILENTLINK
+       /* check if we have a link, then just return */
+       status = phy_read(enc, PHY_REG_PHSTAT1);
+       if (status & ENC_PHSTAT1_LLSTAT)
+               return 0;
+#endif
 
-       if (pkt_cnt > 0) {
-               if ((eir_reg & ENC_EIR_PKTIF) == 0) {
-                       /*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */
+       /* wait for link with 1 second timeout */
+       etime = get_ticks() + get_tbclk();
+       while (get_ticks() <= etime) {
+               status = phy_read(enc, PHY_REG_PHSTAT1);
+               if (status & ENC_PHSTAT1_LLSTAT) {
+                       /* now we have a link */
+                       status = phy_read(enc, PHY_REG_PHSTAT2);
+                       duplex = (status & ENC_PHSTAT2_DPXSTAT) ? 1 : 0;
+                       printf("%s: link up, 10Mbps %s-duplex\n",
+                               enc->dev->name, duplex ? "full" : "half");
+                       return 0;
                }
-               encRx ();
-               /* clear PKTIF bit in EIR, this should not need to be done but it
-                  seems like we get problems if we do not */
-               m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF);
+               udelay(1000);
        }
 
-       if (eir_reg & ENC_EIR_RXERIF) {
-               printf ("encPoll: rx error\n");
-               m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF);
-       }
-       if (eir_reg & ENC_EIR_TXERIF) {
-               printf ("encPoll: tx error\n");
-               m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF);
-       }
-
-#ifdef CONFIG_USE_IRQ
-       /* set global interrupt enable bit in enc28j60 */
-       m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
-#endif
+       /* timeout occured */
+       printf("%s: link down\n", enc->dev->name);
+       return 1;
 }
 
-static void encRx (void)
+/*
+ * This function resets the receiver only.
+ */
+static void enc_reset_rx(enc_dev_t *enc)
 {
-       unsigned short pkt_len;
-       unsigned short copy_len;
-       unsigned short status;
-       unsigned char eir_reg;
-       unsigned char pkt_cnt = 0;
-       unsigned short rxbuf_rdpt;
+       u8 econ1;
 
-       /* switch to bank 0 */
-       m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+       econ1 = enc_r8(enc, CTL_REG_ECON1);
+       if ((econ1 & ENC_ECON1_RXRST) == 0) {
+               enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXRST);
+               enc->rx_reset_counter = RX_RESET_COUNTER;
+       }
+}
 
-       m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
-       m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
+/*
+ * Reset receiver and reenable it.
+ */
+static void enc_reset_rx_call(enc_dev_t *enc)
+{
+       enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_RXRST);
+       enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXEN);
+}
 
+/*
+ * Copy a packet from the receive ring and forward it to
+ * the protocol stack.
+ */
+static void enc_receive(enc_dev_t *enc)
+{
+       u8 *packet = (u8 *)NetRxPackets[0];
+       u16 pkt_len;
+       u16 copy_len;
+       u16 status;
+       u8 eir_reg;
+       u8 pkt_cnt = 0;
+       u16 rxbuf_rdpt;
+       u8 hbuf[6];
+
+       enc_w16(enc, CTL_REG_ERDPTL, enc->next_pointer);
        do {
-               m_nic_read_data (6, buffer);
-               next_pointer_lsb = buffer[0];
-               next_pointer_msb = buffer[1];
-               pkt_len = buffer[2];
-               pkt_len |= (unsigned short) buffer[3] << 8;
-               status = buffer[4];
-               status |= (unsigned short) buffer[5] << 8;
-
+               enc_rbuf(enc, 6, hbuf);
+               enc->next_pointer = hbuf[0] | (hbuf[1] << 8);
+               pkt_len = hbuf[2] | (hbuf[3] << 8);
+               status = hbuf[4] | (hbuf[5] << 8);
+               debug("next_pointer=$%04x pkt_len=%u status=$%04x\n",
+                       enc->next_pointer, pkt_len, status);
                if (pkt_len <= ENC_MAX_FRM_LEN)
                        copy_len = pkt_len;
                else
                        copy_len = 0;
-
                if ((status & (1L << 7)) == 0) /* check Received Ok bit */
                        copy_len = 0;
-
-               /* taken from the Linux driver */
                /* check if next pointer is resonable */
-               if ((((unsigned int)next_pointer_msb << 8) |
-                       (unsigned int)next_pointer_lsb) >= ENC_TX_BUF_START)
+               if (enc->next_pointer >= ENC_TX_BUF_START)
                        copy_len = 0;
-
                if (copy_len > 0) {
-                       m_nic_read_data (copy_len, buffer);
+                       enc_rbuf(enc, copy_len, packet);
                }
-
                /* advance read pointer to next pointer */
-               m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
-               m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
-
+               enc_w16(enc, CTL_REG_ERDPTL, enc->next_pointer);
                /* decrease packet counter */
-               m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC);
-
-               /* taken from the Linux driver */
-               /* Only odd values should be written to ERXRDPTL,
+               enc_bset(enc, CTL_REG_ECON2, ENC_ECON2_PKTDEC);
+               /*
+                * Only odd values should be written to ERXRDPTL,
                 * see errata B4 pt.13
                 */
-               rxbuf_rdpt = (next_pointer_msb << 8 | next_pointer_lsb) - 1;
-               if ((rxbuf_rdpt < (m_nic_read(CTL_REG_ERXSTH) << 8 |
-                               m_nic_read(CTL_REG_ERXSTL))) || (rxbuf_rdpt >
-                               (m_nic_read(CTL_REG_ERXNDH) << 8 |
-                               m_nic_read(CTL_REG_ERXNDL)))) {
-                       m_nic_write(CTL_REG_ERXRDPTL, m_nic_read(CTL_REG_ERXNDL));
-                       m_nic_write(CTL_REG_ERXRDPTH, m_nic_read(CTL_REG_ERXNDH));
+               rxbuf_rdpt = enc->next_pointer - 1;
+               if ((rxbuf_rdpt < enc_r16(enc, CTL_REG_ERXSTL)) ||
+                       (rxbuf_rdpt > enc_r16(enc, CTL_REG_ERXNDL))) {
+                       enc_w16(enc, CTL_REG_ERXRDPTL,
+                               enc_r16(enc, CTL_REG_ERXNDL));
                } else {
-                       m_nic_write(CTL_REG_ERXRDPTL, rxbuf_rdpt & 0xFF);
-                       m_nic_write(CTL_REG_ERXRDPTH, rxbuf_rdpt >> 8);
+                       enc_w16(enc, CTL_REG_ERXRDPTL, rxbuf_rdpt);
                }
-
-               /* move to bank 1 */
-               m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
-               m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
-
                /* read pktcnt */
-               pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
-
-               /* switch to bank 0 */
-               m_nic_bfc (CTL_REG_ECON1,
-                          (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
-
+               pkt_cnt = enc_r8(enc, CTL_REG_EPKTCNT);
                if (copy_len == 0) {
-                       eir_reg = m_nic_read (CTL_REG_EIR);
-                       encReceiverReset ();
-                       printf ("eth_rx: copy_len=0\n");
+                       eir_reg = enc_r8(enc, CTL_REG_EIR);
+                       enc_reset_rx(enc);
+                       printf("%s: receive copy_len=0\n", enc->dev->name);
                        continue;
                }
-
-               NetReceive ((unsigned char *) buffer, pkt_len);
-
-               eir_reg = m_nic_read (CTL_REG_EIR);
-       } while (pkt_cnt);      /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
-}
-
-static void encWriteReg (unsigned char regNo, unsigned char data)
-{
-       spi_lock ();
-       enc_cfg_spi ();
-       enc_enable ();
-
-       spi_write (0x40 | regNo);       /* write in regNo */
-       spi_write (data);
-
-       enc_disable ();
-       enc_enable ();
-
-       spi_write (0x1f);       /* write reg 0x1f */
-
-       enc_disable ();
-       spi_unlock ();
+               /*
+                * Because NetReceive() might call enc_send(), we need to
+                * release the SPI bus, call NetReceive(), reclaim the bus
+                */
+               enc_release_bus(enc);
+               NetReceive(packet, pkt_len);
+               if (enc_claim_bus(enc))
+                       return;
+               eir_reg = enc_r8(enc, CTL_REG_EIR);
+       } while (pkt_cnt);
+       /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
 }
 
-static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c)
+/*
+ * Poll for completely received packets.
+ */
+static void enc_poll(enc_dev_t *enc)
 {
-       unsigned char readback;
-       int i;
-
-       spi_lock ();
+       u8 eir_reg;
+       u8 estat_reg;
+       u8 pkt_cnt;
 
-       for (i = 0; i < c; i++) {
-               enc_cfg_spi ();
-               enc_enable ();
-
-               spi_write (0x40 | regNo);       /* write in regNo */
-               spi_write (data);
-
-               enc_disable ();
-               enc_enable ();
-
-               spi_write (0x1f);       /* write reg 0x1f */
-
-               enc_disable ();
-
-               spi_unlock ();  /* we must unlock spi first */
-
-               readback = encReadReg (regNo);
-
-               spi_lock ();
-
-               if (readback == data)
-                       break;
+#ifdef CONFIG_USE_IRQ
+       /* clear global interrupt enable bit in enc28j60 */
+       enc_bclr(enc, CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+       estat_reg = enc_r8(enc, CTL_REG_ESTAT);
+       eir_reg = enc_r8(enc, CTL_REG_EIR);
+       if (eir_reg & ENC_EIR_TXIF) {
+               /* clear TXIF bit in EIR */
+               enc_bclr(enc, CTL_REG_EIR, ENC_EIR_TXIF);
        }
-       spi_unlock ();
-
-       if (i == c) {
-               printf ("enc28j60: write reg %d failed\n", regNo);
+       /* We have to use pktcnt and not pktif bit, see errata pt. 6 */
+       pkt_cnt = enc_r8(enc, CTL_REG_EPKTCNT);
+       if (pkt_cnt > 0) {
+               if ((eir_reg & ENC_EIR_PKTIF) == 0) {
+                       debug("enc_poll: pkt cnt > 0, but pktif not set\n");
+               }
+               enc_receive(enc);
+               /*
+                * clear PKTIF bit in EIR, this should not need to be done
+                * but it seems like we get problems if we do not
+                */
+               enc_bclr(enc, CTL_REG_EIR, ENC_EIR_PKTIF);
        }
-}
-
-static unsigned char encReadReg (unsigned char regNo)
-{
-       unsigned char rxByte;
-
-       spi_lock ();
-       enc_cfg_spi ();
-       enc_enable ();
-
-       spi_write (0x1f);       /* read reg 0x1f */
-
-       bank = spi_read () & 0x3;
-
-       enc_disable ();
-       enc_enable ();
-
-       spi_write (regNo);
-       rxByte = spi_read ();
-
-       /* check if MAC or MII register */
-       if (((bank == 2) && (regNo <= 0x1a)) ||
-           ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) {
-               /* ignore first byte and read another byte */
-               rxByte = spi_read ();
+       if (eir_reg & ENC_EIR_RXERIF) {
+               printf("%s: rx error\n", enc->dev->name);
+               enc_bclr(enc, CTL_REG_EIR, ENC_EIR_RXERIF);
        }
-
-       enc_disable ();
-       spi_unlock ();
-
-       return rxByte;
-}
-
-static void encReadBuff (unsigned short length, unsigned char *pBuff)
-{
-       spi_lock ();
-       enc_cfg_spi ();
-       enc_enable ();
-
-       spi_write (0x20 | 0x1a);        /* read buffer memory */
-
-       while (length--) {
-               if (pBuff != NULL)
-                       *pBuff++ = spi_read ();
-               else
-                       spi_write (0);
+       if (eir_reg & ENC_EIR_TXERIF) {
+               printf("%s: tx error\n", enc->dev->name);
+               enc_bclr(enc, CTL_REG_EIR, ENC_EIR_TXERIF);
        }
-
-       enc_disable ();
-       spi_unlock ();
-}
-
-static void encWriteBuff (unsigned short length, unsigned char *pBuff)
-{
-       spi_lock ();
-       enc_cfg_spi ();
-       enc_enable ();
-
-       spi_write (0x60 | 0x1a);        /* write buffer memory */
-
-       spi_write (0x00);       /* control byte */
-
-       while (length--)
-               spi_write (*pBuff++);
-
-       enc_disable ();
-       spi_unlock ();
-}
-
-static void encBitSet (unsigned char regNo, unsigned char data)
-{
-       spi_lock ();
-       enc_cfg_spi ();
-       enc_enable ();
-
-       spi_write (0x80 | regNo);       /* bit field set */
-       spi_write (data);
-
-       enc_disable ();
-       spi_unlock ();
-}
-
-static void encBitClr (unsigned char regNo, unsigned char data)
-{
-       spi_lock ();
-       enc_cfg_spi ();
-       enc_enable ();
-
-       spi_write (0xA0 | regNo);       /* bit field clear */
-       spi_write (data);
-
-       enc_disable ();
-       spi_unlock ();
+#ifdef CONFIG_USE_IRQ
+       /* set global interrupt enable bit in enc28j60 */
+       enc_bset(enc, CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
 }
 
-static void encReset (void)
+/*
+ * Completely Reset the ENC
+ */
+static void enc_reset(enc_dev_t *enc)
 {
-       spi_lock ();
-       enc_cfg_spi ();
-       enc_enable ();
-
-       spi_write (0xff);       /* soft reset */
-
-       enc_disable ();
-       spi_unlock ();
+       u8 dout[1];
 
+       dout[0] = CMD_SRC;
+       spi_xfer(enc->slave, 8, dout, NULL,
+               SPI_XFER_BEGIN | SPI_XFER_END);
        /* sleep 1 ms. See errata pt. 2 */
-       udelay (1000);
+       udelay(1000);
 }
 
-static void encInit (unsigned char *pEthAddr)
-{
-       unsigned short phid1 = 0;
-       unsigned short phid2 = 0;
-
-       /* switch to bank 0 */
-       m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
-
+/*
+ * Initialisation data for most of the ENC registers
+ */
+static const u16 enc_initdata[] = {
        /*
         * Setup the buffer space. The reset values are valid for the
         * other pointers.
+        *
+        * We shall not write to ERXST, see errata pt. 5. Instead we
+        * have to make sure that ENC_RX_BUS_START is 0.
         */
-       /* We shall not write to ERXST, see errata pt. 5. Instead we
-          have to make sure that ENC_RX_BUS_START is 0. */
-       m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1);
-       m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1);
-
-       /* taken from the Linux driver */
-       m_nic_write_retry (CTL_REG_ERXNDL, (ENC_RX_BUF_END & 0xFF), 1);
-       m_nic_write_retry (CTL_REG_ERXNDH, (ENC_RX_BUF_END >> 8), 1);
-
-       m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1);
-       m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1);
-
-       next_pointer_lsb = (ENC_RX_BUF_START & 0xFF);
-       next_pointer_msb = (ENC_RX_BUF_START >> 8);
-
-       /* verify identification */
-       phid1 = phyRead (PHY_REG_PHID1);
-       phid2 = phyRead (PHY_REG_PHID2);
-
-       if (phid1 != ENC_PHID1_VALUE
-           || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) {
-               printf ("ERROR: failed to identify controller\n");
-               printf ("phid1 = %x, phid2 = %x\n",
-                       phid1, (phid2 & ENC_PHID2_MASK));
-               printf ("should be phid1 = %x, phid2 = %x\n",
-                       ENC_PHID1_VALUE, ENC_PHID2_VALUE);
-       }
-
+       CTL_REG_ERXSTL, ENC_RX_BUF_START,
+       CTL_REG_ERXSTH, ENC_RX_BUF_START >> 8,
+       CTL_REG_ERXNDL, ENC_RX_BUF_END,
+       CTL_REG_ERXNDH, ENC_RX_BUF_END >> 8,
+       CTL_REG_ERDPTL, ENC_RX_BUF_START,
+       CTL_REG_ERDPTH, ENC_RX_BUF_START >> 8,
        /*
-        * --- MAC Initialization ---
+        * Set the filter to receive only good-CRC, unicast and broadcast
+        * frames.
+        * Note: some DHCP servers return their answers as broadcasts!
+        * So its unwise to remove broadcast from this. This driver
+        * might incur receiver overruns with packet loss on a broadcast
+        * flooded network.
         */
-
-       /* Pull MAC out of Reset */
-
-       /* switch to bank 2 */
-       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
-       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+       CTL_REG_ERXFCON, ENC_RFR_BCEN | ENC_RFR_UCEN | ENC_RFR_CRCEN,
 
        /* enable MAC to receive frames */
-       /* added some bits from the Linux driver */
-       m_nic_write_retry (CTL_REG_MACON1
-               ,(ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS)
-               ,10);
+       CTL_REG_MACON1,
+               ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS,
 
        /* configure pad, tx-crc and duplex */
-       /* added a bit from the Linux driver */
-       m_nic_write_retry (CTL_REG_MACON3
-               ,(ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN | ENC_MACON3_FRMLNEN)
-               ,10);
+       CTL_REG_MACON3,
+               ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN |
+               ENC_MACON3_FRMLNEN,
 
-       /* added 4 new lines from the Linux driver */
        /* Allow infinite deferals if the medium is continously busy */
-       m_nic_write_retry(CTL_REG_MACON4, (1<<6) /*ENC_MACON4_DEFER*/, 10);
+       CTL_REG_MACON4, ENC_MACON4_DEFER,
 
        /* Late collisions occur beyond 63 bytes */
-       m_nic_write_retry(CTL_REG_MACLCON2, 63, 10);
+       CTL_REG_MACLCON2, 63,
 
-       /* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */
-       m_nic_write_retry(CTL_REG_MAIPGL, 0x12, 10);
+       /*
+        * Set (low byte) Non-Back-to_Back Inter-Packet Gap.
+        * Recommended 0x12
+        */
+       CTL_REG_MAIPGL, 0x12,
 
        /*
-       * Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended
-       * 0x0c for half-duplex. Nothing for full-duplex
-       */
-       m_nic_write_retry(CTL_REG_MAIPGH, 0x0C, 10);
+        * Set (high byte) Non-Back-to_Back Inter-Packet Gap.
+        * Recommended 0x0c for half-duplex. Nothing for full-duplex
+        */
+       CTL_REG_MAIPGH, 0x0C,
 
        /* set maximum frame length */
-       m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10);
-       m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10);
+       CTL_REG_MAMXFLL, ENC_MAX_FRM_LEN,
+       CTL_REG_MAMXFLH, ENC_MAX_FRM_LEN >> 8,
 
        /*
-        * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex
+        * Set MAC back-to-back inter-packet gap.
+        * Recommended 0x12 for half duplex
         * and 0x15 for full duplex.
         */
-       m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10);
+       CTL_REG_MABBIPG, 0x12,
 
-       /* set MAC address */
+       /* end of table */
+       0xffff
+};
 
-       /* switch to bank 3 */
-       m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1));
+/*
+ * Wait for the XTAL oscillator to become ready
+ */
+static int enc_clock_wait(enc_dev_t *enc)
+{
+       uint64_t etime;
 
-       m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1);
-       m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1);
-       m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1);
-       m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1);
-       m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1);
-       m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1);
+       /* one second timeout */
+       etime = get_ticks() + get_tbclk();
 
        /*
-       * PHY Initialization taken from the Linux driver
+        * Wait for CLKRDY to become set (i.e., check that we can
+        * communicate with the ENC)
         */
+       do
+       {
+               if (enc_r8(enc, CTL_REG_ESTAT) & ENC_ESTAT_CLKRDY)
+                       return 0;
+       } while (get_ticks() <= etime);
+
+       printf("%s: timeout waiting for CLKRDY\n", enc->dev->name);
+       return -1;
+}
+
+/*
+ * Write the MAC address into the ENC
+ */
+static int enc_write_macaddr(enc_dev_t *enc)
+{
+       unsigned char *p = enc->dev->enetaddr;
+
+       enc_w8_retry(enc, CTL_REG_MAADR5, *p++, 5);
+       enc_w8_retry(enc, CTL_REG_MAADR4, *p++, 5);
+       enc_w8_retry(enc, CTL_REG_MAADR3, *p++, 5);
+       enc_w8_retry(enc, CTL_REG_MAADR2, *p++, 5);
+       enc_w8_retry(enc, CTL_REG_MAADR1, *p++, 5);
+       enc_w8_retry(enc, CTL_REG_MAADR0, *p, 5);
+       return 0;
+}
+
+/*
+ * Setup most of the ENC registers
+ */
+static int enc_setup(enc_dev_t *enc)
+{
+       u16 phid1 = 0;
+       u16 phid2 = 0;
+       const u16 *tp;
+
+       /* reset enc struct values */
+       enc->next_pointer = ENC_RX_BUF_START;
+       enc->rx_reset_counter = RX_RESET_COUNTER;
+       enc->bank = 0xff;       /* invalidate current bank in enc28j60 */
+
+       /* verify PHY identification */
+       phid1 = phy_read(enc, PHY_REG_PHID1);
+       phid2 = phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK;
+       if (phid1 != ENC_PHID1_VALUE || phid2 != ENC_PHID2_VALUE) {
+               printf("%s: failed to identify PHY. Found %04x:%04x\n",
+                       enc->dev->name, phid1, phid2);
+               return -1;
+       }
 
-       /* Prevent automatic loopback of data beeing transmitted by setting
-          ENC_PHCON2_HDLDIS */
-       phyWrite(PHY_REG_PHCON2, (1<<8));
+       /* now program registers */
+       for (tp = enc_initdata; *tp != 0xffff; tp += 2)
+               enc_w8_retry(enc, tp[0], tp[1], 10);
+
+       /*
+        * Prevent automatic loopback of data beeing transmitted by setting
+        * ENC_PHCON2_HDLDIS
+        */
+       phy_write(enc, PHY_REG_PHCON2, (1<<8));
 
-       /* LEDs configuration
+       /*
+        * LEDs configuration
         * LEDA: LACFG = 0100 -> display link status
         * LEDB: LBCFG = 0111 -> display TX & RX activity
         * STRCH = 1 -> LED pulses
         */
-       phyWrite(PHY_REG_PHLCON, 0x0472);
+       phy_write(enc, PHY_REG_PHLCON, 0x0472);
 
        /* Reset PDPXMD-bit => half duplex */
-       phyWrite(PHY_REG_PHCON1, 0);
-
-       /*
-        * Receive settings
-        */
+       phy_write(enc, PHY_REG_PHCON1, 0);
 
 #ifdef CONFIG_USE_IRQ
        /* enable interrupts */
-       m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE);
-       m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE);
-       m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE);
-       m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE);
-       m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
+       enc_bset(enc, CTL_REG_EIE, ENC_EIE_PKTIE);
+       enc_bset(enc, CTL_REG_EIE, ENC_EIE_TXIE);
+       enc_bset(enc, CTL_REG_EIE, ENC_EIE_RXERIE);
+       enc_bset(enc, CTL_REG_EIE, ENC_EIE_TXERIE);
+       enc_bset(enc, CTL_REG_EIE, ENC_EIE_INTIE);
 #endif
+
+       return 0;
 }
 
-/*****************************************************************************
- *
- * Description:
- *    Read PHY registers.
- *
- *    NOTE! This function will change to Bank 2.
- *
- * Params:
- *    [in] addr address of the register to read
- *
- * Returns:
- *    The value in the register
+/*
+ * Check if ENC has been initialized.
+ * If not, try to initialize it.
+ * Remember initialized state in struct.
  */
-static unsigned short phyRead (unsigned char addr)
+static int enc_initcheck(enc_dev_t *enc, const enum enc_initstate requiredstate)
 {
-       unsigned short ret = 0;
-
-       /* move to bank 2 */
-       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
-       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+       if (enc->initstate >= requiredstate)
+               return 0;
+
+       if (enc->initstate < setupdone) {
+               /* Initialize the ENC only */
+               enc_reset(enc);
+               /* if any of functions fails, skip the rest and return an error */
+               if (enc_clock_wait(enc) || enc_setup(enc) || enc_write_macaddr(enc)) {
+                       return -1;
+               }
+               enc->initstate = setupdone;
+       }
+       /* if that's all we need, return here */
+       if (enc->initstate >= requiredstate)
+               return 0;
 
-       /* write address to MIREGADR */
-       m_nic_write (CTL_REG_MIREGADR, addr);
+       /* now wait for link ready condition */
+       if (enc_phy_link_wait(enc)) {
+               return -1;
+       }
+       enc->initstate = linkready;
+       return 0;
+}
 
-       /* set MICMD.MIIRD */
-       m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD);
+#if defined(CONFIG_CMD_MII)
+/*
+ * Read a PHY register.
+ *
+ * This function is registered with miiphy_register().
+ */
+int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
+{
+       struct eth_device *dev = eth_get_dev_by_name(devname);
+       enc_dev_t *enc;
+
+       if (!dev || phy_adr != 0)
+               return -1;
+
+       enc = dev->priv;
+       if (enc_claim_bus(enc))
+               return -1;
+       if (enc_initcheck(enc, setupdone)) {
+               enc_release_bus(enc);
+               return -1;
+       }
+       *value = phy_read(enc, reg);
+       enc_release_bus(enc);
+       return 0;
+}
 
-       /* taken from the Linux driver */
-       /* move to bank 3 */
-       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
-       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+/*
+ * Write a PHY register.
+ *
+ * This function is registered with miiphy_register().
+ */
+int enc_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
+{
+       struct eth_device *dev = eth_get_dev_by_name(devname);
+       enc_dev_t *enc;
+
+       if (!dev || phy_adr != 0)
+               return -1;
+
+       enc = dev->priv;
+       if (enc_claim_bus(enc))
+               return -1;
+       if (enc_initcheck(enc, setupdone)) {
+               enc_release_bus(enc);
+               return -1;
+       }
+       phy_write(enc, reg, value);
+       enc_release_bus(enc);
+       return 0;
+}
+#endif
 
-       /* poll MISTAT.BUSY bit until operation is complete */
-       while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
-               static int cnt = 0;
+/*
+ * Write hardware (MAC) address.
+ *
+ * This function entered into eth_device structure.
+ */
+static int enc_write_hwaddr(struct eth_device *dev)
+{
+       enc_dev_t *enc = dev->priv;
 
-               if (cnt++ >= 1000) {
-                       /* GJ - this seems extremely dangerous! */
-                       /* printf("#"); */
-                       cnt = 0;
-               }
+       if (enc_claim_bus(enc))
+               return -1;
+       if (enc_initcheck(enc, setupdone)) {
+               enc_release_bus(enc);
+               return -1;
        }
+       enc_release_bus(enc);
+       return 0;
+}
 
-       /* taken from the Linux driver */
-       /* move to bank 2 */
-       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
-       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+/*
+ * Initialize ENC28J60 for use.
+ *
+ * This function entered into eth_device structure.
+ */
+static int enc_init(struct eth_device *dev, bd_t *bis)
+{
+       enc_dev_t *enc = dev->priv;
 
-       /* clear MICMD.MIIRD */
-       m_nic_write (CTL_REG_MICMD, 0);
+       if (enc_claim_bus(enc))
+               return -1;
+       if (enc_initcheck(enc, linkready)) {
+               enc_release_bus(enc);
+               return -1;
+       }
+       /* enable receive */
+       enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXEN);
+       enc_release_bus(enc);
+       return 0;
+}
 
-       ret = (m_nic_read (CTL_REG_MIRDH) << 8);
-       ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF);
+/*
+ * Check for received packets.
+ *
+ * This function entered into eth_device structure.
+ */
+static int enc_recv(struct eth_device *dev)
+{
+       enc_dev_t *enc = dev->priv;
 
-       return ret;
+       if (enc_claim_bus(enc))
+               return -1;
+       if (enc_initcheck(enc, linkready)) {
+               enc_release_bus(enc);
+               return -1;
+       }
+       /* Check for dead receiver */
+       if (enc->rx_reset_counter > 0)
+               enc->rx_reset_counter--;
+       else
+               enc_reset_rx_call(enc);
+       enc_poll(enc);
+       enc_release_bus(enc);
+       return 0;
 }
 
-/*****************************************************************************
- *
- * Taken from the Linux driver.
- * Description:
- * Write PHY registers.
- *
- * NOTE! This function will change to Bank 3.
+/*
+ * Send a packet.
  *
- * Params:
- * [in] addr address of the register to write to
- * [in] data to be written
+ * This function entered into eth_device structure.
  *
- * Returns:
- *    None
+ * Should we wait here until we have a Link? Or shall we leave that to
+ * protocol retries?
  */
-static void phyWrite(unsigned char addr, unsigned short data)
+static int enc_send(
+       struct eth_device *dev,
+       volatile void *packet,
+       int length)
 {
-       /* move to bank 2 */
-       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
-       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+       enc_dev_t *enc = dev->priv;
+
+       if (enc_claim_bus(enc))
+               return -1;
+       if (enc_initcheck(enc, linkready)) {
+               enc_release_bus(enc);
+               return -1;
+       }
+       /* setup transmit pointers */
+       enc_w16(enc, CTL_REG_EWRPTL, ENC_TX_BUF_START);
+       enc_w16(enc, CTL_REG_ETXNDL, length + ENC_TX_BUF_START);
+       enc_w16(enc, CTL_REG_ETXSTL, ENC_TX_BUF_START);
+       /* write packet to ENC */
+       enc_wbuf(enc, length, (u8 *) packet, 0x00);
+       /*
+        * Check that the internal transmit logic has not been altered
+        * by excessive collisions. Reset transmitter if so.
+        * See Errata B4 12 and 14.
+        */
+       if (enc_r8(enc, CTL_REG_EIR) & ENC_EIR_TXERIF) {
+               enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_TXRST);
+               enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_TXRST);
+       }
+       enc_bclr(enc, CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF));
+       /* start transmitting */
+       enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_TXRTS);
+       enc_release_bus(enc);
+       return 0;
+}
 
-       /* write address to MIREGADR */
-       m_nic_write(CTL_REG_MIREGADR, addr);
+/*
+ * Finish use of ENC.
+ *
+ * This function entered into eth_device structure.
+ */
+static void enc_halt(struct eth_device *dev)
+{
+       enc_dev_t *enc = dev->priv;
 
-       m_nic_write(CTL_REG_MIWRL, data & 0xff);
-       m_nic_write(CTL_REG_MIWRH, data >> 8);
+       if (enc_claim_bus(enc))
+               return;
+       /* Just disable receiver */
+       enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_RXEN);
+       enc_release_bus(enc);
+}
 
-       /* move to bank 3 */
-       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
-       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+/*
+ * This is the only exported function.
+ *
+ * It may be called several times with different bus:cs combinations.
+ */
+int enc28j60_initialize(unsigned int bus, unsigned int cs,
+       unsigned int max_hz, unsigned int mode)
+{
+       struct eth_device *dev;
+       enc_dev_t *enc;
 
-       /* poll MISTAT.BUSY bit until operation is complete */
-       while((m_nic_read(CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
-               static int cnt = 0;
+       /* try to allocate, check and clear eth_device object */
+       dev = malloc(sizeof(*dev));
+       if (!dev) {
+               return -1;
+       }
+       memset(dev, 0, sizeof(*dev));
 
-               if(cnt++ >= 1000) {
-                       cnt = 0;
-               }
+       /* try to allocate, check and clear enc_dev_t object */
+       enc = malloc(sizeof(*enc));
+       if (!enc) {
+               free(dev);
+               return -1;
+       }
+       memset(enc, 0, sizeof(*enc));
+
+       /* try to setup the SPI slave */
+       enc->slave = spi_setup_slave(bus, cs, max_hz, mode);
+       if (!enc->slave) {
+               printf("enc28j60: invalid SPI device %i:%i\n", bus, cs);
+               free(enc);
+               free(dev);
+               return -1;
        }
+
+       enc->dev = dev;
+       /* now fill the eth_device object */
+       dev->priv = enc;
+       dev->init = enc_init;
+       dev->halt = enc_halt;
+       dev->send = enc_send;
+       dev->recv = enc_recv;
+       dev->write_hwaddr = enc_write_hwaddr;
+       sprintf(dev->name, "enc%i.%i", bus, cs);
+       eth_register(dev);
+#if defined(CONFIG_CMD_MII)
+       miiphy_register(dev->name, enc_miiphy_read, enc_miiphy_write);
+#endif
+       return 0;
 }
diff --git a/drivers/net/enc28j60.h b/drivers/net/enc28j60.h
new file mode 100644 (file)
index 0000000..888c599
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * (X) extracted from enc28j60.c
+ * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.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
+ */
+
+#ifndef _enc28j60_h
+#define _enc28j60_h
+
+/*
+ * SPI Commands
+ *
+ * Bits 7-5: Command
+ * Bits 4-0: Register
+ */
+#define CMD_RCR(x)     (0x00+((x)&0x1f))       /* Read Control Register */
+#define CMD_RBM                0x3a                    /* Read Buffer Memory */
+#define CMD_WCR(x)     (0x40+((x)&0x1f))       /* Write Control Register */
+#define CMD_WBM                0x7a                    /* Write Buffer Memory */
+#define CMD_BFS(x)     (0x80+((x)&0x1f))       /* Bit Field Set */
+#define CMD_BFC(x)     (0xa0+((x)&0x1f))       /* Bit Field Clear */
+#define CMD_SRC                0xff                    /* System Reset Command */
+
+/* NEW: encode (bank number+1) in upper byte */
+
+/* Common Control Registers accessible in all Banks */
+#define CTL_REG_EIE            0x01B
+#define CTL_REG_EIR            0x01C
+#define CTL_REG_ESTAT          0x01D
+#define CTL_REG_ECON2          0x01E
+#define CTL_REG_ECON1          0x01F
+
+/* Control Registers accessible in Bank 0 */
+#define CTL_REG_ERDPTL         0x100
+#define CTL_REG_ERDPTH         0x101
+#define CTL_REG_EWRPTL         0x102
+#define CTL_REG_EWRPTH         0x103
+#define CTL_REG_ETXSTL         0x104
+#define CTL_REG_ETXSTH         0x105
+#define CTL_REG_ETXNDL         0x106
+#define CTL_REG_ETXNDH         0x107
+#define CTL_REG_ERXSTL         0x108
+#define CTL_REG_ERXSTH         0x109
+#define CTL_REG_ERXNDL         0x10A
+#define CTL_REG_ERXNDH         0x10B
+#define CTL_REG_ERXRDPTL       0x10C
+#define CTL_REG_ERXRDPTH       0x10D
+#define CTL_REG_ERXWRPTL       0x10E
+#define CTL_REG_ERXWRPTH       0x10F
+#define CTL_REG_EDMASTL                0x110
+#define CTL_REG_EDMASTH                0x111
+#define CTL_REG_EDMANDL                0x112
+#define CTL_REG_EDMANDH                0x113
+#define CTL_REG_EDMADSTL       0x114
+#define CTL_REG_EDMADSTH       0x115
+#define CTL_REG_EDMACSL                0x116
+#define CTL_REG_EDMACSH                0x117
+
+/* Control Registers accessible in Bank 1 */
+#define CTL_REG_EHT0           0x200
+#define CTL_REG_EHT1           0x201
+#define CTL_REG_EHT2           0x202
+#define CTL_REG_EHT3           0x203
+#define CTL_REG_EHT4           0x204
+#define CTL_REG_EHT5           0x205
+#define CTL_REG_EHT6           0x206
+#define CTL_REG_EHT7           0x207
+#define CTL_REG_EPMM0          0x208
+#define CTL_REG_EPMM1          0x209
+#define CTL_REG_EPMM2          0x20A
+#define CTL_REG_EPMM3          0x20B
+#define CTL_REG_EPMM4          0x20C
+#define CTL_REG_EPMM5          0x20D
+#define CTL_REG_EPMM6          0x20E
+#define CTL_REG_EPMM7          0x20F
+#define CTL_REG_EPMCSL         0x210
+#define CTL_REG_EPMCSH         0x211
+#define CTL_REG_EPMOL          0x214
+#define CTL_REG_EPMOH          0x215
+#define CTL_REG_EWOLIE         0x216
+#define CTL_REG_EWOLIR         0x217
+#define CTL_REG_ERXFCON                0x218
+#define CTL_REG_EPKTCNT                0x219
+
+/* Control Registers accessible in Bank 2 */
+#define CTL_REG_MACON1         0x300
+#define CTL_REG_MACON2         0x301
+#define CTL_REG_MACON3         0x302
+#define CTL_REG_MACON4         0x303
+#define CTL_REG_MABBIPG                0x304
+#define CTL_REG_MAIPGL         0x306
+#define CTL_REG_MAIPGH         0x307
+#define CTL_REG_MACLCON1       0x308
+#define CTL_REG_MACLCON2       0x309
+#define CTL_REG_MAMXFLL                0x30A
+#define CTL_REG_MAMXFLH                0x30B
+#define CTL_REG_MAPHSUP                0x30D
+#define CTL_REG_MICON          0x311
+#define CTL_REG_MICMD          0x312
+#define CTL_REG_MIREGADR       0x314
+#define CTL_REG_MIWRL          0x316
+#define CTL_REG_MIWRH          0x317
+#define CTL_REG_MIRDL          0x318
+#define CTL_REG_MIRDH          0x319
+
+/* Control Registers accessible in Bank 3 */
+#define CTL_REG_MAADR1         0x400
+#define CTL_REG_MAADR0         0x401
+#define CTL_REG_MAADR3         0x402
+#define CTL_REG_MAADR2         0x403
+#define CTL_REG_MAADR5         0x404
+#define CTL_REG_MAADR4         0x405
+#define CTL_REG_EBSTSD         0x406
+#define CTL_REG_EBSTCON                0x407
+#define CTL_REG_EBSTCSL                0x408
+#define CTL_REG_EBSTCSH                0x409
+#define CTL_REG_MISTAT         0x40A
+#define CTL_REG_EREVID         0x412
+#define CTL_REG_ECOCON         0x415
+#define CTL_REG_EFLOCON                0x417
+#define CTL_REG_EPAUSL         0x418
+#define CTL_REG_EPAUSH         0x419
+
+/* PHY Register */
+#define PHY_REG_PHCON1         0x00
+#define PHY_REG_PHSTAT1                0x01
+#define PHY_REG_PHID1          0x02
+#define PHY_REG_PHID2          0x03
+#define PHY_REG_PHCON2         0x10
+#define PHY_REG_PHSTAT2                0x11
+#define PHY_REG_PHLCON         0x14
+
+/* Receive Filter Register (ERXFCON) bits */
+#define ENC_RFR_UCEN           0x80
+#define ENC_RFR_ANDOR          0x40
+#define ENC_RFR_CRCEN          0x20
+#define ENC_RFR_PMEN           0x10
+#define ENC_RFR_MPEN           0x08
+#define ENC_RFR_HTEN           0x04
+#define ENC_RFR_MCEN           0x02
+#define ENC_RFR_BCEN           0x01
+
+/* ECON1 Register Bits */
+#define ENC_ECON1_TXRST                0x80
+#define ENC_ECON1_RXRST                0x40
+#define ENC_ECON1_DMAST                0x20
+#define ENC_ECON1_CSUMEN       0x10
+#define ENC_ECON1_TXRTS                0x08
+#define ENC_ECON1_RXEN         0x04
+#define ENC_ECON1_BSEL1                0x02
+#define ENC_ECON1_BSEL0                0x01
+
+/* ECON2 Register Bits */
+#define ENC_ECON2_AUTOINC      0x80
+#define ENC_ECON2_PKTDEC       0x40
+#define ENC_ECON2_PWRSV                0x20
+#define ENC_ECON2_VRPS         0x08
+
+/* EIR Register Bits */
+#define ENC_EIR_PKTIF          0x40
+#define ENC_EIR_DMAIF          0x20
+#define ENC_EIR_LINKIF         0x10
+#define ENC_EIR_TXIF           0x08
+#define ENC_EIR_WOLIF          0x04
+#define ENC_EIR_TXERIF         0x02
+#define ENC_EIR_RXERIF         0x01
+
+/* ESTAT Register Bits */
+#define ENC_ESTAT_INT          0x80
+#define ENC_ESTAT_LATECOL      0x10
+#define ENC_ESTAT_RXBUSY       0x04
+#define ENC_ESTAT_TXABRT       0x02
+#define ENC_ESTAT_CLKRDY       0x01
+
+/* EIE Register Bits */
+#define ENC_EIE_INTIE          0x80
+#define ENC_EIE_PKTIE          0x40
+#define ENC_EIE_DMAIE          0x20
+#define ENC_EIE_LINKIE         0x10
+#define ENC_EIE_TXIE           0x08
+#define ENC_EIE_WOLIE          0x04
+#define ENC_EIE_TXERIE         0x02
+#define ENC_EIE_RXERIE         0x01
+
+/* MACON1 Register Bits */
+#define ENC_MACON1_LOOPBK      0x10
+#define ENC_MACON1_TXPAUS      0x08
+#define ENC_MACON1_RXPAUS      0x04
+#define ENC_MACON1_PASSALL     0x02
+#define ENC_MACON1_MARXEN      0x01
+
+/* MACON2 Register Bits */
+#define ENC_MACON2_MARST       0x80
+#define ENC_MACON2_RNDRST      0x40
+#define ENC_MACON2_MARXRST     0x08
+#define ENC_MACON2_RFUNRST     0x04
+#define ENC_MACON2_MATXRST     0x02
+#define ENC_MACON2_TFUNRST     0x01
+
+/* MACON3 Register Bits */
+#define ENC_MACON3_PADCFG2     0x80
+#define ENC_MACON3_PADCFG1     0x40
+#define ENC_MACON3_PADCFG0     0x20
+#define ENC_MACON3_TXCRCEN     0x10
+#define ENC_MACON3_PHDRLEN     0x08
+#define ENC_MACON3_HFRMEN      0x04
+#define ENC_MACON3_FRMLNEN     0x02
+#define ENC_MACON3_FULDPX      0x01
+
+/* MACON4 Register Bits */
+#define ENC_MACON4_DEFER       0x40
+
+/* MICMD Register Bits */
+#define ENC_MICMD_MIISCAN      0x02
+#define ENC_MICMD_MIIRD                0x01
+
+/* MISTAT Register Bits */
+#define ENC_MISTAT_NVALID      0x04
+#define ENC_MISTAT_SCAN                0x02
+#define ENC_MISTAT_BUSY                0x01
+
+/* PHID1 and PHID2 values */
+#define ENC_PHID1_VALUE                0x0083
+#define ENC_PHID2_VALUE                0x1400
+#define ENC_PHID2_MASK         0xFC00
+
+/* PHCON1 values */
+#define        ENC_PHCON1_PDPXMD       0x0100
+
+/* PHSTAT1 values */
+#define        ENC_PHSTAT1_LLSTAT      0x0004
+
+/* PHSTAT2 values */
+#define        ENC_PHSTAT2_LSTAT       0x0400
+#define        ENC_PHSTAT2_DPXSTAT     0x0200
+
+#endif
diff --git a/drivers/net/enc28j60_lpc2292.c b/drivers/net/enc28j60_lpc2292.c
new file mode 100644 (file)
index 0000000..bf95052
--- /dev/null
@@ -0,0 +1,983 @@
+/*
+ * 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
+ */
+
+#warning This driver is depreciated. Please update to new SPI framework enc28j60 driver
+#include <config.h>
+#include <common.h>
+#include <net.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/spi.h>
+
+/*
+ * Control Registers in Bank 0
+ */
+
+#define CTL_REG_ERDPTL  0x00
+#define CTL_REG_ERDPTH  0x01
+#define CTL_REG_EWRPTL  0x02
+#define CTL_REG_EWRPTH  0x03
+#define CTL_REG_ETXSTL  0x04
+#define CTL_REG_ETXSTH  0x05
+#define CTL_REG_ETXNDL  0x06
+#define CTL_REG_ETXNDH  0x07
+#define CTL_REG_ERXSTL  0x08
+#define CTL_REG_ERXSTH  0x09
+#define CTL_REG_ERXNDL  0x0A
+#define CTL_REG_ERXNDH  0x0B
+#define CTL_REG_ERXRDPTL 0x0C
+#define CTL_REG_ERXRDPTH 0x0D
+#define CTL_REG_ERXWRPTL 0x0E
+#define CTL_REG_ERXWRPTH 0x0F
+#define CTL_REG_EDMASTL  0x10
+#define CTL_REG_EDMASTH  0x11
+#define CTL_REG_EDMANDL  0x12
+#define CTL_REG_EDMANDH  0x13
+#define CTL_REG_EDMADSTL 0x14
+#define CTL_REG_EDMADSTH 0x15
+#define CTL_REG_EDMACSL  0x16
+#define CTL_REG_EDMACSH  0x17
+/* these are common in all banks */
+#define CTL_REG_EIE     0x1B
+#define CTL_REG_EIR     0x1C
+#define CTL_REG_ESTAT   0x1D
+#define CTL_REG_ECON2   0x1E
+#define CTL_REG_ECON1   0x1F
+
+/*
+ * Control Registers in Bank 1
+ */
+
+#define CTL_REG_EHT0   0x00
+#define CTL_REG_EHT1   0x01
+#define CTL_REG_EHT2   0x02
+#define CTL_REG_EHT3   0x03
+#define CTL_REG_EHT4   0x04
+#define CTL_REG_EHT5   0x05
+#define CTL_REG_EHT6   0x06
+#define CTL_REG_EHT7   0x07
+#define CTL_REG_EPMM0  0x08
+#define CTL_REG_EPMM1  0x09
+#define CTL_REG_EPMM2  0x0A
+#define CTL_REG_EPMM3  0x0B
+#define CTL_REG_EPMM4  0x0C
+#define CTL_REG_EPMM5  0x0D
+#define CTL_REG_EPMM6  0x0E
+#define CTL_REG_EPMM7  0x0F
+#define CTL_REG_EPMCSL 0x10
+#define CTL_REG_EPMCSH 0x11
+#define CTL_REG_EPMOL  0x14
+#define CTL_REG_EPMOH  0x15
+#define CTL_REG_EWOLIE 0x16
+#define CTL_REG_EWOLIR 0x17
+#define CTL_REG_ERXFCON 0x18
+#define CTL_REG_EPKTCNT 0x19
+
+/*
+ * Control Registers in Bank 2
+ */
+
+#define CTL_REG_MACON1  0x00
+#define CTL_REG_MACON2  0x01
+#define CTL_REG_MACON3  0x02
+#define CTL_REG_MACON4  0x03
+#define CTL_REG_MABBIPG  0x04
+#define CTL_REG_MAIPGL  0x06
+#define CTL_REG_MAIPGH  0x07
+#define CTL_REG_MACLCON1 0x08
+#define CTL_REG_MACLCON2 0x09
+#define CTL_REG_MAMXFLL  0x0A
+#define CTL_REG_MAMXFLH  0x0B
+#define CTL_REG_MAPHSUP  0x0D
+#define CTL_REG_MICON   0x11
+#define CTL_REG_MICMD   0x12
+#define CTL_REG_MIREGADR 0x14
+#define CTL_REG_MIWRL   0x16
+#define CTL_REG_MIWRH   0x17
+#define CTL_REG_MIRDL   0x18
+#define CTL_REG_MIRDH   0x19
+
+/*
+ * Control Registers in Bank 3
+ */
+
+#define CTL_REG_MAADR1 0x00
+#define CTL_REG_MAADR0 0x01
+#define CTL_REG_MAADR3 0x02
+#define CTL_REG_MAADR2 0x03
+#define CTL_REG_MAADR5 0x04
+#define CTL_REG_MAADR4 0x05
+#define CTL_REG_EBSTSD 0x06
+#define CTL_REG_EBSTCON 0x07
+#define CTL_REG_EBSTCSL 0x08
+#define CTL_REG_EBSTCSH 0x09
+#define CTL_REG_MISTAT 0x0A
+#define CTL_REG_EREVID 0x12
+#define CTL_REG_ECOCON 0x15
+#define CTL_REG_EFLOCON 0x17
+#define CTL_REG_EPAUSL 0x18
+#define CTL_REG_EPAUSH 0x19
+
+
+/*
+ * PHY Register
+ */
+
+#define PHY_REG_PHID1 0x02
+#define PHY_REG_PHID2 0x03
+/* taken from the Linux driver */
+#define PHY_REG_PHCON1 0x00
+#define PHY_REG_PHCON2 0x10
+#define PHY_REG_PHLCON 0x14
+
+/*
+ * Receive Filter Register (ERXFCON) bits
+ */
+
+#define ENC_RFR_UCEN  0x80
+#define ENC_RFR_ANDOR 0x40
+#define ENC_RFR_CRCEN 0x20
+#define ENC_RFR_PMEN  0x10
+#define ENC_RFR_MPEN  0x08
+#define ENC_RFR_HTEN  0x04
+#define ENC_RFR_MCEN  0x02
+#define ENC_RFR_BCEN  0x01
+
+/*
+ * ECON1 Register Bits
+ */
+
+#define ENC_ECON1_TXRST  0x80
+#define ENC_ECON1_RXRST  0x40
+#define ENC_ECON1_DMAST  0x20
+#define ENC_ECON1_CSUMEN 0x10
+#define ENC_ECON1_TXRTS  0x08
+#define ENC_ECON1_RXEN  0x04
+#define ENC_ECON1_BSEL1  0x02
+#define ENC_ECON1_BSEL0  0x01
+
+/*
+ * ECON2 Register Bits
+ */
+#define ENC_ECON2_AUTOINC 0x80
+#define ENC_ECON2_PKTDEC  0x40
+#define ENC_ECON2_PWRSV   0x20
+#define ENC_ECON2_VRPS   0x08
+
+/*
+ * EIR Register Bits
+ */
+#define ENC_EIR_PKTIF  0x40
+#define ENC_EIR_DMAIF  0x20
+#define ENC_EIR_LINKIF 0x10
+#define ENC_EIR_TXIF   0x08
+#define ENC_EIR_WOLIF  0x04
+#define ENC_EIR_TXERIF 0x02
+#define ENC_EIR_RXERIF 0x01
+
+/*
+ * ESTAT Register Bits
+ */
+
+#define ENC_ESTAT_INT    0x80
+#define ENC_ESTAT_LATECOL 0x10
+#define ENC_ESTAT_RXBUSY  0x04
+#define ENC_ESTAT_TXABRT  0x02
+#define ENC_ESTAT_CLKRDY  0x01
+
+/*
+ * EIE Register Bits
+ */
+
+#define ENC_EIE_INTIE  0x80
+#define ENC_EIE_PKTIE  0x40
+#define ENC_EIE_DMAIE  0x20
+#define ENC_EIE_LINKIE 0x10
+#define ENC_EIE_TXIE   0x08
+#define ENC_EIE_WOLIE  0x04
+#define ENC_EIE_TXERIE 0x02
+#define ENC_EIE_RXERIE 0x01
+
+/*
+ * MACON1 Register Bits
+ */
+#define ENC_MACON1_LOOPBK  0x10
+#define ENC_MACON1_TXPAUS  0x08
+#define ENC_MACON1_RXPAUS  0x04
+#define ENC_MACON1_PASSALL 0x02
+#define ENC_MACON1_MARXEN  0x01
+
+
+/*
+ * MACON2 Register Bits
+ */
+#define ENC_MACON2_MARST   0x80
+#define ENC_MACON2_RNDRST  0x40
+#define ENC_MACON2_MARXRST 0x08
+#define ENC_MACON2_RFUNRST 0x04
+#define ENC_MACON2_MATXRST 0x02
+#define ENC_MACON2_TFUNRST 0x01
+
+/*
+ * MACON3 Register Bits
+ */
+#define ENC_MACON3_PADCFG2 0x80
+#define ENC_MACON3_PADCFG1 0x40
+#define ENC_MACON3_PADCFG0 0x20
+#define ENC_MACON3_TXCRCEN 0x10
+#define ENC_MACON3_PHDRLEN 0x08
+#define ENC_MACON3_HFRMEN  0x04
+#define ENC_MACON3_FRMLNEN 0x02
+#define ENC_MACON3_FULDPX  0x01
+
+/*
+ * MICMD Register Bits
+ */
+#define ENC_MICMD_MIISCAN 0x02
+#define ENC_MICMD_MIIRD   0x01
+
+/*
+ * MISTAT Register Bits
+ */
+#define ENC_MISTAT_NVALID 0x04
+#define ENC_MISTAT_SCAN   0x02
+#define ENC_MISTAT_BUSY   0x01
+
+/*
+ * PHID1 and PHID2 values
+ */
+#define ENC_PHID1_VALUE 0x0083
+#define ENC_PHID2_VALUE 0x1400
+#define ENC_PHID2_MASK 0xFC00
+
+
+#define ENC_SPI_SLAVE_CS 0x00010000    /* pin P1.16 */
+#define ENC_RESET       0x00020000     /* pin P1.17 */
+
+#define FAILSAFE_VALUE 5000
+
+/*
+ * Controller memory layout:
+ *
+ * 0x0000 - 0x17ff  6k bytes receive buffer
+ * 0x1800 - 0x1fff  2k bytes transmit buffer
+ */
+/* Use the lower memory for receiver buffer. See errata pt. 5 */
+#define ENC_RX_BUF_START 0x0000
+#define ENC_TX_BUF_START 0x1800
+/* taken from the Linux driver */
+#define ENC_RX_BUF_END   0x17ff
+#define ENC_TX_BUF_END   0x1fff
+
+/* maximum frame length */
+#define ENC_MAX_FRM_LEN 1518
+
+#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS)
+#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS)
+#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8);
+
+
+static unsigned char encReadReg (unsigned char regNo);
+static void encWriteReg (unsigned char regNo, unsigned char data);
+static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c);
+static void encReadBuff (unsigned short length, unsigned char *pBuff);
+static void encWriteBuff (unsigned short length, unsigned char *pBuff);
+static void encBitSet (unsigned char regNo, unsigned char data);
+static void encBitClr (unsigned char regNo, unsigned char data);
+static void encReset (void);
+static void encInit (unsigned char *pEthAddr);
+static unsigned short phyRead (unsigned char addr);
+static void phyWrite(unsigned char, unsigned short);
+static void encPoll (void);
+static void encRx (void);
+
+#define m_nic_read(reg) encReadReg(reg)
+#define m_nic_write(reg, data) encWriteReg(reg, data)
+#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count)
+#define m_nic_read_data(len, buf) encReadBuff((len), (buf))
+#define m_nic_write_data(len, buf) encWriteBuff((len), (buf))
+
+/* bit field set */
+#define m_nic_bfs(reg, data) encBitSet(reg, data)
+
+/* bit field clear */
+#define m_nic_bfc(reg, data) encBitClr(reg, data)
+
+static unsigned char bank = 0; /* current bank in enc28j60 */
+static unsigned char next_pointer_lsb;
+static unsigned char next_pointer_msb;
+
+static unsigned char buffer[ENC_MAX_FRM_LEN];
+static int rxResetCounter = 0;
+
+#define RX_RESET_COUNTER 1000;
+
+/*-----------------------------------------------------------------------------
+ * Always returns 0
+ */
+int eth_init (bd_t * bis)
+{
+       unsigned char estatVal;
+       uchar enetaddr[6];
+
+       /* configure GPIO */
+       (*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS;
+       (*((volatile unsigned long *) IO1DIR)) |= ENC_RESET;
+
+       /* CS and RESET active low */
+       PUT32 (IO1SET, ENC_SPI_SLAVE_CS);
+       PUT32 (IO1SET, ENC_RESET);
+
+       spi_init ();
+
+       /* taken from the Linux driver - dangerous stuff here! */
+       /* Wait for CLKRDY to become set (i.e., check that we can communicate with
+          the ENC) */
+       do
+       {
+               estatVal = m_nic_read(CTL_REG_ESTAT);
+       } while ((estatVal & 0x08) || (~estatVal & ENC_ESTAT_CLKRDY));
+
+       /* initialize controller */
+       encReset ();
+       eth_getenv_enetaddr("ethaddr", enetaddr);
+       encInit (enetaddr);
+
+       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN);      /* enable receive */
+
+       return 0;
+}
+
+int eth_send (volatile void *packet, int length)
+{
+       /* check frame length, etc. */
+       /* TODO: */
+
+       /* switch to bank 0 */
+       m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+       /* set EWRPT */
+       m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff));
+       m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8));
+
+       /* set ETXND */
+       m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF);
+       m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8);
+
+       /* set ETXST */
+       m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF);
+       m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8);
+
+       /* write packet */
+       m_nic_write_data (length, (unsigned char *) packet);
+
+       /* taken from the Linux driver */
+       /* Verify that the internal transmit logic has not been altered by excessive
+          collisions.  See Errata B4 12 and 14.
+        */
+       if (m_nic_read(CTL_REG_EIR) & ENC_EIR_TXERIF) {
+               m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_TXRST);
+               m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_TXRST);
+       }
+       m_nic_bfc(CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF));
+
+       /* set ECON1.TXRTS */
+       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS);
+
+       return 0;
+}
+
+
+/*****************************************************************************
+ * This function resets the receiver only. This function may be called from
+ * interrupt-context.
+ */
+static void encReceiverReset (void)
+{
+       unsigned char econ1;
+
+       econ1 = m_nic_read (CTL_REG_ECON1);
+       if ((econ1 & ENC_ECON1_RXRST) == 0) {
+               m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST);
+               rxResetCounter = RX_RESET_COUNTER;
+       }
+}
+
+/*****************************************************************************
+ * receiver reset timer
+ */
+static void encReceiverResetCallback (void)
+{
+       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST);
+       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN);      /* enable receive */
+}
+
+/*-----------------------------------------------------------------------------
+ * Check for received packets. Call NetReceive for each packet. The return
+ * value is ignored by the caller.
+ */
+int eth_rx (void)
+{
+       if (rxResetCounter > 0 && --rxResetCounter == 0) {
+               encReceiverResetCallback ();
+       }
+
+       encPoll ();
+
+       return 0;
+}
+
+void eth_halt (void)
+{
+       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN);      /* disable receive */
+}
+
+/*****************************************************************************/
+
+static void encPoll (void)
+{
+       unsigned char eir_reg;
+       volatile unsigned char estat_reg;
+       unsigned char pkt_cnt;
+
+#ifdef CONFIG_USE_IRQ
+       /* clear global interrupt enable bit in enc28j60 */
+       m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+       estat_reg = m_nic_read (CTL_REG_ESTAT);
+
+       eir_reg = m_nic_read (CTL_REG_EIR);
+
+       if (eir_reg & ENC_EIR_TXIF) {
+               /* clear TXIF bit in EIR */
+               m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF);
+       }
+
+       /* We have to use pktcnt and not pktif bit, see errata pt. 6 */
+
+       /* move to bank 1 */
+       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+
+       /* read pktcnt */
+       pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
+
+       if (pkt_cnt > 0) {
+               if ((eir_reg & ENC_EIR_PKTIF) == 0) {
+                       /*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */
+               }
+               encRx ();
+               /* clear PKTIF bit in EIR, this should not need to be done but it
+                  seems like we get problems if we do not */
+               m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF);
+       }
+
+       if (eir_reg & ENC_EIR_RXERIF) {
+               printf ("encPoll: rx error\n");
+               m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF);
+       }
+       if (eir_reg & ENC_EIR_TXERIF) {
+               printf ("encPoll: tx error\n");
+               m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF);
+       }
+
+#ifdef CONFIG_USE_IRQ
+       /* set global interrupt enable bit in enc28j60 */
+       m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+}
+
+static void encRx (void)
+{
+       unsigned short pkt_len;
+       unsigned short copy_len;
+       unsigned short status;
+       unsigned char eir_reg;
+       unsigned char pkt_cnt = 0;
+       unsigned short rxbuf_rdpt;
+
+       /* switch to bank 0 */
+       m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+       m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
+       m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
+
+       do {
+               m_nic_read_data (6, buffer);
+               next_pointer_lsb = buffer[0];
+               next_pointer_msb = buffer[1];
+               pkt_len = buffer[2];
+               pkt_len |= (unsigned short) buffer[3] << 8;
+               status = buffer[4];
+               status |= (unsigned short) buffer[5] << 8;
+
+               if (pkt_len <= ENC_MAX_FRM_LEN)
+                       copy_len = pkt_len;
+               else
+                       copy_len = 0;
+
+               if ((status & (1L << 7)) == 0) /* check Received Ok bit */
+                       copy_len = 0;
+
+               /* taken from the Linux driver */
+               /* check if next pointer is resonable */
+               if ((((unsigned int)next_pointer_msb << 8) |
+                       (unsigned int)next_pointer_lsb) >= ENC_TX_BUF_START)
+                       copy_len = 0;
+
+               if (copy_len > 0) {
+                       m_nic_read_data (copy_len, buffer);
+               }
+
+               /* advance read pointer to next pointer */
+               m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
+               m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
+
+               /* decrease packet counter */
+               m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC);
+
+               /* taken from the Linux driver */
+               /* Only odd values should be written to ERXRDPTL,
+                * see errata B4 pt.13
+                */
+               rxbuf_rdpt = (next_pointer_msb << 8 | next_pointer_lsb) - 1;
+               if ((rxbuf_rdpt < (m_nic_read(CTL_REG_ERXSTH) << 8 |
+                               m_nic_read(CTL_REG_ERXSTL))) || (rxbuf_rdpt >
+                               (m_nic_read(CTL_REG_ERXNDH) << 8 |
+                               m_nic_read(CTL_REG_ERXNDL)))) {
+                       m_nic_write(CTL_REG_ERXRDPTL, m_nic_read(CTL_REG_ERXNDL));
+                       m_nic_write(CTL_REG_ERXRDPTH, m_nic_read(CTL_REG_ERXNDH));
+               } else {
+                       m_nic_write(CTL_REG_ERXRDPTL, rxbuf_rdpt & 0xFF);
+                       m_nic_write(CTL_REG_ERXRDPTH, rxbuf_rdpt >> 8);
+               }
+
+               /* move to bank 1 */
+               m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+               m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+
+               /* read pktcnt */
+               pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
+
+               /* switch to bank 0 */
+               m_nic_bfc (CTL_REG_ECON1,
+                          (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+               if (copy_len == 0) {
+                       eir_reg = m_nic_read (CTL_REG_EIR);
+                       encReceiverReset ();
+                       printf ("eth_rx: copy_len=0\n");
+                       continue;
+               }
+
+               NetReceive ((unsigned char *) buffer, pkt_len);
+
+               eir_reg = m_nic_read (CTL_REG_EIR);
+       } while (pkt_cnt);      /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
+}
+
+static void encWriteReg (unsigned char regNo, unsigned char data)
+{
+       spi_lock ();
+       enc_cfg_spi ();
+       enc_enable ();
+
+       spi_write (0x40 | regNo);       /* write in regNo */
+       spi_write (data);
+
+       enc_disable ();
+       enc_enable ();
+
+       spi_write (0x1f);       /* write reg 0x1f */
+
+       enc_disable ();
+       spi_unlock ();
+}
+
+static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c)
+{
+       unsigned char readback;
+       int i;
+
+       spi_lock ();
+
+       for (i = 0; i < c; i++) {
+               enc_cfg_spi ();
+               enc_enable ();
+
+               spi_write (0x40 | regNo);       /* write in regNo */
+               spi_write (data);
+
+               enc_disable ();
+               enc_enable ();
+
+               spi_write (0x1f);       /* write reg 0x1f */
+
+               enc_disable ();
+
+               spi_unlock ();  /* we must unlock spi first */
+
+               readback = encReadReg (regNo);
+
+               spi_lock ();
+
+               if (readback == data)
+                       break;
+       }
+       spi_unlock ();
+
+       if (i == c) {
+               printf ("enc28j60: write reg %d failed\n", regNo);
+       }
+}
+
+static unsigned char encReadReg (unsigned char regNo)
+{
+       unsigned char rxByte;
+
+       spi_lock ();
+       enc_cfg_spi ();
+       enc_enable ();
+
+       spi_write (0x1f);       /* read reg 0x1f */
+
+       bank = spi_read () & 0x3;
+
+       enc_disable ();
+       enc_enable ();
+
+       spi_write (regNo);
+       rxByte = spi_read ();
+
+       /* check if MAC or MII register */
+       if (((bank == 2) && (regNo <= 0x1a)) ||
+           ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) {
+               /* ignore first byte and read another byte */
+               rxByte = spi_read ();
+       }
+
+       enc_disable ();
+       spi_unlock ();
+
+       return rxByte;
+}
+
+static void encReadBuff (unsigned short length, unsigned char *pBuff)
+{
+       spi_lock ();
+       enc_cfg_spi ();
+       enc_enable ();
+
+       spi_write (0x20 | 0x1a);        /* read buffer memory */
+
+       while (length--) {
+               if (pBuff != NULL)
+                       *pBuff++ = spi_read ();
+               else
+                       spi_write (0);
+       }
+
+       enc_disable ();
+       spi_unlock ();
+}
+
+static void encWriteBuff (unsigned short length, unsigned char *pBuff)
+{
+       spi_lock ();
+       enc_cfg_spi ();
+       enc_enable ();
+
+       spi_write (0x60 | 0x1a);        /* write buffer memory */
+
+       spi_write (0x00);       /* control byte */
+
+       while (length--)
+               spi_write (*pBuff++);
+
+       enc_disable ();
+       spi_unlock ();
+}
+
+static void encBitSet (unsigned char regNo, unsigned char data)
+{
+       spi_lock ();
+       enc_cfg_spi ();
+       enc_enable ();
+
+       spi_write (0x80 | regNo);       /* bit field set */
+       spi_write (data);
+
+       enc_disable ();
+       spi_unlock ();
+}
+
+static void encBitClr (unsigned char regNo, unsigned char data)
+{
+       spi_lock ();
+       enc_cfg_spi ();
+       enc_enable ();
+
+       spi_write (0xA0 | regNo);       /* bit field clear */
+       spi_write (data);
+
+       enc_disable ();
+       spi_unlock ();
+}
+
+static void encReset (void)
+{
+       spi_lock ();
+       enc_cfg_spi ();
+       enc_enable ();
+
+       spi_write (0xff);       /* soft reset */
+
+       enc_disable ();
+       spi_unlock ();
+
+       /* sleep 1 ms. See errata pt. 2 */
+       udelay (1000);
+}
+
+static void encInit (unsigned char *pEthAddr)
+{
+       unsigned short phid1 = 0;
+       unsigned short phid2 = 0;
+
+       /* switch to bank 0 */
+       m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+       /*
+        * Setup the buffer space. The reset values are valid for the
+        * other pointers.
+        */
+       /* We shall not write to ERXST, see errata pt. 5. Instead we
+          have to make sure that ENC_RX_BUS_START is 0. */
+       m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1);
+       m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1);
+
+       /* taken from the Linux driver */
+       m_nic_write_retry (CTL_REG_ERXNDL, (ENC_RX_BUF_END & 0xFF), 1);
+       m_nic_write_retry (CTL_REG_ERXNDH, (ENC_RX_BUF_END >> 8), 1);
+
+       m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1);
+       m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1);
+
+       next_pointer_lsb = (ENC_RX_BUF_START & 0xFF);
+       next_pointer_msb = (ENC_RX_BUF_START >> 8);
+
+       /* verify identification */
+       phid1 = phyRead (PHY_REG_PHID1);
+       phid2 = phyRead (PHY_REG_PHID2);
+
+       if (phid1 != ENC_PHID1_VALUE
+           || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) {
+               printf ("ERROR: failed to identify controller\n");
+               printf ("phid1 = %x, phid2 = %x\n",
+                       phid1, (phid2 & ENC_PHID2_MASK));
+               printf ("should be phid1 = %x, phid2 = %x\n",
+                       ENC_PHID1_VALUE, ENC_PHID2_VALUE);
+       }
+
+       /*
+        * --- MAC Initialization ---
+        */
+
+       /* Pull MAC out of Reset */
+
+       /* switch to bank 2 */
+       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+       /* enable MAC to receive frames */
+       /* added some bits from the Linux driver */
+       m_nic_write_retry (CTL_REG_MACON1
+               ,(ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS)
+               ,10);
+
+       /* configure pad, tx-crc and duplex */
+       /* added a bit from the Linux driver */
+       m_nic_write_retry (CTL_REG_MACON3
+               ,(ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN | ENC_MACON3_FRMLNEN)
+               ,10);
+
+       /* added 4 new lines from the Linux driver */
+       /* Allow infinite deferals if the medium is continously busy */
+       m_nic_write_retry(CTL_REG_MACON4, (1<<6) /*ENC_MACON4_DEFER*/, 10);
+
+       /* Late collisions occur beyond 63 bytes */
+       m_nic_write_retry(CTL_REG_MACLCON2, 63, 10);
+
+       /* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */
+       m_nic_write_retry(CTL_REG_MAIPGL, 0x12, 10);
+
+       /*
+       * Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended
+       * 0x0c for half-duplex. Nothing for full-duplex
+       */
+       m_nic_write_retry(CTL_REG_MAIPGH, 0x0C, 10);
+
+       /* set maximum frame length */
+       m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10);
+       m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10);
+
+       /*
+        * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex
+        * and 0x15 for full duplex.
+        */
+       m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10);
+
+       /* set MAC address */
+
+       /* switch to bank 3 */
+       m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1));
+
+       m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1);
+       m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1);
+       m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1);
+       m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1);
+       m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1);
+       m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1);
+
+       /*
+       * PHY Initialization taken from the Linux driver
+        */
+
+       /* Prevent automatic loopback of data beeing transmitted by setting
+          ENC_PHCON2_HDLDIS */
+       phyWrite(PHY_REG_PHCON2, (1<<8));
+
+       /* LEDs configuration
+        * LEDA: LACFG = 0100 -> display link status
+        * LEDB: LBCFG = 0111 -> display TX & RX activity
+        * STRCH = 1 -> LED pulses
+        */
+       phyWrite(PHY_REG_PHLCON, 0x0472);
+
+       /* Reset PDPXMD-bit => half duplex */
+       phyWrite(PHY_REG_PHCON1, 0);
+
+       /*
+        * Receive settings
+        */
+
+#ifdef CONFIG_USE_IRQ
+       /* enable interrupts */
+       m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE);
+       m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE);
+       m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE);
+       m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE);
+       m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+}
+
+/*****************************************************************************
+ *
+ * Description:
+ *    Read PHY registers.
+ *
+ *    NOTE! This function will change to Bank 2.
+ *
+ * Params:
+ *    [in] addr address of the register to read
+ *
+ * Returns:
+ *    The value in the register
+ */
+static unsigned short phyRead (unsigned char addr)
+{
+       unsigned short ret = 0;
+
+       /* move to bank 2 */
+       m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+       m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+       /* write address to MIREGADR */
+       m_nic_write (CTL_REG_MIREGADR, addr);
+
+       /* set MICMD.MIIRD */
+       m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD);
+
+       /* taken from the Linux driver */
+       /* move to bank 3 */
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+       /* poll MISTAT.BUSY bit until operation is complete */
+       while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
+               static int cnt = 0;
+
+               if (cnt++ >= 1000) {
+                       /* GJ - this seems extremely dangerous! */
+                       /* printf("#"); */
+                       cnt = 0;
+               }
+       }
+
+       /* taken from the Linux driver */
+       /* move to bank 2 */
+       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+       /* clear MICMD.MIIRD */
+       m_nic_write (CTL_REG_MICMD, 0);
+
+       ret = (m_nic_read (CTL_REG_MIRDH) << 8);
+       ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF);
+
+       return ret;
+}
+
+/*****************************************************************************
+ *
+ * Taken from the Linux driver.
+ * Description:
+ * Write PHY registers.
+ *
+ * NOTE! This function will change to Bank 3.
+ *
+ * Params:
+ * [in] addr address of the register to write to
+ * [in] data to be written
+ *
+ * Returns:
+ *    None
+ */
+static void phyWrite(unsigned char addr, unsigned short data)
+{
+       /* move to bank 2 */
+       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+       /* write address to MIREGADR */
+       m_nic_write(CTL_REG_MIREGADR, addr);
+
+       m_nic_write(CTL_REG_MIWRL, data & 0xff);
+       m_nic_write(CTL_REG_MIWRH, data >> 8);
+
+       /* move to bank 3 */
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+       /* poll MISTAT.BUSY bit until operation is complete */
+       while((m_nic_read(CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
+               static int cnt = 0;
+
+               if(cnt++ >= 1000) {
+                       cnt = 0;
+               }
+       }
+}
index c88e596c01fa222dd5b0cfc2034791c898316c5b..bc8c9222dcf8f9ac9f9d41ba9d16b03279b19cda 100644 (file)
@@ -249,6 +249,13 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
 
        mpc5xxx_fec_init_phy(dev, bis);
 
+       /*
+        * Call board-specific PHY fixups (if any)
+        */
+#ifdef CONFIG_RESET_PHY_R
+       reset_phy();
+#endif
+
        /*
         * Initialize RxBD/TxBD rings
         */
index 54a1bfb2a9237518b8815e2c1c3ffef7dbc5122e..ba9c67e4c903478a82ba690e513bf2925a7d25a7 100644 (file)
@@ -654,6 +654,28 @@ again:
        return length;
 }
 
+static int smc_write_hwaddr(struct eth_device *dev)
+{
+       int i;
+
+       swap_to(ETHERNET);
+       SMC_SELECT_BANK (dev, 1);
+#ifdef USE_32_BIT
+       for (i = 0; i < 6; i += 2) {
+               word address;
+
+               address = dev->enetaddr[i + 1] << 8;
+               address |= dev->enetaddr[i];
+               SMC_outw(dev, address, (ADDR0_REG + i));
+       }
+#else
+       for (i = 0; i < 6; i++)
+               SMC_outb(dev, dev->enetaddr[i], (ADDR0_REG + i));
+#endif
+       swap_to(FLASH);
+       return 0;
+}
+
 /*
  * Open and Initialize the board
  *
@@ -662,8 +684,6 @@ again:
  */
 static int smc_init(struct eth_device *dev, bd_t *bd)
 {
-       int i;
-
        swap_to(ETHERNET);
 
        PRINTK2 ("%s: smc_init\n", SMC_DEV_NAME);
@@ -680,20 +700,6 @@ static int smc_init(struct eth_device *dev, bd_t *bd)
        /* conservative setting (10Mbps, HalfDuplex, no AutoNeg.) */
 /*     SMC_SELECT_BANK(dev, 0); */
 /*     SMC_outw(dev, 0, RPC_REG); */
-       SMC_SELECT_BANK (dev, 1);
-
-#ifdef USE_32_BIT
-       for (i = 0; i < 6; i += 2) {
-               word address;
-
-               address = dev->enetaddr[i + 1] << 8;
-               address |= dev->enetaddr[i];
-               SMC_outw(dev, address, (ADDR0_REG + i));
-       }
-#else
-       for (i = 0; i < 6; i++)
-               SMC_outb(dev, dev->enetaddr[i], (ADDR0_REG + i));
-#endif
 
        printf(SMC_DEV_NAME ": MAC %pM\n", dev->enetaddr);
 
@@ -1360,6 +1366,7 @@ int smc91111_initialize(u8 dev_num, int base_addr)
                return 0;
        }
 
+       memset(dev, 0, sizeof(*dev));
        priv->dev_num = dev_num;
        dev->priv = priv;
        dev->iobase = base_addr;
@@ -1374,6 +1381,7 @@ int smc91111_initialize(u8 dev_num, int base_addr)
        dev->halt = smc_halt;
        dev->send = smc_send;
        dev->recv = smc_rcv;
+       dev->write_hwaddr = smc_write_hwaddr;
        sprintf(dev->name, "%s-%hu", SMC_DEV_NAME, dev_num);
 
        eth_register(dev);
index 0820daa2bb8284d0ac7a304813262d79801f5687..76af939e98f7f93e4853ae86178a301026216eca 100644 (file)
@@ -26,6 +26,7 @@
 #include <common.h>
 #include <net.h>
 #include <config.h>
+#include <malloc.h>
 #include <asm/io.h>
 
 #undef DEBUG
 #define XEL_RSR_RECV_IE_MASK           0x00000008UL
 
 typedef struct {
-       unsigned int baseaddress;       /* Base address for device (IPIF) */
-       unsigned int nexttxbuffertouse; /* Next TX buffer to write to */
-       unsigned int nextrxbuffertouse; /* Next RX buffer to read from */
-       unsigned char deviceid;         /* Unique ID of device - for future */
+       u32 baseaddress;        /* Base address for device (IPIF) */
+       u32 nexttxbuffertouse;  /* Next TX buffer to write to */
+       u32 nextrxbuffertouse;  /* Next RX buffer to read from */
+       uchar deviceid;         /* Unique ID of device - for future */
 } xemaclite;
 
 static xemaclite emaclite;
 
 static u32 etherrxbuff[PKTSIZE_ALIGN/4]; /* Receive buffer */
 
-/* hardcoded MAC address for the Xilinx EMAC Core when env is nowhere*/
-#ifdef CONFIG_ENV_IS_NOWHERE
-static u8 emacaddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 };
-#else
-static u8 emacaddr[ENET_ADDR_LENGTH];
-#endif
-
-void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount)
+static void xemaclite_alignedread (u32 *srcptr, void *destptr, u32 bytecount)
 {
-       unsigned int i;
+       u32 i;
        u32 alignbuffer;
        u32 *to32ptr;
        u32 *from32ptr;
@@ -107,9 +101,9 @@ void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount)
        }
 }
 
-void xemaclite_alignedwrite (void *srcptr, u32 destptr, unsigned bytecount)
+static void xemaclite_alignedwrite (void *srcptr, u32 destptr, u32 bytecount)
 {
-       unsigned i;
+       u32 i;
        u32 alignbuffer;
        u32 *to32ptr = (u32 *) destptr;
        u32 *from32ptr;
@@ -134,23 +128,16 @@ void xemaclite_alignedwrite (void *srcptr, u32 destptr, unsigned bytecount)
        *to32ptr++ = alignbuffer;
 }
 
-void eth_halt (void)
+static void emaclite_halt(struct eth_device *dev)
 {
        debug ("eth_halt\n");
 }
 
-int eth_init (bd_t * bis)
+static int emaclite_init(struct eth_device *dev, bd_t *bis)
 {
-       uchar enetaddr[6];
-
        debug ("EmacLite Initialization Started\n");
        memset (&emaclite, 0, sizeof (xemaclite));
-       emaclite.baseaddress = XILINX_EMACLITE_BASEADDR;
-
-       if (!eth_getenv_enetaddr("ethaddr", enetaddr)) {
-               memcpy(enetaddr, emacaddr, ENET_ADDR_LENGTH);
-               eth_setenv_enetaddr("ethaddr", enetaddr);
-       }
+       emaclite.baseaddress = dev->iobase;
 
 /*
  * TX - TX_PING & TX_PONG initialization
@@ -158,7 +145,7 @@ int eth_init (bd_t * bis)
        /* Restart PING TX */
        out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0);
        /* Copy MAC address */
-       xemaclite_alignedwrite (enetaddr,
+       xemaclite_alignedwrite (dev->enetaddr,
                emaclite.baseaddress, ENET_ADDR_LENGTH);
        /* Set the length */
        out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH);
@@ -171,7 +158,7 @@ int eth_init (bd_t * bis)
 #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
        /* The same operation with PONG TX */
        out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 0);
-       xemaclite_alignedwrite (enetaddr, emaclite.baseaddress +
+       xemaclite_alignedwrite (dev->enetaddr, emaclite.baseaddress +
                XEL_BUFFER_OFFSET, ENET_ADDR_LENGTH);
        out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH);
        out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET,
@@ -194,7 +181,7 @@ int eth_init (bd_t * bis)
        return 0;
 }
 
-int xemaclite_txbufferavailable (xemaclite * instanceptr)
+static int xemaclite_txbufferavailable (xemaclite *instanceptr)
 {
        u32 reg;
        u32 txpingbusy;
@@ -216,12 +203,12 @@ int xemaclite_txbufferavailable (xemaclite * instanceptr)
        return (!(txpingbusy && txpongbusy));
 }
 
-int eth_send (volatile void *ptr, int len) {
-
-       unsigned int reg;
-       unsigned int baseaddress;
+static int emaclite_send (struct eth_device *dev, volatile void *ptr, int len)
+{
+       u32 reg;
+       u32 baseaddress;
 
-       unsigned maxtry = 1000;
+       u32 maxtry = 1000;
 
        if (len > ENET_MAX_MTU)
                len = ENET_MAX_MTU;
@@ -293,11 +280,11 @@ int eth_send (volatile void *ptr, int len) {
        return 0;
 }
 
-int eth_rx (void)
+static int emaclite_recv(struct eth_device *dev)
 {
-       unsigned int length;
-       unsigned int reg;
-       unsigned int baseaddress;
+       u32 length;
+       u32 reg;
+       u32 baseaddress;
 
        baseaddress = emaclite.baseaddress + emaclite.nextrxbuffertouse;
        reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
@@ -322,7 +309,7 @@ int eth_rx (void)
 #endif
        }
        /* Get the length of the frame that arrived */
-       switch(((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC)) &
+       switch(((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC))) &
                        0xFFFF0000 ) >> 16) {
                case 0x806:
                        length = 42 + 20; /* FIXME size of ARP */
@@ -330,7 +317,7 @@ int eth_rx (void)
                        break;
                case 0x800:
                        length = 14 + 14 +
-                       (((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0x10)) &
+                       (((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0x10))) &
                        0xFFFF0000) >> 16); /* FIXME size of IP packet */
                        debug ("IP Packet\n");
                        break;
@@ -353,3 +340,26 @@ int eth_rx (void)
        return 1;
 
 }
+
+int xilinx_emaclite_initialize (bd_t *bis, int base_addr)
+{
+       struct eth_device *dev;
+
+       dev = malloc(sizeof(*dev));
+       if (dev == NULL)
+               hang();
+
+       memset(dev, 0, sizeof(*dev));
+       sprintf(dev->name, "Xilinx_Emaclite");
+
+       dev->iobase = base_addr;
+       dev->priv = 0;
+       dev->init = emaclite_init;
+       dev->halt = emaclite_halt;
+       dev->send = emaclite_send;
+       dev->recv = emaclite_recv;
+
+       eth_register(dev);
+
+       return 0;
+}
index e10c0f328c4ae8e94976b2b3ce743b9226f1da91..48033d750c3cee5eb649ee67889e37a0405220c0 100644 (file)
@@ -1223,8 +1223,10 @@ static int uec_init(struct eth_device* dev, bd_t *bd)
                i = 50;
                do {
                        err = curphy->read_status(uec->mii_info);
+                       if (!(((i-- > 0) && !uec->mii_info->link) || err))
+                               break;
                        udelay(100000);
-               } while (((i-- > 0) && !uec->mii_info->link) || err);
+               } while (1);
 
                if (err || i <= 0)
                        printf("warning: %s: timeout on PHY link\n", dev->name);
index 2d3a896d6f3f9fe7abada120fe5cc162f7ffaf17..9be784e6add8063ebf7fe72efa92e808fa4fadaa 100644 (file)
@@ -351,6 +351,15 @@ static int marvell_config_aneg (struct uec_mii_info *mii_info)
 static int genmii_config_aneg (struct uec_mii_info *mii_info)
 {
        if (mii_info->autoneg) {
+               /* Speed up the common case, if link is already up, speed and
+                  duplex match, skip auto neg as it already matches */
+               if (!genmii_read_status(mii_info) && mii_info->link)
+                       if (mii_info->duplex == DUPLEX_FULL &&
+                           mii_info->speed == SPEED_100)
+                               if (mii_info->advertising &
+                                   ADVERTISED_100baseT_Full)
+                                       return 0;
+
                config_genmii_advert (mii_info);
                genmii_restart_aneg (mii_info);
        } else
@@ -389,7 +398,6 @@ static int genmii_update_link (struct uec_mii_info *mii_info)
                        status = phy_read(mii_info, PHY_BMSR);
                }
                mii_info->link = 1;
-               udelay(500000); /* another 500 ms (results in faster booting) */
        } else {
                if (status & PHY_BMSR_LS)
                        mii_info->link = 1;
index bc6480c78d020e8450d6df4e8360a986fd58db76..b22ca90fc6824b92e19c34cea1f69b10d2675777 100644 (file)
@@ -1276,9 +1276,6 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
        debug("%s: status %d\n", __func__, req->status);
 
        packet_received = 1;
-
-       if (req)
-               dev->rx_req = req;
 }
 
 static int alloc_requests(struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
@@ -1287,16 +1284,18 @@ static int alloc_requests(struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
        dev->tx_req = usb_ep_alloc_request(dev->in_ep, 0);
 
        if (!dev->tx_req)
-               goto fail;
+               goto fail1;
 
        dev->rx_req = usb_ep_alloc_request(dev->out_ep, 0);
 
        if (!dev->rx_req)
-               goto fail;
+               goto fail2;
 
        return 0;
 
-fail:
+fail2:
+       usb_ep_free_request(dev->in_ep, dev->tx_req);
+fail1:
        error("can't alloc requests");
        return -1;
 }
@@ -1791,8 +1790,6 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
        }
 
        dev->network_started = 0;
-       dev->tx_req = NULL;
-       dev->rx_req = NULL;
 
        packet_received = 0;
        packet_sent = 0;
@@ -1813,6 +1810,7 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
                usb_gadget_handle_interrupts();
        }
 
+       packet_received = 0;
        rx_submit(dev, dev->rx_req, 0);
        return 0;
 fail:
@@ -1823,15 +1821,13 @@ static int usb_eth_send(struct eth_device *netdev,
                        volatile void *packet, int length)
 {
        int                     retval;
-       struct usb_request      *req = NULL;
        struct eth_dev          *dev = &l_ethdev;
+       struct usb_request      *req = dev->tx_req;
        unsigned long ts;
        unsigned long timeout = USB_CONNECT_TIMEOUT;
 
        debug("%s:...\n", __func__);
 
-       req = dev->tx_req;
-
        req->buf = (void *)packet;
        req->context = NULL;
        req->complete = tx_complete;
@@ -1883,8 +1879,7 @@ static int usb_eth_recv(struct eth_device *netdev)
                        NetReceive(NetRxPackets[0], dev->rx_req->length);
                        packet_received = 0;
 
-                       if (dev->rx_req)
-                               rx_submit(dev, dev->rx_req, 0);
+                       rx_submit(dev, dev->rx_req, 0);
                } else
                        error("dev->rx_req invalid");
        }
index 3f76c4e9f00eec6ca493aef7deb615b83faee387..d2469789628b4924ae248ca56f5b403feded36fd 100644 (file)
@@ -1529,7 +1529,7 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
        if (usb_pipebulk(pipe))
                timeout = BULK_TO;
        else
-               timeout = 100;
+               timeout = 1000;
 
        /* wait for it to complete */
        for (;;) {
index af989aa78d27175ba22a04958d909e752c51fb57..f38b279096c31fbfaf5abb161526ffa82eca19c1 100644 (file)
@@ -144,19 +144,28 @@ static void write_toggle(struct usb_device *dev, u8 ep, u8 dir_out)
        u16 csr;
 
        if (dir_out) {
-               if (!toggle)
-                       writew(MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
-               else {
-                       csr = readw(&musbr->txcsr);
+               csr = readw(&musbr->txcsr);
+               if (!toggle) {
+                       if (csr & MUSB_TXCSR_MODE)
+                               csr = MUSB_TXCSR_CLRDATATOG;
+                       else
+                               csr = 0;
+                       writew(csr, &musbr->txcsr);
+               } else {
                        csr |= MUSB_TXCSR_H_WR_DATATOGGLE;
                        writew(csr, &musbr->txcsr);
                        csr |= (toggle << MUSB_TXCSR_H_DATATOGGLE_SHIFT);
                        writew(csr, &musbr->txcsr);
                }
        } else {
-               if (!toggle)
-                       writew(MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
-               else {
+               if (!toggle) {
+                       csr = readw(&musbr->txcsr);
+                       if (csr & MUSB_TXCSR_MODE)
+                               csr = MUSB_RXCSR_CLRDATATOG;
+                       else
+                               csr = 0;
+                       writew(csr, &musbr->rxcsr);
+               } else {
                        csr = readw(&musbr->rxcsr);
                        csr |= MUSB_RXCSR_H_WR_DATATOGGLE;
                        writew(csr, &musbr->rxcsr);
index 5f1f8008073648a30643f66e6690e4a76577e63b..c2dd514d9391cc9d65a3b74a679b54bdc1375569 100644 (file)
@@ -82,6 +82,11 @@ CFLAGS := $(filter-out $(RELFLAGS),$(CFLAGS))
 CPPFLAGS := $(filter-out $(RELFLAGS),$(CPPFLAGS))
 endif
 
+# We don't want gcc reordering functions if possible.  This ensures that an
+# application's entry point will be the first function in the application's
+# source file.
+CFLAGS += $(call cc-option,-fno-toplevel-reorder)
+
 all:   $(obj).depend $(OBJS) $(LIB) $(SREC) $(BIN) $(ELF)
 
 #########################################################################
index 003666eaec449008b61721dd645b26f4423c45ce..744e961847263f17da8058bb06736daf967178c0 100644 (file)
@@ -439,11 +439,19 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
 {
        dir_entry *realdent;
        dir_slot *slotptr = (dir_slot *)retdent;
-       __u8 *nextclust = cluster + mydata->clust_size * SECTOR_SIZE;
+       __u8 *buflimit = cluster + ((curclust == 0) ?
+                                       LINEAR_PREFETCH_SIZE :
+                                       (mydata->clust_size * SECTOR_SIZE)
+                                  );
        __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
        int idx = 0;
 
-       while ((__u8 *)slotptr < nextclust) {
+       if (counter > VFAT_MAXSEQ) {
+               debug("Error: VFAT name is too long\n");
+               return -1;
+       }
+
+       while ((__u8 *)slotptr < buflimit) {
                if (counter == 0)
                        break;
                if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
@@ -452,10 +460,11 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
                counter--;
        }
 
-       if ((__u8 *)slotptr >= nextclust) {
+       if ((__u8 *)slotptr >= buflimit) {
                dir_slot *slotptr2;
 
-               slotptr--;
+               if (curclust == 0)
+                       return -1;
                curclust = get_fatent(mydata, curclust);
                if (CHECK_CLUST(curclust, mydata->fatsize)) {
                        debug("curclust: 0x%x\n", curclust);
@@ -470,14 +479,19 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
                }
 
                slotptr2 = (dir_slot *)get_vfatname_block;
-               while (slotptr2->id > 0x01)
+               while (counter > 0) {
+                       if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
+                           & 0xff) != counter)
+                               return -1;
                        slotptr2++;
+                       counter--;
+               }
 
                /* Save the real directory entry */
-               realdent = (dir_entry *)slotptr2 + 1;
-               while ((__u8 *)slotptr2 >= get_vfatname_block) {
-                       slot2str(slotptr2, l_name, &idx);
+               realdent = (dir_entry *)slotptr2;
+               while ((__u8 *)slotptr2 > get_vfatname_block) {
                        slotptr2--;
+                       slot2str(slotptr2, l_name, &idx);
                }
        } else {
                /* Save the real directory entry */
@@ -549,7 +563,7 @@ static dir_entry *get_dentfromdir (fsdata *mydata, int startsect,
                dentptr = (dir_entry *)get_dentfromdir_block;
 
                for (i = 0; i < DIRENTSPERCLUST; i++) {
-                       char s_name[14], l_name[256];
+                       char s_name[14], l_name[VFAT_MAXLEN_BYTES];
 
                        l_name[0] = '\0';
                        if (dentptr->name[0] == DELETED_FLAG) {
@@ -841,7 +855,11 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
                debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%d\n",
                        cursect, mydata->clust_size, DIRENTSPERBLOCK);
 
-               if (disk_read(cursect, mydata->clust_size, do_fat_read_block) < 0) {
+               if (disk_read(cursect,
+                               (mydata->fatsize == 32) ?
+                               (mydata->clust_size) :
+                               LINEAR_PREFETCH_SIZE,
+                               do_fat_read_block) < 0) {
                        debug("Error: reading rootdir block\n");
                        return -1;
                }
@@ -849,9 +867,13 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
                dentptr = (dir_entry *) do_fat_read_block;
 
                for (i = 0; i < DIRENTSPERBLOCK; i++) {
-                       char s_name[14], l_name[256];
+                       char s_name[14], l_name[VFAT_MAXLEN_BYTES];
 
                        l_name[0] = '\0';
+                       if (dentptr->name[0] == DELETED_FLAG) {
+                               dentptr++;
+                               continue;
+                       }
                        if ((dentptr->attr & ATTR_VOLUME)) {
 #ifdef CONFIG_SUPPORT_VFAT
                                if ((dentptr->attr & ATTR_VFAT) &&
@@ -859,7 +881,10 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
                                        prevcksum =
                                                ((dir_slot *)dentptr)->alias_checksum;
 
-                                       get_vfatname(mydata, 0,
+                                       get_vfatname(mydata,
+                                                    (mydata->fatsize == 32) ?
+                                                    root_cluster :
+                                                    0,
                                                     do_fat_read_block,
                                                     dentptr, l_name);
 
index 746bf18f04c61a482e141ed5a1de4770966b643e..cdc5ff10face6dc3d66b16678a9e36360d22d235 100644 (file)
@@ -70,6 +70,7 @@
 #define CONFIG_CMD_PORTIO      /* Port I/O                     */
 #define CONFIG_CMD_REGINFO     /* Register dump                */
 #define CONFIG_CMD_REISER      /* Reiserfs support             */
+#define CONFIG_CMD_RARP                /* rarpboot support             */
 #define CONFIG_CMD_RUN         /* run command in env variable  */
 #define CONFIG_CMD_SAVEENV     /* saveenv                      */
 #define CONFIG_CMD_SAVES       /* save S record dump           */
index adb6ac52e123c43ce0b2da5e7088e9111c87d9b0..ba3ada13a5a5a868257c260f2d1812cc173aa48d 100644 (file)
 #define CONFIG_INITRD_TAG
 #define CONFIG_MMC                     1
 /* we use this ethernet chip */
-#define CONFIG_ENC28J60
+#define CONFIG_ENC28J60_LPC2292
 
 #endif /* __CONFIG_H */
diff --git a/include/configs/a4m072.h b/include/configs/a4m072.h
new file mode 100644 (file)
index 0000000..a54ab1d
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ * (C) Copyright 2003-2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2010
+ * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC5xxx         1       /* This is an MPC5xxx CPU */
+#define CONFIG_MPC5200         1       /* (more precisely a MPC5200 CPU) */
+#define CONFIG_A4M072          1       /* ... on A4M072 board */
+#define CONFIG_MPC5200_DDR     1       /* ... use DDR RAM */
+
+#define CONFIG_MISC_INIT_R
+
+#define CONFIG_SYS_MPC5XXX_CLKIN       33000000 /* ... running at 33.000000MHz */
+
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH  */
+#define BOOTFLAG_WARM          0x02    /* Software reboot           */
+
+#define CONFIG_HIGH_BATS       1       /* High BATs supported */
+
+/*
+ * Serial console configuration
+ */
+#define CONFIG_PSC_CONSOLE     1       /* console is on PSC1 */
+#define CONFIG_BAUDRATE                9600    /* ... at 9600 bps */
+#define CONFIG_SYS_BAUDRATE_TABLE      { 9600, 19200, 38400, 57600, 115200, 230400 }
+/* define to enable silent console */
+#define CONFIG_SILENT_CONSOLE
+#define CONFIG_SYS_DEVICE_NULLDEV      1       /* include nulldev device */
+
+/*
+ * PCI Mapping:
+ * 0x40000000 - 0x4fffffff - PCI Memory
+ * 0x50000000 - 0x50ffffff - PCI IO Space
+ */
+#define CONFIG_PCI
+
+#if defined(CONFIG_PCI)
+#define CONFIG_PCI_PNP         1
+#define CONFIG_PCI_SCAN_SHOW   1
+#define CONFIG_PCIAUTO_SKIP_HOST_BRIDGE        1
+
+#define CONFIG_PCI_MEM_BUS     0x40000000
+#define CONFIG_PCI_MEM_PHYS    CONFIG_PCI_MEM_BUS
+#define CONFIG_PCI_MEM_SIZE    0x10000000
+
+#define CONFIG_PCI_IO_BUS      0x50000000
+#define CONFIG_PCI_IO_PHYS     CONFIG_PCI_IO_BUS
+#define CONFIG_PCI_IO_SIZE     0x01000000
+#endif
+
+#define CONFIG_SYS_XLB_PIPELINING      1
+
+#undef CONFIG_NET_MULTI
+#undef CONFIG_EEPRO100 
+
+/* Partitions */
+#define CONFIG_MAC_PARTITION
+#define CONFIG_DOS_PARTITION
+
+/* USB */
+#define CONFIG_USB_OHCI_NEW
+#define CONFIG_USB_STORAGE
+#define CONFIG_SYS_OHCI_BE_CONTROLLER
+#undef CONFIG_SYS_USB_OHCI_BOARD_INIT
+#define CONFIG_SYS_USB_OHCI_CPU_INIT   1
+#define CONFIG_SYS_USB_OHCI_REGS_BASE  MPC5XXX_USB
+#define CONFIG_SYS_USB_OHCI_SLOT_NAME  "mpc5200"
+#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS     15
+
+#define        CONFIG_TIMESTAMP                /* Print image info with timestamp */
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_EEPROM
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_IDE
+#define CONFIG_CMD_NFS
+#define CONFIG_CMD_SNTP
+#define CONFIG_CMD_USB
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DISPLAY
+
+#if defined(CONFIG_PCI)
+#define CONFIG_CMD_PCI
+#endif
+
+#if (TEXT_BASE == 0xFE000000)          /* Boot low with 32 MB Flash */
+#define CONFIG_SYS_LOWBOOT             1
+#define CONFIG_SYS_LOWBOOT32           1
+#endif
+
+/*
+ * Autobooting
+ */
+#define CONFIG_BOOTDELAY       2       /* autoboot after 2 seconds */
+
+#define CONFIG_SYS_AUTOLOAD    "n"
+
+#define CONFIG_AUTOBOOT_KEYED
+#define CONFIG_AUTOBOOT_PROMPT         "autoboot in %d seconds\n", bootdelay
+#define CONFIG_AUTOBOOT_DELAY_STR      "asdfg"
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_PREBOOT                         "run try_update"
+
+#define        CONFIG_EXTRA_ENV_SETTINGS                                       \
+       "bk=run add_mtd ; run add_consolespec ; bootm 200000\0" \
+       "cf1=diskboot 200000 0:1\0"     \
+       "bootcmd_cf1=run bcf1\0"        \
+       "bcf=setenv bootargs root=/dev/hda3\0"  \
+       "bootcmd_nfs=run bnfs\0"        \
+       "norargs=setenv bootargs root=/dev/mtdblock3 rootfstype=cramfs\0"       \
+       "bootcmd_nor=cp.b ${kernel_addr} 200000 100000; run norargs addip; run bk\0"    \
+       "bnfs=nfs 200000 ${rootpath}/boot/uImage ; run nfsargs addip ; run bk\0"        \
+       "nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath}\0"    \
+       "try_update=usb start;sleep 2;usb start;sleep 1;fatload usb 0 2F0000 PCPUUPDT 2FF;usb stop;source 2F0000\0"     \
+       "env_addr=FE060000\0"   \
+       "kernel_addr=FE100000\0"        \
+       "rootfs_addr=FE200000\0"        \
+       "add_mtd=setenv bootargs ${bootargs} mtdparts=phys_mapped_flash:384k(u),640k(e),1m(k),30m(r)\0" \
+       "bcf1=run cf1; run bcf; run addip; run bk\0"    \
+       "add_consolespec=setenv bootargs ${bootargs} console=/dev/null quiet\0" \
+       "addip=if test \"${ethaddr}\" != \"00:00:00:00:00:00\" ; then if test -n ${ipaddr}; then setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1; fi ; fi\0"     \
+       "hostname=CPUP0\0"      \
+       "ethaddr=00:00:00:00:00:00\0"   \
+       "netdev=eth0\0" \
+       "bootcmd=run bootcmd_nor\0" \
+       ""
+/*
+ * IPB Bus clocking configuration.
+ */
+#undef CONFIG_SYS_IPBCLK_EQUALS_XLBCLK         /* define for 133MHz speed */
+
+/*
+ * I2C configuration
+ */
+#define CONFIG_HARD_I2C                        1       /* I2C with hardware support */
+#define CONFIG_SYS_I2C_MODULE          2       /* Select I2C module #1 or #2 */
+
+#define CONFIG_SYS_I2C_SPEED           100000 /* 100 kHz */
+#define CONFIG_SYS_I2C_SLAVE           0x7F
+
+/*
+ * EEPROM configuration
+ */
+#define CONFIG_SYS_I2C_EEPROM_ADDR             0x52    /* 1010010x */
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN         2
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS      6
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS  10
+#define CONFIG_SYS_EEPROM_WREN                 1
+#define CONFIG_SYS_EEPROM_WP                   GPIO_PSC2_4
+
+/*
+ * Flash configuration
+ */
+#define CONFIG_SYS_FLASH_BASE          0xFE000000
+#define CONFIG_SYS_FLASH_SIZE          0x02000000
+#if !defined(CONFIG_SYS_LOWBOOT)
+#error "CONFIG_SYS_LOWBOOT not defined?"
+#else  /* CONFIG_SYS_LOWBOOT */
+#if defined(CONFIG_SYS_LOWBOOT32)
+#define CONFIG_ENV_ADDR                (CONFIG_SYS_FLASH_BASE + 0x00060000)
+#endif
+#endif /* CONFIG_SYS_LOWBOOT */
+
+#define CONFIG_SYS_MAX_FLASH_BANKS     1       /* max num of memory banks      */
+#define CONFIG_SYS_MAX_FLASH_SECT      256     /* max num of sects on one chip */
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_SYS_FLASH_CFI_WIDTH     FLASH_CFI_16BIT
+#define CONFIG_SYS_FLASH_BANKS_LIST    {CONFIG_SYS_CS0_START}
+
+/*
+ * Environment settings
+ */
+#define CONFIG_ENV_IS_IN_FLASH 1
+#define CONFIG_ENV_SIZE                0x10000
+#define CONFIG_ENV_SECT_SIZE   0x20000
+#define CONFIG_ENV_ADDR_REDUND (CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE)
+#define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE
+
+#define CONFIG_ENV_OVERWRITE   1
+
+/*
+ * Memory map
+ */
+#define CONFIG_SYS_MBAR                0xF0000000
+#define CONFIG_SYS_SDRAM_BASE  0x00000000
+#define CONFIG_SYS_DEFAULT_MBAR        0x80000000
+
+/* Use SRAM until RAM will be available */
+#define CONFIG_SYS_INIT_RAM_ADDR       MPC5XXX_SRAM
+#define CONFIG_SYS_INIT_RAM_END                MPC5XXX_SRAM_SIZE       /* End of used area in DPRAM */
+
+
+#define CONFIG_SYS_GBL_DATA_SIZE       128     /* size in bytes reserved for initial data */
+#define CONFIG_SYS_GBL_DATA_OFFSET     (CONFIG_SYS_INIT_RAM_END - CONFIG_SYS_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_OFFSET      CONFIG_SYS_GBL_DATA_OFFSET
+
+#define CONFIG_SYS_MONITOR_BASE    TEXT_BASE
+#if (CONFIG_SYS_MONITOR_BASE < CONFIG_SYS_FLASH_BASE)
+#   define CONFIG_SYS_RAMBOOT          1
+#endif
+
+#define CONFIG_SYS_MONITOR_LEN         (384 << 10)     /* Reserve 384 kB for Monitor   */
+#define CONFIG_SYS_MALLOC_LEN          (128 << 10)     /* Reserve 128 kB for malloc()  */
+#define CONFIG_SYS_BOOTMAPSZ           (8 << 20)       /* Initial Memory map for Linux */
+
+/*
+ * Ethernet configuration
+ */
+#define CONFIG_MPC5xxx_FEC     1
+#define CONFIG_MPC5xxx_FEC_MII100
+/*
+ * Define CONFIG_MPC5xxx_FEC_MII10 to force FEC at 10Mb
+ */
+/* #define CONFIG_MPC5xxx_FEC_MII10 */
+#define CONFIG_PHY_ADDR                0x1f
+#define CONFIG_PHY_TYPE                0x79c874                /* AMD Phy Controller */
+
+/*
+ * GPIO configuration
+ */
+#define CONFIG_SYS_GPS_PORT_CONFIG     0x18000004
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_CMDLINE_EDITING 1
+#ifdef CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT_HUSH_PS2     "> "
+#endif
+#define CONFIG_SYS_LONGHELP                    /* undef to save memory     */
+#define CONFIG_SYS_PROMPT              "=> "   /* Monitor Command Prompt   */
+#if defined(CONFIG_CMD_KGDB)
+#define CONFIG_SYS_CBSIZE              1024    /* Console I/O Buffer Size  */
+#else
+#define CONFIG_SYS_CBSIZE              256     /* Console I/O Buffer Size  */
+#endif
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16)     /* Print Buffer Size */
+#define CONFIG_SYS_MAXARGS             16              /* max number of command args   */
+#define CONFIG_SYS_BARGSIZE            CONFIG_SYS_CBSIZE       /* Boot Argument Buffer Size    */
+
+#define CONFIG_SYS_MEMTEST_START       0x00100000      /* memtest works on */
+#define CONFIG_SYS_MEMTEST_END         0x00f00000      /* 1 ... 15 MB in DRAM  */
+
+#define CONFIG_SYS_LOAD_ADDR           0x100000        /* default load address */
+
+#define CONFIG_SYS_HZ                  1000    /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_SYS_CACHELINE_SIZE      32      /* For MPC5xxx CPUs */
+#if defined(CONFIG_CMD_KGDB)
+#  define CONFIG_SYS_CACHELINE_SHIFT   5       /* log base 2 of the above value */
+#endif
+
+
+/*
+ * Various low-level settings
+ */
+#define CONFIG_SYS_HID0_INIT           HID0_ICE | HID0_ICFI
+#define CONFIG_SYS_HID0_FINAL          HID0_ICE
+/* Flash at CSBoot, CS0 */
+#define CONFIG_SYS_BOOTCS_START                CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_BOOTCS_SIZE         CONFIG_SYS_FLASH_SIZE
+#define CONFIG_SYS_BOOTCS_CFG          0x0002DD00
+#define CONFIG_SYS_CS0_START           CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_CS0_SIZE            CONFIG_SYS_FLASH_SIZE
+/* External SRAM at CS1 */
+#define CONFIG_SYS_CS1_START           0x62000000
+#define CONFIG_SYS_CS1_SIZE            0x00400000
+#define CONFIG_SYS_CS1_CFG             0x00009930
+#define CONFIG_SYS_SRAM_BASE           CONFIG_SYS_CS1_START
+#define CONFIG_SYS_SRAM_SIZE           CONFIG_SYS_CS1_SIZE
+/* LED display at CS7 */
+#define CONFIG_SYS_CS7_START           0x6a000000
+#define CONFIG_SYS_CS7_SIZE            (64*1024)
+#define CONFIG_SYS_CS7_CFG             0x0000bf30
+
+#define CONFIG_SYS_CS_BURST            0x00000000
+#define CONFIG_SYS_CS_DEADCYCLE                0x33333003
+
+#define CONFIG_SYS_RESET_ADDRESS       0xff000000
+
+/*-----------------------------------------------------------------------
+ * USB stuff
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_USB_CLOCK       0x0001BBBB
+#define CONFIG_USB_CONFIG      0x00001000 /* 0x4000 for SE mode */
+
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff Supports IDE harddisk
+ *-----------------------------------------------------------------------
+ */
+
+#undef  CONFIG_IDE_8xx_PCCARD          /* Use IDE with PC Card Adapter */
+
+#undef CONFIG_IDE_8xx_DIRECT           /* Direct IDE    not supported  */
+#undef CONFIG_IDE_LED                  /* LED   for ide not supported  */
+
+#define CONFIG_IDE_PREINIT
+
+#define CONFIG_SYS_IDE_MAXBUS          1       /* max. 1 IDE bus               */
+#define CONFIG_SYS_IDE_MAXDEVICE       1       /* max. 2 drives per IDE bus    */
+
+#define CONFIG_SYS_ATA_IDE0_OFFSET     0x0000
+
+#define CONFIG_SYS_ATA_BASE_ADDR       MPC5XXX_ATA
+
+/* Offset for data I/O                 */
+#define CONFIG_SYS_ATA_DATA_OFFSET     (0x0060)
+
+/* Offset for normal register accesses */
+#define CONFIG_SYS_ATA_REG_OFFSET      (CONFIG_SYS_ATA_DATA_OFFSET)
+
+/* Offset for alternate registers      */
+#define CONFIG_SYS_ATA_ALT_OFFSET      (0x005C)
+
+/* Interval between registers                                                */
+#define CONFIG_SYS_ATA_STRIDE          4
+
+#define CONFIG_ATAPI                   1
+
+/*-----------------------------------------------------------------------
+ * Open firmware flat tree support
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_OF_LIBFDT       1
+#define CONFIG_OF_BOARD_SETUP  1
+
+#define OF_CPU                 "PowerPC,5200@0"
+#define OF_SOC                 "soc5200@f0000000"
+#define OF_TBCLK               (bd->bi_busfreq / 4)
+#define OF_STDOUT_PATH         "/soc5200@f0000000/serial@2000"
+
+/* Support for the 7-segment display */
+#define CONFIG_SYS_DISP_CHR_RAM             CONFIG_SYS_CS7_START
+#define CONFIG_SHOW_ACTIVITY           /* used for display realization */
+
+#define CONFIG_SHOW_BOOT_PROGRESS
+
+#endif /* __CONFIG_H */
index d40b7a9f52e4da196366c13cebf34e42b44085e9..8b0b773b2a4248488bedc450440fe115555bcf4f 100644 (file)
 /* Display addresses                                                  */
 /*---------------------------------------------------------------------*/
 
+#define CONFIG_PDSP188x
 #define CONFIG_SYS_DISP_CHR_RAM        (CONFIG_SYS_DISPLAY_BASE + 0x38)
 #define CONFIG_SYS_DISP_CWORD          (CONFIG_SYS_DISPLAY_BASE + 0x30)
 
index 7ce8d6de1ff81e6d1f13e04b3939a80a27e07c0f..65276a27c0b7f63d5a620bf3431d160212678074 100644 (file)
 #define CONFIG_INITRD_TAG
 #define CONFIG_MMC 1
 /* we use this ethernet chip */
-#define CONFIG_ENC28J60
+#define CONFIG_ENC28J60_LPC2292
 
 #endif /* __CONFIG_H */
index 022460889a5726f46997609e51fa125adfc75fbd..291b6698caf35399e6569b480a2896a1df596326 100644 (file)
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_SNTP
 
+/*
+ * 8-symbol LED display (can be accessed with 'display' command)
+ */
+#define CONFIG_PDSP188x
+
 #define        CONFIG_TIMESTAMP        1       /* Print image info with timestamp */
 
 /*
index 9b1569a6d47c87d02f60018dff8d083d844b6132..c30cc4cbc86ff48109bcf3a691bb86929d854e73 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2007-2008 Michal Simek
+ * (C) Copyright 2007-2010 Michal Simek
  *
  * Michal SIMEK <monstr@monstr.eu>
  *
 
 #include "../board/xilinx/microblaze-generic/xparameters.h"
 
-#define        CONFIG_MICROBLAZE       1       /* MicroBlaze CPU */
+/* MicroBlaze CPU */
+#define        CONFIG_MICROBLAZE       1
 #define        MICROBLAZE_V5           1
 
 /* uart */
 #ifdef XILINX_UARTLITE_BASEADDR
-       #define CONFIG_XILINX_UARTLITE
-       #define CONFIG_SERIAL_BASE      XILINX_UARTLITE_BASEADDR
-       #define CONFIG_BAUDRATE         XILINX_UARTLITE_BAUDRATE
-       #define CONFIG_SYS_BAUDRATE_TABLE       { CONFIG_BAUDRATE }
-       #define CONSOLE_ARG     "console=console=ttyUL0,115200\0"
+define CONFIG_XILINX_UARTLITE
+# define CONFIG_SERIAL_BASE    XILINX_UARTLITE_BASEADDR
+# define CONFIG_BAUDRATE       XILINX_UARTLITE_BAUDRATE
+# define CONFIG_SYS_BAUDRATE_TABLE     { CONFIG_BAUDRATE }
+# define CONSOLE_ARG   "console=console=ttyUL0,115200\0"
 #elif XILINX_UART16550_BASEADDR
-       #define CONFIG_SYS_NS16550      1
-       #define CONFIG_SYS_NS16550_SERIAL
-       #define CONFIG_SYS_NS16550_REG_SIZE     -4
-       #define CONFIG_CONS_INDEX       1
-       #define CONFIG_SYS_NS16550_COM1 (XILINX_UART16550_BASEADDR + 0x1000 + 0x3)
-       #define CONFIG_SYS_NS16550_CLK  XILINX_UART16550_CLOCK_HZ
-       #define CONFIG_BAUDRATE         115200
-
-       /* The following table includes the supported baudrates */
-       #define CONFIG_SYS_BAUDRATE_TABLE  \
-               {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
-       #define CONSOLE_ARG     "console=console=ttyS0,115200\0"
+# define CONFIG_SYS_NS16550            1
+# define CONFIG_SYS_NS16550_SERIAL
+# define CONFIG_SYS_NS16550_REG_SIZE   -4
+# define CONFIG_CONS_INDEX             1
+# define CONFIG_SYS_NS16550_COM1 \
+                       (XILINX_UART16550_BASEADDR + 0x1000 + 0x3)
+# define CONFIG_SYS_NS16550_CLK        XILINX_UART16550_CLOCK_HZ
+# define CONFIG_BAUDRATE       115200
+
+/* The following table includes the supported baudrates */
+# define CONFIG_SYS_BAUDRATE_TABLE \
+       {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
+# define CONSOLE_ARG   "console=console=ttyS0,115200\0"
 #else
-       #error Undefined uart
+error Undefined uart
 #endif
 
 /* setting reset address */
 
 /* ethernet */
 #ifdef XILINX_EMACLITE_BASEADDR
-       #define CONFIG_XILINX_EMACLITE  1
-       #define CONFIG_SYS_ENET
+# define CONFIG_XILINX_EMACLITE                1
+define CONFIG_SYS_ENET
 #elif XILINX_LLTEMAC_BASEADDR
-       #define CONFIG_XILINX_LL_TEMAC  1
-       #define CONFIG_SYS_ENET
+# define CONFIG_XILINX_LL_TEMAC                1
+define CONFIG_SYS_ENET
 #endif
 
 #undef ET_DEBUG
 
 /* gpio */
 #ifdef XILINX_GPIO_BASEADDR
-       #define CONFIG_SYS_GPIO_0               1
-       #define CONFIG_SYS_GPIO_0_ADDR          XILINX_GPIO_BASEADDR
+# define CONFIG_SYS_GPIO_0             1
+# define CONFIG_SYS_GPIO_0_ADDR                XILINX_GPIO_BASEADDR
 #endif
 
 /* interrupt controller */
 #ifdef XILINX_INTC_BASEADDR
-       #define CONFIG_SYS_INTC_0               1
-       #define CONFIG_SYS_INTC_0_ADDR          XILINX_INTC_BASEADDR
-       #define CONFIG_SYS_INTC_0_NUM           XILINX_INTC_NUM_INTR_INPUTS
+# define CONFIG_SYS_INTC_0             1
+# define CONFIG_SYS_INTC_0_ADDR                XILINX_INTC_BASEADDR
+# define CONFIG_SYS_INTC_0_NUM         XILINX_INTC_NUM_INTR_INPUTS
 #endif
 
 /* timer */
 #ifdef XILINX_TIMER_BASEADDR
-       #if (XILINX_TIMER_IRQ != -1)
-               #define CONFIG_SYS_TIMER_0              1
-               #define CONFIG_SYS_TIMER_0_ADDR XILINX_TIMER_BASEADDR
-               #define CONFIG_SYS_TIMER_0_IRQ          XILINX_TIMER_IRQ
-               #define FREQUENCE               XILINX_CLOCK_FREQ
-               #define CONFIG_SYS_TIMER_0_PRELOAD      ( FREQUENCE/1000 )
-       #endif
+if (XILINX_TIMER_IRQ != -1)
+#  define CONFIG_SYS_TIMER_0           1
+#  define CONFIG_SYS_TIMER_0_ADDR      XILINX_TIMER_BASEADDR
+#  define CONFIG_SYS_TIMER_0_IRQ       XILINX_TIMER_IRQ
+#  define FREQUENCE    XILINX_CLOCK_FREQ
+#  define CONFIG_SYS_TIMER_0_PRELOAD   ( FREQUENCE/1000 )
+endif
 #elif XILINX_CLOCK_FREQ
-       #define CONFIG_XILINX_CLOCK_FREQ        XILINX_CLOCK_FREQ
+# define CONFIG_XILINX_CLOCK_FREQ      XILINX_CLOCK_FREQ
 #else
-       #error BAD CLOCK FREQ
+error BAD CLOCK FREQ
 #endif
 /* FSL */
 /* #define     CONFIG_SYS_FSL_2 */
 /* global pointer */
 #define        CONFIG_SYS_GBL_DATA_SIZE        128 /* size of global data */
 /* start of global data */
-#define        CONFIG_SYS_GBL_DATA_OFFSET      (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE - CONFIG_SYS_GBL_DATA_SIZE)
+#define        CONFIG_SYS_GBL_DATA_OFFSET \
+       (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE \
+                               - CONFIG_SYS_GBL_DATA_SIZE)
 
 /* monitor code */
-#define        SIZE                    0x40000
+#define        SIZE                            0x40000
 #define        CONFIG_SYS_MONITOR_LEN          (SIZE - CONFIG_SYS_GBL_DATA_SIZE)
-#define        CONFIG_SYS_MONITOR_BASE (CONFIG_SYS_GBL_DATA_OFFSET - CONFIG_SYS_MONITOR_LEN)
-#define        CONFIG_SYS_MONITOR_END          (CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)
+#define        CONFIG_SYS_MONITOR_BASE \
+                       (CONFIG_SYS_GBL_DATA_OFFSET - CONFIG_SYS_MONITOR_LEN)
+#define        CONFIG_SYS_MONITOR_END \
+                       (CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)
 #define        CONFIG_SYS_MALLOC_LEN           SIZE
-#define        CONFIG_SYS_MALLOC_BASE          (CONFIG_SYS_MONITOR_BASE - CONFIG_SYS_MALLOC_LEN)
+#define        CONFIG_SYS_MALLOC_BASE \
+                       (CONFIG_SYS_MONITOR_BASE - CONFIG_SYS_MALLOC_LEN)
 
 /* stack */
 #define        CONFIG_SYS_INIT_SP_OFFSET       CONFIG_SYS_MALLOC_BASE
 #define        FLASH
 
 #ifdef FLASH
-       #define CONFIG_SYS_FLASH_BASE           XILINX_FLASH_START
-       #define CONFIG_SYS_FLASH_SIZE           XILINX_FLASH_SIZE
-       #define CONFIG_SYS_FLASH_CFI            1
-       #define CONFIG_FLASH_CFI_DRIVER 1
-       #define CONFIG_SYS_FLASH_EMPTY_INFO     1       /* ?empty sector */
-       #define CONFIG_SYS_MAX_FLASH_BANKS      1       /* max number of memory banks */
-       #define CONFIG_SYS_MAX_FLASH_SECT       512     /* max number of sectors on one chip */
-       #define CONFIG_SYS_FLASH_PROTECTION             /* hardware flash protection */
-
-       #ifdef  RAMENV
-               #define CONFIG_ENV_IS_NOWHERE   1
-               #define CONFIG_ENV_SIZE         0x1000
-               #define CONFIG_ENV_ADDR         (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
-
-       #else   /* !RAMENV */
-               #define CONFIG_ENV_IS_IN_FLASH  1
-               #define CONFIG_ENV_SECT_SIZE    0x20000 /* 128K(one sector) for env */
-               #define CONFIG_ENV_ADDR         (CONFIG_SYS_FLASH_BASE + (2 * CONFIG_ENV_SECT_SIZE))
-               #define CONFIG_ENV_SIZE         0x20000
-       #endif /* !RAMBOOT */
+# define CONFIG_SYS_FLASH_BASE         XILINX_FLASH_START
+# define CONFIG_SYS_FLASH_SIZE         XILINX_FLASH_SIZE
+# define CONFIG_SYS_FLASH_CFI          1
+# define CONFIG_FLASH_CFI_DRIVER       1
+/* ?empty sector */
+# define CONFIG_SYS_FLASH_EMPTY_INFO   1
+/* max number of memory banks */
+# define CONFIG_SYS_MAX_FLASH_BANKS    1
+/* max number of sectors on one chip */
+# define CONFIG_SYS_MAX_FLASH_SECT     512
+/* hardware flash protection */
+# define CONFIG_SYS_FLASH_PROTECTION
+
+# ifdef        RAMENV
+#  define CONFIG_ENV_IS_NOWHERE        1
+#  define CONFIG_ENV_SIZE      0x1000
+#  define CONFIG_ENV_ADDR      (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
+
+# else /* !RAMENV */
+#  define CONFIG_ENV_IS_IN_FLASH       1
+/* 128K(one sector) for env */
+#  define CONFIG_ENV_SECT_SIZE 0x20000
+#  define CONFIG_ENV_ADDR \
+                       (CONFIG_SYS_FLASH_BASE + (2 * CONFIG_ENV_SECT_SIZE))
+#  define CONFIG_ENV_SIZE      0x20000
+# endif /* !RAMBOOT */
 #else /* !FLASH */
-       /* ENV in RAM */
-       #define CONFIG_SYS_NO_FLASH             1
-       #define CONFIG_ENV_IS_NOWHERE   1
-       #define CONFIG_ENV_SIZE         0x1000
-       #define CONFIG_ENV_ADDR         (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
-       #define CONFIG_SYS_FLASH_PROTECTION             /* hardware flash protection */
+/* ENV in RAM */
+# define CONFIG_SYS_NO_FLASH   1
+# define CONFIG_ENV_IS_NOWHERE 1
+# define CONFIG_ENV_SIZE       0x1000
+# define CONFIG_ENV_ADDR       (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
+/* hardware flash protection */
+# define CONFIG_SYS_FLASH_PROTECTION
 #endif /* !FLASH */
 
 /* system ace */
 #ifdef XILINX_SYSACE_BASEADDR
-       #define CONFIG_SYSTEMACE
-       /* #define DEBUG_SYSTEMACE */
-       #define SYSTEMACE_CONFIG_FPGA
-       #define CONFIG_SYS_SYSTEMACE_BASE       XILINX_SYSACE_BASEADDR
-       #define CONFIG_SYS_SYSTEMACE_WIDTH      XILINX_SYSACE_MEM_WIDTH
-       #define CONFIG_DOS_PARTITION
+define CONFIG_SYSTEMACE
+/* #define DEBUG_SYSTEMACE */
+define SYSTEMACE_CONFIG_FPGA
+# define CONFIG_SYS_SYSTEMACE_BASE     XILINX_SYSACE_BASEADDR
+# define CONFIG_SYS_SYSTEMACE_WIDTH    XILINX_SYSACE_MEM_WIDTH
+define CONFIG_DOS_PARTITION
 #endif
 
 #if defined(XILINX_USE_ICACHE)
-       #define CONFIG_ICACHE
+define CONFIG_ICACHE
 #else
-       #undef CONFIG_ICACHE
+undef CONFIG_ICACHE
 #endif
 
 #if defined(XILINX_USE_DCACHE)
-       #define CONFIG_DCACHE
+define CONFIG_DCACHE
 #else
-       #undef CONFIG_DCACHE
+undef CONFIG_DCACHE
 #endif
 
 /*
 #define CONFIG_CMD_ECHO
 
 #if defined(CONFIG_DCACHE) || defined(CONFIG_ICACHE)
-       #define CONFIG_CMD_CACHE
+define CONFIG_CMD_CACHE
 #else
-       #undef CONFIG_CMD_CACHE
+undef CONFIG_CMD_CACHE
 #endif
 
 #ifndef CONFIG_SYS_ENET
-       #undef CONFIG_CMD_NET
+# undef CONFIG_CMD_NET
+# undef CONFIG_NET_MULTI
 #else
-       #define CONFIG_CMD_PING
+# define CONFIG_CMD_PING
+# define CONFIG_CMD_DHCP
+# define CONFIG_NET_MULTI
 #endif
 
 #if defined(CONFIG_SYSTEMACE)
-       #define CONFIG_CMD_EXT2
-       #define CONFIG_CMD_FAT
+define CONFIG_CMD_EXT2
+define CONFIG_CMD_FAT
 #endif
 
 #if defined(FLASH)
-       #define CONFIG_CMD_ECHO
-       #define CONFIG_CMD_FLASH
-       #define CONFIG_CMD_IMLS
-       #define CONFIG_CMD_JFFS2
-
-       #if !defined(RAMENV)
-               #define CONFIG_CMD_SAVEENV
-               #define CONFIG_CMD_SAVES
-       #endif
+define CONFIG_CMD_ECHO
+define CONFIG_CMD_FLASH
+define CONFIG_CMD_IMLS
+define CONFIG_CMD_JFFS2
+
+if !defined(RAMENV)
+#  define CONFIG_CMD_SAVEENV
+#  define CONFIG_CMD_SAVES
+endif
 #else
-       #undef CONFIG_CMD_IMLS
-       #undef CONFIG_CMD_FLASH
-       #undef CONFIG_CMD_JFFS2
+undef CONFIG_CMD_IMLS
+undef CONFIG_CMD_FLASH
+undef CONFIG_CMD_JFFS2
 #endif
 
 #if defined(CONFIG_CMD_JFFS2)
 #define CONFIG_CMD_MTDPARTS    /* mtdparts command line support */
 #define CONFIG_MTD_DEVICE      /* needed for mtdparts commands */
 #define CONFIG_FLASH_CFI_MTD
-#define MTDIDS_DEFAULT         "nor0=ml401-0"
+#define MTDIDS_DEFAULT         "nor0=flash-0"
 
 /* default mtd partition table */
-#define MTDPARTS_DEFAULT       "mtdparts=ml401-0:256k(u-boot),"\
+#define MTDPARTS_DEFAULT       "mtdparts=flash-0:256k(u-boot),"\
                                "256k(env),3m(kernel),1m(romfs),"\
                                "1m(cramfs),-(jffs2)"
 #endif
 
 /* Miscellaneous configurable options */
 #define        CONFIG_SYS_PROMPT       "U-Boot-mONStR> "
-#define        CONFIG_SYS_CBSIZE       512     /* size of console buffer */
-#define        CONFIG_SYS_PBSIZE       (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) /* print buffer size */
-#define        CONFIG_SYS_MAXARGS      15      /* max number of command args */
+/* size of console buffer */
+#define        CONFIG_SYS_CBSIZE       512
+ /* print buffer size */
+#define        CONFIG_SYS_PBSIZE \
+               (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+/* max number of command args */
+#define        CONFIG_SYS_MAXARGS      15
 #define        CONFIG_SYS_LONGHELP
-#define        CONFIG_SYS_LOAD_ADDR    XILINX_RAM_START /* default load address */
+/* default load address */
+#define        CONFIG_SYS_LOAD_ADDR    XILINX_RAM_START
 
 #define        CONFIG_BOOTDELAY        -1      /* -1 disables auto-boot */
 #define        CONFIG_BOOTARGS         "root=romfs"
 
 #define        CONFIG_PREBOOT  "echo U-BOOT for ${hostname};setenv preboot;echo"
 
-#define        CONFIG_EXTRA_ENV_SETTINGS       "unlock=yes\0" /* hardware flash protection */\
-                                       "nor0=ml401-0\0"\
-                                       "mtdparts=mtdparts=ml401-0:"\
+#define        CONFIG_EXTRA_ENV_SETTINGS       "unlock=yes\0" \
+                                       "nor0=flash-0\0"\
+                                       "mtdparts=mtdparts=flash-0:"\
                                        "256k(u-boot),256k(env),3m(kernel),"\
                                        "1m(romfs),1m(cramfs),-(jffs2)\0"
 
 /* Use the HUSH parser */
 #define CONFIG_SYS_HUSH_PARSER
 #ifdef CONFIG_SYS_HUSH_PARSER
-#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+# define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
 #endif
 
 #endif /* __CONFIG_H */
index de48afd730654630f7e7fc803a2ca017feb575a0..afb2116e8e6de29a54db6bac1bc2781ae76d1af8 100644 (file)
 #include <asm/byteorder.h>
 
 #define CONFIG_SUPPORT_VFAT
+/* Maximum Long File Name length supported here is 128 UTF-16 code units */
+#define VFAT_MAXLEN_BYTES      256 /* Maximum LFN buffer in bytes */
+#define VFAT_MAXSEQ            9   /* Up to 9 of 13 2-byte UTF-16 entries */
+#define LINEAR_PREFETCH_SIZE   (SECTOR_SIZE*2) /* Prefetch buffer size */
 
 #define SECTOR_SIZE FS_BLOCK_SIZE
 
index fd94929cefab25cbb3f670e1fbdad0cbf80499ea..deb5dda5c7619c2f27235bb3fc44b927a417186c 100644 (file)
@@ -87,6 +87,7 @@ u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr);
 int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
                                        phys_addr_t compat_off);
 int fdt_alloc_phandle(void *blob);
+int fdt_add_edid(void *blob, const char *compat, unsigned char *buf);
 
 #endif /* ifdef CONFIG_OF_LIBFDT */
 #endif /* ifndef __FDT_SUPPORT_H */
diff --git a/include/led-display.h b/include/led-display.h
new file mode 100644 (file)
index 0000000..41c3744
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2005-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2010
+ * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _led_display_h_
+#define _led_display_h_
+
+/* Display Commands */
+#define DISPLAY_CLEAR  0x1 /* Clear the display */
+#define DISPLAY_HOME   0x2 /* Set cursor at home position */
+#define DISPLAY_MARK   0x4 /* Enable the decimal point led, if implemented */
+
+void display_set(int cmd);
+int display_putc(char c);
+#endif
index 16556c4798da0c41cb3fa3f91c13239d278ff6ec..3b18d7d68865c5605e817aec135de9060e6471cb 100644 (file)
@@ -208,10 +208,6 @@ struct mtd_info {
        int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
        int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
 
-       /* Power Management functions */
-       int (*suspend) (struct mtd_info *mtd);
-       void (*resume) (struct mtd_info *mtd);
-
        /* Bad block management functions */
        int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
        int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
@@ -259,7 +255,9 @@ extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 extern struct mtd_info *get_mtd_device_nm(const char *name);
 
 extern void put_mtd_device(struct mtd_info *mtd);
-
+extern void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
+                                const uint64_t length, uint64_t *len_incl_bad,
+                                int *truncated);
 /* XXX U-BOOT XXX */
 #if 0
 struct mtd_notifier {
index 68e174e310c9a780f2ee1b3d726809973843dcfd..54655626395054869396f4d4887512b5fd87a1fc 100644 (file)
@@ -154,6 +154,7 @@ struct onenand_chip {
 /*
  * OneNAND Flash Manufacturer ID Codes
  */
+#define ONENAND_MFR_NUMONYX    0x20
 #define ONENAND_MFR_SAMSUNG    0xec
 
 /**
index 2d343c7b08259c1aca6e0825bfa6b38d899a5b4f..859d6961940361372afb1e370a329aa69b32665d 100644 (file)
 #define MPC5XXX_WU_GPIO_DATA_O  (MPC5XXX_WU_GPIO + 0x000c)
 #define MPC5XXX_WU_GPIO_DATA_I  (MPC5XXX_WU_GPIO + 0x0020)
 
-/* GPIO pins */
+/* GPIO pins, for Rev.B chip */
 #define GPIO_WKUP_7            0x80000000UL
 #define GPIO_PSC6_0            0x10000000UL
 #define GPIO_PSC3_9            0x04000000UL
 #define GPIO_PSC1_4            0x01000000UL
+#define GPIO_PSC2_4            0x02000000UL
 
 #define MPC5XXX_GPIO_SIMPLE_PSC6_3   0x20000000UL
 #define MPC5XXX_GPIO_SIMPLE_PSC6_2   0x10000000UL
index 8bdf4191a6db159222e83e38ad433fc07f428122..a4524113d00e60f7f6b30acc4c4fff263fc39e62 100644 (file)
@@ -98,13 +98,16 @@ struct nand_read_options {
 typedef struct nand_read_options nand_read_options_t;
 
 struct nand_erase_options {
-       ulong length;           /* number of bytes to erase */
-       ulong offset;           /* first address in NAND to erase */
+       loff_t length;          /* number of bytes to erase */
+       loff_t offset;          /* first address in NAND to erase */
        int quiet;              /* don't display progress messages */
        int jffs2;              /* if true: format for jffs2 usage
                                 * (write appropriate cleanmarker blocks) */
        int scrub;              /* if true, really clean NAND by erasing
                                 * bad blocks (UNSAFE) */
+
+       /* Don't include skipped bad blocks in size to be erased */
+       int spread;
 };
 
 typedef struct nand_erase_options nand_erase_options_t;
index 94eedfe29dedf79688732cf6fb6a296fcc22d016..7f664193506dce3431394369504ba5507733ada2 100644 (file)
@@ -54,6 +54,8 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr);
 int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr);
 int e1000_initialize(bd_t *bis);
 int eepro100_initialize(bd_t *bis);
+int enc28j60_initialize(unsigned int bus, unsigned int cs,
+       unsigned int max_hz, unsigned int mode);
 int ep93xx_eth_initialize(u8 dev_num, int base_addr);
 int ethoc_initialize(u8 dev_num, int base_addr);
 int eth_3com_initialize (bd_t * bis);
@@ -85,9 +87,9 @@ int skge_initialize(bd_t *bis);
 int smc911x_initialize(u8 dev_num, int base_addr);
 int smc91111_initialize(u8 dev_num, int base_addr);
 int tsi108_eth_initialize(bd_t *bis);
-int uec_initialize(int index);
 int uec_standard_init(bd_t *bis);
 int uli526x_initialize(bd_t *bis);
+int xilinx_emaclite_initialize (bd_t *bis, int base_addr);
 int sh_eth_initialize(bd_t *bis);
 int dm9000_initialize(bd_t *bis);
 
index d2b7ad477916b4a03fbe6b6b439cc76456d6a9cb..482a4768a3f9afd9fa4d24b8927c615e892c561f 100644 (file)
@@ -96,11 +96,6 @@ int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp,
 
        s.zalloc = zalloc;
        s.zfree = zfree;
-#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
-       s.outcb = (cb_func)WATCHDOG_RESET;
-#else
-       s.outcb = Z_NULL;
-#endif /* CONFIG_HW_WATCHDOG */
 
        r = inflateInit2(&s, -MAX_WBITS);
        if (r != Z_OK) {
index 26e5af1d8e84bfa74fee86b90adb5d4cbed4b40b..e19484aaa07fbc7a05900f5159c58a795b251343 100644 (file)
@@ -29,6 +29,7 @@
 #include <common.h>
 #include <compiler.h>
 #include <asm/unaligned.h>
+#include <watchdog.h>
 #include "u-boot/zlib.h"
 #undef OFF                             /* avoid conflicts */
 
@@ -1075,8 +1076,7 @@ z_streamp strm;
     state->hold = 0;
     state->bits = 0;
     state->lencode = state->distcode = state->next = state->codes;
-    if (strm->outcb != Z_NULL)
-       (*strm->outcb)(Z_NULL, 0);
+    WATCHDOG_RESET();
     Tracev((stderr, "inflate: reset\n"));
     return Z_OK;
 }
@@ -1599,6 +1599,7 @@ int flush;
             strm->adler = state->check = adler32(0L, Z_NULL, 0);
             state->mode = TYPE;
         case TYPE:
+           WATCHDOG_RESET();
             if (flush == Z_BLOCK) goto inf_leave;
         case TYPEDO:
             if (state->last) {
@@ -1776,8 +1777,7 @@ int flush;
             Tracev((stderr, "inflate:       codes ok\n"));
             state->mode = LEN;
         case LEN:
-            if (strm->outcb != Z_NULL) /* for watchdog (U-Boot) */
-                (*strm->outcb)(Z_NULL, 0);
+           WATCHDOG_RESET();
             if (have >= 6 && left >= 258) {
                 RESTORE();
                 inflate_fast(strm, out);
@@ -1990,8 +1990,7 @@ z_streamp strm;
         return Z_STREAM_ERROR;
     state = (struct inflate_state FAR *)strm->state;
     if (state->window != Z_NULL) {
-       if (strm->outcb != Z_NULL)
-               (*strm->outcb)(Z_NULL, 0);
+       WATCHDOG_RESET();
        ZFREE(strm, state->window);
     }
     ZFREE(strm, strm->state);
index 4f819dd51514497cd6f9c886279adbcfea84f9d8..216d1ec959304e3660bd3f09e0207c43028e9d1e 100644 (file)
@@ -32,7 +32,7 @@ COBJS-$(CONFIG_CMD_DNS)  += dns.o
 COBJS-$(CONFIG_CMD_NET)  += eth.o
 COBJS-$(CONFIG_CMD_NET)  += net.o
 COBJS-$(CONFIG_CMD_NFS)  += nfs.o
-COBJS-$(CONFIG_CMD_NET)  += rarp.o
+COBJS-$(CONFIG_CMD_RARP) += rarp.o
 COBJS-$(CONFIG_CMD_SNTP) += sntp.o
 COBJS-$(CONFIG_CMD_NET)  += tftp.o
 
index 993306f0a47d8ed2a62a14d1006e52be41e2a191..5c70d4f3ff31018eef5be5f32dcd74ea6e02b841 100644 (file)
--- a/net/eth.c
+++ b/net/eth.c
@@ -263,7 +263,6 @@ int eth_initialize(bd_t *bis)
                        dev = dev->next;
                } while(dev != eth_devices);
 
-#ifdef CONFIG_NET_MULTI
                /* update current ethernet name */
                if (eth_current) {
                        char *act = getenv("ethact");
@@ -271,7 +270,6 @@ int eth_initialize(bd_t *bis)
                                setenv("ethact", eth_current->name);
                } else
                        setenv("ethact", NULL);
-#endif
 
                putc ('\n');
        }
@@ -441,7 +439,7 @@ int eth_receive(volatile void *packet, int length)
 void eth_try_another(int first_restart)
 {
        static struct eth_device *first_failed = NULL;
-       char *ethrotate;
+       char *ethrotate, *act;
 
        /*
         * Do not rotate between network interfaces when
@@ -460,21 +458,16 @@ void eth_try_another(int first_restart)
 
        eth_current = eth_current->next;
 
-#ifdef CONFIG_NET_MULTI
        /* update current ethernet name */
-       {
-               char *act = getenv("ethact");
-               if (act == NULL || strcmp(act, eth_current->name) != 0)
-                       setenv("ethact", eth_current->name);
-       }
-#endif
+       act = getenv("ethact");
+       if (act == NULL || strcmp(act, eth_current->name) != 0)
+               setenv("ethact", eth_current->name);
 
        if (first_failed == eth_current) {
                NetRestartWrap = 1;
        }
 }
 
-#ifdef CONFIG_NET_MULTI
 void eth_set_current(void)
 {
        static char *act = NULL;
@@ -501,7 +494,6 @@ void eth_set_current(void)
 
        setenv("ethact", eth_current->name);
 }
-#endif
 
 char *eth_get_name (void)
 {
index 33fcd90cd429ad066da1ca5ed50efef510b85663..d5a5429d1c6e03bbb2ecf78a38567d6b617e45e0 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -80,7 +80,9 @@
 #include <net.h>
 #include "bootp.h"
 #include "tftp.h"
+#ifdef CONFIG_CMD_RARP
 #include "rarp.h"
+#endif
 #include "nfs.h"
 #ifdef CONFIG_STATUS_LED
 #include <status_led.h>
@@ -401,11 +403,13 @@ restart:
                        BootpRequest ();
                        break;
 
+#if defined(CONFIG_CMD_RARP)
                case RARP:
                        RarpTry = 0;
                        NetOurIP = 0;
                        RarpRequest ();
                        break;
+#endif
 #if defined(CONFIG_CMD_PING)
                case PING:
                        PingStart();
@@ -1492,6 +1496,7 @@ NetReceive(volatile uchar * inpkt, int len)
                }
                break;
 
+#ifdef CONFIG_CMD_RARP
        case PROT_RARP:
                debug("Got RARP\n");
                arp = (ARP_t *)ip;
@@ -1515,7 +1520,7 @@ NetReceive(volatile uchar * inpkt, int len)
                        (*packetHandler)(0,0,0,0);
                }
                break;
-
+#endif
        case PROT_IP:
                debug("Got IP\n");
                /* Before we start poking the header, make sure it is there */
@@ -1729,10 +1734,12 @@ static int net_check_prereq (proto_t protocol)
                }
                /* Fall through */
 
-       case DHCP:
+#ifdef CONFIG_CMD_RARP
        case RARP:
+#endif
        case BOOTP:
        case CDP:
+       case DHCP:
                if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
 #ifdef CONFIG_NET_MULTI
                        extern int eth_get_dev_index (void);
index 840727707189a6fcea132f64573ff210123d558e..0caa397b20df30cf8f3c6706909cb3aa59354766 100644 (file)
@@ -67,7 +67,7 @@ $(obj)imls:   $(obj)imls.o $(obj)crc32.o $(obj)image.o $(obj)md5.o \
        $(CC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
        $(STRIP) $@
 
-# Some files complain if compiled with -pedantic, use FIT_CFLAGS
+# Some files complain if compiled with -pedantic, use HOSTCFLAGS_NOPED
 $(obj)image.o: $(SRCTREE)/common/image.c
        $(CC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<