summaryrefslogtreecommitdiffstats
path: root/u-boot/board/bmw
diff options
context:
space:
mode:
authorH. Nikolaus Schaller <hns@goldelico.com>2012-03-26 20:55:28 +0200
committerH. Nikolaus Schaller <hns@goldelico.com>2012-03-26 20:55:28 +0200
commit92988a21ad4c4c9504295ccb580c9f806134471b (patch)
tree5effc9f14170112450de05c67dafbe8d5034d595 /u-boot/board/bmw
parentca2b506783b676c95762c54ea24dcfdaae1947c9 (diff)
downloadbootable_bootloader_goldelico_gta04-92988a21ad4c4c9504295ccb580c9f806134471b.zip
bootable_bootloader_goldelico_gta04-92988a21ad4c4c9504295ccb580c9f806134471b.tar.gz
bootable_bootloader_goldelico_gta04-92988a21ad4c4c9504295ccb580c9f806134471b.tar.bz2
added boot script files to repository
Diffstat (limited to 'u-boot/board/bmw')
-rw-r--r--u-boot/board/bmw/Makefile50
-rw-r--r--u-boot/board/bmw/README331
-rw-r--r--u-boot/board/bmw/bmw.c159
-rw-r--r--u-boot/board/bmw/bmw.h86
-rw-r--r--u-boot/board/bmw/config.mk30
-rw-r--r--u-boot/board/bmw/early_init.S1170
-rw-r--r--u-boot/board/bmw/flash.c779
-rw-r--r--u-boot/board/bmw/m48t59y.c324
-rw-r--r--u-boot/board/bmw/m48t59y.h57
-rw-r--r--u-boot/board/bmw/ns16550.c57
-rw-r--r--u-boot/board/bmw/ns16550.h79
-rw-r--r--u-boot/board/bmw/serial.c81
12 files changed, 3203 insertions, 0 deletions
diff --git a/u-boot/board/bmw/Makefile b/u-boot/board/bmw/Makefile
new file mode 100644
index 0000000..4f88efa
--- /dev/null
+++ b/u-boot/board/bmw/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (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 = $(obj)lib$(BOARD).o
+
+COBJS = $(BOARD).o flash.o ns16550.o serial.o m48t59y.o
+
+SOBJS = early_init.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(call cmd_link_o_target, $(OBJS) $(SOBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/u-boot/board/bmw/README b/u-boot/board/bmw/README
new file mode 100644
index 0000000..1fbef79
--- /dev/null
+++ b/u-boot/board/bmw/README
@@ -0,0 +1,331 @@
+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 CONFIG_SYS_IBAT0L (0x00000000 | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CONFIG_SYS_IBAT0U (0x00000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CONFIG_SYS_IBAT1L (0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CONFIG_SYS_IBAT1U (0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CONFIG_SYS_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CONFIG_SYS_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CONFIG_SYS_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CONFIG_SYS_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CONFIG_SYS_DBAT0L CONFIG_SYS_IBAT0L
+#define CONFIG_SYS_DBAT0U CONFIG_SYS_IBAT0U
+#define CONFIG_SYS_DBAT1L CONFIG_SYS_IBAT1L
+#define CONFIG_SYS_DBAT1U CONFIG_SYS_IBAT1U
+#define CONFIG_SYS_DBAT2L CONFIG_SYS_IBAT2L
+#define CONFIG_SYS_DBAT2U CONFIG_SYS_IBAT2U
+#define CONFIG_SYS_DBAT3L CONFIG_SYS_IBAT3L
+#define CONFIG_SYS_DBAT3U CONFIG_SYS_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/u-boot/board/bmw/bmw.c b/u-boot/board/bmw/bmw.c
new file mode 100644
index 0000000..5ba6c09
--- /dev/null
+++ b/u-boot/board/bmw/bmw.c
@@ -0,0 +1,159 @@
+/*
+ * (C) Copyright 2002
+ * James F. Dougherty, Broadcom Corporation, jfd@broadcom.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 <watchdog.h>
+#include <command.h>
+#include <malloc.h>
+#include <stdio_dev.h>
+#include <net.h>
+#include <timestamp.h>
+#include <dtt.h>
+#include <mpc824x.h>
+#include <asm/processor.h>
+#include <linux/mtd/doc2000.h>
+
+#include "bmw.h"
+#include "m48t59y.h"
+#include <pci.h>
+
+
+int checkboard(void)
+{
+ ulong busfreq = get_bus_freq(0);
+ char buf[32];
+
+ puts ("Board: BMW MPC8245/KAHLUA2 - CHRP (MAP B)\n");
+ printf("Built: %s at %s\n", U_BOOT_DATE, U_BOOT_TIME);
+ /* printf("MPLD: Revision %d\n", SYS_REVID_GET()); */
+ printf("Local Bus at %s MHz\n", strmhz(buf, busfreq));
+ return 0;
+}
+
+phys_size_t initdram(int board_type)
+{
+ return 64*1024*1024;
+}
+
+
+void
+get_tod(void)
+{
+ int year, month, day, hour, minute, second;
+
+ m48_tod_get(&year,
+ &month,
+ &day,
+ &hour,
+ &minute,
+ &second);
+
+ printf(" Current date/time: %d/%d/%d %d:%d:%d \n",
+ month, day, year, hour, minute, second);
+
+}
+
+/*
+ * EPIC, PCI, and I/O devices.
+ * Initialize Mousse Platform, probe for PCI devices,
+ * Query configuration parameters if not set.
+ */
+int misc_init_f (void)
+{
+#if 0
+ m48_tod_init(); /* Init SGS M48T59Y TOD/NVRAM */
+ printf("RTC: M48T589 TOD/NVRAM (%d) bytes\n",
+ TOD_NVRAM_SIZE);
+ get_tod();
+#endif
+
+ sys_led_msg("BOOT");
+ return 0;
+}
+
+
+/*
+ * Initialize PCI Devices, report devices found.
+ */
+struct pci_controller hose;
+
+void pci_init_board (void)
+{
+ pci_mpc824x_init(&hose);
+ /* pci_dev_init(0); */
+}
+
+/*
+ * Write characters to LCD display.
+ * Note that the bytes for the first character is the last address.
+ */
+void
+sys_led_msg(char* msg)
+{
+ LED_REG(0) = msg[3];
+ LED_REG(1) = msg[2];
+ LED_REG(2) = msg[1];
+ LED_REG(3) = msg[0];
+}
+
+#ifdef CONFIG_CMD_DOC
+/*
+ * Map onboard TSOP-16MB DOC FLASH chip.
+ */
+void doc_init (void)
+{
+ doc_probe(DOC_BASE_ADDR);
+}
+#endif
+
+#define NV_ADDR ((volatile unsigned char *) CONFIG_ENV_ADDR)
+
+/* Read from NVRAM */
+void*
+nvram_read(void *dest, const long src, size_t count)
+{
+ int i;
+ volatile unsigned char* d = (unsigned char*)dest;
+ volatile unsigned char* s = (unsigned char*)src;
+
+ for( i = 0; i < count;i++)
+ d[i] = s[i];
+
+ return dest;
+}
+
+/* Write to NVRAM */
+void
+nvram_write(long dest, const void *src, size_t count)
+{
+ int i;
+ volatile unsigned char* d = (unsigned char*)dest;
+ volatile unsigned char* s = (unsigned char*)src;
+
+ SYS_TOD_UNPROTECT();
+
+ for( i = 0; i < count;i++)
+ d[i] = s[i];
+
+ SYS_TOD_PROTECT();
+}
diff --git a/u-boot/board/bmw/bmw.h b/u-boot/board/bmw/bmw.h
new file mode 100644
index 0000000..dd97569
--- /dev/null
+++ b/u-boot/board/bmw/bmw.h
@@ -0,0 +1,86 @@
+/*
+ * BMW/MPC8245 Board definitions.
+ * For more info, see http://www.vooha.com/
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * James Dougherty (jfd@broadcom.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 __BMW_H
+#define __BMW_H
+
+/* System addresses */
+
+#define PCI_SPECIAL_BASE 0xfe000000
+#define PCI_SPECIAL_SIZE 0x01000000
+
+#define EUMBBAR_VAL 0x80500000 /* Location of EUMB region */
+#define EUMBSIZE 0x00100000 /* Size of EUMB region */
+
+/* Extended ROM space devices */
+#define DOC_BASE_ADDR 0xff000000 /* Onboard DOC TSOP 16MB */
+#define DOC2_BASE_ADDR 0x70000000 /* DIP32 socket -> 1GB */
+#define XROM_BASE_ADDR 0x7c000000 /* RCS2 (PAL / Satellite IO) */
+#define PLD_REG_BASE XROM_BASE_ADDR
+#define LED_REG_BASE (XROM_BASE_ADDR | 0x2000)
+#define TOD_BASE (XROM_BASE_ADDR | 0x4000)
+#define LED_REG(x) (*(volatile unsigned char *) \
+ (LED_REG_BASE + (x)))
+#define XROM_DEV_SIZE 0x00006000
+
+#define ENET_DEV_BASE 0x80000000
+
+#define PLD_REG(off) (*(volatile unsigned char *)\
+ (PLD_REG_BASE + (off)))
+
+#define PLD_REVID_B1 0x7f /* Fix me */
+#define PLD_REVID_B2 0x01 /* Fix me */
+
+#define SYS_HARD_RESET() { for (;;) PLD_REG(0) = 0; } /* clr 0x80 bit */
+#define SYS_REVID_GET() ((int) PLD_REG(0) & 0x7f)
+#define SYS_LED_OFF() (PLD_REG(1) |= 0x80)
+#define SYS_LED_ON() (PLD_REG(1) &= ~0x80)
+#define SYS_WATCHDOG_IRQ3() (PLD_REG(2) |= 0x80)
+#define SYS_WATCHDOG_RESET() (PLD_REG(2) &= ~0x80)
+#define SYS_TOD_PROTECT() (PLD_REG(3) |= 0x80)
+#define SYS_TOD_UNPROTECT() (PLD_REG(3) &= ~0x80)
+
+#define TOD_REG_BASE (TOD_BASE | 0x1ff0)
+#define TOD_NVRAM_BASE TOD_BASE
+#define TOD_NVRAM_SIZE 0x1ff0
+#define TOD_NVRAM_LIMIT (TOD_NVRAM_BASE + TOD_NVRAM_SIZE)
+#define RTC(r) (TOD_BASE + r)
+
+/* Onboard BCM570x device */
+#define PCI_ENET_IOADDR 0x80000000
+#define PCI_ENET_MEMADDR 0x80000000
+
+
+#ifndef __ASSEMBLY__
+/* C Function prototypes */
+void sys_led_msg(char* msg);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __BMW_H */
diff --git a/u-boot/board/bmw/config.mk b/u-boot/board/bmw/config.mk
new file mode 100644
index 0000000..a1a44e5
--- /dev/null
+++ b/u-boot/board/bmw/config.mk
@@ -0,0 +1,30 @@
+#
+# (C) Copyright 2001
+# 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
+#
+
+#
+# BMW board
+#
+
+# NOTE: The flags below affect how the BCM570x driver is compiled
+PLATFORM_CPPFLAGS += -DEMBEDDED -DBIG_ENDIAN_HOST -DINCLUDE_5701_AX_FIX=1\
+ -DDBG=0 -DT3_JUMBO_RCV_RCB_ENTRY_COUNT=256
diff --git a/u-boot/board/bmw/early_init.S b/u-boot/board/bmw/early_init.S
new file mode 100644
index 0000000..63c29d5
--- /dev/null
+++ b/u-boot/board/bmw/early_init.S
@@ -0,0 +1,1170 @@
+#include <ppc_asm.tmpl>
+#include <mpc824x.h>
+#include <ppc_defs.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#define USE_V2_INIT 1 /* Jimmy Blair's initialization. */
+
+
+/*
+ * Initialize the MMU using BAT entries and hardwired TLB
+ * This obviates the need for any code in cpu_init_f which
+ * configures the BAT registers.
+*/
+#define MEMORY_MGMT_MSR_BITS (MSR_DR | MSR_IR) /* Data and Inst Relocate */
+ .global iommu_setup
+ /* Initialize IO/MMU mappings via BAT method Ch. 7,
+ * PPC Programming Reference
+ */
+iommu_setup:
+
+/* initialize the BAT registers (SPRs 528 - 543 */
+#define mtibat0u(x) mtspr 528,(x) /* SPR 528 (IBAT0U) */
+#define mtibat0l(x) mtspr 529,(x) /* SPR 529 (IBAT0L) */
+#define mtibat1u(x) mtspr 530,(x) /* SPR 530 (IBAT1U) */
+#define mtibat1l(x) mtspr 531,(x) /* SPR 531 (IBAT1L) */
+#define mtibat2u(x) mtspr 532,(x) /* SPR 532 (IBAT2U) */
+#define mtibat2l(x) mtspr 533,(x) /* SPR 533 (IBAT2L) */
+#define mtibat3u(x) mtspr 534,(x) /* SPR 534 (IBAT3U) */
+#define mtibat3l(x) mtspr 535,(x) /* SPR 535 (IBAT3L) */
+#define mtdbat0u(x) mtspr 536,(x) /* SPR 536 (DBAT0U) */
+#define mtdbat0l(x) mtspr 537,(x) /* SPR 537 (DBAT0L) */
+#define mtdbat1u(x) mtspr 538,(x) /* SPR 538 (DBAT1U) */
+#define mtdbat1l(x) mtspr 539,(x) /* SPR 539 (DBAT1L) */
+#define mtdbat2u(x) mtspr 540,(x) /* SPR 540 (DBAT2U) */
+#define mtdbat2l(x) mtspr 541,(x) /* SPR 541 (DBAT2L) */
+#define mtdbat3u(x) mtspr 542,(x) /* SPR 542 (DBAT3U) */
+#define mtdbat3l(x) mtspr 543,(x) /* SPR 543 (DBAT3L) */
+
+
+/* PowerPC processors do not necessarily initialize the BAT
+ registers on power-up or reset. So they are in an unknown
+ state. Before programming the BATs for the first time, all
+ BAT registers MUST have their Vs and Vp bits cleared in the
+ upper BAT half in order to avoid possibly having 2 BATs
+ valid and mapping the same memory region.
+
+ The reason for this is that, even with address translation
+ disabled, multiple BAT hits for an address are treated as
+ programming errors and can cause unpredictable results.
+
+ It is up to the software to make sure it never has 2 IBAT
+ mappings or 2 DBAT mappings that are valid for the same
+ addresses. It is not necessary to perform this code
+ sequence every time the BATs are programmed, only when
+ there is a possibility that there may be overlapping BAT
+ entries.
+
+ When programming the BATs in non-reset scenarios, even if
+ you are sure that your new mapping will not temporarily
+ create overlapping regions, it is still a wise idea to
+ invalidate a BAT entry by setting its upper BAT register to
+ all 0's before programming it. This will avoid having a
+ BAT marked valid that is in an unknown or transient state
+*/
+
+ addis r5,0,0x0000
+ mtibat0u(r5)
+ mtibat0l(r5)
+ mtibat1u(r5)
+ mtibat1l(r5)
+ mtibat2u(r5)
+ mtibat2l(r5)
+ mtibat3u(r5)
+ mtibat3l(r5)
+ mtdbat0u(r5)
+ mtdbat0l(r5)
+ mtdbat1u(r5)
+ mtdbat1l(r5)
+ mtdbat2u(r5)
+ mtdbat2l(r5)
+ mtdbat3u(r5)
+ mtdbat3l(r5)
+ isync
+
+/*
+ * Set up I/D BAT0
+ */
+ lis r4, CONFIG_SYS_DBAT0L@h
+ ori r4, r4, CONFIG_SYS_DBAT0L@l
+ lis r3, CONFIG_SYS_DBAT0U@h
+ ori r3, r3, CONFIG_SYS_DBAT0U@l
+
+ mtdbat0l(r4)
+ isync
+ mtdbat0u(r3)
+ isync
+ sync
+
+ lis r4, CONFIG_SYS_IBAT0L@h
+ ori r4, r4, CONFIG_SYS_IBAT0L@l
+ lis r3, CONFIG_SYS_IBAT0U@h
+ ori r3, r3, CONFIG_SYS_IBAT0U@l
+
+ isync
+ mtibat0l(r4)
+ isync
+ mtibat0u(r3)
+ isync
+
+/*
+ * Set up I/D BAT1
+ */
+ lis r4, CONFIG_SYS_IBAT1L@h
+ ori r4, r4, CONFIG_SYS_IBAT1L@l
+ lis r3, CONFIG_SYS_IBAT1U@h
+ ori r3, r3, CONFIG_SYS_IBAT1U@l
+
+ isync
+ mtibat1l(r4)
+ isync
+ mtibat1u(r3)
+ isync
+ mtdbat1l(r4)
+ isync
+ mtdbat1u(r3)
+ isync
+ sync
+
+/*
+ * Set up I/D BAT2
+ */
+ lis r4, CONFIG_SYS_IBAT2L@h
+ ori r4, r4, CONFIG_SYS_IBAT2L@l
+ lis r3, CONFIG_SYS_IBAT2U@h
+ ori r3, r3, CONFIG_SYS_IBAT2U@l
+
+ isync
+ mtibat2l(r4)
+ isync
+ mtibat2u(r3)
+ isync
+ mtdbat2l(r4)
+ isync
+ mtdbat2u(r3)
+ isync
+ sync
+
+/*
+ * Setup I/D BAT3
+ */
+ lis r4, CONFIG_SYS_IBAT3L@h
+ ori r4, r4, CONFIG_SYS_IBAT3L@l
+ lis r3, CONFIG_SYS_IBAT3U@h
+ ori r3, r3, CONFIG_SYS_IBAT3U@l
+
+ isync
+ mtibat3l(r4)
+ isync
+ mtibat3u(r3)
+ isync
+ mtdbat3l(r4)
+ isync
+ mtdbat3u(r3)
+ isync
+ sync
+
+
+/*
+ * Invalidate all 64 TLB's
+ */
+ lis r3, 0
+ mtctr r3
+ lis r5, 4
+
+tlblp:
+ tlbie r3
+ sync
+ addi r3, r3, 0x1000
+ cmplw r3, r5
+ blt tlblp
+
+ sync
+
+/*
+ * Enable Data Translation
+ */
+ lis r4, MEMORY_MGMT_MSR_BITS@h
+ ori r4, r4, MEMORY_MGMT_MSR_BITS@l
+ mfmsr r3
+ or r3, r4, r3
+ mtmsr r3
+ isync
+ sync
+
+ blr
+
+
+#ifdef USE_V2_INIT
+/* #define USER_I_CACHE_ENABLE 1*/ /* Fast rom boots */
+/* Macro for hiadjust and lo */
+#define HIADJ(arg) arg@ha
+#define HI(arg) arg@h
+#define LO(arg) arg@l
+
+#undef LOADPTR
+#define LOADPTR(reg,const32) \
+ addis reg,r0,HIADJ(const32); addi reg,reg,LO(const32)
+
+.globl early_init_f
+
+early_init_f:
+/* MPC8245/BMW CPCI System Init
+ * Jimmy Blair, Broadcom Corp, 2002.
+ */
+ mflr r11
+ /* Zero-out registers */
+
+ addis r0,r0,0
+ mtspr SPRG0,r0
+ mtspr SPRG1,r0
+ mtspr SPRG2,r0
+ mtspr SPRG3,r0
+
+ /* Set MPU/MSR to a known state. Turn on FP */
+
+ LOADPTR (r3, MSR_FP)
+ sync
+ mtmsr r3
+ isync
+
+ /* Init the floating point control/status register */
+
+ mtfsfi 7,0x0
+ mtfsfi 6,0x0
+ mtfsfi 5,0x0
+ mtfsfi 4,0x0
+ mtfsfi 3,0x0
+ mtfsfi 2,0x0
+ mtfsfi 1,0x0
+ mtfsfi 0,0x0
+ isync
+
+ /* Set MPU/MSR to a known state. Turn off FP */
+
+#if 1 /* Turn off floating point (remove to keep FP on) */
+ andi. r3, r3, 0
+ sync
+ mtmsr r3
+ isync
+#endif
+
+ /* Init the Segment registers */
+
+ andi. r3, r3, 0
+ isync
+ mtsr 0,r3
+ isync
+ mtsr 1,r3
+ isync
+ mtsr 2,r3
+ isync
+ mtsr 3,r3
+ isync
+ mtsr 4,r3
+ isync
+ mtsr 5,r3
+ isync
+ mtsr 6,r3
+ isync
+ mtsr 7,r3
+ isync
+ mtsr 8,r3
+ isync
+ mtsr 9,r3
+ isync
+ mtsr 10,r3
+ isync
+ mtsr 11,r3
+ isync
+ mtsr 12,r3
+ isync
+ mtsr 13,r3
+ isync
+ mtsr 14,r3
+ isync
+ mtsr 15,r3
+ isync
+
+ /* Turn off data and instruction cache control bits */
+
+ mfspr r3, HID0
+ isync
+ rlwinm r4, r3, 0, 18, 15 /* r4 has ICE and DCE bits cleared */
+ sync
+ isync
+ mtspr HID0, r4 /* HID0 = r4 */
+ isync
+
+ /* Get cpu type */
+
+ mfspr r28, PVR
+ rlwinm r28, r28, 16, 16, 31
+
+ /* invalidate the MPU's data/instruction caches */
+
+ lis r3, 0x0
+ cmpli 0, 0, r28, CPU_TYPE_603
+ beq cpuIs603
+ cmpli 0, 0, r28, CPU_TYPE_603E
+ beq cpuIs603
+ cmpli 0, 0, r28, CPU_TYPE_603P
+ beq cpuIs603
+ cmpli 0, 0, r28, CPU_TYPE_604R
+ bne cpuNot604R
+
+cpuIs604R:
+ lis r3, 0x0
+ mtspr HID0, r3 /* disable the caches */
+ isync
+ ori r4, r4, 0x0002 /* disable BTAC by setting bit 30 */
+
+cpuNot604R:
+ ori r3, r3, (HID0_ICFI |HID0_DCI)
+
+cpuIs603:
+ ori r3, r3, (HID0_ICE | HID0_DCE)
+ or r4, r4, r3 /* set bits */
+ sync
+ isync
+ mtspr HID0, r4 /* HID0 = r4 */
+ andc r4, r4, r3 /* clear bits */
+ isync
+ cmpli 0, 0, r28, CPU_TYPE_604
+ beq cpuIs604
+ cmpli 0, 0, r28, CPU_TYPE_604E
+ beq cpuIs604
+ cmpli 0, 0, r28, CPU_TYPE_604R
+ beq cpuIs604
+ mtspr HID0, r4
+ isync
+
+#ifdef USER_I_CACHE_ENABLE
+ b instCacheOn603
+#else
+ b cacheEnableDone
+#endif
+
+cpuIs604:
+ LOADPTR (r5, 0x1000) /* loop count, 0x1000 */
+ mtspr CTR, r5
+loopDelay:
+ nop
+ bdnz loopDelay
+ isync
+ mtspr HID0, r4
+ isync
+
+ /* turn the Instruction cache ON for faster FLASH ROM boots */
+
+#ifdef USER_I_CACHE_ENABLE
+
+ ori r4, r4, (HID0_ICE | HID0_ICFI)
+ isync /* Synchronize for ICE enable */
+ b writeReg4
+instCacheOn603:
+ ori r4, r4, (HID0_ICE | HID0_ICFI)
+ rlwinm r3, r4, 0, 21, 19 /* clear the ICFI bit */
+
+ /*
+ * The setting of the instruction cache enable (ICE) bit must be
+ * preceded by an isync instruction to prevent the cache from being
+ * enabled or disabled while an instruction access is in progress.
+ */
+ isync
+writeReg4:
+ mtspr HID0, r4 /* Enable Instr Cache & Inval cache */
+ cmpli 0, 0, r28, CPU_TYPE_604
+ beq cacheEnableDone
+ cmpli 0, 0, r28, CPU_TYPE_604E
+ beq cacheEnableDone
+
+ mtspr HID0, r3 /* using 2 consec instructions */
+ /* PPC603 recommendation */
+#endif
+cacheEnableDone:
+
+ /* Detect map A or B */
+
+ addis r5,r0, HI(CHRP_REG_ADDR)
+ addis r6,r0, HI(CHRP_REG_DATA)
+ LOADPTR (r7, KAHLUA_ID) /* Kahlua PCI controller ID */
+ LOADPTR (r8, BMC_BASE)
+
+ stwbrx r8,0,(r5)
+ lwbrx r3,0,(r6) /* Store read value to r3 */
+ cmp 0,0,r3,r7
+ beq cr0, X4_KAHLUA_START
+
+ /* It's not an 8240, is it an 8245? */
+
+ LOADPTR (r7, KAHLUA2_ID) /* Kahlua PCI controller ID */
+ cmp 0,0,r3,r7
+ beq cr0, X4_KAHLUA_START
+
+ /* Save the PCI controller type in r7 */
+ mr r7, r3
+
+ LOADPTR (r5, PREP_REG_ADDR)
+ LOADPTR (r6, PREP_REG_DATA)
+
+X4_KAHLUA_START:
+ /* MPC8245 changes begin here */
+ LOADPTR (r3, MPC107_PCI_CMD) /* PCI command reg */
+ stwbrx r3,0,r5
+ li r4, 6 /* Command register value */
+ sthbrx r4, 0, r6
+
+ LOADPTR (r3, MPC107_PCI_STAT) /* PCI status reg */
+ stwbrx r3,0,r5
+ li r4, -1 /* Write-to-clear all bits */
+ li r3, 2 /* PCI_STATUS is at +2 offset */
+ sthbrx r4, r3, r6
+
+ /*-------PROC_INT1_ADR */
+
+ LOADPTR (r3, PROC_INT1_ADR) /* Processor I/F Config 1 reg. */
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0xff141b98)
+ stwbrx r4,0,r6
+
+ /*-------PROC_INT2_ADR */
+
+ LOADPTR (r3, PROC_INT2_ADR) /* Processor I/F Config 2 reg. */
+ stwbrx r3,0,r5
+ lis r4, 0x2000 /* Flush PCI config writes */
+ stwbrx r4,0,r6
+
+ LOADPTR (r9, KAHLUA2_ID)
+ cmpl 0, 0, r7, r9
+ bne L1not8245
+
+ /* MIOCR1 -- turn on bit for DLL delay */
+
+ LOADPTR (r3, MIOCR1_ADR_X)
+ stwbrx r3,0,r5
+ li r4, 0x04
+ stb r4, MIOCR1_SHIFT(r6)
+
+ /* For the MPC8245, set register 77 to %00100000 (see Errata #15) */
+ /* SDRAM_CLK_DEL (0x77)*/
+
+ LOADPTR (r3, MIOCR2_ADR_X)
+ stwbrx r3,0,r5
+ li r4, 0x10
+ stb r4, MIOCR2_SHIFT(r6)
+
+ /* PMCR2 -- set PCI hold delay to <10>b for 33 MHz */
+
+ LOADPTR (r3, PMCR2_ADR_X)
+ stwbrx r3,0,r5
+ li r4, 0x20
+ stb r4, PMCR2_SHIFT(r6)
+
+ /* Initialize EUMBBAR early since 8245 has internal UART in EUMB */
+
+ LOADPTR (r3, EUMBBAR)
+ stwbrx r3,0,r5
+ LOADPTR (r4, CONFIG_SYS_EUMB_ADDR)
+ stwbrx r4,0,r6
+
+L1not8245:
+
+ /* Toggle the DLL reset bit in AMBOR */
+
+ LOADPTR (r3, AMBOR)
+ stwbrx r3,0,r5
+ lbz r4, 0(r6)
+
+ andi. r4, r4, 0xdf
+ stb r4, 0(r6) /* Clear DLL_RESET */
+ sync
+
+ ori r4, r4, 0x20 /* Set DLL_RESET */
+ stb r4, 0(r6)
+ sync
+
+ andi. r4, r4, 0xdf
+ stb r4, 0(r6) /* Clear DLL_RESET */
+
+
+ /* Enable RCS2, use supplied timings */
+ LOADPTR (r3, ERCR1)
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0x80408000)
+ stwbrx r4,0,r6
+
+ /* Disable RCS3 parameters */
+ LOADPTR (r3, ERCR2)
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0x00000000)
+ stwbrx r4,0,r6
+
+ /* RCS3 at 0x70000000, 64KBytes */
+ LOADPTR (r3, ERCR2)
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0x00000004)
+ stwbrx r4,0,r6
+
+ /*-------MCCR1 */
+
+#ifdef INCLUDE_ECC
+#define MC_ECC 1
+#else /* INCLUDE_ECC */
+#define MC_ECC 0
+#endif /* INCLUDE_ECC */
+
+#define MC1_ROMNAL 8 /* 0-15 */
+#define MC1_ROMFAL 11 /* 0-31 */
+#define MC1_DBUS_SIZE 0 /* 0-3, read only */
+#define MC1_BURST 0 /* 0-1 */
+#define MC1_MEMGO 0 /* 0-1 */
+#define MC1_SREN 1 /* 0-1 */
+#define MC1_RAM_TYPE 0 /* 0-1 */
+#define MC1_PCKEN MC_ECC /* 0-1 */
+#define MC1_BANKBITS 0x5555 /* 2 bits/bank 7-0 */
+
+ LOADPTR (r3, MEM_CONT1_ADR) /* Set MCCR1 (F0) */
+ stwbrx r3,0,r5
+ LOADPTR(r4, \
+ MC1_ROMNAL << 28 | MC1_ROMFAL << 23 | \
+ MC1_DBUS_SIZE << 21 | MC1_BURST << 20 | \
+ MC1_MEMGO << 19 | MC1_SREN << 18 | \
+ MC1_RAM_TYPE << 17 | MC1_PCKEN << 16 )
+ li r3, MC1_BANKBITS
+ cmpl 0, 0, r7, r9 /* Check for Kahlua2 */
+ bne BankBitsAdd
+ cmpli 0, 0, r3, 0x5555
+ beq K2BankBitsHack /* On 8245, 5555 ==> 0 */
+BankBitsAdd:
+ ori r4, r3, 0
+K2BankBitsHack:
+ stwbrx r4, 0, r6
+
+ /*------- MCCR2 */
+
+#define MC2_TS_WAIT_TIMER 0 /* 0-7 */
+#define MC2_ASRISE 8 /* 0-15 */
+#define MC2_ASFALL 4 /* 0-15 */
+#define MC2_INLINE_PAR_NOT_ECC 0 /* 0-1 */
+#define MC2_WRITE_PARITY_CHK_EN MC_ECC /* 0-1 */
+#define MC2_INLRD_PARECC_CHK_EN MC_ECC /* 0-1 */
+#define MC2_ECC_EN 0 /* 0-1 */
+#define MC2_EDO 0 /* 0-1 */
+/*
+* N.B. This refresh interval looks good up to 85 MHz with Hynix SDRAM.
+* May need to be decreased for 100 MHz
+*/
+#define MC2_REFINT 0x3a5 /* 0-0x3fff */
+#define MC2_RSV_PG 0 /* 0-1 */
+#define MC2_RMW_PAR MC_ECC /* 0-1 */
+
+ LOADPTR (r3, MEM_CONT2_ADR) /* Set MCCR2 (F4) */
+ stwbrx r3,0,r5
+ LOADPTR(r4, \
+ MC2_TS_WAIT_TIMER << 29 | MC2_ASRISE << 25 | \
+ MC2_ASFALL << 21 | MC2_INLINE_PAR_NOT_ECC << 20 | \
+ MC2_WRITE_PARITY_CHK_EN << 19 | \
+ MC2_INLRD_PARECC_CHK_EN << 18 | \
+ MC2_ECC_EN << 17 | MC2_EDO << 16 | \
+ MC2_REFINT << 2 | MC2_RSV_PG << 1 | MC2_RMW_PAR)
+ cmpl 0, 0, r7, r9 /* Check for Kahlua2 */
+ bne notK2
+ /* clear Kahlua2 reserved bits */
+ LOADPTR (r3, 0xfffcffff)
+ and r4, r4, r3
+notK2:
+ stwbrx r4,0,r6
+
+ /*------- MCCR3 */
+
+#define MC_BSTOPRE 0x079 /* 0-0x7ff */
+
+#define MC3_BSTOPRE_U (MC_BSTOPRE >> 4 & 0xf)
+#define MC3_REFREC 8 /* 0-15 */
+#define MC3_RDLAT (4+MC_ECC) /* 0-15 */
+#define MC3_CPX 0 /* 0-1 */
+#define MC3_RAS6P 0 /* 0-15 */
+#define MC3_CAS5 0 /* 0-7 */
+#define MC3_CP4 0 /* 0-7 */
+#define MC3_CAS3 0 /* 0-7 */
+#define MC3_RCD2 0 /* 0-7 */
+#define MC3_RP1 0 /* 0-7 */
+
+ LOADPTR (r3, MEM_CONT3_ADR) /* Set MCCR3 (F8) */
+ stwbrx r3,0,r5
+ LOADPTR(r4, \
+ MC3_BSTOPRE_U << 28 | MC3_REFREC << 24 | \
+ MC3_RDLAT << 20 | MC3_CPX << 19 | \
+ MC3_RAS6P << 15 | MC3_CAS5 << 12 | MC3_CP4 << 9 | \
+ MC3_CAS3 << 6 | MC3_RCD2 << 3 | MC3_RP1)
+ cmpl 0, 0, r7, r9 /* Check for Kahlua2 */
+ bne notK2b
+ /* clear Kahlua2 reserved bits */
+ LOADPTR (r3, 0xff000000)
+ and r4, r4, r3
+notK2b:
+ stwbrx r4,0,r6
+
+ /*------- MCCR4 */
+
+#define MC4_PRETOACT 3 /* 0-15 */
+#define MC4_ACTOPRE 5 /* 0-15 */
+#define MC4_WMODE 0 /* 0-1 */
+#define MC4_INLINE MC_ECC /* 0-1 */
+#define MC4_REGISTERED (1-MC_ECC) /* 0-1 */
+#define MC4_BSTOPRE_UU (MC_BSTOPRE >> 8 & 3)
+#define MC4_REGDIMM 0 /* 0-1 */
+#define MC4_SDMODE_CAS 2 /* 0-7 */
+#define MC4_DBUS_RCS1 1 /* 0-1, 8-bit */
+#define MC4_SDMODE_WRAP 0 /* 0-1 */
+#define MC4_SDMODE_BURST 2 /* 0-7 */
+#define MC4_ACTORW 3 /* 0-15 */
+#define MC4_BSTOPRE_L (MC_BSTOPRE & 0xf)
+
+ LOADPTR (r3, MEM_CONT4_ADR) /* Set MCCR4 (FC) */
+ stwbrx r3,0,r5
+ LOADPTR(r4, \
+ MC4_PRETOACT << 28 | MC4_ACTOPRE << 24 | \
+ MC4_WMODE << 23 | MC4_INLINE << 22 | \
+ MC4_REGISTERED << 20 | MC4_BSTOPRE_UU << 18 | \
+ MC4_DBUS_RCS1 << 17 | \
+ MC4_REGDIMM << 15 | MC4_SDMODE_CAS << 12 | \
+ MC4_SDMODE_WRAP << 11 | MC4_SDMODE_BURST << 8 | \
+ MC4_ACTORW << 4 | MC4_BSTOPRE_L)
+ cmpl 0, 0, r7, r9 /* Check for Kahlua 2 */
+ bne notK2c
+ /* Turn on Kahlua2 extended ROM space */
+ LOADPTR (r3, 0x00200000)
+ or r4, r4, r3
+notK2c:
+ stwbrx r4,0,r6
+
+#ifdef INCLUDE_ECC
+ /*------- MEM_ERREN1 */
+
+ LOADPTR (r3, MEM_ERREN1_ADR) /* Set MEM_ERREN1 (c0) */
+ stwbrx r3,0,r5
+ lwbrx r4,0,r6
+ ori r4,r4,4 /* Set MEM_PERR_EN */
+ stwbrx r4,0,r6
+#endif /* INCLUDE_ECC */
+
+ /*------- MSAR/MEAR */
+
+ LOADPTR (r3, MEM_START1_ADR) /* Set MSAR1 (80) */
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0xc0804000)
+ stwbrx r4,0,r6
+
+ LOADPTR (r3, MEM_START2_ADR) /* Set MSAR2 (84) */
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0xc0804000)
+ stwbrx r4,0,r6
+
+ LOADPTR (r3, XMEM_START1_ADR) /* Set MESAR1 (88) */
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0x00000000)
+ stwbrx r4,0,r6
+
+ LOADPTR (r3, XMEM_START2_ADR) /* Set MESAR2 (8c) */
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0x01010101)
+ stwbrx r4,0,r6
+
+ LOADPTR (r3, MEM_END1_ADR) /* Set MEAR1 (90) */
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0xffbf7f3f)
+ stwbrx r4,0,r6
+
+ LOADPTR (r3, MEM_END2_ADR) /* Set MEAR2 (94) */
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0xffbf7f3f)
+ stwbrx r4,0,r6
+
+ LOADPTR (r3, XMEM_END1_ADR) /* MEEAR1 (98) */
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0x00000000)
+ stwbrx r4,0,r6
+
+ LOADPTR (r3, XMEM_END2_ADR) /* MEEAR2 (9c) */
+ stwbrx r3,0,r5
+ LOADPTR (r4, 0x01010101)
+ stwbrx r4,0,r6
+
+ /*-------ODCR */
+
+ LOADPTR (r3, ODCR_ADR_X) /* Set ODCR */
+ stwbrx r3,0,r5
+
+ li r4, 0x7f
+ stb r4, ODCR_SHIFT(r6) /* ODCR is at +3 offset */
+
+ /*-------MBEN */
+
+ LOADPTR (r3, MEM_EN_ADR) /* Set MBEN (a0) */
+ stwbrx r3,0,r5
+ li r4, 0x01 /* Enable bank 0 */
+ stb r4, 0(r6) /* MBEN is at +0 offset */
+
+#if 0 /* Jimmy: I think page made is broken */
+ /*-------PGMAX */
+
+ LOADPTR (r3, MPM_ADR_X)
+ stwbrx r3,0,r5
+ li r4, 0x32
+ stb r4, MPM_SHIFT(r6) /* PAGE_MODE is at +3 offset */
+#endif
+
+ /* Wait before initializing other registers */
+
+ lis r4,0x0001
+ mtctr r4
+
+KahluaX4wait200us:
+ bdnz KahluaX4wait200us
+
+ /* Set MEMGO bit */
+
+ LOADPTR (r3, MEM_CONT1_ADR) /* MCCR1 (F0) |= PGMAX */
+ stwbrx r3,0,r5
+ lwbrx r4,0,r6 /* old MCCR1 */
+ oris r4,r4,0x0008 /* MEMGO=1 */
+ stwbrx r4, 0, r6
+
+ /* Wait again */
+
+ addis r4,r0,0x0002
+ ori r4,r4,0xffff
+
+ mtctr r4
+
+KahluaX4wait8ref:
+ bdnz KahluaX4wait8ref
+
+ sync
+ eieio
+ mtlr r11
+ blr
+
+#else /* USE_V2_INIT */
+
+
+/* U-Boot works, but memory will not run reliably for all address ranges.
+ * Early U-Boot Working init, but 2.4.19 kernel will crash since memory is not
+ * initialized correctly. Could work if debugged.
+ */
+/* PCI Support routines */
+
+ .globl __pci_config_read_32
+__pci_config_read_32:
+ lis r4, 0xfec0
+ stwbrx r3, r0, r4
+ sync
+ lis r4, 0xfee0
+ lwbrx r3, 0, r4
+ blr
+ .globl __pci_config_read_16
+__pci_config_read_16:
+ lis r4, 0xfec0
+ andi. r5, r3, 2
+ stwbrx r3, r0, r4
+ sync
+ oris r4, r5, 0xfee0
+ lhbrx r3, r0, r4
+ blr
+ .globl __pci_config_read_8
+__pci_config_read_8:
+ lis r4, 0xfec0
+ andi. r5, r3, 3
+ stwbrx r3, r0, r4
+ sync
+ oris r4, r5, 0xfee0
+ lbz r3, 0(4)
+ blr
+ .globl __pci_config_write_32
+__pci_config_write_32:
+ lis r5, 0xfec0
+ stwbrx r3, r0, r5
+ sync
+ lis r5, 0xfee0
+ stwbrx r4, r0, r5
+ sync
+ blr
+ .globl __pci_config_write_16
+__pci_config_write_16:
+ lis r5, 0xfec0
+ andi. r6, r3, 2
+ stwbrx r3, r0, 5
+ sync
+ oris r5, r6, 0xfee0
+ sthbrx r4, r0, r5
+ sync
+ blr
+ .globl __pci_config_write_8
+__pci_config_write_8:
+ lis r5, 0xfec0
+ andi. r6, r3, 3
+ stwbrx r3, r0, r5
+ sync
+ oris r5, r6, 0xfee0
+ stb r4, 0(r5)
+ sync
+ blr
+ .globl in_8
+in_8:
+ oris r3, r3, 0xfe00
+ lbz r3,0(r3)
+ blr
+ .globl in_16
+in_16:
+ oris r3, r3, 0xfe00
+ lhbrx r3, 0, r3
+ blr
+ .globl in_16_ne
+in_16_ne:
+ oris r3, r3, 0xfe00
+ lhzx r3, 0, r3
+ blr
+ .globl in_32
+in_32:
+ oris r3, r3, 0xfe00
+ lwbrx r3, 0, r3
+ blr
+ .globl out_8
+out_8:
+ oris r3, r3, 0xfe00
+ stb r4, 0(r3)
+ eieio
+ blr
+ .globl out_16
+out_16:
+ oris r3, r3, 0xfe00
+ sthbrx r4, 0, r3
+ eieio
+ blr
+ .globl out_16_ne
+out_16_ne:
+ oris r3, r3, 0xfe00
+ sth r4, 0(r3)
+ eieio
+ blr
+ .globl out_32
+out_32:
+ oris r3, r3, 0xfe00
+ stwbrx r4, 0, r3
+ eieio
+ blr
+ .globl read_8
+read_8:
+ lbz r3,0(r3)
+ blr
+ .globl read_16
+read_16:
+ lhbrx r3, 0, r3
+ blr
+ .globl read_32
+read_32:
+ lwbrx r3, 0, r3
+ blr
+ .globl read_32_ne
+read_32_ne:
+ lwz r3, 0(r3)
+ blr
+ .globl write_8
+write_8:
+ stb r4, 0(r3)
+ eieio
+ blr
+ .globl write_16
+write_16:
+ sthbrx r4, 0, r3
+ eieio
+ blr
+ .globl write_32
+write_32:
+ stwbrx r4, 0, r3
+ eieio
+ blr
+ .globl write_32_ne
+write_32_ne:
+ stw r4, 0(r3)
+ eieio
+ blr
+
+
+.globl early_init_f
+
+early_init_f:
+ mflr r11
+ lis r10, 0x8000
+
+ /* PCI Latency Timer */
+ li r4, 0x0d
+ ori r3, r10, PLTR@l
+ bl __pci_config_write_8
+
+ /* Cache Line Size */
+ li r4, 0x08
+ ori r3, r10, PCLSR@l
+ bl __pci_config_write_8
+
+ /* PCI Cmd */
+ li r4, 6
+ ori r3, r10, PCICR@l
+ bl __pci_config_write_16
+
+#if 1
+ /* PCI Stat */
+ ori r3, r10, PCISR@l
+ bl __pci_config_read_16
+ ori r4, r4, 0xffff
+ ori r3, r10, PCISR@l
+ bl __pci_config_write_16
+#endif
+
+ /* PICR1 */
+ lis r4, 0xff14
+ ori r4, r4, 0x1b98
+ ori r3, r10, PICR1@l
+ bl __pci_config_write_32
+
+
+ /* PICR2 */
+ lis r4, 0x0404
+ ori r4, r4, 0x0004
+ ori r3, r10, PICR2@l
+ bl __pci_config_write_32
+
+ /* MIOCR1 */
+ li r4, 0x04
+ ori r3, r10, MIOCR1@l
+ bl __pci_config_write_8
+
+ /* For the MPC8245, set register 77 to %00100000 (see Errata #15) */
+ /* SDRAM_CLK_DEL (0x77)*/
+ li r4, 0x10
+ ori r3, r10, MIOCR2@l
+ bl __pci_config_write_8
+
+ /* EUMBBAR */
+ lis r4, 0xfc00
+ ori r3, r10, EUMBBAR@l
+ bl __pci_config_write_32
+
+ /* AMBOR */
+
+ /* Even if Address Map B is not being used (though it should),
+ * the memory DLL needs to be cleared/set/cleared before using memory.
+ */
+
+ ori r3, r10, AMBOR@l
+ bl __pci_config_read_8 /* get Current bits */
+
+ andi. r4, r4, 0xffdf
+ ori r3, r10, AMBOR@l
+ bl __pci_config_write_16 /* Clear DLL_RESET */
+
+ ori r4, r4, 0x0020
+ ori r3, r10, AMBOR@l
+ bl __pci_config_write_16 /* Set DLL_RESET */
+
+ andi. r4, r4, 0xffdf
+ ori r3, r10, AMBOR@l
+ bl __pci_config_write_16 /* Clear DLL_RESET */
+
+ /* ERCR1 */
+ lis r4, 0x8040 /* Enable RCS2, use supplied timings */
+ ori r4, r4, 0x8000
+ ori r3, r10, ERCR1@l
+ bl __pci_config_write_32
+
+ /* ERCR2 */
+ lis r4, 0x0000 /* Disable RCS3 parms */
+ ori r4, r4, 0x0000
+ ori r3, r10, ERCR2@l
+ bl __pci_config_write_32
+
+ /* ERCR3 */
+ lis r4, 0x0000 /* RCS3 at 0x70000000, 64K bytes */
+ ori r4, r4, 0x0004
+ ori r3, r10, ERCR2@l
+ bl __pci_config_write_32
+
+ /* Preserve memgo bit */
+ /* MCCR1 */
+
+/* lis r4, 0x75a8 / Safe Local ROM = 11+3 clocks */
+ lis r4, 0x75a0 /* Safe Local ROM = 11+3 clocks */
+/* lis r4, 0x73a0 / Fast Local ROM = 7+3 clocks */
+/* oris r4, r4, 0x0010 / Burst ROM/Flash enable */
+/* oris r4, r4, 0x0004 / Self-refresh enable */
+
+/* ori r4,r4,0xFFFF / 16Mbit 2bank SDRAM */
+/* ori r4,r4,0xAAAA / 256Mbit 4bank SDRAM (8245 only) */
+/* ori r4,r4,0x5555 / 64Mbit 2bank SDRAM */
+ ori r4,r4,0x0000 /* 64Mbit 4bank SDRAM */
+
+ ori r3, r10, MCCR1@l
+ bl __pci_config_write_32
+
+ /* MCCR2 */
+
+ lis r4,0x0000
+/* oris r4,r4,0x4000 / TS_WAIT_TIMER = 3 clocks */
+ oris r4,r4,0x1000 /* ASRISE = 8 clocks */
+ oris r4,r4,0x0080 /* ASFALL = 8 clocks */
+/* oris r4,r4,0x0010 / SDRAM Parity (else ECC) */
+/* oris r4,r4,0x0008 / Write parity check */
+/* oris r4,r4,0x0004 / SDRAM inline reads */
+
+
+/* Select a refresh rate; it needs to match the bus speed; if too */
+/* slow, data may be lost; if too fast, performance is lost. We */
+/* use the fastest value so we run at all speeds. */
+/* Refresh = (15600ns/busclk) - (213 (see UM)). */
+
+/* ori r4,r4,0x1d2c / 133 MHz mem bus = 1867 */
+/* ori r4,r4,0x150c / 100 MHz mem bus = 1347 */
+/* ori r4,r4,0x10fc / 83 MHz mem bus = 1087 */
+/* ori r4,r4,0x0cc4 / 66 MHz mem bus = 817 */
+ ori r4,r4,0x04cc /* 33 MHz mem bus (SAFE) = 307 */
+/* ori r4,r4,0x0002 / Reserve a page */
+/* ori r4,r4,0x0001 / RWM parity */
+
+ ori r3, r10, MCCR2@l
+ bl __pci_config_write_32
+
+
+ /* MCCR3 */
+ lis r4,0x0000 /* BSTOPRE_M = 7 (see A/N) */
+ oris r4,r4,0x0500 /* REFREC = 8 clocks */
+ ori r3, r10, MCCR3@l
+ bl __pci_config_write_32
+
+ /* MCCR4 */ /* Turn on registered buffer mode */
+ lis r4, 0x2000 /* PRETOACT = 3 clocks */
+ oris r4,r4,0x0400 /* ACTOPRE = 5 clocks */
+/* oris r4,r4,0x0080 / Enable 8-beat burst (32-bit bus) */
+/* oris r4,r4,0x0040 / Enable Inline ECC/Parity */
+ oris r4,r4,0x0020 /* EXTROM enabled */
+ oris r4,r4,0x0010 /* Registered buffers */
+/* oris r4,r4,0x0000 / BSTOPRE_U = 0 (see A/N) */
+ oris r4,r4,0x0002 /* DBUS_SIZ[2] (8 bit on RCS1) */
+
+/* ori r4,r4,0x8000 / Registered DIMMs */
+ ori r4,r4,0x2000 /*CAS Latency (CL=3) (see RDLAT) */
+/* ori r4,r4,0x2000 / CAS Latency (CL=2) (see RDLAT) */
+/* ori r4,r4,0x0300 / Sequential wrap/8-beat burst */
+ ori r4,r4,0x0200 /* Sequential wrap/4-beat burst */
+ ori r4,r4,0x0030 /* ACTORW = 3 clocks */
+ ori r4,r4,0x0009 /* BSTOPRE_L = 9 (see A/N) */
+
+ ori r3, r10, MCCR4@l
+ bl __pci_config_write_32
+
+ /* MSAR1 */
+ lis r4, 0xc0804000@h
+ ori r4, r4, 0xc0804000@l
+ ori r3, r10, MSAR1@l
+ bl __pci_config_write_32
+
+ /* MSAR2 */
+ lis r4, 0xc0804000@h
+ ori r4, r4, 0xc0804000@l
+ ori r3, r10, MSAR2@l
+ bl __pci_config_write_32
+
+ /* MESAR1 */
+ lis r4, 0x00000000@h
+ ori r4, r4, 0x00000000@l
+ ori r3, r10, EMSAR1@l
+ bl __pci_config_write_32
+
+ /* MESAR2 */
+ lis r4, 0x01010101@h
+ ori r4, r4, 0x01010101@l
+ ori r3, r10, EMSAR2@l
+ bl __pci_config_write_32
+
+ /* MEAR1 */
+ lis r4, 0xffbf7f3f@h
+ ori r4, r4, 0xffbf7f3f@l
+ ori r3, r10, MEAR1@l
+ bl __pci_config_write_32
+
+ /* MEAR2 */
+ lis r4, 0xffbf7f3f@h
+ ori r4, r4, 0xffbf7f3f@l
+ ori r3, r10, MEAR2@l
+ bl __pci_config_write_32
+
+ /* MEEAR1 */
+ lis r4, 0x00000000@h
+ ori r4, r4, 0x00000000@l
+ ori r3, r10, EMEAR1@l
+ bl __pci_config_write_32
+
+ /* MEEAR2 */
+ lis r4, 0x01010101@h
+ ori r4, r4, 0x01010101@l
+ ori r3, r10, EMEAR2@l
+ bl __pci_config_write_32
+
+ /* ODCR */
+ li r4, 0x7f
+ ori r3, r10, ODCR@l
+ bl __pci_config_write_8
+
+ /* MBER */
+ li r4, 0x01
+ ori r3, r10, MBER@l
+ bl __pci_config_write_8
+
+ /* Page CTR aka PGMAX */
+ li r4, 0x32
+ ori r3, r10, 0x70
+ bl __pci_config_write_8
+
+#if 0
+ /* CLK Drive */
+ ori r4, r10, 0xfc01 /* Top bit will be ignored */
+ ori r3, r10, 0x74
+ bl __pci_config_write_16
+#endif
+
+ /* delay */
+ lis r7, 1
+ mtctr r7
+label1: bdnz label1
+
+ /* Set memgo bit */
+ /* MCCR1 */
+ ori r3, r10, MCCR1@l
+ bl __pci_config_read_32
+ lis r7, 0x0008
+ or r4, r3, r7
+ ori r3, r10, MCCR1@l
+ bl __pci_config_write_32
+
+ /* delay again */
+ lis r7, 1
+ mtctr r7
+label2: bdnz label2
+#if 0
+/* DEBUG: Infinite loop, write then read */
+loop:
+ lis r7, 0xffff
+ mtctr r7
+ li r3, 0x5004
+ lis r4, 0xa0a0
+ ori r4, r4, 0x5050
+ bl write_32_ne
+ li r3, 0x5004
+ bl read_32_ne
+ bdnz loop
+#endif
+ mtlr r11
+ blr
+#endif
diff --git a/u-boot/board/bmw/flash.c b/u-boot/board/bmw/flash.c
new file mode 100644
index 0000000..57ffe08
--- /dev/null
+++ b/u-boot/board/bmw/flash.c
@@ -0,0 +1,779 @@
+/*
+ * (C) Copyright 2000
+ * 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 <common.h>
+#include <mpc824x.h>
+#include <asm/processor.h>
+#include <asm/pci_io.h>
+
+#define ROM_CS0_START 0xFF800000
+#define ROM_CS1_START 0xFF000000
+
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+#if defined(CONFIG_ENV_IS_IN_FLASH)
+# ifndef CONFIG_ENV_ADDR
+# define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
+# endif
+# ifndef CONFIG_ENV_SIZE
+# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
+# endif
+# ifndef CONFIG_ENV_SECT_SIZE
+# define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE
+# endif
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static int write_word (flash_info_t * info, ulong dest, ulong data);
+
+#if 0
+static void flash_get_offsets (ulong base, flash_info_t * info);
+#endif /* 0 */
+
+/*flash command address offsets*/
+
+#if 0
+#define ADDR0 (0x555)
+#define ADDR1 (0x2AA)
+#define ADDR3 (0x001)
+#else
+#define ADDR0 (0xAAA)
+#define ADDR1 (0x555)
+#define ADDR3 (0x001)
+#endif
+
+#define FLASH_WORD_SIZE unsigned char
+
+/*-----------------------------------------------------------------------
+ */
+
+#if 0
+static int byte_parity_odd (unsigned char x) __attribute__ ((const));
+#endif /* 0 */
+static unsigned long flash_id (unsigned char mfct, unsigned char chip)
+ __attribute__ ((const));
+
+typedef struct {
+ FLASH_WORD_SIZE extval;
+ unsigned short intval;
+} map_entry;
+
+#if 0
+static int byte_parity_odd (unsigned char x)
+{
+ x ^= x >> 4;
+ x ^= x >> 2;
+ x ^= x >> 1;
+ return (x & 0x1) != 0;
+}
+#endif /* 0 */
+
+
+static unsigned long flash_id (unsigned char mfct, unsigned char chip)
+{
+ static const map_entry mfct_map[] = {
+ {(FLASH_WORD_SIZE) AMD_MANUFACT,
+ (unsigned short) ((unsigned long) FLASH_MAN_AMD >> 16)},
+ {(FLASH_WORD_SIZE) FUJ_MANUFACT,
+ (unsigned short) ((unsigned long) FLASH_MAN_FUJ >> 16)},
+ {(FLASH_WORD_SIZE) STM_MANUFACT,
+ (unsigned short) ((unsigned long) FLASH_MAN_STM >> 16)},
+ {(FLASH_WORD_SIZE) MT_MANUFACT,
+ (unsigned short) ((unsigned long) FLASH_MAN_MT >> 16)},
+ {(FLASH_WORD_SIZE) INTEL_MANUFACT,
+ (unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)},
+ {(FLASH_WORD_SIZE) INTEL_ALT_MANU,
+ (unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)}
+ };
+
+ static const map_entry chip_map[] = {
+ {AMD_ID_F040B, FLASH_AM040},
+ {(FLASH_WORD_SIZE) STM_ID_x800AB, FLASH_STM800AB}
+ };
+
+ const map_entry *p;
+ unsigned long result = FLASH_UNKNOWN;
+
+ /* find chip id */
+ for (p = &chip_map[0];
+ p < &chip_map[sizeof chip_map / sizeof chip_map[0]]; p++)
+ if (p->extval == chip) {
+ result = FLASH_VENDMASK | p->intval;
+ break;
+ }
+
+ /* find vendor id */
+ for (p = &mfct_map[0];
+ p < &mfct_map[sizeof mfct_map / sizeof mfct_map[0]]; p++)
+ if (p->extval == mfct) {
+ result &= ~FLASH_VENDMASK;
+ result |= (unsigned long) p->intval << 16;
+ break;
+ }
+
+ return result;
+}
+
+
+unsigned long flash_init (void)
+{
+ unsigned long i;
+ unsigned char j;
+ static const ulong flash_banks[] = CONFIG_SYS_FLASH_BANKS;
+
+ /* Init: no FLASHes known */
+ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
+ flash_info_t *const pflinfo = &flash_info[i];
+
+ pflinfo->flash_id = FLASH_UNKNOWN;
+ pflinfo->size = 0;
+ pflinfo->sector_count = 0;
+ }
+
+ for (i = 0; i < sizeof flash_banks / sizeof flash_banks[0]; i++) {
+ flash_info_t *const pflinfo = &flash_info[i];
+ const unsigned long base_address = flash_banks[i];
+ volatile FLASH_WORD_SIZE *const flash =
+ (FLASH_WORD_SIZE *) base_address;
+#if 0
+ volatile FLASH_WORD_SIZE *addr2;
+#endif
+#if 0
+ /* write autoselect sequence */
+ flash[0x5555] = 0xaa;
+ flash[0x2aaa] = 0x55;
+ flash[0x5555] = 0x90;
+#else
+ flash[0xAAA << (3 * i)] = 0xaa;
+ flash[0x555 << (3 * i)] = 0x55;
+ flash[0xAAA << (3 * i)] = 0x90;
+#endif
+ __asm__ __volatile__ ("sync");
+
+#if 0
+ pflinfo->flash_id = flash_id (flash[0x0], flash[0x1]);
+#else
+ pflinfo->flash_id =
+ flash_id (flash[0x0], flash[0x2 + 14 * i]);
+#endif
+
+ switch (pflinfo->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM040:
+ pflinfo->size = 0x00080000;
+ pflinfo->sector_count = 8;
+ for (j = 0; j < 8; j++) {
+ pflinfo->start[j] =
+ base_address + 0x00010000 * j;
+ pflinfo->protect[j] = flash[(j << 16) | 0x2];
+ }
+ break;
+ case FLASH_STM800AB:
+ pflinfo->size = 0x00100000;
+ pflinfo->sector_count = 19;
+ pflinfo->start[0] = base_address;
+ pflinfo->start[1] = base_address + 0x4000;
+ pflinfo->start[2] = base_address + 0x6000;
+ pflinfo->start[3] = base_address + 0x8000;
+ for (j = 1; j < 16; j++) {
+ pflinfo->start[j + 3] =
+ base_address + 0x00010000 * j;
+ }
+#if 0
+ /* check for protected sectors */
+ for (j = 0; j < pflinfo->sector_count; j++) {
+ /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+ /* D0 = 1 if protected */
+ addr2 = (volatile FLASH_WORD_SIZE
+ *) (pflinfo->start[j]);
+ if (pflinfo->flash_id & FLASH_MAN_SST)
+ pflinfo->protect[j] = 0;
+ else
+ pflinfo->protect[j] = addr2[2] & 1;
+ }
+#endif
+ break;
+ }
+ /* Protect monitor and environment sectors
+ */
+#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
+ flash_protect (FLAG_PROTECT_SET,
+ CONFIG_SYS_MONITOR_BASE,
+ CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
+ &flash_info[0]);
+#endif
+
+#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
+ flash_protect (FLAG_PROTECT_SET,
+ CONFIG_ENV_ADDR,
+ CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
+ &flash_info[0]);
+#endif
+
+ /* reset device to read mode */
+ flash[0x0000] = 0xf0;
+ __asm__ __volatile__ ("sync");
+ }
+
+ return flash_info[0].size + flash_info[1].size;
+}
+
+#if 0
+static void flash_get_offsets (ulong base, flash_info_t * info)
+{
+ int i;
+
+ /* set up sector start address table */
+ if (info->flash_id & FLASH_MAN_SST) {
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * 0x00010000);
+ } else if (info->flash_id & FLASH_BTYPE) {
+ /* set sector offsets for bottom boot block type */
+ info->start[0] = base + 0x00000000;
+ info->start[1] = base + 0x00004000;
+ info->start[2] = base + 0x00006000;
+ info->start[3] = base + 0x00008000;
+ for (i = 4; i < info->sector_count; i++) {
+ info->start[i] = base + (i * 0x00010000) - 0x00030000;
+ }
+ } else {
+ /* set sector offsets for top boot block type */
+ i = info->sector_count - 1;
+ info->start[i--] = base + info->size - 0x00004000;
+ info->start[i--] = base + info->size - 0x00006000;
+ info->start[i--] = base + info->size - 0x00008000;
+ for (; i >= 0; i--) {
+ info->start[i] = base + i * 0x00010000;
+ }
+ }
+
+}
+#endif /* 0 */
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+ static const char unk[] = "Unknown";
+ const char *mfct = unk, *type = unk;
+ unsigned int i;
+
+ if (info->flash_id != FLASH_UNKNOWN) {
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD:
+ mfct = "AMD";
+ break;
+ case FLASH_MAN_FUJ:
+ mfct = "FUJITSU";
+ break;
+ case FLASH_MAN_STM:
+ mfct = "STM";
+ break;
+ case FLASH_MAN_SST:
+ mfct = "SST";
+ break;
+ case FLASH_MAN_BM:
+ mfct = "Bright Microelectonics";
+ break;
+ case FLASH_MAN_INTEL:
+ mfct = "Intel";
+ break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM040:
+ type = "AM29F040B (512K * 8, uniform sector size)";
+ break;
+ case FLASH_AM400B:
+ type = "AM29LV400B (4 Mbit, bottom boot sect)";
+ break;
+ case FLASH_AM400T:
+ type = "AM29LV400T (4 Mbit, top boot sector)";
+ break;
+ case FLASH_AM800B:
+ type = "AM29LV800B (8 Mbit, bottom boot sect)";
+ break;
+ case FLASH_AM800T:
+ type = "AM29LV800T (8 Mbit, top boot sector)";
+ break;
+ case FLASH_AM160T:
+ type = "AM29LV160T (16 Mbit, top boot sector)";
+ break;
+ case FLASH_AM320B:
+ type = "AM29LV320B (32 Mbit, bottom boot sect)";
+ break;
+ case FLASH_AM320T:
+ type = "AM29LV320T (32 Mbit, top boot sector)";
+ break;
+ case FLASH_STM800AB:
+ type = "M29W800AB (8 Mbit, bottom boot sect)";
+ break;
+ case FLASH_SST800A:
+ type = "SST39LF/VF800 (8 Mbit, uniform sector size)";
+ break;
+ case FLASH_SST160A:
+ type = "SST39LF/VF160 (16 Mbit, uniform sector size)";
+ break;
+ }
+ }
+
+ printf ("\n Brand: %s Type: %s\n"
+ " Size: %lu KB in %d Sectors\n",
+ mfct, type, info->size >> 10, info->sector_count);
+
+ printf (" Sector Start Addresses:");
+
+ for (i = 0; i < info->sector_count; i++) {
+ unsigned long size;
+ unsigned int erased;
+ unsigned long *flash = (unsigned long *) info->start[i];
+
+ /*
+ * Check if whole sector is erased
+ */
+ size = (i != (info->sector_count - 1)) ?
+ (info->start[i + 1] - info->start[i]) >> 2 :
+ (info->start[0] + info->size - info->start[i]) >> 2;
+
+ for (flash = (unsigned long *) info->start[i], erased = 1;
+ (flash != (unsigned long *) info->start[i] + size)
+ && erased; flash++)
+ erased = *flash == ~0x0UL;
+
+ printf ("%s %08lX %s %s",
+ (i % 5) ? "" : "\n ",
+ info->start[i],
+ erased ? "E" : " ", info->protect[i] ? "RO" : " ");
+ }
+
+ puts ("\n");
+ return;
+}
+
+#if 0
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+ulong flash_get_size (vu_long * addr, flash_info_t * info)
+{
+ short i;
+ FLASH_WORD_SIZE value;
+ ulong base = (ulong) addr;
+ volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;
+
+ printf ("flash_get_size: \n");
+ /* Write auto select command: read Manufacturer ID */
+ eieio ();
+ addr2[ADDR0] = (FLASH_WORD_SIZE) 0xAA;
+ addr2[ADDR1] = (FLASH_WORD_SIZE) 0x55;
+ addr2[ADDR0] = (FLASH_WORD_SIZE) 0x90;
+ value = addr2[0];
+
+ switch (value) {
+ case (FLASH_WORD_SIZE) AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+ case (FLASH_WORD_SIZE) FUJ_MANUFACT:
+ info->flash_id = FLASH_MAN_FUJ;
+ break;
+ case (FLASH_WORD_SIZE) SST_MANUFACT:
+ info->flash_id = FLASH_MAN_SST;
+ break;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return (0); /* no or unknown flash */
+ }
+ printf ("recognised manufacturer");
+
+ value = addr2[ADDR3]; /* device ID */
+ debug ("\ndev_code=%x\n", value);
+
+ switch (value) {
+ case (FLASH_WORD_SIZE) AMD_ID_LV400T:
+ info->flash_id += FLASH_AM400T;
+ info->sector_count = 11;
+ info->size = 0x00080000;
+ break; /* => 0.5 MB */
+
+ case (FLASH_WORD_SIZE) AMD_ID_LV400B:
+ info->flash_id += FLASH_AM400B;
+ info->sector_count = 11;
+ info->size = 0x00080000;
+ break; /* => 0.5 MB */
+
+ case (FLASH_WORD_SIZE) AMD_ID_LV800T:
+ info->flash_id += FLASH_AM800T;
+ info->sector_count = 19;
+ info->size = 0x00100000;
+ break; /* => 1 MB */
+
+ case (FLASH_WORD_SIZE) AMD_ID_LV800B:
+ info->flash_id += FLASH_AM800B;
+ info->sector_count = 19;
+ info->size = 0x00100000;
+ break; /* => 1 MB */
+
+ case (FLASH_WORD_SIZE) AMD_ID_LV160T:
+ info->flash_id += FLASH_AM160T;
+ info->sector_count = 35;
+ info->size = 0x00200000;
+ break; /* => 2 MB */
+
+ case (FLASH_WORD_SIZE) AMD_ID_LV160B:
+ info->flash_id += FLASH_AM160B;
+ info->sector_count = 35;
+ info->size = 0x00200000;
+ break; /* => 2 MB */
+
+ case (FLASH_WORD_SIZE) SST_ID_xF800A:
+ info->flash_id += FLASH_SST800A;
+ info->sector_count = 16;
+ info->size = 0x00100000;
+ break; /* => 1 MB */
+
+ case (FLASH_WORD_SIZE) SST_ID_xF160A:
+ info->flash_id += FLASH_SST160A;
+ info->sector_count = 32;
+ info->size = 0x00200000;
+ break; /* => 2 MB */
+
+ case (FLASH_WORD_SIZE) AMD_ID_F040B:
+ info->flash_id += FLASH_AM040;
+ info->sector_count = 8;
+ info->size = 0x00080000;
+ break; /* => 0.5 MB */
+
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ return (0); /* => no or unknown flash */
+
+ }
+
+ printf ("flash id %lx; sector count %x, size %lx\n", info->flash_id,
+ info->sector_count, info->size);
+ /* set up sector start address table */
+ if (info->flash_id & FLASH_MAN_SST) {
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * 0x00010000);
+ } else if (info->flash_id & FLASH_BTYPE) {
+ /* set sector offsets for bottom boot block type */
+ info->start[0] = base + 0x00000000;
+ info->start[1] = base + 0x00004000;
+ info->start[2] = base + 0x00006000;
+ info->start[3] = base + 0x00008000;
+ for (i = 4; i < info->sector_count; i++) {
+ info->start[i] = base + (i * 0x00010000) - 0x00030000;
+ }
+ } else {
+ /* set sector offsets for top boot block type */
+ i = info->sector_count - 1;
+ info->start[i--] = base + info->size - 0x00004000;
+ info->start[i--] = base + info->size - 0x00006000;
+ info->start[i--] = base + info->size - 0x00008000;
+ for (; i >= 0; i--) {
+ info->start[i] = base + i * 0x00010000;
+ }
+ }
+
+ /* 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 */
+ addr2 = (volatile FLASH_WORD_SIZE *) (info->start[i]);
+ if (info->flash_id & FLASH_MAN_SST)
+ info->protect[i] = 0;
+ else
+ info->protect[i] = addr2[2] & 1;
+ }
+
+ /*
+ * Prevent writes to uninitialized FLASH.
+ */
+ if (info->flash_id != FLASH_UNKNOWN) {
+ addr2 = (FLASH_WORD_SIZE *) info->start[0];
+ *addr2 = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
+ }
+
+ return (info->size);
+}
+
+#endif
+
+
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+ volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
+ int flag, prot, sect, l_sect;
+ ulong start, now, last;
+ unsigned char sh8b;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("- missing\n");
+ } else {
+ printf ("- no sectors to erase\n");
+ }
+ return 1;
+ }
+
+ if ((info->flash_id == FLASH_UNKNOWN) ||
+ (info->flash_id > (FLASH_MAN_STM | FLASH_AMD_COMP))) {
+ printf ("Can't erase unknown flash type - aborted\n");
+ 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 {
+ printf ("\n");
+ }
+
+ l_sect = -1;
+
+ /* Check the ROM CS */
+ if ((info->start[0] >= ROM_CS1_START)
+ && (info->start[0] < ROM_CS0_START))
+ sh8b = 3;
+ else
+ sh8b = 0;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts ();
+
+ addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00AA00AA;
+ addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE) 0x00550055;
+ addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00800080;
+ addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00AA00AA;
+ addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE) 0x00550055;
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect <= s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ addr = (FLASH_WORD_SIZE *) (info->start[0] + ((info->
+ start
+ [sect]
+ -
+ info->
+ start
+ [0]) <<
+ sh8b));
+ if (info->flash_id & FLASH_MAN_SST) {
+ addr[ADDR0 << sh8b] =
+ (FLASH_WORD_SIZE) 0x00AA00AA;
+ addr[ADDR1 << sh8b] =
+ (FLASH_WORD_SIZE) 0x00550055;
+ addr[ADDR0 << sh8b] =
+ (FLASH_WORD_SIZE) 0x00800080;
+ addr[ADDR0 << sh8b] =
+ (FLASH_WORD_SIZE) 0x00AA00AA;
+ addr[ADDR1 << sh8b] =
+ (FLASH_WORD_SIZE) 0x00550055;
+ addr[0] = (FLASH_WORD_SIZE) 0x00500050; /* block erase */
+ udelay (30000); /* wait 30 ms */
+ } else
+ addr[0] = (FLASH_WORD_SIZE) 0x00300030; /* sector erase */
+ 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 = (FLASH_WORD_SIZE *) (info->start[0] + ((info->start[l_sect] -
+ info->
+ start[0]) << sh8b));
+ while ((addr[0] & (FLASH_WORD_SIZE) 0x00800080) !=
+ (FLASH_WORD_SIZE) 0x00800080) {
+ if ((now = get_timer (start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
+ printf ("Timeout\n");
+ return 1;
+ }
+ /* show that we're waiting */
+ if ((now - last) > 1000) { /* every second */
+ serial_putc ('.');
+ last = now;
+ }
+ }
+
+ DONE:
+ /* reset to read mode */
+ addr = (FLASH_WORD_SIZE *) info->start[0];
+ addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
+
+ printf (" 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)
+{
+ volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) info->start[0];
+ volatile FLASH_WORD_SIZE *dest2;
+ volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
+ ulong start;
+ int flag;
+ int i;
+ unsigned char sh8b;
+
+ /* Check the ROM CS */
+ if ((info->start[0] >= ROM_CS1_START)
+ && (info->start[0] < ROM_CS0_START))
+ sh8b = 3;
+ else
+ sh8b = 0;
+
+ dest2 = (FLASH_WORD_SIZE *) (((dest - info->start[0]) << sh8b) +
+ info->start[0]);
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest2 & (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
+ return (2);
+ }
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts ();
+
+ for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) {
+ addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00AA00AA;
+ addr2[ADDR1 << sh8b] = (FLASH_WORD_SIZE) 0x00550055;
+ addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00A000A0;
+
+ dest2[i << sh8b] = data2[i];
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts ();
+
+ /* data polling for D7 */
+ start = get_timer (0);
+ while ((dest2[i << sh8b] & (FLASH_WORD_SIZE) 0x00800080) !=
+ (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
+ if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
+ return (1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/u-boot/board/bmw/m48t59y.c b/u-boot/board/bmw/m48t59y.c
new file mode 100644
index 0000000..4e83b90
--- /dev/null
+++ b/u-boot/board/bmw/m48t59y.c
@@ -0,0 +1,324 @@
+/*
+ * 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.
+ */
+int
+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
+
+ return 0;
+}
+
+int 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
+
+ return 0;
+}
+
+void
+rtc_reset (void)
+{
+ m48_tod_init();
+}
diff --git a/u-boot/board/bmw/m48t59y.h b/u-boot/board/bmw/m48t59y.h
new file mode 100644
index 0000000..717300d
--- /dev/null
+++ b/u-boot/board/bmw/m48t59y.h
@@ -0,0 +1,57 @@
+/*
+ * 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
+ */
+
+#ifndef __M48_T59_Y_H
+#define __M48_T59_Y_H
+
+/*
+ * M48 T59Y -Timekeeping Battery backed SRAM.
+ */
+
+int m48_tod_init(void);
+
+int m48_tod_set(int year,
+ int month,
+ int day,
+ int hour,
+ int minute,
+ int second);
+
+int m48_tod_get(int *year,
+ int *month,
+ int *day,
+ int *hour,
+ int *minute,
+ int *second);
+
+int m48_tod_get_second(void);
+
+void m48_watchdog_arm(int usec);
+
+#endif /*!__M48_T59_Y_H */
diff --git a/u-boot/board/bmw/ns16550.c b/u-boot/board/bmw/ns16550.c
new file mode 100644
index 0000000..be455bb
--- /dev/null
+++ b/u-boot/board/bmw/ns16550.c
@@ -0,0 +1,57 @@
+/*
+ * COM1 NS16550 support
+ * originally from linux source (arch/powerpc/boot/ns16550.c)
+ * modified to use CONFIG_SYS_ISA_MEM and new defines
+ */
+
+#include <config.h>
+#include "ns16550.h"
+
+typedef struct NS16550 *NS16550_t;
+
+const NS16550_t COM_PORTS[] =
+ { (NS16550_t) ((CONFIG_SYS_EUMB_ADDR) + 0x4500),
+(NS16550_t) ((CONFIG_SYS_EUMB_ADDR) + 0x4600) };
+
+volatile struct NS16550 *NS16550_init (int chan, int baud_divisor)
+{
+ volatile struct NS16550 *com_port;
+
+ com_port = (struct NS16550 *) COM_PORTS[chan];
+ com_port->ier = 0x00;
+ com_port->lcr = LCR_BKSE; /* Access baud rate */
+ com_port->dll = baud_divisor & 0xff; /* 9600 baud */
+ com_port->dlm = (baud_divisor >> 8) & 0xff;
+ com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */
+ com_port->mcr = MCR_RTS; /* RTS/DTR */
+ com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; /* Clear & enable FIFOs */
+ return (com_port);
+}
+
+void NS16550_reinit (volatile struct NS16550 *com_port, int baud_divisor)
+{
+ com_port->ier = 0x00;
+ com_port->lcr = LCR_BKSE; /* Access baud rate */
+ com_port->dll = baud_divisor & 0xff; /* 9600 baud */
+ com_port->dlm = (baud_divisor >> 8) & 0xff;
+ com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */
+ com_port->mcr = MCR_RTS; /* RTS/DTR */
+ com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; /* Clear & enable FIFOs */
+}
+
+void NS16550_putc (volatile struct NS16550 *com_port, unsigned char c)
+{
+ while ((com_port->lsr & LSR_THRE) == 0);
+ com_port->thr = c;
+}
+
+unsigned char NS16550_getc (volatile struct NS16550 *com_port)
+{
+ while ((com_port->lsr & LSR_DR) == 0);
+ return (com_port->rbr);
+}
+
+int NS16550_tstc (volatile struct NS16550 *com_port)
+{
+ return ((com_port->lsr & LSR_DR) != 0);
+}
diff --git a/u-boot/board/bmw/ns16550.h b/u-boot/board/bmw/ns16550.h
new file mode 100644
index 0000000..8aa251d
--- /dev/null
+++ b/u-boot/board/bmw/ns16550.h
@@ -0,0 +1,79 @@
+/*
+ * NS16550 Serial Port
+ * originally from linux source (arch/powerpc/boot/ns16550.h)
+ * modified slightly to
+ * have addresses as offsets from CONFIG_SYS_ISA_BASE
+ * added a few more definitions
+ * added prototypes for ns16550.c
+ * reduced no of com ports to 2
+ * modifications (c) Rob Taylor, Flying Pig Systems. 2000.
+ * further modified to support the 8245 duart
+ * modifications (c) Paul Jimenez, Musenki, Inc. 2001.
+ */
+
+
+struct NS16550 {
+ unsigned char rbrthrdlb; /* 0 */
+ unsigned char ierdmb; /* 1 */
+ unsigned char iirfcrafr; /* 2 */
+ unsigned char lcr; /* 3 */
+ unsigned char mcr; /* 4 */
+ unsigned char lsr; /* 5 */
+ unsigned char msr; /* 6 */
+ unsigned char scr; /* 7 */
+ unsigned char reserved[2]; /* 8 & 9 */
+ unsigned char dsr; /* 10 */
+ unsigned char dcr; /* 11 */
+};
+
+
+#define rbr rbrthrdlb
+#define thr rbrthrdlb
+#define dll rbrthrdlb
+#define ier ierdmb
+#define dlm ierdmb
+#define iir iirfcrafr
+#define fcr iirfcrafr
+#define afr iirfcrafr
+
+#define FCR_FIFO_EN 0x01 /*fifo enable */
+#define FCR_RXSR 0x02 /*reciever soft reset */
+#define FCR_TXSR 0x04 /*transmitter soft reset */
+#define FCR_DMS 0x08 /* DMA Mode Select */
+
+#define MCR_RTS 0x02 /* Readyu to Send */
+#define MCR_LOOP 0x10 /* Local loopback mode enable */
+/* #define MCR_DTR 0x01 noton 8245 duart */
+/* #define MCR_DMA_EN 0x04 noton 8245 duart */
+/* #define MCR_TX_DFR 0x08 noton 8245 duart */
+
+#define LCR_WLS_MSK 0x03 /* character length slect mask */
+#define LCR_WLS_5 0x00 /* 5 bit character length */
+#define LCR_WLS_6 0x01 /* 6 bit character length */
+#define LCR_WLS_7 0x02 /* 7 bit character length */
+#define LCR_WLS_8 0x03 /* 8 bit character length */
+#define LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */
+#define LCR_PEN 0x08 /* Parity eneble */
+#define LCR_EPS 0x10 /* Even Parity Select */
+#define LCR_STKP 0x20 /* Stick Parity */
+#define LCR_SBRK 0x40 /* Set Break */
+#define LCR_BKSE 0x80 /* Bank select enable - aka DLAB on 8245 */
+
+#define LSR_DR 0x01 /* Data ready */
+#define LSR_OE 0x02 /* Overrun */
+#define LSR_PE 0x04 /* Parity error */
+#define LSR_FE 0x08 /* Framing error */
+#define LSR_BI 0x10 /* Break */
+#define LSR_THRE 0x20 /* Xmit holding register empty */
+#define LSR_TEMT 0x40 /* Xmitter empty */
+#define LSR_ERR 0x80 /* Error */
+
+/* useful defaults for LCR*/
+#define LCR_8N1 0x03
+
+
+volatile struct NS16550 *NS16550_init (int chan, int baud_divisor);
+void NS16550_putc (volatile struct NS16550 *com_port, unsigned char c);
+unsigned char NS16550_getc (volatile struct NS16550 *com_port);
+int NS16550_tstc (volatile struct NS16550 *com_port);
+void NS16550_reinit (volatile struct NS16550 *com_port, int baud_divisor);
diff --git a/u-boot/board/bmw/serial.c b/u-boot/board/bmw/serial.c
new file mode 100644
index 0000000..0c97f12
--- /dev/null
+++ b/u-boot/board/bmw/serial.c
@@ -0,0 +1,81 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.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 "ns16550.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if CONFIG_CONS_INDEX == 1
+static struct NS16550 *console =
+ (struct NS16550 *) (CONFIG_SYS_EUMB_ADDR + 0x4500);
+#elif CONFIG_CONS_INDEX == 2
+static struct NS16550 *console =
+ (struct NS16550 *) (CONFIG_SYS_EUMB_ADDR + 0x4500);
+#else
+#error no valid console defined
+#endif
+
+extern ulong get_bus_freq (ulong);
+
+int serial_init (void)
+{
+ int clock_divisor = gd->bus_clk / 16 / gd->baudrate;
+
+ NS16550_init (CONFIG_CONS_INDEX - 1, clock_divisor);
+
+ return (0);
+}
+
+void serial_putc (const char c)
+{
+ if (c == '\n') {
+ serial_putc ('\r');
+ }
+ NS16550_putc (console, c);
+}
+
+void serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+
+int serial_getc (void)
+{
+ return NS16550_getc (console);
+}
+
+int serial_tstc (void)
+{
+ return NS16550_tstc (console);
+}
+
+void serial_setbrg (void)
+{
+ int clock_divisor = get_bus_freq (0) / 16 / gd->baudrate;
+
+ NS16550_reinit (console, clock_divisor);
+}