diff options
author | H. Nikolaus Schaller <hns@goldelico.com> | 2012-03-26 20:55:28 +0200 |
---|---|---|
committer | H. Nikolaus Schaller <hns@goldelico.com> | 2012-03-26 20:55:28 +0200 |
commit | 92988a21ad4c4c9504295ccb580c9f806134471b (patch) | |
tree | 5effc9f14170112450de05c67dafbe8d5034d595 /u-boot/board/bmw | |
parent | ca2b506783b676c95762c54ea24dcfdaae1947c9 (diff) | |
download | bootable_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/Makefile | 50 | ||||
-rw-r--r-- | u-boot/board/bmw/README | 331 | ||||
-rw-r--r-- | u-boot/board/bmw/bmw.c | 159 | ||||
-rw-r--r-- | u-boot/board/bmw/bmw.h | 86 | ||||
-rw-r--r-- | u-boot/board/bmw/config.mk | 30 | ||||
-rw-r--r-- | u-boot/board/bmw/early_init.S | 1170 | ||||
-rw-r--r-- | u-boot/board/bmw/flash.c | 779 | ||||
-rw-r--r-- | u-boot/board/bmw/m48t59y.c | 324 | ||||
-rw-r--r-- | u-boot/board/bmw/m48t59y.h | 57 | ||||
-rw-r--r-- | u-boot/board/bmw/ns16550.c | 57 | ||||
-rw-r--r-- | u-boot/board/bmw/ns16550.h | 79 | ||||
-rw-r--r-- | u-boot/board/bmw/serial.c | 81 |
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); +} |