summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwdenk <wdenk>2002-11-03 00:30:25 +0000
committerwdenk <wdenk>2002-11-03 00:30:25 +0000
commitf9087a3213cc245cf9b90436475b5af822bd7579 (patch)
treec714f776028c8d662c4c876e0b41029238ce1e36
parentc609719b8d1b2dca590e0ed499016d041203e403 (diff)
downloadbootable_bootloader_goldelico_gta04-f9087a3213cc245cf9b90436475b5af822bd7579.zip
bootable_bootloader_goldelico_gta04-f9087a3213cc245cf9b90436475b5af822bd7579.tar.gz
bootable_bootloader_goldelico_gta04-f9087a3213cc245cf9b90436475b5af822bd7579.tar.bz2
Initial revision
-rw-r--r--board/RRvision/flash.c522
-rw-r--r--board/bmw/Makefile43
-rw-r--r--board/bmw/README340
-rw-r--r--board/bmw/m48t59y.c323
-rw-r--r--board/csb226/config.mk16
-rw-r--r--board/csb226/flash.c364
6 files changed, 1608 insertions, 0 deletions
diff --git a/board/RRvision/flash.c b/board/RRvision/flash.c
new file mode 100644
index 0000000..06f7c4b
--- /dev/null
+++ b/board/RRvision/flash.c
@@ -0,0 +1,522 @@
+/*
+ * (C) Copyright 2000-2002
+ * 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
+ */
+
+#define DEBUG
+
+#include <common.h>
+#include <mpc8xx.h>
+
+#ifndef CFG_ENV_ADDR
+#define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
+#endif
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ unsigned long size;
+ int i;
+
+ /* Init: no FLASHes known */
+ for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ }
+
+ /* Static FLASH Bank configuration here - FIXME XXX */
+
+ size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+ if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+ printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+ size, size<<20);
+ }
+
+ /* Remap FLASH according to real size */
+ memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size & OR_AM_MSK);
+ memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
+
+ /* Re-do sizing to get full correct info */
+ size = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+ /* monitor protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+ &flash_info[0]);
+#endif
+
+#ifdef CFG_ENV_IS_IN_FLASH
+ /* ENV protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR+CFG_ENV_SIZE-1,
+ &flash_info[0]);
+#endif
+
+ flash_info[0].size = size;
+
+ return (size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t *info)
+{
+ int i;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ puts ("missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD: puts ("AMD "); break;
+ case FLASH_MAN_FUJ: puts ("FUJITSU "); break;
+ default: puts ("Unknown Vendor "); break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM400B: puts ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM400T: puts ("AM29LV400T (4 Mbit, top boot sector)\n");
+ break;
+ case FLASH_AM800B: puts ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM800T: puts ("AM29LV800T (8 Mbit, top boot sector)\n");
+ break;
+ case FLASH_AM160B: puts ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM160T: puts ("AM29LV160T (16 Mbit, top boot sector)\n");
+ break;
+ case FLASH_AM320B: puts ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM320T: puts ("AM29LV320T (32 Mbit, top boot sector)\n");
+ break;
+ default: puts ("Unknown Chip Type\n");
+ break;
+ }
+
+ printf (" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+
+ puts (" Sector Start Addresses:");
+ for (i=0; i<info->sector_count; ++i) {
+ if ((i % 5) == 0)
+ puts ("\n ");
+ printf (" %08lX%s",
+ info->start[i],
+ info->protect[i] ? " (RO)" : " "
+ );
+ }
+ puts ("\n");
+ return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+ short i;
+ ulong value;
+ ulong base = (ulong)addr;
+
+ /* Write auto select command: read Manufacturer ID */
+ addr[0x0555] = 0x00AA00AA;
+ addr[0x02AA] = 0x00550055;
+ addr[0x0555] = 0x00900090;
+
+ value = addr[0];
+
+ switch (value) {
+ case AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+ case FUJ_MANUFACT:
+ info->flash_id = FLASH_MAN_FUJ;
+ break;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return (0); /* no or unknown flash */
+ }
+
+ value = addr[1]; /* device ID */
+
+ switch (value) {
+ case AMD_ID_LV400T:
+ info->flash_id += FLASH_AM400T;
+ info->sector_count = 11;
+ info->size = 0x00100000;
+ break; /* => 1 MB */
+
+ case AMD_ID_LV400B:
+ info->flash_id += FLASH_AM400B;
+ info->sector_count = 11;
+ info->size = 0x00100000;
+ break; /* => 1 MB */
+
+ case AMD_ID_LV800T:
+ info->flash_id += FLASH_AM800T;
+ info->sector_count = 19;
+ info->size = 0x00200000;
+ break; /* => 2 MB */
+
+ case AMD_ID_LV800B:
+ info->flash_id += FLASH_AM800B;
+ info->sector_count = 19;
+ info->size = 0x00200000;
+ break; /* => 2 MB */
+
+ case AMD_ID_LV160T:
+ info->flash_id += FLASH_AM160T;
+ info->sector_count = 35;
+ info->size = 0x00400000;
+ break; /* => 4 MB */
+
+ case AMD_ID_LV160B:
+ info->flash_id += FLASH_AM160B;
+ info->sector_count = 35;
+ info->size = 0x00400000;
+ break; /* => 4 MB */
+ case AMD_ID_LV320T:
+ info->flash_id += FLASH_AM320T;
+ info->sector_count = 71;
+ info->size = 0x00800000;
+ break; /* => 8 MB */
+
+ case AMD_ID_LV320B:
+ info->flash_id += FLASH_AM320B;
+ info->sector_count = 71;
+ info->size = 0x00800000;
+ break; /* => 8 MB */
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ return (0); /* => no or unknown flash */
+ }
+
+ /* set up sector start address table */
+ switch (value) {
+ case AMD_ID_LV400B:
+ case AMD_ID_LV800B:
+ case AMD_ID_LV160B:
+ /* set sector offsets for bottom boot block type */
+ info->start[0] = base + 0x00000000;
+ info->start[1] = base + 0x00008000;
+ info->start[2] = base + 0x0000C000;
+ info->start[3] = base + 0x00010000;
+ for (i = 4; i < info->sector_count; i++) {
+ info->start[i] = base + (i * 0x00020000) - 0x00060000;
+ }
+ break;
+ case AMD_ID_LV400T:
+ case AMD_ID_LV800T:
+ case AMD_ID_LV160T:
+ /* set sector offsets for top boot block type */
+ i = info->sector_count - 1;
+ info->start[i--] = base + info->size - 0x00008000;
+ info->start[i--] = base + info->size - 0x0000C000;
+ info->start[i--] = base + info->size - 0x00010000;
+ for (; i >= 0; i--) {
+ info->start[i] = base + i * 0x00020000;
+ }
+ break;
+ case AMD_ID_LV320B:
+ for (i = 0; i < info->sector_count; i++) {
+ info->start[i] = base;
+ /*
+ * The first 8 sectors are 8 kB,
+ * all the other ones are 64 kB
+ */
+ base += (i < 8)
+ ? 2 * ( 8 << 10)
+ : 2 * (64 << 10);
+ }
+ break;
+ case AMD_ID_LV320T:
+ for (i = 0; i < info->sector_count; i++) {
+ info->start[i] = base;
+ /*
+ * The last 8 sectors are 8 kB,
+ * all the other ones are 64 kB
+ */
+ base += (i < (info->sector_count - 8))
+ ? 2 * (64 << 10)
+ : 2 * ( 8 << 10);
+ }
+ break;
+ default:
+ return (0);
+ break;
+ }
+
+ /* check for protected sectors */
+ for (i = 0; i < info->sector_count; i++) {
+ /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+ /* D0 = 1 if protected */
+ addr = (volatile unsigned long *)(info->start[i]);
+ info->protect[i] = addr[2] & 1;
+ }
+
+ /*
+ * Prevent writes to uninitialized FLASH.
+ */
+ if (info->flash_id != FLASH_UNKNOWN) {
+ addr = (volatile unsigned long *)info->start[0];
+
+ *addr = 0x00F000F0; /* reset bank */
+ }
+
+ return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ vu_long *addr = (vu_long*)(info->start[0]);
+ int flag, prot, sect, l_sect;
+ ulong start, now, last;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN) {
+ puts ("- missing\n");
+ } else {
+ puts ("- no sectors to erase\n");
+ }
+ return 1;
+ }
+
+ if ((info->flash_id == FLASH_UNKNOWN) ||
+ (info->flash_id > FLASH_AMD_COMP)) {
+ printf ("Can't erase unknown flash type %08lx - aborted\n",
+ info->flash_id);
+ return 1;
+ }
+
+ prot = 0;
+ for (sect=s_first; sect<=s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+
+ if (prot) {
+ printf ("- Warning: %d protected sectors will not be erased!\n",
+ prot);
+ } else {
+ puts ("\n");
+ }
+
+ l_sect = -1;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr[0x0555] = 0x00AA00AA;
+ addr[0x02AA] = 0x00550055;
+ addr[0x0555] = 0x00800080;
+ addr[0x0555] = 0x00AA00AA;
+ addr[0x02AA] = 0x00550055;
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect<=s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ addr = (vu_long*)(info->start[sect]);
+ addr[0] = 0x00300030;
+ l_sect = sect;
+ }
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ /*
+ * We wait for the last triggered sector
+ */
+ if (l_sect < 0)
+ goto DONE;
+
+ start = get_timer (0);
+ last = start;
+ addr = (vu_long*)(info->start[l_sect]);
+ while ((addr[0] & 0x00800080) != 0x00800080) {
+ if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+ puts ("Timeout\n");
+ return 1;
+ }
+ /* show that we're waiting */
+ if ((now - last) > 1000) { /* every second */
+ putc ('.');
+ last = now;
+ }
+ }
+
+DONE:
+ /* reset to read mode */
+ addr = (volatile unsigned long *)info->start[0];
+ addr[0] = 0x00F000F0; /* reset bank */
+
+ puts (" done\n");
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ ulong cp, wp, data;
+ int i, l, rc;
+
+ wp = (addr & ~3); /* get lower word aligned address */
+
+ /*
+ * handle unaligned start bytes
+ */
+ if ((l = addr - wp) != 0) {
+ data = 0;
+ for (i=0, cp=wp; i<l; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+ for (; i<4 && cnt>0; ++i) {
+ data = (data << 8) | *src++;
+ --cnt;
+ ++cp;
+ }
+ for (; cnt==0 && i<4; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 4;
+ }
+
+ /*
+ * handle word aligned part
+ */
+ while (cnt >= 4) {
+ data = 0;
+ for (i=0; i<4; ++i) {
+ data = (data << 8) | *src++;
+ }
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 4;
+ cnt -= 4;
+ }
+
+ if (cnt == 0) {
+ return (0);
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ data = 0;
+ for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+ data = (data << 8) | *src++;
+ --cnt;
+ }
+ for (; i<4; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+
+ return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+ vu_long *addr = (vu_long*)(info->start[0]);
+ ulong start;
+ int flag;
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*((vu_long *)dest) & data) != data) {
+ return (2);
+ }
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr[0x0555] = 0x00AA00AA;
+ addr[0x02AA] = 0x00550055;
+ addr[0x0555] = 0x00A000A0;
+
+ *((vu_long *)dest) = data;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* data polling for D7 */
+ start = get_timer (0);
+ while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/bmw/Makefile b/board/bmw/Makefile
new file mode 100644
index 0000000..46fe791
--- /dev/null
+++ b/board/bmw/Makefile
@@ -0,0 +1,43 @@
+#
+# (C) Copyright 2002
+# James F. Dougherty, Broadcom Corporation, jfd@broadcom.com
+# 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 = lib$(BOARD).a
+
+OBJS = $(BOARD).o flash.o ns16550.o serial.o m48t59y.o
+
+SOBJS = early_init.o
+
+$(LIB): .depend $(OBJS) $(SOBJS)
+ $(AR) crv $@ $^
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/bmw/README b/board/bmw/README
new file mode 100644
index 0000000..55ef56e
--- /dev/null
+++ b/board/bmw/README
@@ -0,0 +1,340 @@
+Broadcom 95xx BMW CPCI Platform
+
+Overview
+=========
+BMW is an MPC8245 system controller featuring:
+* 3U CPCI Form Factor
+* BCM5703 Gigabit Ethernet
+* M48T59Y NVRAM
+* 16MB DOC
+* DIP Socket for Socketed DOC up to 1GB
+* 64MB SDRAM
+* LCD Display
+* Configurable Jumper options for 66,85, and 100Mhz memory bus
+
+
+BMW System Address Map
+======================
+BMW uses the MPC8245 CHRP Address MAP B found in the MPC8245 Users Manual
+(P.121, Section 3.1 Address Maps, Address Map B). Other I/O devices found
+onboard the processor module are listed briefly below:
+
+0x00000000 - 0x40000000 - 64MB SDRAM SIMM
+ (Unregistered PC-100 SDRAM DIMM Module)
+
+0xFF000000 - 0xFF001FFF - M-Systems DiskOnChip (TM) 2000
+ TSOP 16MB (MD2211-D16-V3)
+
+0x70000000 - 0x70001FFF - M-Systems DiskOnChip (TM) 2000
+ DIP32 (Socketed 16MB - 1GB ) *
+ NOTE: this is not populated on all systems.
+
+0x7c000000 - 0x7c000000 - Reset Register
+ (Write 0 to reset)
+
+0x7c000001 - 0x7c000001 - System LED
+ (Clear Bit 7 to turn on, set to shut off)
+
+0x7c000002 - 0x7c000002 - M48T59 Watchdog IRQ3
+ (Clear bit 7 to reset, set to assert IRQ3)
+
+0x7c000003 - 0x7c000003 - M48T59 Write-Protect Register
+ (Clear bit 7 to make R/W, set to make R/O)
+
+0x7c002000 - 0x7c002003 - Infineon OSRAM DLR2416 4 Character
+ 5x7 Dot Matrix Alphanumeric Display
+ (Each byte sets the appropriate character)
+
+0x7c004000 - 0x7c005FF0 - SGS-THOMSON M48T59Y 8K NVRAM/RTC
+ NVRAM Memory Region
+
+0x7c005FF0 - 0x7c005FFF - SGS-THOMSON M48T59Y 8K NVRAM/RTC
+ Realtime Clock Registers
+
+0xFFF00000 - 0xFFF80000 - 512K PLCC32 BootRom
+ (AMD AM29F040, ST 29W040B)
+
+0xFFF00100 - System Reset Vector
+
+
+IO/MMU (BAT) Configuration
+======================
+The following Block-Address-Translation (BAT) configuration
+is recommended to access all I/O devices.
+
+#define CFG_IBAT0L (0x00000000 | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U (0x00000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT1L (0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT1U (0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L CFG_IBAT0L
+#define CFG_DBAT0U CFG_IBAT0U
+#define CFG_DBAT1L CFG_IBAT1L
+#define CFG_DBAT1U CFG_IBAT1U
+#define CFG_DBAT2L CFG_IBAT2L
+#define CFG_DBAT2U CFG_IBAT2U
+#define CFG_DBAT3L CFG_IBAT3L
+#define CFG_DBAT3U CFG_IBAT3U
+
+
+Interrupt Mappings
+======================
+BMW uses MPC8245 discrete mode interrupts. With the following
+hardwired mappings:
+
+BCM5701 10/100/1000 Ethernet IRQ1
+CompactPCI Interrupt A IRQ2
+RTC/Watchdog Interrupt IRQ3
+Internal NS16552 UART IRQ4
+
+
+Jumper Settings
+======================
+
+BMW has a jumper (JP600) for selecting 66, 85, or 100Mhz memory bus.
+A jumper (X) is a 0 bit.
+
+Hence 66= 10110
+ 85= 11000
+ 100= 10000
+
+Jumper Settings for various Speeds
+=======================
+J1 J2 J3 J4 J5
+ X X 66Mhz
+=======================
+J1 J2 J3 J4 J5
+ X X X 85Mhz
+=======================
+J1 J2 J3 J4 J5
+ X X X X 100Mhz
+=======================
+
+Obviously, 100Mhz memory bus is recommended for optimum performance.
+
+
+U-Boot
+===============
+Broadcom BMW board is supported under config_BWM option.
+Supported features:
+
+- NVRAM setenv/getenv (used by Linux Kernel for configuration variables)
+- BCM570x TFTP file transfer support
+- LCD Display Support
+- DOC Support - (underway)
+
+
+
+U-Boot 1.2.0 (Aug 6 2002 - 17:44:48)
+
+CPU: MPC8245 Revision 16.20 at 264 MHz: 16 kB I-Cache 16 kB D-Cache
+Board: BMW MPC8245/KAHLUA2 - CHRP (MAP B)
+Built: Aug 6 2002 at 17:44:37
+Local Bus at 66 MHz
+DRAM: 64 MB
+FLASH: 4095 MB
+In: serial
+Out: serial
+Err: serial
+DOC: No DiskOnChip found
+Hit any key to stop autoboot: 0
+=>printenv
+bootdelay=5
+baudrate=9600
+clocks_in_mhz=1
+hostname=switch-2
+bootcmd=tftp 100000 vmlinux.img;bootm
+gateway=10.16.64.1
+ethaddr=00:00:10:18:10:10
+nfsroot=172.16.40.111:/boot/root-fs
+filesize=5ec8c
+netmask=255.255.240.0
+ipaddr=172.16.40.114
+serverip=172.16.40.111
+root=/dev/nfs
+stdin=serial
+stdout=serial
+stderr=serial
+
+Environment size: 315/8172 bytes
+=>boot
+
+
+
+
+
+
+
+DevTools
+========
+ELDK
+ DENX Embedded Linux Development Kit
+
+ROM Emulator
+ Grammar Engine PROMICE P1160-90-AI21E (2MBx8bit, 90ns access time)
+ Grammar Engine PL32E 32Pin PLCC Emulation cables
+ Grammar Engine 3VA8CON (3Volt adapter with Short cables)
+ Grammar Engine FPNET PromICE Ethernet Adapters
+
+ICE
+ WRS/EST VisionICE-II (PPC8240)
+
+
+
+=>reset
+
+
+U-Boot 1.2.0 (Aug 6 2002 - 17:44:48)
+
+CPU: MPC8245 Revision 16.20 at 264 MHz: 16 kB I-Cache 16 kB D-Cache
+Board: BMW MPC8245/KAHLUA2 - CHRP (MAP B)
+Built: Aug 6 2002 at 17:44:37
+Local Bus at 66 MHz
+DRAM: 64 MB
+FLASH: 4095 MB
+In: serial
+Out: serial
+Err: serial
+DOC: No DiskOnChip found
+Hit any key to stop autoboot: 0
+
+Broadcom BCM5701 1000Base-T: bus 0, device 13, function 0: MBAR=0x80100000
+BCM570x PCI Memory base address @0x80100000
+eth0:Broadcom BCM5701 1000Base-T: 100 Mbps half duplex link up, flow control OFF
+eth0: Broadcom BCM5701 1000Base-T @0x80100000,node addr 000010181010
+eth0: BCM5700 with Broadcom BCM5701 Integrated Copper transceiver found
+eth0: 32-bit PCI 33MHz, MTU: 1500,Rx Checksum ON
+ARP broadcast 1
+TFTP from server 172.16.40.111; our IP address is 172.16.40.114
+Filename 'vmlinux.img'.
+Load address: 0x100000
+Loading: #################################################################
+ ####################################T #############################
+ ######################
+done
+Bytes transferred = 777199 (bdbef hex)
+
+eth0:Broadcom BCM5701 1000Base-T,HALT,POWER DOWN,done - offline.
+## Booting image at 00100000 ...
+ Image Name: vmlinux.bin.gz
+ Created: 2002-08-06 6:30:13 UTC
+ Image Type: PowerPC Linux Kernel Image (gzip compressed)
+ Data Size: 777135 Bytes = 758 kB = 0 MB
+ Load Address: 00000000
+ Entry Point: 00000000
+ Verifying Checksum ... OK
+ Uncompressing Kernel Image ... OK
+Memory BAT mapping: BAT2=64Mb, BAT3=0Mb, residual: 0Mb
+Linux version 2.4.19-rc3 (jfd@que) (gcc version 2.95.3 20010111 (prerelease/franzo/20010111)) #168 Mon Aug 5 23:29:20 PDT 2002
+CPU:82xx: 32 I-Cache Block Size, 32 D-Cache Block Size PVR: 0x810000
+U-Boot Environment: 0xc01b08f0
+IP PNP: 802.3 Ethernet Address=<0:0:10:18:10:10>
+cpu0: MPC8245/KAHLUA-II : BMW Platform : 64MB RAM: BPLD Rev. 6e
+NOTICE: mounting root file system via NFS
+IP PNP: switch-2: eth0 IP 172.16.40.114/255.255.240.0 gateway 10.16.64.1 server 172.16.40.111
+On node 0 totalpages: 16384
+zone(0): 16384 pages.
+zone(1): 0 pages.
+zone(2): 0 pages.
+Kernel command line: console=ttyS0,9600 ip=172.16.40.114:172.16.40.111:10.16.64.1:255.255.240.0:switch-2:eth0 root=/dev/nfs rw nfsroot=172.16.40.111:/boot/root-fs,timeo=200,retrans=500 nfsaddrs=172.16.40.114:172.16.40.111
+root_dev_setup:/dev/nfs or 00:ff
+time_init: decrementer frequency = 16.501145 MHz
+Calibrating delay loop... 175.71 BogoMIPS
+Memory: 62572k available (1396k kernel code, 436k data, 100k init, 0k highmem)
+Dentry cache hash table entries: 8192 (order: 4, 65536 bytes)
+Inode cache hash table entries: 4096 (order: 3, 32768 bytes)
+Mount-cache hash table entries: 1024 (order: 1, 8192 bytes)
+Buffer-cache hash table entries: 4096 (order: 2, 16384 bytes)
+Page-cache hash table entries: 16384 (order: 4, 65536 bytes)
+POSIX conformance testing by UNIFIX
+PCI: Probing PCI hardware
+Linux NET4.0 for Linux 2.4
+Based upon Swansea University Computer Society NET3.039
+Initializing RT netlink socket
+Starting kswapd
+devfs: v1.12a (20020514) Richard Gooch (rgooch@atnf.csiro.au)
+devfs: devfs_debug: 0x0
+devfs: boot_options: 0x1
+Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
+pty: 256 Unix98 ptys configured
+Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI enabled
+Testing ttyS0 (0xf7f51500, 0xf7f51500)...
+Testing ttyS1 (0xfc004600, 0xfc004600)...
+ttyS00 at 0xf7f51500 (irq = 24) is a ST16650
+ttyS01 at 0xfc004600 (irq = 25) is a 16550A
+Real Time Clock Driver v1.10e
+RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
+loop: loaded (max 8 devices)
+TFFS 5.1.1 Flash disk driver for DiskOnChip
+Copyright (C) 1998,2001 M-Systems Flash Disk Pioneers Ltd.
+DOC device(s) found: 1
+fl_init: registered device at major: 100
+fl_geninit: registered device at major: 100
+Partition check:
+ fla: p1
+partition: /dev/fl/0: start_sect: 0,nr_sects: 32000 Fl_blk_size[]: 16000KB
+partition: /dev/fl/1: start_sect: 2,nr_sects: 31998 Fl_blk_size[]: 15999KB
+partition: /dev/fl/2: start_sect: 0,nr_sects: 0 Fl_blk_size[]: 0KB
+partition: /dev/fl/3: start_sect: 0,nr_sects: 0 Fl_blk_size[]: 0KB
+Broadcom Gigabit Ethernet Driver bcm5700 ver. 3.0.7 (07/17/02)
+eth0: Broadcom BCM5701 found at mem bfff0000, IRQ 1, node addr 000010181010
+eth0: Broadcom BCM5701 Integrated Copper transceiver found
+eth0: Scatter-gather ON, 64-bit DMA ON, Tx Checksum ON, Rx Checksum ON, 802.1Q VLAN ON
+bond0 registered without MII link monitoring, in bonding mode.
+rtc: unable to get misc minor
+NET4: Linux TCP/IP 1.0 for NET4.0
+IP Protocols: ICMP, UDP, TCP, IGMP
+IP: routing cache hash table of 512 buckets, 4Kbytes
+TCP: Hash tables configured (established 4096 bind 4096)
+bcm5700: eth0 NIC Link is UP, 100 Mbps half duplex
+IP-Config: Gateway not on directly connected network.
+NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
+802.1Q VLAN Support v1.7 Ben Greear <greearb@candelatech.com>
+All bugs added by David S. Miller <davem@redhat.com>
+Looking up port of RPC 100003/2 on 172.16.40.111
+Looking up port of RPC 100005/1 on 172.16.40.111
+VFS: Mounted root (nfs filesystem).
+Mounted devfs on /dev
+Freeing unused kernel memory: 100k init
+INIT: version 2.78 booting
+Mounting local filesystems...
+not mounted anything
+Setting up symlinks in /dev...done.
+Setting up extra devices in /dev...done.
+Starting devfsd...Started device management daemon for /dev
+INIT: Entering runlevel: 2
+Starting internet superserver: inetd.
+
+
+Welcome to Linux/PPC
+MPC8245/BMW
+
+
+
+switch-2 login: root
+Password:
+PAM_unix[49]: (login) session opened for user root by LOGIN(uid=0)
+Last login: Thu Nov 25 11:51:14 1920 on console
+
+
+Welcome to Linux/PPC
+MPC8245/BMW
+
+
+
+login[49]: ROOT LOGIN on `console'
+
+root@switch-2:~# cat /proc/cpuinfo
+cpu : 82xx
+revision : 16.20 (pvr 8081 1014)
+bogomips : 175.71
+vendor : Broadcom
+machine : BMW/MPC8245
+root@switch-2:~#
diff --git a/board/bmw/m48t59y.c b/board/bmw/m48t59y.c
new file mode 100644
index 0000000..469f1ad
--- /dev/null
+++ b/board/bmw/m48t59y.c
@@ -0,0 +1,323 @@
+/*
+ * SGS M48-T59Y TOD/NVRAM Driver
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp.
+ *
+ * (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp.
+ *
+ * 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
+ */
+
+/*
+ * SGS M48-T59Y TOD/NVRAM Driver
+ *
+ * The SGS M48 an 8K NVRAM starting at offset M48_BASE_ADDR and
+ * continuing for 8176 bytes. After that starts the Time-Of-Day (TOD)
+ * registers which are used to set/get the internal date/time functions.
+ *
+ * This module implements Y2K compliance by taking full year numbers
+ * and translating back and forth from the TOD 2-digit year.
+ *
+ * NOTE: for proper interaction with an operating system, the TOD should
+ * be used to store Universal Coordinated Time (GMT) and timezone
+ * conversions should be used.
+ *
+ * Here is a diagram of the memory layout:
+ *
+ * +---------------------------------------------+ 0xffe0a000
+ * | Non-volatile memory | .
+ * | | .
+ * | (8176 bytes of Non-volatile memory) | .
+ * | | .
+ * +---------------------------------------------+ 0xffe0bff0
+ * | Flags |
+ * +---------------------------------------------+ 0xffe0bff1
+ * | Unused |
+ * +---------------------------------------------+ 0xffe0bff2
+ * | Alarm Seconds |
+ * +---------------------------------------------+ 0xffe0bff3
+ * | Alarm Minutes |
+ * +---------------------------------------------+ 0xffe0bff4
+ * | Alarm Date |
+ * +---------------------------------------------+ 0xffe0bff5
+ * | Interrupts |
+ * +---------------------------------------------+ 0xffe0bff6
+ * | WatchDog |
+ * +---------------------------------------------+ 0xffe0bff7
+ * | Calibration |
+ * +---------------------------------------------+ 0xffe0bff8
+ * | Seconds |
+ * +---------------------------------------------+ 0xffe0bff9
+ * | Minutes |
+ * +---------------------------------------------+ 0xffe0bffa
+ * | Hours |
+ * +---------------------------------------------+ 0xffe0bffb
+ * | Day |
+ * +---------------------------------------------+ 0xffe0bffc
+ * | Date |
+ * +---------------------------------------------+ 0xffe0bffd
+ * | Month |
+ * +---------------------------------------------+ 0xffe0bffe
+ * | Year (2 digits only) |
+ * +---------------------------------------------+ 0xffe0bfff
+ */
+#include <common.h>
+#include <rtc.h>
+#include "bmw.h"
+
+/*
+ * Imported from mousse.h:
+ *
+ * TOD_REG_BASE Base of m48t59y TOD registers
+ * SYS_TOD_UNPROTECT() Disable NVRAM write protect
+ * SYS_TOD_PROTECT() Re-enable NVRAM write protect
+ */
+
+#define YEAR 0xf
+#define MONTH 0xe
+#define DAY 0xd
+#define DAY_OF_WEEK 0xc
+#define HOUR 0xb
+#define MINUTE 0xa
+#define SECOND 0x9
+#define CONTROL 0x8
+#define WATCH 0x7
+#define INTCTL 0x6
+#define WD_DATE 0x5
+#define WD_HOUR 0x4
+#define WD_MIN 0x3
+#define WD_SEC 0x2
+#define _UNUSED 0x1
+#define FLAGS 0x0
+
+#define M48_ADDR ((volatile unsigned char *) TOD_REG_BASE)
+
+int m48_tod_init(void)
+{
+ SYS_TOD_UNPROTECT();
+
+ M48_ADDR[CONTROL] = 0;
+ M48_ADDR[WATCH] = 0;
+ M48_ADDR[INTCTL] = 0;
+
+ /*
+ * If the oscillator is currently stopped (as on a new part shipped
+ * from the factory), start it running.
+ *
+ * Here is an example of the TOD bytes on a brand new M48T59Y part:
+ * 00 00 00 00 00 00 00 00 00 88 8c c3 bf c8 f5 01
+ */
+
+ if (M48_ADDR[SECOND] & 0x80)
+ M48_ADDR[SECOND] = 0;
+
+ /* Is battery low */
+ if ( M48_ADDR[FLAGS] & 0x10) {
+ printf("NOTICE: Battery low on Real-Time Clock (replace SNAPHAT).\n");
+ }
+
+ SYS_TOD_PROTECT();
+
+ return 0;
+}
+
+/*
+ * m48_tod_set
+ */
+
+static int to_bcd(int value)
+{
+ return value / 10 * 16 + value % 10;
+}
+
+static int from_bcd(int value)
+{
+ return value / 16 * 10 + value % 16;
+}
+
+static int day_of_week(int y, int m, int d) /* 0-6 ==> Sun-Sat */
+{
+ static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
+ y -= m < 3;
+ return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
+}
+
+/*
+ * Note: the TOD should store the current GMT
+ */
+
+int m48_tod_set(int year, /* 1980-2079 */
+ int month, /* 01-12 */
+ int day, /* 01-31 */
+ int hour, /* 00-23 */
+ int minute, /* 00-59 */
+ int second) /* 00-59 */
+
+{
+ SYS_TOD_UNPROTECT();
+
+ M48_ADDR[CONTROL] |= 0x80; /* Set WRITE bit */
+
+ M48_ADDR[YEAR] = to_bcd(year % 100);
+ M48_ADDR[MONTH] = to_bcd(month);
+ M48_ADDR[DAY] = to_bcd(day);
+ M48_ADDR[DAY_OF_WEEK] = day_of_week(year, month, day) + 1;
+ M48_ADDR[HOUR] = to_bcd(hour);
+ M48_ADDR[MINUTE] = to_bcd(minute);
+ M48_ADDR[SECOND] = to_bcd(second);
+
+ M48_ADDR[CONTROL] &= ~0x80; /* Clear WRITE bit */
+
+ SYS_TOD_PROTECT();
+
+ return 0;
+}
+
+/*
+ * Note: the TOD should store the current GMT
+ */
+
+int m48_tod_get(int *year, /* 1980-2079 */
+ int *month, /* 01-12 */
+ int *day, /* 01-31 */
+ int *hour, /* 00-23 */
+ int *minute, /* 00-59 */
+ int *second) /* 00-59 */
+{
+ int y;
+
+ SYS_TOD_UNPROTECT();
+
+ M48_ADDR[CONTROL] |= 0x40; /* Set READ bit */
+
+ y = from_bcd(M48_ADDR[YEAR]);
+ *year = y < 80 ? 2000 + y : 1900 + y;
+ *month = from_bcd(M48_ADDR[MONTH]);
+ *day = from_bcd(M48_ADDR[DAY]);
+ /* day_of_week = M48_ADDR[DAY_OF_WEEK] & 0xf; */
+ *hour = from_bcd(M48_ADDR[HOUR]);
+ *minute = from_bcd(M48_ADDR[MINUTE]);
+ *second = from_bcd(M48_ADDR[SECOND] & 0x7f);
+
+ M48_ADDR[CONTROL] &= ~0x40; /* Clear READ bit */
+
+ SYS_TOD_PROTECT();
+
+ return 0;
+}
+
+int m48_tod_get_second(void)
+{
+ return from_bcd(M48_ADDR[SECOND] & 0x7f);
+}
+
+/*
+ * Watchdog function
+ *
+ * If usec is 0, the watchdog timer is disarmed.
+ *
+ * If usec is non-zero, the watchdog timer is armed (or re-armed) for
+ * approximately usec microseconds (if the exact requested usec is
+ * not supported by the chip, the next higher available value is used).
+ *
+ * Minimum watchdog timeout = 62500 usec
+ * Maximum watchdog timeout = 124 sec (124000000 usec)
+ */
+
+void m48_watchdog_arm(int usec)
+{
+ int mpy, res;
+
+ SYS_TOD_UNPROTECT();
+
+ if (usec == 0) {
+ res = 0;
+ mpy = 0;
+ } else if (usec < 2000000) { /* Resolution: 1/16s if below 2s */
+ res = 0;
+ mpy = (usec + 62499) / 62500;
+ } else if (usec < 8000000) { /* Resolution: 1/4s if below 8s */
+ res = 1;
+ mpy = (usec + 249999) / 250000;
+ } else if (usec < 32000000) { /* Resolution: 1s if below 32s */
+ res = 2;
+ mpy = (usec + 999999) / 1000000;
+ } else { /* Resolution: 4s up to 124s */
+ res = 3;
+ mpy = (usec + 3999999) / 4000000;
+ if (mpy > 31)
+ mpy = 31;
+ }
+
+ M48_ADDR[WATCH] = (0x80 | /* Steer to RST signal (IRQ = N/C) */
+ mpy << 2 |
+ res);
+
+ SYS_TOD_PROTECT();
+}
+
+/*
+ * U-Boot RTC support.
+ */
+void
+rtc_get( struct rtc_time *tmp )
+{
+ m48_tod_get(&tmp->tm_year,
+ &tmp->tm_mon,
+ &tmp->tm_mday,
+ &tmp->tm_hour,
+ &tmp->tm_min,
+ &tmp->tm_sec);
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+
+#ifdef RTC_DEBUG
+ printf( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
+#endif
+}
+
+void
+rtc_set( struct rtc_time *tmp )
+{
+ m48_tod_set(tmp->tm_year, /* 1980-2079 */
+ tmp->tm_mon, /* 01-12 */
+ tmp->tm_mday, /* 01-31 */
+ tmp->tm_hour, /* 00-23 */
+ tmp->tm_min, /* 00-59 */
+ tmp->tm_sec); /* 00-59 */
+
+#ifdef RTC_DEBUG
+ printf( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+#endif
+
+}
+
+void
+rtc_reset (void)
+{
+ m48_tod_init();
+}
+
diff --git a/board/csb226/config.mk b/board/csb226/config.mk
new file mode 100644
index 0000000..939ffff
--- /dev/null
+++ b/board/csb226/config.mk
@@ -0,0 +1,16 @@
+#
+# Linux-Kernel is expected to be at c000'8000, entry c000'8000
+#
+# we load ourself to c170'0000, the upper 1 MB of second bank
+#
+# download areas is c800'0000
+#
+
+# This is the address where U-Boot lives in flash:
+#TEXT_BASE = 0
+
+# FIXME: armboot does only work correctly when being compiled
+# for the addresses _after_ relocation to RAM!! Otherwhise the
+# .bss segment is assumed in flash...
+TEXT_BASE = 0xa1fe0000
+
diff --git a/board/csb226/flash.c b/board/csb226/flash.c
new file mode 100644
index 0000000..0b95648
--- /dev/null
+++ b/board/csb226/flash.c
@@ -0,0 +1,364 @@
+/*
+ * (C) Copyright 2002
+ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.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 <common.h>
+
+#define FLASH_BANK_SIZE 0x02000000
+#define MAIN_SECT_SIZE 0x40000 /* 2x16 = 256k per sector */
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+/*-----------------------------------------------------------------------
+ */
+
+ulong flash_init(void)
+{
+ int i, j;
+ ulong size = 0;
+
+ for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
+ {
+ ulong flashbase = 0;
+ flash_info[i].flash_id =
+ (INTEL_MANUFACT & FLASH_VENDMASK) |
+ (INTEL_ID_28F128J3 & FLASH_TYPEMASK);
+ flash_info[i].size = FLASH_BANK_SIZE;
+ flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
+ memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
+
+ switch (i)
+ {
+ case 0:
+ flashbase = PHYS_FLASH_1;
+ break;
+ default:
+ panic("configured to many flash banks!\n");
+ break;
+ }
+ for (j = 0; j < flash_info[i].sector_count; j++)
+ {
+ flash_info[i].start[j] = flashbase + j*MAIN_SECT_SIZE;
+ }
+ size += flash_info[i].size;
+ }
+
+ /* Protect monitor and environment sectors
+ */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_FLASH_BASE,
+ CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
+ &flash_info[0]);
+
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+ &flash_info[0]);
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t *info)
+{
+ int i, j;
+
+ for (j=0; j<CFG_MAX_FLASH_BANKS; j++)
+ {
+ switch (info->flash_id & FLASH_VENDMASK)
+ {
+ case (INTEL_MANUFACT & FLASH_VENDMASK):
+ printf("Intel: ");
+ break;
+ default:
+ printf("Unknown Vendor ");
+ break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK)
+ {
+ case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
+ printf("28F128J3 (128Mbit)\n");
+ break;
+ default:
+ printf("Unknown Chip Type\n");
+ goto Done;
+ break;
+ }
+
+ printf(" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+
+ printf(" Sector Start Addresses:");
+ for (i = 0; i < info->sector_count; i++)
+ {
+ if ((i % 5) == 0)
+ {
+ printf ("\n ");
+ }
+ printf (" %08lX%s", info->start[i],
+ info->protect[i] ? " (RO)" : " ");
+ }
+ printf ("\n");
+ info++;
+ }
+
+Done:
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ int flag, prot, sect;
+ int rc = ERR_OK;
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ return ERR_UNKNOWN_FLASH_TYPE;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ return ERR_INVAL;
+ }
+
+ if ((info->flash_id & FLASH_VENDMASK) !=
+ (INTEL_MANUFACT & FLASH_VENDMASK)) {
+ return ERR_UNKNOWN_FLASH_VENDOR;
+ }
+
+ prot = 0;
+ for (sect=s_first; sect<=s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+ if (prot)
+ return ERR_PROTECTED;
+
+ /*
+ * Disable interrupts which might cause a timeout
+ * here. Remember that our exception vectors are
+ * at address 0 in the flash, and we don't want a
+ * (ticker) exception to happen while the flash
+ * chip is in programming mode.
+ */
+ flag = disable_interrupts();
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
+
+ printf("Erasing sector %2d ... ", sect);
+
+ /* arm simple, non interrupt dependent timer */
+ reset_timer_masked();
+
+ if (info->protect[sect] == 0) { /* not protected */
+ /* vushort *addr = (vushort *)(info->start[sect]); */
+ ushort *addr = (ushort *)(info->start[sect]);
+
+ *addr = 0x20; /* erase setup */
+ *addr = 0xD0; /* erase confirm */
+
+ while ((*addr & 0x80) != 0x80) {
+ if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
+ *addr = 0xB0; /* suspend erase */
+ *addr = 0xFF; /* reset to read mode */
+ rc = ERR_TIMOUT;
+ goto outahere;
+ }
+ }
+
+ /* clear status register command */
+ *addr = 0x50;
+ /* reset to read mode */
+ *addr = 0xFF;
+ }
+ printf("ok.\n");
+ }
+ if (ctrlc())
+ printf("User Interrupt!\n");
+
+outahere:
+
+ /* allow flash to settle - wait 10 ms */
+ udelay_masked(10000);
+
+ if (flag)
+ enable_interrupts();
+
+ return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash
+ */
+
+static int write_word (flash_info_t *info, ulong dest, ushort data)
+{
+ /* vushort *addr = (vushort *)dest, val; */
+ ushort *addr = (ushort *)dest, val;
+ int rc = ERR_OK;
+ int flag;
+
+ /* Check if Flash is (sufficiently) erased
+ */
+ if ((*addr & data) != data)
+ return ERR_NOT_ERASED;
+
+ /*
+ * Disable interrupts which might cause a timeout
+ * here. Remember that our exception vectors are
+ * at address 0 in the flash, and we don't want a
+ * (ticker) exception to happen while the flash
+ * chip is in programming mode.
+ */
+ flag = disable_interrupts();
+
+ /* clear status register command */
+ *addr = 0x50;
+
+ /* program set-up command */
+ *addr = 0x40;
+
+ /* latch address/data */
+ *addr = data;
+
+ /* arm simple, non interrupt dependent timer */
+ reset_timer_masked();
+
+ /* wait while polling the status register */
+ while(((val = *addr) & 0x80) != 0x80)
+ {
+ if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) {
+ rc = ERR_TIMOUT;
+ /* suspend program command */
+ *addr = 0xB0;
+ goto outahere;
+ }
+ }
+
+ if(val & 0x1A) { /* check for error */
+ printf("\nFlash write error %02x at address %08lx\n",
+ (int)val, (unsigned long)dest);
+ if(val & (1<<3)) {
+ printf("Voltage range error.\n");
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+ if(val & (1<<1)) {
+ printf("Device protect error.\n");
+ rc = ERR_PROTECTED;
+ goto outahere;
+ }
+ if(val & (1<<4)) {
+ printf("Programming error.\n");
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+
+outahere:
+ /* read array command */
+ *addr = 0xFF;
+
+ if (flag)
+ enable_interrupts();
+
+ return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash.
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ ulong cp, wp;
+ ushort data;
+ int l;
+ int i, rc;
+
+ wp = (addr & ~1); /* get lower word aligned address */
+
+ /*
+ * handle unaligned start bytes
+ */
+ if ((l = addr - wp) != 0) {
+ data = 0;
+ for (i=0, cp=wp; i<l; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *)cp << 8);
+ }
+ for (; i<2 && cnt>0; ++i) {
+ data = (data >> 8) | (*src++ << 8);
+ --cnt;
+ ++cp;
+ }
+ for (; cnt==0 && i<2; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *)cp << 8);
+ }
+
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 2;
+ }
+
+ /*
+ * handle word aligned part
+ */
+ while (cnt >= 2) {
+ /* data = *((vushort*)src); */
+ data = *((ushort*)src);
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ src += 2;
+ wp += 2;
+ cnt -= 2;
+ }
+
+ if (cnt == 0) {
+ return ERR_OK;
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ data = 0;
+ for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
+ data = (data >> 8) | (*src++ << 8);
+ --cnt;
+ }
+ for (; i<2; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *)cp << 8);
+ }
+
+ return write_word(info, wp, data);
+}