summaryrefslogtreecommitdiffstats
path: root/board
diff options
context:
space:
mode:
authorwdenk <wdenk>2002-11-03 00:24:07 +0000
committerwdenk <wdenk>2002-11-03 00:24:07 +0000
commitc609719b8d1b2dca590e0ed499016d041203e403 (patch)
tree7ea1755d80903ff972f312a249eb856061d40e15 /board
parent5b1d713721c3ea02549940133f09236783dda1f9 (diff)
downloadtalos-obmc-uboot-c609719b8d1b2dca590e0ed499016d041203e403.tar.gz
talos-obmc-uboot-c609719b8d1b2dca590e0ed499016d041203e403.zip
Initial revision
Diffstat (limited to 'board')
-rw-r--r--board/cogent/serial.c190
-rw-r--r--board/cu824/cu824.c119
-rw-r--r--board/dnp1110/u-boot.lds53
-rw-r--r--board/ebony/ebony.c301
-rw-r--r--board/ebony/init.S98
-rw-r--r--board/eltec/bab7xx/asm_init.S1487
-rw-r--r--board/eltec/bab7xx/el_srom.c292
-rw-r--r--board/eltec/bab7xx/u-boot.lds129
-rw-r--r--board/eltec/elppc/asm_init.S877
-rw-r--r--board/eltec/elppc/u-boot.lds129
-rw-r--r--board/ep7312/flash.c341
-rw-r--r--board/ep7312/u-boot.lds53
-rw-r--r--board/esd/common/fpga.c262
-rw-r--r--board/esd/common/pci.c202
-rw-r--r--board/esd/cpci405/cpci405.c451
-rw-r--r--board/esd/cpci440/cpci440.c140
-rw-r--r--board/esd/cpci440/init.S96
-rw-r--r--board/esd/pci405/pci405.c254
-rw-r--r--board/evb64260/eth_addrtbl.c225
-rw-r--r--board/evb64260/pci.c691
-rw-r--r--board/evb64260/sdram_init.c629
-rw-r--r--board/evb64260/serial.c191
-rw-r--r--board/gen860t/README142
-rw-r--r--board/gen860t/beeper.c213
-rw-r--r--board/gen860t/flash.c644
-rw-r--r--board/gen860t/fpga.c401
-rw-r--r--board/gen860t/gen860t.c299
-rw-r--r--board/gen860t/ioport.c276
-rw-r--r--board/gen860t/u-boot.lds135
-rw-r--r--board/impa7/flash.c365
-rw-r--r--board/impa7/u-boot.lds53
-rw-r--r--board/lart/u-boot.lds53
-rw-r--r--board/mbx8xx/mbx8xx.c379
-rw-r--r--board/ml2/serial.c131
-rw-r--r--board/mousse/pci.c283
-rw-r--r--board/mpl/common/common_util.c606
-rw-r--r--board/mpl/common/pci.c102
-rw-r--r--board/mpl/common/pci_parts.h192
-rw-r--r--board/mpl/mip405/Makefile49
-rw-r--r--board/mpl/pip405/Makefile52
-rw-r--r--board/musenki/musenki.c130
-rw-r--r--board/mvs1/Makefile40
-rw-r--r--board/netvia/Makefile40
-rw-r--r--board/netvia/netvia.c374
-rw-r--r--board/netvia/u-boot.lds132
-rw-r--r--board/netvia/u-boot.lds.debug131
-rw-r--r--board/oxc/flash.c372
-rw-r--r--board/oxc/oxc.c237
-rw-r--r--board/pcippc2/cpc710_init_ram.c254
-rw-r--r--board/pcippc2/cpc710_pci.c309
-rw-r--r--board/pcippc2/i2c.c257
-rw-r--r--board/pcippc2/pcippc2.c214
-rw-r--r--board/pn62/cmd_pn62.c164
-rw-r--r--board/pn62/misc.c235
-rw-r--r--board/pn62/pn62.c216
-rw-r--r--board/r360mpi/r360mpi.c423
-rw-r--r--board/sacsng/clkinit.c884
-rw-r--r--board/sacsng/ioconfig.h218
-rw-r--r--board/sandpoint/sandpoint.c127
-rw-r--r--board/shannon/u-boot.lds53
-rw-r--r--board/siemens/CCM/ccm.c440
-rw-r--r--board/siemens/CCM/fpga_ccm.c170
-rw-r--r--board/siemens/SCM/fpga_scm.c104
-rw-r--r--board/siemens/common/README27
-rw-r--r--board/siemens/common/fpga.c358
-rw-r--r--board/smdk2400/u-boot.lds54
-rw-r--r--board/smdk2410/smdk2410.c124
-rw-r--r--board/tqm8xx/flash.c569
-rw-r--r--board/tqm8xx/load_sernum_ethaddr.c105
-rw-r--r--board/trab/README.kbd44
-rw-r--r--board/trab/trab.c301
-rw-r--r--board/trab/u-boot.lds63
-rw-r--r--board/trab/vfd.c414
-rw-r--r--board/utx8245/utx8245.c152
-rw-r--r--board/w7o/flash.c941
-rw-r--r--board/w7o/fpga.c380
-rw-r--r--board/w7o/init.S264
-rw-r--r--board/w7o/post1.S745
-rw-r--r--board/w7o/post2.c109
-rw-r--r--board/w7o/vpd.c408
-rw-r--r--board/w7o/vpd.h135
-rw-r--r--board/w7o/w7o.c271
82 files changed, 22573 insertions, 0 deletions
diff --git a/board/cogent/serial.c b/board/cogent/serial.c
new file mode 100644
index 0000000000..4c200170d0
--- /dev/null
+++ b/board/cogent/serial.c
@@ -0,0 +1,190 @@
+/*
+ * Simple serial driver for Cogent motherboard serial ports
+ * for use during boot
+ */
+
+#include <common.h>
+#include <board/cogent/serial.h>
+
+#if (CMA_MB_CAPS & CMA_MB_CAP_SERPAR)
+
+#if (defined(CONFIG_8xx) && defined(CONFIG_8xx_CONS_NONE)) || \
+ (defined(CONFIG_8260) && defined(CONFIG_CONS_NONE))
+
+#if CONFIG_CONS_INDEX == 1
+#define CMA_MB_SERIAL_BASE CMA_MB_SERIALA_BASE
+#elif CONFIG_CONS_INDEX == 2
+#define CMA_MB_SERIAL_BASE CMA_MB_SERIALB_BASE
+#elif CONFIG_CONS_INDEX == 3 && (CMA_MB_CAPS & CMA_MB_CAP_SER2)
+#define CMA_MB_SERIAL_BASE CMA_MB_SER2A_BASE
+#elif CONFIG_CONS_INDEX == 4 && (CMA_MB_CAPS & CMA_MB_CAP_SER2)
+#define CMA_MB_SERIAL_BASE CMA_MB_SER2B_BASE
+#else
+#error CONFIG_CONS_INDEX must be configured for Cogent motherboard serial
+#endif
+
+int serial_init (void)
+{
+/* DECLARE_GLOBAL_DATA_PTR; */
+
+ cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE;
+
+ cma_mb_reg_write(&mbsp->ser_ier, 0x00); /* turn off interrupts */
+ serial_setbrg ();
+ cma_mb_reg_write(&mbsp->ser_lcr, 0x03); /* 8 data, 1 stop, no parity */
+ cma_mb_reg_write(&mbsp->ser_mcr, 0x03); /* RTS/DTR */
+ cma_mb_reg_write(&mbsp->ser_fcr, 0x07); /* Clear & enable FIFOs */
+
+ return (0);
+}
+
+void
+serial_setbrg (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE;
+ unsigned int divisor;
+ unsigned char lcr;
+
+ if ((divisor = br_to_div(gd->baudrate)) == 0)
+ divisor = DEFDIV;
+
+ lcr = cma_mb_reg_read(&mbsp->ser_lcr);
+ cma_mb_reg_write(&mbsp->ser_lcr, lcr|0x80);/* Access baud rate(set DLAB)*/
+ cma_mb_reg_write(&mbsp->ser_brl, divisor & 0xff);
+ cma_mb_reg_write(&mbsp->ser_brh, (divisor >> 8) & 0xff);
+ cma_mb_reg_write(&mbsp->ser_lcr, lcr); /* unset DLAB */
+}
+
+void
+serial_putc(const char c)
+{
+ cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE;
+
+ if (c == '\n')
+ serial_putc('\r');
+
+ while ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_THRE) == 0)
+ ;
+
+ cma_mb_reg_write(&mbsp->ser_thr, c);
+}
+
+void
+serial_puts(const char *s)
+{
+ while (*s != '\0')
+ serial_putc(*s++);
+}
+
+int
+serial_getc(void)
+{
+ cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE;
+
+ while ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_DR) == 0)
+ ;
+
+ return ((int)cma_mb_reg_read(&mbsp->ser_rhr) & 0x7f);
+}
+
+int
+serial_tstc(void)
+{
+ cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE;
+
+ return ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_DR) != 0);
+}
+
+#endif /* CONS_NONE */
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB) && \
+ defined(CONFIG_KGDB_NONE)
+
+#if CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
+#error Console and kgdb are on the same serial port - this is not supported
+#endif
+
+#if CONFIG_KGDB_INDEX == 1
+#define CMA_MB_KGDB_SER_BASE CMA_MB_SERIALA_BASE
+#elif CONFIG_KGDB_INDEX == 2
+#define CMA_MB_KGDB_SER_BASE CMA_MB_SERIALB_BASE
+#elif CONFIG_KGDB_INDEX == 3 && (CMA_MB_CAPS & CMA_MB_CAP_SER2)
+#define CMA_MB_KGDB_SER_BASE CMA_MB_SER2A_BASE
+#elif CONFIG_KGDB_INDEX == 4 && (CMA_MB_CAPS & CMA_MB_CAP_SER2)
+#define CMA_MB_KGDB_SER_BASE CMA_MB_SER2B_BASE
+#else
+#error CONFIG_KGDB_INDEX must be configured for Cogent motherboard serial
+#endif
+
+void
+kgdb_serial_init(void)
+{
+ cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_KGDB_SER_BASE;
+ unsigned int divisor;
+
+ if ((divisor = br_to_div(CONFIG_KGDB_BAUDRATE)) == 0)
+ divisor = DEFDIV;
+
+ cma_mb_reg_write(&mbsp->ser_ier, 0x00); /* turn off interrupts */
+ cma_mb_reg_write(&mbsp->ser_lcr, 0x80); /* Access baud rate(set DLAB)*/
+ cma_mb_reg_write(&mbsp->ser_brl, divisor & 0xff);
+ cma_mb_reg_write(&mbsp->ser_brh, (divisor >> 8) & 0xff);
+ cma_mb_reg_write(&mbsp->ser_lcr, 0x03); /* 8 data, 1 stop, no parity */
+ cma_mb_reg_write(&mbsp->ser_mcr, 0x03); /* RTS/DTR */
+ cma_mb_reg_write(&mbsp->ser_fcr, 0x07); /* Clear & enable FIFOs */
+
+ printf("[on cma10x serial port B] ");
+}
+
+void
+putDebugChar(int c)
+{
+ cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_KGDB_SER_BASE;
+
+ while ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_THRE) == 0)
+ ;
+
+ cma_mb_reg_write(&mbsp->ser_thr, c & 0xff);
+}
+
+void
+putDebugStr(const char *str)
+{
+ while (*str != '\0') {
+ if (*str == '\n')
+ putDebugChar('\r');
+ putDebugChar(*str++);
+ }
+}
+
+int
+getDebugChar(void)
+{
+ cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_KGDB_SER_BASE;
+
+ while ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_DR) == 0)
+ ;
+
+ return ((int)cma_mb_reg_read(&mbsp->ser_rhr) & 0x7f);
+}
+
+void
+kgdb_interruptible(int yes)
+{
+ cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_KGDB_SER_BASE;
+
+ if (yes == 1) {
+ printf("kgdb: turning serial ints on\n");
+ cma_mb_reg_write(&mbsp->ser_ier, 0xf);
+ }
+ else {
+ printf("kgdb: turning serial ints off\n");
+ cma_mb_reg_write(&mbsp->ser_ier, 0x0);
+ }
+}
+
+#endif /* KGDB && KGDB_NONE */
+
+#endif /* CAPS & SERPAR */
diff --git a/board/cu824/cu824.c b/board/cu824/cu824.c
new file mode 100644
index 0000000000..20aaea2f20
--- /dev/null
+++ b/board/cu824/cu824.c
@@ -0,0 +1,119 @@
+/*
+ * (C) Copyright 2001
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc824x.h>
+#include <asm/processor.h>
+#include <pci.h>
+
+#define BOARD_REV_REG 0xFE80002B
+
+int checkboard (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ char revision = *(volatile char *)(BOARD_REV_REG);
+ char buf[32];
+
+ puts ("Board: CU824 ");
+ printf("Revision %d ", revision);
+ printf("Local Bus at %s MHz\n", strmhz(buf, gd->bus_clk));
+
+ return 0;
+}
+
+long int initdram(int board_type)
+{
+ int i, cnt;
+ volatile uchar * base = CFG_SDRAM_BASE;
+ volatile ulong * addr;
+ ulong save[32];
+ ulong val, ret = 0;
+
+ for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) {
+ addr = (volatile ulong *)base + cnt;
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ addr = (volatile ulong *)base;
+ save[i] = *addr;
+ *addr = 0;
+
+ if (*addr != 0) {
+ *addr = save[i];
+ goto Done;
+ }
+
+ for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) {
+ addr = (volatile ulong *)base + cnt;
+ val = *addr;
+ *addr = save[--i];
+ if (val != ~cnt) {
+ ulong new_bank0_end = cnt * sizeof(long) - 1;
+ ulong mear1 = mpc824x_mpc107_getreg(MEAR1);
+ ulong emear1 = mpc824x_mpc107_getreg(EMEAR1);
+ mear1 = (mear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT);
+ emear1 = (emear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT);
+ mpc824x_mpc107_setreg(MEAR1, mear1);
+ mpc824x_mpc107_setreg(EMEAR1, emear1);
+
+ ret = cnt * sizeof(long);
+ goto Done;
+ }
+ }
+
+ ret = CFG_MAX_RAM_SIZE;
+Done:
+ return ret;
+}
+
+/*
+ * Initialize PCI Devices, report devices found.
+ */
+#ifndef CONFIG_PCI_PNP
+static struct pci_config_table pci_sandpoint_config_table[] = {
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_BUS(CFG_ETH_DEV_FN), PCI_DEV(CFG_ETH_DEV_FN), PCI_FUNC(CFG_ETH_DEV_FN),
+ pci_cfgfunc_config_device, { CFG_ETH_IOBASE,
+ 0,
+ PCI_COMMAND_IO | PCI_COMMAND_MASTER }},
+ { }
+};
+#endif
+
+struct pci_controller hose = {
+#ifndef CONFIG_PCI_PNP
+ config_table: pci_sandpoint_config_table,
+#endif
+};
+
+void pci_init(void)
+{
+ pci_mpc824x_init(&hose);
+}
diff --git a/board/dnp1110/u-boot.lds b/board/dnp1110/u-boot.lds
new file mode 100644
index 0000000000..f4b0ade273
--- /dev/null
+++ b/board/dnp1110/u-boot.lds
@@ -0,0 +1,53 @@
+/*
+ * (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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ cpu/sa1100/start.o (.text)
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ armboot_end_data = .;
+
+ . = ALIGN(4);
+ .bss : { *(.bss) }
+
+ armboot_end = .;
+}
diff --git a/board/ebony/ebony.c b/board/ebony/ebony.c
new file mode 100644
index 0000000000..723fad328c
--- /dev/null
+++ b/board/ebony/ebony.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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
+ */
+
+
+extern long int spd_sdram (void);
+
+#include <common.h>
+#include "ebony.h"
+#include <asm/processor.h>
+
+#define BOOT_SMALL_FLASH 32 /* 00100000 */
+#define FLASH_ONBD_N 2 /* 00000010 */
+#define FLASH_SRAM_SEL 1 /* 00000001 */
+
+long int fixed_sdram (void);
+
+int board_pre_init (void)
+{
+ uint reg;
+ unsigned char *fpga_base = (unsigned char *) CFG_FPGA_BASE;
+ unsigned char status;
+
+
+ /*--------------------------------------------------------------------
+ * Setup the external bus controller/chip selects
+ *-------------------------------------------------------------------*/
+ mtdcr (ebccfga, xbcfg);
+ reg = mfdcr (ebccfgd);
+ mtdcr (ebccfgd, reg | 0x04000000); /* Set ATC */
+
+ mtebc (pb1ap, 0x02815480); /* NVRAM/RTC */
+ mtebc (pb1cr, 0x48018000); /* BA=0x480 1MB R/W 8-bit */
+ mtebc (pb7ap, 0x01015280); /* FPGA registers */
+ mtebc (pb7cr, 0x48318000); /* BA=0x483 1MB R/W 8-bit */
+
+ /* read FPGA_REG0 and set the bus controller */
+ status = *fpga_base;
+ if ((status & BOOT_SMALL_FLASH) && !(status & FLASH_ONBD_N)) {
+ mtebc (pb0ap, 0x9b015480); /* FLASH/SRAM */
+ mtebc (pb0cr, 0xfff18000); /* BAS=0xfff 1MB R/W 8-bit */
+ mtebc (pb2ap, 0x9b015480); /* 4MB FLASH */
+ mtebc (pb2cr, 0xff858000); /* BAS=0xff8 4MB R/W 8-bit */
+ } else {
+ mtebc (pb0ap, 0x9b015480); /* 4MB FLASH */
+ mtebc (pb0cr, 0xffc58000); /* BAS=0xffc 4MB R/W 8-bit */
+
+ /* set CS2 if FLASH_ONBD_N == 0 */
+ if (!(status & FLASH_ONBD_N)) {
+ mtebc (pb2ap, 0x9b015480); /* FLASH/SRAM */
+ mtebc (pb2cr, 0xff818000); /* BAS=0xff8 4MB R/W 8-bit */
+ }
+ }
+
+ /*--------------------------------------------------------------------
+ * Setup the interrupt controller polarities, triggers, etc.
+ *-------------------------------------------------------------------*/
+ mtdcr (uic0sr, 0xffffffff); /* clear all */
+ mtdcr (uic0er, 0x00000000); /* disable all */
+ mtdcr (uic0cr, 0x00000009); /* SMI & UIC1 crit are critical */
+ mtdcr (uic0pr, 0xfffffe13); /* per ref-board manual */
+ mtdcr (uic0tr, 0x01c00008); /* per ref-board manual */
+ mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */
+ mtdcr (uic0sr, 0xffffffff); /* clear all */
+
+ mtdcr (uic1sr, 0xffffffff); /* clear all */
+ mtdcr (uic1er, 0x00000000); /* disable all */
+ mtdcr (uic1cr, 0x00000000); /* all non-critical */
+ mtdcr (uic1pr, 0xffffe0ff); /* per ref-board manual */
+ mtdcr (uic1tr, 0x00ffc000); /* per ref-board manual */
+ mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */
+ mtdcr (uic1sr, 0xffffffff); /* clear all */
+
+ return 0;
+}
+
+
+
+int checkboard (void)
+{
+ sys_info_t sysinfo;
+
+ get_sys_info (&sysinfo);
+
+ printf ("Board: IBM 440GP Evaluation Board (Ebony)\n");
+ printf ("\tVCO: %lu MHz\n", sysinfo.freqVCOMhz / 1000000);
+ printf ("\tCPU: %lu MHz\n", sysinfo.freqProcessor / 1000000);
+ printf ("\tPLB: %lu MHz\n", sysinfo.freqPLB / 1000000);
+ printf ("\tOPB: %lu MHz\n", sysinfo.freqOPB / 1000000);
+ printf ("\tEPB: %lu MHz\n", sysinfo.freqEPB / 1000000);
+ return (0);
+}
+
+
+long int initdram (int board_type)
+{
+ long dram_size = 0;
+ extern long spd_sdram (void);
+
+#if defined(CONFIG_SPD_EEPROM)
+ dram_size = spd_sdram ();
+#else
+ dram_size = fixed_sdram ();
+#endif
+ return dram_size;
+}
+
+
+#if defined(CFG_DRAM_TEST)
+int testdram (void)
+{
+ uint *pstart = (uint *) 0x00000000;
+ uint *pend = (uint *) 0x08000000;
+ uint *p;
+
+ for (p = pstart; p < pend; p++)
+ *p = 0xaaaaaaaa;
+
+ for (p = pstart; p < pend; p++) {
+ if (*p != 0xaaaaaaaa) {
+ printf ("SDRAM test fails at: %08x\n", (uint) p);
+ return 1;
+ }
+ }
+
+ for (p = pstart; p < pend; p++)
+ *p = 0x55555555;
+
+ for (p = pstart; p < pend; p++) {
+ if (*p != 0x55555555) {
+ printf ("SDRAM test fails at: %08x\n", (uint) p);
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif
+
+#if !defined(CONFIG_SPD_EEPROM)
+/*************************************************************************
+ * fixed sdram init -- doesn't use serial presence detect.
+ *
+ * Assumes: 128 MB, non-ECC, non-registered
+ * PLB @ 133 MHz
+ *
+ ************************************************************************/
+long int fixed_sdram (void)
+{
+ uint reg;
+
+ /*--------------------------------------------------------------------
+ * Setup some default
+ *------------------------------------------------------------------*/
+ mtsdram (mem_uabba, 0x00000000); /* ubba=0 (default) */
+ mtsdram (mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */
+ mtsdram (mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */
+ mtsdram (mem_wddctr, 0x00000000); /* wrcp=0 dcd=0 */
+ mtsdram (mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */
+
+ /*--------------------------------------------------------------------
+ * Setup for board-specific specific mem
+ *------------------------------------------------------------------*/
+ /*
+ * Following for CAS Latency = 2.5 @ 133 MHz PLB
+ */
+ mtsdram (mem_b0cr, 0x000a4001); /* SDBA=0x000 128MB, Mode 3, enabled */
+ mtsdram (mem_tr0, 0x410a4012); /* WR=2 WD=1 CL=2.5 PA=3 CP=4 LD=2 */
+ /* RA=10 RD=3 */
+ mtsdram (mem_tr1, 0x8080082f); /* SS=T2 SL=STAGE 3 CD=1 CT=0x02f */
+ mtsdram (mem_rtr, 0x08200000); /* Rate 15.625 ns @ 133 MHz PLB */
+ mtsdram (mem_cfg1, 0x00000000); /* Self-refresh exit, disable PM */
+ udelay (400); /* Delay 200 usecs (min) */
+
+ /*--------------------------------------------------------------------
+ * Enable the controller, then wait for DCEN to complete
+ *------------------------------------------------------------------*/
+ mtsdram (mem_cfg0, 0x86000000); /* DCEN=1, PMUD=1, 64-bit */
+ for (;;) {
+ mfsdram (mem_mcsts, reg);
+ if (reg & 0x80000000)
+ break;
+ }
+
+ return (128 * 1024 * 1024); /* 128 MB */
+}
+#endif /* !defined(CONFIG_SPD_EEPROM) */
+
+
+/*************************************************************************
+ * pci_pre_init
+ *
+ * This routine is called just prior to registering the hose and gives
+ * the board the opportunity to check things. Returning a value of zero
+ * indicates that things are bad & PCI initialization should be aborted.
+ *
+ * Different boards may wish to customize the pci controller structure
+ * (add regions, override default access routines, etc) or perform
+ * certain pre-initialization actions.
+ *
+ ************************************************************************/
+#if defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT)
+int pci_pre_init(struct pci_controller * hose )
+{
+ unsigned long strap;
+
+ /*--------------------------------------------------------------------------+
+ * The ebony board is always configured as the host & requires the
+ * PCI arbiter to be enabled.
+ *--------------------------------------------------------------------------*/
+ strap = mfdcr(cpc0_strp1);
+ if( (strap & 0x00100000) == 0 ){
+ printf("PCI: CPC0_STRP1[PAE] not set.\n");
+ return 0;
+ }
+
+ return 1;
+}
+#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) */
+
+/*************************************************************************
+ * pci_target_init
+ *
+ * The bootstrap configuration provides default settings for the pci
+ * inbound map (PIM). But the bootstrap config choices are limited and
+ * may not be sufficient for a given board.
+ *
+ ************************************************************************/
+#if defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT)
+void pci_target_init(struct pci_controller * hose )
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /*--------------------------------------------------------------------------+
+ * Disable everything
+ *--------------------------------------------------------------------------*/
+ out32r( PCIX0_PIM0SA, 0 ); /* disable */
+ out32r( PCIX0_PIM1SA, 0 ); /* disable */
+ out32r( PCIX0_PIM2SA, 0 ); /* disable */
+ out32r( PCIX0_EROMBA, 0 ); /* disable expansion rom */
+
+ /*--------------------------------------------------------------------------+
+ * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440 strapping
+ * options to not support sizes such as 128/256 MB.
+ *--------------------------------------------------------------------------*/
+ out32r( PCIX0_PIM0LAL, CFG_SDRAM_BASE );
+ out32r( PCIX0_PIM0LAH, 0 );
+ out32r( PCIX0_PIM0SA, ~(gd->ram_size - 1) | 1 );
+
+ out32r( PCIX0_BAR0, 0 );
+
+ /*--------------------------------------------------------------------------+
+ * Program the board's subsystem id/vendor id
+ *--------------------------------------------------------------------------*/
+ out16r( PCIX0_SBSYSVID, CFG_PCI_SUBSYS_VENDORID );
+ out16r( PCIX0_SBSYSID, CFG_PCI_SUBSYS_DEVICEID );
+
+ out16r( PCIX0_CMD, in16r(PCIX0_CMD) | PCI_COMMAND_MEMORY );
+}
+#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */
+
+
+/*************************************************************************
+ * is_pci_host
+ *
+ * This routine is called to determine if a pci scan should be
+ * performed. With various hardware environments (especially cPCI and
+ * PPMC) it's insufficient to depend on the state of the arbiter enable
+ * bit in the strap register, or generic host/adapter assumptions.
+ *
+ * Rather than hard-code a bad assumption in the general 440 code, the
+ * 440 pci code requires the board to decide at runtime.
+ *
+ * Return 0 for adapter mode, non-zero for host (monarch) mode.
+ *
+ *
+ ************************************************************************/
+#if defined(CONFIG_PCI)
+int is_pci_host(struct pci_controller *hose)
+{
+ /* The ebony board is always configured as host. */
+ return(1);
+}
+#endif /* defined(CONFIG_PCI) */
diff --git a/board/ebony/init.S b/board/ebony/init.S
new file mode 100644
index 0000000000..3ae93d67e9
--- /dev/null
+++ b/board/ebony/init.S
@@ -0,0 +1,98 @@
+/*
+* Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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 <ppc_asm.tmpl>
+#include <config.h>
+
+/* General */
+#define TLB_VALID 0x00000200
+
+/* Supported page sizes */
+
+#define SZ_1K 0x00000000
+#define SZ_4K 0x00000010
+#define SZ_16K 0x00000020
+#define SZ_64K 0x00000030
+#define SZ_256K 0x00000040
+#define SZ_1M 0x00000050
+#define SZ_16M 0x00000070
+#define SZ_256M 0x00000090
+
+/* Storage attributes */
+#define SA_W 0x00000800 /* Write-through */
+#define SA_I 0x00000400 /* Caching inhibited */
+#define SA_M 0x00000200 /* Memory coherence */
+#define SA_G 0x00000100 /* Guarded */
+#define SA_E 0x00000080 /* Endian */
+
+/* Access control */
+#define AC_X 0x00000024 /* Execute */
+#define AC_W 0x00000012 /* Write */
+#define AC_R 0x00000009 /* Read */
+
+/* Some handy macros */
+
+#define EPN(e) ((e) & 0xfffffc00)
+#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) )
+#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) )
+#define TLB2(a) ( (a)&0x00000fbf )
+
+#define tlbtab_start\
+ mflr r1 ;\
+ bl 0f ;
+
+#define tlbtab_end\
+ .long 0, 0, 0 ; \
+0: mflr r0 ; \
+ mtlr r1 ; \
+ blr ;
+
+#define tlbentry(epn,sz,rpn,erpn,attr)\
+ .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr)
+
+
+/**************************************************************************
+ * TLB TABLE
+ *
+ * This table is used by the cpu boot code to setup the initial tlb
+ * entries. Rather than make broad assumptions in the cpu source tree,
+ * this table lets each board set things up however they like.
+ *
+ * Pointer to the table is returned in r1
+ *
+ *************************************************************************/
+
+ .section .bootpg,"ax"
+ .globl tlbtab
+
+tlbtab:
+ tlbtab_start
+ tlbentry( 0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I)
+ tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I)
+ tlbentry( CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X )
+ tlbentry( CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X )
+ tlbentry( CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I )
+ tlbentry( CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I )
+ tlbentry( CFG_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_R|AC_W|SA_G|SA_I )
+ tlbtab_end
+
+
diff --git a/board/eltec/bab7xx/asm_init.S b/board/eltec/bab7xx/asm_init.S
new file mode 100644
index 0000000000..d739b81753
--- /dev/null
+++ b/board/eltec/bab7xx/asm_init.S
@@ -0,0 +1,1487 @@
+/*
+ * (C) Copyright 2001 ELTEC Elektronik AG
+ * Frank Gottschling <fgottschling@eltec.de>
+ *
+ * ELTEC BAB PPC RAM initialization
+ *
+ * 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 <config.h>
+#include <mpc75x.h>
+#include <mpc106.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+/*
+ * This following contains the entry code for the initialization code
+ * for the MPC 106, a PCI Bridge/Memory Controller.
+ * Register usage:
+ * r0 = ramtest scratch register, toggleError loop counter
+ * r1 = 0xfec0 0cf8 CONFIG_ADDRESS
+ * r2 = 0xfee0 0cfc CONFIG_DATA
+ * r3 = scratch register, subroutine argument and return value, ramtest size
+ * r4 = scratch register, spdRead clock mask, OutHex loop count
+ * r5 = ramtest scratch register
+ * r6 = toggleError 1st value, spdRead port mask
+ * r7 = toggleError 2nd value, ramtest scratch register,
+ * spdRead scratch register (0x00)
+ * r8 = ramtest scratch register, spdRead scratch register (0x80)
+ * r9 = ramtest scratch register, toggleError loop end, OutHex digit
+ * r10 = ramtest scratch register, spdWriteByte parameter,
+ * spdReadByte return value, printf pointer to COM1
+ * r11 = startType
+ * r12 = ramtest scratch register, spdRead data mask
+ * r13 = pointer to message block
+ * r14 = pointer to GOT
+ * r15 = scratch register, SPD save
+ * r16 = bank0 size, total memory size
+ * r17 = bank1 size
+ * r18 = bank2 size
+ * r19 = bank3 size
+ * r20 = MCCR1, MSAR1
+ * r21 = MCCR3, MEAR1
+ * r22 = MCCR4, MBER
+ * r23 = EMSAR1
+ * r24 = EMEAR1
+ * r25 = save link register 1st level
+ * r26 = save link register 2nd level
+ * r27 = save link register 3rd level
+ * r30 = pointer to GPIO for spdRead
+ */
+
+
+.globl board_asm_init
+board_asm_init:
+/*
+ * setup pointer to message block
+ */
+ mflr r25 /* save away link register */
+ bl get_lnk_reg /* r3=addr of next instruction */
+ subi r4, r3, 8 /* r4=board_asm_init addr */
+ addi r13, r4, (MessageBlock-board_asm_init)
+/*
+ * dcache_disable
+ */
+ mfspr r3, HID0
+ li r4, HID0_DCE
+ andc r3, r3, r4
+ mr r2, r3
+ ori r3, r3, HID0_DCI
+ sync
+ mtspr HID0, r3
+ mtspr HID0, r2
+ isync
+ sync
+/*
+ * icache_disable
+ */
+ mfspr r3, HID0
+ li r4, 0
+ ori r4, r4, HID0_ICE
+ andc r3, r3, r4
+ sync
+ mtspr HID0, r3
+/*
+ * invalidate caches
+ */
+ ori r3, r3, (HID0_ICE | HID0_ICFI | HID0_DCI | HID0_DCE)
+ or r4, r4, r3
+ isync
+ mtspr HID0, r4
+ andc r4, r4, r3
+ isync
+ mtspr HID0, r4
+ isync
+/*
+ * icache_enable
+ */
+ mfspr r3, HID0
+ ori r3, r3, (HID0_ICE | HID0_ICFI)
+ sync
+ mtspr HID0, r3
+
+ lis r1, 0xfec0
+ ori r1, r1, 0x0cf8
+ lis r2, 0xfee0
+ ori r2, r2, 0xcfc
+
+#ifdef CFG_ADDRESS_MAP_A
+/*
+ * Switch to address map A if necessary.
+ */
+ lis r3, MPC106_REG@h
+ ori r3, r3, PCI_PICR1
+ stwbrx r3, 0, r1
+ sync
+ lwbrx r4, 0, r2
+ sync
+ lis r0, PICR1_XIO_MODE@h
+ ori r0, r0, PICR1_XIO_MODE@l
+ andc r4, r4, r0
+ lis r0, PICR1_ADDRESS_MAP@h
+ ori r0, r0, PICR1_ADDRESS_MAP@l
+ or r4, r4, r0
+ stwbrx r4, 0, r2
+ sync
+#endif
+
+/*
+ * Do the init for the SIO.
+ */
+ bl .sioInit
+
+ addi r3, r13, (MinitLogo-MessageBlock)
+ bl Printf
+
+ addi r3, r13, (Mspd01-MessageBlock)
+ bl Printf
+/*
+ * Memory cofiguration using SPD information stored on the SODIMMs
+ */
+ li r17, 0
+ li r18, 0
+ li r19, 0
+
+ li r3, 0x0002 /* get RAM type from spd for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, -1 /* error ? */
+ bne noSpdError
+
+ addi r3, r13, (Mfail-MessageBlock)
+ bl Printf
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x00
+ b toggleError /* fail - loop forever */
+
+noSpdError:
+ mr r15, r3 /* save r3 */
+
+ addi r3, r13, (Mok-MessageBlock)
+ bl Printf
+
+ cmpli 0, 0, r15, 0x0001 /* FPM ? */
+ beq configFPM
+ cmpli 0, 0, r15, 0x0002 /* EDO ? */
+ beq configEDO
+ cmpli 0, 0, r15, 0x0004 /* SDRAM ? */
+ beq configSDRAM
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x01
+ b toggleError /* fail - loop forever */
+
+configSDRAM:
+ addi r3, r13, (MsdRam-MessageBlock)
+ bl Printf
+/*
+ * set the Memory Configuration Reg. 1
+ */
+ li r3, 0x001f /* get bank size from spd bank0/1 */
+ bl spdRead
+
+ andi. r3, r3, 0x0038
+ beq SD16MB2B
+
+ li r3, 0x0011 /* get number of internal banks */
+ /* from spd for bank0/1 */
+ bl spdRead
+
+ cmpli 0, 0, r3, 0x02
+ beq SD64MB2B
+
+ cmpli 0, 0, r3, 0x04
+ beq SD64MB4B
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x02
+ b toggleError /* fail - loop forever */
+
+SD64MB2B:
+ li r20, 0x0005 /* 64-Mbit SDRAM 2 banks */
+ b SDRow2nd
+
+SD64MB4B:
+ li r20, 0x0000 /* 64-Mbit SDRAM 4 banks */
+ b SDRow2nd
+
+SD16MB2B:
+ li r20, 0x000f /* 16-Mbit SDRAM 2 banks */
+
+SDRow2nd:
+ li r3, 0x0102 /* get RAM type spd for bank2/3 */
+ bl spdRead
+
+ cmpli 0, 0, r3, 0x0004
+ bne S2D64MB4B /* bank2/3 isn't present or no SDRAM */
+
+ li r3, 0x011f /* get bank size from spd bank2/3 */
+ bl spdRead
+
+ andi. r3, r3, 0x0038
+ beq S2D16MB2B
+/*
+ * set the Memory Configuration Reg. 2
+ */
+ li r3, 0x0111 /* get number of internal banks */
+ /* from spd for bank2/3 */
+ bl spdRead
+
+ cmpli 0, 0, r3, 0x02
+ beq S2D64MB2B
+
+ cmpli 0, 0, r3, 0x04
+ beq S2D64MB4B
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x03
+ b toggleError /* fail - loop forever */
+
+S2D64MB2B:
+ ori r20, r20, 0x0050 /* 64-Mbit SDRAM 2 banks */
+ b S2D64MB4B
+
+S2D16MB2B:
+ ori r20, r20, 0x00f0 /* 16-Mbit SDRAM 2 banks */
+
+/*
+ * set the Memory Configuration Reg. 3
+ */
+S2D64MB4B:
+ lis r21, 0x8630 /* BSTOPRE = 0x80, REFREC = 6, */
+ /* RDLAT = 3 */
+
+/*
+ * set the Memory Configuration Reg. 4
+ */
+ lis r22, 0x2430 /* PRETOACT = 2, ACTOPRE = 4, */
+ /* WCBUF = 1, RCBUF = 1 */
+ ori r22, r22, 0x2220 /* SDMODE = 0x022, ACTORW = 2 */
+
+/*
+ * get the size of bank 0-3
+ */
+ li r3, 0x001f /* get bank size from spd bank0/1 */
+ bl spdRead
+
+ rlwinm r16, r3, 2, 24, 29 /* calculate size in MByte */
+ /* (128 MB max.) */
+
+ li r3, 0x0005 /* get number of banks from spd */
+ /* for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, 2 /* 2 banks ? */
+ bne SDRAMnobank1
+
+ mr r17, r16
+
+SDRAMnobank1:
+ addi r3, r13, (Mspd23-MessageBlock)
+ bl Printf
+
+ li r3, 0x0102 /* get RAM type spd for bank2/3 */
+ bl spdRead
+
+ cmpli 0, 0, r3, 0x0001 /* FPM ? */
+ bne noFPM23 /* handle as EDO */
+ addi r3, r13, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r13, (MfpmRam-MessageBlock)
+ bl Printf
+ b configRAMcommon
+noFPM23:
+ cmpli 0, 0, r3, 0x0002 /* EDO ? */
+ bne noEDO23
+ addi r3, r13, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r13, (MedoRam-MessageBlock)
+ bl Printf
+ b configRAMcommon
+noEDO23:
+ cmpli 0, 0, r3, 0x0004 /* SDRAM ? */
+ bne noSDRAM23
+ addi r3, r13, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r13, (MsdRam-MessageBlock)
+ bl Printf
+ b configSDRAM23
+noSDRAM23:
+ addi r3, r13, (Mna-MessageBlock)
+ bl Printf
+ b configRAMcommon /* bank2/3 isn't present or no SDRAM */
+
+configSDRAM23:
+ li r3, 0x011f /* get bank size from spd bank2/3 */
+ bl spdRead
+
+ rlwinm r18, r3, 2, 24, 29 /* calculate size in MByte */
+ /* (128 MB max.) */
+
+ li r3, 0x0105 /* get number of banks from */
+ /* spd bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, 2 /* 2 banks ? */
+ bne SDRAMnobank3
+
+ mr r19, r18
+
+SDRAMnobank3:
+ b configRAMcommon
+
+configFPM:
+ addi r3, r13, (MfpmRam-MessageBlock)
+ bl Printf
+ b configEDO0
+/*
+ * set the Memory Configuration Reg. 1
+ */
+configEDO:
+ addi r3, r13, (MedoRam-MessageBlock)
+ bl Printf
+configEDO0:
+ lis r20, MCCR1_TYPE_EDO@h
+
+getSpdRowBank01:
+ li r3, 0x0003 /* get number of row bits from */
+ /* spd from bank0/1 */
+ bl spdRead
+ ori r20, r20, (MCCR1_BK0_9BITS | MCCR1_BK1_9BITS)
+ cmpli 0, 0, r3, 0x0009 /* bank0 - 9 row bits */
+ beq getSpdRowBank23
+
+ ori r20, r20, (MCCR1_BK0_10BITS | MCCR1_BK1_10BITS)
+ cmpli 0, 0, r3, 0x000a /* bank0 - 10 row bits */
+ beq getSpdRowBank23
+
+ ori r20, r20, (MCCR1_BK0_11BITS | MCCR1_BK1_11BITS)
+ cmpli 0, 0, r3, 0x000b /* bank0 - 11 row bits */
+ beq getSpdRowBank23
+
+ ori r20, r20, (MCCR1_BK0_12BITS | MCCR1_BK1_12BITS)
+ cmpli 0, 0, r3, 0x000c /* bank0 - 12 row bits */
+ beq getSpdRowBank23
+
+ cmpli 0, 0, r3, 0x000d /* bank0 - 13 row bits */
+ beq getSpdRowBank23
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x10
+ b toggleError /* fail - loop forever */
+
+getSpdRowBank23:
+ li r3, 0x0103 /* get number of row bits from */
+ /* spd for bank2/3 */
+ bl spdRead
+
+ ori r20, r20, (MCCR1_BK2_9BITS | MCCR1_BK3_9BITS)
+ cmpli 0, 0, r3, 0x0009 /* bank0 - 9 row bits */
+ beq writeRowBits
+
+ ori r20, r20, (MCCR1_BK2_10BITS | MCCR1_BK3_10BITS)
+ cmpli 0, 0, r3, 0x000a /* bank0 - 10 row bits */
+ beq writeRowBits
+
+ ori r20, r20, (MCCR1_BK2_11BITS | MCCR1_BK3_11BITS)
+ cmpli 0, 0, r3, 0x000b /* bank0 - 11 row bits */
+ beq writeRowBits
+
+ ori r20, r20, (MCCR1_BK2_12BITS | MCCR1_BK3_12BITS)
+
+/*
+ * set the Memory Configuration Reg. 3
+ */
+writeRowBits:
+ lis r21, 0x000a /* CPX = 1, RAS6P = 4 */
+ ori r21, r21, 0x2293 /* CAS5 = 2, CP4 = 1, */
+ /* CAS3 = 2, RCD2 = 2, RP = 3 */
+/*
+ * set the Memory Configuration Reg. 4
+ */
+ lis r22, 0x0010 /* all SDRAM parameter 0, */
+ /* WCBUF flow through, */
+ /* RCBUF registered */
+/*
+ * get the size of bank 0-3
+ */
+ li r3, 0x0003 /* get row bits from spd bank0/1 */
+ bl spdRead
+
+ li r16, 0 /* bank size is: */
+ /* (8*2^row*2^column)/0x100000 MB */
+ ori r16, r16, 0x8000
+ rlwnm r16, r16, r3, 0, 31
+
+ li r3, 0x0004 /* get column bits from spd bank0/1 */
+ bl spdRead
+
+ rlwnm r16, r16, r3, 0, 31
+
+ li r3, 0x0005 /* get number of banks from */
+ /* spd for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, 2 /* 2 banks ? */
+ bne EDOnobank1
+
+ mr r17, r16
+
+EDOnobank1:
+ addi r3, r13, (Mspd23-MessageBlock)
+ bl Printf
+
+ li r3, 0x0102 /* get RAM type spd for bank2/3 */
+ bl spdRead
+
+ cmpli 0, 0, r3, 0x0001 /* FPM ? */
+ bne noFPM231 /* handle as EDO */
+ addi r3, r13, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r13, (MfpmRam-MessageBlock)
+ bl Printf
+ b EDObank2
+noFPM231:
+ cmpli 0, 0, r3, 0x0002 /* EDO ? */
+ bne noEDO231
+ addi r3, r13, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r13, (MedoRam-MessageBlock)
+ bl Printf
+ b EDObank2
+noEDO231:
+ cmpli 0, 0, r3, 0x0004 /* SDRAM ? */
+ bne noSDRAM231
+ addi r3, r13, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r13, (MsdRam-MessageBlock)
+ bl Printf
+ b configRAMcommon
+noSDRAM231:
+ addi r3, r13, (Mfail-MessageBlock)
+ bl Printf
+ b configRAMcommon /* bank2/3 isn't present or no SDRAM */
+
+EDObank2:
+ li r3, 0x0103 /* get row bits from spd for bank2/3 */
+ bl spdRead
+
+ li r18, 0 /* bank size is: */
+ /* (8*2^row*2^column)/0x100000 MB */
+ ori r18, r18, 0x8000
+ rlwnm r18, r18, r3, 0, 31
+
+ li r3, 0x0104 /* get column bits from spd bank2/3 */
+ bl spdRead
+
+ rlwnm r18, r18, r3, 0, 31
+
+ li r3, 0x0105 /* get number of banks from */
+ /* spd for bank2/3 */
+ bl spdRead
+
+ cmpi 0, 0, r3, 2 /* 2 banks ? */
+ bne configRAMcommon
+
+ mr r19, r18
+
+configRAMcommon:
+ lis r1, MPC106_REG_ADDR@h
+ ori r1, r1, MPC106_REG_ADDR@l
+ lis r2, MPC106_REG_DATA@h
+ ori r2, r2, MPC106_REG_DATA@l
+
+ li r0, 0
+
+/*
+ * If we are already running in RAM (debug mode), we should
+ * NOT reset the MEMGO flag. Otherwise we will stop all memory
+ * accesses.
+ */
+#ifdef IN_RAM
+ lis r4, MCCR1_MEMGO@h
+ ori r4, r4, MCCR1_MEMGO@l
+ or r20, r20, r4
+#endif
+
+/*
+ * set the Memory Configuration Reg. 1
+ */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR1 /* register number 0xf0 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r20, r0, r2 /* write data to CONFIG_DATA */
+/*
+ * set the Memory Configuration Reg. 3
+ */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR3 /* register number 0xf8 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r21, r0, r2 /* write data to CONFIG_DATA */
+/*
+ * set the Memory Configuration Reg. 4
+ */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR4 /* register number 0xfc */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r22, r0, r2 /* write data to CONFIG_DATA */
+/*
+ * set the memory boundary registers for bank 0-3
+ */
+ li r20, 0
+ li r23, 0
+ li r24, 0
+ subi r21, r16, 1 /* calculate end address bank0 */
+ li r22, (MBER_BANK0)
+
+ cmpi 0, 0, r17, 0 /* bank1 present ? */
+ beq nobank1
+
+ rlwinm r3, r16, 8, 16, 23 /* calculate start address of bank1 */
+ or r20, r20, r3
+ add r16, r16, r17 /* add to total memory size */
+ subi r3, r16, 1 /* calculate end address of bank1 */
+ rlwinm r3, r3, 8, 16, 23
+ or r21, r21, r3
+ ori r22, r22, (MBER_BANK1) /* enable bank1 */
+ b bank2
+
+nobank1:
+ ori r23, r23, 0x0300 /* set bank1 start to unused area */
+ ori r24, r24, 0x0300 /* set bank1 end to unused area */
+
+bank2:
+ cmpi 0, 0, r18, 0 /* bank2 present ? */
+ beq nobank2
+
+ andi. r3, r16, 0x00ff /* calculate start address of bank2 */
+ andi. r4, r16, 0x0300
+ rlwinm r3, r3, 16, 8, 15
+ or r20, r20, r3
+ rlwinm r3, r4, 8, 8, 15
+ or r23, r23, r3
+ add r16, r16, r18 /* add to total memory size */
+ subi r3, r16, 1 /* calculate end address of bank2 */
+ andi. r4, r3, 0x0300
+ andi. r3, r3, 0x00ff
+ rlwinm r3, r3, 16, 8, 15
+ or r21, r21, r3
+ rlwinm r3, r4, 8, 8, 15
+ or r24, r24, r3
+ ori r22, r22, (MBER_BANK2) /* enable bank2 */
+ b bank3
+
+nobank2:
+ lis r3, 0x0003
+ or r23, r23, r3 /* set bank2 start to unused area */
+ or r24, r24, r3 /* set bank2 end to unused area */
+
+bank3:
+ cmpi 0, 0, r19, 0 /* bank3 present ? */
+ beq nobank3
+
+ andi. r3, r16, 0x00ff /* calculate start address of bank3 */
+ andi. r4, r16, 0x0300
+ rlwinm r3, r3, 24, 0, 7
+ or r20, r20, r3
+ rlwinm r3, r4, 16, 0, 7
+ or r23, r23, r3
+ add r16, r16, r19 /* add to total memory size */
+ subi r3, r16, 1 /* calculate end address of bank3 */
+ andi. r4, r3, 0x0300
+ andi. r3, r3, 0x00ff
+ rlwinm r3, r3, 24, 0, 7
+ or r21, r21, r3
+ rlwinm r3, r4, 16, 0, 7
+ or r24, r24, r3
+ ori r22, r22, (MBER_BANK3) /* enable bank3 */
+ b writebound
+
+nobank3:
+ lis r3, 0x0300
+ or r23, r23, r3 /* set bank3 start to unused area */
+ or r24, r24, r3 /* set bank3 end to unused area */
+
+writebound:
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MSAR1 /* register number 0x80 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r20, r0, r2 /* write data to CONFIG_DATA */
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MEAR1 /* register number 0x90 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r21, r0, r2 /* write data to CONFIG_DATA */
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_EMSAR1 /* register number 0x88 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r23, r0, r2 /* write data to CONFIG_DATA */
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_EMEAR1 /* register number 0x98 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r24, r0, r2 /* write data to CONFIG_DATA */
+
+/*
+ * set boundaries of unused banks to unused address space
+ */
+ lis r4, 0x0303
+ ori r4, r4, 0x0303 /* bank 4-7 start and end adresses */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_EMSAR2 /* register number 0x8C */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r4, r0, r2 /* write data to CONFIG_DATA */
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_EMEAR2 /* register number 0x9C */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r4, r0, r2 /* write data to CONFIG_DATA */
+
+/*
+ * set the Memory Configuration Reg. 2
+ */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR2 /* register number 0xf4 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+
+ li r3, 0x000c /* get refresh from spd for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, -1 /* error ? */
+ bne common1
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x20
+ b toggleError /* fail - loop forever */
+
+common1:
+ andi. r15, r3, 0x007f /* mask selfrefresh bit */
+ li r3, 0x010c /* get refresh from spd for bank2/3 */
+ bl spdRead
+
+ cmpi 0, 0, r3, -1 /* error ? */
+ beq common2
+ andi. r3, r3, 0x007f /* mask selfrefresh bit */
+ cmp 0, 0, r3, r15 /* find the lower */
+ blt common3
+
+common2:
+ mr r3, r15
+
+common3:
+ li r4, 0x1010 /* refesh cycle 1028 clocks */
+ /* left shifted 2 */
+ cmpli 0, 0, r3, 0x0000 /* 15.6 us ? */
+ beq writeRefresh
+
+ li r4, 0x0808 /* refesh cycle 514 clocks */
+ /* left shifted 2 */
+ cmpli 0, 0, r3, 0x0002 /* 7.8 us ? */
+ beq writeRefresh
+
+ li r4, 0x2020 /* refesh cycle 2056 clocks */
+ /* left shifted 2 */
+ cmpli 0, 0, r3, 0x0003 /* 31.3 us ? */
+ beq writeRefresh
+
+ li r4, 0x4040 /* refesh cycle 4112 clocks */
+ /* left shifted 2 */
+ cmpli 0, 0, r3, 0x0004 /* 62.5 us ? */
+ beq writeRefresh
+
+ li r4, 0
+ ori r4, r4, 0x8080 /* refesh cycle 8224 clocks */
+ /* left shifted 2 */
+ cmpli 0, 0, r3, 0x0005 /* 125 us ? */
+ beq writeRefresh
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x21
+ b toggleError /* fail - loop forever */
+
+writeRefresh:
+ stwbrx r4, r0, r2 /* write data to CONFIG_DATA */
+
+/*
+ * DRAM BANKS SHOULD BE ENABLED
+ */
+ addi r3, r13, (Mactivate-MessageBlock)
+ bl Printf
+ mr r3, r16
+ bl OutDec
+ addi r3, r13, (Mmbyte-MessageBlock)
+ bl Printf
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MBER /* register number 0xa0 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stb r22, 0(r2) /* write data to CONFIG_DATA */
+ li r8, 0x63 /* PGMAX = 99 */
+ stb r8, 3(r2) /* write data to CONFIG_DATA */
+
+/*
+ * DRAM SHOULD NOW BE CONFIGURED AND ENABLED
+ * MUST WAIT 200us BEFORE ACCESSING
+ */
+ li r0, 0x7800
+ mtctr r0
+
+wait200us:
+ bdnz wait200us
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR1 /* register number 0xf0 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+
+ lwbrx r4, r0, r2 /* load r4 from CONFIG_DATA */
+
+ lis r0, MCCR1_MEMGO@h /* MEMGO=1 */
+ ori r0, r0, MCCR1_MEMGO@l
+ or r4, r4, r0 /* set the MEMGO bit */
+ stwbrx r4, r0, r2 /* write mdfd data to CONFIG_DATA */
+
+ li r0, 0x7000
+ mtctr r0
+
+wait8ref:
+ bdnz wait8ref
+
+ addi r3, r13, (Mok-MessageBlock)
+ bl Printf
+
+ mtlr r25
+ blr
+
+/*
+ * Infinite loop called in case of an error during RAM initialisation.
+ * error codes in r6 and r7.
+ */
+toggleError:
+ li r0, 0
+ lis r9, 127
+ ori r9, r9, 65535
+toggleError1:
+ addic r0, r0, 1
+ cmpw cr1, r0, r9
+ ble cr1, toggleError1
+ li r0, 0
+ lis r9, 127
+ ori r9, r9, 65535
+toggleError2:
+ addic r0, r0, 1
+ cmpw cr1, r0, r9
+ ble cr1, toggleError2
+ b toggleError
+
+
+/******************************************************************************
+ * This function performs a basic initialisation of the superio chip
+ * to enable basic console output and SPD access during RAM initialisation.
+ *
+ * Upon completion, SIO resource registers are mapped as follows:
+ * Resource Enabled Address
+ * UART1 Yes 3F8-3FF COM1
+ * UART2 Yes 2F8-2FF COM2
+ * GPIO Yes 220-227
+ */
+.set SIO_LUNINDEX, 0x07 /* SIO LUN index register */
+.set SIO_CNFG1, 0x21 /* SIO configuration #1 register */
+.set SIO_PCSCI, 0x23 /* SIO PCS configuration index reg */
+.set SIO_PCSCD, 0x24 /* SIO PCS configuration data reg */
+.set SIO_ACTIVATE, 0x30 /* SIO activate register */
+.set SIO_IOBASEHI, 0x60 /* SIO I/O port base address, 15:8 */
+.set SIO_IOBASELO, 0x61 /* SIO I/O port base address, 7:0 */
+.set SIO_LUNENABLE, 0x01 /* SIO LUN enable */
+
+.sioInit:
+ mfspr r7, 8 /* save link register */
+
+.sioInit_87308:
+
+/*
+ * Get base addr of ISA I/O space
+ */
+ lis r6, CFG_ISA_IO@h
+ ori r6, r6, CFG_ISA_IO@l
+
+/*
+ * Set offset to base address for config registers.
+ */
+#if defined(CFG_NS87308_BADDR_0x)
+ addi r4, r0, 0x0279
+#elif defined(CFG_NS87308_BADDR_10)
+ addi r4, r0, 0x015C
+#elif defined(CFG_NS87308_BADDR_11)
+ addi r4, r0, 0x002E
+#endif
+ add r6, r6, r4 /* add offset to base */
+ or r3, r6, r6 /* make a copy */
+
+/*
+ * PMC (LUN 8)
+ */
+ addi r4, r0, SIO_LUNINDEX /* select PMC LUN */
+ addi r5, r0, 0x8
+ bl .sio_bw
+ addi r4, r0, SIO_IOBASEHI /* initialize PMC address to 0x460 */
+ addi r5, r0, 0x04
+ bl .sio_bw
+ addi r4, r0, SIO_IOBASELO
+ addi r5, r0, 0x60
+ bl .sio_bw
+ addi r4, r0, SIO_ACTIVATE /* enable PMC */
+ addi r5, r0, SIO_LUNENABLE
+ bl .sio_bw
+
+ lis r8, CFG_ISA_IO@h
+ ori r8, r8, 0x0460
+ li r9, 0x03
+ stb r9, 0(r8) /* select PMC2 register */
+ eieio
+ li r9, 0x00
+ stb r9, 1(r8) /* SuperI/O clock src: 24MHz via X1 */
+ eieio
+
+/*
+ * map UART1 (LUN 6) or UART2 (LUN 5) to COM1 (0x3F8)
+ */
+ addi r4, r0, SIO_LUNINDEX /* select COM1 LUN */
+ addi r5, r0, 0x6
+ bl .sio_bw
+
+ addi r4, r0, SIO_IOBASEHI /* initialize COM1 address to 0x3F8 */
+ addi r5, r0, 0x03
+ bl .sio_bw
+
+ addi r4, r0, SIO_IOBASELO
+ addi r5, r0, 0xF8
+ bl .sio_bw
+
+ addi r4, r0, SIO_ACTIVATE /* enable COM1 */
+ addi r5, r0, SIO_LUNENABLE
+ bl .sio_bw
+
+/*
+ * Init COM1 for polled output
+ */
+ lis r8, CFG_ISA_IO@h
+ ori r8, r8, 0x03f8
+ li r9, 0x00
+ stb r9, 1(r8) /* int disabled */
+ eieio
+ li r9, 0x00
+ stb r9, 4(r8) /* modem ctrl */
+ eieio
+ li r9, 0x80
+ stb r9, 3(r8) /* link ctrl, bank select */
+ eieio
+ li r9, 115200/CONFIG_BAUDRATE
+ stb r9, 0(r8) /* baud rate (LSB)*/
+ eieio
+ rotrwi r9, r9, 8
+ stb r9, 1(r8) /* baud rate (MSB) */
+ eieio
+ li r9, 0x03
+ stb r9, 3(r8) /* 8 data bits, 1 stop bit, */
+ /* no parity */
+ eieio
+ li r9, 0x0b
+ stb r9, 4(r8) /* enable the receiver and transmitter */
+ eieio
+
+waitEmpty:
+ lbz r9, 5(r8) /* transmit empty */
+ andi. r9, r9, 0x40
+ beq waitEmpty
+ li r9, 0x47
+ stb r9, 3(r8) /* send break, 8 data bits, */
+ /* 2 stop bits, no parity */
+ eieio
+
+ lis r0, 0x0001
+ mtctr r0
+
+waitCOM1:
+ lwz r0, 5(r8) /* load from port for delay */
+ bdnz waitCOM1
+
+waitEmpty1:
+ lbz r9, 5(r8) /* transmit empty */
+ andi. r9, r9, 0x40
+ beq waitEmpty1
+ li r9, 0x07
+ stb r9, 3(r8) /* 8 data bits, 2 stop bits, */
+ /* no parity */
+ eieio
+
+/*
+ * GPIO (LUN 7)
+ */
+ addi r4, r0, SIO_LUNINDEX /* select GPIO LUN */
+ addi r5, r0, 0x7
+ bl .sio_bw
+
+ addi r4, r0, SIO_IOBASEHI /* initialize GPIO address to 0x220 */
+ addi r5, r0, 0x02
+ bl .sio_bw
+
+ addi r4, r0, SIO_IOBASELO
+ addi r5, r0, 0x20
+ bl .sio_bw
+
+ addi r4, r0, SIO_ACTIVATE /* enable GPIO */
+ addi r5, r0, SIO_LUNENABLE
+ bl .sio_bw
+
+.sioInit_done:
+
+/*
+ * Get base addr of ISA I/O space
+ */
+ lis r3, CFG_ISA_IO@h
+ ori r3, r3, CFG_ISA_IO@l
+
+ addi r3, r3, 0x015C /* adjust to superI/O 87308 base */
+ or r6, r3, r3 /* make a copy */
+/*
+ * CS0
+ */
+ addi r4, r0, SIO_PCSCI /* select PCSCIR */
+ addi r5, r0, 0x00
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCD /* select PCSCDR */
+ addi r5, r0, 0x00
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCI /* select PCSCIR */
+ addi r5, r0, 0x01
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCD /* select PCSCDR */
+ addi r5, r0, 0x76
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCI /* select PCSCIR */
+ addi r5, r0, 0x02
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCD /* select PCSCDR */
+ addi r5, r0, 0x40
+ bl .sio_bw
+/*
+ * CS1
+ */
+ addi r4, r0, SIO_PCSCI /* select PCSCIR */
+ addi r5, r0, 0x05
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCD /* select PCSCDR */
+ addi r5, r0, 0x00
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCI /* select PCSCIR */
+ addi r5, r0, 0x05
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCD /* select PCSCDR */
+ addi r5, r0, 0x70
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCI /* select PCSCIR */
+ addi r5, r0, 0x06
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCD /* select PCSCDR */
+ addi r5, r0, 0x1C
+ bl .sio_bw
+/*
+ * CS2
+ */
+ addi r4, r0, SIO_PCSCI /* select PCSCIR */
+ addi r5, r0, 0x08
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCD /* select PCSCDR */
+ addi r5, r0, 0x00
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCI /* select PCSCIR */
+ addi r5, r0, 0x09
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCD /* select PCSCDR */
+ addi r5, r0, 0x71
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCI /* select PCSCIR */
+ addi r5, r0, 0x0A
+ bl .sio_bw
+ addi r4, r0, SIO_PCSCD /* select PCSCDR */
+ addi r5, r0, 0x1C
+ bl .sio_bw
+
+ mtspr 8, r7 /* restore link register */
+ bclr 20, 0 /* return to caller */
+
+/*
+ * this function writes a register to the SIO chip
+ */
+.sio_bw:
+ stb r4, 0(r3) /* write index register with register offset */
+ eieio
+ sync
+ stb r5, 1(r3) /* 1st write */
+ eieio
+ sync
+ stb r5, 1(r3) /* 2nd write */
+ eieio
+ sync
+ bclr 20, 0 /* return to caller */
+/*
+ * this function reads a register from the SIO chip
+ */
+.sio_br:
+ stb r4, 0(r3) /* write index register with register offset */
+ eieio
+ sync
+ lbz r3, 1(r3) /* retrieve specified reg offset contents */
+ eieio
+ sync
+ bclr 20, 0 /* return to caller */
+
+/*
+ * Print a message to COM1 in polling mode
+ * r10=COM1 port, r3=(char*)string
+ */
+.globl Printf
+Printf:
+ lis r10, CFG_ISA_IO@h /* COM1 port */
+ ori r10, r10, 0x03f8
+
+WaitChr:
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, WaitChr /* wait till empty */
+ lbzx r0, r0, r3 /* get char */
+ stb r0, 0(r10) /* write to transmit reg */
+ eieio
+ addi r3, r3, 1 /* next char */
+ lbzx r0, r0, r3 /* get char */
+ cmpwi cr1, r0, 0 /* end of string ? */
+ bne cr1, WaitChr
+ blr
+
+/*
+ * Print 8/4/2 digits hex value to COM1 in polling mode
+ * r10=COM1 port, r3=val
+ */
+OutHex2:
+ li r9, 4 /* shift reg for 2 digits */
+ b OHstart
+OutHex4:
+ li r9, 12 /* shift reg for 4 digits */
+ b OHstart
+ .globl OutHex
+OutHex:
+ li r9, 28 /* shift reg for 8 digits */
+OHstart:
+ lis r10, CFG_ISA_IO@h /* COM1 port */
+ ori r10, r10, 0x03f8
+OutDig:
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutDig
+ sraw r0, r3, r9
+ clrlwi r0, r0, 28
+ cmpwi cr1, r0, 9
+ ble cr1, digIsNum
+ addic r0, r0, 55
+ b nextDig
+digIsNum:
+ addic r0, r0, 48
+nextDig:
+ stb r0, 0(r10) /* write to transmit reg */
+ eieio
+ addic. r9, r9, -4
+ bge OutDig
+ blr
+/*
+ * Print 3 digits hdec value to COM1 in polling mode
+ * r10=COM1 port, r3=val, r7=x00, r8=x0, r9=x, r0, r6=scratch
+ */
+.globl OutDec
+OutDec:
+ li r6, 10
+ divwu r0, r3, r6 /* r0 = r3 / 10, r9 = r3 mod 10 */
+ mullw r10, r0, r6
+ subf r9, r10, r3
+
+ mr r3, r0
+ divwu r0, r3, r6 /* r0 = r3 / 10, r8 = r3 mod 10 */
+ mullw r10, r0, r6
+ subf r8, r10, r3
+
+ mr r3, r0
+ divwu r0, r3, r6 /* r0 = r3 / 10, r7 = r3 mod 10 */
+ mullw r10, r0, r6
+ subf r7, r10, r3
+
+ lis r10, CFG_ISA_IO@h /* COM1 port */
+ ori r10, r10, 0x03f8
+
+ or. r7, r7, r7
+ bne noblank1
+ li r3, 0x20
+ b OutDec4
+
+noblank1:
+ addi r3, r7, 48 /* convert to ASCII */
+
+OutDec4:
+ lbz r0, 0(r13) /* slow down dummy read */
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutDec4
+ stb r3, 0(r10) /* x00 to transmit */
+ eieio
+
+ or. r7, r7, r8
+ beq OutDec5
+
+ addi r3, r8, 48 /* convert to ASCII */
+OutDec5:
+ lbz r0, 0(r13) /* slow down dummy read */
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutDec5
+ stb r3, 0(r10) /* x0 to transmit */
+ eieio
+
+ addi r3, r9, 48 /* convert to ASCII */
+OutDec6:
+ lbz r0, 0(r13) /* slow down dummy read */
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutDec6
+ stb r3, 0(r10) /* x to transmit */
+ eieio
+ blr
+/*
+ * Print a char to COM1 in polling mode
+ * r10=COM1 port, r3=char
+ */
+.globl OutChr
+OutChr:
+ lis r10, CFG_ISA_IO@h /* COM1 port */
+ ori r10, r10, 0x03f8
+
+OutChr1:
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutChr1 /* wait till empty */
+ stb r3, 0(r10) /* write to transmit reg */
+ eieio
+ blr
+/*
+ * Input: r3 adr to read
+ * Output: r3 val or -1 for error
+ */
+spdRead:
+ mfspr r26, 8 /* save link register */
+
+ lis r30, CFG_ISA_IO@h
+ ori r30, r30, 0x220 /* GPIO Port 1 */
+ li r7, 0x00
+ li r8, 0x100
+ and. r5, r3, r8
+ beq spdbank0
+ li r12, 0x08
+ li r4, 0x10
+ li r6, 0x18
+ b spdRead1
+
+spdbank0:
+ li r12, 0x20 /* set I2C data */
+ li r4, 0x40 /* set I2C clock */
+ li r6, 0x60 /* set I2C clock and data */
+
+spdRead1:
+ li r8, 0x80
+
+ bl spdStart /* access I2C bus as master */
+ li r10, 0xa0 /* write to SPD */
+ bl spdWriteByte
+ bl spdReadAck /* ACK returns in r10 */
+ cmpw cr0, r10, r7
+ bne AckErr /* r10 must be 0, if ACK received */
+ mr r10, r3 /* adr to read */
+ bl spdWriteByte
+ bl spdReadAck
+ cmpw cr0, r10, r7
+ bne AckErr
+ bl spdStart
+ li r10, 0xa1 /* read from SPD */
+ bl spdWriteByte
+ bl spdReadAck
+ cmpw cr0, r10, r7
+ bne AckErr
+ bl spdReadByte /* return val in r10 */
+ bl spdWriteAck
+ bl spdStop /* release I2C bus */
+ mr r3, r10
+ mtspr 8, r26 /* restore link register */
+ blr
+/*
+ * ACK error occurred
+ */
+AckErr:
+ bl spdStop
+ orc r3, r0, r0 /* return -1 */
+ mtspr 8, r26 /* restore link register */
+ blr
+
+/*
+ * Routines to read from RAM spd.
+ * r30 - GPIO Port1 address in all cases.
+ * r4 - clock mask for SPD
+ * r6 - port mask for SPD
+ * r12 - data mask for SPD
+ */
+waitSpd:
+ li r0, 0x1000
+ mtctr r0
+wSpd:
+ bdnz wSpd
+ bclr 20, 0 /* return to caller */
+
+/*
+ * establish START condition on I2C bus
+ */
+spdStart:
+ mfspr r27, 8 /* save link register */
+ stb r6, 0(r30) /* set SDA and SCL */
+ eieio
+ stb r6, 1(r30) /* switch GPIO to output */
+ eieio
+ bl waitSpd
+ stb r4, 0(r30) /* reset SDA */
+ eieio
+ bl waitSpd
+ stb r7, 0(r30) /* reset SCL */
+ eieio
+ bl waitSpd
+ mtspr 8, r27
+ bclr 20, 0 /* return to caller */
+
+/*
+ * establish STOP condition on I2C bus
+ */
+spdStop:
+ mfspr r27, 8 /* save link register */
+ stb r7, 0(r30) /* reset SCL and SDA */
+ eieio
+ stb r6, 1(r30) /* switch GPIO to output */
+ eieio
+ bl waitSpd
+ stb r4, 0(r30) /* set SCL */
+ eieio
+ bl waitSpd
+ stb r6, 0(r30) /* set SDA and SCL */
+ eieio
+ bl waitSpd
+ stb r7, 1(r30) /* switch GPIO to input */
+ eieio
+ mtspr 8, r27
+ bclr 20, 0 /* return to caller */
+
+spdReadByte:
+ mfspr r27, 8
+ stb r4, 1(r30) /* set GPIO for SCL output */
+ eieio
+ li r9, 0x08
+ li r10, 0x00
+loopRB:
+ stb r7, 0(r30) /* reset SDA and SCL */
+ eieio
+ bl waitSpd
+ stb r4, 0(r30) /* set SCL */
+ eieio
+ bl waitSpd
+ lbz r5, 0(r30) /* read from GPIO Port1 */
+ rlwinm r10, r10, 1, 0, 31
+ and. r5, r5, r12
+ beq clearBit
+ ori r10, r10, 0x01 /* append _1_ */
+clearBit:
+ stb r7, 0(r30) /* reset SCL */
+ eieio
+ bl waitSpd
+ addic. r9, r9, -1
+ bne loopRB
+ mtspr 8, r27
+ bclr 20, 0 /* return (r10) to caller */
+
+/*
+ * spdWriteByte writes bits 24 - 31 of r10 to I2C.
+ * r8 contains bit mask 0x80
+ */
+spdWriteByte:
+ mfspr r27, 8 /* save link register */
+ li r9, 0x08 /* write octet */
+ and. r5, r10, r8
+ bne sWB1
+ stb r7, 0(r30) /* set SDA to _0_ */
+ eieio
+ b sWB2
+sWB1:
+ stb r12, 0(r30) /* set SDA to _1_ */
+ eieio
+sWB2:
+ stb r6, 1(r30) /* set GPIO to output */
+ eieio
+loopWB:
+ and. r5, r10, r8
+ bne sWB3
+ stb r7, 0(r30) /* set SDA to _0_ */
+ eieio
+ b sWB4
+sWB3:
+ stb r12, 0(r30) /* set SDA to _1_ */
+ eieio
+sWB4:
+ bl waitSpd
+ and. r5, r10, r8
+ bne sWB5
+ stb r4, 0(r30) /* set SDA to _0_ and SCL */
+ eieio
+ b sWB6
+sWB5:
+ stb r6, 0(r30) /* set SDA to _1_ and SCL */
+ eieio
+sWB6:
+ bl waitSpd
+ and. r5, r10, r8
+ bne sWB7
+ stb r7, 0(r30) /* set SDA to _0_ and reset SCL */
+ eieio
+ b sWB8
+sWB7:
+ stb r12, 0(r30) /* set SDA to _1_ and reset SCL */
+ eieio
+sWB8:
+ bl waitSpd
+ rlwinm r10, r10, 1, 0, 31 /* next bit */
+ addic. r9, r9, -1
+ bne loopWB
+ mtspr 8, r27
+ bclr 20, 0 /* return to caller */
+
+/*
+ * Read ACK from SPD, return value in r10
+ */
+spdReadAck:
+ mfspr r27, 8 /* save link register */
+ stb r4, 1(r30) /* set GPIO to output */
+ eieio
+ stb r7, 0(r30) /* reset SDA and SCL */
+ eieio
+ bl waitSpd
+ stb r4, 0(r30) /* set SCL */
+ eieio
+ bl waitSpd
+ lbz r10, 0(r30) /* read GPIO Port 1 and mask SDA */
+ and r10, r10, r12
+ bl waitSpd
+ stb r7, 0(r30) /* reset SDA and SCL */
+ eieio
+ bl waitSpd
+ mtspr 8, r27
+ bclr 20, 0 /* return (r10) to caller */
+
+spdWriteAck:
+ mfspr r27, 8
+ stb r12, 0(r30) /* set SCL */
+ eieio
+ stb r6, 1(r30) /* set GPIO to output */
+ eieio
+ bl waitSpd
+ stb r6, 0(r30) /* SDA and SCL */
+ eieio
+ bl waitSpd
+ stb r12, 0(r30) /* reset SCL */
+ eieio
+ bl waitSpd
+ mtspr 8, r27
+ bclr 20, 0 /* return to caller */
+
+get_lnk_reg:
+ mflr r3 /* return link reg */
+ blr
+
+/*
+ * Messages for console output
+ */
+.globl MessageBlock
+MessageBlock:
+Mok:
+ .ascii "OK\015\012\000"
+Mfail:
+ .ascii "FAILED\015\012\000"
+Mna:
+ .ascii "NA\015\012\000"
+MinitLogo:
+ .ascii "\015\012*** ELTEC Elektronik, Mainz ***\015\012"
+ .ascii "\015\012Initialising RAM\015\012\000"
+Mspd01:
+ .ascii " Reading SPD of bank0/1 ..... \000"
+Mspd23:
+ .ascii " Reading SPD of bank2/3 ..... \000"
+MfpmRam:
+ .ascii " RAM-Type: FPM \015\012\000"
+MedoRam:
+ .ascii " RAM-Type: EDO \015\012\000"
+MsdRam:
+ .ascii " RAM-Type: SDRAM \015\012\000"
+Mactivate:
+ .ascii " Activating \000"
+Mmbyte:
+ .ascii " MB .......... \000"
+ .align 4
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/board/eltec/bab7xx/el_srom.c b/board/eltec/bab7xx/el_srom.c
new file mode 100644
index 0000000000..56abdc7c26
--- /dev/null
+++ b/board/eltec/bab7xx/el_srom.c
@@ -0,0 +1,292 @@
+/*
+ * (C) Copyright 2002 ELTEC Elektronik AG
+ * Frank Gottschling <fgottschling@eltec.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 "srom.h"
+
+/*----------------------------------------------------------------------------*/
+/*
+ * START sequence
+ * _ _________
+ * SCLK _> \____
+ * _ ____
+ * SDIO _> \_________
+ * : : :
+ */
+static void eepStart (void)
+{
+ out8(I2C_BUS_DAT, 0x60); /* SCLK = high SDIO = high */
+ out8(I2C_BUS_DIR, 0x60); /* set output direction for SCLK/SDIO */
+ udelay(10);
+ out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = low */
+ udelay(10);
+ out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = low */
+ udelay(10);
+}
+
+/*----------------------------------------------------------------------------*/
+/*
+ * STOP sequence
+ * _______
+ * SCLK _____/
+ * _ ___
+ * SDIO _>_______/
+ * : : :
+ */
+static void eepStop (void)
+{
+ out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = low */
+ out8(I2C_BUS_DIR, 0x60); /* set output direction for SCLK/SDIO */
+ udelay(10);
+ out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = low */
+ udelay(10);
+ out8(I2C_BUS_DAT, 0x60); /* SCLK = high SDIO = high */
+ udelay(10);
+ out8(I2C_BUS_DIR, 0x00); /* reset to input direction */
+}
+
+/*----------------------------------------------------------------------------*/
+/*
+ * Read one byte from EEPROM
+ * ___ ___ ___ ___ ___ ___ ___ ___
+ * SCLK ___/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \
+ * _________________________________________________________________
+ * SDIO > ^ ^ ^ ^ ^ ^ ^ ^
+ * : : : : : : : : : : : : : : : : :
+ */
+static unsigned char eepReadByte (void)
+{
+ register unsigned char buf = 0x00;
+ register int i;
+
+ out8(I2C_BUS_DIR, 0x40);
+
+ for (i = 0; i < 8; i++)
+ {
+ out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */
+ udelay(10);
+ out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = high */
+ udelay(15);
+ buf <<= 1;
+ buf = (in8(I2C_BUS_DAT) & 0x20) ? (buf | 0x01) : (buf & 0xFE);
+ out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */
+ udelay(10);
+ }
+ return(buf);
+}
+
+/*----------------------------------------------------------------------------*/
+/*
+ * Write one byte to EEPROM
+ * ___ ___ ___ ___ ___ ___ ___ ___
+ * SCLK __/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \__
+ * _______ _______ _______ _______ _______ _______ _______ ________
+ * SDIO X_______X_______X_______X_______X_______X_______X_______X________
+ * : 7 : 6 : 5 : 4 : 3 : 2 : 1 : 0
+ */
+static void eepWriteByte (register unsigned char buf)
+{
+ register int i;
+
+ (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = data */
+ out8(I2C_BUS_DIR, 0x60);
+
+ for (i = 7; i >= 0; i--)
+ {
+ (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK=low SDIO=data */
+ udelay(10);
+ (buf & 0x80) ? out8(I2C_BUS_DAT, 0x60) : out8(I2C_BUS_DAT, 0x40); /* SCLK=high SDIO=data */
+ udelay(15);
+ (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK=low SDIO=data */
+ udelay(10);
+ buf <<= 1;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/*
+ * Read data acknowledge of EEPROM
+ * _______
+ * SCLK ____/ \___
+ * _______________
+ * SDIO >
+ * : : ^ :
+ */
+static int eepReadAck (void)
+{
+ int retval;
+
+ out8(I2C_BUS_DIR, 0x40);
+ out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */
+ udelay(10);
+ out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = high */
+ udelay(10);
+ retval = (in8(I2C_BUS_DAT) & 0x20) ? ERROR : 0;
+ udelay(10);
+ out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */
+ udelay(10);
+
+ return(retval);
+}
+
+/*----------------------------------------------------------------------------*/
+/*
+ * Write data acknowledge to EEPROM
+ * _______
+ * SCLK ____/ \___
+ *
+ * SDIO >_______________
+ * : : :
+ */
+static void eepWriteAck (unsigned char ack)
+{
+ ack ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = ack */
+ out8(I2C_BUS_DIR, 0x60);
+ udelay(10);
+ ack ? out8(I2C_BUS_DAT, 0x60) : out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = ack */
+ udelay(15);
+ ack ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = ack */
+ udelay(10);
+}
+
+/*----------------------------------------------------------------------------*/
+/*
+ * Read bytes from EEPROM
+ */
+int el_srom_load (addr, buf, cnt, device, block)
+unsigned char addr;
+unsigned char *buf;
+int cnt;
+unsigned char device;
+unsigned char block;
+{
+ register int i;
+
+ for (i=0;i<cnt;i++)
+ {
+ eepStart();
+ eepWriteByte(0xA0 | device | block);
+ if (eepReadAck() == ERROR)
+ {
+ eepStop();
+ return(ERROR);
+ }
+ eepWriteByte(addr++);
+ if (eepReadAck() == ERROR)
+ {
+ eepStop();
+ return(ERROR);
+ }
+ eepStart();
+
+ eepWriteByte(0xA1 | device | block);
+ if (eepReadAck() == ERROR)
+ {
+ eepStop();
+ return(ERROR);
+ }
+
+ *buf++ = eepReadByte();
+ eepWriteAck(1);
+ eepStop();
+
+ if ((addr == 0) && (i != (cnt-1))) /* is it the same block ? */
+ {
+ if (block == FIRST_BLOCK)
+ block = SECOND_BLOCK;
+ else
+ return(ERROR);
+ }
+ }
+ return(cnt);
+}
+
+/*----------------------------------------------------------------------------*/
+/*
+ *
+ * Write bytes to EEPROM
+ *
+ */
+int el_srom_store (addr, buf, cnt, device, block)
+unsigned char addr, *buf, device, block;
+int cnt;
+{
+ register int i, retVal;
+
+ for (i=0;i<cnt;i++)
+ {
+ retVal = ERROR;
+ do
+ {
+ eepStart();
+ eepWriteByte(0xA0 | device | block);
+ if ((retVal = eepReadAck()) == ERROR)
+ eepStop();
+ } while (retVal == ERROR);
+
+ eepWriteByte(addr++);
+ if (eepReadAck() == ERROR) return(ERROR);
+
+ if ((addr == 0) && (i != (cnt-1))) /* is it the same block ? */
+ {
+ if (block == FIRST_BLOCK)
+ block = SECOND_BLOCK;
+ else
+ return(ERROR);
+ }
+
+ eepWriteByte(*buf++);
+ if (eepReadAck() == ERROR)
+ return(ERROR);
+
+ eepStop();
+ }
+ return(cnt);
+}
+
+/*----------------------------------------------------------------------------*/
+/*
+ * calculate checksum for ELTEC revision srom
+ */
+unsigned long el_srom_checksum (ptr, size)
+register unsigned char *ptr;
+unsigned long size;
+{
+ u_long f, accu = 0;
+ u_int i;
+ u_char byte;
+
+ for (; size; size--)
+ {
+ byte = *ptr++;
+ for (i = 8; i; i--)
+ {
+ f = ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0;
+ accu >>= 1; accu ^= f;
+ byte >>= 1;
+ }
+ }
+ return(accu);
+}
+
+/*----------------------------------------------------------------------------*/
diff --git a/board/eltec/bab7xx/u-boot.lds b/board/eltec/bab7xx/u-boot.lds
new file mode 100644
index 0000000000..7b10c0d2aa
--- /dev/null
+++ b/board/eltec/bab7xx/u-boot.lds
@@ -0,0 +1,129 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * 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
+ */
+
+/*
+ * u-boot.lds - linker script for U-Boot on the Galileo Eval Board.
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/74xx_7xx/start.o (.text)
+
+/* store the environment in a seperate sector in the boot flash */
+/* . = env_offset; */
+/* common/environment.o(.text) */
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/board/eltec/elppc/asm_init.S b/board/eltec/elppc/asm_init.S
new file mode 100644
index 0000000000..a5605b7033
--- /dev/null
+++ b/board/eltec/elppc/asm_init.S
@@ -0,0 +1,877 @@
+/*
+ * (C) Copyright 2001 ELTEC Elektronik AG
+ * Frank Gottschling <fgottschling@eltec.de>
+ *
+ * ELTEC ELPPC RAM initialization
+ *
+ * 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 <config.h>
+#include <version.h>
+#include <mpc106.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+.globl board_asm_init
+board_asm_init:
+
+/*
+ * setup pointer to message block
+ */
+ mflr r13 /* save away link register */
+ bl get_lnk_reg /* r3=addr of next instruction */
+ subi r4, r3, 8 /* r4=board_asm_init addr */
+ addi r29, r4, (MessageBlock-board_asm_init)
+
+/*
+ * dcache_disable
+ */
+ mfspr r3, HID0
+ li r4, HID0_DCE
+ andc r3, r3, r4
+ mr r2, r3
+ ori r3, r3, HID0_DCI
+ sync
+ mtspr HID0, r3
+ mtspr HID0, r2
+ isync
+ sync
+/*
+ * icache_disable
+ */
+ mfspr r3, HID0
+ li r4, 0
+ ori r4, r4, HID0_ICE
+ andc r3, r3, r4
+ sync
+ mtspr HID0, r3
+/*
+ * invalidate caches
+ */
+ ori r3, r3, (HID0_ICE | HID0_ICFI | HID0_DCI | HID0_DCE)
+ or r4, r4, r3
+ isync
+ mtspr HID0, r4
+ andc r4, r4, r3
+ isync
+ mtspr HID0, r4
+ isync
+/*
+ * icache_enable
+ */
+ mfspr r3, HID0
+ ori r3, r3, (HID0_ICE | HID0_ICFI)
+ sync
+ mtspr HID0, r3
+
+
+/*
+ * setup memory controller
+ */
+ lis r1, MPC106_REG_ADDR@h
+ ori r1, r1, MPC106_REG_ADDR@l
+ lis r2, MPC106_REG_DATA@h
+ ori r2, r2, MPC106_REG_DATA@l
+
+ /* Configure PICR1 */
+ lis r3, MPC106_REG@h
+ ori r3, r3, PCI_PICR1
+ stwbrx r3, 0, r1
+ addis r3, r0, 0xFF14
+ ori r3, r3, 0x1CC8
+ eieio
+ stwbrx r3, 0, r2
+
+ /* Configure PICR2 */
+ lis r3, MPC106_REG@h
+ ori r3, r3, PCI_PICR2
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x0000
+ ori r3, r3, 0x0000
+ eieio
+ stwbrx r3, 0, r2
+
+ /* Configure EUMBAR */
+ lis r3, MPC106_REG@h
+ ori r3, r3, 0x0078 /* offest of EUMBAR in PCI config space */
+ stwbrx r3, 0, r1
+ lis r3, MPC107_EUMB_ADDR@h
+ eieio
+ stwbrx r3, 0, r2
+
+ /* Configure Address Map B Option Reg */
+ lis r3, MPC106_REG@h
+ ori r3, r3, 0x00e0 /* offest of AMBOR in PCI config space */
+ stwbrx r3, 0, r1
+ lis r3, 0
+ eieio
+ stwbrx r3, 0, r2
+
+ /* Configure I2C Controller */
+ lis r14, MPC107_I2C_ADDR@h /* base of I2C controller */
+ ori r14, r14, MPC107_I2C_ADDR@l
+ lis r3, 0x2b10 /* I2C clock = 100MHz/1024 */
+ stw r3, 4(r14)
+ li r3, 0 /* clear arbitration */
+ eieio
+ stw r3, 12(r14)
+
+ /* Configure MCCR1 */
+ lis r3, MPC106_REG@h
+ ori r3, r3, MPC106_MCCR1
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x0660 /* don't set MEMGO now ! */
+ ori r3, r3, 0x0000
+ eieio
+ stwbrx r3, 0, r2
+
+ /* Configure MCCR2 */
+ lis r3, MPC106_REG@h
+ ori r3, r3, MPC106_MCCR2
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x0400
+ ori r3, r3, 0x1800
+ eieio
+ stwbrx r3, 0, r2
+
+
+ /* Configure MCCR3 */
+ lis r3, MPC106_REG@h
+ ori r3, r3, MPC106_MCCR3
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x0230
+ ori r3, r3, 0x0000
+ eieio
+ stwbrx r3, 0, r2
+
+ /* Configure MCCR4 */
+ lis r3, MPC106_REG@h
+ ori r3, r3, MPC106_MCCR4
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x2532
+ ori r3, r3, 0x2220
+ eieio
+ stwbrx r3, 0, r2
+
+/*
+ * configure memory interface (MICRs)
+ */
+ addis r3, r0, 0x8000 /* ADDR_80 */
+ ori r3, r3, 0x0080 /* SMEMADD1 */
+ stwbrx r3, 0, r1
+ addis r3, r0, 0xFFFF
+ ori r3, r3, 0x4000
+ eieio
+ stwbrx r3, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_84 */
+ ori r3, r3, 0x0084 /* SMEMADD2 */
+ stwbrx r3, 0, r1
+ addis r3, r0, 0xFFFF
+ ori r3, r3, 0xFFFF
+ eieio
+ stwbrx r3, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_88 */
+ ori r3, r3, 0x0088 /* EXTSMEM1 */
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x0303
+ ori r3, r3, 0x0000
+ eieio
+ stwbrx r3, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_8C */
+ ori r3, r3, 0x008c /* EXTSMEM2 */
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x0303
+ ori r3, r3, 0x0303
+ eieio
+ stwbrx r3, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_90 */
+ ori r3, r3, 0x0090 /* EMEMADD1 */
+ stwbrx r3, 0, r1
+ addis r3, r0, 0xFFFF
+ ori r3, r3, 0x7F3F
+ eieio
+ stwbrx r3, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_94 */
+ ori r3, r3, 0x0094 /* EMEMADD2 */
+ stwbrx r3, 0, r1
+ addis r3, r0, 0xFFFF
+ ori r3, r3, 0xFFFF
+ eieio
+ stwbrx r3, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_98 */
+ ori r3, r3, 0x0098 /* EXTEMEM1 */
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x0303
+ ori r3, r3, 0x0000
+ eieio
+ stwbrx r3, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_9C */
+ ori r3, r3, 0x009c /* EXTEMEM2 */
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x0303
+ ori r3, r3, 0x0303
+ eieio
+ stwbrx r3, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_A0 */
+ ori r3, r3, 0x00a0 /* MEMBNKEN */
+ stwbrx r3, 0, r1
+ addis r3, r0, 0x0000
+ ori r3, r3, 0x0003
+ eieio
+ stwbrx r3, 0, r2
+
+/*
+ * must wait at least 100us after HRESET to issue a MEMGO
+ */
+ lis r0, 1
+ mtctr r0
+memStartWait:
+ bdnz memStartWait
+
+/*
+ * enable RAM Operations through MCCR1 (MEMGO)
+ */
+ lis r3, 0x8000
+ ori r3, r3, 0x00f0
+ stwbrx r3, r0, r1
+ sync
+ lwbrx r3, 0, r2
+ lis r0, 0x0008
+ or r3, r0, r3
+ stwbrx r3, 0, r2
+ sync
+
+/*
+ * set LEDs first time
+ */
+ li r3, 0x1
+ lis r30, CFG_USR_LED_BASE@h
+ stb r3, 2(r30)
+ sync
+
+/*
+ * init COM1 for polled output
+ */
+ lis r8, CFG_NS16550_COM1@h /* COM1 base address*/
+ ori r8, r8, CFG_NS16550_COM1@l
+ li r9, 0x00
+ stb r9, 1(r8) /* int disabled */
+ eieio
+ li r9, 0x00
+ stb r9, 4(r8) /* modem ctrl */
+ eieio
+ li r9, 0x80
+ stb r9, 3(r8) /* link ctrl */
+ eieio
+ li r9, (CFG_NS16550_CLK / 16 / CONFIG_BAUDRATE)
+ stb r9, 0(r8) /* baud rate (LSB)*/
+ eieio
+ li r9, ((CFG_NS16550_CLK / 16 / CONFIG_BAUDRATE) >> 8)
+ stb r9, 1(r8) /* baud rate (MSB) */
+ eieio
+ li r9, 0x07
+ stb r9, 3(r8) /* 8 data bits, 2 stop bit, no parity */
+ eieio
+ li r9, 0x0b
+ stb r9, 4(r8) /* enable the receiver and transmitter (modem ctrl) */
+ eieio
+waitEmpty:
+ lbz r9, 5(r8) /* transmit empty */
+ andi. r9, r9, 0x40
+ beq waitEmpty
+ li r9, 0x47
+ stb r9, 3(r8) /* send break, 8 data bits, 2 stop bit, no parity */
+ eieio
+
+ lis r0, 0x0001
+ mtctr r0
+waitCOM1:
+ lwz r0, 5(r8) /* load from port for delay */
+ bdnz waitCOM1
+
+waitEmpty1:
+ lbz r9, 5(r8) /* transmit empty */
+ andi. r9, r9, 0x40
+ beq waitEmpty1
+ li r9, 0x07
+ stb r9, 3(r8) /* 8 data bits, 2 stop bit, no parity */
+ eieio
+
+/*
+ * intro message from message block
+ */
+ addi r3, r29, (MnewLine-MessageBlock)
+ bl Printf
+ addi r3, r29, (MinitLogo-MessageBlock)
+ bl Printf
+
+/*
+ * memory cofiguration using SPD information stored on the SODIMMs
+ */
+ addi r3, r29, (Mspd01-MessageBlock)
+ bl Printf
+
+ li r17, 0
+
+ li r3, 0x0002 /* get RAM type from spd for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, -1 /* error ? */
+ bne noSpdError
+
+ addi r3, r29, (Mfail-MessageBlock)
+ bl Printf
+
+ li r6, 0xe /* error codes in r6 and r7 */
+ li r7, 0x0
+ b toggleError /* fail - loop forever */
+
+noSpdError:
+ mr r15, r3 /* save r3 */
+
+ addi r3, r29, (Mok-MessageBlock)
+ bl Printf
+
+ cmpli 0, 0, r15, 0x0004 /* SDRAM ? */
+ beq isSDRAM
+
+ addi r3, r29, (MramTyp-MessageBlock)
+ bl Printf
+
+ li r6, 0xd /* error codes in r6 and r7 */
+ li r7, 0x0
+ b toggleError /* fail - loop forever */
+
+isSDRAM:
+ li r3, 0x0012 /* get supported CAS latencies from byte 18 */
+ bl spdRead
+ mr r15, r3
+ li r3, 0x09
+ andi. r0, r15, 0x04
+ bne maxCLis3
+ li r3, 0x17
+maxCLis3:
+ andi. r0, r15, 0x02
+ bne CL2
+
+ addi r3, r29, (MramTyp-MessageBlock)
+ bl Printf
+
+ li r6, 0xc /* error codes in r6 and r7 */
+ li r7, 0x0
+ b toggleError /* fail - loop forever */
+CL2:
+ bl spdRead
+ cmpli 0, 0, r3, 0xa1 /* cycle time must be 10ns max. */
+ blt speedOk
+
+ addi r3, r29, (MramTyp-MessageBlock)
+ bl Printf
+
+ li r6, 0xb /* error codes in r6 and r7 */
+ li r7, 0x0
+ b toggleError /* fail - loop forever */
+speedOk:
+ lis r20, 0x06e8 /* preset MCR1 value */
+
+ li r3, 0x0011 /* get number of internal banks from spd for bank0/1 */
+ bl spdRead
+
+ cmpli 0, 0, r3, 0x02
+ beq SD_2B
+ cmpli 0, 0, r3, 0x04
+ beq SD_4B
+memConfErr:
+ addi r3, r29, (MramConfErr-MessageBlock)
+ bl Printf
+
+ li r6, 0xa /* error codes in r6 and r7 */
+ li r7, 0x0
+ b toggleError /* fail - loop forever */
+
+SD_2B:
+ li r3, 0x0003 /* get number of row bits from spd for bank0/1 */
+ bl spdRead
+ cmpli 0, 0, r3, 0x0b
+ beq row11x2
+ cmpli 0, 0, r3, 0x0c
+ beq row12x2or13x2
+ cmpli 0, 0, r3, 0x0d
+ beq row12x2or13x2
+ b memConfErr
+SD_4B:
+ li r3, 0x0003 /* get number of row bits from spd for bank0/1 */
+ bl spdRead
+ cmpli 0, 0, r3, 0x0b
+ beq row11x4or12x4
+ cmpli 0, 0, r3, 0x0c
+ beq row11x4or12x4
+ cmpli 0, 0, r3, 0x0d
+ beq row13x4
+ b memConfErr
+row12x2or13x2:
+ ori r20, r20, 0x05
+ b row11x4or12x4
+row13x4:
+ ori r20, r20, 0x0a
+ b row11x4or12x4
+row11x2:
+ ori r20, r20, 0x0f
+row11x4or12x4:
+ /* get the size of bank 0-1 */
+
+ li r3, 0x001f /* get bank size from spd for bank0/1 */
+ bl spdRead
+
+ rlwinm r16, r3, 2, 24, 29 /* calculate size in MByte (128 MB max.) */
+
+ li r3, 0x0005 /* get number of banks from spd for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, 2 /* 2 banks ? */
+ bne SDRAMnobank1
+
+ mr r17, r16
+
+SDRAMnobank1:
+ li r3, 0x000c /* get refresh from spd for bank0/1 */
+ bl spdRead
+ andi. r3, r3, 0x007f /* mask selfrefresh bit */
+ li r4, 0x1800 /* refesh cycle 1536 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0000 /* 15.6 us ? */
+ beq writeRefresh
+
+ li r4, 0x0c00 /* refesh cycle 768 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0002 /* 7.8 us ? */
+ beq writeRefresh
+
+ li r4, 0x3000 /* refesh cycle 3072 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0003 /* 31.3 us ? */
+ beq writeRefresh
+
+ li r4, 0x6000 /* refesh cycle 6144 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0004 /* 62.5 us ? */
+ beq writeRefresh
+
+ li r4, 0
+ ori r4, r4, 0xc000 /* refesh cycle 8224 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0005 /* 125 us ? */
+ beq writeRefresh
+
+ b memConfErr
+
+writeRefresh:
+ lis r21, 0x0400 /* preset MCCR2 value */
+ or r21, r21, r4
+
+ /* Overwrite MCCR1 */
+ lis r3, MPC106_REG@h
+ ori r3, r3, MPC106_MCCR1
+ stwbrx r3, 0, r1
+ eieio
+ stwbrx r20, 0, r2
+
+ /* Overwrite MCCR2 */
+ lis r3, MPC106_REG@h
+ ori r3, r3, MPC106_MCCR2
+ stwbrx r3, 0, r1
+ eieio
+ stwbrx r21, 0, r2
+
+ /* set the memory boundary registers for bank 0-3 */
+ li r20, 0
+ lis r23, 0x0303
+ lis r24, 0x0303
+ subi r21, r16, 1 /* calculate end address bank0 */
+ li r22, 1
+
+ cmpi 0, 0, r17, 0 /* bank1 present ? */
+ beq nobank1
+
+ andi. r3, r16, 0x00ff /* calculate start address of bank1 */
+ andi. r4, r16, 0x0300
+ rlwinm r3, r3, 8, 16, 23
+ or r20, r20, r3
+ or r23, r23, r4
+
+ add r16, r16, r17 /* add to total memory size */
+
+ subi r3, r16, 1 /* calculate end address of bank1 */
+ andi. r4, r3, 0x0300
+ andi. r3, r3, 0x00ff
+ rlwinm r3, r3, 8, 16, 23
+ or r21, r21, r3
+ or r24, r24, r4
+
+ ori r22, r22, 2 /* enable bank1 */
+ b bankOk
+nobank1:
+ ori r23, r23, 0x0300 /* set bank1 start to unused area */
+ ori r24, r24, 0x0300 /* set bank1 end to unused area */
+bankOk:
+ addi r3, r29, (Mactivate-MessageBlock)
+ bl Printf
+ mr r3, r16
+ bl OutDec
+ addi r3, r29, (Mact0123e-MessageBlock)
+ bl Printf
+
+/*
+ * overwrite MSAR1, MEAR1, EMSAR1, and EMEAR1
+ */
+ addis r3, r0, 0x8000 /* ADDR_80 */
+ ori r3, r3, 0x0080 /* MSAR1 */
+ stwbrx r3, 0, r1
+ eieio
+ stwbrx r20, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_88 */
+ ori r3, r3, 0x0088 /* EMSAR1 */
+ stwbrx r3, 0, r1
+ eieio
+ stwbrx r23, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_90 */
+ ori r3, r3, 0x0090 /* MEAR1 */
+ stwbrx r3, 0, r1
+ eieio
+ stwbrx r21, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_98 */
+ ori r3, r3, 0x0098 /* EMEAR1 */
+ stwbrx r3, 0, r1
+ eieio
+ stwbrx r24, 0, r2
+
+ addis r3, r0, 0x8000 /* ADDR_A0 */
+ ori r3, r3, 0x00a0 /* MBER */
+ stwbrx r3, 0, r1
+ eieio
+ stwbrx r22, 0, r2
+
+/*
+ * delay to let SDRAM go through several initialization/refresh cycles
+ */
+ lis r3, 3
+ mtctr r3
+memStartWait_1:
+ bdnz memStartWait_1
+ eieio
+
+/*
+ * set LEDs end
+ */
+ li r3, 0xf
+ lis r30, CFG_USR_LED_BASE@h
+ stb r3, 2(r30)
+ sync
+
+ mtlr r13
+ blr /* EXIT board_asm_init ... */
+
+/*----------------------------------------------------------------------------*/
+/*
+ * print a message to COM1 in polling mode (r10=COM1 port, r3=(char*)string)
+ */
+
+Printf:
+ lis r10, CFG_NS16550_COM1@h /* COM1 base address*/
+ ori r10, r10, CFG_NS16550_COM1@l
+WaitChr:
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, WaitChr /* wait till empty */
+ lbzx r0, r0, r3 /* get char */
+ stb r0, 0(r10) /* write to transmit reg */
+ eieio
+ addi r3, r3, 1 /* next char */
+ lbzx r0, r0, r3 /* get char */
+ cmpwi cr1, r0, 0 /* end of string ? */
+ bne cr1, WaitChr
+ blr
+
+/*
+ * print a char to COM1 in polling mode (r10=COM1 port, r3=char)
+ */
+OutChr:
+ lis r10, CFG_NS16550_COM1@h /* COM1 base address*/
+ ori r10, r10, CFG_NS16550_COM1@l
+OutChr1:
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutChr1 /* wait till empty */
+ stb r3, 0(r10) /* write to transmit reg */
+ eieio
+ blr
+
+/*
+ * print 8/4/2 digits hex value to COM1 in polling mode (r10=COM1 port, r3=val)
+ */
+OutHex2:
+ li r9, 4 /* shift reg for 2 digits */
+ b OHstart
+OutHex4:
+ li r9, 12 /* shift reg for 4 digits */
+ b OHstart
+OutHex:
+ li r9, 28 /* shift reg for 8 digits */
+OHstart:
+ lis r10, CFG_NS16550_COM1@h /* COM1 base address*/
+ ori r10, r10, CFG_NS16550_COM1@l
+OutDig:
+ lbz r0, 0(r29) /* slow down dummy read */
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutDig
+ sraw r0, r3, r9
+ clrlwi r0, r0, 28
+ cmpwi cr1, r0, 9
+ ble cr1, digIsNum
+ addic r0, r0, 55
+ b nextDig
+digIsNum:
+ addic r0, r0, 48
+nextDig:
+ stb r0, 0(r10) /* write to transmit reg */
+ eieio
+ addic. r9, r9, -4
+ bge OutDig
+ blr
+
+/*
+ * print 3 digits hdec value to COM1 in polling mode
+ * (r10=COM1 port, r3=val, r7=x00, r8=x0, r9=x, r0, r6=scratch)
+ */
+OutDec:
+ li r6, 10
+ divwu r0, r3, r6 /* r0 = r3 / 10, r9 = r3 mod 10 */
+ mullw r10, r0, r6
+ subf r9, r10, r3
+ mr r3, r0
+ divwu r0, r3, r6 /* r0 = r3 / 10, r8 = r3 mod 10 */
+ mullw r10, r0, r6
+ subf r8, r10, r3
+ mr r3, r0
+ divwu r0, r3, r6 /* r0 = r3 / 10, r7 = r3 mod 10 */
+ mullw r10, r0, r6
+ subf r7, r10, r3
+ lis r10, CFG_NS16550_COM1@h /* COM1 base address*/
+ ori r10, r10, CFG_NS16550_COM1@l
+ or. r7, r7, r7
+ bne noblank1
+ li r3, 0x20
+ b OutDec4
+noblank1:
+ addi r3, r7, 48 /* convert to ASCII */
+OutDec4:
+ lbz r0, 0(r29) /* slow down dummy read */
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutDec4
+ stb r3, 0(r10) /* x00 to transmit */
+ eieio
+ or. r7, r7, r8
+ beq OutDec5
+ addi r3, r8, 48 /* convert to ASCII */
+OutDec5:
+ lbz r0, 0(r29) /* slow down dummy read */
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutDec5
+ stb r3, 0(r10) /* x0 to transmit */
+ eieio
+ addi r3, r9, 48 /* convert to ASCII */
+OutDec6:
+ lbz r0, 0(r29) /* slow down dummy read */
+ lbz r0, 5(r10) /* read link status */
+ eieio
+ andi. r0, r0, 0x40 /* mask transmitter empty bit */
+ beq cr0, OutDec6
+ stb r3, 0(r10) /* x to transmit */
+ eieio
+ blr
+
+/*
+ * hang endless loop
+ */
+toggleError: /* fail type in r6, r7=0xff, toggle LEDs */
+ stb r7, 2(r30) /* r7 to LED */
+ li r0, 0
+ lis r9, 127
+ ori r9, r9, 65535
+toggleError1:
+ addic r0, r0, 1
+ cmpw cr1, r0, r9
+ ble cr1, toggleError1
+ stb r6, 2(r30) /* r6 to LED */
+ li r0, 0
+ lis r9, 127
+ ori r9, r9, 65535
+toggleError2:
+ addic r0, r0, 1
+ cmpw cr1, r0, r9
+ ble cr1, toggleError2
+ b toggleError
+
+/*
+ * routines to read from ram spd
+ */
+spdWaitIdle:
+ lis r0, 0x1 /* timeout for about 100us */
+ mtctr r0
+iSpd:
+ lbz r10, 12(r14)
+ andi. r10, r10, 0x20 /* mask and test MBB */
+ beq idle
+ bdnz iSpd
+ orc. r10, r0, r0 /* return -1 to caller */
+idle:
+ bclr 20, 0 /* return to caller */
+
+waitSpd:
+ lis r0, 0x10 /* timeout for about 1.5ms */
+ mtctr r0
+wSpd:
+ lbz r10, 12(r14)
+ andi. r10, r10, 0x82
+ cmpli 0, 0, r10, 0x82 /* test MCF and MIF set */
+ beq wend
+ bdnz wSpd
+ orc. r10, r0, r0 /* return -1 to caller */
+ bclr 20, 0 /* return to caller */
+
+wend:
+ li r10, 0
+ stb r10, 12(r14) /* clear status */
+ bclr 20, 0 /* return to caller */
+
+/*
+ * spdread
+ * in: r3 adr to read
+ * out: r3 val or -1 for error
+ * uses r10, assumes that r14 points to I2C controller
+ */
+spdRead:
+ mfspr r25, 8 /* save link register */
+
+ bl spdWaitIdle
+ bne spdErr
+
+ li r10, 0x80 /* start with MEN */
+ stb r10, 8(r14)
+ eieio
+
+ li r10, 0xb0 /* start as master */
+ stb r10, 8(r14)
+ eieio
+
+ li r10, 0xa0 /* write device 0xA0 */
+ stb r10, 16(r14)
+ eieio
+ bl waitSpd
+ bne spdErr
+
+ lbz r10, 12(r14) /* test ACK */
+ andi. r10, r10, 0x01
+ bne gotNoAck
+
+ stb r3, 16(r14) /* data address */
+ eieio
+ bl waitSpd
+ bne spdErr
+
+
+ li r10, 0xb4 /* switch to read - restart */
+ stb r10, 8(r14)
+ eieio
+
+ li r10, 0xa1 /* read device 0xA0 */
+ stb r10, 16(r14)
+ eieio
+ bl waitSpd
+ bne spdErr
+
+ li r10, 0xa8 /* no ACK */
+ stb r10, 8(r14)
+ eieio
+
+ lbz r10, 16(r14) /* trigger read next byte */
+ eieio
+ bl waitSpd
+ bne spdErr
+
+ li r10, 0x88 /* generate STOP condition */
+ stb r10, 8(r14)
+ eieio
+
+ lbz r3, 16(r14) /* return read byte */
+
+ mtspr 8, r25 /* restore link register */
+ blr
+
+gotNoAck:
+ li r10, 0x80 /* generate STOP condition */
+ stb r10, 8(r14)
+ eieio
+spdErr:
+ orc r3, r0, r0 /* return -1 */
+ mtspr 8, r25 /* restore link register */
+ blr
+
+get_lnk_reg:
+ mflr r3 /* return link reg */
+ blr
+
+MessageBlock:
+
+MinitLogo:
+ .ascii "\015\012*** ELTEC Elektronik, Mainz ***\015\012"
+ .ascii "\015\012Initialising RAM\015\012\000"
+Mspd01:
+ .ascii " Reading SPD of SODIMM ...... \000"
+MramTyp:
+ .ascii "\015\012\SDRAM with CL=2 at 100 MHz required!\015\012\000"
+MramConfErr:
+ .ascii "\015\012\Unsupported SODIMM Configuration!\015\012\000"
+Mactivate:
+ .ascii " Activating \000"
+Mact0123e:
+ .ascii " MByte.\015\012\000"
+Mok:
+ .ascii "OK \015\012\000"
+Mfail:
+ .ascii "FAILED \015\012\000"
+MnewLine:
+ .ascii "\015\012\000"
+ .align 4
diff --git a/board/eltec/elppc/u-boot.lds b/board/eltec/elppc/u-boot.lds
new file mode 100644
index 0000000000..7b10c0d2aa
--- /dev/null
+++ b/board/eltec/elppc/u-boot.lds
@@ -0,0 +1,129 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * 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
+ */
+
+/*
+ * u-boot.lds - linker script for U-Boot on the Galileo Eval Board.
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/74xx_7xx/start.o (.text)
+
+/* store the environment in a seperate sector in the boot flash */
+/* . = env_offset; */
+/* common/environment.o(.text) */
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/board/ep7312/flash.c b/board/ep7312/flash.c
new file mode 100644
index 0000000000..373d238ccf
--- /dev/null
+++ b/board/ep7312/flash.c
@@ -0,0 +1,341 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#define FLASH_BANK_SIZE 0x1000000
+#define MAIN_SECT_SIZE 0x20000
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+/*-----------------------------------------------------------------------
+ */
+
+ulong flash_init (void)
+{
+ int i, j;
+ ulong size = 0;
+
+ for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+ ulong flashbase = 0;
+
+ flash_info[i].flash_id =
+ (INTEL_MANUFACT & FLASH_VENDMASK) |
+ (INTEL_ID_28F128J3 & FLASH_TYPEMASK);
+ flash_info[i].size = FLASH_BANK_SIZE;
+ flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
+ memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
+ if (i == 0)
+ flashbase = PHYS_FLASH_1;
+ else
+ panic ("configured to many flash banks!\n");
+ for (j = 0; j < flash_info[i].sector_count; j++) {
+ flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE;
+ }
+ size += flash_info[i].size;
+ }
+
+ /* Protect monitor and environment sectors
+ */
+ flash_protect ( FLAG_PROTECT_SET,
+ CFG_FLASH_BASE,
+ CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
+ &flash_info[0]);
+
+ flash_protect ( FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+ int i;
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case (INTEL_MANUFACT & FLASH_VENDMASK):
+ printf ("Intel: ");
+ break;
+ default:
+ printf ("Unknown Vendor ");
+ break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
+ printf ("28F128J3 (128Mbit)\n");
+ break;
+ default:
+ printf ("Unknown Chip Type\n");
+ goto Done;
+ break;
+ }
+
+ printf (" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+
+ printf (" Sector Start Addresses:");
+ for (i = 0; i < info->sector_count; i++) {
+ if ((i % 5) == 0) {
+ printf ("\n ");
+ }
+ printf (" %08lX%s", info->start[i],
+ info->protect[i] ? " (RO)" : " ");
+ }
+ printf ("\n");
+
+ Done:
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+ int flag, prot, sect;
+ int rc = ERR_OK;
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ return ERR_UNKNOWN_FLASH_TYPE;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ return ERR_INVAL;
+ }
+
+ if ((info->flash_id & FLASH_VENDMASK) !=
+ (INTEL_MANUFACT & FLASH_VENDMASK)) {
+ return ERR_UNKNOWN_FLASH_VENDOR;
+ }
+
+ prot = 0;
+ for (sect = s_first; sect <= s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+ if (prot)
+ return ERR_PROTECTED;
+
+ /*
+ * Disable interrupts which might cause a timeout
+ * here. Remember that our exception vectors are
+ * at address 0 in the flash, and we don't want a
+ * (ticker) exception to happen while the flash
+ * chip is in programming mode.
+ */
+ flag = disable_interrupts ();
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
+
+ printf ("Erasing sector %2d ... ", sect);
+
+ /* arm simple, non interrupt dependent timer */
+ reset_timer_masked ();
+
+ if (info->protect[sect] == 0) { /* not protected */
+ vu_short *addr = (vu_short *) (info->start[sect]);
+
+ *addr = 0x20; /* erase setup */
+ *addr = 0xD0; /* erase confirm */
+
+ while ((*addr & 0x80) != 0x80) {
+ if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
+ *addr = 0xB0; /* suspend erase */
+ *addr = 0xFF; /* reset to read mode */
+ rc = ERR_TIMOUT;
+ goto outahere;
+ }
+ }
+
+ /* clear status register command */
+ *addr = 0x50;
+ /* reset to read mode */
+ *addr = 0xFF;
+ }
+ printf ("ok.\n");
+ }
+ if (ctrlc ())
+ printf ("User Interrupt!\n");
+
+ outahere:
+
+ /* allow flash to settle - wait 10 ms */
+ udelay_masked (10000);
+
+ if (flag)
+ enable_interrupts ();
+
+ return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash
+ */
+
+static int write_word (flash_info_t * info, ulong dest, ushort data)
+{
+ vu_short *addr = (vu_short *) dest, val;
+ int rc = ERR_OK;
+ int flag;
+
+ /* Check if Flash is (sufficiently) erased
+ */
+ if ((*addr & data) != data)
+ return ERR_NOT_ERASED;
+
+ /*
+ * Disable interrupts which might cause a timeout
+ * here. Remember that our exception vectors are
+ * at address 0 in the flash, and we don't want a
+ * (ticker) exception to happen while the flash
+ * chip is in programming mode.
+ */
+ flag = disable_interrupts ();
+
+ /* clear status register command */
+ *addr = 0x50;
+
+ /* program set-up command */
+ *addr = 0x40;
+
+ /* latch address/data */
+ *addr = data;
+
+ /* arm simple, non interrupt dependent timer */
+ reset_timer_masked ();
+
+ /* wait while polling the status register */
+ while (((val = *addr) & 0x80) != 0x80) {
+ if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) {
+ rc = ERR_TIMOUT;
+ /* suspend program command */
+ *addr = 0xB0;
+ goto outahere;
+ }
+ }
+
+ if (val & 0x1A) { /* check for error */
+ printf ("\nFlash write error %02x at address %08lx\n",
+ (int) val, (unsigned long) dest);
+ if (val & (1 << 3)) {
+ printf ("Voltage range error.\n");
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+ if (val & (1 << 1)) {
+ printf ("Device protect error.\n");
+ rc = ERR_PROTECTED;
+ goto outahere;
+ }
+ if (val & (1 << 4)) {
+ printf ("Programming error.\n");
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+
+ outahere:
+ /* read array command */
+ *addr = 0xFF;
+
+ if (flag)
+ enable_interrupts ();
+
+ return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash.
+ */
+
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+ ulong cp, wp;
+ ushort data;
+ int l;
+ int i, rc;
+
+ wp = (addr & ~1); /* get lower word aligned address */
+
+ /*
+ * handle unaligned start bytes
+ */
+ if ((l = addr - wp) != 0) {
+ data = 0;
+ for (i = 0, cp = wp; i < l; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *) cp << 8);
+ }
+ for (; i < 2 && cnt > 0; ++i) {
+ data = (data >> 8) | (*src++ << 8);
+ --cnt;
+ ++cp;
+ }
+ for (; cnt == 0 && i < 2; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *) cp << 8);
+ }
+
+ if ((rc = write_word (info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 2;
+ }
+
+ /*
+ * handle word aligned part
+ */
+ while (cnt >= 2) {
+ data = *((vu_short *) src);
+ if ((rc = write_word (info, wp, data)) != 0) {
+ return (rc);
+ }
+ src += 2;
+ wp += 2;
+ cnt -= 2;
+ }
+
+ if (cnt == 0) {
+ return ERR_OK;
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ data = 0;
+ for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
+ data = (data >> 8) | (*src++ << 8);
+ --cnt;
+ }
+ for (; i < 2; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *) cp << 8);
+ }
+
+ return write_word (info, wp, data);
+}
diff --git a/board/ep7312/u-boot.lds b/board/ep7312/u-boot.lds
new file mode 100644
index 0000000000..084964858b
--- /dev/null
+++ b/board/ep7312/u-boot.lds
@@ -0,0 +1,53 @@
+/*
+ * (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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ cpu/arm720t/start.o (.text)
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ armboot_end_data = .;
+
+ . = ALIGN(4);
+ .bss : { *(.bss) }
+
+ armboot_end = .;
+}
diff --git a/board/esd/common/fpga.c b/board/esd/common/fpga.c
new file mode 100644
index 0000000000..666b4908e0
--- /dev/null
+++ b/board/esd/common/fpga.c
@@ -0,0 +1,262 @@
+/*
+ * (C) Copyright 2001
+ * Matthias Fuchs, esd gmbh germany, matthias.fuchs@esd-electronics.com
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 <asm/processor.h>
+#include <command.h>
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef FPGA_DEBUG
+#define DBG(x...) printf(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG */
+
+#define MAX_ONES 226
+
+#define IBM405GP_GPIO0_OR 0xef600700 /* GPIO Output */
+#define IBM405GP_GPIO0_TCR 0xef600704 /* GPIO Three-State Control */
+#define IBM405GP_GPIO0_ODR 0xef600718 /* GPIO Open Drain */
+#define IBM405GP_GPIO0_IR 0xef60071c /* GPIO Input */
+
+#ifdef CFG_FPGA_PRG
+# define FPGA_PRG CFG_FPGA_PRG /* FPGA program pin (ppc output)*/
+# define FPGA_CLK CFG_FPGA_CLK /* FPGA clk pin (ppc output) */
+# define FPGA_DATA CFG_FPGA_DATA /* FPGA data pin (ppc output) */
+# define FPGA_DONE CFG_FPGA_DONE /* FPGA done pin (ppc input) */
+# define FPGA_INIT CFG_FPGA_INIT /* FPGA init pin (ppc input) */
+#else
+# define FPGA_PRG 0x04000000 /* FPGA program pin (ppc output) */
+# define FPGA_CLK 0x02000000 /* FPGA clk pin (ppc output) */
+# define FPGA_DATA 0x01000000 /* FPGA data pin (ppc output) */
+# define FPGA_DONE 0x00800000 /* FPGA done pin (ppc input) */
+# define FPGA_INIT 0x00400000 /* FPGA init pin (ppc input) */
+#endif
+
+#define ERROR_FPGA_PRG_INIT_LOW -1 /* Timeout after PRG* asserted */
+#define ERROR_FPGA_PRG_INIT_HIGH -2 /* Timeout after PRG* deasserted */
+#define ERROR_FPGA_PRG_DONE -3 /* Timeout after programming */
+
+#define SET_FPGA(data) out32(IBM405GP_GPIO0_OR, data)
+
+#define FPGA_WRITE_1 { \
+ SET_FPGA(FPGA_PRG | FPGA_DATA); /* set clock to 0 */ \
+ SET_FPGA(FPGA_PRG | FPGA_DATA); /* set data to 1 */ \
+ SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set clock to 1 */ \
+ SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */
+
+#define FPGA_WRITE_0 { \
+ SET_FPGA(FPGA_PRG | FPGA_DATA); /* set clock to 0 */ \
+ SET_FPGA(FPGA_PRG); /* set data to 0 */ \
+ SET_FPGA(FPGA_PRG | FPGA_CLK); /* set clock to 1 */ \
+ SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */
+
+
+static int fpga_boot(unsigned char *fpgadata, int size)
+{
+ int i,index,len;
+ int count;
+#ifdef CFG_FPGA_SPARTAN2
+ int j;
+#else
+ unsigned char b;
+ int bit;
+#endif
+
+ /* display infos on fpgaimage */
+ index = 15;
+ for (i=0; i<4; i++)
+ {
+ len = fpgadata[index];
+ DBG("FPGA: %s\n", &(fpgadata[index+1]));
+ index += len+3;
+ }
+
+#ifdef CFG_FPGA_SPARTAN2
+ /* search for preamble 0xFFFFFFFF */
+ while (1)
+ {
+ if ((fpgadata[index] == 0xff) && (fpgadata[index+1] == 0xff) &&
+ (fpgadata[index+2] == 0xff) && (fpgadata[index+3] == 0xff))
+ break; /* preamble found */
+ else
+ index++;
+ }
+#else
+ /* search for preamble 0xFF2X */
+ for (index = 0; index < size-1 ; index++)
+ {
+ if ((fpgadata[index] == 0xff) && ((fpgadata[index+1] & 0xf0) == 0x30))
+ break;
+ }
+ index += 2;
+#endif
+
+ DBG("FPGA: configdata starts at position 0x%x\n",index);
+ DBG("FPGA: length of fpga-data %d\n", size-index);
+
+ /*
+ * Setup port pins for fpga programming
+ */
+ out32(IBM405GP_GPIO0_ODR, 0x00000000); /* no open drain pins */
+ out32(IBM405GP_GPIO0_TCR, FPGA_PRG | FPGA_CLK | FPGA_DATA); /* setup for output */
+ out32(IBM405GP_GPIO0_OR, FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set output pins to high */
+
+ DBG("%s, ",((in32(IBM405GP_GPIO0_IR) & FPGA_DONE) == 0) ? "NOT DONE" : "DONE" );
+ DBG("%s\n",((in32(IBM405GP_GPIO0_IR) & FPGA_INIT) == 0) ? "NOT INIT" : "INIT" );
+
+ /*
+ * Init fpga by asserting and deasserting PROGRAM*
+ */
+ SET_FPGA(FPGA_CLK | FPGA_DATA);
+
+ /* Wait for FPGA init line low */
+ count = 0;
+ while (in32(IBM405GP_GPIO0_IR) & FPGA_INIT)
+ {
+ udelay(1000); /* wait 1ms */
+ /* Check for timeout - 100us max, so use 3ms */
+ if (count++ > 3)
+ {
+ DBG("FPGA: Booting failed!\n");
+ return ERROR_FPGA_PRG_INIT_LOW;
+ }
+ }
+
+ DBG("%s, ",((in32(IBM405GP_GPIO0_IR) & FPGA_DONE) == 0) ? "NOT DONE" : "DONE" );
+ DBG("%s\n",((in32(IBM405GP_GPIO0_IR) & FPGA_INIT) == 0) ? "NOT INIT" : "INIT" );
+
+ /* deassert PROGRAM* */
+ SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA);
+
+ /* Wait for FPGA end of init period . */
+ count = 0;
+ while (!(in32(IBM405GP_GPIO0_IR) & FPGA_INIT))
+ {
+ udelay(1000); /* wait 1ms */
+ /* Check for timeout */
+ if (count++ > 3)
+ {
+ DBG("FPGA: Booting failed!\n");
+ return ERROR_FPGA_PRG_INIT_HIGH;
+ }
+ }
+
+ DBG("%s, ",((in32(IBM405GP_GPIO0_IR) & FPGA_DONE) == 0) ? "NOT DONE" : "DONE" );
+ DBG("%s\n",((in32(IBM405GP_GPIO0_IR) & FPGA_INIT) == 0) ? "NOT INIT" : "INIT" );
+
+ DBG("write configuration data into fpga\n");
+ /* write configuration-data into fpga... */
+
+#ifdef CFG_FPGA_SPARTAN2
+ /*
+ * Load uncompressed image into fpga
+ */
+ for (i=index; i<size; i++)
+ {
+ for (j=0; j<8; j++)
+ {
+ if ((fpgadata[i] & 0x80) == 0x80)
+ {
+ FPGA_WRITE_1;
+ }
+ else
+ {
+ FPGA_WRITE_0;
+ }
+ fpgadata[i] <<= 1;
+ }
+ }
+#else
+ /* send 0xff 0x20 */
+ FPGA_WRITE_1; FPGA_WRITE_1; FPGA_WRITE_1; FPGA_WRITE_1;
+ FPGA_WRITE_1; FPGA_WRITE_1; FPGA_WRITE_1; FPGA_WRITE_1;
+ FPGA_WRITE_0; FPGA_WRITE_0; FPGA_WRITE_1; FPGA_WRITE_0;
+ FPGA_WRITE_0; FPGA_WRITE_0; FPGA_WRITE_0; FPGA_WRITE_0;
+
+ /*
+ ** Bit_DeCompression
+ ** Code 1 .. maxOnes : n '1's followed by '0'
+ ** maxOnes + 1 .. maxOnes + 1 : n - 1 '1's no '0'
+ ** maxOnes + 2 .. 254 : n - (maxOnes + 2) '0's followed by '1'
+ ** 255 : '1'
+ */
+
+ for (i=index; i<size; i++)
+ {
+ b = fpgadata[i];
+ if ((b >= 1) && (b <= MAX_ONES))
+ {
+ for(bit=0; bit<b; bit++)
+ {
+ FPGA_WRITE_1;
+ }
+ FPGA_WRITE_0;
+ }
+ else if (b == (MAX_ONES+1))
+ {
+ for(bit=1; bit<b; bit++)
+ {
+ FPGA_WRITE_1;
+ }
+ }
+ else if ((b >= (MAX_ONES+2)) && (b <= 254))
+ {
+ for(bit=0; bit<(b-(MAX_ONES+2)); bit++)
+ {
+ FPGA_WRITE_0;
+ }
+ FPGA_WRITE_1;
+ }
+ else if (b == 255)
+ {
+ FPGA_WRITE_1;
+ }
+ }
+#endif
+
+ DBG("%s, ",((in32(IBM405GP_GPIO0_IR) & FPGA_DONE) == 0) ? "NOT DONE" : "DONE" );
+ DBG("%s\n",((in32(IBM405GP_GPIO0_IR) & FPGA_INIT) == 0) ? "NOT INIT" : "INIT" );
+
+ /*
+ * Check if fpga's DONE signal - correctly booted ?
+ */
+
+ /* Wait for FPGA end of programming period . */
+ count = 0;
+ while (!(in32(IBM405GP_GPIO0_IR) & FPGA_DONE))
+ {
+ udelay(1000); /* wait 1ms */
+ /* Check for timeout */
+ if (count++ > 3)
+ {
+ DBG("FPGA: Booting failed!\n");
+ return ERROR_FPGA_PRG_DONE;
+ }
+ }
+
+ DBG("FPGA: Booting successful!\n");
+ return 0;
+}
diff --git a/board/esd/common/pci.c b/board/esd/common/pci.c
new file mode 100644
index 0000000000..f8f180c6c4
--- /dev/null
+++ b/board/esd/common/pci.c
@@ -0,0 +1,202 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 <ppc4xx.h>
+#include <asm/processor.h>
+#include <pci.h>
+
+
+u_long pci9054_iobase;
+
+
+#define PCI_PRIMARY_CAR (0x500000dc) /* PCI config address reg */
+#define PCI_PRIMARY_CDR (0x80000000) /* PCI config data reg */
+
+
+/*-----------------------------------------------------------------------------+
+| Subroutine: pci9054_read_config_dword
+| Description: Read a PCI configuration register
+| Inputs:
+| hose PCI Controller
+| dev PCI Bus+Device+Function number
+| offset Configuration register number
+| value Address of the configuration register value
+| Return value:
+| 0 Successful
++-----------------------------------------------------------------------------*/
+int pci9054_read_config_dword(struct pci_controller *hose,
+ pci_dev_t dev, int offset, u32* value)
+{
+ unsigned long conAdrVal;
+ unsigned long val;
+
+ /* generate coded value for CON_ADR register */
+ conAdrVal = dev | (offset & 0xfc) | 0x80000000;
+
+ /* Load the CON_ADR (CAR) value first, then read from CON_DATA (CDR) */
+ *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
+
+ /* Note: *pResult comes back as -1 if machine check happened */
+ val = in32r(PCI_PRIMARY_CDR);
+
+ *value = (unsigned long) val;
+
+ out32r(PCI_PRIMARY_CAR, 0);
+
+ if ((*(unsigned long *)0x50000304) & 0x60000000)
+ {
+ /* clear pci master/target abort bits */
+ *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------+
+| Subroutine: pci9054_write_config_dword
+| Description: Write a PCI configuration register.
+| Inputs:
+| hose PCI Controller
+| dev PCI Bus+Device+Function number
+| offset Configuration register number
+| Value Configuration register value
+| Return value:
+| 0 Successful
+| Updated for pass2 errata #6. Need to disable interrupts and clear the
+| PCICFGADR reg after writing the PCICFGDATA reg.
++-----------------------------------------------------------------------------*/
+int pci9054_write_config_dword(struct pci_controller *hose,
+ pci_dev_t dev, int offset, u32 value)
+{
+ unsigned long conAdrVal;
+
+ conAdrVal = dev | (offset & 0xfc) | 0x80000000;
+
+ *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
+
+ out32r(PCI_PRIMARY_CDR, value);
+
+ out32r(PCI_PRIMARY_CAR, 0);
+
+ /* clear pci master/target abort bits */
+ *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
+
+ return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+#ifdef CONFIG_DASA_SIM
+static void pci_dasa_sim_config_pci9054(struct pci_controller *hose, pci_dev_t dev,
+ struct pci_config_table *_)
+{
+ unsigned int iobase;
+ unsigned short status = 0;
+ unsigned char timer;
+
+ /*
+ * Configure PLX PCI9054
+ */
+ pci_read_config_word(CFG_PCI9054_DEV_FN, PCI_COMMAND, &status);
+ status |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+ pci_write_config_word(CFG_PCI9054_DEV_FN, PCI_COMMAND, status);
+
+ /* Check the latency timer for values >= 0x60.
+ */
+ pci_read_config_byte(CFG_PCI9054_DEV_FN, PCI_LATENCY_TIMER, &timer);
+ if (timer < 0x60)
+ {
+ pci_write_config_byte(CFG_PCI9054_DEV_FN, PCI_LATENCY_TIMER, 0x60);
+ }
+
+ /* Set I/O base register.
+ */
+ pci_write_config_dword(CFG_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, CFG_PCI9054_IOBASE);
+ pci_read_config_dword(CFG_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, &iobase);
+
+ pci9054_iobase = pci_mem_to_phys(CFG_PCI9054_DEV_FN, iobase & PCI_BASE_ADDRESS_MEM_MASK);
+
+ if (pci9054_iobase == 0xffffffff)
+ {
+ printf("Error: Can not set I/O base register.\n");
+ return;
+ }
+}
+#endif
+
+static struct pci_config_table pci9054_config_table[] = {
+#ifndef CONFIG_PCI_PNP
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_BUS(CFG_ETH_DEV_FN), PCI_DEV(CFG_ETH_DEV_FN), PCI_FUNC(CFG_ETH_DEV_FN),
+ pci_cfgfunc_config_device, { CFG_ETH_IOBASE,
+ CFG_ETH_IOBASE,
+ PCI_COMMAND_IO | PCI_COMMAND_MASTER }},
+#ifdef CONFIG_DASA_SIM
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_BUS(CFG_PCI9054_DEV_FN), PCI_DEV(CFG_PCI9054_DEV_FN), PCI_FUNC(CFG_PCI9054_DEV_FN),
+ pci_dasa_sim_config_pci9054 },
+#endif
+#endif
+ { }
+};
+
+static struct pci_controller pci9054_hose = {
+ config_table: pci9054_config_table,
+};
+
+void pci_init(void)
+{
+ struct pci_controller *hose = &pci9054_hose;
+
+ /*
+ * Register the hose
+ */
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ /* System memory space */
+ pci_set_region(hose->regions + 0,
+ 0x00000000, 0x00000000, 0x01000000,
+ PCI_REGION_MEM | PCI_REGION_MEMORY);
+
+ /* PCI Memory space */
+ pci_set_region(hose->regions + 1,
+ 0x00000000, 0xc0000000, 0x10000000,
+ PCI_REGION_MEM);
+
+ pci_set_ops(hose,
+ pci_hose_read_config_byte_via_dword,
+ pci_hose_read_config_word_via_dword,
+ pci9054_read_config_dword,
+ pci_hose_write_config_byte_via_dword,
+ pci_hose_write_config_word_via_dword,
+ pci9054_write_config_dword);
+
+ hose->region_count = 2;
+
+ pci_register_hose(hose);
+
+ hose->last_busno = pci_hose_scan(hose);
+}
diff --git a/board/esd/cpci405/cpci405.c b/board/esd/cpci405/cpci405.c
new file mode 100644
index 0000000000..2dda8fabbd
--- /dev/null
+++ b/board/esd/cpci405/cpci405.c
@@ -0,0 +1,451 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 <asm/processor.h>
+#include <command.h>
+#include <cmd_boot.h>
+#include <malloc.h>
+
+/* ------------------------------------------------------------------------- */
+
+#if 0
+#define FPGA_DEBUG
+#endif
+
+/* fpga configuration data - generated by bin2cc */
+const unsigned char fpgadata[] =
+{
+#ifdef CONFIG_CPCI405_VER2
+# include "fpgadata_cpci4052.c"
+#else
+# include "fpgadata_cpci405.c"
+#endif
+};
+
+/*
+ * include common fpga code (for esd boards)
+ */
+#include "../common/fpga.c"
+
+
+/* Prototypes */
+int version2(void);
+int gunzip(void *, int, unsigned char *, int *);
+
+
+int board_pre_init (void)
+{
+#ifndef CONFIG_CPCI405_VER2
+ int index, len, i;
+ int status;
+#endif
+
+#ifdef FPGA_DEBUG
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /* set up serial port with default baudrate */
+ (void) get_clocks ();
+ gd->baudrate = CONFIG_BAUDRATE;
+ serial_init ();
+ console_init_f();
+#endif
+
+ /*
+ * First pull fpga-prg pin low, to disable fpga logic (on version 2 board)
+ */
+ out32(IBM405GP_GPIO0_ODR, 0x00000000); /* no open drain pins */
+ out32(IBM405GP_GPIO0_TCR, CFG_FPGA_PRG); /* setup for output */
+ out32(IBM405GP_GPIO0_OR, CFG_FPGA_PRG); /* set output pins to high */
+ out32(IBM405GP_GPIO0_OR, 0); /* pull prg low */
+
+ /*
+ * Boot onboard FPGA
+ */
+#ifndef CONFIG_CPCI405_VER2
+ if (!version2()) {
+ status = fpga_boot((unsigned char *)fpgadata, sizeof(fpgadata));
+ if (status != 0) {
+ /* booting FPGA failed */
+#ifndef FPGA_DEBUG
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /* set up serial port with default baudrate */
+ (void) get_clocks ();
+ gd->baudrate = CONFIG_BAUDRATE;
+ serial_init ();
+ console_init_f();
+#endif
+ printf("\nFPGA: Booting failed ");
+ switch (status) {
+ case ERROR_FPGA_PRG_INIT_LOW:
+ printf("(Timeout: INIT not low after asserting PROGRAM*)\n ");
+ break;
+ case ERROR_FPGA_PRG_INIT_HIGH:
+ printf("(Timeout: INIT not high after deasserting PROGRAM*)\n ");
+ break;
+ case ERROR_FPGA_PRG_DONE:
+ printf("(Timeout: DONE not high after programming FPGA)\n ");
+ break;
+ }
+
+ /* display infos on fpgaimage */
+ index = 15;
+ for (i=0; i<4; i++) {
+ len = fpgadata[index];
+ printf("FPGA: %s\n", &(fpgadata[index+1]));
+ index += len+3;
+ }
+ putc ('\n');
+ /* delayed reboot */
+ for (i=20; i>0; i--) {
+ printf("Rebooting in %2d seconds \r",i);
+ for (index=0;index<1000;index++)
+ udelay(1000);
+ }
+ putc ('\n');
+ do_reset(NULL, 0, 0, NULL);
+ }
+ }
+#endif /* !CONFIG_CPCI405_VER2 */
+
+ /*
+ * IRQ 0-15 405GP internally generated; active high; level sensitive
+ * IRQ 16 405GP internally generated; active low; level sensitive
+ * IRQ 17-24 RESERVED
+ * IRQ 25 (EXT IRQ 0) CAN0; active low; level sensitive
+ * IRQ 26 (EXT IRQ 1) CAN1 (+FPGA on CPCI4052) ; active low; level sensitive
+ * IRQ 27 (EXT IRQ 2) PCI SLOT 0; active low; level sensitive
+ * IRQ 28 (EXT IRQ 3) PCI SLOT 1; active low; level sensitive
+ * IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive
+ * IRQ 30 (EXT IRQ 5) PCI SLOT 3; active low; level sensitive
+ * IRQ 31 (EXT IRQ 6) COMPACT FLASH; active high; level sensitive
+ */
+ mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
+ mtdcr(uicer, 0x00000000); /* disable all ints */
+ mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/
+ mtdcr(uicpr, 0xFFFFFF81); /* set int polarities */
+ mtdcr(uictr, 0x10000000); /* set int trigger levels */
+ mtdcr(uicvcr, 0x00000001); /* set vect base=0,INT0 highest priority*/
+ mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
+
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+int ctermm2(void)
+{
+#ifdef CONFIG_CPCI405_VER2
+ return 0; /* no, board is cpci405 */
+#else
+ if ((*(unsigned char *)0xf0000400 == 0x00) &&
+ (*(unsigned char *)0xf0000401 == 0x01))
+ return 0; /* no, board is cpci405 */
+ else
+ return -1; /* yes, board is cterm-m2 */
+#endif
+}
+
+
+int cpci405_host(void)
+{
+ if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+ return -1; /* yes, board is cpci405 host */
+ else
+ return 0; /* no, board is cpci405 adapter */
+}
+
+
+int version2(void)
+{
+ unsigned long cntrl0Reg;
+ unsigned long value;
+
+ /*
+ * Setup GPIO pins (CS2/GPIO11 as GPIO)
+ */
+ cntrl0Reg = mfdcr(cntrl0);
+ mtdcr(cntrl0, cntrl0Reg | 0x02000000);
+
+ udelay(1000); /* wait some time before reading input */
+ value = in32(IBM405GP_GPIO0_IR) & 0x00100000; /* test GPIO11 */
+
+ /*
+ * Setup GPIO pins (CS2/GPIO11 as CS again)
+ */
+ mtdcr(cntrl0, cntrl0Reg);
+
+ if (value)
+ return 0; /* no, board is version 1.x */
+ else
+ return -1; /* yes, board is version 2.x */
+}
+
+
+int misc_init_f (void)
+{
+ return 0; /* dummy implementation */
+}
+
+
+int misc_init_r (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ bd_t *bd = gd->bd;
+ char * tmp; /* Temporary char pointer */
+
+#ifdef CONFIG_CPCI405_VER2
+ unsigned char *dst;
+ ulong len = sizeof(fpgadata);
+ int status;
+ int index;
+ int i;
+ unsigned long cntrl0Reg;
+
+ /*
+ * On CPCI-405 version 2 the environment is saved in eeprom!
+ * FPGA can be gzip compressed (malloc) and booted this late.
+ */
+
+ if (version2()) {
+ /*
+ * Setup GPIO pins (CS6+CS7 as GPIO)
+ */
+ cntrl0Reg = mfdcr(cntrl0);
+ mtdcr(cntrl0, cntrl0Reg | 0x00300000);
+
+ dst = malloc(CFG_FPGA_MAX_SIZE);
+ if (gunzip (dst, CFG_FPGA_MAX_SIZE, (uchar *)fpgadata, (int *)&len) != 0) {
+ printf ("GUNZIP ERROR - must RESET board to recover\n");
+ do_reset (NULL, 0, 0, NULL);
+ }
+
+ status = fpga_boot(dst, len);
+ if (status != 0) {
+ printf("\nFPGA: Booting failed ");
+ switch (status) {
+ case ERROR_FPGA_PRG_INIT_LOW:
+ printf("(Timeout: INIT not low after asserting PROGRAM*)\n ");
+ break;
+ case ERROR_FPGA_PRG_INIT_HIGH:
+ printf("(Timeout: INIT not high after deasserting PROGRAM*)\n ");
+ break;
+ case ERROR_FPGA_PRG_DONE:
+ printf("(Timeout: DONE not high after programming FPGA)\n ");
+ break;
+ }
+
+ /* display infos on fpgaimage */
+ index = 15;
+ for (i=0; i<4; i++) {
+ len = dst[index];
+ printf("FPGA: %s\n", &(dst[index+1]));
+ index += len+3;
+ }
+ putc ('\n');
+ /* delayed reboot */
+ for (i=20; i>0; i--) {
+ printf("Rebooting in %2d seconds \r",i);
+ for (index=0;index<1000;index++)
+ udelay(1000);
+ }
+ putc ('\n');
+ do_reset(NULL, 0, 0, NULL);
+ }
+
+ /* restore gpio/cs settings */
+ mtdcr(cntrl0, cntrl0Reg);
+
+ puts("FPGA: ");
+
+ /* display infos on fpgaimage */
+ index = 15;
+ for (i=0; i<4; i++) {
+ len = dst[index];
+ printf("%s ", &(dst[index+1]));
+ index += len+3;
+ }
+ putc ('\n');
+
+ free(dst);
+ }
+ else {
+ printf("\n*** U-Boot Version does not match Board Version!\n");
+ printf("*** CPCI-405 Version 2.x detected!\n");
+ printf("*** Please use correct U-Boot version (CPCI4052)!\n\n");
+ }
+
+#else /* CONFIG_CPCI405_VER2 */
+
+ /*
+ * Generate last byte of ip-addr from code-plug @ 0xf0000400
+ */
+ if (ctermm2()) {
+ char str[32];
+ unsigned char ipbyte = *(unsigned char *)0xf0000400;
+
+ /*
+ * Only overwrite ip-addr with allowed values
+ */
+ if ((ipbyte != 0x00) && (ipbyte != 0xff)) {
+ bd->bi_ip_addr = (bd->bi_ip_addr & 0xffffff00) | ipbyte;
+ sprintf(str, "%ld.%ld.%ld.%ld",
+ (bd->bi_ip_addr & 0xff000000) >> 24,
+ (bd->bi_ip_addr & 0x00ff0000) >> 16,
+ (bd->bi_ip_addr & 0x0000ff00) >> 8,
+ (bd->bi_ip_addr & 0x000000ff));
+ setenv("ipaddr", str);
+ }
+ }
+
+ if (version2()) {
+ printf("\n*** U-Boot Version does not match Board Version!\n");
+ printf("*** CPCI-405 Board Version 1.x detected!\n");
+ printf("*** Please use correct U-Boot version (CPCI405)!\n\n");
+ }
+
+#endif /* CONFIG_CPCI405_VER2 */
+
+ /*
+ * Write ethernet addr in NVRAM for VxWorks
+ */
+ tmp = (char *)CFG_NVRAM_BASE_ADDR + CFG_NVRAM_VXWORKS_OFFS;
+ memcpy( (char *)tmp, (char *)&bd->bi_enetaddr[0], 6 );
+ return (0);
+}
+
+
+/*
+ * Check Board Identity:
+ */
+
+int checkboard (void)
+{
+#ifndef CONFIG_CPCI405_VER2
+ int index;
+ int len;
+#endif
+ unsigned char str[64];
+ int i = getenv_r ("serial#", str, sizeof(str));
+
+ puts ("Board: ");
+
+ if (i == -1) {
+ puts ("### No HW ID - assuming CPCI405");
+ } else {
+ puts(str);
+ }
+
+ if (version2())
+ puts (" (Ver 2.x, ");
+ else
+ puts (" (Ver 1.x, ");
+
+#if 0
+ if ((*(unsigned short *)((unsigned long)CFG_FPGA_BASE_ADDR) + CFG_FPGA_STATUS)
+ & CFG_FPGA_STATUS_FLASH)
+ puts ("FLASH Bank A, ");
+ else
+ puts ("FLASH Bank B, ");
+#endif
+
+ if (ctermm2()) {
+ printf("CTERM-M2 - Id=0x%02x)", *(unsigned char *)0xf0000400);
+ } else {
+ if (cpci405_host()) {
+ puts ("PCI Host Version)");
+ } else {
+ puts ("PCI Adapter Version)");
+ }
+ }
+
+#ifndef CONFIG_CPCI405_VER2
+ puts ("\nFPGA: ");
+
+ /* display infos on fpgaimage */
+ index = 15;
+ for (i=0; i<4; i++) {
+ len = fpgadata[index];
+ printf("%s ", &(fpgadata[index+1]));
+ index += len+3;
+ }
+#endif
+
+ putc ('\n');
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+long int initdram (int board_type)
+{
+ unsigned long val;
+
+ mtdcr(memcfga, mem_mb0cf);
+ val = mfdcr(memcfgd);
+
+#if 0
+ printf("\nmb0cf=%x\n", val); /* test-only */
+ printf("strap=%x\n", mfdcr(strap)); /* test-only */
+#endif
+
+ return (4*1024*1024 << ((val & 0x000e0000) >> 17));
+}
+
+/* ------------------------------------------------------------------------- */
+
+int testdram (void)
+{
+ /* TODO: XXX XXX XXX */
+ printf ("test: 16 MB - ok\n");
+
+ return (0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_CPCI405_VER2
+#ifdef CONFIG_IDE_RESET
+
+void ide_set_reset(int on)
+{
+ volatile unsigned short *fpga_mode = (unsigned short *)CFG_FPGA_BASE_ADDR;
+
+ /*
+ * Assert or deassert CompactFlash Reset Pin
+ */
+ if (on) { /* assert RESET */
+ *fpga_mode &= ~(CFG_FPGA_MODE_CF_RESET);
+ } else { /* release RESET */
+ *fpga_mode |= CFG_FPGA_MODE_CF_RESET;
+ }
+}
+
+#endif /* CONFIG_IDE_RESET */
+#endif /* CONFIG_CPCI405_VER2 */
+
+/* ------------------------------------------------------------------------- */
diff --git a/board/esd/cpci440/cpci440.c b/board/esd/cpci440/cpci440.c
new file mode 100644
index 0000000000..51a5edd20a
--- /dev/null
+++ b/board/esd/cpci440/cpci440.c
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright 2002
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 <asm/processor.h>
+
+
+long int fixed_sdram( void );
+
+int board_pre_init (void)
+{
+ uint reg;
+
+ /*--------------------------------------------------------------------
+ * Setup the external bus controller/chip selects
+ *-------------------------------------------------------------------*/
+ mtdcr( ebccfga, xbcfg );
+ reg = mfdcr( ebccfgd );
+ mtdcr( ebccfgd, reg | 0x04000000 ); /* Set ATC */
+
+ mtebc( pb0ap, 0x92015480 ); /* FLASH/SRAM */
+ mtebc( pb0cr, 0xFF87A000 ); /* BAS=0xff8 8MB R/W 16-bit */
+ /* test-only: other regs still missing... */
+
+ /*--------------------------------------------------------------------
+ * Setup the interrupt controller polarities, triggers, etc.
+ *-------------------------------------------------------------------*/
+ mtdcr( uic0sr, 0xffffffff ); /* clear all */
+ mtdcr( uic0er, 0x00000000 ); /* disable all */
+ mtdcr( uic0cr, 0x00000009 ); /* SMI & UIC1 crit are critical */
+ mtdcr( uic0pr, 0xfffffe13 ); /* per ref-board manual */
+ mtdcr( uic0tr, 0x01c00008 ); /* per ref-board manual */
+ mtdcr( uic0vr, 0x00000001 ); /* int31 highest, base=0x000 */
+ mtdcr( uic0sr, 0xffffffff ); /* clear all */
+
+ mtdcr( uic1sr, 0xffffffff ); /* clear all */
+ mtdcr( uic1er, 0x00000000 ); /* disable all */
+ mtdcr( uic1cr, 0x00000000 ); /* all non-critical */
+ mtdcr( uic1pr, 0xffffe0ff ); /* per ref-board manual */
+ mtdcr( uic1tr, 0x00ffc000 ); /* per ref-board manual */
+ mtdcr( uic1vr, 0x00000001 ); /* int31 highest, base=0x000 */
+ mtdcr( uic1sr, 0xffffffff ); /* clear all */
+
+ return 0;
+}
+
+
+
+int checkboard (void)
+{
+ sys_info_t sysinfo;
+ get_sys_info(&sysinfo);
+
+ printf("Board: esd CPCI-440\n");
+ printf("\tVCO: %lu MHz\n", sysinfo.freqVCOMhz/1000000);
+ printf("\tCPU: %lu MHz\n", sysinfo.freqProcessor/1000000);
+ printf("\tPLB: %lu MHz\n", sysinfo.freqPLB/1000000);
+ printf("\tOPB: %lu MHz\n", sysinfo.freqOPB/1000000);
+ printf("\tEPB: %lu MHz\n", sysinfo.freqEPB/1000000);
+ return (0);
+}
+
+
+long int initdram (int board_type)
+{
+ long dram_size = 0;
+
+ dram_size = fixed_sdram();
+ return dram_size;
+}
+
+
+/*************************************************************************
+ * fixed sdram init -- doesn't use serial presence detect.
+ *
+ * Assumes: 64 MB, non-ECC, non-registered
+ * PLB @ 133 MHz
+ *
+ ************************************************************************/
+long int fixed_sdram( void )
+{
+ uint reg;
+
+ /*--------------------------------------------------------------------
+ * Setup some default
+ *------------------------------------------------------------------*/
+ mtsdram( mem_uabba, 0x00000000 ); /* ubba=0 (default) */
+ mtsdram( mem_slio, 0x00000000 ); /* rdre=0 wrre=0 rarw=0 */
+ mtsdram( mem_devopt,0x00000000 ); /* dll=0 ds=0 (normal) */
+ mtsdram( mem_wddctr,0x40000000 ); /* wrcp=0 dcd=0 */
+ mtsdram( mem_clktr, 0x40000000 ); /* clkp=1 (90 deg wr) dcdt=0 */
+
+ /*--------------------------------------------------------------------
+ * Setup for board-specific specific mem
+ *------------------------------------------------------------------*/
+ /*
+ * Following for CAS Latency = 2.5 @ 133 MHz PLB
+ */
+ mtsdram( mem_b0cr, 0x00082001 );/* SDBA=0x000, 64MB, Mode 2, enabled*/
+ mtsdram( mem_tr0, 0x410a4012 );/* WR=2 WD=1 CL=2.5 PA=3 CP=4 LD=2 */
+ /* RA=10 RD=3 */
+ mtsdram( mem_tr1, 0x8080082f );/* SS=T2 SL=STAGE 3 CD=1 CT=0x02f */
+ mtsdram( mem_rtr, 0x08200000 );/* Rate 15.625 ns @ 133 MHz PLB */
+ mtsdram( mem_cfg1, 0x00000000 );/* Self-refresh exit, disable PM */
+ udelay( 400 ); /* Delay 200 usecs (min) */
+
+ /*--------------------------------------------------------------------
+ * Enable the controller, then wait for DCEN to complete
+ *------------------------------------------------------------------*/
+ mtsdram( mem_cfg0, 0x86000000 );/* DCEN=1, PMUD=1, 64-bit */
+ for(;;)
+ {
+ mfsdram( mem_mcsts, reg );
+ if( reg & 0x80000000 )
+ break;
+ }
+
+ return( 64 * 1024 * 1024 ); /* 64 MB */
+}
diff --git a/board/esd/cpci440/init.S b/board/esd/cpci440/init.S
new file mode 100644
index 0000000000..2dab9f9a29
--- /dev/null
+++ b/board/esd/cpci440/init.S
@@ -0,0 +1,96 @@
+/*
+* Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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 <ppc_asm.tmpl>
+#include <config.h>
+
+/* General */
+#define TLB_VALID 0x00000200
+
+/* Supported page sizes */
+
+#define SZ_1K 0x00000000
+#define SZ_4K 0x00000010
+#define SZ_16K 0x00000020
+#define SZ_64K 0x00000030
+#define SZ_256K 0x00000040
+#define SZ_1M 0x00000050
+#define SZ_16M 0x00000070
+#define SZ_256M 0x00000090
+
+/* Storage attributes */
+#define SA_W 0x00000800 /* Write-through */
+#define SA_I 0x00000400 /* Caching inhibited */
+#define SA_M 0x00000200 /* Memory coherence */
+#define SA_G 0x00000100 /* Guarded */
+#define SA_E 0x00000080 /* Endian */
+
+/* Access control */
+#define AC_X 0x00000024 /* Execute */
+#define AC_W 0x00000012 /* Write */
+#define AC_R 0x00000009 /* Read */
+
+/* Some handy macros */
+
+#define EPN(e) ((e) & 0xfffffc00)
+#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) )
+#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) )
+#define TLB2(a) ( (a)&0x00000fbf )
+
+#define tlbtab_start\
+ mflr r1 ;\
+ bl 0f ;
+
+#define tlbtab_end\
+ .long 0, 0, 0 ; \
+0: mflr r0 ; \
+ mtlr r1 ; \
+ blr ;
+
+#define tlbentry(epn,sz,rpn,erpn,attr)\
+ .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr)
+
+
+/**************************************************************************
+ * TLB TABLE
+ *
+ * This table is used by the cpu boot code to setup the initial tlb
+ * entries. Rather than make broad assumptions in the cpu source tree,
+ * this table lets each board set things up however they like.
+ *
+ * Pointer to the table is returned in r1
+ *
+ *************************************************************************/
+
+ .section .bootpg,"ax"
+ .globl tlbtab
+
+tlbtab:
+ tlbtab_start
+ tlbentry( 0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I)
+ tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I)
+ tlbentry( CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X )
+ tlbentry( CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X )
+ tlbentry( CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X )
+ tlbtab_end
+
+
diff --git a/board/esd/pci405/pci405.c b/board/esd/pci405/pci405.c
new file mode 100644
index 0000000000..ed86c025f6
--- /dev/null
+++ b/board/esd/pci405/pci405.c
@@ -0,0 +1,254 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 <asm/processor.h>
+#include <command.h>
+#include <cmd_boot.h>
+#include <malloc.h>
+#include <pci.h>
+#include <405gp_pci.h>
+
+/* ------------------------------------------------------------------------- */
+
+#if 0
+#define FPGA_DEBUG
+#endif
+
+#define PCI_RECONFIG_MAGIC 0x07081967
+
+
+struct pci_config_regs {
+ unsigned short command;
+ unsigned char latency_timer;
+ unsigned char int_line;
+ unsigned long bar1;
+ unsigned long bar2;
+ unsigned long magic;
+};
+
+
+/* fpga configuration data - generated by bin2cc */
+const unsigned char fpgadata[] =
+{
+#include "fpgadata.c"
+};
+
+/*
+ * include common fpga code (for esd boards)
+ */
+#include "../common/fpga.c"
+
+
+/* Prototypes */
+int gunzip(void *, int, unsigned char *, int *);
+
+
+int board_pre_init (void)
+{
+ unsigned long cntrl0Reg;
+
+ /*
+ * IRQ 0-15 405GP internally generated; active high; level sensitive
+ * IRQ 16 405GP internally generated; active low; level sensitive
+ * IRQ 17-24 RESERVED
+ * IRQ 25 (EXT IRQ 0) CAN0; active low; level sensitive
+ * IRQ 26 (EXT IRQ 1) CAN1; active low; level sensitive
+ * IRQ 27 (EXT IRQ 2) CAN2; active low; level sensitive
+ * IRQ 28 (EXT IRQ 3) CAN3; active low; level sensitive
+ * IRQ 29 (EXT IRQ 4) unused; active low; level sensitive
+ * IRQ 30 (EXT IRQ 5) FPGA Timestamp; active low; level sensitive
+ * IRQ 31 (EXT IRQ 6) PCI Reset; active low; level sensitive
+ */
+ mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
+ mtdcr(uicer, 0x00000000); /* disable all ints */
+ mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/
+ mtdcr(uicpr, 0xFFFFFF80); /* set int polarities */
+ mtdcr(uictr, 0x10000000); /* set int trigger levels */
+ mtdcr(uicvcr, 0x00000001); /* set vect base=0,INT0 highest priority*/
+ mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
+
+ /*
+ * Setup GPIO pins (IRQ4/GPIO21 as GPIO)
+ */
+ cntrl0Reg = mfdcr(cntrl0);
+ mtdcr(cntrl0, cntrl0Reg | 0x00008000);
+
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+int misc_init_f (void)
+{
+ return 0; /* dummy implementation */
+}
+
+
+int misc_init_r (void)
+{
+ unsigned char *dst;
+ ulong len = sizeof(fpgadata);
+ int status;
+ int index;
+ int i;
+ struct pci_config_regs *pci_regs;
+
+ /*
+ * On PCI-405 the environment is saved in eeprom!
+ * FPGA can be gzip compressed (malloc) and booted this late.
+ */
+
+ dst = malloc(CFG_FPGA_MAX_SIZE);
+ if (gunzip (dst, CFG_FPGA_MAX_SIZE, (uchar *)fpgadata, (int *)&len) != 0) {
+ printf ("GUNZIP ERROR - must RESET board to recover\n");
+ do_reset (NULL, 0, 0, NULL);
+ }
+
+ status = fpga_boot(dst, len);
+ if (status != 0) {
+ printf("\nFPGA: Booting failed ");
+ switch (status) {
+ case ERROR_FPGA_PRG_INIT_LOW:
+ printf("(Timeout: INIT not low after asserting PROGRAM*)\n ");
+ break;
+ case ERROR_FPGA_PRG_INIT_HIGH:
+ printf("(Timeout: INIT not high after deasserting PROGRAM*)\n ");
+ break;
+ case ERROR_FPGA_PRG_DONE:
+ printf("(Timeout: DONE not high after programming FPGA)\n ");
+ break;
+ }
+
+ /* display infos on fpgaimage */
+ index = 15;
+ for (i=0; i<4; i++) {
+ len = dst[index];
+ printf("FPGA: %s\n", &(dst[index+1]));
+ index += len+3;
+ }
+ putc ('\n');
+ /* delayed reboot */
+ for (i=20; i>0; i--) {
+ printf("Rebooting in %2d seconds \r",i);
+ for (index=0;index<1000;index++)
+ udelay(1000);
+ }
+ putc ('\n');
+ do_reset(NULL, 0, 0, NULL);
+ }
+
+ puts("FPGA: ");
+
+ /* display infos on fpgaimage */
+ index = 15;
+ for (i=0; i<4; i++) {
+ len = dst[index];
+ printf("%s ", &(dst[index+1]));
+ index += len+3;
+ }
+ putc ('\n');
+
+ /*
+ * Rewrite pci config regs (only after soft-reset with magic set)
+ */
+ pci_regs = (struct pci_config_regs *)0x10;
+ if (pci_regs->magic == PCI_RECONFIG_MAGIC) {
+ puts("PCI: Found magic, rewriting config regs...\n");
+ pci_write_config_word(PCIDEVID_405GP, PCI_COMMAND,
+ pci_regs->command);
+ pci_write_config_byte(PCIDEVID_405GP, PCI_LATENCY_TIMER,
+ pci_regs->latency_timer);
+ pci_write_config_byte(PCIDEVID_405GP, PCI_INTERRUPT_LINE,
+ pci_regs->int_line);
+ pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_1,
+ pci_regs->bar1);
+ pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2,
+ pci_regs->bar2);
+ }
+ pci_regs->magic = 0; /* clear magic again */
+
+#if 0 /* test-only */
+ pci_read_config_word(PCIDEVID_405GP, PCI_COMMAND, &(pci_regs->command));
+ pci_read_config_byte(PCIDEVID_405GP, PCI_LATENCY_TIMER, &(pci_regs->latency_timer));
+ pci_read_config_byte(PCIDEVID_405GP, PCI_INTERRUPT_LINE, &(pci_regs->int_line));
+ pci_read_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_1, &(pci_regs->bar1));
+ pci_read_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, &(pci_regs->bar2));
+ pci_regs->magic = PCI_RECONFIG_MAGIC; /* set magic */
+#endif
+
+ free(dst);
+ return (0);
+}
+
+
+/*
+ * Check Board Identity:
+ */
+
+int checkboard (void)
+{
+ unsigned char str[64];
+ int i = getenv_r ("serial#", str, sizeof(str));
+
+ puts ("Board: ");
+
+ if (i == -1) {
+ puts ("### No HW ID - assuming CPCI405");
+ } else {
+ puts (str);
+ }
+ putc ('\n');
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+long int initdram (int board_type)
+{
+ unsigned long val;
+
+ mtdcr(memcfga, mem_mb0cf);
+ val = mfdcr(memcfgd);
+
+#if 0
+ printf("\nmb0cf=%x\n", val); /* test-only */
+ printf("strap=%x\n", mfdcr(strap)); /* test-only */
+#endif
+
+ return (4*1024*1024 << ((val & 0x000e0000) >> 17));
+}
+
+/* ------------------------------------------------------------------------- */
+
+int testdram (void)
+{
+ /* TODO: XXX XXX XXX */
+ printf ("test: 16 MB - ok\n");
+
+ return (0);
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/board/evb64260/eth_addrtbl.c b/board/evb64260/eth_addrtbl.c
new file mode 100644
index 0000000000..ea4925a9d0
--- /dev/null
+++ b/board/evb64260/eth_addrtbl.c
@@ -0,0 +1,225 @@
+#include <common.h>
+#include <malloc.h>
+#include <galileo/gt64260R.h>
+#include <galileo/core.h>
+#include <asm/cache.h>
+#include "eth.h"
+#include "eth_addrtbl.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define PRINTF printf
+
+#ifdef CONFIG_GT_USE_MAC_HASH_TABLE
+
+static u32 addressTableHashMode[ GAL_ETH_DEVS ] = { 0, };
+static u32 addressTableHashSize[ GAL_ETH_DEVS ] = { 0, };
+static addrTblEntry *addressTableBase[ GAL_ETH_DEVS ] = { 0, };
+static void *realAddrTableBase[ GAL_ETH_DEVS ] = { 0, };
+
+static const u32 hashLength[ 2 ] = {
+ (0x8000), /* 8K * 4 entries */
+ (0x8000/16), /* 512 * 4 entries */
+};
+
+/* Initialize the address table for a port, if needed */
+unsigned int initAddressTable( u32 port, u32 hashMode, u32 hashSizeSelector)
+{
+ unsigned int tableBase;
+
+ if( port < 0 || port >= GAL_ETH_DEVS ) {
+ printf("%s: Invalid port number %d\n", __FUNCTION__, port );
+ return 0;
+ }
+
+ if (hashMode > 1) {
+ printf("%s: Invalid Hash Mode %d\n", __FUNCTION__, port );
+ return 0;
+ }
+
+ if ( realAddrTableBase[port] &&
+ ( addressTableHashSize[port] != hashSizeSelector )) {
+ /* we have been here before,
+ * but now we want a different sized table
+ */
+ free( realAddrTableBase[port] );
+ realAddrTableBase[port] = 0;
+ addressTableBase[port] = 0;
+
+ }
+
+ tableBase = (unsigned int)addressTableBase[port];
+ /* we get called for every probe, so only do this once */
+ if ( !tableBase ) {
+ int bytes = hashLength[hashSizeSelector] * sizeof(addrTblEntry);
+
+ tableBase = (unsigned int)realAddrTableBase[port] = malloc(bytes+64);
+
+ if(!tableBase)
+ {
+ printf("%s: alloc memory failed \n", __FUNCTION__);
+ return 0;
+ }
+
+ /* align to octal byte */
+ if(tableBase&63) tableBase=(tableBase+63) & ~63;
+
+ addressTableHashMode[port] = hashMode;
+ addressTableHashSize[port] = hashSizeSelector;
+ addressTableBase[port] = (addrTblEntry *)tableBase;
+
+ memset((void *)tableBase,0,bytes);
+ }
+
+ return tableBase;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * This function will calculate the hash function of the address.
+ * depends on the hash mode and hash size.
+ * Inputs
+ * macH - the 2 most significant bytes of the MAC address.
+ * macL - the 4 least significant bytes of the MAC address.
+ * hashMode - hash mode 0 or hash mode 1.
+ * hashSizeSelector - indicates number of hash table entries (0=0x8000,1=0x800)
+ * Outputs
+ * return the calculated entry.
+ */
+u32
+hashTableFunction( u32 macH, u32 macL, u32 HashSize, u32 hash_mode)
+{
+ u32 hashResult;
+ u32 addrH;
+ u32 addrL;
+ u32 addr0;
+ u32 addr1;
+ u32 addr2;
+ u32 addr3;
+ u32 addrHSwapped;
+ u32 addrLSwapped;
+
+
+ addrH = NIBBLE_SWAPPING_16_BIT( macH );
+ addrL = NIBBLE_SWAPPING_32_BIT( macL );
+
+ addrHSwapped = FLIP_4_BITS( addrH & 0xf )
+ + ((FLIP_4_BITS( (addrH >> 4) & 0xf)) << 4)
+ + ((FLIP_4_BITS( (addrH >> 8) & 0xf)) << 8)
+ + ((FLIP_4_BITS( (addrH >> 12) & 0xf)) << 12);
+
+ addrLSwapped = FLIP_4_BITS( addrL & 0xf )
+ + ((FLIP_4_BITS( (addrL >> 4) & 0xf)) << 4)
+ + ((FLIP_4_BITS( (addrL >> 8) & 0xf)) << 8)
+ + ((FLIP_4_BITS( (addrL >> 12) & 0xf)) << 12)
+ + ((FLIP_4_BITS( (addrL >> 16) & 0xf)) << 16)
+ + ((FLIP_4_BITS( (addrL >> 20) & 0xf)) << 20)
+ + ((FLIP_4_BITS( (addrL >> 24) & 0xf)) << 24)
+ + ((FLIP_4_BITS( (addrL >> 28) & 0xf)) << 28);
+
+ addrH = addrHSwapped;
+ addrL = addrLSwapped;
+
+ if( hash_mode == 0 ) {
+ addr0 = (addrL >> 2) & 0x03f;
+ addr1 = (addrL & 0x003) | ((addrL >> 8) & 0x7f) << 2;
+ addr2 = (addrL >> 15) & 0x1ff;
+ addr3 = ((addrL >> 24) & 0x0ff) | ((addrH & 1) << 8);
+ } else {
+ addr0 = FLIP_6_BITS( addrL & 0x03f );
+ addr1 = FLIP_9_BITS( ((addrL >> 6) & 0x1ff));
+ addr2 = FLIP_9_BITS( (addrL >> 15) & 0x1ff);
+ addr3 = FLIP_9_BITS( (((addrL >> 24) & 0x0ff) | ((addrH & 0x1) << 8)));
+ }
+
+ hashResult = (addr0 << 9) | (addr1 ^ addr2 ^ addr3);
+
+ if( HashSize == _8K_TABLE ) {
+ hashResult = hashResult & 0xffff;
+ } else {
+ hashResult = hashResult & 0x07ff;
+ }
+
+ return( hashResult );
+}
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * This function will add an entry to the address table.
+ * depends on the hash mode and hash size that was initialized.
+ * Inputs
+ * port - ETHERNET port number.
+ * macH - the 2 most significant bytes of the MAC address.
+ * macL - the 4 least significant bytes of the MAC address.
+ * skip - if 1, skip this address.
+ * rd - the RD field in the address table.
+ * Outputs
+ * address table entry is added.
+ * TRUE if success.
+ * FALSE if table full
+ */
+int
+addAddressTableEntry(
+ u32 port,
+ u32 macH,
+ u32 macL,
+ u32 rd,
+ u32 skip )
+{
+ addrTblEntry *entry;
+ u32 newHi;
+ u32 newLo;
+ u32 i;
+
+ newLo = (((macH >> 4) & 0xf) << 15)
+ | (((macH >> 0) & 0xf) << 11)
+ | (((macH >> 12) & 0xf) << 7)
+ | (((macH >> 8) & 0xf) << 3)
+ | (((macL >> 20) & 0x1) << 31)
+ | (((macL >> 16) & 0xf) << 27)
+ | (((macL >> 28) & 0xf) << 23)
+ | (((macL >> 24) & 0xf) << 19)
+ | (skip << SKIP_BIT) | (rd << 2) | VALID;
+
+ newHi = (((macL >> 4) & 0xf) << 15)
+ | (((macL >> 0) & 0xf) << 11)
+ | (((macL >> 12) & 0xf) << 7)
+ | (((macL >> 8) & 0xf) << 3)
+ | (((macL >> 21) & 0x7) << 0);
+
+ /*
+ * Pick the appropriate table, start scanning for free/reusable
+ * entries at the index obtained by hashing the specified MAC address
+ */
+ entry = addressTableBase[port];
+ entry += hashTableFunction( macH, macL, addressTableHashSize[port],
+ addressTableHashMode[port] );
+ for( i = 0; i < HOP_NUMBER; i++, entry++ ) {
+ if( !(entry->lo & VALID) /*|| (entry->lo & SKIP)*/ ) {
+ break;
+ } else { /* if same address put in same position */
+ if( ((entry->lo & 0xfffffff8) == (newLo & 0xfffffff8))
+ && (entry->hi == newHi) )
+ {
+ break;
+ }
+ }
+ }
+
+ if( i == HOP_NUMBER ) {
+ PRINTF( "addGT64260addressTableEntry: table section is full\n" );
+ return( FALSE );
+ }
+
+ /*
+ * Update the selected entry
+ */
+ entry->hi = newHi;
+ entry->lo = newLo;
+ DCACHE_FLUSH_N_SYNC( (u32)entry, MAC_ENTRY_SIZE );
+ return( TRUE );
+}
+
+#endif /* CONFIG_GT_USE_MAC_HASH_TABLE */
diff --git a/board/evb64260/pci.c b/board/evb64260/pci.c
new file mode 100644
index 0000000000..8e9178db4f
--- /dev/null
+++ b/board/evb64260/pci.c
@@ -0,0 +1,691 @@
+/* PCI.c - PCI functions */
+
+/* Copyright - Galileo technology. */
+
+#include <common.h>
+#include <pci.h>
+
+#include <galileo/pci.h>
+
+static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = {
+#ifdef CONFIG_ZUMA_V2
+ {0,0,0,0,0,0,0,29, [8 ... PCI_MAX_DEVICES-1]=0},
+ {0,0,0,0,0,0,0,28, [8 ... PCI_MAX_DEVICES-1]=0}
+#else /* EVB??? This is a guess */
+ {0,0,0,0,0,0,0,27,27, [9 ... PCI_MAX_DEVICES-1]=0},
+ {0,0,0,0,0,0,0,29,29, [9 ... PCI_MAX_DEVICES-1]=0}
+#endif
+};
+
+static const unsigned int pci_p2p_configuration_reg[]={
+ PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION};
+
+static const unsigned int pci_configuration_address[]={
+ PCI_0CONFIGURATION_ADDRESS, PCI_1CONFIGURATION_ADDRESS};
+
+static const unsigned int pci_configuration_data[]={
+ PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER,
+ PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER};
+
+static const unsigned int pci_error_cause_reg[]={
+ PCI_0ERROR_CAUSE, PCI_1ERROR_CAUSE};
+
+static const unsigned int pci_arbiter_control[]={
+ PCI_0ARBITER_CONTROL, PCI_1ARBITER_CONTROL};
+
+static const unsigned int pci_snoop_control_base_0_low[]={
+ PCI_0SNOOP_CONTROL_BASE_0_LOW, PCI_1SNOOP_CONTROL_BASE_0_LOW};
+static const unsigned int pci_snoop_control_top_0[]={
+ PCI_0SNOOP_CONTROL_TOP_0, PCI_1SNOOP_CONTROL_TOP_0};
+
+static const unsigned int pci_access_control_base_0_low[]={
+ PCI_0ACCESS_CONTROL_BASE_0_LOW, PCI_1ACCESS_CONTROL_BASE_0_LOW};
+static const unsigned int pci_access_control_top_0[]={
+ PCI_0ACCESS_CONTROL_TOP_0, PCI_1ACCESS_CONTROL_TOP_0};
+
+static const unsigned int pci_scs_bank_size[2][4] = {
+ {PCI_0SCS_0_BANK_SIZE, PCI_0SCS_1_BANK_SIZE,
+ PCI_0SCS_2_BANK_SIZE, PCI_0SCS_3_BANK_SIZE},
+ {PCI_1SCS_0_BANK_SIZE, PCI_1SCS_1_BANK_SIZE,
+ PCI_1SCS_2_BANK_SIZE, PCI_1SCS_3_BANK_SIZE}};
+
+static const unsigned int pci_p2p_configuration[] = {
+ PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION};
+
+/********************************************************************
+* pciWriteConfigReg - Write to a PCI configuration register
+* - Make sure the GT is configured as a master before writing
+* to another device on the PCI.
+* - The function takes care of Big/Little endian conversion.
+*
+*
+* Inputs: unsigned int regOffset: The register offset as it apears in the GT spec
+* (or any other PCI device spec)
+* pciDevNum: The device number needs to be addressed.
+*
+* Configuration Address 0xCF8:
+*
+* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+* |congif|Reserved| Bus |Device|Function|Register|00|
+* |Enable| |Number|Number| Number | Number | | <=field Name
+*
+*********************************************************************/
+void pciWriteConfigReg(PCI_HOST host, unsigned int regOffset,unsigned int pciDevNum,unsigned int data)
+{
+ volatile unsigned int DataForAddrReg;
+ unsigned int functionNum;
+ unsigned int busNum = 0;
+ unsigned int addr;
+
+ if(pciDevNum > 32) /* illegal device Number */
+ return;
+ if(pciDevNum == SELF) /* configure our configuration space. */
+ {
+ pciDevNum = (GTREGREAD(pci_p2p_configuration_reg[host]) >> 24) & 0x1f;
+ busNum = GTREGREAD(pci_p2p_configuration_reg[host]) & 0xff0000;
+ }
+ functionNum = regOffset & 0x00000700;
+ pciDevNum = pciDevNum << 11;
+ regOffset = regOffset & 0xfc;
+ DataForAddrReg = ( regOffset | pciDevNum | functionNum | busNum) | BIT31;
+ GT_REG_WRITE(pci_configuration_address[host],DataForAddrReg);
+ GT_REG_READ(pci_configuration_address[host], &addr);
+ if (addr != DataForAddrReg) return;
+ GT_REG_WRITE(pci_configuration_data[host],data);
+}
+
+/********************************************************************
+* pciReadConfigReg - Read from a PCI0 configuration register
+* - Make sure the GT is configured as a master before reading
+* from another device on the PCI.
+* - The function takes care of Big/Little endian conversion.
+* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI
+* spec)
+* pciDevNum: The device number needs to be addressed.
+* RETURNS: data , if the data == 0xffffffff check the master abort bit in the
+* cause register to make sure the data is valid
+*
+* Configuration Address 0xCF8:
+*
+* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+* |congif|Reserved| Bus |Device|Function|Register|00|
+* |Enable| |Number|Number| Number | Number | | <=field Name
+*
+*********************************************************************/
+unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset,unsigned int pciDevNum)
+{
+ volatile unsigned int DataForAddrReg;
+ unsigned int data;
+ unsigned int functionNum;
+ unsigned int busNum = 0;
+
+ if(pciDevNum > 32) /* illegal device Number */
+ return 0xffffffff;
+ if(pciDevNum == SELF) /* configure our configuration space. */
+ {
+ pciDevNum = (GTREGREAD(pci_p2p_configuration_reg[host]) >> 24) & 0x1f;
+ busNum = GTREGREAD(pci_p2p_configuration_reg[host]) & 0xff0000;
+ }
+ functionNum = regOffset & 0x00000700;
+ pciDevNum = pciDevNum << 11;
+ regOffset = regOffset & 0xfc;
+ DataForAddrReg = (regOffset | pciDevNum | functionNum | busNum) | BIT31 ;
+ GT_REG_WRITE(pci_configuration_address[host],DataForAddrReg);
+ GT_REG_READ(pci_configuration_address[host], &data);
+ if (data != DataForAddrReg)
+ return 0xffffffff;
+ GT_REG_READ(pci_configuration_data[host], &data);
+ return data;
+}
+
+/********************************************************************
+* pciOverBridgeWriteConfigReg - Write to a PCI configuration register where
+* the agent is placed on another Bus. For more
+* information read P2P in the PCI spec.
+*
+* Inputs: unsigned int regOffset - The register offset as it apears in the
+* GT spec (or any other PCI device spec).
+* unsigned int pciDevNum - The device number needs to be addressed.
+* unsigned int busNum - On which bus does the Target agent connect
+* to.
+* unsigned int data - data to be written.
+*
+* Configuration Address 0xCF8:
+*
+* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+* |congif|Reserved| Bus |Device|Function|Register|01|
+* |Enable| |Number|Number| Number | Number | | <=field Name
+*
+* The configuration Address is configure as type-I (bits[1:0] = '01') due to
+* PCI spec referring to P2P.
+*
+*********************************************************************/
+void pciOverBridgeWriteConfigReg(PCI_HOST host,
+ unsigned int regOffset,
+ unsigned int pciDevNum,
+ unsigned int busNum,unsigned int data)
+{
+ unsigned int DataForReg;
+ unsigned int functionNum;
+
+ functionNum = regOffset & 0x00000700;
+ pciDevNum = pciDevNum << 11;
+ regOffset = regOffset & 0xff;
+ busNum = busNum << 16;
+ if(pciDevNum == SELF) /* This board */
+ {
+ DataForReg = ( regOffset | pciDevNum | functionNum) | BIT0;
+ }
+ else
+ {
+ DataForReg = ( regOffset | pciDevNum | functionNum | busNum) |
+ BIT31 | BIT0;
+ }
+ GT_REG_WRITE(pci_configuration_address[host],DataForReg);
+ if(pciDevNum == SELF) /* This board */
+ {
+ GT_REG_WRITE(pci_configuration_data[host],data);
+ }
+ else /* configuration Transaction over the pci. */
+ {
+ /* The PCI is working in LE Mode So it swap the Data. */
+ GT_REG_WRITE(pci_configuration_data[host],WORD_SWAP(data));
+ }
+}
+
+
+/********************************************************************
+* pciOverBridgeReadConfigReg - Read from a PCIn configuration register where
+* the agent target locate on another PCI bus.
+* - Make sure the GT is configured as a master
+* before reading from another device on the PCI.
+* - The function takes care of Big/Little endian
+* conversion.
+* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI
+* spec). (configuration register offset.)
+* pciDevNum: The device number needs to be addressed.
+* busNum: the Bus number where the agent is place.
+* RETURNS: data , if the data == 0xffffffff check the master abort bit in the
+* cause register to make sure the data is valid
+*
+* Configuration Address 0xCF8:
+*
+* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+* |congif|Reserved| Bus |Device|Function|Register|01|
+* |Enable| |Number|Number| Number | Number | | <=field Name
+*
+*********************************************************************/
+unsigned int pciOverBridgeReadConfigReg(PCI_HOST host,
+ unsigned int regOffset,
+ unsigned int pciDevNum,
+ unsigned int busNum)
+{
+ unsigned int DataForReg;
+ unsigned int data;
+ unsigned int functionNum;
+
+ functionNum = regOffset & 0x00000700;
+ pciDevNum = pciDevNum << 11;
+ regOffset = regOffset & 0xff;
+ busNum = busNum << 16;
+ if (pciDevNum == SELF) /* This board */
+ {
+ DataForReg = (regOffset | pciDevNum | functionNum) | BIT31 ;
+ }
+ else /* agent on another bus */
+ {
+ DataForReg = (regOffset | pciDevNum | functionNum | busNum) |
+ BIT0 | BIT31 ;
+ }
+ GT_REG_WRITE(pci_configuration_address[host],DataForReg);
+ if (pciDevNum == SELF) /* This board */
+ {
+ GT_REG_READ(pci_configuration_data[host], &data);
+ return data;
+ }
+ else /* The PCI is working in LE Mode So it swap the Data. */
+ {
+ GT_REG_READ(pci_configuration_data[host], &data);
+ return WORD_SWAP(data);
+ }
+}
+
+/********************************************************************
+* pciGetRegOffset - Gets the register offset for this region config.
+*
+* INPUT: Bus, Region - The bus and region we ask for its base address.
+* OUTPUT: N/A
+* RETURNS: PCI register base address
+*********************************************************************/
+static unsigned int pciGetRegOffset(PCI_HOST host, PCI_REGION region)
+{
+ switch (host)
+ {
+ case PCI_HOST0:
+ switch(region) {
+ case PCI_IO: return PCI_0I_O_LOW_DECODE_ADDRESS;
+ case PCI_REGION0: return PCI_0MEMORY0_LOW_DECODE_ADDRESS;
+ case PCI_REGION1: return PCI_0MEMORY1_LOW_DECODE_ADDRESS;
+ case PCI_REGION2: return PCI_0MEMORY2_LOW_DECODE_ADDRESS;
+ case PCI_REGION3: return PCI_0MEMORY3_LOW_DECODE_ADDRESS;
+ }
+ case PCI_HOST1:
+ switch(region) {
+ case PCI_IO: return PCI_1I_O_LOW_DECODE_ADDRESS;
+ case PCI_REGION0: return PCI_1MEMORY0_LOW_DECODE_ADDRESS;
+ case PCI_REGION1: return PCI_1MEMORY1_LOW_DECODE_ADDRESS;
+ case PCI_REGION2: return PCI_1MEMORY2_LOW_DECODE_ADDRESS;
+ case PCI_REGION3: return PCI_1MEMORY3_LOW_DECODE_ADDRESS;
+ }
+ }
+ return PCI_0MEMORY0_LOW_DECODE_ADDRESS;
+}
+
+static unsigned int pciGetRemapOffset(PCI_HOST host, PCI_REGION region)
+{
+ switch (host)
+ {
+ case PCI_HOST0:
+ switch(region) {
+ case PCI_IO: return PCI_0I_O_ADDRESS_REMAP;
+ case PCI_REGION0: return PCI_0MEMORY0_ADDRESS_REMAP;
+ case PCI_REGION1: return PCI_0MEMORY1_ADDRESS_REMAP;
+ case PCI_REGION2: return PCI_0MEMORY2_ADDRESS_REMAP;
+ case PCI_REGION3: return PCI_0MEMORY3_ADDRESS_REMAP;
+ }
+ case PCI_HOST1:
+ switch(region) {
+ case PCI_IO: return PCI_1I_O_ADDRESS_REMAP;
+ case PCI_REGION0: return PCI_1MEMORY0_ADDRESS_REMAP;
+ case PCI_REGION1: return PCI_1MEMORY1_ADDRESS_REMAP;
+ case PCI_REGION2: return PCI_1MEMORY2_ADDRESS_REMAP;
+ case PCI_REGION3: return PCI_1MEMORY3_ADDRESS_REMAP;
+ }
+ }
+ return PCI_0MEMORY0_ADDRESS_REMAP;
+}
+
+bool pciMapSpace(PCI_HOST host, PCI_REGION region, unsigned int remapBase, unsigned int bankBase,unsigned int bankLength)
+{
+ unsigned int low=0xfff;
+ unsigned int high=0x0;
+ unsigned int regOffset=pciGetRegOffset(host, region);
+ unsigned int remapOffset=pciGetRemapOffset(host, region);
+
+ if(bankLength!=0) {
+ low = (bankBase >> 20) & 0xfff;
+ high=((bankBase+bankLength)>>20)-1;
+ }
+
+ GT_REG_WRITE(regOffset, low | (1<<24)); /* no swapping */
+ GT_REG_WRITE(regOffset+8, high);
+
+ if(bankLength!=0) { /* must do AFTER writing maps */
+ GT_REG_WRITE(remapOffset, remapBase>>20); /* sorry, 32 bits only.
+ dont support upper 32
+ in this driver */
+ }
+ return true;
+}
+
+unsigned int pciGetSpaceBase(PCI_HOST host, PCI_REGION region)
+{
+ unsigned int low;
+ unsigned int regOffset=pciGetRegOffset(host, region);
+ GT_REG_READ(regOffset,&low);
+ return (low&0xfff)<<20;
+}
+
+unsigned int pciGetSpaceSize(PCI_HOST host, PCI_REGION region)
+{
+ unsigned int low,high;
+ unsigned int regOffset=pciGetRegOffset(host, region);
+ GT_REG_READ(regOffset,&low);
+ GT_REG_READ(regOffset+8,&high);
+ high&=0xfff;
+ low&=0xfff;
+ if(high<=low) return 0;
+ return (high+1-low)<<20;
+}
+
+/********************************************************************
+* pciMapMemoryBank - Maps PCI_host memory bank "bank" for the slave.
+*
+* Inputs: base and size of PCI SCS
+*********************************************************************/
+void pciMapMemoryBank(PCI_HOST host, MEMORY_BANK bank, unsigned int pciDramBase,unsigned int pciDramSize)
+{
+ pciDramBase = pciDramBase & 0xfffff000;
+ pciDramBase = pciDramBase | (pciReadConfigReg(host,
+ PCI_SCS_0_BASE_ADDRESS + 4*bank,SELF) & 0x00000fff);
+ pciWriteConfigReg(host,PCI_SCS_0_BASE_ADDRESS + 4*bank,SELF,pciDramBase);
+ if(pciDramSize == 0)
+ pciDramSize ++;
+ GT_REG_WRITE(pci_scs_bank_size[host][bank], pciDramSize-1);
+}
+
+
+/********************************************************************
+* pciSetRegionFeatures - This function modifys one of the 8 regions with
+* feature bits given as an input.
+* - Be advised to check the spec before modifying them.
+* Inputs: PCI_PROTECT_REGION region - one of the eight regions.
+* unsigned int features - See file: pci.h there are defintion for those
+* region features.
+* unsigned int baseAddress - The region base Address.
+* unsigned int topAddress - The region top Address.
+* Returns: false if one of the parameters is erroneous true otherwise.
+*********************************************************************/
+bool pciSetRegionFeatures(PCI_HOST host, PCI_ACCESS_REGIONS region,unsigned int features,
+ unsigned int baseAddress,unsigned int regionLength)
+{
+ unsigned int accessLow;
+ unsigned int accessHigh;
+ unsigned int accessTop = baseAddress + regionLength;
+
+ if(regionLength == 0) /* close the region. */
+ {
+ pciDisableAccessRegion(host, region);
+ return true;
+ }
+ /* base Address is store is bits [11:0] */
+ accessLow = (baseAddress & 0xfff00000) >> 20;
+ /* All the features are update according to the defines in pci.h (to be on
+ the safe side we disable bits: [11:0] */
+ accessLow = accessLow | (features & 0xfffff000);
+ /* write to the Low Access Region register */
+ GT_REG_WRITE( pci_access_control_base_0_low[host] + 0x10*region,accessLow);
+
+ accessHigh = (accessTop & 0xfff00000) >> 20;
+
+ /* write to the High Access Region register */
+ GT_REG_WRITE(pci_access_control_top_0[host] + 0x10*region,accessHigh - 1);
+ return true;
+}
+
+/********************************************************************
+* pciDisableAccessRegion - Disable The given Region by writing MAX size
+* to its low Address and MIN size to its high Address.
+*
+* Inputs: PCI_ACCESS_REGIONS region - The region we to be Disabled.
+* Returns: N/A.
+*********************************************************************/
+void pciDisableAccessRegion(PCI_HOST host, PCI_ACCESS_REGIONS region)
+{
+ /* writing back the registers default values. */
+ GT_REG_WRITE(pci_access_control_base_0_low[host] + 0x10*region,0x01001fff);
+ GT_REG_WRITE(pci_access_control_top_0[host] + 0x10*region,0);
+}
+
+/********************************************************************
+* pciArbiterEnable - Enables PCI-0`s Arbitration mechanism.
+*
+* Inputs: N/A
+* Returns: true.
+*********************************************************************/
+bool pciArbiterEnable(PCI_HOST host)
+{
+ unsigned int regData;
+
+ GT_REG_READ(pci_arbiter_control[host],&regData);
+ GT_REG_WRITE(pci_arbiter_control[host],regData | BIT31);
+ return true;
+}
+
+/********************************************************************
+* pciArbiterDisable - Disable PCI-0`s Arbitration mechanism.
+*
+* Inputs: N/A
+* Returns: true
+*********************************************************************/
+bool pciArbiterDisable(PCI_HOST host)
+{
+ unsigned int regData;
+
+ GT_REG_READ(pci_arbiter_control[host],&regData);
+ GT_REG_WRITE(pci_arbiter_control[host],regData & 0x7fffffff);
+ return true;
+}
+
+/********************************************************************
+* pciParkingDisable - Park on last option disable, with this function you can
+* disable the park on last mechanism for each agent.
+* disabling this option for all agents results parking
+* on the internal master.
+*
+* Inputs: PCI_AGENT_PARK internalAgent - parking Disable for internal agent.
+* PCI_AGENT_PARK externalAgent0 - parking Disable for external#0 agent.
+* PCI_AGENT_PARK externalAgent1 - parking Disable for external#1 agent.
+* PCI_AGENT_PARK externalAgent2 - parking Disable for external#2 agent.
+* PCI_AGENT_PARK externalAgent3 - parking Disable for external#3 agent.
+* PCI_AGENT_PARK externalAgent4 - parking Disable for external#4 agent.
+* PCI_AGENT_PARK externalAgent5 - parking Disable for external#5 agent.
+* Returns: true
+*********************************************************************/
+bool pciParkingDisable(PCI_HOST host, PCI_AGENT_PARK internalAgent,
+ PCI_AGENT_PARK externalAgent0,
+ PCI_AGENT_PARK externalAgent1,
+ PCI_AGENT_PARK externalAgent2,
+ PCI_AGENT_PARK externalAgent3,
+ PCI_AGENT_PARK externalAgent4,
+ PCI_AGENT_PARK externalAgent5)
+{
+ unsigned int regData;
+ unsigned int writeData;
+
+ GT_REG_READ(pci_arbiter_control[host],&regData);
+ writeData = (internalAgent << 14) + (externalAgent0 << 15) + \
+ (externalAgent1 << 16) + (externalAgent2 << 17) + \
+ (externalAgent3 << 18) + (externalAgent4 << 19) + \
+ (externalAgent5 << 20);
+ regData = (regData & ~(0x7f<<14)) | writeData;
+ GT_REG_WRITE(pci_arbiter_control[host],regData);
+ return true;
+}
+
+/********************************************************************
+* pciSetRegionSnoopMode - This function modifys one of the 4 regions which
+* supports Cache Coherency in the PCI_n interface.
+* Inputs: region - One of the four regions.
+* snoopType - There is four optional Types:
+* 1. No Snoop.
+* 2. Snoop to WT region.
+* 3. Snoop to WB region.
+* 4. Snoop & Invalidate to WB region.
+* baseAddress - Base Address of this region.
+* regionLength - Region length.
+* Returns: false if one of the parameters is wrong otherwise return true.
+*********************************************************************/
+bool pciSetRegionSnoopMode(PCI_HOST host, PCI_SNOOP_REGION region,PCI_SNOOP_TYPE snoopType,
+ unsigned int baseAddress,
+ unsigned int regionLength)
+{
+ unsigned int snoopXbaseAddress;
+ unsigned int snoopXtopAddress;
+ unsigned int data;
+ unsigned int snoopHigh = baseAddress + regionLength;
+
+ if( (region > PCI_SNOOP_REGION3) || (snoopType > PCI_SNOOP_WB) )
+ return false;
+ snoopXbaseAddress = pci_snoop_control_base_0_low[host] + 0x10 * region;
+ snoopXtopAddress = pci_snoop_control_top_0[host] + 0x10 * region;
+ if(regionLength == 0) /* closing the region */
+ {
+ GT_REG_WRITE(snoopXbaseAddress,0x0000ffff);
+ GT_REG_WRITE(snoopXtopAddress,0);
+ return true;
+ }
+ baseAddress = baseAddress & 0xfff00000; /* Granularity of 1MByte */
+ data = (baseAddress >> 20) | snoopType << 12;
+ GT_REG_WRITE(snoopXbaseAddress,data);
+ snoopHigh = (snoopHigh & 0xfff00000) >> 20;
+ GT_REG_WRITE(snoopXtopAddress,snoopHigh - 1);
+ return true;
+}
+
+/*
+ *
+ */
+
+static int gt_read_config_dword(struct pci_controller *hose,
+ pci_dev_t dev,
+ int offset, u32* value)
+{
+ *value = pciReadConfigReg((PCI_HOST) hose->cfg_addr, offset, PCI_DEV(dev));
+ return 0;
+}
+
+static int gt_write_config_dword(struct pci_controller *hose,
+ pci_dev_t dev,
+ int offset, u32 value)
+{
+ pciWriteConfigReg((PCI_HOST)hose->cfg_addr, offset, PCI_DEV(dev), value);
+ return 0;
+}
+
+/*
+ *
+ */
+
+static void gt_setup_ide(struct pci_controller *hose,
+ pci_dev_t dev, struct pci_config_table *entry)
+{
+ static const int ide_bar[]={8,4,8,4,0,0};
+ u32 bar_response, bar_value;
+ int bar;
+
+ for (bar=0; bar<6; bar++)
+ {
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, 0x0);
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, &bar_response);
+
+ pciauto_region_allocate(bar_response & PCI_BASE_ADDRESS_SPACE_IO ?
+ hose->pci_io : hose->pci_mem, ide_bar[bar], &bar_value);
+
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, bar_value);
+ }
+}
+
+static void gt_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
+{
+ unsigned char pin, irq;
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+
+ if(pin == 1) { /* only allow INT A */
+ irq = pci_irq_swizzle[(PCI_HOST)hose->cfg_addr][PCI_DEV(dev)];
+ if(irq)
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+ }
+}
+
+struct pci_config_table gt_config_table[] = {
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_ide},
+
+ { }
+};
+
+struct pci_controller pci0_hose = {
+ fixup_irq: gt_fixup_irq,
+ config_table: gt_config_table,
+};
+
+struct pci_controller pci1_hose = {
+ fixup_irq: gt_fixup_irq,
+ config_table: gt_config_table,
+};
+
+void
+pci_init(void)
+{
+ unsigned int command;
+
+ pci0_hose.first_busno = 0;
+ pci0_hose.last_busno = 0xff;
+
+ /* PCI memory space */
+ pci_set_region(pci0_hose.regions + 0,
+ CFG_PCI0_0_MEM_SPACE,
+ CFG_PCI0_0_MEM_SPACE,
+ CFG_PCI0_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI I/O space */
+ pci_set_region(pci0_hose.regions + 1,
+ CFG_PCI0_IO_SPACE_PCI,
+ CFG_PCI0_IO_SPACE,
+ CFG_PCI0_IO_SIZE,
+ PCI_REGION_IO);
+
+ pci_set_ops(&pci0_hose,
+ pci_hose_read_config_byte_via_dword,
+ pci_hose_read_config_word_via_dword,
+ gt_read_config_dword,
+ pci_hose_write_config_byte_via_dword,
+ pci_hose_write_config_word_via_dword,
+ gt_write_config_dword);
+
+ pci0_hose.region_count = 2;
+
+ pci0_hose.cfg_addr = (unsigned int*) PCI_HOST0;
+
+ pci_register_hose(&pci0_hose);
+
+ pciArbiterEnable(PCI_HOST0);
+ pciParkingDisable(PCI_HOST0,1,1,1,1,1,1,1);
+
+ command = pciReadConfigReg(PCI_HOST0, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MASTER;
+ pciWriteConfigReg(PCI_HOST0, PCI_COMMAND, SELF, command);
+
+ pci0_hose.last_busno = pci_hose_scan(&pci0_hose);
+
+ command = pciReadConfigReg(PCI_HOST0, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MEMORY;
+ pciWriteConfigReg(PCI_HOST0, PCI_COMMAND, SELF, command);
+
+ pci1_hose.first_busno = pci0_hose.last_busno + 1;
+ pci1_hose.last_busno = 0xff;
+
+ /* PCI memory space */
+ pci_set_region(pci1_hose.regions + 0,
+ CFG_PCI1_0_MEM_SPACE,
+ CFG_PCI1_0_MEM_SPACE,
+ CFG_PCI1_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI I/O space */
+ pci_set_region(pci1_hose.regions + 1,
+ CFG_PCI1_IO_SPACE_PCI,
+ CFG_PCI1_IO_SPACE,
+ CFG_PCI1_IO_SIZE,
+ PCI_REGION_IO);
+
+ pci_set_ops(&pci1_hose,
+ pci_hose_read_config_byte_via_dword,
+ pci_hose_read_config_word_via_dword,
+ gt_read_config_dword,
+ pci_hose_write_config_byte_via_dword,
+ pci_hose_write_config_word_via_dword,
+ gt_write_config_dword);
+
+ pci1_hose.region_count = 2;
+
+ pci1_hose.cfg_addr = (unsigned int*) PCI_HOST1;
+
+ pci_register_hose(&pci1_hose);
+
+ pciArbiterEnable(PCI_HOST1);
+ pciParkingDisable(PCI_HOST1,1,1,1,1,1,1,1);
+
+ command = pciReadConfigReg(PCI_HOST1, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MASTER;
+ pciWriteConfigReg(PCI_HOST1, PCI_COMMAND, SELF, command);
+
+ pci1_hose.last_busno = pci_hose_scan(&pci1_hose);
+
+ command = pciReadConfigReg(PCI_HOST1, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MEMORY;
+ pciWriteConfigReg(PCI_HOST1, PCI_COMMAND, SELF, command);
+}
diff --git a/board/evb64260/sdram_init.c b/board/evb64260/sdram_init.c
new file mode 100644
index 0000000000..ff98e4db29
--- /dev/null
+++ b/board/evb64260/sdram_init.c
@@ -0,0 +1,629 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * 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
+ */
+
+/* sdram_init.c - automatic memory sizing */
+
+#include <common.h>
+#include <74xx_7xx.h>
+#include <galileo/memory.h>
+#include <galileo/pci.h>
+#include <galileo/gt64260R.h>
+#include <net.h>
+
+#include "eth.h"
+#include "mpsc.h"
+#include "i2c.h"
+#include "64260.h"
+
+/* #define DEBUG */
+#define MAP_PCI
+
+#ifdef DEBUG
+#define DP(x) x
+#else
+#define DP(x)
+#endif
+
+#define GB (1 << 30)
+
+/* structure to store the relevant information about an sdram bank */
+typedef struct sdram_info {
+ uchar drb_size;
+ uchar registered, ecc;
+ uchar tpar;
+ uchar tras_clocks;
+ uchar burst_len;
+ uchar banks, slot;
+ int size; /* detected size, not from I2C but from dram_size() */
+} sdram_info_t;
+
+#ifdef DEBUG
+void dump_dimm_info(struct sdram_info *d)
+{
+ static const char *ecc_legend[]={""," Parity"," ECC"};
+ printf("dimm%s %sDRAM: %dMibytes:\n",
+ ecc_legend[d->ecc],
+ d->registered?"R":"",
+ (d->size>>20));
+ printf(" drb=%d tpar=%d tras=%d burstlen=%d banks=%d slot=%d\n",
+ d->drb_size, d->tpar, d->tras_clocks, d->burst_len,
+ d->banks, d->slot);
+}
+#endif
+
+static int
+memory_map_bank(unsigned int bankNo,
+ unsigned int bankBase,
+ unsigned int bankLength)
+{
+#ifdef DEBUG
+ if (bankLength > 0) {
+ printf("mapping bank %d at %08x - %08x\n",
+ bankNo, bankBase, bankBase + bankLength - 1);
+ } else {
+ printf("unmapping bank %d\n", bankNo);
+ }
+#endif
+
+ memoryMapBank(bankNo, bankBase, bankLength);
+
+ return 0;
+}
+
+#ifdef MAP_PCI
+static int
+memory_map_bank_pci(unsigned int bankNo,
+ unsigned int bankBase,
+ unsigned int bankLength)
+{
+ PCI_HOST host;
+ for (host=PCI_HOST0;host<=PCI_HOST1;host++) {
+ const int features=
+ PREFETCH_ENABLE |
+ DELAYED_READ_ENABLE |
+ AGGRESSIVE_PREFETCH |
+ READ_LINE_AGGRESSIVE_PREFETCH |
+ READ_MULTI_AGGRESSIVE_PREFETCH |
+ MAX_BURST_4 |
+ PCI_NO_SWAP;
+
+ pciMapMemoryBank(host, bankNo, bankBase, bankLength);
+
+ pciSetRegionSnoopMode(host, bankNo, PCI_SNOOP_WB, bankBase,
+ bankLength);
+
+ pciSetRegionFeatures(host, bankNo, features, bankBase, bankLength);
+ }
+ return 0;
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/* much of this code is based on (or is) the code in the pip405 port */
+/* thanks go to the authors of said port - Josh */
+
+
+/*
+ * translate ns.ns/10 coding of SPD timing values
+ * into 10 ps unit values
+ */
+static inline unsigned short
+NS10to10PS(unsigned char spd_byte)
+{
+ unsigned short ns, ns10;
+
+ /* isolate upper nibble */
+ ns = (spd_byte >> 4) & 0x0F;
+ /* isolate lower nibble */
+ ns10 = (spd_byte & 0x0F);
+
+ return(ns*100 + ns10*10);
+}
+
+/*
+ * translate ns coding of SPD timing values
+ * into 10 ps unit values
+ */
+static inline unsigned short
+NSto10PS(unsigned char spd_byte)
+{
+ return(spd_byte*100);
+}
+
+#ifdef CONFIG_ZUMA_V2
+static int
+check_dimm(uchar slot, sdram_info_t *info)
+{
+ /* assume 2 dimms, 2 banks each 256M - we dont have an
+ * dimm i2c so rely on the detection routines later */
+
+ memset(info, 0, sizeof(*info));
+
+ info->slot = slot;
+ info->banks = 2; /* Detect later */
+ info->registered = 0;
+ info->drb_size = 32; /* 16 - 256MBit, 32 - 512MBit
+ but doesn't matter, both do same
+ thing in setup_sdram() */
+ info->tpar = 3;
+ info->tras_clocks = 5;
+ info->burst_len = 4;
+#ifdef CONFIG_ECC
+ info->ecc = 0; /* Detect later */
+#endif /* CONFIG_ECC */
+ return 0;
+}
+
+#else /* ! CONFIG_ZUMA_V2 */
+
+/* This code reads the SPD chip on the sdram and populates
+ * the array which is passed in with the relevant information */
+static int
+check_dimm(uchar slot, sdram_info_t *info)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ uchar addr = slot == 0 ? DIMM0_I2C_ADDR : DIMM1_I2C_ADDR;
+ int ret;
+ uchar rows, cols, sdram_banks, supp_cal, width, cal_val;
+ ulong tmemclk;
+ uchar trp_clocks, trcd_clocks;
+ uchar data[128];
+
+ get_clocks ();
+
+ tmemclk = 1000000000 / (gd->bus_clk / 100); /* in 10 ps units */
+
+#ifdef CONFIG_EVB64260_750CX
+ if (0 != slot) {
+ printf("check_dimm: The EVB-64260-750CX only has 1 DIMM,");
+ printf(" called with slot=%d insetad!\n", slot);
+ return 0;
+ }
+#endif
+ DP(puts("before i2c read\n"));
+
+ ret = i2c_read(addr, 0, 128, data, 0);
+
+ DP(puts("after i2c read\n"));
+
+ /* zero all the values */
+ memset(info, 0, sizeof(*info));
+
+ if (ret) {
+ DP(printf("No DIMM in slot %d [err = %x]\n", slot, ret));
+ return 0;
+ }
+
+ /* first, do some sanity checks */
+ if (data[2] != 0x4) {
+ printf("Not SDRAM in slot %d\n", slot);
+ return 0;
+ }
+
+ /* get various information */
+ rows = data[3];
+ cols = data[4];
+ info->banks = data[5];
+ sdram_banks = data[17];
+ width = data[13] & 0x7f;
+
+ DP(printf("sdram_banks: %d, banks: %d\n", sdram_banks, info->banks));
+
+ /* check if the memory is registered */
+ if (data[21] & (BIT1 | BIT4))
+ info->registered = 1;
+
+#ifdef CONFIG_ECC
+ /* check for ECC/parity [0 = none, 1 = parity, 2 = ecc] */
+ info->ecc = (data[11] & 2) >> 1;
+#endif
+
+ /* bit 1 is CL2, bit 2 is CL3 */
+ supp_cal = (data[18] & 0x6) >> 1;
+
+ /* compute the relevant clock values */
+ trp_clocks = (NSto10PS(data[27])+(tmemclk-1)) / tmemclk;
+ trcd_clocks = (NSto10PS(data[29])+(tmemclk-1)) / tmemclk;
+ info->tras_clocks = (NSto10PS(data[30])+(tmemclk-1)) / tmemclk;
+
+ DP(printf("trp = %d\ntrcd_clocks = %d\ntras_clocks = %d\n",
+ trp_clocks, trcd_clocks, info->tras_clocks));
+
+ /* try a CAS latency of 3 first... */
+ cal_val = 0;
+ if (supp_cal & 3) {
+ if (NS10to10PS(data[9]) <= tmemclk)
+ cal_val = 3;
+ }
+
+ /* then 2... */
+ if (supp_cal & 2) {
+ if (NS10to10PS(data[23]) <= tmemclk)
+ cal_val = 2;
+ }
+
+ DP(printf("cal_val = %d\n", cal_val));
+
+ /* bummer, did't work... */
+ if (cal_val == 0) {
+ DP(printf("Couldn't find a good CAS latency\n"));
+ return 0;
+ }
+
+ /* get the largest delay -- these values need to all be the same
+ * see Res#6 */
+ info->tpar = cal_val;
+ if (trp_clocks > info->tpar)
+ info->tpar = trp_clocks;
+ if (trcd_clocks > info->tpar)
+ info->tpar = trcd_clocks;
+
+ DP(printf("tpar set to: %d\n", info->tpar));
+
+#ifdef CFG_BROKEN_CL2
+ if (info->tpar == 2){
+ info->tpar = 3;
+ DP(printf("tpar fixed-up to: %d\n", info->tpar));
+ }
+#endif
+ /* compute the module DRB size */
+ info->drb_size = (((1 << (rows + cols)) * sdram_banks) * width) / _16M;
+
+ DP(printf("drb_size set to: %d\n", info->drb_size));
+
+ /* find the burst len */
+ info->burst_len = data[16] & 0xf;
+ if ((info->burst_len & 8) == 8) {
+ info->burst_len = 1;
+ } else if ((info->burst_len & 4) == 4) {
+ info->burst_len = 0;
+ } else {
+ return 0;
+ }
+
+ info->slot = slot;
+ return 0;
+}
+#endif /* ! CONFIG_ZUMA_V2 */
+
+static int
+setup_sdram_common(sdram_info_t info[2])
+{
+ ulong tmp;
+ int tpar=2, tras_clocks=5, registered=1, ecc=2;
+
+ if(!info[0].banks && !info[1].banks) return 0;
+
+ if(info[0].banks) {
+ if(info[0].tpar>tpar) tpar=info[0].tpar;
+ if(info[0].tras_clocks>tras_clocks) tras_clocks=info[0].tras_clocks;
+ if(!info[0].registered) registered=0;
+ if(info[0].ecc!=2) ecc=0;
+ }
+
+ if(info[1].banks) {
+ if(info[1].tpar>tpar) tpar=info[1].tpar;
+ if(info[1].tras_clocks>tras_clocks) tras_clocks=info[1].tras_clocks;
+ if(!info[1].registered) registered=0;
+ if(info[1].ecc!=2) ecc=0;
+ }
+
+ /* SDRAM configuration */
+ tmp = GTREGREAD(SDRAM_CONFIGURATION);
+
+ /* Turn on physical interleave if both DIMMs
+ * have even numbers of banks. */
+ if( (info[0].banks == 0 || info[0].banks == 2) &&
+ (info[1].banks == 0 || info[1].banks == 2) ) {
+ /* physical interleave on */
+ tmp &= ~(1 << 15);
+ } else {
+ /* physical interleave off */
+ tmp |= (1 << 15);
+ }
+
+ tmp |= (registered << 17);
+
+ /* Use buffer 1 to return read data to the CPU
+ * See Res #12 */
+ tmp |= (1 << 26);
+
+ GT_REG_WRITE(SDRAM_CONFIGURATION, tmp);
+ DP(printf("SDRAM config: %08x\n",
+ GTREGREAD(SDRAM_CONFIGURATION)));
+
+ /* SDRAM timing */
+ tmp = (((tpar == 3) ? 2 : 1) |
+ (((tpar == 3) ? 2 : 1) << 2) |
+ (((tpar == 3) ? 2 : 1) << 4) |
+ (tras_clocks << 8));
+
+#ifdef CONFIG_ECC
+ /* Setup ECC */
+ if (ecc == 2) tmp |= 1<<13;
+#endif /* CONFIG_ECC */
+
+ GT_REG_WRITE(SDRAM_TIMING, tmp);
+ DP(printf("SDRAM timing: %08x (%d,%d,%d,%d)\n",
+ GTREGREAD(SDRAM_TIMING), tpar,tpar,tpar,tras_clocks));
+
+ /* SDRAM address decode register */
+ /* program this with the default value */
+ GT_REG_WRITE(SDRAM_ADDRESS_DECODE, 0x2);
+ DP(printf("SDRAM decode: %08x\n",
+ GTREGREAD(SDRAM_ADDRESS_DECODE)));
+
+ return 0;
+}
+
+/* sets up the GT properly with information passed in */
+static int
+setup_sdram(sdram_info_t *info)
+{
+ ulong tmp, check;
+ ulong *addr = 0;
+ int i;
+
+ /* sanity checking */
+ if (! info->banks) return 0;
+
+ /* ---------------------------- */
+ /* Program the GT with the discovered data */
+
+ /* bank parameters */
+ tmp = (0xf<<16); /* leave all virt bank pages open */
+
+ DP(printf("drb_size: %d\n", info->drb_size));
+ switch (info->drb_size) {
+ case 1:
+ tmp |= (1 << 14);
+ break;
+ case 4:
+ case 8:
+ tmp |= (2 << 14);
+ break;
+ case 16:
+ case 32:
+ tmp |= (3 << 14);
+ break;
+ default:
+ printf("Error in dram size calculation\n");
+ return 1;
+ }
+
+ /* SDRAM bank parameters */
+ /* the param registers for slot 1 (banks 2+3) are offset by 0x8 */
+ GT_REG_WRITE(SDRAM_BANK0PARAMETERS + (info->slot * 0x8), tmp);
+ GT_REG_WRITE(SDRAM_BANK1PARAMETERS + (info->slot * 0x8), tmp);
+ DP(printf("SDRAM bankparam slot %d (bank %d+%d): %08lx\n", info->slot, info->slot*2, (info->slot*2)+1, tmp));
+
+ /* set the SDRAM configuration for each bank */
+ for (i = info->slot * 2; i < ((info->slot * 2) + info->banks); i++) {
+ DP(printf("*** Running a MRS cycle for bank %d ***\n", i));
+
+ /* map the bank */
+ memory_map_bank(i, 0, GB/4);
+
+ /* set SDRAM mode */
+ GT_REG_WRITE(SDRAM_OPERATION_MODE, 0x3);
+ check = GTREGREAD(SDRAM_OPERATION_MODE);
+
+ /* dummy write */
+ *addr = 0;
+
+ /* wait for the command to complete */
+ while ((GTREGREAD(SDRAM_OPERATION_MODE) & (1 << 31)) == 0)
+ ;
+
+ /* switch back to normal operation mode */
+ GT_REG_WRITE(SDRAM_OPERATION_MODE, 0);
+ check = GTREGREAD(SDRAM_OPERATION_MODE);
+
+ /* unmap the bank */
+ memory_map_bank(i, 0, 0);
+ DP(printf("*** MRS cycle for bank %d done ***\n", i));
+ }
+
+ return 0;
+}
+
+/*
+ * Check memory range for valid RAM. A simple memory test determines
+ * the actually available RAM size between addresses `base' and
+ * `base + maxsize'. Some (not all) hardware errors are detected:
+ * - short between address lines
+ * - short between data lines
+ */
+static long int
+dram_size(long int *base, long int maxsize)
+{
+ volatile long int *addr, *b=base;
+ long int cnt, val, save1, save2;
+
+#define STARTVAL (1<<20) /* start test at 1M */
+ for (cnt = STARTVAL/sizeof(long); cnt < maxsize/sizeof(long); cnt <<= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ save1=*addr; /* save contents of addr */
+ save2=*b; /* save contents of base */
+
+ *addr=cnt; /* write cnt to addr */
+ *b=0; /* put null at base */
+
+ /* check at base address */
+ if ((*b) != 0) {
+ *addr=save1; /* restore *addr */
+ *b=save2; /* restore *b */
+ return (0);
+ }
+ val = *addr; /* read *addr */
+
+ *addr=save1;
+ *b=save2;
+
+ if (val != cnt) {
+ /* fix boundary condition.. STARTVAL means zero */
+ if(cnt==STARTVAL/sizeof(long)) cnt=0;
+ return (cnt * sizeof(long));
+ }
+ }
+ return maxsize;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* U-Boot interface function to SDRAM init - this is where all the
+ * controlling logic happens */
+long int
+initdram(int board_type)
+{
+ ulong checkbank[4] = { [0 ... 3] = 0 };
+ int bank_no;
+ ulong total;
+ int nhr;
+ sdram_info_t dimm_info[2];
+
+
+ /* first, use the SPD to get info about the SDRAM */
+
+ /* check the NHR bit and skip mem init if it's already done */
+ nhr = get_hid0() & (1 << 16);
+
+ if (nhr) {
+ printf("Skipping SDRAM setup due to NHR bit being set\n");
+ } else {
+ /* DIMM0 */
+ check_dimm(0, &dimm_info[0]);
+
+ /* DIMM1 */
+#ifndef CONFIG_EVB64260_750CX /* EVB64260_750CX has only 1 DIMM */
+ check_dimm(1, &dimm_info[1]);
+#else /* CONFIG_EVB64260_750CX */
+ memset(&dimm_info[1], 0, sizeof(sdram_info_t));
+#endif
+
+ /* unmap all banks */
+ memory_map_bank(0, 0, 0);
+ memory_map_bank(1, 0, 0);
+ memory_map_bank(2, 0, 0);
+ memory_map_bank(3, 0, 0);
+
+ /* Now, program the GT with the correct values */
+ if (setup_sdram_common(dimm_info)) {
+ printf("Setup common failed.\n");
+ }
+
+ if (setup_sdram(&dimm_info[0])) {
+ printf("Setup for DIMM1 failed.\n");
+ }
+
+ if (setup_sdram(&dimm_info[1])) {
+ printf("Setup for DIMM2 failed.\n");
+ }
+
+ /* set the NHR bit */
+ set_hid0(get_hid0() | (1 << 16));
+ }
+ /* next, size the SDRAM banks */
+
+ total = 0;
+ if (dimm_info[0].banks > 0) checkbank[0] = 1;
+ if (dimm_info[0].banks > 1) checkbank[1] = 1;
+ if (dimm_info[0].banks > 2)
+ printf("Error, SPD claims DIMM1 has >2 banks\n");
+
+ if (dimm_info[1].banks > 0) checkbank[2] = 1;
+ if (dimm_info[1].banks > 1) checkbank[3] = 1;
+ if (dimm_info[1].banks > 2)
+ printf("Error, SPD claims DIMM2 has >2 banks\n");
+
+ /* Generic dram sizer: works even if we don't have i2c DIMMs,
+ * as long as the timing settings are more or less correct */
+
+ /*
+ * pass 1: size all the banks, using first bat (0-256M)
+ * limitation: we only support 256M per bank due to
+ * us only having 1 BAT for all DRAM
+ */
+ for (bank_no = 0; bank_no < CFG_DRAM_BANKS; bank_no++) {
+ /* skip over banks that are not populated */
+ if (! checkbank[bank_no])
+ continue;
+
+ DP(printf("checking bank %d\n", bank_no));
+
+ memory_map_bank(bank_no, 0, GB/4);
+ checkbank[bank_no] = dram_size(NULL, GB/4);
+ memory_map_bank(bank_no, 0, 0);
+
+ DP(printf("bank %d %08lx\n", bank_no, checkbank[bank_no]));
+ }
+
+ /*
+ * pass 2: contiguously map each bank into physical address
+ * space.
+ */
+ dimm_info[0].banks=dimm_info[1].banks=0;
+ for (bank_no = 0; bank_no < CFG_DRAM_BANKS; bank_no++) {
+ if(!checkbank[bank_no]) continue;
+
+ dimm_info[bank_no/2].banks++;
+ dimm_info[bank_no/2].size+=checkbank[bank_no];
+
+ memory_map_bank(bank_no, total, checkbank[bank_no]);
+#ifdef MAP_PCI
+ memory_map_bank_pci(bank_no, total, checkbank[bank_no]);
+#endif
+ total += checkbank[bank_no];
+ }
+
+#ifdef CONFIG_ECC
+#ifdef CONFIG_ZUMA_V2
+ /*
+ * We always enable ECC when bank 2 and 3 are unpopulated
+ * If we 2 or 3 are populated, we CAN'T support ECC.
+ * (Zuma boards only support ECC in banks 0 and 1; assume that
+ * in that configuration, ECC chips are mounted, even for stacked
+ * chips)
+ */
+ if (checkbank[2]==0 && checkbank[3]==0) {
+ dimm_info[0].ecc=2;
+ GT_REG_WRITE(SDRAM_TIMING, GTREGREAD(SDRAM_TIMING) | (1 << 13));
+ /* TODO: do we have to run MRS cycles again? */
+ }
+#endif /* CONFIG_ZUMA_V2 */
+
+ if (GTREGREAD(SDRAM_TIMING) & (1 << 13)) {
+ puts("[ECC] ");
+ }
+#endif /* CONFIG_ECC */
+
+#ifdef DEBUG
+ dump_dimm_info(&dimm_info[0]);
+ dump_dimm_info(&dimm_info[1]);
+#endif
+ /* TODO: return at MOST 256M? */
+ /* return total > GB/4 ? GB/4 : total; */
+ return total;
+}
diff --git a/board/evb64260/serial.c b/board/evb64260/serial.c
new file mode 100644
index 0000000000..d9c7a157c1
--- /dev/null
+++ b/board/evb64260/serial.c
@@ -0,0 +1,191 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * 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
+ */
+
+/*
+ * serial.c - serial support for the gal ev board
+ */
+
+/* supports both the 16650 duart and the MPSC */
+
+#include <common.h>
+#include <command.h>
+#include <galileo/memory.h>
+
+#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2)
+#include <ns16550.h>
+#endif
+
+#include "serial.h"
+
+#include "mpsc.h"
+
+#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2)
+const NS16550_t COM_PORTS[] = { (NS16550_t) CFG_NS16550_COM1,
+ (NS16550_t) CFG_NS16550_COM2 };
+#endif
+
+#ifdef CONFIG_MPSC
+
+int serial_init (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2)
+ int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate;
+#endif
+
+ mpsc_init(gd->baudrate);
+
+ /* init the DUART chans so that KGDB in the kernel can use them */
+#ifdef CFG_INIT_CHAN1
+ NS16550_reinit(COM_PORTS[0], clock_divisor);
+#endif
+#ifdef CFG_INIT_CHAN2
+ NS16550_reinit(COM_PORTS[1], clock_divisor);
+#endif
+ return (0);
+}
+
+void
+serial_putc(const char c)
+{
+ if (c == '\n')
+ mpsc_putchar('\r');
+
+ mpsc_putchar(c);
+}
+
+int
+serial_getc(void)
+{
+ return mpsc_getchar();
+}
+
+int
+serial_tstc(void)
+{
+ return mpsc_test_char();
+}
+
+void
+serial_setbrg (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ galbrg_set_baudrate(CONFIG_MPSC_PORT, gd->baudrate);
+}
+
+#else /* ! CONFIG_MPSC */
+
+int serial_init (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate;
+
+#ifdef CFG_INIT_CHAN1
+ (void)NS16550_init(COM_PORTS[0], clock_divisor);
+#endif
+#ifdef CFG_INIT_CHAN2
+ (void)NS16550_init(COM_PORTS[1], clock_divisor);
+#endif
+
+ return (0);
+}
+
+void
+serial_putc(const char c)
+{
+ if (c == '\n')
+ NS16550_putc(COM_PORTS[CFG_DUART_CHAN], '\r');
+
+ NS16550_putc(COM_PORTS[CFG_DUART_CHAN], c);
+}
+
+int
+serial_getc(void)
+{
+ return NS16550_getc(COM_PORTS[CFG_DUART_CHAN]);
+}
+
+int
+serial_tstc(void)
+{
+ return NS16550_tstc(COM_PORTS[CFG_DUART_CHAN]);
+}
+
+void
+serial_setbrg (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate;
+
+#ifdef CFG_INIT_CHAN1
+ NS16550_reinit(COM_PORTS[0], clock_divisor);
+#endif
+#ifdef CFG_INIT_CHAN2
+ NS16550_reinit(COM_PORTS[1], clock_divisor);
+#endif
+}
+
+#endif /* CONFIG_MPSC */
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+void
+kgdb_serial_init(void)
+{
+}
+
+void
+putDebugChar (int c)
+{
+ serial_putc (c);
+}
+
+void
+putDebugStr (const char *str)
+{
+ serial_puts (str);
+}
+
+int
+getDebugChar (void)
+{
+ return serial_getc();
+}
+
+void
+kgdb_interruptible (int yes)
+{
+ return;
+}
+#endif /* CFG_CMD_KGDB */
diff --git a/board/gen860t/README b/board/gen860t/README
new file mode 100644
index 0000000000..761ceed302
--- /dev/null
+++ b/board/gen860t/README
@@ -0,0 +1,142 @@
+
+This directory contains board specific code for a generic MPC860T based
+embedded computer, called 'GEN860T'. The design is generic in the sense that
+common, readily available components are used and that the architecture of the
+system is i(relatively) straightforward:
+
+ One eight bit wide boot (FLASH) memory
+ 32 bit main memory using SDRAM
+ DOC 2000+
+ Ethernet PHY
+ Some I2C peripheral devices: Atmel AT24C256 EEPROM, Maxim DS1337 RTC.
+ Some other miscellaneous peripherals
+
+NOTE: There are references to a XIlinx FPGA and Mil-Std 1553 databus in this
+port. I guess the computer is not as generic as I first said 8) However,
+these extras can be safely ignored.
+
+Given the GEN860T files, it should be pretty easy to reverse engineer the
+hardware configuration, if that's useful to you. Hopefully, this code will
+be useful to someone as a basis for a port to a new system or as a head start
+on a custom design. If you end up using any of this, I would appreciate
+hearing from you, especially if you discover bugs or find ways to improve the
+quality of this U-Boot port.
+
+Here are the salient features of the system:
+Clock : 33 Mhz oscillator
+Processor core frequency : 66 Mhz if in 1:2:1 mode; can also run 1:1
+Bus frequency : 33 Mhz
+
+Main memory:
+ Type : SDRAM
+ Width : 32 bits
+ Size : 64 megabytes
+ Chip : Two Micron MT48LC16M16A2TG-7E
+ CS : MPC860T CS1*/UPMA
+ UPMA CONNECTIONS:
+ SDRAM A10 : GPLA0*
+ SDRAM CAS* : GPLA2*
+ SDRAM WE* : GPLA3*
+ SDRAM RAS* : GPLA4*
+
+Boot memory:
+ Type : FLASH
+ Width : 8 bits
+ Size : 16 megabytes
+ Chip : One Intel 28F128J3A (StrataFlash)
+ CS : MPC860T CS0*/GPCM (this is the "boot" chip select)
+
+EEPROM memory:
+ Type : Serial I2C EEPROM
+ Width : 8 bits
+ Size : 32 kibibytes
+ Chip : One Atmel AT25C256
+ CS : 0x50 (external I2C address pins on device are tied to GND)
+
+Filesystem memory:
+ Type : NAND FLASH (Toshiba)
+ Width : 8 bits (i.e. interface to DOC is 8 bits)
+ Size : 32 megabytes
+ Chip : One DiskOnCHip Millenium Plus (DOC 2000+)
+ CS : MPC860T CS2*/GPCM
+
+Network support:
+ MAC : MPC86OT FEC (Fast Ethernet Controller)
+ PHY : Intel LXT971A
+ MII Addr: 0x0 (hardwired on the board)
+ MII IRQ :
+
+Console:
+ RS-232 on SMC1 (Maxim MAX3232 LVCMOS-RS232 level shifter)
+
+Real Time Clock:
+ Type : Low power, I2C interface
+ Chip : Maxim DS1337
+ CS : Address 0x68 on I2C bus
+
+ The MPC860T's internal RTC has a defect in Mask rev D that increases
+ the current drain on the KAPWR line to 10 mA. Since this is an
+ unreasonable amount of current draw for a RTC, and Motorola does not
+ plan to fix this in future mask revisions, a serial (I2C) RTC that
+ works has been included instead. NOTE that the DS1337 can be
+ configured to output a 32768 Hz clock while the main power is on.
+ This clock output has been routed to the MPC860T's EXTAL pin to allow
+ the internal RTC to be used. NOTE also that due to yet another
+ defect in the rev D mask, the RTC does not operate reliably when the
+ internal RTC divisor is set to use a 32768 Hz reference. So just use
+ the I2C RTC.
+
+Miscellaneous:
+ Xilinx Virtex FPGA on CS3*/GPCM.
+ Virtex FPGA slave SelectMap interface on cs4*/UPMB.
+ Mil-Std 1553 databus interface on CS5*/GPCM.
+ Audio sounder (beeper) with digital volume control connected to SPKROUT.
+
+Issues:
+ The DOC 2000+ returns 0x40 as its device ID when probed using the method
+ desxribed in the DOC datasheet. Unfortunately, the U-Boot DOC driver
+ does not recognize this device. As of this writing, it seems that MTD
+ does not support the DOC 2000+ either.
+
+Status:
+ Everything appears to work except DOC support. As of this writing,
+ David Woodhouse has stated on the MTD mailing list that he has no
+ knowledge of the DOC Millineum Plus and therfore there is no support
+ in MTD for this device. I wish I had known this sooner :(
+
+The GEN860T board specific files and configuration is based on the work
+of others who have contributed to U-Boot. The copright and license notices
+of these authors have been retained wherever their code has been reused.
+All new code to support the GEN860T board is:
+
+ (C) Copyright 2001-2002
+ Keith Outwater (keith_outwater@mvis.com)
+
+and the following license applies:
+
+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,
+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
+
+Thanks to Wolfgang Denk for a great software package and to everyone
+who contributed to its development.
+
+Keith Outwater
+Sr. Staff Engineer
+Microvision, Inc.
+<keith_outwater@mvis.com>
+<outwater@eskimo.com>
+
+vim: set ts=4 sw=4 tw=78:
+
diff --git a/board/gen860t/beeper.c b/board/gen860t/beeper.c
new file mode 100644
index 0000000000..46fe66ba61
--- /dev/null
+++ b/board/gen860t/beeper.c
@@ -0,0 +1,213 @@
+/*
+ * (C) Copyright 2002
+ * Keith Outwater, keith_outwater@mvis.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 <mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include <linux/ctype.h>
+
+/*
+ * Basic beeper support for the GEN860T board. The GEN860T includes
+ * an audio sounder driven by a Phillips TDA8551 amplifier. The
+ * TDA8551 features a digital volume control which uses a "trinary"
+ * input (high/high-Z/low) to set volume. The 860's SPKROUT pin
+ * drives the amplifier input.
+ */
+
+
+/*
+ * Initialize beeper-related hardware. Initialize timer 1 for use with
+ * the beeper. Use 66 Mhz internal clock with prescale of 33 to get
+ * 1 uS period per count.
+ * FIXME: we should really compute the prescale based on the reported
+ * core clock frequency.
+ */
+void
+init_beeper(void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+ immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_RST1 | TGCR_STP1;
+ immap->im_cpmtimer.cpmt_tmr1 = ((33 << TMR_PS_SHIFT) & TMR_PS_MSK)
+ | TMR_OM | TMR_FRR | TMR_ICLK_IN_GEN;
+ immap->im_cpmtimer.cpmt_tcn1 = 0;
+ immap->im_cpmtimer.cpmt_ter1 = 0xffff;
+ immap->im_cpmtimer.cpmt_tgcr |= TGCR_RST1;
+}
+
+
+/*
+ * Set beeper frequency. Max allowed frequency is 2.5 KHz. This limit
+ * is mostly arbitrary, but the beeper isn't really much good beyond this
+ * frequency.
+ */
+void
+set_beeper_frequency(uint frequency)
+{
+#define FREQ_LIMIT 2500
+
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+ /*
+ * Compute timer ticks given desired frequency. The timer is set up
+ * to count 0.5 uS per tick and it takes two ticks per cycle (Hz).
+ */
+ if (frequency > FREQ_LIMIT) frequency = FREQ_LIMIT;
+ frequency = 1000000/frequency;
+ immap->im_cpmtimer.cpmt_trr1 = (ushort)frequency;
+}
+
+
+/*
+ * Turn the beeper on
+ */
+void
+beeper_on(void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+ immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_STP1;
+}
+
+
+/*
+ * Turn the beeper off
+ */
+void
+beeper_off(void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+ immap->im_cpmtimer.cpmt_tgcr |= TGCR_STP1;
+}
+
+
+/*
+ * Increase or decrease the beeper volume. Volume can be set
+ * from off to full in 64 steps. To increase volume, the output
+ * pin is actively driven high, then returned to tristate.
+ * To decrease volume, output a low on the port pin (no need to
+ * change pin mode to tristate) then output a high to go back to
+ * tristate.
+ */
+void
+set_beeper_volume(int steps)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ int i;
+
+ if (steps >= 0) {
+ for (i = 0; i < (steps >= 64 ? 64 : steps); i++) {
+ immap->im_cpm.cp_pbodr &= ~(0x80000000 >> 19);
+ udelay(1);
+ immap->im_cpm.cp_pbodr |= (0x80000000 >> 19);
+ udelay(1);
+ }
+ }
+ else {
+ for (i = 0; i > (steps <= -64 ? -64 : steps); i--) {
+ immap->im_cpm.cp_pbdat &= ~(0x80000000 >> 19);
+ udelay(1);
+ immap->im_cpm.cp_pbdat |= (0x80000000 >> 19);
+ udelay(1);
+ }
+ }
+}
+
+
+/*
+ * Check the environment to see if the beeper needs beeping.
+ * Controlled by a sequence of the form:
+ * freq/delta volume/on time/off time;... where:
+ * freq = frequency in Hz (0 - 2500)
+ * delta volume = volume steps up or down (-64 <= vol <= 64)
+ * on time = time in mS
+ * off time = time in mS
+ *
+ * Return 1 on success, 0 on failure
+ */
+int
+do_beeper(char *sequence)
+{
+#define DELIMITER ';'
+
+int args[4];
+int i;
+int val;
+char *p = sequence;
+char *tp;
+
+ /*
+ * Parse the control sequence. This is a really simple parser
+ * without any real error checking. You can probably blow it
+ * up really easily.
+ */
+ if (*p == '\0' || !isdigit(*p)) {
+ printf("%s:%d: null or invalid string (%s)\n",
+ __FILE__, __LINE__, p);
+ return 0;
+ }
+
+ i = 0;
+ while (*p != '\0') {
+ while (*p != DELIMITER) {
+ if (i > 3) i = 0;
+ val = (int) simple_strtol(p, &tp, 0);
+ if (tp == p) {
+ printf("%s:%d: no digits or bad format\n",
+ __FILE__,__LINE__);
+ return 0;
+ }
+ else {
+ args[i] = val;
+ }
+
+ i++;
+ if (*tp == DELIMITER)
+ p = tp;
+ else
+ p = ++tp;
+ }
+ p++;
+
+ /*
+ * Well, we got something that has a chance of being correct
+ */
+#if 0
+ for (i = 0; i < 4; i++) {
+ printf("%s:%d:arg %d = %d\n", __FILE__, __LINE__, i, args[i]);
+ }
+ printf("\n");
+#endif
+
+ set_beeper_frequency(args[0]);
+ set_beeper_volume(args[1]);
+ beeper_on();
+ udelay(1000 * args[2]);
+ beeper_off();
+ udelay(1000 * args[3]);
+ }
+ return 1;
+}
+
+/* vim: set ts=4 sw=4 tw=78: */
diff --git a/board/gen860t/flash.c b/board/gen860t/flash.c
new file mode 100644
index 0000000000..902b1b0afe
--- /dev/null
+++ b/board/gen860t/flash.c
@@ -0,0 +1,644 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Keith Outwater, keith_outwater@mvsi.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 <mpc8xx.h>
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef CFG_ENV_ADDR
+# define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef CFG_ENV_SIZE
+# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
+# endif
+# ifndef CFG_ENV_SECT_SIZE
+# define CFG_ENV_SECT_SIZE CFG_ENV_SIZE
+# endif
+#endif
+
+/*
+ * Use buffered writes to flash by default - they are about 32x faster than
+ * single byte writes.
+ */
+#ifndef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+#define CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+#endif
+
+/*
+ * Max time to wait (in mS) for flash device to allocate a write buffer.
+ */
+#ifndef CFG_FLASH_ALLOC_BUFFER_TOUT
+#define CFG_FLASH_ALLOC_BUFFER_TOUT 100
+#endif
+
+/*
+ * These functions support a single Intel StrataFlash device (28F128J3A)
+ * in byte mode only!. The flash routines are very basic and simple
+ * since there isn't really any remapping necessary.
+ */
+
+/*
+ * Intel SCS (Scalable Command Set) command definitions
+ * (taken from 28F128J3A datasheet)
+ */
+#define SCS_READ_CMD 0xff
+#define SCS_READ_ID_CMD 0x90
+#define SCS_QUERY_CMD 0x98
+#define SCS_READ_STATUS_CMD 0x70
+#define SCS_CLEAR_STATUS_CMD 0x50
+#define SCS_WRITE_BUF_CMD 0xe8
+#define SCS_PROGRAM_CMD 0x40
+#define SCS_BLOCK_ERASE_CMD 0x20
+#define SCS_BLOCK_ERASE_RESUME_CMD 0xd0
+#define SCS_PROGRAM_RESUME_CMD 0xd0
+#define SCS_BLOCK_ERASE_SUSPEND_CMD 0xb0
+#define SCS_SET_BLOCK_LOCK_CMD 0x60
+#define SCS_CLR_BLOCK_LOCK_CMD 0x60
+
+/*
+ * SCS status/extended status register bit definitions
+ */
+#define SCS_SR7 0x80
+#define SCS_XSR7 0x80
+
+/*---------------------------------------------------------------------*/
+#if 0
+#define DEBUG_FLASH
+#endif
+
+#ifdef DEBUG_FLASH
+#define PRINTF(fmt,args...) printf(fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_char *addr, flash_info_t *info);
+static int write_data8 (flash_info_t *info, ulong dest, uchar data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ * Initialize the flash memory.
+ */
+unsigned long
+flash_init (void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ unsigned long size_b0;
+ int i;
+
+ for (i= 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ }
+
+ /*
+ * The gen860t board only has one FLASH memory device, so the
+ * FLASH Bank configuration is done statically.
+ */
+ PRINTF("\n## Get flash bank 1 size @ 0x%08x\n", FLASH_BASE0_PRELIM);
+ size_b0 = flash_get_size((vu_char *)FLASH_BASE0_PRELIM, &flash_info[0]);
+ if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+ printf ("## Unknown FLASH on Bank 0: "
+ "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
+ flash_info[0].flash_id,size_b0, size_b0 << 20);
+ }
+
+ PRINTF("## Before remap:\n"
+ " BR0: 0x%08x OR0: 0x%08x\n BR1: 0x%08x OR1: 0x%08x\n",
+ memctl->memc_br0, memctl->memc_or0,
+ memctl->memc_br1, memctl->memc_or1);
+
+ /*
+ * Remap FLASH according to real size
+ */
+ memctl->memc_or0 |= (-size_b0 & 0xFFFF8000);
+ memctl->memc_br0 |= (CFG_FLASH_BASE & BR_BA_MSK);
+
+ PRINTF("## After remap:\n"
+ " BR0: 0x%08x OR0: 0x%08x\n", memctl->memc_br0, memctl->memc_or0);
+
+ /*
+ * Re-do sizing to get full correct info
+ */
+ size_b0 = flash_get_size ((vu_char *)CFG_FLASH_BASE, &flash_info[0]);
+ flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+ flash_info[0].size = size_b0;
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+ /*
+ * Monitor protection is ON by default
+ */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1,
+ &flash_info[0]);
+#endif
+
+#ifdef CFG_ENV_IS_IN_FLASH
+ /*
+ * Environment protection ON by default
+ */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
+ &flash_info[0]);
+#endif
+
+ PRINTF("## Final Flash bank size: 0x%08lx\n",size_b0);
+ return (size_b0);
+}
+
+
+/*-----------------------------------------------------------------------
+ * Fill in the FLASH offset table
+ */
+static void
+flash_get_offsets (ulong base, flash_info_t *info)
+{
+ int i;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_INTEL:
+ for (i = 0; i < info->sector_count; i++) {
+ info->start[i] = base;
+ base += 1024 * 128;
+ }
+ return;
+
+ default:
+ printf ("Don't know sector offsets for FLASH"
+ " type 0x%lx\n", info->flash_id);
+ return;
+ }
+}
+
+
+/*-----------------------------------------------------------------------
+ * Display FLASH device info
+ */
+void
+flash_print_info (flash_info_t *info)
+{
+ int i;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("Missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_INTEL:
+ printf ("Intel ");
+ break;
+ default:
+ printf ("Unknown Vendor ");
+ break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_28F128J3A:
+ printf ("28F128J3A (128Mbit = 128K x 128)\n");
+ break;
+ default:
+ printf ("Unknown Chip Type\n");
+ break;
+ }
+
+ if (info->size >= (1024 * 1024)) {
+ i = 20;
+ } else {
+ i = 10;
+ }
+ printf (" Size: %ld %cB in %d Sectors\n",
+ info->size >> i,
+ (i == 20) ? 'M' : 'k',
+ info->sector_count);
+
+ printf (" Sector Start Addresses:");
+ for (i=0; i<info->sector_count; ++i) {
+ if ((i % 5) == 0)
+ printf ("\n ");
+ printf (" %08lX%s",
+ info->start[i],
+ info->protect[i] ? " (RO)" : " "
+ );
+ }
+ printf ("\n");
+ return;
+}
+
+
+/*-----------------------------------------------------------------------
+ * Get size and other information for a FLASH device.
+ * NOTE: The following code cannot be run from FLASH!
+ */
+static
+ulong flash_get_size (vu_char *addr, flash_info_t *info)
+{
+#define NO_FLASH 0
+
+ vu_char value[2];
+
+ /*
+ * Try to read the manufacturer ID
+ */
+ addr[0] = SCS_READ_CMD;
+ addr[0] = SCS_READ_ID_CMD;
+ value[0] = addr[0];
+ value[1] = addr[2];
+ addr[0] = SCS_READ_CMD;
+
+ PRINTF("Manuf. ID @ 0x%08lx: 0x%02x\n", (ulong)addr, value[0]);
+ switch (value[0]) {
+ case (INTEL_MANUFACT & 0xff):
+ info->flash_id = FLASH_MAN_INTEL;
+ break;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return (NO_FLASH);
+ }
+
+ /*
+ * Read the device ID
+ */
+ PRINTF("Device ID @ 0x%08lx: 0x%02x\n", (ulong)(&addr[2]), value[1]);
+ switch (value[1]) {
+ case (INTEL_ID_28F128J3A & 0xff):
+ info->flash_id += FLASH_28F128J3A;
+ info->sector_count = 128;
+ info->size = 16 * 1024 * 1024;
+ break;
+
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ return (NO_FLASH);
+ }
+
+ if (info->sector_count > CFG_MAX_FLASH_SECT) {
+ printf ("** ERROR: sector count %d > max (%d) **\n",
+ info->sector_count, CFG_MAX_FLASH_SECT);
+ info->sector_count = CFG_MAX_FLASH_SECT;
+ }
+ return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ * Erase the specified sectors in the specified FLASH device
+ */
+int
+flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+ int flag, prot, sect;
+ ulong start, now, last;
+
+ 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_VENDMASK) != FLASH_MAN_INTEL) {
+ printf ("Can erase only Intel flash types - 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");
+ }
+
+ start = get_timer (0);
+ last = start;
+
+ /*
+ * Start erase on unprotected sectors
+ */
+ for (sect = s_first; sect<=s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ vu_char *addr = (uchar *)(info->start[sect]);
+ vu_char status;
+
+ /*
+ * Disable interrupts which might cause a timeout
+ */
+ flag = disable_interrupts();
+
+ *addr = SCS_CLEAR_STATUS_CMD;
+ *addr = SCS_BLOCK_ERASE_CMD;
+ *addr = SCS_BLOCK_ERASE_RESUME_CMD;
+
+ /*
+ * Re-enable interrupts if necessary
+ */
+ if (flag)
+ enable_interrupts();
+
+ /*
+ * Wait at least 80us - let's wait 1 ms
+ */
+ udelay (1000);
+
+ while (((status = *addr) & SCS_SR7) != SCS_SR7) {
+ if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+ printf ("Timeout\n");
+ *addr = SCS_BLOCK_ERASE_SUSPEND_CMD;
+ *addr = SCS_READ_CMD;
+ return 1;
+ }
+
+ /*
+ * Show that we're waiting
+ */
+ if ((now - last) > 1000) { /* 1 second */
+ putc ('.');
+ last = now;
+ }
+ }
+ *addr = SCS_READ_CMD;
+ }
+ }
+ printf (" done\n");
+ return 0;
+}
+
+
+#ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+/*
+ * Allocate a flash buffer, fill it with data and write it to the flash.
+ * 0 - OK
+ * 1 - Timeout on buffer request
+ *
+ * NOTE: After the last call to this function, WSM status needs to be checked!
+ */
+static int
+write_flash_buffer8(flash_info_t *info_p, vu_char *src_p, vu_char *dest_p,
+ uint count)
+{
+ vu_char *block_addr_p = NULL;
+ vu_char *start_addr_p = NULL;
+ ulong blocksize = info_p->size / (ulong)info_p->sector_count;
+
+ int i;
+ uint time = get_timer(0);
+
+ PRINTF("%s:%d: src: 0x%p dest: 0x%p count: %d\n",
+ __FUNCTION__, __LINE__, src_p, dest_p, count);
+
+ /*
+ * What block are we in? We already know that the source address is
+ * in the flash address range, but we also can't cross a block boundary.
+ * We assume that the block does not cross a boundary (we'll check before
+ * calling this function).
+ */
+ for (i = 0; i < info_p->sector_count; ++i) {
+ if ( ((ulong)dest_p >= info_p->start[i]) &&
+ ((ulong)dest_p < (info_p->start[i] + blocksize)) ) {
+ PRINTF("%s:%d: Dest addr 0x%p is in block %d @ 0x%.8lx\n",
+ __FUNCTION__, __LINE__, dest_p, i, info_p->start[i]);
+ block_addr_p = (vu_char *)info_p->start[i];
+ break;
+ }
+ }
+
+ /*
+ * Request a buffer
+ */
+ *block_addr_p = SCS_WRITE_BUF_CMD;
+ while ((*block_addr_p & SCS_XSR7) != SCS_XSR7) {
+ if (get_timer(time) > CFG_FLASH_ALLOC_BUFFER_TOUT) {
+ PRINTF("%s:%d: Buffer allocation timeout @ 0x%p (waited %d mS)\n",
+ __FUNCTION__, __LINE__, block_addr_p,
+ CFG_FLASH_ALLOC_BUFFER_TOUT);
+ return 1;
+ }
+ *block_addr_p = SCS_WRITE_BUF_CMD;
+ }
+
+ /*
+ * Fill the buffer with data
+ */
+ start_addr_p = dest_p;
+ *block_addr_p = count - 1; /* flash device wants count - 1 */
+ PRINTF("%s:%d: Fill buffer at block addr 0x%p\n",
+ __FUNCTION__, __LINE__, block_addr_p);
+ for (i = 0; i < count; i++) {
+ *start_addr_p++ = *src_p++;
+ }
+
+ /*
+ * Flush buffer to flash
+ */
+ *block_addr_p = SCS_PROGRAM_RESUME_CMD;
+#if 1
+ time = get_timer(0);
+ while ((*block_addr_p & SCS_SR7) != SCS_SR7) {
+ if (get_timer(time) > CFG_FLASH_WRITE_TOUT) {
+ PRINTF("%s:%d: Write timeout @ 0x%p (waited %d mS)\n",
+ __FUNCTION__, __LINE__, block_addr_p, CFG_FLASH_WRITE_TOUT);
+ return 1;
+ }
+ }
+
+#endif
+ return 0;
+}
+#endif
+
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - Flash not identified
+ */
+int
+write_buff(flash_info_t *info_p, uchar *src_p, ulong addr, ulong count)
+{
+ int rc = 0;
+#ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+#define FLASH_WRITE_BUF_SIZE 0x00000020 /* 32 bytes */
+ int i;
+ uint bufs;
+ ulong buf_count;
+ vu_char *sp;
+ vu_char *dp;
+#else
+ ulong wp;
+#endif
+
+ PRINTF("\n%s:%d: src: 0x%.8lx dest: 0x%.8lx size: %d (0x%.8lx)\n",
+ __FUNCTION__, __LINE__, (ulong)src_p, addr, (uint)count, count);
+
+ if (info_p->flash_id == FLASH_UNKNOWN) {
+ return 4;
+ }
+
+#ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+ sp = src_p;
+ dp = (uchar *)addr;
+
+ /*
+ * For maximum performance, we want to align the start address to
+ * the beginning of a write buffer boundary (i.e. A4-A0 of the
+ * start address = 0). See how many bytes are required to get to a
+ * write-buffer-aligned address. If that number is non-zero, do
+ * non buffered writes of the non-aligned data. By doing non-buffered
+ * writes, we avoid the problem of crossing a block (sector) boundary
+ * with buffered writes.
+ */
+ buf_count = FLASH_WRITE_BUF_SIZE - (addr & (FLASH_WRITE_BUF_SIZE - 1));
+ if (buf_count == FLASH_WRITE_BUF_SIZE) { /* already on a boundary */
+ buf_count = 0;
+ }
+ if (buf_count > count) { /* not a full buffers worth of data to write */
+ buf_count = count;
+ }
+ count -= buf_count;
+
+ PRINTF("%s:%d: Write buffer alignment count = %ld\n",
+ __FUNCTION__, __LINE__, buf_count);
+ while (buf_count-- >= 1) {
+ if ((rc = write_data8(info_p, (ulong)dp++, *sp++)) != 0) {
+ return (rc);
+ }
+ }
+
+ PRINTF("%s:%d: count = %ld\n", __FUNCTION__, __LINE__, count);
+ if (count == 0) { /* all done */
+ PRINTF("%s:%d: Less than 1 buffer (%d) worth of bytes\n",
+ __FUNCTION__, __LINE__, FLASH_WRITE_BUF_SIZE);
+ return (rc);
+ }
+
+ /*
+ * Now that we are write buffer aligned, write full or partial buffers.
+ * The fact that we are write buffer aligned automatically avoids
+ * crossing a block address during a write buffer operation.
+ */
+ bufs = count / FLASH_WRITE_BUF_SIZE;
+ PRINTF("%s:%d: %d (0x%x) buffers to write\n", __FUNCTION__, __LINE__,
+ bufs, bufs);
+ while (bufs >= 1) {
+ rc = write_flash_buffer8(info_p, sp, dp, FLASH_WRITE_BUF_SIZE);
+ if (rc != 0) {
+ PRINTF("%s:%d: ** Error writing buf %d\n",
+ __FUNCTION__, __LINE__, bufs);
+ return (rc);
+ }
+ bufs--;
+ sp += FLASH_WRITE_BUF_SIZE;
+ dp += FLASH_WRITE_BUF_SIZE;
+ }
+
+ /*
+ * Do the leftovers
+ */
+ i = count % FLASH_WRITE_BUF_SIZE;
+ PRINTF("%s:%d: %d (0x%x) leftover bytes\n", __FUNCTION__, __LINE__, i, i);
+ if (i > 0) {
+ rc = write_flash_buffer8(info_p, sp, dp, i);
+ }
+
+ sp = (vu_char*)info_p->start[0];
+ *sp = SCS_READ_CMD;
+ return (rc);
+
+#else
+ wp = addr;
+ while (count-- >= 1) {
+ if((rc = write_data8(info_p, wp++, *src_p++)) != 0)
+ return (rc);
+ }
+ return 0;
+#endif
+}
+
+
+/*-----------------------------------------------------------------------
+ * Write a byte to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int
+write_data8 (flash_info_t *info, ulong dest, uchar data)
+{
+ vu_char *addr = (vu_char *)dest;
+ vu_char status;
+ ulong start;
+ int flag;
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*addr & data) != data) {
+ return (2);
+ }
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ *addr = SCS_PROGRAM_CMD;
+ *addr = data;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer (0);
+
+ while (((status = *addr) & SCS_SR7) != SCS_SR7) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *addr = SCS_READ_CMD;
+ return (1);
+ }
+ }
+ *addr = SCS_READ_CMD;
+ return (0);
+}
+
+/* vim: set ts=4 sw=4 tw=78: */
diff --git a/board/gen860t/fpga.c b/board/gen860t/fpga.c
new file mode 100644
index 0000000000..2c4fbf14c8
--- /dev/null
+++ b/board/gen860t/fpga.c
@@ -0,0 +1,401 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.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
+ *
+ */
+
+/*
+ * Virtex2 FPGA configuration support for the GEN860T computer
+ */
+
+#include <common.h>
+#include <virtex2.h>
+#include <command.h>
+#include "fpga.h"
+
+#if (CONFIG_FPGA)
+
+#if 0
+#define GEN860T_FPGA_DEBUG
+#endif
+
+#ifdef GEN860T_FPGA_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/*
+ * Port bit numbers for the Selectmap controls
+ */
+#define FPGA_INIT_BIT_NUM 22 /* PB22 */
+#define FPGA_RESET_BIT_NUM 11 /* PC11 */
+#define FPGA_DONE_BIT_NUM 16 /* PB16 */
+#define FPGA_PROGRAM_BIT_NUM 7 /* PA7 */
+
+/* Note that these are pointers to code that is in Flash. They will be
+ * relocated at runtime.
+ */
+Xilinx_Virtex2_Slave_SelectMap_fns fpga_fns = {
+ fpga_pre_config_fn,
+ fpga_pgm_fn,
+ fpga_init_fn,
+ fpga_err_fn,
+ fpga_done_fn,
+ fpga_clk_fn,
+ fpga_cs_fn,
+ fpga_wr_fn,
+ fpga_read_data_fn,
+ fpga_write_data_fn,
+ fpga_busy_fn,
+ fpga_abort_fn,
+ fpga_post_config_fn
+};
+
+Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
+ { Xilinx_Virtex2,
+ slave_selectmap,
+ XILINX_XC2V3000_SIZE,
+ (void *)&fpga_fns,
+ 0
+ }
+};
+
+/*
+ * Display FPGA revision information
+ */
+void
+print_fpga_revision(void)
+{
+ vu_long *rev_p = (vu_long *)0x60000008;
+
+ printf("FPGA Revision 0x%.8lx"
+ " (Date %.2lx/%.2lx/%.2lx, Status \"%.1lx\", Version %.3lu)\n",
+ *rev_p,
+ ((*rev_p >> 28) & 0xf),
+ ((*rev_p >> 20) & 0xff),
+ ((*rev_p >> 12) & 0xff),
+ ((*rev_p >> 8) & 0xf),
+ (*rev_p & 0xff));
+}
+
+
+/*
+ * Perform a simple test of the FPGA to processor interface using the FPGA's
+ * inverting bus test register. The great thing about doing a read/write
+ * test on a register that inverts it's contents is that you avoid any
+ * problems with bus charging.
+ * Return 0 on failure, 1 on success.
+ */
+int
+test_fpga_ibtr(void)
+{
+ vu_long *ibtr_p = (vu_long *)0x60000010;
+ vu_long readback;
+ vu_long compare;
+ int i;
+ int j;
+ int k;
+ int pass = 1;
+
+ static const ulong bitpattern[] = {
+ 0xdeadbeef, /* magic ID pattern for debug */
+ 0x00000001, /* single bit */
+ 0x00000003, /* two adjacent bits */
+ 0x00000007, /* three adjacent bits */
+ 0x0000000F, /* four adjacent bits */
+ 0x00000005, /* two non-adjacent bits */
+ 0x00000015, /* three non-adjacent bits */
+ 0x00000055, /* four non-adjacent bits */
+ 0xaaaaaaaa, /* alternating 1/0 */
+ };
+
+ for (i = 0; i < 1024; i++) {
+ for (j = 0; j < 31; j++) {
+ for (k = 0; k < sizeof(bitpattern)/sizeof(bitpattern[0]); k++) {
+ *ibtr_p = compare = (bitpattern[k] << j);
+ readback = *ibtr_p;
+ if (readback != ~compare) {
+ printf("%s:%d: FPGA test fail: expected 0x%.8lx"
+ " actual 0x%.8lx\n",
+ __FUNCTION__, __LINE__, ~compare, readback);
+ pass = 0;
+ break;
+ }
+ }
+ if (!pass) break;
+ }
+ if (!pass) break;
+ }
+ if (pass) {
+ printf("FPGA inverting bus test passed\n");
+ print_fpga_revision();
+ }
+ else {
+ printf("** FPGA inverting bus test failed\n");
+ }
+ return pass;
+}
+
+
+/*
+ * Set the active-low FPGA reset signal.
+ */
+void
+fpga_reset(int assert)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+ PRINTF("%s:%d: RESET ", __FUNCTION__, __LINE__);
+ if (assert) {
+ immap->im_ioport.iop_pcdat &= ~(0x8000 >> FPGA_RESET_BIT_NUM);
+ PRINTF("asserted\n");
+ }
+ else {
+ immap->im_ioport.iop_pcdat |= (0x8000 >> FPGA_RESET_BIT_NUM);
+ PRINTF("deasserted\n");
+ }
+}
+
+
+/*
+ * Initialize the SelectMap interface. We assume that the mode and the
+ * initial state of all of the port pins have already been set!
+ */
+void
+fpga_selectmap_init(void)
+{
+ PRINTF("%s:%d: Initialize SelectMap interface\n", __FUNCTION__, __LINE__);
+ fpga_pgm_fn(FALSE, FALSE, 0); /* make sure program pin is inactive */
+}
+
+
+/*
+ * Initialize the fpga. Return 1 on success, 0 on failure.
+ */
+int
+gen860t_init_fpga(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ int i;
+
+ PRINTF("%s:%d: Initialize FPGA interface (relocation offset = 0x%.8lx)\n",
+ __FUNCTION__, __LINE__, gd->reloc_off);
+ fpga_init(gd->reloc_off);
+ fpga_selectmap_init();
+
+ for(i=0; i < CONFIG_FPGA_COUNT; i++) {
+ PRINTF("%s:%d: Adding fpga %d\n", __FUNCTION__, __LINE__, i);
+ fpga_add(fpga_xilinx, &fpga[i]);
+ }
+ return 1;
+}
+
+
+/*
+ * Set the FPGA's active-low SelectMap program line to the specified level
+ */
+int
+fpga_pgm_fn(int assert, int flush, int cookie)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+ PRINTF("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
+
+ if (assert) {
+ immap->im_ioport.iop_padat &= ~(0x8000 >> FPGA_PROGRAM_BIT_NUM);
+ PRINTF("asserted\n");
+ }
+ else {
+ immap->im_ioport.iop_padat |= (0x8000 >> FPGA_PROGRAM_BIT_NUM);
+ PRINTF("deasserted\n");
+ }
+ return assert;
+}
+
+
+/*
+ * Test the state of the active-low FPGA INIT line. Return 1 on INIT
+ * asserted (low).
+ */
+int
+fpga_init_fn(int cookie)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+ PRINTF("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
+ if(immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_INIT_BIT_NUM)) {
+ PRINTF("high\n");
+ return 0;
+ }
+ else {
+ PRINTF("low\n");
+ return 1;
+ }
+}
+
+
+/*
+ * Test the state of the active-high FPGA DONE pin
+ */
+int
+fpga_done_fn(int cookie)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+ PRINTF("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
+ if (immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_DONE_BIT_NUM)) {
+ PRINTF("high\n");
+ return FPGA_SUCCESS;
+ }
+ else {
+ PRINTF("low\n");
+ return FPGA_FAIL;
+ }
+}
+
+
+/*
+ * Read FPGA SelectMap data.
+ */
+int
+fpga_read_data_fn(unsigned char *data, int cookie)
+{
+ vu_char *p = (vu_char *)SELECTMAP_BASE;
+
+ *data = *p;
+#if 0
+ PRINTF("%s: Read 0x%x into 0x%p\n", __FUNCTION__, (int)data, data);
+#endif
+ return (int)data;
+}
+
+
+/*
+ * Write data to the FPGA SelectMap port
+ */
+int
+fpga_write_data_fn(unsigned char data, int flush, int cookie)
+{
+ vu_char *p = (vu_char *)SELECTMAP_BASE;
+
+#if 0
+ PRINTF("%s: Write Data 0x%x\n", __FUNCTION__, (int)data);
+#endif
+ *p = data;
+ return (int)data;
+}
+
+
+/*
+ * Abort and FPGA operation
+ */
+int
+fpga_abort_fn(int cookie)
+{
+ PRINTF("%s:%d: FPGA program sequence aborted\n",
+ __FUNCTION__, __LINE__);
+ return FPGA_FAIL;
+}
+
+
+/*
+ * FPGA pre-configuration function. Just make sure that
+ * FPGA reset is asserted to keep the FPGA from starting up after
+ * configuration.
+ */
+int
+fpga_pre_config_fn(int cookie)
+{
+ PRINTF("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
+ fpga_reset(TRUE);
+ return 0;
+}
+
+
+/*
+ * FPGA post configuration function. Blip the FPGA reset line and then see if
+ * the FPGA appears to be running.
+ */
+int
+fpga_post_config_fn(int cookie)
+{
+ int rc;
+
+ PRINTF("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
+ fpga_reset(TRUE);
+ udelay(1000);
+ fpga_reset(FALSE);
+ udelay (1000);
+
+ /*
+ * Use the FPGA,s inverting bus test register to do a simple test of the
+ * processor interface.
+ */
+ rc = test_fpga_ibtr();
+ return rc;
+}
+
+
+/*
+ * Clock, chip select and write signal assert functions and error check
+ * and busy functions. These are only stubs because the GEN860T selectmap
+ * interface handles sequencing of control signals automatically (it uses
+ * a memory-mapped interface to the FPGA SelectMap port). The design of
+ * the interface guarantees that the SelectMap port cannot be overrun so
+ * no busy check is needed. A configuration error is signalled by INIT
+ * going low during configuration, so there is no need for a separate error
+ * function.
+ */
+int
+fpga_clk_fn(int assert_clk, int flush, int cookie)
+{
+ return assert_clk;
+}
+
+int
+fpga_cs_fn(int assert_cs, int flush, int cookie)
+{
+ return assert_cs;
+}
+
+int
+fpga_wr_fn(int assert_write, int flush, int cookie)
+{
+ return assert_write;
+}
+
+int
+fpga_err_fn(int cookie)
+{
+ return 0;
+}
+
+int
+fpga_busy_fn(int cookie)
+{
+ return 0;
+}
+#endif
+
+/* vim: set ts=4 tw=78 sw=4: */
diff --git a/board/gen860t/gen860t.c b/board/gen860t/gen860t.c
new file mode 100644
index 0000000000..16a3262c4b
--- /dev/null
+++ b/board/gen860t/gen860t.c
@@ -0,0 +1,299 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Keith Outwater, keith_outwater@mvis.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 <virtex2.h>
+#include <common.h>
+#include <mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include "beeper.h"
+#include "fpga.h"
+#include "ioport.h"
+
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+
+#if defined(CFG_CMD_MII) && defined(CONFIG_MII)
+#include <net.h>
+#endif
+
+#if 0
+#define GEN860T_DEBUG
+#endif
+
+#ifdef GEN860T_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/*
+ * The following UPM init tables were generated automatically by
+ * Motorola's MCUINIT program. See the README file for UPM to
+ * SDRAM pin assignments if you want to type this data into
+ * MCUINIT in order to reverse engineer the waveforms.
+ */
+
+/*
+ * UPM initialization tables for MICRON MT48LC16M16A2TG SDRAM devices
+ * (UPMA) and Virtex FPGA SelectMap interface (UPMB).
+ * NOTE that unused areas of the table are used to hold NOP, precharge
+ * and mode register set sequences.
+ *
+ */
+#define UPMA_NOP_ADDR 0x5
+#define UPMA_PRECHARGE_ADDR 0x6
+#define UPMA_MRS_ADDR 0x12
+
+#define UPM_SINGLE_READ_ADDR 0x00
+#define UPM_BURST_READ_ADDR 0x08
+#define UPM_SINGLE_WRITE_ADDR 0x18
+#define UPM_BURST_WRITE_ADDR 0x20
+#define UPM_REFRESH_ADDR 0x30
+
+const uint sdram_upm_table[] = {
+ /* single read (offset 0x00 in upm ram) */
+ 0x0e0fdc04, 0x01adfc04, 0x0fbffc00, 0x1fff5c05,
+ 0xffffffff, 0x0fffffcd, 0x0fff0fce, 0xefcfffff,
+ /* burst read (offset 0x08 in upm ram) */
+ 0x0f0fdc04, 0x00fdfc04, 0xf0fffc00, 0xf0fffc00,
+ 0xf1fffc00, 0xfffffc00, 0xfffffc05, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x0ffffff4, 0x1f3d5ff4,
+ 0xfffffff4, 0xfffffff5, 0xffffffff, 0xffffffff,
+ /* single write (offset 0x18 in upm ram) */
+ 0x0f0fdc04, 0x00ad3c00, 0x1fff5c05, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ /* burst write (offset 0x20 in upm ram) */
+ 0x0f0fdc00, 0x10fd7c00, 0xf0fffc00, 0xf0fffc00,
+ 0xf1fffc04, 0xfffffc05, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff7ff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ /* refresh (offset 0x30 in upm ram) */
+ 0x1ffddc84, 0xfffffc04, 0xfffffc04, 0xfffffc84,
+ 0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ /* exception (offset 0x3C in upm ram) */
+ };
+
+const uint selectmap_upm_table[] = {
+ /* single read (offset 0x00 in upm ram) */
+ 0x88fffc06, 0x00fff404, 0x00fffc04, 0x33fffc00,
+ 0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff,
+ /* burst read (offset 0x08 in upm ram) */
+ 0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ /* single write (offset 0x18 in upm ram) */
+ 0x88fffc04, 0x00fff400, 0x77fffc05, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ /* burst write (offset 0x20 in upm ram) */
+ 0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ /* refresh (offset 0x30 in upm ram) */
+ 0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ /* exception (offset 0x3C in upm ram) */
+ 0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+/*
+ * Check board identity. Always successful (gives information only)
+ */
+int
+checkboard(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ unsigned char *s;
+ unsigned char buf[64];
+ int i;
+
+ i = getenv_r("board_id", buf, sizeof(buf));
+ s = (i>0) ? buf : NULL;
+
+ if (s) {
+ printf("%s ", s);
+ } else {
+ printf("<unknown> ");
+ }
+
+ i = getenv_r("serial#", buf, sizeof(buf));
+ s = (i>0) ? buf : NULL;
+
+ if (s) {
+ printf("S/N %s\n", s);
+ } else {
+ printf("S/N <unknown>\n");
+ }
+
+ printf("CPU at %s MHz, ",strmhz(buf, gd->cpu_clk));
+ printf("local bus at %s MHz\n", strmhz(buf, gd->bus_clk));
+ return (0);
+}
+
+/*
+ * Initialize SDRAM
+ */
+long int
+initdram(int board_type)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immr->im_memctl;
+
+ upmconfig(UPMA,
+ (uint *)sdram_upm_table,
+ sizeof(sdram_upm_table) / sizeof(uint)
+ );
+
+ /*
+ * Setup MAMR register
+ */
+ memctl->memc_mptpr = CFG_MPTPR_1BK_8K;
+ memctl->memc_mamr = CFG_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */
+
+ /*
+ * Map CS1* to SDRAM bank
+ */
+ memctl->memc_or1 = CFG_OR1;
+ memctl->memc_br1 = CFG_BR1;
+
+ /*
+ * Perform SDRAM initialization sequence:
+ * 1. Apply at least one NOP command
+ * 2. 100 uS delay (JEDEC standard says 200 uS)
+ * 3. Issue 4 precharge commands
+ * 4. Perform two refresh cycles
+ * 5. Program mode register
+ *
+ * Program SDRAM for standard operation, sequential burst, burst length
+ * of 4, CAS latency of 2.
+ */
+ memctl->memc_mar = 0x00000000;
+ memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+ MCR_MLCF(0) | UPMA_NOP_ADDR;
+ udelay(200);
+ memctl->memc_mar = 0x00000000;
+ memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+ MCR_MLCF(4) | UPMA_PRECHARGE_ADDR;
+
+ memctl->memc_mar = 0x00000000;
+ memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+ MCR_MLCF(2) | UPM_REFRESH_ADDR;
+
+ memctl->memc_mar = 0x00000088;
+ memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+ MCR_MLCF(1) | UPMA_MRS_ADDR;
+
+ memctl->memc_mar = 0x00000000;
+ memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+ MCR_MLCF(0) | UPMA_NOP_ADDR;
+ /*
+ * Enable refresh
+ */
+ memctl->memc_mamr |= MAMR_PTAE;
+
+ return (SDRAM_SIZE);
+}
+
+/*
+ * Disk On Chip (DOC) Millenium initialization.
+ * The DOC lives in the CS2* space
+ */
+#if (CONFIG_COMMANDS & CFG_CMD_DOC)
+extern void
+doc_probe(ulong physadr);
+
+void
+doc_init(void)
+{
+ printf("Probing at 0x%.8x: ", DOC_BASE);
+ doc_probe(DOC_BASE);
+}
+#endif
+
+/*
+ * Miscellaneous intialization
+ */
+int
+misc_init_r (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immr->im_memctl;
+
+ /*
+ * Set up UPMB to handle the Virtex FPGA SelectMap interface
+ */
+ upmconfig(UPMB, (uint *)selectmap_upm_table,
+ sizeof(selectmap_upm_table) / sizeof(uint));
+
+ memctl->memc_mbmr = 0x0;
+
+ config_mpc8xx_ioports(immr);
+
+#if (CONFIG_COMMANDS & CFG_CMD_MII)
+ mii_init();
+#endif
+
+#if (CONFIG_FPGA)
+ gen860t_init_fpga();
+#endif
+ return 0;
+}
+
+/*
+ * Final init hook before entering command loop.
+ */
+int
+last_stage_init(void)
+{
+ unsigned char buf[256];
+ int i;
+
+ /*
+ * Set LEDs here since status LED init code has already run
+ */
+ status_led_set(STATUS_LED_BIT1, STATUS_LED_ON);
+ status_led_set(STATUS_LED_BIT3, STATUS_LED_ON);
+
+ /*
+ * Turn the beeper volume all the way down in case this is a warm
+ * boot.
+ */
+ set_beeper_volume(-64);
+ init_beeper();
+
+ /*
+ * Read the environment to see what to do with the beeper
+ */
+ i = getenv_r("beeper", buf, sizeof(buf));
+ if (i > 0) {
+ do_beeper(buf);
+ }
+ return 0;
+}
+/* vim: set ts=4 sw=4 tw=78 : */
diff --git a/board/gen860t/ioport.c b/board/gen860t/ioport.c
new file mode 100644
index 0000000000..5d6524dbd3
--- /dev/null
+++ b/board/gen860t/ioport.c
@@ -0,0 +1,276 @@
+/*
+ * (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 <mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include "ioport.h"
+
+#if 0
+#define IOPORT_DEBUG
+#endif
+
+#ifdef IOPORT_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/*
+ * The ioport configuration table.
+ */
+const mpc8xx_iop_conf_t iop_conf_tab[NUM_PORTS][PORT_BITS] = {
+ /*
+ * Port A configuration
+ * Pin Signal Type Active Initial state
+ * PA7 fpgaProgramLowOut Out Low High
+ */
+ { /* conf ppar psor pdir podr pdat pint function */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* No pin */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* No pin */
+ /* PA15 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA14 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA13 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA12 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA11 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA10 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA9 */ { 1, 0, 0, 1, 0, 0, 0 }, /* grn bicolor LED 1*/
+ /* PA8 */ { 1, 0, 0, 1, 0, 0, 0 }, /* red bicolor LED 1*/
+ /* PA7 */ { 1, 0, 0, 1, 0, 1, 0 }, /* fpgaProgramLow */
+ /* PA6 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA5 */ { 1, 0, 0, 1, 0, 0, 0 }, /* grn bicolor LED 0*/
+ /* PA4 */ { 1, 0, 0, 1, 0, 0, 0 }, /* red bicolor LED 0*/
+ /* PA3 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA2 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA1 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PA0 */ { 0, 0, 0, 0, 0, 0, 0 } /* */
+ },
+
+ /*
+ * Pin Signal Type Active Initial state
+ * PB14 docBusyLowIn In Low X
+ * PB15 gpio1Sig Out High Low
+ * PB16 fpgaDoneBi In High X
+ * PB17 swBitOkLowOut Out Low Low
+ * PB19 speakerVolSig Out/Hi-Z High/Low High (Hi-Z)
+ * PB22 fpgaInitLowBi In Low X
+ * PB23 batteryOkSig In High X
+ */
+ { /* conf ppar psor pdir podr pdat pint function */
+ /* PB31 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB30 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB29 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB28 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB27 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB26 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB25 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB24 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB23 */ { 1, 0, 0, 0, 0, 0, 0 }, /* batteryOk */
+ /* PB22 */ { 1, 0, 0, 0, 0, 0, 0 }, /* fpgaInitLowBi */
+ /* PB21 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB20 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB19 */ { 1, 0, 0, 1, 1, 1, 0 }, /* speakerVol */
+ /* PB18 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PB17 */ { 1, 0, 0, 1, 0, 0, 0 }, /* swBitOkLow */
+ /* PB16 */ { 1, 0, 0, 0, 0, 0, 0 }, /* fpgaDone */
+ /* PB15 */ { 1, 0, 0, 1, 0, 0, 0 }, /* gpio1 */
+ /* PB14 */ { 1, 0, 0, 0, 0, 0, 0 } /* docBusyLow */
+ },
+
+ /*
+ * Pin Signal Type Active Initial state
+ * PC4 i2cBus1EnSig Out High High
+ * PC5 i2cBus2EnSig Out High High
+ * PC6 gpio0Sig Out High Low
+ * PC8 i2cBus3EnSig Out High High
+ * PC10 i2cBus4EnSig Out High High
+ * PC11 fpgaResetLowOut Out Low High
+ * PC12 systemBitOkIn In High X
+ * PC15 selfDreqLow In Low X
+ */
+ { /* conf ppar psor pdir podr pdat pint function */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PC15 */ { 1, 0, 0, 0, 0, 0, 0 }, /* selfDreqLowIn */
+ /* PC14 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PC13 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PC12 */ { 1, 0, 0, 0, 0, 0, 0 }, /* systemBitOkIn */
+ /* PC11 */ { 1, 0, 0, 1, 0, 1, 0 }, /* fpgaResetLowOut */
+ /* PC10 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus4EnSig */
+ /* PC9 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PC8 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus3EnSig */
+ /* PC7 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PC6 */ { 1, 0, 0, 1, 0, 1, 0 }, /* gpio0 */
+ /* PC5 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus2EnSig */
+ /* PC4 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus1EnSig */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 } /* */
+ },
+
+ /* Port D configuration */
+ { /* conf ppar psor pdir podr pdat pint function */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD15 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD14 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD13 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD12 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD11 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD10 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD9 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD8 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD7 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD6 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD5 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD4 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* PD3 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */
+ /* N/A */ { 0, 0, 0, 0, 0, 0, 0 } /* */
+ }
+};
+
+/*
+ * Configure the MPC8XX I/O ports per the ioport configuration table
+ * (taken from ./cpu/mpc8260/cpu_init.c)
+ */
+void
+config_mpc8xx_ioports(volatile immap_t *immr)
+{
+ int portnum;
+
+ for (portnum = 0; portnum < NUM_PORTS; portnum++) {
+ uint pmsk = 0, ppar = 0, psor = 0, pdir = 0;
+ uint podr = 0, pdat = 0, pint = 0;
+ uint msk = 1;
+ mpc8xx_iop_conf_t *iopc = (mpc8xx_iop_conf_t *)&iop_conf_tab[portnum][0];
+ mpc8xx_iop_conf_t *eiopc = iopc + PORT_BITS;
+
+ /*
+ * For all ports except port B, ignore the two don't care entries
+ * in the configuration tables.
+ */
+ if (portnum != 1) {
+ iopc = (mpc8xx_iop_conf_t *)&iop_conf_tab[portnum][2];
+ }
+
+ /*
+ * NOTE: index 0 refers to pin 17, index 17 refers to pin 0
+ */
+ while (iopc < eiopc) {
+ if (iopc->conf) {
+ pmsk |= msk;
+ if (iopc->ppar) ppar |= msk;
+ if (iopc->psor) psor |= msk;
+ if (iopc->pdir) pdir |= msk;
+ if (iopc->podr) podr |= msk;
+ if (iopc->pdat) pdat |= msk;
+ if (iopc->pint) pint |= msk;
+ }
+ msk <<= 1;
+ iopc++;
+ }
+
+ PRINTF("%s:%d:\n portnum=%d ", __FUNCTION__, __LINE__, portnum);
+#ifdef IOPORT_DEBUG
+ switch(portnum) {
+ case 0: printf("(A)\n"); break;
+ case 1: printf("(B)\n"); break;
+ case 2: printf("(C)\n"); break;
+ case 3: printf("(D)\n"); break;
+ default: printf("(?)\n"); break;
+ }
+#endif
+ PRINTF(" ppar=0x%.8x pdir=0x%.8x podr=0x%.8x\n"
+ " pdat=0x%.8x psor=0x%.8x pint=0x%.8x pmsk=0x%.8x\n",
+ ppar, pdir, podr, pdat, psor, pint, pmsk);
+
+ /*
+ * Have to handle the ioports on a port-by-port basis since there
+ * are three different flavors.
+ */
+ if (pmsk != 0) {
+ uint tpmsk = ~pmsk;
+
+ if (0 == portnum) { /* port A */
+ immr->im_ioport.iop_papar &= tpmsk;
+ immr->im_ioport.iop_padat =
+ (immr->im_ioport.iop_padat & tpmsk) | pdat;
+ immr->im_ioport.iop_padir =
+ (immr->im_ioport.iop_padir & tpmsk) | pdir;
+ immr->im_ioport.iop_paodr =
+ (immr->im_ioport.iop_paodr & tpmsk) | podr;
+ immr->im_ioport.iop_papar |= ppar;
+ }
+ else if (1 == portnum) { /* port B */
+ immr->im_cpm.cp_pbpar &= tpmsk;
+ immr->im_cpm.cp_pbdat = (immr->im_cpm.cp_pbdat & tpmsk) | pdat;
+ immr->im_cpm.cp_pbdir = (immr->im_cpm.cp_pbdir & tpmsk) | pdir;
+ immr->im_cpm.cp_pbodr = (immr->im_cpm.cp_pbodr & tpmsk) | podr;
+ immr->im_cpm.cp_pbpar |= ppar;
+ }
+ else if (2 == portnum) { /* port C */
+ immr->im_ioport.iop_pcpar &= tpmsk;
+ immr->im_ioport.iop_pcdat =
+ (immr->im_ioport.iop_pcdat & tpmsk) | pdat;
+ immr->im_ioport.iop_pcdir =
+ (immr->im_ioport.iop_pcdir & tpmsk) | pdir;
+ immr->im_ioport.iop_pcint =
+ (immr->im_ioport.iop_pcint & tpmsk) | pint;
+ immr->im_ioport.iop_pcso =
+ (immr->im_ioport.iop_pcso & tpmsk) | psor;
+ immr->im_ioport.iop_pcpar |= ppar;
+ }
+ else if (3 == portnum) { /* port D */
+ immr->im_ioport.iop_pdpar &= tpmsk;
+ immr->im_ioport.iop_pddat =
+ (immr->im_ioport.iop_pddat & tpmsk) | pdat;
+ immr->im_ioport.iop_pddir =
+ (immr->im_ioport.iop_pddir & tpmsk) | pdir;
+ immr->im_ioport.iop_pdpar |= ppar;
+ }
+ }
+ }
+
+ PRINTF("%s:%d: Port A:\n papar=0x%.4x padir=0x%.4x"
+ " paodr=0x%.4x\n padat=0x%.4x\n", __FUNCTION__, __LINE__,
+ immr->im_ioport.iop_papar, immr->im_ioport.iop_padir,
+ immr->im_ioport.iop_paodr, immr->im_ioport.iop_padat);
+ PRINTF("%s:%d: Port B:\n pbpar=0x%.8x pbdir=0x%.8x"
+ " pbodr=0x%.8x\n pbdat=0x%.8x\n", __FUNCTION__, __LINE__,
+ immr->im_cpm.cp_pbpar, immr->im_cpm.cp_pbdir,
+ immr->im_cpm.cp_pbodr, immr->im_cpm.cp_pbdat);
+ PRINTF("%s:%d: Port C:\n pcpar=0x%.4x pcdir=0x%.4x"
+ " pcdat=0x%.4x\n pcso=0x%.4x pcint=0x%.4x\n ",
+ __FUNCTION__, __LINE__, immr->im_ioport.iop_pcpar,
+ immr->im_ioport.iop_pcdir, immr->im_ioport.iop_pcdat,
+ immr->im_ioport.iop_pcso, immr->im_ioport.iop_pcint);
+ PRINTF("%s:%d: Port D:\n pdpar=0x%.4x pddir=0x%.4x"
+ " pddat=0x%.4x\n", __FUNCTION__, __LINE__,
+ immr->im_ioport.iop_pdpar, immr->im_ioport.iop_pddir,
+ immr->im_ioport.iop_pddat);
+}
+
+/* vim: set ts=4 sw=4 tw=78: */
diff --git a/board/gen860t/u-boot.lds b/board/gen860t/u-boot.lds
new file mode 100644
index 0000000000..1b53c723d5
--- /dev/null
+++ b/board/gen860t/u-boot.lds
@@ -0,0 +1,135 @@
+/*
+ * Linker command file for the GEN860T board.
+ *
+ * (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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+SECTIONS
+{
+ /*
+ * Read-only sections, merged into text segment:
+ */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc8xx/start.o (.text)
+ common/dlmalloc.o (.text)
+ lib_ppc/ppcstring.o (.text)
+ lib_generic/vsprintf.o (.text)
+ lib_generic/crc32.o (.text)
+ lib_generic/zlib.o (.text)
+
+/* . = env_offset;
+ common/environment.o(.text) */
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /*
+ * Read-write section, merged into data segment:
+ */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+
+ _end = . ;
+ PROVIDE (end = .);
+}
+
diff --git a/board/impa7/flash.c b/board/impa7/flash.c
new file mode 100644
index 0000000000..c59ffb8658
--- /dev/null
+++ b/board/impa7/flash.c
@@ -0,0 +1,365 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#define FLASH_BANK_SIZE 0x800000
+#define MAIN_SECT_SIZE 0x20000
+#define PARAM_SECT_SIZE 0x4000
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+/*-----------------------------------------------------------------------
+ */
+
+ulong flash_init(void)
+{
+ int i, j;
+ ulong size = 0;
+
+ for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
+ {
+ ulong flashbase = 0;
+ flash_info[i].flash_id =
+ (INTEL_MANUFACT & FLASH_VENDMASK) |
+ (INTEL_ID_28F320B3T & FLASH_TYPEMASK);
+ flash_info[i].size = FLASH_BANK_SIZE;
+ flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
+ memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
+ if (i == 0)
+ flashbase = PHYS_FLASH_1;
+ else if (i == 1)
+ flashbase = PHYS_FLASH_2;
+ else
+ panic("configured to many flash banks!\n");
+ for (j = 0; j < flash_info[i].sector_count; j++)
+ {
+ if (j <= 7)
+ {
+ flash_info[i].start[j] = flashbase + j * PARAM_SECT_SIZE;
+ }
+ else
+ {
+ flash_info[i].start[j] = flashbase + (j - 7)*MAIN_SECT_SIZE;
+ }
+ }
+ size += flash_info[i].size;
+ }
+
+ /* Protect monitor and environment sectors
+ */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_FLASH_BASE,
+ CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
+ &flash_info[0]);
+
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+ &flash_info[0]);
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t *info)
+{
+ int i;
+
+ switch (info->flash_id & FLASH_VENDMASK)
+ {
+ case (INTEL_MANUFACT & FLASH_VENDMASK):
+ printf("Intel: ");
+ break;
+ default:
+ printf("Unknown Vendor ");
+ break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK)
+ {
+ case (INTEL_ID_28F320B3T & FLASH_TYPEMASK):
+ printf("28F320F3B (16Mbit)\n");
+ break;
+ default:
+ printf("Unknown Chip Type\n");
+ goto Done;
+ break;
+ }
+
+ printf(" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+
+ printf(" Sector Start Addresses:");
+ for (i = 0; i < info->sector_count; i++)
+ {
+ if ((i % 5) == 0)
+ {
+ printf ("\n ");
+ }
+ printf (" %08lX%s", info->start[i],
+ info->protect[i] ? " (RO)" : " ");
+ }
+ printf ("\n");
+
+Done:
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ int flag, prot, sect;
+ int rc = ERR_OK;
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ return ERR_UNKNOWN_FLASH_TYPE;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ return ERR_INVAL;
+ }
+
+ if ((info->flash_id & FLASH_VENDMASK) !=
+ (INTEL_MANUFACT & FLASH_VENDMASK)) {
+ return ERR_UNKNOWN_FLASH_VENDOR;
+ }
+
+ prot = 0;
+ for (sect=s_first; sect<=s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+ if (prot)
+ return ERR_PROTECTED;
+
+ /*
+ * Disable interrupts which might cause a timeout
+ * here. Remember that our exception vectors are
+ * at address 0 in the flash, and we don't want a
+ * (ticker) exception to happen while the flash
+ * chip is in programming mode.
+ */
+ flag = disable_interrupts();
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
+
+ printf("Erasing sector %2d ... ", sect);
+
+ /* arm simple, non interrupt dependent timer */
+ reset_timer_masked();
+
+ if (info->protect[sect] == 0) { /* not protected */
+ vu_long *addr = (vu_long *)(info->start[sect]);
+
+ *addr = 0x00200020; /* erase setup */
+ *addr = 0x00D000D0; /* erase confirm */
+
+ while ((*addr & 0x00800080) != 0x00800080) {
+ if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
+ *addr = 0x00B000B0; /* suspend erase */
+ *addr = 0x00FF00FF; /* reset to read mode */
+ rc = ERR_TIMOUT;
+ goto outahere;
+ }
+ }
+
+ *addr = 0x00FF00FF; /* reset to read mode */
+ }
+ printf("ok.\n");
+ }
+ if (ctrlc())
+ printf("User Interrupt!\n");
+
+outahere:
+
+ /* allow flash to settle - wait 10 ms */
+ udelay_masked(10000);
+
+ if (flag)
+ enable_interrupts();
+
+ return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash
+ */
+
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+ vu_long *addr = (vu_long *)dest;
+ ulong barf;
+ int rc = ERR_OK;
+ int flag;
+
+ /* Check if Flash is (sufficiently) erased
+ */
+ if ((*addr & data) != data)
+ return ERR_NOT_ERASED;
+
+ /*
+ * Disable interrupts which might cause a timeout
+ * here. Remember that our exception vectors are
+ * at address 0 in the flash, and we don't want a
+ * (ticker) exception to happen while the flash
+ * chip is in programming mode.
+ */
+ flag = disable_interrupts();
+
+ /* clear status register command */
+ *addr = 0x00500050;
+
+ /* program set-up command */
+ *addr = 0x00400040;
+
+ /* latch address/data */
+ *addr = data;
+
+ /* arm simple, non interrupt dependent timer */
+ reset_timer_masked();
+
+ /* read status register command */
+ *addr = 0x00700070;
+
+ /* wait while polling the status register */
+ while((*addr & 0x00800080) != 0x00800080)
+ {
+ if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) {
+ rc = ERR_TIMOUT;
+ /* suspend program command */
+ *addr = 0x00B000B0;
+ goto outahere;
+ }
+
+ if( *addr & 0x003A003A) { /* check for error */
+ barf = *addr;
+ if( barf & 0x003A0000) {
+ barf >>=16;
+ } else {
+ barf &= 0x0000003A;
+ }
+ printf("\nFlash write error %02lx at address %08lx\n",
+ barf, (unsigned long)dest);
+ if(barf & 0x0002) {
+ printf("Block locked, not erased.\n");
+ rc = ERR_NOT_ERASED;
+ goto outahere;
+ }
+ if(barf & 0x0010) {
+ printf("Programming error.\n");
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+ if(barf & 0x0008) {
+ printf("Vpp Low error.\n");
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+ }
+
+
+outahere:
+ /* read array command */
+ *addr = 0x00FF00FF;
+
+ if (flag)
+ enable_interrupts();
+
+ return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash.
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ ulong cp, wp, data;
+ int l;
+ int i, 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 << 24);
+ }
+ for (; i<4 && cnt>0; ++i) {
+ data = (data >> 8) | (*src++ << 24);
+ --cnt;
+ ++cp;
+ }
+ for (; cnt==0 && i<4; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *)cp << 24);
+ }
+
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 4;
+ }
+
+ /*
+ * handle word aligned part
+ */
+ while (cnt >= 4) {
+ data = *((vu_long*)src);
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ src += 4;
+ wp += 4;
+ cnt -= 4;
+ }
+
+ if (cnt == 0) {
+ return ERR_OK;
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ data = 0;
+ for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+ data = (data >> 8) | (*src++ << 24);
+ --cnt;
+ }
+ for (; i<4; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *)cp << 24);
+ }
+
+ return write_word(info, wp, data);
+}
diff --git a/board/impa7/u-boot.lds b/board/impa7/u-boot.lds
new file mode 100644
index 0000000000..084964858b
--- /dev/null
+++ b/board/impa7/u-boot.lds
@@ -0,0 +1,53 @@
+/*
+ * (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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ cpu/arm720t/start.o (.text)
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ armboot_end_data = .;
+
+ . = ALIGN(4);
+ .bss : { *(.bss) }
+
+ armboot_end = .;
+}
diff --git a/board/lart/u-boot.lds b/board/lart/u-boot.lds
new file mode 100644
index 0000000000..f4b0ade273
--- /dev/null
+++ b/board/lart/u-boot.lds
@@ -0,0 +1,53 @@
+/*
+ * (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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ cpu/sa1100/start.o (.text)
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ armboot_end_data = .;
+
+ . = ALIGN(4);
+ .bss : { *(.bss) }
+
+ armboot_end = .;
+}
diff --git a/board/mbx8xx/mbx8xx.c b/board/mbx8xx/mbx8xx.c
new file mode 100644
index 0000000000..9a9bf809ea
--- /dev/null
+++ b/board/mbx8xx/mbx8xx.c
@@ -0,0 +1,379 @@
+/*
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Board specific routines for the MBX
+ *
+ * - initialisation
+ * - interface to VPD data (mac address, clock speeds)
+ * - memory controller
+ * - serial io initialisation
+ * - ethernet io initialisation
+ *
+ * -----------------------------------------------------------------
+ * 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 <commproc.h>
+#include <mpc8xx.h>
+#include "dimm.h"
+#include "vpd.h"
+#include "csr.h"
+
+/* ------------------------------------------------------------------------- */
+
+static const uint sdram_table_40[] = {
+ /* DRAM - single read. (offset 0 in upm RAM)
+ */
+ 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x30AF0C00,
+ 0xF1BF4805, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM - burst read. (offset 8 in upm RAM)
+ */
+ 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x03AF0C08,
+ 0x0CAF0C04, 0x03AF0C08, 0x0CAF0C04, 0x03AF0C08,
+ 0x0CAF0C04, 0x30AF0C00, 0xF3BF4805, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM - single write. (offset 18 in upm RAM)
+ */
+ 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x33FF4804,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM - burst write. (offset 20 in upm RAM)
+ */
+ 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x03FF0C0C,
+ 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C,
+ 0x0CFF0C00, 0x33FF4804, 0xFFFFC005, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* refresh (offset 30 in upm RAM)
+ */
+ 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004,
+ 0x3FFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* exception. (offset 3c in upm RAM)
+ */
+ 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007,
+};
+
+static const uint sdram_table_50[] = {
+ /* DRAM - single read. (offset 0 in upm RAM)
+ */
+ 0xCFAFC004, 0x0FAFC404, 0x0CAF8C04, 0x10AF0C04,
+ 0xF0AF0C00, 0xF3BF4805, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM - burst read. (offset 8 in upm RAM)
+ */
+ 0xCFAFC004, 0X0FAFC404, 0X0CAF8C04, 0X00AF0C04,
+ /* 0X07AF0C08, 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C04, */
+ 0X07AF0C08, 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C08,
+ 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C08, 0X0CAF0C04,
+ /* 0X10AF0C04, 0XF0AFC000, 0XF3FF4805, 0XFFFFC005, */
+ 0X10AF0C04, 0XF0AFC000, 0XF3BF4805, 0XFFFFC005,
+
+ /* DRAM - single write. (offset 18 in upm RAM)
+ */
+ 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x13FF4804,
+ 0xFFFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* DRAM - burst write. (offset 20 in upm RAM)
+ */
+ 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x03FF0C0C,
+ 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C,
+ 0x0CFF0C00, 0x13FF4804, 0xFFFFC004, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* refresh (offset 30 in upm RAM)
+ */
+ 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004,
+ 0x1FFFC004, 0xFFFFC004, 0xFFFFC005, 0xFFFFC005,
+ 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
+
+ /* exception. (offset 3c in upm RAM)
+ */
+ 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static unsigned int get_reffreq(void);
+static unsigned int board_get_cpufreq(void);
+
+void mbx_init (void)
+{
+ volatile immap_t *immr = (immap_t *) CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immr->im_memctl;
+ ulong speed, refclock, plprcr, sccr;
+ ulong br0_32 = memctl->memc_br0 & 0x400;
+
+ /* real-time clock status and control register */
+ immr->im_sitk.sitk_rtcsck = KAPWR_KEY;
+ immr->im_sit.sit_rtcsc = 0x00C3;
+
+ /* SIEL and SIMASK Registers (see MBX PRG 2-3) */
+ immr->im_siu_conf.sc_simask = 0x00000000;
+ immr->im_siu_conf.sc_siel = 0xAAAA0000;
+ immr->im_siu_conf.sc_tesr = 0xFFFFFFFF;
+
+ /*
+ * Prepare access to i2c bus. The MBX offers 3 devices on the i2c bus:
+ * 1. Vital Product Data (contains clock speeds, MAC address etc, see vpd.h)
+ * 2. RAM Specs (see dimm.h)
+ * 2. DIMM Specs (see dimm.h)
+ */
+ vpd_init ();
+
+ /* system clock and reset control register */
+ immr->im_clkrstk.cark_sccrk = KAPWR_KEY;
+ sccr = immr->im_clkrst.car_sccr;
+ sccr &= SCCR_MASK;
+ sccr |= CFG_SCCR;
+ immr->im_clkrst.car_sccr = sccr;
+
+ speed = board_get_cpufreq ();
+ refclock = get_reffreq ();
+
+#if ((CFG_PLPRCR & PLPRCR_MF_MSK) != 0)
+ plprcr = CFG_PLPRCR;
+#else
+ plprcr = immr->im_clkrst.car_plprcr;
+ plprcr &= PLPRCR_MF_MSK; /* isolate MF field */
+ plprcr |= CFG_PLPRCR; /* reset control bits */
+#endif
+
+#ifdef CFG_USE_OSCCLK /* See doc/README.MBX ! */
+ plprcr |= ((speed + refclock / 2) / refclock - 1) << 20;
+#endif
+
+ immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+ immr->im_clkrst.car_plprcr = plprcr;
+
+ /*
+ * preliminary setup of memory controller:
+ * - map Flash, otherwise configuration/status
+ * registers won't be accessible when read
+ * by board_init_f.
+ * - map NVRAM and configuation/status registers.
+ * - map pci registers.
+ * - DON'T map ram yet, this is done in initdram().
+ */
+ switch (speed / 1000000) {
+ case 40:
+ memctl->memc_br0 = 0xFE000000 | br0_32 | 1;
+ memctl->memc_or0 = 0xFF800930;
+ memctl->memc_or4 = CFG_NVRAM_OR | 0x920;
+ memctl->memc_br4 = CFG_NVRAM_BASE | 0x401;
+ break;
+ case 50:
+ memctl->memc_br0 = 0xFE000000 | br0_32 | 1;
+ memctl->memc_or0 = 0xFF800940;
+ memctl->memc_or4 = CFG_NVRAM_OR | 0x930;
+ memctl->memc_br4 = CFG_NVRAM_BASE | 0x401;
+ break;
+ default:
+ hang ();
+ break;
+ }
+#ifdef CONFIG_USE_PCI
+ memctl->memc_or5 = CFG_PCIMEM_OR;
+ memctl->memc_br5 = CFG_PCIMEM_BASE | 0x001;
+ memctl->memc_or6 = CFG_PCIBRIDGE_OR;
+ memctl->memc_br6 = CFG_PCIBRIDGE_BASE | 0x001;
+#endif
+ /*
+ * FIXME: I do not understand why I have to call this to
+ * initialise the control register here before booting from
+ * the PCMCIA card but if I do not the Linux kernel falls
+ * over in a big heap. If you can answer this question I
+ * would like to know about it.
+ */
+ board_ether_init();
+}
+
+void board_serial_init (void)
+{
+ MBX_CSR1 &= ~(CSR1_COM1EN | CSR1_XCVRDIS);
+}
+
+void board_ether_init (void)
+{
+ MBX_CSR1 &= ~(CSR1_EAEN | CSR1_ELEN);
+ MBX_CSR1 |= CSR1_ETEN | CSR1_TPEN | CSR1_FDDIS;
+}
+
+static unsigned int board_get_cpufreq (void)
+{
+#ifndef CONFIG_8xx_GCLK_FREQ
+ vpd_packet_t *packet;
+
+ packet = vpd_find_packet (VPD_PID_ICS);
+ return *((ulong *) packet->data);
+#else
+ return((unsigned int)CONFIG_8xx_GCLK_FREQ );
+#endif /* CONFIG_8xx_GCLK_FREQ */
+}
+
+static unsigned int get_reffreq (void)
+{
+ vpd_packet_t *packet;
+
+ packet = vpd_find_packet (VPD_PID_RCS);
+ return *((ulong *) packet->data);
+}
+
+void board_get_enetaddr (uchar * addr)
+{
+ int i;
+ vpd_packet_t *packet;
+
+ packet = vpd_find_packet (VPD_PID_EA);
+ for (i = 0; i < 6; i++)
+ addr[i] = packet->data[i];
+}
+
+/*
+ * Check Board Identity:
+ */
+
+int checkboard (void)
+{
+ vpd_packet_t *packet;
+ int i;
+ const char *const fmt =
+ "\n *** Warning: Low Battery Status - %s Battery ***";
+
+ puts ("Board: ");
+
+ packet = vpd_find_packet (VPD_PID_PID);
+ for (i = 0; i < packet->size; i++) {
+ serial_putc (packet->data[i]);
+ }
+ packet = vpd_find_packet (VPD_PID_MT);
+ for (i = 0; i < packet->size; i++) {
+ serial_putc (packet->data[i]);
+ }
+ serial_putc ('(');
+ packet = vpd_find_packet (VPD_PID_FAN);
+ for (i = 0; i < packet->size; i++) {
+ serial_putc (packet->data[i]);
+ }
+ serial_putc (')');
+
+ if (!(MBX_CSR2 & SR2_BATGD))
+ printf (fmt, "On-Board");
+ if (!(MBX_CSR2 & SR2_NVBATGD))
+ printf (fmt, "NVRAM");
+
+ serial_putc ('\n');
+
+ return (0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static ulong get_ramsize (dimm_t * dimm)
+{
+ ulong size = 0;
+
+ if (dimm->fmt == 1 || dimm->fmt == 2 || dimm->fmt == 3
+ || dimm->fmt == 4) {
+ size = (1 << (dimm->n_row + dimm->n_col)) * dimm->n_banks *
+ ((dimm->data_w_hi << 8 | dimm->data_w_lo) / 8);
+ }
+
+ return size;
+}
+
+long int initdram (int board_type)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ unsigned long ram_sz = 0;
+ unsigned long dimm_sz = 0;
+ dimm_t vpd_dimm, vpd_dram;
+ unsigned int speed = board_get_cpufreq () / 1000000;
+
+ if (vpd_read (0xa2, (uchar *) & vpd_dimm, sizeof (vpd_dimm), 0) > 0) {
+ dimm_sz = get_ramsize (&vpd_dimm);
+ }
+ if (vpd_read (0xa6, (uchar *) & vpd_dram, sizeof (vpd_dram), 0) > 0) {
+ ram_sz = get_ramsize (&vpd_dram);
+ }
+
+ /*
+ * Only initialize memory controller when running from FLASH.
+ * When running from RAM, don't touch it.
+ */
+ if ((ulong) initdram & 0xff000000) {
+ ulong dimm_bank;
+ ulong br0_32 = memctl->memc_br0 & 0x400;
+
+ switch (speed) {
+ case 40:
+ upmconfig (UPMA, (uint *) sdram_table_40,
+ sizeof (sdram_table_40) / sizeof (uint));
+ memctl->memc_mptpr = 0x0200;
+ memctl->memc_mamr = dimm_sz ? 0x06801000 : 0x13801000;
+ memctl->memc_or7 = 0xff800930;
+ memctl->memc_br7 = 0xfc000000 | (br0_32 ^ br0_32) | 1;
+ break;
+ case 50:
+ upmconfig (UPMA, (uint *) sdram_table_50,
+ sizeof (sdram_table_50) / sizeof (uint));
+ memctl->memc_mptpr = 0x0200;
+ memctl->memc_mamr = dimm_sz ? 0x08801000 : 0x1880100;
+ memctl->memc_or7 = 0xff800940;
+ memctl->memc_br7 = 0xfc000000 | (br0_32 ^ br0_32) | 1;
+ break;
+ default:
+ hang ();
+ break;
+ }
+
+ /* now map ram and dimm, largest one first */
+ dimm_bank = dimm_sz / 2;
+ if (!dimm_sz) {
+ memctl->memc_or1 = ~(ram_sz - 1) | 0x400;
+ memctl->memc_br1 = CFG_SDRAM_BASE | 0x81;
+ memctl->memc_br2 = 0;
+ memctl->memc_br3 = 0;
+ } else if (ram_sz > dimm_bank) {
+ memctl->memc_or1 = ~(ram_sz - 1) | 0x400;
+ memctl->memc_br1 = CFG_SDRAM_BASE | 0x81;
+ memctl->memc_or2 = ~(dimm_bank - 1) | 0x400;
+ memctl->memc_br2 = (CFG_SDRAM_BASE + ram_sz) | 0x81;
+ memctl->memc_or3 = ~(dimm_bank - 1) | 0x400;
+ memctl->memc_br3 = (CFG_SDRAM_BASE + ram_sz + dimm_bank) \
+ | 0x81;
+ } else {
+ memctl->memc_or2 = ~(dimm_bank - 1) | 0x400;
+ memctl->memc_br2 = CFG_SDRAM_BASE | 0x81;
+ memctl->memc_or3 = ~(dimm_bank - 1) | 0x400;
+ memctl->memc_br3 = (CFG_SDRAM_BASE + dimm_bank) | 0x81;
+ memctl->memc_or1 = ~(ram_sz - 1) | 0x400;
+ memctl->memc_br1 = (CFG_SDRAM_BASE + dimm_sz) | 0x81;
+ }
+ }
+
+ return ram_sz + dimm_sz;
+}
diff --git a/board/ml2/serial.c b/board/ml2/serial.c
new file mode 100644
index 0000000000..dc9a8ea537
--- /dev/null
+++ b/board/ml2/serial.c
@@ -0,0 +1,131 @@
+/*
+ * (C) Copyright 2002
+ * Peter De Schrijver (p2@mind.be), Mind Linux Solutions, NV.
+ *
+ * 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 <asm/u-boot.h>
+#include <asm/processor.h>
+#include <common.h>
+#include <command.h>
+#include <configs/ML2.h>
+
+#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2)
+#include <ns16550.h>
+#endif
+
+#if 0
+#include "serial.h"
+#endif
+
+#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2)
+const NS16550_t COM_PORTS[] = { (NS16550_t) CFG_NS16550_COM1,
+ (NS16550_t) CFG_NS16550_COM2 };
+#endif
+
+int
+serial_init (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate;
+
+#ifdef CFG_INIT_CHAN1
+ (void)NS16550_init(COM_PORTS[0], clock_divisor);
+#endif
+#ifdef CFG_INIT_CHAN2
+ (void)NS16550_init(COM_PORTS[1], clock_divisor);
+#endif
+ return 0;
+
+}
+
+void
+serial_putc(const char c)
+{
+ if (c == '\n')
+ NS16550_putc(COM_PORTS[CFG_DUART_CHAN], '\r');
+
+ NS16550_putc(COM_PORTS[CFG_DUART_CHAN], c);
+}
+
+int
+serial_getc(void)
+{
+ return NS16550_getc(COM_PORTS[CFG_DUART_CHAN]);
+}
+
+int
+serial_tstc(void)
+{
+ return NS16550_tstc(COM_PORTS[CFG_DUART_CHAN]);
+}
+
+void
+serial_setbrg (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate;
+
+#ifdef CFG_INIT_CHAN1
+ NS16550_reinit(COM_PORTS[0], clock_divisor);
+#endif
+#ifdef CFG_INIT_CHAN2
+ NS16550_reinit(COM_PORTS[1], clock_divisor);
+#endif
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+void
+kgdb_serial_init(void)
+{
+}
+
+void
+putDebugChar (int c)
+{
+ serial_putc (c);
+}
+
+void
+putDebugStr (const char *str)
+{
+ serial_puts (str);
+}
+
+int
+getDebugChar (void)
+{
+ return serial_getc();
+}
+
+void
+kgdb_interruptible (int yes)
+{
+ return;
+}
+#endif /* CFG_CMD_KGDB */
diff --git a/board/mousse/pci.c b/board/mousse/pci.c
new file mode 100644
index 0000000000..89ca235d10
--- /dev/null
+++ b/board/mousse/pci.c
@@ -0,0 +1,283 @@
+/*
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2001
+ * James Dougherty (jfd@cs.stanford.edu)
+ *
+ * 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
+ */
+
+/*
+ * PCI Configuration space access support for MPC824x/MPC107 PCI Bridge
+ */
+#include <common.h>
+#include <mpc824x.h>
+#include <pci.h>
+
+#include "mousse.h"
+
+/*
+ * Promise ATA/66 support.
+ */
+#define XFER_PIO_4 0x0C /* 0000|1100 */
+#define XFER_PIO_3 0x0B /* 0000|1011 */
+#define XFER_PIO_2 0x0A /* 0000|1010 */
+#define XFER_PIO_1 0x09 /* 0000|1001 */
+#define XFER_PIO_0 0x08 /* 0000|1000 */
+#define XFER_PIO_SLOW 0x00 /* 0000|0000 */
+
+/* Promise Regs */
+#define REG_A 0x01
+#define REG_B 0x02
+#define REG_C 0x04
+#define REG_D 0x08
+
+void
+pdc202xx_decode_registers (unsigned char registers, unsigned char value)
+{
+ unsigned char bit = 0, bit1 = 0, bit2 = 0;
+ switch(registers) {
+ case REG_A:
+ bit2 = 0;
+ printf(" A Register ");
+ if (value & 0x80) printf("SYNC_IN ");
+ if (value & 0x40) printf("ERRDY_EN ");
+ if (value & 0x20) printf("IORDY_EN ");
+ if (value & 0x10) printf("PREFETCH_EN ");
+ if (value & 0x08) { printf("PA3 ");bit2 |= 0x08; }
+ if (value & 0x04) { printf("PA2 ");bit2 |= 0x04; }
+ if (value & 0x02) { printf("PA1 ");bit2 |= 0x02; }
+ if (value & 0x01) { printf("PA0 ");bit2 |= 0x01; }
+ printf("PIO(A) = %d ", bit2);
+ break;
+ case REG_B:
+ bit1 = 0;bit2 = 0;
+ printf(" B Register ");
+ if (value & 0x80) { printf("MB2 ");bit1 |= 0x80; }
+ if (value & 0x40) { printf("MB1 ");bit1 |= 0x40; }
+ if (value & 0x20) { printf("MB0 ");bit1 |= 0x20; }
+ printf("DMA(B) = %d ", bit1 >> 5);
+ if (value & 0x10) printf("PIO_FORCED/PB4 ");
+ if (value & 0x08) { printf("PB3 ");bit2 |= 0x08; }
+ if (value & 0x04) { printf("PB2 ");bit2 |= 0x04; }
+ if (value & 0x02) { printf("PB1 ");bit2 |= 0x02; }
+ if (value & 0x01) { printf("PB0 ");bit2 |= 0x01; }
+ printf("PIO(B) = %d ", bit2);
+ break;
+ case REG_C:
+ bit2 = 0;
+ printf(" C Register ");
+ if (value & 0x80) printf("DMARQp ");
+ if (value & 0x40) printf("IORDYp ");
+ if (value & 0x20) printf("DMAR_EN ");
+ if (value & 0x10) printf("DMAW_EN ");
+
+ if (value & 0x08) { printf("MC3 ");bit2 |= 0x08; }
+ if (value & 0x04) { printf("MC2 ");bit2 |= 0x04; }
+ if (value & 0x02) { printf("MC1 ");bit2 |= 0x02; }
+ if (value & 0x01) { printf("MC0 ");bit2 |= 0x01; }
+ printf("DMA(C) = %d ", bit2);
+ break;
+ case REG_D:
+ printf(" D Register ");
+ break;
+ default:
+ return;
+ }
+ printf("\n %s ", (registers & REG_D) ? "DP" :
+ (registers & REG_C) ? "CP" :
+ (registers & REG_B) ? "BP" :
+ (registers & REG_A) ? "AP" : "ERROR");
+ for (bit=128;bit>0;bit/=2)
+ printf("%s", (value & bit) ? "1" : "0");
+ printf("\n");
+}
+
+/*
+ * Promise ATA/66 Support: configure Promise ATA66 card in specified mode.
+ */
+int
+pdc202xx_tune_chipset (pci_dev_t dev, int drive, unsigned char speed)
+{
+ unsigned short drive_conf;
+ int err = 0;
+ unsigned char drive_pci, AP, BP, CP, DP;
+ unsigned char TA = 0, TB = 0;
+
+ switch (drive) {
+ case 0: drive_pci = 0x60; break;
+ case 1: drive_pci = 0x64; break;
+ case 2: drive_pci = 0x68; break;
+ case 3: drive_pci = 0x6c; break;
+ default: return -1;
+ }
+
+ pci_read_config_word(dev, drive_pci, &drive_conf);
+ pci_read_config_byte(dev, (drive_pci), &AP);
+ pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+ pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+ pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
+
+ if ((AP & 0x0F) || (BP & 0x07)) {
+ /* clear PIO modes of lower 8421 bits of A Register */
+ pci_write_config_byte(dev, (drive_pci), AP & ~0x0F);
+ pci_read_config_byte(dev, (drive_pci), &AP);
+
+ /* clear PIO modes of lower 421 bits of B Register */
+ pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07);
+ pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+
+ pci_read_config_byte(dev, (drive_pci), &AP);
+ pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+ }
+
+ pci_read_config_byte(dev, (drive_pci), &AP);
+ pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+ pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+
+ switch(speed) {
+ case XFER_PIO_4: TA = 0x01; TB = 0x04; break;
+ case XFER_PIO_3: TA = 0x02; TB = 0x06; break;
+ case XFER_PIO_2: TA = 0x03; TB = 0x08; break;
+ case XFER_PIO_1: TA = 0x05; TB = 0x0C; break;
+ case XFER_PIO_0:
+ default: TA = 0x09; TB = 0x13; break;
+ }
+
+ pci_write_config_byte(dev, (drive_pci), AP|TA);
+ pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
+
+ pci_read_config_byte(dev, (drive_pci), &AP);
+ pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+ pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+ pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
+
+
+#ifdef PDC202XX_DEBUG
+ pdc202xx_decode_registers(REG_A, AP);
+ pdc202xx_decode_registers(REG_B, BP);
+ pdc202xx_decode_registers(REG_C, CP);
+ pdc202xx_decode_registers(REG_D, DP);
+#endif
+ return err;
+}
+/*
+ * Show/Init PCI devices on the specified bus number.
+ */
+
+void pci_mousse_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
+{
+ unsigned int line;
+
+ switch(PCI_DEV(dev)) {
+ case 0x0d:
+ line = 0x00000101;
+ break;
+
+ case 0x0e:
+ default:
+ line = 0x00000303;
+ break;
+ }
+
+ pci_write_config_dword(dev, PCI_INTERRUPT_LINE, line);
+}
+
+void pci_mousse_setup_pdc202xx(struct pci_controller *hose, pci_dev_t dev,
+ struct pci_config_table *_)
+{
+ unsigned short vendorId;
+ unsigned int mbar0, cmd;
+ int bar, a;
+
+ pci_read_config_word(dev, PCI_VENDOR_ID, &vendorId);
+
+ if(vendorId == PCI_VENDOR_ID_PROMISE || vendorId == PCI_VENDOR_ID_CMD){
+ /* PDC 202xx card is handled differently, it is a bootable
+ * device and needs all 5 MBAR's configured
+ */
+ for(bar = 0; bar < 5; bar++){
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, &mbar0);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, ~0);
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, &mbar0);
+#ifdef DEBUG
+ printf(" ATA_bar[%d] = %dbytes\n", bar,
+ ~(mbar0 & PCI_BASE_ADDRESS_MEM_MASK) + 1);
+#endif
+ }
+
+ /* Program all BAR's */
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, PROMISE_MBAR0);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, PROMISE_MBAR1);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, PROMISE_MBAR2);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, PROMISE_MBAR3);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_4, PROMISE_MBAR4);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_5, PROMISE_MBAR5);
+
+ for(bar = 0; bar < 5; bar++){
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, &mbar0);
+#ifdef DEBUG
+ printf(" ATA_bar[%d]@0x%x\n", bar, mbar0);
+#endif
+ }
+
+ /* Enable ROM Expansion base */
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, PROMISE_MBAR5|1);
+
+ /* Io enable, Memory enable, master enable */
+ pci_read_config_dword(dev, PCI_COMMAND, &cmd);
+ cmd &= ~0xffff0000;
+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+ pci_write_config_dword(dev, PCI_COMMAND, cmd);
+
+ /* Breath some life into the controller */
+ for( a = 0; a < 4; a++)
+ pdc202xx_tune_chipset(dev, a, XFER_PIO_0);
+ }
+}
+
+static struct pci_config_table pci_sandpoint_config_table[] = {
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 0x0e, 0x00,
+ pci_mousse_setup_pdc202xx },
+#ifndef CONFIG_PCI_PNP
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 0x0d, 0x00,
+ pci_cfgfunc_config_device, {PCI_ENET_IOADDR,
+ PCI_ENET_MEMADDR,
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER}},
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ pci_cfgfunc_config_device, {PCI_SLOT_IOADDR,
+ PCI_SLOT_MEMADDR,
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER}},
+#endif
+ { }
+};
+
+struct pci_controller hose = {
+ config_table: pci_sandpoint_config_table,
+ fixup_irq: pci_mousse_fixup_irq,
+};
+
+void pci_init(void)
+{
+ pci_mpc824x_init(&hose);
+}
diff --git a/board/mpl/common/common_util.c b/board/mpl/common/common_util.c
new file mode 100644
index 0000000000..60c49af151
--- /dev/null
+++ b/board/mpl/common/common_util.c
@@ -0,0 +1,606 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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 <command.h>
+#include <video_fb.h>
+#include "common_util.h"
+#include <asm/processor.h>
+#include <i2c.h>
+#include <devices.h>
+#include <pci.h>
+
+extern int gunzip (void *, int, unsigned char *, int *);
+extern int mem_test(unsigned long start, unsigned long ramsize, int quiet);
+
+#define I2C_BACKUP_ADDR 0x7C00 /* 0x200 bytes for backup */
+#define IMAGE_SIZE 0x80000
+
+extern flash_info_t flash_info[]; /* info for FLASH chips */
+
+image_header_t header;
+
+
+
+int mpl_prg(unsigned long src,unsigned long size)
+{
+ unsigned long start;
+ flash_info_t *info;
+ int i,rc;
+ unsigned long *magic = (unsigned long *)src;
+
+ info = &flash_info[0];
+ start = 0 - size;
+ for(i=info->sector_count-1;i>0;i--)
+ {
+ info->protect[i] = 0; /* unprotect this sector */
+ if(start>=info->start[i])
+ break;
+ }
+ /* set-up flash location */
+ /* now erase flash */
+ if(magic[0]!=IH_MAGIC) {
+ printf("Bad Magic number\n");
+ return -1;
+ }
+ printf("Erasing at %lx (sector %d) (start %lx)\n",
+ start,i,info->start[i]);
+ flash_erase (info, i, info->sector_count-1);
+ printf("flash erased, programming from 0x%lx 0x%lx Bytes\n",src,size);
+ if ((rc = flash_write ((uchar *)src, start, size)) != 0) {
+ puts ("ERROR ");
+ flash_perror (rc);
+ return (1);
+ }
+ puts ("OK programming done\n");
+ return 0;
+}
+
+
+int mpl_prg_image(unsigned long ld_addr)
+{
+ unsigned long data,len,checksum;
+ image_header_t *hdr=&header;
+ /* Copy header so we can blank CRC field for re-calculation */
+ memcpy (&header, (char *)ld_addr, sizeof(image_header_t));
+ if (hdr->ih_magic != IH_MAGIC) {
+ printf ("Bad Magic Number\n");
+ return 1;
+ }
+ print_image_hdr(hdr);
+ if (hdr->ih_os != IH_OS_U_BOOT) {
+ printf ("No U-Boot Image\n");
+ return 1;
+ }
+ if (hdr->ih_type != IH_TYPE_FIRMWARE) {
+ printf ("No Firmware Image\n");
+ return 1;
+ }
+ data = (ulong)&header;
+ len = sizeof(image_header_t);
+ checksum = hdr->ih_hcrc;
+ hdr->ih_hcrc = 0;
+ if (crc32 (0, (char *)data, len) != checksum) {
+ printf ("Bad Header Checksum\n");
+ return 1;
+ }
+ data = ld_addr + sizeof(image_header_t);
+ len = hdr->ih_size;
+ printf ("Verifying Checksum ... ");
+ if (crc32 (0, (char *)data, len) != hdr->ih_dcrc) {
+ printf ("Bad Data CRC\n");
+ return 1;
+ }
+ switch (hdr->ih_comp) {
+ case IH_COMP_NONE:
+ break;
+ case IH_COMP_GZIP:
+ printf (" Uncompressing ... ");
+ if (gunzip ((void *)(data+0x100000), 0x400000,
+ (uchar *)data, (int *)&len) != 0) {
+ printf ("GUNZIP ERROR\n");
+ return 1;
+ }
+ data+=0x100000;
+ break;
+ default:
+ printf (" Unimplemented compression type %d\n", hdr->ih_comp);
+ return 1;
+ }
+
+ printf (" OK\n");
+ return(mpl_prg(data,len));
+}
+
+
+void get_backup_values(backup_t *buf)
+{
+ i2c_read(CFG_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)buf,sizeof(backup_t));
+}
+
+void set_backup_values(int overwrite)
+{
+ backup_t back;
+ int i;
+
+ get_backup_values(&back);
+ if(!overwrite) {
+ if(strncmp(back.signature,"MPL\0",4)==0) {
+ printf("Not possible to write Backup\n");
+ return;
+ }
+ }
+ memcpy(back.signature,"MPL\0",4);
+ i=getenv_r("serial#",back.serial_name,16);
+ if(i==0) {
+ printf("Not possible to write Backup\n");
+ return;
+ }
+ back.serial_name[16]=0;
+ i=getenv_r("ethaddr",back.eth_addr,20);
+ if(i==0) {
+ printf("Not possible to write Backup\n");
+ return;
+ }
+ back.eth_addr[20]=0;
+ i2c_write(CFG_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t));
+}
+
+void clear_env_values(void)
+{
+ backup_t back;
+ unsigned char env_crc[4];
+
+ memset(&back,0xff,sizeof(backup_t));
+ memset(env_crc,0x00,4);
+ i2c_write(CFG_DEF_EEPROM_ADDR,I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t));
+ i2c_write(CFG_DEF_EEPROM_ADDR,CFG_ENV_OFFSET,2,(void *)env_crc,4);
+}
+
+/*
+ * check crc of "older" environment
+ */
+int check_env_old_size(ulong oldsize)
+{
+ ulong crc, len, new;
+ unsigned off;
+ uchar buf[64];
+
+ /* read old CRC */
+ eeprom_read (CFG_DEF_EEPROM_ADDR,
+ CFG_ENV_OFFSET,
+ (uchar *)&crc, sizeof(ulong));
+
+ new = 0;
+ len = oldsize;
+ off = sizeof(long);
+ len = oldsize-off;
+ while (len > 0) {
+ int n = (len > sizeof(buf)) ? sizeof(buf) : len;
+
+ eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, buf, n);
+ new = crc32 (new, buf, n);
+ len -= n;
+ off += n;
+ }
+
+ return (crc == new);
+}
+
+static ulong oldsizes[] = {
+ 0x200,
+ 0x800,
+ 0
+};
+
+void copy_old_env(ulong size)
+{
+ uchar name_buf[64];
+ uchar value_buf[0x800];
+ uchar c;
+ ulong len;
+ unsigned off;
+ uchar *name, *value;
+
+ name=&name_buf[0];
+ value=&value_buf[0];
+ len=size;
+ off = sizeof(long);
+ while (len > off) {
+ eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, &c, 1);
+ if(c != '=') {
+ *name++=c;
+ off++;
+ }
+ else {
+ *name++='\0';
+ off++;
+ do {
+ eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, &c, 1);
+ *value++=c;
+ off++;
+ if(c == '\0')
+ break;
+ } while(len > off);
+ name=&name_buf[0];
+ value=&value_buf[0];
+ if(strncmp(name,"baudrate",8)!=0) {
+ setenv(name,value);
+ }
+
+ }
+ }
+}
+
+
+void check_env(void)
+{
+ unsigned char *s;
+ int i=0;
+ char buf[32];
+ backup_t back;
+
+ s=getenv("serial#");
+ if(!s) {
+ while(oldsizes[i]) {
+ if(check_env_old_size(oldsizes[i]))
+ break;
+ i++;
+ }
+ if(!oldsizes[i]) {
+ /* no old environment has been found */
+ get_backup_values (&back);
+ if (strncmp (back.signature, "MPL\0", 4) == 0) {
+ sprintf (buf, "%s", back.serial_name);
+ setenv ("serial#", buf);
+ sprintf (buf, "%s", back.eth_addr);
+ setenv ("ethaddr", buf);
+ printf ("INFO: serial# and ethaddr recovered, use saveenv\n");
+ return;
+ }
+ }
+ else {
+ copy_old_env(oldsizes[i]);
+ printf ("INFO: old environment ajusted, use saveenv\n");
+ }
+ }
+ else {
+ /* check if back up is set */
+ get_backup_values(&back);
+ if(strncmp(back.signature,"MPL\0",4)!=0) {
+ set_backup_values(0);
+ }
+ }
+}
+
+
+
+extern device_t *stdio_devices[];
+extern char *stdio_names[];
+
+void show_stdio_dev(void)
+{
+ /* Print informations */
+ printf ("In: ");
+ if (stdio_devices[stdin] == NULL) {
+ printf ("No input devices available!\n");
+ } else {
+ printf ("%s\n", stdio_devices[stdin]->name);
+ }
+
+ printf ("Out: ");
+ if (stdio_devices[stdout] == NULL) {
+ printf ("No output devices available!\n");
+ } else {
+ printf ("%s\n", stdio_devices[stdout]->name);
+ }
+
+ printf ("Err: ");
+ if (stdio_devices[stderr] == NULL) {
+ printf ("No error devices available!\n");
+ } else {
+ printf ("%s\n", stdio_devices[stderr]->name);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+ /* switches the cs0 and the cs1 to the locations.
+ When boot is TRUE, the the mapping is switched
+ to the boot configuration, If it is FALSE, the
+ flash will be switched in the boot area */
+
+#undef SW_CS_DBG
+#ifdef SW_CS_DBG
+#define SW_CS_PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define SW_CS_PRINTF(fmt,args...)
+#endif
+
+
+int switch_cs(unsigned char boot)
+{
+ unsigned long pbcr;
+ mtdcr(ebccfga, pb0cr); /* get cs0 config reg */
+ pbcr = mfdcr(ebccfgd);
+ if((pbcr&0x00002000)==0) {
+ /* we need only to switch if boot from MPS */
+ /*printf(" MPS boot mode detected. ");*/
+ /* printf("cs0 cfg: %lx\n",pbcr); */
+ if(boot) {
+ /* switch to boot configuration */
+ /* this is a 8bit boot, switch cs0 to flash location */
+ SW_CS_PRINTF("switch to boot mode (MPS on High address\n");
+ pbcr&=0x000FFFFF; /*mask base address of the cs0 */
+ pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000);
+ mtdcr(ebccfga, pb0cr);
+ mtdcr(ebccfgd, pbcr);
+ SW_CS_PRINTF(" new cs0 cfg: %lx\n",pbcr);
+ mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */
+ pbcr = mfdcr(ebccfgd);
+ SW_CS_PRINTF(" old cs1 cfg: %lx\n",pbcr);
+ pbcr&=0x000FFFFF; /*mask base address of the cs1 */
+ pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000);
+ mtdcr(ebccfga, pb1cr);
+ mtdcr(ebccfgd, pbcr);
+ SW_CS_PRINTF(" new cs1 cfg: %lx, MPS is on High Address\n",pbcr);
+ }
+ else
+ {
+ /* map flash to boot area, */
+ SW_CS_PRINTF("map Flash to boot area\n");
+ pbcr&=0x000FFFFF; /*mask base address of the cs0 */
+ pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000);
+ mtdcr(ebccfga, pb0cr);
+ mtdcr(ebccfgd, pbcr);
+ SW_CS_PRINTF(" new cs0 cfg: %lx\n",pbcr);
+ mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */
+ pbcr = mfdcr(ebccfgd);
+ SW_CS_PRINTF(" cs1 cfg: %lx\n",pbcr);
+ pbcr&=0x000FFFFF; /*mask base address of the cs1 */
+ pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000);
+ mtdcr(ebccfga, pb1cr);
+ mtdcr(ebccfgd, pbcr);
+ SW_CS_PRINTF(" new cs1 cfg: %lx Flash is on High Address\n",pbcr);
+ }
+ return 1;
+ }
+ else {
+ SW_CS_PRINTF("Normal boot, no switching necessary\n");
+ return 0;
+ }
+}
+
+
+int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ ulong size,src,ld_addr;
+ int result;
+ backup_t back;
+ char sw;
+ src = MULTI_PURPOSE_SOCKET_ADDR;
+ size = IMAGE_SIZE;
+
+ if (strcmp(argv[1], "flash") == 0)
+ {
+ sw = switch_cs(0); /* Switch flash to normal location */
+#if (CONFIG_COMMANDS & CFG_CMD_FDC)
+ if (strcmp(argv[2], "floppy") == 0) {
+ char *local_args[3];
+ extern int do_fdcboot (cmd_tbl_t *, int, int, char *[]);
+ printf ("\nupdating bootloader image from floppy\n");
+ local_args[0] = argv[0];
+ if(argc==4) {
+ local_args[1] = argv[3];
+ local_args[2] = NULL;
+ ld_addr=simple_strtoul(argv[3], NULL, 16);
+ result=do_fdcboot(cmdtp, 0, 2, local_args);
+ }
+ else {
+ local_args[1] = NULL;
+ ld_addr=CFG_LOAD_ADDR;
+ result=do_fdcboot(cmdtp, 0, 1, local_args);
+ }
+ result=mpl_prg_image(ld_addr);
+ switch_cs(sw); /* Switch flash back */
+ return result;
+ }
+#endif /* (CONFIG_COMMANDS & CFG_CMD_FDC) */
+ if (strcmp(argv[2], "mem") == 0) {
+ if(argc==4) {
+ ld_addr=simple_strtoul(argv[3], NULL, 16);
+ }
+ else {
+ ld_addr=load_addr;
+ }
+ printf ("\nupdating bootloader image from memory at %lX\n",ld_addr);
+ result=mpl_prg_image(ld_addr);
+ switch_cs(sw); /* Switch flash back */
+ return result;
+ }
+ if (strcmp(argv[2], "mps") == 0) {
+ printf ("\nupdating bootloader image from MSP\n");
+ result=mpl_prg(src,size);
+ switch_cs(sw); /* Switch flash back */
+ return result;
+ }
+ switch_cs(sw); /* Switch flash back */
+
+ }
+ if (strcmp(argv[1], "mem") == 0)
+ {
+ result=0;
+ if(argc==3)
+ {
+ result = (int)simple_strtol(argv[2], NULL, 16);
+ }
+ src=(unsigned long)&result;
+ src-=CFG_MEMTEST_START;
+ src-=(100*1024); /* - 100k */
+ src&=0xfff00000;
+ size=0;
+ do {
+ size++;
+ printf("\n\nPass %ld\n",size);
+ mem_test(CFG_MEMTEST_START,src,1);
+ if(ctrlc())
+ break;
+ if(result>0)
+ result--;
+
+ }while(result);
+ return 0;
+ }
+ if (strcmp(argv[1], "clearenvvalues") == 0)
+ {
+ if (strcmp(argv[2], "yes") == 0)
+ {
+ clear_env_values();
+ return 0;
+ }
+ }
+ if (strcmp(argv[1], "getback") == 0) {
+ get_backup_values(&back);
+ back.signature[3]=0;
+ back.serial_name[16]=0;
+ back.eth_addr[20]=0;
+ printf("GetBackUp: signature: %s\n",back.signature);
+ printf(" serial#: %s\n",back.serial_name);
+ printf(" ethaddr: %s\n",back.eth_addr);
+ return 0;
+ }
+ if (strcmp(argv[1], "setback") == 0) {
+ set_backup_values(1);
+ return 0;
+ }
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+}
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_DOC)
+extern void doc_probe(ulong physadr);
+void doc_init (void)
+{
+ doc_probe(MULTI_PURPOSE_SOCKET_ADDR);
+}
+#endif
+
+
+#ifdef CONFIG_VIDEO
+/******************************************************
+ * Routines to display the Board information
+ * to the screen (since the VGA will be initialized as last,
+ * we must resend the infos)
+ */
+
+#ifdef CONFIG_CONSOLE_EXTRA_INFO
+extern GraphicDevice ctfb;
+
+void video_get_info_str (int line_number, char *info)
+{
+ /* init video info strings for graphic console */
+ DECLARE_GLOBAL_DATA_PTR;
+ PPC405_SYS_INFO sys_info;
+ char rev;
+ int i;
+ unsigned long pvr;
+ char buf[64];
+ char tmp[16];
+ unsigned char *s, *e, bc, sw;
+ switch (line_number)
+ {
+ case 2:
+ /* CPU and board infos */
+ pvr=get_pvr();
+ get_sys_info (&sys_info);
+ switch (pvr) {
+ case PVR_405GP_RB: rev='B'; break;
+ case PVR_405GP_RC: rev='C'; break;
+ case PVR_405GP_RD: rev='D'; break;
+ case PVR_405GP_RE: rev='E'; break;
+ default: rev='?'; break;
+ }
+ /* Board info */
+ i=0;
+ s=getenv ("serial#");
+#ifdef CONFIG_PIP405
+ if (!s || strncmp (s, "PIP405", 6)) {
+ sprintf(buf,"### No HW ID - assuming PIP405");
+ }
+#endif
+#ifdef CONFIG_MIP405
+ if (!s || strncmp (s, "MIP405", 6)) {
+ sprintf(buf,"### No HW ID - assuming MIP405");
+ }
+#endif
+ else {
+ for (e = s; *e; ++e) {
+ if (*e == ' ')
+ break;
+ }
+ for (; s < e; ++s) {
+ if (*s == '_') {
+ ++s;
+ break;
+ }
+ buf[i++]=*s;
+ }
+ sprintf(&buf[i]," SN ");
+ i+=4;
+ for (; s < e; ++s) {
+ buf[i++]=*s;
+ }
+ buf[i++]=0;
+ }
+ sprintf (info," %s PPC405GP %c %s MHz (%lu/%lu/%lu MHz)",
+ buf,rev,
+ strmhz (tmp, gd->cpu_clk), sys_info.freqPLB / 1000000,
+ sys_info.freqPLB / sys_info.pllOpbDiv / 1000000,
+ sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000);
+ return;
+ case 3:
+ /* Memory Info */
+ sw = switch_cs (0);
+ switch_cs (sw);
+ bc = in8 (CONFIG_PORT_ADDR);
+ sprintf(info, " %luMB RAM, %luMB Flash Cfg 0x%02X %s %s",
+ gd->bd->bi_memsize / 0x100000,
+ gd->bd->bi_flashsize / 0x100000,
+ bc,
+ sw ? "MPS boot" : "Flash boot",
+ ctfb.modeIdent);
+ return;
+ case 1:
+ sprintf (buf, "%s",CONFIG_IDENT_STRING);
+ sprintf (info, " %s", &buf[1]);
+ return;
+ }
+ /* no more info lines */
+ *info = 0;
+ return;
+}
+#endif /* CONFIG_CONSOLE_EXTRA_INFO */
+
+#endif /* CONFIG_VIDEO */
diff --git a/board/mpl/common/pci.c b/board/mpl/common/pci.c
new file mode 100644
index 0000000000..d1965f95f6
--- /dev/null
+++ b/board/mpl/common/pci.c
@@ -0,0 +1,102 @@
+/*-----------------------------------------------------------------------------+
+|
+| This source code has been made available to you by IBM on an AS-IS
+| basis. Anyone receiving this source is licensed under IBM
+| copyrights to use it in any way he or she deems fit, including
+| copying it, modifying it, compiling it, and redistributing it either
+| with or without modifications. No license under IBM patents or
+| patent applications is to be implied by the copyright license.
+|
+| Any user of this software should understand that IBM cannot provide
+| technical support for this software and will not be responsible for
+| any consequences resulting from the use of this software.
+|
+| Any person who transfers this source code or any derivative work
+| must include the IBM copyright notice, this paragraph, and the
+| preceding two paragraphs in the transferred software.
+|
+| COPYRIGHT I B M CORPORATION 1995
+| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
++-----------------------------------------------------------------------------*/
+/*
+ * Adapted for PIP405 03.07.01
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * TODO: Clean-up
+ */
+
+#include <common.h>
+#include <pci.h>
+#include "isa.h"
+
+#ifdef CONFIG_405GP
+#ifdef CONFIG_PCI
+
+#undef DEBUG
+
+#include "piix4_pci.h"
+#include "pci_parts.h"
+
+void pci_pip405_write_regs(struct pci_controller *hose, pci_dev_t dev,
+ struct pci_config_table *entry)
+{
+ struct pci_pip405_config_entry *table;
+ int i;
+
+ table = (struct pci_pip405_config_entry*) entry->priv[0];
+
+ for (i=0; table[i].width; i++)
+ {
+#ifdef DEBUG
+ printf("Reg 0x%02X Value 0x%08lX Width %02d written\n",
+ table[i].index, table[i].val, table[i].width);
+#endif
+
+ switch(table[i].width)
+ {
+ case 1: pci_hose_write_config_byte(hose, dev, table[i].index, table[i].val); break;
+ case 2: pci_hose_write_config_word(hose, dev, table[i].index, table[i].val); break;
+ case 4: pci_hose_write_config_dword(hose, dev, table[i].index, table[i].val); break;
+ }
+ }
+}
+
+
+static void pci_pip405_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
+{
+ unsigned char int_line = 0xff;
+ /*
+ * Write pci interrupt line register
+ */
+ if(PCI_DEV(dev)==0) /* Device0 = PPC405 -> skip */
+ return;
+ if(PCI_FUNC(dev)==0)
+ {
+ /* assuming all function 0 are using their INTA# Pin*/
+ int_line=PCI_IRQ_VECTOR(dev);
+ pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line);
+#ifdef DEBUG
+ printf("Fixup IRQ: dev %d (%x) int line %d 0x%x\n",
+ PCI_DEV(dev),dev,int_line,int_line);
+#endif
+ }
+}
+
+extern void pci_405gp_init(struct pci_controller *hose);
+
+
+static struct pci_controller hose = {
+ config_table: pci_pip405_config_table,
+ fixup_irq: pci_pip405_fixup_irq,
+};
+
+void pci_init(void)
+{
+ /*we want the ptrs to RAM not flash (ie don't use init list)*/
+ hose.fixup_irq = pci_pip405_fixup_irq;
+ hose.config_table = pci_pip405_config_table;
+ pci_405gp_init(&hose);
+}
+
+#endif /* CONFIG_PCI */
+#endif /* CONFIG_405GP */
diff --git a/board/mpl/common/pci_parts.h b/board/mpl/common/pci_parts.h
new file mode 100644
index 0000000000..944585f356
--- /dev/null
+++ b/board/mpl/common/pci_parts.h
@@ -0,0 +1,192 @@
+ /*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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 _PCI_PARTS_H_
+#define _PCI_PARTS_H_
+
+
+/* Board specific file containing:
+ * - PCI Memory Mapping
+ * - PCI IO Mapping
+ * - PCI Interrupt Mapping
+ */
+
+/* PIP405 PCI INT Routing:
+ * IRQ0 VECTOR
+ * PIXX4 IDSEL = AD16 INTA# 28 (Function 2 USB is INTD# = 31)
+ * VGA IDSEL = AD17 INTB# 29
+ * SCSI IDSEL = AD18 INTC# 30
+ * PC104 IDSEL0 = AD20 INTA# 28
+ * PC104 IDSEL1 = AD21 INTB# 29
+ * PC104 IDSEL2 = AD22 INTC# 30
+ * PC104 IDSEL3 = AD23 INTD# 31
+ *
+ * busdevfunc = EXXX XXXX BBBB BBBB DDDD DFFF RRRR RR00
+ * ^ ^ ^ ^ ^
+ * 31 23 15 10 7
+ * E = Enabled
+ * B = Bussnumber
+ * D = Devicenumber (Device0 = AD10)
+ * F = Functionnumber
+ * R = Registernumber
+ *
+ * Device = (busdevfunc>>11) + 10
+ * Vector = devicenumber % 4 + 28
+ *
+ */
+#define PCI_HIGHEST_ON_BOARD_ID 19
+/*#define PCI_DEV_NUMBER(x) (((x>>11) & 0x1f) + 10) */
+#define PCI_IRQ_VECTOR(x) ((PCI_DEV(x) + 10) % 4) + 28
+
+
+
+/* PCI Device List for PIP405 */
+
+/* Mapping:
+ * +-------------+------------+------------+--------------------------------+
+ * ¦ PCI MemAddr | PCI IOAddr | Local Addr | Device / Function |
+ * +-------------+------------+------------+--------------------------------+
+ * | 0x00000000 | | 0xA0000000 | ISA Memory (hard wired) |
+ * | 0x00FFFFFF | | 0xA0FFFFFF | |
+ * +-------------+------------+------------+--------------------------------+
+ * | | 0x00000000 | 0xE8000000 | ISA IO (hard wired) |
+ * | | 0x0000FFFF | 0xE800FFFF | |
+ * +-------------+------------+------------+--------------------------------+
+ * | 0x80000000 | | 0x80000000 | VGA Controller Memory |
+ * | 0x80FFFFFF | | 0x80FFFFFF | |
+ * +-------------+------------+------------+--------------------------------+
+ * | 0x81000000 | | 0x81000000 | SCSI Controller Memory |
+ * | 0x81FFFFFF | | 0x81FFFFFF | |
+ * +-------------+------------+------------+--------------------------------+
+ */
+
+struct pci_pip405_config_entry {
+ int index; /* address */
+ unsigned long val; /* value */
+ int width; /* data size */
+};
+
+extern void pci_pip405_write_regs(struct pci_controller *,
+ pci_dev_t,
+ struct pci_config_table *);
+
+/* PIIX4 ISA Bridge Function 0 */
+static struct pci_pip405_config_entry piix4_isa_bridge_f0[] = {
+ {PCI_CFG_PIIX4_SERIRQ, 0xD0, 1}, /* enable Continous SERIRQ Pin */
+ {PCI_CFG_PIIX4_GENCFG, 0x00010041, 4}, /* enable SERIRQs, ISA, PNP */
+ {PCI_CFG_PIIX4_TOM, 0xFE, 1}, /* Top of Memory */
+ {PCI_CFG_PIIX4_XBCS, 0x02C4, 2}, /* disable all peri CS */
+ {PCI_CFG_PIIX4_RTCCFG, 0x21, 1}, /* enable RTC */
+#if defined(CONFIG_PIP405)
+ {PCI_CFG_PIIX4_MBDMA, 0x82, 1}, /* set MBDMA0 to DMA 2 */
+ {PCI_CFG_PIIX4_MBDMA+1, 0x83, 1}, /* set MBDMA1 to DMA 3 */
+#endif
+ {PCI_CFG_PIIX4_DLC, 0x0, 1}, /* disable passive release feature */
+ { } /* end of device table */
+};
+
+/* PIIX4 IDE Controller Function 1 */
+static struct pci_pip405_config_entry piix4_ide_cntrl_f1[] = {
+ {PCI_COMMAND, 0x0001, 2}, /* enable IO access */
+ {PCI_CFG_PIIX4_IDETIM, 0x80008000, 4}, /* enable Both IDE channels */
+ { } /* end of device table */
+};
+
+/* PIIX4 USB Controller Function 2 */
+static struct pci_pip405_config_entry piix4_usb_cntrl_f2[] = {
+ {PCI_INTERRUPT_LINE, 31, 1}, /* Int vector = 31 */
+ {PCI_BASE_ADDRESS_4, 0x0000E001, 4}, /* Set IO Address to 0xe000 to 0xe01F */
+ {PCI_LATENCY_TIMER, 0x80, 1}, /* Latency Timer 0x80 */
+ {0xC0, 0x2000, 2}, /* Legacy support */
+ {PCI_COMMAND, 0x0005, 2}, /* enable IO access and Master */
+ { } /* end of device table */
+};
+
+/* PIIX4 Power Management Function 3 */
+static struct pci_pip405_config_entry piix4_pmm_cntrl_f3[] = {
+ {PCI_COMMAND, 0x0001, 2}, /* enable IO access */
+ {PCI_CFG_PIIX4_PMAB, 0x00004000, 4}, /* set PMBA to "valid" value */
+ {PCI_CFG_PIIX4_PMMISC, 0x01, 1}, /* enable PMBA IO access */
+ {PCI_CFG_PIIX4_SMBBA, 0x00005000, 4}, /* set SMBBA to "valid" value */
+ { } /* end of device table */
+};
+/* PPC405 Dummy only used to prevent autosetup on this host bridge */
+static struct pci_pip405_config_entry ibm405_dummy[] = {
+ { } /* end of device table */
+};
+
+void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev,
+ struct pci_config_table *entry);
+
+
+static struct pci_config_table pci_pip405_config_table[]={
+ {PCI_VENDOR_ID_IBM, /* 405 dummy */
+ PCI_DEVICE_ID_IBM_405GP,
+ PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID, 0,
+ pci_pip405_write_regs, {(unsigned long) ibm405_dummy}},
+
+ {PCI_VENDOR_ID_INTEL, /* PIIX4 ISA Bridge Function 0 */
+ PCI_DEVICE_ID_INTEL_82371AB_0,
+ PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID, 0,
+ pci_pip405_write_regs, {(unsigned long) piix4_isa_bridge_f0}},
+
+ {PCI_VENDOR_ID_INTEL, /* PIIX4 IDE Controller Function 1 */
+ PCI_DEVICE_ID_INTEL_82371AB,
+ PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID, 1,
+ pci_pip405_write_regs, {(unsigned long) piix4_ide_cntrl_f1}},
+
+ {PCI_VENDOR_ID_INTEL, /* PIIX4 USB Controller Function 2 */
+ PCI_DEVICE_ID_INTEL_82371AB_2,
+ PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID, 2,
+ pci_pip405_write_regs, {(unsigned long) piix4_usb_cntrl_f2}},
+
+ {PCI_VENDOR_ID_INTEL, /* PIIX4 USB Controller Function 3 */
+ PCI_DEVICE_ID_INTEL_82371AB_3,
+ PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID, 3,
+ pci_pip405_write_regs, {(unsigned long) piix4_pmm_cntrl_f3}},
+
+ {PCI_ANY_ID,
+ PCI_ANY_ID,
+ PCI_CLASS_DISPLAY_VGA,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ pci_405gp_setup_vga},
+
+ {PCI_ANY_ID,
+ PCI_ANY_ID,
+ PCI_CLASS_NOT_DEFINED_VGA,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ pci_405gp_setup_vga},
+
+ { }
+};
+#endif /* _PCI_PARTS_H_ */
+
+
+
+
+
diff --git a/board/mpl/mip405/Makefile b/board/mpl/mip405/Makefile
new file mode 100644
index 0000000000..839cafe213
--- /dev/null
+++ b/board/mpl/mip405/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2000, 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS = $(BOARD).o ../common/flash.o cmd_mip405.o ../common/pci.o \
+ ../common/usb_uhci.o ../common/memtst.o ../common/common_util.o
+
+SOBJS = init.o
+
+$(LIB): $(OBJS) $(SOBJS)
+ $(AR) crv $@ $^
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/mpl/pip405/Makefile b/board/mpl/pip405/Makefile
new file mode 100644
index 0000000000..b6cc531bc9
--- /dev/null
+++ b/board/mpl/pip405/Makefile
@@ -0,0 +1,52 @@
+#
+# (C) Copyright 2000, 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS = $(BOARD).o \
+ ../common/flash.o cmd_pip405.o ../common/pci.o \
+ ../common/isa.o ../common/kbd.o \
+ ../common/usb_uhci.o \
+ ../common/memtst.o ../common/common_util.o
+
+SOBJS = init.o
+
+$(LIB): $(OBJS) $(SOBJS)
+ $(AR) crv $@ $^
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/musenki/musenki.c b/board/musenki/musenki.c
new file mode 100644
index 0000000000..3b02f37c3c
--- /dev/null
+++ b/board/musenki/musenki.c
@@ -0,0 +1,130 @@
+/*
+ * (C) Copyright 2001
+ * 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 <mpc824x.h>
+#include <pci.h>
+
+int checkboard (void)
+{
+ ulong busfreq = get_bus_freq(0);
+ char buf[32];
+
+ printf("Board: MUSENKI Local Bus at %s MHz\n", strmhz(buf, busfreq));
+ return 0;
+
+}
+
+#if 0 /* NOT USED */
+int checkflash (void)
+{
+ /* TODO: XXX XXX XXX */
+ printf ("## Test not implemented yet ##\n");
+
+ return (0);
+}
+#endif
+
+long int initdram (int board_type)
+{
+ int i, cnt;
+ volatile uchar * base= CFG_SDRAM_BASE;
+ volatile ulong * addr;
+ ulong save[32];
+ ulong val, ret = 0;
+
+ for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) {
+ addr = (volatile ulong *)base + cnt;
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ addr = (volatile ulong *)base;
+ save[i] = *addr;
+ *addr = 0;
+
+ if (*addr != 0) {
+ *addr = save[i];
+ goto Done;
+ }
+
+ for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) {
+ addr = (volatile ulong *)base + cnt;
+ val = *addr;
+ *addr = save[--i];
+ if (val != ~cnt) {
+ ulong new_bank0_end = cnt * sizeof(long) - 1;
+ ulong mear1 = mpc824x_mpc107_getreg(MEAR1);
+ ulong emear1 = mpc824x_mpc107_getreg(EMEAR1);
+ mear1 = (mear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT);
+ emear1 = (emear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT);
+ mpc824x_mpc107_setreg(MEAR1, mear1);
+ mpc824x_mpc107_setreg(EMEAR1, emear1);
+
+ ret = cnt * sizeof(long);
+ goto Done;
+ }
+ }
+
+ ret = CFG_MAX_RAM_SIZE;
+Done:
+ return ret;
+}
+
+/*
+ * Initialize PCI Devices
+ */
+#ifndef CONFIG_PCI_PNP
+static struct pci_config_table pci_sandpoint_config_table[] = {
+#if 0
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ 0x0, 0x0, 0x0, /* unknown eth0 divice */
+ pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
+ PCI_ENET0_MEMADDR,
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER }},
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ 0x0, 0x0, 0x0, /* unknown eth1 device */
+ pci_cfgfunc_config_device, { PCI_ENET1_IOADDR,
+ PCI_ENET1_MEMADDR,
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER }},
+#endif
+ { }
+};
+#endif
+
+struct pci_controller hose = {
+#ifndef CONFIG_PCI_PNP
+ config_table: pci_sandpoint_config_table,
+#endif
+};
+
+void pci_init(void)
+{
+ pci_mpc824x_init(&hose);
+}
diff --git a/board/mvs1/Makefile b/board/mvs1/Makefile
new file mode 100644
index 0000000000..ef173d0366
--- /dev/null
+++ b/board/mvs1/Makefile
@@ -0,0 +1,40 @@
+#
+# (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 $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS = $(BOARD).o flash.o
+
+$(LIB): .depend $(OBJS)
+ $(AR) crv $@ $^
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/netvia/Makefile b/board/netvia/Makefile
new file mode 100644
index 0000000000..ef173d0366
--- /dev/null
+++ b/board/netvia/Makefile
@@ -0,0 +1,40 @@
+#
+# (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 $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS = $(BOARD).o flash.o
+
+$(LIB): .depend $(OBJS)
+ $(AR) crv $@ $^
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/netvia/netvia.c b/board/netvia/netvia.c
new file mode 100644
index 0000000000..504593effe
--- /dev/null
+++ b/board/netvia/netvia.c
@@ -0,0 +1,374 @@
+/*
+ * (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
+ */
+
+/*
+ * Pantelis Antoniou, Intracom S.A., panto@intracom.gr
+ * U-Boot port on NetVia board
+ */
+
+#include <common.h>
+#include "mpc8xx.h"
+
+/* some sane bit macros */
+#define _BD(_b) (1U << (31-(_b)))
+#define _BDR(_l, _h) (((((1U << (31-(_l))) - 1) << 1) | 1) & ~((1U << (31-(_h))) - 1))
+
+#define _BW(_b) (1U << (15-(_b)))
+#define _BWR(_l, _h) (((((1U << (15-(_l))) - 1) << 1) | 1) & ~((1U << (15-(_h))) - 1))
+
+#define _BB(_b) (1U << (7-(_b)))
+#define _BBR(_l, _h) (((((1U << (7-(_l))) - 1) << 1) | 1) & ~((1U << (7-(_h))) - 1))
+
+#define _B(_b) _BD(_b)
+#define _BR(_l, _h) _BDR(_l, _h)
+
+/* ------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------------------- */
+
+#define _NOT_USED_ 0xFFFFFFFF
+
+/* ------------------------------------------------------------------------- */
+
+#define CS_0000 0x00000000
+#define CS_0001 0x10000000
+#define CS_0010 0x20000000
+#define CS_0011 0x30000000
+#define CS_0100 0x40000000
+#define CS_0101 0x50000000
+#define CS_0110 0x60000000
+#define CS_0111 0x70000000
+#define CS_1000 0x80000000
+#define CS_1001 0x90000000
+#define CS_1010 0xA0000000
+#define CS_1011 0xB0000000
+#define CS_1100 0xC0000000
+#define CS_1101 0xD0000000
+#define CS_1110 0xE0000000
+#define CS_1111 0xF0000000
+
+#define BS_0000 0x00000000
+#define BS_0001 0x01000000
+#define BS_0010 0x02000000
+#define BS_0011 0x03000000
+#define BS_0100 0x04000000
+#define BS_0101 0x05000000
+#define BS_0110 0x06000000
+#define BS_0111 0x07000000
+#define BS_1000 0x08000000
+#define BS_1001 0x09000000
+#define BS_1010 0x0A000000
+#define BS_1011 0x0B000000
+#define BS_1100 0x0C000000
+#define BS_1101 0x0D000000
+#define BS_1110 0x0E000000
+#define BS_1111 0x0F000000
+
+#define A10_AAAA 0x00000000
+#define A10_AAA0 0x00200000
+#define A10_AAA1 0x00300000
+#define A10_000A 0x00800000
+#define A10_0000 0x00A00000
+#define A10_0001 0x00B00000
+#define A10_111A 0x00C00000
+#define A10_1110 0x00E00000
+#define A10_1111 0x00F00000
+
+#define RAS_0000 0x00000000
+#define RAS_0001 0x00040000
+#define RAS_1110 0x00080000
+#define RAS_1111 0x000C0000
+
+#define CAS_0000 0x00000000
+#define CAS_0001 0x00010000
+#define CAS_1110 0x00020000
+#define CAS_1111 0x00030000
+
+#define WE_0000 0x00000000
+#define WE_0001 0x00004000
+#define WE_1110 0x00008000
+#define WE_1111 0x0000C000
+
+#define GPL4_0000 0x00000000
+#define GPL4_0001 0x00001000
+#define GPL4_1110 0x00002000
+#define GPL4_1111 0x00003000
+
+#define GPL5_0000 0x00000000
+#define GPL5_0001 0x00000400
+#define GPL5_1110 0x00000800
+#define GPL5_1111 0x00000C00
+#define LOOP 0x00000080
+
+#define EXEN 0x00000040
+
+#define AMX_COL 0x00000000
+#define AMX_ROW 0x00000020
+#define AMX_MAR 0x00000030
+
+#define NA 0x00000008
+
+#define UTA 0x00000004
+
+#define TODT 0x00000002
+
+#define LAST 0x00000001
+
+const uint sdram_table[0x40] = {
+ /* RSS */
+ CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */
+ CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */
+ CS_0000 | BS_1111 | A10_0001 | RAS_1111 | CAS_0001 | WE_1111 | AMX_COL | UTA, /* READ */
+ CS_0001 | BS_0001 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA, /* PALL */
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA | TODT | LAST, /* NOP */
+ _NOT_USED_, _NOT_USED_,
+
+ /* RBS */
+ CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */
+ CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */
+ CS_0001 | BS_1111 | A10_0001 | RAS_1111 | CAS_0001 | WE_1111 | AMX_COL | UTA, /* READ */
+ CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */
+ CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */
+ CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */
+ CS_0001 | BS_0001 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL, /* PALL */
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | TODT | LAST, /* NOP */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+
+ /* WSS */
+ CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA,
+ CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL,
+ CS_0000 | BS_0001 | A10_0000 | RAS_1111 | CAS_0001 | WE_0000 | AMX_COL | UTA,
+ CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA | TODT | LAST,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+
+ /* WBS */
+ CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */
+ CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */
+ CS_0001 | BS_0000 | A10_0000 | RAS_1111 | CAS_0001 | WE_0000 | AMX_COL, /* WRITE */
+ CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */
+ CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */
+ CS_1111 | BS_0001 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */
+ CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA, /* PALL */
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA | TODT | LAST, /* NOP */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_,
+
+ /* UPT */
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */
+ CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_0001 | WE_1111 | AMX_COL | LOOP,
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL,
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL,
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | LOOP,
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | LAST,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_,
+
+ /* EXC */
+ CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL,
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | TODT | LAST,
+
+ /* REG */
+ CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1110 | AMX_MAR,
+ CS_0001 | BS_1111 | A10_0001 | RAS_0001 | CAS_0001 | WE_0001 | AMX_MAR | TODT | LAST,
+};
+
+/* ------------------------------------------------------------------------- */
+
+
+/*
+ * Check Board Identity:
+ *
+ * Test ETX ID string (ETX_xxx...)
+ *
+ * Return 1 always.
+ */
+
+int checkboard(void)
+{
+ printf ("NETVIA\n");
+ return (0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* 0xC8 = 0b11001000 , CAS3, >> 2 = 0b00 11 0 010 */
+#define MAR_SDRAM_INIT 0x000000C8LU
+
+#define MCR_OP(x) ((unsigned long)((x) & 3) << (31-1))
+#define MCR_OP_MASK MCR_OP(3)
+
+#define MCR_UM(x) ((unsigned long)((x) & 1) << (31 - 8))
+#define MCR_UM_MASK MCR_UM(1)
+#define MCR_UM_UPMA MCR_UM(0)
+#define MCR_UM_UPMB MCR_UM(1)
+
+#define MCR_MB(x) ((unsigned long)((x) & 7) << (31 - 18))
+#define MCR_MB_MASK MCR_MB(7)
+#define MCR_MB_CS(x) MCR_MB(x)
+
+#define MCR_MCLF(x) ((unsigned long)((x) & 15) << (31 - 23))
+#define MCR_MCLF_MASK MCR_MCLF(15)
+
+long int initdram(int board_type)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ long int size;
+
+ upmconfig(UPMA, (uint *) sdram_table, sizeof(sdram_table) / sizeof(uint));
+
+ /*
+ * Preliminary prescaler for refresh
+ */
+ memctl->memc_mptpr = CFG_MPTPR_1BK_8K;
+
+ memctl->memc_mar = MAR_SDRAM_INIT; /* 32-bit address to be output on the address bus if AMX = 0b11 */
+
+ /*
+ * Map controller bank 3 to the SDRAM bank at preliminary address.
+ */
+ memctl->memc_or3 = CFG_OR3_PRELIM;
+ memctl->memc_br3 = CFG_BR3_PRELIM;
+
+ memctl->memc_mamr = CFG_MAMR_9COL & ~MAMR_PTAE; /* no refresh yet */
+
+ udelay(200);
+
+ /* perform SDRAM initialisation sequence */
+ memctl->memc_mcr = MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS3 | MCR_MCLF(1) | MCR_MAD(0x3C); /* precharge all */
+ udelay(1);
+ memctl->memc_mcr = MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS3 | MCR_MCLF(0) | MCR_MAD(0x30); /* refresh 16 times(0) */
+ udelay(1);
+ memctl->memc_mcr = MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS3 | MCR_MCLF(1) | MCR_MAD(0x3E); /* exception program (write mar) */
+ udelay(1);
+
+ memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */
+
+ udelay(1000);
+
+ memctl->memc_mamr = CFG_MAMR_9COL;
+
+ size = SDRAM_MAX_SIZE;
+
+ udelay(10000);
+
+ /* do the ram test */
+ {
+ register unsigned long *rp;
+ register unsigned long v;
+
+ /* first fill */
+ for (rp = (unsigned long *)0; rp < (unsigned long *)SDRAM_MAX_SIZE; )
+ *rp++ = (unsigned long)rp;
+
+ /* now check */
+ for (rp = (unsigned long *)0; rp < (unsigned long *)SDRAM_MAX_SIZE; rp++) {
+ if ((v = *rp) != (unsigned long)rp) {
+ printf("ERROR at 0x%lx (0x%lx)\n", (unsigned long)rp, v);
+ return -1;
+ }
+ }
+
+ }
+
+ return (size);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int misc_init_r(void)
+{
+ return(0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* bits that can have a special purpose or can be configured as inputs/outputs */
+#define PA_MASK (_BWR(4, 9) | _BWR(12, 15))
+#define PA_ODR_MASK (_BW(9) | _BW(12) | _BW(14))
+#define PA_ODR_VAL 0
+#define PA_GP_INMASK 0
+#define PA_GP_OUTMASK (_BW(5) | _BW(14) | _BW(15))
+#define PA_SP_OUTMASK 0
+#define PA_GP_OUTVAL _BW(5)
+#define PA_SP_OUTVAL 0
+
+#define PB_MASK (_BR(16, 19) | _BR(22, 31))
+#define PB_ODR_MASK PB_MASK
+#define PB_ODR_VAL 0
+#define PB_GP_INMASK 0
+#define PB_GP_OUTMASK (_BR(16, 19) | _BR(26, 27) | _B(31))
+#define PB_SP_OUTMASK _BR(28, 30)
+#define PB_SP_OUTVAL _BR(28, 30)
+#define PB_GP_OUTVAL (_BR(16, 19) | _BR(26, 27) | _B(31))
+
+#define PC_MASK _BWR(4, 15)
+#define PC_SO_MASK (_BWR(6, 11) | _BWR(14, 15))
+#define PC_SO_VAL 0
+#define PC_INT_MASK PC_MASK
+#define PC_INT_VAL 0
+#define PC_GP_INMASK (_BWR(5, 7) | _BWR(9, 10) | _BW(13))
+#define PC_GP_OUTMASK _BW(12)
+#define PC_SP_OUTMASK 0
+#define PC_SP_OUTVAL _BW(12)
+#define PC_GP_OUTVAL 0
+
+#define PD_MASK _BWR(0, 15)
+#define PD_GP_INMASK 0
+#define PD_GP_OUTMASK _BWR(3, 15)
+#define PD_SP_OUTMASK 0
+#define PD_GP_OUTVAL (_BW(3) | _BW(5) | _BW(7) | _BWR(8, 15))
+#define PD_SP_OUTVAL 0
+
+int board_pre_init(void)
+{
+ register volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ register volatile iop8xx_t *ioport = &immap->im_ioport;
+ register volatile cpm8xx_t *cpm = &immap->im_cpm;
+
+ ioport->iop_padat = (ioport->iop_padat & ~PA_MASK) | PA_SP_OUTVAL | PA_GP_OUTVAL;
+ ioport->iop_paodr = (ioport->iop_paodr & ~PA_ODR_MASK) | PA_ODR_VAL;
+ ioport->iop_padir = (ioport->iop_padir & ~PA_GP_INMASK)| PA_SP_OUTMASK | PA_GP_OUTMASK;
+ ioport->iop_papar = (ioport->iop_papar & ~(PA_GP_INMASK & PA_GP_OUTMASK));
+
+ cpm->cp_pbdat = (ioport->iop_padat & ~PB_MASK) | PB_SP_OUTVAL | PB_GP_OUTVAL;
+ cpm->cp_pbodr = (ioport->iop_paodr & ~PB_ODR_MASK) | PB_ODR_VAL;
+ cpm->cp_pbdir = (ioport->iop_padir & ~PB_GP_INMASK)| PB_SP_OUTMASK | PB_GP_OUTMASK;
+ cpm->cp_pbpar = (ioport->iop_papar & ~(PB_GP_INMASK & PB_GP_OUTMASK));
+
+ ioport->iop_pcdat = (ioport->iop_pcdat & ~PC_MASK) | PC_SP_OUTVAL | PC_GP_OUTVAL;
+ ioport->iop_pcdir = (ioport->iop_pcdir & ~PC_GP_INMASK)| PC_SP_OUTMASK | PC_GP_OUTMASK;
+ ioport->iop_pcso = (ioport->iop_pcso & ~PC_SO_MASK) | PC_SO_VAL;
+ ioport->iop_pcint = (ioport->iop_pcint & ~PC_INT_MASK) | PC_INT_VAL;
+ ioport->iop_pcpar = (ioport->iop_pcpar & ~(PC_GP_INMASK & PC_GP_OUTMASK));
+
+ ioport->iop_pddat = (ioport->iop_pddat & ~PD_MASK) | PD_SP_OUTVAL | PD_GP_OUTVAL;
+ ioport->iop_pddir = (ioport->iop_pddir & ~PD_GP_INMASK)| PD_SP_OUTMASK | PD_GP_OUTMASK;
+ ioport->iop_pdpar = (ioport->iop_pdpar & ~(PD_GP_INMASK & PD_GP_OUTMASK));
+
+ return 0;
+}
+
diff --git a/board/netvia/u-boot.lds b/board/netvia/u-boot.lds
new file mode 100644
index 0000000000..e75f12cbfb
--- /dev/null
+++ b/board/netvia/u-boot.lds
@@ -0,0 +1,132 @@
+/*
+ * (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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc8xx/start.o (.text)
+ cpu/mpc8xx/traps.o (.text)
+ common/dlmalloc.o (.text)
+ lib_ppc/ppcstring.o (.text)
+ lib_generic/vsprintf.o (.text)
+ lib_generic/crc32.o (.text)
+ lib_generic/zlib.o (.text)
+ lib_ppc/cache.o (.text)
+ lib_ppc/time.o (.text)
+
+ . = env_offset;
+ common/environment.o (.ppcenv)
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/board/netvia/u-boot.lds.debug b/board/netvia/u-boot.lds.debug
new file mode 100644
index 0000000000..fa494fb8da
--- /dev/null
+++ b/board/netvia/u-boot.lds.debug
@@ -0,0 +1,131 @@
+/*
+ * (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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ cpu/mpc8xx/start.o (.text)
+ common/dlmalloc.o (.text)
+ lib_generic/vsprintf.o (.text)
+ lib_generic/crc32.o (.text)
+
+ . = env_offset;
+ common/environment.o(.text)
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
+
diff --git a/board/oxc/flash.c b/board/oxc/flash.c
new file mode 100644
index 0000000000..4f0220eab6
--- /dev/null
+++ b/board/oxc/flash.c
@@ -0,0 +1,372 @@
+/*
+ * (C) Copyright 2000
+ * Marius Groeger <mgroeger@sysgo.de>
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for STM29W320DB/STM29W800D flash chips
+ *
+ *--------------------------------------------------------------------
+ * 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 <mpc8xx.h>
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+
+static ulong flash_get_size (vu_char *addr, flash_info_t *info);
+static int write_byte (flash_info_t *info, ulong dest, uchar data);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+ unsigned long size;
+ int i;
+
+ /* Init: no FLASHes known */
+ for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ }
+
+ /*
+ * We use the following trick here: since flash is cyclically
+ * mapped in the 0xFF800000-0xFFFFFFFF area, we detect the type
+ * and the size of flash using 0xFF800000 as the base address,
+ * and then call flash_get_size() again to fill flash_info.
+ */
+ size = flash_get_size((vu_char *)CFG_FLASH_PRELIMBASE, &flash_info[0]);
+ if (size)
+ {
+ flash_get_size((vu_char *)(-size), &flash_info[0]);
+ }
+
+#if (CFG_MONITOR_BASE >= CFG_FLASH_PRELIMBASE)
+ /* monitor protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+ &flash_info[0]);
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef CFG_ENV_SIZE
+# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
+# endif
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+ &flash_info[0]);
+#endif
+
+ return (size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t *info)
+{
+ int i;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_STM:
+ printf ("ST ");
+ break;
+ default:
+ printf ("Unknown Vendor ");
+ break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_STM320DB:
+ printf ("M29W320DB (32 Mbit)\n");
+ break;
+ case FLASH_STM800DB:
+ printf ("M29W800DB (8 Mbit, bottom boot block)\n");
+ break;
+ case FLASH_STM800DT:
+ printf ("M29W800DT (8 Mbit, top boot block)\n");
+ break;
+ default:
+ printf ("Unknown Chip Type\n");
+ break;
+ }
+
+ printf (" Size: %ld KB in %d Sectors\n",
+ info->size >> 10, info->sector_count);
+
+ printf (" Sector Start Addresses:");
+ for (i=0; i<info->sector_count; ++i) {
+ if ((i % 5) == 0)
+ printf ("\n ");
+ printf (" %08lX%s",
+ info->start[i],
+ info->protect[i] ? " (RO)" : " "
+ );
+ }
+ printf ("\n");
+ return;
+}
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_char *addr, flash_info_t *info)
+{
+ short i;
+ uchar vendor, devid;
+ ulong base = (ulong)addr;
+
+ /* Write auto select command: read Manufacturer ID */
+ addr[0x0AAA] = 0xAA;
+ addr[0x0555] = 0x55;
+ addr[0x0AAA] = 0x90;
+
+ udelay(1000);
+
+ vendor = addr[0];
+ devid = addr[2];
+
+ /* only support STM */
+ if ((vendor << 16) != FLASH_MAN_STM) {
+ return 0;
+ }
+
+ if (devid == FLASH_STM320DB) {
+ /* MPC8240 can address maximum 2Mb of flash, that is why the MSB
+ * lead is grounded and we can access only 2 first Mb */
+ info->flash_id = vendor << 16 | devid;
+ info->sector_count = 32;
+ info->size = info->sector_count * 0x10000;
+ for (i = 0; i < info->sector_count; i++) {
+ info->start[i] = base + i * 0x10000;
+ }
+ }
+ else if (devid == FLASH_STM800DB) {
+ info->flash_id = vendor << 16 | devid;
+ info->sector_count = 19;
+ info->size = 0x100000;
+ info->start[0] = 0x0000;
+ info->start[1] = 0x4000;
+ info->start[2] = 0x6000;
+ info->start[3] = 0x8000;
+ for (i = 4; i < info->sector_count; i++) {
+ info->start[i] = base + (i-3) * 0x10000;
+ }
+ }
+ else if (devid == FLASH_STM800DT) {
+ info->flash_id = vendor << 16 | devid;
+ info->sector_count = 19;
+ info->size = 0x100000;
+ for (i = 0; i < info->sector_count-4; i++) {
+ info->start[i] = base + i * 0x10000;
+ }
+ info->start[i] = base + i * 0x10000;
+ info->start[i+1] = base + i * 0x10000 + 0x8000;
+ info->start[i+2] = base + i * 0x10000 + 0xa000;
+ info->start[i+3] = base + i * 0x10000 + 0xc000;
+ }
+ else {
+ return 0;
+ }
+
+ /* mark all sectors as unprotected */
+ for (i = 0; i < info->sector_count; i++) {
+ info->protect[i] = 0;
+ }
+
+ /* Issue the reset command */
+ if (info->flash_id != FLASH_UNKNOWN) {
+ addr[0] = 0xF0; /* reset bank */
+ }
+
+ return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ vu_char *addr = (vu_char *)(info->start[0]);
+ int flag, prot, sect, l_sect;
+ ulong start, now, last;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("- missing\n");
+ } else {
+ printf ("- no sectors to erase\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;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr[0x0AAA] = 0xAA;
+ addr[0x0555] = 0x55;
+ addr[0x0AAA] = 0x80;
+ addr[0x0AAA] = 0xAA;
+ addr[0x0555] = 0x55;
+
+ /* wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect<=s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ addr = (vu_char *)(info->start[sect]);
+ addr[0] = 0x30;
+ l_sect = sect;
+ }
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ /*
+ * We wait for the last triggered sector
+ */
+ if (l_sect < 0)
+ goto DONE;
+
+ start = get_timer (0);
+ last = start;
+ addr = (vu_char *)(info->start[l_sect]);
+ while ((addr[0] & 0x80) != 0x80) {
+ if ((now = get_timer(start)) > CFG_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 = (volatile unsigned char *)info->start[0];
+ addr[0] = 0xF0; /* 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)
+{
+ int rc;
+
+ while (cnt > 0) {
+ if ((rc = write_byte(info, addr, *src)) != 0) {
+ return (rc);
+ }
+ addr++;
+ src++;
+ cnt--;
+ }
+
+ return (0);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a byte to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_byte (flash_info_t *info, ulong dest, uchar data)
+{
+ vu_char *addr = (vu_char *)(info->start[0]);
+ ulong start;
+ int flag;
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*((vu_char *)dest) & data) != data) {
+ return (2);
+ }
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr[0x0AAA] = 0xAA;
+ addr[0x0555] = 0x55;
+ addr[0x0AAA] = 0xA0;
+
+ *((vu_char *)dest) = data;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* data polling for D7 */
+ start = get_timer (0);
+ while ((*((vu_char *)dest) & 0x80) != (data & 0x80)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/oxc/oxc.c b/board/oxc/oxc.c
new file mode 100644
index 0000000000..8aced84e54
--- /dev/null
+++ b/board/oxc/oxc.c
@@ -0,0 +1,237 @@
+/*
+ * (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 <mpc824x.h>
+#include <pci.h>
+#include <i2c.h>
+
+int checkboard (void)
+{
+ puts ( "Board: OXC8240\n" );
+ return 0;
+}
+
+long int initdram (int board_type)
+{
+#ifndef CFG_RAMBOOT
+ int i, cnt;
+ volatile uchar * base= CFG_SDRAM_BASE;
+ volatile ulong * addr;
+ ulong save[32];
+ ulong val, ret = 0;
+
+ for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) {
+ addr = (volatile ulong *)base + cnt;
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ addr = (volatile ulong *)base;
+ save[i] = *addr;
+ *addr = 0;
+
+ if (*addr != 0) {
+ *addr = save[i];
+ goto Done;
+ }
+
+ for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) {
+ addr = (volatile ulong *)base + cnt;
+ val = *addr;
+ *addr = save[--i];
+ if (val != ~cnt) {
+ ulong new_bank0_end = cnt * sizeof(long) - 1;
+ ulong mear1 = mpc824x_mpc107_getreg(MEAR1);
+ ulong emear1 = mpc824x_mpc107_getreg(EMEAR1);
+ mear1 = (mear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT);
+ emear1 = (emear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT);
+ mpc824x_mpc107_setreg(MEAR1, mear1);
+ mpc824x_mpc107_setreg(EMEAR1, emear1);
+
+ ret = cnt * sizeof(long);
+ goto Done;
+ }
+ }
+
+ ret = CFG_MAX_RAM_SIZE;
+Done:
+ return ret;
+#else
+ /* if U-Boot starts from RAM, then suppose we have 16Mb of RAM */
+ return (16 << 20);
+#endif
+}
+
+/*
+ * Initialize PCI Devices, report devices found.
+ */
+#ifndef CONFIG_PCI_PNP
+static struct pci_config_table pci_oxc_config_table[] = {
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x14, PCI_ANY_ID,
+ pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
+ PCI_ENET0_MEMADDR,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x15, PCI_ANY_ID,
+ pci_cfgfunc_config_device, { PCI_ENET1_IOADDR,
+ PCI_ENET1_MEMADDR,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
+ { }
+};
+#endif
+
+static struct pci_controller hose = {
+#ifndef CONFIG_PCI_PNP
+ config_table: pci_oxc_config_table,
+#endif
+};
+
+void pci_init (void)
+{
+ pci_mpc824x_init(&hose);
+}
+
+int board_pre_init (void)
+{
+ *(volatile unsigned char *)(CFG_CPLD_RESET) = 0x89;
+ return 0;
+}
+
+#ifdef CONFIG_WATCHDOG
+void oxc_wdt_reset(void)
+{
+ *(volatile unsigned char *)(CFG_CPLD_WATCHDOG) = 0xff;
+}
+
+void watchdog_reset(void)
+{
+ int re_enable = disable_interrupts();
+
+ oxc_wdt_reset();
+ if (re_enable)
+ enable_interrupts();
+}
+#endif
+
+static int oxc_get_expander(unsigned char addr, unsigned char * val)
+{
+ return i2c_read(addr, 0, 0, val, 1);
+}
+
+static int oxc_set_expander(unsigned char addr, unsigned char val)
+{
+ return i2c_write(addr, 0, 0, &val, 1);
+}
+
+static int expander0alive = 0;
+
+#ifdef CONFIG_SHOW_ACTIVITY
+static int ledtoggle = 0;
+static int ledstatus = 1;
+
+void oxc_toggle_activeled(void)
+{
+ ledtoggle++;
+}
+
+void show_activity(int arg)
+{
+ static unsigned char led = 0;
+ unsigned char val;
+
+ if (!expander0alive) return;
+
+ if ((ledtoggle > (2 * arg)) && ledstatus) {
+ led ^= 0x80;
+ oxc_get_expander(CFG_I2C_EXPANDER0_ADDR, &val);
+ udelay(200);
+ oxc_set_expander(CFG_I2C_EXPANDER0_ADDR, (val & 0x7F) | led);
+ ledtoggle = 0;
+ }
+}
+#endif
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+void show_boot_progress(int arg)
+{
+ unsigned char val;
+
+ if (!expander0alive) return;
+
+ if (arg > 0 && ledstatus) {
+ ledstatus = 0;
+ oxc_get_expander(CFG_I2C_EXPANDER0_ADDR, &val);
+ udelay(200);
+ oxc_set_expander(CFG_I2C_EXPANDER0_ADDR, val | 0x80);
+ } else if (arg < 0) {
+ oxc_get_expander(CFG_I2C_EXPANDER0_ADDR, &val);
+ udelay(200);
+ oxc_set_expander(CFG_I2C_EXPANDER0_ADDR, val & 0x7F);
+ ledstatus = 1;
+ }
+}
+#endif
+
+int misc_init_r (void)
+{
+ /* check whether the i2c expander #0 is accessible */
+ if (!oxc_set_expander(CFG_I2C_EXPANDER0_ADDR, 0x7F)) {
+ udelay(200);
+ expander0alive = 1;
+ }
+
+#ifdef CFG_OXC_GENERATE_IP
+ {
+ DECLARE_GLOBAL_DATA_PTR;
+
+ char str[32];
+ unsigned long ip = CFG_OXC_IPMASK;
+ bd_t *bd = gd->bd;
+
+ if (expander0alive) {
+ unsigned char val;
+
+ if (!oxc_get_expander(CFG_I2C_EXPANDER0_ADDR, &val)) {
+ ip = (ip & 0xffffff00) | ((val & 0x7c) >> 2);
+ }
+ }
+
+ if ((ip & 0xff) < 3) {
+ /* if fail, set x.x.x.254 */
+ ip = (ip & 0xffffff00) | 0xfe;
+ }
+
+ bd->bi_ip_addr = ip;
+ sprintf(str, "%ld.%ld.%ld.%ld",
+ (bd->bi_ip_addr & 0xff000000) >> 24,
+ (bd->bi_ip_addr & 0x00ff0000) >> 16,
+ (bd->bi_ip_addr & 0x0000ff00) >> 8,
+ (bd->bi_ip_addr & 0x000000ff));
+ setenv("ipaddr", str);
+ printf("ip: %s\n", str);
+ }
+#endif
+ return (0);
+}
diff --git a/board/pcippc2/cpc710_init_ram.c b/board/pcippc2/cpc710_init_ram.c
new file mode 100644
index 0000000000..57ed8f087f
--- /dev/null
+++ b/board/pcippc2/cpc710_init_ram.c
@@ -0,0 +1,254 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+
+#include "pcippc2.h"
+#include "i2c.h"
+
+typedef struct cpc710_mem_org_s
+{
+ u8 rows;
+ u8 cols;
+ u8 banks2;
+ u8 org;
+} cpc710_mem_org_t;
+
+static int cpc710_compute_mcer (u32 * mcer,
+ unsigned long *
+ size,
+ unsigned int sdram);
+static int cpc710_eeprom_checksum (unsigned int sdram);
+static u8 cpc710_eeprom_read (unsigned int sdram,
+ unsigned int offset);
+
+static u32 cpc710_mcer_mem [] =
+{
+ 0x000003f3, /* 18 lines, 4 Mb */
+ 0x000003e3, /* 19 lines, 8 Mb */
+ 0x000003c3, /* 20 lines, 16 Mb */
+ 0x00000383, /* 21 lines, 32 Mb */
+ 0x00000303, /* 22 lines, 64 Mb */
+ 0x00000203, /* 23 lines, 128 Mb */
+ 0x00000003, /* 24 lines, 256 Mb */
+ 0x00000002, /* 25 lines, 512 Mb */
+ 0x00000001 /* 26 lines, 1024 Mb */
+};
+static cpc710_mem_org_t cpc710_mem_org [] =
+{
+ { 0x0c, 0x09, 0x02, 0x00 }, /* 0000: 12/ 9/2 */
+ { 0x0d, 0x09, 0x02, 0x00 }, /* 0000: 13/ 9/2 */
+ { 0x0d, 0x0a, 0x02, 0x00 }, /* 0000: 13/10/2 */
+ { 0x0d, 0x0b, 0x02, 0x00 }, /* 0000: 13/11/2 */
+ { 0x0d, 0x0c, 0x02, 0x00 }, /* 0000: 13/12/2 */
+ { 0x0e, 0x0c, 0x02, 0x00 }, /* 0000: 14/12/2 */
+ { 0x0b, 0x08, 0x02, 0x01 }, /* 0001: 11/ 8/2 */
+ { 0x0b, 0x09, 0x01, 0x02 }, /* 0010: 11/ 9/1 */
+ { 0x0b, 0x0a, 0x01, 0x03 }, /* 0011: 11/10/1 */
+ { 0x0c, 0x08, 0x02, 0x04 }, /* 0100: 12/ 8/2 */
+ { 0x0c, 0x0a, 0x02, 0x05 }, /* 0101: 12/10/2 */
+ { 0x0d, 0x08, 0x01, 0x06 }, /* 0110: 13/ 8/1 */
+ { 0x0d, 0x08, 0x02, 0x07 }, /* 0111: 13/ 8/2 */
+ { 0x0d, 0x09, 0x01, 0x08 }, /* 1000: 13/ 9/1 */
+ { 0x0d, 0x0a, 0x01, 0x09 }, /* 1001: 13/10/1 */
+ { 0x0b, 0x08, 0x01, 0x0a }, /* 1010: 11/ 8/1 */
+ { 0x0c, 0x08, 0x01, 0x0b }, /* 1011: 12/ 8/1 */
+ { 0x0c, 0x09, 0x01, 0x0c }, /* 1100: 12/ 9/1 */
+ { 0x0e, 0x09, 0x02, 0x0d }, /* 1101: 14/ 9/2 */
+ { 0x0e, 0x0a, 0x02, 0x0e }, /* 1110: 14/10/2 */
+ { 0x0e, 0x0b, 0x02, 0x0f } /* 1111: 14/11/2 */
+};
+
+unsigned long cpc710_ram_init (void)
+{
+ unsigned long memsize = 0;
+ unsigned long bank_size;
+ u32 mcer;
+
+#ifndef CFG_RAMBOOT
+ /* Clear memory banks
+ */
+ out32(REG(SDRAM0, MCER0), 0);
+ out32(REG(SDRAM0, MCER1), 0);
+ out32(REG(SDRAM0, MCER2), 0);
+ out32(REG(SDRAM0, MCER3), 0);
+ out32(REG(SDRAM0, MCER4), 0);
+ out32(REG(SDRAM0, MCER5), 0);
+ out32(REG(SDRAM0, MCER6), 0);
+ out32(REG(SDRAM0, MCER7), 0);
+ iobarrier_rw();
+
+ /* Disable memory
+ */
+ out32(REG(SDRAM0,MCCR), 0x13b06000);
+ iobarrier_rw();
+#endif
+
+ /* Only the first memory bank is initialised now
+ */
+ if (! cpc710_compute_mcer(& mcer, & bank_size, 0))
+ {
+ puts("Unsupported SDRAM type !\n");
+ hang();
+ }
+ memsize += bank_size;
+#ifndef CFG_RAMBOOT
+ /* Enable bank, zero start
+ */
+ out32(REG(SDRAM0, MCER0), mcer | 0x80000000);
+ iobarrier_rw();
+#endif
+
+#ifndef CFG_RAMBOOT
+ /* Enable memory
+ */
+ out32(REG(SDRAM0, MCCR), in32(REG(SDRAM0, MCCR)) | 0x80000000);
+
+ /* Wait until initialisation finished
+ */
+ while (! (in32 (REG(SDRAM0, MCCR)) & 0x20000000))
+ {
+ iobarrier_rw();
+ }
+
+ /* Clear Memory Error Status and Address registers
+ */
+ out32(REG(SDRAM0, MESR), 0);
+ out32(REG(SDRAM0, MEAR), 0);
+ iobarrier_rw();
+
+ /* ECC is not configured now
+ */
+#endif
+
+ /* Memory size counter
+ */
+ out32(REG(CPC0, RGBAN1), memsize);
+
+ return memsize;
+}
+
+static int cpc710_compute_mcer (
+ u32 * mcer,
+ unsigned long * size,
+ unsigned int sdram)
+{
+ u8 rows;
+ u8 cols;
+ u8 banks2;
+ unsigned int lines;
+ u32 mc = 0;
+ unsigned int i;
+ cpc710_mem_org_t * org = 0;
+
+
+ if (! i2c_reset())
+ {
+ puts("Can't reset I2C!\n");
+ hang();
+ }
+
+ if (! cpc710_eeprom_checksum(sdram))
+ {
+ puts("Invalid EEPROM checksum !\n");
+ hang();
+ }
+
+ rows = cpc710_eeprom_read(sdram, 3);
+ cols = cpc710_eeprom_read(sdram, 4);
+ /* Can be 2 or 4 banks; divide by 2
+ */
+ banks2 = cpc710_eeprom_read(sdram, 17) / 2;
+
+ lines = rows + cols + banks2;
+
+ if (lines < 18 || lines > 26)
+ {
+ /* Unsupported configuration
+ */
+ return 0;
+ }
+
+
+ mc |= cpc710_mcer_mem [lines - 18] << 6;
+
+ for (i = 0; i < sizeof(cpc710_mem_org) / sizeof(cpc710_mem_org_t); i++)
+ {
+ cpc710_mem_org_t * corg = cpc710_mem_org + i;
+
+ if (corg->rows == rows && corg->cols == cols && corg->banks2 == banks2)
+ {
+ org = corg;
+
+ break;
+ }
+ }
+
+ if (! org)
+ {
+ /* Unsupported configuration
+ */
+ return 0;
+ }
+
+ mc |= (u32) org->org << 2;
+
+ /* Supported configuration
+ */
+ *mcer = mc;
+ *size = 1l << (lines + 4);
+
+ return 1;
+}
+
+static int cpc710_eeprom_checksum (
+ unsigned int sdram)
+{
+ u8 sum = 0;
+ unsigned int i;
+
+ for (i = 0; i < 63; i++)
+ {
+ sum += cpc710_eeprom_read(sdram, i);
+ }
+
+ return sum == cpc710_eeprom_read(sdram, 63);
+}
+
+static u8 cpc710_eeprom_read (
+ unsigned int sdram,
+ unsigned int offset)
+{
+ u8 dev = (sdram << 1) | 0xa0;
+ u8 data;
+
+ if (! i2c_read_byte(& data, dev,offset))
+ {
+ puts("I2C error !\n");
+ hang();
+ }
+
+ return data;
+}
diff --git a/board/pcippc2/cpc710_pci.c b/board/pcippc2/cpc710_pci.c
new file mode 100644
index 0000000000..9975cdaa58
--- /dev/null
+++ b/board/pcippc2/cpc710_pci.c
@@ -0,0 +1,309 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#include "hardware.h"
+#include "pcippc2.h"
+
+struct pci_controller local_hose, cpci_hose;
+
+static u32 cpc710_mapped_ram;
+
+ /* Enable PCI retry timeouts
+ */
+void cpc710_pci_enable_timeout (void)
+{
+ out32(BRIDGE(LOCAL, CFGADDR), 0x50000080);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, CFGDATA), 0x32000000);
+ iobarrier_rw();
+
+ out32(BRIDGE(CPCI, CFGADDR), 0x50000180);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, CFGDATA), 0x32000000);
+ iobarrier_rw();
+}
+
+void cpc710_pci_init (void)
+{
+ u32 sdram_size = pcippc2_sdram_size();
+
+ cpc710_mapped_ram = sdram_size < PCI_MEMORY_MAXSIZE ?
+ sdram_size : PCI_MEMORY_MAXSIZE;
+
+ /* Select the local PCI
+ */
+ out32(REG(CPC0, PCICNFR), 0x80000002);
+ iobarrier_rw();
+
+ out32(REG(CPC0, PCIBAR), BRIDGE_LOCAL_PHYS);
+ iobarrier_rw();
+
+ /* Enable PCI bridge address decoding
+ */
+ out32(REG(CPC0, PCIENB), 0x80000000);
+ iobarrier_rw();
+
+ /* Select the CPCI bridge
+ */
+ out32(REG(CPC0, PCICNFR), 0x80000003);
+ iobarrier_rw();
+
+ out32(REG(CPC0, PCIBAR), BRIDGE_CPCI_PHYS);
+ iobarrier_rw();
+
+ /* Enable PCI bridge address decoding
+ */
+ out32(REG(CPC0, PCIENB), 0x80000000);
+ iobarrier_rw();
+
+ /* Disable configuration accesses
+ */
+ out32(REG(CPC0, PCICNFR), 0x80000000);
+ iobarrier_rw();
+
+ /* Initialise the local PCI
+ */
+ out32(BRIDGE(LOCAL, CRR), 0x7c000000);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, PCIDG), 0x40000000);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, PIBAR), BRIDGE_LOCAL_IO_BUS);
+ out32(BRIDGE(LOCAL, SIBAR), BRIDGE_LOCAL_IO_PHYS);
+ out32(BRIDGE(LOCAL, IOSIZE), -BRIDGE_LOCAL_IO_SIZE);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, PMBAR), BRIDGE_LOCAL_MEM_BUS);
+ out32(BRIDGE(LOCAL, SMBAR), BRIDGE_LOCAL_MEM_PHYS);
+ out32(BRIDGE(LOCAL, MSIZE), -BRIDGE_LOCAL_MEM_SIZE);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, PR), 0x00ffe000);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, ACR), 0xfe000000);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, PSBAR), PCI_MEMORY_BUS >> 24);
+ out32(BRIDGE(LOCAL, BARPS), PCI_MEMORY_PHYS >> 24);
+ out32(BRIDGE(LOCAL, PSSIZE), 256 - (cpc710_mapped_ram >> 24));
+ iobarrier_rw();
+
+ /* Initialise the CPCI bridge
+ */
+ out32(BRIDGE(CPCI, CRR), 0x7c000000);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, PCIDG), 0xC0000000);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, PIBAR), BRIDGE_CPCI_IO_BUS);
+ out32(BRIDGE(CPCI, SIBAR), BRIDGE_CPCI_IO_PHYS);
+ out32(BRIDGE(CPCI, IOSIZE), -BRIDGE_CPCI_IO_SIZE);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, PMBAR), BRIDGE_CPCI_MEM_BUS);
+ out32(BRIDGE(CPCI, SMBAR), BRIDGE_CPCI_MEM_PHYS);
+ out32(BRIDGE(CPCI, MSIZE), -BRIDGE_CPCI_MEM_SIZE);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, PR), 0x80ffe000);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, ACR), 0xdf000000);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, PSBAR), PCI_MEMORY_BUS >> 24);
+ out32(BRIDGE(CPCI, BARPS), PCI_MEMORY_PHYS >> 24);
+ out32(BRIDGE(CPCI, PSSIZE), 256 - (cpc710_mapped_ram >> 24));
+ iobarrier_rw();
+
+ /* Local PCI
+ */
+
+ out32(BRIDGE(LOCAL, CFGADDR), 0x04000080);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, CFGDATA), 0x56010000);
+ iobarrier_rw();
+
+ out32(BRIDGE(LOCAL, CFGADDR), 0x0c000080);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, CFGDATA), PCI_LATENCY_TIMER_VAL << 16);
+ iobarrier_rw();
+
+ /* Set bus and subbus numbers
+ */
+ out32(BRIDGE(LOCAL, CFGADDR), 0x40000080);
+ iobarrier_rw();
+ out32(BRIDGE(LOCAL, CFGDATA), 0x00000000);
+ iobarrier_rw();
+
+ out32(BRIDGE(LOCAL, CFGADDR), 0x50000080);
+ iobarrier_rw();
+ /* PCI retry timeouts will be enabled later
+ */
+ out32(BRIDGE(LOCAL, CFGDATA), 0x00000000);
+ iobarrier_rw();
+
+ /* CPCI
+ */
+
+ /* Set bus and subbus numbers
+ */
+ out32(BRIDGE(CPCI, CFGADDR), 0x40000080);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, CFGDATA), 0x01010000);
+ iobarrier_rw();
+
+ out32(BRIDGE(CPCI, CFGADDR), 0x04000180);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, CFGDATA), 0x56010000);
+ iobarrier_rw();
+
+ out32(BRIDGE(CPCI, CFGADDR), 0x0c000180);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, CFGDATA), PCI_LATENCY_TIMER_VAL << 16);
+ iobarrier_rw();
+
+ /* Write to the PSBAR */
+ out32(BRIDGE(CPCI, CFGADDR), 0x10000180);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, CFGDATA), cpu_to_le32(PCI_MEMORY_BUS));
+ iobarrier_rw();
+
+ /* Set bus and subbus numbers
+ */
+ out32(BRIDGE(CPCI, CFGADDR), 0x40000180);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, CFGDATA), 0x01ff0000);
+ iobarrier_rw();
+
+ out32(BRIDGE(CPCI, CFGADDR), 0x50000180);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, CFGDATA), 0x32000000);
+ /* PCI retry timeouts will be enabled later
+ */
+ out32(BRIDGE(CPCI, CFGDATA), 0x00000000);
+ iobarrier_rw();
+
+ /* Remove reset on the PCI buses
+ */
+ out32(BRIDGE(LOCAL, CRR), 0xfc000000);
+ iobarrier_rw();
+ out32(BRIDGE(CPCI, CRR), 0xfc000000);
+ iobarrier_rw();
+
+ local_hose.first_busno = 0;
+ local_hose.last_busno = 0xff;
+
+ /* System memory space */
+ pci_set_region(local_hose.regions + 0,
+ PCI_MEMORY_BUS,
+ PCI_MEMORY_PHYS,
+ PCI_MEMORY_MAXSIZE,
+ PCI_REGION_MEM | PCI_REGION_MEMORY);
+
+ /* PCI memory space */
+ pci_set_region(local_hose.regions + 1,
+ BRIDGE_LOCAL_MEM_BUS,
+ BRIDGE_LOCAL_MEM_PHYS,
+ BRIDGE_LOCAL_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI I/O space */
+ pci_set_region(local_hose.regions + 2,
+ BRIDGE_LOCAL_IO_BUS,
+ BRIDGE_LOCAL_IO_PHYS,
+ BRIDGE_LOCAL_IO_SIZE,
+ PCI_REGION_IO);
+
+ local_hose.region_count = 3;
+
+ pci_setup_indirect(&local_hose,
+ BRIDGE_LOCAL_PHYS + HW_BRIDGE_CFGADDR,
+ BRIDGE_LOCAL_PHYS + HW_BRIDGE_CFGDATA);
+
+ pci_register_hose(&local_hose);
+
+ /* Initialize PCI32 bus registers */
+ pci_hose_write_config_byte(&local_hose,
+ PCI_BDF(local_hose.first_busno,0,0),
+ CPC710_BUS_NUMBER,
+ local_hose.first_busno);
+ pci_hose_write_config_byte(&local_hose,
+ PCI_BDF(local_hose.first_busno,0,0),
+ CPC710_SUB_BUS_NUMBER,
+ local_hose.last_busno);
+
+ local_hose.last_busno = pci_hose_scan(&local_hose);
+
+ /* Write out correct max subordinate bus number for local hose */
+ pci_hose_write_config_byte(&local_hose,
+ PCI_BDF(local_hose.first_busno,0,0),
+ CPC710_SUB_BUS_NUMBER,
+ local_hose.last_busno);
+
+ cpci_hose.first_busno = local_hose.last_busno + 1;
+ cpci_hose.last_busno = 0xff;
+
+ /* System memory space */
+ pci_set_region(cpci_hose.regions + 0,
+ PCI_MEMORY_BUS,
+ PCI_MEMORY_PHYS,
+ PCI_MEMORY_MAXSIZE,
+ PCI_REGION_MEMORY);
+
+ /* PCI memory space */
+ pci_set_region(cpci_hose.regions + 1,
+ BRIDGE_CPCI_MEM_BUS,
+ BRIDGE_CPCI_MEM_PHYS,
+ BRIDGE_CPCI_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI I/O space */
+ pci_set_region(cpci_hose.regions + 2,
+ BRIDGE_CPCI_IO_BUS,
+ BRIDGE_CPCI_IO_PHYS,
+ BRIDGE_CPCI_IO_SIZE,
+ PCI_REGION_IO);
+
+ cpci_hose.region_count = 3;
+
+ pci_setup_indirect(&cpci_hose,
+ BRIDGE_CPCI_PHYS + HW_BRIDGE_CFGADDR,
+ BRIDGE_CPCI_PHYS + HW_BRIDGE_CFGDATA);
+
+ pci_register_hose(&cpci_hose);
+
+ /* Initialize PCI64 bus registers */
+ pci_hose_write_config_byte(&cpci_hose,
+ PCI_BDF(cpci_hose.first_busno,0,0),
+ CPC710_BUS_NUMBER,
+ cpci_hose.first_busno);
+ pci_hose_write_config_byte(&cpci_hose,
+ PCI_BDF(cpci_hose.first_busno,0,0),
+ CPC710_SUB_BUS_NUMBER,
+ cpci_hose.last_busno);
+
+ cpci_hose.last_busno = pci_hose_scan(&cpci_hose);
+
+ /* Write out correct max subordinate bus number for cpci hose */
+ pci_hose_write_config_byte(&cpci_hose,
+ PCI_BDF(cpci_hose.first_busno,0,0),
+ CPC710_SUB_BUS_NUMBER,
+ cpci_hose.last_busno);
+}
diff --git a/board/pcippc2/i2c.c b/board/pcippc2/i2c.c
new file mode 100644
index 0000000000..36b1d0f44d
--- /dev/null
+++ b/board/pcippc2/i2c.c
@@ -0,0 +1,257 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+
+#include "hardware.h"
+#include "i2c.h"
+
+static void i2c_start (void);
+static void i2c_stop (void);
+static int i2c_write (u8 data);
+static void i2c_read (u8 * data);
+
+static inline void i2c_port_start (void);
+static inline void i2c_clock (unsigned int val);
+static inline void i2c_data (unsigned int val);
+static inline unsigned int
+ i2c_in (void);
+static inline void i2c_write_bit (unsigned int val);
+static inline unsigned int
+ i2c_read_bit (void);
+
+static inline void i2c_udelay (unsigned int time);
+
+int i2c_read_byte (
+ u8 * data,
+ u8 dev,
+ u8 offset)
+{
+ int err = 0;
+
+ i2c_start();
+
+ err = ! i2c_write(dev);
+
+ if (! err)
+ {
+ err = ! i2c_write(offset);
+ }
+
+ if (! err)
+ {
+ i2c_start();
+ }
+
+ if (! err)
+ {
+ err = ! i2c_write(dev | 0x01);
+ }
+
+ if (! err)
+ {
+ i2c_read(data);
+ }
+
+ i2c_stop();
+
+ return ! err;
+}
+
+static inline void i2c_udelay (
+ unsigned int time)
+{
+ int v;
+
+ asm volatile("mtdec %0" : : "r" (time * ((CFG_BUS_CLK / 4) / 1000000)));
+
+ do
+ {
+ asm volatile("isync; mfdec %0" : "=r" (v));
+ } while (v >= 0);
+}
+
+ /* Low-level hardware access
+ */
+
+#define BIT_GPDATA 0x80000000
+#define BIT_GPCLK 0x40000000
+
+static inline void i2c_port_start (void)
+{
+ out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~(BIT_GPCLK | BIT_GPDATA));
+ out32(REG(CPC0, GPOUT), in32(REG(CPC0, GPOUT)) & ~(BIT_GPCLK | BIT_GPDATA));
+ iobarrier_rw();
+
+ i2c_udelay(1);
+}
+
+static inline void i2c_clock (
+ unsigned int val)
+{
+ if (val)
+ {
+ out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPCLK);
+ }
+ else
+ {
+ out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPCLK);
+ }
+
+ iobarrier_rw();
+
+ i2c_udelay(1);
+}
+
+static inline void i2c_data (
+ unsigned int val)
+{
+ if (val)
+ {
+ out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPDATA);
+ }
+ else
+ {
+ out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPDATA);
+ }
+
+ iobarrier_rw();
+
+ i2c_udelay(1);
+}
+
+static inline unsigned int i2c_in (void)
+{
+ unsigned int val = ((in32(REG(CPC0, GPIN)) & BIT_GPDATA) != 0)?1:0;
+
+ iobarrier_rw();
+
+ return val;
+}
+
+
+ /* Protocol implementation
+ */
+
+static inline void i2c_write_bit (
+ unsigned int val)
+{
+ i2c_data(val);
+ i2c_udelay(10);
+ i2c_clock(1);
+ i2c_udelay(10);
+ i2c_clock(0);
+ i2c_udelay(10);
+}
+
+static inline unsigned int i2c_read_bit (void)
+{
+ unsigned int val;
+
+ i2c_data(1);
+ i2c_udelay(10);
+
+ i2c_clock(1);
+ i2c_udelay(10);
+
+ val = i2c_in();
+
+ i2c_clock(0);
+ i2c_udelay(10);
+
+ return val;
+}
+
+unsigned int i2c_reset (void)
+{
+ unsigned int val;
+ int i;
+
+ i2c_port_start();
+
+ i=0;
+ do {
+ i2c_udelay(10);
+ i2c_clock(0);
+ i2c_udelay(10);
+ i2c_clock(1);
+ i2c_udelay(10);
+ val = i2c_in();
+ i++;
+ } while ((i<9)&&(val==0));
+ return (val);
+}
+
+
+static void i2c_start (void)
+{
+ i2c_data(1);
+ i2c_clock(1);
+ i2c_udelay(10);
+ i2c_data(0);
+ i2c_udelay(10);
+ i2c_clock(0);
+ i2c_udelay(10);
+}
+
+static void i2c_stop (void)
+{
+ i2c_data(0);
+ i2c_udelay(10);
+ i2c_clock(1);
+ i2c_udelay(10);
+ i2c_data(1);
+ i2c_udelay(10);
+}
+
+static int i2c_write (
+ u8 data)
+{
+ unsigned int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ i2c_write_bit(data >> 7);
+ data <<= 1;
+ }
+
+ return i2c_read_bit() == 0;
+}
+
+static void i2c_read (
+ u8 * data)
+{
+ unsigned int i;
+ u8 val = 0;
+
+ for (i = 0; i < 8; i++)
+ {
+ val <<= 1;
+ val |= i2c_read_bit();
+ }
+
+ *data = val;
+ i2c_write_bit(1); /* NoAck */
+}
diff --git a/board/pcippc2/pcippc2.c b/board/pcippc2/pcippc2.c
new file mode 100644
index 0000000000..e1b065b0ce
--- /dev/null
+++ b/board/pcippc2/pcippc2.c
@@ -0,0 +1,214 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+#include <linux/mtd/doc2000.h>
+#include <watchdog.h>
+#include <pci.h>
+
+#include "hardware.h"
+#include "pcippc2.h"
+#include "sconsole.h"
+#include "fpga_serial.h"
+
+#if defined(CONFIG_WATCHDOG)
+
+static int pcippc2_wdt_init_done = 0;
+
+void pcippc2_wdt_init (void);
+
+#endif
+
+ /* Check board identity
+ */
+int checkboard (void)
+{
+#ifdef CONFIG_PCIPPC2
+ puts ("Board: Gespac PCIPPC-2\n");
+#else
+ puts ("Board: Gespac PCIPPC-6\n");
+#endif
+ return 0;
+}
+
+ /* RAM size is stored in CPC0_RGBAN1
+ */
+u32 pcippc2_sdram_size (void)
+{
+ return in32 (REG (CPC0, RGBAN1));
+}
+
+long initdram (int board_type)
+{
+ return cpc710_ram_init ();
+}
+
+void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ out32 (REG (CPC0, SPOR), 0);
+ iobarrier_rw ();
+ while (1);
+}
+
+int board_pre_init (void)
+{
+ out32 (REG (CPC0, RSTR), 0xC0000000);
+ iobarrier_rw ();
+
+ out32 (REG (CPC0, RSTR), 0xF0000000);
+ iobarrier_rw ();
+
+ out32 (REG (CPC0, UCTL), 0x00F80000);
+
+ out32 (REG (CPC0, SIOC0), 0x30000000);
+
+ out32 (REG (CPC0, ABCNTL), 0x00000000);
+
+ out32 (REG (CPC0, SESR), 0x00000000);
+ out32 (REG (CPC0, SEAR), 0x00000000);
+
+ /* Detect IBM Avignon CPC710 Revision */
+ if ((in32 (REG (CPC0, UCTL)) & 0x000000F0) == CPC710_TYPE_100P)
+ out32 (REG (CPC0, PGCHP), 0xA0000040);
+ else
+ out32 (REG (CPC0, PGCHP), 0x80800040);
+
+
+ out32 (REG (CPC0, ATAS), 0x709C2508);
+
+ iobarrier_rw ();
+
+ return 0;
+}
+
+void after_reloc (ulong dest_addr)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /* Jump to the main U-Boot board init code
+ */
+ board_init_r (gd, dest_addr);
+}
+
+int misc_init_r (void)
+{
+ pcippc2_fpga_init ();
+
+#if defined(CONFIG_WATCHDOG)
+ pcippc2_wdt_init ();
+#endif
+
+ fpga_serial_init (sconsole_get_baudrate ());
+
+ sconsole_putc = fpga_serial_putc;
+ sconsole_puts = fpga_serial_puts;
+ sconsole_getc = fpga_serial_getc;
+ sconsole_tstc = fpga_serial_tstc;
+ sconsole_setbrg = fpga_serial_setbrg;
+
+ sconsole_flush ();
+ return (0);
+}
+
+void pci_init (void)
+{
+ cpc710_pci_init ();
+
+ /* FPGA requires no retry timeouts to be enabled
+ */
+ cpc710_pci_enable_timeout ();
+}
+
+void doc_init (void)
+{
+ doc_probe (pcippc2_fpga1_phys + HW_FPGA1_DOC);
+}
+
+#if defined(CONFIG_WATCHDOG)
+
+void pcippc2_wdt_init (void)
+{
+ out16r (FPGA (WDT, PROG), 0xffff);
+ out8 (FPGA (WDT, CTRL), 0x1);
+
+ pcippc2_wdt_init_done = 1;
+}
+
+void pcippc2_wdt_done (void)
+{
+ out8 (FPGA (WDT, CTRL), 0x0);
+
+ pcippc2_wdt_init_done = 0;
+}
+
+void pcippc2_wdt_reset (void)
+{
+ if (pcippc2_wdt_init_done == 1)
+ out8 (FPGA (WDT, REFRESH), 0x56);
+}
+
+void watchdog_reset (void)
+{
+ int re_enable = disable_interrupts ();
+
+ pcippc2_wdt_reset ();
+ if (re_enable)
+ enable_interrupts ();
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_BSP)
+int do_wd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ switch (argc) {
+ case 1:
+ printf ("Watchdog timer status is %s\n",
+ pcippc2_wdt_init_done == 1 ? "on" : "off");
+
+ return 0;
+ case 2:
+ if (!strcmp(argv[1],"on")) {
+ pcippc2_wdt_init();
+ printf("Watchdog timer now is on\n");
+
+ return 0;
+
+ } else if (!strcmp(argv[1],"off")) {
+ pcippc2_wdt_done();
+ printf("Watchdog timer now is off\n");
+
+ return 0;
+
+ } else
+ break;
+ default:
+ break;
+ }
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+}
+
+#endif /* CFG_CMD_BSP */
+#endif /* CONFIG_WATCHDOG */
diff --git a/board/pn62/cmd_pn62.c b/board/pn62/cmd_pn62.c
new file mode 100644
index 0000000000..928f6c0943
--- /dev/null
+++ b/board/pn62/cmd_pn62.c
@@ -0,0 +1,164 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Grandegger, DENX Software Engineering, wg@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 <malloc.h>
+#include <net.h>
+#include <asm/io.h>
+#include <pci.h>
+#include <cmd_autoscript.h>
+#include <cmd_bsp.h>
+
+#include "pn62.h"
+
+#if (CONFIG_COMMANDS & CFG_CMD_BSP)
+
+extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
+
+/*
+ * Command led: controls the various LEDs 0..11 on the PN62 card.
+ */
+int do_led (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ unsigned int number, function;
+
+ if (argc != 3) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+ number = simple_strtoul(argv[1], NULL, 10);
+ if (number > PN62_LED_MAX)
+ return 1;
+ function = simple_strtoul(argv[2], NULL, 16);
+ set_led (number, function);
+ return 0;
+}
+
+/*
+ * Command loadpci: loads a image over PCI.
+ */
+#define CMD_MOVE_WINDOW 0x1
+#define CMD_BOOT_IMAGE 0x2
+
+int do_loadpci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *s;
+ ulong addr = 0, count = 0;
+ u32 off;
+ int cmd, rcode = 0;
+
+ /* pre-set load_addr */
+ if ((s = getenv("loadaddr")) != NULL) {
+ addr = simple_strtoul(s, NULL, 16);
+ }
+
+ switch (argc) {
+ case 1:
+ break;
+ case 2:
+ addr = simple_strtoul(argv[1], NULL, 16);
+ break;
+ default:
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ printf ("## Ready for image download ...\n");
+
+ show_startup_phase(12);
+
+ while (1) {
+ /* Alive indicator */
+ i2155x_write_scrapad(BOOT_PROTO, BOOT_PROTO_READY);
+
+ /* Toggle status LEDs */
+ cmd = (count / 200) % 4; /* downscale */
+ set_led(4, cmd == 0 ? LED_1 : LED_0);
+ set_led(5, cmd == 1 ? LED_1 : LED_0);
+ set_led(6, cmd == 2 ? LED_1 : LED_0);
+ set_led(7, cmd == 3 ? LED_1 : LED_0);
+ udelay(1000);
+ count++;
+
+ cmd = i2155x_read_scrapad(BOOT_CMD);
+
+ if (cmd == BOOT_CMD_MOVE) {
+ off = i2155x_read_scrapad(BOOT_DATA);
+ off += addr;
+ i2155x_set_bar_base(3, off);
+ printf ("## BAR3 Addr moved = 0x%08x\n", off);
+ i2155x_write_scrapad(BOOT_CMD, ~cmd);
+ show_startup_phase(13);
+ }
+ else if (cmd == BOOT_CMD_BOOT) {
+ set_led(4, LED_1);
+ set_led(5, LED_1);
+ set_led(6, LED_1);
+ set_led(7, LED_1);
+
+ i2155x_write_scrapad(BOOT_CMD, ~cmd);
+ show_startup_phase(14);
+ break;
+ }
+
+ /* Abort if ctrl-c was pressed */
+ if (ctrlc()) {
+ printf("\nAbort\n");
+ return 0;
+ }
+
+ }
+
+ /* Repoint to the default shared memory */
+ i2155x_set_bar_base(3, PN62_SMEM_DEFAULT);
+
+ load_addr = addr;
+ printf ("## Start Addr = 0x%08lx\n", addr);
+
+ show_startup_phase(15);
+
+ /* Loading ok, check if we should attempt an auto-start */
+ if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) {
+ char *local_args[2];
+ local_args[0] = argv[0];
+ local_args[1] = NULL;
+
+ printf ("Automatic boot of image at addr 0x%08lX ...\n",
+ load_addr);
+ rcode = do_bootm (cmdtp, 0, 1, local_args);
+ }
+
+#ifdef CONFIG_AUTOSCRIPT
+ if (load_addr) {
+ char *s;
+
+ if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
+ printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
+ rcode = autoscript (bd, load_addr);
+ }
+ }
+#endif
+ return rcode;
+}
+
+#endif
diff --git a/board/pn62/misc.c b/board/pn62/misc.c
new file mode 100644
index 0000000000..4f71950f8a
--- /dev/null
+++ b/board/pn62/misc.c
@@ -0,0 +1,235 @@
+/*
+ * (C) Copyright 2002 Wolfgang Grandegger <wg@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/io.h>
+#include <pci.h>
+
+#include "pn62.h"
+
+typedef struct {
+ pci_dev_t devno;
+ volatile u32 *csr;
+
+} i2155x_t;
+
+static i2155x_t i2155x = { 0, NULL };
+
+static struct pci_device_id i2155x_ids[] = {
+ { 0x1011, 0x0046 }, /* i21554 */
+ { 0x8086, 0xb555 } /* i21555 */
+};
+
+int i2155x_init(void)
+{
+ pci_dev_t devno;
+ u32 val;
+ int i;
+
+ /*
+ * Find the Intel bridge.
+ */
+ if ((devno = pci_find_devices(i2155x_ids, 0)) < 0) {
+ printf("Error: Intel bridge 2155x not found!\n");
+ return -1;
+ }
+ i2155x.devno = devno;
+
+ /*
+ * Get auto-configured base address for CSR access.
+ */
+ pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &val);
+ if (val & PCI_BASE_ADDRESS_SPACE_IO) {
+ val &= PCI_BASE_ADDRESS_IO_MASK;
+ i2155x.csr = (volatile u32 *)(_IO_BASE + val);
+ } else {
+ val &= PCI_BASE_ADDRESS_MEM_MASK;
+ i2155x.csr = (volatile u32 *)val;
+ }
+
+ /*
+ * Translate downstream memory 2 (bar3) to base of shared memory.
+ */
+ i2155x_set_bar_base(3, PN62_SMEM_DEFAULT);
+
+ /*
+ * Enable memory space, I/O space and bus master bits
+ * in both Primary and Secondary command registers.
+ */
+ val = PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+ pci_write_config_word(devno, 0x44, val);
+ pci_write_config_word(devno, 0x04, val);
+
+ /*
+ * Clear scratchpad registers.
+ */
+ for (i = 0; i < (I2155X_SCRAPAD_MAX - 1); i++) {
+ i2155x_write_scrapad(i, 0x0);
+ }
+
+ /*
+ * Set interrupt line for Linux.
+ */
+ pci_write_config_byte(devno, PCI_INTERRUPT_LINE, 3);
+
+ return 0;
+}
+
+/*
+ * Access the Scratchpad registers 0..7 of the Intel bridge.
+ */
+void i2155x_write_scrapad(int idx, u32 val)
+{
+ if (idx >= 0 && idx < I2155X_SCRAPAD_MAX)
+ out_le32(i2155x.csr + (I2155X_SCRAPAD_ADDR/4) + idx, val);
+ else
+ printf("i2155x_write_scrapad: invalid index\n");
+}
+
+u32 i2155x_read_scrapad(int idx)
+{
+ if (idx >= 0 && idx < I2155X_SCRAPAD_MAX)
+ return in_le32(i2155x.csr + (I2155X_SCRAPAD_ADDR/4) + idx);
+ else
+ printf("i2155x_read_scrapad: invalid index\n");
+ return -1;
+}
+
+void i2155x_set_bar_base(int bar, u32 base)
+{
+ if (bar >= 2 && bar <= 4) {
+ pci_write_config_dword(i2155x.devno,
+ I2155X_BAR2_BASE + (bar - 2) * 4,
+ base);
+ }
+}
+
+/*
+ * Read Vital Product Data (VPD) from the Serial EPROM attached
+ * to the Intel bridge.
+ */
+int i2155x_read_vpd(int offset, int size, unsigned char *data)
+{
+ int i, n;
+ u16 val16;
+
+ for (i = 0; i < size; i++) {
+ pci_write_config_word(i2155x.devno, I2155X_VPD_ADDR,
+ offset + i - I2155X_VPD_START);
+ for (n = 10000; n > 0; n--) {
+ pci_read_config_word(i2155x.devno, I2155X_VPD_ADDR, &val16);
+ if ((val16 & 0x8000) != 0) /* wait for completion */
+ break;
+ udelay(100);
+ }
+ if (n == 0) {
+ printf("i2155x_read_vpd: TIMEOUT\n");
+ return -1;
+ }
+
+ pci_read_config_byte(i2155x.devno, I2155X_VPD_DATA, &data[i]);
+ }
+
+ return i;
+}
+
+static struct pci_device_id am79c95x_ids [] = {
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE },
+ { }
+};
+
+
+/*
+ * Initialize the AMD ethernet controllers.
+ */
+int am79c95x_init(void)
+{
+ pci_dev_t devno;
+ int i;
+
+ /*
+ * Set interrupt line for Linux.
+ */
+ for (i = 0; i < 2; i++) {
+ if ((devno = pci_find_devices(am79c95x_ids, i)) < 0)
+ break;
+ pci_write_config_byte(devno, PCI_INTERRUPT_LINE, 2+i);
+ }
+ if (i < 2)
+ printf("Error: Only %d AMD Ethernet Controller found!\n", i);
+
+ return 0;
+}
+
+
+void set_led(unsigned int number, unsigned int function)
+{
+ volatile u8 *addr;
+
+ if ((number >= 0) && (number < PN62_LED_MAX) &&
+ (function >= 0) && (function <= LED_LAST_FUNCTION)) {
+ addr = (volatile u8 *)(PN62_LED_BASE + number * 8);
+ out_8(addr, function&0xff);
+ }
+}
+
+/*
+ * Show fatal error indicated by Kinght Rider(tm) effect
+ * in LEDS 0-7. LEDS 8-11 contain 4 bit error code.
+ * Note: this function will not terminate.
+ */
+void fatal_error(unsigned int error_code)
+{
+ int i, d;
+
+ for (i = 0; i < 12; i++) {
+ set_led(i, LED_0);
+ }
+
+ /*
+ * Write error code.
+ */
+ set_led(8, (error_code & 0x01) ? LED_1 : LED_0);
+ set_led(9, (error_code & 0x02) ? LED_1 : LED_0);
+ set_led(10, (error_code & 0x04) ? LED_1 : LED_0);
+ set_led(11, (error_code & 0x08) ? LED_1 : LED_0);
+
+ /*
+ * Yay - Knight Rider effect!
+ */
+ while(1) {
+ unsigned int delay = 2000;
+
+ for (i = 0; i < 8; i++) {
+ set_led(i, LED_1);
+ for (d = 0; d < delay; d++);
+ set_led(i, LED_0);
+ }
+
+ for (i = 7; i > 0; i--) {
+ set_led(i, LED_1);
+ for (d = 0; d < delay; d++);
+ set_led(i, LED_0);
+ }
+ }
+}
diff --git a/board/pn62/pn62.c b/board/pn62/pn62.c
new file mode 100644
index 0000000000..4d87527152
--- /dev/null
+++ b/board/pn62/pn62.c
@@ -0,0 +1,216 @@
+/*
+ * (C) Copyright 2002 Wolfgang Grandegger <wg@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 <pci.h>
+
+#include "pn62.h"
+
+
+static int get_serial_number (char *string, int size);
+static int get_mac_address (int id, u8 * mac, char *string, int size);
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+void show_boot_progress (int phase)
+{
+ /*
+ * Show phases of the bootm command on the front panel
+ * LEDs and the scratchpad register #3 as well. We use
+ * blinking LEDs for logical "1".
+ */
+ if (phase > 0) {
+ set_led (8, (phase & 0x1) ? LED_SLOW_CLOCK : LED_0);
+ set_led (9, (phase & 0x2) ? LED_SLOW_CLOCK : LED_0);
+ set_led (10, (phase & 0x4) ? LED_SLOW_CLOCK : LED_0);
+ set_led (11, (phase & 0x8) ? LED_SLOW_CLOCK : LED_0);
+ }
+ i2155x_write_scrapad (BOOT_STATUS, phase);
+ if (phase < 0)
+ i2155x_write_scrapad (BOOT_DONE, BOOT_DONE_ERROR);
+}
+#endif
+
+void show_startup_phase (int phase)
+{
+ /*
+ * Show the phase of U-Boot startup on the front panel
+ * LEDs and the scratchpad register #3 as well.
+ */
+ if (phase > 0) {
+ set_led (8, (phase & 0x1) ? LED_1 : LED_0);
+ set_led (9, (phase & 0x2) ? LED_1 : LED_0);
+ set_led (10, (phase & 0x4) ? LED_1 : LED_0);
+ set_led (11, (phase & 0x8) ? LED_1 : LED_0);
+ }
+ i2155x_write_scrapad (BOOT_STATUS, phase);
+ if (phase < 0)
+ i2155x_write_scrapad (BOOT_DONE, BOOT_DONE_ERROR);
+}
+
+int checkboard (void)
+{
+ show_startup_phase (1);
+ puts ("Board: PN62\n");
+ return 0;
+}
+
+long int initdram (int board_type)
+{
+ int i, cnt;
+ volatile uchar *base = CFG_SDRAM_BASE;
+ volatile ulong *addr;
+ ulong save[32];
+ ulong val, ret = 0;
+
+ show_startup_phase (2);
+
+ for (i = 0, cnt = (CFG_MAX_RAM_SIZE / sizeof (long)) >> 1; cnt > 0;
+ cnt >>= 1) {
+ addr = (volatile ulong *) base + cnt;
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ addr = (volatile ulong *) base;
+ save[i] = *addr;
+ *addr = 0;
+
+ if (*addr != 0) {
+ *addr = save[i];
+ goto Done;
+ }
+
+ for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof (long); cnt <<= 1) {
+ addr = (volatile ulong *) base + cnt;
+ val = *addr;
+ *addr = save[--i];
+ if (val != ~cnt) {
+ ulong new_bank0_end = cnt * sizeof (long) - 1;
+ ulong mear1 = mpc824x_mpc107_getreg (MEAR1);
+ ulong emear1 = mpc824x_mpc107_getreg (EMEAR1);
+
+ mear1 = (mear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT);
+ emear1 = (emear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT);
+ mpc824x_mpc107_setreg (MEAR1, mear1);
+ mpc824x_mpc107_setreg (EMEAR1, emear1);
+
+ ret = cnt * sizeof (long);
+ goto Done;
+ }
+ }
+
+ ret = CFG_MAX_RAM_SIZE;
+ Done:
+ show_startup_phase (3);
+ return ret;
+}
+
+/*
+ * Initialize PCI Devices. We rely on auto-configuration.
+ */
+#ifndef CONFIG_PCI_PNP
+#error "CONFIG_PCI_PNP is not defined, please correct!"
+#endif
+
+struct pci_controller hose = {
+};
+
+void pci_init (void)
+{
+ show_startup_phase (4);
+ pci_mpc824x_init (&hose);
+
+ show_startup_phase (5);
+ i2155x_init ();
+ show_startup_phase (6);
+ am79c95x_init ();
+ show_startup_phase (7);
+}
+
+int misc_init_r (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ char str[20];
+ u8 mac[6];
+
+ show_startup_phase (8);
+ /*
+ * Get serial number and ethernet addresses if not already defined
+ * and update the board info structure and the environment.
+ */
+ if (getenv ("serial#") == NULL &&
+ get_serial_number (str, strlen (str)) > 0) {
+ setenv ("serial#", str);
+ }
+ show_startup_phase (9);
+
+ if (getenv ("ethaddr") == NULL &&
+ get_mac_address (0, mac, str, sizeof (str)) > 0) {
+ setenv ("ethaddr", str);
+ memcpy (gd->bd->bi_enetaddr, mac, 6);
+ }
+ show_startup_phase (10);
+
+ if (getenv ("eth1addr") == NULL &&
+ get_mac_address (1, mac, str, sizeof (str)) > 0) {
+ setenv ("eth1addr", str);
+ memcpy (gd->bd->bi_enet1addr, mac, 6);
+ }
+ show_startup_phase (11);
+
+ /* Tell everybody that U-Boot is up and runnig */
+ i2155x_write_scrapad (0, 0x12345678);
+ return (0);
+}
+
+static int get_serial_number (char *string, int size)
+{
+ int i;
+ char c;
+
+ if (size < I2155X_VPD_SN_SIZE)
+ size = I2155X_VPD_SN_SIZE;
+ for (i = 0; i < (size - 1); i++) {
+ i2155x_read_vpd (I2155X_VPD_SN_START + i, 1, &c);
+ if (c == '\0')
+ break;
+ string[i] = c;
+ }
+ string[i] = '\0'; /* make sure it's terminated */
+
+ return i;
+}
+
+static int get_mac_address (int id, u8 * mac, char *string, int size)
+{
+ if (size < 6 * 3)
+ return -1;
+
+ i2155x_read_vpd (I2155X_VPD_MAC0_START + 6 * id, 6, mac);
+ return sprintf (string, "%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+}
diff --git a/board/r360mpi/r360mpi.c b/board/r360mpi/r360mpi.c
new file mode 100644
index 0000000000..d7b8873ee3
--- /dev/null
+++ b/board/r360mpi/r360mpi.c
@@ -0,0 +1,423 @@
+/*
+ * (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
+ */
+
+#include <common.h>
+#include <config.h>
+#include <mpc8xx.h>
+#include <i2c.h>
+
+#include <commproc.h>
+#include <command.h>
+#include <cmd_bsp.h>
+#include <malloc.h>
+
+#include <linux/types.h>
+#include <linux/string.h> /* for strdup */
+
+
+/*
+ * Memory Controller Using
+ *
+ * CS0 - Flash memory (0x40000000)
+ * CS1 - SDRAM (0x00000000}
+ * CS2 -
+ * CS3 -
+ * CS4 -
+ * CS5 -
+ * CS6 - PCMCIA device
+ * CS7 - PCMCIA device
+ */
+
+/* ------------------------------------------------------------------------- */
+
+#define _not_used_ 0xffffffff
+
+const uint sdram_table[]=
+{
+ /* single read. (offset 0 in upm RAM) */
+ 0x1f07fc04, 0xeeaefc04, 0x11adfc04, 0xefbbbc00,
+ 0x1ff77c47,
+
+ /* MRS initialization (offset 5) */
+
+ 0x1ff77c34, 0xefeabc34, 0x1fb57c35,
+
+ /* burst read. (offset 8 in upm RAM) */
+ 0x1f07fc04, 0xeeaefc04, 0x10adfc04, 0xf0affc00,
+ 0xf0affc00, 0xf1affc00, 0xefbbbc00, 0x1ff77c47,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+
+ /* single write. (offset 18 in upm RAM) */
+ 0x1f27fc04, 0xeeaebc00, 0x01b93c04, 0x1ff77c47,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+
+ /* burst write. (offset 20 in upm RAM) */
+ 0x1f07fc04, 0xeeaebc00, 0x10ad7c00, 0xf0affc00,
+ 0xf0affc00, 0xe1bbbc04, 0x1ff77c47, _not_used_,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+
+ /* refresh. (offset 30 in upm RAM) */
+ 0x1ff5fc84, 0xfffffc04, 0xfffffc04, 0xfffffc04,
+ 0xfffffc84, 0xfffffc07, _not_used_, _not_used_,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+
+ /* exception. (offset 3c in upm RAM) */
+ 0x7ffffc07, _not_used_, _not_used_, _not_used_ };
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Check Board Identity:
+ */
+
+int checkboard (void)
+{
+ puts ("Board: R360 MPI Board\n");
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static long int dram_size (long int, long int *, long int);
+
+/* ------------------------------------------------------------------------- */
+
+long int initdram (int board_type)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ long int size8, size9;
+ long int size_b0 = 0;
+ unsigned long reg;
+
+ upmconfig (UPMA, (uint *) sdram_table,
+ sizeof (sdram_table) / sizeof (uint));
+
+ /*
+ * Preliminary prescaler for refresh (depends on number of
+ * banks): This value is selected for four cycles every 62.4 us
+ * with two SDRAM banks or four cycles every 31.2 us with one
+ * bank. It will be adjusted after memory sizing.
+ */
+ memctl->memc_mptpr = CFG_MPTPR_2BK_8K;
+
+ memctl->memc_mar = 0x00000088;
+
+ /*
+ * Map controller bank 1 to the SDRAM bank at
+ * preliminary address - these have to be modified after the
+ * SDRAM size has been determined.
+ */
+ memctl->memc_or1 = CFG_OR1_PRELIM;
+ memctl->memc_br1 = CFG_BR1_PRELIM;
+
+ memctl->memc_mamr = CFG_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */
+
+ udelay (200);
+
+ /* perform SDRAM initializsation sequence */
+
+ memctl->memc_mcr = 0x80002105; /* SDRAM bank 0 */
+ udelay (200);
+ memctl->memc_mcr = 0x80002230; /* SDRAM bank 0 - execute twice */
+ udelay (200);
+
+ memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */
+
+ udelay (1000);
+
+ /*
+ * Check Bank 0 Memory Size for re-configuration
+ *
+ * try 8 column mode
+ */
+ size8 = dram_size (CFG_MAMR_8COL, (ulong *) SDRAM_BASE1_PRELIM,
+ SDRAM_MAX_SIZE);
+
+ udelay (1000);
+
+ /*
+ * try 9 column mode
+ */
+ size9 = dram_size (CFG_MAMR_9COL, (ulong *) SDRAM_BASE1_PRELIM,
+ SDRAM_MAX_SIZE);
+
+ if (size8 < size9) { /* leave configuration at 9 columns */
+ size_b0 = size9;
+/* debug ("SDRAM Bank 0 in 9 column mode: %ld MB\n", size >> 20); */
+ } else { /* back to 8 columns */
+ size_b0 = size8;
+ memctl->memc_mamr = CFG_MAMR_8COL;
+ udelay (500);
+/* debug ("SDRAM Bank 0 in 8 column mode: %ld MB\n", size >> 20); */
+ }
+
+ udelay (1000);
+
+ /*
+ * Adjust refresh rate depending on SDRAM type, both banks
+ * For types > 128 MBit leave it at the current (fast) rate
+ */
+ if ((size_b0 < 0x02000000)) {
+ /* reduce to 15.6 us (62.4 us / quad) */
+ memctl->memc_mptpr = CFG_MPTPR_2BK_4K;
+ udelay (1000);
+ }
+
+ /*
+ * Final mapping
+ */
+
+ memctl->memc_or1 = ((-size_b0) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM;
+ memctl->memc_br1 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V;
+
+ /* adjust refresh rate depending on SDRAM type, one bank */
+ reg = memctl->memc_mptpr;
+ reg >>= 1; /* reduce to CFG_MPTPR_1BK_8K / _4K */
+ memctl->memc_mptpr = reg;
+
+ udelay (10000);
+
+ return (size_b0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Check memory range for valid RAM. A simple memory test determines
+ * the actually available RAM size between addresses `base' and
+ * `base + maxsize'. Some (not all) hardware errors are detected:
+ * - short between address lines
+ * - short between data lines
+ */
+
+static long int dram_size (long int mamr_value, long int *base,
+ long int maxsize)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ volatile long int *addr;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
+
+ memctl->memc_mamr = mamr_value;
+
+ for (cnt = maxsize / sizeof (long); cnt > 0; cnt >>= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ /* write 0 to base address */
+ addr = base;
+ save[i] = *addr;
+ *addr = 0;
+
+ /* check at base address */
+ if ((val = *addr) != 0) {
+ *addr = save[i];
+ return (0);
+ }
+
+ for (cnt = 1; cnt <= maxsize / sizeof (long); cnt <<= 1) {
+ addr = base + cnt; /* pointer arith! */
+ val = *addr;
+ *addr = save[--i];
+
+ if (val != (~cnt)) {
+ return (cnt * sizeof (long));
+ }
+ }
+ return (maxsize);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void r360_pwm_write (uchar reg, uchar val)
+{
+ if (i2c_write (CFG_I2C_PWM_ADDR, reg, 1, &val, 1)) {
+ printf ("Can't write PWM register 0x%02X.\n", reg);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*-----------------------------------------------------------------------
+ * Keyboard Controller
+ */
+
+/* Number of bytes returned from Keyboard Controller */
+#define KEYBD_KEY_MAX 20 /* maximum key number */
+#define KEYBD_DATALEN ((KEYBD_KEY_MAX + 7) / 8) /* normal key scan data */
+
+static uchar kbd_addr = CFG_I2C_KBD_ADDR;
+
+static uchar *key_match (uchar *);
+
+int misc_init_r (void)
+{
+ uchar kbd_data[KEYBD_DATALEN];
+ uchar keybd_env[2 * KEYBD_DATALEN + 1];
+ uchar *str;
+ int i;
+
+ i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+
+ i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
+
+ for (i = 0; i < KEYBD_DATALEN; ++i) {
+ sprintf (keybd_env + i + i, "%02X", kbd_data[i]);
+ }
+ setenv ("keybd", keybd_env);
+
+ str = strdup (key_match (kbd_data)); /* decode keys */
+
+#ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */
+ setenv ("preboot", str); /* set or delete definition */
+#endif /* CONFIG_PREBOOT */
+ if (str != NULL) {
+ free (str);
+ }
+
+ return (0);
+}
+
+/*-----------------------------------------------------------------------
+ * Check if pressed key(s) match magic sequence,
+ * and return the command string associated with that key(s).
+ *
+ * If no key press was decoded, NULL is returned.
+ *
+ * Note: the first character of the argument will be overwritten with
+ * the "magic charcter code" of the decoded key(s), or '\0'.
+ *
+ *
+ * Note: the string points to static environment data and must be
+ * saved before you call any function that modifies the environment.
+ */
+#ifdef CONFIG_PREBOOT
+
+static uchar kbd_magic_prefix[] = "key_magic";
+static uchar kbd_command_prefix[] = "key_cmd";
+
+static uchar *key_match (uchar * kbd_data)
+{
+ uchar compare[KEYBD_DATALEN];
+ uchar magic[sizeof (kbd_magic_prefix) + 1];
+ uchar cmd_name[sizeof (kbd_command_prefix) + 1];
+ uchar key_mask;
+ uchar *str, *nxt, *suffix;
+ uchar *kbd_magic_keys;
+ char *cmd;
+ int i;
+
+ /*
+ * The following string defines the characters that can pe appended
+ * to "key_magic" to form the names of environment variables that
+ * hold "magic" key codes, i. e. such key codes that can cause
+ * pre-boot actions. If the string is empty (""), then only
+ * "key_magic" is checked (old behaviour); the string "125" causes
+ * checks for "key_magic1", "key_magic2" and "key_magic5", etc.
+ */
+ if ((kbd_magic_keys = getenv ("magic_keys")) == NULL)
+ kbd_magic_keys = "";
+
+ /* loop over all magic keys;
+ * use '\0' suffix in case of empty string
+ */
+ for (suffix=kbd_magic_keys; *suffix || suffix==kbd_magic_keys; ++suffix) {
+ sprintf (magic, "%s%c", kbd_magic_prefix, *suffix);
+#if 0
+ printf ("### Check magic \"%s\"\n", magic);
+#endif
+
+ memcpy(compare, kbd_data, KEYBD_DATALEN);
+
+ for (str = getenv(magic); str != NULL; str = (*nxt) ? nxt+1 : nxt) {
+ uchar c;
+
+ c = (uchar) simple_strtoul (str, (char **) (&nxt), 16);
+
+ if (str == nxt) /* invalid character */
+ break;
+
+ if (c >= KEYBD_KEY_MAX) /* bad key number */
+ goto next_magic;
+
+ key_mask = 0x80 >> (c % 8);
+
+ if (!(compare[c / 8] & key_mask)) /* key not pressed */
+ goto next_magic;
+
+ compare[c / 8] &= ~key_mask;
+ }
+
+ for (i=0; i<KEYBD_DATALEN; i++)
+ if (compare[i]) /* key(s) not released */
+ goto next_magic;
+
+ sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix);
+
+ cmd = getenv (cmd_name);
+#if 0
+ printf ("### Set PREBOOT to $(%s): \"%s\"\n",
+ cmd_name, cmd ? cmd : "<<NULL>>");
+#endif
+ *kbd_data = *suffix;
+ return (cmd);
+
+ next_magic:;
+ }
+#if 0
+ printf ("### Delete PREBOOT\n");
+#endif
+ *kbd_data = '\0';
+ return (NULL);
+}
+#endif /* CONFIG_PREBOOT */
+
+/* Read Keyboard status */
+int do_kbd (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ uchar kbd_data[KEYBD_DATALEN];
+ uchar keybd_env[2 * KEYBD_DATALEN + 1];
+ int i;
+
+ i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+
+ /* Read keys */
+ i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
+
+ puts ("Keys:");
+ for (i = 0; i < KEYBD_DATALEN; ++i) {
+ sprintf (keybd_env + i + i, "%02X", kbd_data[i]);
+ printf (" %02x", kbd_data[i]);
+ }
+ putc ('\n');
+ setenv ("keybd", keybd_env);
+ return 0;
+}
diff --git a/board/sacsng/clkinit.c b/board/sacsng/clkinit.c
new file mode 100644
index 0000000000..1e851e14d8
--- /dev/null
+++ b/board/sacsng/clkinit.c
@@ -0,0 +1,884 @@
+/*
+ * (C) Copyright 2002
+ * Custom IDEAS, Inc. <www.cideas.com>
+ * Jon Diekema <diekema@cideas.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 <ioports.h>
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+#include <configs/sacsng.h>
+
+#include "clkinit.h"
+
+int Daq64xSampling = 0;
+
+
+void Daq_BRG_Reset(uint brg)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile uint *brg_ptr;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ brg_ptr += brg;
+ *brg_ptr |= CPM_BRG_RST;
+ *brg_ptr &= ~CPM_BRG_RST;
+}
+
+void Daq_BRG_Disable(uint brg)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile uint *brg_ptr;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ brg_ptr += brg;
+ *brg_ptr &= ~CPM_BRG_EN;
+}
+
+void Daq_BRG_Enable(uint brg)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile uint *brg_ptr;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ brg_ptr += brg;
+ *brg_ptr |= CPM_BRG_EN;
+}
+
+uint Daq_BRG_Get_Div16(uint brg)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uint *brg_ptr;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ brg_ptr += brg;
+
+ if (*brg_ptr & CPM_BRG_DIV16) {
+ /* DIV16 active */
+ return (TRUE);
+ }
+ else {
+ /* DIV16 inactive */
+ return (FALSE);
+ }
+}
+
+void Daq_BRG_Set_Div16(uint brg, uint div16)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uint *brg_ptr;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ brg_ptr += brg;
+
+ if (div16) {
+ /* DIV16 active */
+ *brg_ptr |= CPM_BRG_DIV16;
+ }
+ else {
+ /* DIV16 inactive */
+ *brg_ptr &= ~CPM_BRG_DIV16;
+ }
+}
+
+uint Daq_BRG_Get_Count(uint brg)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uint *brg_ptr;
+ uint brg_cnt;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ brg_ptr += brg;
+
+ /* Get the clock divider
+ *
+ * Note: A clock divider of 0 means divide by 1,
+ * therefore we need to add 1 to the count.
+ */
+ brg_cnt = (*brg_ptr & CPM_BRG_CD_MASK) >> CPM_BRG_DIV16_SHIFT;
+ brg_cnt++;
+ if (*brg_ptr & CPM_BRG_DIV16) {
+ brg_cnt *= 16;
+ }
+
+ return (brg_cnt);
+}
+
+void Daq_BRG_Set_Count(uint brg, uint brg_cnt)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uint *brg_ptr;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ brg_ptr += brg;
+
+ /*
+ * Note: A clock divider of 0 means divide by 1,
+ * therefore we need to subtract 1 from the count.
+ */
+ if (brg_cnt > 4096) {
+ /* Prescale = Divide by 16 */
+ *brg_ptr = (*brg_ptr & ~CPM_BRG_CD_MASK) |
+ (((brg_cnt / 16) - 1) << CPM_BRG_DIV16_SHIFT);
+ *brg_ptr |= CPM_BRG_DIV16;
+ }
+ else {
+ /* Prescale = Divide by 1 */
+ *brg_ptr = (*brg_ptr & ~CPM_BRG_CD_MASK) |
+ ((brg_cnt - 1) << CPM_BRG_DIV16_SHIFT);
+ *brg_ptr &= ~CPM_BRG_DIV16;
+ }
+}
+
+uint Daq_BRG_Get_ExtClk(uint brg)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uint *brg_ptr;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ brg_ptr += brg;
+
+ return ((*brg_ptr & CPM_BRG_EXTC_MASK) >> CPM_BRG_EXTC_SHIFT);
+}
+
+char* Daq_BRG_Get_ExtClk_Description(uint brg)
+{
+ uint extc;
+
+ extc = Daq_BRG_Get_ExtClk(brg);
+
+ switch (brg + 1) {
+ case 1:
+ case 2:
+ case 5:
+ case 6: {
+ switch (extc) {
+ case 0: {
+ return ("BRG_INT");
+ }
+ case 1: {
+ return ("CLK3");
+ }
+ case 2: {
+ return ("CLK5");
+ }
+ }
+ return ("??1245??");
+ }
+ case 3:
+ case 4:
+ case 7:
+ case 8: {
+ switch (extc) {
+ case 0: {
+ return ("BRG_INT");
+ }
+ case 1: {
+ return ("CLK9");
+ }
+ case 2: {
+ return ("CLK15");
+ }
+ }
+ return ("??3478??");
+ }
+ }
+ return ("??9876??");
+}
+
+void Daq_BRG_Set_ExtClk(uint brg, uint extc)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uint *brg_ptr;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ brg_ptr += brg;
+
+ *brg_ptr = (*brg_ptr & ~CPM_BRG_EXTC_MASK) |
+ ((extc << CPM_BRG_EXTC_SHIFT) & CPM_BRG_EXTC_MASK);
+}
+
+uint Daq_BRG_Rate(uint brg)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uint *brg_ptr;
+ uint brg_cnt;
+ uint brg_freq = 0;
+
+ brg_ptr = (uint *)&immr->im_brgc1;
+ brg_ptr += brg;
+ if (brg >= 5) {
+ brg_ptr = (uint *)&immr->im_brgc5;
+ brg_ptr += (brg - 4);
+ }
+
+ brg_cnt = Daq_BRG_Get_Count(brg);
+
+ switch (Daq_BRG_Get_ExtClk(brg)) {
+ case CPM_BRG_EXTC_CLK3:
+ case CPM_BRG_EXTC_CLK5: {
+ brg_freq = brg_cnt;
+ break;
+ }
+ default: {
+ brg_freq = (uint)BRG_INT_CLK / brg_cnt;
+ }
+ }
+ return (brg_freq);
+}
+
+uint Daq_Get_SampleRate(void)
+
+{
+ /*
+ * Read the BRG's to return the actual sample rate.
+ */
+ return (Daq_BRG_Rate(MCLK_BRG) / (MCLK_DIVISOR * SCLK_DIVISOR));
+}
+
+uint Daq_Set_SampleRate(uint rate, uint force)
+
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ uint mclk_divisor; /* MCLK divisor */
+ uint rate_curr; /* Current sample rate */
+
+ /*
+ * Limit the sample rate to some sensible values.
+ */
+ if (Daq64xSampling) {
+ if (rate > MAX_64x_SAMPLE_RATE) {
+ rate = MAX_64x_SAMPLE_RATE;
+ }
+ }
+ else {
+ if (rate > MAX_128x_SAMPLE_RATE) {
+ rate = MAX_128x_SAMPLE_RATE;
+ }
+ }
+ if (rate < MIN_SAMPLE_RATE) {
+ rate = MIN_SAMPLE_RATE;
+ }
+
+ /* Check to see if we are really changing rates */
+ rate_curr = Daq_Get_SampleRate();
+ if ((rate != rate_curr) || force) {
+ /*
+ * Dynamically adjust MCLK based on the new sample rate.
+ */
+
+ /* Compute the divisors */
+ mclk_divisor = BRG_INT_CLK / (rate * MCLK_DIVISOR * SCLK_DIVISOR);
+
+ /* Setup MCLK */
+ Daq_BRG_Set_Count(MCLK_BRG, mclk_divisor);
+
+ /* Setup SCLK */
+# ifdef RUN_SCLK_ON_BRG_INT
+ Daq_BRG_Set_Count(SCLK_BRG, mclk_divisor * MCLK_DIVISOR);
+# else
+ Daq_BRG_Set_Count(SCLK_BRG, MCLK_DIVISOR);
+# endif
+
+# ifdef RUN_LRCLK_ON_BRG_INT
+ Daq_BRG_Set_Count(LRCLK_BRG,
+ mclk_divisor * MCLK_DIVISOR * SCLK_DIVISOR);
+# else
+ Daq_BRG_Set_Count(LRCLK_BRG, SCLK_DIVISOR);
+# endif
+
+ /* Read the BRG's to return the actual sample rate. */
+ rate_curr = Daq_Get_SampleRate();
+ }
+
+ return (rate_curr);
+}
+
+void Daq_Init_Clocks(int sample_rate, int sample_64x)
+
+{
+ volatile ioport_t *iopa = ioport_addr((immap_t *)CFG_IMMR, 0 /* port A */);
+
+ /* Save off the clocking data */
+ Daq64xSampling = sample_64x;
+
+ /*
+ * Limit the sample rate to some sensible values.
+ */
+ if (Daq64xSampling) {
+ if (sample_rate > MAX_64x_SAMPLE_RATE) {
+ sample_rate = MAX_64x_SAMPLE_RATE;
+ }
+ }
+ else {
+ if (sample_rate > MAX_128x_SAMPLE_RATE) {
+ sample_rate = MAX_128x_SAMPLE_RATE;
+ }
+ }
+ if (sample_rate < MIN_SAMPLE_RATE) {
+ sample_rate = MIN_SAMPLE_RATE;
+ }
+
+ /*
+ * Initialize the MCLK/SCLK/LRCLK baud rate generators.
+ */
+
+ /* Setup MCLK */
+ Daq_BRG_Set_ExtClk(MCLK_BRG, CPM_BRG_EXTC_BRGCLK);
+
+ /* Setup SCLK */
+# ifdef RUN_SCLK_ON_BRG_INT
+ Daq_BRG_Set_ExtClk(SCLK_BRG, CPM_BRG_EXTC_BRGCLK);
+# else
+ Daq_BRG_Set_ExtClk(SCLK_BRG, CPM_BRG_EXTC_CLK9);
+# endif
+
+ /* Setup LRCLK */
+# ifdef RUN_LRCLK_ON_BRG_INT
+ Daq_BRG_Set_ExtClk(LRCLK_BRG, CPM_BRG_EXTC_BRGCLK);
+# else
+ Daq_BRG_Set_ExtClk(LRCLK_BRG, CPM_BRG_EXTC_CLK5);
+# endif
+
+ /* Setup the BRG rates */
+ Daq_Set_SampleRate(sample_rate, TRUE);
+
+ /* Enable the clock drivers */
+ iopa->pdat &= ~SLRCLK_EN_MASK;
+}
+
+void Daq_Stop_Clocks(void)
+
+{
+#ifdef TIGHTEN_UP_BRG_TIMING
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#endif
+
+# ifdef TIGHTEN_UP_BRG_TIMING
+ /*
+ * Reset MCLK BRG
+ */
+# if (MCLK_BRG == 0)
+ immr->im_brgc1 |= CPM_BRG_RST;
+ immr->im_brgc1 &= ~CPM_BRG_RST;
+# endif
+# if (MCLK_BRG == 1)
+ immr->im_brgc2 |= CPM_BRG_RST;
+ immr->im_brgc2 &= ~CPM_BRG_RST;
+# endif
+# if (MCLK_BRG == 2)
+ immr->im_brgc3 |= CPM_BRG_RST;
+ immr->im_brgc3 &= ~CPM_BRG_RST;
+# endif
+# if (MCLK_BRG == 3)
+ immr->im_brgc4 |= CPM_BRG_RST;
+ immr->im_brgc4 &= ~CPM_BRG_RST;
+# endif
+# if (MCLK_BRG == 4)
+ immr->im_brgc5 |= CPM_BRG_RST;
+ immr->im_brgc5 &= ~CPM_BRG_RST;
+# endif
+# if (MCLK_BRG == 5)
+ immr->im_brgc6 |= CPM_BRG_RST;
+ immr->im_brgc6 &= ~CPM_BRG_RST;
+# endif
+# if (MCLK_BRG == 6)
+ immr->im_brgc7 |= CPM_BRG_RST;
+ immr->im_brgc7 &= ~CPM_BRG_RST;
+# endif
+# if (MCLK_BRG == 7)
+ immr->im_brgc8 |= CPM_BRG_RST;
+ immr->im_brgc8 &= ~CPM_BRG_RST;
+# endif
+
+ /*
+ * Reset SCLK BRG
+ */
+# if (SCLK_BRG == 0)
+ immr->im_brgc1 |= CPM_BRG_RST;
+ immr->im_brgc1 &= ~CPM_BRG_RST;
+# endif
+# if (SCLK_BRG == 1)
+ immr->im_brgc2 |= CPM_BRG_RST;
+ immr->im_brgc2 &= ~CPM_BRG_RST;
+# endif
+# if (SCLK_BRG == 2)
+ immr->im_brgc3 |= CPM_BRG_RST;
+ immr->im_brgc3 &= ~CPM_BRG_RST;
+# endif
+# if (SCLK_BRG == 3)
+ immr->im_brgc4 |= CPM_BRG_RST;
+ immr->im_brgc4 &= ~CPM_BRG_RST;
+# endif
+# if (SCLK_BRG == 4)
+ immr->im_brgc5 |= CPM_BRG_RST;
+ immr->im_brgc5 &= ~CPM_BRG_RST;
+# endif
+# if (SCLK_BRG == 5)
+ immr->im_brgc6 |= CPM_BRG_RST;
+ immr->im_brgc6 &= ~CPM_BRG_RST;
+# endif
+# if (SCLK_BRG == 6)
+ immr->im_brgc7 |= CPM_BRG_RST;
+ immr->im_brgc7 &= ~CPM_BRG_RST;
+# endif
+# if (SCLK_BRG == 7)
+ immr->im_brgc8 |= CPM_BRG_RST;
+ immr->im_brgc8 &= ~CPM_BRG_RST;
+# endif
+
+ /*
+ * Reset LRCLK BRG
+ */
+# if (LRCLK_BRG == 0)
+ immr->im_brgc1 |= CPM_BRG_RST;
+ immr->im_brgc1 &= ~CPM_BRG_RST;
+# endif
+# if (LRCLK_BRG == 1)
+ immr->im_brgc2 |= CPM_BRG_RST;
+ immr->im_brgc2 &= ~CPM_BRG_RST;
+# endif
+# if (LRCLK_BRG == 2)
+ immr->im_brgc3 |= CPM_BRG_RST;
+ immr->im_brgc3 &= ~CPM_BRG_RST;
+# endif
+# if (LRCLK_BRG == 3)
+ immr->im_brgc4 |= CPM_BRG_RST;
+ immr->im_brgc4 &= ~CPM_BRG_RST;
+# endif
+# if (LRCLK_BRG == 4)
+ immr->im_brgc5 |= CPM_BRG_RST;
+ immr->im_brgc5 &= ~CPM_BRG_RST;
+# endif
+# if (LRCLK_BRG == 5)
+ immr->im_brgc6 |= CPM_BRG_RST;
+ immr->im_brgc6 &= ~CPM_BRG_RST;
+# endif
+# if (LRCLK_BRG == 6)
+ immr->im_brgc7 |= CPM_BRG_RST;
+ immr->im_brgc7 &= ~CPM_BRG_RST;
+# endif
+# if (LRCLK_BRG == 7)
+ immr->im_brgc8 |= CPM_BRG_RST;
+ immr->im_brgc8 &= ~CPM_BRG_RST;
+# endif
+# else
+ /*
+ * Reset the clocks
+ */
+ Daq_BRG_Reset(MCLK_BRG);
+ Daq_BRG_Reset(SCLK_BRG);
+ Daq_BRG_Reset(LRCLK_BRG);
+# endif
+}
+
+void Daq_Start_Clocks(int sample_rate)
+
+{
+#ifdef TIGHTEN_UP_BRG_TIMING
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ uint mclk_brg; /* MCLK BRG value */
+ uint sclk_brg; /* SCLK BRG value */
+ uint lrclk_brg; /* LRCLK BRG value */
+ uint temp_lrclk_brg; /* Temporary LRCLK BRG value */
+ uint real_lrclk_brg; /* Permanent LRCLK BRG value */
+ unsigned long flags; /* Interrupt flags */
+ uint sclk_cnt; /* SCLK count */
+ uint delay_cnt; /* Delay count */
+#endif
+
+# ifdef TIGHTEN_UP_BRG_TIMING
+ /*
+ * Obtain the enabled MCLK BRG value
+ */
+# if (MCLK_BRG == 0)
+ mclk_brg = (immr->im_brgc1 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (MCLK_BRG == 1)
+ mclk_brg = (immr->im_brgc2 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (MCLK_BRG == 2)
+ mclk_brg = (immr->im_brgc3 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (MCLK_BRG == 3)
+ mclk_brg = (immr->im_brgc4 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (MCLK_BRG == 4)
+ mclk_brg = (immr->im_brgc5 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (MCLK_BRG == 5)
+ mclk_brg = (immr->im_brgc6 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (MCLK_BRG == 6)
+ mclk_brg = (immr->im_brgc7 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (MCLK_BRG == 7)
+ mclk_brg = (immr->im_brgc8 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+
+ /*
+ * Obtain the enabled SCLK BRG value
+ */
+# if (SCLK_BRG == 0)
+ sclk_brg = (immr->im_brgc1 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (SCLK_BRG == 1)
+ sclk_brg = (immr->im_brgc2 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (SCLK_BRG == 2)
+ sclk_brg = (immr->im_brgc3 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (SCLK_BRG == 3)
+ sclk_brg = (immr->im_brgc4 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (SCLK_BRG == 4)
+ sclk_brg = (immr->im_brgc5 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (SCLK_BRG == 5)
+ sclk_brg = (immr->im_brgc6 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (SCLK_BRG == 6)
+ sclk_brg = (immr->im_brgc7 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (SCLK_BRG == 7)
+ sclk_brg = (immr->im_brgc8 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+
+ /*
+ * Obtain the enabled LRCLK BRG value
+ */
+# if (LRCLK_BRG == 0)
+ lrclk_brg = (immr->im_brgc1 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (LRCLK_BRG == 1)
+ lrclk_brg = (immr->im_brgc2 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (LRCLK_BRG == 2)
+ lrclk_brg = (immr->im_brgc3 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (LRCLK_BRG == 3)
+ lrclk_brg = (immr->im_brgc4 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (LRCLK_BRG == 4)
+ lrclk_brg = (immr->im_brgc5 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (LRCLK_BRG == 5)
+ lrclk_brg = (immr->im_brgc6 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (LRCLK_BRG == 6)
+ lrclk_brg = (immr->im_brgc7 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+# if (LRCLK_BRG == 7)
+ lrclk_brg = (immr->im_brgc8 & ~CPM_BRG_RST) | CPM_BRG_EN;
+# endif
+
+ /* Save off the real LRCLK value */
+ real_lrclk_brg = lrclk_brg;
+
+ /* Obtain the current SCLK count */
+ sclk_cnt = ((sclk_brg & 0x00001FFE) >> 1) + 1;
+
+ /* Compute the delay as a function of SCLK count */
+ delay_cnt = ((sclk_cnt / 4) - 2) * 10 + 6;
+ if (sample_rate == 43402) {
+ delay_cnt++;
+ }
+
+ /* Clear out the count */
+ temp_lrclk_brg = sclk_brg & ~0x00001FFE;
+
+ /* Insert the count */
+ temp_lrclk_brg |= ((delay_cnt + (sclk_cnt / 2) - 1) << 1) & 0x00001FFE;
+
+ /*
+ * Enable MCLK BRG
+ */
+# if (MCLK_BRG == 0)
+ immr->im_brgc1 = mclk_brg;
+# endif
+# if (MCLK_BRG == 1)
+ immr->im_brgc2 = mclk_brg;
+# endif
+# if (MCLK_BRG == 2)
+ immr->im_brgc3 = mclk_brg;
+# endif
+# if (MCLK_BRG == 3)
+ immr->im_brgc4 = mclk_brg;
+# endif
+# if (MCLK_BRG == 4)
+ immr->im_brgc5 = mclk_brg;
+# endif
+# if (MCLK_BRG == 5)
+ immr->im_brgc6 = mclk_brg;
+# endif
+# if (MCLK_BRG == 6)
+ immr->im_brgc7 = mclk_brg;
+# endif
+# if (MCLK_BRG == 7)
+ immr->im_brgc8 = mclk_brg;
+# endif
+
+ /*
+ * Enable SCLK BRG
+ */
+# if (SCLK_BRG == 0)
+ immr->im_brgc1 = sclk_brg;
+# endif
+# if (SCLK_BRG == 1)
+ immr->im_brgc2 = sclk_brg;
+# endif
+# if (SCLK_BRG == 2)
+ immr->im_brgc3 = sclk_brg;
+# endif
+# if (SCLK_BRG == 3)
+ immr->im_brgc4 = sclk_brg;
+# endif
+# if (SCLK_BRG == 4)
+ immr->im_brgc5 = sclk_brg;
+# endif
+# if (SCLK_BRG == 5)
+ immr->im_brgc6 = sclk_brg;
+# endif
+# if (SCLK_BRG == 6)
+ immr->im_brgc7 = sclk_brg;
+# endif
+# if (SCLK_BRG == 7)
+ immr->im_brgc8 = sclk_brg;
+# endif
+
+ /*
+ * Enable LRCLK BRG (1st time - temporary)
+ */
+# if (LRCLK_BRG == 0)
+ immr->im_brgc1 = temp_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 1)
+ immr->im_brgc2 = temp_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 2)
+ immr->im_brgc3 = temp_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 3)
+ immr->im_brgc4 = temp_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 4)
+ immr->im_brgc5 = temp_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 5)
+ immr->im_brgc6 = temp_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 6)
+ immr->im_brgc7 = temp_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 7)
+ immr->im_brgc8 = temp_lrclk_brg;
+# endif
+
+ /*
+ * Enable LRCLK BRG (2nd time - permanent)
+ */
+# if (LRCLK_BRG == 0)
+ immr->im_brgc1 = real_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 1)
+ immr->im_brgc2 = real_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 2)
+ immr->im_brgc3 = real_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 3)
+ immr->im_brgc4 = real_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 4)
+ immr->im_brgc5 = real_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 5)
+ immr->im_brgc6 = real_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 6)
+ immr->im_brgc7 = real_lrclk_brg;
+# endif
+# if (LRCLK_BRG == 7)
+ immr->im_brgc8 = real_lrclk_brg;
+# endif
+# else
+ /*
+ * Enable the clocks
+ */
+ Daq_BRG_Enable(LRCLK_BRG);
+ Daq_BRG_Enable(SCLK_BRG);
+ Daq_BRG_Enable(MCLK_BRG);
+# endif
+}
+
+void Daq_Display_Clocks(void)
+
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uint mclk_divisor; /* Detected MCLK divisor */
+ uint sclk_divisor; /* Detected SCLK divisor */
+
+ printf("\nBRG:\n");
+ if (immr->im_brgc4 != 0) {
+ printf("\tbrgc4\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, MCLK\n",
+ immr->im_brgc4,
+ (uint)&(immr->im_brgc4),
+ Daq_BRG_Get_Count(3),
+ Daq_BRG_Get_ExtClk(3),
+ Daq_BRG_Get_ExtClk_Description(3));
+ }
+ if (immr->im_brgc8 != 0) {
+ printf("\tbrgc8\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, SCLK\n",
+ immr->im_brgc8,
+ (uint)&(immr->im_brgc8),
+ Daq_BRG_Get_Count(7),
+ Daq_BRG_Get_ExtClk(7),
+ Daq_BRG_Get_ExtClk_Description(7));
+ }
+ if (immr->im_brgc6 != 0) {
+ printf("\tbrgc6\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, LRCLK\n",
+ immr->im_brgc6,
+ (uint)&(immr->im_brgc6),
+ Daq_BRG_Get_Count(5),
+ Daq_BRG_Get_ExtClk(5),
+ Daq_BRG_Get_ExtClk_Description(5));
+ }
+ if (immr->im_brgc1 != 0) {
+ printf("\tbrgc1\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, SMC1\n",
+ immr->im_brgc1,
+ (uint)&(immr->im_brgc1),
+ Daq_BRG_Get_Count(0),
+ Daq_BRG_Get_ExtClk(0),
+ Daq_BRG_Get_ExtClk_Description(0));
+ }
+ if (immr->im_brgc2 != 0) {
+ printf("\tbrgc2\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, SMC2\n",
+ immr->im_brgc2,
+ (uint)&(immr->im_brgc2),
+ Daq_BRG_Get_Count(1),
+ Daq_BRG_Get_ExtClk(1),
+ Daq_BRG_Get_ExtClk_Description(1));
+ }
+ if (immr->im_brgc3 != 0) {
+ printf("\tbrgc3\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, SCC1\n",
+ immr->im_brgc3,
+ (uint)&(immr->im_brgc3),
+ Daq_BRG_Get_Count(2),
+ Daq_BRG_Get_ExtClk(2),
+ Daq_BRG_Get_ExtClk_Description(2));
+ }
+ if (immr->im_brgc5 != 0) {
+ printf("\tbrgc5\t0x%08x @ 0x%08x, %5d count, %d extc, %8s\n",
+ immr->im_brgc5,
+ (uint)&(immr->im_brgc5),
+ Daq_BRG_Get_Count(4),
+ Daq_BRG_Get_ExtClk(4),
+ Daq_BRG_Get_ExtClk_Description(4));
+ }
+ if (immr->im_brgc7 != 0) {
+ printf("\tbrgc7\t0x%08x @ 0x%08x, %5d count, %d extc, %8s\n",
+ immr->im_brgc7,
+ (uint)&(immr->im_brgc7),
+ Daq_BRG_Get_Count(6),
+ Daq_BRG_Get_ExtClk(6),
+ Daq_BRG_Get_ExtClk_Description(6));
+ }
+
+# ifdef RUN_SCLK_ON_BRG_INT
+ mclk_divisor = Daq_BRG_Rate(MCLK_BRG) / Daq_BRG_Rate(SCLK_BRG);
+# else
+ mclk_divisor = Daq_BRG_Get_Count(SCLK_BRG);
+# endif
+# ifdef RUN_LRCLK_ON_BRG_INT
+ sclk_divisor = Daq_BRG_Rate(SCLK_BRG) / Daq_BRG_Rate(LRCLK_BRG);
+# else
+ sclk_divisor = Daq_BRG_Get_Count(LRCLK_BRG);
+# endif
+
+ printf("\nADC/DAC Clocking (%d/%d):\n", sclk_divisor, mclk_divisor);
+ printf("\tMCLK %8d Hz, or %3dx SCLK, or %3dx LRCLK\n",
+ Daq_BRG_Rate(MCLK_BRG),
+ mclk_divisor,
+ mclk_divisor * sclk_divisor);
+# ifdef RUN_SCLK_ON_BRG_INT
+ printf("\tSCLK %8d Hz, or %3dx LRCLK\n",
+ Daq_BRG_Rate(SCLK_BRG),
+ sclk_divisor);
+# else
+ printf("\tSCLK %8d Hz, or %3dx LRCLK\n",
+ Daq_BRG_Rate(MCLK_BRG) / mclk_divisor,
+ sclk_divisor);
+# endif
+# ifdef RUN_LRCLK_ON_BRG_INT
+ printf("\tLRCLK %8d Hz\n",
+ Daq_BRG_Rate(LRCLK_BRG));
+# else
+# ifdef RUN_SCLK_ON_BRG_INT
+ printf("\tLRCLK %8d Hz\n",
+ Daq_BRG_Rate(SCLK_BRG) / sclk_divisor);
+# else
+ printf("\tLRCLK %8d Hz\n",
+ Daq_BRG_Rate(MCLK_BRG) / (mclk_divisor * sclk_divisor));
+# endif
+# endif
+ printf("\n");
+}
diff --git a/board/sacsng/ioconfig.h b/board/sacsng/ioconfig.h
new file mode 100644
index 0000000000..6857f99ae5
--- /dev/null
+++ b/board/sacsng/ioconfig.h
@@ -0,0 +1,218 @@
+/*
+ * I/O Port configuration table
+ *
+ * If conf is 1, then that port pin will be configured at boot time
+ * according to the five values podr/pdir/ppar/psor/pdat for that entry
+ */
+
+#ifdef SKIP
+#undef SKIP
+#endif
+
+#ifdef CONF
+#undef CONF
+#endif
+
+#ifdef DIN
+#undef DIN
+#endif
+
+#ifdef DOUT
+#undef DOUT
+#endif
+
+#ifdef GPIO
+#undef GPIO
+#endif
+
+#ifdef SPEC
+#undef SPEC
+#endif
+
+#ifdef ACTV
+#undef ACTV
+#endif
+
+#ifdef OPEN
+#undef OPEN
+#endif
+
+#define SKIP 0 /* SKIP over this port */
+#define CONF 1 /* CONFiguration the port */
+
+#define DIN 0 /* PDIRx 0: Direction IN */
+#define DOUT 1 /* PDIRx 1: Direction OUT */
+
+#define GPIO 0 /* PPARx 0: General Purpose I/O */
+#define SPEC 1 /* PPARx 1: dedicated to a peripheral function, */
+ /* i.e. the port has a SPECial use. */
+
+#define ACTV 0 /* PODRx 0: ACTiVely driven as an output */
+#define OPEN 1 /* PODRx 1: OPEN-drain driver */
+
+const iop_conf_t iop_conf_tab[4][32] = {
+
+ /* Port A configuration */
+ { /* conf ppar psor pdir podr pdat */
+ /* PA31 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS8* */
+ /* PA30 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS7* */
+ /* PA29 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS6* */
+ /* PA28 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS5* */
+ /* PA27 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS4* */
+ /* PA26 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS3* */
+ /* PA25 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS2* */
+ /* PA24 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS1* */
+ /* PA23 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* ODIS_EN* */
+ /* PA22 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* STLED2_EN* */
+ /* PA21 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* STLED1_EN* */
+ /* PA20 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* PLED3_EN* */
+ /* PA19 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* PLED2_EN* */
+ /* PA18 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* PLED1_EN* */
+ /* PA17 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PA16 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* DAC_RST* */
+ /* PA15 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* CH34SDATA_PU */
+ /* PA14 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* CH12SDATA_PU */
+ /* PA13 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* SLRCLK_EN* */
+ /* PA12 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_4ACDC* */
+ /* PA11 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_4TEDS* */
+ /* PA10 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_4XTDS* */
+ /* PA9 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_3ACDC* */
+ /* PA8 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_3TEDS* */
+ /* PA7 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_3XTDS* */
+ /* PA6 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_2ACDC* */
+ /* PA5 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_2TEDS* */
+ /* PA4 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_2XTDS* */
+ /* PA3 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PA2 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_1ACDC* */
+ /* PA1 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_1TEDS* */
+ /* PA0 */ { CONF, GPIO, 0, DOUT, ACTV, 1 } /* MTRX_1XTDS* */
+ },
+
+ /* Port B configuration */
+ { /* conf ppar psor pdir podr pdat */
+ /* PB31 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TX_ER */
+ /* PB30 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RX_DV */
+ /* PB29 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* FCC2 MII_TX_EN */
+ /* PB28 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RX_ER */
+ /* PB27 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_COL */
+ /* PB26 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_CRS */
+ /* PB25 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TXD3 */
+ /* PB24 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TXD2 */
+ /* PB23 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TXD1 */
+ /* PB22 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TXD0 */
+ /* PB21 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RXD0 */
+ /* PB20 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RXD1 */
+ /* PB19 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RXD2 */
+ /* PB18 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RXD3 */
+ /* PB17 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PB16 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PB15 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PB14 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1RXDC1, BSDATA_ADC12 */
+ /* PB13 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PB12 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1RSYNCC1, LRCLK */
+ /* PB11 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1TXDD1, RSDATA_DAC12 */
+ /* PB10 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1RXDD1, BSDATA_ADC34 */
+ /* PB9 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PB8 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1RSYNCD1, LRCLK */
+ /* PB7 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PB6 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* XCITE_SHDN */
+ /* PB5 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* TRIGGER */
+ /* PB4 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* ARM */
+ /* PB3 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */
+ /* PB2 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */
+ /* PB1 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */
+ /* PB0 */ { SKIP, GPIO, 0, DIN, ACTV, 0 } /* pin doesn't exist */
+ },
+
+ /* Port C */
+ { /* conf ppar psor pdir podr pdat */
+ /* PC31 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC30 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC29 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK3, MCLK */
+ /* PC28 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* TOUT2* */
+#ifdef QQQ
+ /* PC28 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* TOUT2* */
+#endif
+ /* PC27 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK5, SCLK */
+ /* PC26 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC25 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK7, SCLK */
+ /* PC24 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC23 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK9, MCLK */
+ /* PC22 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC21 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* BRGO6 (LRCLK) */
+ /* PC20 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC19 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK13, MII_RXCLK */
+ /* PC18 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK14, MII_TXCLK */
+ /* PC17 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* BRGO8 (SCLK) */
+ /* PC16 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC15 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* SMC2_TX */
+ /* PC14 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC13 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC12 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* TDM_STRB3 */
+ /* PC11 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC10 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* TDM_STRB4 */
+ /* PC9 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BPDIS_IN3 */
+ /* PC8 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BPDIS_IN2 */
+ /* PC7 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BPDIS_IN1 */
+ /* PC6 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PC5 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BTST_IN2* */
+ /* PC4 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BTST_IN1* */
+ /* PC3 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* MUSH_STAT */
+ /* PC2 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* OUTDRV_STAT */
+ /* PC1 */ { CONF, GPIO, 0, DOUT, OPEN, 1 }, /* PHY_MDIO */
+ /* PC0 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* PHY_MDC */
+ },
+
+ /* Port D */
+ { /* conf ppar psor pdir podr pdat */
+ /* PD31 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* SCC1_RX */
+ /* PD30 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* SCC1_TX */
+ /* PD29 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD28 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD27 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD26 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD25 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD24 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD23 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD22 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD21 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD20 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* SPI_ADC_CS* */
+ /* PD19 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* SPI_DAC_CS* */
+#if defined(CONFIG_SOFT_SPI)
+ /* PD18 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* SPI_CLK */
+ /* PD17 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* SPI_MOSI */
+ /* PD16 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* SPI_MISO */
+#else
+ /* PD18 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* SPI_CLK */
+ /* PD17 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* SPI_MOSI */
+ /* PD16 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* SPI_MISO */
+#endif
+#if defined(CONFIG_SOFT_I2C)
+ /* PD15 */ { CONF, GPIO, 0, DOUT, OPEN, 1 }, /* I2C_SDA */
+ /* PD14 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* I2C_SCL */
+#else
+#if defined(CONFIG_HARD_I2C)
+ /* PD15 */ { CONF, SPEC, 1, DIN, OPEN, 0 }, /* I2C_SDA */
+ /* PD14 */ { CONF, SPEC, 1, DIN, OPEN, 0 }, /* I2C_SCL */
+#else /* normal I/O port pins */
+ /* PD15 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* I2C_SDA */
+ /* PD14 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* I2C_SCL */
+#endif
+#endif
+ /* PD13 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* TDM_STRB1 */
+ /* PD12 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* TDM_STRB2 */
+ /* PD11 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */
+ /* PD10 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* BRGO4 (MCLK) */
+ /* PD9 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* SMC1_TX */
+ /* PD8 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* SMC1_RX */
+ /* PD7 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* N/C */
+ /* PD6 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* N/C */
+ /* PD5 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* N/C */
+ /* PD4 */ { CONF, SPEC, 1, DOUT, ACTV, 1 }, /* SMC2_RX */
+ /* PD3 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */
+ /* PD2 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */
+ /* PD1 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */
+ /* PD0 */ { SKIP, GPIO, 0, DIN, ACTV, 0 } /* pin doesn't exist */
+ }
+};
+
diff --git a/board/sandpoint/sandpoint.c b/board/sandpoint/sandpoint.c
new file mode 100644
index 0000000000..8d385f7111
--- /dev/null
+++ b/board/sandpoint/sandpoint.c
@@ -0,0 +1,127 @@
+/*
+ * (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 <mpc824x.h>
+#include <pci.h>
+
+int checkboard (void)
+{
+ /*TODO: Check processor type */
+
+ puts ( "Board: Sandpoint "
+#ifdef CONFIG_MPC8240
+ "8240"
+#endif
+#ifdef CONFIG_MPC8245
+ "8245"
+#endif
+ " Unity ##Test not implemented yet##\n");
+ return 0;
+}
+
+#if 0 /* NOT USED */
+int checkflash (void)
+{
+ /* TODO: XXX XXX XXX */
+ printf ("## Test not implemented yet ##\n");
+
+ return (0);
+}
+#endif
+
+long int initdram (int board_type)
+{
+ int i, cnt;
+ volatile uchar * base= CFG_SDRAM_BASE;
+ volatile ulong * addr;
+ ulong save[32];
+ ulong val, ret = 0;
+
+ for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) {
+ addr = (volatile ulong *)base + cnt;
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ addr = (volatile ulong *)base;
+ save[i] = *addr;
+ *addr = 0;
+
+ if (*addr != 0) {
+ *addr = save[i];
+ goto Done;
+ }
+
+ for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) {
+ addr = (volatile ulong *)base + cnt;
+ val = *addr;
+ *addr = save[--i];
+ if (val != ~cnt) {
+ ulong new_bank0_end = cnt * sizeof(long) - 1;
+ ulong mear1 = mpc824x_mpc107_getreg(MEAR1);
+ ulong emear1 = mpc824x_mpc107_getreg(EMEAR1);
+ mear1 = (mear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT);
+ emear1 = (emear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT);
+ mpc824x_mpc107_setreg(MEAR1, mear1);
+ mpc824x_mpc107_setreg(EMEAR1, emear1);
+
+ ret = cnt * sizeof(long);
+ goto Done;
+ }
+ }
+
+ ret = CFG_MAX_RAM_SIZE;
+Done:
+ return ret;
+}
+
+/*
+ * Initialize PCI Devices, report devices found.
+ */
+#ifndef CONFIG_PCI_PNP
+static struct pci_config_table pci_sandpoint_config_table[] = {
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0f, PCI_ANY_ID,
+ pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
+ PCI_ENET0_MEMADDR,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x10, PCI_ANY_ID,
+ pci_cfgfunc_config_device, { PCI_ENET1_IOADDR,
+ PCI_ENET1_MEMADDR,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
+ { }
+};
+#endif
+
+struct pci_controller hose = {
+#ifndef CONFIG_PCI_PNP
+ config_table: pci_sandpoint_config_table,
+#endif
+};
+
+void pci_init(void)
+{
+ pci_mpc824x_init(&hose);
+}
diff --git a/board/shannon/u-boot.lds b/board/shannon/u-boot.lds
new file mode 100644
index 0000000000..f4b0ade273
--- /dev/null
+++ b/board/shannon/u-boot.lds
@@ -0,0 +1,53 @@
+/*
+ * (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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ cpu/sa1100/start.o (.text)
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ armboot_end_data = .;
+
+ . = ALIGN(4);
+ .bss : { *(.bss) }
+
+ armboot_end = .;
+}
diff --git a/board/siemens/CCM/ccm.c b/board/siemens/CCM/ccm.c
new file mode 100644
index 0000000000..079f38f7ec
--- /dev/null
+++ b/board/siemens/CCM/ccm.c
@@ -0,0 +1,440 @@
+/*
+ * (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
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <commproc.h>
+#include <command.h>
+
+/* ------------------------------------------------------------------------- */
+
+static long int dram_size (long int, long int *, long int);
+void can_driver_enable (void);
+void can_driver_disable (void);
+
+int fpga_init(void);
+
+/* ------------------------------------------------------------------------- */
+
+#define _NOT_USED_ 0xFFFFFFFF
+
+const uint sdram_table[] =
+{
+ /*
+ * Single Read. (Offset 0 in UPMA RAM)
+ */
+ 0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBAFC00,
+ 0x1FF5FC47, /* last */
+ /*
+ * SDRAM Initialization (offset 5 in UPMA RAM)
+ *
+ * This is no UPM entry point. The following definition uses
+ * the remaining space to establish an initialization
+ * sequence, which is executed by a RUN command.
+ *
+ */
+ 0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */
+ /*
+ * Burst Read. (Offset 8 in UPMA RAM)
+ */
+ 0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00,
+ 0xF0AFFC00, 0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Single Write. (Offset 18 in UPMA RAM)
+ */
+ 0x1F0DFC04, 0xEEABBC00, 0x01B27C04, 0x1FF5FC47, /* last */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Burst Write. (Offset 20 in UPMA RAM)
+ */
+ 0x1F0DFC04, 0xEEABBC00, 0x10A77C00, 0xF0AFFC00,
+ 0xF0AFFC00, 0xE1BAFC04, 0x1FF5FC47, /* last */
+ _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Refresh (Offset 30 in UPMA RAM)
+ */
+ 0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04,
+ 0xFFFFFC84, 0xFFFFFC07, /* last */
+ _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Exception. (Offset 3c in UPMA RAM)
+ */
+ 0x7FFFFC07, /* last */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_,
+};
+
+/* ------------------------------------------------------------------------- */
+
+
+/*
+ * Check Board Identity:
+ *
+ * Always return 1 (no second DRAM bank since based on TQM8xxL module)
+ */
+
+int checkboard (void)
+{
+ unsigned char *s;
+ unsigned char buf[64];
+
+ s = (getenv_r ("serial#", buf, sizeof(buf)) > 0) ? buf : NULL;
+
+ puts ("Board: Siemens CCM");
+
+ if (s) {
+ puts (" (");
+
+ for (; *s; ++s) {
+ if (*s == ' ')
+ break;
+ putc (*s);
+ }
+ putc (')');
+ }
+
+ putc ('\n');
+
+ return (0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * If Power-On-Reset switch off the Red and Green LED: At reset, the
+ * data direction registers are cleared and must therefore be restored.
+ */
+#define RSR_CSRS 0x08000000
+
+int power_on_reset(void)
+{
+ /* Test Reset Status Register */
+ return ((volatile immap_t *)CFG_IMMR)->im_clkrst.car_rsr & RSR_CSRS ? 0:1;
+}
+
+#define PB_LED_GREEN 0x10000 /* red LED is on PB.15 */
+#define PB_LED_RED 0x20000 /* red LED is on PB.14 */
+#define PB_LEDS (PB_LED_GREEN | PB_LED_RED);
+
+static void init_leds (void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+ immap->im_cpm.cp_pbpar &= ~PB_LEDS;
+ immap->im_cpm.cp_pbodr &= ~PB_LEDS;
+ immap->im_cpm.cp_pbdir |= PB_LEDS;
+ /* Check stop reset status */
+ if (power_on_reset()) {
+ immap->im_cpm.cp_pbdat &= ~PB_LEDS;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+long int initdram (int board_type)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ long int size8, size9;
+ long int size = 0;
+ unsigned long reg;
+
+ upmconfig(UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint));
+
+ /*
+ * Preliminary prescaler for refresh (depends on number of
+ * banks): This value is selected for four cycles every 62.4 us
+ * with two SDRAM banks or four cycles every 31.2 us with one
+ * bank. It will be adjusted after memory sizing.
+ */
+ memctl->memc_mptpr = CFG_MPTPR_2BK_8K;
+
+ memctl->memc_mar = 0x00000088;
+
+ /*
+ * Map controller banks 2 and 3 to the SDRAM banks 2 and 3 at
+ * preliminary addresses - these have to be modified after the
+ * SDRAM size has been determined.
+ */
+ memctl->memc_or2 = CFG_OR2_PRELIM;
+ memctl->memc_br2 = CFG_BR2_PRELIM;
+
+ memctl->memc_mamr = CFG_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */
+
+ udelay(200);
+
+ /* perform SDRAM initializsation sequence */
+
+ memctl->memc_mcr = 0x80004105; /* SDRAM bank 0 */
+ udelay(1);
+ memctl->memc_mcr = 0x80004230; /* SDRAM bank 0 - execute twice */
+ udelay(1);
+
+ memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */
+
+ udelay (1000);
+
+ /*
+ * Check Bank 0 Memory Size for re-configuration
+ *
+ * try 8 column mode
+ */
+ size8 = dram_size (CFG_MAMR_8COL, (ulong *)SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE);
+
+ udelay (1000);
+
+ /*
+ * try 9 column mode
+ */
+ size9 = dram_size (CFG_MAMR_9COL, (ulong *)SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE);
+
+ if (size8 < size9) { /* leave configuration at 9 columns */
+ size = size9;
+/* debug ("SDRAM in 9 column mode: %ld MB\n", size >> 20); */
+ } else { /* back to 8 columns */
+ size = size8;
+ memctl->memc_mamr = CFG_MAMR_8COL;
+ udelay(500);
+/* debug ("SDRAM in 8 column mode: %ld MB\n", size >> 20); */
+ }
+
+ udelay (1000);
+
+ /*
+ * Adjust refresh rate depending on SDRAM type
+ * For types > 128 MBit leave it at the current (fast) rate
+ */
+ if (size < 0x02000000) {
+ /* reduce to 15.6 us (62.4 us / quad) */
+ memctl->memc_mptpr = CFG_MPTPR_2BK_4K;
+ udelay(1000);
+ }
+
+ /*
+ * Final mapping
+ */
+
+ memctl->memc_or2 = ((-size) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM;
+ memctl->memc_br2 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V;
+
+
+ /* adjust refresh rate depending on SDRAM type, one bank */
+ reg = memctl->memc_mptpr;
+ reg >>= 1; /* reduce to CFG_MPTPR_1BK_8K / _4K */
+ memctl->memc_mptpr = reg;
+
+ can_driver_enable ();
+ init_leds ();
+
+ udelay(10000);
+
+ return (size);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Warning - both the PUMA load mode and the CAN driver use UPM B,
+ * so make sure only one of both is active.
+ */
+void can_driver_enable (void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+ /* Initialize MBMR */
+ memctl->memc_mbmr = MAMR_GPL_B4DIS; /* GPL_B4 ouput line Disable */
+
+ /* Initialize UPMB for CAN: single read */
+ memctl->memc_mdr = 0xFFFFC004;
+ memctl->memc_mcr = 0x0100 | UPMB;
+
+ memctl->memc_mdr = 0x0FFFD004;
+ memctl->memc_mcr = 0x0101 | UPMB;
+
+ memctl->memc_mdr = 0x0FFFC000;
+ memctl->memc_mcr = 0x0102 | UPMB;
+
+ memctl->memc_mdr = 0x3FFFC004;
+ memctl->memc_mcr = 0x0103 | UPMB;
+
+ memctl->memc_mdr = 0xFFFFDC05;
+ memctl->memc_mcr = 0x0104 | UPMB;
+
+ /* Initialize UPMB for CAN: single write */
+ memctl->memc_mdr = 0xFFFCC004;
+ memctl->memc_mcr = 0x0118 | UPMB;
+
+ memctl->memc_mdr = 0xCFFCD004;
+ memctl->memc_mcr = 0x0119 | UPMB;
+
+ memctl->memc_mdr = 0x0FFCC000;
+ memctl->memc_mcr = 0x011A | UPMB;
+
+ memctl->memc_mdr = 0x7FFCC004;
+ memctl->memc_mcr = 0x011B | UPMB;
+
+ memctl->memc_mdr = 0xFFFDCC05;
+ memctl->memc_mcr = 0x011C | UPMB;
+
+ /* Initialize OR3 / BR3 for CAN Bus Controller */
+ memctl->memc_or3 = CFG_OR3_CAN;
+ memctl->memc_br3 = CFG_BR3_CAN;
+}
+
+void can_driver_disable (void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+ /* Reset OR3 / BR3 to disable CAN Bus Controller */
+ memctl->memc_br3 = 0;
+ memctl->memc_or3 = 0;
+
+ memctl->memc_mbmr = 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Check memory range for valid RAM. A simple memory test determines
+ * the actually available RAM size between addresses `base' and
+ * `base + maxsize'. Some (not all) hardware errors are detected:
+ * - short between address lines
+ * - short between data lines
+ */
+
+static long int dram_size (long int mamr_value, long int *base, long int maxsize)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ volatile long int *addr;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
+
+ memctl->memc_mamr = mamr_value;
+
+ for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ /* write 0 to base address */
+ addr = base;
+ save[i] = *addr;
+ *addr = 0;
+
+ /* check at base address */
+ if ((val = *addr) != 0) {
+ *addr = save[i];
+ return (0);
+ }
+
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ val = *addr;
+ *addr = save[--i];
+
+ if (val != (~cnt)) {
+ return (cnt * sizeof(long));
+ }
+ }
+ return (maxsize);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#define ETH_CFG_BITS (CFG_PB_ETH_CFG1 | CFG_PB_ETH_CFG2 | CFG_PB_ETH_CFG3 )
+
+#define ETH_ALL_BITS (ETH_CFG_BITS | CFG_PB_ETH_POWERDOWN)
+
+void reset_phy(void)
+{
+ immap_t *immr = (immap_t *)CFG_IMMR;
+ ulong value;
+
+ /* Configure all needed port pins for GPIO */
+#if CFG_ETH_MDDIS_VALUE
+ immr->im_ioport.iop_padat |= CFG_PA_ETH_MDDIS;
+#else
+ immr->im_ioport.iop_padat &= ~(CFG_PA_ETH_MDDIS | CFG_PA_ETH_RESET); /* Set low */
+#endif
+ immr->im_ioport.iop_papar &= ~(CFG_PA_ETH_MDDIS | CFG_PA_ETH_RESET); /* GPIO */
+ immr->im_ioport.iop_paodr &= ~(CFG_PA_ETH_MDDIS | CFG_PA_ETH_RESET); /* active output */
+ immr->im_ioport.iop_padir |= CFG_PA_ETH_MDDIS | CFG_PA_ETH_RESET; /* output */
+
+ immr->im_cpm.cp_pbpar &= ~(ETH_ALL_BITS); /* GPIO */
+ immr->im_cpm.cp_pbodr &= ~(ETH_ALL_BITS); /* active output */
+
+ value = immr->im_cpm.cp_pbdat;
+
+ /* Assert Powerdown and Reset signals */
+ value |= CFG_PB_ETH_POWERDOWN;
+
+ /* PHY configuration includes MDDIS and CFG1 ... CFG3 */
+#if CFG_ETH_CFG1_VALUE
+ value |= CFG_PB_ETH_CFG1;
+#else
+ value &= ~(CFG_PB_ETH_CFG1);
+#endif
+#if CFG_ETH_CFG2_VALUE
+ value |= CFG_PB_ETH_CFG2;
+#else
+ value &= ~(CFG_PB_ETH_CFG2);
+#endif
+#if CFG_ETH_CFG3_VALUE
+ value |= CFG_PB_ETH_CFG3;
+#else
+ value &= ~(CFG_PB_ETH_CFG3);
+#endif
+
+ /* Drive output signals to initial state */
+ immr->im_cpm.cp_pbdat = value;
+ immr->im_cpm.cp_pbdir |= ETH_ALL_BITS;
+ udelay (10000);
+
+ /* De-assert Ethernet Powerdown */
+ immr->im_cpm.cp_pbdat &= ~(CFG_PB_ETH_POWERDOWN); /* Enable PHY power */
+ udelay (10000);
+
+ /* de-assert RESET signal of PHY */
+ immr->im_ioport.iop_padat |= CFG_PA_ETH_RESET;
+ udelay (1000);
+}
+
+
+int misc_init_r (void)
+{
+ fpga_init();
+ return (0);
+}
+/* ------------------------------------------------------------------------- */
diff --git a/board/siemens/CCM/fpga_ccm.c b/board/siemens/CCM/fpga_ccm.c
new file mode 100644
index 0000000000..292387b524
--- /dev/null
+++ b/board/siemens/CCM/fpga_ccm.c
@@ -0,0 +1,170 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Grandegger, DENX Software Engineering, wg@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 <mpc8xx.h>
+#include <commproc.h>
+#include <common.h>
+
+#include "../common/fpga.h"
+
+fpga_t fpga_list[] = {
+ { "PUMA" , PUMA_CONF_BASE ,
+ CFG_PC_PUMA_INIT , CFG_PC_PUMA_PROG , CFG_PC_PUMA_DONE }
+};
+int fpga_count = sizeof(fpga_list) / sizeof(fpga_t);
+
+void can_driver_enable (void);
+void can_driver_disable (void);
+
+#define _NOT_USED_ 0xFFFFFFFF
+
+/*
+ * PUMA access using UPM B
+ */
+const uint puma_table[] =
+{
+ /*
+ * Single Read. (Offset 0 in UPM RAM)
+ */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_,
+ /*
+ * Precharge and MRS
+ */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Burst Read. (Offset 8 in UPM RAM)
+ */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Single Write. (Offset 18 in UPM RAM)
+ */
+ 0x0FFCF804, 0x0FFCF400, 0x3FFDFC47, /* last */
+ _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Burst Write. (Offset 20 in UPM RAM)
+ */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Refresh (Offset 30 in UPM RAM)
+ */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Exception. (Offset 3c in UPM RAM)
+ */
+ 0x7FFFFC07, /* last */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_,
+};
+
+
+ulong fpga_control (fpga_t* fpga, int cmd)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immr->im_memctl;
+
+ switch (cmd) {
+ case FPGA_INIT_IS_HIGH:
+ immr->im_ioport.iop_pcdir &= ~fpga->init_mask; /* input */
+ return (immr->im_ioport.iop_pcdat & fpga->init_mask) ? 1:0;
+
+ case FPGA_INIT_SET_LOW:
+ immr->im_ioport.iop_pcdir |= fpga->init_mask; /* output */
+ immr->im_ioport.iop_pcdat &= ~fpga->init_mask;
+ break;
+
+ case FPGA_INIT_SET_HIGH:
+ immr->im_ioport.iop_pcdir |= fpga->init_mask; /* output */
+ immr->im_ioport.iop_pcdat |= fpga->init_mask;
+ break;
+
+ case FPGA_PROG_SET_LOW:
+ immr->im_ioport.iop_pcdat &= ~fpga->prog_mask;
+ break;
+
+ case FPGA_PROG_SET_HIGH:
+ immr->im_ioport.iop_pcdat |= fpga->prog_mask;
+ break;
+
+ case FPGA_DONE_IS_HIGH:
+ return (immr->im_ioport.iop_pcdat & fpga->done_mask) ? 1:0;
+
+ case FPGA_READ_MODE:
+ /* disable FPGA in memory controller */
+ memctl->memc_br4 = 0;
+ memctl->memc_or4 = PUMA_CONF_OR_READ;
+ memctl->memc_br4 = PUMA_CONF_BR_READ;
+
+ /* (re-) enable CAN drivers */
+ can_driver_enable ();
+
+ break;
+
+ case FPGA_LOAD_MODE:
+ /* disable FPGA in memory controller */
+ memctl->memc_br4 = 0;
+ /*
+ * We must disable the CAN drivers first because
+ * they use UPM B, too.
+ */
+ can_driver_disable ();
+ /*
+ * Configure UPMB for FPGA
+ */
+ upmconfig(UPMB,(uint *)puma_table,sizeof(puma_table)/sizeof(uint));
+ memctl->memc_or4 = PUMA_CONF_OR_LOAD;
+ memctl->memc_br4 = PUMA_CONF_BR_LOAD;
+ break;
+
+ case FPGA_GET_ID:
+ return *(volatile ulong *)fpga->conf_base;
+
+ case FPGA_INIT_PORTS:
+ immr->im_ioport.iop_pcpar &= ~fpga->init_mask; /* INIT I/O */
+ immr->im_ioport.iop_pcso &= ~fpga->init_mask;
+ immr->im_ioport.iop_pcdir &= ~fpga->init_mask;
+
+ immr->im_ioport.iop_pcpar &= ~fpga->prog_mask; /* PROG Output */
+ immr->im_ioport.iop_pcso &= ~fpga->prog_mask;
+ immr->im_ioport.iop_pcdir |= fpga->prog_mask;
+
+ immr->im_ioport.iop_pcpar &= ~fpga->done_mask; /* DONE Input */
+ immr->im_ioport.iop_pcso &= ~fpga->done_mask;
+ immr->im_ioport.iop_pcdir &= ~fpga->done_mask;
+
+ break;
+
+ }
+ return 0;
+}
+
diff --git a/board/siemens/SCM/fpga_scm.c b/board/siemens/SCM/fpga_scm.c
new file mode 100644
index 0000000000..3b93794adc
--- /dev/null
+++ b/board/siemens/SCM/fpga_scm.c
@@ -0,0 +1,104 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Grandegger, DENX Software Engineering, wg@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 <mpc8260.h>
+#include <common.h>
+#include "../common/fpga.h"
+
+fpga_t fpga_list[] = {
+ { "FIOX" , CFG_FIOX_BASE ,
+ CFG_PD_FIOX_INIT , CFG_PD_FIOX_PROG , CFG_PD_FIOX_DONE },
+ { "FDOHM", CFG_FDOHM_BASE,
+ CFG_PD_FDOHM_INIT, CFG_PD_FDOHM_PROG, CFG_PD_FDOHM_DONE }
+};
+int fpga_count = sizeof(fpga_list) / sizeof(fpga_t);
+
+
+ulong fpga_control (fpga_t* fpga, int cmd)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ switch (cmd) {
+ case FPGA_INIT_IS_HIGH:
+ immr->im_ioport.iop_pdird &= ~fpga->init_mask; /* input */
+ return (immr->im_ioport.iop_pdatd & fpga->init_mask) ? 1:0;
+
+ case FPGA_INIT_SET_LOW:
+ immr->im_ioport.iop_pdird |= fpga->init_mask; /* output */
+ immr->im_ioport.iop_pdatd &= ~fpga->init_mask;
+ break;
+
+ case FPGA_INIT_SET_HIGH:
+ immr->im_ioport.iop_pdird |= fpga->init_mask; /* output */
+ immr->im_ioport.iop_pdatd |= fpga->init_mask;
+ break;
+
+ case FPGA_PROG_SET_LOW:
+ immr->im_ioport.iop_pdatd &= ~fpga->prog_mask;
+ break;
+
+ case FPGA_PROG_SET_HIGH:
+ immr->im_ioport.iop_pdatd |= fpga->prog_mask;
+ break;
+
+ case FPGA_DONE_IS_HIGH:
+ return (immr->im_ioport.iop_pdatd & fpga->done_mask) ? 1:0;
+
+ case FPGA_READ_MODE:
+ break;
+
+ case FPGA_LOAD_MODE:
+ break;
+
+ case FPGA_GET_ID:
+ if (fpga->conf_base == CFG_FIOX_BASE) {
+ ulong ver = *(volatile ulong *)(fpga->conf_base + 0x10);
+ return ((ver >> 10) & 0xf) + ((ver >> 2) & 0xf0);
+ }
+ else if (fpga->conf_base == CFG_FDOHM_BASE) {
+ return (*(volatile ushort *)fpga->conf_base) & 0xff;
+ }
+ else {
+ return *(volatile ulong *)fpga->conf_base;
+ }
+
+ case FPGA_INIT_PORTS:
+ immr->im_ioport.iop_ppard &= ~fpga->init_mask; /* INIT I/O */
+ immr->im_ioport.iop_psord &= ~fpga->init_mask;
+ immr->im_ioport.iop_pdird &= ~fpga->init_mask;
+
+ immr->im_ioport.iop_ppard &= ~fpga->prog_mask; /* PROG Output */
+ immr->im_ioport.iop_psord &= ~fpga->prog_mask;
+ immr->im_ioport.iop_pdird |= fpga->prog_mask;
+
+ immr->im_ioport.iop_ppard &= ~fpga->done_mask; /* DONE Input */
+ immr->im_ioport.iop_psord &= ~fpga->done_mask;
+ immr->im_ioport.iop_pdird &= ~fpga->done_mask;
+
+ break;
+
+ }
+ return 0;
+}
diff --git a/board/siemens/common/README b/board/siemens/common/README
new file mode 100644
index 0000000000..d781903840
--- /dev/null
+++ b/board/siemens/common/README
@@ -0,0 +1,27 @@
+CCM/SCM-Ergaenzungen fuer U-Boot und Linux:
+-------------------------------------------
+
+Es gibt nun ein gemeinsames Kommando zum Laden der FPGAs:
+
+ => help fpga
+ fpga fpga status [name] - print FPGA status
+ fpga reset [name] - reset FPGA
+ fpga load [name] addr - load FPGA configuration data
+
+Der Name kann beim CCM-Module auch weggelassen werden.
+Die Laengenangabe und damit "puma_len" ist nicht mehr
+noetig:
+
+ => fpga load puma 40600000
+ FPGA load PUMA: addr 40600000: (00000005)... done
+
+Die MTD-Partitionierung kann nun mittels "bootargs" ueber-
+geben werden:
+
+ => printenv addmtd
+ addmtd=setenv bootargs $(bootargs)
+ mtdparts=0:256k(U-Boot)ro,768k(Kernel),-(Rest)\;1:-(myJFFS2)
+
+Die Portierung auf SMC ist natuerlich noch nicht getestet.
+
+Wolfgang Grandegger (04.06.2002)
diff --git a/board/siemens/common/fpga.c b/board/siemens/common/fpga.c
new file mode 100644
index 0000000000..a17de5ad65
--- /dev/null
+++ b/board/siemens/common/fpga.c
@@ -0,0 +1,358 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Grandegger, DENX Software Engineering, wg@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 <command.h>
+#include <linux/ctype.h>
+#include <common.h>
+#include <cmd_boot.h>
+#include <cmd_bsp.h>
+
+#include "fpga.h"
+
+int power_on_reset(void);
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+
+static int fpga_get_version(fpga_t* fpga, char* name)
+{
+ char vname[12];
+ /*
+ * Net-list string format:
+ * "vvvvvvvvddddddddn...".
+ * Version Date Name
+ * "0000000322042002PUMA" = PUMA version 3 from 22.04.2002.
+ */
+ if (strlen(name) < (16 + strlen(fpga->name)))
+ goto failure;
+ /* Check FPGA name */
+ if (strcmp(&name[16], fpga->name) != 0)
+ goto failure;
+ /* Get version number */
+ memcpy(vname, name, 8);
+ vname[8] = '\0';
+ return simple_strtoul(vname, NULL, 16);
+
+ failure:
+ printf("Image name %s is invalid\n", name);
+ return -1;
+}
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+static fpga_t* fpga_get(char* fpga_name)
+{
+ char name[FPGA_NAME_LEN];
+ int i;
+
+ if (strlen(fpga_name) >= FPGA_NAME_LEN)
+ goto failure;
+ for (i = 0; i < strlen(fpga_name); i++)
+ name[i] = toupper(fpga_name[i]);
+ name[i] = '\0';
+ for (i = 0; i < fpga_count; i++) {
+ if (strcmp(name, fpga_list[i].name) == 0)
+ return &fpga_list[i];
+ }
+ failure:
+ printf("FPGA: name %s is invalid\n", fpga_name);
+ return NULL;
+}
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+static void fpga_status (fpga_t* fpga)
+{
+ /* Check state */
+ if (fpga_control(fpga, FPGA_DONE_IS_HIGH))
+ printf ("%s is loaded (%08lx)\n",
+ fpga->name, fpga_control(fpga, FPGA_GET_ID));
+ else
+ printf ("%s is NOT loaded\n", fpga->name);
+}
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+#define FPGA_RESET_TIMEOUT 100 /* = 10 ms */
+
+static int fpga_reset (fpga_t* fpga)
+{
+ int i;
+
+ /* Set PROG to low and wait til INIT goes low */
+ fpga_control(fpga, FPGA_PROG_SET_LOW);
+ for (i = 0; i < FPGA_RESET_TIMEOUT; i++) {
+ udelay (100);
+ if (!fpga_control(fpga, FPGA_INIT_IS_HIGH))
+ break;
+ }
+ if (i == FPGA_RESET_TIMEOUT)
+ goto failure;
+
+ /* Set PROG to high and wait til INIT goes high */
+ fpga_control(fpga, FPGA_PROG_SET_HIGH);
+ for (i = 0; i < FPGA_RESET_TIMEOUT; i++) {
+ udelay (100);
+ if (fpga_control(fpga, FPGA_INIT_IS_HIGH))
+ break;
+ }
+ if (i == FPGA_RESET_TIMEOUT)
+ goto failure;
+
+ return 0;
+ failure:
+ return 1;
+}
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+#define FPGA_LOAD_TIMEOUT 100 /* = 10 ms */
+
+static int fpga_load (fpga_t* fpga, ulong addr, int checkall)
+{
+ volatile uchar *fpga_addr = (volatile uchar *)fpga->conf_base;
+ image_header_t hdr;
+ ulong len, checksum;
+ uchar *data = (uchar *)&hdr;
+ char *s, msg[32];
+ int verify, i;
+
+ /*
+ * Check the image header and data of the net-list
+ */
+ memcpy (&hdr, (char *)addr, sizeof(image_header_t));
+
+ if (hdr.ih_magic != IH_MAGIC) {
+ strcpy (msg, "Bad Image Magic Number");
+ goto failure;
+ }
+
+ len = sizeof(image_header_t);
+
+ checksum = hdr.ih_hcrc;
+ hdr.ih_hcrc = 0;
+
+ if (crc32 (0, data, len) != checksum) {
+ strcpy (msg, "Bad Image Header CRC");
+ goto failure;
+ }
+
+ data = (uchar*)(addr + sizeof(image_header_t));
+ len = hdr.ih_size;
+
+ s = getenv ("verify");
+ verify = (s && (*s == 'n')) ? 0 : 1;
+ if (verify) {
+ if (crc32 (0, data, len) != hdr.ih_dcrc) {
+ strcpy (msg, "Bad Image Data CRC");
+ goto failure;
+ }
+ }
+
+ if (checkall && fpga_get_version(fpga, hdr.ih_name) < 0)
+ return 1;
+
+ /* align length */
+ if (len & 1)
+ ++len;
+
+ /*
+ * Reset FPGA and wait for completion
+ */
+ if (fpga_reset(fpga)) {
+ strcpy (msg, "Reset Timeout");
+ goto failure;
+ }
+
+ printf ("(%s)... ", hdr.ih_name);
+ /*
+ * Copy data to FPGA
+ */
+ fpga_control (fpga, FPGA_LOAD_MODE);
+ while (len--) {
+ *fpga_addr = *data++;
+ }
+ fpga_control (fpga, FPGA_READ_MODE);
+
+ /*
+ * Wait for completion and check error status if timeout
+ */
+ for (i = 0; i < FPGA_LOAD_TIMEOUT; i++) {
+ udelay (100);
+ if (fpga_control (fpga, FPGA_DONE_IS_HIGH))
+ break;
+ }
+ if (i == FPGA_LOAD_TIMEOUT) {
+ if (fpga_control(fpga, FPGA_INIT_IS_HIGH))
+ strcpy(msg, "Invalid Size");
+ else
+ strcpy(msg, "CRC Error");
+ goto failure;
+ }
+
+ printf("done\n");
+ return 0;
+
+ failure:
+
+ printf("ERROR: %s\n", msg);
+ return 1;
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_BSP)
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+int do_fpga (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ ulong addr = 0;
+ int i;
+ fpga_t* fpga;
+
+ if (argc < 2)
+ goto failure;
+
+ if (strncmp(argv[1], "stat", 4) == 0) { /* status */
+ if (argc == 2) {
+ for (i = 0; i < fpga_count; i++) {
+ fpga_status (&fpga_list[i]);
+ }
+ }
+ else if (argc == 3) {
+ if ((fpga = fpga_get(argv[2])) == 0)
+ goto failure;
+ fpga_status (fpga);
+ }
+ else
+ goto failure;
+ }
+ else if (strcmp(argv[1],"load") == 0) { /* load */
+ if (argc == 3 && fpga_count == 1) {
+ fpga = &fpga_list[0];
+ }
+ else if (argc == 4) {
+ if ((fpga = fpga_get(argv[2])) == 0)
+ goto failure;
+ }
+ else
+ goto failure;
+
+ addr = simple_strtoul(argv[argc-1], NULL, 16);
+
+ printf ("FPGA load %s: addr %08lx: ",
+ fpga->name, addr);
+ fpga_load (fpga, addr, 1);
+
+ }
+ else if (strncmp(argv[1], "rese", 4) == 0) { /* reset */
+ if (argc == 2 && fpga_count == 1) {
+ fpga = &fpga_list[0];
+ }
+ else if (argc == 3) {
+ if ((fpga = fpga_get(argv[2])) == 0)
+ goto failure;
+ }
+ else
+ goto failure;
+
+ printf ("FPGA reset %s: ", fpga->name);
+ if (fpga_reset(fpga))
+ printf ("ERROR: Timeout\n");
+ else
+ printf ("done\n");
+ }
+ else
+ goto failure;
+
+ return 0;
+
+ failure:
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+}
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_BSP */
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+int fpga_init (void)
+{
+ ulong addr;
+ ulong new_id, old_id = 0;
+ image_header_t *hdr;
+ fpga_t* fpga;
+ int do_load, i, j;
+ char name[16], *s;
+
+ /*
+ * Port setup for FPGA control
+ */
+ for (i = 0; i < fpga_count; i++) {
+ fpga_control(&fpga_list[i], FPGA_INIT_PORTS);
+ }
+
+ /*
+ * Load FPGA(s): a new net-list is loaded if the FPGA is
+ * empty, Power-on-Reset or the old one is not up-to-date
+ */
+ for (i = 0; i < fpga_count; i++) {
+ fpga = &fpga_list[i];
+ printf ("%s: ", fpga->name);
+
+ for (j = 0; j < strlen(fpga->name); j++)
+ name[j] = tolower(fpga->name[j]);
+ name[j] = '\0';
+ sprintf(name, "%s_addr", name);
+ addr = 0;
+ if ((s = getenv(name)) != NULL)
+ addr = simple_strtoul(s, NULL, 16);
+
+ if (!addr) {
+ printf ("env. variable %s undefined\n", name);
+ return 1;
+ }
+
+ hdr = (image_header_t *)addr;
+ if ((new_id = fpga_get_version(fpga, hdr->ih_name)) == -1)
+ return 1;
+
+ do_load = 1;
+
+ if (!power_on_reset() && fpga_control(fpga, FPGA_DONE_IS_HIGH)) {
+ old_id = fpga_control(fpga, FPGA_GET_ID);
+ if (new_id == old_id)
+ do_load = 0;
+ }
+
+ if (do_load) {
+ printf ("loading ");
+ fpga_load (fpga, addr, 0);
+ } else {
+ printf ("loaded (%08lx)\n", old_id);
+ }
+ }
+
+ return 0;
+}
diff --git a/board/smdk2400/u-boot.lds b/board/smdk2400/u-boot.lds
new file mode 100644
index 0000000000..8c9c218cca
--- /dev/null
+++ b/board/smdk2400/u-boot.lds
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ cpu/arm920t/start.o (.text)
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ armboot_end_data = .;
+
+ . = ALIGN(4);
+ .bss : { *(.bss) }
+
+ armboot_end = .;
+}
diff --git a/board/smdk2410/smdk2410.c b/board/smdk2410/smdk2410.c
new file mode 100644
index 0000000000..7f983ef5b8
--- /dev/null
+++ b/board/smdk2410/smdk2410.c
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
+ *
+ * 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 <s3c2410.h>
+
+/* ------------------------------------------------------------------------- */
+
+#define FCLK_SPEED 1
+
+#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
+#define M_MDIV 0xC3
+#define M_PDIV 0x4
+#define M_SDIV 0x1
+#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
+#define M_MDIV 0xA1
+#define M_PDIV 0x3
+#define M_SDIV 0x1
+#endif
+
+#define USB_CLOCK 1
+
+#if USB_CLOCK==0
+#define U_M_MDIV 0xA1
+#define U_M_PDIV 0x3
+#define U_M_SDIV 0x1
+#elif USB_CLOCK==1
+#define U_M_MDIV 0x48
+#define U_M_PDIV 0x3
+#define U_M_SDIV 0x2
+#endif
+
+static inline void delay (unsigned long loops)
+{
+ __asm__ volatile ("1:\n"
+ "subs %0, %1, #1\n"
+ "bne 1b":"=r" (loops):"0" (loops));
+}
+
+/*
+ * Miscellaneous platform dependent initialisations
+ */
+
+int board_init (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /* to reduce PLL lock time, adjust the LOCKTIME register */
+ rLOCKTIME = 0xFFFFFF;
+
+ /* configure MPLL */
+ rMPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
+
+ /* some delay between MPLL and UPLL */
+ delay (4000);
+
+ /* configure UPLL */
+ rUPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);
+
+ /* some delay between MPLL and UPLL */
+ delay (8000);
+
+ /* set up the I/O ports */
+ rGPACON = 0x007FFFFF;
+ rGPBCON = 0x00044555;
+ rGPBUP = 0x000007FF;
+ rGPCCON = 0xAAAAAAAA;
+ rGPCUP = 0x0000FFFF;
+ rGPDCON = 0xAAAAAAAA;
+ rGPDUP = 0x0000FFFF;
+ rGPECON = 0xAAAAAAAA;
+ rGPEUP = 0x0000FFFF;
+ rGPFCON = 0x000055AA;
+ rGPFUP = 0x000000FF;
+ rGPGCON = 0xFF95FFBA;
+ rGPGUP = 0x0000FFFF;
+ rGPHCON = 0x002AFAAA;
+ rGPHUP = 0x000007FF;
+
+ /* arch number of SMDK2410-Board */
+ gd->bd->bi_arch_number = 193;
+
+ /* adress of boot parameters */
+ gd->bd->bi_boot_params = 0x30000100;
+
+ icache_enable();
+ dcache_enable();
+
+ return 0;
+}
+
+int dram_init (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+
+ return 0;
+}
diff --git a/board/tqm8xx/flash.c b/board/tqm8xx/flash.c
new file mode 100644
index 0000000000..2f74ccccf2
--- /dev/null
+++ b/board/tqm8xx/flash.c
@@ -0,0 +1,569 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+
+#ifndef CFG_ENV_ADDR
+#define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
+#endif
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ unsigned long size_b0, size_b1;
+ int i;
+
+ /* Init: no FLASHes known */
+ for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ }
+
+ /* Static FLASH Bank configuration here - FIXME XXX */
+
+ size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+ if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+ printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+ size_b0, size_b0<<20);
+ }
+
+ size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+ if (size_b1 > size_b0) {
+ printf ("## ERROR: "
+ "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+ size_b1, size_b1<<20,
+ size_b0, size_b0<<20
+ );
+ flash_info[0].flash_id = FLASH_UNKNOWN;
+ flash_info[1].flash_id = FLASH_UNKNOWN;
+ flash_info[0].sector_count = -1;
+ flash_info[1].sector_count = -1;
+ flash_info[0].size = 0;
+ flash_info[1].size = 0;
+ return (0);
+ }
+
+ /* Remap FLASH according to real size */
+ memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK);
+ memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
+
+ /* Re-do sizing to get full correct info */
+ size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+ /* monitor protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+ &flash_info[0]);
+#endif
+
+#ifdef CFG_ENV_IS_IN_FLASH
+ /* ENV protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR+CFG_ENV_SIZE-1,
+ &flash_info[0]);
+#endif
+
+ if (size_b1) {
+ memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
+ memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
+ BR_MS_GPCM | BR_V;
+
+ /* Re-do sizing to get full correct info */
+ size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0),
+ &flash_info[1]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+ /* monitor protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+ &flash_info[1]);
+#endif
+
+#ifdef CFG_ENV_IS_IN_FLASH
+ /* ENV protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR+CFG_ENV_SIZE-1,
+ &flash_info[1]);
+#endif
+ } else {
+ memctl->memc_br1 = 0; /* invalidate bank */
+
+ flash_info[1].flash_id = FLASH_UNKNOWN;
+ flash_info[1].sector_count = -1;
+ }
+
+ flash_info[0].size = size_b0;
+ flash_info[1].size = size_b1;
+
+ return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t *info)
+{
+ int i;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD: printf ("AMD "); break;
+ case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
+ default: printf ("Unknown Vendor "); break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+ break;
+ case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+ break;
+ case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+ break;
+ case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+ break;
+ default: printf ("Unknown Chip Type\n");
+ break;
+ }
+
+ printf (" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+
+ printf (" Sector Start Addresses:");
+ for (i=0; i<info->sector_count; ++i) {
+ if ((i % 5) == 0)
+ printf ("\n ");
+ printf (" %08lX%s",
+ info->start[i],
+ info->protect[i] ? " (RO)" : " "
+ );
+ }
+ printf ("\n");
+ return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+ short i;
+ ulong value;
+ ulong base = (ulong)addr;
+
+ /* Write auto select command: read Manufacturer ID */
+ addr[0x0555] = 0x00AA00AA;
+ addr[0x02AA] = 0x00550055;
+ addr[0x0555] = 0x00900090;
+
+ value = addr[0];
+
+ switch (value) {
+ case AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+ case FUJ_MANUFACT:
+ info->flash_id = FLASH_MAN_FUJ;
+ break;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return (0); /* no or unknown flash */
+ }
+
+ value = addr[1]; /* device ID */
+
+ switch (value) {
+ case AMD_ID_LV400T:
+ info->flash_id += FLASH_AM400T;
+ info->sector_count = 11;
+ info->size = 0x00100000;
+ break; /* => 1 MB */
+
+ case AMD_ID_LV400B:
+ info->flash_id += FLASH_AM400B;
+ info->sector_count = 11;
+ info->size = 0x00100000;
+ break; /* => 1 MB */
+
+ case AMD_ID_LV800T:
+ info->flash_id += FLASH_AM800T;
+ info->sector_count = 19;
+ info->size = 0x00200000;
+ break; /* => 2 MB */
+
+ case AMD_ID_LV800B:
+ info->flash_id += FLASH_AM800B;
+ info->sector_count = 19;
+ info->size = 0x00200000;
+ break; /* => 2 MB */
+
+ case AMD_ID_LV160T:
+ info->flash_id += FLASH_AM160T;
+ info->sector_count = 35;
+ info->size = 0x00400000;
+ break; /* => 4 MB */
+
+ case AMD_ID_LV160B:
+ info->flash_id += FLASH_AM160B;
+ info->sector_count = 35;
+ info->size = 0x00400000;
+ break; /* => 4 MB */
+ case AMD_ID_LV320T:
+ info->flash_id += FLASH_AM320T;
+ info->sector_count = 71;
+ info->size = 0x00800000;
+ break; /* => 8 MB */
+
+ case AMD_ID_LV320B:
+ info->flash_id += FLASH_AM320B;
+ info->sector_count = 71;
+ info->size = 0x00800000;
+ break; /* => 8 MB */
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ return (0); /* => no or unknown flash */
+ }
+
+ /* set up sector start address table */
+ switch (value) {
+ case AMD_ID_LV400B:
+ case AMD_ID_LV800B:
+ case AMD_ID_LV160B:
+ /* set sector offsets for bottom boot block type */
+ info->start[0] = base + 0x00000000;
+ info->start[1] = base + 0x00008000;
+ info->start[2] = base + 0x0000C000;
+ info->start[3] = base + 0x00010000;
+ for (i = 4; i < info->sector_count; i++) {
+ info->start[i] = base + (i * 0x00020000) - 0x00060000;
+ }
+ break;
+ case AMD_ID_LV400T:
+ case AMD_ID_LV800T:
+ case AMD_ID_LV160T:
+ /* set sector offsets for top boot block type */
+ i = info->sector_count - 1;
+ info->start[i--] = base + info->size - 0x00008000;
+ info->start[i--] = base + info->size - 0x0000C000;
+ info->start[i--] = base + info->size - 0x00010000;
+ for (; i >= 0; i--) {
+ info->start[i] = base + i * 0x00020000;
+ }
+ break;
+ case AMD_ID_LV320B:
+ for (i = 0; i < info->sector_count; i++) {
+ info->start[i] = base;
+ /*
+ * The first 8 sectors are 8 kB,
+ * all the other ones are 64 kB
+ */
+ base += (i < 8)
+ ? 2 * ( 8 << 10)
+ : 2 * (64 << 10);
+ }
+ break;
+ case AMD_ID_LV320T:
+ for (i = 0; i < info->sector_count; i++) {
+ info->start[i] = base;
+ /*
+ * The last 8 sectors are 8 kB,
+ * all the other ones are 64 kB
+ */
+ base += (i < (info->sector_count - 8))
+ ? 2 * (64 << 10)
+ : 2 * ( 8 << 10);
+ }
+ break;
+ default:
+ return (0);
+ break;
+ }
+
+ /* check for protected sectors */
+ for (i = 0; i < info->sector_count; i++) {
+ /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+ /* D0 = 1 if protected */
+ addr = (volatile unsigned long *)(info->start[i]);
+ info->protect[i] = addr[2] & 1;
+ }
+
+ /*
+ * Prevent writes to uninitialized FLASH.
+ */
+ if (info->flash_id != FLASH_UNKNOWN) {
+ addr = (volatile unsigned long *)info->start[0];
+
+ *addr = 0x00F000F0; /* reset bank */
+ }
+
+ return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ vu_long *addr = (vu_long*)(info->start[0]);
+ int flag, prot, sect, l_sect;
+ ulong start, now, last;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("- missing\n");
+ } else {
+ printf ("- no sectors to erase\n");
+ }
+ return 1;
+ }
+
+ if ((info->flash_id == FLASH_UNKNOWN) ||
+ (info->flash_id > FLASH_AMD_COMP)) {
+ printf ("Can't erase unknown flash type %08lx - aborted\n",
+ info->flash_id);
+ return 1;
+ }
+
+ prot = 0;
+ for (sect=s_first; sect<=s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+
+ if (prot) {
+ printf ("- Warning: %d protected sectors will not be erased!\n",
+ prot);
+ } else {
+ printf ("\n");
+ }
+
+ l_sect = -1;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr[0x0555] = 0x00AA00AA;
+ addr[0x02AA] = 0x00550055;
+ addr[0x0555] = 0x00800080;
+ addr[0x0555] = 0x00AA00AA;
+ addr[0x02AA] = 0x00550055;
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect<=s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ addr = (vu_long*)(info->start[sect]);
+ addr[0] = 0x00300030;
+ l_sect = sect;
+ }
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ /*
+ * We wait for the last triggered sector
+ */
+ if (l_sect < 0)
+ goto DONE;
+
+ start = get_timer (0);
+ last = start;
+ addr = (vu_long*)(info->start[l_sect]);
+ while ((addr[0] & 0x00800080) != 0x00800080) {
+ if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+ printf ("Timeout\n");
+ return 1;
+ }
+ /* show that we're waiting */
+ if ((now - last) > 1000) { /* every second */
+ putc ('.');
+ last = now;
+ }
+ }
+
+DONE:
+ /* reset to read mode */
+ addr = (volatile unsigned long *)info->start[0];
+ addr[0] = 0x00F000F0; /* reset bank */
+
+ 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)
+{
+ vu_long *addr = (vu_long*)(info->start[0]);
+ ulong start;
+ int flag;
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*((vu_long *)dest) & data) != data) {
+ return (2);
+ }
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr[0x0555] = 0x00AA00AA;
+ addr[0x02AA] = 0x00550055;
+ addr[0x0555] = 0x00A000A0;
+
+ *((vu_long *)dest) = data;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* data polling for D7 */
+ start = get_timer (0);
+ while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/tqm8xx/load_sernum_ethaddr.c b/board/tqm8xx/load_sernum_ethaddr.c
new file mode 100644
index 0000000000..98baf7f67d
--- /dev/null
+++ b/board/tqm8xx/load_sernum_ethaddr.c
@@ -0,0 +1,105 @@
+/*
+ * (C) Copyright 2000, 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+
+/*-----------------------------------------------------------------------
+ * Process Hardware Information Block:
+ *
+ * If we boot on a system fresh from factory, check if the Hardware
+ * Information Block exists and save the information it contains.
+ *
+ * The TQM8xxL / TQM82xx Hardware Information Block is defined as
+ * follows:
+ * - located in first flash bank
+ * - starts at offset 0x0003FFC0
+ * - size 0x00000040
+ *
+ * Internal structure:
+ * - sequence of ASCII character strings
+ * - fields separated by a single space character (0x20)
+ * - last field terminated by NUL character (0x00)
+ * - remaining space filled with NUL characters (0x00)
+ *
+ * Fields in Hardware Information Block:
+ * 1) Module Type
+ * 2) Serial Number
+ * 3) First MAC Address
+ * 4) Number of additional MAC addresses
+ */
+
+void load_sernum_ethaddr (void)
+{
+ unsigned char *hwi;
+ unsigned char serial [CFG_HWINFO_SIZE];
+ unsigned char ethaddr[CFG_HWINFO_SIZE];
+ unsigned short ih, is, ie, part;
+
+ hwi = (unsigned char *)(CFG_FLASH_BASE + CFG_HWINFO_OFFSET);
+ ih = is = ie = 0;
+
+ if (*((unsigned long *)hwi) != (unsigned long)CFG_HWINFO_MAGIC) {
+ return;
+ }
+
+ part = 1;
+
+ /* copy serial # / MAC address */
+ while ((hwi[ih] != '\0') && (ih < CFG_HWINFO_SIZE)) {
+ if (hwi[ih] < ' ' || hwi[ih] > '~') { /* ASCII strings! */
+ return;
+ }
+ switch (part) {
+ default: /* Copy serial # */
+ if (hwi[ih] == ' ') {
+ ++part;
+ }
+ serial[is++] = hwi[ih];
+ break;
+ case 3: /* Copy MAC address */
+ if (hwi[ih] == ' ') {
+ ++part;
+ break;
+ }
+ ethaddr[ie++] = hwi[ih];
+ if ((ie % 3) == 2)
+ ethaddr[ie++] = ':';
+ break;
+ }
+ ++ih;
+ }
+ serial[is] = '\0';
+ if (ie && ethaddr[ie-1] == ':')
+ --ie;
+ ethaddr[ie] = '\0';
+
+ /* set serial# and ethaddr if not yet defined */
+ if (getenv("serial#") == NULL) {
+ setenv ("serial#", serial);
+ }
+
+ if (getenv("ethaddr") == NULL) {
+ setenv ("ethaddr", ethaddr);
+ }
+}
diff --git a/board/trab/README.kbd b/board/trab/README.kbd
new file mode 100644
index 0000000000..3db00bccec
--- /dev/null
+++ b/board/trab/README.kbd
@@ -0,0 +1,44 @@
+
+The TRAB keyboard implementation is similar to that for LWMON and
+R360MPI boards. The only difference concerns key naming. There are 4
+keys on TRAB: 1, 2, 3, 4.
+
+1) The "kbd" command provides information about the current state of
+ the keys. For example,
+
+ TRAB # kbd
+ Keys: 1 0 1 0
+
+ means that keys 1 and 3 are pressed. The keyboard status is also
+ stored in the "keybd" environment variable. In this example we get
+
+ keybd=1010
+
+2) The "preboot" variable is set according to current environment
+ settings and keys pressed. This is an example:
+
+ TRAB # setenv magic_keys XY
+ TRAB # setenv key_magicX 12
+ TRAB # setenv key_cmdX echo ## Keys 1 + 2 pressed ##\;echo
+ TRAB # setenv key_magicY 13
+ TRAB # setenv key_cmdY echo ## Keys 1 + 3 pressed ##\;echo
+
+ Here "magic_keys=XY" means that the "key_magicX" and "key_magicY"
+ variables will be checked for a match. Each variable "key_magic*"
+ defines a set of keys. In the our example, if keys 1 and 3 are
+ pressed during reset, then "key_magicY" matches, so the "preboot"
+ variable will be set to the contents of "key_cmdY":
+
+ preboot=echo ## Keys 1 + 3 pressed ##;echo
+
+3) The TRAB board has optional modem support. When a certain key
+ combination is pressed on the keyboard at power-on, the firmware
+ performs the necessary initialization of the modem and allows for
+ dial-in. The key combination is specified in the
+ "include/configs/trab.h" file. For example:
+
+ #define CONFIG_MODEM_KEY_MAGIC "23"
+
+ means that modem will be initialized if and only if both keys 2, 3
+ are pressed. Note that the format of this string is similar to the
+ format of "key_magic*" environment variables described above.
diff --git a/board/trab/trab.c b/board/trab/trab.c
new file mode 100644
index 0000000000..3f9b198698
--- /dev/null
+++ b/board/trab/trab.c
@@ -0,0 +1,301 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* #define DEBUG */
+
+#include <common.h>
+#include <cmd_bsp.h>
+#include <malloc.h>
+#include <s3c2400.h>
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_MODEM_SUPPORT
+static int key_pressed(void);
+extern void disable_putc(void);
+extern int do_mdm_init; /* defined in common/main.c */
+
+/*
+ * We need a delay of at least 500 us after turning on the VFD clock
+ * before we can read any useful information for the CPLD controlling
+ * the keyboard switches. Let's play safe and wait 5 ms. The problem
+ * is that timers are not available yet, so we use a manually timed
+ * loop.
+ */
+#define KBD_MDELAY 100000 /* 1000 */
+static void mdelay_no_timer (int msec)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ int i;
+ int delay = msec * 3;
+
+ for (i = 0; i < delay; i ++) gd->bd->bi_arch_number = 145;
+}
+#endif /* CONFIG_MODEM_SUPPORT */
+
+/*
+ * Miscellaneous platform dependent initialisations
+ */
+
+int board_init ()
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /* memory and cpu-speed are setup before relocation */
+#ifdef CONFIG_TRAB_50MHZ
+ /* change the clock to be 50 MHz 1:1:1 */
+ /* MDIV:0x5c PDIV:4 SDIV:2 */
+ rMPLLCON = 0x5c042;
+ rCLKDIVN = 0;
+#else
+ /* change the clock to be 133 MHz 1:2:4 */
+ /* MDIV:0x7d PDIV:4 SDIV:1 */
+ rMPLLCON = 0x7d041;
+ rCLKDIVN = 3;
+#endif
+
+ /* set up the I/O ports */
+ rPACON = 0x3ffff;
+ rPBCON = 0xaaaaaaaa;
+ rPBUP = 0xffff;
+ /* INPUT nCTS0 nRTS0 TXD[1] TXD[0] RXD[1] RXD[0] */
+ /* 00, 10, 10, 10, 10, 10, 10 */
+ rPFCON = (2<<0) | (2<<2) | (2<<4) | (2<<6) | (2<<8) | (2<<10);
+#ifdef CONFIG_HWFLOW
+ /* do not pull up RXD0, RXD1, TXD0, TXD1, CTS0, RTS0 */
+ rPFUP = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5);
+#else
+ /* do not pull up RXD0, RXD1, TXD0, TXD1 */
+ rPFUP = (1<<0) | (1<<1) | (1<<2) | (1<<3);
+#endif
+ rPGCON = 0x0;
+ rPGUP = 0x0;
+ rOPENCR= 0x0;
+
+ /* arch number of SAMSUNG-Board */
+ /* MACH_TYPE_SMDK2400 */
+ /* XXX this isn't really correct, but keep it for now */
+ gd->bd->bi_arch_number = 145;
+
+ /* adress of boot parameters */
+ gd->bd->bi_boot_params = 0x0c000100;
+
+#ifdef CONFIG_MODEM_SUPPORT
+ /* This stuff is needed to get interrupts on stop-position
+ * contact events.
+ * (Copied from the LCD initialization routine.)
+ */
+ if (rLCDCON1 == 0)
+ {
+ rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA;
+ rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8;
+#if 0
+ rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA;
+#endif
+ rLCDCON2 = 0x000DC000;
+ rLCDCON3 = 0x0051000A;
+ rLCDCON4 = 0x00000001;
+ rLCDCON5 = 0x00000440;
+ rLCDCON1 = 0x00000B75;
+ }
+
+ mdelay_no_timer (KBD_MDELAY);
+
+ if (key_pressed()) {
+ disable_putc(); /* modem doesn't understand banner etc */
+ do_mdm_init = 1;
+ }
+#endif /* CONFIG_MODEM_SUPPORT */
+
+ return 0;
+}
+
+int dram_init (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Keyboard Controller
+ */
+
+/* Maximum key number */
+#define KEYBD_KEY_NUM 4
+
+#define KBD_DATA (((*(volatile ulong *)0x04020000) >> 16) & 0xF)
+
+static uchar *key_match (ulong);
+
+int misc_init_r (void)
+{
+ ulong kbd_data = KBD_DATA;
+ uchar keybd_env[KEYBD_KEY_NUM + 1];
+ uchar *str;
+ int i;
+
+ for (i = 0; i < KEYBD_KEY_NUM; ++i) {
+ keybd_env[i] = '0' + ((kbd_data >> i) & 1);
+ }
+ keybd_env[i] = '\0';
+ debug ("** Setting keybd=\"%s\"\n", keybd_env);
+ setenv ("keybd", keybd_env);
+
+ str = strdup (key_match (kbd_data)); /* decode keys */
+
+#ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */
+ debug ("** Setting preboot=\"%s\"\n", str);
+ setenv ("preboot", str); /* set or delete definition */
+#endif /* CONFIG_PREBOOT */
+ if (str != NULL) {
+ free (str);
+ }
+
+ return (0);
+}
+
+#ifdef CONFIG_PREBOOT
+
+static uchar kbd_magic_prefix[] = "key_magic";
+static uchar kbd_command_prefix[] = "key_cmd";
+
+static int compare_magic (ulong kbd_data, uchar *str)
+{
+ uchar key_mask;
+
+ debug ("compare_magic: kbd: %04lx str: \"%s\"\n",kbd_data,str);
+ for (; *str; str++)
+ {
+ uchar c = *str - '1';
+
+ if (c >= KEYBD_KEY_NUM) /* bad key number */
+ return -1;
+
+ key_mask = 1 << c;
+
+ if (!(kbd_data & key_mask)) { /* key not pressed */
+ debug ( "compare_magic: "
+ "kbd: %04lx mask: %04lx - key not pressed\n",
+ kbd_data, key_mask );
+ return -1;
+ }
+
+ kbd_data &= ~key_mask;
+ }
+
+ if (kbd_data) { /* key(s) not released */
+ debug ( "compare_magic: "
+ "kbd: %04lx - key(s) not released\n", kbd_data);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Check if pressed key(s) match magic sequence,
+ * and return the command string associated with that key(s).
+ *
+ * If no key press was decoded, NULL is returned.
+ *
+ * Note: the first character of the argument will be overwritten with
+ * the "magic charcter code" of the decoded key(s), or '\0'.
+ *
+ *
+ * Note: the string points to static environment data and must be
+ * saved before you call any function that modifies the environment.
+ */
+static uchar *key_match (ulong kbd_data)
+{
+ uchar magic[sizeof (kbd_magic_prefix) + 1];
+ uchar cmd_name[sizeof (kbd_command_prefix) + 1];
+ uchar *suffix;
+ uchar *kbd_magic_keys;
+
+ /*
+ * The following string defines the characters that can pe appended
+ * to "key_magic" to form the names of environment variables that
+ * hold "magic" key codes, i. e. such key codes that can cause
+ * pre-boot actions. If the string is empty (""), then only
+ * "key_magic" is checked (old behaviour); the string "125" causes
+ * checks for "key_magic1", "key_magic2" and "key_magic5", etc.
+ */
+ if ((kbd_magic_keys = getenv ("magic_keys")) == NULL)
+ kbd_magic_keys = "";
+
+ debug ("key_match: magic_keys=\"%s\"\n", kbd_magic_keys);
+
+ /* loop over all magic keys;
+ * use '\0' suffix in case of empty string
+ */
+ for (suffix=kbd_magic_keys; *suffix || suffix==kbd_magic_keys; ++suffix)
+ {
+ sprintf (magic, "%s%c", kbd_magic_prefix, *suffix);
+
+ debug ("key_match: magic=\"%s\"\n",
+ getenv(magic) ? getenv(magic) : "<UNDEFINED>");
+
+ if (compare_magic(kbd_data, getenv(magic)) == 0)
+ {
+ sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix);
+ debug ("key_match: cmdname %s=\"%s\"\n",
+ cmd_name,
+ getenv (cmd_name) ?
+ getenv (cmd_name) :
+ "<UNDEFINED>");
+ return (getenv (cmd_name));
+ }
+ }
+ debug ("key_match: no match\n");
+ return (NULL);
+}
+#endif /* CONFIG_PREBOOT */
+
+/* Read Keyboard status */
+int do_kbd (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ ulong kbd_data = KBD_DATA;
+ uchar keybd_env[KEYBD_KEY_NUM + 1];
+ int i;
+
+ puts ("Keys:");
+ for (i = 0; i < KEYBD_KEY_NUM; ++i) {
+ keybd_env[i] = '0' + ((kbd_data >> i) & 1);
+ printf (" %c", keybd_env[i]);
+ }
+ keybd_env[i] = '\0';
+ putc ('\n');
+ setenv ("keybd", keybd_env);
+ return 0;
+}
+
+#ifdef CONFIG_MODEM_SUPPORT
+static int key_pressed(void)
+{
+ return (compare_magic(KBD_DATA, CONFIG_MODEM_KEY_MAGIC) == 0);
+}
+#endif /* CONFIG_MODEM_SUPPORT */
diff --git a/board/trab/u-boot.lds b/board/trab/u-boot.lds
new file mode 100644
index 0000000000..59834afb83
--- /dev/null
+++ b/board/trab/u-boot.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ cpu/arm920t/start.o (.text)
+ lib_arm/_udivsi3.o (.text)
+ lib_arm/_umodsi3.o (.text)
+ lib_generic/zlib.o (.text)
+ lib_generic/crc32.o (.text)
+ lib_generic/string.o (.text)
+
+ . = env_offset;
+ common/environment.o (.ppcenv)
+
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ armboot_end_data = .;
+
+ . = ALIGN(4);
+ .bss : { *(.bss) }
+
+ armboot_end = .;
+}
diff --git a/board/trab/vfd.c b/board/trab/vfd.c
new file mode 100644
index 0000000000..1ea483f0c6
--- /dev/null
+++ b/board/trab/vfd.c
@@ -0,0 +1,414 @@
+/*
+ * (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
+ */
+
+/************************************************************************/
+/* ** DEBUG SETTINGS */
+/************************************************************************/
+
+/* #define DEBUG */
+
+/************************************************************************/
+/* ** HEADER FILES */
+/************************************************************************/
+
+#include <config.h>
+#include <common.h>
+#include <version.h>
+#include <stdarg.h>
+#include <linux/types.h>
+#include <devices.h>
+#include <s3c2400.h>
+
+#ifdef CONFIG_VFD
+
+/************************************************************************/
+/* ** CONFIG STUFF -- should be moved to board config file */
+/************************************************************************/
+
+/************************************************************************/
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+#define ROT 0x09
+#define BLAU 0x0C
+#define VIOLETT 0X0D
+
+ulong vfdbase;
+ulong frame_buf_size;
+#define frame_buf_offs 4
+
+/* taken from armboot/common/vfd.c */
+ulong adr_vfd_table[112][18][2][4][2];
+unsigned char bit_vfd_table[112][18][2][4][2];
+
+/*
+ * initialize the values for the VFD-grid-control in the framebuffer
+ */
+void init_grid_ctrl(void)
+{
+ ulong adr, grid_cycle;
+ unsigned int bit, display;
+ unsigned char temp, bit_nr;
+
+ for (adr=vfdbase; adr<=(vfdbase+7168); adr+=4) /*clear frame buffer */
+ (*(volatile ulong*)(adr))=0;
+
+ for(display=0;display<=3;display++)
+ {
+ for(grid_cycle=0;grid_cycle<=55;grid_cycle++)
+ {
+ bit = grid_cycle*256*4+(grid_cycle+200)*4+frame_buf_offs+display;
+ /* wrap arround if offset (see manual S3C2400) */
+ if (bit>=frame_buf_size*8)
+ bit = bit-(frame_buf_size*8);
+ adr = vfdbase+(bit/32)*4+(3-(bit%32)/8);
+ bit_nr = bit%8;
+ bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
+ temp=(*(volatile unsigned char*)(adr));
+ temp|=(1<<bit_nr);
+ (*(volatile unsigned char*)(adr))=temp;
+
+ if(grid_cycle<55)
+ bit = grid_cycle*256*4+(grid_cycle+201)*4+frame_buf_offs+display;
+ else
+ bit = grid_cycle*256*4+200*4+frame_buf_offs+display-4; /* grid nr. 0 */
+ /* wrap arround if offset (see manual S3C2400) */
+ if (bit>=frame_buf_size*8)
+ bit = bit-(frame_buf_size*8);
+ adr = vfdbase+(bit/32)*4+(3-(bit%32)/8);
+ bit_nr = bit%8;
+ bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
+ temp=(*(volatile unsigned char*)(adr));
+ temp|=(1<<bit_nr);
+ (*(volatile unsigned char*)(adr))=temp;
+ }
+ }
+}
+
+/*
+ *create translation table for getting easy the right position in the
+ *physical framebuffer for some x/y-coordinates of the VFDs
+ */
+void create_vfd_table(void)
+{
+ unsigned int vfd_table[112][18][2][4][2];
+ ulong adr;
+ unsigned int x, y, color, display, entry, pixel, bit_nr;
+
+ /*
+ * Create translation table for Noritake-T119C-VFD-specific
+ * organized frame-buffer.
+ * Created is the number of the bit in the framebuffer (the
+ * first transferred pixel of each frame is bit 0).
+ */
+ for(y=0;y<=17;y++) /* Zeile */
+ {
+ for(x=0;x<=111;x++) /* Spalten */
+ {
+ /*Display 0 blaue Pixel Eintrag 1 */
+ vfd_table[x][y][0][0][0]=((x%4)*4+y*16+(x/4)*2048);
+ /*Display 0 rote Pixel Eintrag 1 */
+ vfd_table[x][y][1][0][0]=((x%4)*4+y*16+(x/4)*2048+512);
+ if(x<=1)
+ {
+ /*Display 0 blaue Pixel Eintrag 2 */
+ vfd_table[x][y][0][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1024);
+ /*Display 0 rote Pixel Eintrag 2 */
+ vfd_table[x][y][1][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1024);
+ }
+ else
+ {
+ /*Display 0 blaue Pixel Eintrag 2 */
+ vfd_table[x][y][0][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+1024);
+ /*Display 0 rote Pixel Eintrag 2 */
+ vfd_table[x][y][1][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1024);
+ }
+ /*Display 1 blaue Pixel Eintrag 1 */
+ vfd_table[x][y][0][1][0]=((x%4)*4+y*16+(x/4)*2048+1);
+ /*Display 1 rote Pixel Eintrag 1 */
+ vfd_table[x][y][1][1][0]=((x%4)*4+y*16+(x/4)*2048+512+1);
+ if(x<=1)
+ {
+ /*Display 1 blaue Pixel Eintrag 2 */
+ vfd_table[x][y][0][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1+1024);
+ /*Display 1 rote Pixel Eintrag 2 */
+ vfd_table[x][y][1][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1+1024);
+ }
+ else
+ {
+ /*Display 1 blaue Pixel Eintrag 2 */
+ vfd_table[x][y][0][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+1+1024);
+ /*Display 1 rote Pixel Eintrag 2 */
+ vfd_table[x][y][1][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1+1024);
+ }
+ /*Display 2 blaue Pixel Eintrag 1 */
+ vfd_table[x][y][0][2][0]=((x%4)*4+y*16+(x/4)*2048+2);
+ /*Display 2 rote Pixel Eintrag 1 */
+ vfd_table[x][y][1][2][0]=((x%4)*4+y*16+(x/4)*2048+512+2);
+ if(x<=1)
+ {
+ /*Display 2 blaue Pixel Eintrag 2 */
+ vfd_table[x][y][0][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+2+1024);
+ /*Display 2 rote Pixel Eintrag 2 */
+ vfd_table[x][y][1][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+2+1024);
+ }
+ else
+ {
+ /*Display 2 blaue Pixel Eintrag 2 */
+ vfd_table[x][y][0][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+2+1024);
+ /*Display 2 rote Pixel Eintrag 2 */
+ vfd_table[x][y][1][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+2+1024);
+ }
+ /*Display 3 blaue Pixel Eintrag 1 */
+ vfd_table[x][y][0][3][0]=((x%4)*4+y*16+(x/4)*2048+3);
+ /*Display 3 rote Pixel Eintrag 1 */
+ vfd_table[x][y][1][3][0]=((x%4)*4+y*16+(x/4)*2048+512+3);
+ if(x<=1)
+ {
+ /*Display 3 blaue Pixel Eintrag 2 */
+ vfd_table[x][y][0][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+3+1024);
+ /*Display 3 rote Pixel Eintrag 2 */
+ vfd_table[x][y][1][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+3+1024);
+ }
+ else
+ {
+ /*Display 3 blaue Pixel Eintrag 2 */
+ vfd_table[x][y][0][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+3+1024);
+ /*Display 3 rote Pixel Eintrag 2 */
+ vfd_table[x][y][1][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+3+1024);
+ }
+ }
+ }
+
+ /*
+ * Create translation table for Noritake-T119C-VFD-specific
+ * organized frame-buffer
+ * Create table with entries for physical byte adresses and
+ * bit-number within the byte
+ * from table with bit-numbers within the total framebuffer
+ */
+ for(y=0;y<=17;y++)
+ {
+ for(x=0;x<=111;x++)
+ {
+ for(color=0;color<=1;color++)
+ {
+ for(display=0;display<=3;display++)
+ {
+ for(entry=0;entry<=1;entry++)
+ {
+ pixel = vfd_table[x][y][color][display][entry] + frame_buf_offs;
+ /*
+ * wrap arround if offset
+ * (see manual S3C2400)
+ */
+ if (pixel>=frame_buf_size*8)
+ pixel = pixel-(frame_buf_size*8);
+ adr = vfdbase+(pixel/32)*4+(3-(pixel%32)/8);
+ bit_nr = pixel%8;
+ bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
+ adr_vfd_table[x][y][color][display][entry] = adr;
+ bit_vfd_table[x][y][color][display][entry] = bit_nr;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Set/clear pixel of the VFDs
+ */
+void set_vfd_pixel(unsigned char x, unsigned char y, unsigned char color, unsigned char display, unsigned char value)
+{
+ ulong adr;
+ unsigned char bit_nr, temp;
+
+ if (value!=0)
+ {
+ /* Pixel-Eintrag Nr. 1 */
+ adr = adr_vfd_table[x][y][color][display][0];
+ /* Pixel-Eintrag Nr. 1 */
+ bit_nr = bit_vfd_table[x][y][color][display][0];
+ temp=(*(volatile unsigned char*)(adr));
+ temp|=1<<bit_nr;
+ (*(volatile unsigned char*)(adr))=temp;
+
+ /* Pixel-Eintrag Nr. 2 */
+ adr = adr_vfd_table[x][y][color][display][1];
+ /* Pixel-Eintrag Nr. 2 */
+ bit_nr = bit_vfd_table[x][y][color][display][1];
+ temp=(*(volatile unsigned char*)(adr));
+ temp|=1<<bit_nr;
+ (*(volatile unsigned char*)(adr))=temp;
+ }
+ else
+ {
+ /* Pixel-Eintrag Nr. 1 */
+ adr = adr_vfd_table[x][y][color][display][0];
+ /* Pixel-Eintrag Nr. 1 */
+ bit_nr = bit_vfd_table[x][y][color][display][0];
+ temp=(*(volatile unsigned char*)(adr));
+ temp&=~(1<<bit_nr);
+ (*(volatile unsigned char*)(adr))=temp;
+
+ /* Pixel-Eintrag Nr. 2 */
+ adr = adr_vfd_table[x][y][color][display][1];
+ /* Pixel-Eintrag Nr. 2 */
+ bit_nr = bit_vfd_table[x][y][color][display][1];
+ temp=(*(volatile unsigned char*)(adr));
+ temp&=~(1<<bit_nr);
+ (*(volatile unsigned char*)(adr))=temp;
+ }
+}
+
+/*
+ * transfer image from BMP-File
+ */
+void transfer_pic(int display, unsigned char *adr, int height, int width)
+{
+ int x, y;
+ unsigned char temp;
+
+ for (; height > 0; height -= 18)
+ {
+ if (height > 18)
+ y = 18;
+ else
+ y = height;
+ for (; y > 0; y--)
+ {
+ for (x = 0; x < width; x += 2)
+ {
+ temp = *adr++;
+ set_vfd_pixel(x, y-1, 0, display, 0);
+ set_vfd_pixel(x, y-1, 1, display, 0);
+ if ((temp >> 4) == BLAU)
+ set_vfd_pixel(x, y-1, 0, display, 1);
+ else if ((temp >> 4) == ROT)
+ set_vfd_pixel(x, y-1, 1, display, 1);
+ else if ((temp >> 4) == VIOLETT)
+ {
+ set_vfd_pixel(x, y-1, 0, display, 1);
+ set_vfd_pixel(x, y-1, 1, display, 1);
+ }
+ set_vfd_pixel(x+1, y-1, 0, display, 0);
+ set_vfd_pixel(x+1, y-1, 1, display, 0);
+ if ((temp & 0x0F) == BLAU)
+ set_vfd_pixel(x+1, y-1, 0, display, 1);
+ else if ((temp & 0x0F) == ROT)
+ set_vfd_pixel(x+1, y-1, 1, display, 1);
+ else if ((temp & 0x0F) == VIOLETT)
+ {
+ set_vfd_pixel(x+1, y-1, 0, display, 1);
+ set_vfd_pixel(x+1, y-1, 1, display, 1);
+ }
+ }
+ }
+ display++;
+ if (display > 3)
+ display = 0;
+ }
+}
+
+/*
+ * initialize LCD-Controller of the S3C2400 for using VFDs
+ */
+int drv_vfd_init(void)
+{
+ ulong palette;
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ vfdbase = gd->fb_base;
+ create_vfd_table();
+ init_grid_ctrl();
+
+ /*
+ * Hinweis: Der Framebuffer ist um genau ein Nibble verschoben
+ * Das erste angezeigte Pixel wird aus dem zweiten Nibble geholt
+ * das letzte angezeigte Pixel wird aus dem ersten Nibble geholt
+ * (wrap around)
+ * see manual S3C2400
+ */
+ /* frame buffer startadr */
+ rLCDSADDR1 = vfdbase >> 1;
+ /* frame buffer endadr */
+ rLCDSADDR2 = (vfdbase + frame_buf_size) >> 1;
+ rLCDSADDR3 = ((256/4));
+
+ /* Port-Pins als LCD-Ausgang */
+ rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA;
+ /* Port-Pins als LCD-Ausgang */
+ rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8;
+#ifdef WITH_VFRAME
+ /* mit VFRAME zum Messen */
+ rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA;
+#endif
+
+ rLCDCON2 = 0x000DC000;
+ rLCDCON3 = 0x0051000A;
+ rLCDCON4 = 0x00000001;
+ rLCDCON5 = 0x00000440;
+ rLCDCON1 = 0x00000B75;
+
+ debug ("LCDSADDR1: %lX\n", rLCDSADDR1);
+ debug ("LCDSADDR2: %lX\n", rLCDSADDR2);
+ debug ("LCDSADDR3: %lX\n", rLCDSADDR3);
+
+ for(palette=0;palette<=15;palette++)
+ (*(volatile unsigned int*)(PALETTE+(palette*4)))=palette;
+ for(palette=16;palette<=255;palette++)
+ (*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00;
+
+ return 0;
+}
+
+/************************************************************************/
+/* ** ROM capable initialization part - needed to reserve FB memory */
+/************************************************************************/
+
+/*
+ * This is called early in the system initialization to grab memory
+ * for the VFD controller.
+ *
+ * Note that this is running from ROM, so no write access to global data.
+ */
+ulong vfd_setmem (ulong addr)
+{
+ ulong size;
+
+ /* MAGIC */
+ frame_buf_size = (256*4*56)/8;
+
+ /* Round up to nearest full page */
+ size = (frame_buf_size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+
+ debug ("Reserving %ldk for VFD Framebuffer at: %08lx\n", size>>10, addr);
+
+ return (size);
+}
+
+#endif /* CONFIG_VFD */
diff --git a/board/utx8245/utx8245.c b/board/utx8245/utx8245.c
new file mode 100644
index 0000000000..249862a5a4
--- /dev/null
+++ b/board/utx8245/utx8245.c
@@ -0,0 +1,152 @@
+/*
+ * (C) Copyright 2001
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * (C) Copyright 2002
+ * Gregory E. Allen, gallen@arlut.utexas.edu
+ * Matthew E. Karger, karger@arlut.utexas.edu
+ * Applied Research Laboratories, The University of Texas at Austin
+ *
+ * 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/io.h>
+#include <pci.h>
+
+#define SAVE_SZ 32
+
+
+int checkboard(void)
+{
+ ulong busfreq = get_bus_freq(0);
+ char buf[32];
+
+ printf("Board: UTX8245 Local Bus at %s MHz\n", strmhz(buf, busfreq));
+ return 0;
+}
+
+
+long int initdram(int board_type)
+{
+#if 1
+ int i, cnt;
+ volatile uchar *base = CFG_SDRAM_BASE;
+ volatile ulong *addr;
+ ulong save[SAVE_SZ];
+ ulong val, ret = 0;
+
+ for (i=0; i<SAVE_SZ; i++) {save[i] = 0;} /* clear table */
+
+ for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1)
+ {
+ addr = (volatile ulong *)base + cnt;
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ addr = (volatile ulong *)base;
+ save[i] = *addr;
+ *addr = 0;
+
+ if (*addr != 0)
+ {
+ *addr = save[i];
+ goto Done;
+ }
+
+ for (cnt = 1; cnt < CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1)
+ {
+ addr = (volatile ulong *)base + cnt;
+ val = *addr;
+ *addr = save[--i];
+ if (val != ~cnt)
+ {
+ ulong new_bank0_end = cnt * sizeof(long) - 1;
+ ulong mear1 = mpc824x_mpc107_getreg(MEAR1);
+ ulong emear1 = mpc824x_mpc107_getreg(EMEAR1);
+ mear1 = (mear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT);
+ emear1 = (emear1 & 0xFFFFFF00) |
+ ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT);
+ mpc824x_mpc107_setreg(MEAR1, mear1);
+ mpc824x_mpc107_setreg(EMEAR1, emear1);
+
+ ret = cnt * sizeof(long);
+ goto Done;
+ }
+ }
+
+ ret = CFG_MAX_RAM_SIZE;
+Done:
+ return ret;
+#else
+ return (CFG_MAX_RAM_SIZE);
+#endif
+
+}
+
+
+/*
+ * Initialize PCI Devices, report devices found.
+ */
+
+static struct pci_config_table pci_utx8245_config_table[] = {
+#ifndef CONFIG_PCI_PNP
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
+ PCI_ENET0_MEMADDR,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ pci_cfgfunc_config_device, { PCI_FIREWIRE_IOADDR,
+ PCI_FIREWIRE_MEMADDR,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
+#endif /*CONFIG_PCI_PNP*/
+ { }
+};
+
+
+static void pci_utx8245_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
+{
+ if (PCI_DEV(dev) == 11)
+ /* assign serial interrupt line 9 (int25) to FireWire */
+ pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 25);
+
+ else if (PCI_DEV(dev) == 12)
+ /* assign serial interrupt line 8 (int24) to Ethernet */
+ pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 24);
+}
+
+static struct pci_controller utx8245_hose = {
+#ifndef CONFIG_PCI_PNP
+ config_table: pci_utx8245_config_table,
+ fixup_irq: pci_utx8245_fixup_irq,
+ write_byte: pci_hose_write_config_byte
+#endif /*CONFIG_PCI_PNP*/
+};
+
+void pci_init (void)
+{
+ pci_mpc824x_init(&utx8245_hose);
+
+ icache_enable();
+}
+
diff --git a/board/w7o/flash.c b/board/w7o/flash.c
new file mode 100644
index 0000000000..0048476236
--- /dev/null
+++ b/board/w7o/flash.c
@@ -0,0 +1,941 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
+ * Based on code by:
+ * 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 <ppc4xx.h>
+#include <asm/processor.h>
+
+#include <watchdog.h>
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word8(flash_info_t *info, ulong dest, ulong data);
+static int write_word32 (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+ int i;
+ unsigned long size_b0, base_b0;
+ unsigned long size_b1, base_b1;
+
+ /* Init: no FLASHes known */
+ for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ }
+
+ /* Get Size of Boot and Main Flashes */
+ size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+ if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+ printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+ size_b0, size_b0<<20);
+ return 0;
+ }
+ size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+ if (flash_info[1].flash_id == FLASH_UNKNOWN) {
+ printf ("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
+ size_b1, size_b1<<20);
+ return 0;
+ }
+
+ /* Calculate base addresses */
+ base_b0 = -size_b0;
+ base_b1 = -size_b1;
+
+ /* Setup offsets for Boot Flash */
+ flash_get_offsets (base_b0, &flash_info[0]);
+
+ /* Protect board level data */
+ (void)flash_protect(FLAG_PROTECT_SET,
+ base_b0,
+ flash_info[0].start[1] - 1,
+ &flash_info[0]);
+
+
+ /* Monitor protection ON by default */
+ (void)flash_protect(FLAG_PROTECT_SET,
+ base_b0 + size_b0 - CFG_MONITOR_LEN,
+ base_b0 + size_b0 - 1,
+ &flash_info[0]);
+
+ /* Protect the FPGA image */
+ (void)flash_protect(FLAG_PROTECT_SET,
+ FLASH_BASE1_PRELIM,
+ FLASH_BASE1_PRELIM + CFG_FPGA_IMAGE_LEN - 1,
+ &flash_info[1]);
+
+ /* Protect the default boot image */
+ (void)flash_protect(FLAG_PROTECT_SET,
+ FLASH_BASE1_PRELIM + CFG_FPGA_IMAGE_LEN,
+ FLASH_BASE1_PRELIM + CFG_FPGA_IMAGE_LEN + 0x600000 - 1,
+ &flash_info[1]);
+
+ /* Setup offsets for Main Flash */
+ flash_get_offsets (FLASH_BASE1_PRELIM, &flash_info[1]);
+
+ return (size_b0 + size_b1);
+} /* end flash_init() */
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+ int i;
+
+ /* set up sector start address table - FOR BOOT ROM ONLY!!! */
+ if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) {
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * 0x00010000);
+ }
+} /* end flash_get_offsets() */
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t *info)
+{
+ int i;
+ int k;
+ int size;
+ int erased;
+ volatile unsigned long *flash;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD: printf ("1 x AMD "); break;
+ case FLASH_MAN_STM: printf ("1 x STM "); break;
+ case FLASH_MAN_INTEL: printf ("2 x Intel "); break;
+ default: printf ("Unknown Vendor ");
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM040:
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
+ printf ("AM29LV040 (4096 Kbit, uniform sector size)\n");
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM)
+ printf ("M29W040B (4096 Kbit, uniform block size)\n");
+ else
+ printf ("UNKNOWN 29x040x (4096 Kbit, uniform sector size)\n");
+ break;
+ case FLASH_28F320J3A:
+ printf ("28F320J3A (32 Mbit = 128K x 32)\n");
+ break;
+ case FLASH_28F640J3A:
+ printf ("28F640J3A (64 Mbit = 128K x 64)\n");
+ break;
+ case FLASH_28F128J3A:
+ printf ("28F128J3A (128 Mbit = 128K x 128)\n");
+ break;
+ default:
+ printf ("Unknown Chip Type\n");
+ }
+
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM) {
+ printf (" Size: %ld KB in %d Blocks\n",
+ info->size >> 10, info->sector_count);
+ } else {
+ printf (" Size: %ld KB in %d Sectors\n",
+ info->size >> 10, info->sector_count);
+ }
+
+ printf (" Sector Start Addresses:");
+ for (i=0; i<info->sector_count; ++i) {
+ /*
+ * Check if whole sector is erased
+ */
+ if (i != (info->sector_count-1))
+ size = info->start[i+1] - info->start[i];
+ else
+ size = info->start[0] + info->size - info->start[i];
+ erased = 1;
+ flash = (volatile unsigned long *)info->start[i];
+ size = size >> 2; /* divide by 4 for longword access */
+ for (k=0; k<size; k++)
+ {
+ if (*flash++ != 0xffffffff)
+ {
+ erased = 0;
+ break;
+ }
+ }
+
+ if ((i % 5) == 0)
+ printf ("\n ");
+ printf (" %08lX%s%s",
+ info->start[i],
+ erased ? " E" : " ",
+ info->protect[i] ? "RO " : " "
+ );
+ }
+ printf ("\n");
+} /* end flash_print_info() */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+ short i;
+ ulong base = (ulong)addr;
+
+ /* Setup default type */
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count =0;
+ info->size = 0;
+
+ /* Test for Boot Flash */
+ if (base == FLASH_BASE0_PRELIM) {
+ unsigned char value;
+ volatile unsigned char * addr2 = (unsigned char *)addr;
+
+ /* Write auto select command: read Manufacturer ID */
+ *(addr2 + 0x555) = 0xaa;
+ *(addr2 + 0x2aa) = 0x55;
+ *(addr2 + 0x555) = 0x90;
+
+ /* Manufacture ID */
+ value = *addr2;
+ switch (value) {
+ case (unsigned char)AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+ case (unsigned char)STM_MANUFACT:
+ info->flash_id = FLASH_MAN_STM;
+ break;
+ default:
+ *addr2 = 0xf0; /* no or unknown flash */
+ return 0;
+ }
+
+ /* Device ID */
+ value = *(addr2 + 1);
+ switch (value) {
+ case (unsigned char)AMD_ID_LV040B:
+ case (unsigned char)STM_ID_29W040B:
+ info->flash_id += FLASH_AM040;
+ info->sector_count = 8;
+ info->size = 0x00080000;
+ break; /* => 512Kb */
+ default:
+ *addr2 = 0xf0; /* => no or unknown flash */
+ return 0;
+ }
+ }
+ else { /* MAIN Flash */
+ unsigned long value;
+ volatile unsigned long * addr2 = (unsigned long *)addr;
+
+ /* Write auto select command: read Manufacturer ID */
+ *addr2 = 0x90909090;
+
+ /* Manufacture ID */
+ value = *addr2;
+ switch (value) {
+ case (unsigned long)INTEL_MANUFACT:
+ info->flash_id = FLASH_MAN_INTEL;
+ break;
+ default:
+ *addr2 = 0xff; /* no or unknown flash */
+ return 0;
+ }
+
+ /* Device ID - This shit is interleaved... */
+ value = *(addr2 + 1);
+ switch (value) {
+ case (unsigned long)INTEL_ID_28F320J3A:
+ info->flash_id += FLASH_28F320J3A;
+ info->sector_count = 32;
+ info->size = 0x00400000 * 2;
+ break; /* => 2 X 4 MB */
+ case (unsigned long)INTEL_ID_28F640J3A:
+ info->flash_id += FLASH_28F640J3A;
+ info->sector_count = 64;
+ info->size = 0x00800000 * 2;
+ break; /* => 2 X 8 MB */
+ case (unsigned long)INTEL_ID_28F128J3A:
+ info->flash_id += FLASH_28F128J3A;
+ info->sector_count = 128;
+ info->size = 0x01000000 * 2;
+ break; /* => 2 X 16 MB */
+ default:
+ *addr2 = 0xff; /* => no or unknown flash */
+ }
+ }
+
+ /* Make sure we don't exceed CFG_MAX_FLASH_SECT */
+ if (info->sector_count > CFG_MAX_FLASH_SECT) {
+ printf ("** ERROR: sector count %d > max (%d) **\n",
+ info->sector_count, CFG_MAX_FLASH_SECT);
+ info->sector_count = CFG_MAX_FLASH_SECT;
+ }
+
+ /* set up sector start address table */
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM040:
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * 0x00010000);
+ break;
+ case FLASH_28F320J3A:
+ case FLASH_28F640J3A:
+ case FLASH_28F128J3A:
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * 0x00020000 * 2); /* 2 Banks */
+ break;
+ }
+
+ /* Test for Boot Flash */
+ if (base == FLASH_BASE0_PRELIM) {
+ volatile unsigned char *addr2;
+ /* check for protected sectors */
+ for (i = 0; i < info->sector_count; i++) {
+ /* read sector protection at sector address, (AX .. A0) = 0x02 */
+ /* D0 = 1 if protected */
+ addr2 = (volatile unsigned char *)(info->start[i]);
+ info->protect[i] = *(addr2 + 2) & 1;
+ }
+
+ /* Restore read mode */
+ *(unsigned char *)base = 0xF0; /* Reset NORMAL Flash */
+ }
+ else { /* Main Flash */
+ volatile unsigned long *addr2;
+ /* check for protected sectors */
+ for (i = 0; i < info->sector_count; i++) {
+ /* read sector protection at sector address, (AX .. A0) = 0x02 */
+ /* D0 = 1 if protected */
+ addr2 = (volatile unsigned long *)(info->start[i]);
+ info->protect[i] = *(addr2 + 2) & 0x1;
+ }
+
+ /* Restore read mode */
+ *(unsigned long *)base = 0xFFFFFFFF; /* Reset Flash */
+ }
+
+ return (info->size);
+} /* end flash_get_size() */
+
+/*-----------------------------------------------------------------------
+ */
+
+static int wait_for_DQ7(ulong addr, uchar cmp_val, ulong tout)
+{
+ int i;
+
+ volatile uchar *vaddr = (uchar *)addr;
+
+ /* Loop X times */
+ for (i = 1; i <= (100 * tout); i++) { /* Wait up to tout ms */
+ udelay(10);
+ /* Pause 10 us */
+
+ /* Check for completion */
+ if ((vaddr[0] & 0x80) == (cmp_val & 0x80)) {
+ return 0;
+ }
+
+ /* KEEP THE LUSER HAPPY - Print a dot every 1.1 seconds */
+ if (!(i % 110000))
+ putc('.');
+
+ /* Kick the dog if needed */
+ WATCHDOG_RESET();
+ }
+
+ return 1;
+} /* wait_for_DQ7() */
+
+/*-----------------------------------------------------------------------
+ */
+
+static int flash_erase8(flash_info_t *info, int s_first, int s_last)
+{
+ int tcode, rcode = 0;
+ volatile uchar *addr = (uchar *)(info->start[0]);
+ volatile uchar *sector_addr;
+ int flag, prot, sect;
+
+ /* Validate arguments */
+ 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;
+ }
+
+ /* Check for KNOWN flash type */
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("Can't erase unknown flash type - aborted\n");
+ return 1;
+ }
+
+ /* Check for protected sectors */
+ 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");
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect <= s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ sector_addr = (uchar *)(info->start[sect]);
+
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM)
+ printf("Erasing block %p\n", sector_addr);
+ else
+ printf("Erasing sector %p\n", sector_addr);
+
+ /* Disable interrupts which might cause Flash to timeout */
+ flag = disable_interrupts();
+
+ *(addr + 0x555) = (uchar)0xAA;
+ *(addr + 0x2aa) = (uchar)0x55;
+ *(addr + 0x555) = (uchar)0x80;
+ *(addr + 0x555) = (uchar)0xAA;
+ *(addr + 0x2aa) = (uchar)0x55;
+ *sector_addr = (uchar)0x30; /* sector erase */
+
+ /*
+ * Wait for each sector to complete, it's more
+ * reliable. According to AMD Spec, you must
+ * issue all erase commands within a specified
+ * timeout. This has been seen to fail, especially
+ * if printf()s are included (for debug)!!
+ * Takes up to 6 seconds.
+ */
+ tcode = wait_for_DQ7((ulong)sector_addr, 0x80, 6000);
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* Make sure we didn't timeout */
+ if (tcode) {
+ printf ("Timeout\n");
+ rcode = 1;
+ }
+ }
+ }
+
+ /* wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ /* reset to read mode */
+ addr = (uchar *)info->start[0];
+ *addr = (uchar)0xF0; /* reset bank */
+
+ printf (" done\n");
+ return rcode;
+} /* end flash_erase8() */
+
+static int flash_erase32(flash_info_t *info, int s_first, int s_last)
+{
+ int flag, sect;
+ ulong start, now, last;
+ int prot = 0;
+
+ /* Validate arguments */
+ 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;
+ }
+
+ /* Check for KNOWN flash type */
+ if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
+ printf ("Can erase only Intel flash types - aborted\n");
+ return 1;
+ }
+
+ /* Check for protected sectors */
+ 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");
+
+ start = get_timer (0);
+ last = start;
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect <= s_last; sect++) {
+ WATCHDOG_RESET();
+ if (info->protect[sect] == 0) { /* not protected */
+ vu_long *addr = (vu_long *)(info->start[sect]);
+ unsigned long status;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ *addr = 0x00500050; /* clear status register */
+ *addr = 0x00200020; /* erase setup */
+ *addr = 0x00D000D0; /* erase confirm */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* Wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ while (((status = *addr) & 0x00800080) != 0x00800080) {
+ if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+ printf ("Timeout\n");
+ *addr = 0x00B000B0; /* suspend erase */
+ *addr = 0x00FF00FF; /* reset to read mode */
+ return 1;
+ }
+
+ /* show that we're waiting */
+ if ((now - last) > 990) { /* every second */
+ putc ('.');
+ last = now;
+ }
+ }
+ *addr = 0x00FF00FF; /* reset to read mode */
+ }
+ }
+ printf (" done\n");
+ return 0;
+} /* end flash_erase32() */
+
+int flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+ if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040)
+ return flash_erase8(info, s_first, s_last);
+ else
+ return flash_erase32(info, s_first, s_last);
+} /* end flash_erase() */
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_buff8(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ ulong cp, wp, data;
+ ulong start;
+ int i, l, rc;
+
+ start = get_timer (0);
+
+ 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_word8(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_word8(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 4;
+ cnt -= 4;
+ if (get_timer(start) > 1000) { /* every second */
+ WATCHDOG_RESET();
+ putc ('.');
+ start = get_timer(0);
+ }
+ }
+
+ 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_word8(info, wp, data));
+} /* end write_buff8() */
+
+#define FLASH_WIDTH 4 /* flash bus width in bytes */
+static int write_buff32 (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ ulong cp, wp, data;
+ int i, l, rc;
+ ulong start;
+
+ start = get_timer (0);
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ return 4;
+ }
+
+ wp = (addr & ~(FLASH_WIDTH-1)); /* get lower FLASH_WIDTH 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<FLASH_WIDTH && cnt>0; ++i) {
+ data = (data << 8) | *src++;
+ --cnt;
+ ++cp;
+ }
+ for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+
+ if ((rc = write_word32(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += FLASH_WIDTH;
+ }
+
+ /*
+ * handle FLASH_WIDTH aligned part
+ */
+ while (cnt >= FLASH_WIDTH) {
+ data = 0;
+ for (i=0; i<FLASH_WIDTH; ++i) {
+ data = (data << 8) | *src++;
+ }
+ if ((rc = write_word32(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += FLASH_WIDTH;
+ cnt -= FLASH_WIDTH;
+ if (get_timer(start) > 990) { /* every second */
+ putc ('.');
+ start = get_timer(0);
+ }
+ }
+
+ if (cnt == 0) {
+ return (0);
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ data = 0;
+ for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) {
+ data = (data << 8) | *src++;
+ --cnt;
+ }
+ for (; i<FLASH_WIDTH; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+
+ return (write_word32(info, wp, data));
+} /* write_buff32() */
+
+int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ int retval;
+
+ if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040)
+ retval = write_buff8(info, src, addr, cnt);
+ else
+ retval = write_buff32(info, src, addr, cnt);
+
+ return retval;
+} /* end write_buff() */
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+static int write_word8(flash_info_t *info, ulong dest, ulong data)
+{
+ volatile uchar *addr2 = (uchar *)(info->start[0]);
+ volatile uchar *dest2 = (uchar *)dest;
+ volatile uchar *data2 = (uchar *)&data;
+ int flag;
+ int i, tcode, rcode = 0;
+
+ /* Check if Flash is (sufficently) erased */
+ if ((*((volatile uchar *)dest) &
+ (uchar)data) != (uchar)data) {
+ return (2);
+ }
+
+ for (i=0; i < (4 / sizeof(uchar)); i++) {
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ *(addr2 + 0x555) = (uchar)0xAA;
+ *(addr2 + 0x2aa) = (uchar)0x55;
+ *(addr2 + 0x555) = (uchar)0xA0;
+
+ dest2[i] = data2[i];
+
+ /* Wait for write to complete, up to 1ms */
+ tcode = wait_for_DQ7((ulong)&dest2[i], data2[i], 1);
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* Make sure we didn't timeout */
+ if (tcode) {
+ rcode = 1;
+ }
+ }
+
+ return rcode;
+} /* end write_word8() */
+
+static int write_word32(flash_info_t *info, ulong dest, ulong data)
+{
+ vu_long *addr = (vu_long *)dest;
+ ulong status;
+ ulong start;
+ int flag;
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*addr & data) != data) {
+ return (2);
+ }
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ *addr = 0x00400040; /* write setup */
+ *addr = data;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer (0);
+
+ while (((status = *addr) & 0x00800080) != 0x00800080) {
+ WATCHDOG_RESET();
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *addr = 0x00FF00FF; /* restore read mode */
+ return (1);
+ }
+ }
+
+ *addr = 0x00FF00FF; /* restore read mode */
+
+ return (0);
+} /* end write_word32() */
+
+
+static int _flash_protect(flash_info_t *info, long sector)
+{
+ int i;
+ int flag;
+ ulong status;
+ int rcode = 0;
+ volatile long *addr = (unsigned long *)sector;
+
+ switch(info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_28F320J3A:
+ case FLASH_28F640J3A:
+ case FLASH_28F128J3A:
+ /* Disable interrupts which might cause Flash to timeout */
+ flag = disable_interrupts();
+
+ /* Issue command */
+ *addr = 0x00500050L; /* Clear the status register */
+ *addr = 0x00600060L; /* Set lock bit setup */
+ *addr = 0x00010001L; /* Set lock bit confirm */
+
+ /* Wait for command completion */
+ for (i = 0; i < 10; i++) { /* 75us timeout, wait 100us */
+ udelay(10);
+ if ((*addr & 0x00800080L) == 0x00800080L)
+ break;
+ }
+
+ /* Not successful? */
+ status = *addr;
+ if (status != 0x00800080L) {
+ printf("Protect %x sector failed: %x\n",
+ (uint)sector, (uint)status);
+ rcode = 1;
+ }
+
+ /* Restore read mode */
+ *addr = 0x00ff00ffL;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ break;
+ case FLASH_AM040: /* No soft sector protection */
+ break;
+ }
+
+ /* Turn protection on for this sector */
+ for (i = 0; i < info->sector_count; i++) {
+ if (info->start[i] == sector) {
+ info->protect[i] = 1;
+ break;
+ }
+ }
+
+ return rcode;
+} /* end _flash_protect() */
+
+static int _flash_unprotect(flash_info_t *info, long sector)
+{
+ int i;
+ int flag;
+ ulong status;
+ int rcode = 0;
+ volatile long *addr = (unsigned long *)sector;
+
+ switch(info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_28F320J3A:
+ case FLASH_28F640J3A:
+ case FLASH_28F128J3A:
+ /* Disable interrupts which might cause Flash to timeout */
+ flag = disable_interrupts();
+
+ *addr = 0x00500050L; /* Clear the status register */
+ *addr = 0x00600060L; /* Clear lock bit setup */
+ *addr = 0x00D000D0L; /* Clear lock bit confirm */
+
+ /* Wait for command completion */
+ for (i = 0; i < 80 ; i++) { /* 700ms timeout, wait 800 */
+ udelay(10000); /* Delay 10ms */
+ if ((*addr & 0x00800080L) == 0x00800080L)
+ break;
+ }
+
+ /* Not successful? */
+ status = *addr;
+ if (status != 0x00800080L) {
+ printf("Un-protect %x sector failed: %x\n",
+ (uint)sector, (uint)status);
+ *addr = 0x00ff00ffL;
+ rcode = 1;
+ }
+
+ /* restore read mode */
+ *addr = 0x00ff00ffL;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ break;
+ case FLASH_AM040: /* No soft sector protection */
+ break;
+ }
+
+ /*
+ * Fix Intel's little red wagon. Reprotect
+ * sectors that were protected before we undid
+ * protection on a specific sector.
+ */
+ for (i = 0; i < info->sector_count; i++) {
+ if (info->start[i] != sector) {
+ if (info->protect[i]) {
+ if (_flash_protect(info, info->start[i]))
+ rcode = 1;
+ }
+ }
+ else /* Turn protection off for this sector */
+ info->protect[i] = 0;
+ }
+
+ return rcode;
+} /* end _flash_unprotect() */
+
+
+int flash_real_protect(flash_info_t *info, long sector, int prot)
+{
+ int rcode;
+
+ if (prot)
+ rcode = _flash_protect(info, info->start[sector]);
+ else
+ rcode = _flash_unprotect(info, info->start[sector]);
+
+ return rcode;
+} /* end flash_real_protect() */
+
+/*-----------------------------------------------------------------------
+ */
+
diff --git a/board/w7o/fpga.c b/board/w7o/fpga.c
new file mode 100644
index 0000000000..e84123b907
--- /dev/null
+++ b/board/w7o/fpga.c
@@ -0,0 +1,380 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
+ * and
+ * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
+ *
+ * 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 <config.h>
+#include <common.h>
+#include "w7o.h"
+#include <asm/processor.h>
+#include "errors.h"
+
+static void
+fpga_img_write(unsigned long *src, unsigned long len, unsigned short *daddr)
+{
+ unsigned long i;
+ volatile unsigned long val;
+ volatile unsigned short *dest = daddr; /* volatile-bypass optimizer */
+
+ for (i = 0; i < len; i++, src++) {
+ val = *src;
+ *dest = (unsigned short)((val & 0xff000000L) >> 16);
+ *dest = (unsigned short)((val & 0x00ff0000L) >> 8);
+ *dest = (unsigned short)(val & 0x0000ff00L);
+ *dest = (unsigned short)((val & 0x000000ffL) << 8);
+ }
+
+ /* Terminate programming with 4 C clocks */
+ dest = daddr;
+ val = *(unsigned short *)dest;
+ val = *(unsigned short *)dest;
+ val = *(unsigned short *)dest;
+ val = *(unsigned short *)dest;
+
+}
+
+
+int
+fpgaDownload(unsigned char *saddr,
+ unsigned long size,
+ unsigned short *daddr)
+{
+ int i; /* index, intr disable flag */
+ int start; /* timer */
+ unsigned long greg, grego; /* GPIO & output register */
+ unsigned long length; /* image size in words */
+ unsigned long *source; /* image source addr */
+ unsigned short *dest; /* destination FPGA addr */
+ volatile unsigned short *ndest; /* temp dest FPGA addr */
+ volatile unsigned short val; /* temp val */
+ unsigned long cnfg = GPIO_XCV_CNFG; /* FPGA CNFG */
+ unsigned long eirq = GPIO_XCV_IRQ;
+ int retval = -1; /* Function return value */
+
+ /* Setup some basic values */
+ length = (size / 4) + 1; /* size in words, rounding UP
+ is OK */
+ source = (unsigned long *)saddr;
+ dest = (unsigned short *)daddr;
+
+ /* Get DCR output register */
+ grego = in32(IBM405GP_GPIO0_OR);
+
+ /* Reset FPGA */
+ grego &= ~GPIO_XCV_PROG; /* PROG line low */
+ out32(IBM405GP_GPIO0_OR, grego);
+
+ /* Setup timeout timer */
+ start = get_timer(0);
+
+ /* Wait for FPGA init line */
+ while(in32(IBM405GP_GPIO0_IR) & GPIO_XCV_INIT) { /* Wait INIT line low */
+ /* Check for timeout - 100us max, so use 3ms */
+ if (get_timer(start) > 3) {
+ printf(" failed to start init.\n");
+ log_warn(ERR_XINIT0); /* Don't halt */
+
+ /* Reset line stays low */
+ goto done; /* I like gotos... */
+ }
+ }
+
+ /* Unreset FPGA */
+ grego |= GPIO_XCV_PROG; /* PROG line high */
+ out32(IBM405GP_GPIO0_OR, grego);
+
+ /* Wait for FPGA end of init period . */
+ while(!(in32(IBM405GP_GPIO0_IR) & GPIO_XCV_INIT)) { /* Wait for INIT hi */
+
+ /* Check for timeout */
+ if (get_timer(start) > 3) {
+ printf(" failed to exit init.\n");
+ log_warn(ERR_XINIT1);
+
+ /* Reset FPGA */
+ grego &= ~GPIO_XCV_PROG; /* PROG line low */
+ out32(IBM405GP_GPIO0_OR, grego);
+
+ goto done;
+ }
+ }
+
+ /* Now program FPGA ... */
+ ndest = dest;
+ for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
+ /* Toggle IRQ/GPIO */
+ greg = mfdcr(CPC0_CR0); /* get chip ctrl register */
+ greg |= eirq; /* toggle irq/gpio */
+ mtdcr(CPC0_CR0, greg); /* ... just do it */
+
+ /* turn on open drain for CNFG */
+ greg = in32(IBM405GP_GPIO0_ODR); /* get open drain register */
+ greg |= cnfg; /* CNFG open drain */
+ out32(IBM405GP_GPIO0_ODR, greg); /* .. just do it */
+
+ /* Turn output enable on for CNFG */
+ greg = in32(IBM405GP_GPIO0_TCR); /* get tristate register */
+ greg |= cnfg; /* CNFG tristate inactive */
+ out32(IBM405GP_GPIO0_TCR, greg); /* ... just do it */
+
+ /* Setup FPGA for programming */
+ grego &= ~cnfg; /* CONFIG line low */
+ out32(IBM405GP_GPIO0_OR, grego);
+
+ /*
+ * Program the FPGA
+ */
+ printf("\n destination: 0x%lx ", (unsigned long)ndest);
+
+ fpga_img_write(source, length, (unsigned short *)ndest);
+
+ /* Done programming */
+ grego |= cnfg; /* CONFIG line high */
+ out32(IBM405GP_GPIO0_OR, grego);
+
+ /* Turn output enable OFF for CNFG */
+ greg = in32(IBM405GP_GPIO0_TCR); /* get tristate register */
+ greg &= ~cnfg; /* CNFG tristate inactive */
+ out32(IBM405GP_GPIO0_TCR, greg); /* ... just do it */
+
+ /* Toggle IRQ/GPIO */
+ greg = mfdcr(CPC0_CR0); /* get chip ctrl register */
+ greg &= ~eirq; /* toggle irq/gpio */
+ mtdcr(CPC0_CR0, greg); /* ... just do it */
+
+ ndest = (unsigned short *)((char *)ndest + 0x00100000L); /* XXX - Next FPGA addr */
+ cnfg >>= 1; /* XXX - Next */
+ eirq >>= 1;
+ }
+
+ /* Terminate programming with 4 C clocks */
+ ndest = dest;
+ for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
+ val = *ndest;
+ val = *ndest;
+ val = *ndest;
+ val = *ndest;
+ ndest = (unsigned short *)((char *)ndest + 0x00100000L);
+ }
+
+ /* Setup timer */
+ start = get_timer(0);
+
+ /* Wait for FPGA end of programming period . */
+ while(!(in32(IBM405GP_GPIO0_IR) & GPIO_XCV_DONE)) { /* Test DONE low */
+
+ /* Check for timeout */
+ if (get_timer(start) > 3) {
+ printf(" done failed to come high.\n");
+ log_warn(ERR_XDONE1);
+
+ /* Reset FPGA */
+ grego &= ~GPIO_XCV_PROG; /* PROG line low */
+ out32(IBM405GP_GPIO0_OR, grego);
+
+ goto done;
+ }
+ }
+
+ printf("\n FPGA load succeeded\n");
+ retval = 0; /* Program OK */
+
+done:
+ return retval;
+}
+
+/* FPGA image is stored in flash */
+extern flash_info_t flash_info[];
+
+int init_fpga(void)
+{
+ unsigned int i,j,ptr; /* General purpose */
+ unsigned char bufchar; /* General purpose character */
+ unsigned char *buf; /* Start of image pointer */
+ unsigned long len; /* Length of image */
+ unsigned char *fn_buf; /* Start of filename string */
+ unsigned int fn_len; /* Length of filename string */
+ unsigned char *xcv_buf; /* Pointer to start of image */
+ unsigned long xcv_len; /* Length of image */
+ unsigned long crc; /* 30bit crc in image */
+ unsigned long calc_crc; /* Calc'd 30bit crc */
+ int retval = -1;
+
+ /* Tell the world what we are doing */
+ printf("FPGA: ");
+
+ /*
+ * Get address of first sector where the FPGA
+ * image is stored.
+ */
+ buf = (unsigned char *)flash_info[1].start[0];
+
+ /*
+ * Get the stored image's CRC & length.
+ */
+ crc = *(unsigned long *)(buf+4); /* CRC is first long word */
+ len = *(unsigned long *)(buf+8); /* Image len is next long */
+
+ /* Pedantic */
+ if ((len < 0x133A4) || (len > 0x80000))
+ goto bad_image;
+
+ /*
+ * Get the file name pointer and length.
+ */
+ fn_len = (*(unsigned short *)(buf+12) & 0xff); /* filename length
+ is next short */
+ fn_buf = buf + 14;
+
+ /*
+ * Get the FPGA image pointer and length length.
+ */
+ xcv_buf = fn_buf + fn_len; /* pointer to fpga image */
+ xcv_len = len - 14 - fn_len; /* fpga image length */
+
+ /* Check for uninitialized FLASH */
+ if ((strncmp(buf, "w7o", 3)!=0) || (len > 0x0007ffffL) || (len == 0))
+ goto bad_image;
+
+ /*
+ * Calculate and Check the image's CRC.
+ */
+ calc_crc = crc32(0, xcv_buf, xcv_len);
+ if (crc != calc_crc) {
+ printf("\nfailed - bad CRC\n");
+ goto done;
+ }
+
+ /* Output the file name */
+ printf("file name : ");
+ for (i=0;i<fn_len;i++) {
+ bufchar = fn_buf[+i];
+ if (bufchar<' ' || bufchar>'~') bufchar = '.';
+ putc(bufchar);
+ }
+
+ /*
+ * find rest of display data
+ */
+ ptr = 15; /* Offset to ncd filename
+ length in fpga image */
+ j = xcv_buf[ptr]; /* Get len of ncd filename */
+ if (j > 32) goto bad_image;
+ ptr = ptr + j + 3; /* skip ncd filename string +
+ 3 bytes more bytes */
+
+ /*
+ * output target device string
+ */
+ j = xcv_buf[ptr++] - 1; /* len of targ str less term */
+ if (j > 32) goto bad_image;
+ printf("\n target : ");
+ for (i = 0; i < j; i++) {
+ bufchar = (xcv_buf[ptr++]);
+ if (bufchar<' ' || bufchar>'~') bufchar = '.';
+ putc(bufchar);
+ }
+
+ /*
+ * output compilation date string and time string
+ */
+ ptr += 3; /* skip 2 bytes */
+ printf("\n synth time : ");
+ j = (xcv_buf[ptr++] - 1); /* len of date str less term */
+ if (j > 32) goto bad_image;
+ for (i = 0; i < j; i++) {
+ bufchar = (xcv_buf[ptr++]);
+ if (bufchar<' ' || bufchar>'~') bufchar = '.';
+ putc(bufchar);
+ }
+
+ ptr += 3; /* Skip 2 bytes */
+ printf(" - ");
+ j = (xcv_buf[ptr++] - 1); /* slen = targ dev str len */
+ if (j > 32) goto bad_image;
+ for (i = 0; i < j; i++) {
+ bufchar = (xcv_buf[ptr++]);
+ if (bufchar<' ' || bufchar>'~') bufchar = '.';
+ putc(bufchar);
+ }
+
+ /*
+ * output crc and length strings
+ */
+ printf("\n len & crc : 0x%lx 0x%lx", len, crc);
+
+ /*
+ * Program the FPGA.
+ */
+ retval = fpgaDownload((unsigned char*)xcv_buf, xcv_len,
+ (unsigned short *)0xfd000000L);
+ return retval;
+
+bad_image:
+ printf("\n BAD FPGA image format @ %lx\n", flash_info[1].start[0]);
+ log_warn(ERR_XIMAGE);
+done:
+ return retval;
+}
+
+void test_fpga(unsigned short *daddr)
+{
+ int i;
+ volatile unsigned short *ndest = daddr;
+
+ for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
+#if defined(CONFIG_W7OLMG)
+ ndest[0x7e] = 0x55aa;
+ if (ndest[0x7e] != 0x55aa)
+ log_warn(ERR_XRW1 + i);
+ ndest[0x7e] = 0xaa55;
+ if (ndest[0x7e] != 0xaa55)
+ log_warn(ERR_XRW1 + i);
+ ndest[0x7e] = 0xc318;
+ if (ndest[0x7e] != 0xc318)
+ log_warn(ERR_XRW1 + i);
+
+#elif defined(CONFIG_W7OLMC)
+ ndest[0x800] = 0x55aa;
+ ndest[0x801] = 0xaa55;
+ ndest[0x802] = 0xc318;
+ ndest[0x4800] = 0x55aa;
+ ndest[0x4801] = 0xaa55;
+ ndest[0x4802] = 0xc318;
+ if ((ndest[0x800] != 0x55aa) ||
+ (ndest[0x801] != 0xaa55) ||
+ (ndest[0x802] != 0xc318))
+ log_warn(ERR_XRW1 + (2 * i)); /* Auto gen error code */
+ if ((ndest[0x4800] != 0x55aa) ||
+ (ndest[0x4801] != 0xaa55) ||
+ (ndest[0x4802] != 0xc318))
+ log_warn(ERR_XRW2 + (2 * i)); /* Auto gen error code */
+
+#else
+# error "Unknown W7O board configuration"
+#endif
+ }
+
+ printf(" FPGA ready\n");
+ return;
+}
+
diff --git a/board/w7o/init.S b/board/w7o/init.S
new file mode 100644
index 0000000000..0abf21fe86
--- /dev/null
+++ b/board/w7o/init.S
@@ -0,0 +1,264 @@
+/******************************************************************************
+ *
+ * This source code has been made available to you by IBM on an AS-IS
+ * basis. Anyone receiving this source is licensed under IBM
+ * copyrights to use it in any way he or she deems fit, including
+ * copying it, modifying it, compiling it, and redistributing it either
+ * with or without modifications. No license under IBM patents or
+ * patent applications is to be implied by the copyright license.
+ *
+ * Any user of this software should understand that IBM cannot provide
+ * technical support for this software and will not be responsible for
+ * any consequences resulting from the use of this software.
+ *
+ * Any person who transfers this source code or any derivative work
+ * must include the IBM copyright notice, this paragraph, and the
+ * preceding two paragraphs in the transferred software.
+ *
+ * COPYRIGHT I B M CORPORATION 1995
+ * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
+ *
+ *****************************************************************************/
+#include <config.h>
+#include <ppc4xx.h>
+
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/******************************************************************************
+ * Function: ext_bus_cntlr_init
+ *
+ * Description: Configures EBC Controller and a few basic chip selects.
+ *
+ * CS0 is setup to get the Boot Flash out of the addresss range
+ * so that we may setup a stack. CS7 is setup so that we can
+ * access and reset the hardware watchdog.
+ *
+ * IMPORTANT: For pass1 this code must run from
+ * cache since you can not reliably change a peripheral banks
+ * timing register (pbxap) while running code from that bank.
+ * For ex., since we are running from ROM on bank 0, we can NOT
+ * execute the code that modifies bank 0 timings from ROM, so
+ * we run it from cache.
+ *
+ * Notes: Does NOT use the stack.
+ *****************************************************************************/
+ .section ".text"
+ .align 2
+ .globl ext_bus_cntlr_init
+ .type ext_bus_cntlr_init, @function
+ext_bus_cntlr_init:
+ mflr r0
+ /********************************************************************
+ * Prefetch entire ext_bus_cntrl_init function into the icache.
+ * This is necessary because we are going to change the same CS we
+ * are executing from. Otherwise a CPU lockup may occur.
+ *******************************************************************/
+ bl ..getAddr
+..getAddr:
+ mflr r3 /* get address of ..getAddr */
+
+ /* Calculate number of cache lines for this function */
+ addi r4, 0, (((.Lfe0 - ..getAddr) / CFG_CACHELINE_SIZE) + 2)
+ mtctr r4
+..ebcloop:
+ icbt r0, r3 /* prefetch cache line for addr in r3*/
+ addi r3, r3, CFG_CACHELINE_SIZE /* move to next cache line */
+ bdnz ..ebcloop /* continue for $CTR cache lines */
+
+ /********************************************************************
+ * Delay to ensure all accesses to ROM are complete before changing
+ * bank 0 timings. 200usec should be enough.
+ * 200,000,000 (cycles/sec) X .000200 (sec) = 0x9C40 cycles.
+ *******************************************************************/
+ addis r3, 0, 0x0
+ ori r3, r3, 0xA000 /* wait 200us from reset */
+ mtctr r3
+..spinlp:
+ bdnz ..spinlp /* spin loop */
+
+ /********************************************************************
+ * Setup External Bus Controller (EBC).
+ *******************************************************************/
+ addi r3, 0, epcr
+ mtdcr ebccfga, r3
+ addis r4, 0, 0xb040 /* Device base timeout = 1024 cycles */
+ ori r4, r4, 0x0 /* Drive CS with external master */
+ mtdcr ebccfgd, r4
+
+ /********************************************************************
+ * Change PCIINT signal to PerWE
+ *******************************************************************/
+ mfdcr r4, cntrl1
+ ori r4, r4, 0x4000
+ mtdcr cntrl1, r4
+
+ /********************************************************************
+ * Memory Bank 0 (Flash Bank 0) initialization
+ *******************************************************************/
+ addi r3, 0, pb0ap
+ mtdcr ebccfga, r3
+ addis r4, 0, CFG_W7O_EBC_PB0AP@h
+ ori r4, r4, CFG_W7O_EBC_PB0AP@l
+ mtdcr ebccfgd, r4
+
+ addi r3, 0, pb0cr
+ mtdcr ebccfga, r3
+ addis r4, 0, CFG_W7O_EBC_PB0CR@h
+ ori r4, r4, CFG_W7O_EBC_PB0CR@l
+ mtdcr ebccfgd, r4
+
+ /********************************************************************
+ * Memory Bank 7 LEDs - NEEDED BECAUSE OF HW WATCHDOG AND LEDs.
+ *******************************************************************/
+ addi r3, 0, pb7ap
+ mtdcr ebccfga, r3
+ addis r4, 0, CFG_W7O_EBC_PB7AP@h
+ ori r4, r4, CFG_W7O_EBC_PB7AP@l
+ mtdcr ebccfgd, r4
+
+ addi r3, 0, pb7cr
+ mtdcr ebccfga, r3
+ addis r4, 0, CFG_W7O_EBC_PB7CR@h
+ ori r4, r4, CFG_W7O_EBC_PB7CR@l
+ mtdcr ebccfgd, r4
+
+ /* We are all done */
+ mtlr r0 /* Restore link register */
+ blr /* Return to calling function */
+.Lfe0: .size ext_bus_cntlr_init,.Lfe0-ext_bus_cntlr_init
+/* end ext_bus_cntlr_init() */
+
+/******************************************************************************
+ * Function: sdram_init
+ *
+ * Description: Configures SDRAM memory banks.
+ *
+ * Serial Presence Detect, "SPD," reads the SDRAM EEPROM
+ * via the IIC bus and then configures the SDRAM memory
+ * banks appropriately. If Auto Memory Configuration is
+ * is not used, it is assumed that a 4MB 11x8x2, non-ECC,
+ * SDRAM is soldered down.
+ *
+ * Notes: Expects that the stack is already setup.
+ *****************************************************************************/
+ .section ".text"
+ .align 2
+ .globl sdram_init
+ .type sdram_init, @function
+sdram_init:
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -8(r1) /* Save back chain and move SP */
+ stw r0, +12(r1) /* Save link register */
+
+ /*
+ * First call spd_sdram to try to init SDRAM according to the
+ * contents of the SPD EEPROM. If the SPD EEPROM is blank or
+ * erronious, spd_sdram returns 0 in R3.
+ */
+ bl spd_sdram
+ addic. r3, r3, 0 /* Check for error, save dram size */
+ bne ..sdri_done /* If it worked, we're done... */
+
+ /********************************************************************
+ * If SPD detection fails, we'll default to 4MB, 11x8x2, as this
+ * is the SMALLEST SDRAM size the 405 supports. We can do this
+ * because W7O boards have soldered on RAM, and there will always
+ * be some amount present. If we were using DIMMs, we should hang
+ * the board instead, since it doesn't have any RAM to continue
+ * running with.
+ *******************************************************************/
+
+ /*
+ * Disable memory controller to allow
+ * values to be changed.
+ */
+ addi r3, 0, mem_mcopt1
+ mtdcr memcfga, r3
+ addis r4, 0, 0x0
+ ori r4, r4, 0x0
+ mtdcr memcfgd, r4
+
+ /*
+ * Set MB0CF for ext bank 0. (0-4MB) Address Mode 5 since 11x8x2
+ * All other banks are disabled.
+ */
+ addi r3, 0, mem_mb0cf
+ mtdcr memcfga, r3
+ addis r4, 0, 0x0000 /* BA=0x0, SZ=4MB */
+ ori r4, r4, 0x8001 /* Mode is 5, 11x8x2or4, BE=Enabled */
+ mtdcr memcfgd, r4
+
+ /* Clear MB1CR,MB2CR,MB3CR to turn other banks off */
+ addi r4, 0, 0 /* Zero the data reg */
+
+ addi r3, r3, 4 /* Point to MB1CF reg */
+ mtdcr memcfga, r3 /* Set the address */
+ mtdcr memcfgd, r4 /* Zero the reg */
+
+ addi r3, r3, 4 /* Point to MB2CF reg */
+ mtdcr memcfga, r3 /* Set the address */
+ mtdcr memcfgd, r4 /* Zero the reg */
+
+ addi r3, r3, 4 /* Point to MB3CF reg */
+ mtdcr memcfga, r3 /* Set the address */
+ mtdcr memcfgd, r4 /* Zero the reg */
+
+ /********************************************************************
+ * Set the SDRAM Timing reg, SDTR1 and the refresh timer reg, RTR.
+ * To set the appropriate timings, we assume sdram is
+ * 100MHz (pc100 compliant).
+ *******************************************************************/
+
+ /*
+ * Set up SDTR1
+ */
+ addi r3, 0, mem_sdtr1
+ mtdcr memcfga, r3
+ addis r4, 0, 0x0086 /* SDTR1 value for 100Mhz */
+ ori r4, r4, 0x400D
+ mtdcr memcfgd, r4
+
+ /*
+ * Set RTR
+ */
+ addi r3, 0, mem_rtr
+ mtdcr memcfga, r3
+ addis r4, 0, 0x05F0 /* RTR refresh val = 15.625ms@100Mhz */
+ mtdcr memcfgd, r4
+
+ /********************************************************************
+ * Delay to ensure 200usec have elapsed since reset. Assume worst
+ * case that the core is running 200Mhz:
+ * 200,000,000 (cycles/sec) X .000200 (sec) = 0x9C40 cycles
+ *******************************************************************/
+ addis r3, 0, 0x0000
+ ori r3, r3, 0xA000 /* Wait 200us from reset */
+ mtctr r3
+..spinlp2:
+ bdnz ..spinlp2 /* spin loop */
+
+ /********************************************************************
+ * Set memory controller options reg, MCOPT1.
+ *******************************************************************/
+ addi r3, 0, mem_mcopt1
+ mtdcr memcfga, r3
+ addis r4, 0, 0x80E0 /* DC_EN=1,SRE=0,PME=0,MEMCHK=0 */
+ ori r4, r4, 0x0000 /* REGEN=0,DRW=00,BRPF=01,ECCDD=1 */
+ mtdcr memcfgd, r4 /* EMDULR=1 */
+
+..sdri_done:
+ /* restore and return */
+ lwz r0, +12(r1) /* Get saved link register */
+ addi r1, r1, +8 /* Remove frame from stack */
+ mtlr r0 /* Restore link register */
+ blr /* Return to calling function */
+.Lfe1: .size sdram_init,.Lfe1-sdram_init
+/* end sdram_init() */
+
diff --git a/board/w7o/post1.S b/board/w7o/post1.S
new file mode 100644
index 0000000000..d510cca1f6
--- /dev/null
+++ b/board/w7o/post1.S
@@ -0,0 +1,745 @@
+/*
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
+ * and
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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
+ */
+/*
+ * Description:
+ * Routine to exercise memory for the bringing up of our boards.
+ */
+#include <config.h>
+#include <ppc4xx.h>
+
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#include <watchdog.h>
+
+#include "errors.h"
+
+#define _ASMLANGUAGE
+
+ .globl test_sdram
+ .globl test_led
+ .globl log_stat
+ .globl log_warn
+ .globl log_err
+ .globl temp_uart_init
+ .globl post_puts
+ .globl disp_hex
+
+/*****************************************************
+******* Text Strings for low level printing ******
+******* In section got2 *******
+*****************************************************/
+
+/*
+ * Define the text strings for errors and warnings.
+ * Switch to .data section.
+ */
+ .section ".data"
+err_str: .asciz "*** POST ERROR = "
+warn_str: .asciz "*** POST WARNING = "
+end_str: .asciz "\r\n"
+
+/*
+ * Enter the labels in Global Entry Table (GOT).
+ * Switch to .got2 section.
+ */
+ START_GOT
+ GOT_ENTRY(err_str)
+ GOT_ENTRY(warn_str)
+ GOT_ENTRY(end_str)
+ END_GOT
+
+/*
+ * Switch back to .text section.
+ */
+ .text
+
+/****************************************
+ ****************************************
+ ******** LED register test ********
+ ****************************************
+ ***************************************/
+test_led:
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -12(r1) /* Save back chain and move SP */
+ stw r0, +16(r1) /* Save link register */
+ stw r4, +8(r1) /* save R4 */
+
+ WATCHDOG_RESET /* Reset the watchdog */
+
+ addi r3, 0, ERR_FF /* first test value is ffff */
+ addi r4, r3, 0 /* save copy of pattern */
+ bl set_led /* store first test value */
+ bl get_led /* read it back */
+ xor. r4, r4, r3 /* compare to original */
+#if defined(CONFIG_W7OLMC)
+ andi. r4, r4, 0x00ff /* lmc has 8 bits */
+#else
+ andi. r4, r4, 0xffff /* lmg has 16 bits */
+#endif
+ beq LED2 /* next test */
+ addi r3, 0, ERR_LED /* error code = 1 */
+ bl log_err /* display error and halt */
+LED2: addi r3, 0, ERR_00 /* 2nd test value is 0000 */
+ addi r4, r3, 0 /* save copy of pattern */
+ bl set_led /* store first test value */
+ bl get_led /* read it back */
+ xor. r4, r4, r3 /* compare to original */
+#if defined(CONFIG_W7OLMC)
+ andi. r4, r4, 0x00ff /* lmc has 8 bits */
+#else
+ andi. r4, r4, 0xffff /* lmg has 16 bits */
+#endif
+ beq LED3 /* next test */
+ addi r3, 0, ERR_LED /* error code = 1 */
+ bl log_err /* display error and halt */
+
+LED3: /* restore stack and return */
+ lwz r0, +16(r1) /* Get saved link register */
+ mtlr r0 /* Restore link register */
+ lwz r4, +8(r1) /* restore r4 */
+ addi r1, r1, +12 /* Remove frame from stack */
+ blr /* Return to calling function */
+
+/****************************************
+ ****************************************
+ ******** SDRAM TESTS ********
+ ****************************************
+ ***************************************/
+test_sdram:
+ /* called with mem size in r3 */
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -16(r1) /* Save back chain and move SP */
+ stw r0, +20(r1) /* Save link register */
+ stmw r30, +8(r1) /* save R30,R31 */
+ /* r30 is log2(mem size) */
+ /* r31 is mem size */
+
+ /* take log2 of total mem size */
+ addi r31, r3, 0 /* save total mem size */
+ addi r30, 0, 0 /* clear r30 */
+l2_loop:
+ srwi. r31, r31, 1 /* shift right 1 */
+ addi r30, r30, 1 /* count shifts */
+ bne l2_loop /* loop till done */
+ addi r30, r30, -1 /* correct for over count */
+ addi r31, r3, 0 /* save original size */
+
+ /* now kick the dog and test the mem */
+ WATCHDOG_RESET /* Reset the watchdog */
+ bl Data_Buster /* test crossed/shorted data lines */
+ addi r3, r30, 0 /* get log2(memsize) */
+ addi r4, r31, 0 /* get memsize */
+ bl Ghost_Buster /* test crossed/shorted addr lines */
+ addi r3, r31, 0 /* get mem size */
+ bl Bit_Buster /* check for bad internal bits */
+
+ /* restore stack and return */
+ lmw r30, +8(r1) /* Restore r30, r31 */
+ lwz r0, +20(r1) /* Get saved link register */
+ mtlr r0 /* Restore link register */
+ addi r1, r1, +16 /* Remove frame from stack */
+ blr /* Return to calling function */
+
+
+/****************************************
+ ******** sdram data bus test ********
+ ***************************************/
+Data_Buster:
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -24(r1) /* Save back chain and move SP */
+ stw r0, +28(r1) /* Save link register */
+ stmw r28, 8(r1) /* save r28 - r31 on stack */
+ /* r31 i/o register */
+ /* r30 sdram base address */
+ /* r29 5555 syndrom */
+ /* r28 aaaa syndrom */
+
+ /* set up led register for this test */
+ addi r3, 0, ERR_RAMG /* set led code to 1 */
+ bl log_stat /* store test value */
+ /* now test the dram data bus */
+ xor r30, r30, r30 /* load r30 with base addr of sdram */
+ addis r31, 0, 0x5555 /* load r31 with test value */
+ ori r31, r31, 0x5555
+ stw r31,0(r30) /* sto the value */
+ lwz r29,0(r30) /* read it back */
+ xor r29,r31,r29 /* compare it to original */
+ addis r31, 0, 0xaaaa /* load r31 with test value */
+ ori r31, r31, 0xaaaa
+ stw r31,0(r30) /* sto the value */
+ lwz r28,0(r30) /* read it back */
+ xor r28,r31,r28 /* compare it to original */
+ or r3,r28,r29 /* or together both error terms */
+ /*
+ * Now that we have the error bits,
+ * we have to decide which part they are in.
+ */
+ bl get_idx /* r5 is now index to error */
+ addi r3, r3, ERR_RAMG
+ cmpwi r3, ERR_RAMG /* check for errors */
+ beq db_done /* skip if no errors */
+ bl log_err /* log the error */
+
+db_done:
+ lmw r28, 8(r1) /* restore r28 - r31 from stack */
+ lwz r0, +28(r1) /* Get saved link register */
+ addi r1, r1, +24 /* Remove frame from stack */
+ mtlr r0 /* Restore link register */
+ blr /* Return to calling function */
+
+
+/****************************************************
+ ******** test for address ghosting in dram ********
+ ***************************************************/
+
+Ghost_Buster:
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -36(r1) /* Save back chain and move SP */
+ stw r0, +40(r1) /* Save link register */
+ stmw r25, 8(r1) /* save r25 - r31 on stack */
+ /* r31 = scratch register */
+ /* r30 is main referance loop counter,
+ 0 to 23 */
+ /* r29 is ghost loop count, 0 to 22 */
+ /* r28 is referance address */
+ /* r27 is ghost address */
+ /* r26 is log2 (mem size) =
+ number of byte addr bits */
+ /* r25 is mem size */
+
+ /* save the log2(mem size) and mem size */
+ addi r26, r3, 0 /* r26 is number of byte addr bits */
+ addi r25, r4, 0 /* r25 is mem size in bytes */
+
+ /* set the leds for address ghost test */
+ addi r3, 0, ERR_ADDG
+ bl set_led
+
+ /* first fill memory with zeros */
+ srwi r31, r25, 2 /* convert bytes to longs */
+ mtctr r31 /* setup byte counter */
+ addi r28, 0, 0 /* start at address at 0 */
+ addi r31, 0, 0 /* data value = 0 */
+clr_loop:
+ stw r31, 0(r28) /* Store zero value */
+ addi r28, r28, 4 /* Increment to next word */
+ andi. r27, r28, 0xffff /* check for 2^16 loops */
+ bne clr_skip /* if not there, then skip */
+ WATCHDOG_RESET /* kick the dog every now and then */
+clr_skip:
+ bdnz clr_loop /* Round and round... */
+
+ /* now do main test */
+ addi r30, 0, 0 /* start referance counter at 0 */
+outside:
+ /*
+ * Calculate the referance address
+ * the referance address is calculated by setting the (r30-1)
+ * bit of the base address
+ * when r30=0, the referance address is the base address.
+ * thus the sequence 0,1,2,4,8,..,2^(n-1)
+ * setting the bit is done with the following shift functions.
+ */
+ WATCHDOG_RESET /* Reset the watchdog */
+
+ addi r31, 0, 1 /* r31 = 1 */
+ slw r28, r31, r30 /* set bit coresponding to loop cnt */
+ srwi r28, r28, 1 /* then shift it right one so */
+ /* we start at location 0 */
+ /* fill referance address with Fs */
+ addi r31, 0, 0x00ff /* r31 = one byte of set bits */
+ stb r31,0(r28) /* save ff in referance address */
+
+ /* ghost (inner) loop, now check all posible ghosted addresses */
+ addi r29, 0, 0 /* start ghosted loop counter at 0 */
+inside:
+ /*
+ * Calculate the ghost address by flipping one
+ * bit of referance address. This gives the
+ * sequence 1,2,4,8,...,2^(n-1)
+ */
+ addi r31, 0, 1 /* r31 = 1 */
+ slw r27, r31, r29 /* set bit coresponding to loop cnt */
+ xor r27, r28, r27 /* ghost address = ref addr with
+ bit flipped*/
+
+ /* now check for ghosting */
+ lbz r31,0(r27) /* get content of ghost addr */
+ cmpwi r31, 0 /* compare read value to 0 */
+ bne Casper /* we found a ghost! */
+
+ /* now close ghost ( inner ) loop */
+ addi r29, r29, 1 /* increment inner loop counter */
+ cmpw r29, r26 /* check for last inner loop */
+ blt inside /* do more inner loops */
+
+ /* now close referance ( outer ) loop */
+ addi r31, 0, 0 /* r31 = zero */
+ stb r31, 0(28) /* zero out the altered address loc. */
+ /*
+ * Increment and check for end, count is zero based.
+ * With the ble, this gives us one more loops than
+ * address bits for sequence 0,1,2,4,8,...2^(n-1)
+ */
+ addi r30, r30, 1 /* increment outer loop counter */
+ cmpw r30, r26 /* check for last inner loop */
+ ble outside /* do more outer loops */
+
+ /* were done, lets go home */
+ b gb_done
+Casper: /* we found a ghost !! */
+ addi r3, 0, ERR_ADDF /* get indexed error message */
+ bl log_err /* log error led error code */
+gb_done: /* pack your bags, and go home */
+ lmw r25, 8(r1) /* restore r25 - r31 from stack */
+ lwz r0, +40(r1) /* Get saved link register */
+ addi r1, r1, +36 /* Remove frame from stack */
+ mtlr r0 /* Restore link register */
+ blr /* Return to calling function */
+
+/****************************************************
+ ******** SDRAM data fill tests **********
+ ***************************************************/
+Bit_Buster:
+ /* called with mem size in r3 */
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -16(r1) /* Save back chain and move SP */
+ stw r0, +20(r1) /* Save link register */
+ stw r4, +8(r1) /* save R4 */
+ stw r5, +12(r1) /* save r5 */
+
+ addis r5, r3, 0 /* save mem size */
+
+ /* Test 55555555 */
+ addi r3, 0, ERR_R55G /* set up error code in case we fail */
+ bl log_stat /* store test value */
+ addis r4, 0, 0x5555
+ ori r4, r4, 0x5555
+ bl fill_test
+
+ /* Test aaaaaaaa */
+ addi r3, 0, ERR_RAAG /* set up error code in case we fail */
+ bl log_stat /* store test value */
+ addis r4, 0, 0xAAAA
+ ori r4, r4, 0xAAAA
+ bl fill_test
+
+ /* Test 00000000 */
+ addi r3, 0, ERR_R00G /* set up error code in case we fail */
+ bl log_stat /* store test value */
+ addis r4, 0, 0
+ ori r4, r4, 0
+ bl fill_test
+
+ /* restore stack and return */
+ lwz r5, +12(r1) /* restore r4 */
+ lwz r4, +8(r1) /* restore r4 */
+ lwz r0, +20(r1) /* Get saved link register */
+ addi r1, r1, +16 /* Remove frame from stack */
+ mtlr r0 /* Restore link register */
+ blr /* Return to calling function */
+
+
+
+/****************************************************
+ ******** fill test ********
+ ***************************************************/
+/* tests memory by filling with value, and reading back */
+/* r5 = Size of memory in bytes */
+/* r4 = Value to write */
+/* r3 = Error code */
+fill_test:
+ mflr r0 /* Get link register */
+ stwu r1, -32(r1) /* Save back chain and move SP */
+ stw r0, +36(r1) /* Save link register */
+ stmw r27, 8(r1) /* save r27 - r31 on stack */
+ /* r31 - scratch register */
+ /* r30 - memory address */
+ mr r27, r3
+ mr r28, r4
+ mr r29, r5
+
+ WATCHDOG_RESET /* Reset the watchdog */
+
+ /* first fill memory with Value */
+ srawi r31, r29, 2 /* convert bytes to longs */
+ mtctr r31 /* setup counter */
+ addi r30, 0, 0 /* Make r30 = addr 0 */
+ft_0: stw r28, 0(r30) /* Store value */
+ addi r30, r30, 4 /* Increment to next word */
+ andi. r31, r30, 0xffff /* check for 2^16 loops */
+ bne ft_0a /* if not there, then skip */
+ WATCHDOG_RESET /* kick the dog every now and then */
+ft_0a: bdnz ft_0 /* Round and round... */
+
+ WATCHDOG_RESET /* Reset the watchdog */
+
+ /* Now confirm Value is in memory */
+ srawi r31, r29, 2 /* convert bytes to longs */
+ mtctr r31 /* setup counter */
+ addi r30, 0, 0 /* Make r30 = addr 0 */
+ft_1: lwz r31, 0(r30) /* get value from memory */
+ xor. r31, r31, r28 /* Writen = Read ? */
+ bne ft_err /* If bad, than halt */
+ addi r30, r30, 4 /* Increment to next word */
+ andi. r31, r30, 0xffff /* check for 2^16 loops*/
+ bne ft_1a /* if not there, then skip */
+ WATCHDOG_RESET /* kick the dog every now and then */
+ft_1a: bdnz ft_1 /* Round and round... */
+
+ WATCHDOG_RESET /* Reset the watchdog */
+
+ b fill_done /* restore and return */
+
+ft_err: addi r29, r27, 0 /* save current led code */
+ addi r27, r31, 0 /* get pattern in r27 */
+ bl get_idx /* get index from r27 */
+ add r27, r27, r29 /* add index to old led code */
+ bl log_err /* output led err code, halt CPU */
+
+fill_done:
+ lmw r27, 8(r1) /* restore r27 - r31 from stack */
+ lwz r0, +36(r1) /* Get saved link register */
+ addi r1, r1, +32 /* Remove frame from stack */
+ mtlr r0 /* Restore link register */
+ blr /* Return to calling function */
+
+
+/****************************************************
+ ******* get error index from r3 pattern ********
+ ***************************************************/
+get_idx: /* r3 = (MSW(r3) !=0)*2 +
+ (LSW(r3) !=0) */
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -12(r1) /* Save back chain and move SP */
+ stw r0, +16(r1) /* Save link register */
+ stw r4, +8(r1) /* save R4 */
+
+ andi. r4, r3, 0xffff /* check for lower bits */
+ beq gi2 /* skip if no bits set */
+ andis. r4, r3, 0xffff /* check for upper bits */
+ beq gi3 /* skip if no bits set */
+ addi r3, 0, 3 /* both upper and lower bits set */
+ b gi_done
+gi2: andis. r4, r3, 0xffff /* check for upper bits*/
+ beq gi4 /* skip if no bits set */
+ addi r3, 0, 2 /* only upper bits set */
+ b gi_done
+gi3: addi r3, 0, 1 /* only lower bits set */
+ b gi_done
+gi4: addi r3, 0, 0 /* no bits set */
+gi_done:
+ /* restore stack and return */
+ lwz r0, +16(r1) /* Get saved link register */
+ mtlr r0 /* Restore link register */
+ lwz r4, +8(r1) /* restore r4 */
+ addi r1, r1, +12 /* Remove frame from stack */
+ blr /* Return to calling function */
+
+/****************************************************
+ ******** set LED to R5 and hang ********
+ ***************************************************/
+log_stat: /* output a led code and continue */
+set_led:
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -12(r1) /* Save back chain and move SP */
+ stw r0, +16(r1) /* Save link register */
+ stw r4, +8(r1) /* save R4 */
+
+ addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */
+#if defined(CONFIG_W7OLMG) /* only on gateway, invert outputs */
+ xori r3,r3, 0xffff /* complement led code, active low */
+ sth r3, 0(r4) /* store first test value */
+ xori r3,r3, 0xffff /* complement led code, active low */
+#else /* if not gateway, then don't invert */
+ sth r3, 0(r4) /* store first test value */
+#endif
+
+ /* restore stack and return */
+ lwz r0, +16(r1) /* Get saved link register */
+ mtlr r0 /* Restore link register */
+ lwz r4, +8(r1) /* restore r4 */
+ addi r1, r1, +12 /* Remove frame from stack */
+ blr /* Return to calling function */
+
+get_led:
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -12(r1) /* Save back chain and move SP */
+ stw r0, +16(r1) /* Save link register */
+ stw r4, +8(r1) /* save R4 */
+
+ addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */
+ lhz r3, 0(r4) /* store first test value */
+#if defined(CONFIG_W7OLMG) /* only on gateway, invert inputs */
+ xori r3,r3, 0xffff /* complement led code, active low */
+#endif
+
+ /* restore stack and return */
+ lwz r0, +16(r1) /* Get saved link register */
+ mtlr r0 /* Restore link register */
+ lwz r4, +8(r1) /* restore r4 */
+ addi r1, r1, +12 /* Remove frame from stack */
+ blr /* Return to calling function */
+
+log_err: /* output the error and hang the board ( for now ) */
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -12(r1) /* Save back chain and move SP */
+ stw r0, +16(r1) /* Save link register */
+ stw r3, +8(r1) /* save a copy of error code */
+ bl set_led /* set the led pattern */
+ GET_GOT /* get GOT address in r14 */
+ lwz r3,GOT(err_str) /* get address of string */
+ bl post_puts /* output the warning string */
+ lwz r3, +8(r1) /* get error code */
+ addi r4, 0, 2 /* set disp length to 2 nibbles */
+ bl disp_hex /* output the error code */
+ lwz r3,GOT(end_str) /* get address of string */
+ bl post_puts /* output the warning string */
+halt:
+ b halt /* hang */
+
+ /* restore stack and return */
+ lwz r0, +16(r1) /* Get saved link register */
+ mtlr r0 /* Restore link register */
+ addi r1, r1, +12 /* Remove frame from stack */
+ blr /* Return to calling function */
+
+log_warn: /* output a warning, then continue with operations */
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -16(r1) /* Save back chain and move SP */
+ stw r0, +20(r1) /* Save link register */
+ stw r3, +8(r1) /* save a copy of error code */
+ stw r14, +12(r1) /* save a copy of r14 (used by GOT) */
+
+ bl set_led /* set the led pattern */
+ GET_GOT /* get GOT address in r14 */
+ lwz r3,GOT(warn_str) /* get address of string */
+ bl post_puts /* output the warning string */
+ lwz r3, +8(r1) /* get error code */
+ addi r4, 0, 2 /* set disp length to 2 nibbles */
+ bl disp_hex /* output the error code */
+ lwz r3,GOT(end_str) /* get address of string */
+ bl post_puts /* output the warning string */
+
+ addis r3, 0, 64 /* has a long delay */
+ mtctr r3
+log_2:
+ WATCHDOG_RESET /* this keeps dog from barking, */
+ /* and takes time */
+ bdnz log_2 /* loop till time expires */
+
+ /* restore stack and return */
+ lwz r0, +20(r1) /* Get saved link register */
+ lwz r14, +12(r1) /* restore r14 */
+ mtlr r0 /* Restore link register */
+ addi r1, r1, +16 /* Remove frame from stack */
+ blr /* Return to calling function */
+
+/*******************************************************************
+ * temp_uart_init
+ * Temporary UART initialization routine
+ * Sets up UART0 to run at 9600N81 off of the internal clock.
+ * R3-R4 are used.
+ ******************************************************************/
+temp_uart_init:
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -8(r1) /* Save back chain and move SP */
+ stw r0, +12(r1) /* Save link register */
+
+ addis r3, 0, 0xef60
+ ori r3, r3, 0x0303 /* r3 = UART0_LCR */
+ addi r4, 0, 0x83 /* n81 format, divisor regs enabled */
+ stb r4, 0(r3)
+
+ /* set baud rate to use internal clock,
+ baud = (200e6/16)/31/42 = 9600 */
+
+ addis r3, 0, 0xef60 /* Address of baud divisor reg */
+ ori r3, r3, 0x0300 /* UART0_DLM */
+ addi r4, 0, +42 /* uart baud divisor LSB = 93 */
+ stb r4, 0(r3) /* baud = (200 /16)/14/93 */
+
+ addi r3, r3, 0x0001 /* uart baud divisor addr */
+ addi r4, 0, 0
+ stb r4, 0(r3) /* Divisor Latch MSB = 0 */
+
+ addis r3, 0, 0xef60
+ ori r3, r3, 0x0303 /* r3 = UART0_LCR */
+ addi r4, 0, 0x03 /* n81 format, tx/rx regs enabled */
+ stb r4, 0(r3)
+
+ /* output a few line feeds */
+ addi r3, 0, '\n' /* load line feed */
+ bl post_putc /* output the char */
+ addi r3, 0, '\n' /* load line feed */
+ bl post_putc /* output the char */
+
+ /* restore stack and return */
+ lwz r0, +12(r1) /* Get saved link register */
+ mtlr r0 /* Restore link register */
+ addi r1, r1, +8 /* Remove frame from stack */
+ blr /* Return to calling function */
+
+/**********************************************************************
+ ** post_putc
+ ** outputs charactor in R3
+ ** r3 returns the error code ( -1 if there is an error )
+ *********************************************************************/
+
+post_putc:
+
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -20(r1) /* Save back chain and move SP */
+ stw r0, +24(r1) /* Save link register */
+ stmw r29, 8(r1) /* save r29 - r31 on stack
+ r31 - uart base address
+ r30 - delay counter
+ r29 - scratch reg */
+
+ addis r31, 0, 0xef60 /* Point to uart base */
+ ori r31, r31, 0x0300
+ addis r30, 0, 152 /* Load about 10,000,000 ticks. */
+pputc_lp:
+ lbz r29, 5(r31) /* Read Line Status Register */
+ andi. r29, r29, 0x20 /* Check THRE status */
+ bne thre_set /* Branch if FIFO empty */
+ addic. r30, r30, -1 /* Decrement and check if empty. */
+ bne pputc_lp /* Try, try again */
+ addi r3, 0, -1 /* Load error code for timeout */
+ b pputc_done /* Bail out with error code set */
+thre_set:
+ stb r3, 0(r31) /* Store character to UART */
+ addi r3, 0, 0 /* clear error code */
+pputc_done:
+ lmw r29, 8(r1) /*restore r29 - r31 from stack */
+ lwz r0, +24(r1) /* Get saved link register */
+ addi r1, r1, +20 /* Remove frame from stack */
+ mtlr r0 /* Restore link register */
+ blr /* Return to calling function */
+
+
+/****************************************************************
+ post_puts
+ Accepts a null-terminated string pointed to by R3
+ Outputs to the serial port until 0x00 is found.
+ r3 returns the error code ( -1 if there is an error )
+*****************************************************************/
+post_puts:
+
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -12(r1) /* Save back chain and move SP */
+ stw r0, +16(r1) /* Save link register */
+ stw r31, 8(r1) /* save r31 - char pointer */
+
+ addi r31, r3, 0 /* move pointer to R31 */
+pputs_nxt:
+ lbz r3, 0(r31) /* Get next character */
+ addic. r3, r3, 0 /* Check for zero */
+ beq pputs_term /* bail out if zero */
+ bl post_putc /* output the char */
+ addic. r3, r3, 0 /* check for error */
+ bne pputs_err
+ addi r31, r31, 1 /* point to next char */
+ b pputs_nxt /* loop till term */
+pputs_err:
+ addi r3, 0, -1 /* set error code */
+ b pputs_end /* were outa here */
+pputs_term:
+ addi r3, 0, 1 /* set success code */
+ /* restore stack and return */
+pputs_end:
+ lwz r31, 8(r1) /* restore r27 - r31 from stack */
+ lwz r0, +16(r1) /* Get saved link register */
+ addi r1, r1, +12 /* Remove frame from stack */
+ mtlr r0 /* Restore link register */
+ blr /* Return to calling function */
+
+
+
+/********************************************************************
+ ***** disp_hex
+ ***** Routine to display a hex value from a register.
+ ***** R3 is value to display
+ ***** R4 is number of nibbles to display ie 2 for byte 8 for (long)word
+ ***** Returns -1 in R3 if there is an error ( ie serial port hangs )
+ ***** Returns 0 in R3 if no error
+ *******************************************************************/
+disp_hex:
+ /* save the return info on stack */
+ mflr r0 /* Get link register */
+ stwu r1, -16(r1) /* Save back chain and move SP */
+ stw r0, +20(r1) /* Save link register */
+ stmw r30, 8(r1) /* save r30 - r31 on stack */
+ /* r31 output char */
+ /* r30 uart base address */
+ addi r30, 0, 8 /* Go through 8 nibbles. */
+ addi r31, r3, 0
+pputh_nxt:
+ rlwinm r31, r31, 4, 0, 31 /* Rotate next nibble into position */
+ andi. r3, r31, 0x0f /* Get nibble. */
+ addi r3, r3, 0x30 /* Add zero's ASCII code. */
+ cmpwi r3, 0x03a
+ blt pputh_out
+ addi r3, r3, 0x07 /* 0x27 for lower case. */
+pputh_out:
+ cmpw r30, r4
+ bgt pputh_skip
+ bl post_putc
+ addic. r3, r3, 0 /* check for error */
+ bne pputh_err
+pputh_skip:
+ addic. r30, r30, -1
+ bne pputh_nxt
+ xor r3, r3, r3 /* Clear error code */
+ b pputh_done
+pputh_err:
+ addi r3, 0, -1 /* set error code */
+pputh_done:
+ /* restore stack and return */
+ lmw r30, 8(r1) /* restore r30 - r31 from stack */
+ lwz r0, +20(r1) /* Get saved link register */
+ addi r1, r1, +16 /* Remove frame from stack */
+ mtlr r0 /* Restore link register */
+ blr /* Return to calling function */
+
diff --git a/board/w7o/post2.c b/board/w7o/post2.c
new file mode 100644
index 0000000000..271c197f06
--- /dev/null
+++ b/board/w7o/post2.c
@@ -0,0 +1,109 @@
+/*
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net
+ * and
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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 <config.h>
+#include <rtc.h>
+#include "errors.h"
+#include "dtt.h"
+
+#if defined(CONFIG_RTC_M48T35A)
+void rtctest(void)
+{
+ volatile uchar *tchar = (uchar*)(CFG_NVRAM_BASE_ADDR + CFG_NVRAM_SIZE - 9);
+ struct rtc_time tmp;
+
+ /* set up led code for RTC tests */
+ log_stat(ERR_RTCG);
+
+ /*
+ * Do RTC battery test. The first write after power up
+ * fails if battery is low.
+ */
+ *tchar = 0xaa;
+ if ((*tchar ^ 0xaa) != 0x0) log_warn(ERR_RTCBAT);
+ *tchar = 0x55; /* Reset test address */
+
+ /*
+ * Now lets check the validity of the values in the RTC.
+ */
+ rtc_get(&tmp);
+ if ((tmp.tm_sec < 0) | (tmp.tm_sec > 59) |
+ (tmp.tm_min < 0) | (tmp.tm_min > 59) |
+ (tmp.tm_hour < 0) | (tmp.tm_hour > 23) |
+ (tmp.tm_mday < 1 ) | (tmp.tm_mday > 31) |
+ (tmp.tm_mon < 1 ) | (tmp.tm_mon > 12) |
+ (tmp.tm_year < 2000) | (tmp.tm_year > 2500) |
+ (tmp.tm_wday < 1 ) | (tmp.tm_wday > 7)) {
+ log_warn(ERR_RTCTIM);
+ rtc_reset();
+ }
+
+ /*
+ * Now lets do a check to see if the NV RAM is there.
+ */
+ *tchar = 0xaa;
+ if ((*tchar ^ 0xaa) != 0x0) log_err(ERR_RTCVAL);
+ *tchar = 0x55; /* Reset test address */
+
+} /* rtctest() */
+#endif /* CONFIG_RTC_M48T35A */
+
+
+#ifdef CONFIG_DTT_LM75
+int dtt_test(int sensor)
+{
+ short temp, trip, hyst;
+
+ /* get values */
+ temp = dtt_read(sensor, DTT_READ_TEMP) / 256;
+ trip = dtt_read(sensor, DTT_TEMP_SET) / 256;
+ hyst = dtt_read(sensor, DTT_TEMP_HYST) / 256;
+
+ /* check values */
+ if ((hyst != (CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS)) ||
+ (trip != CFG_DTT_MAX_TEMP) ||
+ (temp < CFG_DTT_LOW_TEMP) || (temp > CFG_DTT_MAX_TEMP))
+ return 1;
+
+ return 0;
+} /* dtt_test() */
+#endif /* CONFIG_DTT_LM75 */
+
+/*****************************************/
+
+void post2(void)
+{
+#if defined(CONFIG_RTC_M48T35A)
+ rtctest();
+#endif /* CONFIG_RTC_M48T35A */
+
+#ifdef CONFIG_DTT_LM75
+ log_stat(ERR_TempG);
+ if(dtt_test(2) != 0) log_warn(ERR_Ttest0);
+ if(dtt_test(4) != 0) log_warn(ERR_Ttest1);
+#endif /* CONFIG_DTT_LM75 */
+} /* post2() */
+
diff --git a/board/w7o/vpd.c b/board/w7o/vpd.c
new file mode 100644
index 0000000000..c24b127d3c
--- /dev/null
+++ b/board/w7o/vpd.c
@@ -0,0 +1,408 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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
+ */
+
+#if defined(VXWORKS)
+# include <stdio.h>
+# include <string.h>
+# define CFG_DEF_EEPROM_ADDR 0xa0
+extern char iicReadByte( char, char );
+extern ulong_t crc32( unsigned char *, unsigned long );
+#else
+#include <common.h>
+#endif
+
+#include "vpd.h"
+
+/*
+ * vpd_reader() - reads VPD data from I2C EEPROMS.
+ * returns pointer to buffer or NULL.
+ */
+static unsigned char *
+vpd_reader(unsigned char *buf, unsigned dev_addr, unsigned off, unsigned count)
+{
+ unsigned offset = off; /* Calculated offset */
+
+ /*
+ * The main board EEPROM contains
+ * SDRAM SPD in the first 128 bytes,
+ * so skew the offset.
+ */
+ if (dev_addr == CFG_DEF_EEPROM_ADDR)
+ offset += SDRAM_SPD_DATA_SIZE;
+
+ /* Try to read the I2C EEPROM */
+#if defined(VXWORKS)
+ {
+ int i;
+ for( i = 0; i < count; ++i ) {
+ buf[ i ] = iicReadByte( dev_addr, offset+i );
+ }
+ }
+#else
+ if (eeprom_read(dev_addr, offset, buf, count)) {
+ printf("Failed to read %d bytes from VPD EEPROM 0x%x @ 0x%x\n",
+ count, dev_addr, offset);
+ return NULL;
+ }
+#endif
+
+ return buf;
+} /* vpd_reader() */
+
+
+/*
+ * vpd_get_packet() - returns next VPD packet or NULL.
+ */
+static vpd_packet_t *vpd_get_packet(vpd_packet_t *vpd_packet)
+{
+ vpd_packet_t *packet = vpd_packet;
+
+ if (packet != NULL) {
+ if (packet->identifier == VPD_PID_TERM)
+ return NULL;
+ else
+ packet = (vpd_packet_t *)((char *)packet + packet->size + 2);
+ }
+
+ return packet;
+} /* vpd_get_packet() */
+
+
+/*
+ * vpd_find_packet() - Locates and returns the specified
+ * VPD packet or NULL on error.
+ */
+static vpd_packet_t *vpd_find_packet(vpd_t *vpd, unsigned char ident)
+{
+ vpd_packet_t *packet = (vpd_packet_t *)&vpd->packets;
+
+ /* Guaranteed illegal */
+ if (ident == VPD_PID_GI)
+ return NULL;
+
+ /* Scan tuples looking for a match */
+ while ((packet->identifier != ident) &&
+ (packet->identifier != VPD_PID_TERM))
+ packet = vpd_get_packet(packet);
+
+ /* Did we find it? */
+ if ((packet->identifier) && (packet->identifier != ident))
+ return NULL;
+ return packet;
+}
+
+
+/*
+ * vpd_is_valid() - Validates contents of VPD data
+ * in I2C EEPROM. Returns 1 for
+ * success or 0 for failure.
+ */
+static int vpd_is_valid(unsigned dev_addr, unsigned char *buf)
+{
+ unsigned num_bytes;
+ vpd_packet_t *packet;
+ vpd_t *vpd = (vpd_t *)buf;
+ unsigned short stored_crc16, calc_crc16 = 0xffff;
+
+ /* Check Eyecatcher */
+ if (strncmp(vpd->header.eyecatcher, VPD_EYECATCHER, VPD_EYE_SIZE) != 0) {
+ unsigned offset = 0;
+ if (dev_addr == CFG_DEF_EEPROM_ADDR)
+ offset += SDRAM_SPD_DATA_SIZE;
+ printf("Error: VPD EEPROM 0x%x corrupt @ 0x%x\n", dev_addr, offset);
+
+ return 0;
+ }
+
+ /* Check Length */
+ if (vpd->header.size> VPD_MAX_EEPROM_SIZE) {
+ printf("Error: VPD EEPROM 0x%x contains bad size 0x%x\n",
+ dev_addr, vpd->header.size);
+ return 0;
+ }
+
+ /* Now find the termination packet */
+ if ((packet = vpd_find_packet(vpd, VPD_PID_TERM)) == NULL) {
+ printf("Error: VPD EEPROM 0x%x missing termination packet\n",
+ dev_addr);
+ return 0;
+ }
+
+ /* Calculate data size */
+ num_bytes = (unsigned long)((unsigned char *)packet -
+ (unsigned char *)vpd + sizeof(vpd_packet_t));
+
+ /* Find stored CRC and clear it */
+ if ((packet = vpd_find_packet(vpd, VPD_PID_CRC)) == NULL) {
+ printf("Error: VPD EEPROM 0x%x missing CRC\n", dev_addr);
+ return 0;
+ }
+ stored_crc16 = *((ushort *)packet->data);
+ *(ushort *)packet->data = 0;
+
+ /* OK, lets calculate the CRC and check it */
+#if defined(VXWORKS)
+ calc_crc16 = (0xffff & crc32(buf, num_bytes));
+#else
+ calc_crc16 = (0xffff & crc32(0, buf, num_bytes));
+#endif
+ *(ushort *)packet->data = stored_crc16; /* Now restore the CRC */
+ if (stored_crc16 != calc_crc16) {
+ printf("Error: VPD EEPROM 0x%x has bad CRC 0x%x\n",
+ dev_addr, stored_crc16);
+ return 0;
+ }
+
+ return 1;
+} /* vpd_is_valid() */
+
+
+/*
+ * size_ok() - Check to see if packet size matches
+ * size of data we want. Returns 1 for
+ * good match or 0 for failure.
+ */
+static int size_ok(vpd_packet_t *packet, unsigned long size)
+{
+ if (packet->size != size) {
+ printf("VPD Packet 0x%x corrupt.\n", packet->identifier);
+ return 0;
+ }
+ return 1;
+} /* size_ok() */
+
+
+/*
+ * strlen_ok() - Check to see if packet size matches
+ * strlen of the string we want to populate.
+ * Returns 1 for valid length or 0 for failure.
+ */
+static int strlen_ok(vpd_packet_t *packet, unsigned long length)
+{
+ if (packet->size >= length) {
+ printf("VPD Packet 0x%x corrupt.\n", packet->identifier);
+ return 0;
+ }
+ return 1;
+} /* strlen_ok() */
+
+
+/*
+ * get_vpd_data() - populates the passed VPD structure 'vpdInfo'
+ * with data obtained from the specified
+ * I2C EEPROM 'dev_addr'. Returns 0 for
+ * success or 1 for failure.
+ */
+int vpd_get_data(unsigned char dev_addr, VPD *vpdInfo)
+{
+ unsigned char buf[VPD_EEPROM_SIZE];
+ vpd_t *vpd = (vpd_t *)buf;
+ vpd_packet_t *packet;
+
+ if (vpdInfo == NULL)
+ return 1;
+
+ /*
+ * Fill vpdInfo with 0s to blank out
+ * unused fields, fill vpdInfo->ethAddrs
+ * with all 0xffs so that other's code can
+ * determine how many real Ethernet addresses
+ * there are. OUIs starting with 0xff are
+ * broadcast addresses, and would never be
+ * permantely stored.
+ */
+ memset((void *)vpdInfo, 0, sizeof(VPD));
+ memset((void *)&vpdInfo->ethAddrs, 0xff, sizeof(vpdInfo->ethAddrs));
+ vpdInfo->_devAddr = dev_addr;
+
+ /* Read the minimum size first */
+ if (vpd_reader(buf, dev_addr, 0, VPD_EEPROM_SIZE) == NULL) {
+ return 1;
+ }
+
+ /* Check validity of VPD data */
+ if (!vpd_is_valid(dev_addr, buf)) {
+ printf("VPD Data is INVALID!\n");
+ return 1;
+ }
+
+ /*
+ * Walk all the packets and populate
+ * the VPD info structure.
+ */
+ packet = (vpd_packet_t *)&vpd->packets;
+ do {
+ switch (packet->identifier) {
+ case VPD_PID_GI:
+ printf("Error: Illegal VPD value\n");
+ break;
+ case VPD_PID_PID:
+ if (strlen_ok(packet, MAX_PROD_ID)) {
+ strncpy(vpdInfo->productId,
+ packet->data, packet->size);
+ }
+ break;
+ case VPD_PID_REV:
+ if (size_ok(packet, sizeof(char)))
+ vpdInfo->revisionId = *packet->data;
+ break;
+ case VPD_PID_SN:
+ if (size_ok(packet, sizeof(unsigned long))) {
+ vpdInfo->serialNum =
+ *(unsigned long *)packet->data;
+ }
+ break;
+ case VPD_PID_MANID:
+ if (size_ok(packet, sizeof(unsigned char)))
+ vpdInfo->manuID = *packet->data;
+ break;
+ case VPD_PID_PCO:
+ if (size_ok(packet, sizeof(unsigned long))) {
+ vpdInfo->configOpt =
+ *(unsigned long *)packet->data;
+ }
+ break;
+ case VPD_PID_SYSCLK:
+ if (size_ok(packet, sizeof(unsigned long)))
+ vpdInfo->sysClk = *(unsigned long *)packet->data;
+ break;
+ case VPD_PID_SERCLK:
+ if (size_ok(packet, sizeof(unsigned long)))
+ vpdInfo->serClk = *(unsigned long *)packet->data;
+ break;
+ case VPD_PID_FLASH:
+ if (size_ok(packet, 9)) { /* XXX - hardcoded,
+ padding in struct */
+ memcpy(&vpdInfo->flashCfg, packet->data, 9);
+ }
+ break;
+ case VPD_PID_ETHADDR:
+ memcpy(vpdInfo->ethAddrs, packet->data, packet->size);
+ break;
+ case VPD_PID_POTS:
+ if (size_ok(packet, sizeof(char)))
+ vpdInfo->numPOTS = (unsigned)*packet->data;
+ break;
+ case VPD_PID_DS1:
+ if (size_ok(packet, sizeof(char)))
+ vpdInfo->numDS1 = (unsigned)*packet->data;
+ case VPD_PID_GAL:
+ case VPD_PID_CRC:
+ case VPD_PID_TERM:
+ break;
+ default:
+ printf("Warning: Found unknown VPD packet ID 0x%x\n",
+ packet->identifier);
+ break;
+ }
+ } while ((packet = vpd_get_packet(packet)));
+
+ return 0;
+} /* end get_vpd_data() */
+
+
+/*
+ * vpd_init() - Initialize default VPD environment
+ */
+int vpd_init(unsigned char dev_addr)
+{
+ return (0);
+} /* vpd_init() */
+
+
+/*
+ * vpd_print() - Pretty print the VPD data.
+ */
+void vpd_print(VPD *vpdInfo)
+{
+ const char *const sp = "";
+ const char *const sfmt = "%4s%-20s: \"%s\"\n";
+ const char *const cfmt = "%4s%-20s: '%c'\n";
+ const char *const dfmt = "%4s%-20s: %ld\n";
+ const char *const hfmt = "%4s%-20s: %08lX\n";
+ const char *const dsfmt = "%4s%-20s: %d\n";
+ const char *const hsfmt = "%4s%-20s: %04X\n";
+ const char *const dhfmt = "%4s%-20s: %ld (%lX)\n";
+
+ printf("VPD read from I2C device: %02X\n", vpdInfo->_devAddr);
+
+ if (vpdInfo->productId[0])
+ printf(sfmt, sp, "Product ID", vpdInfo->productId);
+ else
+ printf(sfmt, sp, "Product ID", "UNKNOWN");
+
+ if (vpdInfo->revisionId)
+ printf(cfmt, sp, "Revision ID", vpdInfo->revisionId);
+
+ if (vpdInfo->serialNum)
+ printf(dfmt, sp, "Serial Number", vpdInfo->serialNum);
+
+ if (vpdInfo->manuID)
+ printf(dfmt, sp, "Manufacture ID", (long)vpdInfo->manuID);
+
+ if (vpdInfo->configOpt)
+ printf(hfmt, sp, "Configuration", vpdInfo->configOpt);
+
+ if (vpdInfo->sysClk)
+ printf(dhfmt, sp, "System Clock", vpdInfo->sysClk, vpdInfo->sysClk);
+
+ if (vpdInfo->serClk)
+ printf(dhfmt, sp, "Serial Clock", vpdInfo->serClk, vpdInfo->serClk);
+
+ if (vpdInfo->numPOTS)
+ printf(dfmt, sp, "Number of POTS lines", vpdInfo->numPOTS);
+
+ if (vpdInfo->numDS1)
+ printf(dfmt, sp, "Number of DS1s", vpdInfo->numDS1);
+
+ /* Print Ethernet Addresses */
+ if (vpdInfo->ethAddrs[0][0] != 0xff) {
+ int i, j;
+ printf("%4sEtherNet Address(es): ", sp);
+ for (i = 0; i < MAX_ETH_ADDRS; i++) {
+ if (vpdInfo->ethAddrs[i][0] != 0xff) {
+ for (j = 0; j < 6; j++) {
+ printf("%02X", vpdInfo->ethAddrs[i][j]);
+ if (((j + 1) % 6) != 0)
+ printf(":");
+ else
+ printf(" ");
+ }
+ if (((i + 1) % 3) == 0) printf("\n%24s: ", sp);
+ }
+ }
+ printf("\n");
+ }
+
+ if (vpdInfo->flashCfg.mfg && vpdInfo->flashCfg.dev) {
+ printf("Main Flash Configuration:\n");
+ printf(hsfmt, sp, "Manufacture ID", vpdInfo->flashCfg.mfg);
+ printf(hsfmt, sp, "Device ID", vpdInfo->flashCfg.dev);
+ printf(dsfmt, sp, "Device Width", vpdInfo->flashCfg.devWidth);
+ printf(dsfmt, sp, "Num. Devices", vpdInfo->flashCfg.numDevs);
+ printf(dsfmt, sp, "Num. Columns", vpdInfo->flashCfg.numCols);
+ printf(dsfmt, sp, "Column Width", vpdInfo->flashCfg.colWidth);
+ printf(dsfmt, sp, "WE Data Width", vpdInfo->flashCfg.weDataWidth);
+ }
+} /* vpd_print() */
+
diff --git a/board/w7o/vpd.h b/board/w7o/vpd.h
new file mode 100644
index 0000000000..35bbe3e62d
--- /dev/null
+++ b/board/w7o/vpd.h
@@ -0,0 +1,135 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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 _VPD_H_
+#define _VPD_H_
+
+/*
+ * Main Flash Configuration.
+ */
+typedef struct flashCfg_s {
+ unsigned short mfg; /* Manufacture ID */
+ unsigned short dev; /* Device ID */
+ unsigned char devWidth; /* Device Width */
+ unsigned char numDevs; /* Number of devices */
+ unsigned char numCols; /* Number of columns */
+ unsigned char colWidth; /* Width of a column */
+ unsigned char weDataWidth; /* Write/Erase Data Width */
+} flashCfg_t;
+
+/*
+ * Vital Product Data - VPD
+ */
+#define MAX_PROD_ID 15
+#define MAX_ETH_ADDRS 10
+typedef unsigned char EthAddr[6];
+typedef struct vpd {
+ unsigned char _devAddr; /* Device address during read */
+ char productId[MAX_PROD_ID]; /* Product ID */
+ char revisionId; /* Revision ID as a char */
+ unsigned long serialNum; /* Serial number */
+ unsigned char manuID; /* Manufact ID - byte int */
+ unsigned long configOpt; /* Config Option - bit field */
+ unsigned long sysClk; /* System clock in Hertz */
+ unsigned long serClk; /* Ext. clock in Hertz */
+ flashCfg_t flashCfg; /* Flash configuration */
+ unsigned long numPOTS; /* Number of POTS lines */
+ unsigned long numDS1; /* Number of DS1 circuits */
+ EthAddr ethAddrs[MAX_ETH_ADDRS]; /* Ethernet MAC, 1st = craft */
+} VPD;
+
+
+#define VPD_MAX_EEPROM_SIZE 512 /* Max size VPD EEPROM */
+#define SDRAM_SPD_DATA_SIZE 128 /* Size SPD in VPD EEPROM */
+
+/*
+ * PIDs - Packet Identifiers
+ */
+#define VPD_PID_GI 0x0 /* Guaranted Illegal */
+#define VPD_PID_PID 0x1 /* Product Identifier */
+#define VPD_PID_REV 0x2 /* Product Revision */
+#define VPD_PID_SN 0x3 /* Serial Number */
+#define VPD_PID_MANID 0x4 /* Manufacture ID */
+#define VPD_PID_PCO 0x5 /* Product configuration */
+#define VPD_PID_SYSCLK 0x6 /* System Clock */
+#define VPD_PID_SERCLK 0x7 /* Ser. Clk. Speed in Hertz */
+#define VPD_PID_CRC 0x8 /* VPD CRC */
+#define VPD_PID_FLASH 0x9 /* Flash Configuration */
+#define VPD_PID_ETHADDR 0xA /* Ethernet Address(es) */
+#define VPD_PID_GAL 0xB /* Galileo Switch Config */
+#define VPD_PID_POTS 0xC /* Number of POTS Lines */
+#define VPD_PID_DS1 0xD /* Number of DS1s */
+#define VPD_PID_TERM 0xFF /* Termination packet */
+
+/*
+ * VPD - Eyecatcher/Magic
+ */
+#define VPD_EYECATCHER "W7O"
+#define VPD_EYE_SIZE 3
+typedef struct vpd_header {
+ unsigned char eyecatcher[VPD_EYE_SIZE]; /* eyecatcher - "W7O" */
+ unsigned short size __attribute__((packed)); /* size of EEPROM */
+} vpd_header_t;
+
+
+#define VPD_DATA_SIZE (VPD_MAX_EEPROM_SIZE - SDRAM_SPD_DATA_SIZE - \
+ sizeof(vpd_header_t))
+typedef struct vpd_s {
+ vpd_header_t header;
+ unsigned char packets[VPD_DATA_SIZE];
+} vpd_t;
+
+typedef struct vpd_packet {
+ unsigned char identifier;
+ unsigned char size;
+ unsigned char data[1];
+} vpd_packet_t;
+
+/*
+ * VPD configOpt bit mask
+ */
+#define VPD_HAS_BBRAM 0x1 /* Battery backed SRAM */
+#define VPD_HAS_RTC 0x2 /* Battery backed RTC */
+#define VPD_HAS_EXT_SER_CLK 0x4 /* External serial clock */
+#define VPD_HAS_SER_TRANS_1 0x8 /* COM1 transceiver */
+#define VPD_HAS_SER_TRANS_2 0x10 /* COM2 transceiver */
+#define VPD_HAS_CRAFT_PHY 0x20 /* CRAFT Ethernet */
+#define VPD_HAS_DTT_1 0x40 /* I2C Digital therm. #1 */
+#define VPD_HAS_DTT_2 0x80 /* I2C Digital therm. #2 */
+#define VPD_HAS_1000_UP_LASER 0x100 /* GMM - 1000Mbit Uplink */
+#define VPD_HAS_70KM_UP_LASER 0x200 /* CMM - 70KM Uplink laser */
+#define VPD_HAS_2_UPLINKS 0x400 /* CMM - 2 uplink lasers */
+#define VPD_HAS_FPGA 0x800 /* Has 1 or more FPGAs */
+#define VPD_HAS_DFA 0x1000 /* CLM - Has 2 Fiber Inter. */
+#define VPD_HAS_GAL_SWITCH 0x2000 /* GMM - Has a Gal switch */
+#define VPD_HAS_POTS_LINES 0x4000 /* GMM - Has POTS lines */
+#define VPD_HAS_DS1_CHANNELS 0x8000 /* GMM - Has DS1 channels */
+#define VPD_HAS_CABLE_RETURN 0x10000 /* GBM/GBR - Cable ret. path */
+
+#define VPD_EEPROM_SIZE (256 - SDRAM_SPD_DATA_SIZE) /* Size EEPROM */
+
+extern int vpd_get_data(unsigned char dev_addr, VPD *vpd);
+extern void vpd_print(VPD *vpdInfo);
+
+#endif /* _VPD_H_ */
+
diff --git a/board/w7o/w7o.c b/board/w7o/w7o.c
new file mode 100644
index 0000000000..b404d61c1a
--- /dev/null
+++ b/board/w7o/w7o.c
@@ -0,0 +1,271 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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 "w7o.h"
+#include <asm/processor.h>
+
+#include "vpd.h"
+#include "errors.h"
+#include <watchdog.h>
+
+unsigned long get_dram_size(void);
+
+/*
+ * Macros to transform values
+ * into environment strings.
+ */
+#define XMK_STR(x) #x
+#define MK_STR(x) XMK_STR(x)
+
+/* ------------------------------------------------------------------------- */
+
+int board_pre_init (void)
+{
+#if defined(CONFIG_W7OLMG)
+ /*
+ * Setup GPIO pins - reset devices.
+ */
+ out32(IBM405GP_GPIO0_ODR, 0x10000000); /* one open drain pin */
+ out32(IBM405GP_GPIO0_OR, 0x3E000000); /* set output pins to default */
+ out32(IBM405GP_GPIO0_TCR, 0x7f800000); /* setup for output */
+
+ /*
+ * IRQ 0-15 405GP internally generated; active high; level sensitive
+ * IRQ 16 405GP internally generated; active low; level sensitive
+ * IRQ 17-24 RESERVED
+ * IRQ 25 (EXT IRQ 0) XILINX; active low; level sensitive
+ * IRQ 26 (EXT IRQ 1) PCI INT A; active low; level sensitive
+ * IRQ 27 (EXT IRQ 2) PCI INT B; active low; level sensitive
+ * IRQ 28 (EXT IRQ 3) SAM 2; active low; level sensitive
+ * IRQ 29 (EXT IRQ 4) Battery Bad; active low; level sensitive
+ * IRQ 30 (EXT IRQ 5) Level One PHY; active low; level sensitive
+ * IRQ 31 (EXT IRQ 6) SAM 1; active high; level sensitive
+ */
+ mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
+ mtdcr(uicer, 0x00000000); /* disable all ints */
+
+ mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/
+ mtdcr(uicpr, 0xFFFFFF80); /* set int polarities */
+ mtdcr(uictr, 0x10000000); /* set int trigger levels */
+ mtdcr(uicvcr, 0x00000001); /* set vect base=0,
+ INT0 highest priority*/
+
+ mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
+
+#elif defined(CONFIG_W7OLMC)
+ /*
+ * Setup GPIO pins
+ */
+ out32(IBM405GP_GPIO0_ODR, 0x01800000); /* XCV Done Open Drain */
+ out32(IBM405GP_GPIO0_OR, 0x03800000); /* set out pins to default */
+ out32(IBM405GP_GPIO0_TCR, 0x66C00000); /* setup for output */
+
+ /*
+ * IRQ 0-15 405GP internally generated; active high; level sensitive
+ * IRQ 16 405GP internally generated; active low; level sensitive
+ * IRQ 17-24 RESERVED
+ * IRQ 25 (EXT IRQ 0) DBE 0; active low; level sensitive
+ * IRQ 26 (EXT IRQ 1) DBE 1; active low; level sensitive
+ * IRQ 27 (EXT IRQ 2) DBE 2; active low; level sensitive
+ * IRQ 28 (EXT IRQ 3) DBE Common; active low; level sensitive
+ * IRQ 29 (EXT IRQ 4) PCI; active low; level sensitive
+ * IRQ 30 (EXT IRQ 5) RCMM Reset; active low; level sensitive
+ * IRQ 31 (EXT IRQ 6) PHY; active high; level sensitive
+ */
+ mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
+ mtdcr(uicer, 0x00000000); /* disable all ints */
+
+ mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/
+ mtdcr(uicpr, 0xFFFFFF80); /* set int polarities */
+ mtdcr(uictr, 0x10000000); /* set int trigger levels */
+ mtdcr(uicvcr, 0x00000001); /* set vect base=0,
+ INT0 highest priority*/
+
+ mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
+
+#else /* Unknown */
+# error "Unknown W7O board configuration"
+#endif
+
+ WATCHDOG_RESET(); /* Reset the watchdog */
+ temp_uart_init(); /* init the uart for debug */
+ WATCHDOG_RESET(); /* Reset the watchdog */
+ test_led(); /* test the LEDs */
+ test_sdram(get_dram_size()); /* test the dram */
+ log_stat(ERR_POST1); /* log status,post1 complete */
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Check Board Identity:
+ */
+int checkboard (void)
+{
+ VPD vpd;
+
+ puts ("Board: ");
+
+ /* VPD data present in I2C EEPROM */
+ if (vpd_get_data(CFG_DEF_EEPROM_ADDR, &vpd) == 0) {
+ /*
+ * Known board type.
+ */
+ if (vpd.productId[0] &&
+ ((strncmp(vpd.productId, "GMM", 3) == 0) ||
+ (strncmp(vpd.productId, "CMM", 3) == 0))) {
+
+ /* Output board information on startup */
+ printf("\"%s\", revision '%c', serial# %ld, manufacturer %u\n",
+ vpd.productId, vpd.revisionId, vpd.serialNum, vpd.manuID);
+ return (0);
+ }
+ }
+
+ puts ("### Unknown HW ID - assuming NOTHING\n");
+ return (0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+long int initdram (int board_type)
+{
+ return get_dram_size();
+}
+
+unsigned long get_dram_size (void)
+{
+ int tmp, i, regs[4];
+ int size = 0;
+
+ /* Get bank Size registers */
+ mtdcr(memcfga, mem_mb0cf); /* get bank 0 config reg */
+ regs[0] = mfdcr(memcfgd);
+
+ mtdcr(memcfga, mem_mb1cf); /* get bank 1 config reg */
+ regs[1] = mfdcr(memcfgd);
+
+ mtdcr(memcfga, mem_mb2cf); /* get bank 2 config reg */
+ regs[2] = mfdcr(memcfgd);
+
+ mtdcr(memcfga, mem_mb3cf); /* get bank 3 config reg */
+ regs[3] = mfdcr(memcfgd);
+
+ /* compute the size, add each bank if enabled */
+ for(i = 0; i < 4; i++) {
+ if (regs[i] & 0x0001) { /* if enabled, */
+ tmp = ((regs[i] >> (31 - 14)) & 0x7); /* get size bits */
+ tmp = 0x400000 << tmp; /* Size bits X 4MB = size */
+ size += tmp;
+ }
+ }
+
+ return size;
+}
+
+int misc_init_f (void)
+{
+ return 0;
+}
+
+static void
+w7o_env_init(VPD *vpd)
+{
+ /*
+ * Read VPD
+ */
+ if (vpd_get_data(CFG_DEF_EEPROM_ADDR, vpd) != 0)
+ return;
+
+ /*
+ * Known board type.
+ */
+ if (vpd->productId[0] &&
+ ((strncmp(vpd->productId, "GMM", 3) == 0) ||
+ (strncmp(vpd->productId, "CMM", 3) == 0))) {
+ char buf[30];
+ char *eth;
+ unsigned char *serial = getenv("serial#");
+ unsigned char *ethaddr = getenv("ethaddr");
+
+ /* Set 'serial#' envvar if serial# isn't set */
+ if (!serial) {
+ sprintf(buf, "%s-%ld", vpd->productId, vpd->serialNum);
+ setenv("serial#", buf);
+ }
+
+ /* Set 'ethaddr' envvar if 'ethaddr' envvar is the default */
+ eth = vpd->ethAddrs[0];
+ if (ethaddr && (strcmp(ethaddr, MK_STR(CONFIG_ETHADDR)) == 0)) {
+ /* Now setup ethaddr */
+ sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+ setenv("ethaddr", buf);
+ }
+ }
+} /* w7o_env_init() */
+
+
+int misc_init_r (void)
+{
+ VPD vpd; /* VPD information */
+
+#if defined(CONFIG_W7OLMG)
+ unsigned long greg; /* GPIO Register */
+
+ greg = in32(IBM405GP_GPIO0_OR);
+
+ /*
+ * XXX - Unreset devices - this should be moved into VxWorks driver code
+ */
+ greg |= 0x41800000L; /* SAM, PHY, Galileo */
+
+ out32(IBM405GP_GPIO0_OR, greg); /* set output pins to default */
+#endif /* CONFIG_W7OLMG */
+
+ /*
+ * Initialize W7O environment variables
+ */
+ w7o_env_init(&vpd);
+
+ /*
+ * Initialize the FPGA(s).
+ */
+ if (init_fpga() == 0)
+ test_fpga((unsigned short *)CONFIG_FPGAS_BASE);
+
+ /* More POST testing. */
+ post2();
+
+ /* Done with hardware initialization and POST. */
+ log_stat(ERR_POSTOK);
+
+ /* Call silly, fail safe boot init routine */
+ init_fsboot();
+
+ return (0);
+}
+
OpenPOWER on IntegriCloud