Das U-Boot: Universal Boot Loader
authorwdenk <wdenk>
Sun, 3 Nov 2002 00:24:07 +0000 (00:24 +0000)
committerwdenk <wdenk>
Sun, 3 Nov 2002 00:24:07 +0000 (00:24 +0000)
208 files changed:
CREDITS [new file with mode: 0644]
README [new file with mode: 0644]
board/cogent/serial.c [new file with mode: 0644]
board/cu824/cu824.c [new file with mode: 0644]
board/dnp1110/u-boot.lds [new file with mode: 0644]
board/ebony/ebony.c [new file with mode: 0644]
board/ebony/init.S [new file with mode: 0644]
board/eltec/bab7xx/asm_init.S [new file with mode: 0644]
board/eltec/bab7xx/el_srom.c [new file with mode: 0644]
board/eltec/bab7xx/u-boot.lds [new file with mode: 0644]
board/eltec/elppc/asm_init.S [new file with mode: 0644]
board/eltec/elppc/u-boot.lds [new file with mode: 0644]
board/ep7312/flash.c [new file with mode: 0644]
board/ep7312/u-boot.lds [new file with mode: 0644]
board/esd/common/fpga.c [new file with mode: 0644]
board/esd/common/pci.c [new file with mode: 0644]
board/esd/cpci405/cpci405.c [new file with mode: 0644]
board/esd/cpci440/cpci440.c [new file with mode: 0644]
board/esd/cpci440/init.S [new file with mode: 0644]
board/esd/pci405/pci405.c [new file with mode: 0644]
board/evb64260/eth_addrtbl.c [new file with mode: 0644]
board/evb64260/pci.c [new file with mode: 0644]
board/evb64260/sdram_init.c [new file with mode: 0644]
board/evb64260/serial.c [new file with mode: 0644]
board/gen860t/README [new file with mode: 0644]
board/gen860t/beeper.c [new file with mode: 0644]
board/gen860t/flash.c [new file with mode: 0644]
board/gen860t/fpga.c [new file with mode: 0644]
board/gen860t/gen860t.c [new file with mode: 0644]
board/gen860t/ioport.c [new file with mode: 0644]
board/gen860t/u-boot.lds [new file with mode: 0644]
board/impa7/flash.c [new file with mode: 0644]
board/impa7/u-boot.lds [new file with mode: 0644]
board/lart/u-boot.lds [new file with mode: 0644]
board/mbx8xx/mbx8xx.c [new file with mode: 0644]
board/ml2/serial.c [new file with mode: 0644]
board/mousse/pci.c [new file with mode: 0644]
board/mpl/common/common_util.c [new file with mode: 0644]
board/mpl/common/pci.c [new file with mode: 0644]
board/mpl/common/pci_parts.h [new file with mode: 0644]
board/mpl/mip405/Makefile [new file with mode: 0644]
board/mpl/pip405/Makefile [new file with mode: 0644]
board/musenki/musenki.c [new file with mode: 0644]
board/mvs1/Makefile [new file with mode: 0644]
board/netvia/Makefile [new file with mode: 0644]
board/netvia/netvia.c [new file with mode: 0644]
board/netvia/u-boot.lds [new file with mode: 0644]
board/netvia/u-boot.lds.debug [new file with mode: 0644]
board/oxc/flash.c [new file with mode: 0644]
board/oxc/oxc.c [new file with mode: 0644]
board/pcippc2/cpc710_init_ram.c [new file with mode: 0644]
board/pcippc2/cpc710_pci.c [new file with mode: 0644]
board/pcippc2/i2c.c [new file with mode: 0644]
board/pcippc2/pcippc2.c [new file with mode: 0644]
board/pn62/cmd_pn62.c [new file with mode: 0644]
board/pn62/misc.c [new file with mode: 0644]
board/pn62/pn62.c [new file with mode: 0644]
board/r360mpi/r360mpi.c [new file with mode: 0644]
board/sacsng/clkinit.c [new file with mode: 0644]
board/sacsng/ioconfig.h [new file with mode: 0644]
board/sandpoint/sandpoint.c [new file with mode: 0644]
board/shannon/u-boot.lds [new file with mode: 0644]
board/siemens/CCM/ccm.c [new file with mode: 0644]
board/siemens/CCM/fpga_ccm.c [new file with mode: 0644]
board/siemens/SCM/fpga_scm.c [new file with mode: 0644]
board/siemens/common/README [new file with mode: 0644]
board/siemens/common/fpga.c [new file with mode: 0644]
board/smdk2400/u-boot.lds [new file with mode: 0644]
board/smdk2410/smdk2410.c [new file with mode: 0644]
board/tqm8xx/flash.c [new file with mode: 0644]
board/tqm8xx/load_sernum_ethaddr.c [new file with mode: 0644]
board/trab/README.kbd [new file with mode: 0644]
board/trab/trab.c [new file with mode: 0644]
board/trab/u-boot.lds [new file with mode: 0644]
board/trab/vfd.c [new file with mode: 0644]
board/utx8245/utx8245.c [new file with mode: 0644]
board/w7o/flash.c [new file with mode: 0644]
board/w7o/fpga.c [new file with mode: 0644]
board/w7o/init.S [new file with mode: 0644]
board/w7o/post1.S [new file with mode: 0644]
board/w7o/post2.c [new file with mode: 0644]
board/w7o/vpd.c [new file with mode: 0644]
board/w7o/vpd.h [new file with mode: 0644]
board/w7o/w7o.c [new file with mode: 0644]
common/cmd_doc.c [new file with mode: 0644]
common/cmd_ide.c [new file with mode: 0644]
common/cmd_immap.c [new file with mode: 0644]
common/cmd_jffs2.c [new file with mode: 0644]
common/cmd_pci.c [new file with mode: 0644]
common/cmd_pcmcia.c [new file with mode: 0644]
common/env_flash.c [new file with mode: 0644]
common/env_nvram.c [new file with mode: 0644]
common/environment.c [new file with mode: 0644]
common/main.c [new file with mode: 0644]
common/miiphyutil.c [new file with mode: 0644]
common/soft_i2c.c [new file with mode: 0644]
cpu/arm720t/Makefile [new file with mode: 0644]
cpu/arm720t/interrupts.c [new file with mode: 0644]
cpu/arm920t/Makefile [new file with mode: 0644]
cpu/arm920t/interrupts.c [new file with mode: 0644]
cpu/arm920t/serial.c [new file with mode: 0644]
cpu/arm920t/speed.c [new file with mode: 0644]
cpu/mpc824x/cpu_init.c [new file with mode: 0644]
cpu/mpc824x/drivers/i2c/i2c1.c [new file with mode: 0644]
cpu/mpc824x/pci.c [new file with mode: 0644]
cpu/mpc824x/start.S [new file with mode: 0644]
cpu/mpc8260/cpu_init.c [new file with mode: 0644]
cpu/mpc8260/i2c.c [new file with mode: 0644]
cpu/mpc8xx/cpu.c [new file with mode: 0644]
cpu/mpc8xx/fec.c [new file with mode: 0644]
cpu/mpc8xx/spi.c [new file with mode: 0644]
cpu/ppc4xx/405gp_enet.c [new file with mode: 0644]
cpu/ppc4xx/405gp_pci.c [new file with mode: 0644]
cpu/ppc4xx/cpu.c [new file with mode: 0644]
cpu/ppc4xx/i2c.c [new file with mode: 0644]
cpu/ppc4xx/sdram.c [new file with mode: 0644]
cpu/ppc4xx/speed.c [new file with mode: 0644]
cpu/ppc4xx/vecnum.h [new file with mode: 0644]
cpu/sa1100/Makefile [new file with mode: 0644]
cpu/xscale/serial.c [new file with mode: 0644]
cpu/xscale/start.S [new file with mode: 0644]
doc/README.JFFS2 [new file with mode: 0644]
doc/README.Modem [new file with mode: 0644]
doc/README.commands [new file with mode: 0644]
doc/README.ebony [new file with mode: 0644]
doc/README.ppc440 [new file with mode: 0644]
drivers/3c589.h [new file with mode: 0644]
drivers/5701rls.c [new file with mode: 0644]
drivers/5701rls.h [new file with mode: 0644]
drivers/bcm570x_autoneg.h [new file with mode: 0644]
drivers/bcm570x_debug.h [new file with mode: 0644]
drivers/bcm570x_lm.h [new file with mode: 0644]
drivers/bcm570x_mm.h [new file with mode: 0644]
drivers/bcm570x_queue.h [new file with mode: 0644]
drivers/cfb_console.c [new file with mode: 0644]
drivers/cs8900.c [new file with mode: 0644]
drivers/ct69000.c [new file with mode: 0644]
drivers/dc2114x.c [new file with mode: 0644]
drivers/i8042.c [new file with mode: 0644]
drivers/ns87308.c [new file with mode: 0644]
drivers/pci.c [new file with mode: 0644]
drivers/pci_auto.c [new file with mode: 0644]
drivers/pcnet.c [new file with mode: 0644]
drivers/smiLynxEM.c [new file with mode: 0644]
drivers/tigon3.c [new file with mode: 0644]
drivers/tigon3.h [new file with mode: 0644]
dtt/ds1621.c [new file with mode: 0644]
dtt/lm75.c [new file with mode: 0644]
include/altera.h [new file with mode: 0644]
include/asm-arm/bitops.h [new file with mode: 0644]
include/asm-arm/proc-armv/ptrace.h [new file with mode: 0644]
include/asm-arm/u-boot-arm.h [new file with mode: 0644]
include/asm-arm/u-boot.h [new file with mode: 0644]
include/cmd_bsp.h [new file with mode: 0644]
include/configs/BMW.h [new file with mode: 0644]
include/configs/CCM.h [new file with mode: 0644]
include/configs/CPCI405.h [new file with mode: 0644]
include/configs/CPCI4052.h [new file with mode: 0644]
include/configs/CPCIISER4.h [new file with mode: 0644]
include/configs/CRAYL1.h [new file with mode: 0644]
include/configs/CU824.h [new file with mode: 0644]
include/configs/DU405.h [new file with mode: 0644]
include/configs/EVB64260.h [new file with mode: 0644]
include/configs/MUSENKI.h [new file with mode: 0644]
include/configs/MVS1.h [new file with mode: 0644]
include/configs/OCRTC.h [new file with mode: 0644]
include/configs/ORSG.h [new file with mode: 0644]
include/configs/OXC.h [new file with mode: 0644]
include/configs/PCI405.h [new file with mode: 0644]
include/configs/PIP405.h [new file with mode: 0644]
include/configs/PN62.h [new file with mode: 0644]
include/configs/Sandpoint8240.h [new file with mode: 0644]
include/configs/Sandpoint8245.h [new file with mode: 0644]
include/configs/ZUMA.h [new file with mode: 0644]
include/configs/shannon.h [new file with mode: 0644]
include/configs/trab.h [new file with mode: 0644]
include/configs/utx8245.h [new file with mode: 0644]
include/dtt.h [new file with mode: 0644]
include/environment.h [new file with mode: 0644]
include/linux/byteorder/generic.h [new file with mode: 0644]
include/mpc824x.h [new file with mode: 0644]
include/pci.h [new file with mode: 0644]
include/smiLynxEM.h [new file with mode: 0644]
include/spartan2.h [new file with mode: 0644]
include/status_led.h [new file with mode: 0644]
include/video_fb.h [new file with mode: 0644]
include/virtex2.h [new file with mode: 0644]
include/xilinx.h [new file with mode: 0644]
lib_arm/_udivsi3.S [new file with mode: 0644]
lib_arm/_umodsi3.S [new file with mode: 0644]
lib_arm/armlinux.c [new file with mode: 0644]
lib_arm/board.c [new file with mode: 0644]
lib_generic/string.c [new file with mode: 0644]
net/eth.c [new file with mode: 0644]
post/cache_8xx.S [new file with mode: 0644]
post/cpu.c [new file with mode: 0644]
post/cpu/b.c [new file with mode: 0644]
post/cpu/cmp.c [new file with mode: 0644]
post/cpu/cmpi.c [new file with mode: 0644]
post/cpu/cr.c [new file with mode: 0644]
post/cpu/three.c [new file with mode: 0644]
post/cpu/threei.c [new file with mode: 0644]
post/cpu/threex.c [new file with mode: 0644]
post/cpu/two.c [new file with mode: 0644]
post/cpu/twox.c [new file with mode: 0644]
post/ether.c [new file with mode: 0644]
post/memory.c [new file with mode: 0644]
rtc/ds1556.c [new file with mode: 0644]

diff --git a/CREDITS b/CREDITS
new file mode 100644 (file)
index 0000000..2358817
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,242 @@
+#
+#   Parts of the development effort for this project have been
+#   sponsored by SIEMENS AG, Austria. Thanks to SIEMENS for
+#   supporting an Open Source project!
+#
+#
+#   This is at least a partial credits-file of individual people that
+#   have contributed to the U-Boot project. It is sorted by name and
+#   formatted to allow easy grepping and beautification by scripts.
+#   The fields are: name (N), email (E), web-address (W), PGP key ID
+#   and fingerprint (P), description (D), and snail-mail address (S).
+#   Thanks,
+#
+#                       Wolfgang Denk
+#----------
+
+N: Dr. Bruno Achauer
+E: bruno@exet-ag.de
+D: Support for NetBSD (both as host and target system)
+
+N: Swen Anderson
+E: sand@peppercon.de
+D: ERIC Support
+
+N: Guillaume Alexandre
+E: guillaume.alexandre@gespac.ch
+D: Add PCIPPC6 configuration
+
+N: Pierre Aubert
+E: <p.aubert@staubli.com>
+D: Support for RPXClassic board
+
+N: Andre Beaudin
+E: <andre.beaudin@colubris.com>
+D: PCMCIA, Ethernet, TFTP
+
+N: Jerry van Baren
+E: <vanbaren@cideas.com>
+D: BedBug port to 603e core (MPC82xx). Code for enhanced memory test.
+
+N: Raphael Bossek
+E: raphael.bossek@solutions4linux.de
+D: 8xxrom-0.3.0
+
+N: David Brown
+E: DBrown03@harris.com
+D: Extensions to 8xxrom-0.3.0
+
+N: Oliver Brown
+E: obrown@adventnetworks.com
+D: Port to the gw8260 board
+
+N: Jonathan De Bruyne
+E: jonathan.debruyne@siemens.atea.be
+D: Port to Siemens IAD210 board
+
+N: Conn Clark
+E: clark@esteem.com
+D: ESTEEM192E support
+
+N: Magnus Damm
+E: eramdam@kieray1.p.y.ki.era.ericsson.se
+D: 8xxrom
+
+N: Kári Davíðsson
+E: kd@flaga.is
+D: FLAGA DM Support
+
+N: Wolfgang Denk
+E: wd@denx.de
+D: U-Boot initial version, continuing maintenance, ARMBoot merge
+W: http://www.denx.de
+
+N: Dan A. Dickey
+E: ddickey@charter.net
+D: FADS Support
+
+N: James F. Dougherty
+E: jfd@GigabitNetworks.COM
+D: Port to the MOUSSE board
+
+N: Dave Ellis
+E: DGE@sixnetio.com
+D: EEPROM Speedup, SXNI855T port
+
+N: Dr. Wolfgang Grandegger
+E: wg@denx.de
+D: Support for Interphase 4539 T1/E1/J1 PMC, PN62, CCM, SCM boards
+W: www.denx.de
+
+N: Frank Gottschling
+E: fgottschling@eltec.de
+D: Support for ELTEC MHPC/BAB7xx/ELPPC boards, cfb-console, i8042, SMI LynxEM
+W: www.eltec.de
+
+N: Marius Groeger
+E: mgroeger@sysgo.de
+D: MBX Support, board specific function interface, EST SBC8260 support; initial support for StrongARM (LART), ARM720TDMI (implementa A7)
+W: www.elinos.com
+
+N: Kirk Haderlie
+E: khaderlie@vividimage.com
+D: Added TFTP to 8xxrom (-> 0.3.1)
+
+N: Chris Hallinan
+E: clh@net1plus.com
+D: DHCP Support
+
+N: Anne-Sophie Harnois
+E: Anne-Sophie.Harnois@nextream.fr
+D: Port to Walnut405 board
+
+N: Andreas Heppel
+E: aheppel@sysgo.de
+D: CPU Support for MPC 75x; board support for Eltec BAB750 [obsolete!]
+
+N: Josh Huber
+E: huber@alum.wpi.edu
+D: Port to the Galileo Evaluation Board, and the MPC74xx cpu series.
+W: http://www.mclx.com/
+
+H: Stuart Hughes
+E: stuarth@lineo.com
+D: Port to MPC8260ADS board
+
+H: Rich Ireland
+E: r.ireland@computer.org
+D: FPGA device configuration driver
+
+N: Gary Jennejohn
+E: garyj@jennejohn.org, gj@denx.de
+D: Support for Samsung ARM920T S3C2400X, ARM920T "TRAB"
+W: www.denx.de
+
+N: Murray Jensen
+E: Murray.Jensen@cmst.csiro.au
+D: Initial 8260 support; GDB support
+D: Port to Cogent+Hymod boards; Hymod Board Database
+W: http://www.msa.cmst.csiro.au/ourstaff/MurrayJensen/mjj.html
+
+N: Yoo. Jonghoon
+E: yooth@ipone.co.kr
+D: Added port to the RPXlite board
+
+N: Brad Kemp
+E: Brad.Kemp@seranoa.com
+D: Port to Windriver ppmc8260 board
+
+N: Thomas Koeller
+E: tkoeller@gmx.net
+D: Port to Motorola Sandpoint 3 (MPC8240)
+
+N: Thomas Lange
+E: thomas@corelatus.com
+D: Support for GTH board; lots of PCMCIA fixes
+
+N: Raymond Lo
+E: lo@routefree.com
+D: Support for DOS partitions
+
+N: Dan Malek
+E: dan@netx4.com
+D: FADSROM, the grandfather of all of this
+
+N: Jay Monkman
+E: jtm@smoothsmoothie.com
+D: EST SBC8260 support
+
+N: Frank Morauf
+E: frank.morauf@salzbrenner.com
+D: Support for Embedded Planet RPX Super Board
+
+N: David Müller
+E: d.mueller@elsoft.ch
+D: Support for Samsung ARM920T SMDK2410 eval board
+
+N: Rolf Offermanns
+E: rof@sysgo.de
+D: Initial support for SSV-DNP1110, SMC91111 driver
+W: www.elinos.com
+
+N: Keith Outwater
+E: Keith_Outwater@mvis.com
+D: Support for GEN860T board
+
+N: Keith Outwater
+E: keith_outwater@mvis.com
+D: Support for generic/custom MPC860T board (GEN860T)
+
+N: Frank Panno
+E: fpanno@delphintech.com
+D: Support for Embedded Planet EP8260 Board
+
+N: Denis Peter
+E: d.peter@mpl.ch
+D: Support for 4xx SCSI, floppy, CDROM, CT69000 video, ...
+D: Support for PIP405 board
+D: Support for MIP405 board
+
+N: Bill Pitts
+E: wlp@mindspring.com
+D: BedBug embedded debugger code
+
+N: Stefan Roese
+E: stefan.roese@esd-electronics.com
+D: IBM PPC401/403/405GP Support; Windows environment support
+
+N: Neil Russell
+E: caret@c-side.com
+D: Author of LiMon-1.4.2, which contributed some ideas
+
+N: Paolo Scaffardi
+E: arsenio@tin.it
+D: FADS823 configuration, MPC823 video support, I2C, wireless keyboard, lots more
+
+N: Robert Schwebel
+E: r.schwebel@pengutronix.de
+D: Support for csb226 board (xscale)
+N: Rob Taylor
+E: robt@flyingpig.com
+D: Port to MBX860T and Sandpoint8240
+
+N: Erik Theisen
+E: etheisen@mindspring.com
+D: MBX8xx and many other patches
+
+N: Jim Thompson
+E: jim@musenki.com
+D: Support for MUSENKI board
+
+N: David Updegraff
+E: dave@cray.com
+D: Port to Cray L1 board; DHCP vendor extensions
+
+N: Christian Vejlbo
+E: christian.vejlbo@tellabs.com
+D: FADS860T ethernet support
+
+N: Alex Zuepke
+E: azu@sysgo.de
+D: Overall improvements on StrongARM, ARM720TDMI; Support for Tuxscreen; initial PCMCIA support for ARM
+W: www.elinos.com
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..30ff772
--- /dev/null
+++ b/README
@@ -0,0 +1,2663 @@
+#
+# (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
+#
+
+Summary:
+========
+
+This directory contains the source code for U-Boot, a monitor for
+Embedded PowerPC boards, which can be installed in a boot ROM and
+used to test the hardware or download and run application code.
+
+The development of U-Boot is closely related to Linux: some parts of
+the source code originate in the Linux source tree, we still have
+some header files in common, and special provision has been made to
+support booting of Linux images.
+
+Some attention has been paid to make this software easily
+configurable and extendable. For instance, all monitor commands are
+implemented with the same call interface, so that it's very easy to
+add new commands. Also, instead of permanently adding rarely used
+code (for instance hardware test utilities) to the monitor, you can
+load and run it dynamically.
+
+
+Status:
+=======
+
+In general, all boards for which a configuration option exists in the
+Makefile have been tested  to  some  extent  and  can  be  considered
+"working". In fact, many of them are used in production systems.
+
+In case of problems see the CHANGELOG and CREDITS files to  find  out
+who contributed the specific port.
+
+Exception from this rule: the port to the Sandpoint 8240 has not been
+completed yet.
+
+
+Where to get help:
+==================
+
+In case you have questions about, problems with or contributions  for
+U-Boot  you  should  send  a  message to the U-Boot mailing list at
+<u-boot-users@lists.sourceforge.net>. There is also  an  archive  of
+previous  traffic  on  the  mailing  list - please search the archive
+before asking FAQ's. Please see
+http://lists.sourceforge.net/lists/listinfo/u-boot-users/
+
+
+Where we come from:
+===================
+
+- start from 8xxrom sources
+- clean up code
+- make it easier to add custom boards
+- make it possible to add other [PowerPC] CPUs
+- extend functions, especially:
+  * Provide extended interface to Linux boot loader
+  * S-Record download
+  * network boot
+  * PCMCIA / CompactFLash / ATA disk / SCSI ... boot
+- add other CPU families (starting with ARM)
+
+
+Directory Hierarchy:
+====================
+
+- board                Board dependend files
+- common       Misc architecture independend functions
+- cpu          CPU specific files
+- disk         Code for disk drive partition handling
+- doc          Documentation (don't expect too much)
+- drivers      Common used device drivers
+- dtt          Digital Thermometer and Thermostat drivers
+- examples     Example code for standalone applications, etc.
+- include      Header Files
+- disk         Harddisk interface code
+- net          Networking code
+- ppc          Files generic to PowerPC architecture
+- post         Power On Self Test
+- post/arch            Symlink to architecture specific Power On Self Test
+- post/arch-ppc                PowerPC architecture specific Power On Self Test
+- post/cpu/mpc8260     MPC8260 CPU specific Power On Self Test
+- post/cpu/mpc8xx      MPC8xx CPU specific Power On Self Test
+- rtc          Real Time Clock drivers
+- tools                Tools to build S-Record or U-Boot images, etc.
+
+- cpu/74xx_7xx Files specific to Motorola MPC74xx and 7xx CPUs
+- cpu/mpc8xx   Files specific to Motorola MPC8xx  CPUs
+- cpu/mpc824x  Files specific to Motorola MPC824x CPUs
+- cpu/mpc8260  Files specific to Motorola MPC8260 CPU
+- cpu/ppc4xx   Files specific to IBM      4xx     CPUs
+
+- board/RPXClassic
+               Files specific to RPXClassic boards
+- board/RPXlite        Files specific to RPXlite    boards
+- board/c2mon  Files specific to c2mon      boards
+- board/cogent Files specific to Cogent     boards
+               (need further configuration)
+               Files specific to CPCIISER4  boards
+- board/cpu86  Files specific to CPU86      boards
+- board/cray/  Files specific to boards manufactured by Cray
+- board/cray/L1                Files specific to L1         boards
+- board/cu824  Files specific to CU824      boards
+- board/ebony   Files specific to IBM Ebony board
+- board/eric   Files specific to ERIC       boards
+- board/esd/   Files specific to boards manufactured by ESD
+- board/esd/adciop     Files specific to ADCIOP     boards
+- board/esd/ar405      Files specific to AR405      boards
+- board/esd/canbt      Files specific to CANBT      boards
+- board/esd/cpci405    Files specific to CPCI405    boards
+- board/esd/cpciiser4  Files specific to CPCIISER4  boards
+- board/esd/common     Common files for ESD boards
+- board/esd/dasa_sim   Files specific to DASA_SIM   boards
+- board/esd/du405      Files specific to DU405      boards
+- board/esd/ocrtc      Files specific to OCRTC      boards
+- board/esd/pci405     Files specific to PCI405     boards
+- board/esteem192e
+               Files specific to ESTEEM192E boards
+- board/etx094 Files specific to ETX_094    boards
+- board/evb64260
+               Files specific to EVB64260   boards
+- board/fads   Files specific to FADS       boards
+- board/flagadm Files specific to FLAGADM    boards
+- board/gen860t Files specific to GEN860T    boards
+- board/genietv Files specific to GENIETV    boards
+- board/gth    Files specific to GTH        boards
+- board/hermes Files specific to HERMES     boards
+- board/hymod  Files specific to HYMOD      boards
+- board/icu862 Files specific to ICU862     boards
+- board/ip860  Files specific to IP860      boards
+- board/iphase4539
+               Files specific to Interphase4539 boards
+- board/ivm    Files specific to IVMS8/IVML24 boards
+- board/lantec Files specific to LANTEC     boards
+- board/lwmon  Files specific to LWMON      boards
+- board/mbx8xx Files specific to MBX        boards
+- board/mpc8260ads
+               Files specific to MMPC8260ADS boards
+- board/mpl/   Files specific to boards manufactured by MPL
+- board/mpl/common     Common files for MPL boards
+- board/mpl/pip405     Files specific to PIP405     boards
+- board/mpl/mip405     Files specific to MIP405     boards
+- board/musenki        Files specific to MUSEKNI    boards
+- board/mvs1   Files specific to MVS1       boards
+- board/nx823   Files specific to NX823      boards
+- board/oxc    Files specific to OXC        boards
+- board/pcippc2        Files specific to PCIPPC2/PCIPPC6 boards
+- board/pm826  Files specific to PM826      boards
+- board/ppmc8260
+               Files specific to PPMC8260   boards
+- board/rpxsuper
+               Files specific to RPXsuper   boards
+- board/rsdproto
+               Files specific to RSDproto   boards
+- board/sandpoint
+               Files specific to Sandpoint  boards
+- board/sbc8260        Files specific to SBC8260    boards
+- board/sacsng Files specific to SACSng     boards
+- board/siemens Files specific to boards manufactured by Siemens AG
+- board/siemens/CCM    Files specific to CCM        boards
+- board/siemens/IAD210 Files specific to IAD210     boards
+- board/siemens/SCM    Files specific to SCM        boards
+- board/siemens/pcu_e  Files specific to PCU_E      boards
+- board/sixnet Files specific to SIXNET     boards
+- board/spd8xx Files specific to SPD8xxTS   boards
+- board/tqm8260 Files specific to TQM8260    boards
+- board/tqm8xx Files specific to TQM8xxL    boards
+- board/w7o    Files specific to W7O        boards
+- board/walnut405
+               Files specific to Walnut405  boards
+- board/westel/        Files specific to boards manufactured by Westel Wireless
+- board/westel/amx860  Files specific to AMX860     boards
+- board/utx8245        Files specific to UTX8245   boards
+
+Software Configuration:
+=======================
+
+Configuration is usually done using C preprocessor defines; the
+rationale behind that is to avoid dead code whenever possible.
+
+There are two classes of configuration variables:
+
+* Configuration _OPTIONS_:
+  These are selectable by the user and have names beginning with
+  "CONFIG_".
+
+* Configuration _SETTINGS_:
+  These depend on the hardware etc. and should not be meddled with if
+  you don't know what you're doing; they have names beginning with
+  "CFG_".
+
+Later we will add a configuration tool - probably similar to or even
+identical to what's used for the Linux kernel. Right now, we have to
+do the configuration by hand, which means creating some symbolic
+links and editing some configuration files. We use the TQM8xxL boards
+as an example here.
+
+
+Selection of Processor Architecture and Board Type:
+---------------------------------------------------
+
+For all supported boards there are ready-to-use default
+configurations available; just type "make <board_name>_config".
+
+Example: For a TQM823L module type:
+
+       cd u-boot
+       make TQM823L_config
+
+For the Cogent platform, you need to specify the cpu type as well;
+e.g. "make cogent_mpc8xx_config". And also configure the cogent
+directory according to the instructions in cogent/README.
+
+
+Configuration Options:
+----------------------
+
+Configuration depends on the combination of board and CPU type; all
+such information is kept in a configuration file
+"include/configs/<board_name>.h".
+
+Example: For a TQM823L module, all configuration settings are in
+"include/configs/TQM823L.h".
+
+
+The following options need to be configured:
+
+- CPU Type:    Define exactly one of
+
+               PowerPC based CPUs:
+               -------------------
+               CONFIG_MPC823,  CONFIG_MPC850,  CONFIG_MPC855,  CONFIG_MPC860
+       or      CONFIG_MPC824X, CONFIG_MPC8260
+       or      CONFIG_IOP480
+       or      CONFIG_405GP
+       or      CONFIG_440
+       or      CONFIG_MPC74xx
+
+               ARM based CPUs:
+               ---------------
+               CONFIG_SA1110
+               CONFIG_ARM7
+               CONFIG_PXA250
+
+
+- Board Type:  Define exactly one of
+
+               PowerPC based boards:
+               ---------------------
+
+               CONFIG_ADCIOP,     CONFIG_ICU862      CONFIG_RPXsuper,
+               CONFIG_ADS860,     CONFIG_IP860,      CONFIG_SM850,
+               CONFIG_AMX860,     CONFIG_IPHASE4539, CONFIG_SPD823TS,
+               CONFIG_AR405,      CONFIG_IVML24,     CONFIG_SXNI855T,
+               CONFIG_BAB7xx,     CONFIG_IVML24_128, CONFIG_Sandpoint8240,
+               CONFIG_CANBT,      CONFIG_IVML24_256, CONFIG_Sandpoint8245,
+               CONFIG_CCM,        CONFIG_IVMS8,      CONFIG_TQM823L,
+               CONFIG_CPCI405,    CONFIG_IVMS8_128,  CONFIG_TQM850L,
+               CONFIG_CPCI4052,   CONFIG_IVMS8_256,  CONFIG_TQM855L,
+               CONFIG_CPCIISER4,  CONFIG_LANTEC,     CONFIG_TQM860L,
+               CONFIG_CPU86,      CONFIG_MBX,        CONFIG_TQM8260,
+               CONFIG_CRAYL1,     CONFIG_MBX860T,    CONFIG_TTTech,
+               CONFIG_CU824,      CONFIG_MHPC,       CONFIG_UTX8245,
+               CONFIG_DASA_SIM,   CONFIG_MIP405,     CONFIG_W7OLMC,
+               CONFIG_DU405,      CONFIG_MOUSSE,     CONFIG_W7OLMG,
+               CONFIG_ELPPC,      CONFIG_MPC8260ADS, CONFIG_WALNUT405,
+               CONFIG_ERIC,       CONFIG_MUSENKI,    CONFIG_ZUMA,
+               CONFIG_ESTEEM192E, CONFIG_MVS1,       CONFIG_c2mon,
+               CONFIG_ETX094,     CONFIG_NX823,      CONFIG_cogent_mpc8260,
+               CONFIG_EVB64260,   CONFIG_OCRTC,      CONFIG_cogent_mpc8xx,
+               CONFIG_FADS823,    CONFIG_ORSG,       CONFIG_ep8260,
+               CONFIG_FADS850SAR, CONFIG_OXC,        CONFIG_gw8260,
+               CONFIG_FADS860T,   CONFIG_PCI405,     CONFIG_hermes,
+               CONFIG_FLAGADM,    CONFIG_PCIPPC2,    CONFIG_hymod,
+               CONFIG_FPS850L,    CONFIG_PCIPPC6,    CONFIG_lwmon,
+               CONFIG_GEN860T,    CONFIG_PIP405,     CONFIG_pcu_e,
+               CONFIG_GENIETV,    CONFIG_PM826,      CONFIG_ppmc8260,
+               CONFIG_GTH,        CONFIG_RPXClassic, CONFIG_rsdproto,
+               CONFIG_IAD210,     CONFIG_RPXlite,    CONFIG_sbc8260,
+               CONFIG_EBONY,      CONFIG_sacsng
+
+               ARM based boards:
+               -----------------
+
+               CONFIG_HHP_CRADLE,  CONFIG_DNP1110,    CONFIG_EP7312,
+               CONFIG_IMPA7,       CONFIG_LART,       CONFIG_LUBBOCK,
+               CONFIG_SHANNON,     CONFIG_SMDK2400,   CONFIG_SMDK2410,
+               CONFIG_TRAB
+
+
+- CPU Module Type: (if CONFIG_COGENT is defined)
+               Define exactly one of
+               CONFIG_CMA286_60_OLD
+--- FIXME --- not tested yet:
+               CONFIG_CMA286_60, CONFIG_CMA286_21, CONFIG_CMA286_60P,
+               CONFIG_CMA287_23, CONFIG_CMA287_50
+
+- Motherboard Type: (if CONFIG_COGENT is defined)
+               Define exactly one of
+               CONFIG_CMA101, CONFIG_CMA102
+
+- Motherboard I/O Modules: (if CONFIG_COGENT is defined)
+               Define one or more of
+               CONFIG_CMA302
+
+- Motherboard Options: (if CONFIG_CMA101 or CONFIG_CMA102 are defined)
+               Define one or more of
+               CONFIG_LCD_HEARTBEAT    - update a character position on
+                                         the lcd display every second with
+                                         a "rotator" |\-/|\-/
+
+- MPC824X Family Member (if CONFIG_MPC824X is defined)
+       Define exactly one of
+       CONFIG_MPC8240, CONFIG_MPC8245
+
+- 8xx CPU Options: (if using an 8xx cpu)
+               Define one or more of
+               CONFIG_8xx_GCLK_FREQ    - if get_gclk_freq() can not work e.g.
+                                         no 32KHz reference PIT/RTC clock
+
+- Clock Interface:
+               CONFIG_CLOCKS_IN_MHZ
+
+               U-Boot stores all clock information in Hz
+               internally. For binary compatibility with older Linux
+               kernels (which expect the clocks passed in the
+               bd_info data to be in MHz) the environment variable
+               "clocks_in_mhz" can be defined so that U-Boot
+               converts clock data to MHZ before passing it to the
+               Linux kernel.
+
+               When CONFIG_CLOCKS_IN_MHZ is defined, a definition of
+               "clocks_in_mhz=1" is  automatically  included  in  the
+               default environment.
+
+- Console Interface:
+                Depending on board, define exactly one serial port
+                (like CONFIG_8xx_CONS_SMC1, CONFIG_8xx_CONS_SMC2,
+                CONFIG_8xx_CONS_SCC1, ...), or switch off the serial
+                console by defining CONFIG_8xx_CONS_NONE
+
+               Note: if CONFIG_8xx_CONS_NONE is defined, the serial
+               port routines must be defined elsewhere
+               (i.e. serial_init(), serial_getc(), ...)
+
+               CONFIG_CFB_CONSOLE
+               Enables console device for a color framebuffer. Needs following
+               defines (cf. smiLynxEM, i8042, board/eltec/bab7xx)
+                       VIDEO_FB_LITTLE_ENDIAN  graphic memory organisation
+                                               (default big endian)
+                       VIDEO_HW_RECTFILL       graphic chip supports
+                                               rectangle fill
+                                               (cf. smiLynxEM)
+                       VIDEO_HW_BITBLT         graphic chip supports
+                                               bit-blit (cf. smiLynxEM)
+                       VIDEO_VISIBLE_COLS      visible pixel columns
+                                               (cols=pitch)
+                       VIDEO_VISIBLE_ROWS      visible pixel rows
+                       VIDEO_PIXEL_SIZE        bytes per pixel
+                       VIDEO_DATA_FORMAT       graphic data format
+                                               (0-5, cf. cfb_console.c)
+                       VIDEO_FB_ADRS           framebuffer address
+                       VIDEO_KBD_INIT_FCT      keyboard int fct
+                                               (i.e. i8042_kbd_init())
+                       VIDEO_TSTC_FCT          test char fct
+                                               (i.e. i8042_tstc)
+                       VIDEO_GETC_FCT          get char fct
+                                               (i.e. i8042_getc)
+                       CONFIG_CONSOLE_CURSOR   cursor drawing on/off
+                                               (requires blink timer
+                                               cf. i8042.c)
+                       CFG_CONSOLE_BLINK_COUNT blink interval (cf. i8042.c)
+                       CONFIG_CONSOLE_TIME     display time/date info in
+                                               upper right corner
+                                               (requires CFG_CMD_DATE)
+                       CONFIG_VIDEO_LOGO       display Linux logo in
+                                               upper left corner
+                       CONFIG_CONSOLE_EXTRA_INFO
+                                               addional board info beside
+                                               the logo
+
+                When CONFIG_CFB_CONSOLE is defined, video console is
+                default i/o. Serial console can be forced with
+                environment 'console=serial'.
+
+- Console Baudrate:
+               CONFIG_BAUDRATE - in bps
+               Select one of the baudrates listed in
+               CFG_BAUDRATE_TABLE, see below.
+
+- Interrupt driven serial port input:
+               CONFIG_SERIAL_SOFTWARE_FIFO
+
+               PPC405GP only.
+               Use an interrupt handler for receiving data on the
+               serial port. It also enables using hardware handshake
+               (RTS/CTS) and UART's built-in FIFO. Set the number of
+               bytes the interrupt driven input buffer should have.
+
+               Set to 0 to disable this feature (this is the default).
+               This will also disable hardware handshake.
+
+- Boot Delay:  CONFIG_BOOTDELAY - in seconds
+               Delay before automatically booting the default image;
+               set to -1 to disable autoboot.
+
+               See doc/README.autoboot for these options that
+               work with CONFIG_BOOTDELAY. None are required.
+               CONFIG_BOOT_RETRY_TIME
+               CONFIG_BOOT_RETRY_MIN
+               CONFIG_AUTOBOOT_KEYED
+               CONFIG_AUTOBOOT_PROMPT
+               CONFIG_AUTOBOOT_DELAY_STR
+               CONFIG_AUTOBOOT_STOP_STR
+               CONFIG_AUTOBOOT_DELAY_STR2
+               CONFIG_AUTOBOOT_STOP_STR2
+               CONFIG_ZERO_BOOTDELAY_CHECK
+               CONFIG_RESET_TO_RETRY
+
+- Autoboot Command:
+               CONFIG_BOOTCOMMAND
+               Only needed when CONFIG_BOOTDELAY is enabled;
+               define a command string that is automatically executed
+               when no character is read on the console interface
+               within "Boot Delay" after reset.
+
+               CONFIG_BOOTARGS
+                This can be used to pass arguments to the bootm
+                command. The value of CONFIG_BOOTARGS goes into the
+                environment value "bootargs".
+
+               CONFIG_RAMBOOT and CONFIG_NFSBOOT
+                The value of these goes into the environment as
+                "ramboot" and "nfsboot" respectively, and can be used
+                as a convenience, when switching between booting from
+                ram and nfs.
+
+- Pre-Boot Commands:
+               CONFIG_PREBOOT
+
+               When this option is #defined, the existence of the
+               environment variable "preboot" will be checked
+               immediately before starting the CONFIG_BOOTDELAY
+               countdown and/or running the auto-boot command resp.
+               entering interactive mode.
+
+               This feature is especially useful when "preboot" is
+               automatically generated or modified. For an example
+               see the LWMON board specific code: here "preboot" is
+               modified when the user holds down a certain
+               combination of keys on the (special) keyboard when
+               booting the systems
+
+- Serial Download Echo Mode:
+               CONFIG_LOADS_ECHO
+               If defined to 1, all characters received during a
+               serial download (using the "loads" command) are
+               echoed back. This might be needed by some terminal
+               emulations (like "cu"), but may as well just take
+               time on others. This setting #define's the initial
+               value of the "loads_echo" environment variable.
+
+- Kgdb Serial Baudrate: (if CFG_CMD_KGDB is defined)
+               CONFIG_KGDB_BAUDRATE
+               Select one of the baudrates listed in
+               CFG_BAUDRATE_TABLE, see below.
+
+- Monitor Functions:
+               CONFIG_COMMANDS
+               Most monitor functions can be selected (or
+               de-selected) by adjusting the definition of
+               CONFIG_COMMANDS; to select individual functions,
+               #define CONFIG_COMMANDS by "OR"ing any of the
+               following values:
+
+               #define enables commands:
+               -------------------------
+               CFG_CMD_ASKENV  * ask for env variable
+               CFG_CMD_BDI       bdinfo
+               CFG_CMD_BEDBUG    Include BedBug Debugger
+               CFG_CMD_BOOTD     bootd
+               CFG_CMD_CACHE     icache, dcache
+               CFG_CMD_CONSOLE   coninfo
+               CFG_CMD_DATE    * support for RTC, date/time...
+               CFG_CMD_DHCP      DHCP support
+               CFG_CMD_ECHO    * echo arguments
+               CFG_CMD_EEPROM  * EEPROM read/write support
+               CFG_CMD_ELF       bootelf, bootvx
+               CFG_CMD_ENV       saveenv
+               CFG_CMD_FDC     * Floppy Disk Support
+               CFG_CMD_FLASH     flinfo, erase, protect
+               CFG_CMD_FPGA      FPGA device initialization support
+               CFG_CMD_I2C     * I2C serial bus support
+               CFG_CMD_IDE     * IDE harddisk support
+               CFG_CMD_IMI       iminfo
+               CFG_CMD_IMMAP   * IMMR dump support
+               CFG_CMD_IRQ     * irqinfo
+               CFG_CMD_KGDB    * kgdb
+               CFG_CMD_LOADB     loadb
+               CFG_CMD_LOADS     loads
+               CFG_CMD_MEMORY    md, mm, nm, mw, cp, cmp, crc, base,
+                                 loop, mtest
+               CFG_CMD_MII       MII utility commands
+               CFG_CMD_NET       bootp, tftpboot, rarpboot
+               CFG_CMD_PCI     * pciinfo
+               CFG_CMD_PCMCIA  * PCMCIA support
+               CFG_CMD_REGINFO * Register dump
+               CFG_CMD_RUN       run command in env variable
+               CFG_CMD_SCSI    * SCSI Support
+               CFG_CMD_SETGETDCR Support for DCR Register access (4xx only)
+               CFG_CMD_SPI     * SPI serial bus support
+               CFG_CMD_USB     * USB support
+               CFG_CMD_BSP     * Board SPecific functions
+               -----------------------------------------------
+               CFG_CMD_ALL     all
+
+               CFG_CMD_DFL     Default configuration; at the moment
+                               this is includes all commands, except
+                               the ones marked with "*" in the list
+                               above.
+
+               If you don't define CONFIG_COMMANDS it defaults to
+               CFG_CMD_DFL in include/cmd_confdefs.h. A board can
+               override the default settings in the respective
+               include file.
+
+               EXAMPLE: If you want all functions except of network
+               support you can write:
+
+               #define CONFIG_COMMANDS (CFG_CMD_ALL & ~CFG_CMD_NET)
+
+
+       Note:   Don't enable the "icache" and "dcache" commands
+                (configuration option CFG_CMD_CACHE) unless you know
+                what you (and your U-Boot users) are doing. Data
+                cache cannot be enabled on systems like the 8xx or
+                8260 (where accesses to the IMMR region must be
+                uncached), and it cannot be disabled on all other
+                systems where we (mis-) use the data cache to hold an
+                initial stack and some data.
+
+
+               XXX - this list needs to get updated!
+
+- Watchdog:
+               CONFIG_WATCHDOG
+               If this variable is defined, it enables watchdog
+               support. There must support in the platform specific
+               code for a watchdog. For the 8xx and 8260 CPUs, the
+               SIU Watchdog feature is enabled in the SYPCR
+               register.
+
+- Real-Time Clock:
+
+               When CFG_CMD_DATE is selected, the type of the RTC
+               has to be selected, too. Define exactly one of the
+               following options:
+
+               CONFIG_RTC_MPC8xx       - use internal RTC of MPC8xx
+               CONFIG_RTC_PCF8563      - use Philips PCF8563 RTC
+               CONFIG_RTC_MC146818     - use MC146818 RTC
+               CONFIG_RTC_DS1337       - use Maxim, Inc. DS1337 RTC
+
+- Timestamp Support:
+
+                When CONFIG_TIMESTAMP is selected, the timestamp
+                (date and time) of an image is printed by image
+                commands like bootm or iminfo. This option is
+                automatically enabled when you select CFG_CMD_DATE .
+
+- Partition Support:
+               CONFIG_MAC_PARTITION and/or CONFIG_DOS_PARTITION
+               and/or CONFIG_ISO_PARTITION
+
+               If IDE or SCSI support  is  enabled  (CFG_CMD_IDE  or
+               CFG_CMD_SCSI) you must configure support for at least
+               one partition type as well.
+
+- IDE Reset method:
+               CONFIG_IDE_RESET_ROUTINE
+
+               Set this to define that instead of a reset Pin, the
+               routine ide_set_reset(int idereset) will be used.
+
+- ATAPI Support:
+               CONFIG_ATAPI
+
+               Set this to enable ATAPI support.
+
+- SCSI Support:
+               At the moment only there is only support for the
+               SYM53C8XX SCSI controller; define
+               CONFIG_SCSI_SYM53C8XX to enable it.
+
+               CFG_SCSI_MAX_LUN [8], CFG_SCSI_MAX_SCSI_ID [7] and
+               CFG_SCSI_MAX_DEVICE [CFG_SCSI_MAX_SCSI_ID *
+               CFG_SCSI_MAX_LUN] can be adjusted to define the
+               maximum numbers of LUNs, SCSI ID's and target
+               devices.
+               CFG_SCSI_SYM53C8XX_CCF to fix clock timing (80Mhz)
+
+- NETWORK Support (PCI):
+               CONFIG_EEPRO100
+               Support for Intel 82557/82559/82559ER chips.
+               Optional CONFIG_EEPRO100_SROM_WRITE enables eeprom
+               write routine for first time initialisation.
+
+               CONFIG_TULIP
+               Support for Digital 2114x chips.
+               Optional CONFIG_TULIP_SELECT_MEDIA for board specific
+               modem chip initialisation (KS8761/QS6611).
+
+               CONFIG_NATSEMI
+               Support for National dp83815 chips.
+
+               CONFIG_NS8382X
+               Support for National dp8382[01] gigabit chips.
+
+- USB Support:
+               At the moment only the UHCI host controller is
+               supported (PIP405, MIP405); define
+               CONFIG_USB_UHCI to enable it.
+               define CONFIG_USB_KEYBOARD to enable the USB Keyboard
+               end define CONFIG_USB_STORAGE to enable the USB
+               storage devices.
+               Note:
+               Supported are USB Keyboards and USB Floppy drives
+               (TEAC FD-05PUB).
+
+- Keyboard Support:
+               CONFIG_ISA_KEYBOARD
+
+               Define this to enable standard (PC-Style) keyboard
+               support
+
+               CONFIG_I8042_KBD
+               Standard PC keyboard driver with US (is default) and
+               GERMAN key layout (switch via environment 'keymap=de') support.
+               Export function i8042_kbd_init, i8042_tstc and i8042_getc
+               for cfb_console. Supports cursor blinking.
+
+- Video support:
+               CONFIG_VIDEO
+
+               Define this to enable video support (for output to
+               video).
+
+               CONFIG_VIDEO_CT69000
+
+               Enable Chips & Technologies 69000 Video chip
+
+               CONFIG_VIDEO_SMI_LYNXEM
+               Enable Silicon Motion SMI 712/710/810 Video chip
+               Videomode are selected via environment 'videomode' with
+               standard LiLo mode numbers.
+               Following modes are supported  (* is default):
+
+                            800x600  1024x768  1280x1024
+              256  (8bit)     303*      305       307
+            65536 (16bit)     314       317       31a
+        16,7 Mill (24bit)     315       318       31b
+               (i.e. setenv videomode 317; saveenv; reset;)
+
+- LCD Support: CONFIG_LCD
+
+               Define this to enable LCD support (for output to LCD
+               display); also select one of the supported displays
+               by defining one of these:
+
+               CONFIG_NEC_NL6648AC33:
+
+                       NEC NL6648AC33-18. Active, color, single scan.
+
+               CONFIG_NEC_NL6648BC20
+
+                       NEC NL6648BC20-08. 6.5", 640x480.
+                       Active, color, single scan.
+
+               CONFIG_SHARP_16x9
+
+                       Sharp 320x240. Active, color, single scan.
+                       It isn't 16x9, and I am not sure what it is.
+
+               CONFIG_SHARP_LQ64D341
+
+                       Sharp LQ64D341 display, 640x480.
+                       Active, color, single scan.
+
+               CONFIG_HLD1045
+
+                       HLD1045 display, 640x480.
+                       Active, color, single scan.
+
+               CONFIG_OPTREX_BW
+
+                       Optrex   CBL50840-2 NF-FW 99 22 M5
+                       or
+                       Hitachi  LMG6912RPFC-00T
+                       or
+                       Hitachi  SP14Q002
+
+                       320x240. Black & white.
+
+               Normally display is black on white background; define
+               CFG_WHITE_ON_BLACK to get it inverted.
+
+- Ethernet address:
+               CONFIG_ETHADDR
+               CONFIG_ETH2ADDR
+               CONFIG_ETH3ADDR
+
+               Define a default value for ethernet address to use
+               for the respective ethernet interface, in case this
+               is not determined automatically.
+
+- IP address:
+               CONFIG_IPADDR
+
+               Define a default value for the IP address to use for
+               the default ethernet interface, in case this is not
+               determined through e.g. bootp.
+
+- Server IP address:
+               CONFIG_SERVERIP
+
+               Defines a default value for theIP address of a TFTP
+               server to contact when using the "tftboot" command.
+
+- BOOTP Recovery Mode:
+               CONFIG_BOOTP_RANDOM_DELAY
+
+               If you have many targets in a network that try to
+               boot using BOOTP, you may want to avoid that all
+               systems send out BOOTP requests at precisely the same
+               moment (which would happen for instance at recovery
+               from a power failure, when all systems will try to
+               boot, thus flooding the BOOTP server. Defining
+               CONFIG_BOOTP_RANDOM_DELAY causes a random delay to be
+               inserted before sending out BOOTP requests. The
+               following delays are insterted then:
+
+               1st BOOTP request:      delay 0 ... 1 sec
+               2nd BOOTP request:      delay 0 ... 2 sec
+               3rd BOOTP request:      delay 0 ... 4 sec
+               4th and following
+               BOOTP requests:         delay 0 ... 8 sec
+
+- Status LED:  CONFIG_STATUS_LED
+
+               Several configurations allow to display the current
+               status using a LED. For instance, the LED will blink
+               fast while running U-Boot code, stop blinking as
+               soon as a reply to a BOOTP request was received, and
+               start blinking slow once the Linux kernel is running
+               (supported by a status LED driver in the Linux
+               kernel). Defining CONFIG_STATUS_LED enables this
+               feature in U-Boot.
+
+- CAN Support: CONFIG_CAN_DRIVER
+
+               Defining CONFIG_CAN_DRIVER enables CAN driver support
+               on those systems that support this (optional)
+               feature, like the TQM8xxL modules.
+
+- I2C Support: CONFIG_HARD_I2C | CONFIG_SOFT_I2C
+
+               Enables I2C serial bus commands.  If this is selected,
+               either CONFIG_HARD_I2C or CONFIG_SOFT_I2C must be defined
+               to include the appropriate I2C driver.
+
+                See also: common/cmd_i2c.c for a description of the
+                command line interface.
+
+
+               CONFIG_HARD_I2C
+
+               Selects the CPM hardware driver for I2C.
+
+               CONFIG_SOFT_I2C
+
+               Use software (aka bit-banging) driver instead of CPM
+               or similar hardware support for I2C.  This is configured
+               via the following defines.
+
+               I2C_INIT
+
+                (Optional). Any commands necessary to enable I2C
+                controller or configure ports.
+
+               I2C_PORT
+
+                (Only for MPC8260 CPU). The I/O port to use (the code
+                assumes both bits are on the same port). Valid values
+                are 0..3 for ports A..D.
+
+               I2C_ACTIVE
+
+               The code necessary to make the I2C data line active
+               (driven).  If the data line is open collector, this
+               define can be null.
+
+               I2C_TRISTATE
+
+               The code necessary to make the I2C data line tri-stated
+               (inactive).  If the data line is open collector, this
+               define can be null.
+
+               I2C_READ
+
+               Code that returns TRUE if the I2C data line is high,
+               FALSE if it is low.
+
+               I2C_SDA(bit)
+
+               If <bit> is TRUE, sets the I2C data line high. If it
+               is FALSE, it clears it (low).
+
+               I2C_SCL(bit)
+
+               If <bit> is TRUE, sets the I2C clock line high. If it
+               is FALSE, it clears it (low).
+
+               I2C_DELAY
+
+               This delay is invoked four times per clock cycle so this
+               controls the rate of data transfer.  The data rate thus
+               is 1 / (I2C_DELAY * 4).
+
+- SPI Support: CONFIG_SPI
+
+               Enables SPI driver (so far only tested with
+               SPI EEPROM, also an instance works with Crystal A/D and
+               D/As on the SACSng board)
+
+               CONFIG_SPI_X
+
+               Enables extended (16-bit) SPI EEPROM addressing.
+               (symmetrical to CONFIG_I2C_X)
+
+               CONFIG_SOFT_SPI
+
+                Enables a software (bit-bang) SPI driver rather than
+                using hardware support. This is a general purpose
+                driver that only requires three general I/O port pins
+                (two outputs, one input) to function. If this is
+                defined, the board configuration must define several
+                SPI configuration items (port pins to use, etc). For
+                an example, see include/configs/sacsng.h.
+
+- FPGA Support: CONFIG_FPGA_COUNT
+
+                Specify the number of FPGA devices to support.
+
+                CONFIG_FPGA
+
+                Used to specify the types of FPGA devices. For
+               example,
+               #define CONFIG_FPGA  CFG_XILINX_VIRTEX2
+
+               CFG_FPGA_PROG_FEEDBACK
+
+                Enable printing of hash marks during FPGA
+               configuration.
+
+               CFG_FPGA_CHECK_BUSY
+
+                Enable checks on FPGA configuration interface busy
+                status by the configuration function. This option
+                will require a board or device specific function to
+                be written.
+
+               CONFIG_FPGA_DELAY
+
+                If defined, a function that provides delays in the
+                FPGA configuration driver.
+
+               CFG_FPGA_CHECK_CTRLC
+
+               Allow Control-C to interrupt FPGA configuration
+
+               CFG_FPGA_CHECK_ERROR
+
+                Check for configuration errors during FPGA bitfile
+                loading. For example, abort during Virtex II
+                configuration if the INIT_B line goes low (which
+                indicated a CRC error).
+
+               CFG_FPGA_WAIT_INIT
+
+                Maximum time to wait for the INIT_B line to deassert
+                after PROB_B has been deasserted during a Virtex II
+                FPGA configuration sequence. The default time is 500 mS.
+
+               CFG_FPGA_WAIT_BUSY
+
+                Maximum time to wait for BUSY to deassert during
+                Virtex II FPGA configuration. The default is 5 mS.
+
+               CFG_FPGA_WAIT_CONFIG
+
+                Time to wait after FPGA configuration. The default is
+               200 mS.
+
+- FPGA Support:        CONFIG_FPGA_COUNT
+
+               Specify the number of FPGA devices to support.
+
+               CONFIG_FPGA
+
+               Used to specify the types of FPGA devices.  For example,
+               #define CONFIG_FPGA  CFG_XILINX_VIRTEX2
+
+               CFG_FPGA_PROG_FEEDBACK
+
+               Enable printing of hash marks during FPGA configuration.
+
+               CFG_FPGA_CHECK_BUSY
+
+                Enable checks on FPGA configuration interface busy
+                status by the configuration function. This option
+                will require a board or device specific function to
+                be written.
+
+               CONFIG_FPGA_DELAY
+
+               If defined, a function that provides delays in the FPGA
+               configuration driver.
+
+               CFG_FPGA_CHECK_CTRLC
+               Allow Control-C to interrupt FPGA configuration
+
+               CFG_FPGA_CHECK_ERROR
+
+                Check for configuration errors during FPGA bitfile
+                loading. For example, abort during Virtex II
+                configuration if the INIT_B line goes low (which
+                indicated a CRC error).
+
+               CFG_FPGA_WAIT_INIT
+
+                Maximum time to wait for the INIT_B line to deassert
+                after PROB_B has been deasserted during a Virtex II
+                FPGA configuration sequence. The default time is 500
+                mS.
+
+               CFG_FPGA_WAIT_BUSY
+
+                Maximum time to wait for BUSY to deassert during
+                Virtex II FPGA configuration. The default is 5 mS.
+
+               CFG_FPGA_WAIT_CONFIG
+
+                Time to wait after FPGA configuration. The default is
+                200 mS.
+
+- Configuration Management:
+               CONFIG_IDENT_STRING
+
+                If defined, this string will be added to the U-Boot
+                version information (U_BOOT_VERSION)
+
+- Vendor Parameter Protection:
+
+                U-Boot considers the values of the environment
+                variables "serial#" (Board Serial Number) and
+                "ethaddr" (Ethernet Address) to bb parameters that
+                are set once by the board vendor / manufacturer, and
+                protects these variables from casual modification by
+                the user. Once set, these variables are read-only,
+                and write or delete attempts are rejected. You can
+                change this behviour:
+
+               If CONFIG_ENV_OVERWRITE is #defined in your config
+               file, the write protection for vendor parameters is
+               completely disabled. Anybody can change or delte
+               these parameters.
+
+               Alternatively, if you #define _both_ CONFIG_ETHADDR
+               _and_ CONFIG_OVERWRITE_ETHADDR_ONCE, a default
+               ethernet address is installed in the environment,
+               which can be changed exactly ONCE by the user. [The
+               serial# is unaffected by this, i. e. it remains
+               read-only.]
+
+- Protected RAM:
+               CONFIG_PRAM
+
+               Define this variable to enable the reservation of
+               "protected RAM", i. e. RAM which is not overwritten
+               by U-Boot. Define CONFIG_PRAM to hold the number of
+               kB you want to reserve for pRAM. You can overwrite
+               this default value by defining an environment
+               variable "pram" to the number of kB you want to
+               reserve. Note that the board info structure will
+               still show the full amount of RAM. If pRAM is
+               reserved, a new environment variable "mem" will
+               automatically be defined to hold the amount of
+               remaining RAM in a form that can be passed as boot
+               argument to Linux, for instance like that:
+
+                       setenv bootargs ... mem=\$(mem)
+                       saveenv
+
+               This way you can tell Linux not to use this memory,
+               either, which results in a memory region that will
+               not be affected by reboots.
+
+               *WARNING* If your board configuration uses automatic
+               detection of the RAM size, you must make sure that
+               this memory test is non-destructive. So far, the
+               following board configurations are known to be
+               "pRAM-clean":
+
+                       ETX094, IVMS8, IVML24, SPD8xx, TQM8xxL,
+                       HERMES, IP860, RPXlite, LWMON, LANTEC,
+                       PCU_E, FLAGADM, TQM8260
+
+- Error Recovery:
+               CONFIG_PANIC_HANG
+
+               Define this variable to stop the system in case of a
+               fatal error, so that you have to reset it manually.
+               This is probably NOT a good idea for an embedded
+               system where you want to system to reboot
+               automatically as fast as possible, but it may be
+               useful during development since you can try to debug
+               the conditions that lead to the situation.
+
+               CONFIG_NET_RETRY_COUNT
+
+                This variable defines the number of retries for
+                network operations like ARP, RARP, TFTP, or BOOTP
+                before giving up the operation. If not defined, a
+                default value of 5 is used.
+
+- Command Interpreter:
+               CFG_HUSH_PARSER
+
+               Define this variable to enable the "hush" shell (from
+               Busybox) as command line interpreter, thus enabling
+               powerful command line syntax like
+               if...then...else...fi conditionals or `&&' and '||'
+               constructs ("shell scripts").
+
+               If undefined, you get the old, much simpler behaviour
+               with a somewhat smaller memory footprint.
+
+
+               CFG_PROMPT_HUSH_PS2
+
+               This defines the secondary prompt string, which is
+               printed when the command interpreter needs more input
+               to complete a command. Usually "> ".
+
+       Note:
+
+                In the current implementation, the local variables
+                space and global environment variables space are
+                separated. Local variables are those you define by
+                simply typing like `name=value'. To access a local
+                variable later on, you have write `$name' or
+                `${name}'; variable directly by typing say `$name' at
+                the command prompt.
+
+                Global environment variables are those you use
+                setenv/printenv to work with. To run a command stored
+                in such a variable, you need to use the run command,
+                and you must not use the '$' sign to access them.
+
+               To store commands and special characters in a
+               variable, please use double quotation marks
+               surrounding the whole text of the variable, instead
+               of the backslashes before semicolons and special
+               symbols.
+
+- Default Environment
+               CONFIG_EXTRA_ENV_SETTINGS
+
+                Define this to contain any number of null terminated
+                strings (variable = value pairs) that will be part of
+                the default enviroment compiled into the boot image.
+                For example, place something like this in your
+                board's config file:
+
+               #define CONFIG_EXTRA_ENV_SETTINGS \
+                       "myvar1=value1\0" \
+                       "myvar2=value2\0"
+
+                Warning: This method is based on knowledge about the
+                internal format how the environment is stored by the
+                U-Boot code. This is NOT an official, expoerted
+                interface! Although it is unlikely that this format
+                will change soon, there is no guarantee either.
+               You better know what you are doing here.
+
+                Note: overly (ab)use of the default environment is
+                discouraged. Make sure to check other ways to preset
+                the environment like the autoscript function or the
+                boot command first.
+
+- Show boot progress
+               CONFIG_SHOW_BOOT_PROGRESS
+
+                Defining this option allows to add some board-
+                specific code (calling a user-provided function
+                "show_boot_progress(int)") that enables you to show
+                the system's boot progress on some display (for
+                example, some LED's) on your board. At the moment,
+                the following checkpoints are implemented:
+
+  Arg  Where                   When
+    1  common/cmd_bootm.c      before attempting to boot an image
+   -1  common/cmd_bootm.c      Image header has bad     magic number
+    2  common/cmd_bootm.c      Image header has correct magic number
+   -2  common/cmd_bootm.c      Image header has bad     checksum
+    3  common/cmd_bootm.c      Image header has correct checksum
+   -3  common/cmd_bootm.c      Image data   has bad     checksum
+    4  common/cmd_bootm.c      Image data   has correct checksum
+   -4  common/cmd_bootm.c      Image is for unsupported architecture
+    5  common/cmd_bootm.c      Architecture check OK
+   -5  common/cmd_bootm.c      Wrong Image Type (not kernel, multi, standalone)
+    6  common/cmd_bootm.c      Image Type check OK
+   -6  common/cmd_bootm.c      gunzip uncompression error
+   -7  common/cmd_bootm.c      Unimplemented compression type
+    7  common/cmd_bootm.c      Uncompression OK
+   -8  common/cmd_bootm.c      Wrong Image Type (not kernel, multi, standalone)
+    8  common/cmd_bootm.c      Image Type check OK
+   -9  common/cmd_bootm.c      Unsupported OS (not Linux, BSD, VxWorks, QNX)
+    9  common/cmd_bootm.c      Start initial ramdisk verification
+  -10  common/cmd_bootm.c      Ramdisk header has bad     magic number
+  -11  common/cmd_bootm.c      Ramdisk header has bad     checksum
+   10  common/cmd_bootm.c      Ramdisk header is OK
+  -12  common/cmd_bootm.c      Ramdisk data   has bad     checksum
+   11  common/cmd_bootm.c      Ramdisk data   has correct checksum
+   12  common/cmd_bootm.c      Ramdisk verification complete, start loading
+  -13  common/cmd_bootm.c      Wrong Image Type (not PPC Linux Ramdisk)
+   13  common/cmd_bootm.c      Start multifile image verification
+   14  common/cmd_bootm.c      No initial ramdisk, no multifile, continue.
+   15  common/cmd_bootm.c      All preparation done, transferring control to OS
+
+   -1  common/cmd_doc.c        Bad usage of "doc" command
+   -1  common/cmd_doc.c        No boot device
+   -1  common/cmd_doc.c        Unknown Chip ID on boot device
+   -1  common/cmd_doc.c        Read Error on boot device
+   -1  common/cmd_doc.c        Image header has bad magic number
+
+   -1  common/cmd_ide.c        Bad usage of "ide" command
+   -1  common/cmd_ide.c        No boot device
+   -1  common/cmd_ide.c        Unknown boot device
+   -1  common/cmd_ide.c        Unknown partition table
+   -1  common/cmd_ide.c        Invalid partition type
+   -1  common/cmd_ide.c        Read Error on boot device
+   -1  common/cmd_ide.c        Image header has bad magic number
+
+   -1  common/cmd_nvedit.c     Environment not changable, but has bad CRC
+
+
+Modem Support:
+--------------
+
+[so far only for SMDK2400 board]
+
+- Modem support endable:
+               CONFIG_MODEM_SUPPORT
+
+- RTS/CTS Flow control enable:
+               CONFIG_HWFLOW
+
+- Modem debug support:
+               CONFIG_MODEM_SUPPORT_DEBUG
+
+                Enables debugging stuff (char screen[1024], dbg())
+                for modem support. Useful only with BDI2000.
+
+- General:
+
+                In the target system modem support is enabled when a
+                specific key (key combination) is pressed during
+                power-on. Otherwise U-Boot will boot normally
+                (autoboot). The key_pressed() fuction is called from
+                board_init(). Currently key_pressed() is a dummy
+                function, returning 1 and thus enabling modem
+                initialization.
+
+                If there are no modem init strings in the
+                environment, U-Boot proceed to autoboot; the
+                previous output (banner, info printfs) will be
+                supressed, though.
+
+               See also: doc/README.Modem
+
+
+
+
+Configuration Settings:
+-----------------------
+
+- CFG_LONGHELP: Defined when you want long help messages included;
+               undefine this when you're short of memory.
+
+- CFG_PROMPT:  This is what U-Boot prints on the console to
+               prompt for user input.
+
+- CFG_CBSIZE:  Buffer size for input from the Console
+
+- CFG_PBSIZE:  Buffer size for Console output
+
+- CFG_MAXARGS: max. Number of arguments accepted for monitor commands
+
+- CFG_BARGSIZE: Buffer size for Boot Arguments which are passed to
+               the application (usually a Linux kernel) when it is
+               booted
+
+- CFG_BAUDRATE_TABLE:
+               List of legal baudrate settings for this board.
+
+- CFG_CONSOLE_INFO_QUIET
+               Suppress display of console information at boot.
+
+- CFG_CONSOLE_IS_IN_ENV
+               If the board specific function
+                       extern int overwrite_console (void);
+               returns 1, the stdin, stderr and stdout are switched to the
+               serial port, else the settings in the environment are used.
+
+- CFG_CONSOLE_OVERWRITE_ROUTINE
+               Enable the call to overwrite_console().
+
+- CFG_CONSOLE_ENV_OVERWRITE
+               Enable overwrite of previous console environment settings.
+
+- CFG_MEMTEST_START, CFG_MEMTEST_END:
+               Begin and End addresses of the area used by the
+               simple memory test.
+
+- CFG_ALT_MEMTEST:
+               Enable an alternate, more extensive memory test.
+
+- CFG_TFTP_LOADADDR:
+               Default load address for network file downloads
+
+- CFG_LOADS_BAUD_CHANGE:
+               Enable temporary baudrate change while serial download
+
+- CFG_SDRAM_BASE:
+               Physical start address of SDRAM. _Must_ be 0 here.
+
+- CFG_MBIO_BASE:
+               Physical start address of Motherboard I/O (if using a
+               Cogent motherboard)
+
+- CFG_FLASH_BASE:
+               Physical start address of Flash memory.
+
+- CFG_MONITOR_BASE:
+               Physical start address of boot monitor code (set by
+               make config files to be same as the text base address
+               (TEXT_BASE) used when linking) - same as
+               CFG_FLASH_BASE when booting from flash.
+
+- CFG_MONITOR_LEN:
+               Size of memory reserved for monitor code
+
+- CFG_MALLOC_LEN:
+               Size of DRAM reserved for malloc() use.
+
+- CFG_BOOTMAPSZ:
+               Maximum size of memory mapped by the startup code of
+               the Linux kernel; all data that must be processed by
+               the Linux kernel (bd_info, boot arguments, eventually
+               initrd image) must be put below this limit.
+
+- CFG_MAX_FLASH_BANKS:
+               Max number of Flash memory banks
+
+- CFG_MAX_FLASH_SECT:
+               Max number of sectors on a Flash chip
+
+- CFG_FLASH_ERASE_TOUT:
+               Timeout for Flash erase operations (in ms)
+
+- CFG_FLASH_WRITE_TOUT:
+               Timeout for Flash write operations (in ms)
+
+- CFG_DIRECT_FLASH_TFTP:
+
+               Enable TFTP transfers directly to flash memory;
+               without this option such a download has to be
+               performed in two steps: (1) download to RAM, and (2)
+               copy from RAM to flash.
+
+               The two-step approach is usually more reliable, since
+               you can check if the download worked before you erase
+               the flash, but in some situations (when sytem RAM is
+               too limited to allow for a tempory copy of the
+               downloaded image) this option may be very useful.
+
+- CFG_FLASH_CFI:
+                Define if the flash driver uses extra elements in the
+                common flash structure for storing flash geometry
+
+The following definitions that deal with the placement and management
+of environment data (variable area); in general, we support the
+following configurations:
+
+- CFG_ENV_IS_IN_FLASH:
+
+       Define this if the environment is in flash memory.
+
+       a) The environment occupies one whole flash sector, which is
+          "embedded" in the text segment with the U-Boot code. This
+          happens usually with "bottom boot sector" or "top boot
+          sector" type flash chips, which have several smaller
+          sectors at the start or the end. For instance, such a
+          layout can have sector sizes of 8, 2x4, 16, Nx32 kB. In
+          such a case you would place the environment in one of the
+          4 kB sectors - with U-Boot code before and after it. With
+          "top boot sector" type flash chips, you would put the
+          environment in one of the last sectors, leaving a gap
+          between U-Boot and the environment.
+
+       - CFG_ENV_OFFSET:
+
+          Offset of environment data (variable area) to the
+          beginning of flash memory; for instance, with bottom boot
+          type flash chips the second sector can be used: the offset
+          for this sector is given here.
+
+          CFG_ENV_OFFSET is used relative to CFG_FLASH_BASE.
+
+       - CFG_ENV_ADDR:
+
+          This is just another way to specify the start address of
+          the flash sector containing the environment (instead of
+          CFG_ENV_OFFSET).
+
+       - CFG_ENV_SECT_SIZE:
+
+          Size of the sector containing the environment.
+
+
+       b) Sometimes flash chips have few, equal sized, BIG sectors.
+          In such a case you don't want to spend a whole sector for
+          the environment.
+
+       - CFG_ENV_SIZE:
+
+          If you use this in combination with CFG_ENV_IS_IN_FLASH
+          and CFG_ENV_SECT_SIZE, you can specify to use only a part
+          of this flash sector for the environment. This saves
+          memory for the RAM copy of the environment.
+
+          It may also save flash memory if you decide to use this
+          when your environment is "embedded" within U-Boot code,
+          since then the remainder of the flash sector could be used
+          for U-Boot code. It should be pointed out that this is
+          STRONGLY DISCOURAGED from a robustness point of view:
+          updating the environment in flash makes it always
+          necessary to erase the WHOLE sector. If something goes
+          wrong before the contents has been restored from a copy in
+          RAM, your target system will be dead.
+
+       - CFG_ENV_ADDR_REDUND
+         CFG_ENV_SIZE_REDUND
+
+           These settings describe a second storage area used to hold
+           a redundand copy of the environment data, so that there is
+           a valid backup copy in case there is a power failur during
+           a "saveenv" operation.
+
+BE CAREFUL! Any changes to the flash layout, and some changes to the
+source code will make it necessary to adapt <board>/u-boot.lds*
+accordingly!
+
+
+- CFG_ENV_IS_IN_NVRAM:
+
+       Define this if you have some non-volatile memory device
+       (NVRAM, battery buffered SRAM) which you want to use for the
+       environment.
+
+       - CFG_ENV_ADDR:
+       - CFG_ENV_SIZE:
+
+         These two #defines are used to determin the memory area you
+         want to use for environment. It is assumed that this memory
+         can just be read and written to, without any special
+         provision.
+
+BE CAREFUL! The first access to the environment happens quite early
+in U-Boot initalization (when we try to get the setting of for the
+console baudrate). You *MUST* have mappend your NVRAM area then, or
+U-Boot will hang.
+
+Please note that even with NVRAM we still use a copy of the
+environment in RAM: we could work on NVRAM directly, but we want to
+keep settings there always unmodified except somebody uses "saveenv"
+to save the current settings.
+
+
+- CFG_ENV_IS_IN_EEPROM:
+
+       Use this if you have an EEPROM or similar serial access
+       device and a driver for it.
+
+       - CFG_ENV_OFFSET:
+       - CFG_ENV_SIZE:
+
+         These two #defines specify the offset and size of the
+         environment area within the total memory of your EEPROM.
+
+       - CFG_I2C_EEPROM_ADDR:
+         If defined, specified the chip address of the EEPROM device.
+         The default address is zero.
+
+       - CFG_EEPROM_PAGE_WRITE_BITS:
+         If defined, the number of bits used to address bytes in a
+         single page in the EEPROM device.  A 64 byte page, for example
+         would require six bits.
+
+       - CFG_EEPROM_PAGE_WRITE_DELAY_MS:
+         If defined, the number of milliseconds to delay between
+         page writes.  The default is zero milliseconds.
+
+       - CFG_I2C_EEPROM_ADDR_LEN:
+         The length in bytes of the EEPROM memory array address.  Note
+         that this is NOT the chip address length!
+
+       - CFG_EEPROM_SIZE:
+         The size in bytes of the EEPROM device.
+
+       - CFG_I2C_EEPROM_ADDR:
+         If defined, specified the chip address of the EEPROM device.
+         The default address is zero.
+
+       - CFG_EEPROM_PAGE_WRITE_BITS:
+         If defined, the number of bits used to address bytes in a
+         single page in the EEPROM device.  A 64 byte page, for example
+         would require six bits.
+
+       - CFG_EEPROM_PAGE_WRITE_DELAY_MS:
+         If defined, the number of milliseconds to delay between
+         page writes.  The default is zero milliseconds.
+
+       - CFG_I2C_EEPROM_ADDR_LEN:
+         The length in bytes of the EEPROM memory array address.  Note
+         that this is NOT the chip address length!
+
+       - CFG_EEPROM_SIZE:
+         The size in bytes of the EEPROM device.
+
+- CFG_SPI_INIT_OFFSET
+
+       Defines offset to the initial SPI buffer area in DPRAM. The
+       area is used at an early stage (ROM part) if the environment
+       is configured to reside in the SPI EEPROM: We need a 520 byte
+       scratch DPRAM area. It is used between the two initialization
+       calls (spi_init_f() and spi_init_r()). A value of 0xB00 seems
+       to be a good choice since it makes it far enough from the
+       start of the data area as well as from the stack pointer.
+
+Please note that the environment is read-only as long as the monitor
+has been relocated to RAM and a RAM copy of the environment has been
+created; also, when using EEPROM you will have to use getenv_r()
+until then to read environment variables.
+
+The environment is now protected by a CRC32 checksum. Before the
+monitor is relocated into RAM, as a result of a bad CRC you will be
+working with the compiled-in default environment - *silently*!!!
+[This is necessary, because the first environment variable we need is
+the "baudrate" setting for the console - if we have a bad CRC, we
+don't have any device yet where we could complain.]
+
+Note: once the monitor has been relocated, then it will complain if
+the default environment is used; a new CRC is computed as soon as you
+use the "setenv" command to modify / delete / add any environment
+variable [even when you try to delete a non-existing variable!].
+
+Note2: you must edit your u-boot.lds file to reflect this
+configuration.
+
+
+Many of the options are named exactly as the corresponding Linux
+kernel configuration options. The intention is to make it easier to
+build a config tool - later.
+
+Low Level (hardware related) configuration options:
+
+- CFG_CACHELINE_SIZE:
+               Cache Line Size of the CPU.
+
+- CFG_DEFAULT_IMMR:
+               Default address of the IMMR after system reset.
+               Needed on some 8260 systems (MPC8260ADS and RPXsuper)
+               to be able to adjust the position of the IMMR
+               register after a reset.
+
+- CFG_IMMR:    Physical address of the Internal Memory Mapped
+               Register; DO NOT CHANGE! (11-4)
+               [MPC8xx systems only]
+
+- CFG_INIT_RAM_ADDR:
+
+               Start address of memory area tha can be used for
+               initial data and stack; please note that this must be
+               writable memory that is working WITHOUT special
+               initialization, i. e. you CANNOT use normal RAM which
+               will become available only after programming the
+               memory controller and running certain initialization
+               sequences.
+
+               U-Boot uses the following memory types:
+               - MPC8xx and MPC8260: IMMR (internal memory of the CPU)
+               - MPC824X: data cache
+               - PPC4xx:  data cache
+
+- CFG_INIT_DATA_OFFSET:
+
+               Offset of the initial data structure in the memory
+               area defined by CFG_INIT_RAM_ADDR. Usually
+               CFG_INIT_DATA_OFFSET is chosen such that the initial
+               data is located at the end of the available space
+               (sometimes written as (CFG_INIT_RAM_END -
+               CFG_INIT_DATA_SIZE), and the initial stack is just
+               below that area (growing from (CFG_INIT_RAM_ADDR +
+               CFG_INIT_DATA_OFFSET) downward.
+
+       Note:
+               On the MPC824X (or other systems that use the data
+               cache for initial memory) the address chosen for
+               CFG_INIT_RAM_ADDR is basically arbitrary - it must
+               point to an otherwise UNUSED address space between
+               the top of RAM and the start of the PCI space.
+
+- CFG_SIUMCR:  SIU Module Configuration (11-6)
+
+- CFG_SYPCR:   System Protection Control (11-9)
+
+- CFG_TBSCR:   Time Base Status and Control (11-26)
+
+- CFG_PISCR:   Periodic Interrupt Status and Control (11-31)
+
+- CFG_PLPRCR:  PLL, Low-Power, and Reset Control Register (15-30)
+
+- CFG_SCCR:    System Clock and reset Control Register (15-27)
+
+- CFG_OR_TIMING_SDRAM:
+               SDRAM timing
+
+- CFG_MAMR_PTA:
+               periodic timer for refresh
+
+- CFG_DER:     Debug Event Register (37-47)
+
+- FLASH_BASE0_PRELIM, FLASH_BASE1_PRELIM, CFG_REMAP_OR_AM,
+  CFG_PRELIM_OR_AM, CFG_OR_TIMING_FLASH, CFG_OR0_REMAP,
+  CFG_OR0_PRELIM, CFG_BR0_PRELIM, CFG_OR1_REMAP, CFG_OR1_PRELIM,
+  CFG_BR1_PRELIM:
+               Memory Controller Definitions: BR0/1 and OR0/1 (FLASH)
+
+- SDRAM_BASE2_PRELIM, SDRAM_BASE3_PRELIM, SDRAM_MAX_SIZE,
+  CFG_OR_TIMING_SDRAM, CFG_OR2_PRELIM, CFG_BR2_PRELIM,
+  CFG_OR3_PRELIM, CFG_BR3_PRELIM:
+               Memory Controller Definitions: BR2/3 and OR2/3 (SDRAM)
+
+- CFG_MAMR_PTA, CFG_MPTPR_2BK_4K, CFG_MPTPR_1BK_4K, CFG_MPTPR_2BK_8K,
+  CFG_MPTPR_1BK_8K, CFG_MAMR_8COL, CFG_MAMR_9COL:
+               Machine Mode Register and Memory Periodic Timer
+               Prescaler definitions (SDRAM timing)
+
+- CFG_I2C_UCODE_PATCH, CFG_I2C_DPMEM_OFFSET [0x1FC0]:
+               enable I2C microcode relocation patch (MPC8xx);
+               define relocation offset in DPRAM [DSP2]
+
+- CFG_SPI_UCODE_PATCH, CFG_SPI_DPMEM_OFFSET [0x1FC0]:
+               enable SPI microcode relocation patch (MPC8xx);
+               define relocation offset in DPRAM [SCC4]
+
+- CFG_USE_OSCCLK:
+               Use OSCM clock mode on MBX8xx board. Be careful,
+               wrong setting might damage your board. Read
+               doc/README.MBX before setting this variable!
+
+Building the Software:
+======================
+
+Building U-Boot has been tested in native PPC environments (on a
+PowerBook G3 running LinuxPPC 2000) and in cross environments
+(running RedHat 6.x and 7.x Linux on x86, Solaris 2.6 on a SPARC, and
+NetBSD 1.5 on x86).
+
+If you are not using a native PPC environment, it is assumed that you
+have the GNU cross compiling tools available in your path and named
+with a prefix of "powerpc-linux-". If this is not the case, (e.g. if
+you are using Monta Vista's Hard Hat Linux CDK 1.2) you must change
+the definition of CROSS_COMPILE in Makefile. For HHL on a 4xx CPU,
+change it to:
+
+       CROSS_COMPILE = ppc_4xx-
+
+
+U-Boot is intended to be  simple  to  build.  After  installing  the
+sources         you must configure U-Boot for one specific board type. This
+is done by typing:
+
+       make NAME_config
+
+where "NAME_config" is the name of one of the existing
+configurations; the following names are supported:
+
+    ADCIOP_config        GTH_config            TQM850L_config
+    ADS860_config        IP860_config          TQM855L_config
+    AR405_config         IVML24_config         TQM860L_config
+    CANBT_config         IVMS8_config          WALNUT405_config
+    CPCI405_config       LANTEC_config         cogent_common_config
+    CPCIISER4_config     MBX_config            cogent_mpc8260_config
+    CU824_config         MBX860T_config        cogent_mpc8xx_config
+    ESTEEM192E_config    RPXlite_config        hermes_config
+    ETX094_config        RPXsuper_config       hymod_config
+    FADS823_config       SM850_config          lwmon_config
+    FADS850SAR_config    SPD823TS_config       pcu_e_config
+    FADS860T_config      SXNI855T_config       rsdproto_config
+    FPS850L_config       Sandpoint8240_config  sbc8260_config
+    GENIETV_config       TQM823L_config        PIP405_config
+    GEN860T_config       EBONY_config
+
+Note: for some board special configuration names may exist; check  if
+      additional  information is available from the board vendor; for
+      instance, the TQM8xxL systems run normally at 50 MHz and use  a
+      SCC  for 10baseT  ethernet; there are also systems with 80 MHz
+      CPU clock, and an optional Fast Ethernet module  is  available
+      for  CPU's  with FEC. You can select such additional "features"
+      when chosing the configuration, i. e.
+
+      make TQM860L_config
+       - will configure for a plain TQM860L, i. e. 50MHz, no FEC
+
+      make TQM860L_FEC_config
+       - will configure for a TQM860L at 50MHz with FEC for ethernet
+
+      make TQM860L_80MHz_config
+       - will configure for a TQM860L at 80 MHz, with normal 10baseT
+         interface
+
+      make TQM860L_FEC_80MHz_config
+       - will configure for a TQM860L at 80 MHz with FEC for ethernet
+
+      make TQM823L_LCD_config
+       - will configure for a TQM823L with U-Boot console on LCD
+
+      make TQM823L_LCD_80MHz_config
+       - will configure for a TQM823L at 80 MHz with U-Boot console on LCD
+
+      etc.
+
+
+
+Finally, type "make all", and you should  get  some  working  U-Boot
+images ready for downlod to / installation on your system:
+
+- "u-boot.bin" is a raw binary image
+- "u-boot" is an image in ELF binary format
+- "u-boot.srec" is in Motorola S-Record format
+
+
+Please be aware that the Makefiles assume you are using GNU make, so
+for instance on NetBSD you might need to use "gmake" instead of
+native "make".
+
+
+If the system board that you have is not listed, then you will need
+to port U-Boot to your hardware platform. To do this, follow these
+steps:
+
+1.  Add a new configuration option for your board to the toplevel
+    "Makefile", using the existing entries as examples.
+2.  Create a new directory to hold your board specific code. Add any
+    files you need.
+3.  If you're porting U-Boot to a new CPU, then also create a new
+    directory to hold your CPU specific code. Add any files you need.
+4.  Run "make config_name" with your new name.
+5.  Type "make", and you should get a working "u-boot.srec" file
+    to be installed on your target system.
+    [Of course, this last step is much harder than it sounds.]
+
+
+Testing of U-Boot Modifications, Ports to New Hardware, etc.:
+==============================================================
+
+If you have modified U-Boot sources (for instance added a new  board
+or  support  for  new  devices,         a new CPU, etc.) you are expected to
+provide feedback to the other developers. The feedback normally takes
+the form of a "patch", i. e. a context diff against a certain (latest
+official or latest in CVS) version of U-Boot sources.
+
+But before you submit such a patch, please verify that your  modifi-
+cation did not break existing code. At least make sure that *ALL* of
+the supported boards compile WITHOUT ANY compiler warnings. To do so,
+just run the "MAKEALL" script, which will configure and build U-Boot
+for ALL supported system. Be warned, this will take a while. You  can
+select which  (cross)  compiler  to use py passing a `CROSS_COMPILE'
+environment variable to the script, i. e. to use the cross tools from
+MontaVista's Hard Hat Linux you can type
+
+       CROSS_COMPILE=ppc_8xx- MAKEALL
+
+or to build on a native PowerPC system you can type
+
+       CROSS_COMPILE=' ' MAKEALL
+
+See also "U-Boot Porting Guide" below.
+
+
+
+Monitor Commands - Overview:
+============================
+
+go     - start application at address 'addr'
+run    - run commands in an environment variable
+bootm  - boot application image from memory
+bootp  - boot image via network using BootP/TFTP protocol
+tftpboot- boot image via network using TFTP protocol
+              and env variables "ipaddr" and "serverip"
+              (and eventually "gatewayip")
+rarpboot- boot image via network using RARP/TFTP protocol
+diskboot- boot from IDE devicebootd   - boot default, i.e., run 'bootcmd'
+loads  - load S-Record file over serial line
+loadb  - load binary file over serial line (kermit mode)
+md     - memory display
+mm     - memory modify (auto-incrementing)
+nm     - memory modify (constant address)
+mw     - memory write (fill)
+cp     - memory copy
+cmp    - memory compare
+crc32  - checksum calculation
+imd     - i2c memory display
+imm     - i2c memory modify (auto-incrementing)
+inm     - i2c memory modify (constant address)
+imw     - i2c memory write (fill)
+icrc32  - i2c checksum calculation
+iprobe  - probe to discover valid I2C chip addresses
+iloop   - infinite loop on address range
+isdram  - print SDRAM configuration information
+sspi    - SPI utility commands
+base   - print or set address offset
+printenv- print environment variables
+setenv - set environment variables
+saveenv - save environment variables to persistent storage
+protect - enable or disable FLASH write protection
+erase  - erase FLASH memory
+flinfo - print FLASH memory information
+bdinfo - print Board Info structure
+iminfo - print header information for application image
+coninfo - print console devices and informations
+ide    - IDE sub-system
+loop   - infinite loop on address range
+mtest  - simple RAM test
+icache - enable or disable instruction cache
+dcache - enable or disable data cache
+reset  - Perform RESET of the CPU
+echo   - echo args to console
+version - print monitor version
+help   - print online help
+?      - alias for 'help'
+
+
+Monitor Commands - Detailed Description:
+========================================
+
+TODO.
+
+For now: just type "help <command>".
+
+
+Environment Variables:
+======================
+
+U-Boot supports user configuration using Environment Variables which
+can be made persistent by saving to Flash memory.
+
+Environment Variables are set using "setenv", printed using
+"printenv", and saved to Flash using "saveenv". Using "setenv"
+without a value can be used to delete a variable from the
+environment. As long as you don't save the environment you are
+working with an in-memory copy. In case the Flash area containing the
+environment is erased by accident, a default environment is provided.
+
+Some configuration options can be set using Environment Variables:
+
+  baudrate     - see CONFIG_BAUDRATE
+
+  bootdelay    - see CONFIG_BOOTDELAY
+
+  bootcmd      - see CONFIG_BOOTCOMMAND
+
+  bootargs     - Boot arguments when booting an RTOS image
+
+  bootfile     - Name of the image to load with TFTP
+
+  autoload     - if set to "no" (any string beginning with 'n'),
+                 "bootp" will just load perform a lookup of the
+                 configuration from the BOOTP server, but not try to
+                 load any image using TFTP
+
+  autostart    - if set to "yes", an image loaded using the "bootp",
+                 "rarpboot", "tftpboot" or "diskboot" commands will
+                 be automatically started (by internally calling
+                 "bootm")
+
+  initrd_high  - restrict positioning of initrd images:
+                 If this variable is not set, initrd images will be
+                 copied to the highest possible address in RAM; this
+                 is usually what you want since it allows for
+                 maximum initrd size. If for some reason you want to
+                 make sure that the initrd image is loaded below the
+                 CFG_BOOTMAPSZ limit, you can set this environment
+                 variable to a value of "no" or "off" or "0".
+                 Alternatively, you can set it to a maximum upper
+                 address to use (U-Boot will still check that it
+                 does not overwrite the U-Boot stack and data).
+
+                 For instance, when you have a system with 16 MB
+                 RAM, and want to reseve 4 MB from use by Linux,
+                 you can do this by adding "mem=12M" to the value of
+                 the "bootargs" variable. However, now you must make
+                 sure, that the initrd image is placed in the first
+                 12 MB as well - this can be done with
+
+                 setenv initrd_high 00c00000
+
+  ipaddr       - IP address; needed for tftpboot command
+
+  loadaddr     - Default load address for commands like "bootp",
+                 "rarpboot", "tftpboot" or "diskboot"
+
+  loads_echo   - see CONFIG_LOADS_ECHO
+
+  serverip     - TFTP server IP address; needed for tftpboot command
+
+  bootretry    - see CONFIG_BOOT_RETRY_TIME
+
+  bootdelaykey - see CONFIG_AUTOBOOT_DELAY_STR
+
+  bootstopkey  - see CONFIG_AUTOBOOT_STOP_STR
+
+
+The following environment variables may be used and automatically
+updated by the network boot commands ("bootp" and "rarpboot"),
+depending the information provided by your boot server:
+
+  bootfile     - see above
+  dnsip                - IP address of your Domain Name Server
+  gatewayip    - IP address of the Gateway (Router) to use
+  hostname     - Target hostname
+  ipaddr       - see above
+  netmask      - Subnet Mask
+  rootpath     - Pathname of the root filesystem on the NFS server
+  serverip     - see above
+
+
+There are two special Environment Variables:
+
+  serial#      - contains hardware identification information such
+                 as type string and/or serial number
+  ethaddr      - Ethernet address
+
+These variables can be set only once (usually during manufacturing of
+the board). U-Boot refuses to delete or overwrite these variables
+once they have been set once.
+
+
+Please note that changes to some configuration parameters may take
+only effect after the next boot (yes, that's just like Windoze :-).
+
+
+Note for Redundant Ethernet Interfaces:
+=======================================
+
+Some boards come with redundand ethernet interfaces; U-Boot supports
+such configurations and is capable of automatic selection of a
+"working" interface when needed. MAC assignemnt works as follows:
+
+Network interfaces are numbered eth0, eth1, eth2, ... Corresponding
+MAC addresses can be stored in the environment as "ethaddr" (=>eth0),
+"eth1addr" (=>eth1), "eth2addr", ...
+
+If the network interface stores some valid MAC address (for instance
+in SROM), this is used as default address if there is NO correspon-
+ding setting in the environment; if the corresponding environment
+variable is set, this overrides the settings in the card; that means:
+
+o If the SROM has a valid MAC address, and there is no address in the
+  environment, the SROM's address is used.
+
+o If there is no valid address in the SROM, and a definition in the
+  environment exists, then the value from the environment variable is
+  used.
+
+o If both the SROM and the environment contain a MAC address, and
+  both addresses are the same, this MAC address is used.
+
+o If both the SROM and the environment contain a MAC address, and the
+  addresses differ, the value from the environment is used and a
+  warning is printed.
+
+o If neither SROM nor the environment contain a MAC address, an error
+  is raised.
+
+
+
+Image Formats:
+==============
+
+The "boot" commands of this monitor operate on "image" files which
+can be basicly anything, preceeded by a special header; see the
+definitions in include/image.h for details; basicly, the header
+defines the following image properties:
+
+* Target Operating System (Provisions for OpenBSD, NetBSD, FreeBSD,
+  4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks,
+  LynxOS, pSOS, QNX;
+  Currently supported: Linux, NetBSD, VxWorks, QNX).
+* Target CPU Architecture (Provisions for Alpha, ARM, Intel x86,
+  IA64, MIPS, MIPS, PowerPC, IBM S390, SuperH, Sparc, Sparc 64 Bit;
+  Currently supported: PowerPC).
+* Compression Type (Provisions for uncompressed, gzip, bzip2;
+  Currently supported: uncompressed, gzip).
+* Load Address
+* Entry Point
+* Image Name
+* Image Timestamp
+
+The header is marked by a special Magic Number, and both the header
+and the data portions of the image are secured against corruption by
+CRC32 checksums.
+
+
+Linux Support:
+==============
+
+Although U-Boot should support any OS or standalone application
+easily, Linux has always been in the focus during the design of
+U-Boot.
+
+U-Boot includes many features that so far have been part of some
+special "boot loader" code within the Linux kernel. Also, any
+"initrd" images to be used are no longer part of one big Linux image;
+instead, kernel and "initrd" are separate images. This implementation
+serves serveral purposes:
+
+- the same features can be used for other OS or standalone
+  applications (for instance: using compressed images to reduce the
+  Flash memory footprint)
+
+- it becomes much easier to port new Linux kernel versions because
+  lots of low-level, hardware dependend stuff are done by U-Boot
+
+- the same Linux kernel image can now be used with different "initrd"
+  images; of course this also means that different kernel images can
+  be run with the same "initrd". This makes testing easier (you don't
+  have to build a new "zImage.initrd" Linux image when you just
+  change a file in your "initrd"). Also, a field-upgrade of the
+  software is easier now.
+
+
+Linux HOWTO:
+============
+
+Porting Linux to U-Boot based systems:
+---------------------------------------
+
+U-Boot cannot save you from doing all the necessary modifications to
+configure the Linux device drivers for use with your target hardware
+(no, we don't intend to provide a full virtual machine interface to
+Linux :-).
+
+But now you can ignore ALL boot loader code (in arch/ppc/mbxboot).
+
+Just make sure your machine specific header file (for instance
+include/asm-ppc/tqm8xx.h) includes the same definition of the Board
+Information structure as we define in include/u-boot.h, and make
+sure that your definition of IMAP_ADDR uses the same value as your
+U-Boot configuration in CFG_IMMR.
+
+
+Configuring the Linux kernel:
+-----------------------------
+
+No specific requirements for U-Boot. Make sure you have some root
+device (initial ramdisk, NFS) for your target system.
+
+
+Building a Linux Image:
+-----------------------
+
+No specific requirements for U-Boot. There is no need to add a
+"ramdisk.image.gz" file when building the kernel, even when you
+intend to run it with initial ramdisk.
+
+Example:
+
+       make TQM850L_config
+       make oldconfig
+       make dep
+       make zImage
+
+However, we don't use the 'zImage' (= 'arch/ppc/mbxboot/zvmlinux') we
+build this way. The 'zImage' includes the old boot loader code which
+we don't ned any more. Instead, we use the raw (compressed) Linux
+kernel image in 'arch/ppc/coffboot/vmlinux.gz'.
+
+There is a special tool (in 'tools/mkimage') to encapsulate this
+image with header information, CRC32 checksum etc. for use with
+U-Boot:
+
+In the first form (with "-l" option) mkimage  lists  the  information
+contained  in  the header of an existing U-Boot image; this includes
+checksum verification:
+
+       tools/mkimage -l image
+         -l ==> list image header information
+
+The second form (with "-d" option) is used to build a U-Boot image
+from a "data file" which is used as image payload:
+
+       tools/mkimage -A arch -O os -T type -C comp -a addr -e ep \
+                     -n name -d data_file image
+         -A ==> set architecture to 'arch'
+         -O ==> set operating system to 'os'
+         -T ==> set image type to 'type'
+         -C ==> set compression type 'comp'
+         -a ==> set load address to 'addr' (hex)
+         -e ==> set entry point to 'ep' (hex)
+         -n ==> set image name to 'name'
+         -d ==> use image data from 'datafile'
+
+Right now, all Linux kernels use the same load address (0x00000000),
+but the entry point address depends on the kernel version:
+
+- 2.2.x kernels have the entry point at 0x0000000C,
+- 2.3.x and 2.4.x kernels have the entry point at 0x00000000.
+
+So a typical call to build a U-Boot image would read:
+
+       -> tools/mkimage -n '2.2.13 for initrd on TQM850L' \
+       > -A ppc -O linux -T kernel -C gzip -a 00000000 -e 0000000C \
+       > -d /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux.gz \
+       > examples/image-2.2.13-initrd
+       Image Name:   2.2.13 for initrd on TQM850L
+       Created:      Wed Jul 19 02:34:59 2000
+       Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+       Data Size:    335725 Bytes = 327.86 kB = 0.32 MB
+       Load Address: 0x00000000
+       Entry Point:  0x0000000c
+
+To verify the contents of the image (or check for corruption):
+
+       -> tools/mkimage -l examples/image-2.2.13-initrd
+       Image Name:   2.2.13 for initrd on TQM850L
+       Created:      Wed Jul 19 02:34:59 2000
+       Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+       Data Size:    335725 Bytes = 327.86 kB = 0.32 MB
+       Load Address: 0x00000000
+       Entry Point:  0x0000000c
+
+NOTE: for embedded systems where boot time is critical you can trade
+speed for memory and install an UNCOMPRESSED image instead: this
+needs more space in Flash, but boots much faster since it does not
+need to be uncompressed:
+
+       -> gunzip /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux.gz
+       -> tools/mkimage -n '2.2.13 for initrd on TQM850L' \
+       > -A ppc -O linux -T kernel -C none -a 00000000 -e 0000000C \
+       > -d /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux \
+       > examples/image-2.2.13-initrd-uncompressed
+       Image Name:   2.2.13 for initrd on TQM850L
+       Created:      Wed Jul 19 02:34:59 2000
+       Image Type:   PowerPC Linux Kernel Image (uncompressed)
+       Data Size:    792160 Bytes = 773.59 kB = 0.76 MB
+       Load Address: 0x00000000
+       Entry Point:  0x0000000c
+
+
+Similar you can build U-Boot images from a 'ramdisk.image.gz' file
+when your kernel is intended to use an initial ramdisk:
+
+       -> tools/mkimage -n 'Simple Ramdisk Image' \
+       > -A ppc -O linux -T ramdisk -C gzip \
+       > -d /LinuxPPC/images/SIMPLE-ramdisk.image.gz examples/simple-initrd
+       Image Name:   Simple Ramdisk Image
+       Created:      Wed Jan 12 14:01:50 2000
+       Image Type:   PowerPC Linux RAMDisk Image (gzip compressed)
+       Data Size:    566530 Bytes = 553.25 kB = 0.54 MB
+       Load Address: 0x00000000
+       Entry Point:  0x00000000
+
+
+Installing a Linux Image:
+-------------------------
+
+To downloading a U-Boot image over the serial (console) interface,
+you must convert the image to S-Record format:
+
+       objcopy -I binary -O srec examples/image examples/image.srec
+
+The 'objcopy' does not understand the information in the U-Boot
+image header, so the resulting S-Record file will be relative to
+address 0x00000000. To load it to a given address, you need to
+specify the target address as 'offset' parameter with the 'loads'
+command.
+
+Example: install the image to address 0x40100000 (which on the
+TQM8xxL is in the first Flash bank):
+
+       => erase 40100000 401FFFFF
+
+       .......... done
+       Erased 8 sectors
+
+       => loads 40100000
+       ## Ready for S-Record download ...
+       ~>examples/image.srec
+       1 2 3 4 5 6 7 8 9 10 11 12 13 ...
+       ...
+       15989 15990 15991 15992
+       [file transfer complete]
+       [connected]
+       ## Start Addr = 0x00000000
+
+
+You can check the success of the download using the 'iminfo' command;
+this includes a checksum verification so you  can  be  sure  no         data
+corruption happened:
+
+       => imi 40100000
+
+       ## Checking Image at 40100000 ...
+          Image Name:   2.2.13 for initrd on TQM850L
+          Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+          Data Size:    335725 Bytes = 327 kB = 0 MB
+          Load Address: 00000000
+          Entry Point:  0000000c
+          Verifying Checksum ... OK
+
+
+
+Boot Linux:
+-----------
+
+The "bootm" command is used to boot an application that is stored in
+memory (RAM or Flash). In case of a Linux kernel image, the contents
+of the "bootargs" environment variable is passed to the kernel as
+parameters. You can check and modify this variable using the
+"printenv" and "setenv" commands:
+
+
+       => printenv bootargs
+       bootargs=root=/dev/ram
+
+       => setenv bootargs root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
+
+       => printenv bootargs
+       bootargs=root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
+
+       => bootm 40020000
+       ## Booting Linux kernel at 40020000 ...
+          Image Name:   2.2.13 for NFS on TQM850L
+          Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+          Data Size:    381681 Bytes = 372 kB = 0 MB
+          Load Address: 00000000
+          Entry Point:  0000000c
+          Verifying Checksum ... OK
+          Uncompressing Kernel Image ... OK
+       Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:35:17 MEST 2000
+       Boot arguments: root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
+       time_init: decrementer frequency = 187500000/60
+       Calibrating delay loop... 49.77 BogoMIPS
+       Memory: 15208k available (700k kernel code, 444k data, 32k init) [c0000000,c1000000]
+       ...
+
+If you want to boot a Linux kernel with initial ram disk, you pass
+the memory addreses of both the kernel and the initrd image (PPBCOOT
+format!) to the "bootm" command:
+
+       => imi 40100000 40200000
+
+       ## Checking Image at 40100000 ...
+          Image Name:   2.2.13 for initrd on TQM850L
+          Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+          Data Size:    335725 Bytes = 327 kB = 0 MB
+          Load Address: 00000000
+          Entry Point:  0000000c
+          Verifying Checksum ... OK
+
+       ## Checking Image at 40200000 ...
+          Image Name:   Simple Ramdisk Image
+          Image Type:   PowerPC Linux RAMDisk Image (gzip compressed)
+          Data Size:    566530 Bytes = 553 kB = 0 MB
+          Load Address: 00000000
+          Entry Point:  00000000
+          Verifying Checksum ... OK
+
+       => bootm 40100000 40200000
+       ## Booting Linux kernel at 40100000 ...
+          Image Name:   2.2.13 for initrd on TQM850L
+          Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+          Data Size:    335725 Bytes = 327 kB = 0 MB
+          Load Address: 00000000
+          Entry Point:  0000000c
+          Verifying Checksum ... OK
+          Uncompressing Kernel Image ... OK
+       ## Loading RAMDisk Image at 40200000 ...
+          Image Name:   Simple Ramdisk Image
+          Image Type:   PowerPC Linux RAMDisk Image (gzip compressed)
+          Data Size:    566530 Bytes = 553 kB = 0 MB
+          Load Address: 00000000
+          Entry Point:  00000000
+          Verifying Checksum ... OK
+          Loading Ramdisk ... OK
+       Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:32:08 MEST 2000
+       Boot arguments: root=/dev/ram
+       time_init: decrementer frequency = 187500000/60
+       Calibrating delay loop... 49.77 BogoMIPS
+       ...
+       RAMDISK: Compressed image found at block 0
+       VFS: Mounted root (ext2 filesystem).
+
+       bash#
+
+
+Standalone HOWTO:
+=================
+
+One of the features of U-Boot is that you can dynamically load and
+run "standalone" applications, which can use some resources of
+U-Boot like console I/O functions or interrupt services.
+
+Two simple examples are included with the sources:
+
+"Hello World" Demo:
+-------------------
+
+'examples/hello_world.c' contains a small "Hello World" Demo
+application; it is automatically compiled when you build U-Boot.
+It's configured to run at address 0x00040004, so you can play with it
+like that:
+
+       => loads
+       ## Ready for S-Record download ...
+       ~>examples/hello_world.srec
+       1 2 3 4 5 6 7 8 9 10 11 ...
+       [file transfer complete]
+       [connected]
+       ## Start Addr = 0x00040004
+
+       => go 40004 Hello World! This is a test.
+       ## Starting application at 0x00040004 ...
+       Hello World
+       argc = 7
+       argv[0] = "40004"
+       argv[1] = "Hello"
+       argv[2] = "World!"
+       argv[3] = "This"
+       argv[4] = "is"
+       argv[5] = "a"
+       argv[6] = "test."
+       argv[7] = "<NULL>"
+       Hit any key to exit ...
+
+       ## Application terminated, rc = 0x0
+
+Another example, which demonstrates how to register a CPM interrupt
+handler with the U-Boot code, can be found in 'examples/timer.c'.
+Here, a CPM timer is set up to generate an interrupt every second.
+The interrupt service routine is trivial, just printing a '.'
+character, but this is just a demo program. The application can be
+controlled by the following keys:
+
+       ? - print current values og the CPM Timer registers
+       b - enable interrupts and start timer
+       e - stop timer and disable interrupts
+       q - quit application
+
+       => loads
+       ## Ready for S-Record download ...
+       ~>examples/timer.srec
+       1 2 3 4 5 6 7 8 9 10 11 ...
+       [file transfer complete]
+       [connected]
+       ## Start Addr = 0x00040004
+
+       => go 40004
+       ## Starting application at 0x00040004 ...
+       TIMERS=0xfff00980
+       Using timer 1
+         tgcr @ 0xfff00980, tmr @ 0xfff00990, trr @ 0xfff00994, tcr @ 0xfff00998, tcn @ 0xfff0099c, ter @ 0xfff009b0
+
+Hit 'b':
+       [q, b, e, ?] Set interval 1000000 us
+       Enabling timer
+Hit '?':
+       [q, b, e, ?] ........
+       tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0xef6, ter=0x0
+Hit '?':
+       [q, b, e, ?] .
+       tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x2ad4, ter=0x0
+Hit '?':
+       [q, b, e, ?] .
+       tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x1efc, ter=0x0
+Hit '?':
+       [q, b, e, ?] .
+       tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x169d, ter=0x0
+Hit 'e':
+       [q, b, e, ?] ...Stopping timer
+Hit 'q':
+       [q, b, e, ?] ## Application terminated, rc = 0x0
+
+
+NetBSD Notes:
+=============
+
+Starting at version 0.9.2, U-Boot supports NetBSD both as host
+(build U-Boot) and target system (boots NetBSD/mpc8xx).
+
+Building requires a cross environment; it is known to work on
+NetBSD/i386 with the cross-powerpc-netbsd-1.3 package (you will also
+need gmake since the Makefiles are not compatible with BSD make).
+Note that the cross-powerpc package does not install include files;
+attempting to build U-Boot will fail because <machine/ansi.h> is
+missing.  This file has to be installed and patched manually:
+
+       # cd /usr/pkg/cross/powerpc-netbsd/include
+       # mkdir powerpc
+       # ln -s powerpc machine
+       # cp /usr/src/sys/arch/powerpc/include/ansi.h powerpc/ansi.h
+       # ${EDIT} powerpc/ansi.h        ## must remove __va_list, _BSD_VA_LIST
+
+Native builds *don't* work due to incompatibilities between native
+and U-Boot include files.
+
+Booting assumes that (the first part of) the image booted is a
+stage-2 loader which in turn loads and then invokes the kernel
+proper. Loader sources will eventually appear in the NetBSD source
+tree (probably in sys/arc/mpc8xx/stand/u-boot_stage2/); in the
+meantime, send mail to bruno@exet-ag.de and/or wd@denx.de for
+details.
+
+
+Implementation Internals:
+=========================
+
+The following is not intended to be a complete description of every
+implementation detail. However, it should help to understand the
+inner workings of U-Boot and make it easier to port it to custom
+hardware.
+
+
+Initial Stack, Global Data:
+---------------------------
+
+The implementation of U-Boot is complicated by the fact that U-Boot
+starts running out of ROM (flash memory), usually without access to
+system RAM (because the memory controller is not initialized yet).
+This means that we don't have writable Data or BSS segments, and BSS
+is not initialized as zero. To be able to get a C environment working
+at all, we have to allocate at least a minimal stack. Implementation
+options for this are defined and restricted by the CPU used: Some CPU
+models provide on-chip memory (like the IMMR area on MPC8xx and
+MPC826x processors), on others (parts of) the data cache can be
+locked as (mis-) used as memory, etc.
+
+It is essential to remember this, since it has some impact on the C
+code for the initialization procedures:
+
+* Initialized global data (data segment) is read-only. Do not attempt
+  to write it.
+
+* Do not use any unitialized global data (or implicitely initialized
+  as zero data - BSS segment) at all - this is undefined, initiali-
+  zation is performed later (when relocationg to RAM).
+
+* Stack space is very limited. Avoid big data buffers or things  like
+  that.
+
+Having only the stack as writable memory limits means we cannot use
+normal global data to share information beween the code. But it
+turned out that the implementation of U-Boot can be greatly
+simplified by making a global data structure (gd_t) available to all
+functions. We could pass a pointer to this data as argument to _all_
+functions, but this would bloat the code. Instead we use a feature of
+the GCC compiler (Global Register Variables) to share the data: we
+place a pointer (gd) to the global data into a register which we
+reserve for this purpose.
+
+When chosing a register for such a purpose we are restricted  by  the
+relevant  (E)ABI  specifications for the current architecture, and by
+GCC's implementation.
+
+For PowerPC, the following registers have specific use:
+       R1:     stack pointer
+       R2:     TOC pointer
+       R3-R4:  parameter passing and return values
+       R5-R10: parameter passing
+       R13:    small data area pointer
+       R30:    GOT pointer
+       R31:    frame pointer
+
+       (U-Boot also uses R14 as internal GOT pointer.)
+
+    ==> U-Boot will use R29 to hold a pointer to the global data
+
+    Note: on PPC, we could use a static initializer (since the
+    address of the global data structure is known at compile time),
+    but it turned out that reserving a register results in somewhat
+    smaller code - although the code savings are not that big (on
+    average for all boards 752 bytes for the whole U-Boot image,
+    624 text + 127 data).
+
+On ARM, the following registers are used:
+
+       R0:     function argument word/integer result
+       R1-R3:  function argument word
+       R9:     GOT pointer
+       R10:    stack limit (used only if stack checking if enabled)
+       R11:    argument (frame) pointer
+       R12:    temporary workspace
+       R13:    stack pointer
+       R14:    link register
+       R15:    program counter
+
+    ==> U-Boot will use R8 to hold a pointer to the global data
+
+
+
+Memory Management:
+------------------
+
+U-Boot runs in system state and uses physical addresses, i.e. the
+MMU is not used either for address mapping nor for memory protection.
+
+The available memory is mapped to fixed addresses using the memory
+controller. In this process, a contiguous block is formed for each
+memory type (Flash, SDRAM, SRAM), even when it consists of several
+physical memory banks.
+
+U-Boot is installed in the first 128 kB of the first Flash bank (on
+TQM8xxL modules this is the range 0x40000000 ... 0x4001FFFF). After
+booting and sizing and initializing DRAM, the code relocates itself
+to the upper end of DRAM. Immediately below the U-Boot code some
+memory is reserved for use by malloc() [see CFG_MALLOC_LEN
+configuration setting]. Below that, a structure with global Board
+Info data is placed, followed by the stack (growing downward).
+
+Additionally, some exception handler code is copied to the low 8 kB
+of DRAM (0x00000000 ... 0x00001FFF).
+
+So a typical memory configuration with 16 MB of DRAM could look like
+this:
+
+       0x0000 0000     Exception Vector code
+             :
+       0x0000 1FFF
+       0x0000 2000     Free for Application Use
+             :
+             :
+
+             :
+             :
+       0x00FB FF20     Monitor Stack (Growing downward)
+       0x00FB FFAC     Board Info Data and permanent copy of global data
+       0x00FC 0000     Malloc Arena
+             :
+       0x00FD FFFF
+       0x00FE 0000     RAM Copy of Monitor Code
+       ...             eventually: LCD or video framebuffer
+       ...             eventually: pRAM (Protected RAM - unchanged by reset)
+       0x00FF FFFF     [End of RAM]
+
+
+System Initialization:
+----------------------
+
+In the reset configuration, U-Boot starts at the reset entry point
+(on most PowerPC systens at address 0x00000100). Because of the reset
+configuration for CS0# this is a mirror of the onboard Flash memory.
+To be able to re-map memory U-Boot then jumps to it's link address.
+To be able to implement the initialization code in C, a (small!)
+initial stack is set up in the internal Dual Ported RAM (in case CPUs
+which provide such a feature like MPC8xx or MPC8260), or in a locked
+part of the data cache. After that, U-Boot initializes the CPU core,
+the caches and the SIU.
+
+Next, all (potentially) available memory banks are mapped using a
+preliminary mapping. For example, we put them on 512 MB boundaries
+(multiples of 0x20000000: SDRAM on 0x00000000 and 0x20000000, Flash
+on 0x40000000 and 0x60000000, SRAM on 0x80000000). Then UPM A is
+programmed for SDRAM access. Using the temporary configuration, a
+simple memory test is run that determines the size of the SDRAM
+banks.
+
+When there is more than one SDRAM bank, and the banks are of
+different size, the larger is mapped first. For equal size, the first
+bank (CS2#) is mapped first. The first mapping is always for address
+0x00000000, with any additional banks following immediately to create
+contiguous memory starting from 0.
+
+Then, the monitor installs itself at the upper end of the SDRAM area
+and allocates memory for use by malloc() and for the global Board
+Info data; also, the exception vector code is copied to the low RAM
+pages, and the final stack is set up.
+
+Only after this relocation will you have a "normal" C environment;
+until that you are restricted in several ways, mostly because you are
+running from ROM, and because the code will have to be relocated to a
+new address in RAM.
+
+
+U-Boot Porting Guide:
+----------------------
+
+[Based on messages by Jerry Van Baren in the U-Boot-Users mailing
+list, Octover 2002]
+
+
+int main (int argc, char *argv[])
+{
+       sighandler_t no_more_time;
+
+       signal (SIGALRM, no_more_time);
+       alarm (PROJECT_DEADLINE - toSec (3 * WEEK));
+
+       if (available_money > available_manpower) {
+               pay consultant to port U-Boot;
+               return 0;
+       }
+
+       Download latest U-Boot source;
+
+       if (clueless) {
+               email ("Hi, I am new to U-Boot, how do I get started?");
+       }
+
+       while (learning) {
+               Read the README file in the top level directory;
+               Read http://www.denx.de/re/DPLG.html
+               Read the source, Luke;
+       }
+
+       if (available_money > toLocalCurrency ($2500)) {
+               Buy a BDI2000;
+       } else {
+               Add a lot of aggravation and time;
+       }
+
+       Create your own board support subdirectory;
+
+       while (!running) {
+               do {
+                       Add / modify source code;
+               } until (compiles);
+               Debug;
+               if (clueless)
+                       email ("Hi, I am having problems...");
+       }
+       Send patch file to Wolfgang;
+
+       return 0;
+}
+
+void no_more_time (int sig)
+{
+      hire_a_guru();
+}
+
+
+
+Coding Standards:
+-----------------
+
+All contributions to U-Boot should conform to the Linux kernel
+coding style; see the file "Documentation/CodingStyle" in your Linux
+kernel source directory.
+
+Please note that U-Boot is implemented in C (and to some small parts
+in Assembler); no C++ is used, so please do not use C++ style
+comments (//) in your code.
+
+Submissions which do not conform to the standards may be returned
+with a request to reformat the changes.
+
+
+Submitting Patches:
+-------------------
+
+Since the number of patches for U-Boot is growing, we need to
+establish some rules. Submissions which do not conform to these rules
+may be rejected, even when they contain important and valuable stuff.
+
+
+When you send a patch, please include the following information with
+it:
+
+* For bug fixes: a description of the bug and how your patch fixes
+  this bug. Please try to include a way of demonstrating that the
+  patch actually fixes something.
+
+* For new features: a description of the feature and your
+  implementation.
+
+* A CHANGELOG entry as plaintext (separate from the patch)
+
+* For major contributions, your entry to the CREDITS file
+
+* When you add support for a new board, don't forget to add this
+  board to the MAKEALL script, too.
+
+* If your patch adds new configuration options, don't forget to
+  document these in the README file.
+
+* The patch itself. If you are accessing the CVS repository use "cvs
+  update; cvs diff -puRN"; else, use "diff -purN OLD NEW". If your
+  version of diff does not support these options, then get the latest
+  version of GNU diff.
+
+  We accept patches as plain text, MIME attachments or as uuencoded
+  gzipped text.
+
+Notes:
+
+* Before sending the patch, run the MAKEALL script on your patched
+  source tree and make sure that no errors or warnings are reported
+  for any of the boards.
+
+* Keep your modifications to the necessary minimum: A patch
+  containing several unrelated changes or arbitrary reformats will be
+  returned with a request to re-formatting / split it.
+
+* If you modify existing code, make sure that your new code does not
+  add to the memory footprint of the code ;-) Small is beautiful!
+  When adding new features, these should compile conditionally only
+  (using #ifdef), and the resulting code with the new feature
+  disabled must not need more memory than the old code without your
+  modification.
diff --git a/board/cogent/serial.c b/board/cogent/serial.c
new file mode 100644 (file)
index 0000000..4c20017
--- /dev/null
@@ -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 (file)
index 0000000..20aaea2
--- /dev/null
@@ -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 (file)
index 0000000..f4b0ade
--- /dev/null
@@ -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 (file)
index 0000000..723fad3
--- /dev/null
@@ -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 (file)
index 0000000..3ae93d6
--- /dev/null
@@ -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 (file)
index 0000000..d739b81
--- /dev/null
@@ -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 (file)
index 0000000..56abdc7
--- /dev/null
@@ -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 (file)
index 0000000..7b10c0d
--- /dev/null
@@ -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 (file)
index 0000000..a5605b7
--- /dev/null
@@ -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 (file)
index 0000000..7b10c0d
--- /dev/null
@@ -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 (file)
index 0000000..373d238
--- /dev/null
@@ -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 (file)
index 0000000..0849648
--- /dev/null
@@ -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 (file)
index 0000000..666b490
--- /dev/null
@@ -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 (file)
index 0000000..f8f180c
--- /dev/null
@@ -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 (file)
index 0000000..2dda8fa
--- /dev/null
@@ -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 (file)
index 0000000..51a5edd
--- /dev/null
@@ -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 (file)
index 0000000..2dab9f9
--- /dev/null
@@ -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 (file)
index 0000000..ed86c02
--- /dev/null
@@ -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 (file)
index 0000000..ea4925a
--- /dev/null
@@ -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 (file)
index 0000000..8e9178d
--- /dev/null
@@ -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 (file)
index 0000000..ff98e4d
--- /dev/null
@@ -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 (file)
index 0000000..d9c7a15
--- /dev/null
@@ -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 (file)
index 0000000..761ceed
--- /dev/null
@@ -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 (file)
index 0000000..46fe66b
--- /dev/null
@@ -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 (file)
index 0000000..902b1b0
--- /dev/null
@@ -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 (file)
index 0000000..2c4fbf1
--- /dev/null
@@ -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 (file)
index 0000000..16a3262
--- /dev/null
@@ -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 (file)
index 0000000..5d6524d
--- /dev/null
@@ -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 (file)
index 0000000..1b53c72
--- /dev/null
@@ -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 (file)
index 0000000..c59ffb8
--- /dev/null
@@ -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 (file)
index 0000000..0849648
--- /dev/null
@@ -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 (file)
index 0000000..f4b0ade
--- /dev/null
@@ -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 (file)
index 0000000..9a9bf80
--- /dev/null
@@ -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 (file)
index 0000000..dc9a8ea
--- /dev/null
@@ -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 (file)
index 0000000..89ca235
--- /dev/null
@@ -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 (file)
index 0000000..60c49af
--- /dev/null
@@ -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 (file)
index 0000000..d1965f9
--- /dev/null
@@ -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 (file)
index 0000000..944585f
--- /dev/null
@@ -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 (file)
index 0000000..839cafe
--- /dev/null
@@ -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 (file)
index 0000000..b6cc531
--- /dev/null
@@ -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 (file)
index 0000000..3b02f37
--- /dev/null
@@ -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 (file)
index 0000000..ef173d0
--- /dev/null
@@ -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 (file)
index 0000000..ef173d0
--- /dev/null
@@ -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 (file)
index 0000000..504593e
--- /dev/null
@@ -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 (file)
index 0000000..e75f12c
--- /dev/null
@@ -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 (file)
index 0000000..fa494fb
--- /dev/null
@@ -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 (file)
index 0000000..4f0220e
--- /dev/null
@@ -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 (file)
index 0000000..8aced84
--- /dev/null
@@ -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 (file)
index 0000000..57ed8f0
--- /dev/null
@@ -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 (file)
index 0000000..9975cda
--- /dev/null
@@ -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 (file)
index 0000000..36b1d0f
--- /dev/null
@@ -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 (file)
index 0000000..e1b065b
--- /dev/null
@@ -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 (file)
index 0000000..928f6c0
--- /dev/null
@@ -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 (file)
index 0000000..4f71950
--- /dev/null
@@ -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 (file)
index 0000000..4d87527
--- /dev/null
@@ -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 (file)
index 0000000..d7b8873
--- /dev/null
@@ -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 (file)
index 0000000..1e851e1
--- /dev/null
@@ -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 (file)
index 0000000..6857f99
--- /dev/null
@@ -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 (file)
index 0000000..8d385f7
--- /dev/null
@@ -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 (file)
index 0000000..f4b0ade
--- /dev/null
@@ -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 (file)
index 0000000..079f38f
--- /dev/null
@@ -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 (file)
index 0000000..292387b
--- /dev/null
@@ -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 (file)
index 0000000..3b93794
--- /dev/null
@@ -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 (file)
index 0000000..d781903
--- /dev/null
@@ -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 (file)
index 0000000..a17de5a
--- /dev/null
@@ -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 (file)
index 0000000..8c9c218
--- /dev/null
@@ -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 (file)
index 0000000..7f983ef
--- /dev/null
@@ -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 (file)
index 0000000..2f74ccc
--- /dev/null
@@ -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 (file)
index 0000000..98baf7f
--- /dev/null
@@ -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 (file)
index 0000000..3db00bc
--- /dev/null
@@ -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 (file)
index 0000000..3f9b198
--- /dev/null
@@ -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 (file)
index 0000000..59834af
--- /dev/null
@@ -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 (file)
index 0000000..1ea483f
--- /dev/null
@@ -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 (file)
index 0000000..249862a
--- /dev/null
@@ -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 (file)
index 0000000..0048476
--- /dev/null
@@ -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 (file)
index 0000000..e84123b
--- /dev/null
@@ -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 (file)
index 0000000..0abf21f
--- /dev/null
@@ -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 (file)
index 0000000..d510cca
--- /dev/null
@@ -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 (file)
index 0000000..271c197
--- /dev/null
@@ -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 (file)
index 0000000..c24b127
--- /dev/null
@@ -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 (file)
index 0000000..35bbe3e
--- /dev/null
@@ -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 (file)
index 0000000..b404d61
--- /dev/null
@@ -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);
+}
+
diff --git a/common/cmd_doc.c b/common/cmd_doc.c
new file mode 100644 (file)
index 0000000..37d0fbd
--- /dev/null
@@ -0,0 +1,1563 @@
+/*
+ * Driver for Disk-On-Chip 2000 and Millennium
+ * (c) 1999 Machine Vision Holdings, Inc.
+ * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
+ *
+ * $Id: doc2000.c,v 1.46 2001/10/02 15:05:13 dwmw2 Exp $
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <malloc.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg)       show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_DOC)
+
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ids.h>
+#include <linux/mtd/doc2000.h>
+#include <linux/mtd/nftl.h>
+
+#ifdef CFG_DOC_SUPPORT_2000
+#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k)
+#else
+#define DoC_is_2000(doc) (0)
+#endif
+
+#ifdef CFG_DOC_SUPPORT_MILLENNIUM
+#define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil)
+#else
+#define DoC_is_Millennium(doc) (0)
+#endif
+
+/* CFG_DOC_PASSIVE_PROBE:
+   In order to ensure that the BIOS checksum is correct at boot time, and
+   hence that the onboard BIOS extension gets executed, the DiskOnChip
+   goes into reset mode when it is read sequentially: all registers
+   return 0xff until the chip is woken up again by writing to the
+   DOCControl register.
+
+   Unfortunately, this means that the probe for the DiskOnChip is unsafe,
+   because one of the first things it does is write to where it thinks
+   the DOCControl register should be - which may well be shared memory
+   for another device. I've had machines which lock up when this is
+   attempted. Hence the possibility to do a passive probe, which will fail
+   to detect a chip in reset mode, but is at least guaranteed not to lock
+   the machine.
+
+   If you have this problem, uncomment the following line:
+#define CFG_DOC_PASSIVE_PROBE
+*/
+
+#undef DOC_DEBUG
+#undef ECC_DEBUG
+#undef PSYCHO_DEBUG
+#undef NFTL_DEBUG
+
+static struct DiskOnChip doc_dev_desc[CFG_MAX_DOC_DEVICE];
+
+/* Current DOC Device  */
+static int curr_device = -1;
+
+/* ------------------------------------------------------------------------- */
+
+int do_doc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+    int rcode = 0;
+
+    switch (argc) {
+    case 0:
+    case 1:
+       printf ("Usage:\n%s\n", cmdtp->usage);
+       return 1;
+    case 2:
+        if (strcmp(argv[1],"info") == 0) {
+               int i;
+
+               putc ('\n');
+
+               for (i=0; i<CFG_MAX_DOC_DEVICE; ++i) {
+                       if(doc_dev_desc[i].ChipID == DOC_ChipID_UNKNOWN)
+                               continue; /* list only known devices */
+                       printf ("Device %d: ", i);
+                       doc_print(&doc_dev_desc[i]);
+               }
+               return 0;
+
+       } else if (strcmp(argv[1],"device") == 0) {
+               if ((curr_device < 0) || (curr_device >= CFG_MAX_DOC_DEVICE)) {
+                       puts ("\nno devices available\n");
+                       return 1;
+               }
+               printf ("\nDevice %d: ", curr_device);
+               doc_print(&doc_dev_desc[curr_device]);
+               return 0;
+       }
+       printf ("Usage:\n%s\n", cmdtp->usage);
+       return 1;
+    case 3:
+       if (strcmp(argv[1],"device") == 0) {
+               int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+               printf ("\nDevice %d: ", dev);
+               if (dev >= CFG_MAX_DOC_DEVICE) {
+                       puts ("unknown device\n");
+                       return 1;
+               }
+               doc_print(&doc_dev_desc[dev]);
+               /*doc_print (dev);*/
+
+               if (doc_dev_desc[dev].ChipID == DOC_ChipID_UNKNOWN) {
+                       return 1;
+               }
+
+               curr_device = dev;
+
+               puts ("... is now current device\n");
+
+               return 0;
+       }
+
+       printf ("Usage:\n%s\n", cmdtp->usage);
+       return 1;
+    default:
+       /* at least 4 args */
+
+       if (strcmp(argv[1],"read") == 0 || strcmp(argv[1],"write") == 0) {
+               ulong addr = simple_strtoul(argv[2], NULL, 16);
+               ulong off  = simple_strtoul(argv[3], NULL, 16);
+               ulong size = simple_strtoul(argv[4], NULL, 16);
+               int cmd    = (strcmp(argv[1],"read") == 0);
+               int ret, total;
+
+               printf ("\nDOC %s: device %d offset %ld, size %ld ... ",
+                       cmd ? "read" : "write", curr_device, off, size);
+
+               ret = doc_rw(doc_dev_desc + curr_device, cmd, off, size,
+                            &total, (u_char*)addr);
+
+               printf ("%d bytes %s: %s\n", total, cmd ? "read" : "write",
+                       ret ? "ERROR" : "OK");
+
+               return ret;
+       } else if (strcmp(argv[1],"erase") == 0) {
+               ulong off = simple_strtoul(argv[2], NULL, 16);
+               ulong size = simple_strtoul(argv[3], NULL, 16);
+               int ret;
+
+               printf ("\nDOC erase: device %d offset %ld, size %ld ... ",
+                       curr_device, off, size);
+
+               ret = doc_erase (doc_dev_desc + curr_device, off, size);
+
+               printf("%s\n", ret ? "ERROR" : "OK");
+
+               return ret;
+       } else {
+               printf ("Usage:\n%s\n", cmdtp->usage);
+               rcode = 1;
+       }
+
+       return rcode;
+    }
+}
+
+int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       char *boot_device = NULL;
+       char *ep;
+       int dev;
+       ulong cnt;
+       ulong addr;
+       ulong offset = 0;
+       image_header_t *hdr;
+       int rcode = 0;
+
+       switch (argc) {
+       case 1:
+               addr = CFG_LOAD_ADDR;
+               boot_device = getenv ("bootdevice");
+               break;
+       case 2:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = getenv ("bootdevice");
+               break;
+       case 3:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = argv[2];
+               break;
+       case 4:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = argv[2];
+               offset = simple_strtoul(argv[3], NULL, 16);
+               break;
+       default:
+               printf ("Usage:\n%s\n", cmdtp->usage);
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       if (!boot_device) {
+               puts ("\n** No boot device **\n");
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       dev = simple_strtoul(boot_device, &ep, 16);
+
+       if ((dev >= CFG_MAX_DOC_DEVICE) ||
+           (doc_dev_desc[dev].ChipID == DOC_ChipID_UNKNOWN)) {
+               printf ("\n** Device %d not available\n", dev);
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       printf ("\nLoading from device %d: %s at 0x%lX (offset 0x%lX)\n",
+               dev, doc_dev_desc[dev].name, doc_dev_desc[dev].physadr,
+               offset);
+
+       if (doc_rw (doc_dev_desc + dev, 1, offset,
+                   SECTORSIZE, NULL, (u_char *)addr)) {
+               printf ("** Read error on %d\n", dev);
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       hdr = (image_header_t *)addr;
+
+       if (hdr->ih_magic == IH_MAGIC) {
+
+               print_image_hdr (hdr);
+
+               cnt = (hdr->ih_size + sizeof(image_header_t));
+               cnt -= SECTORSIZE;
+       } else {
+               puts ("\n** Bad Magic Number **\n");
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       if (doc_rw (doc_dev_desc + dev, 1, offset + SECTORSIZE, cnt,
+                   NULL, (u_char *)(addr+SECTORSIZE))) {
+               printf ("** Read error on %d\n", dev);
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       /* Loading ok, update default load address */
+
+       load_addr = addr;
+
+       /* Check if we should attempt an auto-start */
+       if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
+               char *local_args[2];
+               extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
+
+               local_args[0] = argv[0];
+               local_args[1] = NULL;
+
+               printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
+
+               do_bootm (cmdtp, 0, 1, local_args);
+               rcode = 1;
+       }
+       return rcode;
+}
+
+int doc_rw (struct DiskOnChip* this, int cmd,
+           loff_t from, size_t len,
+           size_t * retlen, u_char * buf)
+{
+       int noecc, ret = 0, n, total = 0;
+       char eccbuf[6];
+
+       while(len) {
+               /* The ECC will not be calculated correctly if
+                  less than 512 is written or read */
+               noecc = (from != (from | 0x1ff) + 1) || (len < 0x200);
+
+               if (cmd)
+                       ret = doc_read_ecc(this, from, len,
+                                          &n, (u_char*)buf,
+                                          noecc ? NULL : eccbuf);
+               else
+                       ret = doc_write_ecc(this, from, len,
+                                           &n, (u_char*)buf,
+                                           noecc ? NULL : eccbuf);
+
+               if (ret)
+                       break;
+
+               from  += n;
+               buf   += n;
+               total += n;
+               len   -= n;
+       }
+
+       if (retlen)
+               *retlen = total;
+
+       return ret;
+}
+
+void doc_print(struct DiskOnChip *this) {
+       printf("%s at 0x%lX,\n"
+              "\t  %d chip%s %s, size %d MB, \n"
+              "\t  total size %ld MB, sector size %ld kB\n",
+              this->name, this->physadr, this->numchips,
+              this->numchips>1 ? "s" : "", this->chips_name,
+              1 << (this->chipshift - 20),
+              this->totlen >> 20, this->erasesize >> 10);
+
+       if (this->nftl_found) {
+               struct NFTLrecord *nftl = &this->nftl;
+               unsigned long bin_size, flash_size;
+
+               bin_size = nftl->nb_boot_blocks * this->erasesize;
+               flash_size = (nftl->nb_blocks - nftl->nb_boot_blocks) * this->erasesize;
+
+               printf("\t  NFTL boot record:\n"
+                      "\t    Binary partition: size %ld%s\n"
+                      "\t    Flash disk partition: size %ld%s, offset 0x%lx\n",
+                      bin_size > (1 << 20) ? bin_size >> 20 : bin_size >> 10,
+                      bin_size > (1 << 20) ? "MB" : "kB",
+                      flash_size > (1 << 20) ? flash_size >> 20 : flash_size >> 10,
+                      flash_size > (1 << 20) ? "MB" : "kB", bin_size);
+       } else {
+               puts ("\t  No NFTL boot record found.\n");
+       }
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* This function is needed to avoid calls of the __ashrdi3 function. */
+static int shr(int val, int shift) {
+       return val >> shift;
+}
+
+/* Perform the required delay cycles by reading from the appropriate register */
+static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles)
+{
+       volatile char dummy;
+       int i;
+
+       for (i = 0; i < cycles; i++) {
+               if (DoC_is_Millennium(doc))
+                       dummy = ReadDOC(doc->virtadr, NOP);
+               else
+                       dummy = ReadDOC(doc->virtadr, DOCStatus);
+       }
+
+}
+
+/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
+static int _DoC_WaitReady(struct DiskOnChip *doc)
+{
+       unsigned long docptr = doc->virtadr;
+       unsigned long start = get_timer(0);
+
+#ifdef PSYCHO_DEBUG
+       puts ("_DoC_WaitReady called for out-of-line wait\n");
+#endif
+
+       /* Out-of-line routine to wait for chip response */
+       while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
+#ifdef CFG_DOC_SHORT_TIMEOUT
+               /* it seems that after a certain time the DoC deasserts
+                * the CDSN_CTRL_FR_B although it is not ready...
+                * using a short timout solve this (timer increments every ms) */
+               if (get_timer(start) > 10) {
+                       return DOC_ETIMEOUT;
+               }
+#else
+               if (get_timer(start) > 10 * 1000) {
+                       puts ("_DoC_WaitReady timed out.\n");
+                       return DOC_ETIMEOUT;
+               }
+#endif
+               udelay(1);
+        }
+
+       return 0;
+}
+
+static int DoC_WaitReady(struct DiskOnChip *doc)
+{
+       unsigned long docptr = doc->virtadr;
+       /* This is inline, to optimise the common case, where it's ready instantly */
+       int ret = 0;
+
+       /* 4 read form NOP register should be issued in prior to the read from CDSNControl
+          see Software Requirement 11.4 item 2. */
+       DoC_Delay(doc, 4);
+
+       if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
+               /* Call the out-of-line routine to wait */
+               ret = _DoC_WaitReady(doc);
+
+       /* issue 2 read from NOP register after reading from CDSNControl register
+          see Software Requirement 11.4 item 2. */
+       DoC_Delay(doc, 2);
+
+       return ret;
+}
+
+/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to
+   bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
+   required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
+
+static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command,
+                             unsigned char xtraflags)
+{
+       unsigned long docptr = doc->virtadr;
+
+       if (DoC_is_2000(doc))
+               xtraflags |= CDSN_CTRL_FLASH_IO;
+
+       /* Assert the CLE (Command Latch Enable) line to the flash chip */
+       WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
+       DoC_Delay(doc, 4);      /* Software requirement 11.4.3 for Millennium */
+
+       if (DoC_is_Millennium(doc))
+               WriteDOC(command, docptr, CDSNSlowIO);
+
+       /* Send the command */
+       WriteDOC_(command, docptr, doc->ioreg);
+
+       /* Lower the CLE line */
+       WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
+       DoC_Delay(doc, 4);      /* Software requirement 11.4.3 for Millennium */
+
+       /* Wait for the chip to respond - Software requirement 11.4.1 (extended for any command) */
+       return DoC_WaitReady(doc);
+}
+
+/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to
+   bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
+   required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
+
+static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs,
+                      unsigned char xtraflags1, unsigned char xtraflags2)
+{
+       unsigned long docptr;
+       int i;
+
+       docptr = doc->virtadr;
+
+       if (DoC_is_2000(doc))
+               xtraflags1 |= CDSN_CTRL_FLASH_IO;
+
+       /* Assert the ALE (Address Latch Enable) line to the flash chip */
+       WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
+
+       DoC_Delay(doc, 4);      /* Software requirement 11.4.3 for Millennium */
+
+       /* Send the address */
+       /* Devices with 256-byte page are addressed as:
+          Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
+          * there is no device on the market with page256
+          and more than 24 bits.
+          Devices with 512-byte page are addressed as:
+          Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
+          * 25-31 is sent only if the chip support it.
+          * bit 8 changes the read command to be sent
+          (NAND_CMD_READ0 or NAND_CMD_READ1).
+        */
+
+       if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) {
+               if (DoC_is_Millennium(doc))
+                       WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
+               WriteDOC_(ofs & 0xff, docptr, doc->ioreg);
+       }
+
+       if (doc->page256) {
+               ofs = ofs >> 8;
+       } else {
+               ofs = ofs >> 9;
+       }
+
+       if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) {
+               for (i = 0; i < doc->pageadrlen; i++, ofs = ofs >> 8) {
+                       if (DoC_is_Millennium(doc))
+                               WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
+                       WriteDOC_(ofs & 0xff, docptr, doc->ioreg);
+               }
+       }
+
+       DoC_Delay(doc, 2);      /* Needed for some slow flash chips. mf. */
+
+       /* FIXME: The SlowIO's for millennium could be replaced by
+          a single WritePipeTerm here. mf. */
+
+       /* Lower the ALE line */
+       WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr,
+                CDSNControl);
+
+       DoC_Delay(doc, 4);      /* Software requirement 11.4.3 for Millennium */
+
+       /* Wait for the chip to respond - Software requirement 11.4.1 */
+       return DoC_WaitReady(doc);
+}
+
+/* Read a buffer from DoC, taking care of Millennium odditys */
+static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len)
+{
+       volatile int dummy;
+       int modulus = 0xffff;
+       unsigned long docptr;
+       int i;
+
+       docptr = doc->virtadr;
+
+       if (len <= 0)
+               return;
+
+       if (DoC_is_Millennium(doc)) {
+               /* Read the data via the internal pipeline through CDSN IO register,
+                  see Pipelined Read Operations 11.3 */
+               dummy = ReadDOC(docptr, ReadPipeInit);
+
+               /* Millennium should use the LastDataRead register - Pipeline Reads */
+               len--;
+
+               /* This is needed for correctly ECC calculation */
+               modulus = 0xff;
+       }
+
+       for (i = 0; i < len; i++)
+               buf[i] = ReadDOC_(docptr, doc->ioreg + (i & modulus));
+
+       if (DoC_is_Millennium(doc)) {
+               buf[i] = ReadDOC(docptr, LastDataRead);
+       }
+}
+
+/* Write a buffer to DoC, taking care of Millennium odditys */
+static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len)
+{
+       unsigned long docptr;
+       int i;
+
+       docptr = doc->virtadr;
+
+       if (len <= 0)
+               return;
+
+       for (i = 0; i < len; i++)
+               WriteDOC_(buf[i], docptr, doc->ioreg + i);
+
+       if (DoC_is_Millennium(doc)) {
+               WriteDOC(0x00, docptr, WritePipeTerm);
+       }
+}
+
+
+/* DoC_SelectChip: Select a given flash chip within the current floor */
+
+static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip)
+{
+       unsigned long docptr = doc->virtadr;
+
+       /* Software requirement 11.4.4 before writing DeviceSelect */
+       /* Deassert the CE line to eliminate glitches on the FCE# outputs */
+       WriteDOC(CDSN_CTRL_WP, docptr, CDSNControl);
+       DoC_Delay(doc, 4);      /* Software requirement 11.4.3 for Millennium */
+
+       /* Select the individual flash chip requested */
+       WriteDOC(chip, docptr, CDSNDeviceSelect);
+       DoC_Delay(doc, 4);
+
+       /* Reassert the CE line */
+       WriteDOC(CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP, docptr,
+                CDSNControl);
+       DoC_Delay(doc, 4);      /* Software requirement 11.4.3 for Millennium */
+
+       /* Wait for it to be ready */
+       return DoC_WaitReady(doc);
+}
+
+/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
+
+static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor)
+{
+       unsigned long docptr = doc->virtadr;
+
+       /* Select the floor (bank) of chips required */
+       WriteDOC(floor, docptr, FloorSelect);
+
+       /* Wait for the chip to be ready */
+       return DoC_WaitReady(doc);
+}
+
+/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
+
+static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
+{
+       int mfr, id, i;
+       volatile char dummy;
+
+       /* Page in the required floor/chip */
+       DoC_SelectFloor(doc, floor);
+       DoC_SelectChip(doc, chip);
+
+       /* Reset the chip */
+       if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {
+#ifdef DOC_DEBUG
+               printf("DoC_Command (reset) for %d,%d returned true\n",
+                      floor, chip);
+#endif
+               return 0;
+       }
+
+
+       /* Read the NAND chip ID: 1. Send ReadID command */
+       if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {
+#ifdef DOC_DEBUG
+               printf("DoC_Command (ReadID) for %d,%d returned true\n",
+                      floor, chip);
+#endif
+               return 0;
+       }
+
+       /* Read the NAND chip ID: 2. Send address byte zero */
+       DoC_Address(doc, ADDR_COLUMN, 0, CDSN_CTRL_WP, 0);
+
+       /* Read the manufacturer and device id codes from the device */
+
+       /* CDSN Slow IO register see Software Requirement 11.4 item 5. */
+       dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
+       DoC_Delay(doc, 2);
+       mfr = ReadDOC_(doc->virtadr, doc->ioreg);
+
+       /* CDSN Slow IO register see Software Requirement 11.4 item 5. */
+       dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
+       DoC_Delay(doc, 2);
+       id = ReadDOC_(doc->virtadr, doc->ioreg);
+
+       /* No response - return failure */
+       if (mfr == 0xff || mfr == 0)
+               return 0;
+
+       /* Check it's the same as the first chip we identified.
+        * M-Systems say that any given DiskOnChip device should only
+        * contain _one_ type of flash part, although that's not a
+        * hardware restriction. */
+       if (doc->mfr) {
+               if (doc->mfr == mfr && doc->id == id)
+                       return 1;       /* This is another the same the first */
+               else
+                       printf("Flash chip at floor %d, chip %d is different:\n",
+                              floor, chip);
+       }
+
+       /* Print and store the manufacturer and ID codes. */
+       for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+               if (mfr == nand_flash_ids[i].manufacture_id &&
+                   id == nand_flash_ids[i].model_id) {
+#ifdef DOC_DEBUG
+                       printf("Flash chip found: Manufacturer ID: %2.2X, "
+                              "Chip ID: %2.2X (%s)\n", mfr, id,
+                              nand_flash_ids[i].name);
+#endif
+                       if (!doc->mfr) {
+                               doc->mfr = mfr;
+                               doc->id = id;
+                               doc->chipshift =
+                                   nand_flash_ids[i].chipshift;
+                               doc->page256 = nand_flash_ids[i].page256;
+                               doc->pageadrlen =
+                                   nand_flash_ids[i].pageadrlen;
+                               doc->erasesize =
+                                   nand_flash_ids[i].erasesize;
+                               doc->chips_name =
+                                   nand_flash_ids[i].name;
+                               return 1;
+                       }
+                       return 0;
+               }
+       }
+
+
+#ifdef DOC_DEBUG
+       /* We haven't fully identified the chip. Print as much as we know. */
+       printf("Unknown flash chip found: %2.2X %2.2X\n",
+              id, mfr);
+#endif
+
+       return 0;
+}
+
+/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
+
+static void DoC_ScanChips(struct DiskOnChip *this)
+{
+       int floor, chip;
+       int numchips[MAX_FLOORS];
+       int maxchips = MAX_CHIPS;
+       int ret = 1;
+
+       this->numchips = 0;
+       this->mfr = 0;
+       this->id = 0;
+
+       if (DoC_is_Millennium(this))
+               maxchips = MAX_CHIPS_MIL;
+
+       /* For each floor, find the number of valid chips it contains */
+       for (floor = 0; floor < MAX_FLOORS; floor++) {
+               ret = 1;
+               numchips[floor] = 0;
+               for (chip = 0; chip < maxchips && ret != 0; chip++) {
+
+                       ret = DoC_IdentChip(this, floor, chip);
+                       if (ret) {
+                               numchips[floor]++;
+                               this->numchips++;
+                       }
+               }
+       }
+
+       /* If there are none at all that we recognise, bail */
+       if (!this->numchips) {
+               puts ("No flash chips recognised.\n");
+               return;
+       }
+
+       /* Allocate an array to hold the information for each chip */
+       this->chips = malloc(sizeof(struct Nand) * this->numchips);
+       if (!this->chips) {
+               puts ("No memory for allocating chip info structures\n");
+               return;
+       }
+
+       ret = 0;
+
+       /* Fill out the chip array with {floor, chipno} for each
+        * detected chip in the device. */
+       for (floor = 0; floor < MAX_FLOORS; floor++) {
+               for (chip = 0; chip < numchips[floor]; chip++) {
+                       this->chips[ret].floor = floor;
+                       this->chips[ret].chip = chip;
+                       this->chips[ret].curadr = 0;
+                       this->chips[ret].curmode = 0x50;
+                       ret++;
+               }
+       }
+
+       /* Calculate and print the total size of the device */
+       this->totlen = this->numchips * (1 << this->chipshift);
+
+#ifdef DOC_DEBUG
+       printf("%d flash chips found. Total DiskOnChip size: %ld MB\n",
+              this->numchips, this->totlen >> 20);
+#endif
+}
+
+/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
+ *     various device information of the NFTL partition and Bad Unit Table. Update
+ *     the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
+ *     is used for management of Erase Unit in other routines in nftl.c and nftlmount.c
+ */
+static int find_boot_record(struct NFTLrecord *nftl)
+{
+       struct nftl_uci1 h1;
+       struct nftl_oob oob;
+       unsigned int block, boot_record_count = 0;
+       int retlen;
+       u8 buf[SECTORSIZE];
+       struct NFTLMediaHeader *mh = &nftl->MediaHdr;
+       unsigned int i;
+
+       nftl->MediaUnit = BLOCK_NIL;
+       nftl->SpareMediaUnit = BLOCK_NIL;
+
+       /* search for a valid boot record */
+       for (block = 0; block < nftl->nb_blocks; block++) {
+               int ret;
+
+               /* Check for ANAND header first. Then can whinge if it's found but later
+                  checks fail */
+               if ((ret = doc_read_ecc(nftl->mtd, block * nftl->EraseSize, SECTORSIZE,
+                                       &retlen, buf, NULL))) {
+                       static int warncount = 5;
+
+                       if (warncount) {
+                               printf("Block read at 0x%x failed\n", block * nftl->EraseSize);
+                               if (!--warncount)
+                                       puts ("Further failures for this block will not be printed\n");
+                       }
+                       continue;
+               }
+
+               if (retlen < 6 || memcmp(buf, "ANAND", 6)) {
+                       /* ANAND\0 not found. Continue */
+#ifdef PSYCHO_DEBUG
+                       printf("ANAND header not found at 0x%x\n", block * nftl->EraseSize);
+#endif
+                       continue;
+               }
+
+#ifdef NFTL_DEBUG
+               printf("ANAND header found at 0x%x\n", block * nftl->EraseSize);
+#endif
+
+               /* To be safer with BIOS, also use erase mark as discriminant */
+               if ((ret = doc_read_oob(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8,
+                               8, &retlen, (char *)&h1) < 0)) {
+#ifdef NFTL_DEBUG
+                       printf("ANAND header found at 0x%x, but OOB data read failed\n",
+                              block * nftl->EraseSize);
+#endif
+                       continue;
+               }
+
+               /* OK, we like it. */
+
+               if (boot_record_count) {
+                       /* We've already processed one. So we just check if
+                          this one is the same as the first one we found */
+                       if (memcmp(mh, buf, sizeof(struct NFTLMediaHeader))) {
+#ifdef NFTL_DEBUG
+                               printf("NFTL Media Headers at 0x%x and 0x%x disagree.\n",
+                                      nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize);
+#endif
+                               /* if (debug) Print both side by side */
+                               return -1;
+                       }
+                       if (boot_record_count == 1)
+                               nftl->SpareMediaUnit = block;
+
+                       boot_record_count++;
+                       continue;
+               }
+
+               /* This is the first we've seen. Copy the media header structure into place */
+               memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
+
+               /* Do some sanity checks on it */
+               if (mh->UnitSizeFactor != 0xff) {
+                       puts ("Sorry, we don't support UnitSizeFactor "
+                             "of != 1 yet.\n");
+                       return -1;
+               }
+
+               nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
+               if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
+                       printf ("NFTL Media Header sanity check failed:\n"
+                               "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",
+                               nftl->nb_boot_blocks, nftl->nb_blocks);
+                       return -1;
+               }
+
+               nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize;
+               if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) {
+                       printf ("NFTL Media Header sanity check failed:\n"
+                               "numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n",
+                               nftl->numvunits,
+                               nftl->nb_blocks,
+                               nftl->nb_boot_blocks);
+                       return -1;
+               }
+
+               nftl->nr_sects  = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);
+
+               /* If we're not using the last sectors in the device for some reason,
+                  reduce nb_blocks accordingly so we forget they're there */
+               nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN);
+
+               /* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
+               for (i = 0; i < nftl->nb_blocks; i++) {
+                       if ((i & (SECTORSIZE - 1)) == 0) {
+                               /* read one sector for every SECTORSIZE of blocks */
+                               if ((ret = doc_read_ecc(nftl->mtd, block * nftl->EraseSize +
+                                                      i + SECTORSIZE, SECTORSIZE,
+                                                      &retlen, buf, (char *)&oob)) < 0) {
+                                       puts ("Read of bad sector table failed\n");
+                                       return -1;
+                               }
+                       }
+                       /* mark the Bad Erase Unit as RESERVED in ReplUnitTable */
+                       if (buf[i & (SECTORSIZE - 1)] != 0xff)
+                               nftl->ReplUnitTable[i] = BLOCK_RESERVED;
+               }
+
+               nftl->MediaUnit = block;
+               boot_record_count++;
+
+       } /* foreach (block) */
+
+       return boot_record_count?0:-1;
+}
+
+/* This routine is made available to other mtd code via
+ * inter_module_register.  It must only be accessed through
+ * inter_module_get which will bump the use count of this module.  The
+ * addresses passed back in mtd are valid as long as the use count of
+ * this module is non-zero, i.e. between inter_module_get and
+ * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
+ */
+static void DoC2k_init(struct DiskOnChip* this)
+{
+       struct NFTLrecord *nftl;
+
+       switch (this->ChipID) {
+       case DOC_ChipID_Doc2k:
+               this->name = "DiskOnChip 2000";
+               this->ioreg = DoC_2k_CDSN_IO;
+               break;
+       case DOC_ChipID_DocMil:
+               this->name = "DiskOnChip Millennium";
+               this->ioreg = DoC_Mil_CDSN_IO;
+               break;
+       }
+
+#ifdef DOC_DEBUG
+       printf("%s found at address 0x%lX\n", this->name,
+              this->physadr);
+#endif
+
+       this->totlen = 0;
+       this->numchips = 0;
+
+       this->curfloor = -1;
+       this->curchip = -1;
+
+       /* Ident all the chips present. */
+       DoC_ScanChips(this);
+
+       nftl = &this->nftl;
+
+       /* Get physical parameters */
+       nftl->EraseSize = this->erasesize;
+        nftl->nb_blocks = this->totlen / this->erasesize;
+       nftl->mtd = this;
+
+       if (find_boot_record(nftl) != 0)
+               this->nftl_found = 0;
+       else
+               this->nftl_found = 1;
+
+       printf("%s @ 0x%lX, %ld MB\n", this->name, this->physadr, this->totlen >> 20);
+}
+
+int doc_read_ecc(struct DiskOnChip* this, loff_t from, size_t len,
+                size_t * retlen, u_char * buf, u_char * eccbuf)
+{
+       unsigned long docptr;
+       struct Nand *mychip;
+       unsigned char syndrome[6];
+       volatile char dummy;
+       int i, len256 = 0, ret=0;
+
+       docptr = this->virtadr;
+
+       /* Don't allow read past end of device */
+       if (from >= this->totlen) {
+               puts ("Out of flash\n");
+               return DOC_EINVAL;
+       }
+
+       /* Don't allow a single read to cross a 512-byte block boundary */
+       if (from + len > ((from | 0x1ff) + 1))
+               len = ((from | 0x1ff) + 1) - from;
+
+       /* The ECC will not be calculated correctly if less than 512 is read */
+       if (len != 0x200 && eccbuf)
+               printf("ECC needs a full sector read (adr: %lx size %lx)\n",
+                      (long) from, (long) len);
+
+#ifdef PHYCH_DEBUG
+       printf("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len);
+#endif
+
+       /* Find the chip which is to be used and select it */
+       mychip = &this->chips[shr(from, this->chipshift)];
+
+       if (this->curfloor != mychip->floor) {
+               DoC_SelectFloor(this, mychip->floor);
+               DoC_SelectChip(this, mychip->chip);
+       } else if (this->curchip != mychip->chip) {
+               DoC_SelectChip(this, mychip->chip);
+       }
+
+       this->curfloor = mychip->floor;
+       this->curchip = mychip->chip;
+
+       DoC_Command(this,
+                   (!this->page256
+                    && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
+                   CDSN_CTRL_WP);
+       DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
+                   CDSN_CTRL_ECC_IO);
+
+       if (eccbuf) {
+               /* Prime the ECC engine */
+               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+               WriteDOC(DOC_ECC_EN, docptr, ECCConf);
+       } else {
+               /* disable the ECC engine */
+               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+               WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+       }
+
+       /* treat crossing 256-byte sector for 2M x 8bits devices */
+       if (this->page256 && from + len > (from | 0xff) + 1) {
+               len256 = (from | 0xff) + 1 - from;
+               DoC_ReadBuf(this, buf, len256);
+
+               DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP);
+               DoC_Address(this, ADDR_COLUMN_PAGE, from + len256,
+                           CDSN_CTRL_WP, CDSN_CTRL_ECC_IO);
+       }
+
+       DoC_ReadBuf(this, &buf[len256], len - len256);
+
+       /* Let the caller know we completed it */
+       *retlen = len;
+
+       if (eccbuf) {
+               /* Read the ECC data through the DiskOnChip ECC logic */
+               /* Note: this will work even with 2M x 8bit devices as   */
+               /*       they have 8 bytes of OOB per 256 page. mf.      */
+               DoC_ReadBuf(this, eccbuf, 6);
+
+               /* Flush the pipeline */
+               if (DoC_is_Millennium(this)) {
+                       dummy = ReadDOC(docptr, ECCConf);
+                       dummy = ReadDOC(docptr, ECCConf);
+                       i = ReadDOC(docptr, ECCConf);
+               } else {
+                       dummy = ReadDOC(docptr, 2k_ECCStatus);
+                       dummy = ReadDOC(docptr, 2k_ECCStatus);
+                       i = ReadDOC(docptr, 2k_ECCStatus);
+               }
+
+               /* Check the ECC Status */
+               if (i & 0x80) {
+                       int nb_errors;
+                       /* There was an ECC error */
+#ifdef ECC_DEBUG
+                       printf("DiskOnChip ECC Error: Read at %lx\n", (long)from);
+#endif
+                       /* Read the ECC syndrom through the DiskOnChip ECC logic.
+                          These syndrome will be all ZERO when there is no error */
+                       for (i = 0; i < 6; i++) {
+                               syndrome[i] =
+                                   ReadDOC(docptr, ECCSyndrome0 + i);
+                       }
+                        nb_errors = doc_decode_ecc(buf, syndrome);
+
+#ifdef ECC_DEBUG
+                       printf("Errors corrected: %x\n", nb_errors);
+#endif
+                        if (nb_errors < 0) {
+                               /* We return error, but have actually done the read. Not that
+                                  this can be told to user-space, via sys_read(), but at least
+                                  MTD-aware stuff can know about it by checking *retlen */
+                               printf("ECC Errors at %lx\n", (long)from);
+                               ret = DOC_EECC;
+                        }
+               }
+
+#ifdef PSYCHO_DEBUG
+               printf("ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+                            (long)from, eccbuf[0], eccbuf[1], eccbuf[2],
+                            eccbuf[3], eccbuf[4], eccbuf[5]);
+#endif
+
+               /* disable the ECC engine */
+               WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
+       }
+
+       /* according to 11.4.1, we need to wait for the busy line
+         * drop if we read to the end of the page.  */
+       if(0 == ((from + *retlen) & 0x1ff))
+       {
+           DoC_WaitReady(this);
+       }
+
+       return ret;
+}
+
+int doc_write_ecc(struct DiskOnChip* this, loff_t to, size_t len,
+                 size_t * retlen, const u_char * buf,
+                 u_char * eccbuf)
+{
+       int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */
+       unsigned long docptr;
+       volatile char dummy;
+       int len256 = 0;
+       struct Nand *mychip;
+
+       docptr = this->virtadr;
+
+       /* Don't allow write past end of device */
+       if (to >= this->totlen) {
+               puts ("Out of flash\n");
+               return DOC_EINVAL;
+       }
+
+       /* Don't allow a single write to cross a 512-byte block boundary */
+       if (to + len > ((to | 0x1ff) + 1))
+               len = ((to | 0x1ff) + 1) - to;
+
+       /* The ECC will not be calculated correctly if less than 512 is written */
+       if (len != 0x200 && eccbuf)
+               printf("ECC needs a full sector write (adr: %lx size %lx)\n",
+                      (long) to, (long) len);
+
+       /* printf("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */
+
+       /* Find the chip which is to be used and select it */
+       mychip = &this->chips[shr(to, this->chipshift)];
+
+       if (this->curfloor != mychip->floor) {
+               DoC_SelectFloor(this, mychip->floor);
+               DoC_SelectChip(this, mychip->chip);
+       } else if (this->curchip != mychip->chip) {
+               DoC_SelectChip(this, mychip->chip);
+       }
+
+       this->curfloor = mychip->floor;
+       this->curchip = mychip->chip;
+
+       /* Set device to main plane of flash */
+       DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
+       DoC_Command(this,
+                   (!this->page256
+                    && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
+                   CDSN_CTRL_WP);
+
+       DoC_Command(this, NAND_CMD_SEQIN, 0);
+       DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
+
+       if (eccbuf) {
+               /* Prime the ECC engine */
+               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+               WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
+       } else {
+               /* disable the ECC engine */
+               WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+               WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+       }
+
+       /* treat crossing 256-byte sector for 2M x 8bits devices */
+       if (this->page256 && to + len > (to | 0xff) + 1) {
+               len256 = (to | 0xff) + 1 - to;
+               DoC_WriteBuf(this, buf, len256);
+
+               DoC_Command(this, NAND_CMD_PAGEPROG, 0);
+
+               DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
+               /* There's an implicit DoC_WaitReady() in DoC_Command */
+
+               dummy = ReadDOC(docptr, CDSNSlowIO);
+               DoC_Delay(this, 2);
+
+               if (ReadDOC_(docptr, this->ioreg) & 1) {
+                       puts ("Error programming flash\n");
+                       /* Error in programming */
+                       *retlen = 0;
+                       return DOC_EIO;
+               }
+
+               DoC_Command(this, NAND_CMD_SEQIN, 0);
+               DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0,
+                           CDSN_CTRL_ECC_IO);
+       }
+
+       DoC_WriteBuf(this, &buf[len256], len - len256);
+
+       if (eccbuf) {
+               WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
+                        CDSNControl);
+
+               if (DoC_is_Millennium(this)) {
+                       WriteDOC(0, docptr, NOP);
+                       WriteDOC(0, docptr, NOP);
+                       WriteDOC(0, docptr, NOP);
+               } else {
+                       WriteDOC_(0, docptr, this->ioreg);
+                       WriteDOC_(0, docptr, this->ioreg);
+                       WriteDOC_(0, docptr, this->ioreg);
+               }
+
+               /* Read the ECC data through the DiskOnChip ECC logic */
+               for (di = 0; di < 6; di++) {
+                       eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
+               }
+
+               /* Reset the ECC engine */
+               WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+
+#ifdef PSYCHO_DEBUG
+               printf
+                   ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+                    (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
+                    eccbuf[4], eccbuf[5]);
+#endif
+       }
+
+       DoC_Command(this, NAND_CMD_PAGEPROG, 0);
+
+       DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
+       /* There's an implicit DoC_WaitReady() in DoC_Command */
+
+       dummy = ReadDOC(docptr, CDSNSlowIO);
+       DoC_Delay(this, 2);
+
+       if (ReadDOC_(docptr, this->ioreg) & 1) {
+               puts ("Error programming flash\n");
+               /* Error in programming */
+               *retlen = 0;
+               return DOC_EIO;
+       }
+
+       /* Let the caller know we completed it */
+       *retlen = len;
+
+       if (eccbuf) {
+               unsigned char x[8];
+               size_t dummy;
+               int ret;
+
+               /* Write the ECC data to flash */
+               for (di=0; di<6; di++)
+                       x[di] = eccbuf[di];
+
+               x[6]=0x55;
+               x[7]=0x55;
+
+               ret = doc_write_oob(this, to, 8, &dummy, x);
+               return ret;
+       }
+       return 0;
+}
+
+int doc_read_oob(struct DiskOnChip* this, loff_t ofs, size_t len,
+                size_t * retlen, u_char * buf)
+{
+       int len256 = 0, ret;
+       unsigned long docptr;
+       struct Nand *mychip;
+
+       docptr = this->virtadr;
+
+       mychip = &this->chips[shr(ofs, this->chipshift)];
+
+       if (this->curfloor != mychip->floor) {
+               DoC_SelectFloor(this, mychip->floor);
+               DoC_SelectChip(this, mychip->chip);
+       } else if (this->curchip != mychip->chip) {
+               DoC_SelectChip(this, mychip->chip);
+       }
+       this->curfloor = mychip->floor;
+       this->curchip = mychip->chip;
+
+       /* update address for 2M x 8bit devices. OOB starts on the second */
+       /* page to maintain compatibility with doc_read_ecc. */
+       if (this->page256) {
+               if (!(ofs & 0x8))
+                       ofs += 0x100;
+               else
+                       ofs -= 0x8;
+       }
+
+       DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
+       DoC_Address(this, ADDR_COLUMN_PAGE, ofs, CDSN_CTRL_WP, 0);
+
+       /* treat crossing 8-byte OOB data for 2M x 8bit devices */
+       /* Note: datasheet says it should automaticaly wrap to the */
+       /*       next OOB block, but it didn't work here. mf.      */
+       if (this->page256 && ofs + len > (ofs | 0x7) + 1) {
+               len256 = (ofs | 0x7) + 1 - ofs;
+               DoC_ReadBuf(this, buf, len256);
+
+               DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
+               DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff),
+                           CDSN_CTRL_WP, 0);
+       }
+
+       DoC_ReadBuf(this, &buf[len256], len - len256);
+
+       *retlen = len;
+       /* Reading the full OOB data drops us off of the end of the page,
+         * causing the flash device to go into busy mode, so we need
+         * to wait until ready 11.4.1 and Toshiba TC58256FT docs */
+
+       ret = DoC_WaitReady(this);
+
+       return ret;
+
+}
+
+int doc_write_oob(struct DiskOnChip* this, loff_t ofs, size_t len,
+                 size_t * retlen, const u_char * buf)
+{
+       int len256 = 0;
+       unsigned long docptr = this->virtadr;
+       struct Nand *mychip = &this->chips[shr(ofs, this->chipshift)];
+       volatile int dummy;
+
+#ifdef PSYCHO_DEBUG
+       printf("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",
+              (long)ofs, len, buf[0], buf[1], buf[2], buf[3],
+              buf[8], buf[9], buf[14],buf[15]);
+#endif
+
+       /* Find the chip which is to be used and select it */
+       if (this->curfloor != mychip->floor) {
+               DoC_SelectFloor(this, mychip->floor);
+               DoC_SelectChip(this, mychip->chip);
+       } else if (this->curchip != mychip->chip) {
+               DoC_SelectChip(this, mychip->chip);
+       }
+       this->curfloor = mychip->floor;
+       this->curchip = mychip->chip;
+
+       /* disable the ECC engine */
+       WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+       WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
+
+       /* Reset the chip, see Software Requirement 11.4 item 1. */
+       DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
+
+       /* issue the Read2 command to set the pointer to the Spare Data Area. */
+       DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
+
+       /* update address for 2M x 8bit devices. OOB starts on the second */
+       /* page to maintain compatibility with doc_read_ecc. */
+       if (this->page256) {
+               if (!(ofs & 0x8))
+                       ofs += 0x100;
+               else
+                       ofs -= 0x8;
+       }
+
+       /* issue the Serial Data In command to initial the Page Program process */
+       DoC_Command(this, NAND_CMD_SEQIN, 0);
+       DoC_Address(this, ADDR_COLUMN_PAGE, ofs, 0, 0);
+
+       /* treat crossing 8-byte OOB data for 2M x 8bit devices */
+       /* Note: datasheet says it should automaticaly wrap to the */
+       /*       next OOB block, but it didn't work here. mf.      */
+       if (this->page256 && ofs + len > (ofs | 0x7) + 1) {
+               len256 = (ofs | 0x7) + 1 - ofs;
+               DoC_WriteBuf(this, buf, len256);
+
+               DoC_Command(this, NAND_CMD_PAGEPROG, 0);
+               DoC_Command(this, NAND_CMD_STATUS, 0);
+               /* DoC_WaitReady() is implicit in DoC_Command */
+
+               dummy = ReadDOC(docptr, CDSNSlowIO);
+               DoC_Delay(this, 2);
+
+               if (ReadDOC_(docptr, this->ioreg) & 1) {
+                       puts ("Error programming oob data\n");
+                       /* There was an error */
+                       *retlen = 0;
+                       return DOC_EIO;
+               }
+               DoC_Command(this, NAND_CMD_SEQIN, 0);
+               DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), 0, 0);
+       }
+
+       DoC_WriteBuf(this, &buf[len256], len - len256);
+
+       DoC_Command(this, NAND_CMD_PAGEPROG, 0);
+       DoC_Command(this, NAND_CMD_STATUS, 0);
+       /* DoC_WaitReady() is implicit in DoC_Command */
+
+       dummy = ReadDOC(docptr, CDSNSlowIO);
+       DoC_Delay(this, 2);
+
+       if (ReadDOC_(docptr, this->ioreg) & 1) {
+               puts ("Error programming oob data\n");
+               /* There was an error */
+               *retlen = 0;
+               return DOC_EIO;
+       }
+
+       *retlen = len;
+       return 0;
+
+}
+
+int doc_erase(struct DiskOnChip* this, loff_t ofs, size_t len)
+{
+       volatile int dummy;
+       unsigned long docptr;
+       struct Nand *mychip;
+
+       if (ofs & (this->erasesize-1) || len & (this->erasesize-1)) {
+               puts ("Offset and size must be sector aligned\n");
+               return DOC_EINVAL;
+       }
+
+       docptr = this->virtadr;
+
+       /* FIXME: Do this in the background. Use timers or schedule_task() */
+       while(len) {
+               mychip = &this->chips[shr(ofs, this->chipshift)];
+
+               if (this->curfloor != mychip->floor) {
+                       DoC_SelectFloor(this, mychip->floor);
+                       DoC_SelectChip(this, mychip->chip);
+               } else if (this->curchip != mychip->chip) {
+                       DoC_SelectChip(this, mychip->chip);
+               }
+               this->curfloor = mychip->floor;
+               this->curchip = mychip->chip;
+
+               DoC_Command(this, NAND_CMD_ERASE1, 0);
+               DoC_Address(this, ADDR_PAGE, ofs, 0, 0);
+               DoC_Command(this, NAND_CMD_ERASE2, 0);
+
+               DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
+
+               dummy = ReadDOC(docptr, CDSNSlowIO);
+               DoC_Delay(this, 2);
+
+               if (ReadDOC_(docptr, this->ioreg) & 1) {
+                       printf("Error erasing at 0x%lx\n", (long)ofs);
+                       /* There was an error */
+                       goto callback;
+               }
+               ofs += this->erasesize;
+               len -= this->erasesize;
+       }
+
+ callback:
+       return 0;
+}
+
+static inline int doccheck(unsigned long potential, unsigned long physadr)
+{
+       unsigned long window=potential;
+       unsigned char tmp, ChipID;
+#ifndef DOC_PASSIVE_PROBE
+       unsigned char tmp2;
+#endif
+
+       /* Routine copied from the Linux DOC driver */
+
+#ifdef CFG_DOCPROBE_55AA
+       /* Check for 0x55 0xAA signature at beginning of window,
+          this is no longer true once we remove the IPL (for Millennium */
+       if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
+               return 0;
+#endif /* CFG_DOCPROBE_55AA */
+
+#ifndef DOC_PASSIVE_PROBE
+       /* It's not possible to cleanly detect the DiskOnChip - the
+        * bootup procedure will put the device into reset mode, and
+        * it's not possible to talk to it without actually writing
+        * to the DOCControl register. So we store the current contents
+        * of the DOCControl register's location, in case we later decide
+        * that it's not a DiskOnChip, and want to put it back how we
+        * found it.
+        */
+       tmp2 = ReadDOC(window, DOCControl);
+
+       /* Reset the DiskOnChip ASIC */
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
+                window, DOCControl);
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
+                window, DOCControl);
+
+       /* Enable the DiskOnChip ASIC */
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
+                window, DOCControl);
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
+                window, DOCControl);
+#endif /* !DOC_PASSIVE_PROBE */
+
+       ChipID = ReadDOC(window, ChipID);
+
+       switch (ChipID) {
+       case DOC_ChipID_Doc2k:
+               /* Check the TOGGLE bit in the ECC register */
+               tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
+               if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp)
+                               return ChipID;
+               break;
+
+       case DOC_ChipID_DocMil:
+               /* Check the TOGGLE bit in the ECC register */
+               tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
+               if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp)
+                               return ChipID;
+               break;
+
+       default:
+#ifndef CFG_DOCPROBE_55AA
+/*
+ * if the ID isn't the DoC2000 or DoCMillenium ID, so we can assume
+ * the DOC is missing
+ */
+# if 0
+               printf("Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
+                      ChipID, physadr);
+# endif
+#endif
+#ifndef DOC_PASSIVE_PROBE
+               /* Put back the contents of the DOCControl register, in case it's not
+                * actually a DiskOnChip.
+                */
+               WriteDOC(tmp2, window, DOCControl);
+#endif
+               return 0;
+       }
+
+       puts ("DiskOnChip failed TOGGLE test, dropping.\n");
+
+#ifndef DOC_PASSIVE_PROBE
+       /* Put back the contents of the DOCControl register: it's not a DiskOnChip */
+       WriteDOC(tmp2, window, DOCControl);
+#endif
+       return 0;
+}
+
+void doc_probe(unsigned long physadr)
+{
+       struct DiskOnChip *this = NULL;
+       int i=0, ChipID;
+
+       if ((ChipID = doccheck(physadr, physadr))) {
+
+               for (i=0; i<CFG_MAX_DOC_DEVICE; i++) {
+                       if (doc_dev_desc[i].ChipID == DOC_ChipID_UNKNOWN) {
+                               this = doc_dev_desc + i;
+                               break;
+                       }
+               }
+
+               if (!this) {
+                       puts ("Cannot allocate memory for data structures.\n");
+                       return;
+               }
+
+               if (curr_device == -1)
+                       curr_device = i;
+
+               memset((char *)this, 0, sizeof(struct DiskOnChip));
+
+               this->virtadr = physadr;
+               this->physadr = physadr;
+               this->ChipID = ChipID;
+
+               DoC2k_init(this);
+       } else {
+               puts ("No DiskOnChip found\n");
+       }
+}
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_DOC) */
diff --git a/common/cmd_ide.c b/common/cmd_ide.c
new file mode 100644 (file)
index 0000000..9cbfe1b
--- /dev/null
@@ -0,0 +1,1563 @@
+/*
+ * (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
+ *
+ */
+
+/*
+ * IDE support
+ */
+#include <common.h>
+#include <config.h>
+#include <watchdog.h>
+#include <command.h>
+#include <image.h>
+#include <asm/byteorder.h>
+#if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA)
+# include <pcmcia.h>
+#endif
+#ifdef CONFIG_8xx
+# include <mpc8xx.h>
+#endif
+#include <ide.h>
+#include <ata.h>
+#include <cmd_ide.h>
+#include <cmd_disk.h>
+#ifdef CONFIG_STATUS_LED
+# include <status_led.h>
+#endif
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg)       show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+
+#undef IDE_DEBUG
+
+#ifdef IDE_DEBUG
+#define        PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_IDE)
+
+/* Timings for IDE Interface
+ *
+ * SETUP / LENGTH / HOLD - cycles valid for 50 MHz clk
+ * 70     165      30     PIO-Mode 0, [ns]
+ *  4       9       2                 [Cycles]
+ * 50     125      20     PIO-Mode 1, [ns]
+ *  3       7       2                 [Cycles]
+ * 30     100      15     PIO-Mode 2, [ns]
+ *  2       6       1                 [Cycles]
+ * 30      80      10     PIO-Mode 3, [ns]
+ *  2       5       1                 [Cycles]
+ * 25      70      10     PIO-Mode 4, [ns]
+ *  2       4       1                 [Cycles]
+ */
+
+const static pio_config_t pio_config_ns [IDE_MAX_PIO_MODE+1] =
+{
+    /* Setup  Length  Hold  */
+       { 70,   165,    30 },           /* PIO-Mode 0, [ns]     */
+       { 50,   125,    20 },           /* PIO-Mode 1, [ns]     */
+       { 30,   101,    15 },           /* PIO-Mode 2, [ns]     */
+       { 30,    80,    10 },           /* PIO-Mode 3, [ns]     */
+       { 25,    70,    10 },           /* PIO-Mode 4, [ns]     */
+};
+
+static pio_config_t pio_config_clk [IDE_MAX_PIO_MODE+1];
+
+#ifndef        CFG_PIO_MODE
+#define        CFG_PIO_MODE    0               /* use a relaxed default */
+#endif
+static int pio_mode = CFG_PIO_MODE;
+
+/* Make clock cycles and always round up */
+
+#define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U )
+
+/* ------------------------------------------------------------------------- */
+
+/* Current I/O Device  */
+static int curr_device = -1;
+
+/* Current offset for IDE0 / IDE1 bus access   */
+ulong ide_bus_offset[CFG_IDE_MAXBUS] = {
+#if defined(CFG_ATA_IDE0_OFFSET)
+       CFG_ATA_IDE0_OFFSET,
+#endif
+#if defined(CFG_ATA_IDE1_OFFSET) && (CFG_IDE_MAXBUS > 1)
+       CFG_ATA_IDE1_OFFSET,
+#endif
+};
+
+#define        ATA_CURR_BASE(dev)      (CFG_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)])
+
+static int         ide_bus_ok[CFG_IDE_MAXBUS];
+
+static  block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE];
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_IDE_LED
+static void  ide_led   (uchar led, uchar status);
+#else
+#define ide_led(a,b)   /* dummy */
+#endif
+
+#ifdef CONFIG_IDE_RESET
+static void  ide_reset (void);
+#else
+#define ide_reset()    /* dummy */
+#endif
+
+static void  ide_ident (block_dev_desc_t *dev_desc);
+static uchar ide_wait  (int dev, ulong t);
+
+#define IDE_TIME_OUT   2000    /* 2 sec timeout */
+
+#define ATAPI_TIME_OUT 7000    /* 7 sec timeout (5 sec seems to work...) */
+
+#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
+
+static void __inline__ outb(int dev, int port, unsigned char val);
+static unsigned char __inline__ inb(int dev, int port);
+static void input_swap_data(int dev, ulong *sect_buf, int words);
+static void input_data(int dev, ulong *sect_buf, int words);
+static void output_data(int dev, ulong *sect_buf, int words);
+static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
+
+
+#ifdef CONFIG_ATAPI
+static void    atapi_inquiry(block_dev_desc_t *dev_desc);
+ulong atapi_read (int device, ulong blknr, ulong blkcnt, ulong *buffer);
+#endif
+
+
+#ifdef CONFIG_IDE_8xx_DIRECT
+static void set_pcmcia_timing (int pmode);
+#else
+#define set_pcmcia_timing(a)   /* dummy */
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+int do_ide (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+    int rcode = 0;
+
+    switch (argc) {
+    case 0:
+    case 1:
+       printf ("Usage:\n%s\n", cmdtp->usage);
+       return 1;
+    case 2:
+       if (strncmp(argv[1],"res",3) == 0) {
+               puts ("\nReset IDE"
+#ifdef CONFIG_IDE_8xx_DIRECT
+                       " on PCMCIA " PCMCIA_SLOT_MSG
+#endif
+                       ": ");
+
+               ide_init ();
+               return 0;
+       } else if (strncmp(argv[1],"inf",3) == 0) {
+               int i;
+
+               putc ('\n');
+
+               for (i=0; i<CFG_IDE_MAXDEVICE; ++i) {
+                       if (ide_dev_desc[i].type==DEV_TYPE_UNKNOWN)
+                               continue; /* list only known devices */
+                       printf ("IDE device %d: ", i);
+                       dev_print(&ide_dev_desc[i]);
+               }
+               return 0;
+
+       } else if (strncmp(argv[1],"dev",3) == 0) {
+               if ((curr_device < 0) || (curr_device >= CFG_IDE_MAXDEVICE)) {
+                       puts ("\nno IDE devices available\n");
+                       return 1;
+               }
+               printf ("\nIDE device %d: ", curr_device);
+               dev_print(&ide_dev_desc[curr_device]);
+               return 0;
+       } else if (strncmp(argv[1],"part",4) == 0) {
+               int dev, ok;
+
+               for (ok=0, dev=0; dev<CFG_IDE_MAXDEVICE; ++dev) {
+                       if (ide_dev_desc[dev].part_type!=PART_TYPE_UNKNOWN) {
+                               ++ok;
+                               if (dev)
+                                       putc ('\n');
+                               print_part(&ide_dev_desc[dev]);
+                       }
+               }
+               if (!ok) {
+                       puts ("\nno IDE devices available\n");
+                       rcode ++;
+               }
+               return rcode;
+       }
+       printf ("Usage:\n%s\n", cmdtp->usage);
+       return 1;
+    case 3:
+       if (strncmp(argv[1],"dev",3) == 0) {
+               int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+               printf ("\nIDE device %d: ", dev);
+               if (dev >= CFG_IDE_MAXDEVICE) {
+                       puts ("unknown device\n");
+                       return 1;
+               }
+               dev_print(&ide_dev_desc[dev]);
+               /*ide_print (dev);*/
+
+               if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
+                       return 1;
+               }
+
+               curr_device = dev;
+
+               puts ("... is now current device\n");
+
+               return 0;
+       } else if (strncmp(argv[1],"part",4) == 0) {
+               int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+               if (ide_dev_desc[dev].part_type!=PART_TYPE_UNKNOWN) {
+                               print_part(&ide_dev_desc[dev]);
+               } else {
+                       printf ("\nIDE device %d not available\n", dev);
+                       rcode = 1;
+               }
+               return rcode;
+#if 0
+       } else if (strncmp(argv[1],"pio",4) == 0) {
+               int mode = (int)simple_strtoul(argv[2], NULL, 10);
+
+               if ((mode >= 0) && (mode <= IDE_MAX_PIO_MODE)) {
+                       puts ("\nSetting ");
+                       pio_mode = mode;
+                       ide_init ();
+               } else {
+                       printf ("\nInvalid PIO mode %d (0 ... %d only)\n",
+                               mode, IDE_MAX_PIO_MODE);
+               }
+               return;
+#endif
+       }
+
+       printf ("Usage:\n%s\n", cmdtp->usage);
+       return 1;
+    default:
+       /* at least 4 args */
+
+       if (strcmp(argv[1],"read") == 0) {
+               ulong addr = simple_strtoul(argv[2], NULL, 16);
+               ulong blk  = simple_strtoul(argv[3], NULL, 16);
+               ulong cnt  = simple_strtoul(argv[4], NULL, 16);
+               ulong n;
+
+               printf ("\nIDE read: device %d block # %ld, count %ld ... ",
+                       curr_device, blk, cnt);
+
+               n = ide_dev_desc[curr_device].block_read (curr_device,
+                                                         blk, cnt,
+                                                         (ulong *)addr);
+               /* flush cache after read */
+               flush_cache (addr, cnt*ide_dev_desc[curr_device].blksz);
+
+               printf ("%ld blocks read: %s\n",
+                       n, (n==cnt) ? "OK" : "ERROR");
+               if (n==cnt) {
+                       return 0;
+               } else {
+                       return 1;
+               }
+       } else if (strcmp(argv[1],"write") == 0) {
+               ulong addr = simple_strtoul(argv[2], NULL, 16);
+               ulong blk  = simple_strtoul(argv[3], NULL, 16);
+               ulong cnt  = simple_strtoul(argv[4], NULL, 16);
+               ulong n;
+
+               printf ("\nIDE write: device %d block # %ld, count %ld ... ",
+                       curr_device, blk, cnt);
+
+               n = ide_write (curr_device, blk, cnt, (ulong *)addr);
+
+               printf ("%ld blocks written: %s\n",
+                       n, (n==cnt) ? "OK" : "ERROR");
+               if (n==cnt) {
+                       return 0;
+               } else {
+                       return 1;
+               }
+       } else {
+               printf ("Usage:\n%s\n", cmdtp->usage);
+               rcode = 1;
+       }
+
+       return rcode;
+    }
+}
+
+int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       char *boot_device = NULL;
+       char *ep;
+       int dev, part = 0;
+       ulong cnt;
+       ulong addr;
+       disk_partition_t info;
+       image_header_t *hdr;
+       int rcode = 0;
+
+       switch (argc) {
+       case 1:
+               addr = CFG_LOAD_ADDR;
+               boot_device = getenv ("bootdevice");
+               break;
+       case 2:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = getenv ("bootdevice");
+               break;
+       case 3:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = argv[2];
+               break;
+       default:
+               printf ("Usage:\n%s\n", cmdtp->usage);
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       if (!boot_device) {
+               puts ("\n** No boot device **\n");
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       dev = simple_strtoul(boot_device, &ep, 16);
+
+       if (ide_dev_desc[dev].type==DEV_TYPE_UNKNOWN) {
+               printf ("\n** Device %d not available\n", dev);
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       if (*ep) {
+               if (*ep != ':') {
+                       puts ("\n** Invalid boot device, use `dev[:part]' **\n");
+                       SHOW_BOOT_PROGRESS (-1);
+                       return 1;
+               }
+               part = simple_strtoul(++ep, NULL, 16);
+       }
+       if (get_partition_info (&ide_dev_desc[dev], part, &info)) {
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+       if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
+               printf ("\n** Invalid partition type \"%.32s\""
+                       " (expect \"" BOOT_PART_TYPE "\")\n",
+                       info.type);
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       printf ("\nLoading from IDE device %d, partition %d: "
+               "Name: %.32s  Type: %.32s\n",
+               dev, part, info.name, info.type);
+
+       PRINTF ("First Block: %ld,  # of blocks: %ld, Block Size: %ld\n",
+               info.start, info.size, info.blksz);
+
+       if (ide_dev_desc[dev].block_read (dev, info.start, 1, (ulong *)addr) != 1) {
+               printf ("** Read error on %d:%d\n", dev, part);
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       hdr = (image_header_t *)addr;
+
+       if (ntohl(hdr->ih_magic) == IH_MAGIC) {
+
+               print_image_hdr (hdr);
+
+               cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
+               cnt += info.blksz - 1;
+               cnt /= info.blksz;
+               cnt -= 1;
+       } else {
+               printf("\n** Bad Magic Number **\n");
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+       if (ide_dev_desc[dev].block_read (dev, info.start+1, cnt,
+                     (ulong *)(addr+info.blksz)) != cnt) {
+               printf ("** Read error on %d:%d\n", dev, part);
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+
+
+       /* Loading ok, update default load address */
+
+       load_addr = addr;
+
+       /* Check if we should attempt an auto-start */
+       if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
+               char *local_args[2];
+               extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
+
+               local_args[0] = argv[0];
+               local_args[1] = NULL;
+
+               printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
+
+               do_bootm (cmdtp, 0, 1, local_args);
+               rcode = 1;
+       }
+       return rcode;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void ide_init (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_IDE_8xx_DIRECT
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+       volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
+#endif
+       unsigned char c;
+       int i, bus;
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+       extern int pcmcia_on (void);
+
+       WATCHDOG_RESET();
+
+       /* initialize the PCMCIA IDE adapter card */
+       if (pcmcia_on())
+               return;
+       udelay (1000000);       /* 1 s */
+#endif /* CONFIG_IDE_8xx_PCCARD */
+
+       WATCHDOG_RESET();
+
+       /* Initialize PIO timing tables */
+       for (i=0; i <= IDE_MAX_PIO_MODE; ++i) {
+           pio_config_clk[i].t_setup  = PCMCIA_MK_CLKS(pio_config_ns[i].t_setup,
+                                                           gd->bus_clk);
+           pio_config_clk[i].t_length = PCMCIA_MK_CLKS(pio_config_ns[i].t_length,
+                                                           gd->bus_clk);
+           pio_config_clk[i].t_hold   = PCMCIA_MK_CLKS(pio_config_ns[i].t_hold,
+                                                           gd->bus_clk);
+           PRINTF ("PIO Mode %d: setup=%2d ns/%d clk"
+                   "  len=%3d ns/%d clk"
+                   "  hold=%2d ns/%d clk\n",
+                   i,
+                   pio_config_ns[i].t_setup,  pio_config_clk[i].t_setup,
+                   pio_config_ns[i].t_length, pio_config_clk[i].t_length,
+                   pio_config_ns[i].t_hold,   pio_config_clk[i].t_hold);
+       }
+
+       /* Reset the IDE just to be sure.
+        * Light LED's to show
+        */
+       ide_led ((LED_IDE1 | LED_IDE2), 1);             /* LED's on     */
+       ide_reset (); /* ATAPI Drives seems to need a proper IDE Reset */
+
+#ifdef CONFIG_IDE_8xx_DIRECT
+       /* PCMCIA / IDE initialization for common mem space */
+       pcmp->pcmc_pgcrb = 0;
+#endif
+
+       /* start in PIO mode 0 - most relaxed timings */
+       pio_mode = 0;
+       set_pcmcia_timing (pio_mode);
+
+       /*
+        * Wait for IDE to get ready.
+        * According to spec, this can take up to 31 seconds!
+        */
+       for (bus=0; bus<CFG_IDE_MAXBUS; ++bus) {
+               int dev = bus * (CFG_IDE_MAXDEVICE / CFG_IDE_MAXBUS);
+
+               printf ("Bus %d: ", bus);
+
+               ide_bus_ok[bus] = 0;
+
+               /* Select device
+                */
+               udelay (100000);                /* 100 ms */
+               outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
+               udelay (100000);                /* 100 ms */
+
+               i = 0;
+               do {
+                       udelay (10000);         /* 10 ms */
+
+                       c = inb (dev, ATA_STATUS);
+                       i++;
+                       if (i > (ATA_RESET_TIME * 100)) {
+                               puts ("** Timeout **\n");
+                               ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
+                               return;
+                       }
+                       if ((i >= 100) && ((i%100)==0)) {
+                               putc ('.');
+                       }
+               } while (c & ATA_STAT_BUSY);
+
+               if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
+                       puts ("not available  ");
+                       PRINTF ("Status = 0x%02X ", c);
+#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */
+               } else  if ((c & ATA_STAT_READY) == 0) {
+                       puts ("not available  ");
+                       PRINTF ("Status = 0x%02X ", c);
+#endif
+               } else {
+                       puts ("OK ");
+                       ide_bus_ok[bus] = 1;
+               }
+               WATCHDOG_RESET();
+       }
+       putc ('\n');
+
+       ide_led ((LED_IDE1 | LED_IDE2), 0);     /* LED's off    */
+
+       curr_device = -1;
+       for (i=0; i<CFG_IDE_MAXDEVICE; ++i) {
+#ifdef CONFIG_IDE_LED
+               int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2;
+#endif
+               ide_dev_desc[i].if_type=IF_TYPE_IDE;
+               ide_dev_desc[i].dev=i;
+               ide_dev_desc[i].part_type=PART_TYPE_UNKNOWN;
+               ide_dev_desc[i].blksz=0;
+               ide_dev_desc[i].lba=0;
+               ide_dev_desc[i].block_read=ide_read;
+               if (!ide_bus_ok[IDE_BUS(i)])
+                       continue;
+               ide_led (led, 1);               /* LED on       */
+               ide_ident(&ide_dev_desc[i]);
+               ide_led (led, 0);               /* LED off      */
+               dev_print(&ide_dev_desc[i]);
+/*             ide_print (i); */
+               if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
+                       init_part (&ide_dev_desc[i]);                   /* initialize partition type */
+                       if (curr_device < 0)
+                               curr_device = i;
+               }
+       }
+       WATCHDOG_RESET();
+}
+
+/* ------------------------------------------------------------------------- */
+
+block_dev_desc_t * ide_get_dev(int dev)
+{
+       return ((block_dev_desc_t *)&ide_dev_desc[dev]);
+}
+
+
+#ifdef CONFIG_IDE_8xx_DIRECT
+
+static void
+set_pcmcia_timing (int pmode)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+       volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
+       ulong timings;
+
+       PRINTF ("Set timing for PIO Mode %d\n", pmode);
+
+       timings = PCMCIA_SHT(pio_config_clk[pmode].t_hold)
+               | PCMCIA_SST(pio_config_clk[pmode].t_setup)
+               | PCMCIA_SL (pio_config_clk[pmode].t_length)
+               ;
+
+       /* IDE 0
+        */
+       pcmp->pcmc_pbr0 = CFG_PCMCIA_PBR0;
+       pcmp->pcmc_por0 = CFG_PCMCIA_POR0
+#if (CFG_PCMCIA_POR0 != 0)
+                       | timings
+#endif
+                       ;
+       PRINTF ("PBR0: %08x  POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0);
+
+       pcmp->pcmc_pbr1 = CFG_PCMCIA_PBR1;
+       pcmp->pcmc_por1 = CFG_PCMCIA_POR1
+#if (CFG_PCMCIA_POR1 != 0)
+                       | timings
+#endif
+                       ;
+       PRINTF ("PBR1: %08x  POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1);
+
+       pcmp->pcmc_pbr2 = CFG_PCMCIA_PBR2;
+       pcmp->pcmc_por2 = CFG_PCMCIA_POR2
+#if (CFG_PCMCIA_POR2 != 0)
+                       | timings
+#endif
+                       ;
+       PRINTF ("PBR2: %08x  POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2);
+
+       pcmp->pcmc_pbr3 = CFG_PCMCIA_PBR3;
+       pcmp->pcmc_por3 = CFG_PCMCIA_POR3
+#if (CFG_PCMCIA_POR3 != 0)
+                       | timings
+#endif
+                       ;
+       PRINTF ("PBR3: %08x  POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3);
+
+       /* IDE 1
+        */
+       pcmp->pcmc_pbr4 = CFG_PCMCIA_PBR4;
+       pcmp->pcmc_por4 = CFG_PCMCIA_POR4
+#if (CFG_PCMCIA_POR4 != 0)
+                       | timings
+#endif
+                       ;
+       PRINTF ("PBR4: %08x  POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4);
+
+       pcmp->pcmc_pbr5 = CFG_PCMCIA_PBR5;
+       pcmp->pcmc_por5 = CFG_PCMCIA_POR5
+#if (CFG_PCMCIA_POR5 != 0)
+                       | timings
+#endif
+                       ;
+       PRINTF ("PBR5: %08x  POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5);
+
+       pcmp->pcmc_pbr6 = CFG_PCMCIA_PBR6;
+       pcmp->pcmc_por6 = CFG_PCMCIA_POR6
+#if (CFG_PCMCIA_POR6 != 0)
+                       | timings
+#endif
+                       ;
+       PRINTF ("PBR6: %08x  POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6);
+
+       pcmp->pcmc_pbr7 = CFG_PCMCIA_PBR7;
+       pcmp->pcmc_por7 = CFG_PCMCIA_POR7
+#if (CFG_PCMCIA_POR7 != 0)
+                       | timings
+#endif
+                       ;
+       PRINTF ("PBR7: %08x  POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7);
+
+}
+
+#endif /* CONFIG_IDE_8xx_DIRECT */
+
+/* ------------------------------------------------------------------------- */
+
+static void __inline__
+outb(int dev, int port, unsigned char val)
+{
+       /* Ensure I/O operations complete */
+       __asm__ volatile("eieio");
+       *((uchar *)(ATA_CURR_BASE(dev)+port)) = val;
+#if 0
+       printf ("OUTB: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
+#endif
+}
+
+static unsigned char __inline__
+inb(int dev, int port)
+{
+       uchar val;
+       /* Ensure I/O operations complete */
+       __asm__ volatile("eieio");
+       val = *((uchar *)(ATA_CURR_BASE(dev)+port));
+#if 0
+       printf ("INB: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
+#endif
+       return (val);
+}
+
+__inline__ unsigned ld_le16(const volatile unsigned short *addr)
+{
+       unsigned val;
+
+       __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r"(val) : "r"(addr), "m"(*addr));
+       return val;
+}
+
+static void
+input_swap_data(int dev, ulong *sect_buf, int words)
+{
+       volatile ushort *pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
+       ushort  *dbuf = (ushort *)sect_buf;
+
+       while (words--) {
+               *dbuf++ = ld_le16(pbuf);
+               *dbuf++ = ld_le16(pbuf);
+       }
+}
+
+static void
+output_data(int dev, ulong *sect_buf, int words)
+{
+       ushort  *dbuf;
+       volatile ushort *pbuf;
+
+       pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
+       dbuf = (ushort *)sect_buf;
+       while (words--) {
+               __asm__ volatile ("eieio");
+               *pbuf = *dbuf++;
+               __asm__ volatile ("eieio");
+               *pbuf = *dbuf++;
+       }
+}
+
+static void
+input_data(int dev, ulong *sect_buf, int words)
+{
+       ushort  *dbuf;
+       volatile ushort *pbuf;
+
+       pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
+       dbuf = (ushort *)sect_buf;
+       while (words--) {
+               __asm__ volatile ("eieio");
+               *dbuf++ = *pbuf;
+               __asm__ volatile ("eieio");
+               *dbuf++ = *pbuf;
+       }
+}
+
+/* -------------------------------------------------------------------------
+ */
+static void ide_ident (block_dev_desc_t *dev_desc)
+{
+       ulong iobuf[ATA_SECTORWORDS];
+       unsigned char c;
+       hd_driveid_t *iop = (hd_driveid_t *)iobuf;
+
+#if 0
+       int mode, cycle_time;
+#endif
+       int device;
+       device=dev_desc->dev;
+       printf ("  Device %d: ", device);
+
+       ide_led (DEVICE_LED(device), 1);        /* LED on       */
+       /* Select device
+        */
+       outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+       dev_desc->if_type=IF_TYPE_IDE;
+#ifdef CONFIG_ATAPI
+       /* check signature */
+       if ((inb(device,ATA_SECT_CNT)==0x01) &&
+                (inb(device,ATA_SECT_NUM)==0x01) &&
+                (inb(device,ATA_CYL_LOW)==0x14) &&
+                (inb(device,ATA_CYL_HIGH)==0xEB)) {
+               /* ATAPI Signature found */
+               dev_desc->if_type=IF_TYPE_ATAPI;
+               /* Start Ident Command
+                */
+               outb (device, ATA_COMMAND, ATAPI_CMD_IDENT);
+               /*
+                * Wait for completion - ATAPI devices need more time
+                * to become ready
+                */
+               c = ide_wait (device, ATAPI_TIME_OUT);
+       }
+       else
+#endif
+       {
+               /* Start Ident Command
+                */
+               outb (device, ATA_COMMAND, ATA_CMD_IDENT);
+
+               /* Wait for completion
+                */
+               c = ide_wait (device, IDE_TIME_OUT);
+       }
+       ide_led (DEVICE_LED(device), 0);        /* LED off      */
+
+       if (((c & ATA_STAT_DRQ) == 0) ||
+           ((c & (ATA_STAT_FAULT|ATA_STAT_ERR)) != 0) ) {
+               dev_desc->type=DEV_TYPE_UNKNOWN;
+               return;
+       }
+
+       input_swap_data (device, iobuf, ATA_SECTORWORDS);
+
+       ident_cpy (dev_desc->revision, iop->fw_rev, sizeof(dev_desc->revision));
+       ident_cpy (dev_desc->vendor, iop->model, sizeof(dev_desc->vendor));
+       ident_cpy (dev_desc->product, iop->serial_no, sizeof(dev_desc->product));
+
+       if ((iop->config & 0x0080)==0x0080)
+               dev_desc->removable = 1;
+       else
+               dev_desc->removable = 0;
+
+#if 0
+       /*
+        * Drive PIO mode autoselection
+        */
+       mode = iop->tPIO;
+
+       printf ("tPIO = 0x%02x = %d\n",mode, mode);
+       if (mode > 2) {         /* 2 is maximum allowed tPIO value */
+               mode = 2;
+               PRINTF ("Override tPIO -> 2\n");
+       }
+       if (iop->field_valid & 2) {     /* drive implements ATA2? */
+               PRINTF ("Drive implements ATA2\n");
+               if (iop->capability & 8) {      /* drive supports use_iordy? */
+                       cycle_time = iop->eide_pio_iordy;
+               } else {
+                       cycle_time = iop->eide_pio;
+               }
+               PRINTF ("cycle time = %d\n", cycle_time);
+               mode = 4;
+               if (cycle_time > 120) mode = 3; /* 120 ns for PIO mode 4 */
+               if (cycle_time > 180) mode = 2; /* 180 ns for PIO mode 3 */
+               if (cycle_time > 240) mode = 1; /* 240 ns for PIO mode 4 */
+               if (cycle_time > 383) mode = 0; /* 383 ns for PIO mode 4 */
+       }
+       printf ("PIO mode to use: PIO %d\n", mode);
+#endif /* 0 */
+
+#ifdef CONFIG_ATAPI
+       if (dev_desc->if_type==IF_TYPE_ATAPI) {
+               atapi_inquiry(dev_desc);
+               return;
+       }
+#endif /* CONFIG_ATAPI */
+
+       /* swap shorts */
+       dev_desc->lba = (iop->lba_capacity << 16) | (iop->lba_capacity >> 16);
+       /* assuming HD */
+       dev_desc->type=DEV_TYPE_HARDDISK;
+       dev_desc->blksz=ATA_BLOCKSIZE;
+       dev_desc->lun=0; /* just to fill something in... */
+
+#if 0  /* only used to test the powersaving mode,
+        * if enabled, the drive goes after 5 sec
+        * in standby mode */
+       outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+       c = ide_wait (device, IDE_TIME_OUT);
+       outb (device, ATA_SECT_CNT, 1);
+       outb (device, ATA_LBA_LOW,  0);
+       outb (device, ATA_LBA_MID,  0);
+       outb (device, ATA_LBA_HIGH, 0);
+       outb (device, ATA_DEV_HD,   ATA_LBA             |
+                                   ATA_DEVICE(device));
+       outb (device, ATA_COMMAND,  0xe3);
+       udelay (50);
+       c = ide_wait (device, IDE_TIME_OUT);    /* can't take over 500 ms */
+#endif
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
+{
+       ulong n = 0;
+       unsigned char c;
+       unsigned char pwrsave=0; /* power save */
+
+       PRINTF ("ide_read dev %d start %lX, blocks %lX buffer at %lX\n",
+               device, blknr, blkcnt, (ulong)buffer);
+
+       ide_led (DEVICE_LED(device), 1);        /* LED on       */
+
+       /* Select device
+        */
+       outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+       c = ide_wait (device, IDE_TIME_OUT);
+
+       if (c & ATA_STAT_BUSY) {
+               printf ("IDE read: device %d not ready\n", device);
+               goto IDE_READ_E;
+       }
+
+       /* first check if the drive is in Powersaving mode, if yes,
+        * increase the timeout value */
+       outb (device, ATA_COMMAND,  ATA_CMD_CHK_PWR);
+       udelay (50);
+
+       c = ide_wait (device, IDE_TIME_OUT);    /* can't take over 500 ms */
+
+       if (c & ATA_STAT_BUSY) {
+               printf ("IDE read: device %d not ready\n", device);
+               goto IDE_READ_E;
+       }
+       if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
+               printf ("No Powersaving mode %X\n", c);
+       } else {
+               c = inb(device,ATA_SECT_CNT);
+               PRINTF("Powersaving %02X\n",c);
+               if(c==0)
+                       pwrsave=1;
+       }
+
+
+       while (blkcnt-- > 0) {
+
+               c = ide_wait (device, IDE_TIME_OUT);
+
+               if (c & ATA_STAT_BUSY) {
+                       printf ("IDE read: device %d not ready\n", device);
+                       break;
+               }
+
+               outb (device, ATA_SECT_CNT, 1);
+               outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
+               outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
+               outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
+               outb (device, ATA_DEV_HD,   ATA_LBA             |
+                                           ATA_DEVICE(device)  |
+                                           ((blknr >> 24) & 0xF) );
+               outb (device, ATA_COMMAND,  ATA_CMD_READ);
+
+               udelay (50);
+
+               if(pwrsave) {
+                       c = ide_wait (device, IDE_SPIN_UP_TIME_OUT);    /* may take up to 4 sec */
+                       pwrsave=0;
+               } else {
+                       c = ide_wait (device, IDE_TIME_OUT);    /* can't take over 500 ms */
+               }
+
+               if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) {
+                       printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
+                               device, blknr, c);
+                       break;
+               }
+
+               input_data (device, buffer, ATA_SECTORWORDS);
+               (void) inb (device, ATA_STATUS);        /* clear IRQ */
+
+               ++n;
+               ++blknr;
+               buffer += ATA_SECTORWORDS;
+       }
+IDE_READ_E:
+       ide_led (DEVICE_LED(device), 0);        /* LED off      */
+       return (n);
+}
+
+/* ------------------------------------------------------------------------- */
+
+
+ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)
+{
+       ulong n = 0;
+       unsigned char c;
+
+       ide_led (DEVICE_LED(device), 1);        /* LED on       */
+
+       /* Select device
+        */
+       outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+
+       while (blkcnt-- > 0) {
+
+               c = ide_wait (device, IDE_TIME_OUT);
+
+               if (c & ATA_STAT_BUSY) {
+                       printf ("IDE read: device %d not ready\n", device);
+                       goto WR_OUT;
+               }
+
+               outb (device, ATA_SECT_CNT, 1);
+               outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
+               outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
+               outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
+               outb (device, ATA_DEV_HD,   ATA_LBA             |
+                                           ATA_DEVICE(device)  |
+                                           ((blknr >> 24) & 0xF) );
+               outb (device, ATA_COMMAND,  ATA_CMD_WRITE);
+
+               udelay (50);
+
+               c = ide_wait (device, IDE_TIME_OUT);    /* can't take over 500 ms */
+
+               if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) {
+                       printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
+                               device, blknr, c);
+                       goto WR_OUT;
+               }
+
+               output_data (device, buffer, ATA_SECTORWORDS);
+               c = inb (device, ATA_STATUS);   /* clear IRQ */
+               ++n;
+               ++blknr;
+               buffer += ATA_SECTORWORDS;
+       }
+WR_OUT:
+       ide_led (DEVICE_LED(device), 0);        /* LED off      */
+       return (n);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * copy src to dest, skipping leading and trailing blanks and null
+ * terminate the string
+ */
+static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len)
+{
+       int start,end;
+
+       start=0;
+       while (start<len) {
+               if (src[start]!=' ')
+                       break;
+               start++;
+       }
+       end=len-1;
+       while (end>start) {
+               if (src[end]!=' ')
+                       break;
+               end--;
+       }
+       for ( ; start<=end; start++) {
+               *dest++=src[start];
+       }
+       *dest='\0';
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Wait until Busy bit is off, or timeout (in ms)
+ * Return last status
+ */
+static uchar ide_wait (int dev, ulong t)
+{
+       ulong delay = 10 * t;           /* poll every 100 us */
+       uchar c;
+
+       while ((c = inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
+               udelay (100);
+               if (delay-- == 0) {
+                       break;
+               }
+       }
+       return (c);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_IDE_RESET
+extern void ide_set_reset(int idereset);
+
+static void ide_reset (void)
+{
+#if defined(CFG_PB_12V_ENABLE) || defined(CFG_PB_IDE_MOTOR)
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#endif
+       int i;
+
+       curr_device = -1;
+       for (i=0; i<CFG_IDE_MAXBUS; ++i)
+               ide_bus_ok[i] = 0;
+       for (i=0; i<CFG_IDE_MAXDEVICE; ++i)
+               ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
+
+       ide_set_reset (1); /* assert reset */
+
+       WATCHDOG_RESET();
+
+#ifdef CFG_PB_12V_ENABLE
+       immr->im_cpm.cp_pbdat &= ~(CFG_PB_12V_ENABLE);  /* 12V Enable output OFF */
+       immr->im_cpm.cp_pbpar &= ~(CFG_PB_12V_ENABLE);
+       immr->im_cpm.cp_pbodr &= ~(CFG_PB_12V_ENABLE);
+       immr->im_cpm.cp_pbdir |=   CFG_PB_12V_ENABLE;
+
+       /* wait 500 ms for the voltage to stabilize
+        */
+       for (i=0; i<500; ++i) {
+               udelay (1000);
+       }
+
+       immr->im_cpm.cp_pbdat |=   CFG_PB_12V_ENABLE;   /* 12V Enable output ON */
+#endif /* CFG_PB_12V_ENABLE */
+
+#ifdef CFG_PB_IDE_MOTOR
+       /* configure IDE Motor voltage monitor pin as input */
+       immr->im_cpm.cp_pbpar &= ~(CFG_PB_IDE_MOTOR);
+       immr->im_cpm.cp_pbodr &= ~(CFG_PB_IDE_MOTOR);
+       immr->im_cpm.cp_pbdir &= ~(CFG_PB_IDE_MOTOR);
+
+       /* wait up to 1 s for the motor voltage to stabilize
+        */
+       for (i=0; i<1000; ++i) {
+               if ((immr->im_cpm.cp_pbdat & CFG_PB_IDE_MOTOR) != 0) {
+                       break;
+               }
+               udelay (1000);
+       }
+
+       if (i == 1000) {        /* Timeout */
+               printf ("\nWarning: 5V for IDE Motor missing\n");
+# ifdef CONFIG_STATUS_LED
+#  ifdef STATUS_LED_YELLOW
+               status_led_set  (STATUS_LED_YELLOW, STATUS_LED_ON );
+#  endif
+#  ifdef STATUS_LED_GREEN
+               status_led_set  (STATUS_LED_GREEN,  STATUS_LED_OFF);
+#  endif
+# endif        /* CONFIG_STATUS_LED */
+       }
+#endif /* CFG_PB_IDE_MOTOR */
+
+       WATCHDOG_RESET();
+
+       /* de-assert RESET signal */
+       ide_set_reset(0);
+
+       /* wait 250 ms */
+       for (i=0; i<250; ++i) {
+               udelay (1000);
+       }
+}
+
+#endif /* CONFIG_IDE_RESET */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_IDE_LED
+
+static uchar   led_buffer = 0;         /* Buffer for current LED status        */
+
+static void ide_led (uchar led, uchar status)
+{
+       uchar *led_port = LED_PORT;
+
+       if (status)     {               /* switch LED on        */
+               led_buffer |=  led;
+       } else {                        /* switch LED off       */
+               led_buffer &= ~led;
+       }
+
+       *led_port = led_buffer;
+}
+
+#endif /* CONFIG_IDE_LED */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_ATAPI
+/****************************************************************************
+ * ATAPI Support
+ */
+
+
+
+#undef ATAPI_DEBUG
+
+#ifdef ATAPI_DEBUG
+#define        AT_PRINTF(fmt,args...)  printf (fmt ,##args)
+#else
+#define AT_PRINTF(fmt,args...)
+#endif
+
+/* since ATAPI may use commands with not 4 bytes alligned length
+ * we have our own transfer functions, 2 bytes alligned */
+static void
+output_data_shorts(int dev, ushort *sect_buf, int shorts)
+{
+       ushort  *dbuf;
+       volatile ushort *pbuf;
+
+       pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
+       dbuf = (ushort *)sect_buf;
+       while (shorts--) {
+               __asm__ volatile ("eieio");
+               *pbuf = *dbuf++;
+       }
+}
+
+static void
+input_data_shorts(int dev, ushort *sect_buf, int shorts)
+{
+       ushort  *dbuf;
+       volatile ushort *pbuf;
+
+       pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
+       dbuf = (ushort *)sect_buf;
+       while (shorts--) {
+               __asm__ volatile ("eieio");
+               *dbuf++ = *pbuf;
+       }
+}
+
+/*
+ * Wait until (Status & mask) == res, or timeout (in ms)
+ * Return last status
+ * This is used since some ATAPI CD ROMs clears their Busy Bit first
+ * and then they set their DRQ Bit
+ */
+static uchar atapi_wait_mask (int dev, ulong t,uchar mask, uchar res)
+{
+       ulong delay = 10 * t;           /* poll every 100 us */
+       uchar c;
+
+       c = inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */
+       while (((c = inb(dev, ATA_STATUS)) & mask)
+                       != res) {
+               /* break if error occurs (doesn't make sense to wait more) */
+               if((c & ATA_STAT_ERR)==ATA_STAT_ERR)
+                       break;
+               udelay (100);
+               if (delay-- == 0) {
+                       break;
+               }
+       }
+       return (c);
+}
+
+/*
+ * issue an atapi command
+ */
+unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned char * buffer,int buflen)
+{
+       unsigned char c,err,mask,res;
+       int n;
+       ide_led (DEVICE_LED(device), 1);        /* LED on       */
+
+       /* Select device
+        */
+       mask = ATA_STAT_BUSY|ATA_STAT_DRQ;
+       res = 0;
+       outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+       c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
+       if ((c & mask) != res) {
+               printf ("ATAPI_ISSUE: device %d not ready status %X\n", device,c);
+               err=0xFF;
+               goto AI_OUT;
+       }
+       /* write taskfile */
+       outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
+       outb (device, ATA_CYL_LOW,  (unsigned char)(buflen & 0xFF));
+       outb (device, ATA_CYL_HIGH, (unsigned char)((buflen<<8) & 0xFF));
+       outb (device, ATA_DEV_HD,   ATA_LBA | ATA_DEVICE(device));
+
+       outb (device, ATA_COMMAND,  ATAPI_CMD_PACKET);
+       udelay (50);
+
+       mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR;
+       res = ATA_STAT_DRQ;
+       c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
+
+       if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */
+               printf ("ATTAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",device,c);
+               err=0xFF;
+               goto AI_OUT;
+       }
+
+       output_data_shorts (device, (unsigned short *)ccb,ccblen/2); /* write command block */
+       /* ATAPI Command written wait for completition */
+       udelay (5000); /* device must set bsy */
+
+       mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR;
+       /* if no data wait for DRQ = 0 BSY = 0
+        * if data wait for DRQ = 1 BSY = 0 */
+       res=0;
+       if(buflen)
+               res = ATA_STAT_DRQ;
+       c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
+       if ((c & mask) != res ) {
+               if (c & ATA_STAT_ERR) {
+                       err=(inb(device,ATA_ERROR_REG))>>4;
+                       AT_PRINTF("atapi_issue 1 returned sense key %X status %02X\n",err,c);
+               } else {
+                       printf ("ATTAPI_ISSUE: (no DRQ) after sending ccb (%x)  status 0x%02x\n", ccb[0],c);
+                       err=0xFF;
+               }
+               goto AI_OUT;
+       }
+       n=inb(device, ATA_CYL_HIGH);
+       n<<=8;
+       n+=inb(device, ATA_CYL_LOW);
+       if(n>buflen) {
+               printf("ERROR, transfer bytes %d requested only %d\n",n,buflen);
+               err=0xff;
+               goto AI_OUT;
+       }
+       if((n==0)&&(buflen<0)) {
+               printf("ERROR, transfer bytes %d requested %d\n",n,buflen);
+               err=0xff;
+               goto AI_OUT;
+       }
+       if(n!=buflen) {
+               AT_PRINTF("WARNING, transfer bytes %d not equal with requested %d\n",n,buflen);
+       }
+       if(n!=0) { /* data transfer */
+               AT_PRINTF("ATAPI_ISSUE: %d Bytes to transfer\n",n);
+                /* we transfer shorts */
+               n>>=1;
+               /* ok now decide if it is an in or output */
+               if ((inb(device, ATA_SECT_CNT)&0x02)==0) {
+                       AT_PRINTF("Write to device\n");
+                       output_data_shorts(device,(unsigned short *)buffer,n);
+               } else {
+                       AT_PRINTF("Read from device @ %p shorts %d\n",buffer,n);
+                       input_data_shorts(device,(unsigned short *)buffer,n);
+               }
+       }
+       udelay(5000); /* seems that some CD ROMs need this... */
+       mask = ATA_STAT_BUSY|ATA_STAT_ERR;
+       res=0;
+       c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
+       if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
+               err=(inb(device,ATA_ERROR_REG) >> 4);
+               AT_PRINTF("atapi_issue 2 returned sense key %X status %X\n",err,c);
+       } else {
+               err = 0;
+       }
+AI_OUT:
+       ide_led (DEVICE_LED(device), 0);        /* LED off      */
+       return (err);
+}
+
+/*
+ * sending the command to atapi_issue. If an status other than good
+ * returns, an request_sense will be issued
+ */
+
+#define ATAPI_DRIVE_NOT_READY  100
+#define ATAPI_UNIT_ATTN                10
+
+unsigned char atapi_issue_autoreq (int device,
+                                  unsigned char* ccb,
+                                  int ccblen,
+                                  unsigned char *buffer,
+                                  int buflen)
+{
+       unsigned char sense_data[18],sense_ccb[12];
+       unsigned char res,key,asc,ascq;
+       int notready,unitattn;
+
+       unitattn=ATAPI_UNIT_ATTN;
+       notready=ATAPI_DRIVE_NOT_READY;
+
+retry:
+       res= atapi_issue(device,ccb,ccblen,buffer,buflen);
+       if (res==0)
+               return (0); /* Ok */
+
+       if (res==0xFF)
+               return (0xFF); /* error */
+
+       AT_PRINTF("(auto_req)atapi_issue returned sense key %X\n",res);
+
+       memset(sense_ccb,0,sizeof(sense_ccb));
+       memset(sense_data,0,sizeof(sense_data));
+       sense_ccb[0]=ATAPI_CMD_REQ_SENSE;
+       sense_ccb[4]=18; /* allocation Legnth */
+
+       res=atapi_issue(device,sense_ccb,12,sense_data,18);
+       key=(sense_data[2]&0xF);
+       asc=(sense_data[12]);
+       ascq=(sense_data[13]);
+
+       AT_PRINTF("ATAPI_CMD_REQ_SENSE returned %x\n",res);
+       AT_PRINTF(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",
+               sense_data[0],
+               key,
+               asc,
+               ascq);
+
+       if((key==0))
+               return 0; /* ok device ready */
+
+       if((key==6)|| (asc==0x29) || (asc==0x28)) { /* Unit Attention */
+               if(unitattn-->0) {
+                       udelay(200*1000);
+                       goto retry;
+               }
+               printf("Unit Attention, tried %d\n",ATAPI_UNIT_ATTN);
+               goto error;
+       }
+       if((asc==0x4) && (ascq==0x1)) { /* not ready, but will be ready soon */
+               if (notready-->0) {
+                       udelay(200*1000);
+                       goto retry;
+               }
+               printf("Drive not ready, tried %d times\n",ATAPI_DRIVE_NOT_READY);
+               goto error;
+       }
+       if(asc==0x3a) {
+               AT_PRINTF("Media not present\n");
+               goto error;
+       }
+       printf ("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq);
+error:
+       AT_PRINTF ("ERROR Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq);
+       return (0xFF);
+}
+
+
+
+static void    atapi_inquiry(block_dev_desc_t * dev_desc)
+{
+       unsigned char ccb[12]; /* Command descriptor block */
+       unsigned char iobuf[64]; /* temp buf */
+       unsigned char c;
+       int device;
+
+       device=dev_desc->dev;
+       dev_desc->type=DEV_TYPE_UNKNOWN; /* not yet valid */
+       dev_desc->block_read=atapi_read;
+
+       memset(ccb,0,sizeof(ccb));
+       memset(iobuf,0,sizeof(iobuf));
+
+       ccb[0]=ATAPI_CMD_INQUIRY;
+       ccb[4]=40; /* allocation Legnth */
+       c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,40);
+
+       AT_PRINTF("ATAPI_CMD_INQUIRY returned %x\n",c);
+       if (c!=0)
+               return;
+
+       /* copy device ident strings */
+       ident_cpy(dev_desc->vendor,&iobuf[8],8);
+       ident_cpy(dev_desc->product,&iobuf[16],16);
+       ident_cpy(dev_desc->revision,&iobuf[32],5);
+
+       dev_desc->lun=0;
+       dev_desc->lba=0;
+       dev_desc->blksz=0;
+       dev_desc->type=iobuf[0] & 0x1f;
+
+       if ((iobuf[1]&0x80)==0x80)
+               dev_desc->removable = 1;
+       else
+               dev_desc->removable = 0;
+
+       memset(ccb,0,sizeof(ccb));
+       memset(iobuf,0,sizeof(iobuf));
+       ccb[0]=ATAPI_CMD_START_STOP;
+       ccb[4]=0x03; /* start */
+
+       c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0);
+
+       AT_PRINTF("ATAPI_CMD_START_STOP returned %x\n",c);
+       if (c!=0)
+               return;
+
+       memset(ccb,0,sizeof(ccb));
+       memset(iobuf,0,sizeof(iobuf));
+       c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0);
+
+       AT_PRINTF("ATAPI_CMD_UNIT_TEST_READY returned %x\n",c);
+       if (c!=0)
+               return;
+
+       memset(ccb,0,sizeof(ccb));
+       memset(iobuf,0,sizeof(iobuf));
+       ccb[0]=ATAPI_CMD_READ_CAP;
+       c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,8);
+       AT_PRINTF("ATAPI_CMD_READ_CAP returned %x\n",c);
+       if (c!=0)
+               return;
+
+       AT_PRINTF("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",
+               iobuf[0],iobuf[1],iobuf[2],iobuf[3],
+               iobuf[4],iobuf[5],iobuf[6],iobuf[7]);
+
+       dev_desc->lba  =((unsigned long)iobuf[0]<<24) +
+                       ((unsigned long)iobuf[1]<<16) +
+                       ((unsigned long)iobuf[2]<< 8) +
+                       ((unsigned long)iobuf[3]);
+       dev_desc->blksz=((unsigned long)iobuf[4]<<24) +
+                       ((unsigned long)iobuf[5]<<16) +
+                       ((unsigned long)iobuf[6]<< 8) +
+                       ((unsigned long)iobuf[7]);
+       return;
+}
+
+
+/*
+ * atapi_read:
+ * we transfer only one block per command, since the multiple DRQ per
+ * command is not yet implemented
+ */
+#define ATAPI_READ_MAX_BYTES   2048    /* we read max 2kbytes */
+#define ATAPI_READ_BLOCK_SIZE  2048    /* assuming CD part */
+#define ATAPI_READ_MAX_BLOCK ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE        /* max blocks */
+
+ulong atapi_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
+{
+       ulong n = 0;
+       unsigned char ccb[12]; /* Command descriptor block */
+       ulong cnt;
+
+       AT_PRINTF("atapi_read dev %d start %lX, blocks %lX buffer at %lX\n",
+               device, blknr, blkcnt, (ulong)buffer);
+
+       do {
+               if (blkcnt>ATAPI_READ_MAX_BLOCK) {
+                       cnt=ATAPI_READ_MAX_BLOCK;
+               } else {
+                       cnt=blkcnt;
+               }
+               ccb[0]=ATAPI_CMD_READ_12;
+               ccb[1]=0; /* reserved */
+               ccb[2]=(unsigned char) (blknr>>24) & 0xFF; /* MSB Block */
+               ccb[3]=(unsigned char) (blknr>>16) & 0xFF; /*  */
+               ccb[4]=(unsigned char) (blknr>> 8) & 0xFF;
+               ccb[5]=(unsigned char)  blknr      & 0xFF; /* LSB Block */
+               ccb[6]=(unsigned char) (cnt  >>24) & 0xFF; /* MSB Block count */
+               ccb[7]=(unsigned char) (cnt  >>16) & 0xFF;
+               ccb[8]=(unsigned char) (cnt  >> 8) & 0xFF;
+               ccb[9]=(unsigned char)  cnt        & 0xFF; /* LSB Block */
+               ccb[10]=0; /* reserved */
+               ccb[11]=0; /* reserved */
+
+               if (atapi_issue_autoreq(device,ccb,12,
+                                       (unsigned char *)buffer,
+                                       cnt*ATAPI_READ_BLOCK_SIZE) == 0xFF) {
+                       return (n);
+               }
+               n+=cnt;
+               blkcnt-=cnt;
+               blknr+=cnt;
+               buffer+=cnt*(ATAPI_READ_BLOCK_SIZE/4); /* ulong blocksize in ulong */
+       } while (blkcnt > 0);
+       return (n);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#endif /* CONFIG_ATAPI */
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_IDE */
diff --git a/common/cmd_immap.c b/common/cmd_immap.c
new file mode 100644 (file)
index 0000000..443335b
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * (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
+ */
+
+/*
+ * MPC8xx/MPC8260 Internal Memory Map Functions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cmd_immap.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_IMMAP) && \
+    (defined(CONFIG_8xx) || defined(CONFIG_8260))
+
+#if defined(CONFIG_8xx)
+#include <asm/8xx_immap.h>
+#include <commproc.h>
+#elif defined(CONFIG_8260)
+#include <asm/immap_8260.h>
+#include <asm/cpm_8260.h>
+#include <asm/iopin_8260.h>
+#endif
+
+static void
+unimplemented ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       printf ("Sorry, but the '%s' command has not been implemented\n",
+               cmdtp->name);
+}
+
+int
+do_siuinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+#if defined(CONFIG_8xx)
+       volatile sysconf8xx_t *sc = &immap->im_siu_conf;
+#elif defined(CONFIG_8260)
+       volatile sysconf8260_t *sc = &immap->im_siu_conf;
+#endif
+
+       printf ("SIUMCR= %08x SYPCR = %08x\n", sc->sc_siumcr, sc->sc_sypcr);
+#if defined(CONFIG_8xx)
+       printf ("SWT   = %08x\n", sc->sc_swt);
+       printf ("SIPEND= %08x SIMASK= %08x\n", sc->sc_sipend, sc->sc_simask);
+       printf ("SIEL  = %08x SIVEC = %08x\n", sc->sc_siel, sc->sc_sivec);
+       printf ("TESR  = %08x SDCR  = %08x\n", sc->sc_tesr, sc->sc_sdcr);
+#elif defined(CONFIG_8260)
+       printf ("BCR   = %08x\n", sc->sc_bcr);
+       printf ("P_ACR =       %02x P_ALRH= %08x P_ALRL= %08x\n",
+               sc->sc_ppc_acr, sc->sc_ppc_alrh, sc->sc_ppc_alrl);
+       printf ("L_ACR =       %02x L_ALRH= %08x L_ALRL= %08x\n",
+               sc->sc_lcl_acr, sc->sc_lcl_alrh, sc->sc_lcl_alrl);
+       printf ("PTESR1= %08x PTESR2= %08x\n", sc->sc_tescr1, sc->sc_tescr2);
+       printf ("LTESR1= %08x LTESR2= %08x\n", sc->sc_ltescr1, sc->sc_ltescr2);
+       printf ("PDTEA = %08x PDTEM =       %02x\n", sc->sc_pdtea, sc->sc_pdtem);
+       printf ("LDTEA = %08x LDTEM =       %02x\n", sc->sc_ldtea, sc->sc_ldtem);
+#endif
+       return 0;
+}
+
+int
+do_memcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+#if defined(CONFIG_8xx)
+       volatile memctl8xx_t *memctl = &immap->im_memctl;
+       int nbanks = 8;
+#elif defined(CONFIG_8260)
+       volatile memctl8260_t *memctl = &immap->im_memctl;
+       int nbanks = 12;
+#endif
+       volatile uint *p = &memctl->memc_br0;
+       int i;
+
+       for (i = 0; i < nbanks; i++, p += 2) {
+               if (i < 10) {
+                       printf ("BR%d   = %08x OR%d   = %08x\n",
+                               i, p[0], i, p[1]);
+               } else {
+                       printf ("BR%d  = %08x OR%d  = %08x\n",
+                               i, p[0], i, p[1]);
+               }
+       }
+
+       printf ("MAR   = %08x", memctl->memc_mar);
+#if defined(CONFIG_8xx)
+       printf (" MCR   = %08x\n", memctl->memc_mcr);
+#elif defined(CONFIG_8260)
+       printf ("\n");
+#endif
+       printf ("MAMR  = %08x MBMR  = %08x",
+               memctl->memc_mamr, memctl->memc_mbmr);
+#if defined(CONFIG_8xx)
+       printf ("\nMSTAT =     %04x\n", memctl->memc_mstat);
+#elif defined(CONFIG_8260)
+       printf (" MCMR  = %08x\n", memctl->memc_mcmr);
+#endif
+       printf ("MPTPR =     %04x MDR   = %08x\n",
+               memctl->memc_mptpr, memctl->memc_mdr);
+#if defined(CONFIG_8260)
+       printf ("PSDMR = %08x LSDMR = %08x\n",
+               memctl->memc_psdmr, memctl->memc_lsdmr);
+       printf ("PURT  =       %02x PSRT  =       %02x\n",
+               memctl->memc_purt, memctl->memc_psrt);
+       printf ("LURT  =       %02x LSRT  =       %02x\n",
+               memctl->memc_lurt, memctl->memc_lsrt);
+       printf ("IMMR  = %08x\n", memctl->memc_immr);
+#endif
+       return 0;
+}
+
+int
+do_sitinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+
+#ifdef CONFIG_8260
+int
+do_icinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+#endif
+
+int
+do_carinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+
+static int counter;
+
+static void
+header(void)
+{
+       char *data = "\
+       --------------------------------        --------------------------------\
+       00000000001111111111222222222233        00000000001111111111222222222233\
+       01234567890123456789012345678901        01234567890123456789012345678901\
+       --------------------------------        --------------------------------\
+    ";
+       int i;
+
+       if (counter % 2)
+       putc('\n');
+       counter = 0;
+
+       for (i = 0; i < 4; i++, data += 79)
+               printf("%.79s\n", data);
+}
+
+static void binary (char *label, uint value, int nbits)
+{
+       uint mask = 1 << (nbits - 1);
+       int i, second = (counter++ % 2);
+
+       if (second)
+               putc (' ');
+       puts (label);
+       for (i = 32 + 1; i != nbits; i--)
+               putc (' ');
+
+       while (mask != 0) {
+               if (value & mask)
+                       putc ('1');
+               else
+                       putc ('0');
+               mask >>= 1;
+       }
+
+       if (second)
+               putc ('\n');
+}
+
+#if defined(CONFIG_8xx)
+#define PA_NBITS       16
+#define PA_NB_ODR       8
+#define PB_NBITS       18
+#define PB_NB_ODR      16
+#define PC_NBITS       12
+#define PD_NBITS       13
+#elif defined(CONFIG_8260)
+#define PA_NBITS       32
+#define PA_NB_ODR      32
+#define PB_NBITS       28
+#define PB_NB_ODR      28
+#define PC_NBITS       32
+#define PD_NBITS       28
+#endif
+
+int
+do_iopinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+#if defined(CONFIG_8xx)
+       volatile iop8xx_t *iop = &immap->im_ioport;
+       volatile ushort *l, *r;
+#elif defined(CONFIG_8260)
+       volatile iop8260_t *iop = &immap->im_ioport;
+       volatile uint *l, *r;
+#endif
+       volatile uint *R;
+
+       counter = 0;
+       header ();
+
+       /*
+        * Ports A & B
+        */
+
+#if defined(CONFIG_8xx)
+       l = &iop->iop_padir;
+       R = &immap->im_cpm.cp_pbdir;
+#elif defined(CONFIG_8260)
+       l = &iop->iop_pdira;
+       R = &iop->iop_pdirb;
+#endif
+       binary ("PA_DIR", *l++, PA_NBITS);
+       binary ("PB_DIR", *R++, PB_NBITS);
+       binary ("PA_PAR", *l++, PA_NBITS);
+       binary ("PB_PAR", *R++, PB_NBITS);
+#if defined(CONFIG_8260)
+       binary ("PA_SOR", *l++, PA_NBITS);
+       binary ("PB_SOR", *R++, PB_NBITS);
+#endif
+       binary ("PA_ODR", *l++, PA_NB_ODR);
+       binary ("PB_ODR", *R++, PB_NB_ODR);
+       binary ("PA_DAT", *l++, PA_NBITS);
+       binary ("PB_DAT", *R++, PB_NBITS);
+
+       header ();
+
+       /*
+        * Ports C & D
+        */
+
+#if defined(CONFIG_8xx)
+       l = &iop->iop_pcdir;
+       r = &iop->iop_pddir;
+#elif defined(CONFIG_8260)
+       l = &iop->iop_pdirc;
+       r = &iop->iop_pdird;
+#endif
+       binary ("PC_DIR", *l++, PC_NBITS);
+       binary ("PD_DIR", *r++, PD_NBITS);
+       binary ("PC_PAR", *l++, PC_NBITS);
+       binary ("PD_PAR", *r++, PD_NBITS);
+#if defined(CONFIG_8xx)
+       binary ("PC_SO ", *l++, PC_NBITS);
+       binary ("      ", 0, 0);
+       r++;
+#elif defined(CONFIG_8260)
+       binary ("PC_SOR", *l++, PC_NBITS);
+       binary ("PD_SOR", *r++, PD_NBITS);
+       binary ("PC_ODR", *l++, PC_NBITS);
+       binary ("PD_ODR", *r++, PD_NBITS);
+#endif
+       binary ("PC_DAT", *l++, PC_NBITS);
+       binary ("PD_DAT", *r++, PD_NBITS);
+#if defined(CONFIG_8xx)
+       binary ("PC_INT", *l++, PC_NBITS);
+#endif
+
+       header ();
+       return 0;
+}
+
+/*
+ * set the io pins
+ * this needs a clean up for smaller tighter code
+ * use *uint and set the address based on cmd + port
+ */
+int
+do_iopset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+#if defined(CONFIG_8260)
+       uint rcode = 0;
+       static uint port = 0;
+       static uint pin = 0;
+       static uint value = 0;
+       static enum { DIR, PAR, SOR, ODR, DAT } cmd = DAT;
+       iopin_t iopin;
+
+       if (argc != 5) {
+               printf ("iopset PORT PIN CMD VALUE\n");
+               return 1;
+       }
+       port = argv[1][0] - 'A';
+       if (port > 3)
+               port -= 0x20;
+       if (port > 3)
+               rcode = 1;
+       pin = simple_strtol (argv[2], NULL, 10);
+       if (pin > 31)
+               rcode = 1;
+
+
+       switch (argv[3][0]) {
+       case 'd':
+               if (argv[3][1] == 'a')
+                       cmd = DAT;
+               else if (argv[3][1] == 'i')
+                       cmd = DIR;
+               else
+                       rcode = 1;
+               break;
+       case 'p':
+               cmd = PAR;
+               break;
+       case 'o':
+               cmd = ODR;
+               break;
+       case 's':
+               cmd = SOR;
+               break;
+       default:
+               printf ("iopset: unknown command %s\n", argv[3]);
+               rcode = 1;
+       }
+       if (argv[4][0] == '1')
+               value = 1;
+       else if (argv[4][0] == '0')
+               value = 0;
+       else
+               rcode = 1;
+       if (rcode == 0) {
+               iopin.port = port;
+               iopin.pin = pin;
+               switch (cmd) {
+               case DIR:
+                       if (value)
+                               iopin_set_out (&iopin);
+                       else
+                               iopin_set_in (&iopin);
+                       break;
+               case PAR:
+                       if (value)
+                               iopin_set_ded (&iopin);
+                       else
+                               iopin_set_gen (&iopin);
+                       break;
+               case SOR:
+                       if (value)
+                               iopin_set_opt2 (&iopin);
+                       else
+                               iopin_set_opt1 (&iopin);
+                       break;
+               case ODR:
+                       if (value)
+                               iopin_set_odr (&iopin);
+                       else
+                               iopin_set_act (&iopin);
+                       break;
+               case DAT:
+                       if (value)
+                               iopin_set_high (&iopin);
+                       else
+                               iopin_set_low (&iopin);
+                       break;
+               }
+
+       }
+       return rcode;
+#else
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+#endif
+}
+
+int
+do_dmainfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+
+int
+do_fccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+
+static void prbrg (int n, uint val)
+{
+       uint extc = (val >> 14) & 3;
+       uint cd = (val & CPM_BRG_CD_MASK) >> 1;
+       uint div16 = (val & CPM_BRG_DIV16) != 0;
+
+#if defined(CONFIG_8xx)
+       DECLARE_GLOBAL_DATA_PTR;
+       ulong clock = gd->cpu_clk;
+#elif defined(CONFIG_8260)
+       DECLARE_GLOBAL_DATA_PTR;
+       ulong clock = gd->brg_clk;
+#endif
+
+       printf ("BRG%d:", n);
+
+       if (val & CPM_BRG_RST)
+               puts (" RESET");
+       else
+               puts ("      ");
+
+       if (val & CPM_BRG_EN)
+               puts ("  ENABLED");
+       else
+               puts (" DISABLED");
+
+       printf (" EXTC=%d", extc);
+
+       if (val & CPM_BRG_ATB)
+               puts (" ATB");
+       else
+               puts ("    ");
+
+       printf (" DIVIDER=%4d", cd);
+       if (extc == 0 && cd != 0) {
+               uint baudrate;
+
+               if (div16)
+                       baudrate = (clock / 16) / (cd + 1);
+               else
+                       baudrate = clock / (cd + 1);
+
+               printf ("=%6d bps", baudrate);
+       } else {
+               puts ("           ");
+       }
+
+       if (val & CPM_BRG_DIV16)
+               puts (" DIV16");
+       else
+               puts ("      ");
+
+       putc ('\n');
+}
+
+int
+do_brginfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+#if defined(CONFIG_8xx)
+       volatile cpm8xx_t *cp = &immap->im_cpm;
+       volatile uint *p = &cp->cp_brgc1;
+#elif defined(CONFIG_8260)
+       volatile uint *p = &immap->im_brgc1;
+#endif
+       int i = 1;
+
+       while (i <= 4)
+               prbrg (i++, *p++);
+
+#if defined(CONFIG_8260)
+       p = &immap->im_brgc5;
+       while (i <= 8)
+               prbrg (i++, *p++);
+#endif
+       return 0;
+}
+
+int
+do_i2cinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+#if defined(CONFIG_8xx)
+       volatile i2c8xx_t *i2c = &immap->im_i2c;
+       volatile cpm8xx_t *cp = &immap->im_cpm;
+       volatile iic_t *iip = (iic_t *) & cp->cp_dparam[PROFF_IIC];
+#elif defined(CONFIG_8260)
+       volatile i2c8260_t *i2c = &immap->im_i2c;
+       volatile iic_t *iip;
+       uint dpaddr;
+
+       dpaddr = *((unsigned short *) (&immap->im_dprambase[PROFF_I2C_BASE]));
+       if (dpaddr == 0)
+               iip = NULL;
+       else
+               iip = (iic_t *) & immap->im_dprambase[dpaddr];
+#endif
+
+       printf ("I2MOD = %02x I2ADD = %02x\n", i2c->i2c_i2mod, i2c->i2c_i2add);
+       printf ("I2BRG = %02x I2COM = %02x\n", i2c->i2c_i2brg, i2c->i2c_i2com);
+       printf ("I2CER = %02x I2CMR = %02x\n", i2c->i2c_i2cer, i2c->i2c_i2cmr);
+
+       if (iip == NULL)
+               printf ("i2c parameter ram not allocated\n");
+       else {
+               printf ("RBASE = %08x TBASE = %08x\n",
+                       iip->iic_rbase, iip->iic_tbase);
+               printf ("RFCR  =       %02x TFCR  =       %02x\n",
+                       iip->iic_rfcr, iip->iic_tfcr);
+               printf ("MRBLR =     %04x\n", iip->iic_mrblr);
+               printf ("RSTATE= %08x RDP   = %08x\n",
+                       iip->iic_rstate, iip->iic_rdp);
+               printf ("RBPTR =     %04x RBC   =     %04x\n",
+                       iip->iic_rbptr, iip->iic_rbc);
+               printf ("RXTMP = %08x\n", iip->iic_rxtmp);
+               printf ("TSTATE= %08x TDP   = %08x\n",
+                       iip->iic_tstate, iip->iic_tdp);
+               printf ("TBPTR =     %04x TBC   =     %04x\n",
+                       iip->iic_tbptr, iip->iic_tbc);
+               printf ("TXTMP = %08x\n", iip->iic_txtmp);
+       }
+       return 0;
+}
+
+int
+do_sccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+
+int
+do_smcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+
+int
+do_spiinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+
+int
+do_muxinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+
+int
+do_siinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+
+int
+do_mccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unimplemented (cmdtp, flag, argc, argv);
+       return 0;
+}
+#endif /* CFG_CMD_IMMAP && (CONFIG_8xx || CONFIG_8260) */
diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c
new file mode 100644 (file)
index 0000000..fc1d9c4
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * (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
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <cmd_boot.h>
+#include <cmd_autoscript.h>
+#include <s_record.h>
+#include <net.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
+
+#include <jffs2/jffs2.h>
+static int part_num=0;
+
+#ifndef CFG_JFFS_CUSTOM_PART
+
+static struct part_info part;
+
+struct part_info*
+jffs2_part_info(int part_num)
+{
+       extern flash_info_t flash_info[];       /* info for FLASH chips */
+       int i;
+
+       if(part_num==0){
+
+               if(part.usr_priv==(void*)1)
+                       return &part;
+
+               memset(&part, 0, sizeof(part));
+
+#if defined(CFG_JFFS2_FIRST_SECTOR)
+               part.offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR];
+#else
+               part.offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[0];
+#endif
+
+               /* Figure out flash partition size */
+               for (i = CFG_JFFS2_FIRST_BANK; i < CFG_JFFS2_NUM_BANKS+CFG_JFFS2_FIRST_BANK; i++)
+                       part.size += flash_info[i].size;
+
+#if defined(CFG_JFFS2_FIRST_SECTOR) && (CFG_JFFS2_FIRST_SECTOR > 0)
+               part.size -=
+                       flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR] -
+                       flash_info[CFG_JFFS2_FIRST_BANK].start[0];
+#endif
+
+               /* unused in current jffs2 loader */
+               part.erasesize = 0;
+
+               /* Mark the struct as ready */
+               part.usr_priv=(void*)1;
+
+               return &part;
+       }
+       return 0;
+}
+#endif /* ifndef CFG_JFFS_CUSTOM_PART */
+int
+do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       char *filename = "pImage";
+       ulong offset = CFG_LOAD_ADDR;
+       int size;
+       struct part_info *part;
+
+       if (argc == 2) {
+               filename = argv[1];
+       }
+       if (argc == 3) {
+               offset = simple_strtoul(argv[1], NULL, 16);
+               filename = argv[2];
+       }
+
+       if (0 != (part=jffs2_part_info(part_num))){
+
+               printf("### JFFS2 loading '%s' to 0x%lx\n", filename, offset);
+               size = jffs2_1pass_load((char *)offset, part, filename);
+
+               if (size > 0) {
+                       char buf[10];
+                       printf("### JFFS2 load complete: %d bytes loaded to 0x%lx\n",
+                               size, offset);
+                       sprintf(buf, "%x", size);
+                       setenv("filesize", buf);
+               } else {
+                       printf("### JFFS2 LOAD ERROR<%x> for %s!\n", size, filename);
+               }
+
+               return !(size > 0);
+       }
+       printf("Active partition not valid\n");
+       return 0;
+}
+
+int
+do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       char *filename = "/";
+       int ret;
+       struct part_info *part;
+
+       if (argc == 2)
+               filename = argv[1];
+
+       if (0 != (part=jffs2_part_info(part_num))){
+
+               ret = jffs2_1pass_ls(jffs2_part_info(part_num), filename);
+
+               return (ret == 1);
+       }
+       printf("Active partition not valid\n");
+       return 0;
+}
+
+int
+do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       int ret;
+       struct part_info *part;
+
+       if (0 != (part=jffs2_part_info(part_num))){
+
+               ret = jffs2_1pass_info(jffs2_part_info(part_num));
+
+               return (ret == 1);
+       }
+       printf("Active partition not valid\n");
+       return 0;
+}
+
+int
+do_jffs2_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       int tmp_part;
+
+       if (argc >= 2) {
+               tmp_part = simple_strtoul(argv[1], NULL, 16);
+       }else{
+               printf("Need partition number in argument list\n");
+               return 0;
+
+       }
+
+       if (jffs2_part_info(tmp_part)){
+               printf("Partiton changed to %d\n",tmp_part);
+               part_num=tmp_part;
+               return 0;
+       }
+
+       printf("Partition %d is not valid partiton\n",tmp_part);
+       return 0;
+
+}
+#endif /* CFG_CMD_JFFS2 */
diff --git a/common/cmd_pci.c b/common/cmd_pci.c
new file mode 100644 (file)
index 0000000..22e4b9a
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * 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
+ */
+
+/*
+ * PCI routines
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <command.h>
+#include <cmd_boot.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <cmd_pci.h>
+#include <pci.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCI)
+
+extern int cmd_get_data_size(char* arg, int default_size);
+
+unsigned char  ShortPCIListing = 1;
+
+/*
+ * Follows routines for the output of infos about devices on PCI bus.
+ */
+
+void pci_header_show(pci_dev_t dev);
+void pci_header_show_brief(pci_dev_t dev);
+
+/*
+ * Subroutine:  pciinfo
+ *
+ * Description: Show information about devices on PCI bus.
+ *                             Depending on the define CFG_SHORT_PCI_LISTING
+ *                             the output will be more or less exhaustive.
+ *
+ * Inputs:     bus_no          the number of the bus to be scanned.
+ *
+ * Return:      None
+ *
+ */
+void pciinfo(int BusNum, int ShortPCIListing)
+{
+       int Device;
+       int Function;
+       unsigned char HeaderType;
+       unsigned short VendorID;
+       pci_dev_t dev;
+
+       printf("Scanning PCI devices on bus %d\n", BusNum);
+
+       if (ShortPCIListing) {
+               printf("BusDevFun  VendorId   DeviceId   Device Class       Sub-Class\n");
+               printf("_____________________________________________________________\n");
+       }
+
+       for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) {
+               HeaderType = 0;
+               VendorID = 0;
+               for (Function = 0; Function < PCI_MAX_PCI_FUNCTIONS; Function++) {
+                       /*
+                        * If this is not a multi-function device, we skip the rest.
+                        */
+                       if (Function && !(HeaderType & 0x80))
+                               break;
+
+                       dev = PCI_BDF(BusNum, Device, Function);
+
+                       pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID);
+                       if ((VendorID == 0xFFFF) || (VendorID == 0x0000))
+                               continue;
+
+                       pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType);
+
+                       if (ShortPCIListing)
+                       {
+                               printf("%02x.%02x.%02x   ", BusNum, Device, Function);
+                               pci_header_show_brief(dev);
+                       }
+                       else
+                       {
+                               printf("\nFound PCI device %02x.%02x.%02x:\n",
+                                      BusNum, Device, Function);
+                               pci_header_show(dev);
+                       }
+           }
+    }
+}
+
+char* pci_classes_str(u8 class)
+{
+       static char *pci_classes[] = {
+               "Build before PCI Rev2.0",
+               "Mass storage controller",
+               "Network controller     ",
+               "Display controller     ",
+               "Multimedia device      ",
+               "Memory controller      ",
+               "Bridge device          ",
+               "Simple comm. controller",
+               "Base system peripheral ",
+               "Input device           ",
+               "Docking station        ",
+               "Processor              ",
+               "Serial bus controller  ",
+               "Reserved entry         ",
+               "Does not fit any class "
+       };
+
+       if (class < (sizeof pci_classes / sizeof *pci_classes))
+               return pci_classes[(int) class];
+
+       return  "???                    ";
+}
+
+/*
+ * Subroutine:  pci_header_show_brief
+ *
+ * Description: Reads and prints the header of the
+ *             specified PCI device in short form.
+ *
+ * Inputs:     dev      Bus+Device+Function number
+ *
+ * Return:      None
+ *
+ */
+void pci_header_show_brief(pci_dev_t dev)
+{
+       u16 vendor, device;
+       u8 class, subclass;
+
+       pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
+       pci_read_config_word(dev, PCI_DEVICE_ID, &device);
+       pci_read_config_byte(dev, PCI_CLASS_CODE, &class);
+       pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &subclass);
+
+       printf("0x%.4x     0x%.4x     %s 0x%.2x\n",
+              vendor, device,
+              pci_classes_str(class), subclass);
+}
+
+/*
+ * Subroutine:  PCI_Header_Show
+ *
+ * Description: Reads the header of the specified PCI device.
+ *
+ * Inputs:             BusDevFunc      Bus+Device+Function number
+ *
+ * Return:      None
+ *
+ */
+void pci_header_show(pci_dev_t dev)
+{
+       u8 _byte, header_type;
+       u16 _word;
+       u32 _dword;
+
+#define PRINT(msg, type, reg) \
+       pci_read_config_##type(dev, reg, &_##type); \
+       printf(msg, _##type)
+
+#define PRINT2(msg, type, reg, func) \
+       pci_read_config_##type(dev, reg, &_##type); \
+       printf(msg, _##type, func(_##type))
+
+       pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+       PRINT ("  vendor ID =                   0x%.4x\n", word, PCI_VENDOR_ID);
+       PRINT ("  device ID =                   0x%.4x\n", word, PCI_DEVICE_ID);
+       PRINT ("  command register =            0x%.4x\n", word, PCI_COMMAND);
+       PRINT ("  status register =             0x%.4x\n", word, PCI_STATUS);
+       PRINT ("  revision ID =                 0x%.2x\n", byte, PCI_REVISION_ID);
+       PRINT2("  class code =                  0x%.2x (%s)\n", byte, PCI_CLASS_CODE,
+                                                               pci_classes_str);
+       PRINT ("  sub class code =              0x%.2x\n", byte, PCI_CLASS_SUB_CODE);
+       PRINT ("  programming interface =       0x%.2x\n", byte, PCI_CLASS_PROG);
+       PRINT ("  cache line =                  0x%.2x\n", byte, PCI_CACHE_LINE_SIZE);
+       PRINT ("  latency time =                0x%.2x\n", byte, PCI_LATENCY_TIMER);
+       PRINT ("  header type =                 0x%.2x\n", byte, PCI_HEADER_TYPE);
+       PRINT ("  BIST =                        0x%.2x\n", byte, PCI_BIST);
+       PRINT ("  base address 0 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_0);
+       PRINT ("  base address 1 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_1);
+
+       if (header_type & 0x01) {               /* PCI-to-PCI bridge */
+               PRINT ("  primary bus number =          0x%.2x\n", byte, PCI_PRIMARY_BUS);
+               PRINT ("  secondary bus number =        0x%.2x\n", byte, PCI_SECONDARY_BUS);
+               PRINT ("  subordinate bus number =      0x%.2x\n", byte, PCI_SUBORDINATE_BUS);
+               PRINT ("  secondary latency timer =     0x%.2x\n", byte, PCI_SEC_LATENCY_TIMER);
+               PRINT ("  IO base =                     0x%.2x\n", byte, PCI_IO_BASE);
+               PRINT ("  IO limit =                    0x%.2x\n", byte, PCI_IO_LIMIT);
+               PRINT ("  secondary status =            0x%.4x\n", word, PCI_SEC_STATUS);
+               PRINT ("  memory base =                 0x%.4x\n", word, PCI_MEMORY_BASE);
+               PRINT ("  memory limit =                0x%.4x\n", word, PCI_MEMORY_LIMIT);
+               PRINT ("  prefetch memory base =        0x%.4x\n", word, PCI_PREF_MEMORY_BASE);
+               PRINT ("  prefetch memory limit =       0x%.4x\n", word, PCI_PREF_MEMORY_LIMIT);
+               PRINT ("  prefetch memory base upper =  0x%.8x\n", dword, PCI_PREF_BASE_UPPER32);
+               PRINT ("  prefetch memory limit upper = 0x%.8x\n", dword, PCI_PREF_LIMIT_UPPER32);
+               PRINT ("  IO base upper 16 bits =       0x%.4x\n", word, PCI_IO_BASE_UPPER16);
+               PRINT ("  IO limit upper 16 bits =      0x%.4x\n", word, PCI_IO_LIMIT_UPPER16);
+               PRINT ("  expansion ROM base address =  0x%.8x\n", dword, PCI_ROM_ADDRESS1);
+               PRINT ("  interrupt line =              0x%.2x\n", byte, PCI_INTERRUPT_LINE);
+               PRINT ("  interrupt pin =               0x%.2x\n", byte, PCI_INTERRUPT_PIN);
+               PRINT ("  bridge control =              0x%.4x\n", word, PCI_BRIDGE_CONTROL);
+    } else {                                   /* PCI device */
+               PRINT("  base address 2 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_2);
+               PRINT("  base address 3 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_3);
+               PRINT("  base address 4 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_4);
+               PRINT("  base address 5 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_5);
+               PRINT("  cardBus CIS pointer =         0x%.8x\n", dword, PCI_CARDBUS_CIS);
+               PRINT("  sub system vendor ID =        0x%.4x\n", word, PCI_SUBSYSTEM_VENDOR_ID);
+               PRINT("  sub system ID =               0x%.4x\n", word, PCI_SUBSYSTEM_ID);
+               PRINT("  expansion ROM base address =  0x%.8x\n", dword, PCI_ROM_ADDRESS);
+               PRINT("  interrupt line =              0x%.2x\n", byte, PCI_INTERRUPT_LINE);
+               PRINT("  interrupt pin =               0x%.2x\n", byte, PCI_INTERRUPT_PIN);
+               PRINT("  min Grant =                   0x%.2x\n", byte, PCI_MIN_GNT);
+               PRINT("  max Latency =                 0x%.2x\n", byte, PCI_MAX_LAT);
+    }
+
+#undef PRINT
+#undef PRINT2
+}
+
+/* Convert the "bus.device.function" identifier into a number.
+ */
+static pci_dev_t get_pci_dev(char* name)
+{
+       char cnum[12];
+       int len, i, iold, n;
+       int bdfs[3] = {0,0,0};
+
+       len = strlen(name);
+       if (len > 8)
+               return -1;
+       for (i = 0, iold = 0, n = 0; i < len; i++) {
+               if (name[i] == '.') {
+                       memcpy(cnum, &name[iold], i - iold);
+                       cnum[i - iold] = '\0';
+                       bdfs[n++] = simple_strtoul(cnum, NULL, 16);
+                       iold = i + 1;
+               }
+       }
+       strcpy(cnum, &name[iold]);
+       if (n == 0)
+               n = 1;
+       bdfs[n] = simple_strtoul(cnum, NULL, 16);
+       return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]);
+}
+
+static int pci_cfg_display(pci_dev_t bdf, ulong addr, ulong size, ulong length)
+{
+#define DISP_LINE_LEN  16
+       ulong i, nbytes, linebytes;
+       int rc = 0;
+
+       if (length == 0)
+               length = 0x40 / size; /* Standard PCI configuration space */
+
+       /* Print the lines.
+        * once, and all accesses are with the specified bus width.
+        */
+       nbytes = length * size;
+       do {
+               uint    val4;
+               ushort  val2;
+               u_char  val1;
+
+               printf("%08lx:", addr);
+               linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
+               for (i=0; i<linebytes; i+= size) {
+                       if (size == 4) {
+                               pci_read_config_dword(bdf, addr, &val4);
+                               printf(" %08x", val4);
+                       } else if (size == 2) {
+                               pci_read_config_word(bdf, addr, &val2);
+                               printf(" %04x", val2);
+                       } else {
+                               pci_read_config_byte(bdf, addr, &val1);
+                               printf(" %02x", val1);
+                       }
+                       addr += size;
+               }
+               printf("\n");
+               nbytes -= linebytes;
+               if (ctrlc()) {
+                       rc = 1;
+                       break;
+               }
+       } while (nbytes > 0);
+
+       return (rc);
+}
+
+static int pci_cfg_write (pci_dev_t bdf, ulong addr, ulong size, ulong value)
+{
+       if (size == 4) {
+               pci_write_config_dword(bdf, addr, value);
+       }
+       else if (size == 2) {
+               ushort val = value & 0xffff;
+               pci_write_config_word(bdf, addr, val);
+       }
+       else {
+               u_char val = value & 0xff;
+               pci_write_config_byte(bdf, addr, val);
+       }
+       return 0;
+}
+
+static int
+pci_cfg_modify (pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag)
+{
+       ulong   i;
+       int     nbytes;
+       extern char console_buffer[];
+       uint    val4;
+       ushort  val2;
+       u_char  val1;
+
+       /* Print the address, followed by value.  Then accept input for
+        * the next value.  A non-converted value exits.
+        */
+       do {
+               printf("%08lx:", addr);
+               if (size == 4) {
+                       pci_read_config_dword(bdf, addr, &val4);
+                       printf(" %08x", val4);
+               }
+               else if (size == 2) {
+                       pci_read_config_word(bdf, addr, &val2);
+                       printf(" %04x", val2);
+               }
+               else {
+                       pci_read_config_byte(bdf, addr, &val1);
+                       printf(" %02x", val1);
+               }
+
+               nbytes = readline (" ? ");
+               if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
+                       /* <CR> pressed as only input, don't modify current
+                        * location and move to next. "-" pressed will go back.
+                        */
+                       if (incrflag)
+                               addr += nbytes ? -size : size;
+                       nbytes = 1;
+#ifdef CONFIG_BOOT_RETRY_TIME
+                       reset_cmd_timeout(); /* good enough to not time out */
+#endif
+               }
+#ifdef CONFIG_BOOT_RETRY_TIME
+               else if (nbytes == -2) {
+                       break;  /* timed out, exit the command  */
+               }
+#endif
+               else {
+                       char *endp;
+                       i = simple_strtoul(console_buffer, &endp, 16);
+                       nbytes = endp - console_buffer;
+                       if (nbytes) {
+#ifdef CONFIG_BOOT_RETRY_TIME
+                               /* good enough to not time out
+                                */
+                               reset_cmd_timeout();
+#endif
+                               pci_cfg_write (bdf, addr, size, i);
+                               if (incrflag)
+                                       addr += size;
+                       }
+               }
+       } while (nbytes);
+
+       return 0;
+}
+
+/* PCI Configuration Space access commands
+ *
+ * Syntax:
+ *     pci display[.b, .w, .l] bus.device.function} [addr] [len]
+ *     pci next[.b, .w, .l] bus.device.function [addr]
+ *      pci modify[.b, .w, .l] bus.device.function [addr]
+ *      pci write[.b, .w, .l] bus.device.function addr value
+ */
+int do_pci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       ulong addr = 0, value = 0, size = 0;
+       pci_dev_t bdf = 0;
+       char cmd = 's';
+
+       if (argc > 1)
+               cmd = argv[1][0];
+
+       switch (cmd) {
+       case 'd':               /* display */
+       case 'n':               /* next */
+       case 'm':               /* modify */
+       case 'w':               /* write */
+               /* Check for a size specification. */
+               size = cmd_get_data_size(argv[1], 4);
+               if (argc > 3)
+                       addr = simple_strtoul(argv[3], NULL, 16);
+               if (argc > 4)
+                       value = simple_strtoul(argv[4], NULL, 16);
+       case 'h':               /* header */
+               if (argc < 3)
+                       goto usage;
+               if ((bdf = get_pci_dev(argv[2])) == -1)
+                       return 1;
+               break;
+       default:                /* scan bus */
+               value = 1; /* short listing */
+               bdf = 0;   /* bus number  */
+               if (argc > 1) {
+                       if (argv[argc-1][0] == 'l') {
+                               value = 0;
+                               argc--;
+                       }
+                       if (argc > 1)
+                               bdf = simple_strtoul(argv[1], NULL, 16);
+               }
+               pciinfo(bdf, value);
+               return 0;
+       }
+
+       switch (argv[1][0]) {
+       case 'h':               /* header */
+               pci_header_show(bdf);
+               return 0;
+       case 'd':               /* display */
+               return pci_cfg_display(bdf, addr, size, value);
+       case 'n':               /* next */
+               if (argc < 4)
+                       goto usage;
+               return pci_cfg_modify(bdf, addr, size, value, 0);
+       case 'm':               /* modify */
+               if (argc < 4)
+                       goto usage;
+               return pci_cfg_modify(bdf, addr, size, value, 1);
+       case 'w':               /* write */
+               if (argc < 5)
+                       goto usage;
+               return pci_cfg_write(bdf, addr, size, value);
+       }
+
+       return 1;
+ usage:
+       printf ("Usage:\n%s\n", cmdtp->usage);
+       return 1;
+}
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_PCI) */
+
+#endif /* CONFIG_PCI */
diff --git a/common/cmd_pcmcia.c b/common/cmd_pcmcia.c
new file mode 100644 (file)
index 0000000..ccf21a9
--- /dev/null
@@ -0,0 +1,2243 @@
+/*
+ * (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
+ *
+ ********************************************************************
+ *
+ * Lots of code copied from:
+ *
+ * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
+ * (C) 1999-2000 Magnus Damm <damm@bitsmart.com>
+ *
+ * "The ExCA standard specifies that socket controllers should provide
+ * two IO and five memory windows per socket, which can be independently
+ * configured and positioned in the host address space and mapped to
+ * arbitrary segments of card address space. " - David A Hinds. 1999
+ *
+ * This controller does _not_ meet the ExCA standard.
+ *
+ * m8xx pcmcia controller brief info:
+ * + 8 windows (attrib, mem, i/o)
+ * + up to two slots (SLOT_A and SLOT_B)
+ * + inputpins, outputpins, event and mask registers.
+ * - no offset register. sigh.
+ *
+ * Because of the lacking offset register we must map the whole card.
+ * We assign each memory window PCMCIA_MEM_WIN_SIZE address space.
+ * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO
+ * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE.
+ * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE.
+ * They are maximum 64KByte each...
+ */
+
+/* #define DEBUG       1       */
+
+/*
+ * PCMCIA support
+ */
+#include <common.h>
+#include <command.h>
+#include <config.h>
+#include <pcmcia.h>
+#include <cmd_pcmcia.h>
+#if defined(CONFIG_IDE_8xx_PCCARD) && defined(CONFIG_8xx)
+#include <mpc8xx.h>
+#endif
+#if defined(CONFIG_LWMON)
+#include <i2c.h>
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) || \
+    ((CONFIG_COMMANDS & CFG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD))
+
+int pcmcia_on (void);
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int  pcmcia_off (void);
+static int  hardware_disable(int slot);
+#endif
+static int  hardware_enable (int slot);
+static int  voltage_set(int slot, int vcc, int vpp);
+#ifdef CONFIG_IDE_8xx_PCCARD
+static void print_funcid (int func);
+static void print_fixed  (volatile uchar *p);
+static int  identify     (volatile uchar *p);
+static int  check_ide_device (void);
+#endif /* CONFIG_IDE_8xx_PCCARD */
+
+static u_int m8xx_get_graycode(u_int size);
+#if 0
+static u_int m8xx_get_speed(u_int ns, u_int is_io);
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/* look up table for pgcrx registers */
+
+static u_int *pcmcia_pgcrx[2] = {
+       &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra,
+       &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb,
+};
+
+#define PCMCIA_PGCRX(slot)     (*pcmcia_pgcrx[slot])
+
+const char *indent = "\t   ";
+
+/* ------------------------------------------------------------------------- */
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+
+int do_pinit (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       int rcode = 0;
+
+       if (argc != 2) {
+               printf ("Usage: pinit {on | off}\n");
+               return 1;
+       }
+       if (strcmp(argv[1],"on") == 0) {
+               rcode = pcmcia_on ();
+       } else if (strcmp(argv[1],"off") == 0) {
+               rcode = pcmcia_off ();
+       } else {
+               printf ("Usage: pinit {on | off}\n");
+               return 1;
+       }
+
+       return rcode;
+}
+#endif /* CFG_CMD_PCMCIA */
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_LWMON)
+# define  CFG_PCMCIA_TIMING    (PCMCIA_SHT(9) | PCMCIA_SST(3) | PCMCIA_SL(12))
+#else
+# define  CFG_PCMCIA_TIMING    (PCMCIA_SHT(2) | PCMCIA_SST(4) | PCMCIA_SL(9))
+#endif
+
+int pcmcia_on (void)
+{
+       int i;
+       u_long reg, base;
+       pcmcia_win_t *win;
+
+       debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n");
+
+       /* intialize the fixed memory windows */
+       win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0);
+       base = CFG_PCMCIA_MEM_ADDR;
+
+       if((reg = m8xx_get_graycode(CFG_PCMCIA_MEM_SIZE)) == -1) {
+               printf ("Cannot set window size to 0x%08x\n",
+                       CFG_PCMCIA_MEM_SIZE);
+               return (1);
+       }
+
+       for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) {
+               win->br = base;
+
+               switch (i) {
+#ifdef CONFIG_IDE_8xx_PCCARD
+               case 0: {       /* map attribute memory */
+                       win->or = (     PCMCIA_BSIZE_64M
+                               |       PCMCIA_PPS_8
+                               |       PCMCIA_PRS_ATTR
+                               |       PCMCIA_SLOT_x
+                               |       PCMCIA_PV
+                               |       CFG_PCMCIA_TIMING );
+                       break;
+                   }
+
+               case 1: {       /* map I/O window for data reg */
+                       win->or = (     PCMCIA_BSIZE_1K
+                               |       PCMCIA_PPS_16
+                               |       PCMCIA_PRS_IO
+                               |       PCMCIA_SLOT_x
+                               |       PCMCIA_PV
+                               |       CFG_PCMCIA_TIMING );
+                       break;
+                   }
+
+               case 2: {       /* map I/O window for command/ctrl reg block */
+                       win->or = (     PCMCIA_BSIZE_1K
+                               |       PCMCIA_PPS_8
+                               |       PCMCIA_PRS_IO
+                               |       PCMCIA_SLOT_x
+                               |       PCMCIA_PV
+                               |       CFG_PCMCIA_TIMING );
+                       break;
+                   }
+#endif /* CONFIG_IDE_8xx_PCCARD */
+               default:        /* set to not valid */
+                       win->or = 0;
+                       break;
+               }
+
+               debug ("MemWin %d: PBR 0x%08lX  POR %08lX\n",
+                       i, win->br, win->or);
+               base += CFG_PCMCIA_MEM_SIZE;
+               ++win;
+       }
+
+       /* turn off voltage */
+       if (voltage_set(_slot_, 0, 0))
+               return (1);
+
+       /* Enable external hardware */
+       if (hardware_enable(_slot_))
+               return (1);
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+       if (check_ide_device())
+               return (1);
+#endif
+       return (0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+
+static int pcmcia_off (void)
+{
+       int i;
+       pcmcia_win_t *win;
+
+       printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
+
+       /* clear interrupt state, and disable interrupts */
+       ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pscr =  PCMCIA_MASK(_slot_);
+       ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_per &= ~PCMCIA_MASK(_slot_);
+
+       /* turn off interrupt and disable CxOE */
+       PCMCIA_PGCRX(_slot_) = __MY_PCMCIA_GCRX_CXOE;
+
+       /* turn off memory windows */
+       win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0);
+
+       for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) {
+               /* disable memory window */
+               win->or = 0;
+               ++win;
+       }
+
+       /* turn off voltage */
+       voltage_set(_slot_, 0, 0);
+
+       /* disable external hardware */
+       printf ("Shutdown and Poweroff " PCMCIA_SLOT_MSG "\n");
+       hardware_disable(_slot_);
+       return 0;
+}
+
+#endif /* CFG_CMD_PCMCIA */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+
+#define        MAX_TUPEL_SZ    512
+#define MAX_FEATURES   4
+
+static int check_ide_device (void)
+{
+       volatile uchar *ident = NULL;
+       volatile uchar *feature_p[MAX_FEATURES];
+       volatile uchar *p, *start;
+       int n_features = 0;
+       uchar func_id = ~0;
+       uchar code, len;
+       ushort config_base = 0;
+       int found = 0;
+       int i;
+
+       debug ("PCMCIA MEM: %08X\n", CFG_PCMCIA_MEM_ADDR);
+
+       start = p = (volatile uchar *) CFG_PCMCIA_MEM_ADDR;
+
+       while ((p - start) < MAX_TUPEL_SZ) {
+
+               code = *p; p += 2;
+
+               if (code == 0xFF) { /* End of chain */
+                       break;
+               }
+
+               len = *p; p += 2;
+#if defined(DEBUG) && (DEBUG > 1)
+               { volatile uchar *q = p;
+                       printf ("\nTuple code %02x  length %d\n\tData:",
+                               code, len);
+
+                       for (i = 0; i < len; ++i) {
+                               printf (" %02x", *q);
+                               q+= 2;
+                       }
+               }
+#endif /* DEBUG */
+               switch (code) {
+               case CISTPL_VERS_1:
+                       ident = p + 4;
+                       break;
+               case CISTPL_FUNCID:
+                       /* Fix for broken SanDisk which may have 0x80 bit set */
+                       func_id = *p & 0x7F;
+                       break;
+               case CISTPL_FUNCE:
+                       if (n_features < MAX_FEATURES)
+                               feature_p[n_features++] = p;
+                       break;
+               case CISTPL_CONFIG:
+                       config_base = (*(p+6) << 8) + (*(p+4));
+                       debug ("\n## Config_base = %04x ###\n", config_base);
+               default:
+                       break;
+               }
+               p += 2 * len;
+       }
+
+       found = identify (ident);
+
+       if (func_id != ((uchar)~0)) {
+               print_funcid (func_id);
+
+               if (func_id == CISTPL_FUNCID_FIXED)
+                       found = 1;
+               else
+                       return (1);     /* no disk drive */
+       }
+
+       for (i=0; i<n_features; ++i) {
+               print_fixed (feature_p[i]);
+       }
+
+       if (!found) {
+               printf ("unknown card type\n");
+               return (1);
+       }
+
+       /* set I/O area in config reg -> only valid for ARGOSY D5!!! */
+       *((uchar *)(CFG_PCMCIA_MEM_ADDR + config_base)) = 1;
+
+       return (0);
+}
+#endif /* CONFIG_IDE_8xx_PCCARD */
+
+/* ------------------------------------------------------------------------- */
+
+
+/* ---------------------------------------------------------------------------- */
+/* board specific stuff:                                                       */
+/* voltage_set(), hardware_enable() and hardware_disable()                     */
+/* ---------------------------------------------------------------------------- */
+
+/* ---------------------------------------------------------------------------- */
+/* RPX Boards from Embedded Planet                                             */
+/* ---------------------------------------------------------------------------- */
+
+#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
+
+/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
+ * SYPCR is write once only, therefore must the slowest memory be faster
+ * than the bus monitor or we will get a machine check due to the bus timeout.
+ */
+
+#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"
+
+#undef PCMCIA_BMT_LIMIT
+#define PCMCIA_BMT_LIMIT (6*8)
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+       u_long reg = 0;
+
+       switch(vcc) {
+       case 0: break;
+       case 33: reg |= BCSR1_PCVCTL4; break;
+       case 50: reg |= BCSR1_PCVCTL5; break;
+       default: return 1;
+       }
+
+       switch(vpp) {
+       case 0: break;
+       case 33:
+       case 50:
+               if(vcc == vpp)
+                       reg |= BCSR1_PCVCTL6;
+               else
+                       return 1;
+               break;
+       case 120:
+               reg |= BCSR1_PCVCTL7;
+       default: return 1;
+       }
+
+       if(vcc == 120)
+          return 1;
+
+       /* first, turn off all power */
+
+       *((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5
+                                    | BCSR1_PCVCTL6 | BCSR1_PCVCTL7);
+
+       /* enable new powersettings */
+
+       *((uint *)RPX_CSR_ADDR) |= reg;
+
+       return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+static int hardware_enable (int slot)
+{
+       return 0;       /* No hardware to enable */
+}
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable(int slot)
+{
+       return 0;       /* No hardware to disable */
+}
+#endif /* CFG_CMD_PCMCIA */
+#endif /* CONFIG_RPXCLASSIC */
+
+/* ---------------------------------------------------------------------------- */
+/* (F)ADS Boards from Motorola                                                 */
+/* ---------------------------------------------------------------------------- */
+
+#if defined(CONFIG_ADS) || defined(CONFIG_FADS)
+
+#ifdef CONFIG_ADS
+#define PCMCIA_BOARD_MSG "ADS"
+#define PCMCIA_GLITCHY_CD  /* My ADS board needs this */
+#else
+#define PCMCIA_BOARD_MSG "FADS"
+#endif
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+       u_long reg = 0;
+
+       switch(vpp) {
+       case 0: reg = 0; break;
+       case 50: reg = 1; break;
+       case 120: reg = 2; break;
+       default: return 1;
+       }
+
+       switch(vcc) {
+       case 0: reg = 0; break;
+#ifdef CONFIG_ADS
+       case 50: reg = BCSR1_PCCVCCON; break;
+#endif
+#ifdef CONFIG_FADS
+       case 33: reg = BCSR1_PCCVCC0 | BCSR1_PCCVCC1; break;
+       case 50: reg = BCSR1_PCCVCC1; break;
+#endif
+       default: return 1;
+       }
+
+       /* first, turn off all power */
+
+#ifdef CONFIG_ADS
+       *((uint *)BCSR1) |= BCSR1_PCCVCCON;
+#endif
+#ifdef CONFIG_FADS
+       *((uint *)BCSR1) &= ~(BCSR1_PCCVCC0 | BCSR1_PCCVCC1);
+#endif
+       *((uint *)BCSR1) &= ~BCSR1_PCCVPP_MASK;
+
+       /* enable new powersettings */
+
+#ifdef CONFIG_ADS
+       *((uint *)BCSR1) &= ~reg;
+#endif
+#ifdef CONFIG_FADS
+       *((uint *)BCSR1) |= reg;
+#endif
+
+       *((uint *)BCSR1) |= reg << 20;
+
+       return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+
+static int hardware_enable(int slot)
+{
+       *((uint *)BCSR1) &= ~BCSR1_PCCEN;
+       return 0;
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable(int slot)
+{
+       *((uint *)BCSR1) &= ~BCSR1_PCCEN;
+       return 0;
+}
+#endif /* CFG_CMD_PCMCIA */
+
+#endif /* (F)ADS */
+
+/* ---------------------------------------------------------------------------- */
+/* TQM8xxL Boards by TQ Components                                             */
+/* ---------------------------------------------------------------------------- */
+
+#if defined(CONFIG_TQM8xxL)
+
+#define PCMCIA_BOARD_MSG "TQM8xxL"
+
+
+static int hardware_enable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       volatile pcmconf8xx_t   *pcmp;
+       volatile sysconf8xx_t   *sysp;
+       uint reg, mask;
+
+       debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       udelay(10000);
+
+       immap = (immap_t *)CFG_IMMR;
+       sysp  = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
+       pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+       /*
+        * Configure SIUMCR to enable PCMCIA port B
+        * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
+        */
+       sysp->sc_siumcr &= ~SIUMCR_DBGC11;      /* set DBGC to 00 */
+
+       /* clear interrupt state, and disable interrupts */
+       pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
+       pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
+
+       /* disable interrupts & DMA */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Configure Port C pins for
+        * 5 Volts Enable and 3 Volts enable
+        */
+       immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004);
+       immap->im_ioport.iop_pcso  &= ~(0x0002 | 0x0004);
+       /* remove all power */
+
+       immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
+
+       /*
+        * Make sure there is a card in the slot, then configure the interface.
+        */
+       udelay(10000);
+       debug ("[%d] %s: PIPR(%p)=0x%x\n",
+               __LINE__,__FUNCTION__,
+               &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
+       if (pcmp->pcmc_pipr & 0x00001800) {
+               printf ("   No Card found\n");
+               return (1);
+       }
+
+       /*
+        * Power On.
+        */
+       mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
+       reg  = pcmp->pcmc_pipr;
+       debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
+               reg,
+               (reg&PCMCIA_VS1(slot))?"n":"ff",
+               (reg&PCMCIA_VS2(slot))?"n":"ff");
+       if ((reg & mask) == mask) {
+               immap->im_ioport.iop_pcdat |= 0x0004;
+               puts (" 5.0V card found: ");
+       } else {
+               immap->im_ioport.iop_pcdat |= 0x0002;
+               puts (" 3.3V card found: ");
+       }
+       immap->im_ioport.iop_pcdir |=  (0x0002 | 0x0004);
+#if 0
+       /*  VCC switch error flag, PCMCIA slot INPACK_ pin */
+       cp->cp_pbdir &= ~(0x0020 | 0x0010);
+       cp->cp_pbpar &= ~(0x0020 | 0x0010);
+       udelay(500000);
+#endif
+       udelay(1000);
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       udelay(250000); /* some cards need >150 ms to come up :-( */
+
+       debug ("# hardware_enable done\n");
+
+       return (0);
+}
+
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+
+       debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       immap = (immap_t *)CFG_IMMR;
+       pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+
+       /* remove all power */
+       immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
+
+       /* Configure PCMCIA General Control Register */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
+       reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       udelay(10000);
+
+       return (0);
+}
+#endif /* CFG_CMD_PCMCIA */
+
+
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+       volatile immap_t        *immap;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+
+       debug ("voltage_set: "
+               PCMCIA_BOARD_MSG
+               " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
+               'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
+
+       immap = (immap_t *)CFG_IMMR;
+       pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Configure Port C pins for
+        * 5 Volts Enable and 3 Volts enable,
+        * Turn off all power
+        */
+       debug ("PCMCIA power OFF\n");
+       immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004);
+       immap->im_ioport.iop_pcso  &= ~(0x0002 | 0x0004);
+       immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
+
+       reg = 0;
+       switch(vcc) {
+       case  0:                break;
+       case 33: reg |= 0x0002; break;
+       case 50: reg |= 0x0004; break;
+       default:                goto done;
+       }
+
+       /* Checking supported voltages */
+
+       debug ("PIPR: 0x%x --> %s\n",
+               pcmp->pcmc_pipr,
+               (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
+
+       immap->im_ioport.iop_pcdat |= reg;
+       immap->im_ioport.iop_pcdir |=  (0x0002 | 0x0004);
+       if (reg) {
+               debug ("PCMCIA powered at %sV\n",
+                       (reg&0x0004) ? "5.0" : "3.3");
+       } else {
+               debug ("PCMCIA powered down\n");
+       }
+
+done:
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
+               slot+'A');
+       return (0);
+}
+
+#endif /* TQM8xxL */
+
+
+/* ---------------------------------------------------------------------------- */
+/* LWMON Board                                                                 */
+/* ---------------------------------------------------------------------------- */
+
+#if defined(CONFIG_LWMON)
+
+#define PCMCIA_BOARD_MSG "LWMON"
+
+/* #define's for MAX1604 Power Switch */
+#define MAX1604_OP_SUS         0x80
+#define MAX1604_VCCBON         0x40
+#define MAX1604_VCC_35         0x20
+#define MAX1604_VCCBHIZ                0x10
+#define MAX1604_VPPBON         0x08
+#define MAX1604_VPPBPBPGM      0x04
+#define MAX1604_VPPBHIZ                0x02
+/* reserved                    0x01    */
+
+static int hardware_enable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       volatile pcmconf8xx_t   *pcmp;
+       volatile sysconf8xx_t   *sysp;
+       uint reg, mask;
+       uchar val;
+
+
+       debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       /* Switch on PCMCIA port in PIC register 0x60 */
+       reg = pic_read  (0x60);
+       debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
+       reg &= ~0x10;
+       /* reg |=  0x08; Vpp not needed */
+       pic_write (0x60, reg);
+#ifdef DEBUG
+       reg = pic_read  (0x60);
+       printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
+#endif
+       udelay(10000);
+
+       immap = (immap_t *)CFG_IMMR;
+       sysp  = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
+       pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+       /*
+        * Configure SIUMCR to enable PCMCIA port B
+        * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
+        */
+       sysp->sc_siumcr &= ~SIUMCR_DBGC11;      /* set DBGC to 00 */
+
+       /* clear interrupt state, and disable interrupts */
+       pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
+       pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
+
+       /* disable interrupts & DMA */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Make sure there is a card in the slot, then configure the interface.
+        */
+       udelay(10000);
+       debug ("[%d] %s: PIPR(%p)=0x%x\n",
+               __LINE__,__FUNCTION__,
+               &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
+       if (pcmp->pcmc_pipr & 0x00001800) {
+               printf ("   No Card found\n");
+               return (1);
+       }
+
+       /*
+        * Power On.
+        */
+       mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
+       reg  = pcmp->pcmc_pipr;
+       debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
+               reg,
+               (reg&PCMCIA_VS1(slot))?"n":"ff",
+               (reg&PCMCIA_VS2(slot))?"n":"ff");
+       if ((reg & mask) == mask) {
+               val = 0;                /* VCCB3/5 = 0 ==> use Vx = 5.0 V */
+               puts (" 5.0V card found: ");
+       } else {
+               val = MAX1604_VCC_35;   /* VCCB3/5 = 1 ==> use Vy = 3.3 V */
+               puts (" 3.3V card found: ");
+       }
+
+       /*  switch VCC on */
+       val |=  MAX1604_OP_SUS | MAX1604_VCCBON;
+       i2c_init  (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+       i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
+
+       udelay(500000);
+
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       udelay(250000); /* some cards need >150 ms to come up :-( */
+
+       debug ("# hardware_enable done\n");
+
+       return (0);
+}
+
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+       uchar val;
+
+       debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       immap = (immap_t *)CFG_IMMR;
+       pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+
+       /* remove all power, put output in high impedance state */
+       val  = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ;
+       i2c_init  (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+       i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
+
+       /* Configure PCMCIA General Control Register */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
+       reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       /* Switch off PCMCIA port in PIC register 0x60 */
+       reg = pic_read  (0x60);
+       debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
+       reg |=  0x10;
+       reg &= ~0x08;
+       pic_write (0x60, reg);
+#ifdef DEBUG
+       reg = pic_read  (0x60);
+       printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
+#endif
+       udelay(10000);
+
+       return (0);
+}
+#endif /* CFG_CMD_PCMCIA */
+
+
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+       volatile immap_t        *immap;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+       uchar val;
+
+       debug ("voltage_set: "
+               PCMCIA_BOARD_MSG
+               " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
+               'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
+
+       immap = (immap_t *)CFG_IMMR;
+       pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Turn off all power (switch to high impedance)
+        */
+       debug ("PCMCIA power OFF\n");
+       val  = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ;
+       i2c_init  (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+       i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
+
+       val = 0;
+       switch(vcc) {
+       case  0:                        break;
+       case 33: val = MAX1604_VCC_35;  break;
+       case 50:                        break;
+       default:                        goto done;
+       }
+
+       /* Checking supported voltages */
+
+       debug ("PIPR: 0x%x --> %s\n",
+               pcmp->pcmc_pipr,
+               (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
+
+       i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
+       if (val) {
+               debug ("PCMCIA powered at %sV\n",
+                       (val & MAX1604_VCC_35) ? "3.3" : "5.0");
+       } else {
+               debug ("PCMCIA powered down\n");
+       }
+
+done:
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
+               slot+'A');
+       return (0);
+}
+
+#endif /* LWMON */
+
+/* ---------------------------------------------------------------------------- */
+/* GTH board by Corelatus AB                                                    */
+/* ---------------------------------------------------------------------------- */
+#if defined(CONFIG_GTH)
+
+#define PCMCIA_BOARD_MSG "GTH COMPACT FLASH"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{  /* Do nothing */
+  return 0;
+}
+
+static int hardware_enable (int slot)
+{
+  volatile immap_t     *immap;
+  volatile cpm8xx_t    *cp;
+  volatile pcmconf8xx_t        *pcmp;
+  volatile sysconf8xx_t        *sysp;
+  uint reg, mask;
+
+  debug ("hardware_enable: GTH Slot %c\n", 'A'+slot);
+
+  immap = (immap_t *)CFG_IMMR;
+  sysp  = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
+  pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+  cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+  /* clear interrupt state, and disable interrupts */
+  pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
+  pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
+
+  /* disable interrupts & DMA */
+  PCMCIA_PGCRX(_slot_) = 0;
+
+  /*
+   * Disable PCMCIA buffers (isolate the interface)
+   * and assert RESET signal
+   */
+  debug ("Disable PCMCIA buffers and assert RESET\n");
+  reg  =  PCMCIA_PGCRX(_slot_);
+  reg |=  __MY_PCMCIA_GCRX_CXRESET;    /* active high */
+  reg |=  __MY_PCMCIA_GCRX_CXOE;               /* active low  */
+  PCMCIA_PGCRX(_slot_) = reg;
+  udelay(500);
+
+  /*
+   * Make sure there is a card in the slot, then configure the interface.
+   */
+  udelay(10000);
+  debug ("[%d] %s: PIPR(%p)=0x%x\n",
+               __LINE__,__FUNCTION__,
+               &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
+  if (pcmp->pcmc_pipr & 0x98000000) {
+    printf ("   No Card found\n");
+    return (1);
+  }
+
+  mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
+  reg  = pcmp->pcmc_pipr;
+  debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
+               reg,
+               (reg&PCMCIA_VS1(slot))?"n":"ff",
+               (reg&PCMCIA_VS2(slot))?"n":"ff");
+
+  debug ("Enable PCMCIA buffers and stop RESET\n");
+  reg  =  PCMCIA_PGCRX(_slot_);
+  reg &= ~__MY_PCMCIA_GCRX_CXRESET;    /* active high */
+  reg &= ~__MY_PCMCIA_GCRX_CXOE;               /* active low  */
+  PCMCIA_PGCRX(_slot_) = reg;
+
+  udelay(250000);      /* some cards need >150 ms to come up :-( */
+
+  debug ("# hardware_enable done\n");
+
+  return 0;
+}
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable(int slot)
+{
+       return 0;       /* No hardware to disable */
+}
+#endif /* CFG_CMD_PCMCIA */
+#endif /* CONFIG_GTH */
+
+/* ---------------------------------------------------------------------------- */
+/* ICU862 Boards by Cambridge Broadband Ltd.                                   */
+/* ---------------------------------------------------------------------------- */
+
+#if defined(CONFIG_ICU862)
+
+#define PCMCIA_BOARD_MSG "ICU862"
+
+static void cfg_port_B (void);
+
+static int hardware_enable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       volatile pcmconf8xx_t   *pcmp;
+       volatile sysconf8xx_t   *sysp;
+       uint reg, pipr, mask;
+       int i;
+
+       debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       udelay(10000);
+
+       immap = (immap_t *)CFG_IMMR;
+       sysp  = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
+       pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+       /* Configure Port B for TPS2205 PC-Card Power-Interface Switch */
+       cfg_port_B ();
+
+       /*
+        * Configure SIUMCR to enable PCMCIA port B
+        * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
+        */
+       sysp->sc_siumcr &= ~SIUMCR_DBGC11;      /* set DBGC to 00 */
+
+       /* clear interrupt state, and disable interrupts */
+       pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
+       pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
+
+       /* disable interrupts & DMA */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Make sure there is a card in the slot, then configure the interface.
+        */
+       udelay(10000);
+       debug ("[%d] %s: PIPR(%p)=0x%x\n",
+               __LINE__,__FUNCTION__,
+               &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
+       if (pcmp->pcmc_pipr & 0x00001800) {
+               printf ("   No Card found\n");
+               return (1);
+       }
+
+       /*
+        * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z
+        */
+       mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
+       pipr = pcmp->pcmc_pipr;
+       debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
+               pipr,
+               (reg&PCMCIA_VS1(slot))?"n":"ff",
+               (reg&PCMCIA_VS2(slot))?"n":"ff");
+
+       reg  = cp->cp_pbdat;
+       if ((pipr & mask) == mask) {
+               reg |=  (TPS2205_VPP_PGM | TPS2205_VPP_VCC |    /* VAVPP => Hi-Z */
+                        TPS2205_VCC3);                         /* 3V off       */
+               reg &= ~(TPS2205_VCC5);                         /* 5V on        */
+               puts (" 5.0V card found: ");
+       } else {
+               reg |=  (TPS2205_VPP_PGM | TPS2205_VPP_VCC |    /* VAVPP => Hi-Z */
+                        TPS2205_VCC5);                         /* 5V off       */
+               reg &= ~(TPS2205_VCC3);                         /* 3V on        */
+               puts (" 3.3V card found: ");
+       }
+
+       debug ("\nPB DAT: %08x -> 3.3V %s 5.0V %s VPP_PGM %s VPP_VCC %s\n",
+               reg,
+               (reg & TPS2205_VCC3)    ? "off" : "on",
+               (reg & TPS2205_VCC5)    ? "off" : "on",
+               (reg & TPS2205_VPP_PGM) ? "off" : "on",
+               (reg & TPS2205_VPP_VCC) ? "off" : "on" );
+
+       cp->cp_pbdat = reg;
+
+       /*  Wait 500 ms; use this to check for over-current */
+       for (i=0; i<5000; ++i) {
+               if ((cp->cp_pbdat & TPS2205_OC) == 0) {
+                       printf ("   *** Overcurrent - Safety shutdown ***\n");
+                       cp->cp_pbdat &= ~(TPS2205_SHDN);
+                       return (1);
+               }
+               udelay (100);
+       }
+
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       udelay(250000); /* some cards need >150 ms to come up :-( */
+
+       debug ("# hardware_enable done\n");
+
+       return (0);
+}
+
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+
+       debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       immap = (immap_t *)CFG_IMMR;
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+       pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+
+       /* Shut down */
+       cp->cp_pbdat &= ~(TPS2205_SHDN);
+
+       /* Configure PCMCIA General Control Register */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
+       reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       udelay(10000);
+
+       return (0);
+}
+#endif /* CFG_CMD_PCMCIA */
+
+
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+
+       debug ("voltage_set: "
+               PCMCIA_BOARD_MSG
+               " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
+               'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
+
+       immap = (immap_t *)CFG_IMMR;
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+       pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Configure Port C pins for
+        * 5 Volts Enable and 3 Volts enable,
+        * Turn all power pins to Hi-Z
+        */
+       debug ("PCMCIA power OFF\n");
+       cfg_port_B ();  /* Enables switch, but all in Hi-Z */
+
+       reg  = cp->cp_pbdat;
+
+       switch(vcc) {
+       case  0:                        break;  /* Switch off           */
+       case 33: reg &= ~TPS2205_VCC3;  break;  /* Switch on 3.3V       */
+       case 50: reg &= ~TPS2205_VCC5;  break;  /* Switch on 5.0V       */
+       default:                        goto done;
+       }
+
+       /* Checking supported voltages */
+
+       debug ("PIPR: 0x%x --> %s\n",
+               pcmp->pcmc_pipr,
+               (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
+
+       cp->cp_pbdat = reg;
+
+#ifdef DEBUG
+    {
+       char *s;
+
+       if ((reg & TPS2205_VCC3) == 0) {
+               s = "at 3.3V";
+       } else if ((reg & TPS2205_VCC5) == 0) {
+               s = "at 5.0V";
+       } else {
+               s = "down";
+       }
+       printf ("PCMCIA powered %s\n", s);
+    }
+#endif
+
+done:
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
+               slot+'A');
+       return (0);
+}
+
+static void cfg_port_B (void)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       uint reg;
+
+       immap = (immap_t *)CFG_IMMR;
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+       /*
+        * Configure Port B for TPS2205 PC-Card Power-Interface Switch
+        *
+        * Switch off all voltages, assert shutdown
+        */
+       reg  = cp->cp_pbdat;
+       reg |=  (TPS2205_VPP_PGM | TPS2205_VPP_VCC |    /* VAVPP => Hi-Z */
+                TPS2205_VCC3    | TPS2205_VCC5    |    /* VAVCC => Hi-Z */
+                TPS2205_SHDN);                         /* enable switch */
+       cp->cp_pbdat = reg;
+
+       cp->cp_pbpar &= ~(TPS2205_INPUTS | TPS2205_OUTPUTS);
+
+       reg = cp->cp_pbdir & ~(TPS2205_INPUTS);
+       cp->cp_pbdir = reg | TPS2205_OUTPUTS;
+
+       debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n",
+               cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat);
+}
+
+#endif /* ICU862 */
+
+
+/* ---------------------------------------------------------------------------- */
+/* C2MON Boards by TTTech Computertechnik AG                                   */
+/* ---------------------------------------------------------------------------- */
+
+#if defined(CONFIG_C2MON)
+
+#define PCMCIA_BOARD_MSG "C2MON"
+
+static void cfg_ports (void);
+
+static int hardware_enable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       volatile pcmconf8xx_t   *pcmp;
+       volatile sysconf8xx_t   *sysp;
+       uint reg, pipr, mask;
+       ushort sreg;
+       int i;
+
+       debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       udelay(10000);
+
+       immap = (immap_t *)CFG_IMMR;
+       sysp  = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
+       pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+       /* Configure Ports for TPS2211A PC-Card Power-Interface Switch */
+       cfg_ports ();
+
+       /*
+        * Configure SIUMCR to enable PCMCIA port B
+        * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
+        */
+       sysp->sc_siumcr &= ~SIUMCR_DBGC11;      /* set DBGC to 00 */
+
+       /* clear interrupt state, and disable interrupts */
+       pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
+       pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
+
+       /* disable interrupts & DMA */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Make sure there is a card in the slot, then configure the interface.
+        */
+       udelay(10000);
+       debug ("[%d] %s: PIPR(%p)=0x%x\n",
+               __LINE__,__FUNCTION__,
+               &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
+       if (pcmp->pcmc_pipr & 0x00001800) {
+               printf ("   No Card found\n");
+               return (1);
+       }
+
+       /*
+        * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z
+        */
+       mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
+       pipr = pcmp->pcmc_pipr;
+       debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
+               pipr,
+               (reg&PCMCIA_VS1(slot))?"n":"ff",
+               (reg&PCMCIA_VS2(slot))?"n":"ff");
+
+       sreg = immap->im_ioport.iop_pcdat;
+       if ((pipr & mask) == mask) {
+               sreg |=  (TPS2211_VPPD0 | TPS2211_VPPD1 |       /* VAVPP => Hi-Z */
+                         TPS2211_VCCD1);                       /* 5V on        */
+               sreg &= ~(TPS2211_VCCD0);                       /* 3V off       */
+               puts (" 5.0V card found: ");
+       } else {
+               sreg |=  (TPS2211_VPPD0 | TPS2211_VPPD1 |       /* VAVPP => Hi-Z */
+                         TPS2211_VCCD0);                       /* 3V on        */
+               sreg &= ~(TPS2211_VCCD1);                       /* 5V off       */
+               puts (" 3.3V card found: ");
+       }
+
+       debug ("\nPC DAT: %04x -> 3.3V %s 5.0V %s\n",
+               sreg,
+               ( (sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) ? "on" : "off",
+               (!(sreg & TPS2211_VCCD0) &&  (sreg & TPS2211_VCCD1)) ? "on" : "off"
+       );
+
+       immap->im_ioport.iop_pcdat = sreg;
+
+       /*  Wait 500 ms; use this to check for over-current */
+       for (i=0; i<5000; ++i) {
+               if ((cp->cp_pbdat & TPS2211_OC) == 0) {
+                   printf ("   *** Overcurrent - Safety shutdown ***\n");
+                   immap->im_ioport.iop_pcdat &= ~(TPS2211_VCCD0|TPS2211_VCCD1);
+                   return (1);
+               }
+               udelay (100);
+       }
+
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       udelay(250000); /* some cards need >150 ms to come up :-( */
+
+       debug ("# hardware_enable done\n");
+
+       return (0);
+}
+
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+
+       debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       immap = (immap_t *)CFG_IMMR;
+       pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+
+       /* Configure PCMCIA General Control Register */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
+       reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       /* ALl voltages off / Hi-Z */
+       immap->im_ioport.iop_pcdat |= (TPS2211_VPPD0 | TPS2211_VPPD1 |
+                                      TPS2211_VCCD0 | TPS2211_VCCD1 );
+
+       udelay(10000);
+
+       return (0);
+}
+#endif /* CFG_CMD_PCMCIA */
+
+
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+       ushort sreg;
+
+       debug ("voltage_set: "
+               PCMCIA_BOARD_MSG
+               " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
+               'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
+
+       immap = (immap_t *)CFG_IMMR;
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+       pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Configure Port C pins for
+        * 5 Volts Enable and 3 Volts enable,
+        * Turn all power pins to Hi-Z
+        */
+       debug ("PCMCIA power OFF\n");
+       cfg_ports ();   /* Enables switch, but all in Hi-Z */
+
+       sreg  = immap->im_ioport.iop_pcdat;
+       sreg |= TPS2211_VPPD0 | TPS2211_VPPD1;          /* VAVPP always Hi-Z */
+
+       switch(vcc) {
+       case  0:                        break;  /* Switch off           */
+       case 33: sreg |=  TPS2211_VCCD0;        /* Switch on 3.3V       */
+                sreg &= ~TPS2211_VCCD1;
+                                       break;
+       case 50: sreg &= ~TPS2211_VCCD0;        /* Switch on 5.0V       */
+                sreg |=  TPS2211_VCCD1;
+                                       break;
+       default:                        goto done;
+       }
+
+       /* Checking supported voltages */
+
+       debug ("PIPR: 0x%x --> %s\n",
+               pcmp->pcmc_pipr,
+               (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
+
+       immap->im_ioport.iop_pcdat = sreg;
+
+#ifdef DEBUG
+    {
+       char *s;
+
+       if ((sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) {
+               s = "at 3.3V";
+       } else if (!(sreg & TPS2211_VCCD0) &&  (sreg & TPS2211_VCCD1)) {
+               s = "at 5.0V";
+       } else {
+               s = "down";
+       }
+       printf ("PCMCIA powered %s\n", s);
+    }
+#endif
+
+done:
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
+               slot+'A');
+       return (0);
+}
+
+static void cfg_ports (void)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       ushort sreg;
+
+       immap = (immap_t *)CFG_IMMR;
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+       /*
+        * Configure Port C for TPS2211 PC-Card Power-Interface Switch
+        *
+        * Switch off all voltages, assert shutdown
+        */
+       sreg = immap->im_ioport.iop_pcdat;
+       sreg |=  (TPS2211_VPPD0 | TPS2211_VPPD1);       /* VAVPP => Hi-Z */
+       sreg &= ~(TPS2211_VCCD0 | TPS2211_VCCD1);       /* 3V and 5V off */
+       immap->im_ioport.iop_pcdat = sreg;
+
+       immap->im_ioport.iop_pcpar &= ~(TPS2211_OUTPUTS);
+       immap->im_ioport.iop_pcdir |=   TPS2211_OUTPUTS;
+
+       debug ("Set Port C: PAR:     %04x DIR:     %04x DAT:     %04x\n",
+               immap->im_ioport.iop_pcpar,
+               immap->im_ioport.iop_pcdir,
+               immap->im_ioport.iop_pcdat);
+
+       /*
+        * Configure Port B for TPS2211 PC-Card Power-Interface Switch
+        *
+        * Over-Current Input only
+        */
+       cp->cp_pbpar &= ~(TPS2211_INPUTS);
+       cp->cp_pbdir &= ~(TPS2211_INPUTS);
+
+       debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n",
+               cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat);
+}
+
+#endif /* C2MON */
+
+/* ----------------------------------------------------------------------------
+   MBX board from Morotola
+   ---------------------------------------------------------------------------- */
+
+#if defined( CONFIG_MBX )
+#include <../board/mbx8xx/csr.h>
+
+/* A lot of this has been taken from the RPX code in this file it works from me.
+   I have added the voltage selection for the MBX board. */
+
+/* MBX voltage bit in control register #2 */
+#define CR2_VPP12       ((uchar)0x10)
+#define CR2_VPPVDD      ((uchar)0x20)
+#define CR2_VDD5        ((uchar)0x40)
+#define CR2_VDD3        ((uchar)0x80)
+
+#define PCMCIA_BOARD_MSG "MBX860"
+
+static int voltage_set (int slot, int vcc, int vpp)
+{
+       uchar reg = 0;
+
+       debug ("voltage_set: PCMCIA_BOARD_MSG Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
+                'A' + slot, vcc / 10, vcc % 10, vpp / 10, vcc % 10);
+
+       switch (vcc) {
+       case 0:
+               break;
+       case 33:
+               reg |= CR2_VDD3;
+               break;
+       case 50:
+               reg |= CR2_VDD5;
+               break;
+       default:
+               return 1;
+       }
+
+       switch (vpp) {
+       case 0:
+               break;
+       case 33:
+       case 50:
+               if (vcc == vpp) {
+                       reg |= CR2_VPPVDD;
+               } else {
+                       return 1;
+               }
+               break;
+       case 120:
+               reg |= CR2_VPP12;
+               break;
+       default:
+               return 1;
+       }
+
+       /* first, turn off all power */
+       MBX_CSR2 &= ~(CR2_VDDSEL | CR2_VPPSEL);
+
+       /* enable new powersettings */
+       MBX_CSR2 |= reg;
+       debug ("MBX_CSR2 read = 0x%02x\n", MBX_CSR2);
+
+       return (0);
+}
+
+static int hardware_enable (int slot)
+{
+       volatile immap_t *immap;
+       volatile cpm8xx_t *cp;
+       volatile pcmconf8xx_t *pcmp;
+       volatile sysconf8xx_t *sysp;
+       uint reg, mask;
+
+       debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n",
+                                 'A' + slot);
+
+       udelay (10000);
+
+       immap = (immap_t *) CFG_IMMR;
+       sysp = (sysconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_siu_conf));
+       pcmp = (pcmconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_pcmcia));
+       cp = (cpm8xx_t *) (&(((immap_t *) CFG_IMMR)->im_cpm));
+
+       /* clear interrupt state, and disable interrupts */
+       pcmp->pcmc_pscr = PCMCIA_MASK (_slot_);
+       pcmp->pcmc_per &= ~PCMCIA_MASK (_slot_);
+
+       /* disable interrupts & DMA */
+       PCMCIA_PGCRX (_slot_) = 0;
+
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg = PCMCIA_PGCRX (_slot_);
+       reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
+       reg |= __MY_PCMCIA_GCRX_CXOE;   /* active low  */
+       PCMCIA_PGCRX (_slot_) = reg;
+       udelay (500);
+
+       /* remove all power */
+       voltage_set (slot, 0, 0);
+       /*
+        * Make sure there is a card in the slot, then configure the interface.
+        */
+       udelay (10000);
+       debug ("[%d] %s: PIPR(%p)=0x%x\n", __LINE__, __FUNCTION__,
+                 &(pcmp->pcmc_pipr), pcmp->pcmc_pipr);
+
+       if (pcmp->pcmc_pipr & 0x00001800) {
+               printf ("   No Card found\n");
+               return (1);
+       }
+
+       /*
+        * Power On.
+        */
+       mask = PCMCIA_VS1 (_slot_) | PCMCIA_VS2 (_slot_);
+       reg = pcmp->pcmc_pipr;
+       debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", reg,
+                 (reg & PCMCIA_VS1 (slot)) ? "n" : "ff",
+                 (reg & PCMCIA_VS2 (slot)) ? "n" : "ff");
+
+       if ((reg & mask) == mask) {
+               voltage_set (_slot_, 50, 0);
+               printf (" 5.0V card found: ");
+       } else {
+               voltage_set (_slot_, 33, 0);
+               printf (" 3.3V card found: ");
+       }
+
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg = PCMCIA_PGCRX (_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;  /* active low  */
+       PCMCIA_PGCRX (_slot_) = reg;
+
+       udelay (250000);        /* some cards need >150 ms to come up :-( */
+
+       debug ("# hardware_enable done\n");
+
+       return (0);
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable (int slot)
+{
+       return 0;       /* No hardware to disable */
+}
+#endif /* CFG_CMD_PCMCIA */
+#endif /* CONFIG_MBX */
+/* ---------------------------------------------------------------------------- */
+/* R360MPI Board                                                               */
+/* ---------------------------------------------------------------------------- */
+
+#if defined(CONFIG_R360MPI)
+
+#define PCMCIA_BOARD_MSG "R360MPI"
+
+
+static int hardware_enable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile cpm8xx_t       *cp;
+       volatile pcmconf8xx_t   *pcmp;
+       volatile sysconf8xx_t   *sysp;
+       uint reg, mask;
+
+       debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       udelay(10000);
+
+       immap = (immap_t *)CFG_IMMR;
+       sysp  = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
+       pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
+
+       /*
+        * Configure SIUMCR to enable PCMCIA port B
+        * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
+        */
+       sysp->sc_siumcr &= ~SIUMCR_DBGC11;      /* set DBGC to 00 */
+
+       /* clear interrupt state, and disable interrupts */
+       pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
+       pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
+
+       /* disable interrupts & DMA */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Configure Ports A, B & C pins for
+        * 5 Volts Enable and 3 Volts enable
+        */
+       immap->im_ioport.iop_pcpar &= ~(0x0400);
+       immap->im_ioport.iop_pcso  &= ~(0x0400);/*
+       immap->im_ioport.iop_pcdir |= 0x0400;*/
+
+       immap->im_ioport.iop_papar &= ~(0x0200);/*
+       immap->im_ioport.iop_padir |= 0x0200;*/
+#if 0
+       immap->im_ioport.iop_pbpar &= ~(0xC000);
+       immap->im_ioport.iop_pbdir &= ~(0xC000);
+#endif
+       /* remove all power */
+
+       immap->im_ioport.iop_pcdat |= 0x0400;
+       immap->im_ioport.iop_padat |= 0x0200;
+
+       /*
+        * Make sure there is a card in the slot, then configure the interface.
+        */
+       udelay(10000);
+       debug ("[%d] %s: PIPR(%p)=0x%x\n",
+               __LINE__,__FUNCTION__,
+               &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
+       if (pcmp->pcmc_pipr & 0x00001800) {
+               printf ("   No Card found\n");
+               return (1);
+       }
+
+       /*
+        * Power On.
+        */
+       mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
+       reg  = pcmp->pcmc_pipr;
+       debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
+               reg,
+               (reg&PCMCIA_VS1(slot))?"n":"ff",
+               (reg&PCMCIA_VS2(slot))?"n":"ff");
+       if ((reg & mask) == mask) {
+               immap->im_ioport.iop_pcdat &= ~(0x4000);
+               puts (" 5.0V card found: ");
+       } else {
+               immap->im_ioport.iop_padat &= ~(0x0002);
+               puts (" 3.3V card found: ");
+       }
+       immap->im_ioport.iop_pcdir |= 0x0400;
+       immap->im_ioport.iop_padir |= 0x0200;
+#if 0
+       /*  VCC switch error flag, PCMCIA slot INPACK_ pin */
+       cp->cp_pbdir &= ~(0x0020 | 0x0010);
+       cp->cp_pbpar &= ~(0x0020 | 0x0010);
+       udelay(500000);
+#endif
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       udelay(250000); /* some cards need >150 ms to come up :-( */
+
+       debug ("# hardware_enable done\n");
+
+       return (0);
+}
+
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+static int hardware_disable(int slot)
+{
+       volatile immap_t        *immap;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+
+       debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
+
+       immap = (immap_t *)CFG_IMMR;
+       pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+
+       /* remove all power */
+       immap->im_ioport.iop_pcdat |= 0x0400;
+       immap->im_ioport.iop_padat |= 0x0200;
+
+       /* Configure PCMCIA General Control Register */
+       PCMCIA_PGCRX(_slot_) = 0;
+
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
+       reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+
+       udelay(10000);
+
+       return (0);
+}
+#endif /* CFG_CMD_PCMCIA */
+
+
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+       volatile immap_t        *immap;
+       volatile pcmconf8xx_t   *pcmp;
+       u_long reg;
+
+       debug ("voltage_set: "
+               PCMCIA_BOARD_MSG
+               " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
+               'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
+
+       immap = (immap_t *)CFG_IMMR;
+       pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
+       /*
+        * Disable PCMCIA buffers (isolate the interface)
+        * and assert RESET signal
+        */
+       debug ("Disable PCMCIA buffers and assert RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg |=  __MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg |=  __MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       /*
+        * Configure Ports A & C pins for
+        * 5 Volts Enable and 3 Volts enable,
+        * Turn off all power
+        */
+       debug ("PCMCIA power OFF\n");
+       immap->im_ioport.iop_pcpar &= ~(0x0400);
+       immap->im_ioport.iop_pcso  &= ~(0x0400);/*
+       immap->im_ioport.iop_pcdir |= 0x0400;*/
+
+       immap->im_ioport.iop_papar &= ~(0x0200);/*
+       immap->im_ioport.iop_padir |= 0x0200;*/
+
+       immap->im_ioport.iop_pcdat |= 0x0400;
+       immap->im_ioport.iop_padat |= 0x0200;
+
+       reg = 0;
+       switch(vcc) {
+       case  0:                break;
+       case 33: reg |= 0x0200; break;
+       case 50: reg |= 0x0400; break;
+       default:                goto done;
+       }
+
+       /* Checking supported voltages */
+
+       debug ("PIPR: 0x%x --> %s\n",
+               pcmp->pcmc_pipr,
+               (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
+
+       if (reg & 0x0200)
+               immap->im_ioport.iop_pcdat &= !reg;
+       if (reg & 0x0400)
+               immap->im_ioport.iop_padat &= !reg;
+       immap->im_ioport.iop_pcdir |=  0x0200;
+       immap->im_ioport.iop_padir |=  0x0400;
+       if (reg) {
+               debug ("PCMCIA powered at %sV\n",
+                       (reg&0x0400) ? "5.0" : "3.3");
+       } else {
+               debug ("PCMCIA powered down\n");
+       }
+
+done:
+       debug ("Enable PCMCIA buffers and stop RESET\n");
+       reg  =  PCMCIA_PGCRX(_slot_);
+       reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
+       reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
+       PCMCIA_PGCRX(_slot_) = reg;
+       udelay(500);
+
+       debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
+               slot+'A');
+       return (0);
+}
+
+#endif /* R360MPI */
+
+
+/* ---------------------------------------------------------------------------- */
+/* End of Board Specific Stuff                                                 */
+/* ---------------------------------------------------------------------------- */
+
+
+/* ---------------------------------------------------------------------------- */
+/* MPC8xx Specific Stuff - should go to MPC8xx directory                       */
+/* ---------------------------------------------------------------------------- */
+
+/*
+ * Search this table to see if the windowsize is
+ * supported...
+ */
+
+#define M8XX_SIZES_NO 32
+
+static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] =
+{ 0x00000001, 0x00000002, 0x00000008, 0x00000004,
+  0x00000080, 0x00000040, 0x00000010, 0x00000020,
+  0x00008000, 0x00004000, 0x00001000, 0x00002000,
+  0x00000100, 0x00000200, 0x00000800, 0x00000400,
+
+  0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+  0x01000000, 0x02000000, 0xffffffff, 0x04000000,
+  0x00010000, 0x00020000, 0x00080000, 0x00040000,
+  0x00800000, 0x00400000, 0x00100000, 0x00200000 };
+
+
+/* ---------------------------------------------------------------------------- */
+
+static u_int m8xx_get_graycode(u_int size)
+{
+       u_int k;
+
+       for (k = 0; k < M8XX_SIZES_NO; k++) {
+               if(m8xx_size_to_gray[k] == size)
+                       break;
+       }
+
+       if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
+               k = -1;
+
+       return k;
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if 0
+static u_int m8xx_get_speed(u_int ns, u_int is_io)
+{
+       u_int reg, clocks, psst, psl, psht;
+
+       if(!ns) {
+
+               /*
+                * We get called with IO maps setup to 0ns
+                * if not specified by the user.
+                * They should be 255ns.
+                */
+
+               if(is_io)
+                       ns = 255;
+               else
+                       ns = 100;  /* fast memory if 0 */
+       }
+
+       /*
+        * In PSST, PSL, PSHT fields we tell the controller
+        * timing parameters in CLKOUT clock cycles.
+        * CLKOUT is the same as GCLK2_50.
+        */
+
+/* how we want to adjust the timing - in percent */
+
+#define ADJ 180 /* 80 % longer accesstime - to be sure */
+
+       clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
+       clocks = (clocks * ADJ) / (100*1000);
+
+       if(clocks >= PCMCIA_BMT_LIMIT) {
+               DEBUG(0, "Max access time limit reached\n");
+               clocks = PCMCIA_BMT_LIMIT-1;
+       }
+
+       psst = clocks / 7;          /* setup time */
+       psht = clocks / 7;          /* hold time */
+       psl  = (clocks * 5) / 7;    /* strobe length */
+
+       psst += clocks - (psst + psht + psl);
+
+       reg =  psst << 12;
+       reg |= psl  << 7;
+       reg |= psht << 16;
+
+       return reg;
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+static void print_funcid (int func)
+{
+       puts (indent);
+       switch (func) {
+       case CISTPL_FUNCID_MULTI:
+               puts (" Multi-Function");
+               break;
+       case CISTPL_FUNCID_MEMORY:
+               puts (" Memory");
+               break;
+       case CISTPL_FUNCID_SERIAL:
+               puts (" Serial Port");
+               break;
+       case CISTPL_FUNCID_PARALLEL:
+               puts (" Parallel Port");
+               break;
+       case CISTPL_FUNCID_FIXED:
+               puts (" Fixed Disk");
+               break;
+       case CISTPL_FUNCID_VIDEO:
+               puts (" Video Adapter");
+               break;
+       case CISTPL_FUNCID_NETWORK:
+               puts (" Network Adapter");
+               break;
+       case CISTPL_FUNCID_AIMS:
+               puts (" AIMS Card");
+               break;
+       case CISTPL_FUNCID_SCSI:
+               puts (" SCSI Adapter");
+               break;
+       default:
+               puts (" Unknown");
+               break;
+       }
+       puts (" Card\n");
+}
+#endif /* CONFIG_IDE_8xx_PCCARD */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+static void print_fixed (volatile uchar *p)
+{
+       if (p == NULL)
+               return;
+
+       puts(indent);
+
+       switch (*p) {
+       case CISTPL_FUNCE_IDE_IFACE:
+           {   uchar iface = *(p+2);
+
+               puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown");
+               puts (" interface ");
+               break;
+           }
+       case CISTPL_FUNCE_IDE_MASTER:
+       case CISTPL_FUNCE_IDE_SLAVE:
+           {   uchar f1 = *(p+2);
+               uchar f2 = *(p+4);
+
+               puts ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]");
+
+               if (f1 & CISTPL_IDE_UNIQUE)
+                       puts (" [unique]");
+
+               puts ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]");
+
+               if (f2 & CISTPL_IDE_HAS_SLEEP)
+                       puts (" [sleep]");
+
+               if (f2 & CISTPL_IDE_HAS_STANDBY)
+                       puts (" [standby]");
+
+               if (f2 & CISTPL_IDE_HAS_IDLE)
+                       puts (" [idle]");
+
+               if (f2 & CISTPL_IDE_LOW_POWER)
+                       puts (" [low power]");
+
+               if (f2 & CISTPL_IDE_REG_INHIBIT)
+                       puts (" [reg inhibit]");
+
+               if (f2 & CISTPL_IDE_HAS_INDEX)
+                       puts (" [index]");
+
+               if (f2 & CISTPL_IDE_IOIS16)
+                       puts (" [IOis16]");
+
+               break;
+           }
+       }
+       putc ('\n');
+}
+#endif /* CONFIG_IDE_8xx_PCCARD */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+
+#define MAX_IDENT_CHARS                64
+#define        MAX_IDENT_FIELDS        4
+
+static uchar *known_cards[] = {
+       "ARGOSY PnPIDE D5",
+       NULL
+};
+
+static int identify  (volatile uchar *p)
+{
+       uchar id_str[MAX_IDENT_CHARS];
+       uchar data;
+       uchar *t;
+       uchar **card;
+       int i, done;
+
+       if (p == NULL)
+               return (0);     /* Don't know */
+
+       t = id_str;
+       done =0;
+
+       for (i=0; i<=4 && !done; ++i, p+=2) {
+               while ((data = *p) != '\0') {
+                       if (data == 0xFF) {
+                               done = 1;
+                               break;
+                       }
+                       *t++ = data;
+                       if (t == &id_str[MAX_IDENT_CHARS-1]) {
+                               done = 1;
+                               break;
+                       }
+                       p += 2;
+               }
+               if (!done)
+                       *t++ = ' ';
+       }
+       *t = '\0';
+       while (--t > id_str) {
+               if (*t == ' ')
+                       *t = '\0';
+               else
+                       break;
+       }
+       puts (id_str);
+       putc ('\n');
+
+       for (card=known_cards; *card; ++card) {
+               debug ("## Compare against \"%s\"\n", *card);
+               if (strcmp(*card, id_str) == 0) {       /* found! */
+                       debug ("## CARD FOUND ##\n");
+                       return (1);
+               }
+       }
+
+       return (0);     /* don't know */
+}
+#endif /* CONFIG_IDE_8xx_PCCARD */
+
+/* ------------------------------------------------------------------------- */
+
+#endif /* CFG_CMD_PCMCIA || (CFG_CMD_IDE && CONFIG_IDE_8xx_PCCARD) */
diff --git a/common/env_flash.c b/common/env_flash.c
new file mode 100644 (file)
index 0000000..1593d2c
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@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
+ */
+
+/* #define DEBUG */
+
+#include <common.h>
+
+#if defined(CFG_ENV_IS_IN_FLASH) /* Environment is in Flash */
+
+#include <command.h>
+#include <environment.h>
+#include <cmd_nvedit.h>
+#include <linux/stddef.h>
+
+#if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_FLASH)) == (CFG_CMD_ENV|CFG_CMD_FLASH))
+#define CMD_SAVEENV
+#elif defined(CFG_ENV_ADDR_REDUND)
+#error Cannot use CFG_ENV_ADDR_REDUND without CFG_CMD_ENV & CFG_CMD_FLASH
+#endif
+
+#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE) && \
+    defined(CFG_ENV_ADDR_REDUND)
+#error CFG_ENV_ADDR_REDUND should not be used when CFG_ENV_SECT_SIZE > CFG_ENV_SIZE
+#endif
+
+#if defined(CFG_ENV_SIZE_REDUND) && (CFG_ENV_SIZE_REDUND < CFG_ENV_SIZE)
+#error CFG_ENV_SIZE_REDUND should not be less then CFG_ENV_SIZE
+#endif
+
+#ifdef CONFIG_INFERNO
+# ifdef CFG_ENV_ADDR_REDUND
+#error CFG_ENV_ADDR_REDUND is not implemented for CONFIG_INFERNO
+# endif
+#endif
+
+char * env_name_spec = "Flash";
+
+#ifdef ENV_IS_EMBEDDED
+
+extern uchar environment[];
+env_t *env_ptr = (env_t *)(&environment[0]);
+
+#ifdef CMD_SAVEENV
+/* static env_t *flash_addr = (env_t *)(&environment[0]);-broken on ARM-wd-*/
+static env_t *flash_addr = (env_t *)CFG_ENV_ADDR;
+#endif
+
+#else /* ! ENV_IS_EMBEDDED */
+
+env_t *env_ptr = (env_t *)CFG_ENV_ADDR;
+#ifdef CMD_SAVEENV
+static env_t *flash_addr = (env_t *)CFG_ENV_ADDR;
+#endif
+
+#endif /* ENV_IS_EMBEDDED */
+
+#ifdef CFG_ENV_ADDR_REDUND
+static env_t *flash_addr_new = (env_t *)CFG_ENV_ADDR_REDUND;
+
+static ulong end_addr = CFG_ENV_ADDR + CFG_ENV_SIZE - 1;
+static ulong end_addr_new = CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1;
+
+static uchar active_flag = 1;
+static uchar obsolete_flag = 0;
+#endif
+
+extern uchar default_environment[];
+extern int default_environment_size;
+
+
+uchar env_get_char_spec (int index)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       return ( *((uchar *)(gd->env_addr + index)) );
+}
+
+#ifdef CFG_ENV_ADDR_REDUND
+
+int  env_init(void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       int crc1_ok =
+               (crc32(0, flash_addr->data, ENV_SIZE) == flash_addr->crc);
+       int crc2_ok =
+               (crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc);
+
+       uchar flag1 = flash_addr->flags;
+       uchar flag2 = flash_addr_new->flags;
+
+       ulong addr_default = (ulong)&default_environment[0];
+       ulong addr1 = (ulong)&(flash_addr->data);
+       ulong addr2 = (ulong)&(flash_addr_new->data);
+
+       if (crc1_ok && ! crc2_ok)
+       {
+               gd->env_addr  = addr1;
+               gd->env_valid = 1;
+       }
+       else if (! crc1_ok && crc2_ok)
+       {
+               gd->env_addr  = addr2;
+               gd->env_valid = 1;
+       }
+       else if (! crc1_ok && ! crc2_ok)
+       {
+               gd->env_addr  = addr_default;
+               gd->env_valid = 0;
+       }
+       else if (flag1 == active_flag && flag2 == obsolete_flag)
+       {
+               gd->env_addr  = addr1;
+               gd->env_valid = 1;
+       }
+       else if (flag1 == obsolete_flag && flag2 == active_flag)
+       {
+               gd->env_addr  = addr2;
+               gd->env_valid = 1;
+       }
+       else if (flag1 == flag2)
+       {
+               gd->env_addr  = addr1;
+               gd->env_valid = 2;
+       }
+       else if (flag1 == 0xFF)
+       {
+               gd->env_addr  = addr1;
+               gd->env_valid = 2;
+       }
+       else if (flag2 == 0xFF)
+       {
+               gd->env_addr  = addr2;
+               gd->env_valid = 2;
+       }
+
+       return (0);
+}
+
+#ifdef CMD_SAVEENV
+int saveenv(void)
+{
+       int rc = 1;
+
+       debug ("Protect off %08lX ... %08lX\n",
+               (ulong)flash_addr, end_addr);
+
+       if (flash_sect_protect (0, (ulong)flash_addr, end_addr)) {
+               goto Done;
+       }
+
+       debug ("Protect off %08lX ... %08lX\n",
+               (ulong)flash_addr_new, end_addr_new);
+
+       if (flash_sect_protect (0, (ulong)flash_addr_new, end_addr_new)) {
+               goto Done;
+       }
+
+       puts ("Erasing Flash...");
+       debug (" %08lX ... %08lX ...",
+               (ulong)flash_addr_new, end_addr_new);
+
+       if (flash_sect_erase ((ulong)flash_addr_new, end_addr_new)) {
+               goto Done;
+       }
+
+       puts ("Writing to Flash... ");
+       debug (" %08lX ... %08lX ...",
+               (ulong)&(flash_addr_new->data),
+               sizeof(env_ptr->data)+(ulong)&(flash_addr_new->data));
+       if (flash_write(env_ptr->data,
+                       (ulong)&(flash_addr_new->data),
+                       sizeof(env_ptr->data)) ||
+
+           flash_write((char *)&(env_ptr->crc),
+                       (ulong)&(flash_addr_new->crc),
+                       sizeof(env_ptr->crc)) ||
+
+           flash_write((char *)&obsolete_flag,
+                       (ulong)&(flash_addr->flags),
+                       sizeof(flash_addr->flags)) ||
+
+           flash_write((char *)&active_flag,
+                       (ulong)&(flash_addr_new->flags),
+                       sizeof(flash_addr_new->flags)))
+       {
+               flash_perror (rc);
+               goto Done;
+       }
+       puts ("done\n");
+
+       {
+               env_t * etmp = flash_addr;
+               ulong ltmp = end_addr;
+
+               flash_addr = flash_addr_new;
+               flash_addr_new = etmp;
+
+               end_addr = end_addr_new;
+               end_addr_new = ltmp;
+       }
+
+       rc = 0;
+Done:
+
+       /* try to re-protect */
+       (void) flash_sect_protect (1, (ulong)flash_addr, end_addr);
+       (void) flash_sect_protect (1, (ulong)flash_addr_new, end_addr_new);
+
+       return rc;
+}
+#endif /* CMD_SAVEENV */
+
+#else /* ! CFG_ENV_ADDR_REDUND */
+
+int  env_init(void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
+               gd->env_addr  = (ulong)&(env_ptr->data);
+               gd->env_valid = 1;
+       } else {
+               gd->env_addr  = (ulong)&default_environment[0];
+               gd->env_valid = 0;
+       }
+
+       return (0);
+}
+
+#ifdef CMD_SAVEENV
+
+int saveenv(void)
+{
+       int     len, rc;
+       ulong   end_addr;
+       ulong   flash_sect_addr;
+#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
+       ulong   flash_offset;
+       uchar   env_buffer[CFG_ENV_SECT_SIZE];
+#else
+       uchar *env_buffer = (char *)env_ptr;
+#endif /* CFG_ENV_SECT_SIZE */
+       int rcode = 0;
+
+#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
+
+       flash_offset    = ((ulong)flash_addr) & (CFG_ENV_SECT_SIZE-1);
+       flash_sect_addr = ((ulong)flash_addr) & ~(CFG_ENV_SECT_SIZE-1);
+
+       debug ( "copy old content: "
+               "sect_addr: %08lX  env_addr: %08lX  offset: %08lX\n",
+               flash_sect_addr, (ulong)flash_addr, flash_offset);
+
+       /* copy old contents to temporary buffer */
+       memcpy (env_buffer, (void *)flash_sect_addr, CFG_ENV_SECT_SIZE);
+
+       /* copy current environment to temporary buffer */
+       memcpy ((uchar *)((unsigned long)env_buffer + flash_offset),
+               env_ptr,
+               CFG_ENV_SIZE);
+
+       len      = CFG_ENV_SECT_SIZE;
+#else
+       flash_sect_addr = (ulong)flash_addr;
+       len      = CFG_ENV_SIZE;
+#endif /* CFG_ENV_SECT_SIZE */
+
+#ifndef CONFIG_INFERNO
+       end_addr = flash_sect_addr + len - 1;
+#else
+       /* this is the last sector, and the size is hardcoded here */
+       /* otherwise we will get stack problems on loading 128 KB environment */
+       end_addr = flash_sect_addr + 0x20000 - 1;
+#endif
+
+       debug ("Protect off %08lX ... %08lX\n",
+               (ulong)flash_sect_addr, end_addr);
+
+       if (flash_sect_protect (0, flash_sect_addr, end_addr))
+               return 1;
+
+       puts ("Erasing Flash...");
+       if (flash_sect_erase (flash_sect_addr, end_addr))
+               return 1;
+
+       puts ("Writing to Flash... ");
+       rc = flash_write(env_buffer, flash_sect_addr, len);
+       if (rc != 0) {
+               flash_perror (rc);
+               rcode = 1;
+       } else {
+               puts ("done\n");
+       }
+
+       /* try to re-protect */
+       (void) flash_sect_protect (1, flash_sect_addr, end_addr);
+       return rcode;
+}
+
+#endif /* CMD_SAVEENV */
+
+#endif /* CFG_ENV_ADDR_REDUND */
+
+void env_relocate_spec (void)
+{
+#if !defined(ENV_IS_EMBEDDED) || defined(CFG_ENV_ADDR_REDUND)
+#ifdef CFG_ENV_ADDR_REDUND
+       DECLARE_GLOBAL_DATA_PTR;
+
+       if (gd->env_addr != (ulong)&(flash_addr->data))
+       {
+               env_t * etmp = flash_addr;
+               ulong ltmp = end_addr;
+
+               flash_addr = flash_addr_new;
+               flash_addr_new = etmp;
+
+               end_addr = end_addr_new;
+               end_addr_new = ltmp;
+       }
+
+       if (flash_addr_new->flags != obsolete_flag &&
+           crc32(0, flash_addr_new->data, ENV_SIZE) ==
+           flash_addr_new->crc)
+       {
+               gd->env_valid = 2;
+               flash_sect_protect (0, (ulong)flash_addr_new, end_addr_new);
+               flash_write((char *)&obsolete_flag,
+                           (ulong)&(flash_addr_new->flags),
+                           sizeof(flash_addr_new->flags));
+               flash_sect_protect (1, (ulong)flash_addr_new, end_addr_new);
+       }
+
+       if (flash_addr->flags != active_flag &&
+           (flash_addr->flags & active_flag) == active_flag)
+       {
+               gd->env_valid = 2;
+               flash_sect_protect (0, (ulong)flash_addr, end_addr);
+               flash_write((char *)&active_flag,
+                           (ulong)&(flash_addr->flags),
+                           sizeof(flash_addr->flags));
+               flash_sect_protect (1, (ulong)flash_addr, end_addr);
+       }
+
+       if (gd->env_valid == 2)
+               puts ("*** Warning - some problems detected "
+                     "reading environment; recovered successfully\n\n");
+#endif /* CFG_ENV_ADDR_REDUND */
+       memcpy (env_ptr, (void*)flash_addr, CFG_ENV_SIZE);
+#endif /* ! ENV_IS_EMBEDDED || CFG_ENV_ADDR_REDUND */
+}
+
+#endif /* CFG_ENV_IS_IN_FLASH) */
diff --git a/common/env_nvram.c b/common/env_nvram.c
new file mode 100644 (file)
index 0000000..fdfa4fc
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@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
+ */
+
+/*
+ * 09-18-2001 Andreas Heppel, Sysgo RTS GmbH <aheppel@sysgo.de>
+ *
+ * It might not be possible in all cases to use 'memcpy()' to copy
+ * the environment to NVRAM, as the NVRAM might not be mapped into
+ * the memory space. (I.e. this is the case for the BAB750). In those
+ * cases it might be possible to access the NVRAM using a different
+ * method. For example, the RTC on the BAB750 is accessible in IO
+ * space using its address and data registers. To enable usage of
+ * NVRAM in those cases I invented the functions 'nvram_read()' and
+ * 'nvram_write()', which will be activated upon the configuration
+ * #define CFG_NVRAM_ACCESS_ROUTINE. Note, that those functions are
+ * strongly dependent on the used HW, and must be redefined for each
+ * board that wants to use them.
+ */
+
+#include <common.h>
+
+#ifdef CFG_ENV_IS_IN_NVRAM /* Environment is in NVRAM */
+
+#include <command.h>
+#include <environment.h>
+#include <cmd_nvedit.h>
+#include <linux/stddef.h>
+#include <malloc.h>
+
+#ifdef CFG_NVRAM_ACCESS_ROUTINE
+extern void *nvram_read(void *dest, const long src, size_t count);
+extern void nvram_write(long dest, const void *src, size_t count);
+env_t *env_ptr = NULL;
+#else
+env_t *env_ptr = (env_t *)CFG_ENV_ADDR;
+#endif
+
+char * env_name_spec = "NVRAM";
+
+extern uchar default_environment[];
+extern int default_environment_size;
+
+extern uchar (*env_get_char)(int);
+extern uchar env_get_char_memory (int index);
+
+
+uchar env_get_char_spec (int index)
+{
+#ifdef CFG_NVRAM_ACCESS_ROUTINE
+       uchar c;
+
+       nvram_read(&c, CFG_ENV_ADDR+index, 1);
+
+       return c;
+#else
+       DECLARE_GLOBAL_DATA_PTR;
+
+       return *((uchar *)(gd->env_addr + index));
+#endif
+}
+
+void env_relocate_spec (void)
+{
+#if defined(CFG_NVRAM_ACCESS_ROUTINE)
+       nvram_read(env_ptr, CFG_ENV_ADDR, CFG_ENV_SIZE);
+#else
+       memcpy (env_ptr, (void*)CFG_ENV_ADDR, CFG_ENV_SIZE);
+#endif
+}
+
+int saveenv (void)
+{
+       int rcode = 0;
+
+#ifdef CFG_NVRAM_ACCESS_ROUTINE
+       nvram_write(CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE);
+#else
+       if (memcpy ((char *)CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE) == NULL)
+                   rcode = 1 ;
+#endif
+       return rcode;
+}
+
+
+/************************************************************************
+ * Initialize Environment use
+ *
+ * We are still running from ROM, so data use is limited
+ */
+int env_init (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CFG_NVRAM_ACCESS_ROUTINE)
+       ulong crc;
+       uchar data[ENV_SIZE];
+       nvram_read (&crc, CFG_ENV_ADDR, sizeof(ulong));
+       nvram_read (data, CFG_ENV_ADDR+sizeof(ulong), ENV_SIZE);
+
+       if (crc32(0, data, ENV_SIZE) == crc) {
+               gd->env_addr  = (ulong)CFG_ENV_ADDR + sizeof(long);
+#else
+       if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
+               gd->env_addr  = (ulong)&(env_ptr->data);
+#endif
+               gd->env_valid = 1;
+       } else {
+               gd->env_addr  = (ulong)&default_environment[0];
+               gd->env_valid = 0;
+       }
+
+       return (0);
+}
+
+#endif /* CFG_ENV_IS_IN_NVRAM */
diff --git a/common/environment.c b/common/environment.c
new file mode 100644 (file)
index 0000000..74bfd62
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * (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 <config.h>
+#include <environment.h>
+
+/*
+ * Handle HOSTS that have prepended
+ * crap on symbol names, not TARGETS.
+ */
+#if defined(__APPLE__)
+/* Leading underscore on symbols */
+#  define SYM_CHAR "_"
+#else /* No leading character on symbols */
+#  define SYM_CHAR
+#endif
+
+/*
+ * Generate embedded environment table
+ * inside U-Boot image, if needed.
+ */
+#if defined(ENV_IS_EMBEDDED)
+/*
+ * Only put the environment in it's own section when we are building
+ * U-Boot proper.  The host based program "tools/envcrc" does not need
+ * a seperate section.  Note that ENV_CRC is only defined when building
+ * U-Boot itself.
+ */
+#if (defined(CONFIG_FADS)      || \
+     defined(CONFIG_HYMOD)     || \
+     defined(CONFIG_ICU862)    || \
+     defined(CONFIG_R360MPI)   || \
+     defined(CONFIG_TQM8xxL)   || \
+     defined(CONFIG_RRVISION)  || \
+     defined(CONFIG_TRAB)   )  && \
+     defined(ENV_CRC) /* Environment embedded in U-Boot .ppcenv section */
+/* XXX - This only works with GNU C */
+#  define __PPCENV__ __attribute__ ((section(".ppcenv")))
+#  define __PPCTEXT__ __attribute__ ((section(".text")))
+
+#elif defined(USE_HOSTCC) /* Native for 'tools/envcrc' */
+#  define __PPCENV__ /*XXX DO_NOT_DEL_THIS_COMMENT*/
+#  define __PPCTEXT__ /*XXX DO_NOT_DEL_THIS_COMMENT*/
+
+#else /* Environment is embedded in U-Boot's .text section */
+/* XXX - This only works with GNU C */
+#  define __PPCENV__ __attribute__ ((section(".text")))
+#  define __PPCTEXT__ __attribute__ ((section(".text")))
+#endif
+
+/*
+ * Macros to generate global absolutes.
+ */
+#define GEN_SYMNAME(str) SYM_CHAR #str
+#define GEN_VALUE(str) #str
+#define GEN_ABS(name, value) \
+               asm (".globl " GEN_SYMNAME(name)); \
+               asm (GEN_SYMNAME(name) " = " GEN_VALUE(value))
+
+/*
+ * Macros to transform values
+ * into environment strings.
+ */
+#define XMK_STR(x)     #x
+#define MK_STR(x)      XMK_STR(x)
+
+/*
+ * Check to see if we are building with a
+ * computed CRC.  Otherwise define it as ~0.
+ */
+#if !defined(ENV_CRC)
+#  define ENV_CRC      ~0
+#endif
+
+env_t environment __PPCENV__ = {
+       ENV_CRC,        /* CRC Sum */
+#ifdef CFG_REDUNDAND_ENVIRONMENT
+       1,              /* Flags: valid */
+#endif
+       {
+#if defined(CONFIG_BOOTARGS)
+       "bootargs="     CONFIG_BOOTARGS                 "\0"
+#endif
+#if defined(CONFIG_BOOTCOMMAND)
+       "bootcmd="      CONFIG_BOOTCOMMAND              "\0"
+#endif
+#if defined(CONFIG_RAMBOOTCOMMAND)
+       "ramboot="      CONFIG_RAMBOOTCOMMAND           "\0"
+#endif
+#if defined(CONFIG_NFSBOOTCOMMAND)
+       "nfsboot="      CONFIG_NFSBOOTCOMMAND           "\0"
+#endif
+#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
+       "bootdelay="    MK_STR(CONFIG_BOOTDELAY)        "\0"
+#endif
+#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
+       "baudrate="     MK_STR(CONFIG_BAUDRATE)         "\0"
+#endif
+#ifdef CONFIG_LOADS_ECHO
+       "loads_echo="   MK_STR(CONFIG_LOADS_ECHO)       "\0"
+#endif
+#ifdef CONFIG_ETHADDR
+       "ethaddr="      MK_STR(CONFIG_ETHADDR)          "\0"
+#endif
+#ifdef CONFIG_ETH1ADDR
+       "eth1addr="     MK_STR(CONFIG_ETH1ADDR)         "\0"
+#endif
+#ifdef CONFIG_ETH2ADDR
+       "eth2addr="     MK_STR(CONFIG_ETH2ADDR)         "\0"
+#endif
+#ifdef CONFIG_ETHPRIME
+       "ethprime="     CONFIG_ETHPRIME                 "\0"
+#endif
+#ifdef CONFIG_IPADDR
+       "ipaddr="       MK_STR(CONFIG_IPADDR)           "\0"
+#endif
+#ifdef CONFIG_SERVERIP
+       "serverip="     MK_STR(CONFIG_SERVERIP)         "\0"
+#endif
+#ifdef CFG_AUTOLOAD
+       "autoload="     CFG_AUTOLOAD                    "\0"
+#endif
+#ifdef CONFIG_ROOTPATH
+       "rootpath="     MK_STR(CONFIG_ROOTPATH)         "\0"
+#endif
+#ifdef CONFIG_GATEWAYIP
+       "gatewayip="    MK_STR(CONFIG_GATEWAYIP)        "\0"
+#endif
+#ifdef CONFIG_NETMASK
+       "netmask="      MK_STR(CONFIG_NETMASK)          "\0"
+#endif
+#ifdef CONFIG_HOSTNAME
+       "hostname="     MK_STR(CONFIG_HOSTNAME)         "\0"
+#endif
+#ifdef CONFIG_BOOTFILE
+       "bootfile="     MK_STR(CONFIG_BOOTFILE)         "\0"
+#endif
+#ifdef CONFIG_LOADADDR
+       "loadaddr="     MK_STR(CONFIG_LOADADDR)         "\0"
+#endif
+#ifdef CONFIG_PREBOOT
+       "preboot="      CONFIG_PREBOOT                  "\0"
+#endif
+#ifdef CONFIG_CLOCKS_IN_MHZ
+       "clocks_in_mhz=" "1"                            "\0"
+#endif
+#ifdef  CONFIG_EXTRA_ENV_SETTINGS
+       CONFIG_EXTRA_ENV_SETTINGS
+#endif
+       "\0"            /* Term. env_t.data with 2 NULLs */
+       }
+};
+#ifdef CFG_ENV_ADDR_REDUND
+env_t redundand_environment __PPCENV__ = {
+       0,              /* CRC Sum: invalid */
+       0,              /* Flags:   invalid */
+       {
+       "\0"
+       }
+};
+#endif /* CFG_ENV_ADDR_REDUND */
+
+/*
+ * These will end up in the .text section
+ * if the environment strings are embedded
+ * in the image.  When this is used for
+ * tools/envcrc, they are placed in the
+ * .data/.sdata section.
+ *
+ */
+unsigned long env_size __PPCTEXT__ = sizeof(env_t);
+
+/*
+ * Add in absolutes.
+ */
+GEN_ABS(env_offset, CFG_ENV_OFFSET);
+
+#endif /* ENV_IS_EMBEDDED */
diff --git a/common/main.c b/common/main.c
new file mode 100644 (file)
index 0000000..014804b
--- /dev/null
@@ -0,0 +1,817 @@
+/*
+ * (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 <watchdog.h>
+#include <command.h>
+#include <cmd_nvedit.h>
+#include <cmd_bootm.h>
+#include <malloc.h>
+#if defined(CONFIG_BOOT_RETRY_TIME) && defined(CONFIG_RESET_TO_RETRY)
+#include <cmd_boot.h>          /* for do_reset() prototype */
+#endif
+
+#ifdef CFG_HUSH_PARSER
+#include <hush.h>
+#endif
+
+#define MAX_DELAY_STOP_STR 32
+
+static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen);
+static int parse_line (char *, char *[]);
+#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
+static int abortboot(int);
+#endif
+
+#undef DEBUG_PARSER
+
+char        console_buffer[CFG_CBSIZE];                /* console I/O buffer   */
+
+static char erase_seq[] = "\b \b";             /* erase sequence       */
+static char   tab_seq[] = "        ";          /* used to expand TABs  */
+
+#ifdef CONFIG_BOOT_RETRY_TIME
+static uint64_t endtime = 0;  /* must be set, default is instant timeout */
+static int      retry_time = -1; /* -1 so can call readline before main_loop */
+#endif
+
+#define        endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk())
+
+#ifndef CONFIG_BOOT_RETRY_MIN
+#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME
+#endif
+
+#ifdef CONFIG_MODEM_SUPPORT
+int do_mdm_init = 0;
+extern void mdm_init(void); /* defined in board.c */
+#endif
+
+/***************************************************************************
+ * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
+ * returns: 0 -  no key string, allow autoboot
+ *          1 - got key string, abort
+ */
+#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
+# if defined(CONFIG_AUTOBOOT_KEYED)
+static __inline__ int abortboot(int bootdelay)
+{
+       int abort = 0;
+       uint64_t etime = endtick(bootdelay);
+       struct
+       {
+               char* str;
+               u_int len;
+               int retry;
+       }
+       delaykey [] =
+       {
+               { str: getenv ("bootdelaykey"),  retry: 1 },
+               { str: getenv ("bootdelaykey2"), retry: 1 },
+               { str: getenv ("bootstopkey"),   retry: 0 },
+               { str: getenv ("bootstopkey2"),  retry: 0 },
+       };
+
+       char presskey [MAX_DELAY_STOP_STR];
+       u_int presskey_len = 0;
+       u_int presskey_max = 0;
+       u_int i;
+
+#  ifdef CONFIG_AUTOBOOT_PROMPT
+       printf (CONFIG_AUTOBOOT_PROMPT, bootdelay);
+#  endif
+
+#  ifdef CONFIG_AUTOBOOT_DELAY_STR
+       if (delaykey[0].str == NULL)
+               delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
+#  endif
+#  ifdef CONFIG_AUTOBOOT_DELAY_STR2
+       if (delaykey[1].str == NULL)
+               delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2;
+#  endif
+#  ifdef CONFIG_AUTOBOOT_STOP_STR
+       if (delaykey[2].str == NULL)
+               delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR;
+#  endif
+#  ifdef CONFIG_AUTOBOOT_STOP_STR2
+       if (delaykey[3].str == NULL)
+               delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2;
+#  endif
+
+       for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
+               delaykey[i].len = delaykey[i].str == NULL ?
+                                   0 : strlen (delaykey[i].str);
+               delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?
+                                   MAX_DELAY_STOP_STR : delaykey[i].len;
+
+               presskey_max = presskey_max > delaykey[i].len ?
+                                   presskey_max : delaykey[i].len;
+
+#  if DEBUG_BOOTKEYS
+               printf("%s key:<%s>\n",
+                      delaykey[i].retry ? "delay" : "stop",
+                      delaykey[i].str ? delaykey[i].str : "NULL");
+#  endif
+       }
+
+       /* In order to keep up with incoming data, check timeout only
+        * when catch up.
+        */
+       while (!abort && get_ticks() <= etime) {
+               for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
+                       if (delaykey[i].len > 0 &&
+                           presskey_len >= delaykey[i].len &&
+                           memcmp (presskey + presskey_len - delaykey[i].len,
+                                   delaykey[i].str,
+                                   delaykey[i].len) == 0) {
+#  if DEBUG_BOOTKEYS
+                               printf("got %skey\n",
+                                      delaykey[i].retry ? "delay" : "stop");
+#  endif
+
+#  ifdef CONFIG_BOOT_RETRY_TIME
+                               /* don't retry auto boot */
+                               if (! delaykey[i].retry)
+                                       retry_time = -1;
+#  endif
+                               abort = 1;
+                       }
+               }
+
+               if (tstc()) {
+                       if (presskey_len < presskey_max) {
+                               presskey [presskey_len ++] = getc();
+                       }
+                       else {
+                               for (i = 0; i < presskey_max - 1; i ++)
+                                       presskey [i] = presskey [i + 1];
+
+                               presskey [i] = getc();
+                       }
+               }
+       }
+#  if DEBUG_BOOTKEYS
+       if (!abort)
+               printf("key timeout\n");
+#  endif
+
+       return abort;
+}
+
+# else /* !defined(CONFIG_AUTOBOOT_KEYED) */
+
+static __inline__ int abortboot(int bootdelay)
+{
+       int abort = 0;
+
+       printf("Hit any key to stop autoboot: %2d ", bootdelay);
+
+#if defined CONFIG_ZERO_BOOTDELAY_CHECK
+        /*
+         * Check if key already pressed
+         * Don't check if bootdelay < 0
+         */
+       if (bootdelay >= 0) {
+               if (tstc()) {   /* we got a key press   */
+                       (void) getc();  /* consume input        */
+                       printf ("\b\b\b 0\n");
+                       return 1;       /* don't auto boot      */
+               }
+        }
+#endif
+
+       while (bootdelay > 0) {
+               int i;
+
+               --bootdelay;
+               /* delay 100 * 10ms */
+               for (i=0; !abort && i<100; ++i) {
+                       if (tstc()) {   /* we got a key press   */
+                               abort  = 1;     /* don't auto boot      */
+                               bootdelay = 0;  /* no more delay        */
+                               (void) getc();  /* consume input        */
+                               break;
+                       }
+                       udelay (10000);
+               }
+
+               printf ("\b\b\b%2d ", bootdelay);
+       }
+
+       putc ('\n');
+
+       return abort;
+}
+# endif        /* CONFIG_AUTOBOOT_KEYED */
+#endif /* CONFIG_BOOTDELAY >= 0  */
+
+/****************************************************************************/
+
+void main_loop (void)
+{
+#ifndef CFG_HUSH_PARSER
+       static char lastcommand[CFG_CBSIZE] = { 0, };
+       int len;
+       int rc = 1;
+       int flag;
+#endif
+
+#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
+       char *s;
+       int bootdelay;
+#endif
+#ifdef CONFIG_PREBOOT
+       char *p;
+#endif
+
+#if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO)
+       ulong bmp = 0;          /* default bitmap */
+       extern int trab_vfd (ulong bitmap);
+
+#ifdef CONFIG_MODEM_SUPPORT
+       if (do_mdm_init)
+               bmp = 1;        /* alternate bitmap */
+#endif
+       trab_vfd (bmp);
+#endif /* CONFIG_VFD && VFD_TEST_LOGO */
+
+#ifdef CONFIG_MODEM_SUPPORT
+       debug ("DEBUG: main_loop:   do_mdm_init=%d\n", do_mdm_init);
+       if (do_mdm_init) {
+               uchar *str = strdup(getenv("mdm_cmd"));
+               setenv ("preboot", str);  /* set or delete definition */
+               if (str != NULL)
+                       free (str);
+               mdm_init(); /* wait for modem connection */
+       }
+#endif  /* CONFIG_MODEM_SUPPORT */
+
+#ifdef CFG_HUSH_PARSER
+       u_boot_hush_start ();
+#endif
+
+#ifdef CONFIG_PREBOOT
+       if ((p = getenv ("preboot")) != NULL) {
+# ifdef CONFIG_AUTOBOOT_KEYED
+               int prev = disable_ctrlc(1);    /* disable Control C checking */
+# endif
+
+# ifndef CFG_HUSH_PARSER
+               run_command (p, 0);
+# else
+               parse_string_outer(p, FLAG_PARSE_SEMICOLON |
+                                   FLAG_EXIT_FROM_LOOP);
+# endif
+
+# ifdef CONFIG_AUTOBOOT_KEYED
+               disable_ctrlc(prev);    /* restore Control C checking */
+# endif
+       }
+#endif /* CONFIG_PREBOOT */
+
+#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
+       s = getenv ("bootdelay");
+       bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
+
+#if 0
+       printf ("### main_loop entered:\n\n");
+#endif
+
+# ifdef CONFIG_BOOT_RETRY_TIME
+       s = getenv ("bootretry");
+       if (s != NULL)
+               retry_time = (int)simple_strtoul(s, NULL, 10);
+       else
+               retry_time =  CONFIG_BOOT_RETRY_TIME;
+       if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN)
+               retry_time = CONFIG_BOOT_RETRY_MIN;
+# endif        /* CONFIG_BOOT_RETRY_TIME */
+
+       s = getenv ("bootcmd");
+       if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
+# ifdef CONFIG_AUTOBOOT_KEYED
+               int prev = disable_ctrlc(1);    /* disable Control C checking */
+# endif
+
+# ifndef CFG_HUSH_PARSER
+               run_command (s, 0);
+# else
+               parse_string_outer(s, FLAG_PARSE_SEMICOLON |
+                                   FLAG_EXIT_FROM_LOOP);
+# endif
+
+# ifdef CONFIG_AUTOBOOT_KEYED
+               disable_ctrlc(prev);    /* restore Control C checking */
+# endif
+       }
+#endif /* CONFIG_BOOTDELAY */
+
+       /*
+        * Main Loop for Monitor Command Processing
+        */
+#ifdef CFG_HUSH_PARSER
+       parse_file_outer();
+       /* This point is never reached */
+       for (;;);
+#else
+       for (;;) {
+#ifdef CONFIG_BOOT_RETRY_TIME
+               if (rc >= 0) {
+                       /* Saw enough of a valid command to
+                        * restart the timeout.
+                        */
+                       reset_cmd_timeout();
+               }
+#endif
+               len = readline (CFG_PROMPT);
+
+               flag = 0;       /* assume no special flags for now */
+               if (len > 0)
+                       strcpy (lastcommand, console_buffer);
+               else if (len == 0)
+                       flag |= CMD_FLAG_REPEAT;
+#ifdef CONFIG_BOOT_RETRY_TIME
+               else if (len == -2) {
+                       /* -2 means timed out, retry autoboot
+                        */
+                       printf("\nTimed out waiting for command\n");
+# ifdef CONFIG_RESET_TO_RETRY
+                       /* Reinit board to run initialization code again */
+                       do_reset (NULL, 0, 0, NULL);
+# else
+                       return;         /* retry autoboot */
+# endif
+               }
+#endif
+
+               if (len == -1)
+                       printf ("<INTERRUPT>\n");
+               else
+                       rc = run_command (lastcommand, flag);
+
+               if (rc <= 0) {
+                       /* invalid command or not repeatable, forget it */
+                       lastcommand[0] = 0;
+               }
+       }
+#endif /*CFG_HUSH_PARSER*/
+}
+
+/***************************************************************************
+ * reset command line timeout to retry_time seconds
+ */
+#ifdef CONFIG_BOOT_RETRY_TIME
+void reset_cmd_timeout(void)
+{
+       endtime = endtick(retry_time);
+}
+#endif
+
+/****************************************************************************/
+
+/*
+ * Prompt for input and read a line.
+ * If  CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
+ * time out when time goes past endtime (timebase time in ticks).
+ * Return:     number of read characters
+ *             -1 if break
+ *             -2 if timed out
+ */
+int readline (const char *const prompt)
+{
+       char   *p = console_buffer;
+       int     n = 0;                          /* buffer index         */
+       int     plen = 0;                       /* prompt length        */
+       int     col;                            /* output column cnt    */
+       char    c;
+
+       /* print prompt */
+       if (prompt) {
+               plen = strlen (prompt);
+               puts (prompt);
+       }
+       col = plen;
+
+       for (;;) {
+#ifdef CONFIG_BOOT_RETRY_TIME
+               while (!tstc()) {       /* while no incoming data */
+                       if (retry_time >= 0 && get_ticks() > endtime)
+                               return (-2);    /* timed out */
+               }
+#endif
+               WATCHDOG_RESET();               /* Trigger watchdog, if needed */
+
+#ifdef CONFIG_SHOW_ACTIVITY
+               while (!tstc()) {
+                       extern void show_activity(int arg);
+                       show_activity(0);
+               }
+#endif
+               c = getc();
+
+               /*
+                * Special character handling
+                */
+               switch (c) {
+               case '\r':                              /* Enter                */
+               case '\n':
+                       *p = '\0';
+                       puts ("\r\n");
+                       return (p - console_buffer);
+
+               case 0x03:                              /* ^C - break           */
+                       console_buffer[0] = '\0';       /* discard input */
+                       return (-1);
+
+               case 0x15:                              /* ^U - erase line      */
+                       while (col > plen) {
+                               puts (erase_seq);
+                               --col;
+                       }
+                       p = console_buffer;
+                       n = 0;
+                       continue;
+
+               case 0x17:                              /* ^W - erase word      */
+                       p=delete_char(console_buffer, p, &col, &n, plen);
+                       while ((n > 0) && (*p != ' ')) {
+                               p=delete_char(console_buffer, p, &col, &n, plen);
+                       }
+                       continue;
+
+               case 0x08:                              /* ^H  - backspace      */
+               case 0x7F:                              /* DEL - backspace      */
+                       p=delete_char(console_buffer, p, &col, &n, plen);
+                       continue;
+
+               default:
+                       /*
+                        * Must be a normal character then
+                        */
+                       if (n < CFG_CBSIZE-2) {
+                               if (c == '\t') {        /* expand TABs          */
+                                       puts (tab_seq+(col&07));
+                                       col += 8 - (col&07);
+                               } else {
+                                       ++col;          /* echo input           */
+                                       putc (c);
+                               }
+                               *p++ = c;
+                               ++n;
+                       } else {                        /* Buffer full          */
+                               putc ('\a');
+                       }
+               }
+       }
+}
+
+/****************************************************************************/
+
+static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen)
+{
+       char *s;
+
+       if (*np == 0) {
+               return (p);
+       }
+
+       if (*(--p) == '\t') {                   /* will retype the whole line   */
+               while (*colp > plen) {
+                       puts (erase_seq);
+                       (*colp)--;
+               }
+               for (s=buffer; s<p; ++s) {
+                       if (*s == '\t') {
+                               puts (tab_seq+((*colp) & 07));
+                               *colp += 8 - ((*colp) & 07);
+                       } else {
+                               ++(*colp);
+                               putc (*s);
+                       }
+               }
+       } else {
+               puts (erase_seq);
+               (*colp)--;
+       }
+       (*np)--;
+       return (p);
+}
+
+/****************************************************************************/
+
+int parse_line (char *line, char *argv[])
+{
+       int nargs = 0;
+
+#ifdef DEBUG_PARSER
+       printf ("parse_line: \"%s\"\n", line);
+#endif
+       while (nargs < CFG_MAXARGS) {
+
+               /* skip any white space */
+               while ((*line == ' ') || (*line == '\t')) {
+                       ++line;
+               }
+
+               if (*line == '\0') {    /* end of line, no more args    */
+                       argv[nargs] = NULL;
+#ifdef DEBUG_PARSER
+               printf ("parse_line: nargs=%d\n", nargs);
+#endif
+                       return (nargs);
+               }
+
+               argv[nargs++] = line;   /* begin of argument string     */
+
+               /* find end of string */
+               while (*line && (*line != ' ') && (*line != '\t')) {
+                       ++line;
+               }
+
+               if (*line == '\0') {    /* end of line, no more args    */
+                       argv[nargs] = NULL;
+#ifdef DEBUG_PARSER
+               printf ("parse_line: nargs=%d\n", nargs);
+#endif
+                       return (nargs);
+               }
+
+               *line++ = '\0';         /* terminate current arg         */
+       }
+
+       printf ("** Too many args (max. %d) **\n", CFG_MAXARGS);
+
+#ifdef DEBUG_PARSER
+       printf ("parse_line: nargs=%d\n", nargs);
+#endif
+       return (nargs);
+}
+
+/****************************************************************************/
+
+static void process_macros (const char *input, char *output)
+{
+       char c, prev;
+       const char *varname_start = NULL;
+       int inputcnt  = strlen (input);
+       int outputcnt = CFG_CBSIZE;
+       int state = 0;  /* 0 = waiting for '$'  */
+                       /* 1 = waiting for '('  */
+                       /* 2 = waiting for ')'  */
+
+#ifdef DEBUG_PARSER
+       char *output_start = output;
+
+       printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input), input);
+#endif
+
+       prev = '\0';                    /* previous character   */
+
+       while (inputcnt && outputcnt) {
+           c = *input++;
+           inputcnt--;
+
+           /* remove one level of escape characters */
+           if ((c == '\\') && (prev != '\\')) {
+               if (inputcnt-- == 0)
+                       break;
+               prev = c;
+               c = *input++;
+           }
+
+           switch (state) {
+           case 0:                     /* Waiting for (unescaped) $    */
+               if ((c == '$') && (prev != '\\')) {
+                       state++;
+               } else {
+                       *(output++) = c;
+                       outputcnt--;
+               }
+               break;
+           case 1:                     /* Waiting for (        */
+               if (c == '(') {
+                       state++;
+                       varname_start = input;
+               } else {
+                       state = 0;
+                       *(output++) = '$';
+                       outputcnt--;
+
+                       if (outputcnt) {
+                               *(output++) = c;
+                               outputcnt--;
+                       }
+               }
+               break;
+           case 2:                     /* Waiting for )        */
+               if (c == ')') {
+                       int i;
+                       char envname[CFG_CBSIZE], *envval;
+                       int envcnt = input-varname_start-1; /* Varname # of chars */
+
+                       /* Get the varname */
+                       for (i = 0; i < envcnt; i++) {
+                               envname[i] = varname_start[i];
+                       }
+                       envname[i] = 0;
+
+                       /* Get its value */
+                       envval = getenv (envname);
+
+                       /* Copy into the line if it exists */
+                       if (envval != NULL)
+                               while ((*envval) && outputcnt) {
+                                       *(output++) = *(envval++);
+                                       outputcnt--;
+                               }
+                       /* Look for another '$' */
+                       state = 0;
+               }
+               break;
+           }
+
+           prev = c;
+       }
+
+       if (outputcnt)
+               *output = 0;
+
+#ifdef DEBUG_PARSER
+       printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
+               strlen(output_start), output_start);
+#endif
+}
+
+/****************************************************************************
+ * returns:
+ *     1  - command executed, repeatable
+ *     0  - command executed but not repeatable, interrupted commands are
+ *          always considered not repeatable
+ *     -1 - not executed (unrecognized, bootd recursion or too many args)
+ *           (If cmd is NULL or "" or longer than CFG_CBSIZE-1 it is
+ *           considered unrecognized)
+ *
+ * WARNING:
+ *
+ * We must create a temporary copy of the command since the command we get
+ * may be the result from getenv(), which returns a pointer directly to
+ * the environment data, which may change magicly when the command we run
+ * creates or modifies environment variables (like "bootp" does).
+ */
+
+int run_command (const char *cmd, int flag)
+{
+       cmd_tbl_t *cmdtp;
+       char cmdbuf[CFG_CBSIZE];        /* working copy of cmd          */
+       char *token;                    /* start of token in cmdbuf     */
+       char *sep;                      /* end of token (separator) in cmdbuf */
+       char finaltoken[CFG_CBSIZE];
+       char *str = cmdbuf;
+       char *argv[CFG_MAXARGS + 1];    /* NULL terminated      */
+       int argc;
+       int repeatable = 1;
+
+#ifdef DEBUG_PARSER
+       printf ("[RUN_COMMAND] cmd[%p]=\"", cmd);
+       puts (cmd ? cmd : "NULL");      /* use puts - string may be loooong */
+       puts ("\"\n");
+#endif
+
+       clear_ctrlc();          /* forget any previous Control C */
+
+       if (!cmd || !*cmd) {
+               return -1;      /* empty command */
+       }
+
+       if (strlen(cmd) >= CFG_CBSIZE) {
+               puts ("## Command too long!\n");
+               return -1;
+       }
+
+       strcpy (cmdbuf, cmd);
+
+       /* Process separators and check for invalid
+        * repeatable commands
+        */
+
+#ifdef DEBUG_PARSER
+       printf ("[PROCESS_SEPARATORS] %s\n", cmd);
+#endif
+       while (*str) {
+
+               /*
+                * Find separator, or string end
+                * Allow simple escape of ';' by writing "\;"
+                */
+               for (sep = str; *sep; sep++) {
+                       if ((*sep == ';') &&    /* separator            */
+                           ( sep != str) &&    /* past string start    */
+                           (*(sep-1) != '\\')) /* and NOT escaped      */
+                               break;
+               }
+
+               /*
+                * Limit the token to data between separators
+                */
+               token = str;
+               if (*sep) {
+                       str = sep + 1;  /* start of command for next pass */
+                       *sep = '\0';
+               }
+               else
+                       str = sep;      /* no more commands for next pass */
+#ifdef DEBUG_PARSER
+               printf ("token: \"%s\"\n", token);
+#endif
+
+               /* find macros in this token and replace them */
+               process_macros (token, finaltoken);
+
+               /* Extract arguments */
+               argc = parse_line (finaltoken, argv);
+
+               /* Look up command in command table */
+               if ((cmdtp = find_cmd(argv[0])) == NULL) {
+                       printf ("Unknown command '%s' - try 'help'\n", argv[0]);
+                       return -1;      /* give up after bad command */
+               }
+
+               /* found - check max args */
+               if (argc > cmdtp->maxargs) {
+                       printf ("Usage:\n%s\n", cmdtp->usage);
+                       return -1;
+               }
+
+#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
+               /* avoid "bootd" recursion */
+               if (cmdtp->cmd == do_bootd) {
+#ifdef DEBUG_PARSER
+                       printf ("[%s]\n", finaltoken);
+#endif
+                       if (flag & CMD_FLAG_BOOTD) {
+                               printf ("'bootd' recursion detected\n");
+                               return -1;
+                       }
+                       else
+                               flag |= CMD_FLAG_BOOTD;
+               }
+#endif /* CFG_CMD_BOOTD */
+
+               /* OK - call function to do the command */
+               if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
+                       return (-1);
+               }
+
+               repeatable &= cmdtp->repeatable;
+
+               /* Did the user stop this? */
+               if (had_ctrlc ())
+                       return 0;       /* if stopped then not repeatable */
+       }
+
+       return repeatable;
+}
+
+/****************************************************************************/
+
+#if (CONFIG_COMMANDS & CFG_CMD_RUN)
+int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+       int i;
+       int rcode = 1;
+
+       if (argc < 2) {
+               printf ("Usage:\n%s\n", cmdtp->usage);
+               return 1;
+       }
+
+       for (i=1; i<argc; ++i) {
+#ifndef CFG_HUSH_PARSER
+           if (run_command (getenv (argv[i]), flag) != -1) ++rcode;
+#else
+           if (parse_string_outer(getenv (argv[i]),
+                   FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) == 0) ++rcode;
+#endif
+       }
+       return ((rcode == i) ? 0 : 1);
+}
+#endif
diff --git a/common/miiphyutil.c b/common/miiphyutil.c
new file mode 100644 (file)
index 0000000..6b2425f
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * (C) Copyright 2001
+ * Gerald Van Baren, Custom IDEAS, vanbaren@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
+ */
+
+/*
+ * This provides a bit-banged interface to the ethernet MII management
+ * channel.
+ */
+
+#include <common.h>
+#include <miiphy.h>
+
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+
+/*****************************************************************************
+ *
+ * Read the OUI, manufacture's model number, and revision number.
+ *
+ * OUI:     22 bits (unsigned int)
+ * Model:    6 bits (unsigned char)
+ * Revision: 4 bits (unsigned char)
+ *
+ * Returns:
+ *   0 on success
+ */
+int miiphy_info (unsigned char addr,
+                unsigned int *oui,
+                unsigned char *model, unsigned char *rev)
+{
+       unsigned int reg = 0;
+
+       /*
+        * Trick: we are reading two 16 registers into a 32 bit variable
+        * so we do a 16 read into the high order bits of the variable (big
+        * endian, you know), shift it down 16 bits, and the read the rest.
+        */
+       if (miiphy_read (addr, PHY_PHYIDR2, (unsigned short *) &reg) != 0) {
+#ifdef DEBUG
+               printf ("PHY ID register 2 read failed\n");
+#endif
+               return (-1);
+       }
+       reg >>= 16;
+
+#ifdef DEBUG
+       printf ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg);
+#endif
+       if (reg == 0xFFFF) {
+               /* No physical device present at this address */
+               return (-1);
+       }
+
+       if (miiphy_read (addr, PHY_PHYIDR1, (unsigned short *) &reg) != 0) {
+#ifdef DEBUG
+               printf ("PHY ID register 1 read failed\n");
+#endif
+               return (-1);
+       }
+#ifdef DEBUG
+       printf ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
+#endif
+       *oui   =                 ( reg >> 10);
+       *model = (unsigned char) ((reg >>  4) & 0x0000003F);
+       *rev   = (unsigned char) ( reg        & 0x0000000F);
+       return (0);
+}
+
+
+/*****************************************************************************
+ *
+ * Reset the PHY.
+ * Returns:
+ *   0 on success
+ */
+int miiphy_reset (unsigned char addr)
+{
+       unsigned short reg;
+       int loop_cnt;
+
+       if (miiphy_write (addr, PHY_BMCR, 0x8000) != 0) {
+#ifdef DEBUG
+               printf ("PHY reset failed\n");
+#endif
+               return (-1);
+       }
+
+       /*
+        * Poll the control register for the reset bit to go to 0 (it is
+        * auto-clearing).  This should happen within 0.5 seconds per the
+        * IEEE spec.
+        */
+       loop_cnt = 0;
+       reg = 0x8000;
+       while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) {
+               if (miiphy_read (addr, PHY_BMCR, &reg) != 0) {
+#     ifdef DEBUG
+                       printf ("PHY status read failed\n");
+#     endif
+                       return (-1);
+               }
+       }
+       if ((reg & 0x8000) == 0) {
+               return (0);
+       } else {
+               printf ("PHY reset timed out\n");
+               return (-1);
+       }
+       return (0);
+}
+
+
+/*****************************************************************************
+ *
+ * Determine the ethernet speed (10/100).
+ */
+int miiphy_speed (unsigned char addr)
+{
+       unsigned short reg;
+
+       if (miiphy_read (addr, PHY_ANLPAR, &reg)) {
+               printf ("PHY speed1 read failed, assuming 10bT\n");
+               return (_10BASET);
+       }
+
+       if ((reg & PHY_ANLPAR_100) != 0) {
+               return (_100BASET);
+       } else {
+               return (_10BASET);
+       }
+}
+
+
+/*****************************************************************************
+ *
+ * Determine full/half duplex.
+ */
+int miiphy_duplex (unsigned char addr)
+{
+       unsigned short reg;
+
+       if (miiphy_read (addr, PHY_ANLPAR, &reg)) {
+               printf ("PHY duplex read failed, assuming half duplex\n");
+               return (HALF);
+       }
+
+       if ((reg & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0) {
+               return (FULL);
+       } else {
+               return (HALF);
+       }
+}
+
+#endif /* CONFIG_MII || (CONFIG_COMMANDS & CFG_CMD_MII) */
diff --git a/common/soft_i2c.c b/common/soft_i2c.c
new file mode 100644 (file)
index 0000000..7777480
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ * (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
+ *
+ * This has been changed substantially by Gerald Van Baren, Custom IDEAS,
+ * vanbaren@cideas.com.  It was heavily influenced by LiMon, written by
+ * Neil Russell.
+ */
+
+#include <common.h>
+#ifdef CONFIG_MPC8260                  /* only valid for MPC8260 */
+#include <ioports.h>
+#endif
+#include <i2c.h>
+
+#if defined(CONFIG_SOFT_I2C)
+
+/* #define     DEBUG_I2C       */
+
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+#define RETRIES                0
+
+
+#define I2C_ACK                0               /* PD_SDA level to ack a byte */
+#define I2C_NOACK      1               /* PD_SDA level to noack a byte */
+
+
+#ifdef DEBUG_I2C
+#define PRINTD(fmt,args...)    do {    \
+       DECLARE_GLOBAL_DATA_PTR;        \
+       if (gd->have_console)           \
+               printf (fmt ,##args);   \
+       } while (0)
+#else
+#define PRINTD(fmt,args...)
+#endif
+
+/*-----------------------------------------------------------------------
+ * Local functions
+ */
+static void  send_reset        (void);
+static void  send_start        (void);
+static void  send_stop (void);
+static void  send_ack  (int);
+static int   write_byte        (uchar byte);
+static uchar read_byte (int);
+
+
+/*-----------------------------------------------------------------------
+ * Send a reset sequence consisting of 9 clocks with the data signal high
+ * to clock any confused device back into an idle state.  Also send a
+ * <stop> at the end of the sequence for belts & suspenders.
+ */
+static void send_reset(void)
+{
+#ifdef CONFIG_MPC8260
+       volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT);
+#endif
+#ifdef CONFIG_8xx
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#endif
+       int j;
+
+       I2C_ACTIVE;
+       I2C_SDA(1);
+       for(j = 0; j < 9; j++) {
+               I2C_SCL(0);
+               I2C_DELAY;
+               I2C_DELAY;
+               I2C_SCL(1);
+               I2C_DELAY;
+               I2C_DELAY;
+       }
+       send_stop();
+       I2C_TRISTATE;
+}
+
+/*-----------------------------------------------------------------------
+ * START: High -> Low on SDA while SCL is High
+ */
+static void send_start(void)
+{
+#ifdef CONFIG_MPC8260
+       volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT);
+#endif
+#ifdef CONFIG_8xx
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#endif
+
+       I2C_DELAY;
+       I2C_SDA(1);
+       I2C_ACTIVE;
+       I2C_DELAY;
+       I2C_SCL(1);
+       I2C_DELAY;
+       I2C_SDA(0);
+       I2C_DELAY;
+}
+
+/*-----------------------------------------------------------------------
+ * STOP: Low -> High on SDA while SCL is High
+ */
+static void send_stop(void)
+{
+#ifdef CONFIG_MPC8260
+       volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT);
+#endif
+#ifdef CONFIG_8xx
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#endif
+
+       I2C_SCL(0);
+       I2C_DELAY;
+       I2C_SDA(0);
+       I2C_ACTIVE;
+       I2C_DELAY;
+       I2C_SCL(1);
+       I2C_DELAY;
+       I2C_SDA(1);
+       I2C_DELAY;
+       I2C_TRISTATE;
+}
+
+
+/*-----------------------------------------------------------------------
+ * ack should be I2C_ACK or I2C_NOACK
+ */
+static void send_ack(int ack)
+{
+#ifdef CONFIG_MPC8260
+       volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT);
+#endif
+#ifdef CONFIG_8xx
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#endif
+
+       I2C_ACTIVE;
+       I2C_SCL(0);
+       I2C_DELAY;
+
+       I2C_SDA(ack);
+
+       I2C_ACTIVE;
+       I2C_DELAY;
+       I2C_SCL(1);
+       I2C_DELAY;
+       I2C_DELAY;
+       I2C_SCL(0);
+       I2C_DELAY;
+}
+
+
+/*-----------------------------------------------------------------------
+ * Send 8 bits and look for an acknowledgement.
+ */
+static int write_byte(uchar data)
+{
+#ifdef CONFIG_MPC8260
+       volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT);
+#endif
+#ifdef CONFIG_8xx
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#endif
+       int j;
+       int nack;
+
+       I2C_ACTIVE;
+       for(j = 0; j < 8; j++) {
+               I2C_SCL(0);
+               I2C_DELAY;
+               I2C_SDA(data & 0x80);
+               I2C_DELAY;
+               I2C_SCL(1);
+               I2C_DELAY;
+               I2C_DELAY;
+
+               data <<= 1;
+       }
+
+       /*
+        * Look for an <ACK>(negative logic) and return it.
+        */
+       I2C_SCL(0);
+       I2C_DELAY;
+       I2C_SDA(1);
+       I2C_TRISTATE;
+       I2C_DELAY;
+       I2C_SCL(1);
+       I2C_DELAY;
+       I2C_DELAY;
+       nack = I2C_READ;
+       I2C_SCL(0);
+       I2C_DELAY;
+       I2C_ACTIVE;
+
+       return(nack);   /* not a nack is an ack */
+}
+
+
+/*-----------------------------------------------------------------------
+ * if ack == I2C_ACK, ACK the byte so can continue reading, else
+ * send I2C_NOACK to end the read.
+ */
+static uchar read_byte(int ack)
+{
+#ifdef CONFIG_MPC8260
+       volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT);
+#endif
+#ifdef CONFIG_8xx
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#endif
+       int  data;
+       int  j;
+
+       /*
+        * Read 8 bits, MSB first.
+        */
+       I2C_TRISTATE;
+       data = 0;
+       for(j = 0; j < 8; j++) {
+               I2C_SCL(0);
+               I2C_DELAY;
+               I2C_SCL(1);
+               I2C_DELAY;
+               data <<= 1;
+               data |= I2C_READ;
+               I2C_DELAY;
+       }
+       send_ack(ack);
+
+       return(data);
+}
+
+/*=====================================================================*/
+/*                         Public Functions                            */
+/*=====================================================================*/
+
+/*-----------------------------------------------------------------------
+ * Initialization
+ */
+void i2c_init (int speed, int slaveaddr)
+{
+#ifdef CONFIG_8xx
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#endif
+
+#ifdef I2C_INIT
+       I2C_INIT;
+#endif
+       /*
+         * WARNING: Do NOT save speed in a static variable: if the
+         * I2C routines are called before RAM is initialized (to read
+         * the DIMM SPD, for instance), RAM won't be usable and your
+         * system will crash.
+        */
+       send_reset ();
+}
+
+/*-----------------------------------------------------------------------
+ * Probe to see if a chip is present.  Also good for checking for the
+ * completion of EEPROM writes since the chip stops responding until
+ * the write completes (typically 10mSec).
+ */
+int i2c_probe(uchar addr)
+{
+       int rc;
+
+       send_start();
+       rc = write_byte ((addr << 1) | 1);
+       send_stop();
+
+       return (rc ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------------
+ * Read bytes
+ */
+int  i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+       int shift;
+       PRINTD("i2c_read: chip %02X addr %02X alen %d buffer %p len %d\n",
+               chip, addr, alen, buffer, len);
+
+#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
+       /*
+        * EEPROM chips that implement "address overflow" are ones
+        * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
+        * address and the extra bits end up in the "chip address"
+        * bit slots. This makes a 24WC08 (1Kbyte) chip look like
+        * four 256 byte chips.
+        *
+        * Note that we consider the length of the address field to
+        * still be one byte because the extra address bits are
+        * hidden in the chip address.
+        */
+       chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
+
+       PRINTD("i2c_read: fix addr_overflow: chip %02X addr %02X\n",
+               chip, addr);
+#endif
+
+       /*
+        * Do the addressing portion of a write cycle to set the
+        * chip's address pointer.  If the address length is zero,
+        * don't do the normal write cycle to set the address pointer,
+        * there is no address pointer in this chip.
+        */
+       send_start();
+       if(alen > 0) {
+               if(write_byte(chip << 1)) {     /* write cycle */
+                       send_stop();
+                       PRINTD("i2c_read, no chip responded %02X\n", chip);
+                       return(1);
+               }
+               shift = (alen-1) * 8;
+               while(alen-- > 0) {
+                       if(write_byte(addr >> shift)) {
+                               PRINTD("i2c_read, address not <ACK>ed\n");
+                               return(1);
+                       }
+                       shift -= 8;
+               }
+               send_stop();    /* reportedly some chips need a full stop */
+               send_start();
+       }
+       /*
+        * Send the chip address again, this time for a read cycle.
+        * Then read the data.  On the last byte, we do a NACK instead
+        * of an ACK(len == 0) to terminate the read.
+        */
+       write_byte((chip << 1) | 1);    /* read cycle */
+       while(len-- > 0) {
+               *buffer++ = read_byte(len == 0);
+       }
+       send_stop();
+       return(0);
+}
+
+/*-----------------------------------------------------------------------
+ * Write bytes
+ */
+int  i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+       int shift, failures = 0;
+
+       PRINTD("i2c_write: chip %02X addr %02X alen %d buffer %p len %d\n",
+               chip, addr, alen, buffer, len);
+
+       send_start();
+       if(write_byte(chip << 1)) {     /* write cycle */
+               send_stop();
+               PRINTD("i2c_write, no chip responded %02X\n", chip);
+               return(1);
+       }
+       shift = (alen-1) * 8;
+       while(alen-- > 0) {
+               if(write_byte(addr >> shift)) {
+                       PRINTD("i2c_write, address not <ACK>ed\n");
+                       return(1);
+               }
+               shift -= 8;
+       }
+
+       while(len-- > 0) {
+               if(write_byte(*buffer++)) {
+                       failures++;
+               }
+       }
+       send_stop();
+       return(failures);
+}
+
+/*-----------------------------------------------------------------------
+ * Read a register
+ */
+uchar i2c_reg_read(uchar i2c_addr, uchar reg)
+{
+       char buf;
+
+       i2c_read(i2c_addr, reg, 1, &buf, 1);
+
+       return(buf);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a register
+ */
+void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val)
+{
+       i2c_write(i2c_addr, reg, 1, &val, 1);
+}
+
+
+#endif /* CONFIG_SOFT_I2C */
diff --git a/cpu/arm720t/Makefile b/cpu/arm720t/Makefile
new file mode 100644 (file)
index 0000000..8c950da
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# (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$(CPU).a
+
+START  = start.o
+OBJS   = serial.o interrupts.o cpu.o
+
+all:   .depend $(START) $(LIB)
+
+$(LIB):        $(OBJS)
+       $(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend:       Makefile $(START:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/cpu/arm720t/interrupts.c b/cpu/arm720t/interrupts.c
new file mode 100644 (file)
index 0000000..52787fe
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@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>
+#include <clps7111.h>
+
+#include <asm/proc-armv/ptrace.h>
+
+extern void reset_cpu(ulong addr);
+
+/* we always count down the max. */
+#define TIMER_LOAD_VAL 0xffff
+
+/* macro to read the 16 bit timer */
+#define READ_TIMER (IO_TC1D & 0xffff)
+
+#ifdef CONFIG_USE_IRQ
+/* enable IRQ/FIQ interrupts */
+void enable_interrupts (void)
+{
+       unsigned long temp;
+       __asm__ __volatile__("mrs %0, cpsr\n"
+                            "bic %0, %0, #0x80\n"
+                            "msr cpsr_c, %0"
+                            : "=r" (temp)
+                            :
+                            : "memory");
+}
+
+
+/*
+ * disable IRQ/FIQ interrupts
+ * returns true if interrupts had been enabled before we disabled them
+ */
+int disable_interrupts (void)
+{
+       unsigned long old,temp;
+       __asm__ __volatile__("mrs %0, cpsr\n"
+                            "orr %1, %0, #0x80\n"
+                            "msr cpsr_c, %1"
+                            : "=r" (old), "=r" (temp)
+                            :
+                            : "memory");
+       return (old & 0x80) == 0;
+}
+#else
+void enable_interrupts (void)
+{
+       return;
+}
+int disable_interrupts (void)
+{
+       return 0;
+}
+#endif
+
+
+
+void bad_mode (void)
+{
+       panic ("Resetting CPU ...\n");
+       reset_cpu (0);
+}
+
+void show_regs (struct pt_regs *regs)
+{
+       unsigned long flags;
+       const char *processor_modes[] =
+                       { "USER_26", "FIQ_26", "IRQ_26", "SVC_26", "UK4_26", "UK5_26",
+"UK6_26", "UK7_26",
+               "UK8_26", "UK9_26", "UK10_26", "UK11_26", "UK12_26", "UK13_26",
+                               "UK14_26", "UK15_26",
+               "USER_32", "FIQ_32", "IRQ_32", "SVC_32", "UK4_32", "UK5_32",
+                               "UK6_32", "ABT_32",
+               "UK8_32", "UK9_32", "UK10_32", "UND_32", "UK12_32", "UK13_32",
+                               "UK14_32", "SYS_32"
+       };
+
+       flags = condition_codes (regs);
+
+       printf ("pc : [<%08lx>]    lr : [<%08lx>]\n"
+                       "sp : %08lx  ip : %08lx  fp : %08lx\n",
+                       instruction_pointer (regs),
+                       regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+       printf ("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
+                       regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
+       printf ("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+                       regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
+       printf ("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+                       regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
+       printf ("Flags: %c%c%c%c",
+                       flags & CC_N_BIT ? 'N' : 'n',
+                       flags & CC_Z_BIT ? 'Z' : 'z',
+                       flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v');
+       printf ("  IRQs %s  FIQs %s  Mode %s%s\n",
+                       interrupts_enabled (regs) ? "on" : "off",
+                       fast_interrupts_enabled (regs) ? "on" : "off",
+                       processor_modes[processor_mode (regs)],
+                       thumb_mode (regs) ? " (T)" : "");
+}
+
+void do_undefined_instruction (struct pt_regs *pt_regs)
+{
+       printf ("undefined instruction\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_software_interrupt (struct pt_regs *pt_regs)
+{
+       printf ("software interrupt\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_prefetch_abort (struct pt_regs *pt_regs)
+{
+       printf ("prefetch abort\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_data_abort (struct pt_regs *pt_regs)
+{
+       printf ("data abort\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_not_used (struct pt_regs *pt_regs)
+{
+       printf ("not used\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_fiq (struct pt_regs *pt_regs)
+{
+       printf ("fast interrupt request\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_irq (struct pt_regs *pt_regs)
+{
+       printf ("interrupt request\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+static ulong timestamp;
+static ulong lastdec;
+
+int interrupt_init (void)
+{
+       /* disable all interrupts */
+       IO_INTMR1 = 0;
+
+       /* operate timer 1 in prescale mode */
+       IO_SYSCON1 |= SYSCON1_TC1M;
+
+       /* select 2kHz clock source for timer 1 */
+       IO_SYSCON1 &= ~SYSCON1_TC1S;
+
+       /* set timer 1 counter */
+       lastdec = IO_TC1D = TIMER_LOAD_VAL;
+       timestamp = 0;
+
+       return (0);
+}
+
+/*
+ * timer without interrupts
+ */
+
+void reset_timer (void)
+{
+       reset_timer_masked ();
+}
+
+ulong get_timer (ulong base)
+{
+       return get_timer_masked () - base;
+}
+
+void set_timer (ulong t)
+{
+       timestamp = t;
+}
+
+void udelay (unsigned long usec)
+{
+       ulong tmo;
+
+       tmo = usec / 1000;
+       tmo *= CFG_HZ;
+       tmo /= 1000;
+
+       tmo += get_timer (0);
+
+       while (get_timer_masked () < tmo)
+               /*NOP*/;
+}
+
+void reset_timer_masked (void)
+{
+       /* reset time */
+       lastdec = READ_TIMER;
+       timestamp = 0;
+}
+
+ulong get_timer_masked (void)
+{
+       ulong now = READ_TIMER;
+
+       if (lastdec >= now) {
+               /* normal mode */
+               timestamp += lastdec - now;
+       } else {
+               /* we have an overflow ... */
+               timestamp += lastdec + TIMER_LOAD_VAL - now;
+       }
+       lastdec = now;
+
+       return timestamp;
+}
+
+void udelay_masked (unsigned long usec)
+{
+       ulong tmo;
+
+       tmo = usec / 1000;
+       tmo *= CFG_HZ;
+       tmo /= 1000;
+
+       reset_timer_masked ();
+
+       while (get_timer_masked () < tmo)
+               /*NOP*/;
+}
diff --git a/cpu/arm920t/Makefile b/cpu/arm920t/Makefile
new file mode 100644 (file)
index 0000000..e5ec81d
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# (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 $(TOPDIR)/config.mk
+
+LIB    = lib$(CPU).a
+
+START  = start.o
+OBJS   = serial.o interrupts.o cpu.o speed.o
+
+all:   .depend $(START) $(LIB)
+
+$(LIB):        $(OBJS)
+       $(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend:       Makefile $(START:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/cpu/arm920t/interrupts.c b/cpu/arm920t/interrupts.c
new file mode 100644 (file)
index 0000000..963ccbd
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (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
+ */
+
+#include <common.h>
+#include <arm920t.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#include <asm/proc-armv/ptrace.h>
+
+extern void reset_cpu(ulong addr);
+int timer_load_val = 0;
+
+/* macro to read the 16 bit timer */
+#define READ_TIMER (rTCNTO4 & 0xffff)
+
+#ifdef CONFIG_USE_IRQ
+/* enable IRQ interrupts */
+void enable_interrupts (void)
+{
+       unsigned long temp;
+       __asm__ __volatile__("mrs %0, cpsr\n"
+                            "bic %0, %0, #0x80\n"
+                            "msr cpsr_c, %0"
+                            : "=r" (temp)
+                            :
+                            : "memory");
+}
+
+
+/*
+ * disable IRQ/FIQ interrupts
+ * returns true if interrupts had been enabled before we disabled them
+ */
+int disable_interrupts (void)
+{
+       unsigned long old,temp;
+       __asm__ __volatile__("mrs %0, cpsr\n"
+                            "orr %1, %0, #0xc0\n"
+                            "msr cpsr_c, %1"
+                            : "=r" (old), "=r" (temp)
+                            :
+                            : "memory");
+       return (old & 0x80) == 0;
+}
+#else
+void enable_interrupts (void)
+{
+       return;
+}
+int disable_interrupts (void)
+{
+       return 0;
+}
+#endif
+
+
+
+void bad_mode (void)
+{
+       panic ("Resetting CPU ...\n");
+       reset_cpu (0);
+}
+
+void show_regs (struct pt_regs *regs)
+{
+       unsigned long flags;
+       const char *processor_modes[] = {
+       "USER_26",      "FIQ_26",       "IRQ_26",       "SVC_26",
+       "UK4_26",       "UK5_26",       "UK6_26",       "UK7_26",
+       "UK8_26",       "UK9_26",       "UK10_26",      "UK11_26",
+       "UK12_26",      "UK13_26",      "UK14_26",      "UK15_26",
+       "USER_32",      "FIQ_32",       "IRQ_32",       "SVC_32",
+       "UK4_32",       "UK5_32",       "UK6_32",       "ABT_32",
+       "UK8_32",       "UK9_32",       "UK10_32",      "UND_32",
+       "UK12_32",      "UK13_32",      "UK14_32",      "SYS_32",
+       };
+
+       flags = condition_codes (regs);
+
+       printf ("pc : [<%08lx>]    lr : [<%08lx>]\n"
+               "sp : %08lx  ip : %08lx  fp : %08lx\n",
+               instruction_pointer (regs),
+               regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+       printf ("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
+               regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
+       printf ("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+               regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
+       printf ("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+               regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
+       printf ("Flags: %c%c%c%c",
+               flags & CC_N_BIT ? 'N' : 'n',
+               flags & CC_Z_BIT ? 'Z' : 'z',
+               flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v');
+       printf ("  IRQs %s  FIQs %s  Mode %s%s\n",
+               interrupts_enabled (regs) ? "on" : "off",
+               fast_interrupts_enabled (regs) ? "on" : "off",
+               processor_modes[processor_mode (regs)],
+               thumb_mode (regs) ? " (T)" : "");
+}
+
+void do_undefined_instruction (struct pt_regs *pt_regs)
+{
+       printf ("undefined instruction\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_software_interrupt (struct pt_regs *pt_regs)
+{
+       printf ("software interrupt\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_prefetch_abort (struct pt_regs *pt_regs)
+{
+       printf ("prefetch abort\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_data_abort (struct pt_regs *pt_regs)
+{
+       printf ("data abort\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_not_used (struct pt_regs *pt_regs)
+{
+       printf ("not used\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_fiq (struct pt_regs *pt_regs)
+{
+       printf ("fast interrupt request\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+void do_irq (struct pt_regs *pt_regs)
+{
+       printf ("interrupt request\n");
+       show_regs (pt_regs);
+       bad_mode ();
+}
+
+static ulong timestamp;
+static ulong lastdec;
+
+int interrupt_init (void)
+{
+       /* use PWM Timer 4 because it has no output */
+       /* prescaler for Timer 4 is 16 */
+       rTCFG0 = 0x0f00;
+       if (timer_load_val == 0)
+       {
+               /*
+                * for 10 ms clock period @ PCLK with 4 bit divider = 1/2
+                * (default) and prescaler = 16. Should be 10390
+                * @33.25MHz and 15625 @ 50 MHz
+                */
+               timer_load_val = get_PCLK()/(2 * 16 * 100);
+       }
+       /* load value for 10 ms timeout */
+       lastdec = rTCNTB4 = timer_load_val;
+       /* auto load, manual update of Timer 4 */
+       rTCON = 0x600000;
+       /* auto load, start Timer 4 */
+       rTCON = 0x500000;
+       timestamp = 0;
+
+       return (0);
+}
+
+/*
+ * timer without interrupts
+ */
+
+void reset_timer (void)
+{
+       reset_timer_masked ();
+}
+
+ulong get_timer (ulong base)
+{
+       return get_timer_masked () - base;
+}
+
+void set_timer (ulong t)
+{
+       timestamp = t;
+}
+
+void udelay (unsigned long usec)
+{
+       ulong tmo;
+
+       tmo = usec / 1000;
+       tmo *= (timer_load_val * 100);
+       tmo /= 1000;
+
+       tmo += get_timer (0);
+
+       while (get_timer_masked () < tmo)
+               /*NOP*/;
+}
+
+void reset_timer_masked (void)
+{
+       /* reset time */
+       lastdec = READ_TIMER;
+       timestamp = 0;
+}
+
+ulong get_timer_masked (void)
+{
+       ulong now = READ_TIMER;
+
+       if (lastdec >= now) {
+               /* normal mode */
+               timestamp += lastdec - now;
+       } else {
+               /* we have an overflow ... */
+               timestamp += lastdec + timer_load_val - now;
+       }
+       lastdec = now;
+
+       return timestamp;
+}
+
+void udelay_masked (unsigned long usec)
+{
+       ulong tmo;
+
+       tmo = usec / 1000;
+       tmo *= (timer_load_val * 100);
+       tmo /= 1000;
+
+       reset_timer_masked ();
+
+       while (get_timer_masked () < tmo)
+               /*NOP*/;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+       return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk (void)
+{
+       ulong tbclk;
+
+#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)
+       tbclk = timer_load_val * 100;
+#elif defined(CONFIG_SMDK2410)
+       tbclk = CFG_HZ;
+#endif
+
+       return tbclk;
+}
diff --git a/cpu/arm920t/serial.c b/cpu/arm920t/serial.c
new file mode 100644 (file)
index 0000000..c32e73b
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <common.h>
+#if defined(CONFIG_S3C2400) || defined(CONFIG_TRAB)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+
+void serial_setbrg (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       int i;
+       unsigned int reg = 0;
+
+       /* value is calculated so : (int)(PCLK/16./baudrate) -1 */
+       reg = get_PCLK() / (16 * gd->baudrate) - 1;
+
+#ifdef CONFIG_SERIAL1
+       /* FIFO enable, Tx/Rx FIFO clear */
+       rUFCON0 = 0x07;
+       rUMCON0 = 0x0;
+       /* Normal,No parity,1 stop,8 bit */
+       rULCON0 = 0x3;
+       /*
+        * tx=level,rx=edge,disable timeout int.,enable rx error int.,
+        * normal,interrupt or polling
+        */
+       rUCON0 = 0x245;
+       rUBRDIV0 = reg;
+
+#ifdef CONFIG_HWFLOW
+       rUMCON0 = 0x1; /* RTS up */
+#endif
+       for (i = 0; i < 100; i++);
+#elif CONFIG_SERIAL2
+# if defined(CONFIG_TRAB)
+#  #error "TRAB supports only CONFIG_SERIAL1"
+# endif
+       /* FIFO enable, Tx/Rx FIFO clear */
+       rUFCON1 = 0x06;
+       rUMCON1 = 0x0;
+       /* Normal,No parity,1 stop,8 bit */
+       rULCON1 = 0x3;
+       /*
+        * tx=level,rx=edge,disable timeout int.,enable rx error int.,
+        * normal,interrupt or polling
+        */
+       rUCON1 = 0x245;
+       rUBRDIV1 = reg;
+
+#ifdef CONFIG_HWFLOW
+       rUMCON1 = 0x1; /* RTS up */
+#endif
+       for (i = 0; i < 100; i++);
+#else
+#error "Bad: you didn't configure serial ..."
+#endif
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+       serial_setbrg ();
+
+       return (0);
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+#ifdef CONFIG_SERIAL1
+       while (!(rUTRSTAT0 & 0x1));
+
+       return rURXH0 & 0xff;
+#elif CONFIG_SERIAL2
+       while (!(rUTRSTAT1 & 0x1));
+
+       return rURXH1 & 0xff;
+#endif
+}
+
+#ifdef CONFIG_HWFLOW
+static int hwflow = 0; /* turned off by default */
+int hwflow_onoff(int on)
+{
+       switch(on) {
+       case 0:
+       default:
+               break; /* return current */
+       case 1:
+               hwflow = 1; /* turn on */
+               break;
+       case -1:
+               hwflow = 0; /* turn off */
+               break;
+       }
+       return hwflow;
+}
+#endif
+
+#ifdef CONFIG_MODEM_SUPPORT
+static int be_quiet = 0;
+void disable_putc(void)
+{
+       be_quiet = 1;
+}
+
+void enable_putc(void)
+{
+       be_quiet = 0;
+}
+#endif
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+#ifdef CONFIG_MODEM_SUPPORT
+       if (be_quiet)
+               return;
+#endif
+
+#ifdef CONFIG_SERIAL1
+       /* wait for room in the tx FIFO on SERIAL1 */
+       while (!(rUTRSTAT0 & 0x2));
+
+#ifdef CONFIG_HWFLOW
+       /* Wait for CTS up */
+       while(hwflow && !(rUMSTAT0 & 0x1))
+               ;
+#endif
+
+       rUTXH0 = c;
+#elif CONFIG_SERIAL2
+       /* wait for room in the tx FIFO on SERIAL2 */
+       while (!(rUTRSTAT1 & 0x2));
+
+#ifdef CONFIG_HWFLOW
+       /* Wait for CTS up */
+       while(hwflow && !(rUMSTAT1 & 0x1))
+               ;
+#endif
+       rUTXH1 = c;
+#endif
+
+       /* If \n, also do \r */
+       if (c == '\n')
+               serial_putc ('\r');
+}
+
+/*
+ * Test whether a character is in the RX buffer
+ */
+int serial_tstc (void)
+{
+#ifdef CONFIG_SERIAL1
+       return rUTRSTAT0 & 0x1;
+#elif CONFIG_SERIAL2
+       return rUTRSTAT1 & 0x1;
+#endif
+}
+
+void
+serial_puts (const char *s)
+{
+       while (*s) {
+               serial_putc (*s++);
+       }
+}
diff --git a/cpu/arm920t/speed.c b/cpu/arm920t/speed.c
new file mode 100644 (file)
index 0000000..1ee0c1a
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * (C) Copyright 2001-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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
+ */
+
+/* This code should work for both the S3C2400 and the S3C2410
+ * as they seem to have the same PLL and clock machinery inside.
+ * The different address mapping is handled by the s3c24xx.h files below.
+ */
+
+#include <common.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#define MPLL 0
+#define UPLL 1
+
+/* ------------------------------------------------------------------------- */
+/* NOTE: This describes the proper use of this file.
+ *
+ * CONFIG_PLL_INPUT_FREQ should be defined as the input frequency of the PLL.
+ *
+ * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of
+ * the specified bus in HZ.
+ */
+/* ------------------------------------------------------------------------- */
+
+static ulong get_PLLCLK(int pllreg)
+{
+    ulong r, m, p, s;
+
+    if (pllreg == MPLL)
+       r = rMPLLCON;
+    else if (pllreg == UPLL)
+       r = rUPLLCON;
+    else
+       hang();
+
+    m = ((r & 0xFF000) >> 12) + 8;
+    p = ((r & 0x003F0) >> 4) + 2;
+    s = r & 0x3;
+
+    return((CONFIG_PLL_INPUT_FREQ * m) / (p << s));
+}
+
+/* return FCLK frequency */
+ulong get_FCLK(void)
+{
+    return(get_PLLCLK(MPLL));
+}
+
+/* return HCLK frequency */
+ulong get_HCLK(void)
+{
+    ulong clkdiv = rCLKDIVN;
+
+    return((clkdiv & 0x2) ? get_FCLK()/2 : get_FCLK());
+}
+
+/* return PCLK frequency */
+ulong get_PCLK(void)
+{
+    ulong clkdiv = rCLKDIVN;
+
+    return((clkdiv & 0x1) ? get_HCLK()/2 : get_HCLK());
+}
+
+/* return UCLK frequency */
+ulong get_UCLK(void)
+{
+    return(get_PLLCLK(UPLL));
+}
diff --git a/cpu/mpc824x/cpu_init.c b/cpu/mpc824x/cpu_init.c
new file mode 100644 (file)
index 0000000..602f65d
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * (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 <asm/processor.h>
+#include <mpc824x.h>
+
+#ifndef CFG_BANK0_ROW
+#define CFG_BANK0_ROW 0
+#endif
+#ifndef CFG_BANK1_ROW
+#define CFG_BANK1_ROW 0
+#endif
+#ifndef CFG_BANK2_ROW
+#define CFG_BANK2_ROW 0
+#endif
+#ifndef CFG_BANK3_ROW
+#define CFG_BANK3_ROW 0
+#endif
+#ifndef CFG_BANK4_ROW
+#define CFG_BANK4_ROW 0
+#endif
+#ifndef CFG_BANK5_ROW
+#define CFG_BANK5_ROW 0
+#endif
+#ifndef CFG_BANK6_ROW
+#define CFG_BANK6_ROW 0
+#endif
+#ifndef CFG_BANK7_ROW
+#define CFG_BANK7_ROW 0
+#endif
+#ifndef CFG_DBUS_SIZE2
+#define CFG_DBUS_SIZE2 0
+#endif
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ */
+void
+cpu_init_f (void)
+{
+/* MOUSSE board is initialized in asm */
+#if !defined(CONFIG_MOUSSE) && !defined(CONFIG_BMW)
+    register unsigned long val;
+    CONFIG_WRITE_HALFWORD(PCICR, 0x06); /* Bus Master, respond to PCI memory space acesses*/
+/*    CONFIG_WRITE_HALFWORD(PCISR, 0xffff); */ /*reset PCISR*/
+
+#if defined(CONFIG_MUSENKI) || defined(CONFIG_PN62)
+/* Why is this here, you ask?  Try, just try setting 0x8000
+ * in PCIACR with CONFIG_WRITE_HALFWORD()
+ * this one was a stumper, and we are annoyed
+ */
+
+#define M_CONFIG_WRITE_HALFWORD( addr, data ) \
+    __asm__ __volatile__(     \
+      "                       \
+      stw  %2,0(%0)\n         \
+      sync\n                  \
+      sth  %3,2(%1)\n         \
+      sync\n                  \
+      "                       \
+      : /* no output */       \
+      : "r" (CONFIG_ADDR), "r" (CONFIG_DATA),                 \
+        "r" (PCISWAP(addr & ~3)), "r" (PCISWAP(data << 16))   \
+      );
+
+    M_CONFIG_WRITE_HALFWORD(PCIACR, 0x8000);
+#endif
+
+    CONFIG_WRITE_BYTE(PCLSR, 0x8);     /* set PCI cache line size */
+
+    /*
+     * Note that although this bit is cleared after a hard reset, it
+     * must be explicitly set and then cleared by software during
+     * initialization in order to guarantee correct operation of the
+     * DLL and the SDRAM_CLK[0:3] signals (if they are used).
+     */
+    CONFIG_READ_BYTE (AMBOR, val);
+    CONFIG_WRITE_BYTE(AMBOR, val & 0xDF);
+    CONFIG_WRITE_BYTE(AMBOR, val | 0x20);
+    CONFIG_WRITE_BYTE(AMBOR, val & 0xDF);
+
+    CONFIG_READ_WORD(PICR1, val);
+#if defined(CONFIG_MPC8240)
+    CONFIG_WRITE_WORD( PICR1,
+       (val & (PICR1_ADDRESS_MAP | PICR1_RCS0)) |
+              PIRC1_MSK | PICR1_PROC_TYPE_603E |
+              PICR1_FLASH_WR_EN | PICR1_MCP_EN |
+              PICR1_CF_DPARK | PICR1_EN_PCS |
+              PICR1_CF_APARK );
+#elif defined(CONFIG_MPC8245)
+    CONFIG_WRITE_WORD( PICR1,
+       (val & (PICR1_RCS0)) |
+              PICR1_PROC_TYPE_603E |
+              PICR1_FLASH_WR_EN | PICR1_MCP_EN |
+              PICR1_CF_DPARK | PICR1_NO_BUSW_CK |
+              PICR1_DEC| PICR1_CF_APARK | 0x10);       /* 8245 UM says bit 4 must be set */
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+
+    CONFIG_READ_WORD(PICR2, val);
+    val= val & ~ (PICR2_CF_SNOOP_WS_MASK | PICR2_CF_APHASE_WS_MASK); /*mask off waitstate bits*/
+#ifndef CONFIG_PN62
+    val |= PICR2_CF_SNOOP_WS_1WS | PICR2_CF_APHASE_WS_1WS; /*1 wait state*/
+#endif
+    CONFIG_WRITE_WORD(PICR2, val);
+
+    CONFIG_WRITE_WORD(EUMBBAR, CFG_EUMB_ADDR);
+#ifndef CFG_RAMBOOT
+    CONFIG_WRITE_WORD(MCCR1, (CFG_ROMNAL << MCCR1_ROMNAL_SHIFT) |
+                                (CFG_BANK0_ROW) |
+                                (CFG_BANK1_ROW << MCCR1_BANK1ROW_SHIFT) |
+                                (CFG_BANK2_ROW << MCCR1_BANK2ROW_SHIFT) |
+                                (CFG_BANK3_ROW << MCCR1_BANK3ROW_SHIFT) |
+                                (CFG_BANK4_ROW << MCCR1_BANK4ROW_SHIFT) |
+                                (CFG_BANK5_ROW << MCCR1_BANK5ROW_SHIFT) |
+                                (CFG_BANK6_ROW << MCCR1_BANK6ROW_SHIFT) |
+                                (CFG_BANK7_ROW << MCCR1_BANK7ROW_SHIFT) |
+                            (CFG_ROMFAL << MCCR1_ROMFAL_SHIFT));
+#endif
+
+#if defined(CFG_ASRISE) && defined(CFG_ASFALL)
+    CONFIG_WRITE_WORD(MCCR2, CFG_REFINT << MCCR2_REFINT_SHIFT |
+                            CFG_ASRISE << MCCR2_ASRISE_SHIFT |
+                            CFG_ASFALL << MCCR2_ASFALL_SHIFT);
+#else
+    CONFIG_WRITE_WORD(MCCR2, CFG_REFINT << MCCR2_REFINT_SHIFT);
+#endif
+
+#if defined(CONFIG_MPC8240)
+    CONFIG_WRITE_WORD(MCCR3,
+       (((CFG_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) |
+       (CFG_REFREC << MCCR3_REFREC_SHIFT) |
+       (CFG_RDLAT  << MCCR3_RDLAT_SHIFT));
+#elif defined(CONFIG_MPC8245)
+    CONFIG_WRITE_WORD(MCCR3,
+       (((CFG_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) |
+       (CFG_REFREC << MCCR3_REFREC_SHIFT));
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+
+/* this is gross.  We think these should all be the same, and various boards
+ *  should define CFG_ACTORW to 0 if they don't want to set it, or even, if
+ *  its not set, we define it to zero in this file
+ */
+#if defined(CONFIG_CU824) || defined(CONFIG_PN62)
+       CONFIG_WRITE_WORD(MCCR4,
+       (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+       (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+       MCCR4_BIT21 |
+       (CFG_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+       ((CFG_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+       (((CFG_SDMODE_CAS_LAT <<4) | (CFG_SDMODE_WRAP <<3) |
+                 CFG_SDMODE_BURSTLEN) << MCCR4_SDMODE_SHIFT) |
+       (CFG_ACTORW << MCCR4_ACTTORW_SHIFT) |
+       (((CFG_BSTOPRE & 0x03c0) >> 6) << MCCR4_BSTOPRE6TO9_SHIFT));
+#elif defined(CONFIG_MPC8240)
+       CONFIG_WRITE_WORD(MCCR4,
+       (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+       (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+       MCCR4_BIT21 |
+       (CFG_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+       ((CFG_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+       (((CFG_SDMODE_CAS_LAT <<4) | (CFG_SDMODE_WRAP <<3) |
+                 (CFG_SDMODE_BURSTLEN)) <<MCCR4_SDMODE_SHIFT) |
+       (((CFG_BSTOPRE & 0x03c0) >> 6) <<MCCR4_BSTOPRE6TO9_SHIFT ));
+#elif defined(CONFIG_MPC8245)
+    CONFIG_READ_WORD(MCCR1, val);
+    val &= MCCR1_DBUS_SIZE0;    /* test for 64-bit mem bus */
+
+    CONFIG_WRITE_WORD(MCCR4,
+       (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+       (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+        (CFG_EXTROM ? MCCR4_EXTROM : 0) |
+        (CFG_REGDIMM ? MCCR4_REGDIMM : 0) |
+       (CFG_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+       ((CFG_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+       (CFG_DBUS_SIZE2 << MCCR4_DBUS_SIZE2_SHIFT) |
+       (((CFG_SDMODE_CAS_LAT <<4) | (CFG_SDMODE_WRAP <<3) |
+              (val ? 2 : 3)) << MCCR4_SDMODE_SHIFT)  |
+       (CFG_ACTORW << MCCR4_ACTTORW_SHIFT) |
+       (((CFG_BSTOPRE & 0x03c0) >> 6) <<MCCR4_BSTOPRE6TO9_SHIFT ));
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+
+    CONFIG_WRITE_WORD(MSAR1,
+       ( (CFG_BANK0_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+       (((CFG_BANK1_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+       (((CFG_BANK2_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+       (((CFG_BANK3_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+    CONFIG_WRITE_WORD(EMSAR1,
+       ( (CFG_BANK0_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+       (((CFG_BANK1_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+       (((CFG_BANK2_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+       (((CFG_BANK3_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+    CONFIG_WRITE_WORD(MSAR2,
+       ( (CFG_BANK4_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+       (((CFG_BANK5_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+       (((CFG_BANK6_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+       (((CFG_BANK7_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+    CONFIG_WRITE_WORD(EMSAR2,
+       ( (CFG_BANK4_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+       (((CFG_BANK5_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+       (((CFG_BANK6_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+       (((CFG_BANK7_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+    CONFIG_WRITE_WORD(MEAR1,
+       ( (CFG_BANK0_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+       (((CFG_BANK1_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+       (((CFG_BANK2_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+       (((CFG_BANK3_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+    CONFIG_WRITE_WORD(EMEAR1,
+       ( (CFG_BANK0_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+       (((CFG_BANK1_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+       (((CFG_BANK2_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+       (((CFG_BANK3_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+    CONFIG_WRITE_WORD(MEAR2,
+       ( (CFG_BANK4_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+       (((CFG_BANK5_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+       (((CFG_BANK6_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+       (((CFG_BANK7_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+    CONFIG_WRITE_WORD(EMEAR2,
+       ( (CFG_BANK4_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+       (((CFG_BANK5_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+       (((CFG_BANK6_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+       (((CFG_BANK7_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+
+    CONFIG_WRITE_BYTE(ODCR, CFG_ODCR);
+#ifdef CFG_DLL_MAX_DELAY
+       CONFIG_WRITE_BYTE(MIOCR1, CFG_DLL_MAX_DELAY);   /* needed to make DLL lock */
+#endif
+#if defined(CFG_DLL_EXTEND) && defined(CFG_PCI_HOLD_DEL)
+       CONFIG_WRITE_BYTE(PMCR2, CFG_DLL_EXTEND | CFG_PCI_HOLD_DEL);
+#endif
+#if defined(MIOCR2) && defined(CFG_SDRAM_DSCD)
+       CONFIG_WRITE_BYTE(MIOCR2, CFG_SDRAM_DSCD);      /* change memory input */
+#endif /* setup & hold time */
+
+    CONFIG_WRITE_BYTE(MBER,
+        CFG_BANK0_ENABLE |
+       (CFG_BANK1_ENABLE << 1) |
+       (CFG_BANK2_ENABLE << 2) |
+       (CFG_BANK3_ENABLE << 3) |
+       (CFG_BANK4_ENABLE << 4) |
+       (CFG_BANK5_ENABLE << 5) |
+       (CFG_BANK6_ENABLE << 6) |
+       (CFG_BANK7_ENABLE << 7));
+
+#ifdef CFG_PGMAX
+    CONFIG_WRITE_BYTE(MPMR, CFG_PGMAX);
+#endif
+
+    /* ! Wait 200us before initialize other registers */
+    /*FIXME: write a decent udelay wait */
+    __asm__ __volatile__(
+      " mtctr  %0 \n \
+       0: bdnz  0b\n"
+      :
+      : "r" (0x10000));
+
+   CONFIG_READ_WORD(MCCR1, val);
+   CONFIG_WRITE_WORD(MCCR1, val | MCCR1_MEMGO); /* set memory access going */
+   __asm__ __volatile__("eieio");
+
+#endif /* !CONFIG_MOUSSE && !CONFIG_BMW */
+}
+
+
+#ifdef CONFIG_MOUSSE
+#ifdef INCLUDE_MPC107_REPORT
+struct MPC107_s{
+    unsigned int iobase;
+    char desc[120];
+} MPC107Regs[] ={
+    {BMC_BASE+0x0,  "MPC107 Vendor/Device ID"},
+    {BMC_BASE+0x4,  "MPC107 PCI Command/Status Register"},
+    {BMC_BASE+0x8,  "MPC107 Revision"},
+    {BMC_BASE+0xC,  "MPC107 Cache Line Size"},
+    {BMC_BASE+0x10, "MPC107 LMBAR"},
+    {BMC_BASE+0x14, "MPC824x PCSR"},
+    {BMC_BASE+0xA8, "MPC824x PICR1"},
+    {BMC_BASE+0xAC, "MPC824x PICR2"},
+    {BMC_BASE+0x46, "MPC824x PACR"},
+    {BMC_BASE+0x310, "MPC824x ITWR"},
+    {BMC_BASE+0x300, "MPC824x OMBAR"},
+    {BMC_BASE+0x308, "MPC824x OTWR"},
+    {BMC_BASE+0x14, "MPC107 Peripheral Control and Status Register"},
+    {BMC_BASE+0x78, "MPC107 EUMBAR"},
+    {BMC_BASE+0xC0, "MPC107 Processor Bus Error Status"},
+    {BMC_BASE+0xC4, "MPC107 PCI Bus Error Status"},
+    {BMC_BASE+0xC8, "MPC107 Processor/PCI Error Address"},
+    {BMC_BASE+0xE0, "MPC107 AMBOR Register"},
+    {BMC_BASE+0xF0, "MPC107 MCCR1 Register"},
+    {BMC_BASE+0xF4, "MPC107 MCCR2 Register"},
+    {BMC_BASE+0xF8, "MPC107 MCCR3 Register"},
+    {BMC_BASE+0xFC, "MPC107 MCCR4 Register"}
+};
+#define N_MPC107_Regs  (sizeof(MPC107Regs)/sizeof(MPC107Regs[0]))
+#endif /* INCLUDE_MPC107_REPORT */
+#endif /* CONFIG_MOUSSE */
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+#ifdef CONFIG_MOUSSE
+#ifdef INCLUDE_MPC107_REPORT
+       unsigned int tmp = 0, i;
+#endif
+       /*
+        * Initialize the EUMBBAR (Embedded Util Mem Block Base Addr Reg).
+        * This is necessary before the EPIC, DMA ctlr, I2C ctlr, etc. can
+        * be accessed.
+        */
+
+#ifdef CONFIG_MPC8240                  /* only on MPC8240 */
+       mpc824x_mpc107_setreg (EUMBBAR, EUMBBAR_VAL);
+       /* MOT/SPS: Issue #10002, PCI (FD Alias enable) */
+       mpc824x_mpc107_setreg (AMBOR, 0x000000C0);
+#endif
+
+
+#ifdef INCLUDE_MPC107_REPORT
+       /* Check MPC824x PCI Device and Vendor ID */
+       while ((tmp = mpc824x_mpc107_getreg (BMC_BASE)) != 0x31057) {
+               printf ("       MPC107: offset=0x%x, val = 0x%x\n",
+                       BMC_BASE,
+                       tmp);
+       }
+
+       for (i = 0; i < N_MPC107_Regs; i++) {
+               printf ("       0x%x/%s = 0x%x\n",
+                       MPC107Regs[i].iobase,
+                       MPC107Regs[i].desc,
+                       mpc824x_mpc107_getreg (MPC107Regs[i].iobase));
+       }
+
+       printf ("IBAT0L = 0x%08X\n", mfspr (IBAT0L));
+       printf ("IBAT0U = 0x%08X\n", mfspr (IBAT0U));
+       printf ("IBAT1L = 0x%08X\n", mfspr (IBAT1L));
+       printf ("IBAT1U = 0x%08X\n", mfspr (IBAT1U));
+       printf ("IBAT2L = 0x%08X\n", mfspr (IBAT2L));
+       printf ("IBAT2U = 0x%08X\n", mfspr (IBAT2U));
+       printf ("IBAT3L = 0x%08X\n", mfspr (IBAT3L));
+       printf ("IBAT3U = 0x%08X\n", mfspr (IBAT3U));
+       printf ("DBAT0L = 0x%08X\n", mfspr (DBAT0L));
+       printf ("DBAT0U = 0x%08X\n", mfspr (DBAT0U));
+       printf ("DBAT1L = 0x%08X\n", mfspr (DBAT1L));
+       printf ("DBAT1U = 0x%08X\n", mfspr (DBAT1U));
+       printf ("DBAT2L = 0x%08X\n", mfspr (DBAT2L));
+       printf ("DBAT2U = 0x%08X\n", mfspr (DBAT2U));
+       printf ("DBAT3L = 0x%08X\n", mfspr (DBAT3L));
+       printf ("DBAT3U = 0x%08X\n", mfspr (DBAT3U));
+#endif /* INCLUDE_MPC107_REPORT */
+#endif /* CONFIG_MOUSSE */
+       return (0);
+}
diff --git a/cpu/mpc824x/drivers/i2c/i2c1.c b/cpu/mpc824x/drivers/i2c/i2c1.c
new file mode 100644 (file)
index 0000000..be6ec60
--- /dev/null
@@ -0,0 +1,1228 @@
+/*************************************************************
+ *
+ * Copyright @ Motorola, 1999
+ *
+ ************************************************************/
+#include <common.h>
+
+#ifdef CONFIG_HARD_I2C
+#include <i2c.h>
+#include "i2c_export.h"
+#include "i2c.h"
+
+#undef  I2CDBG0
+#undef  DEBUG
+
+/* Define a macro to use an optional application-layer print function, if
+ * one was passed to the I2C library during initialization.  If there was
+ * no function pointer passed, this protects against calling it.  Also define
+ * the global variable that holds the passed pointer.
+ */
+#define TIMEOUT (CFG_HZ/4)
+#define PRINT if ( app_print ) app_print
+static int (*app_print) (char *, ...);
+
+/******************* Internal to I2C Driver *****************/
+static unsigned int ByteToXmit = 0;
+static unsigned int XmitByte = 0;
+static unsigned char *XmitBuf = 0;
+static unsigned int XmitBufEmptyStop = 0;
+static unsigned int ByteToRcv = 0;
+static unsigned int RcvByte = 0;
+static unsigned char *RcvBuf = 0;
+static unsigned int RcvBufFulStop = 0;
+static unsigned int MasterRcvAddress = 0;
+
+/* Set by call to get_eumbbar during I2C_Initialize.
+ * This could be globally available to the I2C library, but there is
+ * an advantage to passing it as a parameter: it is already in a register
+ * and doesn't have to be loaded from memory.  Also, that is the way the
+ * I2C library was already implemented and I don't want to change it without
+ * a more detailed analysis.
+ * It is being set as a global variable in I2C_Initialize to hide it from
+ * the DINK application layer, because it is Kahlua-specific.  I think that
+ * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in
+ * a Kahlua-specific library dealing with the embedded utilities memory block.
+ * Right now, get_eumbbar is defined in dink32/kahlua.s.  The other two are
+ * defined in dink32/drivers/i2c/i2c2.s.
+ */
+static unsigned int Global_eumbbar = 0;
+
+extern unsigned int load_runtime_reg (unsigned int eumbbar,
+                                     unsigned int reg);
+
+extern unsigned int store_runtime_reg (unsigned int eumbbar,
+                                      unsigned int reg, unsigned int val);
+
+/************************** API *****************/
+
+/* Application Program Interface (API) are the calls provided by the I2C
+ * library to upper layer applications (i.e., DINK) to access the Kahlua
+ * I2C bus interface.  The functions and values that are part of this API
+ * are declared in i2c_export.h.
+ */
+
+/*  Initialize I2C unit with the following:
+ *  driver's slave address
+ *  interrupt enabled
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  desired clock rate
+ *  digital filter frequency sampling rate
+ *
+ *  This function must be called before I2C unit can be used.
+ */
+I2C_Status I2C_Initialize (unsigned char addr,
+                          I2C_INTERRUPT_MODE en_int,
+                          int (*p) (char *, ...))
+{
+       I2CStatus status;
+
+       /* establish the pointer, if there is one, to the application's "printf" */
+       app_print = p;
+
+       /* If this is the first call, get the embedded utilities memory block
+        * base address.  I'm not sure what to do about error handling here:
+        * if a non-zero value is returned, accept it.
+        */
+       if (Global_eumbbar == 0)
+               Global_eumbbar = get_eumbbar ();
+       if (Global_eumbbar == 0) {
+               PRINT ("I2C_Initialize: can't find EUMBBAR\n");
+               return I2C_ERROR;
+       }
+
+       /* validate the I2C address */
+       if (addr & 0x80) {
+               PRINT ("I2C_Initialize, I2C address invalid:  %d 0x%x\n",
+                          (unsigned int) addr, (unsigned int) addr);
+               return I2C_ERROR;
+       }
+
+       /* Call the internal I2C library function to perform work.
+        * Accept the default frequency sampling rate (no way to set it currently,
+        * via I2C_Init) and set the clock frequency to something reasonable.
+        */
+       status = I2C_Init (Global_eumbbar, (unsigned char) 0x31, addr, en_int);
+       if (status != I2CSUCCESS) {
+               PRINT ("I2C_Initialize: error in initiation\n");
+               return I2C_ERROR;
+       }
+
+       /* all is well */
+       return I2C_SUCCESS;
+}
+
+
+/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV
+ * are implemented.  Both are only in polling mode.
+ *
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * i2c_addr is the I2C address of the slave device
+ * data_addr is the address of the data on the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+I2C_Status I2C_do_transaction ( I2C_INTERRUPT_MODE en_int,
+                               I2C_TRANSACTION_MODE act,
+                               unsigned char i2c_addr,
+                               unsigned char data_addr,
+                               int len,
+                               char *buffer,
+                               I2C_STOP_MODE stop,
+                               int retry, I2C_RESTART_MODE rsta)
+{
+       I2C_Status status;
+       unsigned char data_addr_buffer[1];
+
+#if 1
+/* This is a temporary work-around.  The I2C library breaks the protocol
+ * if it attempts to handle a data transmission in more than one
+ * transaction, so the data address and the actual data bytes are put
+ * into a single buffer before sending it to the library internal functions.
+ * The problem is related to being able to restart a transaction without
+ * sending the I2C device address or repeating the data address.  It may take
+ * a day or two to sort it all out, so I'll have to get back to it later.
+ * Look at I2C_Start to see about using some status flags (I'm not sure that
+ * "stop" and "rsta" are enough to reflect the states, maybe so; but the logic
+ * in the library is insufficient) to control correct handling of the protocol.
+ */
+       unsigned char dummy_buffer[257];
+
+       if (act == I2C_MASTER_XMIT) {
+               int i;
+
+               if (len > 256)
+                       return I2C_ERROR;
+               for (i = 1; i <= len; i++)
+                       dummy_buffer[i] = buffer[i - 1];
+               dummy_buffer[0] = data_addr;
+               status = I2C_do_buffer (en_int, act, i2c_addr, 1 + len,
+                                       dummy_buffer, stop, retry, rsta);
+               if (status != I2C_SUCCESS) {
+                       PRINT ("I2C_do_transaction: can't perform data transfer\n");
+                       return I2C_ERROR;
+               }
+               return I2C_SUCCESS;
+       }
+#endif /* end of temp work-around */
+
+       /* validate requested transaction type */
+       if ((act != I2C_MASTER_XMIT) && (act != I2C_MASTER_RCV)) {
+               PRINT ("I2C_do_transaction, invalid transaction request:  %d\n",
+                       act);
+               return I2C_ERROR;
+       }
+
+       /* range check the I2C address */
+       if (i2c_addr & 0x80) {
+               PRINT ("I2C_do_transaction, I2C address out of range:  %d 0x%x\n",
+                       (unsigned int) i2c_addr, (unsigned int) i2c_addr);
+               return I2C_ERROR;
+       } else {
+               data_addr_buffer[0] = data_addr;
+       }
+
+       /*
+         * We first have to contact the slave device and transmit the
+         * data address. Be careful about the STOP and restart stuff.
+         * We don't want to signal STOP after sending the data
+         * address, but this could be a continuation if the
+         * application didn't release the bus after the previous
+         * transaction, by not sending a STOP after it.
+        */
+       status = I2C_do_buffer (en_int, I2C_MASTER_XMIT, i2c_addr, 1,
+                               data_addr_buffer, I2C_NO_STOP, retry, rsta);
+       if (status != I2C_SUCCESS) {
+               PRINT ("I2C_do_transaction: can't send data address for read\n");
+               return I2C_ERROR;
+       }
+
+       /* The data transfer will be a continuation. */
+       rsta = I2C_RESTART;
+
+       /* now handle the user data */
+       status = I2C_do_buffer (en_int, act, i2c_addr, len,
+                               buffer, stop, retry, rsta);
+       if (status != I2C_SUCCESS) {
+               PRINT ("I2C_do_transaction: can't perform data transfer\n");
+               return I2C_ERROR;
+       }
+
+       /* all is well */
+       return I2C_SUCCESS;
+}
+
+/* This function performs the work for I2C_do_transaction.  The work is
+ * split into this function to enable I2C_do_transaction to first transmit
+ * the data address to the I2C slave device without putting the data address
+ * into the first byte of the buffer.
+ *
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * i2c_addr is the I2C address of the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+static I2C_Status I2C_do_buffer (I2C_INTERRUPT_MODE en_int,
+                                I2C_TRANSACTION_MODE act,
+                                unsigned char i2c_addr,
+                                int len,
+                                unsigned char *buffer,
+                                I2C_STOP_MODE stop,
+                                int retry, I2C_RESTART_MODE rsta)
+{
+       I2CStatus rval;
+       unsigned int dev_stat;
+
+       if (act == I2C_MASTER_RCV) {
+               /* set up for master-receive transaction */
+               rval = I2C_get (Global_eumbbar, i2c_addr, buffer, len, stop, rsta);
+       } else {
+               /* set up for master-transmit transaction */
+               rval = I2C_put (Global_eumbbar, i2c_addr, buffer, len, stop, rsta);
+       }
+
+       /* validate the setup */
+       if (rval != I2CSUCCESS) {
+               dev_stat = load_runtime_reg (Global_eumbbar, I2CSR);
+               PRINT ("Error(I2C_do_buffer): control phase, code(0x%08x), status(0x%08x)\n", rval, dev_stat);
+               I2C_Stop (Global_eumbbar);
+               return I2C_ERROR;
+       }
+
+       if (en_int == 1) {
+               /* this should not happen, no interrupt handling yet */
+               return I2C_SUCCESS;
+       }
+
+       /* this performs the polling action, when the transfer is completed,
+        * the status returned from I2C_Timer_Event will be I2CBUFFFULL or
+        * I2CBUFFEMPTY (rcv or xmit), I2CSUCCESS or I2CADDRESS indicates the
+        * transaction is not yet complete, anything else is an error.
+        */
+       while (rval == I2CSUCCESS || rval == I2CADDRESS) {
+               int timeval = get_timer (0);
+
+               /* poll the device until something happens */
+               do {
+                       rval = I2C_Timer_Event (Global_eumbbar, 0);
+               }
+               while (rval == I2CNOEVENT && get_timer (timeval) < TIMEOUT);
+
+               /* check for error condition */
+               if (rval == I2CSUCCESS   ||
+                   rval == I2CBUFFFULL  ||
+                   rval == I2CBUFFEMPTY ||
+                   rval == I2CADDRESS) {
+                       ;       /* do nothing */
+               } else {
+                       /* report the error condition */
+                       dev_stat = load_runtime_reg (Global_eumbbar, I2CSR);
+                       PRINT ("Error(I2C_do_buffer):  code(0x%08x), status(0x%08x)\n",
+                                  rval, dev_stat);
+                       return I2C_ERROR;
+               }
+       }
+
+       /* all is well */
+       return I2C_SUCCESS;
+}
+
+/**
+ * Note:
+ *
+ * In all following functions,
+ * the caller shall pass the configured embedded utility memory
+ * block base, EUMBBAR.
+ **/
+
+/***********************************************************
+ * function: I2C_put
+ *
+ * description:
+   Send a buffer of data to the intended rcv_addr.
+ * If stop_flag is set, after the whole buffer
+ * is sent, generate a STOP signal provided that the
+ * receiver doesn't signal the STOP in the middle.
+ * I2C is the master performing transmitting. If
+ * no STOP signal is generated at the end of current
+ * transaction, the master can generate a START signal
+ * to another slave addr.
+ *
+ * note: this is master xmit API
+ *********************************************************/
+static I2CStatus I2C_put (unsigned int eumbbar, unsigned char rcv_addr,        /* receiver's address */
+         unsigned char *buffer_ptr,    /* pointer of data to be sent */
+         unsigned int length,  /* number of byte of in the buffer */
+         unsigned int stop_flag,       /* 1 - signal STOP when buffer is empty
+                                        * 0 - no STOP signal when buffer is empty
+                                        */
+         unsigned int is_cnt)
+{                                      /* 1 - this is a restart, don't check MBB
+                                        * 0 - this is a new start, check MBB
+                                        */
+       if (buffer_ptr == 0 || length == 0) {
+               return I2CERROR;
+       }
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_put\n", __FILE__, __LINE__);
+#endif
+
+       XmitByte = 0;
+       ByteToXmit = length;
+       XmitBuf = buffer_ptr;
+       XmitBufEmptyStop = stop_flag;
+
+       RcvByte = 0;
+       ByteToRcv = 0;
+       RcvBuf = 0;
+
+       /* we are the master, start transaction */
+       return I2C_Start (eumbbar, rcv_addr, XMIT, is_cnt);
+}
+
+/***********************************************************
+ * function: I2C_get
+ *
+ * description:
+ * Receive a buffer of data from the desired sender_addr
+ * If stop_flag is set, when the buffer is full and the
+ * sender does not signal STOP, generate a STOP signal.
+ * I2C is the master performing receiving. If no STOP signal
+ * is generated, the master can generate a START signal
+ * to another slave addr.
+ *
+ * note: this is master receive API
+ **********************************************************/
+static I2CStatus I2C_get (unsigned int eumbbar, unsigned char rcv_from,        /* sender's address */
+                 unsigned char *buffer_ptr,    /* pointer of receiving buffer */
+                 unsigned int length,  /* length of the receiving buffer */
+                 unsigned int stop_flag,       /* 1 - signal STOP when buffer is full
+                                                * 0 - no STOP signal when buffer is full
+                                                */
+                 unsigned int is_cnt)
+{                                              /* 1 - this is a restart, don't check MBB
+                                                * 0 - this is a new start, check MBB
+                                                */
+       if (buffer_ptr == 0 || length == 0) {
+               return I2CERROR;
+       }
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_get\n", __FILE__, __LINE__);
+#endif
+
+       RcvByte = 0;
+       ByteToRcv = length;
+       RcvBuf = buffer_ptr;
+       RcvBufFulStop = stop_flag;
+
+       XmitByte = 0;
+       ByteToXmit = 0;
+       XmitBuf = 0;
+
+       /* we are the master, start the transaction */
+       return I2C_Start (eumbbar, rcv_from, RCV, is_cnt);
+
+}
+
+#if 0  /* turn off dead code */
+/*********************************************************
+ * function: I2C_write
+ *
+ * description:
+ * Send a buffer of data to the requiring master.
+ * If stop_flag is set, after the whole buffer is sent,
+ * generate a STOP signal provided that the requiring
+ * receiver doesn't signal the STOP in the middle.
+ * I2C is the slave performing transmitting.
+ *
+ * Note: this is slave xmit API.
+ *
+ *       due to the current Kahlua design, slave transmitter
+ *       shall not signal STOP since there is no way
+ *       for master to detect it, causing I2C bus hung.
+ *
+ *       For the above reason, the stop_flag is always
+ *       set, i.e., 0.
+ *
+ *       programmer shall use the timer on Kahlua to
+ *       control the interval of data byte at the
+ *       master side.
+ *******************************************************/
+static I2CStatus I2C_write (unsigned int eumbbar, unsigned char *buffer_ptr,   /* pointer of data to be sent */
+               unsigned int length,    /* number of byte of in the buffer */
+               unsigned int stop_flag)
+{                                      /* 1 - signal STOP when buffer is empty
+                                        * 0 - no STOP signal when buffer is empty
+                                        */
+       if (buffer_ptr == 0 || length == 0) {
+               return I2CERROR;
+       }
+
+       XmitByte = 0;
+       ByteToXmit = length;
+       XmitBuf = buffer_ptr;
+       XmitBufEmptyStop = 0;   /* in order to avoid bus hung, ignored the user's stop_flag */
+
+       RcvByte = 0;
+       ByteToRcv = 0;
+       RcvBuf = 0;
+
+       /* we are the slave, just wait for being called, or pull */
+       /* I2C_Timer_Event( eumbbar ); */
+}
+
+/******************************************************
+ * function: I2C_read
+ *
+ * description:
+ * Receive a buffer of data from the sending master.
+ * If stop_flag is set, when the buffer is full and the
+ * sender does not signal STOP, generate a STOP signal.
+ * I2C is the slave performing receiving.
+ *
+ * note: this is slave receive API
+ ****************************************************/
+static I2CStatus I2C_read (unsigned int eumbbar, unsigned char *buffer_ptr,    /* pointer of receiving buffer */
+                  unsigned int length, /* length of the receiving buffer */
+                  unsigned int stop_flag)
+{                                      /* 1 - signal STOP when buffer is full
+                                        * 0 - no STOP signal when buffer is full
+                                        */
+       if (buffer_ptr == 0 || length == 0) {
+               return I2CERROR;
+       }
+
+       RcvByte = 0;
+       ByteToRcv = length;
+       RcvBuf = buffer_ptr;
+       RcvBufFulStop = stop_flag;
+
+       XmitByte = 0;
+       ByteToXmit = 0;
+       XmitBuf = 0;
+
+       /* wait for master to call us, or poll */
+       /* I2C_Timer_Event( eumbbar ); */
+}
+#endif /* turn off dead code */
+
+/*********************************************************
+ * function: I2c_Timer_Event
+ *
+ * description:
+ * if interrupt is not used, this is the timer event handler.
+ * After each fixed time interval, this function can be called
+ * to check the I2C status and call appropriate function to
+ * handle the status event.
+ ********************************************************/
+static I2CStatus I2C_Timer_Event (unsigned int eumbbar,
+                                 I2CStatus (*handler) (unsigned int))
+{
+       I2C_STAT stat;
+
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_Timer_Event\n", __FILE__, __LINE__);
+#endif
+
+       stat = I2C_Get_Stat (eumbbar);
+
+       if (stat.mif == 1) {
+               if (handler == 0) {
+                       return I2C_ISR (eumbbar);
+               } else {
+                       return (*handler) (eumbbar);
+               }
+       }
+
+       return I2CNOEVENT;
+}
+
+
+/****************** Device I/O function *****************/
+
+/******************************************************
+ * function: I2C_Start
+ *
+ * description: Generate a START signal in the desired mode.
+ *              I2C is the master.
+ *
+ *              Return I2CSUCCESS if no error.
+ *
+ * note:
+ ****************************************************/
+static I2CStatus I2C_Start (unsigned int eumbbar, unsigned char slave_addr,    /* address of the receiver */
+                       I2C_MODE mode,  /* XMIT(1) - put (write)
+                                        * RCV(0)  - get (read)
+                                        */
+                       unsigned int is_cnt)
+{                                      /* 1 - this is a restart, don't check MBB
+                                        * 0 - this is a new start
+                                        */
+       unsigned int tmp = 0;
+       I2C_STAT stat;
+       I2C_CTRL ctrl;
+
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_Start addr 0x%x mode %d cnt %d\n", __FILE__,
+                  __LINE__, slave_addr, mode, is_cnt);
+#endif
+
+       ctrl = I2C_Get_Ctrl (eumbbar);
+
+       /* first make sure I2C has been initialized */
+       if (ctrl.men == 0) {
+               return I2CERROR;
+       }
+
+       /* next make sure bus is idle */
+       stat = I2C_Get_Stat (eumbbar);
+
+       if (is_cnt == 0 && stat.mbb == 1) {
+               /* sorry, we lost */
+               return I2CBUSBUSY;
+       } else if (is_cnt == 1 && stat.mif == 1 && stat.mal == 0) {
+               /* sorry, we lost the bus */
+               return I2CALOSS;
+       }
+
+
+       /* OK, I2C is enabled and we have the bus */
+
+       /* prepare to write the slave address */
+       ctrl.msta = 1;
+       ctrl.mtx = 1;
+       ctrl.txak = 0;
+       ctrl.rsta = is_cnt;             /* set the repeat start bit */
+       I2C_Set_Ctrl (eumbbar, ctrl);
+
+       /* write the slave address and xmit/rcv mode bit */
+       tmp = load_runtime_reg (eumbbar, I2CDR);
+       tmp = (tmp & 0xffffff00) |
+             ((slave_addr & 0x007f) << 1) |
+             (mode == XMIT ? 0x0 : 0x1);
+       store_runtime_reg (eumbbar, I2CDR, tmp);
+
+       if (mode == RCV) {
+               MasterRcvAddress = 1;
+       } else {
+               MasterRcvAddress = 0;
+       }
+
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_Start exit\n", __FILE__, __LINE__);
+#endif
+
+       /* wait for the interrupt or poll  */
+       return I2CSUCCESS;
+}
+
+/***********************************************************
+ * function: I2c_Stop
+ *
+ * description: Generate a STOP signal to terminate the master
+ *              transaction.
+ *              return I2CSUCCESS
+ *
+ **********************************************************/
+static I2CStatus I2C_Stop (unsigned int eumbbar)
+{
+       I2C_CTRL ctrl;
+
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_Stop enter\n", __FILE__, __LINE__);
+#endif
+
+       ctrl = I2C_Get_Ctrl (eumbbar);
+       ctrl.msta = 0;
+       I2C_Set_Ctrl (eumbbar, ctrl);
+
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_Stop exit\n", __FILE__, __LINE__);
+#endif
+
+       return I2CSUCCESS;
+}
+
+/****************************************************
+ * function: I2C_Master_Xmit
+ *
+ * description: Master sends one byte of data to
+ *              slave target
+ *
+ *              return I2CSUCCESS if the byte transmitted.
+ *              Otherwise no-zero
+ *
+ * Note: condition must meet when this function is called:
+ *       I2CSR(MIF) == 1 && I2CSR(MCF)  == 1  && I2CSR(RXAK) == 0
+ *       I2CCR(MSTA) == 1  && I2CCR(MTX) == 1
+ *
+ ***************************************************/
+static I2CStatus I2C_Master_Xmit (unsigned int eumbbar)
+{
+       unsigned int val;
+
+       if (ByteToXmit > 0) {
+
+               if (ByteToXmit == XmitByte) {
+                       /* all xmitted */
+                       ByteToXmit = 0;
+
+                       if (XmitBufEmptyStop == 1) {
+                               I2C_Stop (eumbbar);
+                       }
+
+                       return I2CBUFFEMPTY;
+
+               }
+#ifdef I2CDBG0
+               PRINT ("%s(%d): xmit 0x%02x\n", __FILE__, __LINE__,
+                          *(XmitBuf + XmitByte));
+#endif
+
+               val = *(XmitBuf + XmitByte);
+               val &= 0x000000ff;
+               store_runtime_reg (eumbbar, I2CDR, val);
+               XmitByte++;
+
+               return I2CSUCCESS;
+
+       }
+
+       return I2CBUFFEMPTY;
+}
+
+/***********************************************
+ * function: I2C_Master_Rcv
+ *
+ * description: master reads one byte data
+ *              from slave source
+ *
+ *              return I2CSUCCESS if no error
+ *
+ * Note: condition must meet when this function is called:
+ *       I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&
+ *       I2CCR(MSTA) == 1 && I2CCR(MTX) == 0
+ *
+ ***********************************************/
+static I2CStatus I2C_Master_Rcv (unsigned int eumbbar)
+{
+       I2C_CTRL ctrl;
+       unsigned int val;
+
+       if (ByteToRcv > 0) {
+
+               if (ByteToRcv - RcvByte == 2 && RcvBufFulStop == 1) {
+                       /* master requests more than or equal to 2 bytes
+                        * we are reading 2nd to last byte
+                        */
+
+                       /* we need to set I2CCR(TXAK) to generate a STOP */
+                       ctrl = I2C_Get_Ctrl (eumbbar);
+                       ctrl.txak = 1;
+                       I2C_Set_Ctrl (eumbbar, ctrl);
+
+                       /* Kahlua will automatically generate a STOP
+                        * next time a transaction happens
+                        */
+
+                       /* note: the case of master requesting one byte is
+                        *       handled in I2C_ISR
+                        */
+               }
+
+               /* generat a STOP before reading the last byte */
+               if (RcvByte + 1 == ByteToRcv && RcvBufFulStop == 1) {
+                       I2C_Stop (eumbbar);
+               }
+
+               val = load_runtime_reg (eumbbar, I2CDR);
+               *(RcvBuf + RcvByte) = val & 0xFF;
+
+#ifdef I2CDBG0
+               PRINT ("%s(%d): rcv 0x%02x\n", __FILE__, __LINE__,
+                          *(RcvBuf + RcvByte));
+#endif
+
+               RcvByte++;
+
+               if (ByteToRcv == RcvByte) {
+                       ByteToRcv = 0;
+
+                       return I2CBUFFFULL;
+               }
+
+               return I2CSUCCESS;
+       }
+
+       return I2CBUFFFULL;
+
+}
+
+/****************************************************
+ * function: I2C_Slave_Xmit
+ *
+ * description: Slave sends one byte of data to
+ *              requesting destination
+ *
+ *        return SUCCESS if the byte transmitted. Otherwise
+ *        No-zero
+ *
+ * Note: condition must meet when this function is called:
+ *       I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&  I2CSR(RXAK) = 0
+ *       I2CCR(MSTA) == 0  && I2CCR(MTX) == 1
+ *
+ ***************************************************/
+static I2CStatus I2C_Slave_Xmit (unsigned int eumbbar)
+{
+       unsigned int val;
+
+       if (ByteToXmit > 0) {
+
+               if (ByteToXmit == XmitByte) {
+                       /* no more data to send */
+                       ByteToXmit = 0;
+
+                       /*
+                         * do not toggle I2CCR(MTX). Doing so will
+                         * cause bus-hung since current Kahlua design
+                         * does not give master a way to detect slave
+                         * stop. It is always a good idea for master
+                         * to use timer to prevent the long long
+                         * delays
+                        */
+
+                       return I2CBUFFEMPTY;
+               }
+#ifdef I2CDBG
+               PRINT ("%s(%d): xmit 0x%02x\n", __FILE__, __LINE__,
+                          *(XmitBuf + XmitByte));
+#endif
+
+               val = *(XmitBuf + XmitByte);
+               val &= 0x000000ff;
+               store_runtime_reg (eumbbar, I2CDR, val);
+               XmitByte++;
+
+               return I2CSUCCESS;
+       }
+
+       return I2CBUFFEMPTY;
+}
+
+/***********************************************
+ * function: I2C_Slave_Rcv
+ *
+ * description: slave reads one byte data
+ *              from master source
+ *
+ *              return I2CSUCCESS if no error otherwise non-zero
+ *
+ * Note: condition must meet when this function is called:
+ *       I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&
+ *       I2CCR(MSTA) == 0 && I2CCR(MTX)  = 0
+ *
+ ***********************************************/
+static I2CStatus I2C_Slave_Rcv (unsigned int eumbbar)
+{
+       unsigned int val;
+       I2C_CTRL ctrl;
+
+       if (ByteToRcv > 0) {
+               val = load_runtime_reg (eumbbar, I2CDR);
+               *(RcvBuf + RcvByte) = val & 0xff;
+#ifdef I2CDBG
+               PRINT ("%s(%d): rcv 0x%02x\n", __FILE__, __LINE__,
+                          *(RcvBuf + RcvByte));
+#endif
+               RcvByte++;
+
+               if (ByteToRcv == RcvByte) {
+                       if (RcvBufFulStop == 1) {
+                               /* all done */
+                               ctrl = I2C_Get_Ctrl (eumbbar);
+                               ctrl.txak = 1;
+                               I2C_Set_Ctrl (eumbbar, ctrl);
+                       }
+
+                       ByteToRcv = 0;
+                       return I2CBUFFFULL;
+               }
+
+               return I2CSUCCESS;
+       }
+
+       return I2CBUFFFULL;
+}
+
+/****************** Device Control Function *************/
+
+/*********************************************************
+ * function: I2C_Init
+ *
+ * description: Initialize I2C unit with desired frequency divider,
+ *              master's listening address, with interrupt enabled
+ *              or disabled.
+ *
+ * note:
+ ********************************************************/
+static I2CStatus I2C_Init (unsigned int eumbbar, unsigned char fdr,    /* frequency divider */
+                  unsigned char slave_addr,    /* driver's address used for receiving */
+                  unsigned int en_int)
+{                                              /* 1 - enable I2C interrupt
+                                                * 0 - disable I2C interrup
+                                                */
+       I2C_CTRL ctrl;
+       unsigned int tmp;
+
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_Init enter\n", __FILE__, __LINE__);
+#endif
+
+       ctrl = I2C_Get_Ctrl (eumbbar);
+       /* disable the I2C module before we change everything */
+       ctrl.men = 0;
+       I2C_Set_Ctrl (eumbbar, ctrl);
+
+       /* set the frequency diver */
+       tmp = load_runtime_reg (eumbbar, I2CFDR);
+       tmp = (tmp & 0xffffffc0) | (fdr & 0x3f);
+       store_runtime_reg (eumbbar, I2CFDR, tmp);
+
+       /* Set our listening (slave) address */
+       tmp = load_runtime_reg (eumbbar, I2CADR);
+       tmp = (tmp & 0xffffff01) | ((slave_addr & 0x7f) << 1);
+       store_runtime_reg (eumbbar, I2CADR, tmp);
+
+       /* enable I2C with desired interrupt setting */
+       ctrl.men = 1;
+       ctrl.mien = en_int & 0x1;
+       I2C_Set_Ctrl (eumbbar, ctrl);
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_Init exit\n", __FILE__, __LINE__);
+#endif
+
+       return I2CSUCCESS;
+
+}
+
+/*****************************************
+ * function I2c_Get_Stat
+ *
+ * description: Query I2C Status, i.e., read I2CSR
+ *
+ ****************************************/
+static I2C_STAT I2C_Get_Stat (unsigned int eumbbar)
+{
+       unsigned int temp;
+       I2C_STAT stat;
+
+       temp = load_runtime_reg (eumbbar, I2CSR);
+
+#ifdef I2CDBG0
+       PRINT ("%s(%d): get stat = 0x%08x\n", __FILE__, __LINE__, temp);
+#endif
+
+       stat.rsrv0 = (temp & 0xffffff00) >> 8;
+       stat.mcf   = (temp & 0x00000080) >> 7;
+       stat.maas  = (temp & 0x00000040) >> 6;
+       stat.mbb   = (temp & 0x00000020) >> 5;
+       stat.mal   = (temp & 0x00000010) >> 4;
+       stat.rsrv1 = (temp & 0x00000008) >> 3;
+       stat.srw   = (temp & 0x00000004) >> 2;
+       stat.mif   = (temp & 0x00000002) >> 1;
+       stat.rxak  = (temp & 0x00000001);
+       return stat;
+}
+
+/*********************************************
+ * function: I2c_Set_Ctrl
+ *
+ * description: Change I2C Control bits,
+ *              i.e., write to I2CCR
+ *
+ ********************************************/
+static void I2C_Set_Ctrl (unsigned int eumbbar, I2C_CTRL ctrl)
+{                                              /* new control value */
+       unsigned int temp = load_runtime_reg (eumbbar, I2CCR);
+
+       temp &= 0xffffff03;
+       temp |= ((ctrl.men  & 0x1) << 7);
+       temp |= ((ctrl.mien & 0x1) << 6);
+       temp |= ((ctrl.msta & 0x1) << 5);
+       temp |= ((ctrl.mtx  & 0x1) << 4);
+       temp |= ((ctrl.txak & 0x1) << 3);
+       temp |= ((ctrl.rsta & 0x1) << 2);
+#ifdef I2CDBG0
+       PRINT ("%s(%d): set ctrl = 0x%08x\n", __FILE__, __LINE__, temp);
+#endif
+       store_runtime_reg (eumbbar, I2CCR, temp);
+
+}
+
+/*****************************************
+ * function: I2C_Get_Ctrl
+ *
+ * description: Query I2C Control bits,
+ *              i.e., read I2CCR
+ *****************************************/
+static I2C_CTRL I2C_Get_Ctrl (unsigned int eumbbar)
+{
+       union {
+               I2C_CTRL ctrl;
+               unsigned int temp;
+       } s;
+
+       s.temp = load_runtime_reg (eumbbar, I2CCR);
+#ifdef I2CDBG0
+       PRINT ("%s(%d): get ctrl = 0x%08x\n", __FILE__, __LINE__, s.temp);
+#endif
+
+       return s.ctrl;
+}
+
+
+/****************************************
+ * function: I2C_Slave_Addr
+ *
+ * description: Process slave address phase.
+ *              return I2CSUCCESS if no error
+ *
+ * note: Precondition for calling this function:
+ *       I2CSR(MIF) == 1 &&
+ *       I2CSR(MAAS) == 1
+ ****************************************/
+static I2CStatus I2C_Slave_Addr (unsigned int eumbbar)
+{
+       I2C_STAT stat = I2C_Get_Stat (eumbbar);
+       I2C_CTRL ctrl = I2C_Get_Ctrl (eumbbar);
+
+       if (stat.srw == 1) {
+               /* we are asked to xmit */
+               ctrl.mtx = 1;
+               I2C_Set_Ctrl (eumbbar, ctrl);   /* set MTX */
+               return I2C_Slave_Xmit (eumbbar);
+       }
+
+       /* we are asked to receive data */
+       ctrl.mtx = 0;
+       I2C_Set_Ctrl (eumbbar, ctrl);
+       (void) load_runtime_reg (eumbbar, I2CDR);       /* do a fake read to start */
+
+       return I2CADDRESS;
+}
+
+/***********************************************
+ * function: I2C_ISR
+ *
+ * description: I2C Interrupt service routine
+ *
+ * note: Precondition:
+ *      I2CSR(MIF) == 1
+ **********************************************/
+static I2CStatus I2C_ISR (unsigned int eumbbar)
+{
+       I2C_STAT stat;
+       I2C_CTRL ctrl;
+
+#ifdef I2CDBG0
+       PRINT ("%s(%d): I2C_ISR\n", __FILE__, __LINE__);
+#endif
+
+       stat = I2C_Get_Stat (eumbbar);
+       ctrl = I2C_Get_Ctrl (eumbbar);
+
+       /* clear MIF */
+       stat.mif = 0;
+
+       /* Now let see what kind of event this is */
+       if (stat.mcf == 1) {
+               /* transfer compete */
+
+               /* clear the MIF bit */
+               I2C_Set_Stat (eumbbar, stat);
+
+               if (ctrl.msta == 1) {
+                       /* master */
+                       if (ctrl.mtx == 1) {
+                               /* check if this is the address phase for master receive */
+                               if (MasterRcvAddress == 1) {
+                                       /* Yes, it is the address phase of master receive */
+                                       ctrl.mtx = 0;
+                                       /* now check how much we want to receive */
+                                       if (ByteToRcv == 1 && RcvBufFulStop == 1) {
+                                               ctrl.txak = 1;
+                                       }
+
+                                       I2C_Set_Ctrl (eumbbar, ctrl);
+                                       (void) load_runtime_reg (eumbbar, I2CDR);       /* fake read first */
+
+                                       MasterRcvAddress = 0;
+                                       return I2CADDRESS;
+
+                               }
+
+                               /* master xmit */
+                               if (stat.rxak == 0) {
+                                       /* slave has acknowledged */
+                                       return I2C_Master_Xmit (eumbbar);
+                               }
+
+                               /* slave has not acknowledged yet, generate a STOP */
+                               if (XmitBufEmptyStop == 1) {
+                                       ctrl.msta = 0;
+                                       I2C_Set_Ctrl (eumbbar, ctrl);
+                               }
+
+                               return I2CSUCCESS;
+                       }
+
+                       /* master receive */
+                       return I2C_Master_Rcv (eumbbar);
+               }
+
+               /* slave */
+               if (ctrl.mtx == 1) {
+                       /* slave xmit */
+                       if (stat.rxak == 0) {
+                               /* master has acknowledged */
+                               return I2C_Slave_Xmit (eumbbar);
+                       }
+
+                       /* master has not acknowledged, wait for STOP */
+                       /* do nothing for preventing bus from hung */
+                       return I2CSUCCESS;
+               }
+
+               /* slave rcv */
+               return I2C_Slave_Rcv (eumbbar);
+
+       } else if (stat.maas == 1) {
+               /* received a call from master */
+
+               /* clear the MIF bit */
+               I2C_Set_Stat (eumbbar, stat);
+
+               /* master is calling us, process the address phase */
+               return I2C_Slave_Addr (eumbbar);
+       } else {
+               /* has to be arbitration lost */
+               stat.mal = 0;
+               I2C_Set_Stat (eumbbar, stat);
+
+               ctrl.msta = 0;                  /* return to receive mode */
+               I2C_Set_Ctrl (eumbbar, ctrl);
+       }
+
+       return I2CSUCCESS;
+
+}
+
+/******************************************************
+ * function: I2C_Set_Stat
+ *
+ * description: modify the I2CSR
+ *
+ *****************************************************/
+static void I2C_Set_Stat (unsigned int eumbbar, I2C_STAT stat)
+{
+       union {
+               unsigned int val;
+               I2C_STAT stat;
+       } s_tmp;
+       union {
+               unsigned int val;
+               I2C_STAT stat;
+       } s;
+
+       s.val = load_runtime_reg (eumbbar, I2CSR);
+       s.val &= 0xffffff08;
+       s_tmp.stat = stat;
+       s.val |= (s_tmp.val & 0xf7);
+
+#ifdef I2CDBG0
+       PRINT ("%s(%d): set stat = 0x%08x\n", __FILE__, __LINE__, s.val);
+#endif
+
+       store_runtime_reg (eumbbar, I2CSR, s.val);
+
+}
+
+/******************************************************
+ * The following are routines to glue the rest of
+ * U-Boot to the Sandpoint I2C driver.
+ *****************************************************/
+
+void i2c_init (int speed, int slaveadd)
+{
+#ifdef DEBUG
+       I2C_Initialize (0x7f, 0, (void *) printf);
+#else
+       I2C_Initialize (0x7f, 0, 0);
+#endif
+}
+
+int i2c_probe (uchar chip)
+{
+       int tmp;
+
+       /*
+        * Try to read the first location of the chip.  The underlying
+        * driver doesn't appear to support sending just the chip address
+        * and looking for an <ACK> back.
+        */
+       udelay(10000);
+       return i2c_read (chip, 0, 1, (char *)&tmp, 1);
+}
+
+int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+       I2CStatus status;
+       uchar xaddr[4];
+
+       if (alen > 0) {
+               xaddr[0] = (addr >> 24) & 0xFF;
+               xaddr[1] = (addr >> 16) & 0xFF;
+               xaddr[2] = (addr >> 8) & 0xFF;
+               xaddr[3] = addr & 0xFF;
+
+               status = I2C_do_buffer (0, I2C_MASTER_XMIT, chip, alen,
+                                       &xaddr[4 - alen], I2C_NO_STOP, 1,
+                                       I2C_NO_RESTART);
+               if (status != I2C_SUCCESS) {
+                       PRINT ("i2c_read: can't send data address for read\n");
+                       return 1;
+               }
+       }
+
+       /* The data transfer will be a continuation. */
+       status = I2C_do_buffer (0, I2C_MASTER_RCV, chip, len,
+                               buffer, I2C_STOP, 1, (alen > 0 ? I2C_RESTART :
+                               I2C_NO_RESTART));
+
+       if (status != I2C_SUCCESS) {
+               PRINT ("i2c_read: can't perform data transfer\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+       I2CStatus status;
+       unsigned char dummy_buffer[I2C_RXTX_LEN + 2];
+       int i;
+
+       dummy_buffer[0] = addr & 0xFF;
+       if (alen == 2)
+               dummy_buffer[1] = (addr >> 8) & 0xFF;
+       for (i = 0; i < len; i++)
+               dummy_buffer[i + alen] = buffer[i];
+
+       status = I2C_do_buffer (0, I2C_MASTER_XMIT, chip, alen + len,
+                               dummy_buffer, I2C_STOP, 1, I2C_NO_RESTART);
+
+#ifdef CFG_EEPROM_PAGE_WRITE_DELAY_MS
+       udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
+#endif
+       if (status != I2C_SUCCESS) {
+               PRINT ("i2c_write: can't perform data transfer\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+uchar i2c_reg_read (uchar i2c_addr, uchar reg)
+{
+       char buf[1];
+
+       i2c_init (0, 0);
+
+       i2c_read (i2c_addr, reg, 1, buf, 1);
+
+       return (buf[0]);
+}
+
+void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
+{
+       i2c_init (0, 0);
+
+       i2c_write (i2c_addr, reg, 1, &val, 1);
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/cpu/mpc824x/pci.c b/cpu/mpc824x/pci.c
new file mode 100644 (file)
index 0000000..7e3c4c3
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * arch/ppc/kernel/mpc10x_common.c
+ *
+ * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge,
+ * Mem ctlr, EPIC, etc.
+ *
+ * Author: Mark A. Greer
+ *         mgreer@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+#include <mpc824x.h>
+
+void pci_mpc824x_init (struct pci_controller *hose)
+{
+       hose->first_busno = 0;
+       hose->last_busno = 0xff;
+
+       /* System memory space */
+       pci_set_region(hose->regions + 0,
+                      CHRP_PCI_MEMORY_BUS,
+                      CHRP_PCI_MEMORY_PHYS,
+                      CHRP_PCI_MEMORY_SIZE,
+                      PCI_REGION_MEM | PCI_REGION_MEMORY);
+
+       /* PCI memory space */
+       pci_set_region(hose->regions + 1,
+                      CHRP_PCI_MEM_BUS,
+                      CHRP_PCI_MEM_PHYS,
+                      CHRP_PCI_MEM_SIZE,
+                      PCI_REGION_MEM);
+
+       /* ISA/PCI memory space */
+       pci_set_region(hose->regions + 2,
+                      CHRP_ISA_MEM_BUS,
+                      CHRP_ISA_MEM_PHYS,
+                      CHRP_ISA_MEM_SIZE,
+                      PCI_REGION_MEM);
+
+       /* PCI I/O space */
+       pci_set_region(hose->regions + 3,
+                      CHRP_PCI_IO_BUS,
+                      CHRP_PCI_IO_PHYS,
+                      CHRP_PCI_IO_SIZE,
+                      PCI_REGION_IO);
+
+       /* ISA/PCI I/O space */
+       pci_set_region(hose->regions + 4,
+                      CHRP_ISA_IO_BUS,
+                      CHRP_ISA_IO_PHYS,
+                      CHRP_ISA_IO_SIZE,
+                      PCI_REGION_IO);
+
+       hose->region_count = 5;
+
+       pci_setup_indirect(hose,
+                          CHRP_REG_ADDR,
+                          CHRP_REG_DATA);
+
+       pci_register_hose(hose);
+
+       hose->last_busno = pci_hose_scan(hose);
+}
+
+#endif
diff --git a/cpu/mpc824x/start.S b/cpu/mpc824x/start.S
new file mode 100644 (file)
index 0000000..bd9706d
--- /dev/null
@@ -0,0 +1,835 @@
+/*
+ *  Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000,2001,2002 Wolfgang Denk <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
+ */
+
+/* U-Boot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ * The processor starts at 0x00000100 and the code is executed
+ * from flash. The code is organized to be at an other address
+ * in memory, but as long we don't jump around before relocating.
+ * board_init lies at a quite high address and when the cpu has
+ * jumped there, everything is ok.
+ * This works because the cpu gives the FLASH (CS0) the whole
+ * address space at startup, and board_init lies as a echo of
+ * the flash somewhere up there in the memorymap.
+ *
+ * board_init will change CS0 to be positioned at the correct
+ * address and (s)dram will be positioned at address 0
+ */
+#include <config.h>
+#include <mpc824x.h>
+#include <version.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>
+
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+/* FP, Machine Check and Recoverable Interr. */
+#define MSR_KERNEL ( MSR_FP | MSR_ME | MSR_RI )
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r14 to access the GOT
+ */
+       START_GOT
+       GOT_ENTRY(_GOT2_TABLE_)
+       GOT_ENTRY(_FIXUP_TABLE_)
+
+       GOT_ENTRY(_start)
+       GOT_ENTRY(_start_of_vectors)
+       GOT_ENTRY(_end_of_vectors)
+       GOT_ENTRY(transfer_to_handler)
+
+       GOT_ENTRY(_end)
+       GOT_ENTRY(.bss)
+#if defined(CONFIG_FADS)
+       GOT_ENTRY(environment)
+#endif
+       END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+       .text
+       .long   0x27051956              /* U-Boot Magic Number                  */
+       .globl  version_string
+version_string:
+       .ascii U_BOOT_VERSION
+       .ascii " (", __DATE__, " - ", __TIME__, ")"
+       .ascii CONFIG_IDENT_STRING, "\0"
+
+       . = EXC_OFF_SYS_RESET
+       .globl  _start
+_start:
+       li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH     */
+       b       boot_cold
+
+       . = EXC_OFF_SYS_RESET + 0x10
+
+       .globl  _start_warm
+_start_warm:
+       li      r21, BOOTFLAG_WARM      /* Software reboot                      */
+       b       boot_warm
+
+boot_cold:
+boot_warm:
+
+       /* Initialize machine status; enable machine check interrupt            */
+       /*----------------------------------------------------------------------*/
+       li      r3, MSR_KERNEL          /* Set FP, ME, RI flags */
+       mtmsr   r3
+       mtspr   SRR1, r3                /* Make SRR1 match MSR */
+
+       addis   r0,0,0x0000             /* lets make sure that r0 is really 0 */
+       mtspr   HID0, r0                /* disable I and D caches */
+
+       mfspr   r3, ICR                 /* clear Interrupt Cause Register */
+
+       mfmsr   r3                      /* turn off address translation */
+       addis   r4,0,0xffff
+       ori     r4,r4,0xffcf
+       and     r3,r3,r4
+       mtmsr   r3
+       isync
+       sync                            /* the MMU should be off... */
+
+
+in_flash:
+#if defined(CONFIG_BMW)
+       bl early_init_f /* Must be ASM: no stack yet! */
+#endif
+       /*
+        * Setup BATs - cannot be done in C since we don't have a stack yet
+        */
+       bl      setup_bats
+
+       /* Enable MMU.
+        */
+       mfmsr   r3
+       ori     r3, r3, (MSR_IR | MSR_DR)
+       mtmsr   r3
+#if !defined(CONFIG_BMW)
+       /* Enable and invalidate data cache.
+        */
+       mfspr   r3, HID0
+       mr      r2, r3
+       ori     r3, r3, HID0_DCE | HID0_DCI
+       ori     r2, r2, HID0_DCE
+       sync
+       mtspr   HID0, r3
+       mtspr   HID0, r2
+       sync
+
+       /* Allocate Initial RAM in data cache.
+        */
+       lis     r3, CFG_INIT_RAM_ADDR@h
+       ori     r3, r3, CFG_INIT_RAM_ADDR@l
+       li      r2, 128
+       mtctr   r2
+1:
+       dcbz    r0, r3
+       addi    r3, r3, 32
+       bdnz    1b
+
+       /* Lock way0 in data cache.
+        */
+       mfspr   r3, 1011
+       lis     r2, 0xffff
+       ori     r2, r2, 0xff1f
+       and     r3, r3, r2
+       ori     r3, r3, 0x0080
+       sync
+       mtspr   1011, r3
+#endif /* !CONFIG_BMW */
+       /*
+        * Thisk the stack pointer *somewhere* sensible. Doesnt
+        * matter much where as we'll move it when we relocate
+        */
+       lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
+       ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
+
+       li      r0, 0                   /* Make room for stack frame header and */
+       stwu    r0, -4(r1)              /* clear final stack frame so that      */
+       stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
+
+       /* let the C-code set up the rest                                       */
+       /*                                                                      */
+       /* Be careful to keep code relocatable !                                */
+       /*----------------------------------------------------------------------*/
+
+       GET_GOT                 /* initialize GOT access                        */
+
+       /* r3: IMMR */
+       bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
+
+       mr      r3, r21
+       /* r3: BOOTFLAG */
+       bl      board_init_f    /* run 1st part of board init code (from Flash) */
+
+
+
+       .globl  _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+       STD_EXCEPTION(EXC_OFF_MACH_CHCK, MachineCheck, MachineCheckException)
+
+/* Data Storage exception.  "Never" generated on the 860. */
+       STD_EXCEPTION(EXC_OFF_DATA_STOR, DataStorage, UnknownException)
+
+/* Instruction Storage exception.  "Never" generated on the 860. */
+       STD_EXCEPTION(EXC_OFF_INS_STOR, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+       STD_EXCEPTION(EXC_OFF_EXTERNAL, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+       . = EXC_OFF_ALIGN
+Alignment:
+       EXCEPTION_PROLOG
+       mfspr   r4,DAR
+       stw     r4,_DAR(r21)
+       mfspr   r5,DSISR
+       stw     r5,_DSISR(r21)
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r20,MSR_KERNEL
+       rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
+       lwz     r6,GOT(transfer_to_handler)
+       mtlr    r6
+       blrl
+.L_Alignment:
+       .long   AlignmentException - _start + EXC_OFF_SYS_RESET
+       .long   int_return - _start + EXC_OFF_SYS_RESET
+
+/* Program check exception */
+       . = EXC_OFF_PROGRAM
+ProgramCheck:
+       EXCEPTION_PROLOG
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r20,MSR_KERNEL
+       rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
+       lwz     r6,GOT(transfer_to_handler)
+       mtlr    r6
+       blrl
+.L_ProgramCheck:
+       .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
+       .long   int_return - _start + EXC_OFF_SYS_RESET
+
+       /* No FPU on MPC8xx. This exception is not supposed to happen.
+       */
+       STD_EXCEPTION(EXC_OFF_FPUNAVAIL, FPUnavailable, UnknownException)
+
+       /* I guess we could implement decrementer, and may have
+        * to someday for timekeeping.
+        */
+       STD_EXCEPTION(EXC_OFF_DECR, Decrementer, timer_interrupt)
+       STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+       STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+
+       . = 0xc00
+/*
+ * r0 - SYSCALL number
+ * r3-... arguments
+ */
+SystemCall:
+       addis   r11,r0,0                /* get functions table addr */
+       ori     r11,r11,0               /* Note: this code is patched in trap_init */
+       addis   r12,r0,0                /* get number of functions */
+       ori     r12,r12,0
+
+       cmplw   0, r0, r12
+       bge     1f
+
+       rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
+       add     r11,r11,r0
+       lwz     r11,0(r11)
+
+       li      r12,0xd00-4*3           /* save LR & SRRx */
+       mflr    r0
+       stw     r0,0(r12)
+       mfspr   r0,SRR0
+       stw     r0,4(r12)
+       mfspr   r0,SRR1
+       stw     r0,8(r12)
+
+       li      r12,0xc00+_back-SystemCall
+       mtlr    r12
+       mtspr   SRR0,r11
+
+1:     SYNC
+       rfi
+
+_back:
+
+       mfmsr   r11                     /* Disable interrupts */
+       li      r12,0
+       ori     r12,r12,MSR_EE
+       andc    r11,r11,r12
+       SYNC                            /* Some chip revs need this... */
+       mtmsr   r11
+       SYNC
+
+       li      r12,0xd00-4*3           /* restore regs */
+       lwz     r11,0(r12)
+       mtlr    r11
+       lwz     r11,4(r12)
+       mtspr   SRR0,r11
+       lwz     r11,8(r12)
+       mtspr   SRR1,r11
+
+       SYNC
+       rfi
+
+       STD_EXCEPTION(EXC_OFF_TRACE, SingleStep, UnknownException)
+
+       STD_EXCEPTION(EXC_OFF_FPUNASSIST, Trap_0e, UnknownException)
+       STD_EXCEPTION(EXC_OFF_PMI, Trap_0f, UnknownException)
+
+       STD_EXCEPTION(EXC_OFF_ITME, InstructionTransMiss, UnknownException)
+       STD_EXCEPTION(EXC_OFF_DLTME, DataLoadTransMiss, UnknownException)
+       STD_EXCEPTION(EXC_OFF_DSTME, DataStoreTransMiss, UnknownException)
+       STD_EXCEPTION(EXC_OFF_IABE, InstructionBreakpoint, UnknownException)
+       STD_EXCEPTION(EXC_OFF_SMIE, SysManageInt, UnknownException)
+       STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+       STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+       STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+       STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+       STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+       STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+       STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+       STD_EXCEPTION(0x1c00, ReservedC, UnknownException)
+       STD_EXCEPTION(0x1d00, ReservedD, UnknownException)
+       STD_EXCEPTION(0x1e00, ReservedE, UnknownException)
+       STD_EXCEPTION(0x1f00, ReservedF, UnknownException)
+
+       STD_EXCEPTION(EXC_OFF_RMTE, RunModeTrace, UnknownException)
+
+       .globl  _end_of_vectors
+_end_of_vectors:
+
+
+       . = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+       .globl  transfer_to_handler
+transfer_to_handler:
+       stw     r22,_NIP(r21)
+       lis     r22,MSR_POW@h
+       andc    r23,r23,r22
+       stw     r23,_MSR(r21)
+       SAVE_GPR(7, r21)
+       SAVE_4GPRS(8, r21)
+       SAVE_8GPRS(12, r21)
+       SAVE_8GPRS(24, r21)
+#if 0
+       andi.   r23,r23,MSR_PR
+       mfspr   r23,SPRG3               /* if from user, fix up tss.regs */
+       beq     2f
+       addi    r24,r1,STACK_FRAME_OVERHEAD
+       stw     r24,PT_REGS(r23)
+2:     addi    r2,r23,-TSS             /* set r2 to current */
+       tovirt(r2,r2,r23)
+#endif
+       mflr    r23
+       andi.   r24,r23,0x3f00          /* get vector offset */
+       stw     r24,TRAP(r21)
+       li      r22,0
+       stw     r22,RESULT(r21)
+       mtspr   SPRG2,r22               /* r1 is now kernel sp */
+#if 0
+       addi    r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
+       cmplw   0,r1,r2
+       cmplw   1,r1,r24
+       crand   1,1,4
+       bgt     stack_ovf               /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
+#endif
+       lwz     r24,0(r23)              /* virtual address of handler */
+       lwz     r23,4(r23)              /* where to go when done */
+       mtspr   SRR0,r24
+       ori     r20,r20,0x30            /* enable IR, DR */
+       mtspr   SRR1,r20
+       mtlr    r23
+       SYNC
+       rfi                             /* jump to handler, enable MMU */
+
+int_return:
+       mfmsr   r28             /* Disable interrupts */
+       li      r4,0
+       ori     r4,r4,MSR_EE
+       andc    r28,r28,r4
+       SYNC                    /* Some chip revs need this... */
+       mtmsr   r28
+       SYNC
+       lwz     r2,_CTR(r1)
+       lwz     r0,_LINK(r1)
+       mtctr   r2
+       mtlr    r0
+       lwz     r2,_XER(r1)
+       lwz     r0,_CCR(r1)
+       mtspr   XER,r2
+       mtcrf   0xFF,r0
+       REST_10GPRS(3, r1)
+       REST_10GPRS(13, r1)
+       REST_8GPRS(23, r1)
+       REST_GPR(31, r1)
+       lwz     r2,_NIP(r1)     /* Restore environment */
+       lwz     r0,_MSR(r1)
+       mtspr   SRR0,r2
+       mtspr   SRR1,r0
+       lwz     r0,GPR0(r1)
+       lwz     r2,GPR2(r1)
+       lwz     r1,GPR1(r1)
+       SYNC
+       rfi
+
+/* Cache functions.
+*/
+       .globl  icache_enable
+icache_enable:
+       mfspr   r5,HID0         /* turn on the I cache. */
+       ori     r5,r5,0x8800    /* Instruction cache only! */
+       addis   r6,0,0xFFFF
+       ori     r6,r6,0xF7FF
+       and     r6,r5,r6        /* clear the invalidate bit */
+       sync
+       mtspr   HID0,r5
+       mtspr   HID0,r6
+       isync
+       sync
+       blr
+
+       .globl  icache_disable
+icache_disable:
+       mfspr   r5,HID0
+       addis   r6,0,0xFFFF
+       ori     r6,r6,0x7FFF
+       and     r5,r5,r6
+       sync
+       mtspr   HID0,r5
+       isync
+       sync
+       blr
+
+       .globl  icache_status
+icache_status:
+       mfspr   r3, HID0
+       srwi    r3, r3, 15      /* >>15 & 1=> select bit 16 */
+       andi.   r3, r3, 1
+       blr
+
+       .globl  dcache_enable
+dcache_enable:
+       mfspr   r5,HID0         /* turn on the D cache. */
+       ori     r5,r5,0x4400    /* Data cache only! */
+       mfspr   r4, PVR         /* read PVR */
+       srawi   r3, r4, 16      /* shift off the least 16 bits */
+       cmpi    0, 0, r3, 0xC   /* Check for Max pvr */
+       bne     NotMax
+       ori     r5,r5,0x0040    /* setting the DCFA bit, for Max rev 1 errata */
+NotMax:
+       addis   r6,0,0xFFFF
+       ori     r6,r6,0xFBFF
+       and     r6,r5,r6        /* clear the invalidate bit */
+       sync
+       mtspr   HID0,r5
+       mtspr   HID0,r6
+       isync
+       sync
+       blr
+
+       .globl  dcache_disable
+dcache_disable:
+       mfspr   r5,HID0
+       addis   r6,0,0xFFFF
+       ori     r6,r6,0xBFFF
+       and     r5,r5,r6
+       sync
+       mtspr   HID0,r5
+       isync
+       sync
+       blr
+
+       .globl  dcache_status
+dcache_status:
+       mfspr   r3, HID0
+       srwi    r3, r3, 14      /* >>14 & 1=> select bit 17 */
+       andi.   r3, r3, 1
+       blr
+
+       .globl  dc_read
+dc_read:
+/*TODO : who uses this, what should it do?
+*/
+       blr
+
+
+       .globl get_pvr
+get_pvr:
+       mfspr   r3, PVR
+       blr
+
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+       .globl  relocate_code
+relocate_code:
+
+       mr      r1,  r3         /* Set new stack pointer                */
+       mr      r9,  r4         /* Save copy of Global Data pointer     */
+       mr      r10, r5         /* Save copy of Destination Address     */
+
+       mr      r3,  r5                         /* Destination Address  */
+#ifdef DEBUG
+       lis     r4, CFG_SDRAM_BASE@h            /* Source      Address  */
+       ori     r4, r4, CFG_SDRAM_BASE@l
+#else
+       lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
+       ori     r4, r4, CFG_MONITOR_BASE@l
+#endif
+       lis     r5, CFG_MONITOR_LEN@h           /* Length in Bytes      */
+       ori     r5, r5, CFG_MONITOR_LEN@l
+       li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
+
+       /*
+        * Fix GOT pointer:
+        *
+        * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
+        *
+        * Offset:
+        */
+       sub     r15, r10, r4
+
+       /* First our own GOT */
+       add     r14, r14, r15
+       /* the the one used by the C code */
+       add     r30, r30, r15
+
+       /*
+        * Now relocate code
+        */
+
+       cmplw   cr1,r3,r4
+       addi    r0,r5,3
+       srwi.   r0,r0,2
+       beq     cr1,4f          /* In place copy is not necessary       */
+       beq     7f              /* Protect against 0 count              */
+       mtctr   r0
+       bge     cr1,2f
+
+       la      r8,-4(r4)
+       la      r7,-4(r3)
+1:     lwzu    r0,4(r8)
+       stwu    r0,4(r7)
+       bdnz    1b
+       b       4f
+
+2:     slwi    r0,r0,2
+       add     r8,r4,r0
+       add     r7,r3,r0
+3:     lwzu    r0,-4(r8)
+       stwu    r0,-4(r7)
+       bdnz    3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:     cmpwi   r6,0
+       add     r5,r3,r5
+       beq     7f              /* Always flush prefetch queue in any case */
+       subi    r0,r6,1
+       andc    r3,r3,r0
+       mr      r4,r3
+5:     dcbst   0,r4
+       add     r4,r4,r6
+       cmplw   r4,r5
+       blt     5b
+       sync                    /* Wait for all dcbst to complete on bus */
+       mr      r4,r3
+6:     icbi    0,r4
+       add     r4,r4,r6
+       cmplw   r4,r5
+       blt     6b
+7:     sync                    /* Wait for all icbi to complete on bus */
+       isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+       addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+       mtlr    r0
+       blr
+
+in_ram:
+
+       /*
+        * Relocation Function, r14 point to got2+0x8000
+        *
+        * Adjust got2 pointers, no need to check for 0, this code
+        * already puts a few entries in the table.
+        */
+       li      r0,__got2_entries@sectoff@l
+       la      r3,GOT(_GOT2_TABLE_)
+       lwz     r11,GOT(_GOT2_TABLE_)
+       mtctr   r0
+       sub     r11,r3,r11
+       addi    r3,r3,-4
+1:     lwzu    r0,4(r3)
+       add     r0,r0,r11
+       stw     r0,0(r3)
+       bdnz    1b
+
+       /*
+        * Now adjust the fixups and the pointers to the fixups
+        * in case we need to move ourselves again.
+        */
+2:     li      r0,__fixup_entries@sectoff@l
+       lwz     r3,GOT(_FIXUP_TABLE_)
+       cmpwi   r0,0
+       mtctr   r0
+       addi    r3,r3,-4
+       beq     4f
+3:     lwzu    r4,4(r3)
+       lwzux   r0,r4,r11
+       add     r0,r0,r11
+       stw     r10,0(r3)
+       stw     r0,0(r4)
+       bdnz    3b
+4:
+clear_bss:
+       /*
+        * Now clear BSS segment
+        */
+       lwz     r3,GOT(.bss)
+       lwz     r4,GOT(_end)
+
+       cmplw   0, r3, r4
+       beq     6f
+
+       li      r0, 0
+5:
+       stw     r0, 0(r3)
+       addi    r3, r3, 4
+       cmplw   0, r3, r4
+       blt     5b
+6:
+
+       mr      r3, r9          /* Global Data pointer          */
+       mr      r4, r10         /* Destination Address          */
+       bl      board_init_r
+
+       /* Problems accessing "end" in C, so do it here */
+       .globl  get_endaddr
+get_endaddr:
+       lwz     r3,GOT(_end)
+       blr
+
+       /*
+        * Copy exception vector code to low memory
+        *
+        * r3: dest_addr
+        * r7: source address, r8: end address, r9: target address
+        */
+       .globl  trap_init
+trap_init:
+       lwz     r7, GOT(_start)
+       lwz     r8, GOT(_end_of_vectors)
+
+       rlwinm  r9, r7, 0, 18, 31       /* _start & 0x3FFF      */
+
+       cmplw   0, r7, r8
+       bgelr                           /* return if r7>=r8 - just in case */
+
+       mflr    r4                      /* save link register           */
+1:
+       lwz     r0, 0(r7)
+       stw     r0, 0(r9)
+       addi    r7, r7, 4
+       addi    r9, r9, 4
+       cmplw   0, r7, r8
+       bne     1b
+
+       /*
+        * relocate `hdlr' and `int_return' entries
+        */
+       li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+       li      r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     2b
+
+       li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+       bl      trap_reloc
+
+       li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+       bl      trap_reloc
+
+       li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+       li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     3b
+
+       li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+       li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     4b
+
+       mtlr    r4                      /* restore link register        */
+       blr
+
+       /*
+        * Function: relocate entries for one exception vector
+        */
+trap_reloc:
+       lwz     r0, 0(r7)               /* hdlr ...                     */
+       add     r0, r0, r3              /*  ... += dest_addr            */
+       stw     r0, 0(r7)
+
+       lwz     r0, 4(r7)               /* int_return ...               */
+       add     r0, r0, r3              /*  ... += dest_addr            */
+       stw     r0, 4(r7)
+
+       blr
+
+       /* Setup the BAT registers.
+        */
+setup_bats:
+       lis     r4, CFG_IBAT0L@h
+       ori     r4, r4, CFG_IBAT0L@l
+       lis     r3, CFG_IBAT0U@h
+       ori     r3, r3, CFG_IBAT0U@l
+       mtspr   IBAT0L, r4
+       mtspr   IBAT0U, r3
+       isync
+
+       lis     r4, CFG_DBAT0L@h
+       ori     r4, r4, CFG_DBAT0L@l
+       lis     r3, CFG_DBAT0U@h
+       ori     r3, r3, CFG_DBAT0U@l
+       mtspr   DBAT0L, r4
+       mtspr   DBAT0U, r3
+       isync
+
+       lis     r4, CFG_IBAT1L@h
+       ori     r4, r4, CFG_IBAT1L@l
+       lis     r3, CFG_IBAT1U@h
+       ori     r3, r3, CFG_IBAT1U@l
+       mtspr   IBAT1L, r4
+       mtspr   IBAT1U, r3
+       isync
+
+       lis     r4, CFG_DBAT1L@h
+       ori     r4, r4, CFG_DBAT1L@l
+       lis     r3, CFG_DBAT1U@h
+       ori     r3, r3, CFG_DBAT1U@l
+       mtspr   DBAT1L, r4
+       mtspr   DBAT1U, r3
+       isync
+
+       lis     r4, CFG_IBAT2L@h
+       ori     r4, r4, CFG_IBAT2L@l
+       lis     r3, CFG_IBAT2U@h
+       ori     r3, r3, CFG_IBAT2U@l
+       mtspr   IBAT2L, r4
+       mtspr   IBAT2U, r3
+       isync
+
+       lis     r4, CFG_DBAT2L@h
+       ori     r4, r4, CFG_DBAT2L@l
+       lis     r3, CFG_DBAT2U@h
+       ori     r3, r3, CFG_DBAT2U@l
+       mtspr   DBAT2L, r4
+       mtspr   DBAT2U, r3
+       isync
+
+       lis     r4, CFG_IBAT3L@h
+       ori     r4, r4, CFG_IBAT3L@l
+       lis     r3, CFG_IBAT3U@h
+       ori     r3, r3, CFG_IBAT3U@l
+       mtspr   IBAT3L, r4
+       mtspr   IBAT3U, r3
+       isync
+
+       lis     r4, CFG_DBAT3L@h
+       ori     r4, r4, CFG_DBAT3L@l
+       lis     r3, CFG_DBAT3U@h
+       ori     r3, r3, CFG_DBAT3U@l
+       mtspr   DBAT3L, r4
+       mtspr   DBAT3U, r3
+       isync
+
+       /* Invalidate TLBs.
+        * -> for (val = 0; val < 0x20000; val+=0x1000)
+        * ->   tlbie(val);
+        */
+       lis     r3, 0
+       lis     r5, 2
+
+1:
+       tlbie   r3
+       addi    r3, r3, 0x1000
+       cmp     0, 0, r3, r5
+       blt     1b
+
+       blr
+
+
diff --git a/cpu/mpc8260/cpu_init.c b/cpu/mpc8260/cpu_init.c
new file mode 100644 (file)
index 0000000..9f9369a
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * (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 <mpc8260.h>
+#include <asm/cpm_8260.h>
+#include <ioports.h>
+
+static void config_8260_ioports (volatile immap_t * immr)
+{
+       int portnum;
+
+       for (portnum = 0; portnum < 4; portnum++) {
+               uint pmsk = 0,
+                    ppar = 0,
+                    psor = 0,
+                    pdir = 0,
+                    podr = 0,
+                    pdat = 0;
+               iop_conf_t *iopc = (iop_conf_t *) & iop_conf_tab[portnum][0];
+               iop_conf_t *eiopc = iopc + 32;
+               uint msk = 1;
+
+               /*
+                * NOTE:
+                * index 0 refers to pin 31,
+                * index 31 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;
+                       }
+
+                       msk <<= 1;
+                       iopc++;
+               }
+
+               if (pmsk != 0) {
+                       volatile ioport_t *iop = ioport_addr (immr, portnum);
+                       uint tpmsk = ~pmsk;
+
+                       /*
+                         * the (somewhat confused) paragraph at the
+                         * bottom of page 35-5 warns that there might
+                         * be "unknown behaviour" when programming
+                         * PSORx and PDIRx, if PPARx = 1, so I
+                         * decided this meant I had to disable the
+                         * dedicated function first, and enable it
+                         * last.
+                        */
+                       iop->ppar &= tpmsk;
+                       iop->psor = (iop->psor & tpmsk) | psor;
+                       iop->pdat = (iop->pdat & tpmsk) | pdat;
+                       iop->pdir = (iop->pdir & tpmsk) | pdir;
+                       iop->podr = (iop->podr & tpmsk) | podr;
+                       iop->ppar |= ppar;
+               }
+       }
+}
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * immr)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       volatile memctl8260_t *memctl = &immr->im_memctl;
+       extern void m8260_cpm_reset (void);
+
+       /* Pointer is writable since we allocated a register for it */
+       gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
+
+       /* Clear initial global data */
+       memset ((void *) gd, 0, sizeof (gd_t));
+
+       /* RSR - Reset Status Register - clear all status (5-4) */
+       gd->reset_status = immr->im_clkrst.car_rsr;
+       immr->im_clkrst.car_rsr = RSR_ALLBITS;
+
+       /* RMR - Reset Mode Register - contains checkstop reset enable (5-5) */
+       immr->im_clkrst.car_rmr = CFG_RMR;
+
+       /* BCR - Bus Configuration Register (4-25) */
+       immr->im_siu_conf.sc_bcr = CFG_BCR;
+
+       /* SIUMCR - contains debug pin configuration (4-31) */
+       immr->im_siu_conf.sc_siumcr = CFG_SIUMCR;
+
+       config_8260_ioports (immr);
+
+       /* initialize time counter status and control register (4-40) */
+       immr->im_sit.sit_tmcntsc = CFG_TMCNTSC;
+
+       /* initialize the PIT (4-42) */
+       immr->im_sit.sit_piscr = CFG_PISCR;
+
+#if !defined(CONFIG_COGENT)            /* done in start.S for the cogent */
+       /* System clock control register (9-8) */
+       immr->im_clkrst.car_sccr = CFG_SCCR;
+#endif /* !CONFIG_COGENT */
+
+       /*
+        * Memory Controller:
+        */
+
+       /* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+        * addresses - these have to be modified later when FLASH size
+        * has been determined
+        */
+
+#if defined(CFG_OR0_REMAP)
+       memctl->memc_or0 = CFG_OR0_REMAP;
+#endif
+#if defined(CFG_OR1_REMAP)
+       memctl->memc_or1 = CFG_OR1_REMAP;
+#endif
+
+       /* now restrict to preliminary range */
+       memctl->memc_br0 = CFG_BR0_PRELIM;
+       memctl->memc_or0 = CFG_OR0_PRELIM;
+
+#if defined(CFG_BR1_PRELIM) && defined(CFG_OR1_PRELIM)
+       memctl->memc_or1 = CFG_OR1_PRELIM;
+       memctl->memc_br1 = CFG_BR1_PRELIM;
+#endif
+
+#if defined(CFG_BR2_PRELIM) && defined(CFG_OR2_PRELIM)
+       memctl->memc_or2 = CFG_OR2_PRELIM;
+       memctl->memc_br2 = CFG_BR2_PRELIM;
+#endif
+
+#if defined(CFG_BR3_PRELIM) && defined(CFG_OR3_PRELIM)
+       memctl->memc_or3 = CFG_OR3_PRELIM;
+       memctl->memc_br3 = CFG_BR3_PRELIM;
+#endif
+
+#if defined(CFG_BR4_PRELIM) && defined(CFG_OR4_PRELIM)
+       memctl->memc_or4 = CFG_OR4_PRELIM;
+       memctl->memc_br4 = CFG_BR4_PRELIM;
+#endif
+
+#if defined(CFG_BR5_PRELIM) && defined(CFG_OR5_PRELIM)
+       memctl->memc_or5 = CFG_OR5_PRELIM;
+       memctl->memc_br5 = CFG_BR5_PRELIM;
+#endif
+
+#if defined(CFG_BR6_PRELIM) && defined(CFG_OR6_PRELIM)
+       memctl->memc_or6 = CFG_OR6_PRELIM;
+       memctl->memc_br6 = CFG_BR6_PRELIM;
+#endif
+
+#if defined(CFG_BR7_PRELIM) && defined(CFG_OR7_PRELIM)
+       memctl->memc_or7 = CFG_OR7_PRELIM;
+       memctl->memc_br7 = CFG_BR7_PRELIM;
+#endif
+
+#if defined(CFG_BR8_PRELIM) && defined(CFG_OR8_PRELIM)
+       memctl->memc_or8 = CFG_OR8_PRELIM;
+       memctl->memc_br8 = CFG_BR8_PRELIM;
+#endif
+
+#if defined(CFG_BR9_PRELIM) && defined(CFG_OR9_PRELIM)
+       memctl->memc_or9 = CFG_OR9_PRELIM;
+       memctl->memc_br9 = CFG_BR9_PRELIM;
+#endif
+
+#if defined(CFG_BR10_PRELIM) && defined(CFG_OR10_PRELIM)
+       memctl->memc_or10 = CFG_OR10_PRELIM;
+       memctl->memc_br10 = CFG_BR10_PRELIM;
+#endif
+
+#if defined(CFG_BR11_PRELIM) && defined(CFG_OR11_PRELIM)
+       memctl->memc_or11 = CFG_OR11_PRELIM;
+       memctl->memc_br11 = CFG_BR11_PRELIM;
+#endif
+
+       m8260_cpm_reset ();
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       volatile immap_t *immr = (immap_t *) gd->bd->bi_immr_base;
+
+       immr->im_cpm.cp_rccr = CFG_RCCR;
+
+       return (0);
+}
+
+/*
+ * print out the reason for the reset
+ */
+int prt_8260_rsr (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       static struct {
+               ulong mask;
+               char *desc;
+       } bits[] = {
+               {
+               RSR_JTRS, "JTAG"}, {
+               RSR_CSRS, "Check Stop"}, {
+               RSR_SWRS, "Software Watchdog"}, {
+               RSR_BMRS, "Bus Monitor"}, {
+               RSR_ESRS, "External Soft"}, {
+               RSR_EHRS, "External Hard"}
+       };
+       static int n = sizeof bits / sizeof bits[0];
+       ulong rsr = gd->reset_status;
+       int i;
+       char *sep;
+
+       puts ("MPC8260 Reset Status:");
+
+       sep = " ";
+       for (i = 0; i < n; i++)
+               if (rsr & bits[i].mask) {
+                       printf ("%s%s", sep, bits[i].desc);
+                       sep = ", ";
+               }
+
+       puts ("\n\n");
+       return (0);
+}
diff --git a/cpu/mpc8260/i2c.c b/cpu/mpc8260/i2c.c
new file mode 100644 (file)
index 0000000..8bfa2e8
--- /dev/null
@@ -0,0 +1,733 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ *
+ * (C) Copyright 2000 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>
+
+#if defined(CONFIG_HARD_I2C)
+
+#include <asm/cpm_8260.h>
+#include <i2c.h>
+
+/* define to enable debug messages */
+#undef  DEBUG_I2C
+
+/* uSec to wait between polls of the i2c */
+#define DELAY_US       100
+/* uSec to wait for the CPM to start processing the buffer */
+#define START_DELAY_US 1000
+
+/*
+ * tx/rx per-byte timeout: we delay DELAY_US uSec between polls so the
+ * timeout will be (tx_length + rx_length) * DELAY_US * TOUT_LOOP
+ */
+#define TOUT_LOOP 5
+
+/*-----------------------------------------------------------------------
+ * Set default values
+ */
+#ifndef        CFG_I2C_SPEED
+#define        CFG_I2C_SPEED   50000
+#endif
+
+#ifndef        CFG_I2C_SLAVE
+#define        CFG_I2C_SLAVE   0xFE
+#endif
+/*-----------------------------------------------------------------------
+ */
+
+typedef void (*i2c_ecb_t)(int, int);    /* error callback function */
+
+/* This structure keeps track of the bd and buffer space usage. */
+typedef struct i2c_state {
+       int             rx_idx;         /* index   to next free Rx BD */
+       int             tx_idx;         /* index   to next free Tx BD */
+       void            *rxbd;          /* pointer to next free Rx BD */
+       void            *txbd;          /* pointer to next free Tx BD */
+       int             tx_space;       /* number  of Tx bytes left   */
+       unsigned char   *tx_buf;        /* pointer to free Tx area    */
+       i2c_ecb_t       err_cb;         /* error callback function    */
+} i2c_state_t;
+
+/* flags for i2c_send() and i2c_receive() */
+#define        I2CF_ENABLE_SECONDARY   0x01    /* secondary_address is valid   */
+#define        I2CF_START_COND         0x02    /* tx: generate start condition */
+#define I2CF_STOP_COND         0x04    /* tx: generate stop  condition */
+
+/* return codes */
+#define I2CERR_NO_BUFFERS      0x01    /* no more BDs or buffer space  */
+#define I2CERR_MSG_TOO_LONG    0x02    /* tried to send/receive to much data   */
+#define I2CERR_TIMEOUT         0x03    /* timeout in i2c_doio()        */
+#define I2CERR_QUEUE_EMPTY     0x04    /* i2c_doio called without send/receive */
+
+/* error callback flags */
+#define I2CECB_RX_ERR          0x10    /* this is a receive error      */
+#define     I2CECB_RX_ERR_OV   0x02    /* receive overrun error        */
+#define     I2CECB_RX_MASK     0x0f    /* mask for error bits          */
+#define I2CECB_TX_ERR          0x20    /* this is a transmit error     */
+#define     I2CECB_TX_CL       0x01    /* transmit collision error     */
+#define     I2CECB_TX_UN       0x02    /* transmit underflow error     */
+#define     I2CECB_TX_NAK      0x04    /* transmit no ack error        */
+#define     I2CECB_TX_MASK     0x0f    /* mask for error bits          */
+#define I2CECB_TIMEOUT         0x40    /* this is a timeout error      */
+
+#define ERROR_I2C_NONE         0
+#define ERROR_I2C_LENGTH       1
+
+#define I2C_WRITE_BIT          0x00
+#define I2C_READ_BIT           0x01
+
+#define I2C_RXTX_LEN   128     /* maximum tx/rx buffer length */
+
+
+#define NUM_RX_BDS 4
+#define NUM_TX_BDS 4
+#define MAX_TX_SPACE 256
+
+typedef struct I2C_BD
+{
+  unsigned short status;
+  unsigned short length;
+  unsigned char *addr;
+} I2C_BD;
+#define BD_I2C_TX_START 0x0400  /* special status for i2c: Start condition */
+
+#define BD_I2C_TX_CL   0x0001  /* collision error */
+#define BD_I2C_TX_UN   0x0002  /* underflow error */
+#define BD_I2C_TX_NAK  0x0004  /* no acknowledge error */
+#define BD_I2C_TX_ERR  (BD_I2C_TX_NAK|BD_I2C_TX_UN|BD_I2C_TX_CL)
+
+#define BD_I2C_RX_ERR  BD_SC_OV
+
+#ifdef DEBUG_I2C
+#define PRINTD(x) printf x
+#else
+#define PRINTD(x)
+#endif
+
+/*
+ * Returns the best value of I2BRG to meet desired clock speed of I2C with
+ * input parameters (clock speed, filter, and predivider value).
+ * It returns computer speed value and the difference between it and desired
+ * speed.
+ */
+static inline int
+i2c_roundrate(int hz, int speed, int filter, int modval,
+               int *brgval, int *totspeed)
+{
+    int moddiv = 1 << (5-(modval & 3)), brgdiv, div;
+
+    PRINTD(("\t[I2C] trying hz=%d, speed=%d, filter=%d, modval=%d\n",
+       hz, speed, filter, modval));
+
+    div = moddiv * speed;
+    brgdiv = (hz + div - 1) / div;
+
+    PRINTD(("\t\tmoddiv=%d, brgdiv=%d\n", moddiv, brgdiv));
+
+    *brgval = (brgdiv / 2) - 3 - (2*filter);
+
+    if ((*brgval < 0) || (*brgval > 255)) {
+         PRINTD(("\t\trejected brgval=%d\n", *brgval));
+         return -1;
+    }
+
+    brgdiv = 2 * (*brgval + 3 + (2 * filter));
+    div = moddiv * brgdiv ;
+    *totspeed = (hz + div - 1) / div;
+
+    PRINTD(("\t\taccepted brgval=%d, totspeed=%d\n", *brgval, *totspeed));
+
+    return  0;
+}
+
+/*
+ * Sets the I2C clock predivider and divider to meet required clock speed.
+ */
+static int i2c_setrate(int hz, int speed)
+{
+    immap_t    *immap = (immap_t *)CFG_IMMR ;
+    volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
+    int brgval,
+         modval,       /* 0-3 */
+         bestspeed_diff = speed,
+         bestspeed_brgval=0,
+         bestspeed_modval=0,
+         bestspeed_filter=0,
+         totspeed,
+         filter = 0; /* Use this fixed value */
+
+       for (modval = 0; modval < 4; modval++)
+       {
+               if (i2c_roundrate (hz, speed, filter, modval, &brgval, &totspeed) == 0)
+               {
+                       int diff = speed - totspeed ;
+
+                       if ((diff >= 0) && (diff < bestspeed_diff))
+                       {
+                               bestspeed_diff  = diff ;
+                               bestspeed_modval        = modval;
+                               bestspeed_brgval        = brgval;
+                               bestspeed_filter        = filter;
+                       }
+               }
+       }
+
+    PRINTD(("[I2C] Best is:\n"));
+    PRINTD(("[I2C] CPU=%dhz RATE=%d F=%d I2MOD=%08x I2BRG=%08x DIFF=%dhz\n",
+                  hz, speed,
+                  bestspeed_filter, bestspeed_modval, bestspeed_brgval,
+                  bestspeed_diff));
+
+    i2c->i2c_i2mod |= ((bestspeed_modval & 3) << 1) | (bestspeed_filter << 3);
+    i2c->i2c_i2brg = bestspeed_brgval & 0xff;
+
+    PRINTD(("[I2C] i2mod=%08x i2brg=%08x\n", i2c->i2c_i2mod, i2c->i2c_i2brg));
+
+    return 1 ;
+}
+
+void i2c_init(int speed, int slaveadd)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       volatile immap_t *immap = (immap_t *)CFG_IMMR ;
+       volatile cpm8260_t *cp = (cpm8260_t *)&immap->im_cpm;
+       volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
+       volatile iic_t *iip;
+       ulong rbase, tbase;
+       volatile I2C_BD *rxbd, *txbd;
+       uint dpaddr;
+
+       dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE]));
+       if (dpaddr == 0) {
+           /* need to allocate dual port ram */
+           dpaddr = m8260_cpm_dpalloc(64 +
+               (NUM_RX_BDS * sizeof(I2C_BD)) + (NUM_TX_BDS * sizeof(I2C_BD)) +
+               MAX_TX_SPACE, 64);
+           *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE])) = dpaddr;
+       }
+
+       /*
+        * initialise data in dual port ram:
+        *
+        *        dpaddr -> parameter ram (64 bytes)
+        *         rbase -> rx BD         (NUM_RX_BDS * sizeof(I2C_BD) bytes)
+        *         tbase -> tx BD         (NUM_TX_BDS * sizeof(I2C_BD) bytes)
+        *                  tx buffer     (MAX_TX_SPACE bytes)
+        */
+
+       iip = (iic_t *)&immap->im_dprambase[dpaddr];
+       memset((void*)iip, 0, sizeof(iic_t));
+
+       rbase = dpaddr + 64;
+       tbase = rbase + NUM_RX_BDS * sizeof(I2C_BD);
+
+       /* Disable interrupts */
+       i2c->i2c_i2mod = 0x00;
+       i2c->i2c_i2cmr = 0x00;
+       i2c->i2c_i2cer = 0xff;
+       i2c->i2c_i2add = slaveadd;
+
+       /*
+        * Set the I2C BRG Clock division factor from desired i2c rate
+        * and current CPU rate (we assume sccr dfbgr field is 0;
+        * divide BRGCLK by 1)
+        */
+       PRINTD(("[I2C] Setting rate...\n"));
+       i2c_setrate (gd->brg_clk, CFG_I2C_SPEED) ;
+
+       /* Set I2C controller in master mode */
+       i2c->i2c_i2com = 0x01;
+
+       /* Initialize Tx/Rx parameters */
+       iip->iic_rbase = rbase;
+       iip->iic_tbase = tbase;
+       rxbd = (I2C_BD *)((unsigned char *)&immap->im_dprambase[iip->iic_rbase]);
+       txbd = (I2C_BD *)((unsigned char *)&immap->im_dprambase[iip->iic_tbase]);
+
+       PRINTD(("[I2C] rbase = %04x\n", iip->iic_rbase));
+       PRINTD(("[I2C] tbase = %04x\n", iip->iic_tbase));
+       PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd));
+       PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
+
+       /* Set big endian byte order */
+       iip->iic_tfcr = 0x10;
+       iip->iic_rfcr = 0x10;
+
+       /* Set maximum receive size. */
+       iip->iic_mrblr = I2C_RXTX_LEN;
+
+    cp->cp_cpcr = mk_cr_cmd(CPM_CR_I2C_PAGE,
+                                                       CPM_CR_I2C_SBLOCK,
+                                                       0x00,
+                                                       CPM_CR_INIT_TRX) | CPM_CR_FLG;
+    do {
+               __asm__ __volatile__ ("eieio");
+    } while (cp->cp_cpcr & CPM_CR_FLG);
+
+       /* Clear events and interrupts */
+       i2c->i2c_i2cer = 0xff;
+       i2c->i2c_i2cmr = 0x00;
+}
+
+static
+void i2c_newio(i2c_state_t *state)
+{
+       volatile immap_t *immap = (immap_t *)CFG_IMMR ;
+       volatile iic_t *iip;
+       uint dpaddr;
+
+       PRINTD(("[I2C] i2c_newio\n"));
+
+       dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE]));
+       iip = (iic_t *)&immap->im_dprambase[dpaddr];
+       state->rx_idx = 0;
+       state->tx_idx = 0;
+       state->rxbd = (void*)&immap->im_dprambase[iip->iic_rbase];
+       state->txbd = (void*)&immap->im_dprambase[iip->iic_tbase];
+       state->tx_space = MAX_TX_SPACE;
+       state->tx_buf = (uchar*)state->txbd + NUM_TX_BDS * sizeof(I2C_BD);
+       state->err_cb = NULL;
+
+       PRINTD(("[I2C] rxbd = %08x\n", (int)state->rxbd));
+       PRINTD(("[I2C] txbd = %08x\n", (int)state->txbd));
+       PRINTD(("[I2C] tx_buf = %08x\n", (int)state->tx_buf));
+
+       /* clear the buffer memory */
+       memset((char *)state->tx_buf, 0, MAX_TX_SPACE);
+}
+
+static
+int i2c_send(i2c_state_t *state,
+                        unsigned char address,
+                        unsigned char secondary_address,
+                        unsigned int flags,
+                        unsigned short size,
+                        unsigned char *dataout)
+{
+       volatile I2C_BD *txbd;
+       int i,j;
+
+       PRINTD(("[I2C] i2c_send add=%02d sec=%02d flag=%02d size=%d\n",
+                       address, secondary_address, flags, size));
+
+       /* trying to send message larger than BD */
+       if (size > I2C_RXTX_LEN)
+         return I2CERR_MSG_TOO_LONG;
+
+       /* no more free bds */
+       if (state->tx_idx >= NUM_TX_BDS || state->tx_space < (2 + size))
+         return I2CERR_NO_BUFFERS;
+
+       txbd = (I2C_BD *)state->txbd;
+       txbd->addr = state->tx_buf;
+
+       PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
+
+    if (flags & I2CF_START_COND)
+    {
+       PRINTD(("[I2C] Formatting addresses...\n"));
+       if (flags & I2CF_ENABLE_SECONDARY)
+       {
+               txbd->length = size + 2;  /* Length of message plus dest addresses */
+               txbd->addr[0] = address << 1;
+               txbd->addr[1] = secondary_address;
+               i = 2;
+       }
+       else
+       {
+               txbd->length = size + 1;  /* Length of message plus dest address */
+               txbd->addr[0] = address << 1;  /* Write destination address to BD */
+               i = 1;
+       }
+    }
+    else
+    {
+       txbd->length = size;  /* Length of message */
+       i = 0;
+    }
+
+       /* set up txbd */
+       txbd->status = BD_SC_READY;
+       if (flags & I2CF_START_COND)
+         txbd->status |= BD_I2C_TX_START;
+       if (flags & I2CF_STOP_COND)
+         txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+
+       /* Copy data to send into buffer */
+       PRINTD(("[I2C] copy data...\n"));
+       for(j = 0; j < size; i++, j++)
+         txbd->addr[i] = dataout[j];
+
+       PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+                  txbd->length,
+                  txbd->status,
+                  txbd->addr[0],
+                  txbd->addr[1]));
+
+       /* advance state */
+       state->tx_buf += txbd->length;
+       state->tx_space -= txbd->length;
+       state->tx_idx++;
+       state->txbd = (void*)(txbd + 1);
+
+       return 0;
+}
+
+static
+int i2c_receive(i2c_state_t *state,
+                               unsigned char address,
+                               unsigned char secondary_address,
+                               unsigned int flags,
+                               unsigned short size_to_expect,
+                               unsigned char *datain)
+{
+       volatile I2C_BD *rxbd, *txbd;
+
+       PRINTD(("[I2C] i2c_receive %02d %02d %02d\n", address, secondary_address, flags));
+
+       /* Expected to receive too much */
+       if (size_to_expect > I2C_RXTX_LEN)
+         return I2CERR_MSG_TOO_LONG;
+
+       /* no more free bds */
+       if (state->tx_idx >= NUM_TX_BDS || state->rx_idx >= NUM_RX_BDS
+                || state->tx_space < 2)
+         return I2CERR_NO_BUFFERS;
+
+       rxbd = (I2C_BD *)state->rxbd;
+       txbd = (I2C_BD *)state->txbd;
+
+       PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd));
+       PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
+
+       txbd->addr = state->tx_buf;
+
+       /* set up TXBD for destination address */
+       if (flags & I2CF_ENABLE_SECONDARY)
+       {
+               txbd->length = 2;
+               txbd->addr[0] = address << 1;   /* Write data */
+               txbd->addr[1] = secondary_address;  /* Internal address */
+               txbd->status = BD_SC_READY;
+       }
+       else
+       {
+               txbd->length = 1 + size_to_expect;
+               txbd->addr[0] = (address << 1) | 0x01;
+               txbd->status = BD_SC_READY;
+               memset(&txbd->addr[1], 0, txbd->length);
+       }
+
+       /* set up rxbd for reception */
+       rxbd->status = BD_SC_EMPTY;
+       rxbd->length = size_to_expect;
+       rxbd->addr = datain;
+
+       txbd->status |= BD_I2C_TX_START;
+       if (flags & I2CF_STOP_COND)
+       {
+               txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+               rxbd->status |= BD_SC_WRAP;
+       }
+
+       PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+                  txbd->length,
+                  txbd->status,
+                  txbd->addr[0],
+                  txbd->addr[1]));
+       PRINTD(("[I2C] rxbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+                  rxbd->length,
+                  rxbd->status,
+                  rxbd->addr[0],
+                  rxbd->addr[1]));
+
+       /* advance state */
+       state->tx_buf += txbd->length;
+       state->tx_space -= txbd->length;
+       state->tx_idx++;
+       state->txbd = (void*)(txbd + 1);
+       state->rx_idx++;
+       state->rxbd = (void*)(rxbd + 1);
+
+       return 0;
+}
+
+
+static
+int i2c_doio(i2c_state_t *state)
+{
+       volatile immap_t *immap = (immap_t *)CFG_IMMR ;
+       volatile iic_t *iip;
+       volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
+       volatile I2C_BD *txbd, *rxbd;
+       int  j;
+        int  timeout;
+       uint dpaddr;
+
+       PRINTD(("[I2C] i2c_doio\n"));
+
+        timeout = TOUT_LOOP * 256;     /* arbitrarily long */
+
+       if (state->tx_idx <= 0 && state->rx_idx <= 0) {
+               PRINTD(("[I2C] No I/O is queued\n"));
+               return I2CERR_QUEUE_EMPTY;
+       }
+
+       dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE]));
+       iip = (iic_t *)&immap->im_dprambase[dpaddr];
+       iip->iic_rbptr = iip->iic_rbase;
+       iip->iic_tbptr = iip->iic_tbase;
+
+       /* Enable I2C */
+       PRINTD(("[I2C] Enabling I2C...\n"));
+       i2c->i2c_i2mod |= 0x01;
+
+       /* Begin transmission */
+       i2c->i2c_i2com |= 0x80;
+
+       /* Loop until transmit & receive completed */
+
+       txbd = ((I2C_BD*)state->txbd) - 1;
+       j = 0;
+       if (state->tx_idx > 0) {
+               timeout = TOUT_LOOP * txbd->length;
+
+               PRINTD(("[I2C] Transmitting...(txbd=0x%08lx)\n", (ulong)txbd));
+               udelay(START_DELAY_US); /* give it time to start */
+               while((txbd->status & BD_SC_READY) && (j++ < timeout)) {
+                       udelay(DELAY_US);
+                       if (ctrlc())
+                               return (-1);
+                       __asm__ __volatile__ ("eieio");
+               }
+       }
+
+       rxbd = ((I2C_BD*)state->rxbd) - 1;
+       j = 0;
+       if ((state->rx_idx > 0) && (j < timeout)) {
+               timeout = TOUT_LOOP * rxbd->length;
+               PRINTD(("[I2C] Receiving...(rxbd=0x%08lx)\n", (ulong)rxbd));
+               udelay(START_DELAY_US); /* give it time to start */
+               while((rxbd->status & BD_SC_EMPTY) && (j++ < timeout)) {
+                       udelay(DELAY_US);
+                       if (ctrlc())
+                               return (-1);
+                       __asm__ __volatile__ ("eieio");
+               }
+       }
+
+       /* Turn off I2C */
+       i2c->i2c_i2mod &= ~0x01;
+
+       if (state->err_cb != NULL) {
+               int n, i, b;
+
+               /*
+                * if we have an error callback function, look at the
+                * error bits in the bd status and pass them back
+                */
+
+               if ((n = state->tx_idx) > 0) {
+                       for (i = 0; i < n; i++) {
+                               txbd = ((I2C_BD*)state->txbd) - (n - i);
+                               if ((b = txbd->status & BD_I2C_TX_ERR) != 0)
+                                       (*state->err_cb)(I2CECB_TX_ERR|b, i);
+                       }
+               }
+
+               if ((n = state->rx_idx) > 0) {
+                       for (i = 0; i < n; i++) {
+                               rxbd = ((I2C_BD*)state->rxbd) - (n - i);
+                               if ((b = rxbd->status & BD_I2C_RX_ERR) != 0)
+                                       (*state->err_cb)(I2CECB_RX_ERR|b, i);
+                       }
+               }
+
+               if (j >= timeout)
+                       (*state->err_cb)(I2CECB_TIMEOUT, 0);
+       }
+
+       /* sort out errors and return appropriate good/error status */
+       if(j >= timeout)
+               return(I2CERR_TIMEOUT);
+       if((txbd->status & BD_I2C_TX_ERR) != 0)
+               return(I2CECB_TX_ERR | (txbd->status & I2CECB_TX_MASK));
+       if((rxbd->status & BD_I2C_RX_ERR) != 0)
+               return(I2CECB_RX_ERR | (rxbd->status & I2CECB_RX_MASK));
+
+       return(0);
+}
+
+static int had_tx_nak;
+
+static void
+i2c_test_callback(int flags, int xnum)
+{
+       if ((flags & I2CECB_TX_ERR) && (flags & I2CECB_TX_NAK))
+               had_tx_nak = 1;
+}
+
+int i2c_probe(uchar chip)
+{
+       i2c_state_t state;
+       int rc;
+       uchar buf[1];
+
+       i2c_newio(&state);
+
+       state.err_cb = i2c_test_callback;
+       had_tx_nak = 0;
+
+       rc = i2c_receive(&state, chip, 0, I2CF_START_COND|I2CF_STOP_COND, 1, buf);
+
+       if (rc != 0)
+               return (rc);
+
+       rc = i2c_doio(&state);
+
+       if ((rc != 0) && (rc != I2CERR_TIMEOUT))
+               return (rc);
+
+       return (had_tx_nak);
+}
+
+
+int
+i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+       i2c_state_t state;
+       uchar xaddr[4];
+       int rc;
+
+       xaddr[0] = (addr >> 24) & 0xFF;
+       xaddr[1] = (addr >> 16) & 0xFF;
+       xaddr[2] = (addr >>  8) & 0xFF;
+       xaddr[3] =  addr        & 0xFF;
+
+#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
+        /*
+         * EEPROM chips that implement "address overflow" are ones
+         * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address
+         * and the extra bits end up in the "chip address" bit slots.
+         * This makes a 24WC08 (1Kbyte) chip look like four 256 byte
+         * chips.
+         *
+         * Note that we consider the length of the address field to still
+         * be one byte because the extra address bits are hidden in the
+         * chip address.
+         */
+       chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+       i2c_newio(&state);
+
+       rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]);
+       if (rc != 0) {
+               printf("i2c_read: i2c_send failed (%d)\n", rc);
+               return 1;
+       }
+
+       rc = i2c_receive(&state, chip, 0, I2CF_STOP_COND, len, buffer);
+       if (rc != 0) {
+               printf("i2c_read: i2c_receive failed (%d)\n", rc);
+               return 1;
+       }
+
+       rc = i2c_doio(&state);
+       if (rc != 0) {
+               printf("i2c_read: i2c_doio failed (%d)\n", rc);
+               return 1;
+       }
+       return 0;
+}
+
+int
+i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+       i2c_state_t state;
+       uchar xaddr[4];
+       int rc;
+
+       xaddr[0] = (addr >> 24) & 0xFF;
+       xaddr[1] = (addr >> 16) & 0xFF;
+       xaddr[2] = (addr >>  8) & 0xFF;
+       xaddr[3] =  addr        & 0xFF;
+
+#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
+        /*
+         * EEPROM chips that implement "address overflow" are ones
+         * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address
+         * and the extra bits end up in the "chip address" bit slots.
+         * This makes a 24WC08 (1Kbyte) chip look like four 256 byte
+         * chips.
+         *
+         * Note that we consider the length of the address field to still
+         * be one byte because the extra address bits are hidden in the
+         * chip address.
+         */
+       chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+       i2c_newio(&state);
+
+       rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]);
+       if (rc != 0) {
+               printf("i2c_write: first i2c_send failed (%d)\n", rc);
+               return 1;
+       }
+
+       rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer);
+       if (rc != 0) {
+               printf("i2c_write: second i2c_send failed (%d)\n", rc);
+               return 1;
+       }
+
+       rc = i2c_doio(&state);
+       if (rc != 0) {
+               printf("i2c_write: i2c_doio failed (%d)\n", rc);
+               return 1;
+       }
+       return 0;
+}
+
+uchar
+i2c_reg_read(uchar chip, uchar reg)
+{
+       char buf;
+
+       i2c_read(chip, reg, 1, &buf, 1);
+
+       return (buf);
+}
+
+void
+i2c_reg_write(uchar chip, uchar reg, uchar val)
+{
+       i2c_write(chip, reg, 1, &val, 1);
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/cpu/mpc8xx/cpu.c b/cpu/mpc8xx/cpu.c
new file mode 100644 (file)
index 0000000..b1b58b0
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ * (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
+ */
+
+/*
+ * m8xx.c
+ *
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc8xx.h>
+#include <asm/cache.h>
+
+static char *cpu_warning = "\n         " \
+       "*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***";
+
+#if ((defined(CONFIG_MPC860) || defined(CONFIG_MPC855)) && \
+     !defined(CONFIG_MPC862))
+# ifdef        CONFIG_MPC855
+#  define      ID_STR  "PC855"
+# else
+#  define      ID_STR  "PC860"
+# endif
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+       volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+       uint k, m;
+       char buf[32];
+       char pre = 'X';
+       char *mid = "xx";
+       char *suf;
+
+       /* the highest 16 bits should be 0x0050 for a 860 */
+
+       if ((pvr >> 16) != 0x0050)
+               return -1;
+
+       k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]);
+       m = 0;
+
+       switch (k) {
+       case 0x00020001: pre = 'p'; suf = ""; break;
+       case 0x00030001: suf = ""; break;
+       case 0x00120003: suf = "A"; break;
+       case 0x00130003: suf = "A3"; break;
+
+       case 0x00200004: suf = "B"; break;
+
+       case 0x00300004: suf = "C"; break;
+       case 0x00310004: suf = "C1"; m = 1;
+               break;
+
+       case 0x00200064: mid = "SR"; suf = "B"; break;
+       case 0x00300065: mid = "SR"; suf = "C"; break;
+       case 0x00310065: mid = "SR"; suf = "C1"; m = 1; break;
+       case 0x05010000: suf = "D3"; m = 1; break;
+       case 0x05020000: suf = "D4"; m = 1; break;
+
+               /* this value is not documented anywhere */
+       case 0x40000000: pre = 'P'; suf = "D"; m = 1; break;
+
+       default: suf = NULL; break;
+       }
+
+       if (suf)
+               printf ("%c" ID_STR "%sZPnn%s", pre, mid, suf);
+       else
+               printf ("unknown M" ID_STR " (0x%08x)", k);
+
+       printf (" at %s MHz:", strmhz (buf, clock));
+
+       printf (" %u kB I-Cache", checkicache () >> 10);
+       printf (" %u kB D-Cache", checkdcache () >> 10);
+
+       /* lets check and see if we're running on a 860T (or P?) */
+
+       immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+       if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+               printf (" FEC present");
+       }
+
+       if (!m) {
+               puts (cpu_warning);
+       }
+
+       putc ('\n');
+
+       return 0;
+}
+
+#elif defined(CONFIG_MPC862)
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+       volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+       uint k, m;
+       char buf[32];
+       char pre = 'X';
+       char *mid = "xx";
+       char *suf;
+
+       /* the highest 16 bits should be 0x0050 for a 8xx */
+
+       if ((pvr >> 16) != 0x0050)
+               return -1;
+
+       k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]);
+       m = 0;
+
+       switch (k) {
+
+               /* this value is not documented anywhere */
+       case 0x06000000: mid = "P"; suf = "0"; break;
+       case 0x06010001: mid = "P"; suf = "A"; m = 1; break;
+       case 0x07000003: mid = "P"; suf = "B"; m = 1; break;
+       default: suf = NULL; break;
+       }
+
+       if (suf)
+               printf ("%cPC862%sZPnn%s", pre, mid, suf);
+       else
+               printf ("unknown MPC862 (0x%08x)", k);
+
+       printf (" at %s MHz:", strmhz (buf, clock));
+
+       printf (" %u kB I-Cache", checkicache () >> 10);
+       printf (" %u kB D-Cache", checkdcache () >> 10);
+
+       /* lets check and see if we're running on a 862T (or P?) */
+
+       immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+       if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+               printf (" FEC present");
+       }
+
+       if (!m) {
+               puts (cpu_warning);
+       }
+
+       putc ('\n');
+
+       return 0;
+}
+
+#elif defined(CONFIG_MPC823)
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+       volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+       uint k, m;
+       char buf[32];
+       char *suf;
+
+       /* the highest 16 bits should be 0x0050 for a 8xx */
+
+       if ((pvr >> 16) != 0x0050)
+               return -1;
+
+       k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]);
+       m = 0;
+
+       switch (k) {
+               /* MPC823 */
+       case 0x20000000: suf = "0"; break;
+       case 0x20010000: suf = "0.1"; break;
+       case 0x20020000: suf = "Z2/3"; break;
+       case 0x20020001: suf = "Z3"; break;
+       case 0x21000000: suf = "A"; break;
+       case 0x21010000: suf = "B"; m = 1; break;
+       case 0x21010001: suf = "B2"; m = 1; break;
+               /* MPC823E */
+       case 0x24010000: suf = NULL;
+                       puts ("PPC823EZTnnB2");
+                       m = 1;
+                       break;
+       default:
+                       suf = NULL;
+                       printf ("unknown MPC823 (0x%08x)", k);
+                       break;
+       }
+       if (suf)
+               printf ("PPC823ZTnn%s", suf);
+
+       printf (" at %s MHz:", strmhz (buf, clock));
+
+       printf (" %u kB I-Cache", checkicache () >> 10);
+       printf (" %u kB D-Cache", checkdcache () >> 10);
+
+       /* lets check and see if we're running on a 860T (or P?) */
+
+       immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+       if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+               puts (" FEC present");
+       }
+
+       if (!m) {
+               puts (cpu_warning);
+       }
+
+       putc ('\n');
+
+       return 0;
+}
+
+#elif defined(CONFIG_MPC850)
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+       volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+       uint k, m;
+       char buf[32];
+
+       /* the highest 16 bits should be 0x0050 for a 8xx */
+
+       if ((pvr >> 16) != 0x0050)
+               return -1;
+
+       k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]);
+       m = 0;
+
+       switch (k) {
+       case 0x20020001:
+               printf ("XPC850xxZT");
+               break;
+       case 0x21000065:
+               printf ("XPC850xxZTA");
+               break;
+       case 0x21010067:
+               printf ("XPC850xxZTB");
+               m = 1;
+               break;
+       case 0x21020068:
+               printf ("XPC850xxZTC");
+               m = 1;
+               break;
+       default:
+               printf ("unknown MPC850 (0x%08x)", k);
+       }
+       printf (" at %s MHz:", strmhz (buf, clock));
+
+       printf (" %u kB I-Cache", checkicache () >> 10);
+       printf (" %u kB D-Cache", checkdcache () >> 10);
+
+       /* lets check and see if we're running on a 850T (or P?) */
+
+       immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+       if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+               printf (" FEC present");
+       }
+
+       if (!m) {
+               puts (cpu_warning);
+       }
+
+       putc ('\n');
+
+       return 0;
+}
+#else
+#error CPU undefined
+#endif
+/* ------------------------------------------------------------------------- */
+
+int checkcpu (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       ulong clock = gd->cpu_clk;
+       uint immr = get_immr (0);       /* Return full IMMR contents */
+       uint pvr = get_pvr ();
+
+       puts ("CPU:   ");
+
+       /* 850 has PARTNUM 20 */
+       /* 801 has PARTNUM 10 */
+       return check_CPU (clock, pvr, immr);
+}
+
+/* ------------------------------------------------------------------------- */
+/* L1 i-cache                                                                */
+/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB)              */
+/* the 860 P (plus) has 256 sets of 16 bytes in 4 ways (= 16 kB)             */
+
+int checkicache (void)
+{
+       volatile immap_t *immap = (immap_t *) CFG_IMMR;
+       volatile memctl8xx_t *memctl = &immap->im_memctl;
+       u32 cacheon = rd_ic_cst () & IDC_ENABLED;
+
+#ifdef CONFIG_IP860
+       u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */
+#else
+       u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */
+#endif
+       u32 m;
+       u32 lines = -1;
+
+       wr_ic_cst (IDC_UNALL);
+       wr_ic_cst (IDC_INVALL);
+       wr_ic_cst (IDC_DISABLE);
+       __asm__ volatile ("isync");
+
+       while (!((m = rd_ic_cst ()) & IDC_CERR2)) {
+               wr_ic_adr (k);
+               wr_ic_cst (IDC_LDLCK);
+               __asm__ volatile ("isync");
+
+               lines++;
+               k += 0x10;                              /* the number of bytes in a cacheline */
+       }
+
+       wr_ic_cst (IDC_UNALL);
+       wr_ic_cst (IDC_INVALL);
+
+       if (cacheon)
+               wr_ic_cst (IDC_ENABLE);
+       else
+               wr_ic_cst (IDC_DISABLE);
+
+       __asm__ volatile ("isync");
+
+       return lines << 4;
+};
+
+/* ------------------------------------------------------------------------- */
+/* L1 d-cache                                                                */
+/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB)              */
+/* the 860 P (plus) has 256 sets of 16 bytes in 2 ways (= 8 kB)              */
+/* call with cache disabled                                                  */
+
+int checkdcache (void)
+{
+       volatile immap_t *immap = (immap_t *) CFG_IMMR;
+       volatile memctl8xx_t *memctl = &immap->im_memctl;
+       u32 cacheon = rd_dc_cst () & IDC_ENABLED;
+
+#ifdef CONFIG_IP860
+       u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */
+#else
+       u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */
+#endif
+       u32 m;
+       u32 lines = -1;
+
+       wr_dc_cst (IDC_UNALL);
+       wr_dc_cst (IDC_INVALL);
+       wr_dc_cst (IDC_DISABLE);
+
+       while (!((m = rd_dc_cst ()) & IDC_CERR2)) {
+               wr_dc_adr (k);
+               wr_dc_cst (IDC_LDLCK);
+               lines++;
+               k += 0x10;      /* the number of bytes in a cacheline */
+       }
+
+       wr_dc_cst (IDC_UNALL);
+       wr_dc_cst (IDC_INVALL);
+
+       if (cacheon)
+               wr_dc_cst (IDC_ENABLE);
+       else
+               wr_dc_cst (IDC_DISABLE);
+
+       return lines << 4;
+};
+
+/* ------------------------------------------------------------------------- */
+
+void upmconfig (uint upm, uint * table, uint size)
+{
+       uint i;
+       uint addr = 0;
+       volatile immap_t *immap = (immap_t *) CFG_IMMR;
+       volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+       for (i = 0; i < size; i++) {
+               memctl->memc_mdr = table[i];    /* (16-15) */
+               memctl->memc_mcr = addr | upm;  /* (16-16) */
+               addr++;
+       }
+}
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc,
+                         char *argv[])
+{
+       ulong msr, addr;
+
+       volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+       immap->im_clkrst.car_plprcr |= PLPRCR_CSR;      /* Checkstop Reset enable */
+
+       /* Interrupts and MMU off */
+       __asm__ volatile ("mtspr    81, 0");
+       __asm__ volatile ("mfmsr    %0":"=r" (msr));
+
+       msr &= ~0x1030;
+       __asm__ volatile ("mtmsr    %0"::"r" (msr));
+
+       /*
+        * Trying to execute the next instruction at a non-existing address
+        * should cause a machine check, resulting in reset
+        */
+#ifdef CFG_RESET_ADDRESS
+       addr = CFG_RESET_ADDRESS;
+#else
+       /*
+        * note: when CFG_MONITOR_BASE points to a RAM address, CFG_MONITOR_BASE
+        * - sizeof (ulong) is usually a valid address. Better pick an address
+        * known to be invalid on your system and assign it to CFG_RESET_ADDRESS.
+        * "(ulong)-1" used to be a good choice for many systems...
+        */
+       addr = CFG_MONITOR_BASE - sizeof (ulong);
+#endif
+       ((void (*)(void)) addr) ();
+       return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ * See table 15-5 pp. 15-16, and SCCR[RTSEL] pp. 15-27.
+ */
+unsigned long get_tbclk (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       volatile immap_t *immr = (volatile immap_t *) CFG_IMMR;
+       ulong oscclk, factor;
+
+       if (immr->im_clkrst.car_sccr & SCCR_TBS) {
+               return (gd->cpu_clk / 16);
+       }
+
+       factor = (((CFG_PLPRCR) & PLPRCR_MF_MSK) >> PLPRCR_MF_SHIFT) + 1;
+
+       oscclk = gd->cpu_clk / factor;
+
+       if ((immr->im_clkrst.car_sccr & SCCR_RTSEL) == 0 || factor > 2) {
+               return (oscclk / 4);
+       }
+       return (oscclk / 16);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+       int re_enable = disable_interrupts ();
+
+       reset_8xx_watchdog ((immap_t *) CFG_IMMR);
+       if (re_enable)
+               enable_interrupts ();
+}
+
+void reset_8xx_watchdog (volatile immap_t * immr)
+{
+# if defined(CONFIG_LWMON)
+       /*
+        * The LWMON board uses a MAX6301 Watchdog
+        * with the trigger pin connected to port PA.7
+        *
+        * (The old board version used a MAX706TESA Watchdog, which
+        * had to be handled exactly the same.)
+        */
+# define WATCHDOG_BIT  0x0100
+       immr->im_ioport.iop_papar &= ~(WATCHDOG_BIT);   /* GPIO     */
+       immr->im_ioport.iop_padir |= WATCHDOG_BIT;      /* Output   */
+       immr->im_ioport.iop_paodr &= ~(WATCHDOG_BIT);   /* active output */
+
+       immr->im_ioport.iop_padat ^= WATCHDOG_BIT;      /* Toggle WDI   */
+# else
+       /*
+        * All other boards use the MPC8xx Internal Watchdog
+        */
+       immr->im_siu_conf.sc_swsr = 0x556c;     /* write magic1 */
+       immr->im_siu_conf.sc_swsr = 0xaa39;     /* write magic2 */
+# endif /* CONFIG_LWMON */
+}
+
+#endif /* CONFIG_WATCHDOG */
+
+/* ------------------------------------------------------------------------- */
diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c
new file mode 100644 (file)
index 0000000..d43dcaa
--- /dev/null
@@ -0,0 +1,710 @@
+/*
+ * (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 <malloc.h>
+#include <commproc.h>
+#include <net.h>
+#include <command.h>
+
+#undef ET_DEBUG
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET)
+
+#ifdef CFG_DISCOVER_PHY
+#include <miiphy.h>
+static void mii_discover_phy(void);
+#endif
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH  1520
+
+#define TX_BUF_CNT 2
+
+#define TOUT_LOOP 100
+
+#define PKT_MAXBUF_SIZE                1518
+#define PKT_MINBUF_SIZE                64
+#define PKT_MAXBLR_SIZE                1520
+
+
+static char txbuf[DBUF_LENGTH];
+
+static uint rxIdx;     /* index of the current RX buffer */
+static uint txIdx;     /* index of the current TX buffer */
+
+/*
+  * FEC Ethernet Tx and Rx buffer descriptors allocated at the
+  *  immr->udata_bd address on Dual-Port RAM
+  * Provide for Double Buffering
+  */
+
+typedef volatile struct CommonBufferDescriptor {
+    cbd_t rxbd[PKTBUFSRX];             /* Rx BD */
+    cbd_t txbd[TX_BUF_CNT];            /* Tx BD */
+} RTXBD;
+
+static RTXBD *rtx = NULL;
+
+static int fec_send(struct eth_device* dev, volatile void *packet, int length);
+static int fec_recv(struct eth_device* dev);
+static int fec_init(struct eth_device* dev, bd_t * bd);
+static void fec_halt(struct eth_device* dev);
+
+int fec_initialize(bd_t *bis)
+{
+       struct eth_device* dev;
+
+       dev = (struct eth_device*) malloc(sizeof *dev);
+
+       sprintf(dev->name, "FEC ETHERNET");
+       dev->iobase = 0;
+       dev->priv   = 0;
+       dev->init   = fec_init;
+       dev->halt   = fec_halt;
+       dev->send   = fec_send;
+       dev->recv   = fec_recv;
+
+       eth_register(dev);
+
+       return 1;
+}
+
+static int fec_send(struct eth_device* dev, volatile void *packet, int length)
+{
+       int j, rc;
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+       volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
+
+       /* section 16.9.23.3
+        * Wait for ready
+        */
+       j = 0;
+       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+               udelay(1);
+               j++;
+       }
+       if (j>=TOUT_LOOP) {
+               printf("TX not ready\n");
+       }
+
+       rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
+       rtx->txbd[txIdx].cbd_datlen  = length;
+       rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST;
+       __asm__ ("eieio");
+
+       /* Activate transmit Buffer Descriptor polling */
+       fecp->fec_x_des_active = 0x01000000;    /* Descriptor polling active    */
+
+       j = 0;
+       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+#if defined(CONFIG_ICU862)
+               udelay(10);
+#else
+               udelay(1);
+#endif
+               j++;
+       }
+       if (j>=TOUT_LOOP) {
+               printf("TX timeout\n");
+       }
+#ifdef ET_DEBUG
+       printf("%s[%d] %s: cycles: %d    status: %x  retry cnt: %d\n",
+       __FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc,
+       (rtx->txbd[txIdx].cbd_sc & 0x003C)>>2);
+#endif
+       /* return only status bits */;
+       rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS);
+
+       txIdx = (txIdx + 1) % TX_BUF_CNT;
+
+       return rc;
+}
+
+static int fec_recv(struct eth_device* dev)
+{
+       int length;
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+       volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
+
+   for (;;) {
+       /* section 16.9.23.2 */
+       if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+               length = -1;
+               break;     /* nothing received - leave for() loop */
+       }
+
+       length = rtx->rxbd[rxIdx].cbd_datlen;
+
+       if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
+#ifdef ET_DEBUG
+               printf("%s[%d] err: %x\n",
+               __FUNCTION__,__LINE__,rtx->rxbd[rxIdx].cbd_sc);
+#endif
+       } else {
+               /* Pass the packet up to the protocol layers. */
+               NetReceive(NetRxPackets[rxIdx], length - 4);
+       }
+
+       /* Give the buffer back to the FEC. */
+       rtx->rxbd[rxIdx].cbd_datlen = 0;
+
+       /* wrap around buffer index when necessary */
+       if ((rxIdx + 1) >= PKTBUFSRX) {
+               rtx->rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+               rxIdx = 0;
+       } else {
+               rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+               rxIdx++;
+       }
+
+       __asm__ ("eieio");
+
+       /* Try to fill Buffer Descriptors */
+       fecp->fec_r_des_active = 0x01000000;    /* Descriptor polling active    */
+   }
+
+   return length;
+}
+
+/**************************************************************
+ *
+ * FEC Ethernet Initialization Routine
+ *
+ *************************************************************/
+
+#define        FEC_ECNTRL_PINMUX       0x00000004
+#define FEC_ECNTRL_ETHER_EN    0x00000002
+#define FEC_ECNTRL_RESET       0x00000001
+
+#define FEC_RCNTRL_BC_REJ      0x00000010
+#define FEC_RCNTRL_PROM                0x00000008
+#define FEC_RCNTRL_MII_MODE    0x00000004
+#define FEC_RCNTRL_DRT         0x00000002
+#define FEC_RCNTRL_LOOP                0x00000001
+
+#define FEC_TCNTRL_FDEN                0x00000004
+#define FEC_TCNTRL_HBC         0x00000002
+#define FEC_TCNTRL_GTS         0x00000001
+
+#define        FEC_RESET_DELAY         50
+
+static int fec_init(struct eth_device* dev, bd_t * bd)
+{
+
+       int i;
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+       volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
+
+#if defined(CONFIG_FADS) && defined(CONFIG_MPC860T)
+       /* configure FADS for fast (FEC) ethernet, half-duplex */
+       /* The LXT970 needs about 50ms to recover from reset, so
+        * wait for it by discovering the PHY before leaving eth_init().
+        */
+       {
+               volatile uint *bcsr4 = (volatile uint *) BCSR4;
+               *bcsr4 = (*bcsr4 & ~(BCSR4_FETH_EN | BCSR4_FETHCFG1))
+                       | (BCSR4_FETHCFG0 | BCSR4_FETHFDE | BCSR4_FETHRST);
+
+               /* reset the LXT970 PHY */
+               *bcsr4 &= ~BCSR4_FETHRST;
+               udelay (10);
+               *bcsr4 |= BCSR4_FETHRST;
+               udelay (10);
+       }
+#endif
+       /* Whack a reset.
+        * A delay is required between a reset of the FEC block and
+        * initialization of other FEC registers because the reset takes
+        * some time to complete. If you don't delay, subsequent writes
+        * to FEC registers might get killed by the reset routine which is
+        * still in progress.
+        */
+       fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+       for (i = 0;
+            (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+            ++i) {
+               udelay (1);
+       }
+       if (i == FEC_RESET_DELAY) {
+               printf ("FEC_RESET_DELAY timeout\n");
+               return 0;
+       }
+
+       /* We use strictly polling mode only
+        */
+       fecp->fec_imask = 0;
+
+       /* Clear any pending interrupt
+        */
+       fecp->fec_ievent = 0xffc0;
+
+       /* No need to set the IVEC register */
+
+       /* Set station address
+        */
+#define ea eth_get_dev()->enetaddr
+       fecp->fec_addr_low   =  (ea[0] << 24) | (ea[1] << 16) |
+                               (ea[2] <<  8) | (ea[3]      ) ;
+       fecp->fec_addr_high  =  (ea[4] <<  8) | (ea[5]      ) ;
+#undef ea
+
+       /* Clear multicast address hash table
+        */
+       fecp->fec_hash_table_high = 0;
+       fecp->fec_hash_table_low  = 0;
+
+       /* Set maximum receive buffer size.
+        */
+       fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
+
+       /* Set maximum frame length
+        */
+       fecp->fec_r_hash = PKT_MAXBUF_SIZE;
+
+       /*
+        * Setup Buffers and Buffer Desriptors
+        */
+       rxIdx = 0;
+       txIdx = 0;
+
+       if (!rtx) {
+#ifdef CFG_ALLOC_DPRAM
+           rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + dpram_alloc_align(sizeof(RTXBD),8));
+#else
+           rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);
+#endif
+       }
+       /*
+        * Setup Receiver Buffer Descriptors (13.14.24.18)
+        * Settings:
+        *     Empty, Wrap
+        */
+       for (i = 0; i < PKTBUFSRX; i++) {
+               rtx->rxbd[i].cbd_sc      = BD_ENET_RX_EMPTY;
+               rtx->rxbd[i].cbd_datlen  = 0;   /* Reset */
+               rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
+       }
+       rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+       /*
+        * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
+        * Settings:
+        *    Last, Tx CRC
+        */
+       for (i = 0; i < TX_BUF_CNT; i++) {
+               rtx->txbd[i].cbd_sc      = BD_ENET_TX_LAST | BD_ENET_TX_TC;
+               rtx->txbd[i].cbd_datlen  = 0;   /* Reset */
+               rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
+       }
+       rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+       /* Set receive and transmit descriptor base
+        */
+       fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]);
+       fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]);
+
+       /* Enable MII mode
+        */
+#if 0  /* Full duplex mode */
+       fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE;
+       fecp->fec_x_cntrl = FEC_TCNTRL_FDEN;
+#else  /* Half duplex mode */
+       fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT;
+       fecp->fec_x_cntrl = 0;
+#endif
+
+       /* Enable big endian and don't care about SDMA FC.
+        */
+       fecp->fec_fun_code = 0x78000000;
+
+       /* Set MII speed to 2.5 MHz or slightly below.
+        * According to the MPC860T (Rev. D) Fast ethernet controller user
+        * manual (6.2.14),
+        * the MII management interface clock must be less than or equal
+        * to 2.5 MHz.
+        * This MDC frequency is equal to system clock / (2 * MII_SPEED).
+        * Then MII_SPEED = system_clock / 2 * 2,5 Mhz.
+        */
+       fecp->fec_mii_speed = ((bd->bi_busfreq + 4999999) / 5000000) << 1;
+
+#if !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210)
+       /* Configure all of port D for MII.
+        */
+       immr->im_ioport.iop_pdpar = 0x1fff;
+
+       /* Bits moved from Rev. D onward */
+       if ((get_immr (0) & 0xffff) < 0x0501) {
+               immr->im_ioport.iop_pddir = 0x1c58;     /* Pre rev. D */
+       } else {
+               immr->im_ioport.iop_pddir = 0x1fff;     /* Rev. D and later */
+       }
+#else
+       /* Configure port A for MII.
+       */
+
+#if defined(CONFIG_ICU862) && defined(CFG_DISCOVER_PHY)
+
+       /* On the ICU862 board the MII-MDC pin is routed to PD8 pin
+        * of CPU, so for this board we need to configure Utopia and
+        * enable PD8 to MII-MDC function */
+       immr->im_ioport.iop_pdpar |= 0x4080;
+#endif
+
+       /* Has Utopia been configured? */
+       if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) {
+               /*
+                * YES - Use MUXED mode for UTOPIA bus.
+                * This frees Port A for use by MII (see 862UM table 41-6).
+                */
+               immr->im_ioport.utmode &= ~0x80;
+       } else {
+               /*
+                * NO - set SPLIT mode for UTOPIA bus.
+                *
+                * This doesn't really effect UTOPIA (which isn't
+                * enabled anyway) but just tells the 862
+                * to use port A for MII (see 862UM table 41-6).
+                */
+               immr->im_ioport.utmode |= 0x80;
+       }
+#endif /* !defined(CONFIG_ICU862) */
+
+       rxIdx = 0;
+       txIdx = 0;
+
+       /* Now enable the transmit and receive processing
+        */
+       fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
+
+#ifdef CFG_DISCOVER_PHY
+       /* wait for the PHY to wake up after reset
+        */
+       mii_discover_phy();
+#endif
+
+       /* And last, try to fill Rx Buffer Descriptors */
+       fecp->fec_r_des_active = 0x01000000;    /* Descriptor polling active    */
+
+       return 1;
+}
+
+
+
+static void fec_halt(struct eth_device* dev)
+{
+#if 0
+    volatile immap_t *immr = (immap_t *)CFG_IMMR;
+    immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+}
+
+#if 0
+void restart(void)
+{
+   volatile immap_t *immr = (immap_t *)CFG_IMMR;
+   immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+}
+#endif
+
+#if defined(CFG_DISCOVER_PHY) || (CONFIG_COMMANDS & CFG_CMD_MII)
+
+static int     phyaddr = -1;   /* didn't find a PHY yet */
+static uint    phytype;
+
+/* Make MII read/write commands for the FEC.
+*/
+
+#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \
+                                               (REG & 0x1f) << 18))
+
+#define mk_mii_write(ADDR, REG, VAL)   (0x50020000 | ((ADDR << 23) | \
+                                               (REG & 0x1f) << 18) | \
+                                               (VAL & 0xffff))
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR ((uint)0x80000000)      /* Heartbeat error */
+#define FEC_ENET_BABR  ((uint)0x40000000)      /* Babbling receiver */
+#define FEC_ENET_BABT  ((uint)0x20000000)      /* Babbling transmitter */
+#define FEC_ENET_GRA   ((uint)0x10000000)      /* Graceful stop complete */
+#define FEC_ENET_TXF   ((uint)0x08000000)      /* Full frame transmitted */
+#define FEC_ENET_TXB   ((uint)0x04000000)      /* A buffer was transmitted */
+#define FEC_ENET_RXF   ((uint)0x02000000)      /* Full frame received */
+#define FEC_ENET_RXB   ((uint)0x01000000)      /* A buffer was received */
+#define FEC_ENET_MII   ((uint)0x00800000)      /* MII interrupt */
+#define FEC_ENET_EBERR ((uint)0x00400000)      /* SDMA bus error */
+
+/* PHY identification
+ */
+#define PHY_ID_LXT970          0x78100000      /* LXT970 */
+#define PHY_ID_LXT971          0x001378e0      /* LXT971 and 972 */
+#define PHY_ID_82555           0x02a80150      /* Intel 82555 */
+#define PHY_ID_QS6612          0x01814400      /* QS6612 */
+#define PHY_ID_AMD79C784       0x00225610      /* AMD 79C784 */
+#define PHY_ID_LSI80225                0x0016f870      /* LSI 80225 */
+#define PHY_ID_LSI80225B       0x0016f880      /* LSI 80225/B */
+
+
+/* send command to phy using mii, wait for result */
+static uint
+mii_send(uint mii_cmd)
+{
+       uint mii_reply;
+       volatile fec_t  *ep;
+
+       ep = &(((immap_t *)CFG_IMMR)->im_cpm.cp_fec);
+
+       ep->fec_mii_data = mii_cmd;     /* command to phy */
+
+       /* wait for mii complete */
+       while (!(ep->fec_ievent & FEC_ENET_MII))
+               ;       /* spin until done */
+       mii_reply = ep->fec_mii_data;           /* result from phy */
+       ep->fec_ievent = FEC_ENET_MII;          /* clear MII complete */
+#if 0
+       printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",
+               __FILE__,__LINE__,__FUNCTION__,mii_cmd,mii_reply);
+#endif
+       return (mii_reply & 0xffff);            /* data read from phy */
+}
+#endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CFG_CMD_MII) */
+
+#if defined(CFG_DISCOVER_PHY)
+static void
+mii_discover_phy(void)
+{
+#define MAX_PHY_PASSES 11
+       uint phyno;
+       int  pass;
+
+       phyaddr = -1;   /* didn't find a PHY yet */
+       for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
+               if (pass > 1) {
+                       /* PHY may need more time to recover from reset.
+                        * The LXT970 needs 50ms typical, no maximum is
+                        * specified, so wait 10ms before try again.
+                        * With 11 passes this gives it 100ms to wake up.
+                        */
+                       udelay(10000);  /* wait 10ms */
+               }
+               for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
+                       phytype = mii_send(mk_mii_read(phyno, PHY_PHYIDR1));
+#ifdef ET_DEBUG
+                       printf("PHY type 0x%x pass %d type ", phytype, pass);
+#endif
+                       if (phytype != 0xffff) {
+                               phyaddr = phyno;
+                               phytype <<= 16;
+                               phytype |= mii_send(mk_mii_read(phyno,
+                                                               PHY_PHYIDR2));
+
+#ifdef ET_DEBUG
+                               printf("PHY @ 0x%x pass %d type ",phyno,pass);
+                               switch (phytype & 0xfffffff0) {
+                               case PHY_ID_LXT970:
+                                       printf("LXT970\n");
+                                       break;
+                               case PHY_ID_LXT971:
+                                       printf("LXT971\n");
+                                       break;
+                               case PHY_ID_82555:
+                                       printf("82555\n");
+                                       break;
+                               case PHY_ID_QS6612:
+                                       printf("QS6612\n");
+                                       break;
+                               case PHY_ID_AMD79C784:
+                                       printf("AMD79C784\n");
+                                       break;
+                               case PHY_ID_LSI80225B:
+                                       printf("LSI L80225/B\n");
+                                       break;
+                               default:
+                                       printf("0x%08x\n", phytype);
+                                       break;
+                               }
+#endif
+                       }
+               }
+       }
+       if (phyaddr < 0) {
+               printf("No PHY device found.\n");
+       }
+}
+#endif /* CFG_DISCOVER_PHY */
+
+#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)
+
+static int mii_init_done = 0;
+
+/****************************************************************************
+ * mii_init -- Initialize the MII for MII command without ethernet
+ * This function is a subset of eth_init
+ ****************************************************************************
+ */
+void mii_init (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+       bd_t *bd = gd->bd;
+
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+       volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
+       int i;
+
+       if (mii_init_done != 0) {
+               return;
+       }
+
+       /* Whack a reset.
+        * A delay is required between a reset of the FEC block and
+        * initialization of other FEC registers because the reset takes
+        * some time to complete. If you don't delay, subsequent writes
+        * to FEC registers might get killed by the reset routine which is
+        * still in progress.
+        */
+
+       fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+       for (i = 0;
+            (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+            ++i) {
+               udelay (1);
+       }
+       if (i == FEC_RESET_DELAY) {
+               printf ("FEC_RESET_DELAY timeout\n");
+               return;
+       }
+
+       /* We use strictly polling mode only
+        */
+       fecp->fec_imask = 0;
+
+       /* Clear any pending interrupt
+        */
+       fecp->fec_ievent = 0xffc0;
+
+       /* Set MII speed to 2.5 MHz or slightly below.
+        * According to the MPC860T (Rev. D) Fast ethernet controller user
+        * manual (6.2.14),
+        * the MII management interface clock must be less than or equal
+        * to 2.5 MHz.
+        * This MDC frequency is equal to system clock / (2 * MII_SPEED).
+        * Then MII_SPEED = system_clock / 2 * 2,5 Mhz.
+        */
+       fecp->fec_mii_speed = ((bd->bi_busfreq + 4999999) / 5000000) << 1;
+
+#if !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210)
+       /* Configure all of port D for MII.
+        */
+       immr->im_ioport.iop_pdpar = 0x1fff;
+
+       /* Bits moved from Rev. D onward */
+       if ((get_immr (0) & 0xffff) < 0x0501) {
+               immr->im_ioport.iop_pddir = 0x1c58;     /* Pre rev. D */
+       } else {
+               immr->im_ioport.iop_pddir = 0x1fff;     /* Rev. D and later */
+       }
+#else
+       /* Configure port A for MII.
+       */
+
+#if defined(CONFIG_ICU862)
+
+       /* On the ICU862 board the MII-MDC pin is routed to PD8 pin
+        * of CPU, so for this board we need to configure Utopia and
+        * enable PD8 to MII-MDC function */
+       immr->im_ioport.iop_pdpar |= 0x4080;
+#endif
+
+       /* Has Utopia been configured? */
+       if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) {
+               /*
+                * YES - Use MUXED mode for UTOPIA bus.
+                * This frees Port A for use by MII (see 862UM table 41-6).
+                */
+               immr->im_ioport.utmode &= ~0x80;
+       } else {
+               /*
+                * NO - set SPLIT mode for UTOPIA bus.
+                *
+                * This doesn't really effect UTOPIA (which isn't
+                * enabled anyway) but just tells the 862
+                * to use port A for MII (see 862UM table 41-6).
+                */
+               immr->im_ioport.utmode |= 0x80;
+       }
+#endif /* !defined(CONFIG_ICU862) */
+       /* Now enable the transmit and receive processing
+        */
+       fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
+
+       mii_init_done = 1;
+}
+/*****************************************************************************
+ * Read and write a MII PHY register, routines used by MII Utilities
+ *
+ * FIXME: These routines are expected to return 0 on success, but mii_send
+ *       does _not_ return an error code. Maybe 0xFFFF means error, i.e.
+ *       no PHY connected...
+ *       For now always return 0.
+ * FIXME: These routines only work after calling eth_init() at least once!
+ *       Otherwise they hang in mii_send() !!! Sorry!
+ *****************************************************************************/
+
+int miiphy_read(unsigned char addr, unsigned char  reg, unsigned short *value)
+{
+       short rdreg;    /* register working value */
+
+#ifdef MII_DEBUG
+       printf ("miiphy_read(0x%x) @ 0x%x = ", reg, addr);
+#endif
+       rdreg = mii_send(mk_mii_read(addr, reg));
+
+       *value = rdreg;
+
+#ifdef MII_DEBUG
+       printf ("0x%04x\n", *value);
+#endif
+
+       return 0;
+}
+
+int miiphy_write(unsigned char  addr, unsigned char  reg, unsigned short value)
+{
+       short rdreg;    /* register working value */
+
+#ifdef MII_DEBUG
+       printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
+#endif
+
+       rdreg = mii_send(mk_mii_write(addr, reg, value));
+
+#ifdef MII_DEBUG
+       printf ("0x%04x\n", value);
+#endif
+
+       return 0;
+}
+#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)*/
+
+#endif /* CFG_CMD_NET, FEC_ENET */
diff --git a/cpu/mpc8xx/spi.c b/cpu/mpc8xx/spi.c
new file mode 100644 (file)
index 0000000..f04d88e
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * Copyright (c) 2001 Navin Boppuri / Prashant Patel
+ *     <nboppuri@trinetcommunication.com>,
+ *     <pmpatel@trinetcommunication.com>
+ * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de>
+ * Copyright (c) 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
+ */
+
+/*
+ * MPC8xx CPM SPI interface.
+ *
+ * Parts of this code are probably not portable and/or specific to
+ * the board which I used for the tests. Please send fixes/complaints
+ * to wd@denx.de
+ *
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <commproc.h>
+#include <linux/ctype.h>
+#include <malloc.h>
+#include <post.h>
+#include <net.h>
+
+#if (defined(CONFIG_SPI)) || (CONFIG_POST & CFG_POST_SPI)
+
+/* Warning:
+ * You cannot enable DEBUG for early system initalization, i. e. when
+ * this driver is used to read environment parameters like "baudrate"
+ * from EEPROM which are used to initialize the serial port which is
+ * needed to print the debug messages...
+ */
+#undef DEBUG
+
+#define SPI_EEPROM_WREN                0x06
+#define SPI_EEPROM_RDSR                0x05
+#define SPI_EEPROM_READ                0x03
+#define SPI_EEPROM_WRITE       0x02
+
+/* ---------------------------------------------------------------
+ * Offset for initial SPI buffers in DPRAM:
+ * We need a 520 byte scratch DPRAM area to use at an early stage.
+ * It is used between the two initialization calls (spi_init_f()
+ * and spi_init_r()).
+ * The value 0xb00 makes it far enough from the start of the data
+ * area (as well as from the stack pointer).
+ * --------------------------------------------------------------- */
+#ifndef        CFG_SPI_INIT_OFFSET
+#define        CFG_SPI_INIT_OFFSET     0xB00
+#endif
+
+#ifdef DEBUG
+
+#define        DPRINT(a)       printf a;
+/* -----------------------------------------------
+ * Helper functions to peek into tx and rx buffers
+ * ----------------------------------------------- */
+static const char * const hex_digit = "0123456789ABCDEF";
+
+static char quickhex (int i)
+{
+       return hex_digit[i];
+}
+
+static void memdump (void *pv, int num)
+{
+       int i;
+       unsigned char *pc = (unsigned char *) pv;
+
+       for (i = 0; i < num; i++)
+               printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
+       printf ("\t");
+       for (i = 0; i < num; i++)
+               printf ("%c", isprint (pc[i]) ? pc[i] : '.');
+       printf ("\n");
+}
+#else  /* !DEBUG */
+
+#define        DPRINT(a)
+
+#endif /* DEBUG */
+
+/* -------------------
+ * Function prototypes
+ * ------------------- */
+void spi_init (void);
+
+ssize_t spi_read (uchar *, int, uchar *, int);
+ssize_t spi_write (uchar *, int, uchar *, int);
+ssize_t spi_xfer (size_t);
+
+/* -------------------
+ * Variables
+ * ------------------- */
+
+#define MAX_BUFFER     0x104
+
+/* ----------------------------------------------------------------------
+ * Initially we place the RX and TX buffers at a fixed location in DPRAM!
+ * ---------------------------------------------------------------------- */
+static uchar *rxbuf =
+  (uchar *)&((cpm8xx_t *)&((immap_t *)CFG_IMMR)->im_cpm)->cp_dpmem
+                       [CFG_SPI_INIT_OFFSET];
+static uchar *txbuf =
+  (uchar *)&((cpm8xx_t *)&((immap_t *)CFG_IMMR)->im_cpm)->cp_dpmem
+                       [CFG_SPI_INIT_OFFSET+MAX_BUFFER];
+
+/* **************************************************************************
+ *
+ *  Function:    spi_init_f
+ *
+ *  Description: Init SPI-Controller (ROM part)
+ *
+ *  return:      ---
+ *
+ * *********************************************************************** */
+void spi_init_f (void)
+{
+       unsigned int dpaddr;
+
+       volatile spi_t *spi;
+       volatile immap_t *immr;
+       volatile cpic8xx_t *cpi;
+       volatile cpm8xx_t *cp;
+       volatile iop8xx_t *iop;
+       volatile cbd_t *tbdf, *rbdf;
+
+       immr = (immap_t *)  CFG_IMMR;
+       cpi  = (cpic8xx_t *)&immr->im_cpic;
+       iop  = (iop8xx_t *) &immr->im_ioport;
+       cp   = (cpm8xx_t *) &immr->im_cpm;
+
+#ifdef CFG_SPI_UCODE_PATCH
+       spi  = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
+#else
+       spi  = (spi_t *)&cp->cp_dparam[PROFF_SPI];
+       /* Disable relocation */
+       spi->spi_rpbase = 0;
+#endif
+
+/* 1 */
+       /* ------------------------------------------------
+        * Initialize Port B SPI pins -> page 34-8 MPC860UM
+        * (we are only in Master Mode !)
+        * ------------------------------------------------ */
+
+       /* --------------------------------------------
+        * GPIO or per. Function
+        * PBPAR[28] = 1 [0x00000008] -> PERI: (SPIMISO)
+        * PBPAR[29] = 1 [0x00000004] -> PERI: (SPIMOSI)
+        * PBPAR[30] = 1 [0x00000002] -> PERI: (SPICLK)
+        * PBPAR[31] = 0 [0x00000001] -> GPIO: (CS for PCUE/CCM-EEPROM)
+        * -------------------------------------------- */
+       cp->cp_pbpar |=  0x0000000E;    /* set  bits    */
+       cp->cp_pbpar &= ~0x00000001;    /* reset bit    */
+
+       /* ----------------------------------------------
+        * In/Out or per. Function 0/1
+        * PBDIR[28] = 1 [0x00000008] -> PERI1: SPIMISO
+        * PBDIR[29] = 1 [0x00000004] -> PERI1: SPIMOSI
+        * PBDIR[30] = 1 [0x00000002] -> PERI1: SPICLK
+        * PBDIR[31] = 1 [0x00000001] -> GPIO OUT: CS for PCUE/CCM-EEPROM
+        * ---------------------------------------------- */
+       cp->cp_pbdir |= 0x0000000F;
+
+       /* ----------------------------------------------
+        * open drain or active output
+        * PBODR[28] = 1 [0x00000008] -> open drain: SPIMISO
+        * PBODR[29] = 0 [0x00000004] -> active output SPIMOSI
+        * PBODR[30] = 0 [0x00000002] -> active output: SPICLK
+        * PBODR[31] = 0 [0x00000001] -> active output: GPIO OUT: CS for PCUE/CCM
+        * ---------------------------------------------- */
+
+       cp->cp_pbodr |=  0x00000008;
+       cp->cp_pbodr &= ~0x00000007;
+
+       /* Initialize the parameter ram.
+        * We need to make sure many things are initialized to zero
+        */
+       spi->spi_rstate = 0;
+       spi->spi_rdp    = 0;
+       spi->spi_rbptr  = 0;
+       spi->spi_rbc    = 0;
+       spi->spi_rxtmp  = 0;
+       spi->spi_tstate = 0;
+       spi->spi_tdp    = 0;
+       spi->spi_tbptr  = 0;
+       spi->spi_tbc    = 0;
+       spi->spi_txtmp  = 0;
+
+       /* Allocate space for one transmit and one receive buffer
+        * descriptor in the DP ram
+        */
+#ifdef CFG_ALLOC_DPRAM
+       dpaddr = dpram_alloc_align (sizeof(cbd_t)*2, 8);
+#else
+       dpaddr = CPM_SPI_BASE;
+#endif
+
+/* 3 */
+       /* Set up the SPI parameters in the parameter ram */
+       spi->spi_rbase = dpaddr;
+       spi->spi_tbase = dpaddr + sizeof (cbd_t);
+
+       /***********IMPORTANT******************/
+
+        /*
+         * Setting transmit and receive buffer descriptor pointers
+         * initially to rbase and tbase. Only the microcode patches
+         * documentation talks about initializing this pointer. This
+         * is missing from the sample I2C driver. If you dont
+         * initialize these pointers, the kernel hangs.
+        */
+       spi->spi_rbptr = spi->spi_rbase;
+       spi->spi_tbptr = spi->spi_tbase;
+
+/* 4 */
+#ifdef CFG_SPI_UCODE_PATCH
+       /*
+        *  Initialize required parameters if using microcode patch.
+        */
+       spi->spi_rstate = 0;
+       spi->spi_tstate = 0;
+#else
+       /* Init SPI Tx + Rx Parameters */
+       while (cp->cp_cpcr & CPM_CR_FLG)
+               ;
+       cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SPI, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+       while (cp->cp_cpcr & CPM_CR_FLG)
+               ;
+#endif /* CFG_SPI_UCODE_PATCH */
+
+/* 5 */
+       /* Set SDMA configuration register */
+       immr->im_siu_conf.sc_sdcr = 0x0001;
+
+/* 6 */
+       /* Set to big endian. */
+       spi->spi_tfcr = SMC_EB;
+       spi->spi_rfcr = SMC_EB;
+
+/* 7 */
+       /* Set maximum receive size. */
+       spi->spi_mrblr = MAX_BUFFER;
+
+/* 8 + 9 */
+       /* tx and rx buffer descriptors */
+       tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
+       rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
+
+       tbdf->cbd_sc &= ~BD_SC_READY;
+       rbdf->cbd_sc &= ~BD_SC_EMPTY;
+
+       /* Set the bd's rx and tx buffer address pointers */
+       rbdf->cbd_bufaddr = (ulong) rxbuf;
+       tbdf->cbd_bufaddr = (ulong) txbuf;
+
+/* 10 + 11 */
+       cp->cp_spim = 0;                        /* Mask  all SPI events */
+       cp->cp_spie = SPI_EMASK;                /* Clear all SPI events */
+
+       return;
+}
+
+/* **************************************************************************
+ *
+ *  Function:    spi_init_r
+ *
+ *  Description: Init SPI-Controller (RAM part) -
+ *              The malloc engine is ready and we can move our buffers to
+ *              normal RAM
+ *
+ *  return:      ---
+ *
+ * *********************************************************************** */
+void spi_init_r (void)
+{
+       volatile cpm8xx_t *cp;
+       volatile spi_t *spi;
+       volatile immap_t *immr;
+       volatile cbd_t *tbdf, *rbdf;
+
+       immr = (immap_t *)  CFG_IMMR;
+       cp   = (cpm8xx_t *) &immr->im_cpm;
+
+#ifdef CFG_SPI_UCODE_PATCH
+       spi  = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
+#else
+       spi  = (spi_t *)&cp->cp_dparam[PROFF_SPI];
+       /* Disable relocation */
+       spi->spi_rpbase = 0;
+#endif
+
+       /* tx and rx buffer descriptors */
+       tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
+       rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
+
+       /* Allocate memory for RX and TX buffers */
+       rxbuf = (uchar *) malloc (MAX_BUFFER);
+       txbuf = (uchar *) malloc (MAX_BUFFER);
+
+       rbdf->cbd_bufaddr = (ulong) rxbuf;
+       tbdf->cbd_bufaddr = (ulong) txbuf;
+
+       return;
+}
+
+/****************************************************************************
+ *  Function:    spi_write
+ **************************************************************************** */
+ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+       int i;
+
+       memset(rxbuf, 0, MAX_BUFFER);
+       memset(txbuf, 0, MAX_BUFFER);
+       *txbuf = SPI_EEPROM_WREN;               /* write enable         */
+       spi_xfer(1);
+       memcpy(txbuf, addr, alen);
+       *txbuf = SPI_EEPROM_WRITE;              /* WRITE memory array   */
+       memcpy(alen + txbuf, buffer, len);
+       spi_xfer(alen + len);
+                                               /* ignore received data */
+       for (i = 0; i < 1000; i++) {
+               *txbuf = SPI_EEPROM_RDSR;       /* read status          */
+               txbuf[1] = 0;
+               spi_xfer(2);
+               if (!(rxbuf[1] & 1)) {
+                       break;
+               }
+               udelay(1000);
+       }
+       if (i >= 1000) {
+               printf ("*** spi_write: Time out while writing!\n");
+       }
+
+       return len;
+}
+
+/****************************************************************************
+ *  Function:    spi_read
+ **************************************************************************** */
+ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+       memset(rxbuf, 0, MAX_BUFFER);
+       memset(txbuf, 0, MAX_BUFFER);
+       memcpy(txbuf, addr, alen);
+       *txbuf = SPI_EEPROM_READ;               /* READ memory array    */
+
+       /*
+        * There is a bug in 860T (?) that cuts the last byte of input
+        * if we're reading into DPRAM. The solution we choose here is
+        * to always read len+1 bytes (we have one extra byte at the
+        * end of the buffer).
+        */
+       spi_xfer(alen + len + 1);
+       memcpy(buffer, alen + rxbuf, len);
+
+       return len;
+}
+
+/****************************************************************************
+ *  Function:    spi_xfer
+ **************************************************************************** */
+ssize_t spi_xfer (size_t count)
+{
+       volatile immap_t *immr;
+       volatile cpm8xx_t *cp;
+       volatile spi_t *spi;
+       cbd_t *tbdf, *rbdf;
+       ushort loop;
+       int tm;
+
+       DPRINT (("*** spi_xfer entered ***\n"));
+
+       immr = (immap_t *) CFG_IMMR;
+       cp   = (cpm8xx_t *) &immr->im_cpm;
+
+#ifdef CFG_SPI_UCODE_PATCH
+       spi  = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
+#else
+       spi  = (spi_t *)&cp->cp_dparam[PROFF_SPI];
+       /* Disable relocation */
+       spi->spi_rpbase = 0;
+#endif
+
+       tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
+       rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
+
+       /* Set CS for device */
+       cp->cp_pbdat &= ~0x0001;
+
+       /* Setting tx bd status and data length */
+       tbdf->cbd_sc  = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP;
+       tbdf->cbd_datlen = count;
+
+       DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n",
+                                                       tbdf->cbd_datlen));
+
+       /* Setting rx bd status and data length */
+       rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+       rbdf->cbd_datlen = 0;    /* rx length has no significance */
+
+       loop = cp->cp_spmode & SPMODE_LOOP;
+       cp->cp_spmode = /*SPMODE_DIV16  |*/     /* BRG/16 mode not used here */
+                       loop            |
+                       SPMODE_REV      |
+                       SPMODE_MSTR     |
+                       SPMODE_EN       |
+                       SPMODE_LEN(8)   |       /* 8 Bits per char */
+                       SPMODE_PM(0x8) ;        /* medium speed */
+       cp->cp_spim = 0;                        /* Mask  all SPI events */
+       cp->cp_spie = SPI_EMASK;                /* Clear all SPI events */
+
+       /* start spi transfer */
+       DPRINT (("*** spi_xfer: Performing transfer ...\n"));
+       cp->cp_spcom |= SPI_STR;                /* Start transmit */
+
+       /* --------------------------------
+        * Wait for SPI transmit to get out
+        * or time out (1 second = 1000 ms)
+        * -------------------------------- */
+       for (tm=0; tm<1000; ++tm) {
+               if (cp->cp_spie & SPI_TXB) {    /* Tx Buffer Empty */
+                       DPRINT (("*** spi_xfer: Tx buffer empty\n"));
+                       break;
+               }
+               if ((tbdf->cbd_sc & BD_SC_READY) == 0) {
+                       DPRINT (("*** spi_xfer: Tx BD done\n"));
+                       break;
+               }
+               udelay (1000);
+       }
+       if (tm >= 1000) {
+               printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
+       }
+       DPRINT (("*** spi_xfer: ... transfer ended\n"));
+
+#ifdef DEBUG
+       printf ("\nspi_xfer: txbuf after xfer\n");
+       memdump ((void *) txbuf, 16);   /* dump of txbuf before transmit */
+       printf ("spi_xfer: rxbuf after xfer\n");
+       memdump ((void *) rxbuf, 16);   /* dump of rxbuf after transmit */
+       printf ("\n");
+#endif
+
+       /* Clear CS for device */
+       cp->cp_pbdat |= 0x0001;
+
+       return count;
+}
+#endif /* CONFIG_SPI || (CONFIG_POST & CFG_POST_SPI) */
+
+/*
+ * SPI test
+ *
+ * The Serial Peripheral Interface (SPI) is tested in the local loopback mode.
+ * The interface is configured accordingly and several packets
+ * are transfered. The configurable test parameters are:
+ *   TEST_MIN_LENGTH - minimum size of packet to transfer
+ *   TEST_MAX_LENGTH - maximum size of packet to transfer
+ *   TEST_NUM - number of tests
+ */
+
+#if CONFIG_POST & CFG_POST_SPI
+
+#define TEST_MIN_LENGTH                1
+#define TEST_MAX_LENGTH                MAX_BUFFER
+#define TEST_NUM               1
+
+static void packet_fill (char * packet, int length)
+{
+       char c = (char) length;
+       int i;
+
+       for (i = 0; i < length; i++)
+       {
+           packet[i] = c++;
+       }
+}
+
+static int packet_check (char * packet, int length)
+{
+       char c = (char) length;
+       int i;
+
+       for (i = 0; i < length; i++)
+       {
+           if (packet[i] != c++) return -1;
+       }
+
+       return 0;
+}
+
+int spi_post_test (int flags)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       int res = -1;
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+       volatile cpm8xx_t *cp = (cpm8xx_t *) &immr->im_cpm;
+       int i;
+       int l;
+
+       spi_init_f();
+       spi_init_r();
+
+       cp->cp_spmode |= SPMODE_LOOP;
+
+       for (i = 0; i < TEST_NUM; i++)
+       {
+           for (l = TEST_MIN_LENGTH; l <= TEST_MAX_LENGTH; l += 8)
+           {
+               packet_fill(txbuf, l);
+
+               spi_xfer(l);
+
+               if (packet_check(rxbuf, l) < 0)
+               {
+                   goto Done;
+               }
+           }
+       }
+
+       res = 0;
+
+       Done:
+
+       cp->cp_spmode &= ~SPMODE_LOOP;
+
+       /*
+        * SCC2 Ethernet parameter RAM space overlaps
+        * the SPI parameter RAM space. So we need to restore
+        * the SCC2 configuration if it is used by UART or Ethernet.
+        */
+
+#if defined(CONFIG_8xx_CONS_SCC2)
+       serial_init();
+#endif
+
+#if defined(SCC_ENET) && (SCC_ENET == 1)
+       eth_init(gd->bd);
+#endif
+
+       if (res != 0)
+       {
+               post_log("SPI test failed\n");
+       }
+
+       return res;
+}
+#endif /* CONFIG_POST & CFG_POST_SPI */
diff --git a/cpu/ppc4xx/405gp_enet.c b/cpu/ppc4xx/405gp_enet.c
new file mode 100644 (file)
index 0000000..49e9e42
--- /dev/null
@@ -0,0 +1,867 @@
+/*-----------------------------------------------------------------------------+
+ *
+ *       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
+ *-----------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------+
+ *
+ *  File Name:  enetemac.c
+ *
+ *  Function:   Device driver for the ethernet EMAC3 macro on the 405GP.
+ *
+ *  Author:     Mark Wisner
+ *
+ *  Change Activity-
+ *
+ *  Date        Description of Change                                       BY
+ *  ---------   ---------------------                                       ---
+ *  05-May-99   Created                                                     MKW
+ *  27-Jun-99   Clean up                                                    JWB
+ *  16-Jul-99   Added MAL error recovery and better IP packet handling      MKW
+ *  29-Jul-99   Added Full duplex support                                   MKW
+ *  06-Aug-99   Changed names for Mal CR reg                                MKW
+ *  23-Aug-99   Turned off SYE when running at 10Mbs                        MKW
+ *  24-Aug-99   Marked descriptor empty after call_xlc                      MKW
+ *  07-Sep-99   Set MAL RX buffer size reg to ENET_MAX_MTU_ALIGNED / 16     MCG
+ *              to avoid chaining maximum sized packets. Push starting
+ *              RX descriptor address up to the next cache line boundary.
+ *  16-Jan-00   Added support for booting with IP of 0x0                    MKW
+ *  15-Mar-00   Updated enetInit() to enable broadcast addresses in the
+ *             EMAC_RXM register.                                          JWB
+ *  12-Mar-01   anne-sophie.harnois@nextream.fr
+ *               - Variables are compatible with those already defined in
+ *                include/net.h
+ *              - Receive buffer descriptor ring is used to send buffers
+ *                to the user
+ *              - Info print about send/received/handled packet number if
+ *                INFO_405_ENET is set
+ *  17-Apr-01   stefan.roese@esd-electronics.com
+ *              - MAL reset in "eth_halt" included
+ *              - Enet speed and duplex output now in one line
+ *  08-May-01   stefan.roese@esd-electronics.com
+ *              - MAL error handling added (eth_init called again)
+ *  13-Nov-01   stefan.roese@esd-electronics.com
+ *              - Set IST bit in EMAC_M1 reg upon 100MBit or full duplex
+ *  04-Jan-02   stefan.roese@esd-electronics.com
+ *              - Wait for PHY auto negotiation to complete added
+ *  06-Feb-02   stefan.roese@esd-electronics.com
+ *              - Bug fixed in waiting for auto negotiation to complete
+ *  26-Feb-02   stefan.roese@esd-electronics.com
+ *              - rx and tx buffer descriptors now allocated (no fixed address
+ *                used anymore)
+ *  17-Jun-02   stefan.roese@esd-electronics.com
+ *              - MAL error debug printf 'M' removed (rx de interrupt may
+ *                occur upon many incoming packets with only 4 rx buffers).
+ *-----------------------------------------------------------------------------*/
+
+#include <common.h>
+#include <asm/processor.h>
+#include <ppc4xx.h>
+#include <commproc.h>
+#include <405gp_enet.h>
+#include <405_mal.h>
+#include <miiphy.h>
+#include <net.h>
+#include <malloc.h>
+#include "vecnum.h"
+
+#if defined(CONFIG_405GP) || defined(CONFIG_440)
+
+#define EMAC_RESET_TIMEOUT 1000        /* 1000 ms reset timeout */
+#define PHY_AUTONEGOTIATE_TIMEOUT 2000 /* 2000 ms autonegotiate timeout */
+
+#define NUM_TX_BUFF 1
+/* AS.HARNOIS
+ * Use PKTBUFSRX (include/net.h) instead of setting NUM_RX_BUFF again
+ * These both variables are used to define the same thing!
+ * #define NUM_RX_BUFF 4
+ */
+#define NUM_RX_BUFF PKTBUFSRX
+
+/* Ethernet Transmit and Receive Buffers */
+/* AS.HARNOIS
+ * In the same way ENET_MAX_MTU and ENET_MAX_MTU_ALIGNED are set from
+ * PKTSIZE and PKTSIZE_ALIGN (include/net.h)
+ */
+#define ENET_MAX_MTU           PKTSIZE
+#define ENET_MAX_MTU_ALIGNED   PKTSIZE_ALIGN
+
+static char *txbuf_ptr;
+
+/* define the number of channels implemented */
+#define EMAC_RXCHL      1
+#define EMAC_TXCHL      1
+
+/*-----------------------------------------------------------------------------+
+ * Defines for MAL/EMAC interrupt conditions as reported in the UIC (Universal
+ * Interrupt Controller).
+ *-----------------------------------------------------------------------------*/
+#define MAL_UIC_ERR ( UIC_MAL_SERR | UIC_MAL_TXDE  | UIC_MAL_RXDE)
+#define MAL_UIC_DEF  (UIC_MAL_RXEOB | MAL_UIC_ERR)
+#define EMAC_UIC_DEF UIC_ENET
+
+/*-----------------------------------------------------------------------------+
+ * Global variables. TX and RX descriptors and buffers.
+ *-----------------------------------------------------------------------------*/
+static volatile mal_desc_t *tx;
+static volatile mal_desc_t *rx;
+static mal_desc_t *alloc_tx_buf = NULL;
+static mal_desc_t *alloc_rx_buf = NULL;
+
+/* IER globals */
+static unsigned long emac_ier;
+static unsigned long mal_ier;
+
+
+/* Statistic Areas */
+#define MAX_ERR_LOG 10
+struct emac_stats {
+       int data_len_err;
+       int rx_frames;
+       int rx;
+       int rx_prot_err;
+};
+
+static struct stats {                  /* Statistic Block */
+       struct emac_stats emac;
+       int int_err;
+       short tx_err_log[MAX_ERR_LOG];
+       short rx_err_log[MAX_ERR_LOG];
+} stats;
+
+static int first_init = 0;
+
+static int tx_err_index = 0;   /* Transmit Error Index for tx_err_log */
+static int rx_err_index = 0;   /* Receive Error Index for rx_err_log */
+
+static int rx_slot = 0;                        /* MAL Receive Slot */
+static int rx_i_index = 0;             /* Receive Interrupt Queue Index */
+static int rx_u_index = 0;             /* Receive User Queue Index */
+static int rx_ready[NUM_RX_BUFF];      /* Receive Ready Queue */
+
+static int tx_slot = 0;                        /* MAL Transmit Slot */
+static int tx_i_index = 0;             /* Transmit Interrupt Queue Index */
+static int tx_u_index = 0;             /* Transmit User Queue Index */
+static int tx_run[NUM_TX_BUFF];        /* Transmit Running Queue */
+
+#undef INFO_405_ENET 1
+#ifdef INFO_405_ENET
+static int packetSent = 0;
+static int packetReceived = 0;
+static int packetHandled = 0;
+#endif
+
+static char emac_hwd_addr[ENET_ADDR_LENGTH];
+
+static bd_t *bis_save = NULL;  /* for eth_init upon mal error */
+
+static int is_receiving = 0;   /* sync with eth interrupt */
+static int print_speed = 1;    /* print speed message upon start */
+
+static void enet_rcv (unsigned long malisr);
+
+/*-----------------------------------------------------------------------------+
+ * Prototypes and externals.
+ *-----------------------------------------------------------------------------*/
+void mal_err (unsigned long isr, unsigned long uic, unsigned long mal_def,
+             unsigned long mal_errr);
+void emac_err (unsigned long isr);
+
+
+void eth_halt (void)
+{
+       mtdcr (malier, 0x00000000);     /* disable mal interrupts */
+       out32 (EMAC_IER, 0x00000000);   /* disable emac interrupts */
+
+       /* 1st reset MAL */
+       mtdcr (malmcr, MAL_CR_MMSR);
+
+       /* wait for reset */
+       while (mfdcr (malmcr) & MAL_CR_MMSR) {
+       };
+
+       /* EMAC RESET */
+       out32 (EMAC_M0, EMAC_M0_SRST);
+
+       print_speed = 1;                /* print speed message again next time */
+}
+
+
+int eth_init (bd_t * bis)
+{
+       int i;
+       unsigned long reg;
+       unsigned long msr;
+       unsigned long speed;
+       unsigned long duplex;
+       unsigned mode_reg;
+       unsigned short reg_short;
+
+       msr = mfmsr ();
+       mtmsr (msr & ~(MSR_EE));        /* disable interrupts */
+
+#ifdef INFO_405_ENET
+       /* AS.HARNOIS
+        * We should have :
+        * packetHandled <=  packetReceived <= packetHandled+PKTBUFSRX
+         * In the most cases packetHandled = packetReceived, but it
+         * is possible that new packets (without relationship with
+         * current transfer) have got the time to arrived before
+         * netloop calls eth_halt
+        */
+       printf ("About preceeding transfer:\n"
+               "- Sent packet number %d\n"
+               "- Received packet number %d\n"
+               "- Handled packet number %d\n",
+               packetSent, packetReceived, packetHandled);
+       packetSent = 0;
+       packetReceived = 0;
+       packetHandled = 0;
+#endif
+
+       /* MAL RESET */
+       mtdcr (malmcr, MAL_CR_MMSR);
+       /* wait for reset */
+       while (mfdcr (malmcr) & MAL_CR_MMSR) {
+       };
+
+       tx_err_index = 0;               /* Transmit Error Index for tx_err_log */
+       rx_err_index = 0;               /* Receive Error Index for rx_err_log */
+
+       rx_slot = 0;                    /* MAL Receive Slot */
+       rx_i_index = 0;                 /* Receive Interrupt Queue Index */
+       rx_u_index = 0;                 /* Receive User Queue Index */
+
+       tx_slot = 0;                    /* MAL Transmit Slot */
+       tx_i_index = 0;                 /* Transmit Interrupt Queue Index */
+       tx_u_index = 0;                 /* Transmit User Queue Index */
+
+#if defined(CONFIG_440)
+        /* set RMII mode */
+        out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0);
+#endif /* CONFIG_440 */
+
+       /* EMAC RESET */
+       out32 (EMAC_M0, EMAC_M0_SRST);
+
+       /* wait for PHY to complete auto negotiation */
+       reg_short = 0;
+#ifndef CONFIG_CS8952_PHY
+       miiphy_read (CONFIG_PHY_ADDR, PHY_BMSR, &reg_short);
+
+       /*
+        * Wait if PHY is able of autonegotiation and autonegotiation is not complete
+        */
+       if ((reg_short & PHY_BMSR_AUTN_ABLE)
+           && !(reg_short & PHY_BMSR_AUTN_COMP)) {
+               puts ("Waiting for PHY auto negotiation to complete");
+               i = 0;
+               while (!(reg_short & PHY_BMSR_AUTN_COMP)) {
+                       if ((i++ % 100) == 0)
+                               putc ('.');
+                       udelay (10000);         /* 10 ms */
+                       miiphy_read (CONFIG_PHY_ADDR, PHY_BMSR, &reg_short);
+
+                       /*
+                        * Timeout reached ?
+                        */
+                       if (i * 10 > PHY_AUTONEGOTIATE_TIMEOUT) {
+                               puts (" TIMEOUT !\n");
+                               break;
+                       }
+               }
+               puts (" done\n");
+               udelay (500000);        /* another 500 ms (results in faster booting) */
+       }
+#endif
+       speed = miiphy_speed (CONFIG_PHY_ADDR);
+       duplex = miiphy_duplex (CONFIG_PHY_ADDR);
+       if (print_speed) {
+               print_speed = 0;
+               printf ("ENET Speed is %d Mbps - %s duplex connection\n",
+                       (int) speed, (duplex == HALF) ? "HALF" : "FULL");
+       }
+
+       /* set the Mal configuration reg */
+#if defined(CONFIG_440)
+       /* Errata 1.12: MAL_1 -- Disable MAL bursting */
+       if( get_pvr() == PVR_440GP_RB )
+           mtdcr (malmcr, MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
+       else
+#else
+       mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
+#endif
+
+       /* Free "old" buffers */
+       if (alloc_tx_buf) free(alloc_tx_buf);
+       if (alloc_rx_buf) free(alloc_rx_buf);
+
+       /*
+        * Malloc MAL buffer desciptors, make sure they are
+        * aligned on cache line boundary size
+        * (401/403/IOP480 = 16, 405 = 32)
+        * and doesn't cross cache block boundaries.
+        */
+       alloc_tx_buf = (mal_desc_t *)malloc((sizeof(mal_desc_t) * NUM_TX_BUFF) +
+                                           ((2 * CFG_CACHELINE_SIZE) - 2));
+       if (((int)alloc_tx_buf & CACHELINE_MASK) != 0) {
+               tx = (mal_desc_t *)((int)alloc_tx_buf + CFG_CACHELINE_SIZE -
+                                   ((int)alloc_tx_buf & CACHELINE_MASK));
+       } else {
+               tx = alloc_tx_buf;
+       }
+
+       alloc_rx_buf = (mal_desc_t *)malloc((sizeof(mal_desc_t) * NUM_RX_BUFF) +
+                                           ((2 * CFG_CACHELINE_SIZE) - 2));
+       if (((int)alloc_rx_buf & CACHELINE_MASK) != 0) {
+               rx = (mal_desc_t *)((int)alloc_rx_buf + CFG_CACHELINE_SIZE -
+                                   ((int)alloc_rx_buf & CACHELINE_MASK));
+       } else {
+               rx = alloc_rx_buf;
+       }
+
+       for (i = 0; i < NUM_TX_BUFF; i++) {
+               tx[i].ctrl = 0;
+               tx[i].data_len = 0;
+               if (first_init == 0)
+                       txbuf_ptr = (char *) malloc (ENET_MAX_MTU_ALIGNED);
+               tx[i].data_ptr = txbuf_ptr;
+               if ((NUM_TX_BUFF - 1) == i)
+                       tx[i].ctrl |= MAL_TX_CTRL_WRAP;
+               tx_run[i] = -1;
+#if 0
+               printf ("TX_BUFF %d @ 0x%08lx\n", i, (ulong) tx[i].data_ptr);
+#endif
+       }
+
+       for (i = 0; i < NUM_RX_BUFF; i++) {
+               rx[i].ctrl = 0;
+               rx[i].data_len = 0;
+               /*       rx[i].data_ptr = (char *) &rx_buff[i]; */
+               rx[i].data_ptr = (char *) NetRxPackets[i];
+               if ((NUM_RX_BUFF - 1) == i)
+                       rx[i].ctrl |= MAL_RX_CTRL_WRAP;
+               rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR;
+               rx_ready[i] = -1;
+#if 0
+               printf ("RX_BUFF %d @ 0x%08lx\n", i, (ulong) rx[i].data_ptr);
+#endif
+       }
+
+       memcpy (emac_hwd_addr, bis->bi_enetaddr, ENET_ADDR_LENGTH);
+
+       reg = 0x00000000;
+
+       reg |= emac_hwd_addr[0];        /* set high address */
+       reg = reg << 8;
+       reg |= emac_hwd_addr[1];
+
+       out32 (EMAC_IAH, reg);
+
+       reg = 0x00000000;
+       reg |= emac_hwd_addr[2];        /* set low address  */
+       reg = reg << 8;
+       reg |= emac_hwd_addr[3];
+       reg = reg << 8;
+       reg |= emac_hwd_addr[4];
+       reg = reg << 8;
+       reg |= emac_hwd_addr[5];
+
+       out32 (EMAC_IAL, reg);
+
+       /* setup MAL tx & rx channel pointers */
+       mtdcr (maltxctp0r, tx);
+       mtdcr (malrxctp0r, rx);
+
+       /* Reset transmit and receive channels */
+       mtdcr (malrxcarr, 0x80000000);  /* 2 channels */
+       mtdcr (maltxcarr, 0x80000000);  /* 2 channels */
+
+       /* Enable MAL transmit and receive channels */
+       mtdcr (maltxcasr, 0x80000000);  /* 1 channel */
+       mtdcr (malrxcasr, 0x80000000);  /* 1 channel */
+
+       /* set RX buffer size */
+       mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16);
+
+       /* set transmit enable & receive enable */
+       out32 (EMAC_M0, EMAC_M0_TXE | EMAC_M0_RXE);
+
+       /* set receive fifo to 4k and tx fifo to 2k */
+       mode_reg = EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K;
+
+       /* set speed */
+       if (speed == _100BASET)
+               mode_reg = mode_reg | EMAC_M1_MF_100MBPS | EMAC_M1_IST;
+       else
+               mode_reg = mode_reg & ~0x00C00000;      /* 10 MBPS */
+       if (duplex == FULL)
+               mode_reg = mode_reg | 0x80000000 | EMAC_M1_IST;
+
+       out32 (EMAC_M1, mode_reg);
+
+       /* Enable broadcast and indvidual address */
+       out32 (EMAC_RXM, EMAC_RMR_BAE | EMAC_RMR_IAE
+              /*| EMAC_RMR_ARRP| EMAC_RMR_SFCS | EMAC_RMR_SP */ );
+
+       /* we probably need to set the tx mode1 reg? maybe at tx time */
+
+       /* set transmit request threshold register */
+       out32 (EMAC_TRTR, 0x18000000);  /* 256 byte threshold */
+
+       /* set receive  low/high water mark register */
+#if defined(CONFIG_440)
+       /* 440GP has a 64 byte burst length */
+        out32 (EMAC_RX_HI_LO_WMARK, 0x80009000);
+        out32 (EMAC_TXM1,           0xf8640000);
+#else /* CONFIG_440 */
+       /* 405s have a 16 byte burst length */
+       out32 (EMAC_RX_HI_LO_WMARK, 0x0f002000);
+#endif /* CONFIG_440 */
+
+       /* Frame gap set */
+       out32 (EMAC_I_FRAME_GAP_REG, 0x00000008);
+
+       if (first_init == 0) {
+               /*
+                * Connect interrupt service routines
+                */
+               irq_install_handler (VECNUM_EWU0, (interrupt_handler_t *) enetInt, NULL);
+               irq_install_handler (VECNUM_MS, (interrupt_handler_t *) enetInt, NULL);
+               irq_install_handler (VECNUM_MTE, (interrupt_handler_t *) enetInt, NULL);
+               irq_install_handler (VECNUM_MRE, (interrupt_handler_t *) enetInt, NULL);
+               irq_install_handler (VECNUM_TXDE, (interrupt_handler_t *) enetInt, NULL);
+               irq_install_handler (VECNUM_RXDE, (interrupt_handler_t *) enetInt, NULL);
+               irq_install_handler (VECNUM_ETH0, (interrupt_handler_t *) enetInt, NULL);
+       }
+
+       /* set up interrupt handler */
+       /* setup interrupt controler to take interrupts from the MAL &
+          EMAC */
+       mtdcr (uicsr, 0xffffffff);      /* clear pending interrupts */
+       mtdcr (uicer, mfdcr (uicer) | MAL_UIC_DEF | EMAC_UIC_DEF);
+
+       /* set the MAL IER ??? names may change with new spec ??? */
+       mal_ier = MAL_IER_DE | MAL_IER_NE | MAL_IER_TE | MAL_IER_OPBE |
+               MAL_IER_PLBE;
+       mtdcr (malesr, 0xffffffff);     /* clear pending interrupts */
+       mtdcr (maltxdeir, 0xffffffff);  /* clear pending interrupts */
+       mtdcr (malrxdeir, 0xffffffff);  /* clear pending interrupts */
+       mtdcr (malier, mal_ier);
+
+       /* Set EMAC IER */
+       emac_ier = EMAC_ISR_PTLE | EMAC_ISR_BFCS |
+               EMAC_ISR_PTLE | EMAC_ISR_ORE  | EMAC_ISR_IRE;
+       if (speed == _100BASET)
+               emac_ier = emac_ier | EMAC_ISR_SYE;
+
+       out32 (EMAC_ISR, 0xffffffff);   /* clear pending interrupts */
+       out32 (EMAC_IER, emac_ier);
+
+       mtmsr (msr);                            /* enable interrupts again */
+
+       bis_save = bis;
+       first_init = 1;
+
+       return (0);
+}
+
+
+int eth_send (volatile void *ptr, int len)
+{
+       struct enet_frame *ef_ptr;
+       ulong time_start, time_now;
+       unsigned long temp_txm0;
+
+       ef_ptr = (struct enet_frame *) ptr;
+
+       /*-----------------------------------------------------------------------+
+        *  Copy in our address into the frame.
+        *-----------------------------------------------------------------------*/
+       (void) memcpy (ef_ptr->source_addr, emac_hwd_addr, ENET_ADDR_LENGTH);
+
+       /*-----------------------------------------------------------------------+
+        * If frame is too long or too short, modify length.
+        *-----------------------------------------------------------------------*/
+       if (len > ENET_MAX_MTU)
+               len = ENET_MAX_MTU;
+
+       /*   memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */
+       memcpy ((void *) txbuf_ptr, (const void *) ptr, len);
+
+       /*-----------------------------------------------------------------------+
+        * set TX Buffer busy, and send it
+        *-----------------------------------------------------------------------*/
+       tx[tx_slot].ctrl = (MAL_TX_CTRL_LAST |
+                           EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP) &
+               ~(EMAC_TX_CTRL_ISA | EMAC_TX_CTRL_RSA);
+       if ((NUM_TX_BUFF - 1) == tx_slot)
+               tx[tx_slot].ctrl |= MAL_TX_CTRL_WRAP;
+
+       tx[tx_slot].data_len = (short) len;
+       tx[tx_slot].ctrl |= MAL_TX_CTRL_READY;
+
+    __asm__ volatile ("eieio");
+       out32 (EMAC_TXM0, in32 (EMAC_TXM0) | EMAC_TXM0_GNP0);
+#ifdef INFO_405_ENET
+       packetSent++;
+#endif
+
+       /*-----------------------------------------------------------------------+
+        * poll unitl the packet is sent and then make sure it is OK
+        *-----------------------------------------------------------------------*/
+       time_start = get_timer (0);
+       while (1) {
+               temp_txm0 = in32 (EMAC_TXM0);
+               /* loop until either TINT turns on or 3 seconds elapse */
+               if ((temp_txm0 & EMAC_TXM0_GNP0) != 0) {
+                       /* transmit is done, so now check for errors
+                         * If there is an error, an interrupt should
+                         * happen when we return
+                        */
+                       time_now = get_timer (0);
+                       if ((time_now - time_start) > 3000) {
+                               return (-1);
+                       }
+               } else {
+                       return (0);
+               }
+       }
+}
+
+
+#if defined(CONFIG_440)
+/*-----------------------------------------------------------------------------+
+| EnetInt.
+| EnetInt is the interrupt handler.  It will determine the
+| cause of the interrupt and call the apporpriate servive
+| routine.
++-----------------------------------------------------------------------------*/
+int enetInt ()
+{
+       int serviced;
+       int rc = -1;                            /* default to not us */
+       unsigned long mal_isr;
+       unsigned long emac_isr = 0;
+       unsigned long mal_rx_eob;
+       unsigned long my_uic0msr, my_uic1msr;
+
+       /* enter loop that stays in interrupt code until nothing to service */
+       do {
+               serviced = 0;
+
+               my_uic0msr = mfdcr (uic0msr);
+               my_uic1msr = mfdcr (uic1msr);
+
+               if (!(my_uic0msr & UIC_MRE)
+                    && !(my_uic1msr & (UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE))) {
+                        /* not for us */
+                       return (rc);
+               }
+
+               /* get and clear controller status interrupts */
+               /* look at Mal and EMAC interrupts */
+               if ((my_uic0msr & UIC_MRE)
+                    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
+                        /* we have a MAL interrupt */
+                       mal_isr = mfdcr (malesr);
+                       /* look for mal error */
+                       if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) {
+                               mal_err (mal_isr, my_uic0msr, MAL_UIC_DEF, MAL_UIC_ERR);
+                               serviced = 1;
+                               rc = 0;
+                       }
+               }
+               if (UIC_ETH0 & my_uic1msr) {    /* look for EMAC errors */
+                       emac_isr = in32 (EMAC_ISR);
+                       if ((emac_ier & emac_isr) != 0) {
+                               emac_err (emac_isr);
+                               serviced = 1;
+                               rc = 0;
+                       }
+               }
+               if ((emac_ier & emac_isr)
+                    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
+                       mtdcr (uic0sr, UIC_MRE); /* Clear */
+                       mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+                       return (rc);            /* we had errors so get out */
+               }
+
+               /* handle MAL RX EOB  interupt from a receive */
+               /* check for EOB on valid channels            */
+               if (my_uic0msr & UIC_MRE) {
+                       mal_rx_eob = mfdcr (malrxeobisr);
+                       if ((mal_rx_eob & 0x80000000) != 0) {   /* call emac routine for channel 0 */
+                               /* clear EOB
+                                  mtdcr(malrxeobisr, mal_rx_eob); */
+                               enet_rcv (emac_isr);
+                               /* indicate that we serviced an interrupt */
+                               serviced = 1;
+                               rc = 0;
+                       }
+               }
+                mtdcr (uic0sr, UIC_MRE); /* Clear */
+                mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+       } while (serviced);
+
+       return (rc);
+}
+#else /* CONFIG_440 */
+/*-----------------------------------------------------------------------------+
+ * EnetInt.
+ * EnetInt is the interrupt handler.  It will determine the
+ * cause of the interrupt and call the apporpriate servive
+ * routine.
+ *-----------------------------------------------------------------------------*/
+int enetInt ()
+{
+       int serviced;
+       int rc = -1;                            /* default to not us */
+       unsigned long mal_isr;
+       unsigned long emac_isr = 0;
+       unsigned long mal_rx_eob;
+       unsigned long my_uicmsr;
+
+       /* enter loop that stays in interrupt code until nothing to service */
+       do {
+               serviced = 0;
+
+               my_uicmsr = mfdcr (uicmsr);
+               if ((my_uicmsr & (MAL_UIC_DEF | EMAC_UIC_DEF)) == 0) {  /* not for us */
+                       return (rc);
+               }
+
+
+               /* get and clear controller status interrupts */
+               /* look at Mal and EMAC interrupts */
+               if ((MAL_UIC_DEF & my_uicmsr) != 0) {   /* we have a MAL interrupt */
+                       mal_isr = mfdcr (malesr);
+                       /* look for mal error */
+                       if ((my_uicmsr & MAL_UIC_ERR) != 0) {
+                               mal_err (mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR);
+                               serviced = 1;
+                               rc = 0;
+                       }
+               }
+               if ((EMAC_UIC_DEF & my_uicmsr) != 0) {  /* look for EMAC errors */
+                       emac_isr = in32 (EMAC_ISR);
+                       if ((emac_ier & emac_isr) != 0) {
+                               emac_err (emac_isr);
+                               serviced = 1;
+                               rc = 0;
+                       }
+               }
+               if (((emac_ier & emac_isr) != 0) | ((MAL_UIC_ERR & my_uicmsr) != 0)) {
+                       mtdcr (uicsr, MAL_UIC_DEF | EMAC_UIC_DEF); /* Clear */
+                       return (rc);            /* we had errors so get out */
+               }
+
+
+               /* handle MAL RX EOB  interupt from a receive */
+               /* check for EOB on valid channels            */
+               if ((my_uicmsr & UIC_MAL_RXEOB) != 0) {
+                       mal_rx_eob = mfdcr (malrxeobisr);
+                       if ((mal_rx_eob & 0x80000000) != 0) {   /* call emac routine for channel 0 */
+                               /* clear EOB
+                                  mtdcr(malrxeobisr, mal_rx_eob); */
+                               enet_rcv (emac_isr);
+                               /* indicate that we serviced an interrupt */
+                               serviced = 1;
+                               rc = 0;
+                       }
+               }
+               mtdcr (uicsr, MAL_UIC_DEF | EMAC_UIC_DEF);      /* Clear */
+       }
+       while (serviced);
+
+       return (rc);
+}
+#endif /* CONFIG_440 */
+
+/*-----------------------------------------------------------------------------+
+ *  MAL Error Routine
+ *-----------------------------------------------------------------------------*/
+void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef,
+             unsigned long mal_errr)
+{
+       mtdcr (malesr, isr);            /* clear interrupt */
+
+       /* clear DE interrupt */
+       mtdcr (maltxdeir, 0xC0000000);
+       mtdcr (malrxdeir, 0x80000000);
+
+#if 1  /*sr */
+       printf ("\nMAL error occured.... ISR = %lx UIC = = %lx  MAL_DEF = %lx  MAL_ERR= %lx \n",
+               isr, uic, maldef, mal_errr);
+#else
+#if 0
+       /*
+        * MAL error is RX DE error (out of rx buffers)! This is OK here, upon
+        * many incoming packets with only 4 rx buffers.
+        */
+       printf ("M");                   /* just to see something upon mal error */
+#endif
+#endif /*sr */
+
+       eth_init (bis_save);            /* start again... */
+}
+
+/*-----------------------------------------------------------------------------+
+ *  EMAC Error Routine
+ *-----------------------------------------------------------------------------*/
+void emac_err (unsigned long isr)
+{
+       printf ("EMAC error occured.... ISR = %lx\n", isr);
+       out32 (EMAC_ISR, isr);
+}
+
+/*-----------------------------------------------------------------------------+
+ *  enet_rcv() handles the ethernet receive data
+ *-----------------------------------------------------------------------------*/
+static void enet_rcv (unsigned long malisr)
+{
+       struct enet_frame *ef_ptr;
+       unsigned long data_len;
+       unsigned long rx_eob_isr;
+
+       int handled = 0;
+       int i;
+       int loop_count = 0;
+
+       rx_eob_isr = mfdcr (malrxeobisr);
+       if ((0x80000000 >> (EMAC_RXCHL - 1)) & rx_eob_isr) {
+               /* clear EOB */
+               mtdcr (malrxeobisr, rx_eob_isr);
+
+               /* EMAC RX done */
+               while (1) {                             /* do all */
+                       i = rx_slot;
+
+                       if ((MAL_RX_CTRL_EMPTY & rx[i].ctrl)
+                           || (loop_count >= NUM_RX_BUFF))
+                               break;
+                       loop_count++;
+                       rx_slot++;
+                       if (NUM_RX_BUFF == rx_slot)
+                               rx_slot = 0;
+                       handled++;
+                       data_len = (unsigned long) rx[i].data_len;      /* Get len */
+                       if (data_len) {
+                               if (data_len > ENET_MAX_MTU)    /* Check len */
+                                       data_len = 0;
+                               else {
+                                       if (EMAC_RX_ERRORS & rx[i].ctrl) {      /* Check Errors */
+                                               data_len = 0;
+                                               stats.rx_err_log[rx_err_index] = rx[i].ctrl;
+                                               rx_err_index++;
+                                               if (rx_err_index == MAX_ERR_LOG)
+                                                       rx_err_index = 0;
+                                       }       /* emac_erros         */
+                               }               /* data_len < max mtu */
+                       }                       /* if data_len        */
+                       if (!data_len) {        /* no data */
+                               rx[i].ctrl |= MAL_RX_CTRL_EMPTY;        /* Free Recv Buffer */
+
+                               stats.emac.data_len_err++;      /* Error at Rx */
+                       }
+
+                       /* !data_len */
+                       /* AS.HARNOIS */
+                       /* Check if user has already eaten buffer */
+                       /* if not => ERROR */
+                       else if (rx_ready[rx_i_index] != -1) {
+                               if (is_receiving)
+                                       printf ("ERROR : Receive buffers are full!\n");
+                               break;
+                       } else {
+                               stats.emac.rx_frames++;
+                               stats.emac.rx += data_len;
+                               ef_ptr = (struct enet_frame *) rx[i].data_ptr;
+#ifdef INFO_405_ENET
+                               packetReceived++;
+#endif
+                               /* AS.HARNOIS
+                                * use ring buffer
+                                */
+                               rx_ready[rx_i_index] = i;
+                               rx_i_index++;
+                               if (NUM_RX_BUFF == rx_i_index)
+                                       rx_i_index = 0;
+
+                               /* printf("X");  /|* test-only *|/ */
+
+                               /*  AS.HARNOIS
+                                * free receive buffer only when
+                                * buffer has been handled (eth_rx)
+                                rx[i].ctrl |= MAL_RX_CTRL_EMPTY;
+                               */
+                       }                       /* if data_len */
+               }                               /* while */
+       }                                       /* if EMACK_RXCHL */
+}
+
+
+int eth_rx (void)
+{
+       int length;
+       int user_index;
+       unsigned long msr;
+
+       is_receiving = 1;                       /* tell driver */
+
+       for (;;) {
+               /* AS.HARNOIS
+                * use ring buffer and
+                * get index from rx buffer desciptor queue
+                */
+               user_index = rx_ready[rx_u_index];
+               if (user_index == -1) {
+                       length = -1;
+                       break;  /* nothing received - leave for() loop */
+               }
+
+               msr = mfmsr ();
+               mtmsr (msr & ~(MSR_EE));
+
+               length = rx[user_index].data_len;
+
+               /* Pass the packet up to the protocol layers. */
+               /*       NetReceive(NetRxPackets[rxIdx], length - 4); */
+               /*       NetReceive(NetRxPackets[i], length); */
+               NetReceive (NetRxPackets[user_index], length - 4);
+               /* Free Recv Buffer */
+               rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY;
+               /* Free rx buffer descriptor queue */
+               rx_ready[rx_u_index] = -1;
+               rx_u_index++;
+               if (NUM_RX_BUFF == rx_u_index)
+                       rx_u_index = 0;
+
+#ifdef INFO_405_ENET
+               packetHandled++;
+#endif
+
+               mtmsr (msr);                    /* Enable IRQ's */
+       }
+
+       is_receiving = 0;                       /* tell driver */
+
+       return length;
+}
+
+#endif /* CONFIG_405GP */
diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c
new file mode 100644 (file)
index 0000000..1c2c59b
--- /dev/null
@@ -0,0 +1,502 @@
+/*-----------------------------------------------------------------------------+
+ *
+ *       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
+ *-----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+ *
+ *  File Name:   405gp_pci.c
+ *
+ *  Function:    Initialization code for the 405GP PCI Configuration regs.
+ *
+ *  Author:      Mark Game
+ *
+ *  Change Activity-
+ *
+ *  Date        Description of Change                                       BY
+ *  ---------   ---------------------                                       ---
+ *  09-Sep-98   Created                                                     MCG
+ *  02-Nov-98   Removed External arbiter selected message                   JWB
+ *  27-Nov-98   Zero out PTMBAR2 and disable in PTM2MS                      JWB
+ *  04-Jan-99   Zero out other unused PMM and PTM regs. Change bus scan     MCG
+ *              from (0 to n) to (1 to n).
+ *  17-May-99   Port to Walnut                                              JWB
+ *  17-Jun-99   Updated for VGA support                                     JWB
+ *  21-Jun-99   Updated to allow SRAM region to be a target from PCI bus    JWB
+ *  19-Jul-99   Updated for 405GP pass 1 errata #26 (Low PCI subsequent     MCG
+ *              target latency timer values are not supported).
+ *              Should be fixed in pass 2.
+ *  09-Sep-99   Removed use of PTM2 since the SRAM region no longer needs   JWB
+ *              to be a PCI target. Zero out PTMBAR2 and disable in PTM2MS.
+ *  10-Dec-99   Updated PCI_Write_CFG_Reg for pass2 errata #6               JWB
+ *  11-Jan-00   Ensure PMMxMAs disabled before setting PMMxLAs. This is not
+ *              really required after a reset since PMMxMAs are already
+ *             disabled but is a good practice nonetheless.                JWB
+ *  12-Jun-01   stefan.roese@esd-electronics.com
+ *              - PCI host/adapter handling reworked
+ *  09-Jul-01   stefan.roese@esd-electronics.com
+ *              - PCI host now configures from device 0 (not 1) to max_dev,
+ *                (host configures itself)
+ *              - On CPCI-405 pci base address and size is generated from
+ *                SDRAM and FLASH size (CFG regs not used anymore)
+ *              - Some minor changes for CPCI-405-A (adapter version)
+ *  14-Sep-01   stefan.roese@esd-electronics.com
+ *              - CONFIG_PCI_SCAN_SHOW added to print pci devices upon startup
+ *  28-Sep-01   stefan.roese@esd-electronics.com
+ *              - Changed pci master configuration for linux compatibility
+ *                (no need for bios_fixup() anymore)
+ *  26-Feb-02   stefan.roese@esd-electronics.com
+ *              - Bug fixed in pci configuration (Andrew May)
+ *              - Removed pci class code init for CPCI405 board
+ *  15-May-02   stefan.roese@esd-electronics.com
+ *              - New vga device handling
+ *  29-May-02   stefan.roese@esd-electronics.com
+ *              - PCI class code init added (if defined)
+ *----------------------------------------------------------------------------*/
+
+#include <common.h>
+#include <command.h>
+#include <cmd_boot.h>
+#if !defined(CONFIG_440)
+#include <405gp_pci.h>
+#endif
+#include <asm/processor.h>
+#include <pci.h>
+
+#if defined(CONFIG_405GP)
+
+#ifdef CONFIG_PCI
+
+/*#define DEBUG*/
+
+/*-----------------------------------------------------------------------------+
+ * pci_init.  Initializes the 405GP PCI Configuration regs.
+ *-----------------------------------------------------------------------------*/
+void pci_405gp_init(struct pci_controller *hose)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       int i, reg_num = 0;
+       bd_t *bd = gd->bd;
+
+       unsigned short temp_short;
+       unsigned long ptmpcila[2] = {CFG_PCI_PTM1PCI, CFG_PCI_PTM2PCI};
+#if defined(CONFIG_CPCI405)
+       unsigned long ptmla[2]    = {bd->bi_memstart, bd->bi_flashstart};
+       unsigned long ptmms[2]    = {~(bd->bi_memsize - 1) | 1, ~(bd->bi_flashsize - 1) | 1};
+#else
+       unsigned long ptmla[2]    = {CFG_PCI_PTM1LA, CFG_PCI_PTM2LA};
+       unsigned long ptmms[2]    = {CFG_PCI_PTM1MS, CFG_PCI_PTM2MS};
+#endif
+#if defined(CONFIG_PIP405) || defined (CONFIG_MIP405)
+       unsigned long pmmla[3]    = {0x80000000, 0xA0000000, 0};
+       unsigned long pmmma[3]    = {0xE0000001, 0xE0000001, 0};
+       unsigned long pmmpcila[3] = {0x80000000, 0x00000000, 0};
+       unsigned long pmmpciha[3] = {0x00000000, 0x00000000, 0};
+#else
+       unsigned long pmmla[3]    = {0x80000000, 0,0};
+       unsigned long pmmma[3]    = {0xC0000001, 0,0};
+       unsigned long pmmpcila[3] = {0x80000000, 0,0};
+       unsigned long pmmpciha[3] = {0x00000000, 0,0};
+#endif
+
+       /*
+        * Register the hose
+        */
+       hose->first_busno = 0;
+       hose->last_busno = 0xff;
+
+       /* ISA/PCI I/O space */
+       pci_set_region(hose->regions + reg_num++,
+                      MIN_PCI_PCI_IOADDR,
+                      MIN_PLB_PCI_IOADDR,
+                      0x10000,
+                      PCI_REGION_IO);
+
+       /* PCI I/O space */
+       pci_set_region(hose->regions + reg_num++,
+                      0x00800000,
+                      0xe8800000,
+                      0x03800000,
+                      PCI_REGION_IO);
+
+       reg_num = 2;
+
+       /* Memory spaces */
+       for (i=0; i<2; i++)
+               if (ptmms[i] & 1)
+               {
+                       if (!i) hose->pci_fb = hose->regions + reg_num;
+
+                       pci_set_region(hose->regions + reg_num++,
+                                      ptmpcila[i], ptmla[i],
+                                      ~(ptmms[i] & 0xfffff000) + 1,
+                                      PCI_REGION_MEM |
+                                      PCI_REGION_MEMORY);
+               }
+
+       /* PCI memory spaces */
+       for (i=0; i<3; i++)
+               if (pmmma[i] & 1)
+               {
+                       pci_set_region(hose->regions + reg_num++,
+                                      pmmpcila[i], pmmla[i],
+                                      ~(pmmma[i] & 0xfffff000) + 1,
+                                      PCI_REGION_MEM);
+               }
+
+       hose->region_count = reg_num;
+
+       pci_setup_indirect(hose,
+                          PCICFGADR,
+                          PCICFGDATA);
+
+       if (hose->pci_fb)
+               pciauto_region_init(hose->pci_fb);
+
+       pci_register_hose(hose);
+
+       /*--------------------------------------------------------------------------+
+        * 405GP PCI Master configuration.
+        * Map one 512 MB range of PLB/processor addresses to PCI memory space.
+        * PLB address 0x80000000-0xBFFFFFFF ==> PCI address 0x80000000-0xBFFFFFFF
+        * Use byte reversed out routines to handle endianess.
+        *--------------------------------------------------------------------------*/
+       out32r(PMM0MA,    pmmma[0]);          /* ensure disabled b4 setting PMM0LA */
+       out32r(PMM0LA,    pmmla[0]);
+       out32r(PMM0PCILA, pmmpcila[0]);
+       out32r(PMM0PCIHA, pmmpciha[0]);
+       out32r(PMM0MA,    pmmma[0]);
+
+       /*--------------------------------------------------------------------------+
+        * PMM1 is not used.  Initialize them to zero.
+        *--------------------------------------------------------------------------*/
+       out32r(PMM1MA,    pmmma[1]);          /* ensure disabled b4 setting PMM2LA */
+       out32r(PMM1LA,    pmmla[1]);
+       out32r(PMM1PCILA, pmmpcila[1]);
+       out32r(PMM1PCIHA, pmmpciha[1]);
+       out32r(PMM1MA,    pmmma[1]);
+
+       /*--------------------------------------------------------------------------+
+        * PMM2 is not used.  Initialize them to zero.
+        *--------------------------------------------------------------------------*/
+       out32r(PMM2MA,    pmmma[2]);          /* ensure disabled b4 setting PMM2LA */
+       out32r(PMM2LA,    pmmla[2]);
+       out32r(PMM2PCILA, pmmpcila[2]);
+       out32r(PMM2PCIHA, pmmpciha[2]);
+       out32r(PMM2MA,    pmmma[2]);
+
+       /*--------------------------------------------------------------------------+
+        * 405GP PCI Target configuration.  (PTM1)
+        * Note: PTM1MS is hardwire enabled but we set the enable bit anyway.
+        *--------------------------------------------------------------------------*/
+       out32r(PTM1LA,    ptmla[0]);         /* insert address                     */
+       out32r(PTM1MS,    ptmms[0]);         /* insert size, enable bit is 1       */
+
+       /*--------------------------------------------------------------------------+
+        * 405GP PCI Target configuration.  (PTM2)
+        *--------------------------------------------------------------------------*/
+       out32r(PTM2LA, ptmla[1]);            /* insert address                     */
+       if (ptmms[1] == 0)
+       {
+               out32r(PTM2MS,    0x00000001);   /* set enable bit                     */
+               pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, 0x00000000);
+               out32r(PTM2MS,    0x00000000);   /* disable                            */
+       }
+       else
+       {
+               out32r(PTM2MS, ptmms[1]);        /* insert size, enable bit is 1       */
+       }
+
+       /*
+        * Insert Subsystem Vendor and Device ID
+        */
+       pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_VENDOR_ID, CFG_PCI_SUBSYS_VENDORID);
+#ifdef CONFIG_CPCI405
+       if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+               pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_DEVICEID);
+       else
+               pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_DEVICEID2);
+#else
+       pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_DEVICEID);
+#endif
+
+       /*
+        * Insert Class-code
+        */
+#ifdef CFG_PCI_CLASSCODE
+       pci_write_config_word(PCIDEVID_405GP, PCI_CLASS_SUB_CODE, CFG_PCI_CLASSCODE);
+#endif /* CFG_PCI_CLASSCODE */
+
+       /*--------------------------------------------------------------------------+
+        * If PCI speed = 66Mhz, set 66Mhz capable bit.
+        *--------------------------------------------------------------------------*/
+       if (bd->bi_pci_busfreq >= 66000000) {
+               pci_read_config_word(PCIDEVID_405GP, PCI_STATUS, &temp_short);
+               pci_write_config_word(PCIDEVID_405GP,PCI_STATUS,(temp_short|PCI_STATUS_66MHZ));
+       }
+
+#if (CONFIG_PCI_HOST != PCI_HOST_ADAPTER)
+#if (CONFIG_PCI_HOSE == PCI_HOST_AUTO)
+       if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+#endif
+       {
+               /*--------------------------------------------------------------------------+
+                * Write the 405GP PCI Configuration regs.
+                * Enable 405GP to be a master on the PCI bus (PMM).
+                * Enable 405GP to act as a PCI memory target (PTM).
+                *--------------------------------------------------------------------------*/
+               pci_read_config_word(PCIDEVID_405GP, PCI_COMMAND, &temp_short);
+               pci_write_config_word(PCIDEVID_405GP, PCI_COMMAND, temp_short |
+                                     PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+       }
+#endif
+
+       /*
+        * Set HCE bit (Host Configuration Enabled)
+        */
+       pci_read_config_word(PCIDEVID_405GP, PCIBRDGOPT2, &temp_short);
+       pci_write_config_word(PCIDEVID_405GP, PCIBRDGOPT2, (temp_short | 0x0001));
+
+#ifdef CONFIG_PCI_PNP
+       /*--------------------------------------------------------------------------+
+        * Scan the PCI bus and configure devices found.
+        *--------------------------------------------------------------------------*/
+#if (CONFIG_PCI_HOST == PCI_HOST_AUTO)
+       if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+#endif
+       {
+#ifdef CONFIG_PCI_SCAN_SHOW
+               printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+
+               hose->last_busno = pci_hose_scan(hose);
+       }
+#endif  /* CONFIG_PCI_PNP */
+
+}
+
+/*
+ * drivers/pci.c skips every host bridge but the 405GP since it could
+ * be set as an Adapter.
+ *
+ * I (Andrew May) don't know what we should do here, but I don't want
+ * the auto setup of a PCI device disabling what is done pci_405gp_init
+ * as has happened before.
+ */
+void pci_405gp_setup_bridge(struct pci_controller *hose, pci_dev_t dev,
+                           struct pci_config_table *entry)
+{
+#ifdef DEBUG
+        printf("405gp_setup_bridge\n");
+#endif
+}
+
+/*
+ *
+ */
+
+void pci_405gp_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
+{
+       unsigned char int_line = 0xff;
+
+       /*
+        * Write pci interrupt line register (cpci405 specific)
+        */
+       switch (PCI_DEV(dev) & 0x03)
+       {
+       case 0:
+               int_line = 27 + 2;
+               break;
+       case 1:
+               int_line = 27 + 3;
+               break;
+       case 2:
+               int_line = 27 + 0;
+               break;
+       case 3:
+               int_line = 27 + 1;
+               break;
+       }
+
+       pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line);
+}
+
+void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev,
+                        struct pci_config_table *entry)
+{
+       unsigned int cmdstat = 0;
+
+       pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
+
+       /* always enable io space on vga boards */
+       pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat);
+       cmdstat |= PCI_COMMAND_IO;
+       pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat);
+}
+
+#if !(defined(CONFIG_PIP405) || defined (CONFIG_MIP405))
+
+/*
+ *As is these functs get called out of flash Not a horrible
+ *thing, but something to keep in mind. (no statics?)
+ */
+static struct pci_config_table pci_405gp_config_table[] = {
+/*if VendID is 0 it terminates the table search (ie Walnut)*/
+#if CFG_PCI_SUBSYS_VENDORID
+       {CFG_PCI_SUBSYS_VENDORID, PCI_ANY_ID, PCI_CLASS_BRIDGE_HOST,
+        PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_bridge},
+#endif
+       {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},
+
+       { }
+};
+
+static struct pci_controller hose = {
+       fixup_irq: pci_405gp_fixup_irq,
+       config_table: pci_405gp_config_table,
+};
+
+void pci_init(void)
+{
+       /*we want the ptrs to RAM not flash (ie don't use init list)*/
+       hose.fixup_irq    = pci_405gp_fixup_irq;
+       hose.config_table = pci_405gp_config_table;
+       pci_405gp_init(&hose);
+}
+
+#endif
+
+#endif /* CONFIG_PCI */
+
+#endif /* CONFIG_405GP */
+
+/*-----------------------------------------------------------------------------+
+ * CONFIG_440
+ *-----------------------------------------------------------------------------*/
+#if defined(CONFIG_440) && defined(CONFIG_PCI)
+
+static struct pci_controller ppc440_hose = {0};
+
+
+void pci_440_init (struct pci_controller *hose)
+{
+       int reg_num = 0;
+       unsigned long strap;
+
+       /*--------------------------------------------------------------------------+
+        * The PCI initialization sequence enable bit must be set ... if not abort
+     * pci setup since updating the bit requires chip reset.
+        *--------------------------------------------------------------------------*/
+    strap = mfdcr(cpc0_strp1);
+    if( (strap & 0x00040000) == 0 ){
+        printf("PCI: CPC0_STRP1[PISE] not set.\n");
+        printf("PCI: Configuration aborted.\n");
+        return;
+    }
+
+       /*--------------------------------------------------------------------------+
+        * PCI controller init
+        *--------------------------------------------------------------------------*/
+       hose->first_busno = 0;
+       hose->last_busno = 0xff;
+
+       pci_set_region(hose->regions + reg_num++,
+                      0x00000000,
+                          PCIX0_IOBASE,
+                          0x10000,
+                          PCI_REGION_IO);
+
+       pci_set_region(hose->regions + reg_num++,
+                      CFG_PCI_TARGBASE,
+                          CFG_PCI_MEMBASE,
+                          0x10000000,
+                          PCI_REGION_MEM );
+       hose->region_count = reg_num;
+
+       pci_setup_indirect(hose, PCIX0_CFGADR, PCIX0_CFGDATA);
+
+#if defined(CFG_PCI_PRE_INIT)
+    /* Let board change/modify hose & do initial checks */
+    if( pci_pre_init (hose) == 0 ){
+        printf("PCI: Board-specific initialization failed.\n");
+        printf("PCI: Configuration aborted.\n");
+        return;
+    }
+#endif
+
+       pci_register_hose( hose );
+
+       /*--------------------------------------------------------------------------+
+        * PCI target init
+        *--------------------------------------------------------------------------*/
+#if defined(CFG_PCI_TARGET_INIT)
+       pci_target_init(hose);                /* Let board setup pci target */
+#else
+    out16r( PCIX0_SBSYSVID, CFG_PCI_SUBSYS_VENDORID );
+    out16r( PCIX0_SBSYSID, CFG_PCI_SUBSYS_ID );
+    out16r( PCIX0_CLS, 0x00060000 ); /* Bridge, host bridge */
+#endif
+
+    out32r( PCIX0_BRDGOPT1, 0x10000060 );               /* PLB Rq pri highest   */
+    out32r( PCIX0_BRDGOPT2, in32(PCIX0_BRDGOPT2) | 1 ); /* Enable host config   */
+
+       /*--------------------------------------------------------------------------+
+        * PCI master init: default is one 256MB region for PCI memory:
+        * 0x3_00000000 - 0x3_0FFFFFFF  ==> CFG_PCI_MEMBASE
+        *--------------------------------------------------------------------------*/
+#if defined(CFG_PCI_MASTER_INIT)
+       pci_master_init(hose);          /* Let board setup pci master */
+#else
+       out32r( PCIX0_POM0SA, 0 ); /* disable */
+       out32r( PCIX0_POM1SA, 0 ); /* disable */
+       out32r( PCIX0_POM2SA, 0 ); /* disable */
+       out32r( PCIX0_POM0LAL, 0x00000000 );
+       out32r( PCIX0_POM0LAH, 0x00000003 );
+       out32r( PCIX0_POM0PCIAL, CFG_PCI_MEMBASE );
+       out32r( PCIX0_POM0PCIAH, 0x00000000 );
+       out32r( PCIX0_POM0SA, 0xf0000001 ); /* 256MB, enabled */
+    out32r( PCIX0_STS, in32r( PCIX0_STS ) & ~0x0000fff8 );
+#endif
+
+       /*--------------------------------------------------------------------------+
+        * PCI host configuration -- we don't make any assumptions here ... the
+     * _board_must_indicate_ what to do -- there's just too many runtime
+     * scenarios in environments like cPCI, PPMC, etc. to make a determination
+     * based on hard-coded values or state of arbiter enable.
+        *--------------------------------------------------------------------------*/
+    if( is_pci_host(hose) ){
+#ifdef CONFIG_PCI_SCAN_SHOW
+        printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+        out16r( PCIX0_CMD, in16r( PCIX0_CMD ) | PCI_COMMAND_MASTER);
+        hose->last_busno = pci_hose_scan(hose);
+    }
+}
+
+
+void pci_init(void)
+{
+       pci_440_init (&ppc440_hose);
+}
+
+#endif /* CONFIG_440 & CONFIG_PCI */
diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c
new file mode 100644 (file)
index 0000000..8aaffb1
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * (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
+ */
+
+/*
+ * m8xx.c
+ *
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <ppc4xx.h>
+
+
+#if defined(CONFIG_440)
+static int do_chip_reset( unsigned long sys0, unsigned long sys1 );
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+int checkcpu (void)
+{
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_IOP480) || defined(CONFIG_440)
+       uint pvr = get_pvr();
+#endif
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_IOP480)
+       DECLARE_GLOBAL_DATA_PTR;
+
+       ulong clock = gd->cpu_clk;
+       char buf[32];
+#endif
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
+       PPC405_SYS_INFO sys_info;
+
+       puts ("CPU:   ");
+
+       get_sys_info(&sys_info);
+
+#if CONFIG_405GP
+       puts("IBM PowerPC 405GP");
+       if (pvr == PVR_405GPR_RA) {
+               putc('r');
+       }
+       puts(" Rev. ");
+#endif
+#if CONFIG_405CR
+       puts("IBM PowerPC 405CR Rev. ");
+#endif
+       switch (pvr) {
+       case PVR_405GP_RB:
+               putc('B');
+               break;
+       case PVR_405GP_RC:
+#if CONFIG_405CR
+       case PVR_405CR_RC:
+#endif
+               putc('C');
+               break;
+       case PVR_405GP_RD:
+               putc('D');
+               break;
+#if CONFIG_405GP
+       case PVR_405GP_RE:
+               putc('E');
+               break;
+#endif
+       case PVR_405CR_RA:
+       case PVR_405GPR_RA:
+               putc('A');
+               break;
+       case PVR_405CR_RB:
+               putc('B');
+               break;
+       default:
+               printf("? (PVR=%08x)", pvr);
+               break;
+       }
+
+       printf(" at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf, clock),
+              sys_info.freqPLB / 1000000,
+              sys_info.freqPLB / sys_info.pllOpbDiv / 1000000,
+              sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000);
+
+#if CONFIG_405GP
+       if (mfdcr(strap) & PSR_PCI_ASYNC_EN)
+               printf("           PCI async ext clock used, ");
+       else
+               printf("           PCI sync clock at %lu MHz, ",
+                      sys_info.freqPLB / sys_info.pllPciDiv / 1000000);
+       if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+               printf("internal PCI arbiter enabled\n");
+       else
+               printf("external PCI arbiter enabled\n");
+#endif
+
+       if ((pvr | 0x00000001) == PVR_405GPR_RA) {
+               printf("           16 kB I-Cache 16 kB D-Cache");
+       } else {
+               printf("           16 kB I-Cache 8 kB D-Cache");
+       }
+
+
+#endif  /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
+
+#ifdef CONFIG_IOP480
+       printf("PLX IOP480 (PVR=%08x)", pvr);
+       printf(" at %s MHz:", strmhz(buf, clock));
+       printf(" %u kB I-Cache", 4);
+       printf(" %u kB D-Cache", 2);
+#endif
+
+#if defined(CONFIG_440)
+       puts("IBM PowerPC 440 Rev. ");
+       switch(pvr)
+       {
+        case PVR_440GP_RB:
+               putc('B');
+        /* See errata 1.12: CHIP_4 */
+        if(   ( mfdcr(cpc0_sys0) != mfdcr(cpc0_strp0) )
+            ||( mfdcr(cpc0_sys1) != mfdcr(cpc0_strp1) ) ){
+            puts("\n\t CPC0_SYSx DCRs corrupted. Resetting chip ...\n");
+            udelay( 1000 * 1000 ); /* Give time for serial buf to clear */
+            do_chip_reset( mfdcr(cpc0_strp0), mfdcr(cpc0_strp1) );
+        }
+               break;
+        case PVR_440GP_RC:
+               putc('C');
+               break;
+        default:
+               printf("UNKNOWN (PVR=%08x)", pvr);
+               break;
+       }
+#endif
+
+       printf("\n");
+
+       return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+        /*
+         * Initiate system reset in debug control register DBCR
+         */
+       __asm__ __volatile__("lis   3, 0x3000" ::: "r3");
+#if defined(CONFIG_440)
+       __asm__ __volatile__("mtspr 0x134, 3");
+#else
+       __asm__ __volatile__("mtspr 0x3f2, 3");
+#endif
+       return 1;
+}
+
+#if defined(CONFIG_440)
+static
+int do_chip_reset( unsigned long sys0, unsigned long sys1 )
+{
+    /* Changes to cpc0_sys0 and cpc0_sys1 require chip
+     * reset.
+     */
+    mtdcr( cntrl0, mfdcr(cntrl0) | 0x80000000 ); /* Set SWE */
+    mtdcr( cpc0_sys0, sys0 );
+    mtdcr( cpc0_sys1, sys1 );
+    mtdcr( cntrl0, mfdcr(cntrl0) & ~0x80000000 ); /* Clr SWE */
+    mtspr( dbcr0, 0x20000000);  /* Reset the chip */
+
+    return 1;
+}
+#endif
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long get_tbclk (void)
+{
+#if defined(CONFIG_440)
+
+       sys_info_t  sys_info;
+
+       get_sys_info(&sys_info);
+       return (sys_info.freqProcessor);
+
+#elif defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405)
+
+       PPC405_SYS_INFO sys_info;
+
+       get_sys_info(&sys_info);
+       return (sys_info.freqProcessor);
+
+#elif defined(CONFIG_IOP480)
+
+       return (66000000);
+
+#else
+
+# error get_tbclk() not implemented
+
+#endif
+
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void
+watchdog_reset(void)
+{
+       int re_enable = disable_interrupts();
+       reset_4xx_watchdog();
+       if (re_enable) enable_interrupts();
+}
+
+void
+reset_4xx_watchdog(void)
+{
+       /*
+        * Clear TSR(WIS) bit
+        */
+       mtspr(tsr, 0x40000000);
+}
+#endif /* CONFIG_WATCHDOG */
diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c
new file mode 100644 (file)
index 0000000..68af057
--- /dev/null
@@ -0,0 +1,417 @@
+/*****************************************************************************/
+/* I2C Bus interface initialisation and I2C Commands                         */
+/* for PPC405GP                                                                     */
+/* Author : AS HARNOIS                                                       */
+/* Date   : 13.Dec.00                                                        */
+/*****************************************************************************/
+
+#include <common.h>
+#include <ppc4xx.h>
+#if defined(CONFIG_440)
+#   include <440_i2c.h>
+#else
+#   include <405gp_i2c.h>
+#endif
+#include <i2c.h>
+
+#ifdef CONFIG_HARD_I2C
+
+#define IIC_OK         0
+#define IIC_NOK                1
+#define IIC_NOK_LA     2               /* Lost arbitration */
+#define IIC_NOK_ICT    3               /* Incomplete transfer */
+#define IIC_NOK_XFRA   4               /* Transfer aborted */
+#define IIC_NOK_DATA   5               /* No data in buffer */
+#define IIC_NOK_TOUT   6               /* Transfer timeout */
+
+#define IIC_TIMEOUT 1                  /* 1 seconde */
+
+
+static void _i2c_bus_reset (void)
+{
+       int i, status;
+
+       /* Reset status register */
+       /* write 1 in SCMP and IRQA to clear these fields */
+       out8 (IIC_STS, 0x0A);
+
+       /* write 1 in IRQP IRQD LA ICT XFRA to clear these fields */
+       out8 (IIC_EXTSTS, 0x8F);
+       __asm__ volatile ("eieio");
+
+       /*
+        * Get current state, reset bus
+        * only if no transfers are pending.
+        */
+       i = 10;
+       do {
+               /* Get status */
+               status = in8 (IIC_STS);
+               udelay (500);                   /* 500us */
+               i--;
+       } while ((status & IIC_STS_PT) && (i > 0));
+       /* Soft reset controller */
+       status = in8 (IIC_XTCNTLSS);
+       out8 (IIC_XTCNTLSS, (status | IIC_XTCNTLSS_SRST));
+       __asm__ volatile ("eieio");
+
+       /* make sure where in initial state, data hi, clock hi */
+       out8 (IIC_DIRECTCNTL, 0xC);
+       for (i = 0; i < 10; i++) {
+               if ((in8 (IIC_DIRECTCNTL) & 0x3) != 0x3) {
+                       /* clock until we get to known state */
+                       out8 (IIC_DIRECTCNTL, 0x8);     /* clock lo */
+                       udelay (100);           /* 100us */
+                       out8 (IIC_DIRECTCNTL, 0xC);     /* clock hi */
+                       udelay (100);           /* 100us */
+               } else {
+                       break;
+               }
+       }
+       /* send start condition */
+       out8 (IIC_DIRECTCNTL, 0x4);
+       udelay (1000);                          /* 1ms */
+       /* send stop condition */
+       out8 (IIC_DIRECTCNTL, 0xC);
+       udelay (1000);                          /* 1ms */
+       /* Unreset controller */
+       out8 (IIC_XTCNTLSS, (status & ~IIC_XTCNTLSS_SRST));
+       udelay (1000);                          /* 1ms */
+}
+
+void i2c_init (int speed, int slaveadd)
+{
+       sys_info_t sysInfo;
+       unsigned long freqOPB;
+       int val, divisor;
+
+       /* Handle possible failed I2C state */
+       _i2c_bus_reset ();
+
+       /* clear lo master address */
+       out8 (IIC_LMADR, 0);
+
+       /* clear hi master address */
+       out8 (IIC_HMADR, 0);
+
+       /* clear lo slave address */
+       out8 (IIC_LSADR, 0);
+
+       /* clear hi slave address */
+       out8 (IIC_HSADR, 0);
+
+       /* Clock divide Register */
+       /* get OPB frequency */
+       get_sys_info (&sysInfo);
+       freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv;
+       /* set divisor according to freqOPB */
+       divisor = (freqOPB - 1) / 10000000;
+       if (divisor == 0)
+               divisor = 1;
+       out8 (IIC_CLKDIV, divisor);
+
+       /* no interrupts */
+       out8 (IIC_INTRMSK, 0);
+
+       /* clear transfer count */
+       out8 (IIC_XFRCNT, 0);
+
+       /* clear extended control & stat */
+       /* write 1 in SRC SRS SWC SWS to clear these fields */
+       out8 (IIC_XTCNTLSS, 0xF0);
+
+       /* Mode Control Register
+          Flush Slave/Master data buffer */
+       out8 (IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB);
+       __asm__ volatile ("eieio");
+
+
+        val = in8(IIC_MDCNTL);
+        __asm__ volatile ("eieio");
+
+        /* Ignore General Call, slave transfers are ignored,
+           disable interrupts, exit unknown bus state, enable hold
+           SCL
+           100kHz normaly or FastMode for 400kHz and above
+        */
+
+        val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL;
+        if( speed >= 400000 ){
+                val |= IIC_MDCNTL_FSM;
+        }
+       out8 (IIC_MDCNTL, val);
+
+       /* clear control reg */
+       out8 (IIC_CNTL, 0x00);
+       __asm__ volatile ("eieio");
+
+}
+
+/*
+  This code tries to use the features of the 405GP i2c
+  controller. It will transfer up to 4 bytes in one pass
+  on the loop. It only does out8(lbz) to the buffer when it
+  is possible to do out16(lhz) transfers.
+
+  cmd_type is 0 for write 1 for read.
+
+  addr_len can take any value from 0-255, it is only limited
+  by the char, we could make it larger if needed. If it is
+  0 we skip the address write cycle.
+
+  Typical case is a Write of an addr followd by a Read. The
+  IBM FAQ does not cover this. On the last byte of the write
+  we don't set the creg CHT bit, and on the first bytes of the
+  read we set the RPST bit.
+
+  It does not support address only transfers, there must be
+  a data part. If you want to write the address yourself, put
+  it in the data pointer.
+
+  It does not support transfer to/from address 0.
+
+  It does not check XFRCNT.
+*/
+static
+int i2c_transfer(unsigned char cmd_type,
+                 unsigned char chip,
+                 unsigned char addr[],
+                 unsigned char addr_len,
+                 unsigned char data[],
+                unsigned short data_len )
+{
+        unsigned char* ptr;
+        int reading;
+        int tran,cnt;
+        int result;
+        int status;
+        int i;
+        uchar creg;
+
+        if( data == 0 || data_len == 0 ){
+                /*Don't support data transfer of no length or to address 0*/
+                printf( "i2c_transfer: bad call\n" );
+                return IIC_NOK;
+        }
+        if( addr && addr_len ){
+                ptr = addr;
+                cnt = addr_len;
+                reading = 0;
+        }else{
+                ptr = data;
+                cnt = data_len;
+                reading = cmd_type;
+        }
+
+        /*Clear Stop Complete Bit*/
+        out8(IIC_STS,IIC_STS_SCMP);
+        /* Check init */
+        i=10;
+        do {
+                /* Get status */
+                status = in8(IIC_STS);
+                __asm__ volatile("eieio");
+                i--;
+        } while ((status & IIC_STS_PT) && (i>0));
+
+        if (status & IIC_STS_PT) {
+                result = IIC_NOK_TOUT;
+                return(result);
+        }
+        /*flush the Master/Slave Databuffers*/
+        out8(IIC_MDCNTL, ((in8(IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB));
+        /*need to wait 4 OPB clocks? code below should take that long*/
+
+        /* 7-bit adressing */
+        out8(IIC_HMADR,0);
+        out8(IIC_LMADR, chip);
+        __asm__ volatile("eieio");
+
+        tran = 0;
+        result = IIC_OK;
+        creg = 0;
+
+        while ( tran != cnt && (result == IIC_OK)) {
+                int  bc,j;
+
+                /* Control register =
+                   Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start,
+                   Transfer is a sequence of transfers
+                */
+                creg |= IIC_CNTL_PT;
+
+                bc = (cnt - tran) > 4 ? 4 :
+                        cnt - tran;
+                creg |= (bc-1)<<4;
+                /* if the real cmd type is write continue trans*/
+                if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) )
+                        creg |= IIC_CNTL_CHT;
+
+                if (reading)
+                        creg |= IIC_CNTL_READ;
+                else {
+                        for(j=0; j<bc; j++) {
+                                /* Set buffer */
+                                out8(IIC_MDBUF,ptr[tran+j]);
+                                __asm__ volatile("eieio");
+                        }
+                }
+                out8(IIC_CNTL, creg );
+                __asm__ volatile("eieio");
+
+                /* Transfer is in progress
+                   we have to wait for upto 5 bytes of data
+                   1 byte chip address+r/w bit then bc bytes
+                   of data.
+                   udelay(10) is 1 bit time at 100khz
+                   Doubled for slop. 20 is too small.
+               */
+                i=2*5*8;
+                do {
+                        /* Get status */
+                        status = in8(IIC_STS);
+                        __asm__ volatile("eieio");
+                        udelay (10);
+                        i--;
+                } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR)
+                        && (i>0));
+
+                if (status & IIC_STS_ERR) {
+                        result = IIC_NOK;
+                        status = in8 (IIC_EXTSTS);
+                        /* Lost arbitration? */
+                        if (status & IIC_EXTSTS_LA)
+                                result = IIC_NOK_LA;
+                        /* Incomplete transfer? */
+                        if (status & IIC_EXTSTS_ICT)
+                                result = IIC_NOK_ICT;
+                        /* Transfer aborted? */
+                        if (status & IIC_EXTSTS_XFRA)
+                                result = IIC_NOK_XFRA;
+                } else if ( status & IIC_STS_PT) {
+                        result = IIC_NOK_TOUT;
+                }
+                /* Command is reading => get buffer */
+                if ((reading) && (result == IIC_OK)) {
+                        /* Are there data in buffer */
+                        if (status & IIC_STS_MDBS) {
+                                /*
+                                  even if we have data we have to wait 4OPB clocks
+                                  for it to hit the front of the FIFO, after that
+                                  we can just read. We should check XFCNT here and
+                                  if the FIFO is full there is no need to wait.
+                               */
+                                udelay (1);
+                                for(j=0;j<bc;j++) {
+                                        ptr[tran+j] = in8(IIC_MDBUF);
+                                        __asm__ volatile("eieio");
+                                }
+                        } else
+                                result = IIC_NOK_DATA;
+                }
+                creg = 0;
+                tran+=bc;
+                if( ptr == addr && tran == cnt ) {
+                        ptr = data;
+                        cnt = data_len;
+                        tran = 0;
+                        reading = cmd_type;
+                        if( reading )
+                                creg = IIC_CNTL_RPST;
+                }
+        }
+        return (result);
+}
+
+int i2c_probe (uchar chip)
+{
+       uchar buf[1];
+
+       buf[0] = 0;
+
+        /*
+         * What is needed is to send the chip address and verify that the
+         * address was <ACK>ed (i.e. there was a chip at that address which
+         * drove the data line low).
+         */
+        return(i2c_transfer (1, chip << 1, 0,0, buf, 1) != 0);
+}
+
+
+
+int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+        uchar xaddr[4];
+        int ret;
+
+       if ( alen > 4 ) {
+               printf ("I2C read: addr len %d not supported\n", alen);
+               return 1;
+       }
+
+        if ( alen > 0 ) {
+                xaddr[0] = (addr >> 24) & 0xFF;
+                xaddr[1] = (addr >> 16) & 0xFF;
+                xaddr[2] = (addr >> 8) & 0xFF;
+                xaddr[3] = addr & 0xFF;
+        }
+
+
+#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
+       /*
+         * EEPROM chips that implement "address overflow" are ones
+         * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
+         * address and the extra bits end up in the "chip address"
+         * bit slots. This makes a 24WC08 (1Kbyte) chip look like
+         * four 256 byte chips.
+        *
+         * Note that we consider the length of the address field to
+         * still be one byte because the extra address bits are
+         * hidden in the chip address.
+        */
+        if( alen > 0 )
+                chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+        if( (ret = i2c_transfer( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
+                printf( "I2c read: failed %d\n", ret);
+                return 1;
+        }
+        return 0;
+}
+
+int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+        uchar xaddr[4];
+
+       if ( alen > 4 ) {
+               printf ("I2C write: addr len %d not supported\n", alen);
+               return 1;
+
+       }
+        if ( alen > 0 ) {
+                xaddr[0] = (addr >> 24) & 0xFF;
+                xaddr[1] = (addr >> 16) & 0xFF;
+                xaddr[2] = (addr >> 8) & 0xFF;
+                xaddr[3] = addr & 0xFF;
+        }
+
+#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
+       /*
+         * EEPROM chips that implement "address overflow" are ones
+         * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
+         * address and the extra bits end up in the "chip address"
+         * bit slots. This makes a 24WC08 (1Kbyte) chip look like
+         * four 256 byte chips.
+        *
+         * Note that we consider the length of the address field to
+         * still be one byte because the extra address bits are
+         * hidden in the chip address.
+        */
+        if( alen > 0 )
+                chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+        return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/cpu/ppc4xx/sdram.c b/cpu/ppc4xx/sdram.c
new file mode 100644 (file)
index 0000000..d64bf96
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * (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 <ppc4xx.h>
+#include <asm/processor.h>
+#include <pci.h>
+
+
+#ifdef CONFIG_SDRAM_BANK0
+
+
+#define MAGIC0 0x00000000
+#define MAGIC1 0x11111111
+#define MAGIC2 0x22222222
+#define MAGIC3 0x33333333
+#define MAGIC4 0x44444444
+
+#define ADDR_ZERO 0x00000000
+#define ADDR_400  0x00000400
+#define ADDR_08MB 0x00800000
+#define ADDR_16MB 0x01000000
+#define ADDR_32MB 0x02000000
+#define ADDR_64MB 0x04000000
+
+#define mtsdram0(reg, data)  mtdcr(memcfga,reg);mtdcr(memcfgd,data)
+
+
+/*-----------------------------------------------------------------------
+ */
+void sdram_init(void)
+{
+       ulong speed;
+       ulong sdtr1;
+       ulong rtr;
+
+       /*
+        * Determine SDRAM speed
+        */
+       speed = get_bus_freq(0); /* parameter not used on ppc4xx */
+
+       /*
+        * Support for 100MHz and 133MHz SDRAM
+        */
+       if (speed > 100000000) {
+               /*
+                * 133 MHz SDRAM
+                */
+               sdtr1 = 0x01074015;
+               rtr = 0x07f00000;
+       } else {
+               /*
+                * default: 100 MHz SDRAM
+                */
+               sdtr1 = 0x0086400d;
+               rtr = 0x05f00000;
+       }
+
+       /*
+        * Set MB0CF for bank 0. (0-64MB) Address Mode 3 since 13x9(4)
+        */
+       mtsdram0(mem_mb0cf, 0x00084001);
+
+       mtsdram0(mem_sdtr1, sdtr1);
+       mtsdram0(mem_rtr, rtr);
+
+       /*
+        * Wait for 200us
+        */
+       udelay(200);
+
+       /*
+        * Set memory controller options reg, MCOPT1.
+        * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
+        * read/prefetch.
+        */
+       mtsdram0(mem_mcopt1, 0x80800000);
+
+       /*
+        * Wait for 10ms
+        */
+       udelay(10000);
+
+       /*
+        * Test if 64 MByte are equipped (mirror test)
+        */
+       *(volatile ulong *)ADDR_ZERO = MAGIC0;
+       *(volatile ulong *)ADDR_08MB = MAGIC1;
+       *(volatile ulong *)ADDR_16MB = MAGIC2;
+       *(volatile ulong *)ADDR_32MB = MAGIC3;
+
+       if ((*(volatile ulong *)ADDR_ZERO == MAGIC0) &&
+           (*(volatile ulong *)ADDR_08MB == MAGIC1) &&
+           (*(volatile ulong *)ADDR_16MB == MAGIC2)) {
+               /*
+                * OK, 64MB detected -> all done
+                */
+               return;
+       }
+
+       /*
+        * Now test for 32 MByte...
+        */
+
+        /*
+        * Disable memory controller.
+        */
+       mtsdram0(mem_mcopt1, 0x00000000);
+
+       /*
+        * Set MB0CF for bank 0. (0-32MB) Address Mode 2 since 12x9(4)
+        */
+       mtsdram0(mem_mb0cf, 0x00062001);
+
+       /*
+        * Set memory controller options reg, MCOPT1.
+        * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
+        * read/prefetch.
+        */
+       mtsdram0(mem_mcopt1, 0x80800000);
+
+       /*
+        * Wait for 10ms
+        */
+       udelay(10000);
+
+       /*
+        * Test if 32 MByte are equipped (mirror test)
+        */
+       *(volatile ulong *)ADDR_ZERO = MAGIC0;
+       *(volatile ulong *)ADDR_400  = MAGIC1;
+       *(volatile ulong *)ADDR_08MB = MAGIC2;
+       *(volatile ulong *)ADDR_16MB = MAGIC3;
+
+       if ((*(volatile ulong *)ADDR_ZERO == MAGIC0) &&
+           (*(volatile ulong *)ADDR_400  == MAGIC1) &&
+           (*(volatile ulong *)ADDR_08MB == MAGIC2)) {
+               /*
+                * OK, 32MB detected -> all done
+                */
+               return;
+       }
+
+       /*
+        * Setup for 16 MByte...
+        */
+
+        /*
+        * Disable memory controller.
+        */
+       mtsdram0(mem_mcopt1, 0x00000000);
+
+       /*
+        * Set MB0CF for bank 0. (0-16MB) Address Mode 4 since 12x8(4)
+        */
+       mtsdram0(mem_mb0cf, 0x00046001);
+
+       /*
+        * Set memory controller options reg, MCOPT1.
+        * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
+        * read/prefetch.
+        */
+       mtsdram0(mem_mcopt1, 0x80800000);
+
+       /*
+        * Wait for 10ms
+        */
+       udelay(10000);
+}
+
+#endif /* CONFIG_SDRAM_BANK0 */
diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c
new file mode 100644 (file)
index 0000000..4541529
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * (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 <ppc_asm.tmpl>
+#include <ppc4xx.h>
+#include <asm/processor.h>
+
+/* ------------------------------------------------------------------------- */
+
+#define ONE_BILLION        1000000000
+
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
+
+void get_sys_info (PPC405_SYS_INFO * sysInfo)
+{
+       unsigned long pllmr;
+       unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
+       uint pvr = get_pvr();
+       unsigned long psr;
+       unsigned long m;
+
+       /*
+        * Read PLL Mode register
+        */
+       pllmr = mfdcr (pllmd);
+
+       /*
+        * Read Pin Strapping register
+        */
+       psr = mfdcr (strap);
+
+       /*
+        * Determine FWD_DIV.
+        */
+       sysInfo->pllFwdDiv = 8 - ((pllmr & PLLMR_FWD_DIV_MASK) >> 29);
+
+       /*
+        * Determine FBK_DIV.
+        */
+       sysInfo->pllFbkDiv = ((pllmr & PLLMR_FB_DIV_MASK) >> 25);
+       if (sysInfo->pllFbkDiv == 0) {
+               sysInfo->pllFbkDiv = 16;
+       }
+
+       /*
+        * Determine PLB_DIV.
+        */
+       sysInfo->pllPlbDiv = ((pllmr & PLLMR_CPU_TO_PLB_MASK) >> 17) + 1;
+
+       /*
+        * Determine PCI_DIV.
+        */
+       sysInfo->pllPciDiv = ((pllmr & PLLMR_PCI_TO_PLB_MASK) >> 13) + 1;
+
+       /*
+        * Determine EXTBUS_DIV.
+        */
+       sysInfo->pllExtBusDiv = ((pllmr & PLLMR_EXB_TO_PLB_MASK) >> 11) + 2;
+
+       /*
+        * Determine OPB_DIV.
+        */
+       sysInfo->pllOpbDiv = ((pllmr & PLLMR_OPB_TO_PLB_MASK) >> 15) + 1;
+
+       /*
+        * Check if PPC405GPr used (mask minor revision field)
+        */
+       if ((pvr & 0xfffffff0) == (PVR_405GPR_RA & 0xfffffff0)) {
+               /*
+                * Determine FWD_DIV B (only PPC405GPr with new mode strapping).
+                */
+               sysInfo->pllFwdDivB = 8 - (pllmr & PLLMR_FWDB_DIV_MASK);
+
+               /*
+                * Determine factor m depending on PLL feedback clock source
+                */
+               if (!(psr & PSR_PCI_ASYNC_EN)) {
+                       if (psr & PSR_NEW_MODE_EN) {
+                               /*
+                                * sync pci clock used as feedback (new mode)
+                                */
+                               m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllPciDiv;
+                       } else {
+                               /*
+                                * sync pci clock used as feedback (legacy mode)
+                                */
+                               m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllPciDiv;
+                       }
+               } else if (psr & PSR_NEW_MODE_EN) {
+                       if (psr & PSR_PERCLK_SYNC_MODE_EN) {
+                               /*
+                                * PerClk used as feedback (new mode)
+                                */
+                               m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllExtBusDiv;
+                       } else {
+                               /*
+                                * CPU clock used as feedback (new mode)
+                                */
+                               m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
+                       }
+               } else if (sysInfo->pllExtBusDiv == sysInfo->pllFbkDiv) {
+                       /*
+                        * PerClk used as feedback (legacy mode)
+                        */
+                       m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllExtBusDiv;
+               } else {
+                       /*
+                        * PLB clock used as feedback (legacy mode)
+                        */
+                       m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv;
+               }
+
+               sysInfo->freqVCOMhz = (1000000 * m) / sysClkPeriodPs;
+               sysInfo->freqProcessor = (sysInfo->freqVCOMhz * 1000000) / sysInfo->pllFwdDiv;
+               sysInfo->freqPLB = (sysInfo->freqVCOMhz * 1000000) /
+                       (sysInfo->pllFwdDivB * sysInfo->pllPlbDiv);
+       } else {
+               /*
+                * Check pllFwdDiv to see if running in bypass mode where the CPU speed
+                * is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO
+                * to make sure it is within the proper range.
+                *    spec:    VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV
+                * Note freqVCO is calculated in Mhz to avoid errors introduced by rounding.
+                */
+               if (sysInfo->pllFwdDiv == 1) {
+                       sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ;
+                       sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv;
+               } else {
+                       sysInfo->freqVCOMhz = ( 1000000 *
+                                               sysInfo->pllFwdDiv *
+                                               sysInfo->pllFbkDiv *
+                                               sysInfo->pllPlbDiv
+                               ) / sysClkPeriodPs;
+                       if (sysInfo->freqVCOMhz >= VCO_MIN
+                           && sysInfo->freqVCOMhz <= VCO_MAX) {
+                               sysInfo->freqPLB = (ONE_BILLION /
+                                                   ((sysClkPeriodPs * 10) /
+                                                    sysInfo->pllFbkDiv)) * 10000;
+                               sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv;
+                       } else {
+                               printf ("\nInvalid VCO frequency calculated :  %ld MHz \a\n",
+                                       sysInfo->freqVCOMhz);
+                               printf ("It must be between %d-%d MHz \a\n",
+                                       VCO_MIN, VCO_MAX);
+                               printf ("PLL Mode reg           :  %8.8lx\a\n",
+                                       pllmr);
+                               hang ();
+                       }
+               }
+       }
+}
+
+
+/********************************************
+ * get_OPB_freq
+ * return OPB bus freq in Hz
+ *********************************************/
+ulong get_OPB_freq (void)
+{
+       ulong val = 0;
+
+       PPC405_SYS_INFO sys_info;
+
+       get_sys_info (&sys_info);
+       val = sys_info.freqPLB / sys_info.pllOpbDiv;
+
+       return val;
+}
+
+
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+       ulong val;
+       PPC405_SYS_INFO sys_info;
+
+       get_sys_info (&sys_info);
+       val = sys_info.freqPLB / sys_info.pllPciDiv;
+       return val;
+}
+
+
+#elif defined(CONFIG_440)
+void get_sys_info (sys_info_t * sysInfo)
+{
+       unsigned long strp0;
+       unsigned long temp;
+       unsigned long m;
+
+       /* Extract configured divisors */
+       strp0 = mfdcr( cpc0_strp0 );
+       sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15);
+       sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12);
+       temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18;
+       sysInfo->pllFbkDiv = temp ? temp : 16;
+       sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10);
+       sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8);
+
+       /* Calculate 'M' based on feedback source */
+       if( strp0 & PLLSYS0_EXTSL_MASK )
+               m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+       else
+               m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+
+       /* Now calculate the individual clocks */
+       sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
+       sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+       sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
+    if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
+        sysInfo->freqPLB >>= 1;
+       sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+       sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
+
+}
+
+ulong get_OPB_freq (void)
+{
+
+       sys_info_t sys_info;
+       get_sys_info (&sys_info);
+       return sys_info.freqOPB;
+}
+
+#elif defined(CONFIG_405)
+
+void get_sys_info (sys_info_t * sysInfo) {
+
+       sysInfo->freqVCOMhz=3125000;
+       sysInfo->freqProcessor=12*1000*1000;
+       sysInfo->freqPLB=50*1000*1000;
+       sysInfo->freqPCI=66*1000*1000;
+
+}
+
+#endif
+
+int get_clocks (void)
+{
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || defined(CONFIG_405)
+       DECLARE_GLOBAL_DATA_PTR;
+
+       sys_info_t sys_info;
+
+       get_sys_info (&sys_info);
+       gd->cpu_clk = sys_info.freqProcessor;
+       gd->bus_clk = sys_info.freqPLB;
+
+#endif /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
+
+#ifdef CONFIG_IOP480
+       DECLARE_GLOBAL_DATA_PTR;
+
+       gd->cpu_clk = 66000000;
+       gd->bus_clk = 66000000;
+#endif
+       return (0);
+}
+
+
+/********************************************
+ * get_bus_freq
+ * return PLB bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+       ulong val;
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405) || defined(CONFIG_440)
+       sys_info_t sys_info;
+
+       get_sys_info (&sys_info);
+       val = sys_info.freqPLB;
+
+#elif defined(CONFIG_IOP480)
+
+       val = 66;
+
+#else
+# error get_bus_freq() not implemented
+#endif
+
+       return val;
+}
diff --git a/cpu/ppc4xx/vecnum.h b/cpu/ppc4xx/vecnum.h
new file mode 100644 (file)
index 0000000..d493a5d
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+*  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
+*/
+
+/*
+ * Interrupt vector number definitions to ease the
+ * 405 -- 440 porting pain ;-)
+ *
+ * NOTE: They're not all here yet ... update as needed.
+ *
+ */
+
+#ifndef _VECNUMS_H_
+#define _VECNUMS_H_
+
+#if defined(CONFIG_440)
+
+/* UIC 0 */
+#define VECNUM_U0           0           /* UART0                        */
+#define VECNUM_U1           1           /* UART1                        */
+#define VECNUM_IIC0         2           /* IIC0                         */
+#define VECNUM_IIC1         3           /* IIC1                         */
+#define VECNUM_PIM          4           /* PCI inbound message          */
+#define VECNUM_PCRW         5           /* PCI command reg write        */
+#define VECNUM_PPM          6           /* PCI power management         */
+#define VECNUM_MSI0         7           /* PCI MSI level 0              */
+#define VECNUM_MSI1         8           /* PCI MSI level 0              */
+#define VECNUM_MSI2         9           /* PCI MSI level 0              */
+#define VECNUM_MTE          10          /* MAL TXEOB                    */
+#define VECNUM_MRE          11          /* MAL RXEOB                    */
+#define VECNUM_D0           12          /* DMA channel 0                */
+#define VECNUM_D1           13          /* DMA channel 1                */
+#define VECNUM_D2           14          /* DMA channel 2                */
+#define VECNUM_D3           15          /* DMA channel 3                */
+#define VECNUM_CT0          18          /* GPT compare timer 0          */
+#define VECNUM_CT1          19          /* GPT compare timer 1          */
+#define VECNUM_CT2          20          /* GPT compare timer 2          */
+#define VECNUM_CT3          21          /* GPT compare timer 3          */
+#define VECNUM_CT4          22          /* GPT compare timer 4          */
+#define VECNUM_EIR0         23          /* External interrupt 0         */
+#define VECNUM_EIR1         24          /* External interrupt 1         */
+#define VECNUM_EIR2         25          /* External interrupt 2         */
+#define VECNUM_EIR3         26          /* External interrupt 3         */
+#define VECNUM_EIR4         27          /* External interrupt 4         */
+#define VECNUM_EIR5         28          /* External interrupt 5         */
+#define VECNUM_EIR6         29          /* External interrupt 6         */
+#define VECNUM_UIC1NC       30          /* UIC1 non-critical interrupt  */
+#define VECNUM_UIC1C        31          /* UIC1 critical interrupt      */
+
+/* UIC 1 */
+#define VECNUM_MS           (32 + 0 )   /* MAL SERR                     */
+#define VECNUM_TXDE         (32 + 1 )   /* MAL TXDE                     */
+#define VECNUM_RXDE         (32 + 2 )   /* MAL RXDE                     */
+#define VECNUM_ETH0         (32 + 28)   /* Ethernet 0 interrupt status  */
+#define VECNUM_EWU0         (32 + 29)   /* Ethernet 0 wakeup            */
+
+#else /* !defined(CONFIG_440) */
+
+#define VECNUM_U0           0           /* UART0                        */
+#define VECNUM_U1           1           /* UART1                        */
+#define VECNUM_D0           5           /* DMA channel 0                */
+#define VECNUM_D1           6           /* DMA channel 1                */
+#define VECNUM_D2           7           /* DMA channel 2                */
+#define VECNUM_D3           8           /* DMA channel 3                */
+#define VECNUM_EWU0         9           /* Ethernet wakeup              */
+#define VECNUM_MS           10          /* MAL SERR                     */
+#define VECNUM_MTE          11          /* MAL TXEOB                    */
+#define VECNUM_MRE          12          /* MAL RXEOB                    */
+#define VECNUM_TXDE         13          /* MAL TXDE                     */
+#define VECNUM_RXDE         14          /* MAL RXDE                     */
+#define VECNUM_ETH0         15          /* Ethernet interrupt status    */
+#define VECNUM_EIR0         25          /* External interrupt 0         */
+#define VECNUM_EIR1         26          /* External interrupt 1         */
+#define VECNUM_EIR2         27          /* External interrupt 2         */
+#define VECNUM_EIR3         28          /* External interrupt 3         */
+#define VECNUM_EIR4         29          /* External interrupt 4         */
+#define VECNUM_EIR5         30          /* External interrupt 5         */
+#define VECNUM_EIR6         31          /* External interrupt 6         */
+
+#endif /* defined(CONFIG_440) */
+
+#endif /* _VECNUMS_H_ */
diff --git a/cpu/sa1100/Makefile b/cpu/sa1100/Makefile
new file mode 100644 (file)
index 0000000..8c950da
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# (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$(CPU).a
+
+START  = start.o
+OBJS   = serial.o interrupts.o cpu.o
+
+all:   .depend $(START) $(LIB)
+
+$(LIB):        $(OBJS)
+       $(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend:       Makefile $(START:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/cpu/xscale/serial.c b/cpu/xscale/serial.c
new file mode 100644 (file)
index 0000000..35302a7
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * 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/arch/pxa-regs.h>
+
+void serial_setbrg (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       unsigned int quot = 0;
+
+       if (gd->baudrate == 1200)
+               quot = 192;
+       else if (gd->baudrate == 9600)
+               quot = 96;
+       else if (gd->baudrate == 19200)
+               quot = 48;
+       else if (gd->baudrate == 38400)
+               quot = 24;
+       else if (gd->baudrate == 57600)
+               quot = 16;
+       else if (gd->baudrate == 115200)
+               quot = 8;
+       else
+               hang ();
+
+#ifdef CONFIG_FFUART
+
+       CKEN |= CKEN6_FFUART;
+
+       FFIER = 0;                                      /* Disable for now */
+       FFFCR = 0;                                      /* No fifos enabled */
+
+       /* set baud rate */
+       FFLCR = LCR_WLS0 | LCR_WLS1 | LCR_DLAB;
+       FFDLL = quot & 0xff;
+       FFDLH = quot >> 8;
+       FFLCR = LCR_WLS0 | LCR_WLS1;
+
+       FFIER = IER_UUE;                        /* Enable FFUART */
+
+#elif CONFIG_STUART
+#error "Bad: not implemented yet!"
+#else
+#error "Bad: you didn't configured serial ..."
+#endif
+}
+
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+       serial_setbrg ();
+
+       return (0);
+}
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+#ifdef CONFIG_FFUART
+       /* wait for room in the tx FIFO on FFUART */
+       while ((FFLSR & LSR_TEMT) == 0);
+
+       FFTHR = c;
+#elif CONFIG_STUART
+#endif
+
+       /* If \n, also do \r */
+       if (c == '\n')
+               serial_putc ('\r');
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_tstc (void)
+{
+#ifdef CONFIG_FFUART
+       return FFLSR & LSR_DR;
+#elif CONFIG_STUART
+#endif
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+#ifdef CONFIG_FFUART
+       while (!(FFLSR & LSR_DR));
+
+       return (char) FFRBR & 0xff;
+#elif CONFIG_STUART
+#endif
+}
+
+void
+serial_puts (const char *s)
+{
+       while (*s) {
+               serial_putc (*s++);
+       }
+}
diff --git a/cpu/xscale/start.S b/cpu/xscale/start.S
new file mode 100644 (file)
index 0000000..f1049a8
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ *  armboot - Startup Code for XScale
+ *
+ *  Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000 Wolfgang Denk <wd@denx.de>
+ *  Copyright (c) 2001 Alex Züpke <azu@sysgo.de>
+ *  Copyright (c) 2002 Kyle Harris <kharris@nexus-tech.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 <version.h>
+
+.globl _start
+_start:        b       reset
+       ldr     pc, _undefined_instruction
+       ldr     pc, _software_interrupt
+       ldr     pc, _prefetch_abort
+       ldr     pc, _data_abort
+       ldr     pc, _not_used
+       ldr     pc, _irq
+       ldr     pc, _fiq
+
+_undefined_instruction:        .word undefined_instruction
+_software_interrupt:   .word software_interrupt
+_prefetch_abort:       .word prefetch_abort
+_data_abort:           .word data_abort
+_not_used:             .word not_used
+_irq:                  .word irq
+_fiq:                  .word fiq
+
+       .balignl 16,0xdeadbeef
+
+
+/*
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * - relocate armboot to ram
+ * - setup stack
+ * - jump to second stage
+ */
+
+/*
+ * CFG_MEM_END is in the board dependent config-file (configs/config_BOARD.h)
+ */
+_TEXT_BASE:
+       .word   TEXT_BASE
+
+.globl _armboot_start
+_armboot_start:
+       .word _start
+
+/*
+ * Note: _armboot_end_data and _armboot_end are defined
+ * by the (board-dependent) linker script.
+ * _armboot_end_data is the first usable FLASH address after armboot
+ */
+.globl _armboot_end_data
+_armboot_end_data:
+       .word armboot_end_data
+.globl _armboot_end
+_armboot_end:
+       .word armboot_end
+
+/*
+ * _armboot_real_end is the first usable RAM address behind armboot
+ * and the various stacks
+ */
+.globl _armboot_real_end
+_armboot_real_end:
+       .word 0x0badc0de
+
+/*
+ * We relocate uboot to this address (end of RAM - 128 KiB)
+ */
+.globl _uboot_reloc
+_uboot_reloc:
+       .word CFG_DRAM_BASE + CFG_DRAM_SIZE - CFG_MONITOR_LEN
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+       .word   0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+       .word 0x0badc0de
+#endif
+
+
+/****************************************************************************/
+/*                                                                          */
+/* the actual reset code                                                    */
+/*                                                                          */
+/****************************************************************************/
+
+reset:
+       mrs     r0,cpsr                 /* set the cpu to SVC32 mode        */
+       bic     r0,r0,#0x1f             /* (superviser mode, M=10011)       */
+       orr     r0,r0,#0x13
+       msr     cpsr,r0
+
+       bl      cpu_init_crit           /* we do sys-critical inits         */
+
+relocate:                              /* relocate U-Boot to RAM          */
+       adr     r0, _start              /* r0 <- current position of code */
+       ldr     r2, _armboot_start
+       ldr     r3, _armboot_end
+       sub     r2, r3, r2              /* r2 <- size of armboot */
+/*     ldr     r1, _uboot_reloc        / * r1 <- destination address        */
+       ldr     r1, _TEXT_BASE
+       add     r2, r0, r2              /* r2 <- source end address */
+
+copy_loop:
+       ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
+       stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
+       cmp     r0, r2                  /* until source end addreee [r2]    */
+       ble     copy_loop
+
+       /* Set up the stack                                                 */
+       ldr     r0, _uboot_reloc        /* upper 128 KiB: relocated uboot   */
+       sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
+                                       /* FIXME: bdinfo should be here     */
+       sub     sp, r0, #12             /* leave 3 words for abort-stack */
+
+       ldr     pc, _start_armboot
+
+_start_armboot:        .word start_armboot
+
+
+/****************************************************************************/
+/*                                                                          */
+/* CPU_init_critical registers                                              */
+/*                                                                          */
+/* - setup important registers                                              */
+/* - setup memory timing                                                    */
+/*                                                                          */
+/****************************************************************************/
+
+       /* Interrupt-Controller base address                                */
+IC_BASE:          .word           0x40d00000
+#define ICMR   0x04
+
+/* Reset-Controller */
+RST_BASE:      .word   0x40f00030
+#define RCSR   0x00
+
+
+       /* Clock Manager Registers                                          */
+CC_BASE:               .word   0x41300000
+#define CCCR    0x00
+cpuspeed:      .word   CFG_CPUSPEED
+
+       /* RS: ???                                                          */
+       .macro CPWAIT
+    mrc  p15,0,r0,c2,c0,0
+       mov  r0,r0
+       sub  pc,pc,#4
+       .endm
+
+
+cpu_init_crit:
+
+       /* mask all IRQs                                                    */
+       ldr     r0, IC_BASE
+       mov     r1, #0x00
+       str     r1, [r0, #ICMR]
+
+       /* set clock speed */
+       ldr     r0, CC_BASE
+       ldr     r1, cpuspeed
+       str     r1, [r0, #CCCR]
+
+       /*
+        * before relocating, we have to setup RAM timing
+        * because memory timing is board-dependend, you will
+        * find a memsetup.S in your board directory.
+        */
+       mov     ip,     lr
+       bl      memsetup
+       mov     lr,     ip
+
+       /* Memory interfaces are working. Disable MMU and enable I-cache.   */
+
+       ldr     r0, =0x2001             /* enable access to all coproc.     */
+       mcr     p15, 0, r0, c15, c1, 0
+    CPWAIT
+
+       mcr     p15, 0, r0, c7, c10, 4  /* drain the write & fill buffers   */
+    CPWAIT
+
+       mcr     p15, 0, r0, c7, c7, 0   /* flush Icache, Dcache and BTB     */
+    CPWAIT
+
+       mcr     p15, 0, r0, c8, c7, 0   /* flush instuction and data TLBs   */
+    CPWAIT
+
+       /* Enable the Icache                                                */
+/*
+       mrc     p15, 0, r0, c1, c0, 0
+       orr     r0, r0, #0x1800
+       mcr     p15, 0, r0, c1, c0, 0
+    CPWAIT
+*/
+       mov     pc, lr
+
+
+/****************************************************************************/
+/*                                                                          */
+/* Interrupt handling                                                       */
+/*                                                                          */
+/****************************************************************************/
+
+/* IRQ stack frame                                                          */
+
+#define S_FRAME_SIZE   72
+
+#define S_OLD_R0       68
+#define S_PSR          64
+#define S_PC           60
+#define S_LR           56
+#define S_SP           52
+
+#define S_IP           48
+#define S_FP           44
+#define S_R10          40
+#define S_R9           36
+#define S_R8           32
+#define S_R7           28
+#define S_R6           24
+#define S_R5           20
+#define S_R4           16
+#define S_R3           12
+#define S_R2           8
+#define S_R1           4
+#define S_R0           0
+
+#define MODE_SVC 0x13
+
+       /* use bad_save_user_regs for abort/prefetch/undef/swi ...          */
+
+       .macro  bad_save_user_regs
+       sub     sp, sp, #S_FRAME_SIZE
+       stmia   sp, {r0 - r12}                  /* Calling r0-r12           */
+       add     r8, sp, #S_PC
+
+       ldr     r2, _armboot_end
+       add     r2, r2, #CONFIG_STACKSIZE
+       sub     r2, r2, #8
+       ldmia   r2, {r2 - r4}                   /* get pc, cpsr, old_r0     */
+       add     r0, sp, #S_FRAME_SIZE           /* restore sp_SVC           */
+
+       add     r5, sp, #S_SP
+       mov     r1, lr
+       stmia   r5, {r0 - r4}                   /* save sp_SVC, lr_SVC, pc, cpsr, old_r */
+       mov     r0, sp
+       .endm
+
+
+       /* use irq_save_user_regs / irq_restore_user_regs for                */
+       /* IRQ/FIQ handling                                                  */
+
+       .macro  irq_save_user_regs
+       sub     sp, sp, #S_FRAME_SIZE
+       stmia   sp, {r0 - r12}                  /* Calling r0-r12            */
+       add     r8, sp, #S_PC
+       stmdb   r8, {sp, lr}^                   /* Calling SP, LR            */
+       str     lr, [r8, #0]                    /* Save calling PC           */
+       mrs     r6, spsr
+       str     r6, [r8, #4]                    /* Save CPSR                 */
+       str     r0, [r8, #8]                    /* Save OLD_R0               */
+       mov     r0, sp
+       .endm
+
+       .macro  irq_restore_user_regs
+       ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
+       mov     r0, r0
+       ldr     lr, [sp, #S_PC]                 @ Get PC
+       add     sp, sp, #S_FRAME_SIZE
+       subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
+       .endm
+
+       .macro get_bad_stack
+       ldr     r13, _armboot_end               @ setup our mode stack
+       add     r13, r13, #CONFIG_STACKSIZE     @ resides at top of normal stack
+       sub     r13, r13, #8
+
+       str     lr, [r13]                       @ save caller lr / spsr
+       mrs     lr, spsr
+       str     lr, [r13, #4]
+
+       mov     r13, #MODE_SVC                  @ prepare SVC-Mode
+       msr     spsr_c, r13
+       mov     lr, pc
+       movs    pc, lr
+       .endm
+
+       .macro get_irq_stack                    @ setup IRQ stack
+       ldr     sp, IRQ_STACK_START
+       .endm
+
+       .macro get_fiq_stack                    @ setup FIQ stack
+       ldr     sp, FIQ_STACK_START
+       .endm
+
+
+/****************************************************************************/
+/*                                                                          */
+/* exception handlers                                                       */
+/*                                                                          */
+/****************************************************************************/
+
+       .align  5
+undefined_instruction:
+       get_bad_stack
+       bad_save_user_regs
+       bl      do_undefined_instruction
+
+       .align  5
+software_interrupt:
+       get_bad_stack
+       bad_save_user_regs
+       bl      do_software_interrupt
+
+       .align  5
+prefetch_abort:
+       get_bad_stack
+       bad_save_user_regs
+       bl      do_prefetch_abort
+
+       .align  5
+data_abort:
+       get_bad_stack
+       bad_save_user_regs
+       bl      do_data_abort
+
+       .align  5
+not_used:
+       get_bad_stack
+       bad_save_user_regs
+       bl      do_not_used
+
+#ifdef CONFIG_USE_IRQ
+
+       .align  5
+irq:
+       get_irq_stack
+       irq_save_user_regs
+       bl      do_irq
+       irq_restore_user_regs
+
+       .align  5
+fiq:
+       get_fiq_stack
+       irq_save_user_regs              /* someone ought to write a more    */
+       bl      do_fiq                  /* effiction fiq_save_user_regs     */
+       irq_restore_user_regs
+
+#else
+
+       .align  5
+irq:
+       get_bad_stack
+       bad_save_user_regs
+       bl      do_irq
+
+       .align  5
+fiq:
+       get_bad_stack
+       bad_save_user_regs
+       bl      do_fiq
+
+#endif
+
+/*
+ * FIXME How do we reset??? Watchdog timeout??
+ */
+       .align  5
+.globl reset_cpu
+reset_cpu:
+       /*
+       ldr     r0, RST_BASE
+       mov     r1, #0x0                        @ set bit 3-0 ...
+       str     r1, [r0, #RCSR]                 @ ... to clear in RCSR
+       mov     r1, #0x1
+       str     r1, [r0, #RCSR]                 @ and perform reset
+       */
+       b       reset_cpu                       @ silly, but repeat endlessly
+
diff --git a/doc/README.JFFS2 b/doc/README.JFFS2
new file mode 100644 (file)
index 0000000..0d39c46
--- /dev/null
@@ -0,0 +1,68 @@
+JFFS2 options and usage.
+-----------------------
+
+JFFS2 in U-Boot is a read only implementation of the file system in
+Linux with the same name. To use JFFS2 define CFG_CMD_JFFS2.
+
+The module adds three new commands.
+fsload  - load binary file from a file system image
+fsinfo  - print information about file systems
+ls      - list files in a directory
+
+
+There is two ways for JFFS2 to find the disk. The default way uses
+the flash_info structure to find the start of a JFFS2 disk (called
+partition in the code) and you can change where the partition is with
+two defines.
+
+CFG_JFFS2_FIRST_BANK
+       defined the first flash bank to use
+
+CFG_JFFS2_FIRST_SECTOR
+       defines the first sector to use
+
+
+The second way is to define CFG_JFFS_CUSTOM_PART and implement the
+jffs2_part_info(int part_num) function in your board specific files.
+In this mode CFG_JFFS2_FIRST_BANK and CFG_JFFS2_FIRST_SECTOR is not
+used.
+
+The input is a partition number starting with 0.
+Return a pointer to struct part_info or NULL for error;
+
+Ex jffs2_part_info() for one partition.
+---
+#if defined CFG_JFFS_CUSTOM_PART
+#include <jffs2/jffs2.h>
+
+static struct part_info part;
+
+struct part_info*
+jffs2_part_info(int part_num)
+{
+       if(part_num==0){
+               if(part.usr_priv==(void*)1)
+                       return &part;
+
+               memset(&part, 0, sizeof(part));
+               part.offset=(char*)0xFF800000;
+               part.size=1024*1024*8;
+
+               /* Mark the struct as ready */
+               part.usr_priv=(void*)1;
+
+               return &part;
+       }
+       return 0;
+}
+#endif
+---
+
+TODO.
+
+        Add a new command so it's actually possible to change
+       partition.
+
+        Remove the assumption that JFFS can dereference a pointer
+        into the disk. The current code do not work with memory holes
+        or hardware with a sliding window (PCMCIA).
diff --git a/doc/README.Modem b/doc/README.Modem
new file mode 100644 (file)
index 0000000..a3ba7b7
--- /dev/null
@@ -0,0 +1,73 @@
+How to configure modem support in U-Boot :
+
+1. Define modem initialization strings:
+---------------------------------------
+
+The modem initialization strings have following format:
+
+       mdm_init1=<AT-command>
+       mdm_init2=<AT-command>
+       ...
+
+Turning off modem verbose responses with ATV0 or ATQ1 is not allowed;
+U-Boot analyzes only verbose (not numeric) result codes. Modem local
+command echo can be turned off (ATE0).
+
+2. RTS/CTS hardware flow control:
+---------------------------------
+
+You may wish to enable RTS/CTS hardware flow control, if the board's
+UART driver supports it (see CONFIG_HWFLOW compile-time flag in
+config/<board>.h). This is controlled by the 'mdm_flow_control'
+environment variable:
+
+       'mdm_flow_control=rts/cts'  - to enable RTS/CTS flow control.
+       'mdm_flow_control=none '    - to disable.
+
+
+The following are the examples using a Rockwell OEM modem
+configuration:
+
+SAMSUNG # setenv mdm_init1 ATZ                 - reset the modem to
+                                                 the factory defaults.
+SAMSUNG # setenv mdm_init2 ATS0=1               - set modem into
+                                                 answer mode.
+SAMSUNG # setenv mdm_flow_control rts/cts       - enable serial port
+                                                 flow control
+SAMSUNG # saveenv
+
+The example above initializes modem into answer mode to wait for the
+incoming call. RTS/CTS flow control is enabled for the serial port.
+(The RTS/CTS flow control is enabled by default on the modem).
+
+
+SAMSUNG # setenv mdm_init1 ATZ
+SAMSUNG # setenv mdm_init2 ATS39=0+IFC=0,0     - disable modem
+                                                 RTS/CTS flow control
+SAMSUNG # setenv mdm_init3 ATDT1643973         -  dial out the number
+SAMSUNG # setenv mdm_flow_control none
+SAMSUNG # saveenv
+
+The example above initializes modem to dial-up connection on the
+number 1643973. Flow control is disabled.
+
+Note that flow control must be turned both off or both on for the
+board serial port and for the modem.
+
+
+If the connection was set up successfully, the U-Boot prompt appears
+on the terminal console. If not (U-Boot modem was configured for
+originating the call and connection was not established) - the board
+should be reset for another dial-up try.
+
+
+Note on the SMDK2400 board:
+---------------------------
+
+Since the board serial ports does not have DTR signal wired, modem
+should be told to ignore port DTR setting prior to connection to the
+SMDK board, and this setting should be stored in modem NVRAM. For the
+Rockwell OEM modem this can to be done with the following command:
+
+AT&D0&W
+
diff --git a/doc/README.commands b/doc/README.commands
new file mode 100644 (file)
index 0000000..576186e
--- /dev/null
@@ -0,0 +1,99 @@
+#
+# The commands in this table are sorted alphabetically by the
+# command name and in descending order by the command name string
+# length. This is to prevent conflicts in command name parsing.
+# Please ensure that new commands are added according to that rule.
+# See $(TOPDIR)/common/command.c
+#
+########################
+#
+# command      length
+#
+########################
+askenv         8
+as             2
+autoscr                5
+base           2
+bdinfo         2
+bootelf                7
+bootm          5
+bootp          5
+bootvx         6
+bootd          4
+break          2
+brginfo                3
+carinfo                3
+chpart         6
+cmp            3
+coninfo                5
+continue       4
+cp             2
+crc32          3
+date           3
+dcache         2
+dhcp           4
+dmainfo                3
+ds             2
+dtt            3
+echo           4
+eeprom         3
+erase          3
+fccinfo                3
+fdcboot                4
+flinfo         3
+fpga           4
+fsinfo         5
+fsload         5
+getdcr         6               # IBM 4XX DCR registers
+go             2
+help           1
+i2cinfo                4
+i2c            3
+icache         2
+icinfo         3
+ide            3
+iminfo         3
+iopinfo                3
+irqinfo                3
+kgdb           4
+loadb          5
+loads          5
+loop           4
+ls             2
+mccinfo                3
+md             2
+memcinfo       4
+mii            3
+mm             2
+mtest          5
+muxinfo                3
+mw             2
+next           4
+nm             2
+pciinfo                3
+pinit          4
+printenv       8
+protect                4
+rarpboot       4
+rdump          5
+reginfo                3
+reset          5
+run            3
+saveenv                4
+sccinfo                3
+scsiboot       5
+scsi           4
+siiinfo                3
+sitinfo                3
+siuinfo                3
+setdcr         6               # IBM 4XX DCR registers
+setenv         6
+smcinfo                3
+spiinfo                3
+stack          5
+step           4
+tftpboot       4
+usbboot                5
+usb            4
+version                4
+?              1
diff --git a/doc/README.ebony b/doc/README.ebony
new file mode 100644 (file)
index 0000000..12a0d70
--- /dev/null
@@ -0,0 +1,138 @@
+                           IBM Ebony Board
+
+                    Last Update: September 12, 2002
+=======================================================================
+
+This file contains some handy info regarding U-Boot and the IBM
+Ebony evalutation board. See the README.ppc440 for additional
+information.
+
+
+SWITCH SETTINGS & JUMPERS
+==========================
+
+Here's what I've been using successfully. If you feel inclined to
+change things ... please read the docs!
+
+DIPSW   U46         U80
+------------------------
+SW 1    off         on
+SW 2    on          on
+SW 3    on          on
+SW 4    off         on
+SW 5    on          off
+SW 6    on          on
+SW 7    on          off
+SW 8    on          off
+
+J41: strapped
+J42: open
+
+All others are factory default.
+
+
+I2C iprobe
+=====================
+
+The i2c utilities have been tested on both Rev B. and Rev C. and
+look good. The CFG_I2C_NOPROBES macro is defined to prevent
+probing the CDCV850 clock controller at address 0x69 (since reading
+it causes the i2c implementation to misbehave. The output of
+iprobe should look like this (assuming you are only using a single
+SO-DIMM:
+
+=> iprobe
+Valid chip addresses: 50 53 54
+Excluded chip addresses: 69
+
+
+GETTING OUT OF I2C TROUBLE
+===========================
+
+If you're like me ... you may have screwed up your bootstrap serial
+eeprom ... or worse, your SPD eeprom when experimenting with the
+i2c commands. If so, here are some ideas on how to get out of
+trouble:
+
+Serial bootstrap eeprom corruption:
+-----------------------------------
+Power down the board and set the following straps:
+
+J41 - open
+J42 - strapped
+
+This will select the default sys0 and sys1 settings (the serial
+eeproms are not used). Then power up the board and fix the serial
+eeprom using the imm command. Here are the values I currently
+use:
+
+=> imd 50 0 10
+0000: bf a2 04 01 ae 94 11 00 00 00 00 00 00 00 00 00    ................
+
+=> imd 54 0 10
+0000: 8f b3 24 01 4d 14 11 00 00 00 00 00 00 00 00 00    ..$.M...........
+
+Once you have the eeproms set correctly change the
+J41/J42 straps as you desire.
+
+SPD eeprom corruption:
+------------------------
+I've corrupted the SPD eeprom several times ... perhaps too much coffee
+and not enough presence of mind ;-). By default, the ebony code uses
+the SPD to initialize the DDR SDRAM control registers. So if the SPD
+eeprom is corrupted, U-Boot will never get into ram. Here's how I got
+out of this situation:
+
+0. First, _before_ playing with the i2c utilities, do an iprobe, then
+use imd to capture the various device contents to a file. Some day
+you may be glad you did this ... trust me :-). Otherwise try the
+following:
+
+1. In the include/configs/EBONY.h file find the line that defines
+the CONFIG_SPD_EEPROM macro and undefine it. E.g:
+
+#undef CONFIG_SPD_EEPROM
+
+This will make the code use default SDRAM control register
+settings without using the SPD eeprom.
+
+2. Rebuild U-Boot
+
+3. Load the new U-Boot image and reboot ebony.
+
+4. Repair the SPD eeprom using the imm command. Here's the eeprom
+contents that work with the default SO-DIMM that comes with the
+ebony board (micron 8VDDT164AG-265A1). Note: these are probably
+_not_ the factory settings ... but they work.
+
+=> imd 53 0 10 80
+0000: 80 08 07 0c 0a 01 40 00 04 75 75 00 80 08 00 01    ......@..uu.....
+0010: 0e 04 0c 01 02 20 00 a0 75 00 00 50 3c 50 2d 20    ..... ..u..P<P-
+0020: 90 90 50 50 00 00 00 00 00 41 4b 34 32 75 00 00    ..PP.....AK42u..
+0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9c    ................
+0040: 2c 00 00 00 00 00 00 00 08 38 56 44 44 54 31 36    ,........8VDDT16
+0050: 36 34 41 47 2d 32 36 35 41 31 20 01 00 01 2c 63    64AG-265A1 ...,c
+0060: 22 25 ab 00 00 00 00 00 00 00 00 00 00 00 00 00    "%..............
+0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
+
+
+PCI DOUBLE-ENUMERATION WOES
+===========================
+
+If you're not using PCI-X cards and are simply using 32-bit and/or
+33 MHz cards via extenders and the like, you may notice that the
+initial pci scan reports various devices twice ... and configuration
+does not succeed (one or more devices are enumerated twice). To correct
+this we replaced the 2K ohm resistor on the IDSEL line(s) with a
+22 ohm resistor and the problem went away. This change hasn't broken
+anything yet -- use at your own risk.
+
+We never tested anything other than 33 MHz/32-bit cards. If you have
+the chance to do this, please let me know how things turn out :-)
+
+
+
+Regards,
+--Scott
+<smcnutt@artesyncp.com>
+
diff --git a/doc/README.ppc440 b/doc/README.ppc440
new file mode 100644 (file)
index 0000000..acb0c6f
--- /dev/null
@@ -0,0 +1,204 @@
+                           PowerPC 440
+
+                    Last Update: September 11, 2002
+=======================================================================
+
+
+OVERVIEW
+============
+
+Support for the ppc440 is contained in the cpu/ppc44x directory
+and enabled via the CONFIG_440 flag. It is largely based on the
+405gp code. A sample board support implementation is contained
+in the board/ebony directory.
+
+All testing was performed using the IBM Ebony board using both
+Rev B and Rev C silicon. However, since the Rev B. silicon has
+extensive errata, support for Rev B. is minimal (it boots, and
+features such as i2c, pci, tftpboot, etc. seem to work ok).
+The expectation is that all new board designs will be using
+Rev C or later parts -- if not, you may be in for a rough ride ;-)
+
+The ppc440 port does a fair job of keeping "board-specific" code
+out of the "cpu-specific" source. The goal of course was to
+provide mechanisms for each board to customize without having
+to clutter the cpu-specific source with a lot of ifdefs. Most
+of these mechanisms are described in the following sections.
+
+
+MEMORY MANAGEMENT
+=================
+
+The ppc440 doesn't run in "real mode". The MMU must be active
+at all times. Additionally, the 440 implements a 36-bit physical
+memory space that gets mapped into the PowerPC 32-bit virtual
+address space. So things like memory-mapped peripherals, etc must
+all be mapped in. Once this is done, the 32-bit virtual address
+space is then viewed as though it were physical memory.
+
+However, this means that memory, peripherals, etc can be configured
+to appear (mostly) anywhere in the virtual address space. Each board
+must define its own mappings using the tlbtab (see board/ebony/init.S).
+The actual TLB setup is performed by the cpu-specific code.
+
+Although each board is free to define its own mappings, there are
+several definitions to be aware of. These definitions may be used in
+the cpu-specific code (vs. board-specific code), so you should
+at least review these before deciding to make any changes ... it
+will probably save you some headaches ;-)
+
+CFG_SDRAM_BASE - The virtual address where SDRAM is mapped (always 0)
+
+CFG_FLASH_BASE - The virtual address where FLASH is mapped.
+
+CFG_PCI_MEMBASE - The virtual address where PCI-bus memory is mapped.
+    This mapping provides access to PCI-bus memory.
+
+CFG_PERIPHERAL_BASE - The virtual address where the 440 memory-mapped
+    peripherals are mapped. (e.g. -- UART registers, IIC registers, etc).
+
+CFG_ISRAM_BASE - The virtual address where the 440 internal SRAM is
+    mapped. The internal SRAM is equivalent to 405gp OCM and is used
+    for the initial stack.
+
+CFG_PCI_BASE - The virtual address where the 440 PCI-x bridge config
+    registers are mapped.
+
+CFG_PCI_TARGBASE - The PCI address that is mapped to the virtual address
+    defined by CFG_PCI_MEMBASE.
+
+
+UART / SERIAL
+=================
+
+The UART port works fine when an external serial clock is provided
+(like the one on the Ebony board) and when using internal clocking.
+This is controlled with the CFG_EXT_SERIAL_CLOCK flag. When using
+internal clocking, the "ideal baud rate" settings in the 440GP
+user manual are automatically calculated.
+
+CONFIG_SERIAL_SOFTWARE_FIFO enables interrupt-driven serial operation.
+But the last time I checked, interrupts were initialized after the
+serial port causing the interrupt handler to be removed from the
+handler table. This will probably be fixed soon ... or fix it
+yourself and submit a patch :-)
+
+
+I2C
+=================
+
+The i2c utilities have been tested on both Rev B. and Rev C. and
+look good. The iprobe command implementation has been updated to
+allow for 'skipped' addresses. Some i2c slaves are write only and
+cause problems when a probe (read) is performed (for example the
+CDCV850 clock controller at address 0x69 on the ebony board).
+
+To prevent probing certain addresses you can define the
+CFG_I2C_NOPROBES macro in your board-specific header file. When
+defined, all specified addresses are skipped during a probe.
+The addresses that are skipped will be displayed in the output
+of the iprobe command.
+
+For example, to prevent probing address 0x69, define the macro as
+follows:
+
+#define CFG_I2C_NOPROBES {0x69}
+
+Similarly, to prevent probing addresses 0x69 and 0x70, define the
+macro a:
+
+#define CFG_I2C_NOPROBES {0x69, 0x70}
+
+
+DDR SDRAM CONTROLLER
+====================
+
+SDRAM controller intialization using Serial Presence Detect (SPD) is
+now supported (thanks Jun). It is enabled by defining CONFIG_SPD_EEPROM.
+The i2c eeprom addresses are controlled by the SPD_EEPROM_ADDRESS macro.
+
+NOTE: The SPD_EEPROM_ADDRESS macro is defined differently than for other
+processors. Traditionally, it defined a single address. For the 440 it
+defines an array of addresses to support multiple banks. Address order
+is significant: the addresses are used in order to program the BankN
+registers. For example, two banks with i2c addresses of 0x53 (bank 0)
+and 0x52 (bank 1) would be defined as follows:
+
+#define SPD_EEPROM_ADDRESS {0x53,0x52}
+
+
+PCI-X BRIDGE
+====================
+
+PCI is an area that requires lots of flexibility since every board has
+its own set of constraints and configuration. This section describes the
+440 implementation.
+
+CPC0_STRP1[PISE] -- if the PISE strap bit is not asserted, PCI init
+is aborted and an indication is printed. This is NOT considered an
+error -- only an indication that PCI shouldn't be initialized. This
+gives you a chance to edit the i2c bootstrap eeproms using the i2c
+utilities once you get to the U-Boot command prompt. NOTE: the default
+440 bootstrap options (not using i2c eeprom) negates this bit.
+
+The cpu-specific code sets up a default pci_controller structure
+that maps in a single PCI I/O space and PCI memory space. The I/O
+space begins at PCI I/O address 0 and the PCI memory space is
+256 MB starting at PCI address CFG_PCI_TARGBASE. After the
+pci_controller structure is initialized, the cpu-specific code will
+call the routine pci_pre_init() if the CFG_PCI_PRE_INIT flag is
+defined. This routine is implemented by board-specific code & is where
+the board can over-ride/extend the default pci_controller structure
+settings and do other pre-initialization tasks. If pci_pre_init()
+returns a value of zero, PCI initialization is aborted; otherwise the
+controller structure is registered and initialization continues.
+
+The default 440GP PCI target configuration is minimal -- it assumes that
+the strapping registers are set as necessary. Since the strapping bits
+provide very limited flexibility, you may want to customize the boards
+target configuration. If CFG_PCI_TARGET_INIT is defined, the cpu-specific
+code will call the routine pci_target_init() which you must implement
+in your board-specific code.
+
+Target initialization is completed by the cpu-specific code by
+initializing the subsystem id and subsystem vendor id, and then ensuring
+that the 'enable host configuration' bit in the PCIX0_BRDGOPT2 is set.
+
+The default PCI master initialization maps in 256 MB of pci memory
+starting at PCI address CFG_PCI_MEMBASE. To customize this, define
+PCI_MASTER_INIT. This will call the routine pci_master_init() in your
+board-specific code rather than performing the default master
+initialization.
+
+The decision to perform PCI host configuration must often be determined
+at run time. The ppc440 port differs from most other implementations in
+that it requires the board to determine its host configuration at run
+time rather than by using compile-time flags. This shouldn't create a
+large impact on the board-specific code since the board only needs to
+implement a single routine that returns a zero or non-zero value:
+is_pci_host().
+
+Justification for this becomes clear when considering systems running
+in a cPCI environment:
+
+1. Arbiter strapping: Many cPCI boards provide an external arbiter (often
+part of the PCI-to-PCI bridge). Even though the arbiter is external (the
+arbiter strapping is negated), the CPU may still be required to perform
+local PCI bus configuration.
+
+2. Host only: PPMC boards must sample the MONARCH# signal at run-time.
+Depending on the configuration of the carrier boar, the PPMC board must
+determine if it should configure the PCI bus at run-time. And in most
+cases, access to the MONARCH# signal is board-specific (e.g. via
+board-specific FPGA registers, etc).
+
+In any event, the is_pci_host() routine gives each board the opportunity
+to decide at run-time. If your board is always configured a certain way,
+then just hardcode a return of 1 or 0 as appropriate.
+
+
+
+Regards,
+--Scott
+<smcnutt@artesyncp.com>
+
diff --git a/drivers/3c589.h b/drivers/3c589.h
new file mode 100644 (file)
index 0000000..00e7f7c
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2. The name
+ * of the author may not be used to endorse or promote products derived from
+ * this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ October 2, 1994
+
+ Modified by: Andres Vega Garcia
+
+ INRIA - Sophia Antipolis, France
+ e-mail: avega@sophia.inria.fr
+ finger: avega@pax.inria.fr
+
+ */
+
+/*
+ * Created from if_epreg.h by Fred Gray (fgray@rice.edu) to support the
+ * 3c590 family.
+ */
+
+/*
+ * Modified by Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp>
+ * for etherboot
+ * Mar. 14, 2000
+*/
+
+/*
+ * Ethernet software status per interface.
+ */
+
+/*
+ * Some global constants
+ */
+
+#define TX_INIT_RATE         16
+#define TX_INIT_MAX_RATE     64
+#define RX_INIT_LATENCY      64
+#define RX_INIT_EARLY_THRESH 64
+#define MIN_RX_EARLY_THRESHF   16 /* not less than ether_header */
+#define MIN_RX_EARLY_THRESHL   4
+
+#define EEPROMSIZE      0x40
+#define MAX_EEPROMBUSY  1000
+#define VX_LAST_TAG     0xd7
+#define VX_MAX_BOARDS   16
+#define VX_ID_PORT      0x100
+
+/*
+ * some macros to acces long named fields
+ */
+#define BASE   (EL_BASE_ADDR)
+
+/*
+ * Commands to read/write EEPROM trough EEPROM command register (Window 0,
+ * Offset 0xa)
+ */
+#define EEPROM_CMD_RD    0x0080        /* Read:  Address required (5 bits) */
+#define EEPROM_CMD_WR    0x0040        /* Write: Address required (5 bits) */
+#define EEPROM_CMD_ERASE 0x00c0        /* Erase: Address required (5 bits) */
+#define EEPROM_CMD_EWEN  0x0030        /* Erase/Write Enable: No data required */
+
+#define EEPROM_BUSY            (1<<15)
+
+/*
+ * Some short functions, worth to let them be a macro
+ */
+
+/**************************************************************************
+ *                                                                       *
+ * These define the EEPROM data structure.  They are used in the probe
+ * function to verify the existence of the adapter after having sent
+ * the ID_Sequence.
+ *
+ * There are others but only the ones we use are defined here.
+ *
+ **************************************************************************/
+
+#define EEPROM_NODE_ADDR_0     0x0     /* Word */
+#define EEPROM_NODE_ADDR_1     0x1     /* Word */
+#define EEPROM_NODE_ADDR_2     0x2     /* Word */
+#define EEPROM_PROD_ID         0x3     /* 0x9[0-f]50 */
+#define EEPROM_MFG_ID          0x7     /* 0x6d50 */
+#define EEPROM_ADDR_CFG                0x8     /* Base addr */
+#define EEPROM_RESOURCE_CFG    0x9     /* IRQ. Bits 12-15 */
+#define EEPROM_OEM_ADDR_0      0xa     /* Word */
+#define EEPROM_OEM_ADDR_1      0xb     /* Word */
+#define EEPROM_OEM_ADDR_2      0xc     /* Word */
+#define EEPROM_SOFT_INFO_2     0xf     /* Software information 2 */
+
+#define NO_RX_OVN_ANOMALY       (1<<5)
+
+/**************************************************************************
+ *                                                                               *
+ * These are the registers for the 3Com 3c509 and their bit patterns when *
+ * applicable.  They have been taken out the the "EtherLink III Parallel  *
+ * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual *
+ * from 3com.                                                            *
+ *                                                                               *
+ **************************************************************************/
+
+#define VX_COMMAND             0x0e    /* Write. BASE+0x0e is always a
+                                        * command reg. */
+#define VX_STATUS              0x0e    /* Read. BASE+0x0e is always status
+                                        * reg. */
+#define VX_WINDOW              0x0f    /* Read. BASE+0x0f is always window
+                                        * reg. */
+/*
+ * Window 0 registers. Setup.
+ */
+/* Write */
+#define VX_W0_EEPROM_DATA      0x0c
+#define VX_W0_EEPROM_COMMAND   0x0a
+#define VX_W0_RESOURCE_CFG     0x08
+#define VX_W0_ADDRESS_CFG      0x06
+#define VX_W0_CONFIG_CTRL      0x04
+        /* Read */
+#define VX_W0_PRODUCT_ID       0x02
+#define VX_W0_MFG_ID           0x00
+
+
+/*
+ * Window 1 registers. Operating Set.
+ */
+/* Write */
+#define VX_W1_TX_PIO_WR_2      0x02
+#define VX_W1_TX_PIO_WR_1      0x00
+/* Read */
+#define VX_W1_FREE_TX          0x0c
+#define VX_W1_TX_STATUS                0x0b    /* byte */
+#define VX_W1_TIMER            0x0a    /* byte */
+#define VX_W1_RX_STATUS                0x08
+#define VX_W1_RX_PIO_RD_2      0x02
+#define VX_W1_RX_PIO_RD_1      0x00
+
+/*
+ * Window 2 registers. Station Address Setup/Read
+ */
+/* Read/Write */
+#define VX_W2_ADDR_5           0x05
+#define VX_W2_ADDR_4           0x04
+#define VX_W2_ADDR_3           0x03
+#define VX_W2_ADDR_2           0x02
+#define VX_W2_ADDR_1           0x01
+#define VX_W2_ADDR_0           0x00
+
+/*
+ * Window 3 registers. FIFO Management.
+ */
+/* Read */
+#define VX_W3_INTERNAL_CFG     0x00
+#define VX_W3_RESET_OPT                0x08
+#define VX_W3_FREE_TX          0x0c
+#define VX_W3_FREE_RX          0x0a
+
+/*
+ * Window 4 registers. Diagnostics.
+ */
+/* Read/Write */
+#define VX_W4_MEDIA_TYPE       0x0a
+#define VX_W4_CTRLR_STATUS     0x08
+#define VX_W4_NET_DIAG         0x06
+#define VX_W4_FIFO_DIAG                0x04
+#define VX_W4_HOST_DIAG                0x02
+#define VX_W4_TX_DIAG          0x00
+
+/*
+ * Window 5 Registers.  Results and Internal status.
+ */
+/* Read */
+#define VX_W5_READ_0_MASK      0x0c
+#define VX_W5_INTR_MASK                0x0a
+#define VX_W5_RX_FILTER                0x08
+#define VX_W5_RX_EARLY_THRESH  0x06
+#define VX_W5_TX_AVAIL_THRESH  0x02
+#define VX_W5_TX_START_THRESH  0x00
+
+/*
+ * Window 6 registers. Statistics.
+ */
+/* Read/Write */
+#define TX_TOTAL_OK            0x0c
+#define RX_TOTAL_OK            0x0a
+#define TX_DEFERRALS           0x08
+#define RX_FRAMES_OK           0x07
+#define TX_FRAMES_OK           0x06
+#define RX_OVERRUNS            0x05
+#define TX_COLLISIONS          0x04
+#define TX_AFTER_1_COLLISION   0x03
+#define TX_AFTER_X_COLLISIONS  0x02
+#define TX_NO_SQE              0x01
+#define TX_CD_LOST             0x00
+
+/****************************************
+ *
+ * Register definitions.
+ *
+ ****************************************/
+
+/*
+ * Command register. All windows.
+ *
+ * 16 bit register.
+ *     15-11:  5-bit code for command to be executed.
+ *     10-0:   11-bit arg if any. For commands with no args;
+ *           this can be set to anything.
+ */
+#define GLOBAL_RESET           (unsigned short) 0x0000 /* Wait at least 1ms
+                                                        * after issuing */
+#define WINDOW_SELECT          (unsigned short) (0x1<<11)
+#define START_TRANSCEIVER      (unsigned short) (0x2<<11)      /* Read ADDR_CFG reg to
+                                                        * determine whether
+                                                        * this is needed. If
+                                                        * so; wait 800 uSec
+                                                        * before using trans-
+                                                        * ceiver. */
+#define RX_DISABLE             (unsigned short) (0x3<<11)      /* state disabled on
+                                                        * power-up */
+#define RX_ENABLE              (unsigned short) (0x4<<11)
+#define RX_RESET               (unsigned short) (0x5<<11)
+#define RX_DISCARD_TOP_PACK    (unsigned short) (0x8<<11)
+#define TX_ENABLE              (unsigned short) (0x9<<11)
+#define TX_DISABLE             (unsigned short) (0xa<<11)
+#define TX_RESET               (unsigned short) (0xb<<11)
+#define REQ_INTR               (unsigned short) (0xc<<11)
+/*
+ * The following C_* acknowledge the various interrupts. Some of them don't
+ * do anything.  See the manual.
+ */
+#define ACK_INTR               (unsigned short) (0x6800)
+#      define C_INTR_LATCH     (unsigned short) (ACK_INTR|0x1)
+#      define C_CARD_FAILURE   (unsigned short) (ACK_INTR|0x2)
+#      define C_TX_COMPLETE    (unsigned short) (ACK_INTR|0x4)
+#      define C_TX_AVAIL       (unsigned short) (ACK_INTR|0x8)
+#      define C_RX_COMPLETE    (unsigned short) (ACK_INTR|0x10)
+#      define C_RX_EARLY       (unsigned short) (ACK_INTR|0x20)
+#      define C_INT_RQD                (unsigned short) (ACK_INTR|0x40)
+#      define C_UPD_STATS      (unsigned short) (ACK_INTR|0x80)
+#define SET_INTR_MASK          (unsigned short) (0xe<<11)
+#define SET_RD_0_MASK          (unsigned short) (0xf<<11)
+#define SET_RX_FILTER          (unsigned short) (0x10<<11)
+#      define FIL_INDIVIDUAL   (unsigned short) (0x1)
+#      define FIL_MULTICAST     (unsigned short) (0x02)
+#      define FIL_BRDCST        (unsigned short) (0x04)
+#      define FIL_PROMISC       (unsigned short) (0x08)
+#define SET_RX_EARLY_THRESH    (unsigned short) (0x11<<11)
+#define SET_TX_AVAIL_THRESH    (unsigned short) (0x12<<11)
+#define SET_TX_START_THRESH    (unsigned short) (0x13<<11)
+#define STATS_ENABLE           (unsigned short) (0x15<<11)
+#define STATS_DISABLE          (unsigned short) (0x16<<11)
+#define STOP_TRANSCEIVER       (unsigned short) (0x17<<11)
+
+/*
+ * Status register. All windows.
+ *
+ *     15-13:  Window number(0-7).
+ *     12:     Command_in_progress.
+ *     11:     reserved.
+ *     10:     reserved.
+ *     9:      reserved.
+ *     8:      reserved.
+ *     7:      Update Statistics.
+ *     6:      Interrupt Requested.
+ *     5:      RX Early.
+ *     4:      RX Complete.
+ *     3:      TX Available.
+ *     2:      TX Complete.
+ *     1:      Adapter Failure.
+ *     0:      Interrupt Latch.
+ */
+#define S_INTR_LATCH           (unsigned short) (0x1)
+#define S_CARD_FAILURE         (unsigned short) (0x2)
+#define S_TX_COMPLETE          (unsigned short) (0x4)
+#define S_TX_AVAIL             (unsigned short) (0x8)
+#define S_RX_COMPLETE          (unsigned short) (0x10)
+#define S_RX_EARLY             (unsigned short) (0x20)
+#define S_INT_RQD              (unsigned short) (0x40)
+#define S_UPD_STATS            (unsigned short) (0x80)
+#define S_COMMAND_IN_PROGRESS  (unsigned short) (0x1000)
+
+#define VX_BUSY_WAIT while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS)
+
+/* Address Config. Register.
+ * Window 0/Port 06
+ */
+
+#define ACF_CONNECTOR_BITS     14
+#define ACF_CONNECTOR_UTP      0
+#define ACF_CONNECTOR_AUI      1
+#define ACF_CONNECTOR_BNC      3
+
+#define INTERNAL_CONNECTOR_BITS 20
+#define INTERNAL_CONNECTOR_MASK 0x01700000
+
+/*
+ * FIFO Registers. RX Status.
+ *
+ *     15:     Incomplete or FIFO empty.
+ *     14:     1: Error in RX Packet   0: Incomplete or no error.
+ *     13-11:  Type of error.
+ *           1000 = Overrun.
+ *           1011 = Run Packet Error.
+ *           1100 = Alignment Error.
+ *           1101 = CRC Error.
+ *           1001 = Oversize Packet Error (>1514 bytes)
+ *           0010 = Dribble Bits.
+ *           (all other error codes, no errors.)
+ *
+ *     10-0:   RX Bytes (0-1514)
+ */
+#define ERR_INCOMPLETE  (unsigned short) (0x8000)
+#define ERR_RX          (unsigned short) (0x4000)
+#define ERR_MASK        (unsigned short) (0x7800)
+#define ERR_OVERRUN     (unsigned short) (0x4000)
+#define ERR_RUNT        (unsigned short) (0x5800)
+#define ERR_ALIGNMENT   (unsigned short) (0x6000)
+#define ERR_CRC         (unsigned short) (0x6800)
+#define ERR_OVERSIZE    (unsigned short) (0x4800)
+#define ERR_DRIBBLE     (unsigned short) (0x1000)
+
+/*
+ * TX Status.
+ *
+ *   Reports the transmit status of a completed transmission. Writing this
+ *   register pops the transmit completion stack.
+ *
+ *   Window 1/Port 0x0b.
+ *
+ *     7:      Complete
+ *     6:      Interrupt on successful transmission requested.
+ *     5:      Jabber Error (TP Only, TX Reset required. )
+ *     4:      Underrun (TX Reset required. )
+ *     3:      Maximum Collisions.
+ *     2:      TX Status Overflow.
+ *     1-0:    Undefined.
+ *
+ */
+#define TXS_COMPLETE           0x80
+#define TXS_INTR_REQ           0x40
+#define TXS_JABBER             0x20
+#define TXS_UNDERRUN           0x10
+#define TXS_MAX_COLLISION      0x8
+#define TXS_STATUS_OVERFLOW    0x4
+
+#define RS_AUI                 (1<<5)
+#define RS_BNC                 (1<<4)
+#define RS_UTP                 (1<<3)
+#define        RS_T4                   (1<<0)
+#define        RS_TX                   (1<<1)
+#define        RS_FX                   (1<<2)
+#define        RS_MII                  (1<<6)
+
+
+/*
+ * FIFO Status (Window 4)
+ *
+ *   Supports FIFO diagnostics
+ *
+ *   Window 4/Port 0x04.1
+ *
+ *     15:     1=RX receiving (RO). Set when a packet is being received
+ *             into the RX FIFO.
+ *     14:     Reserved
+ *     13:     1=RX underrun (RO). Generates Adapter Failure interrupt.
+ *             Requires RX Reset or Global Reset command to recover.
+ *             It is generated when you read past the end of a packet -
+ *             reading past what has been received so far will give bad
+ *             data.
+ *     12:     1=RX status overrun (RO). Set when there are already 8
+ *             packets in the RX FIFO. While this bit is set, no additional
+ *             packets are received. Requires no action on the part of
+ *             the host. The condition is cleared once a packet has been
+ *             read out of the RX FIFO.
+ *     11:     1=RX overrun (RO). Set when the RX FIFO is full (there
+ *             may not be an overrun packet yet). While this bit is set,
+ *             no additional packets will be received (some additional
+ *             bytes can still be pending between the wire and the RX
+ *             FIFO). Requires no action on the part of the host. The
+ *             condition is cleared once a few bytes have been read out
+ *             from the RX FIFO.
+ *     10:     1=TX overrun (RO). Generates adapter failure interrupt.
+ *             Requires TX Reset or Global Reset command to recover.
+ *             Disables Transmitter.
+ *     9-8:    Unassigned.
+ *     7-0:    Built in self test bits for the RX and TX FIFO's.
+ */
+#define FIFOS_RX_RECEIVING     (unsigned short) 0x8000
+#define FIFOS_RX_UNDERRUN      (unsigned short) 0x2000
+#define FIFOS_RX_STATUS_OVERRUN        (unsigned short) 0x1000
+#define FIFOS_RX_OVERRUN       (unsigned short) 0x0800
+#define FIFOS_TX_OVERRUN       (unsigned short) 0x0400
+
+/*
+ * Misc defines for various things.
+ */
+#define TAG_ADAPTER                     0xd0
+#define ACTIVATE_ADAPTER_TO_CONFIG      0xff
+#define ENABLE_DRQ_IRQ                  0x0001
+#define MFG_ID                          0x506d  /* `TCM' */
+#define PROD_ID                         0x5090
+#define GO_WINDOW(x)           outw(WINDOW_SELECT|(x),BASE+VX_COMMAND)
+#define JABBER_GUARD_ENABLE    0x40
+#define LINKBEAT_ENABLE                0x80
+#define        ENABLE_UTP              (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE)
+#define DISABLE_UTP            0x0
+#define RX_BYTES_MASK          (unsigned short) (0x07ff)
+#define RX_ERROR        0x4000
+#define RX_INCOMPLETE   0x8000
+#define TX_INDICATE            1<<15
+#define is_eeprom_busy(b)      (inw((b)+VX_W0_EEPROM_COMMAND)&EEPROM_BUSY)
+
+#define        VX_IOSIZE       0x20
+
+#define VX_CONNECTORS 8
+
+/*
+ * Local variables:
+ *  c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/5701rls.c b/drivers/5701rls.c
new file mode 100644 (file)
index 0000000..c4409e4
--- /dev/null
@@ -0,0 +1,46 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* 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, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*                                                                            */
+/******************************************************************************/
+
+#if INCLUDE_5701_AX_FIX
+
+#include "bcm570x_mm.h"
+#include "5701rls.h"
+
+LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice)
+{
+  T3_FWIMG_INFO FwImgInfo;
+
+  FwImgInfo.StartAddress = t3FwStartAddr;
+  FwImgInfo.Text.Buffer = (PLM_UINT8)t3FwText;
+  FwImgInfo.Text.Offset  = t3FwTextAddr;
+  FwImgInfo.Text.Length  = t3FwTextLen;
+  FwImgInfo.ROnlyData.Buffer = (PLM_UINT8)t3FwRodata;
+  FwImgInfo.ROnlyData.Offset  = t3FwRodataAddr;
+  FwImgInfo.ROnlyData.Length  = t3FwRodataLen;
+  FwImgInfo.Data.Buffer = (PLM_UINT8)t3FwData;
+  FwImgInfo.Data.Offset  = t3FwDataAddr;
+  FwImgInfo.Data.Length  = t3FwDataLen;
+
+  if (LM_LoadFirmware(pDevice,
+                      &FwImgInfo,
+                      T3_RX_CPU_ID | T3_TX_CPU_ID,
+                      T3_RX_CPU_ID) != LM_STATUS_SUCCESS)
+    {
+      return LM_STATUS_FAILURE;
+    }
+
+  return LM_STATUS_SUCCESS;
+}
+
+#endif /* INCLUDE_5701_AX_FIX */
diff --git a/drivers/5701rls.h b/drivers/5701rls.h
new file mode 100644 (file)
index 0000000..30b127a
--- /dev/null
@@ -0,0 +1,198 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* 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, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+
+typedef unsigned long U32;
+int t3FwReleaseMajor = 0x0;
+int t3FwReleaseMinor = 0x0;
+int t3FwReleaseFix = 0x0;
+U32 t3FwStartAddr = 0x08000000;
+U32 t3FwTextAddr = 0x08000000;
+int t3FwTextLen = 0x9c0;
+U32 t3FwRodataAddr = 0x080009c0;
+int t3FwRodataLen = 0x60;
+U32 t3FwDataAddr = 0x08000a40;
+int t3FwDataLen = 0x20;
+U32 t3FwSbssAddr = 0x08000a60;
+int t3FwSbssLen = 0xc;
+U32 t3FwBssAddr = 0x08000a70;
+int t3FwBssLen = 0x10;
+U32 t3FwText[(0x9c0/4) + 1] = {
+0x0,
+0x10000003, 0x0, 0xd, 0xd,
+0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800,
+0x26100000, 0xe000018, 0x0, 0xd,
+0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800,
+0x26100034, 0xe00021c, 0x0, 0xd,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0x3c1cc000, 0xafbf0018, 0xaf80680c, 0xe00004c,
+0x241b2105, 0x97850000, 0x97870002, 0x9782002c,
+0x9783002e, 0x3c040800, 0x248409c0, 0xafa00014,
+0x21400, 0x621825, 0x52c00, 0xafa30010,
+0x8f860010, 0xe52825, 0xe000060, 0x24070102,
+0x3c02ac00, 0x34420100, 0x3c03ac01, 0x34630100,
+0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498,
+0xaf82049c, 0x24020001, 0xaf825ce0, 0xe00003f,
+0xaf825d00, 0xe000140, 0x0, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x2402ffff, 0xaf825404,
+0x8f835400, 0x34630400, 0xaf835400, 0xaf825404,
+0x3c020800, 0x24420034, 0xaf82541c, 0x3e00008,
+0xaf805400, 0x0, 0x0, 0x3c020800,
+0x34423000, 0x3c030800, 0x34633000, 0x3c040800,
+0x348437ff, 0x3c010800, 0xac220a64, 0x24020040,
+0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60,
+0xac600000, 0x24630004, 0x83102b, 0x5040fffd,
+0xac600000, 0x3e00008, 0x0, 0x804821,
+0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800,
+0x8c840a68, 0x8fab0014, 0x24430001, 0x44102b,
+0x3c010800, 0xac230a60, 0x14400003, 0x4021,
+0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60,
+0x3c030800, 0x8c630a64, 0x91240000, 0x21140,
+0x431021, 0x481021, 0x25080001, 0xa0440000,
+0x29020008, 0x1440fff4, 0x25290001, 0x3c020800,
+0x8c420a60, 0x3c030800, 0x8c630a64, 0x8f84680c,
+0x21140, 0x431021, 0xac440008, 0xac45000c,
+0xac460010, 0xac470014, 0xac4a0018, 0x3e00008,
+0xac4b001c, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x2000008,
+0x0, 0xa0001e3, 0x3c0a0001, 0xa0001e3,
+0x3c0a0002, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x3c0a0007, 0xa0001e3, 0x3c0a0008, 0xa0001e3,
+0x3c0a0009, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x3c0a000b, 0xa0001e3,
+0x3c0a000c, 0xa0001e3, 0x3c0a000d, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x3c0a000e, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x3c0a0013, 0xa0001e3,
+0x3c0a0014, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0x1821, 0x1021, 0xafbf0018, 0xafb10014,
+0xafb00010, 0x3c010800, 0x220821, 0xac200a70,
+0x3c010800, 0x220821, 0xac200a74, 0x3c010800,
+0x220821, 0xac200a78, 0x24630001, 0x1860fff5,
+0x2442000c, 0x24110001, 0x8f906810, 0x32020004,
+0x14400005, 0x24040001, 0x3c020800, 0x8c420a78,
+0x18400003, 0x2021, 0xe000182, 0x0,
+0x32020001, 0x10400003, 0x0, 0xe000169,
+0x0, 0xa000153, 0xaf915028, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
+0x3c050800, 0x8ca50a70, 0x3c060800, 0x8cc60a80,
+0x3c070800, 0x8ce70a78, 0x27bdffe0, 0x3c040800,
+0x248409d0, 0xafbf0018, 0xafa00010, 0xe000060,
+0xafa00014, 0xe00017b, 0x2021, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x24020001, 0x8f836810,
+0x821004, 0x21027, 0x621824, 0x3e00008,
+0xaf836810, 0x27bdffd8, 0xafbf0024, 0x1080002e,
+0xafb00020, 0x8f825cec, 0xafa20018, 0x8f825cec,
+0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000,
+0xaf825cec, 0x8e020000, 0x18400016, 0x0,
+0x3c020800, 0x94420a74, 0x8fa3001c, 0x221c0,
+0xac830004, 0x8fa2001c, 0x3c010800, 0xe000201,
+0xac220a74, 0x10400005, 0x0, 0x8e020000,
+0x24420001, 0xa0001df, 0xae020000, 0x3c020800,
+0x8c420a70, 0x21c02, 0x321c0, 0xa0001c5,
+0xafa2001c, 0xe000201, 0x0, 0x1040001f,
+0x0, 0x8e020000, 0x8fa3001c, 0x24420001,
+0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74,
+0xa0001df, 0xae020000, 0x3c100800, 0x26100a78,
+0x8e020000, 0x18400028, 0x0, 0xe000201,
+0x0, 0x14400024, 0x0, 0x8e020000,
+0x3c030800, 0x8c630a70, 0x2442ffff, 0xafa3001c,
+0x18400006, 0xae020000, 0x31402, 0x221c0,
+0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e,
+0x2442ff00, 0x2c420300, 0x1440000b, 0x24024000,
+0x3c040800, 0x248409dc, 0xafa00010, 0xafa00014,
+0x8fa6001c, 0x24050008, 0xe000060, 0x3821,
+0xa0001df, 0x0, 0xaf825cf8, 0x3c020800,
+0x8c420a40, 0x8fa3001c, 0x24420001, 0xaf835cf8,
+0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020,
+0x3e00008, 0x27bd0028, 0x27bdffe0, 0x3c040800,
+0x248409e8, 0x2821, 0x3021, 0x3821,
+0xafbf0018, 0xafa00010, 0xe000060, 0xafa00014,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f82680c,
+0x8f85680c, 0x21827, 0x3182b, 0x31823,
+0x431024, 0x441021, 0xa2282b, 0x10a00006,
+0x0, 0x401821, 0x8f82680c, 0x43102b,
+0x1440fffd, 0x0, 0x3e00008, 0x0,
+0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40,
+0x64102b, 0x54400002, 0x831023, 0x641023,
+0x2c420008, 0x3e00008, 0x38420001, 0x27bdffe0,
+0x802821, 0x3c040800, 0x24840a00, 0x3021,
+0x3821, 0xafbf0018, 0xafa00010, 0xe000060,
+0xafa00014, 0xa000216, 0x0, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x0, 0x27bdffe0,
+0x3c1cc000, 0xafbf0018, 0xe00004c, 0xaf80680c,
+0x3c040800, 0x24840a10, 0x3802821, 0x3021,
+0x3821, 0xafa00010, 0xe000060, 0xafa00014,
+0x2402ffff, 0xaf825404, 0x3c0200aa, 0xe000234,
+0xaf825434, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x0, 0x0, 0x0, 0x27bdffe8,
+0xafb00010, 0x24100001, 0xafbf0014, 0x3c01c003,
+0xac200000, 0x8f826810, 0x30422000, 0x10400003,
+0x0, 0xe000246, 0x0, 0xa00023a,
+0xaf905428, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x27bdfff8, 0x8f845d0c, 0x3c0200ff,
+0x3c030800, 0x8c630a50, 0x3442fff8, 0x821024,
+0x1043001e, 0x3c0500ff, 0x34a5fff8, 0x3c06c003,
+0x3c074000, 0x851824, 0x8c620010, 0x3c010800,
+0xac230a50, 0x30420008, 0x10400005, 0x871025,
+0x8cc20000, 0x24420001, 0xacc20000, 0x871025,
+0xaf825d0c, 0x8fa20000, 0x24420001, 0xafa20000,
+0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000,
+0x8fa20000, 0x8f845d0c, 0x3c030800, 0x8c630a50,
+0x851024, 0x1443ffe8, 0x851824, 0x27bd0008,
+0x3e00008, 0x0, 0x0, 0x0 };
+U32 t3FwRodata[(0x60/4) + 1] = {
+0x35373031, 0x726c7341, 0x0,
+0x0, 0x53774576, 0x656e7430, 0x0,
+0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e,
+0x45766e74, 0x0, 0x0, 0x0,
+0x0, 0x66617461, 0x6c457272, 0x0,
+0x0, 0x4d61696e, 0x43707542, 0x0,
+0x0, 0x0 };
+U32 t3FwData[(0x20/4) + 1] = {
+0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0 };
diff --git a/drivers/bcm570x_autoneg.h b/drivers/bcm570x_autoneg.h
new file mode 100644 (file)
index 0000000..95fcc07
--- /dev/null
@@ -0,0 +1,415 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* 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, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+
+
+#ifndef AUTONEG_H
+#define AUTONEG_H
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+#define AN_LINK_TIMER_INTERVAL_US           9000       /* 10ms */
+
+/* TRUE, FALSE */
+#define AN_TRUE                             1
+#define AN_FALSE                            0
+
+
+
+/******************************************************************************/
+/* Main data structure for keeping track of 802.3z auto-negotation state */
+/* variables as shown in Figure 37-6 of the IEEE 802.3z specification. */
+/******************************************************************************/
+
+typedef struct
+{
+    /* Current auto-negotiation state. */
+    unsigned long State;
+    #define AN_STATE_UNKNOWN                        0
+    #define AN_STATE_AN_ENABLE                      1
+    #define AN_STATE_AN_RESTART_INIT                2
+    #define AN_STATE_AN_RESTART                     3
+    #define AN_STATE_DISABLE_LINK_OK                4
+    #define AN_STATE_ABILITY_DETECT_INIT            5
+    #define AN_STATE_ABILITY_DETECT                 6
+    #define AN_STATE_ACK_DETECT_INIT                7
+    #define AN_STATE_ACK_DETECT                     8
+    #define AN_STATE_COMPLETE_ACK_INIT              9
+    #define AN_STATE_COMPLETE_ACK                   10
+    #define AN_STATE_IDLE_DETECT_INIT               11
+    #define AN_STATE_IDLE_DETECT                    12
+    #define AN_STATE_LINK_OK                        13
+    #define AN_STATE_NEXT_PAGE_WAIT_INIT            14
+    #define AN_STATE_NEXT_PAGE_WAIT                 16
+
+    /* Link timer. */
+    unsigned long LinkTime_us;
+
+    /* Current time. */
+    unsigned long CurrentTime_us;
+
+    /* Need these values for consistency check. */
+    unsigned short AbilityMatchCfg;
+
+    /* Ability, idle, and ack match functions. */
+    unsigned long AbilityMatchCnt;
+    char AbilityMatch;
+    char IdleMatch;
+    char AckMatch;
+
+    /* Tx config data */
+    union
+    {
+        /* The TxConfig register is arranged as follows:                      */
+        /*                                                                    */
+        /* MSB                                                           LSB  */
+        /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+  */
+        /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8|  */
+        /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+  */
+        struct
+        {
+#ifdef BIG_ENDIAN_HOST
+            unsigned int D7:1;        /* PS1 */
+            unsigned int D6:1;        /* HD */
+            unsigned int D5:1;        /* FD */
+            unsigned int D4:1;
+            unsigned int D3:1;
+            unsigned int D2:1;
+            unsigned int D1:1;
+            unsigned int D0:1;
+            unsigned int D15:1;       /* NP */
+            unsigned int D14:1;       /* ACK */
+            unsigned int D13:1;       /* RF2 */
+            unsigned int D12:1;       /* RF1 */
+            unsigned int D11:1;
+            unsigned int D10:1;
+            unsigned int D9:1;
+            unsigned int D8:1;        /* PS2 */
+#else /* BIG_ENDIAN_HOST */
+            unsigned int D8:1;        /* PS2 */
+            unsigned int D9:1;
+            unsigned int D10:1;
+            unsigned int D11:1;
+            unsigned int D12:1;       /* RF1 */
+            unsigned int D13:1;       /* RF2 */
+            unsigned int D14:1;       /* ACK */
+            unsigned int D15:1;       /* NP */
+            unsigned int D0:1;
+            unsigned int D1:1;
+            unsigned int D2:1;
+            unsigned int D3:1;
+            unsigned int D4:1;
+            unsigned int D5:1;        /* FD */
+            unsigned int D6:1;        /* HD */
+            unsigned int D7:1;        /* PS1 */
+#endif
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define D8_PS2                      bits.D8
+        #define D12_RF1                     bits.D12
+        #define D13_RF2                     bits.D13
+        #define D14_ACK                     bits.D14
+        #define D15_NP                      bits.D15
+        #define D5_FD                       bits.D5
+        #define D6_HD                       bits.D6
+        #define D7_PS1                      bits.D7
+    } TxConfig;
+
+    /* Rx config data */
+    union
+    {
+        /* The RxConfig register is arranged as follows:                      */
+        /*                                                                    */
+        /* MSB                                                           LSB  */
+        /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+  */
+        /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8|  */
+        /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+  */
+        struct
+        {
+#ifdef BIG_ENDIAN_HOST
+           unsigned int D7:1;        /* PS1 */
+            unsigned int D6:1;        /* HD */
+           unsigned int D5:1;        /* FD */
+            unsigned int D4:1;
+            unsigned int D3:1;
+            unsigned int D2:1;
+            unsigned int D1:1;
+            unsigned int D0:1;
+           unsigned int D15:1;       /* NP */
+            unsigned int D14:1;       /* ACK */
+            unsigned int D13:1;       /* RF2 */
+            unsigned int D12:1;       /* RF1 */
+            unsigned int D11:1;
+            unsigned int D10:1;
+            unsigned int D9:1;
+            unsigned int D8:1;        /* PS2 */
+#else /* BIG_ENDIAN_HOST */
+            unsigned int D8:1;        /* PS2 */
+            unsigned int D9:1;
+            unsigned int D10:1;
+            unsigned int D11:1;
+            unsigned int D12:1;       /* RF1 */
+            unsigned int D13:1;       /* RF2 */
+            unsigned int D14:1;       /* ACK */
+            unsigned int D15:1;       /* NP */
+            unsigned int D0:1;
+            unsigned int D1:1;
+            unsigned int D2:1;
+            unsigned int D3:1;
+            unsigned int D4:1;
+            unsigned int D5:1;        /* FD */
+            unsigned int D6:1;        /* HD */
+            unsigned int D7:1;        /* PS1 */
+#endif
+        } bits;
+
+        unsigned short AsUSHORT;
+    } RxConfig;
+
+    #define AN_CONFIG_NP                            0x0080
+    #define AN_CONFIG_ACK                           0x0040
+    #define AN_CONFIG_RF2                           0x0020
+    #define AN_CONFIG_RF1                           0x0010
+    #define AN_CONFIG_PS2                           0x0001
+    #define AN_CONFIG_PS1                           0x8000
+    #define AN_CONFIG_HD                            0x4000
+    #define AN_CONFIG_FD                            0x2000
+
+
+    /* Management registers. */
+
+    /* Control register. */
+    union
+    {
+        struct
+        {
+            unsigned int an_enable:1;
+            unsigned int loopback:1;
+            unsigned int reset:1;
+            unsigned int restart_an:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_an_enable                Mr0.bits.an_enable
+        #define mr_loopback                 Mr0.bits.loopback
+        #define mr_main_reset               Mr0.bits.reset
+        #define mr_restart_an               Mr0.bits.restart_an
+    } Mr0;
+
+    /* Status register. */
+    union
+    {
+        struct
+        {
+            unsigned int an_complete:1;
+            unsigned int link_ok:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_an_complete              Mr1.bits.an_complete
+        #define mr_link_ok                  Mr1.bits.link_ok
+    } Mr1;
+
+    /* Advertisement register. */
+    union
+    {
+        struct
+        {
+            unsigned int reserved_4:5;
+            unsigned int full_duplex:1;
+            unsigned int half_duplex:1;
+            unsigned int sym_pause:1;
+            unsigned int asym_pause:1;
+            unsigned int reserved_11:3;
+            unsigned int remote_fault1:1;
+            unsigned int remote_fault2:1;
+            unsigned int reserved_14:1;
+            unsigned int next_page:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_adv_full_duplex          Mr4.bits.full_duplex
+        #define mr_adv_half_duplex          Mr4.bits.half_duplex
+        #define mr_adv_sym_pause            Mr4.bits.sym_pause
+        #define mr_adv_asym_pause           Mr4.bits.asym_pause
+        #define mr_adv_remote_fault1        Mr4.bits.remote_fault1
+        #define mr_adv_remote_fault2        Mr4.bits.remote_fault2
+        #define mr_adv_next_page            Mr4.bits.next_page
+    } Mr4;
+
+    /* Link partner advertisement register. */
+    union
+    {
+        struct
+        {
+            unsigned int reserved_4:5;
+            unsigned int lp_full_duplex:1;
+            unsigned int lp_half_duplex:1;
+            unsigned int lp_sym_pause:1;
+            unsigned int lp_asym_pause:1;
+            unsigned int reserved_11:3;
+            unsigned int lp_remote_fault1:1;
+            unsigned int lp_remote_fault2:1;
+            unsigned int lp_ack:1;
+            unsigned int lp_next_page:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_lp_adv_full_duplex       Mr5.bits.lp_full_duplex
+        #define mr_lp_adv_half_duplex       Mr5.bits.lp_half_duplex
+        #define mr_lp_adv_sym_pause         Mr5.bits.lp_sym_pause
+        #define mr_lp_adv_asym_pause        Mr5.bits.lp_asym_pause
+        #define mr_lp_adv_remote_fault1     Mr5.bits.lp_remote_fault1
+        #define mr_lp_adv_remote_fault2     Mr5.bits.lp_remote_fault2
+        #define mr_lp_adv_next_page         Mr5.bits.lp_next_page
+    } Mr5;
+
+    /* Auto-negotiation expansion register. */
+    union
+    {
+        struct
+        {
+            unsigned int reserved_0:1;
+            unsigned int page_received:1;
+            unsigned int next_pageable:1;
+            unsigned int reserved_15:13;
+        } bits;
+
+        unsigned short AsUSHORT;
+    } Mr6;
+
+    /* Auto-negotiation next page transmit register. */
+    union
+    {
+        struct
+        {
+            unsigned int code_field:11;
+            unsigned int toggle:1;
+            unsigned int ack2:1;
+            unsigned int message_page:1;
+            unsigned int reserved_14:1;
+            unsigned int next_page:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_np_tx                    Mr7.AsUSHORT
+    } Mr7;
+
+    /* Auto-negotiation link partner ability register. */
+    union
+    {
+        struct
+        {
+            unsigned int code_field:11;
+            unsigned int toggle:1;
+            unsigned int ack2:1;
+            unsigned int message_page:1;
+            unsigned int ack:1;
+            unsigned int next_page:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_lp_np_rx                 Mr8.AsUSHORT
+    } Mr8;
+
+    /* Extended status register. */
+    union
+    {
+        struct
+        {
+            unsigned int reserved_11:12;
+            unsigned int base1000_t_hd:1;
+            unsigned int base1000_t_fd:1;
+            unsigned int base1000_x_hd:1;
+            unsigned int base1000_x_fd:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+    } Mr15;
+
+    /* Miscellaneous state variables. */
+    union
+    {
+        struct
+        {
+            unsigned int toggle_tx:1;
+            unsigned int toggle_rx:1;
+            unsigned int np_rx:1;
+            unsigned int page_rx:1;
+            unsigned int np_loaded:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_toggle_tx                MrMisc.bits.toggle_tx
+        #define mr_toggle_rx                MrMisc.bits.toggle_rx
+        #define mr_np_rx                    MrMisc.bits.np_rx
+        #define mr_page_rx                  MrMisc.bits.page_rx
+        #define mr_np_loaded                MrMisc.bits.np_loaded
+    } MrMisc;
+
+
+    /* Implement specifics */
+
+    /* Pointer to the operating system specific data structure. */
+    void *pContext;
+} AN_STATE_INFO, *PAN_STATE_INFO;
+
+
+
+/******************************************************************************/
+/* Return code of Autoneg8023z. */
+/******************************************************************************/
+
+typedef enum
+{
+    AUTONEG_STATUS_OK               = 0,
+    AUTONEG_STATUS_DONE             = 1,
+    AUTONEG_STATUS_TIMER_ENABLED    = 2,
+    AUTONEG_STATUS_FAILED           = 0xfffffff
+} AUTONEG_STATUS, *PAUTONEG_STATUS;
+
+
+
+/******************************************************************************/
+/* Function prototypes. */
+/******************************************************************************/
+
+AUTONEG_STATUS Autoneg8023z(PAN_STATE_INFO pAnInfo);
+void AutonegInit(PAN_STATE_INFO pAnInfo);
+
+
+
+/******************************************************************************/
+/* The following functions are defined in the os-dependent module. */
+/******************************************************************************/
+
+void MM_AnTxConfig(PAN_STATE_INFO pAnInfo);
+void MM_AnTxIdle(PAN_STATE_INFO pAnInfo);
+char MM_AnRxConfig(PAN_STATE_INFO pAnInfo, unsigned short *pRxConfig);
+
+
+
+#endif /* AUTONEG_H */
+
diff --git a/drivers/bcm570x_debug.h b/drivers/bcm570x_debug.h
new file mode 100644 (file)
index 0000000..0a688cf
--- /dev/null
@@ -0,0 +1,111 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* 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, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#ifdef VXWORKS
+#include <vxWorks.h>
+#endif
+
+/******************************************************************************/
+/* Debug macros                                                               */
+/******************************************************************************/
+
+/* Code path for controlling output debug messages. */
+/* Define your code path here. */
+#define CP_INIT                     0x010000
+#define CP_SEND                     0x020000
+#define CP_RCV                      0x040000
+#define CP_INT                      0x080000
+#define CP_UINIT                    0x100000
+#define CP_RESET                    0x200000
+
+#define CP_ALL                      (CP_INIT | CP_SEND | CP_RCV | CP_INT | \
+                                    CP_RESET | CP_UINIT)
+
+#define CP_MASK                     0xffff0000
+
+
+/* Debug message levels. */
+#define LV_VERBOSE                  0x03
+#define LV_INFORM                   0x02
+#define LV_WARN                     0x01
+#define LV_FATAL                    0x00
+
+#define LV_MASK                     0xffff
+
+
+/* Code path and messsage level combined.  These are the first argument of */
+/* the DbgMessage macro. */
+#define INIT_V                      (CP_INIT | LV_VERBOSE)
+#define INIT_I                      (CP_INIT | LV_INFORM)
+#define INIT_W                      (CP_INIT | LV_WARN)
+#define SEND_V                      (CP_SEND | LV_VERBOSE)
+#define SEND_I                      (CP_SEND | LV_INFORM)
+#define SEND_W                      (CP_SEND | LV_WARN)
+#define RCV_V                       (CP_RCV | LV_VERBOSE)
+#define RCV_I                       (CP_RCV | LV_INFORM)
+#define RCV_W                       (CP_RCV | LV_WARN)
+#define INT_V                       (CP_INT | LV_VERBOSE)
+#define INT_I                       (CP_INT | LV_INFORM)
+#define INT_W                       (CP_INT | LV_WARN)
+#define UINIT_V                     (CP_UINIT | LV_VERBOSE)
+#define UINIT_I                     (CP_UINIT | LV_INFORM)
+#define UINIT_W                     (CP_UINIT | LV_WARN)
+#define RESET_V                     (CP_RESET | LV_VERBOSE)
+#define RESET_I                     (CP_RESET | LV_INFORM)
+#define RESET_W                     (CP_RESET | LV_WARN)
+#define CPALL_V                     (CP_ALL | LV_VERBOSE)
+#define CPALL_I                     (CP_ALL | LV_INFORM)
+#define CPALL_W                     (CP_ALL | LV_WARN)
+
+
+/* All code path message levels. */
+#define FATAL                       (CP_ALL | LV_FATAL)
+#define WARN                        (CP_ALL | LV_WARN)
+#define INFORM                      (CP_ALL | LV_INFORM)
+#define VERBOSE                     (CP_ALL | LV_VERBOSE)
+
+
+/* These constants control the message output. */
+/* Set your debug message output level and code path here. */
+#ifndef DBG_MSG_CP
+#define DBG_MSG_CP                  CP_ALL      /* Where to output messages. */
+#endif
+
+#ifndef DBG_MSG_LV
+#define DBG_MSG_LV                  LV_VERBOSE  /* Level of message output. */
+#endif
+
+/* DbgMessage macro. */
+#if DBG
+#define DbgMessage(CNTRL, MESSAGE)  \
+    if((CNTRL & DBG_MSG_CP) && ((CNTRL & LV_MASK) <= DBG_MSG_LV)) \
+        printf MESSAGE
+#define DbgBreak()                 DbgBreakPoint()
+#undef STATIC
+#define STATIC
+#else
+#define DbgMessage(CNTRL, MESSAGE)
+#define DbgBreak()
+#undef STATIC
+#define STATIC static
+#endif /* DBG */
+
+
+
+#endif /* DEBUG_H */
+
diff --git a/drivers/bcm570x_lm.h b/drivers/bcm570x_lm.h
new file mode 100644 (file)
index 0000000..79073a8
--- /dev/null
@@ -0,0 +1,469 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* 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, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef LM_H
+#define LM_H
+
+#include "bcm570x_queue.h"
+#include "bcm570x_bits.h"
+
+
+
+/******************************************************************************/
+/* Basic types. */
+/******************************************************************************/
+
+typedef char           LM_CHAR,    *PLM_CHAR;
+typedef unsigned int   LM_UINT,    *PLM_UINT;
+typedef unsigned char  LM_UINT8,   *PLM_UINT8;
+typedef unsigned short LM_UINT16,  *PLM_UINT16;
+typedef unsigned int   LM_UINT32,  *PLM_UINT32;
+typedef unsigned int   LM_COUNTER, *PLM_COUNTER;
+typedef void           LM_VOID,    *PLM_VOID;
+typedef char           LM_BOOL,    *PLM_BOOL;
+
+/* 64bit value. */
+typedef struct {
+#ifdef BIG_ENDIAN_HOST
+    LM_UINT32 High;
+    LM_UINT32 Low;
+#else /* BIG_ENDIAN_HOST */
+    LM_UINT32 Low;
+    LM_UINT32 High;
+#endif /* !BIG_ENDIAN_HOST */
+} LM_UINT64, *PLM_UINT64;
+
+typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS;
+
+/* void LM_INC_PHYSICAL_ADDRESS(PLM_PHYSICAL_ADDRESS pAddr,LM_UINT32 IncSize) */
+#define LM_INC_PHYSICAL_ADDRESS(pAddr, IncSize)             \
+    {                                                       \
+        LM_UINT32 OrgLow;                                   \
+                                                            \
+        OrgLow = (pAddr)->Low;                              \
+        (pAddr)->Low += IncSize;                            \
+        if((pAddr)->Low < OrgLow) {                         \
+            (pAddr)->High++; /* Wrap around. */             \
+        }                                                   \
+    }
+
+
+#ifndef NULL
+#define NULL                ((void *) 0)
+#endif /* NULL */
+
+#ifndef OFFSETOF
+#define OFFSETOF(_s, _m)    (MM_UINT_PTR(&(((_s *) 0)->_m)))
+#endif /* OFFSETOF */
+
+
+
+/******************************************************************************/
+/* Simple macros. */
+/******************************************************************************/
+
+#define IS_ETH_BROADCAST(_pEthAddr)                                         \
+    (((unsigned char *) (_pEthAddr))[0] == ((unsigned char) 0xff))
+
+#define IS_ETH_MULTICAST(_pEthAddr)                                         \
+    (((unsigned char *) (_pEthAddr))[0] & ((unsigned char) 0x01))
+
+#define IS_ETH_ADDRESS_EQUAL(_pEtherAddr1, _pEtherAddr2)                    \
+    ((((unsigned char *) (_pEtherAddr1))[0] ==                              \
+    ((unsigned char *) (_pEtherAddr2))[0]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[1] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[1]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[2] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[2]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[3] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[3]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[4] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[4]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[5] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[5]))
+
+#define COPY_ETH_ADDRESS(_Src, _Dst)                                        \
+    ((unsigned char *) (_Dst))[0] = ((unsigned char *) (_Src))[0];          \
+    ((unsigned char *) (_Dst))[1] = ((unsigned char *) (_Src))[1];          \
+    ((unsigned char *) (_Dst))[2] = ((unsigned char *) (_Src))[2];          \
+    ((unsigned char *) (_Dst))[3] = ((unsigned char *) (_Src))[3];          \
+    ((unsigned char *) (_Dst))[4] = ((unsigned char *) (_Src))[4];          \
+    ((unsigned char *) (_Dst))[5] = ((unsigned char *) (_Src))[5];
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+#define ETHERNET_ADDRESS_SIZE           6
+#define ETHERNET_PACKET_HEADER_SIZE     14
+#define MIN_ETHERNET_PACKET_SIZE        64      /* with 4 byte crc. */
+#define MAX_ETHERNET_PACKET_SIZE        1518    /* with 4 byte crc. */
+#define MIN_ETHERNET_PACKET_SIZE_NO_CRC 60
+#define MAX_ETHERNET_PACKET_SIZE_NO_CRC 1514
+#define MAX_ETHERNET_PACKET_BUFFER_SIZE 1536    /* A nice even number. */
+
+#ifndef LM_MAX_MC_TABLE_SIZE
+#define LM_MAX_MC_TABLE_SIZE            32
+#endif /* LM_MAX_MC_TABLE_SIZE */
+#define LM_MC_ENTRY_SIZE                (ETHERNET_ADDRESS_SIZE+1)
+#define LM_MC_INSTANCE_COUNT_INDEX      (LM_MC_ENTRY_SIZE-1)
+
+
+/* Receive filter masks. */
+#define LM_ACCEPT_UNICAST               0x0001
+#define LM_ACCEPT_MULTICAST             0x0002
+#define LM_ACCEPT_ALL_MULTICAST         0x0004
+#define LM_ACCEPT_BROADCAST             0x0008
+#define LM_ACCEPT_ERROR_PACKET          0x0010
+
+#define LM_PROMISCUOUS_MODE             0x10000
+
+
+
+/******************************************************************************/
+/* PCI registers. */
+/******************************************************************************/
+
+#define PCI_VENDOR_ID_REG               0x00
+#define PCI_DEVICE_ID_REG               0x02
+
+#define PCI_COMMAND_REG                 0x04
+#define PCI_IO_SPACE_ENABLE             0x0001
+#define PCI_MEM_SPACE_ENABLE            0x0002
+#define PCI_BUSMASTER_ENABLE            0x0004
+#define PCI_MEMORY_WRITE_INVALIDATE     0x0010
+#define PCI_PARITY_ERROR_ENABLE         0x0040
+#define PCI_SYSTEM_ERROR_ENABLE         0x0100
+#define PCI_FAST_BACK_TO_BACK_ENABLE    0x0200
+
+#define PCI_STATUS_REG                  0x06
+#define PCI_REV_ID_REG                  0x08
+
+#define PCI_CACHE_LINE_SIZE_REG         0x0c
+
+#define PCI_IO_BASE_ADDR_REG            0x10
+#define PCI_IO_BASE_ADDR_MASK           0xfffffff0
+
+#define PCI_MEM_BASE_ADDR_LOW           0x10
+#define PCI_MEM_BASE_ADDR_HIGH          0x14
+
+#define PCI_SUBSYSTEM_VENDOR_ID_REG     0x2c
+#define PCI_SUBSYSTEM_ID_REG            0x2e
+#define PCI_INT_LINE_REG                0x3c
+
+#define PCIX_CAP_REG                    0x40
+#define PCIX_ENABLE_RELAXED_ORDERING    BIT_17
+
+/******************************************************************************/
+/* Fragment structure. */
+/******************************************************************************/
+
+typedef struct {
+    LM_UINT32 FragSize;
+    LM_PHYSICAL_ADDRESS FragBuf;
+} LM_FRAG, *PLM_FRAG;
+
+typedef struct {
+    /* FragCount is initialized for the caller to the maximum array size, on */
+    /* return FragCount is the number of the actual fragments in the array. */
+    LM_UINT32 FragCount;
+
+    /* Total buffer size. */
+    LM_UINT32 TotalSize;
+
+    /* Fragment array buffer. */
+    LM_FRAG Fragments[1];
+} LM_FRAG_LIST, *PLM_FRAG_LIST;
+
+#define DECLARE_FRAG_LIST_BUFFER_TYPE(_FRAG_LIST_TYPE_NAME, _MAX_FRAG_COUNT) \
+    typedef struct {                                                         \
+        LM_FRAG_LIST FragList;                                               \
+        LM_FRAG FragListBuffer[_MAX_FRAG_COUNT-1];                           \
+    } _FRAG_LIST_TYPE_NAME, *P##_FRAG_LIST_TYPE_NAME
+
+
+
+/******************************************************************************/
+/* Status codes. */
+/******************************************************************************/
+
+#define LM_STATUS_SUCCESS                                       0
+#define LM_STATUS_FAILURE                                       1
+
+#define LM_STATUS_INTERRUPT_ACTIVE                              2
+#define LM_STATUS_INTERRUPT_NOT_ACTIVE                          3
+
+#define LM_STATUS_LINK_ACTIVE                                   4
+#define LM_STATUS_LINK_DOWN                                     5
+#define LM_STATUS_LINK_SETTING_MISMATCH                         6
+
+#define LM_STATUS_TOO_MANY_FRAGMENTS                            7
+#define LM_STATUS_TRANSMIT_ABORTED                              8
+#define LM_STATUS_TRANSMIT_ERROR                                9
+#define LM_STATUS_RECEIVE_ABORTED                               10
+#define LM_STATUS_RECEIVE_ERROR                                 11
+#define LM_STATUS_INVALID_PACKET_SIZE                           12
+#define LM_STATUS_OUT_OF_MAP_REGISTERS                          13
+#define LM_STATUS_UNKNOWN_ADAPTER                               14
+
+typedef LM_UINT LM_STATUS, *PLM_STATUS;
+
+
+
+/******************************************************************************/
+/* Requested media type. */
+/******************************************************************************/
+
+#define LM_REQUESTED_MEDIA_TYPE_AUTO                            0
+#define LM_REQUESTED_MEDIA_TYPE_BNC                             1
+#define LM_REQUESTED_MEDIA_TYPE_UTP_AUTO                        2
+#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS                      3
+#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX          4
+#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS                     5
+#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX         6
+#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS                    7
+#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX        8
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS                   9
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX       10
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS                  11
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX      12
+#define LM_REQUESTED_MEDIA_TYPE_MAC_LOOPBACK                    0xfffe
+#define LM_REQUESTED_MEDIA_TYPE_PHY_LOOPBACK                    0xffff
+
+typedef LM_UINT32 LM_REQUESTED_MEDIA_TYPE, *PLM_REQUESTED_MEDIA_TYPE;
+
+
+
+/******************************************************************************/
+/* Media type. */
+/******************************************************************************/
+
+#define LM_MEDIA_TYPE_UNKNOWN                                   -1
+#define LM_MEDIA_TYPE_AUTO                                      0
+#define LM_MEDIA_TYPE_UTP                                       1
+#define LM_MEDIA_TYPE_BNC                                       2
+#define LM_MEDIA_TYPE_AUI                                       3
+#define LM_MEDIA_TYPE_FIBER                                     4
+
+typedef LM_UINT32 LM_MEDIA_TYPE, *PLM_MEDIA_TYPE;
+
+
+
+/******************************************************************************/
+/* Line speed. */
+/******************************************************************************/
+
+#define LM_LINE_SPEED_UNKNOWN                                   0
+#define LM_LINE_SPEED_10MBPS                                    1
+#define LM_LINE_SPEED_100MBPS                                   2
+#define LM_LINE_SPEED_1000MBPS                                  3
+
+typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED;
+
+
+
+/******************************************************************************/
+/* Duplex mode. */
+/******************************************************************************/
+
+#define LM_DUPLEX_MODE_UNKNOWN                                  0
+#define LM_DUPLEX_MODE_HALF                                     1
+#define LM_DUPLEX_MODE_FULL                                     2
+
+typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE;
+
+
+
+/******************************************************************************/
+/* Power state. */
+/******************************************************************************/
+
+#define LM_POWER_STATE_D0       0
+#define LM_POWER_STATE_D1       1
+#define LM_POWER_STATE_D2       2
+#define LM_POWER_STATE_D3       3
+
+typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE;
+
+
+
+/******************************************************************************/
+/* Task offloading. */
+/******************************************************************************/
+
+#define LM_TASK_OFFLOAD_NONE                    0x0000
+#define LM_TASK_OFFLOAD_TX_IP_CHECKSUM          0x0001
+#define LM_TASK_OFFLOAD_RX_IP_CHECKSUM          0x0002
+#define LM_TASK_OFFLOAD_TX_TCP_CHECKSUM         0x0004
+#define LM_TASK_OFFLOAD_RX_TCP_CHECKSUM         0x0008
+#define LM_TASK_OFFLOAD_TX_UDP_CHECKSUM         0x0010
+#define LM_TASK_OFFLOAD_RX_UDP_CHECKSUM         0x0020
+#define LM_TASK_OFFLOAD_TCP_SEGMENTATION        0x0040
+
+typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD;
+
+
+
+/******************************************************************************/
+/* Flow control. */
+/******************************************************************************/
+
+#define LM_FLOW_CONTROL_NONE                    0x00
+#define LM_FLOW_CONTROL_RECEIVE_PAUSE           0x01
+#define LM_FLOW_CONTROL_TRANSMIT_PAUSE          0x02
+#define LM_FLOW_CONTROL_RX_TX_PAUSE (LM_FLOW_CONTROL_RECEIVE_PAUSE | \
+    LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+
+/* This value can be or-ed with RECEIVE_PAUSE and TRANSMIT_PAUSE.  If the */
+/* auto-negotiation is disabled and the RECEIVE_PAUSE and TRANSMIT_PAUSE */
+/* bits are set, then flow control is enabled regardless of link partner's */
+/* flow control capability. */
+#define LM_FLOW_CONTROL_AUTO_PAUSE              0x80000000
+
+typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL;
+
+
+
+/******************************************************************************/
+/* Wake up mode. */
+/******************************************************************************/
+
+#define LM_WAKE_UP_MODE_NONE                    0
+#define LM_WAKE_UP_MODE_MAGIC_PACKET            1
+#define LM_WAKE_UP_MODE_NWUF                    2
+#define LM_WAKE_UP_MODE_LINK_CHANGE             4
+
+typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE;
+
+
+
+/******************************************************************************/
+/* Counters. */
+/******************************************************************************/
+
+#define LM_COUNTER_FRAMES_XMITTED_OK                            0
+#define LM_COUNTER_FRAMES_RECEIVED_OK                           1
+#define LM_COUNTER_ERRORED_TRANSMIT_COUNT                       2
+#define LM_COUNTER_ERRORED_RECEIVE_COUNT                        3
+#define LM_COUNTER_RCV_CRC_ERROR                                4
+#define LM_COUNTER_ALIGNMENT_ERROR                              5
+#define LM_COUNTER_SINGLE_COLLISION_FRAMES                      6
+#define LM_COUNTER_MULTIPLE_COLLISION_FRAMES                    7
+#define LM_COUNTER_FRAMES_DEFERRED                              8
+#define LM_COUNTER_MAX_COLLISIONS                               9
+#define LM_COUNTER_RCV_OVERRUN                                  10
+#define LM_COUNTER_XMIT_UNDERRUN                                11
+#define LM_COUNTER_UNICAST_FRAMES_XMIT                          12
+#define LM_COUNTER_MULTICAST_FRAMES_XMIT                        13
+#define LM_COUNTER_BROADCAST_FRAMES_XMIT                        14
+#define LM_COUNTER_UNICAST_FRAMES_RCV                           15
+#define LM_COUNTER_MULTICAST_FRAMES_RCV                         16
+#define LM_COUNTER_BROADCAST_FRAMES_RCV                         17
+
+typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE;
+
+
+
+/******************************************************************************/
+/* Forward definition. */
+/******************************************************************************/
+
+typedef struct _LM_DEVICE_BLOCK *PLM_DEVICE_BLOCK;
+typedef struct _LM_PACKET *PLM_PACKET;
+
+
+
+/******************************************************************************/
+/* Function prototypes. */
+/******************************************************************************/
+
+LM_STATUS LM_GetAdapterInfo(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_InitializeAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_ResetAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_DisableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_EnableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS LM_ServiceInterrupts(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetReceiveMask(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask);
+LM_STATUS LM_Halt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_MulticastAdd(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS LM_MulticastDel(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS LM_MulticastClear(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetMacAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress);
+LM_STATUS LM_LoopbackAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pAddress);
+
+LM_UINT32 LM_GetCrcCounter(PLM_DEVICE_BLOCK pDevice);
+
+LM_WAKE_UP_MODE LM_PMCapabilities(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_NwufAdd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize,
+    LM_UINT8 *pByteMask, LM_UINT8 *pPattern);
+LM_STATUS LM_NwufRemove(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize,
+    LM_UINT8 *pByteMask, LM_UINT8 *pPattern);
+LM_STATUS LM_SetPowerState(PLM_DEVICE_BLOCK pDevice, LM_POWER_STATE PowerLevel);
+
+LM_VOID LM_ReadPhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+    PLM_UINT32 pData32);
+LM_VOID LM_WritePhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+    LM_UINT32 Data32);
+
+LM_STATUS LM_ControlLoopBack(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Control);
+LM_STATUS LM_SetupPhy(PLM_DEVICE_BLOCK pDevice);
+int LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDuration);
+
+
+
+/******************************************************************************/
+/* These are the OS specific functions called by LMAC. */
+/******************************************************************************/
+
+LM_STATUS MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT16 *pValue16);
+LM_STATUS MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT16 Value16);
+LM_STATUS MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 *pValue32);
+LM_STATUS MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 Value32);
+LM_STATUS MM_MapMemBase(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_MapIoBase(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+    PLM_VOID *pMemoryBlockVirt);
+LM_STATUS MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+    PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
+    LM_BOOL Cached);
+LM_STATUS MM_GetConfig(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status);
+LM_STATUS MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS LM_MbufWorkAround(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetLinkSpeed(PLM_DEVICE_BLOCK pDevice,
+                         LM_REQUESTED_MEDIA_TYPE RequestedMediaType);
+
+#if INCLUDE_5703_A0_FIX
+LM_STATUS LM_Load5703DmaWFirmware(PLM_DEVICE_BLOCK pDevice);
+#endif
+
+
+#endif /* LM_H */
+
diff --git a/drivers/bcm570x_mm.h b/drivers/bcm570x_mm.h
new file mode 100644 (file)
index 0000000..badd0d2
--- /dev/null
@@ -0,0 +1,160 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* 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, located in the file LICENSE.                 */
+/*                                                                            */
+/******************************************************************************/
+
+#ifndef MM_H
+#define MM_H
+
+#define __raw_readl readl
+#define __raw_writel writel
+
+#define BIG_ENDIAN_HOST 1
+#define readl(addr) (*(volatile unsigned int*)(addr))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+
+/* Define memory barrier function here if needed */
+#define wmb()
+#define membar()
+#include <common.h>
+#include <asm/types.h>
+#include "bcm570x_lm.h"
+#include "bcm570x_queue.h"
+#include "tigon3.h"
+#include <pci.h>
+
+#define FALSE 0
+#define TRUE  1
+#define ERROR -1
+
+#if DBG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+extern int MM_Packet_Desc_Size;
+
+#define MM_PACKET_DESC_SIZE MM_Packet_Desc_Size
+
+DECLARE_QUEUE_TYPE(UM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT+1);
+
+#define MAX_MEM 16
+
+/* Synch */
+typedef int mutex_t;
+typedef int spinlock_t;
+
+/* Embedded device control */
+typedef struct _UM_DEVICE_BLOCK {
+       LM_DEVICE_BLOCK lm_dev;
+        pci_dev_t pdev;
+       char *name;
+       void *mem_list[MAX_MEM];
+       dma_addr_t dma_list[MAX_MEM];
+       int mem_size_list[MAX_MEM];
+       int mem_list_num;
+        int mtu;
+        int index;
+       int opened;
+       int delayed_link_ind; /* Delay link status during initial load */
+       int adapter_just_inited; /* the first few seconds after init. */
+       int spurious_int;            /* new -- unsupported */
+       int timer_interval;
+       int adaptive_expiry;
+       int crc_counter_expiry;         /* new -- unsupported */
+       int poll_tib_expiry;         /* new -- unsupported */
+        int tx_full;
+       int tx_queued;
+       int line_speed;         /* in Mbps, 0 if link is down */
+       UM_RX_PACKET_Q rx_out_of_buf_q;
+       int rx_out_of_buf;
+       int rx_low_buf_thresh; /* changed to rx_buf_repl_thresh */
+       int rx_buf_repl_panic_thresh;
+       int rx_buf_align;            /* new -- unsupported */
+       int do_global_lock;
+        mutex_t global_lock;
+        mutex_t undi_lock;
+       long undi_flags;
+       volatile int interrupt;
+       int tasklet_pending;
+       int tasklet_busy;            /* new -- unsupported */
+        int rx_pkt;
+        int tx_pkt;
+#ifdef NICE_SUPPORT   /* unsupported, this is a linux ioctl */
+       void (*nice_rx)(void*, void* );
+       void* nice_ctx;
+#endif /* NICE_SUPPORT */
+       int rx_adaptive_coalesce;
+       unsigned int rx_last_cnt;
+       unsigned int tx_last_cnt;
+       unsigned int rx_curr_coalesce_frames;
+       unsigned int rx_curr_coalesce_ticks;
+       unsigned int tx_curr_coalesce_frames;  /* new -- unsupported */
+#if TIGON3_DEBUG          /* new -- unsupported */
+        uint tx_zc_count;
+        uint tx_chksum_count;
+        uint tx_himem_count;
+        uint rx_good_chksum_count;
+#endif
+        unsigned int rx_bad_chksum_count;   /* new -- unsupported */
+        unsigned int rx_misc_errors;        /* new -- unsupported */
+} UM_DEVICE_BLOCK, *PUM_DEVICE_BLOCK;
+
+
+/* Physical/PCI DMA address */
+typedef union {
+        dma_addr_t dma_map;
+} dma_map_t;
+
+/* Packet */
+typedef struct
+_UM_PACKET {
+    LM_PACKET lm_packet;
+    void* skbuff;      /* Address of packet buffer */
+} UM_PACKET, *PUM_PACKET;
+
+#define MM_ACQUIRE_UNDI_LOCK(_pDevice)
+#define MM_RELEASE_UNDI_LOCK(_pDevice)
+#define MM_ACQUIRE_INT_LOCK(_pDevice)
+#define MM_RELEASE_INT_LOCK(_pDevice)
+#define MM_UINT_PTR(_ptr)   ((unsigned long) (_ptr))
+
+/* Macro for setting 64bit address struct */
+#define set_64bit_addr(paddr, low, high) \
+        (paddr)->Low = low;             \
+        (paddr)->High = high;
+
+/* Assume that PCI controller's view of host memory is same as host */
+
+#define MEM_TO_PCI_PHYS(addr) (addr)
+
+extern void MM_SetAddr (LM_PHYSICAL_ADDRESS *paddr, dma_addr_t addr);
+extern void MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr);
+extern void MM_MapTxDma (PLM_DEVICE_BLOCK pDevice,
+                        struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR *paddr,
+                        LM_UINT32 *len, int frag);
+extern void MM_MapRxDma ( PLM_DEVICE_BLOCK pDevice,
+                         struct _LM_PACKET *pPacket,
+                         T3_64BIT_HOST_ADDR *paddr);
+
+
+/* BSP needs to provide sysUsecDelay and sysSerialPrintString */
+extern void sysSerialPrintString (char *s);
+#define MM_Wait(usec) udelay(usec)
+
+/* Define memory barrier function here if needed */
+#define wmb()
+
+#if 0
+#define cpu_to_le32(val) LONGSWAP(val)
+#endif
+#endif /* MM_H */
diff --git a/drivers/bcm570x_queue.h b/drivers/bcm570x_queue.h
new file mode 100644 (file)
index 0000000..bc32ad7
--- /dev/null
@@ -0,0 +1,399 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* 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, located in the file LICENSE.                 */
+/*                                                                            */
+/* Queue functions.                                                           */
+/*    void          QQ_InitQueue(PQQ_CONTAINER pQueue)                        */
+/*    char          QQ_Full(PQQ_CONTAINER pQueue)                             */
+/*    char          QQ_Empty(PQQ_CONTAINER pQueue)                            */
+/*    unsigned int QQ_GetSize(PQQ_CONTAINER pQueue)                          */
+/*    unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue)                      */
+/*    char          QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
+/*    char          QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
+/*    PQQ_ENTRY     QQ_PopHead(PQQ_CONTAINER pQueue)                          */
+/*    PQQ_ENTRY     QQ_PopTail(PQQ_CONTAINER pQueue)                          */
+/*    PQQ_ENTRY     QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx)       */
+/*    PQQ_ENTRY     QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx)       */
+/*                                                                            */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef BCM_QUEUE_H
+#define BCM_QUEUE_H
+#ifndef EMBEDDED
+#define EMBEDDED 1
+#endif
+
+/******************************************************************************/
+/* Queue definitions. */
+/******************************************************************************/
+
+/* Entry for queueing. */
+typedef void *PQQ_ENTRY;
+
+/* Linux Atomic Ops support */
+typedef struct { int counter; } atomic_t;
+
+
+/*
+ * This combination of `inline' and `extern' has almost the effect of a
+ * macro.  The way to use it is to put a function definition in a header
+ * file with these keywords, and put another copy of the definition
+ * (lacking `inline' and `extern') in a library file.  The definition in
+ * the header file will cause most calls to the function to be inlined.
+ * If any uses of the function remain, they will refer to the single copy
+ * in the library.
+ */
+extern __inline void
+atomic_set(atomic_t* entry, int val)
+{
+    entry->counter = val;
+}
+extern __inline int
+atomic_read(atomic_t* entry)
+{
+    return entry->counter;
+}
+extern __inline void
+atomic_inc(atomic_t* entry)
+{
+    if(entry)
+       entry->counter++;
+}
+
+extern __inline void
+atomic_dec(atomic_t* entry)
+{
+    if(entry)
+       entry->counter--;
+}
+
+extern __inline void
+atomic_sub(int a, atomic_t* entry)
+{
+    if(entry)
+       entry->counter -= a;
+}
+extern __inline void
+atomic_add(int a, atomic_t* entry)
+{
+    if(entry)
+       entry->counter += a;
+}
+
+
+/* Queue header -- base type. */
+typedef struct {
+    unsigned int Head;
+    unsigned int Tail;
+    unsigned int Size;
+    atomic_t EntryCnt;
+    PQQ_ENTRY Array[1];
+} QQ_CONTAINER, *PQQ_CONTAINER;
+
+
+/* Declare queue type macro. */
+#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE)            \
+                                                                \
+    typedef struct {                                            \
+        QQ_CONTAINER Container;                                 \
+        PQQ_ENTRY EntryBuffer[_QUEUE_SIZE];                     \
+    } _QUEUE_TYPE, *P##_QUEUE_TYPE
+
+
+
+/******************************************************************************/
+/* Compilation switches. */
+/******************************************************************************/
+
+#if DBG
+#undef QQ_NO_OVERFLOW_CHECK
+#undef QQ_NO_UNDERFLOW_CHECK
+#endif /* DBG */
+
+#ifdef QQ_USE_MACROS
+/* notdone */
+#else
+
+#ifdef QQ_NO_INLINE
+#define __inline
+#endif /* QQ_NO_INLINE */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline void
+QQ_InitQueue(
+PQQ_CONTAINER pQueue,
+unsigned int QueueSize) {
+    pQueue->Head = 0;
+    pQueue->Tail = 0;
+    pQueue->Size = QueueSize+1;
+    atomic_set(&pQueue->EntryCnt, 0);
+} /* QQ_InitQueue */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline char
+QQ_Full(
+PQQ_CONTAINER pQueue) {
+    unsigned int NewHead;
+
+    NewHead = (pQueue->Head + 1) % pQueue->Size;
+
+    return(NewHead == pQueue->Tail);
+} /* QQ_Full */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline char
+QQ_Empty(
+PQQ_CONTAINER pQueue) {
+    return(pQueue->Head == pQueue->Tail);
+} /* QQ_Empty */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline unsigned int
+QQ_GetSize(
+PQQ_CONTAINER pQueue) {
+    return pQueue->Size;
+} /* QQ_GetSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline unsigned int
+QQ_GetEntryCnt(
+PQQ_CONTAINER pQueue) {
+    return atomic_read(&pQueue->EntryCnt);
+} /* QQ_GetEntryCnt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+extern __inline char
+QQ_PushHead(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Head;
+
+    Head = (pQueue->Head + 1) % pQueue->Size;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[pQueue->Head] = pEntry;
+    wmb();
+    pQueue->Head = Head;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+extern __inline char
+QQ_PushTail(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Tail;
+
+    Tail = pQueue->Tail;
+    if(Tail == 0) {
+        Tail = pQueue->Size;
+    } /* if */
+    Tail--;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[Tail] = pEntry;
+    wmb();
+    pQueue->Tail = Tail;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_PopHead(
+PQQ_CONTAINER pQueue) {
+    unsigned int Head;
+    PQQ_ENTRY Entry;
+
+    Head = pQueue->Head;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    if(Head == 0) {
+        Head = pQueue->Size;
+    } /* if */
+    Head--;
+
+    Entry = pQueue->Array[Head];
+#ifdef EMBEDDED
+    membar();
+#else
+    mb();
+#endif
+    pQueue->Head = Head;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_PopTail(
+PQQ_CONTAINER pQueue) {
+    unsigned int Tail;
+    PQQ_ENTRY Entry;
+
+    Tail = pQueue->Tail;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    Entry = pQueue->Array[Tail];
+#ifdef EMBEDDED
+    membar();
+#else
+    mb();
+#endif
+    pQueue->Tail = (Tail + 1) % pQueue->Size;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_GetHead(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    if(pQueue->Head > Idx)
+    {
+        Idx = pQueue->Head - Idx;
+    }
+    else
+    {
+        Idx = pQueue->Size - (Idx - pQueue->Head);
+    }
+    Idx--;
+
+    return pQueue->Array[Idx];
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_GetTail(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    Idx += pQueue->Tail;
+    if(Idx >= pQueue->Size)
+    {
+        Idx = Idx - pQueue->Size;
+    }
+
+    return pQueue->Array[Idx];
+}
+
+#endif /* QQ_USE_MACROS */
+
+
+
+#endif /* QUEUE_H */
diff --git a/drivers/cfb_console.c b/drivers/cfb_console.c
new file mode 100644 (file)
index 0000000..ee2fa9c
--- /dev/null
@@ -0,0 +1,912 @@
+/*
+ * (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
+ */
+
+/*
+ * cfb_console.c
+ *
+ * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel.
+ *
+ * At the moment only the 8x16 font is tested and the font fore- and
+ * background color is limited to black/white/gray colors. The Linux
+ * logo can be placed in the upper left corner and additional board
+ * information strings (that normaly goes to serial port) can be drawed.
+ *
+ * The console driver can use the standard PC keyboard interface (i8042)
+ * for character input. Character output goes to a memory mapped video
+ * framebuffer with little or big-endian organisation.
+ * With environment setting 'console=serial' the console i/o can be
+ * forced to serial port.
+
+ The driver uses graphic specific defines/parameters/functions:
+
+ (for SMI LynxE graphic chip)
+
+ CONFIG_VIDEO_SMI_LYNXEM - use graphic driver for SMI 710,712,810
+ VIDEO_FB_LITTLE_ENDIAN  - framebuffer organisation default: big endian
+ VIDEO_HW_RECTFILL       - graphic driver supports hardware rectangle fill
+ VIDEO_HW_BITBLT         - graphic driver supports hardware bit blt
+
+ Console Parameters are set by graphic drivers global struct:
+
+ VIDEO_VISIBLE_COLS          - x resolution
+ VIDEO_VISIBLE_ROWS          - y resolution
+ VIDEO_PIXEL_SIZE            - storage size in byte per pixel
+ VIDEO_DATA_FORMAT           - graphical data format GDF
+ VIDEO_FB_ADRS               - start of video memory
+
+ CONFIG_I8042_KBD            - AT Keyboard driver for i8042
+ VIDEO_KBD_INIT_FCT          - init function for keyboard
+ VIDEO_TSTC_FCT              - keyboard_tstc function
+ VIDEO_GETC_FCT              - keyboard_getc function
+
+ CONFIG_CONSOLE_CURSOR       - on/off drawing cursor is done with delay
+                               loop in VIDEO_TSTC_FCT (i8042)
+ CFG_CONSOLE_BLINK_COUNT     - value for delay loop - blink rate
+ CONFIG_CONSOLE_TIME         - display time/date in upper right corner,
+                               needs CFG_CMD_DATE and CONFIG_CONSOLE_CURSOR
+ CONFIG_VIDEO_LOGO           - display Linux Logo in upper left corner
+ CONFIG_CONSOLE_EXTRA_INFO   - display additional board information strings
+                               that normaly goes to serial port. This define
+                               requires a board specific function:
+                               video_drawstring (VIDEO_INFO_X,
+                                                 VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT,
+                                                 info);
+                               that fills a info buffer at i=row.
+                               s.a: board/eltec/bab7xx.
+CONFIG_VGA_AS_SINGLE_DEVICE  - If set the framebuffer device will be initialised
+                               as an output only device. The Keyboard driver
+                               will not be set-up. This may be used, if you
+                               have none or more than one Keyboard devices
+                               (USB Keyboard, AT Keyboard).
+
+CONFIG_VIDEO_SW_CURSOR:      - Draws a cursor after the last character. No
+                               blinking is provided. Uses the macros CURSOR_SET
+                               and CURSOR_OFF.
+CONFIG_VIDEO_HW_CURSOR:      - Uses the hardware cursor capability of the
+                               graphic chip. Uses the macro CURSOR_SET.
+                               ATTENTION: If booting an OS, the display driver
+                               must disable the hardware register of the graphic
+                               chip. Otherwise a blinking field is displayed
+*/
+
+#include <common.h>
+
+#ifdef CONFIG_CFB_CONSOLE
+
+/*****************************************************************************/
+/* Console device defines with SMI graphic                                   */
+/* Any other graphic must change this section                                */
+/*****************************************************************************/
+
+#ifdef  CONFIG_VIDEO_SMI_LYNXEM
+
+#define VIDEO_FB_LITTLE_ENDIAN
+#define VIDEO_HW_RECTFILL
+#define VIDEO_HW_BITBLT
+#endif
+
+/*****************************************************************************/
+/* Defines for the CT69000 driver                                            */
+/*****************************************************************************/
+#ifdef  CONFIG_VIDEO_CT69000
+
+#define VIDEO_FB_LITTLE_ENDIAN
+#define VIDEO_HW_RECTFILL
+#define VIDEO_HW_BITBLT
+#endif
+
+/*****************************************************************************/
+/* Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc             */
+/*****************************************************************************/
+#include <video_fb.h>
+
+/*****************************************************************************/
+/* some Macros                                                               */
+/*****************************************************************************/
+#define VIDEO_VISIBLE_COLS      (pGD->winSizeX)
+#define VIDEO_VISIBLE_ROWS      (pGD->winSizeY)
+#define VIDEO_PIXEL_SIZE        (pGD->gdfBytesPP)
+#define VIDEO_DATA_FORMAT       (pGD->gdfIndex)
+#define VIDEO_FB_ADRS           (pGD->frameAdrs)
+
+/*****************************************************************************/
+/* Console device defines with i8042 keyboard controller                     */
+/* Any other keyboard controller must change this section                    */
+/*****************************************************************************/
+
+#ifdef  CONFIG_I8042_KBD
+#include <i8042.h>
+
+#define VIDEO_KBD_INIT_FCT      i8042_kbd_init()
+#define VIDEO_TSTC_FCT          i8042_tstc
+#define VIDEO_GETC_FCT          i8042_getc
+#endif
+
+/*****************************************************************************/
+/* Console device                                                            */
+/*****************************************************************************/
+
+#include <version.h>
+#include <linux/types.h>
+#include <devices.h>
+#include <video_font.h>
+#ifdef CFG_CMD_DATE
+#include <rtc.h>
+
+#endif
+
+/*****************************************************************************/
+/* Cursor definition:                                                        */
+/* CONFIG_CONSOLE_CURSOR:  Uses a timer function (see drivers/i8042.c) to    */
+/*                         let the cursor blink. Uses the macros CURSOR_OFF  */
+/*                         and CURSOR_ON.                                    */
+/* CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No       */
+/*                         blinking is provided. Uses the macros CURSOR_SET  */
+/*                         and CURSOR_OFF.                                   */
+/* CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the        */
+/*                         graphic chip. Uses the macro CURSOR_SET.          */
+/*                         ATTENTION: If booting an OS, the display driver   */
+/*                         must disable the hardware register of the graphic */
+/*                         chip. Otherwise a blinking field is displayed     */
+/*****************************************************************************/
+#if !defined(CONFIG_CONSOLE_CURSOR) && \
+    !defined(CONFIG_VIDEO_SW_CURSOR) && \
+    !defined(CONFIG_VIDEO_HW_CURSOR)
+/* no Cursor defined */
+#define CURSOR_ON
+#define CURSOR_OFF
+#define CURSOR_SET
+#endif
+
+#ifdef  CONFIG_CONSOLE_CURSOR
+#ifdef  CURSOR_ON
+#error  only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
+#endif
+void    console_cursor (int state);
+#define CURSOR_ON  console_cursor(1);
+#define CURSOR_OFF console_cursor(0);
+#define CURSOR_SET
+#ifndef CONFIG_I8042_KBD
+#warning Cursor drawing on/off needs timer function s.a. drivers/i8042.c
+#endif
+#else
+#ifdef  CONFIG_CONSOLE_TIME
+#error  CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
+#endif
+#endif /* CONFIG_CONSOLE_CURSOR */
+
+#ifdef  CONFIG_VIDEO_SW_CURSOR
+#ifdef  CURSOR_ON
+#error  only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
+#endif
+#define CURSOR_ON
+#define CURSOR_OFF video_putchar(console_col * VIDEO_FONT_WIDTH,\
+                                 console_row * VIDEO_FONT_HEIGHT, ' ');
+#define CURSOR_SET video_set_cursor();
+#endif /* CONFIG_VIDEO_SW_CURSOR */
+
+
+#ifdef CONFIG_VIDEO_HW_CURSOR
+#ifdef  CURSOR_ON
+#error  only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
+#endif
+#define CURSOR_ON
+#define CURSOR_OFF
+#define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \
+                  (console_row * VIDEO_FONT_HEIGHT) + VIDEO_LOGO_HEIGHT);
+#endif  /* CONFIG_VIDEO_HW_CURSOR */
+
+#ifdef  CONFIG_VIDEO_LOGO
+#define LINUX_LOGO_WIDTH        80
+#define LINUX_LOGO_HEIGHT       80
+#define LINUX_LOGO_COLORS       214
+#define LINUX_LOGO_LUT_OFFSET   0x20
+#define __initdata
+#include <linux_logo.h>
+#define VIDEO_LOGO_WIDTH        LINUX_LOGO_WIDTH
+#define VIDEO_LOGO_HEIGHT       LINUX_LOGO_HEIGHT
+
+#define VIDEO_INFO_X            (VIDEO_LOGO_WIDTH)
+#define VIDEO_INFO_Y            (VIDEO_FONT_HEIGHT/2)
+#else
+#define VIDEO_LOGO_WIDTH        0
+#define VIDEO_LOGO_HEIGHT       0
+#endif
+
+#define VIDEO_COLS              VIDEO_VISIBLE_COLS
+#define VIDEO_ROWS              VIDEO_VISIBLE_ROWS
+#define VIDEO_SIZE              (VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)
+#define VIDEO_PIX_BLOCKS        (VIDEO_SIZE >> 2)
+#define VIDEO_LINE_LEN          (VIDEO_COLS*VIDEO_PIXEL_SIZE)
+#define VIDEO_BURST_LEN         (VIDEO_COLS/8)
+
+#ifdef  CONFIG_VIDEO_LOGO
+#define CONSOLE_ROWS            ((VIDEO_ROWS - VIDEO_LOGO_HEIGHT) / VIDEO_FONT_HEIGHT)
+#else
+#define CONSOLE_ROWS            (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
+#endif
+
+#define CONSOLE_COLS            (VIDEO_COLS / VIDEO_FONT_WIDTH)
+#define CONSOLE_ROW_SIZE        (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
+#define CONSOLE_ROW_FIRST       (video_console_address)
+#define CONSOLE_ROW_SECOND      (video_console_address + CONSOLE_ROW_SIZE)
+#define CONSOLE_ROW_LAST        (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+#define CONSOLE_SIZE            (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
+#define CONSOLE_SCROLL_SIZE     (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+
+/* Macros */
+#ifdef  VIDEO_FB_LITTLE_ENDIAN
+#define SWAP16(x)        ((((x) & 0x00ff) << 8) | ( (x) >> 8))
+#define SWAP32(x)        ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\
+                          (((x) & 0x00ff0000) >>  8) | (((x) & 0xff000000) >> 24) )
+#define SHORTSWAP32(x)   ((((x) & 0x000000ff) <<  8) | (((x) & 0x0000ff00) >> 8)|\
+                          (((x) & 0x00ff0000) <<  8) | (((x) & 0xff000000) >> 8) )
+#else
+#define SWAP16(x)        (x)
+#define SWAP32(x)        (x)
+#define SHORTSWAP32(x)   (x)
+#endif
+
+#if defined(DEBUG) || defined(DEBUG_CFB_CONSOLE)
+#define PRINTD(x)         printf(x)
+#else
+#define PRINTD(x)
+#endif
+
+
+#ifdef CONFIG_CONSOLE_EXTRA_INFO
+extern void video_get_info_str (    /* setup a board string: type, speed, etc. */
+    int line_number,        /* location to place info string beside logo */
+    char *info              /* buffer for info string */
+    );
+
+#endif
+
+/* Locals */
+static GraphicDevice *pGD;     /* Pointer to Graphic array */
+
+static void *video_fb_address;          /* frame buffer address */
+static void *video_console_address;     /* console buffer start address */
+
+static int console_col = 0; /* cursor col */
+static int console_row = 0; /* cursor row */
+
+static u32 eorx, fgx, bgx;  /* color pats */
+
+static const int video_font_draw_table8[] = {
+            0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
+            0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
+            0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
+            0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff };
+
+static const int video_font_draw_table15[] = {
+            0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff };
+
+static const int video_font_draw_table16[] = {
+            0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff };
+
+static const int video_font_draw_table24[16][3] = {
+            { 0x00000000, 0x00000000, 0x00000000 },
+            { 0x00000000, 0x00000000, 0x00ffffff },
+            { 0x00000000, 0x0000ffff, 0xff000000 },
+            { 0x00000000, 0x0000ffff, 0xffffffff },
+            { 0x000000ff, 0xffff0000, 0x00000000 },
+            { 0x000000ff, 0xffff0000, 0x00ffffff },
+            { 0x000000ff, 0xffffffff, 0xff000000 },
+            { 0x000000ff, 0xffffffff, 0xffffffff },
+            { 0xffffff00, 0x00000000, 0x00000000 },
+            { 0xffffff00, 0x00000000, 0x00ffffff },
+            { 0xffffff00, 0x0000ffff, 0xff000000 },
+            { 0xffffff00, 0x0000ffff, 0xffffffff },
+            { 0xffffffff, 0xffff0000, 0x00000000 },
+            { 0xffffffff, 0xffff0000, 0x00ffffff },
+            { 0xffffffff, 0xffffffff, 0xff000000 },
+            { 0xffffffff, 0xffffffff, 0xffffffff } };
+
+static const int video_font_draw_table32[16][4] = {
+            { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+            { 0x00000000, 0x00000000, 0x00000000, 0x00ffffff },
+            { 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 },
+            { 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff },
+            { 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 },
+            { 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff },
+            { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 },
+            { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff },
+            { 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 },
+            { 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff },
+            { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 },
+            { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff },
+            { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 },
+            { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff },
+            { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 },
+            { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } };
+
+
+/******************************************************************************/
+
+
+static void video_drawchars (int xx, int yy, unsigned char *s, int count)
+{
+    u8  *cdat, *dest, *dest0;
+    int rows, offset, c;
+
+    offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
+    dest0 = video_fb_address + offset;
+
+    switch (VIDEO_DATA_FORMAT)
+    {
+    case GDF__8BIT_INDEX:
+    case GDF__8BIT_332RGB:
+        while (count--)
+        {
+        c = *s ;
+        cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+        for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+        {
+            u8 bits = *cdat++;
+            ((u32 *)dest)[0] = (video_font_draw_table8[bits >> 4] & eorx) ^ bgx;
+            ((u32 *)dest)[1] = (video_font_draw_table8[bits & 15] & eorx) ^ bgx;
+        }
+        dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+        s++;
+        }
+        break;
+
+    case GDF_15BIT_555RGB:
+        while (count--)
+        {
+        c = *s ;
+        cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+        for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+        {
+            u8 bits = *cdat++;
+            ((u32 *)dest)[0] = SHORTSWAP32((video_font_draw_table15[bits >> 6] & eorx) ^ bgx);
+            ((u32 *)dest)[1] = SHORTSWAP32((video_font_draw_table15[bits >> 4 & 3] & eorx) ^ bgx);
+            ((u32 *)dest)[2] = SHORTSWAP32((video_font_draw_table15[bits >> 2 & 3] & eorx) ^ bgx);
+            ((u32 *)dest)[3] = SHORTSWAP32((video_font_draw_table15[bits & 3] & eorx) ^ bgx);
+            }
+            dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+            s++ ;
+        }
+        break;
+
+    case GDF_16BIT_565RGB:
+        while (count--)
+        {
+        c = *s ;
+        cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+        for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+        {
+            u8 bits = *cdat++;
+            ((u32 *)dest)[0] = SHORTSWAP32((video_font_draw_table16[bits >> 6] & eorx) ^ bgx);
+            ((u32 *)dest)[1] = SHORTSWAP32((video_font_draw_table16[bits >> 4 & 3] & eorx) ^ bgx);
+            ((u32 *)dest)[2] = SHORTSWAP32((video_font_draw_table16[bits >> 2 & 3] & eorx) ^ bgx);
+            ((u32 *)dest)[3] = SHORTSWAP32((video_font_draw_table16[bits & 3] & eorx) ^ bgx);
+        }
+        dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+        s++ ;
+        }
+        break;
+
+    case GDF_32BIT_X888RGB:
+        while (count--)
+        {
+        c = *s ;
+        cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+        for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+        {
+            u8 bits = *cdat++;
+            ((u32 *)dest)[0] = SWAP32((video_font_draw_table32[bits >> 4][0] & eorx) ^ bgx);
+            ((u32 *)dest)[1] = SWAP32((video_font_draw_table32[bits >> 4][1] & eorx) ^ bgx);
+            ((u32 *)dest)[2] = SWAP32((video_font_draw_table32[bits >> 4][2] & eorx) ^ bgx);
+            ((u32 *)dest)[3] = SWAP32((video_font_draw_table32[bits >> 4][3] & eorx) ^ bgx);
+            ((u32 *)dest)[4] = SWAP32((video_font_draw_table32[bits & 15][0] & eorx) ^ bgx);
+            ((u32 *)dest)[5] = SWAP32((video_font_draw_table32[bits & 15][1] & eorx) ^ bgx);
+            ((u32 *)dest)[6] = SWAP32((video_font_draw_table32[bits & 15][2] & eorx) ^ bgx);
+            ((u32 *)dest)[7] = SWAP32((video_font_draw_table32[bits & 15][3] & eorx) ^ bgx);
+        }
+        dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+        s++ ;
+        }
+        break;
+
+    case GDF_24BIT_888RGB:
+        while (count--)
+        {
+        c = *s ;
+        cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+        for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+        {
+            u8 bits = *cdat++;
+            ((u32 *)dest)[0] = (video_font_draw_table24[bits >> 4][0] & eorx) ^ bgx;
+            ((u32 *)dest)[1] = (video_font_draw_table24[bits >> 4][1] & eorx) ^ bgx;
+            ((u32 *)dest)[2] = (video_font_draw_table24[bits >> 4][2] & eorx) ^ bgx;
+            ((u32 *)dest)[3] = (video_font_draw_table24[bits & 15][0] & eorx) ^ bgx;
+            ((u32 *)dest)[4] = (video_font_draw_table24[bits & 15][1] & eorx) ^ bgx;
+            ((u32 *)dest)[5] = (video_font_draw_table24[bits & 15][2] & eorx) ^ bgx;
+        }
+        dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+        s++ ;
+        }
+        break;
+    }
+}
+
+/*****************************************************************************/
+
+static inline void video_drawstring(int xx, int yy, unsigned char *s)
+{
+    video_drawchars (xx, yy, s, strlen(s));
+}
+
+/*****************************************************************************/
+
+static void video_putchar(int xx, int yy, unsigned char c)
+{
+#ifdef CONFIG_VIDEO_LOGO
+    video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, &c, 1);
+#else
+    video_drawchars (xx, yy, &c, 1);
+#endif
+}
+
+/*****************************************************************************/
+#if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
+static void video_set_cursor(void)
+{
+    /* swap drawing colors */
+    eorx = fgx;
+    fgx  = bgx;
+    bgx  = eorx;
+    eorx = fgx ^ bgx;
+    /* draw cursor */
+    video_putchar (console_col * VIDEO_FONT_WIDTH,
+                   console_row * VIDEO_FONT_HEIGHT, ' ');
+    /* restore drawing colors */
+    eorx = fgx;
+    fgx  = bgx;
+    bgx  = eorx;
+    eorx = fgx ^ bgx;
+}
+#endif
+/*****************************************************************************/
+#ifdef CONFIG_CONSOLE_CURSOR
+void console_cursor (int state)
+{
+    static int last_state = 0;
+#ifdef CONFIG_CONSOLE_TIME
+    struct rtc_time tm;
+    char info[16];
+
+    /* time update only if cursor is on (faster scroll) */
+    if (state)
+    {
+    rtc_get (&tm);
+
+    sprintf(info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec);
+    video_drawstring(VIDEO_VISIBLE_COLS-10*VIDEO_FONT_WIDTH,
+             VIDEO_INFO_Y, info);
+
+    sprintf(info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon, tm.tm_year);
+    video_drawstring(VIDEO_VISIBLE_COLS-10*VIDEO_FONT_WIDTH,
+             VIDEO_INFO_Y+1*VIDEO_FONT_HEIGHT, info);
+    }
+#endif
+
+    if (state && (last_state != state))
+    {
+        video_set_cursor();
+    }
+
+    if (!state && (last_state != state))
+    {
+        /* clear cursor */
+        video_putchar (console_col * VIDEO_FONT_WIDTH,
+                       console_row * VIDEO_FONT_HEIGHT, ' ');
+    }
+
+    last_state = state;
+}
+#endif
+
+/*****************************************************************************/
+
+#ifndef VIDEO_HW_RECTFILL
+static void memsetl (int *p, int c, int v)
+{
+    while (c--)
+        *(p++) = v;
+}
+#endif
+
+/*****************************************************************************/
+
+#ifndef VIDEO_HW_BITBLT
+static void memcpyl (int *d, int *s, int c)
+{
+    while (c--)
+        *(d++) = *(s++);
+}
+#endif
+
+/*****************************************************************************/
+
+static void console_scrollup (void)
+{
+    /* copy up rows ignoring the first one */
+
+#ifdef VIDEO_HW_BITBLT
+    video_hw_bitblt (
+    VIDEO_PIXEL_SIZE,     /* bytes per pixel */
+    0,                    /* source pos x */
+    VIDEO_LOGO_HEIGHT + VIDEO_FONT_HEIGHT, /* source pos y */
+    0,                    /* dest pos x */
+    VIDEO_LOGO_HEIGHT,    /* dest pos y */
+    VIDEO_VISIBLE_COLS,   /* frame width */
+    VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT /* frame height */
+    );
+#else
+    memcpyl (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE >> 2);
+#endif
+
+    /* clear the last one */
+#ifdef VIDEO_HW_RECTFILL
+    video_hw_rectfill (
+    VIDEO_PIXEL_SIZE,     /* bytes per pixel */
+    0,                    /* dest pos x */
+    VIDEO_VISIBLE_ROWS - VIDEO_FONT_HEIGHT,  /* dest pos y */
+    VIDEO_VISIBLE_COLS,   /* frame width */
+    VIDEO_FONT_HEIGHT,    /* frame height */
+    CONSOLE_BG_COL          /* fill color */
+    );
+#else
+    memsetl (CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, CONSOLE_BG_COL);
+#endif
+}
+
+/*****************************************************************************/
+
+static void console_back (void)
+{
+    CURSOR_OFF
+    console_col--;
+
+    if (console_col < 0)
+    {
+        console_col = CONSOLE_COLS - 1;
+        console_row--;
+        if (console_row < 0)
+        console_row = 0;
+    }
+    video_putchar (console_col * VIDEO_FONT_WIDTH,
+                   console_row * VIDEO_FONT_HEIGHT, ' ');
+}
+
+/*****************************************************************************/
+
+static void console_newline (void)
+{
+    CURSOR_OFF
+    console_row++;
+    console_col = 0;
+
+    /* Check if we need to scroll the terminal */
+    if (console_row >= CONSOLE_ROWS)
+    {
+    /* Scroll everything up */
+    console_scrollup ();
+
+    /* Decrement row number */
+    console_row--;
+    }
+}
+
+/*****************************************************************************/
+
+void video_putc (const char c)
+{
+    switch (c)
+    {
+    case 13: /* ignore */
+        break;
+
+    case '\n': /* next line */
+        console_newline();
+        break;
+
+    case 9:    /* tab 8 */
+        CURSOR_OFF
+        console_col |=  0x0008;
+        console_col &= ~0x0007;
+
+        if (console_col >= CONSOLE_COLS)
+            console_newline();
+        break;
+
+    case 8:    /* backspace */
+        console_back();
+        break;
+
+    default: /* draw the char */
+        video_putchar (console_col * VIDEO_FONT_WIDTH,
+                       console_row * VIDEO_FONT_HEIGHT, c);
+        console_col++ ;
+
+        /* check for newline */
+        if (console_col >= CONSOLE_COLS)
+            console_newline();
+    }
+    CURSOR_SET
+}
+
+
+
+/*****************************************************************************/
+
+void video_puts (const char *s)
+{
+    int count = strlen(s);
+
+    while(count--)
+        video_putc(*s++);
+}
+
+/*****************************************************************************/
+
+#ifdef CONFIG_VIDEO_LOGO
+void logo_plot (void *screen, int width, int x, int y)
+{
+    int skip = (width - LINUX_LOGO_WIDTH) * VIDEO_PIXEL_SIZE,
+        xcount, i,
+        ycount = LINUX_LOGO_HEIGHT;
+    unsigned char
+        *source = linux_logo,
+        *dest   = (unsigned char *) screen + ((y * width * VIDEO_PIXEL_SIZE) + x),
+        r, g, b;
+
+    if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX)
+    {
+        for (i = 0; i < LINUX_LOGO_COLORS; i++)
+        {
+            r = (unsigned char)linux_logo_red  [i];
+            g = (unsigned char)linux_logo_green[i];
+            b = (unsigned char)linux_logo_blue [i];
+            video_set_lut (LINUX_LOGO_LUT_OFFSET + i, r, g, b);
+        }
+    }
+
+    while (ycount--)
+    {
+    xcount = LINUX_LOGO_WIDTH;
+    while (xcount--)
+    {
+        r = (unsigned char)linux_logo_red  [*source - LINUX_LOGO_LUT_OFFSET];
+        g = (unsigned char)linux_logo_green[*source - LINUX_LOGO_LUT_OFFSET];
+        b = (unsigned char)linux_logo_blue [*source - LINUX_LOGO_LUT_OFFSET];
+
+        switch (VIDEO_DATA_FORMAT)
+        {
+        case GDF__8BIT_INDEX:
+            *dest = *source;
+            break;
+        case GDF__8BIT_332RGB:
+            *dest = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6);
+            break;
+        case GDF_15BIT_555RGB:
+            *(unsigned short *)dest =
+            SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3)));
+            break;
+        case GDF_16BIT_565RGB:
+            *(unsigned short *)dest =
+            SWAP16((unsigned short)(((r>>3)<<11) | ((g>>2)<<5) | (b>>3)));
+            break;
+        case GDF_32BIT_X888RGB:
+            *(unsigned long  *)dest =
+            SWAP32((unsigned long)((r<<16) | (g<<8) | b));
+            break;
+        case GDF_24BIT_888RGB:
+#ifdef VIDEO_FB_LITTLE_ENDIAN
+            dest[0] = b;
+            dest[1] = g;
+            dest[2] = r;
+#else
+            dest[0] = r;
+            dest[1] = g;
+            dest[2] = b;
+#endif
+            break;
+        }
+        source++;
+        dest += VIDEO_PIXEL_SIZE;
+    }
+    dest += skip;
+    }
+}
+
+
+/*****************************************************************************/
+
+static void *video_logo (void)
+{
+    char info[128];
+
+    logo_plot (video_fb_address, VIDEO_COLS, 0, 0);
+
+    sprintf(info, " %s (%s - %s)", U_BOOT_VERSION, __DATE__, __TIME__);
+    video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, info);
+
+#ifdef CONFIG_CONSOLE_EXTRA_INFO
+    {
+    int i, n = ((VIDEO_LOGO_HEIGHT-VIDEO_FONT_HEIGHT)/VIDEO_FONT_HEIGHT);
+
+    for (i = 1; i < n; i++)
+    {
+        video_get_info_str (i, info);
+        if (*info)
+        video_drawstring (VIDEO_INFO_X,
+                          VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT, info);
+    }
+    }
+#endif
+
+    return (video_fb_address + VIDEO_LOGO_HEIGHT * VIDEO_LINE_LEN);
+}
+#endif
+
+
+/*****************************************************************************/
+
+static int video_init(void)
+{
+    unsigned char color8;
+
+    if ((pGD=video_hw_init()) == NULL)
+        return -1;
+
+    video_fb_address = (void*)VIDEO_FB_ADRS;
+#ifdef CONFIG_VIDEO_HW_CURSOR
+    video_init_hw_cursor(VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
+#endif
+
+    /* Init drawing pats */
+    switch (VIDEO_DATA_FORMAT)
+    {
+    case GDF__8BIT_INDEX:
+        video_set_lut (0x01, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
+        video_set_lut (0x00, CONSOLE_BG_COL, CONSOLE_BG_COL, CONSOLE_BG_COL);
+        fgx = 0x01010101;
+        bgx = 0x00000000;
+        break;
+    case GDF__8BIT_332RGB:
+        color8 = ((CONSOLE_FG_COL & 0xe0) | ((CONSOLE_FG_COL>>3) & 0x1c) | CONSOLE_FG_COL>>6);
+        fgx = (color8<<24) | (color8<<16) | (color8<<8) | color8;
+        color8 = ((CONSOLE_BG_COL & 0xe0) | ((CONSOLE_BG_COL>>3) & 0x1c) | CONSOLE_BG_COL>>6);
+        bgx = (color8<<24) | (color8<<16) | (color8<<8) | color8;
+        break;
+    case GDF_15BIT_555RGB:
+        fgx = (((CONSOLE_FG_COL>>3)<<26) | ((CONSOLE_FG_COL>>3)<<21) | ((CONSOLE_FG_COL>>3)<<16) |
+           ((CONSOLE_FG_COL>>3)<<10) | ((CONSOLE_FG_COL>>3)<<5)  |  (CONSOLE_FG_COL>>3));
+        bgx = (((CONSOLE_BG_COL>>3)<<26) | ((CONSOLE_BG_COL>>3)<<21) | ((CONSOLE_BG_COL>>3)<<16) |
+           ((CONSOLE_BG_COL>>3)<<10) | ((CONSOLE_BG_COL>>3)<<5)  |  (CONSOLE_BG_COL>>3));
+        break;
+    case GDF_16BIT_565RGB:
+        fgx = (((CONSOLE_FG_COL>>3)<<27) | ((CONSOLE_FG_COL>>2)<<21) | ((CONSOLE_FG_COL>>3)<<16) |
+           ((CONSOLE_FG_COL>>3)<<11) | ((CONSOLE_FG_COL>>2)<<5)  |  (CONSOLE_FG_COL>>3));
+        bgx = (((CONSOLE_BG_COL>>3)<<27) | ((CONSOLE_BG_COL>>2)<<21) | ((CONSOLE_BG_COL>>3)<<16) |
+           ((CONSOLE_BG_COL>>3)<<11) | ((CONSOLE_BG_COL>>2)<<5)  |  (CONSOLE_BG_COL>>3));
+        break;
+    case GDF_32BIT_X888RGB:
+        fgx = (CONSOLE_FG_COL<<16) | (CONSOLE_FG_COL<<8) | CONSOLE_FG_COL;
+        bgx = (CONSOLE_BG_COL<<16) | (CONSOLE_BG_COL<<8) | CONSOLE_BG_COL;
+        break;
+    case GDF_24BIT_888RGB:
+        fgx = (CONSOLE_FG_COL<<24) | (CONSOLE_FG_COL<<16) | (CONSOLE_FG_COL<<8) | CONSOLE_FG_COL;
+        bgx = (CONSOLE_BG_COL<<24) | (CONSOLE_BG_COL<<16) | (CONSOLE_BG_COL<<8) | CONSOLE_BG_COL;
+        break;
+    }
+    eorx = fgx ^ bgx;
+
+#ifdef CONFIG_VIDEO_LOGO
+    /* Plot the logo and get start point of console */
+    PRINTD("Video: Drawing the logo ...\n");
+    video_console_address = video_logo();
+#else
+    video_console_address = video_fb_address;
+#endif
+
+    /* Initialize the console */
+    console_col  = 0;
+    console_row  = 0;
+
+    return 0 ;
+}
+
+
+/*****************************************************************************/
+
+int drv_video_init (void)
+{
+    int skip_dev_init;
+    device_t console_dev;
+    char *penv;
+
+    skip_dev_init = 0;
+
+     /* Force console i/o to serial ? */
+    if ((penv = getenv ("console")) != NULL)
+        if (strcmp (penv, "serial") == 0)
+            return 0;
+
+   /* Init video chip - returns with framebuffer cleared */
+    if (video_init() == -1)
+        skip_dev_init = 1;
+#ifdef CONFIG_VGA_AS_SINGLE_DEVICE
+   /* Devices VGA and Keyboard will be assigned seperately */
+    /* Init vga device */
+    if (!skip_dev_init)
+    {
+        memset (&console_dev, 0, sizeof(console_dev));
+        strcpy(console_dev.name, "vga");
+        console_dev.ext   = DEV_EXT_VIDEO;    /* Video extensions */
+        console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
+        console_dev.putc  = video_putc;        /* 'putc' function */
+        console_dev.puts  = video_puts;        /* 'puts' function */
+        console_dev.tstc  = NULL;              /* 'tstc' function */
+        console_dev.getc  = NULL;              /* 'getc' function */
+
+        if (device_register (&console_dev) == 0)
+            return 1;
+    }
+#else
+    PRINTD("KBD: Keyboard init ...\n");
+    if (VIDEO_KBD_INIT_FCT == -1)
+        skip_dev_init = 1;
+
+    /* Init console device */
+    if (!skip_dev_init)
+    {
+        memset (&console_dev, 0, sizeof(console_dev));
+        strcpy(console_dev.name, "console");
+        console_dev.ext   = DEV_EXT_VIDEO;    /* Video extensions */
+        console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+        console_dev.putc  = video_putc;        /* 'putc' function */
+        console_dev.puts  = video_puts;        /* 'puts' function */
+        console_dev.tstc  = VIDEO_TSTC_FCT;    /* 'tstc' function */
+        console_dev.getc  = VIDEO_GETC_FCT;    /* 'getc' function */
+
+        if (device_register (&console_dev) == 0)
+            return 1;
+    }
+#endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
+    /* No console dev available */
+    return 0;
+}
+
+#endif /* CONFIG_CFB_CONSOLE */
+
+
+
+
+
+
+
diff --git a/drivers/cs8900.c b/drivers/cs8900.c
new file mode 100644 (file)
index 0000000..ecc7c13
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Cirrus Logic CS8900A Ethernet
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Copyright (C) 1999 Ben Williamson <benw@pobox.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is loaded into SRAM in bootstrap mode, where it waits
+ * for commands on UART1 to read and write memory, jump to code etc.
+ * A design goal for this program is to be entirely independent of the
+ * target board.  Anything with a CL-PS7111 or EP7211 should be able to run
+ * this code in bootstrap mode.  All the board specifics can be handled on
+ * the host.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <common.h>
+#include <command.h>
+#include "cs8900.h"
+#include <net.h>
+
+#ifdef CONFIG_DRIVER_CS8900
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+
+
+/* packet page register access functions */
+
+#ifdef CS8900_BUS32
+/* we don't need 16 bit initialisation on 32 bit bus */
+#define get_reg_init_bus(x) get_reg((x))
+#else
+static unsigned short get_reg_init_bus(int regno)
+{
+    /* force 16 bit busmode */
+    volatile unsigned char c;
+    c = CS8900_BUS16_0;
+    c = CS8900_BUS16_1;
+    c = CS8900_BUS16_0;
+    c = CS8900_BUS16_1;
+    c = CS8900_BUS16_0;
+
+    CS8900_PPTR = regno;
+    return (unsigned short) CS8900_PDATA;
+}
+#endif
+
+static unsigned short
+get_reg(int regno)
+{
+    CS8900_PPTR = regno;
+    return (unsigned short) CS8900_PDATA;
+}
+
+
+static void put_reg(int regno, unsigned short val)
+{
+    CS8900_PPTR = regno;
+    CS8900_PDATA = val;
+}
+
+static void eth_reset(void)
+{
+    int tmo;
+    unsigned short us;
+
+    /* reset NIC */
+    put_reg(PP_SelfCTL, get_reg(PP_SelfCTL) | PP_SelfCTL_Reset );
+
+    /* wait for 200ms */
+    udelay(200000);
+    /* Wait until the chip is reset */
+
+    tmo = get_timer(0) + 1 * CFG_HZ;
+    while ((((us = get_reg_init_bus(PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0)
+          && tmo < get_timer(0))
+      /*NOP*/;
+}
+
+void cs8900_get_enetaddr (uchar *addr)
+{
+    int i;
+    /* verify chip id */
+    if (get_reg_init_bus(PP_ChipID) != 0x630e)
+       return;
+    eth_reset();
+    if ((get_reg(PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) ==
+             (PP_SelfSTAT_EEPROM|PP_SelfSTAT_EEPROM_OK)) {
+       /* Load the MAC from EEPROM */
+       for (i=0; i<6/2; i++) {
+           unsigned int Addr;
+           Addr = get_reg(PP_IA+i*2);
+           addr[i*2] = Addr & 0xFF;
+           addr[i*2+1] = Addr >> 8;
+       }
+    }
+}
+
+void eth_halt( void )
+{
+    /* disable transmitter/receiver mode */
+    put_reg(PP_LineCTL, 0);
+
+    /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */
+    get_reg_init_bus(PP_ChipID);
+}
+
+int eth_init( bd_t *bd )
+{
+
+    /* verify chip id */
+    if (get_reg_init_bus(PP_ChipID) != 0x630e)
+    {
+       printf( "CS8900 Ethernet chip not found?!\n" );
+       return 0;
+    }
+
+    eth_reset();
+    /* set the ethernet address */
+    put_reg(PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8));
+    put_reg(PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8));
+    put_reg(PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8));
+
+    /* receive only error free packets addressed to this card */
+    put_reg(PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK);
+
+    /* do not generate any interrupts on receive operations */
+    put_reg(PP_RxCFG, 0);
+
+    /* do not generate any interrupts on transmit operations */
+    put_reg(PP_TxCFG, 0);
+
+    /* do not generate any interrupts on buffer operations */
+    put_reg(PP_BufCFG, 0);
+
+    /* enable transmitter/receiver mode */
+    put_reg(PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
+
+    return 0;
+}
+
+/* Get a data block via Ethernet */
+extern int eth_rx(void)
+{
+    int i;
+    unsigned short rxlen;
+    unsigned short *addr;
+    unsigned short status;
+
+    status = get_reg(PP_RER);
+
+    if ((status & PP_RER_RxOK) == 0)
+      return 0;
+
+    status = CS8900_RTDATA;       /* stat */
+    rxlen = CS8900_RTDATA;        /* len */
+
+    if(rxlen > PKTSIZE_ALIGN + PKTALIGN)
+      printf("packet too big!\n");
+
+    for(addr = (unsigned short *)NetRxPackets[0], i = rxlen >> 1; i > 0; i-- )
+      *addr++ = CS8900_RTDATA;
+    if(rxlen & 1)
+      *addr++ = CS8900_RTDATA;
+
+    /* Pass the packet up to the protocol layers. */
+    NetReceive(NetRxPackets[0], rxlen);
+
+    return rxlen;
+}
+
+/* Send a data block via Ethernet. */
+extern int eth_send(volatile void *packet, int length)
+{
+    volatile unsigned short *addr;
+    int tmo;
+    unsigned short s;
+
+retry:
+    /* initiate a transmit sequence */
+    CS8900_TxCMD = PP_TxCmd_TxStart_Full;
+    CS8900_TxLEN = length;
+
+    /* Test to see if the chip has allocated memory for the packet */
+    if ((get_reg(PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) {
+       /* Oops... this should not happen! */
+       printf("cs: unable to send packet; retrying...\n");
+       for (tmo = get_timer(0) + 5 * CFG_HZ; get_timer(0) < tmo; )
+         /*NOP*/;
+       eth_reset();
+       goto retry;
+    }
+
+    /* Write the contents of the packet */
+    /* assume even number of bytes */
+    for(addr = packet; length > 0; length -= 2 )
+      CS8900_RTDATA = *addr++;
+
+    /* wait for transfer to succeed */
+    tmo = get_timer(0) + 5 * CFG_HZ;
+    while((s = get_reg(PP_TER) & ~0x1F) == 0)
+    {
+       if (get_timer(0) >= tmo)
+         break;
+    }
+
+      /* nothing */ ;
+    if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) {
+       printf("\ntransmission error %#x\n", s);
+    }
+
+    return 0;
+}
+
+#endif /* COMMANDS & CFG_NET */
+
+#endif /* CONFIG_DRIVER_CS8900 */
diff --git a/drivers/ct69000.c b/drivers/ct69000.c
new file mode 100644 (file)
index 0000000..7962f74
--- /dev/null
@@ -0,0 +1,1484 @@
+/*
+ * (C) Copyright 2002
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ */
+
+/*
+ * ported from ctfb.c (linux kernel) for the U-Boot
+ *
+ */
+
+/************************************************************************
+  Get Parameters for the video mode:
+  Parameters can be set via the variable "videomode" in the environment.
+  2 diferent ways are possible:
+  "videomode=301"   - 301 is a hexadecimal number describing the VESA
+                      mode. Following modes are implemented:
+
+                      Colors    640x480 800x600 1024x768 1152x864
+                     --------+-----------------------------------
+                      8 bits |  0x301   0x303    0x305    0x161
+                     15 bits |  0x310   0x313    0x316    0x162
+                     16 bits |  0x311   0x314    0x317    0x163
+                     24 bits |  0x312   0x315    0x318      ?
+                     --------+-----------------------------------
+  "videomode=bootargs"
+                   - the parameters are parsed from the bootargs.
+                      The format is "NAME:VALUE,NAME:VALUE" etc.
+                      Ex.:
+                      "bootargs=video=ctfb:x:800,y:600,depth:16,pclk:25000"
+                      Parameters not included in the list will be taken from
+                      the default mode, which is one of the following:
+                      mode:0  640x480x24
+                      mode:1  800x600x16
+                      mode:2  1024x768x8
+                      mode:3  960x720x24
+                      mode:4  1152x864x16
+                      if "mode" is not provided within the parameter list,
+                      mode:0 is assumed.
+                      Following parameters are supported:
+                      x       xres = visible resolution horizontal
+                      y       yres = visible resolution vertical
+                      pclk    pixelclocks in pico sec
+                      le      left_marging time from sync to picture in pixelclocks
+                      ri      right_marging time from picture to sync in pixelclocks
+                      up      upper_margin time from sync to picture
+                      lo      lower_margin
+                      hs      hsync_len length of horizontal sync
+                      vs      vsync_len length of vertical sync
+                      sync    see FB_SYNC_*
+                      vmode   see FB_VMODE_*
+                      depth   Color depth in bits per pixel
+                      All other parameters in the variable bootargs are ignored.
+                      It is also possible to set the parameters direct in the
+                      variable "videomode", or in another variable i.e.
+                      "myvideo" and setting the variable "videomode=myvideo"..
+****************************************************************************/
+
+#include <common.h>
+
+#ifdef CONFIG_VIDEO
+
+#include <pci.h>
+#include <video_fb.h>
+
+#ifdef CONFIG_VIDEO_CT69000
+
+/* debug */
+#undef VGA_DEBUG
+#undef VGA_DUMP_REG
+#ifdef VGA_DEBUG
+#define        PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Macros */
+#ifndef min
+#define min( a, b ) ( ( a ) < ( b ) ) ? ( a ) : ( b )
+#endif
+#ifndef max
+#define max( a, b ) ( ( a ) > ( b ) ) ? ( a ) : ( b )
+#endif
+#ifdef minmax
+#error "term minmax already used."
+#endif
+#define minmax( a, x, b ) max( ( a ), min( ( x ), ( b ) ) )
+#define N_ELTS( x ) ( sizeof( x ) / sizeof( x[ 0 ] ) )
+
+/* CT Register Offsets */
+#define CT_AR_O                        0x3c0   /* Index and Data write port of the attribute Registers */
+#define CT_GR_O                        0x3ce   /* Index port of the Graphic Controller Registers */
+#define CT_SR_O                        0x3c4   /* Index port of the Sequencer Controller */
+#define CT_CR_O                        0x3d4   /* Index port of the CRT Controller */
+#define CT_XR_O                        0x3d6   /* Extended Register index */
+#define CT_MSR_W_O             0x3c2   /* Misc. Output Register (write only) */
+#define CT_LUT_MASK_O          0x3c6   /* Color Palette Mask */
+#define CT_LUT_START_O         0x3c8   /* Color Palette Write Mode Index */
+#define CT_LUT_RGB_O           0x3c9   /* Color Palette Data Port */
+#define CT_STATUS_REG0_O       0x3c2   /* Status Register 0 (read only) */
+#define CT_STATUS_REG1_O       0x3da   /* Input Status Register 1 (read only) */
+
+#define CT_FP_O                        0x3d0   /* Index port of the Flat panel Registers */
+#define CT_MR_O                        0x3d2   /* Index Port of the Multimedia Extension */
+
+/* defines for the memory mapped registers */
+#define BR00_o         0x400000        /* Source and Destination Span Register */
+#define BR01_o         0x400004        /* Pattern/Source Expansion Background Color & Transparency Key Register */
+#define BR02_o         0x400008        /* Pattern/Source Expansion Foreground Color Register */
+#define BR03_o         0x40000C        /* Monochrome Source Control Register */
+#define BR04_o         0x400010        /* BitBLT Control Register */
+#define BR05_o         0x400014        /* Pattern Address Registe */
+#define BR06_o         0x400018        /* Source Address Register */
+#define BR07_o         0x40001C        /* Destination Address Register */
+#define BR08_o         0x400020        /* Destination Width & Height Register */
+#define BR09_o         0x400024        /* Source Expansion Background Color & Transparency Key Register */
+#define BR0A_o         0x400028        /* Source Expansion Foreground Color Register */
+
+#define CURSOR_SIZE    0x1000  /* in KByte for HW Cursor */
+#define PATTERN_ADR    (pGD->dprBase + CURSOR_SIZE)    /* pattern Memory after Cursor Memory */
+#define PATTERN_SIZE   8*8*4   /* 4 Bytes per Pixel 8 x 8 Pixel */
+#define ACCELMEMORY    (CURSOR_SIZE + PATTERN_SIZE)    /* reserved Memory for BITBlt and hw cursor */
+
+/* Some Mode definitions */
+#define FB_SYNC_HOR_HIGH_ACT   1       /* horizontal sync high active  */
+#define FB_SYNC_VERT_HIGH_ACT  2       /* vertical sync high active    */
+#define FB_SYNC_EXT            4       /* external sync                */
+#define FB_SYNC_COMP_HIGH_ACT  8       /* composite sync high active   */
+#define FB_SYNC_BROADCAST      16      /* broadcast video timings      */
+                                       /* vtotal = 144d/288n/576i => PAL  */
+                                       /* vtotal = 121d/242n/484i => NTSC */
+#define FB_SYNC_ON_GREEN       32      /* sync on green */
+
+#define FB_VMODE_NONINTERLACED  0      /* non interlaced */
+#define FB_VMODE_INTERLACED    1       /* interlaced   */
+#define FB_VMODE_DOUBLE                2       /* double scan */
+#define FB_VMODE_MASK          255
+
+#define FB_VMODE_YWRAP         256     /* ywrap instead of panning     */
+#define FB_VMODE_SMOOTH_XPAN   512     /* smooth xpan possible (internally used) */
+#define FB_VMODE_CONUPDATE     512     /* don't update x/yoffset       */
+
+#define text                   0
+#define fntwidth               8
+
+/* table for VGA Initialization  */
+typedef struct {
+       const unsigned char reg;
+       const unsigned char val;
+} CT_CFG_TABLE;
+
+/* this table provides some basic initialisations such as Memory Clock etc */
+static CT_CFG_TABLE xreg[] = {
+       {0x09, 0x01},           /* CRT Controller Extensions Enable */
+       {0x0A, 0x02},           /* Frame Buffer Mapping */
+       {0x0B, 0x01},           /* PCI Write Burst support */
+       {0x20, 0x00},           /* BitBLT Configuration */
+       {0x40, 0x03},           /* Memory Access Control */
+       {0x60, 0x00},           /* Video Pin Control */
+       {0x61, 0x00},           /* DPMS Synch control */
+       {0x62, 0x00},           /* GPIO Pin Control */
+       {0x63, 0xBD},           /* GPIO Pin Data */
+       {0x67, 0x00},           /* Pin Tri-State */
+       {0x80, 0x80},           /* Pixel Pipeline Config 0 register */
+       {0xA0, 0x00},           /* Cursor 1 Control Reg */
+       {0xA1, 0x00},           /* Cursor 1 Vertical Extension Reg */
+       {0xA2, 0x00},           /* Cursor 1 Base Address Low */
+       {0xA3, 0x00},           /* Cursor 1 Base Address High */
+       {0xA4, 0x00},           /* Cursor 1 X-Position Low */
+       {0xA5, 0x00},           /* Cursor 1 X-Position High */
+       {0xA6, 0x00},           /* Cursor 1 Y-Position Low */
+       {0xA7, 0x00},           /* Cursor 1 Y-Position High */
+       {0xA8, 0x00},           /* Cursor 2 Control Reg */
+       {0xA9, 0x00},           /* Cursor 2 Vertical Extension Reg */
+       {0xAA, 0x00},           /* Cursor 2 Base Address Low */
+       {0xAB, 0x00},           /* Cursor 2 Base Address High */
+       {0xAC, 0x00},           /* Cursor 2 X-Position Low */
+       {0xAD, 0x00},           /* Cursor 2 X-Position High */
+       {0xAE, 0x00},           /* Cursor 2 Y-Position Low */
+       {0xAF, 0x00},           /* Cursor 2 Y-Position High */
+       {0xC0, 0x7D},           /* Dot Clock 0 VCO M-Divisor */
+       {0xC1, 0x07},           /* Dot Clock 0 VCO N-Divisor */
+       {0xC3, 0x34},           /* Dot Clock 0 Divisor select */
+       {0xC4, 0x55},           /* Dot Clock 1 VCO M-Divisor */
+       {0xC5, 0x09},           /* Dot Clock 1 VCO N-Divisor */
+       {0xC7, 0x24},           /* Dot Clock 1 Divisor select */
+       {0xC8, 0x7D},           /* Dot Clock 2 VCO M-Divisor */
+       {0xC9, 0x07},           /* Dot Clock 2 VCO N-Divisor */
+       {0xCB, 0x34},           /* Dot Clock 2 Divisor select */
+       {0xCC, 0x38},           /* Memory Clock 0 VCO M-Divisor */
+       {0xCD, 0x03},           /* Memory Clock 0 VCO N-Divisor */
+       {0xCE, 0x90},           /* Memory Clock 0 Divisor select */
+       {0xCF, 0x06},           /* Clock Config */
+       {0xD0, 0x0F},           /* Power Down */
+       {0xD1, 0x01},           /* Power Down BitBLT */
+       {0xFF, 0xFF}            /* end of table */
+};
+/* Clock Config:
+ * =============
+ *
+ * PD Registers:
+ * -------------
+ * Bit2 and Bit4..6 are used for the Loop Divisor and Post Divisor.
+ * They are encoded as follows:
+ *
+ * +---+--------------+
+ * | 2 | Loop Divisor |
+ * +---+--------------+
+ * | 1 | 1            |
+ * +---+--------------+
+ * | 0 | 4            |
+ * +---+--------------+
+ * Note: The Memory Clock does not have a Loop Divisor.
+ * +---+---+---+--------------+
+ * | 6 | 5 | 4 | Post Divisor |
+ * +---+---+---+--------------+
+ * | 0 | 0 | 0 | 1            |
+ * +---+---+---+--------------+
+ * | 0 | 0 | 1 | 2            |
+ * +---+---+---+--------------+
+ * | 0 | 1 | 0 | 4            |
+ * +---+---+---+--------------+
+ * | 0 | 1 | 1 | 8            |
+ * +---+---+---+--------------+
+ * | 1 | 0 | 0 | 16           |
+ * +---+---+---+--------------+
+ * | 1 | 0 | 1 | 32           |
+ * +---+---+---+--------------+
+ * | 1 | 1 | X | reserved     |
+ * +---+---+---+--------------+
+ *
+ * All other bits are reserved in these registers.
+ *
+ * Clock VCO M Registers:
+ * ----------------------
+ * These Registers contain the M Value -2.
+ *
+ * Clock VCO N Registers:
+ * ----------------------
+ * These Registers contain the N Value -2.
+ *
+ * Formulas:
+ * ---------
+ * Fvco = (Fref * Loop Divisor * M/N), whereas 100MHz < Fvco < 220MHz
+ * Fout = Fvco / Post Divisor
+ *
+ * Dot Clk0 (default 25MHz):
+ * -------------------------
+ * Fvco = 14.318 * 127 / 9 = 202.045MHz
+ * Fout = 202.045MHz / 8 = 25.25MHz
+ * Post Divisor = 8
+ * Loop Divisor = 1
+ * XRC0 = (M - 2) = 125 = 0x7D
+ * XRC1 = (N - 2) = 7   = 0x07
+ * XRC3 =                 0x34
+ *
+ * Dot Clk1 (default 28MHz):
+ * -------------------------
+ * Fvco = 14.318 * 87 / 11 = 113.24MHz
+ * Fout = 113.24MHz / 4 = 28.31MHz
+ * Post Divisor = 4
+ * Loop Divisor = 1
+ * XRC4 = (M - 2) = 85 = 0x55
+ * XRC5 = (N - 2) = 9  = 0x09
+ * XRC7 =                0x24
+ *
+ * Dot Clk2 (variable for extended modes set to 25MHz):
+ * ----------------------------------------------------
+ * Fvco = 14.318 * 127 / 9 = 202.045MHz
+ * Fout = 202.045MHz / 8 = 25.25MHz
+ * Post Divisor = 8
+ * Loop Divisor = 1
+ * XRC8 = (M - 2) = 125 = 0x7D
+ * XRC9 = (N - 2) = 7   = 0x07
+ * XRCB =                 0x34
+ *
+ * Memory Clk for most modes >50MHz:
+ * ----------------------------------
+ * Fvco = 14.318 * 58 / 5 = 166MHz
+ * Fout = 166MHz / 2      = 83MHz
+ * Post Divisor = 2
+ * XRCC = (M - 2) = 57  = 0x38
+ * XRCD = (N - 2) = 3   = 0x03
+ * XRCE =                 0x90
+ *
+ * Note Bit7 enables the clock source from the VCO
+ *
+ */
+
+/******************************************************************
+ * Resolution Struct
+ ******************************************************************/
+struct ctfb_res_modes {
+       int xres;               /* visible resolution           */
+       int yres;
+       /* Timing: All values in pixclocks, except pixclock (of course) */
+       int pixclock;           /* pixel clock in ps (pico seconds) */
+       int left_margin;        /* time from sync to picture    */
+       int right_margin;       /* time from picture to sync    */
+       int upper_margin;       /* time from sync to picture    */
+       int lower_margin;
+       int hsync_len;          /* length of horizontal sync    */
+       int vsync_len;          /* length of vertical sync      */
+       int sync;               /* see FB_SYNC_*                */
+       int vmode;              /* see FB_VMODE_*               */
+};
+
+/******************************************************************
+ * Vesa Mode Struct
+ ******************************************************************/
+struct ctfb_vesa_modes {
+       int vesanr;             /* Vesa number as in LILO (VESA Nr + 0x200} */
+       int resindex;           /* index to resolution struct */
+       int bits_per_pixel;     /* bpp */
+};
+/*******************************************************************
+ * Chips struct
+ *******************************************************************/
+struct ctfb_chips_properties {
+       int device_id;          /* PCI Device ID */
+       unsigned long max_mem;  /* memory for frame buffer */
+       int vld_set;            /* value of VLD if bit2 in clock control is set */
+       int vld_not_set;        /* value of VLD if bit2 in clock control is set */
+       int mn_diff;            /* difference between M/N Value + mn_diff = M/N Register */
+       int mn_min;             /* min value of M/N Value */
+       int mn_max;             /* max value of M/N Value */
+       int vco_min;            /* VCO Min in MHz */
+       int vco_max;            /* VCO Max in MHz */
+};
+
+static const struct ctfb_chips_properties chips[] = {
+       {PCI_DEVICE_ID_CT_69000, 0x200000, 1, 4, -2, 3, 257, 100, 220},
+       {PCI_DEVICE_ID_CT_65555, 0x100000, 16, 4, 0, 1, 255, 48, 220},  /* NOT TESTED */
+       {0, 0, 0, 0, 0, 0, 0, 0, 0}     /* Terminator */
+};
+
+/*************************************************
+ Video Modes:
+Colours   640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200
+--------+--------------------------------------------------------------
+ 4 bits |    ?       ?     0x302      ?        ?        ?         ?
+ 8 bits |  0x300   0x301   0x303    0x305    0x161    0x307     0x31C
+15 bits |    ?     0x310   0x313    0x316    0x162    0x319     0x31D
+16 bits |    ?     0x311   0x314    0x317    0x163    0x31A     0x31E
+24 bits |    ?     0x312   0x315    0x318      ?      0x31B     0x31F
+32 bits |    ?       ?       ?        ?      0x164      ?
+*/
+
+#define RES_MODE_640x480       0
+#define RES_MODE_800x600       1
+#define RES_MODE_1024x768      2
+#define RES_MODE_960_720       3
+#define RES_MODE_1152x864      4
+#define RES_MODES_COUNT                5
+
+#define VESA_MODES_COUNT 15
+
+static const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
+       {0x301, RES_MODE_640x480, 8},
+       {0x310, RES_MODE_640x480, 15},
+       {0x311, RES_MODE_640x480, 16},
+       {0x312, RES_MODE_640x480, 24},
+       {0x303, RES_MODE_800x600, 8},
+       {0x313, RES_MODE_800x600, 15},
+       {0x314, RES_MODE_800x600, 16},
+       {0x315, RES_MODE_800x600, 24},
+       {0x305, RES_MODE_1024x768, 8},
+       {0x316, RES_MODE_1024x768, 15},
+       {0x317, RES_MODE_1024x768, 16},
+       {0x318, RES_MODE_1024x768, 24},
+       {0x161, RES_MODE_1152x864, 8},
+       {0x162, RES_MODE_1152x864, 15},
+       {0x163, RES_MODE_1152x864, 16}
+};
+
+static const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
+       /* x     y pixclk   le  ri  up  lo   hs vs  s  vmode */
+       {640, 480, 39721, 40, 24, 32, 11, 96, 2, 0,
+        FB_VMODE_NONINTERLACED},
+       {800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},
+       {1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0,
+        FB_VMODE_NONINTERLACED},
+       {960, 720, 13100, 160, 40, 32, 8, 80, 4, 0,
+        FB_VMODE_NONINTERLACED},
+       {1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0,
+        FB_VMODE_NONINTERLACED}
+};
+
+/*
+ * The Graphic Device
+ */
+GraphicDevice ctfb;
+
+/*******************************************************************************
+*
+* Low Level Routines
+*/
+
+/*******************************************************************************
+*
+* Read CT ISA register
+*/
+#ifdef VGA_DEBUG
+static unsigned char
+ctRead (unsigned short index)
+{
+       GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+       if (index == CT_AR_O)
+               /* synch the Flip Flop */
+               in8 (pGD->isaBase + CT_STATUS_REG1_O);
+
+       return (in8 (pGD->isaBase + index));
+}
+#endif
+/*******************************************************************************
+*
+* Write CT ISA register
+*/
+static void
+ctWrite (unsigned short index, unsigned char val)
+{
+       GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+
+       out8 ((pGD->isaBase + index), val);
+}
+
+/*******************************************************************************
+*
+* Read CT ISA register indexed
+*/
+static unsigned char
+ctRead_i (unsigned short index, char reg)
+{
+       GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+       if (index == CT_AR_O)
+               /* synch the Flip Flop */
+               in8 (pGD->isaBase + CT_STATUS_REG1_O);
+       out8 ((pGD->isaBase + index), reg);
+       return (in8 (pGD->isaBase + index + 1));
+}
+
+/*******************************************************************************
+*
+* Write CT ISA register indexed
+*/
+static void
+ctWrite_i (unsigned short index, char reg, char val)
+{
+       GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+       if (index == CT_AR_O) {
+               /* synch the Flip Flop */
+               in8 (pGD->isaBase + CT_STATUS_REG1_O);
+               out8 ((pGD->isaBase + index), reg);
+               out8 ((pGD->isaBase + index), val);
+       } else {
+               out8 ((pGD->isaBase + index), reg);
+               out8 ((pGD->isaBase + index + 1), val);
+       }
+}
+
+/*******************************************************************************
+*
+* Write a table of CT ISA register
+*/
+static void
+ctLoadRegs (unsigned short index, CT_CFG_TABLE * regTab)
+{
+       while (regTab->reg != 0xFF) {
+               ctWrite_i (index, regTab->reg, regTab->val);
+               regTab++;
+       }
+}
+
+/*****************************************************************************/
+static void
+SetArRegs (void)
+{
+       int i, tmp;
+
+       for (i = 0; i < 0x10; i++)
+               ctWrite_i (CT_AR_O, i, i);
+       if (text)
+               tmp = 0x04;
+       else
+               tmp = 0x41;
+
+       ctWrite_i (CT_AR_O, 0x10, tmp); /* Mode Control Register */
+       ctWrite_i (CT_AR_O, 0x11, 0x00);        /* Overscan Color Register */
+       ctWrite_i (CT_AR_O, 0x12, 0x0f);        /* Memory Plane Enable Register */
+       if (fntwidth == 9)
+               tmp = 0x08;
+       else
+               tmp = 0x00;
+       ctWrite_i (CT_AR_O, 0x13, tmp); /* Horizontal Pixel Panning */
+       ctWrite_i (CT_AR_O, 0x14, 0x00);        /* Color Select Register    */
+       ctWrite (CT_AR_O, 0x20);        /* enable video             */
+}
+
+/*****************************************************************************/
+static void
+SetGrRegs (void)
+{                              /* Set Graphics Mode */
+       int i;
+
+       for (i = 0; i < 0x05; i++)
+               ctWrite_i (CT_GR_O, i, 0);
+       if (text) {
+               ctWrite_i (CT_GR_O, 0x05, 0x10);
+               ctWrite_i (CT_GR_O, 0x06, 0x02);
+       } else {
+               ctWrite_i (CT_GR_O, 0x05, 0x40);
+               ctWrite_i (CT_GR_O, 0x06, 0x05);
+       }
+       ctWrite_i (CT_GR_O, 0x07, 0x0f);
+       ctWrite_i (CT_GR_O, 0x08, 0xff);
+}
+
+/*****************************************************************************/
+static void
+SetSrRegs (void)
+{
+       int tmp = 0;
+
+       ctWrite_i (CT_SR_O, 0x00, 0x00);        /* reset */
+       /*rr( sr, 0x01, tmp );
+          if( fntwidth == 8 ) tmp |= 0x01; else tmp &= ~0x01;
+          wr( sr, 0x01, tmp );  */
+       if (fntwidth == 8)
+               ctWrite_i (CT_SR_O, 0x01, 0x01);        /* Clocking Mode Register */
+       else
+               ctWrite_i (CT_SR_O, 0x01, 0x00);        /* Clocking Mode Register */
+       ctWrite_i (CT_SR_O, 0x02, 0x0f);        /* Enable CPU wr access to given memory plane */
+       ctWrite_i (CT_SR_O, 0x03, 0x00);        /* Character Map Select Register */
+       if (text)
+               tmp = 0x02;
+       else
+               tmp = 0x0e;
+       ctWrite_i (CT_SR_O, 0x04, tmp); /* Enable CPU accesses to the rest of the 256KB
+                                          total VGA memory beyond the first 64KB and set
+                                          fb mapping mode. */
+       ctWrite_i (CT_SR_O, 0x00, 0x03);        /* enable */
+}
+
+/*****************************************************************************/
+static void
+SetBitsPerPixelIntoXrRegs (int bpp)
+{
+       unsigned int n = (bpp >> 3), tmp;       /* only for 15, 8, 16, 24 bpp */
+       static char md[4] = { 0x04, 0x02, 0x05, 0x06 }; /* DisplayColorMode */
+       static char off[4] = { ~0x20, ~0x30, ~0x20, ~0x10 };    /* mask */
+       static char on[4] = { 0x10, 0x00, 0x10, 0x20 }; /* mask */
+       if (bpp == 15)
+               n = 0;
+       tmp = ctRead_i (CT_XR_O, 0x20);
+       tmp &= off[n];
+       tmp |= on[n];
+       ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
+       ctWrite_i (CT_XR_O, 0x81, md[n]);
+}
+
+/*****************************************************************************/
+static void
+SetCrRegs (struct ctfb_res_modes *var, int bits_per_pixel)
+{                              /* he -le-   ht|0    hd -ri- hs     -h-      he */
+       unsigned char cr[0x7a];
+       int i, tmp;
+       unsigned int hd, hs, he, ht, hbe;       /* Horizontal.  */
+       unsigned int vd, vs, ve, vt;    /* vertical */
+       unsigned int bpp, wd, dblscan, interlaced, bcast, CrtHalfLine;
+       unsigned int CompSyncCharClkDelay, CompSyncPixelClkDelay;
+       unsigned int NTSC_PAL_HorizontalPulseWidth, BlDelayCtrl;
+       unsigned int HorizontalEqualizationPulses;
+       unsigned int HorizontalSerration1Start, HorizontalSerration2Start;
+
+       const int LineCompare = 0x3ff;
+       unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor   */
+       unsigned int RAMDAC_BlankPedestalEnable = 0;    /* 1=en-, 0=disable, see XR82 */
+
+       hd = (var->xres) / 8;   /* HDisp.  */
+       hs = (var->xres + var->right_margin) / 8;       /* HsStrt  */
+       he = (var->xres + var->right_margin + var->hsync_len) / 8;      /* HsEnd   */
+       ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8;   /* HTotal  */
+       hbe = ht - 1;           /* HBlankEnable todo docu wants ht here, but it does not work */
+       /* ve -up-  vt|0    vd -lo- vs     -v-      ve */
+       vd = var->yres;         /* VDisplay   */
+       vs = var->yres + var->lower_margin;     /* VSyncStart */
+       ve = var->yres + var->lower_margin + var->vsync_len;    /* VSyncEnd */
+       vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len;        /* VTotal  */
+       bpp = bits_per_pixel;
+       dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
+       interlaced = var->vmode & FB_VMODE_INTERLACED;
+       bcast = var->sync & FB_SYNC_BROADCAST;
+       CrtHalfLine = bcast ? (hd >> 1) : 0;
+       BlDelayCtrl = bcast ? 1 : 0;
+       CompSyncCharClkDelay = 0;       /* 2 bit */
+       CompSyncPixelClkDelay = 0;      /* 3 bit */
+       if (bcast) {
+               NTSC_PAL_HorizontalPulseWidth = 7;      /*( var->hsync_len >> 1 ) + 1 */
+               HorizontalEqualizationPulses = 0;       /* inverse value */
+               HorizontalSerration1Start = 31; /* ( ht >> 1 ) */
+               HorizontalSerration2Start = 89; /* ( ht >> 1 ) */
+       } else {
+               NTSC_PAL_HorizontalPulseWidth = 0;
+               /* 4 bit: hsync pulse width = ( ( CR74[4:0] - CR74[5] )
+                * / 2 ) + 1 --> CR74[4:0] = 2*(hs-1) + CR74[5] */
+               HorizontalEqualizationPulses = 1;       /* inverse value */
+               HorizontalSerration1Start = 0;  /* ( ht >> 1 ) */
+               HorizontalSerration2Start = 0;  /* ( ht >> 1 ) */
+       }
+
+       if (bpp == 15)
+               bpp = 16;
+       wd = var->xres * bpp / 64;      /* double words per line */
+       if (interlaced) {       /* we divide all vertical timings, exept vd */
+               vs >>= 1;
+               ve >>= 1;
+               vt >>= 1;
+       }
+       memset (cr, 0, sizeof (cr));
+       cr[0x00] = 0xff & (ht - 5);
+       cr[0x01] = hd - 1;      /* soll:4f ist 59 */
+       cr[0x02] = hd;
+       cr[0x03] = (hbe & 0x1F) | 0x80; /* hd + ht - hd  */
+       cr[0x04] = hs;
+       cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
+       cr[0x06] = (vt - 2) & 0xFF;
+       cr[0x30] = (vt - 2) >> 8;
+       cr[0x07] = ((vt & 0x100) >> 8)
+           | ((vd & 0x100) >> 7)
+           | ((vs & 0x100) >> 6)
+           | ((vs & 0x100) >> 5)
+           | ((LineCompare & 0x100) >> 4)
+           | ((vt & 0x200) >> 4)
+           | ((vd & 0x200) >> 3)
+           | ((vs & 0x200) >> 2);
+       cr[0x08] = 0x00;
+       cr[0x09] = (dblscan << 7)
+           | ((LineCompare & 0x200) >> 3)
+           | ((vs & 0x200) >> 4)
+           | (TextScanLines - 1);
+       cr[0x10] = vs & 0xff;   /* VSyncPulseStart */
+       cr[0x32] = (vs & 0xf00) >> 8;   /* VSyncPulseStart */
+       cr[0x11] = (ve & 0x0f); /* | 0x20;      */
+       cr[0x12] = (vd - 1) & 0xff;     /* LineCount  */
+       cr[0x31] = ((vd - 1) & 0xf00) >> 8;     /* LineCount */
+       cr[0x13] = wd & 0xff;
+       cr[0x41] = (wd & 0xf00) >> 8;
+       cr[0x15] = vs & 0xff;
+       cr[0x33] = (vs & 0xf00) >> 8;
+       cr[0x38] = (0x100 & (ht - 5)) >> 8;
+       cr[0x3C] = 0xc0 & hbe;
+       cr[0x16] = (vt - 1) & 0xff;     /* vbe - docu wants vt here, */
+       cr[0x17] = 0xe3;        /* but it does not work */
+       cr[0x18] = 0xff & LineCompare;
+       cr[0x22] = 0xff;        /* todo? */
+       cr[0x70] = interlaced ? (0x80 | CrtHalfLine) : 0x00;    /* check:0xa6  */
+       cr[0x71] = 0x80 | (RAMDAC_BlankPedestalEnable << 6)
+           | (BlDelayCtrl << 5)
+           | ((0x03 & CompSyncCharClkDelay) << 3)
+           | (0x07 & CompSyncPixelClkDelay);   /* todo: see XR82 */
+       cr[0x72] = HorizontalSerration1Start;
+       cr[0x73] = HorizontalSerration2Start;
+       cr[0x74] = (HorizontalEqualizationPulses << 5)
+           | NTSC_PAL_HorizontalPulseWidth;
+       /* todo: ct69000 has also 0x75-79 */
+       /* now set the registers */
+       for (i = 0; i <= 0x0d; i++) {   /*CR00 .. CR0D */
+               ctWrite_i (CT_CR_O, i, cr[i]);
+       }
+       for (i = 0x10; i <= 0x18; i++) {        /*CR10 .. CR18 */
+               ctWrite_i (CT_CR_O, i, cr[i]);
+       }
+       i = 0x22;               /*CR22 */
+       ctWrite_i (CT_CR_O, i, cr[i]);
+       for (i = 0x30; i <= 0x33; i++) {        /*CR30 .. CR33 */
+               ctWrite_i (CT_CR_O, i, cr[i]);
+       }
+       i = 0x38;               /*CR38 */
+       ctWrite_i (CT_CR_O, i, cr[i]);
+       i = 0x3C;               /*CR3C */
+       ctWrite_i (CT_CR_O, i, cr[i]);
+       for (i = 0x40; i <= 0x41; i++) {        /*CR40 .. CR41 */
+               ctWrite_i (CT_CR_O, i, cr[i]);
+       }
+       for (i = 0x70; i <= 0x74; i++) {        /*CR70 .. CR74 */
+               ctWrite_i (CT_CR_O, i, cr[i]);
+       }
+       tmp = ctRead_i (CT_CR_O, 0x40);
+       tmp &= 0x0f;
+       tmp |= 0x80;
+       ctWrite_i (CT_CR_O, 0x40, tmp); /* StartAddressEnable */
+}
+
+/* pixelclock control */
+
+/*****************************************************************************
+ We have a rational number p/q and need an m/n which is very close to p/q
+ but has m and n within mnmin and mnmax. We have no floating point in the
+ kernel. We can use long long without divide. And we have time to compute...
+******************************************************************************/
+static unsigned int
+FindBestPQFittingMN (unsigned int p, unsigned int q, unsigned int mnmin,
+                    unsigned int mnmax, unsigned int *pm, unsigned int *pn)
+{
+       /* this code is not for general purpose usable but good for our number ranges */
+       unsigned int n = mnmin, m = 0;
+       long long int L = 0, P = p, Q = q, H = P >> 1;
+       long long int D = 0x7ffffffffffffffLL;
+       for (n = mnmin; n <= mnmax; n++) {
+               m = mnmin;      /* p/q ~ m/n -> p*n ~ m*q -> p*n-x*q ~ 0 */
+               L = P * n - m * Q;      /* n * vco - m * fref should be near 0 */
+               while (L > 0 && m < mnmax) {
+                       L -= q; /* difference is greater as 0 subtract fref */
+                       m++;    /* and increment m */
+               }
+               /* difference is less or equal than 0 or m > maximum */
+               if (m > mnmax)
+                       break;  /* no solution: if we increase n we get the same situation */
+               /* L is <= 0 now */
+               if (-L > H && m > mnmin) {      /* if difference > the half fref */
+                       L += q; /* we take the situation before */
+                       m--;    /* because its closer to 0 */
+               }
+               L = (L < 0) ? -L : +L;  /* absolute value */
+               if (D < L)      /* if last difference was better take next n */
+                       continue;
+               D = L;
+               *pm = m;
+               *pn = n;        /*  keep improved data */
+               if (D == 0)
+                       break;  /* best result we can get */
+       }
+       return (unsigned int) (0xffffffff & D);
+}
+
+/* that is the hardware < 69000 we have to manage
+ +---------+  +-------------------+  +----------------------+  +--+
+ | REFCLK  |__|NTSC Divisor Select|__|FVCO Reference Divisor|__|÷N|__
+ | 14.3MHz |  |(NTSCDS) (÷1, Ã·5)  |  |Select (RDS) (÷1, Ã·4) |  |  |  |
+ +---------+  +-------------------+  +----------------------+  +--+  |
+  ___________________________________________________________________|
+ |
+ |                                    fvco                      fout
+ | +--------+  +------------+  +-----+     +-------------------+   +----+
+ +-| Phase  |__|Charge Pump |__| VCO |_____|Post Divisor (PD)  |___|CLK |--->
+ +-| Detect |  |& Filter VCO|  |     |  |  |÷1, 2, 4, 8, 16, 32|   |    |
+ | +--------+  +------------+  +-----+  |  +-------------------+   +----+
+ |                                      |
+ |    +--+   +---------------+          |
+ |____|÷M|___|VCO Loop Divide|__________|
+      |  |   |(VLD)(÷4, Ã·16) |
+      +--+   +---------------+
+****************************************************************************
+  that is the hardware >= 69000 we have to manage
+ +---------+  +--+
+ | REFCLK  |__|÷N|__
+ | 14.3MHz |  |  |  |
+ +---------+  +--+  |
+  __________________|
+ |
+ |                                    fvco                      fout
+ | +--------+  +------------+  +-----+     +-------------------+   +----+
+ +-| Phase  |__|Charge Pump |__| VCO |_____|Post Divisor (PD)  |___|CLK |--->
+ +-| Detect |  |& Filter VCO|  |     |  |  |÷1, 2, 4, 8, 16, 32|   |    |
+ | +--------+  +------------+  +-----+  |  +-------------------+   +----+
+ |                                      |
+ |    +--+   +---------------+          |
+ |____|÷M|___|VCO Loop Divide|__________|
+      |  |   |(VLD)(÷1, Ã·4)  |
+      +--+   +---------------+
+
+
+*/
+
+#define VIDEO_FREF 14318180;   /* Hz  */
+/*****************************************************************************/
+static int
+ReadPixClckFromXrRegsBack (struct ctfb_chips_properties *param)
+{
+       unsigned int m, n, vld, pd, PD, fref, xr_cb, i, pixclock;
+       i = 0;
+       pixclock = -1;
+       fref = VIDEO_FREF;
+       m = ctRead_i (CT_XR_O, 0xc8);
+       n = ctRead_i (CT_XR_O, 0xc9);
+       m -= param->mn_diff;
+       n -= param->mn_diff;
+       xr_cb = ctRead_i (CT_XR_O, 0xcb);
+       PD = (0x70 & xr_cb) >> 4;
+       pd = 1;
+       for (i = 0; i < PD; i++) {
+               pd *= 2;
+       }
+       vld = (0x04 & xr_cb) ? param->vld_set : param->vld_not_set;
+       if (n * vld * m) {
+               unsigned long long p = 1000000000000LL * pd * n;
+               unsigned long long q = (long long) fref * vld * m;
+               while ((p > 0xffffffffLL) || (q > 0xffffffffLL)) {
+                       p >>= 1;        /* can't divide with long long so we scale down */
+                       q >>= 1;
+               }
+               pixclock = (unsigned) p / (unsigned) q;
+       } else
+               printf ("Invalid data in xr regs.\n");
+       return pixclock;
+}
+
+/*****************************************************************************/
+static void
+FindAndSetPllParamIntoXrRegs (unsigned int pixelclock,
+                             struct ctfb_chips_properties *param)
+{
+       unsigned int m, n, vld, pd, PD, fref, xr_cb;
+       unsigned int fvcomin, fvcomax, pclckmin, pclckmax, pclk;
+       unsigned int pfreq, fvco, new_pixclock;
+
+       fref = VIDEO_FREF;
+       pd = 1;
+       PD = 0;
+       fvcomin = param->vco_min;
+       fvcomax = param->vco_max;       /* MHz */
+       pclckmin = 1000000 / fvcomax + 1;       /*   4546 */
+       pclckmax = 32000000 / fvcomin - 1;      /* 666665 */
+       pclk = minmax (pclckmin, pixelclock, pclckmax); /* ps pp */
+       pfreq = 250 * (4000000000U / pclk);
+       fvco = pfreq;           /* Hz */
+       new_pixclock = 0;
+       while (fvco < fvcomin * 1000000) {
+               /* double VCO starting with the pixelclock frequency
+                * as long as it is lower than the minimal VCO frequency */
+               fvco *= 2;
+               pd *= 2;
+               PD++;
+       }
+       /* fvco is exactly pd * pixelclock and higher than the ninmal VCO frequency */
+       vld = (param->vld_set > param->vld_not_set) ?
+           param->vld_not_set : param->vld_set;
+       /* start with lower VLD (higher VLD is NOT yet implemented */
+       FindBestPQFittingMN (fvco / vld, fref, param->mn_min, param->mn_max, &m, &n);   /* rds = 1 */
+       m += param->mn_diff;
+       n += param->mn_diff;
+       PRINTF ("VCO %d, pd %d, m %d n %d vld %d \n", fvco, pd, m, n, vld);
+       xr_cb = ((0x7 & PD) << 4) | (vld == param->vld_set ? 0x04 : 0);
+       /* All four of the registers used for dot clock 2 (XRC8 - XRCB) must be
+        * written, and in order from XRC8 to XRCB, before the hardware will
+        * update the synthesizer s settings.
+        */
+       ctWrite_i (CT_XR_O, 0xc8, m);
+       ctWrite_i (CT_XR_O, 0xc9, n);   /* xrca does not exist in CT69000 and CT69030 */
+       ctWrite_i (CT_XR_O, 0xca, 0);   /* because of a hw bug I guess, but we write */
+       ctWrite_i (CT_XR_O, 0xcb, xr_cb);       /* 0 to it for savety */
+       new_pixclock = ReadPixClckFromXrRegsBack (param);
+       PRINTF ("pixelclock.set = %d, pixelclock.real = %d \n",
+               pixelclock, new_pixclock);
+}
+
+/*****************************************************************************/
+static void
+SetMsrRegs (struct ctfb_res_modes *mode)
+{
+       unsigned char h_synch_high, v_synch_high;
+
+       h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40;  /* horizontal Synch High active */
+       v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
+       ctWrite (CT_MSR_W_O, (h_synch_high | v_synch_high | 0x29));
+       /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
+        * Selects the upper 64KB page.Bit5=1
+        * CLK2 (left reserved in standard VGA) Bit3|2=1|0
+        * Disables CPU access to frame buffer. Bit1=0
+        * Sets the I/O address decode for ST01, FCR, and all CR registers
+        * to the 3Dx I/O address range (CGA emulation). Bit0=1
+        */
+}
+
+/************************************************************************************/
+#ifdef VGA_DUMP_REG
+
+static void
+ctDispRegs (unsigned short index, int from, int to)
+{
+       unsigned char status;
+       int i;
+
+       for (i = from; i < to; i++) {
+               status = ctRead_i (index, i);
+               printf ("%02X: is %02X\n", i, status);
+       }
+}
+
+void
+video_dump_reg (void)
+{
+       int i;
+
+       printf ("Extended Regs:\n");
+       ctDispRegs (CT_XR_O, 0, 0xC);
+       ctDispRegs (CT_XR_O, 0xe, 0xf);
+       ctDispRegs (CT_XR_O, 0x20, 0x21);
+       ctDispRegs (CT_XR_O, 0x40, 0x50);
+       ctDispRegs (CT_XR_O, 0x60, 0x64);
+       ctDispRegs (CT_XR_O, 0x67, 0x68);
+       ctDispRegs (CT_XR_O, 0x70, 0x72);
+       ctDispRegs (CT_XR_O, 0x80, 0x83);
+       ctDispRegs (CT_XR_O, 0xA0, 0xB0);
+       ctDispRegs (CT_XR_O, 0xC0, 0xD3);
+       printf ("Sequencer Regs:\n");
+       ctDispRegs (CT_SR_O, 0, 0x8);
+       printf ("Graphic Regs:\n");
+       ctDispRegs (CT_GR_O, 0, 0x9);
+       printf ("CRT Regs:\n");
+       ctDispRegs (CT_CR_O, 0, 0x19);
+       ctDispRegs (CT_CR_O, 0x22, 0x23);
+       ctDispRegs (CT_CR_O, 0x30, 0x34);
+       ctDispRegs (CT_CR_O, 0x38, 0x39);
+       ctDispRegs (CT_CR_O, 0x3C, 0x3D);
+       ctDispRegs (CT_CR_O, 0x40, 0x42);
+       ctDispRegs (CT_CR_O, 0x70, 0x80);
+       /* don't display the attributes */
+}
+
+#endif
+
+#ifdef CONFIG_VIDEO_HW_CURSOR
+/***************************************************************
+ * Set Hardware Cursor in Pixel
+ */
+void
+video_set_hw_cursor (int x, int y)
+{
+       int sig_x = 0, sig_y = 0;
+       if (x < 0) {
+               x *= -1;
+               sig_x = 1;
+       }
+       if (y < 0) {
+               y *= -1;
+               sig_y = 1;
+       }
+       ctWrite_i (CT_XR_O, 0xa4, x & 0xff);
+       ctWrite_i (CT_XR_O, 0xa5, (x >> 8) & 0x7);
+       ctWrite_i (CT_XR_O, 0xa6, y & 0xff);
+       ctWrite_i (CT_XR_O, 0xa7, (y >> 8) & 0x7);
+}
+
+/***************************************************************
+ * Init Hardware Cursor. To know the size of the Cursor,
+ * we have to know the Font size.
+ */
+void
+video_init_hw_cursor (int font_width, int font_height)
+{
+       unsigned char xr_80;
+       unsigned long *curs, pattern;
+       int i;
+       int cursor_start;
+       GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+
+       cursor_start = pGD->dprBase;
+       xr_80 = ctRead_i (CT_XR_O, 0x80);
+       /* set start address */
+       ctWrite_i (CT_XR_O, 0xa2, (cursor_start >> 8) & 0xf0);
+       ctWrite_i (CT_XR_O, 0xa3, (cursor_start >> 16) & 0x3f);
+       /* set cursor shape */
+       curs = (unsigned long *) cursor_start;
+       i = 0;
+       while (i < 0x400) {
+               curs[i++] = 0xffffffff; /* AND mask */
+               curs[i++] = 0xffffffff; /* AND mask */
+               curs[i++] = 0;  /* XOR mask */
+               curs[i++] = 0;  /* XOR mask */
+               /* Transparent */
+       }
+       pattern = 0xffffffff >> font_width;
+       i = 0;
+       while (i < (font_height * 2)) {
+               curs[i++] = pattern;    /* AND mask */
+               curs[i++] = pattern;    /* AND mask */
+               curs[i++] = 0;  /* XOR mask */
+               curs[i++] = 0;  /* XOR mask */
+               /* Cursor Color 0 */
+       }
+       /* set blink rate */
+       ctWrite_i (CT_FP_O, 0x19, 0xf);
+
+       /* set cursors colors */
+       xr_80 = ctRead_i (CT_XR_O, 0x80);
+       xr_80 |= 0x1;           /* alternate palette select */
+       ctWrite_i (CT_XR_O, 0x80, xr_80);
+       video_set_lut (4, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
+       /* position 4 is color 0 cursor 0 */
+       xr_80 &= 0xfe;          /* normal palette select */
+       ctWrite_i (CT_XR_O, 0x80, xr_80);
+       /* cursor enable */
+       ctWrite_i (CT_XR_O, 0xa0, 0x91);
+       xr_80 |= 0x10;          /* enable hwcursor */
+       ctWrite_i (CT_XR_O, 0x80, xr_80);
+       video_set_hw_cursor (0, 0);
+}
+#endif                         /* CONFIG_VIDEO_HW_CURSOR */
+
+/***************************************************************
+ * Wait for BitBlt ready
+ */
+static int
+video_wait_bitblt (unsigned long addr)
+{
+       unsigned long br04;
+       int i = 0;
+       br04 = in32r (addr);
+       while (br04 & 0x80000000) {
+               udelay (1);
+               br04 = in32r (addr);
+               if (i++ > 1000000) {
+                       printf ("ERROR Timeout %lx\n", br04);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/***************************************************************
+ * Set up BitBlt Registrs
+ */
+static void
+SetDrawingEngine (int bits_per_pixel)
+{
+       unsigned long br04, br00;
+       unsigned char tmp;
+
+       GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+
+       tmp = ctRead_i (CT_XR_O, 0x20); /* BitBLT Configuration */
+       tmp |= 0x02;            /* reset BitBLT */
+       ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
+       udelay (10);
+       tmp &= 0xfd;            /* release reset BitBLT */
+       ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
+       video_wait_bitblt (pGD->pciBase + BR04_o);
+
+       /* set pattern Address */
+       out32r (pGD->pciBase + BR05_o, PATTERN_ADR & 0x003ffff8);
+       br04 = 0;
+       if (bits_per_pixel == 1) {
+               br04 |= 0x00040000;     /* monochome Pattern */
+               br04 |= 0x00001000;     /* monochome source */
+       }
+       br00 = ((pGD->winSizeX * pGD->gdfBytesPP) << 16) + (pGD->winSizeX * pGD->gdfBytesPP);   /* bytes per scanline */
+       out32r (pGD->pciBase + BR00_o, br00);   /* */
+       out32r (pGD->pciBase + BR08_o, (10 << 16) + 10);        /* dummy */
+       out32r (pGD->pciBase + BR04_o, br04);   /* write all 0 */
+       out32r (pGD->pciBase + BR07_o, 0);      /* destination */
+       video_wait_bitblt (pGD->pciBase + BR04_o);
+}
+
+/************************************************************************
+ * Get Parameters for the video mode:
+ */
+/*********************************************************************
+ * returns the length to the next seperator
+ */
+static int
+video_get_param_len (char *start, char sep)
+{
+       int i = 0;
+       while ((*start != 0) && (*start != sep)) {
+               start++;
+               i++;
+       }
+       return i;
+}
+
+static int
+video_search_param (char *start, char *param)
+{
+       int len, totallen, i;
+       char *p = start;
+       len = strlen (param);
+       totallen = len + strlen (start);
+       for (i = 0; i < totallen; i++) {
+               if (strncmp (p++, param, len) == 0)
+                       return (i);
+       }
+       return -1;
+}
+
+/***************************************************************
+* Get parameter via the environment as it is done for the
+* linux kernel i.e:
+* video=ctfb:x:800,xv:1280,y:600,yv:1024,depth:16,mode:0,pclk:25000,
+*       le:56,ri:48,up:26,lo:5,hs:152,vs:2,sync:0,vmode:0,accel:0
+*
+* penv is a pointer to the environment, containing the string, or the name of
+* another environment variable. It could even be the term "bootargs"
+*/
+
+#define GET_OPTION(name,var)                           \
+               if(strncmp(p,name,strlen(name))==0) {   \
+                       val_s=p+strlen(name);           \
+                       var=simple_strtoul(val_s, NULL, 10); \
+               }
+
+static int
+video_get_params (struct ctfb_res_modes *pPar, char *penv)
+{
+       char *p, *s, *val_s;
+       int i = 0, t;
+       int bpp;
+       int mode;
+       /* first search for the environment containing the real param string */
+       s = penv;
+       if ((p = getenv (s)) != NULL) {
+               s = p;
+       }
+       /* in case of the bootargs line, we have to start
+        * after "video=ctfb:"
+        */
+       i = video_search_param (s, "video=ctfb:");
+       if (i >= 0) {
+               s += i;
+               s += strlen ("video=ctfb:");
+       }
+       /* search for mode as a default value */
+       p = s;
+       t = 0;
+       mode = 0;               /* default */
+       while ((i = video_get_param_len (p, ',')) != 0) {
+               GET_OPTION ("mode:", mode)
+                   p += i;
+               if (*p != 0)
+                       p++;    /* skip ',' */
+       }
+       if (mode >= RES_MODES_COUNT)
+               mode = 0;
+       *pPar = res_mode_init[mode];    /* copy default values */
+       bpp = 24 - ((mode % 3) * 8);
+       p = s;                  /* restart */
+       while ((i = video_get_param_len (p, ',')) != 0) {
+               GET_OPTION ("x:", pPar->xres)
+                   GET_OPTION ("y:", pPar->yres)
+                   GET_OPTION ("le:", pPar->left_margin)
+                   GET_OPTION ("ri:", pPar->right_margin)
+                   GET_OPTION ("up:", pPar->upper_margin)
+                   GET_OPTION ("lo:", pPar->lower_margin)
+                   GET_OPTION ("hs:", pPar->hsync_len)
+                   GET_OPTION ("vs:", pPar->vsync_len)
+                   GET_OPTION ("sync:", pPar->sync)
+                   GET_OPTION ("vmode:", pPar->vmode)
+                   GET_OPTION ("pclk:", pPar->pixclock)
+                   GET_OPTION ("depth:", bpp)
+                   p += i;
+               if (*p != 0)
+                       p++;    /* skip ',' */
+       }
+       return bpp;
+}
+
+/****************************************************************************
+* supported Video Chips
+*/
+static struct pci_device_id supported[] = {
+       {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000},
+       {}
+};
+
+/*******************************************************************************
+*
+* Init video chip
+*/
+void *
+video_hw_init (void)
+{
+       GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+       unsigned short device_id;
+       pci_dev_t devbusfn;
+       int videomode;
+       unsigned long t1, hsynch, vsynch;
+       unsigned int pci_mem_base, *vm;
+       int tmp, i, bits_per_pixel;
+       char *penv;
+       struct ctfb_res_modes *res_mode;
+       struct ctfb_res_modes var_mode;
+       struct ctfb_chips_properties *chips_param;
+       /* Search for video chip */
+
+       if ((devbusfn = pci_find_devices (supported, 0)) < 0) {
+#ifdef CONFIG_VIDEO_ONBOARD
+               printf ("Video: Controller not found !\n");
+#endif
+               return (NULL);
+       }
+
+       /* PCI setup */
+       pci_write_config_dword (devbusfn, PCI_COMMAND,
+                               (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
+       pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
+       pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
+       pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
+
+       /* get chips params */
+       for (chips_param = (struct ctfb_chips_properties *) &chips[0];
+            chips_param->device_id != 0; chips_param++) {
+               if (chips_param->device_id == device_id)
+                       break;
+       }
+       if (chips_param->device_id == 0) {
+#ifdef CONFIG_VIDEO_ONBOARD
+               printf ("Video: controller 0x%X not supported\n", device_id);
+#endif
+               return NULL;
+       }
+       /* supported Video controller found */
+       printf ("Video: ");
+
+       tmp = 0;
+       videomode = 0x301;
+       /* get video mode via environment */
+       if ((penv = getenv ("videomode")) != NULL) {
+               /* deceide if it is a string */
+               if (penv[0] <= '9') {
+                       videomode = (int) simple_strtoul (penv, NULL, 16);
+                       tmp = 1;
+               }
+       } else {
+               tmp = 1;
+       }
+       if (tmp) {
+               /* parameter are vesa modes */
+               /* search params */
+               for (i = 0; i < VESA_MODES_COUNT; i++) {
+                       if (vesa_modes[i].vesanr == videomode)
+                               break;
+               }
+               if (i == VESA_MODES_COUNT) {
+                       printf ("no VESA Mode found, switching to mode 0x301 ");
+                       i = 0;
+               }
+               res_mode =
+                   (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
+                                                            resindex];
+               bits_per_pixel = vesa_modes[i].bits_per_pixel;
+       } else {
+
+               res_mode = (struct ctfb_res_modes *) &var_mode;
+               bits_per_pixel = video_get_params (res_mode, penv);
+       }
+
+       /* calculate available color depth for controller memory */
+       if (bits_per_pixel == 15)
+               tmp = 2;
+       else
+               tmp = bits_per_pixel >> 3;      /* /8 */
+       if (((chips_param->max_mem -
+             ACCELMEMORY) / (res_mode->xres * res_mode->yres)) < tmp) {
+               tmp =
+                   ((chips_param->max_mem -
+                     ACCELMEMORY) / (res_mode->xres * res_mode->yres));
+               if (tmp == 0) {
+                       printf
+                           ("No matching videomode found .-> reduce resolution\n");
+                       return NULL;
+               } else {
+                       printf ("Switching back to %d Bits per Pixel ",
+                               tmp << 3);
+                       bits_per_pixel = tmp << 3;
+               }
+       }
+
+       /* calculate hsynch and vsynch freq (info only) */
+       t1 = (res_mode->left_margin + res_mode->xres +
+             res_mode->right_margin + res_mode->hsync_len) / 8;
+       t1 *= 8;
+       t1 *= res_mode->pixclock;
+       t1 /= 1000;
+       hsynch = 1000000000L / t1;
+       t1 *=
+           (res_mode->upper_margin + res_mode->yres +
+            res_mode->lower_margin + res_mode->vsync_len);
+       t1 /= 1000;
+       vsynch = 1000000000L / t1;
+
+       /* fill in Graphic device struct */
+       sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
+                res_mode->yres, bits_per_pixel, (hsynch / 1000),
+                (vsynch / 1000));
+       printf ("%s\n", pGD->modeIdent);
+       pGD->winSizeX = res_mode->xres;
+       pGD->winSizeY = res_mode->yres;
+       pGD->plnSizeX = res_mode->xres;
+       pGD->plnSizeY = res_mode->yres;
+       switch (bits_per_pixel) {
+       case 8:
+               pGD->gdfBytesPP = 1;
+               pGD->gdfIndex = GDF__8BIT_INDEX;
+               break;
+       case 15:
+               pGD->gdfBytesPP = 2;
+               pGD->gdfIndex = GDF_15BIT_555RGB;
+               break;
+       case 16:
+               pGD->gdfBytesPP = 2;
+               pGD->gdfIndex = GDF_16BIT_565RGB;
+               break;
+       case 24:
+               pGD->gdfBytesPP = 3;
+               pGD->gdfIndex = GDF_24BIT_888RGB;
+               break;
+       }
+       pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
+       pGD->pciBase = pci_mem_base;
+       pGD->frameAdrs = pci_mem_base;
+       pGD->memSize = chips_param->max_mem;
+       /* Cursor Start Address */
+       pGD->dprBase =
+           (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + pci_mem_base;
+       if ((pGD->dprBase & 0x0fff) != 0) {
+               /* allign it */
+               pGD->dprBase &= 0xfffff000;
+               pGD->dprBase += 0x00001000;
+       }
+       PRINTF ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
+               PATTERN_ADR);
+       pGD->vprBase = pci_mem_base;    /* Dummy */
+       pGD->cprBase = pci_mem_base;    /* Dummy */
+       /* set up Hardware */
+
+       ctWrite (CT_MSR_W_O, 0x01);
+
+       /* set the extended Registers */
+       ctLoadRegs (CT_XR_O, xreg);
+       /* set atribute registers */
+       SetArRegs ();
+       /* set Graphics register */
+       SetGrRegs ();
+       /* set sequencer */
+       SetSrRegs ();
+
+       /* set msr */
+       SetMsrRegs (res_mode);
+
+       /* set CRT Registers */
+       SetCrRegs (res_mode, bits_per_pixel);
+       /* set color mode */
+       SetBitsPerPixelIntoXrRegs (bits_per_pixel);
+
+       /* set PLL */
+       FindAndSetPllParamIntoXrRegs (res_mode->pixclock, chips_param);
+
+       ctWrite_i (CT_SR_O, 0, 0x03);   /* clear synchronous reset */
+       /* Clear video memory */
+       i = pGD->memSize / 4;
+       vm = (unsigned int *) pGD->pciBase;
+       while (i--)
+               *vm++ = 0;
+       SetDrawingEngine (bits_per_pixel);
+#ifdef VGA_DUMP_REG
+       video_dump_reg ();
+#endif
+
+       return ((void *) &ctfb);
+}
+
+ /*******************************************************************************
+*
+* Set a RGB color in the LUT (8 bit index)
+*/
+void
+video_set_lut (unsigned int index,     /* color number */
+              unsigned char r, /* red */
+              unsigned char g, /* green */
+              unsigned char b  /* blue */
+    )
+{
+
+       ctWrite (CT_LUT_MASK_O, 0xff);
+
+       ctWrite (CT_LUT_START_O, (char) index);
+
+       ctWrite (CT_LUT_RGB_O, r);      /* red */
+       ctWrite (CT_LUT_RGB_O, g);      /* green */
+       ctWrite (CT_LUT_RGB_O, b);      /* blue */
+       udelay (1);
+       ctWrite (CT_LUT_MASK_O, 0xff);
+}
+
+/*******************************************************************************
+*
+* Drawing engine fill on screen region
+*/
+void
+video_hw_rectfill (unsigned int bpp,   /* bytes per pixel */
+                  unsigned int dst_x,  /* dest pos x */
+                  unsigned int dst_y,  /* dest pos y */
+                  unsigned int dim_x,  /* frame width */
+                  unsigned int dim_y,  /* frame height */
+                  unsigned int color   /* fill color */
+    )
+{
+       GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+       unsigned long *p, br04;
+
+       video_wait_bitblt (pGD->pciBase + BR04_o);
+
+       p = (unsigned long *) PATTERN_ADR;
+       dim_x *= bpp;
+       if (bpp == 3)
+               bpp++;          /* 24Bit needs a 32bit pattern */
+       memset (p, color, (bpp * sizeof (unsigned char) * 8 * 8));      /* 8 x 8 pattern data */
+       out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP);    /* destination */
+       br04 = in32r (pGD->pciBase + BR04_o) & 0xffffff00;
+       br04 |= 0xF0;           /* write Pattern P -> D */
+       out32r (pGD->pciBase + BR04_o, br04);   /* */
+       out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x);  /* starts the BITBlt */
+       video_wait_bitblt (pGD->pciBase + BR04_o);
+}
+
+/*******************************************************************************
+*
+* Drawing engine bitblt with screen region
+*/
+void
+video_hw_bitblt (unsigned int bpp,     /* bytes per pixel */
+                unsigned int src_x,    /* source pos x */
+                unsigned int src_y,    /* source pos y */
+                unsigned int dst_x,    /* dest pos x */
+                unsigned int dst_y,    /* dest pos y */
+                unsigned int dim_x,    /* frame width */
+                unsigned int dim_y     /* frame height */
+    )
+{
+       GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+       unsigned long br04;
+
+       br04 = in32r (pGD->pciBase + BR04_o);
+
+       /* to prevent data corruption due to overlap, we have to
+        * find out if, and how the frames overlaps */
+       if (src_x < dst_x) {
+               /* src is more left than dest
+                * the frame may overlap -> start from right to left */
+               br04 |= 0x00000100;     /* set bit 8 */
+               src_x += dim_x;
+               dst_x += dim_x;
+       } else {
+               br04 &= 0xfffffeff;     /* clear bit 8 left to right */
+       }
+       if (src_y < dst_y) {
+               /* src is higher than dst
+                * the frame may overlap => start from bottom */
+               br04 |= 0x00000200;     /* set bit 9 */
+               src_y += dim_y;
+               dst_y += dim_y;
+       } else {
+               br04 &= 0xfffffdff;     /* clear bit 9 top to bottom */
+       }
+       dim_x *= bpp;
+       out32r (pGD->pciBase + BR06_o, ((pGD->winSizeX * src_y) + src_x) * pGD->gdfBytesPP);    /* source */
+       out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP);    /* destination */
+       br04 &= 0xffffff00;
+       br04 |= 0x000000CC;     /* S -> D */
+       out32r (pGD->pciBase + BR04_o, br04);   /* */
+       out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x);  /* start the BITBlt */
+       video_wait_bitblt (pGD->pciBase + BR04_o);
+}
+
+#endif                         /* CONFIG_CT69000 */
+
+#endif                         /* CONFIG_VIDEO */
diff --git a/drivers/dc2114x.c b/drivers/dc2114x.c
new file mode 100644 (file)
index 0000000..e1147c0
--- /dev/null
@@ -0,0 +1,720 @@
+/*
+ * 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>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
+       && defined(CONFIG_TULIP)
+
+#include <malloc.h>
+#include <net.h>
+#include <pci.h>
+
+#undef DEBUG
+#undef DEBUG_SROM
+#undef DEBUG_SROM2
+
+#undef UPDATE_SROM
+
+/* PCI Registers.
+ */
+#define PCI_CFDA_PSM           0x43
+
+#define CFRV_RN                0x000000f0      /* Revision Number */
+
+#define WAKEUP         0x00            /* Power Saving Wakeup */
+#define SLEEP          0x80            /* Power Saving Sleep Mode */
+
+#define DC2114x_BRK    0x0020          /* CFRV break between DC21142 & DC21143 */
+
+/* Ethernet chip registers.
+ */
+#define DE4X5_BMR      0x000           /* Bus Mode Register */
+#define DE4X5_TPD      0x008           /* Transmit Poll Demand Reg */
+#define DE4X5_RRBA     0x018           /* RX Ring Base Address Reg */
+#define DE4X5_TRBA     0x020           /* TX Ring Base Address Reg */
+#define DE4X5_STS      0x028           /* Status Register */
+#define DE4X5_OMR      0x030           /* Operation Mode Register */
+#define DE4X5_SICR     0x068           /* SIA Connectivity Register */
+#define DE4X5_APROM    0x048           /* Ethernet Address PROM */
+
+/* Register bits.
+ */
+#define BMR_SWR                0x00000001      /* Software Reset */
+#define STS_TS         0x00700000      /* Transmit Process State */
+#define STS_RS         0x000e0000      /* Receive Process State */
+#define OMR_ST         0x00002000      /* Start/Stop Transmission Command */
+#define OMR_SR         0x00000002      /* Start/Stop Receive */
+#define OMR_PS         0x00040000      /* Port Select */
+#define OMR_SDP                0x02000000      /* SD Polarity - MUST BE ASSERTED */
+#define OMR_PM         0x00000080      /* Pass All Multicast */
+
+/* Descriptor bits.
+ */
+#define R_OWN          0x80000000      /* Own Bit */
+#define RD_RER         0x02000000      /* Receive End Of Ring */
+#define RD_LS          0x00000100      /* Last Descriptor */
+#define RD_ES          0x00008000      /* Error Summary */
+#define TD_TER         0x02000000      /* Transmit End Of Ring */
+#define T_OWN          0x80000000      /* Own Bit */
+#define TD_LS          0x40000000      /* Last Segment */
+#define TD_FS          0x20000000      /* First Segment */
+#define TD_ES          0x00008000      /* Error Summary */
+#define TD_SET         0x08000000      /* Setup Packet */
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define SROM_WRITE_CMD 5
+#define SROM_READ_CMD  6
+#define SROM_ERASE_CMD 7
+
+#define SROM_HWADD         0x0014      /* Hardware Address offset in SROM */
+#define SROM_RD                0x00004000      /* Read from Boot ROM */
+#define EE_DATA_WRITE  0x04    /* EEPROM chip data in. */
+#define EE_WRITE_0             0x4801
+#define EE_WRITE_1             0x4805
+#define EE_DATA_READ   0x08    /* EEPROM chip data out. */
+#define SROM_SR                0x00000800      /* Select Serial ROM when set */
+
+#define DT_IN          0x00000004      /* Serial Data In */
+#define DT_CLK         0x00000002      /* Serial ROM Clock */
+#define DT_CS          0x00000001      /* Serial ROM Chip Select */
+
+#define POLL_DEMAND    1
+
+#define RESET_DE4X5(dev) {\
+    int i;\
+    i=INL(dev, DE4X5_BMR);\
+    udelay(1000);\
+    OUTL(dev, i | BMR_SWR, DE4X5_BMR);\
+    udelay(1000);\
+    OUTL(dev, i, DE4X5_BMR);\
+    udelay(1000);\
+    for (i=0;i<5;i++) {INL(dev, DE4X5_BMR); udelay(10000);}\
+    udelay(1000);\
+}
+
+#define START_DE4X5(dev) {\
+    s32 omr; \
+    omr = INL(dev, DE4X5_OMR);\
+    omr |= OMR_ST | OMR_SR;\
+    OUTL(dev, omr, DE4X5_OMR);         /* Enable the TX and/or RX */\
+}
+
+#define STOP_DE4X5(dev) {\
+    s32 omr; \
+    omr = INL(dev, DE4X5_OMR);\
+    omr &= ~(OMR_ST|OMR_SR);\
+    OUTL(dev, omr, DE4X5_OMR);         /* Disable the TX and/or RX */ \
+}
+
+#define NUM_RX_DESC PKTBUFSRX
+#define NUM_TX_DESC 1                  /* Number of TX descriptors   */
+#define RX_BUFF_SZ  PKTSIZE_ALIGN
+
+#define TOUT_LOOP   1000000
+
+#define SETUP_FRAME_LEN 192
+#define ETH_ALEN       6
+
+
+struct de4x5_desc {
+       volatile s32 status;
+       u32 des1;
+       u32 buf;
+       u32 next;
+};
+
+static struct de4x5_desc rx_ring[NUM_RX_DESC]; /* RX descriptor ring         */
+static struct de4x5_desc tx_ring[NUM_TX_DESC]; /* TX descriptor ring         */
+static int rx_new;                             /* RX descriptor ring pointer */
+static int tx_new;                             /* TX descriptor ring pointer */
+
+static char rxRingSize;
+static char txRingSize;
+
+static void  sendto_srom(struct eth_device* dev, u_int command, u_long addr);
+static int   getfrom_srom(struct eth_device* dev, u_long addr);
+static int   do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len);
+static int   do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len);
+static int   read_srom(struct eth_device *dev, u_long ioaddr, int index);
+#ifdef UPDATE_SROM
+static int   write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value);
+static void  update_srom(struct eth_device *dev, bd_t *bis);
+#endif
+static void  read_hw_addr(struct eth_device* dev, bd_t * bis);
+static void  send_setup_frame(struct eth_device* dev, bd_t * bis);
+
+static int   dc21x4x_init(struct eth_device* dev, bd_t* bis);
+static int   dc21x4x_send(struct eth_device* dev, volatile void *packet, int length);
+static int   dc21x4x_recv(struct eth_device* dev);
+static void  dc21x4x_halt(struct eth_device* dev);
+#ifdef CONFIG_TULIP_SELECT_MEDIA
+extern void  dc21x4x_select_media(struct eth_device* dev);
+#endif
+
+#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a)
+
+static int INL(struct eth_device* dev, u_long addr)
+{
+       return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase));
+}
+
+static void OUTL(struct eth_device* dev, int command, u_long addr)
+{
+       *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command);
+}
+
+static struct pci_device_id supported[] = {
+       { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST },
+       { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 },
+       { }
+};
+
+int dc21x4x_initialize(bd_t *bis)
+{
+       int                     idx=0;
+       int                     card_number = 0;
+       int                     cfrv;
+       unsigned char           timer;
+       pci_dev_t               devbusfn;
+       unsigned int            iobase;
+       unsigned short          status;
+       struct eth_device*      dev;
+
+       while(1) {
+               devbusfn =  pci_find_devices(supported, idx++);
+               if (devbusfn == -1) {
+                       break;
+               }
+
+               /* Get the chip configuration revision register. */
+               pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv);
+
+               if ((cfrv & CFRV_RN) < DC2114x_BRK ) {
+                       printf("Error: The chip is not DC21143.\n");
+                       continue;
+               }
+
+               pci_read_config_word(devbusfn, PCI_COMMAND, &status);
+               status |=
+#ifdef CONFIG_TULIP_USE_IO
+                 PCI_COMMAND_IO |
+#else
+                 PCI_COMMAND_MEMORY |
+#endif
+                 PCI_COMMAND_MASTER;
+               pci_write_config_word(devbusfn, PCI_COMMAND, status);
+
+               pci_read_config_word(devbusfn, PCI_COMMAND, &status);
+               if (!(status & PCI_COMMAND_IO)) {
+                       printf("Error: Can not enable I/O access.\n");
+                       continue;
+               }
+
+               if (!(status & PCI_COMMAND_IO)) {
+                       printf("Error: Can not enable I/O access.\n");
+                       continue;
+               }
+
+               if (!(status & PCI_COMMAND_MASTER)) {
+                       printf("Error: Can not enable Bus Mastering.\n");
+                       continue;
+               }
+
+               /* Check the latency timer for values >= 0x60. */
+               pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer);
+
+               if (timer < 0x60) {
+                       pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x60);
+               }
+
+#ifdef CONFIG_TULIP_USE_IO
+               /* read BAR for memory space access */
+               pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase);
+               iobase &= PCI_BASE_ADDRESS_IO_MASK;
+#else
+               /* read BAR for memory space access */
+               pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase);
+               iobase &= PCI_BASE_ADDRESS_MEM_MASK;
+#endif
+
+#ifdef DEBUG
+               printf("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase);
+#endif
+
+               dev = (struct eth_device*) malloc(sizeof *dev);
+
+               sprintf(dev->name, "dc21x4x#%d", card_number);
+#ifdef CONFIG_TULIP_USE_IO
+               dev->iobase = pci_io_to_phys(devbusfn, iobase);
+#else
+               dev->iobase = pci_mem_to_phys(devbusfn, iobase);
+#endif
+               dev->priv   = (void*) devbusfn;
+               dev->init   = dc21x4x_init;
+               dev->halt   = dc21x4x_halt;
+               dev->send   = dc21x4x_send;
+               dev->recv   = dc21x4x_recv;
+
+               /* Ensure we're not sleeping. */
+               pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
+
+               udelay(10 * 1000);
+
+               read_hw_addr(dev, bis);
+
+               eth_register(dev);
+
+               card_number++;
+       }
+
+       return card_number;
+}
+
+static int dc21x4x_init(struct eth_device* dev, bd_t* bis)
+{
+       int             i;
+       int             devbusfn = (int) dev->priv;
+
+       /* Ensure we're not sleeping. */
+       pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
+
+       RESET_DE4X5(dev);
+
+       if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) {
+               printf("Error: Cannot reset ethernet controller.\n");
+               return 0;
+       }
+
+#ifdef CONFIG_TULIP_SELECT_MEDIA
+       dc21x4x_select_media(dev);
+#else
+       OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);
+#endif
+
+       for (i = 0; i < NUM_RX_DESC; i++) {
+               rx_ring[i].status = cpu_to_le32(R_OWN);
+               rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
+               rx_ring[i].buf = cpu_to_le32(phys_to_bus((u32) NetRxPackets[i]));
+               rx_ring[i].next = 0;
+       }
+
+       for (i=0; i < NUM_TX_DESC; i++) {
+               tx_ring[i].status = 0;
+               tx_ring[i].des1 = 0;
+               tx_ring[i].buf = 0;
+               tx_ring[i].next = 0;
+       }
+
+       rxRingSize = NUM_RX_DESC;
+       txRingSize = NUM_TX_DESC;
+
+       /* Write the end of list marker to the descriptor lists. */
+       rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);
+       tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER);
+
+       /* Tell the adapter where the TX/RX rings are located. */
+       OUTL(dev, phys_to_bus((u32) &rx_ring), DE4X5_RRBA);
+       OUTL(dev, phys_to_bus((u32) &tx_ring), DE4X5_TRBA);
+
+       START_DE4X5(dev);
+
+       tx_new = 0;
+       rx_new = 0;
+
+       send_setup_frame(dev, bis);
+
+       return 1;
+}
+
+static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length)
+{
+       int             status = -1;
+       int             i;
+
+       if (length <= 0) {
+               printf("%s: bad packet size: %d\n", dev->name, length);
+               goto Done;
+       }
+
+       for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+               if (i >= TOUT_LOOP) {
+                       printf("%s: tx error buffer not ready\n", dev->name);
+                       goto Done;
+               }
+       }
+
+       tx_ring[tx_new].buf    = cpu_to_le32(phys_to_bus((u32) packet));
+       tx_ring[tx_new].des1   = cpu_to_le32(TD_TER | TD_LS | TD_FS | length);
+       tx_ring[tx_new].status = cpu_to_le32(T_OWN);
+
+       OUTL(dev, POLL_DEMAND, DE4X5_TPD);
+
+       for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+               if (i >= TOUT_LOOP) {
+                       printf(".%s: tx buffer not ready\n", dev->name);
+                       goto Done;
+               }
+       }
+
+       if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) {
+#if 0 /* test-only */
+               printf("TX error status = 0x%08X\n",
+                      le32_to_cpu(tx_ring[tx_new].status));
+#endif
+               goto Done;
+       }
+
+       status = length;
+
+ Done:
+       return status;
+}
+
+static int dc21x4x_recv(struct eth_device* dev)
+{
+       s32             status;
+       int             length    = 0;
+
+       for ( ; ; ) {
+               status = (s32)le32_to_cpu(rx_ring[rx_new].status);
+
+               if (status & R_OWN) {
+                       break;
+               }
+
+               if (status & RD_LS) {
+                       /* Valid frame status.
+                        */
+                       if (status & RD_ES) {
+
+                               /* There was an error.
+                                */
+                               printf("RX error status = 0x%08X\n", status);
+                       } else {
+                               /* A valid frame received.
+                                */
+                               length = (le32_to_cpu(rx_ring[rx_new].status) >> 16);
+
+                               /* Pass the packet up to the protocol
+                                * layers.
+                                */
+                               NetReceive(NetRxPackets[rx_new], length - 4);
+                       }
+
+                       /* Change buffer ownership for this frame, back
+                        * to the adapter.
+                        */
+                       rx_ring[rx_new].status = cpu_to_le32(R_OWN);
+               }
+
+               /* Update entry information.
+                */
+               rx_new = (rx_new + 1) % rxRingSize;
+       }
+
+       return length;
+}
+
+static void dc21x4x_halt(struct eth_device* dev)
+{
+       int             devbusfn = (int) dev->priv;
+
+       STOP_DE4X5(dev);
+       OUTL(dev, 0, DE4X5_SICR);
+
+       pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP);
+}
+
+static void send_setup_frame(struct eth_device* dev, bd_t *bis)
+{
+       int             i;
+       char    setup_frame[SETUP_FRAME_LEN];
+       char    *pa = &setup_frame[0];
+
+       memset(pa, 0xff, SETUP_FRAME_LEN);
+
+       for (i = 0; i < ETH_ALEN; i++) {
+               *(pa + (i & 1)) = dev->enetaddr[i];
+               if (i & 0x01) {
+                       pa += 4;
+               }
+       }
+
+       for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+               if (i >= TOUT_LOOP) {
+                       printf("%s: tx error buffer not ready\n", dev->name);
+                       goto Done;
+               }
+       }
+
+       tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0]));
+       tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN);
+       tx_ring[tx_new].status = cpu_to_le32(T_OWN);
+
+       OUTL(dev, POLL_DEMAND, DE4X5_TPD);
+
+       for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+               if (i >= TOUT_LOOP) {
+                       printf("%s: tx buffer not ready\n", dev->name);
+                       goto Done;
+               }
+       }
+
+       if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) {
+               printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status));
+       }
+Done:
+       return;
+}
+
+/* SROM Read and write routines.
+ */
+
+static void
+sendto_srom(struct eth_device* dev, u_int command, u_long addr)
+{
+       OUTL(dev, command, addr);
+       udelay(1);
+}
+
+static int
+getfrom_srom(struct eth_device* dev, u_long addr)
+{
+       s32 tmp;
+
+       tmp = INL(dev, addr);
+       udelay(1);
+
+       return tmp;
+}
+
+/* Note: this routine returns extra data bits for size detection. */
+static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len)
+{
+       int i;
+       unsigned retval = 0;
+       int read_cmd = location | (SROM_READ_CMD << addr_len);
+
+       sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
+       sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+
+#ifdef DEBUG_SROM
+       printf(" EEPROM read at %d ", location);
+#endif
+
+       /* Shift the read command bits out. */
+       for (i = 4 + addr_len; i >= 0; i--) {
+               short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+               sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, ioaddr);
+               udelay(10);
+               sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, ioaddr);
+               udelay(10);
+#ifdef DEBUG_SROM2
+               printf("%X", getfrom_srom(dev, ioaddr) & 15);
+#endif
+               retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0);
+       }
+
+       sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+
+#ifdef DEBUG_SROM2
+       printf(" :%X:", getfrom_srom(dev, ioaddr) & 15);
+#endif
+
+       for (i = 16; i > 0; i--) {
+               sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
+               udelay(10);
+#ifdef DEBUG_SROM2
+               printf("%X", getfrom_srom(dev, ioaddr) & 15);
+#endif
+               retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0);
+               sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+               udelay(10);
+       }
+
+       /* Terminate the EEPROM access. */
+       sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
+
+#ifdef DEBUG_SROM2
+       printf(" EEPROM value at %d is %5.5x.\n", location, retval);
+#endif
+
+       return retval;
+}
+
+/* This executes a generic EEPROM command, typically a write or write enable.
+   It returns the data output from the EEPROM, and thus may also be used for
+   reads. */
+static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len)
+{
+       unsigned retval = 0;
+
+#ifdef DEBUG_SROM
+       printf(" EEPROM op 0x%x: ", cmd);
+#endif
+
+       sendto_srom(dev,SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
+
+       /* Shift the command bits out. */
+       do {
+               short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
+               sendto_srom(dev,dataval, ioaddr);
+               udelay(10);
+
+#ifdef DEBUG_SROM2
+               printf("%X", getfrom_srom(dev,ioaddr) & 15);
+#endif
+
+               sendto_srom(dev,dataval | DT_CLK, ioaddr);
+               udelay(10);
+               retval = (retval << 1) | ((getfrom_srom(dev,ioaddr) & EE_DATA_READ) ? 1 : 0);
+       } while (--cmd_len >= 0);
+       sendto_srom(dev,SROM_RD | SROM_SR | DT_CS, ioaddr);
+
+       /* Terminate the EEPROM access. */
+       sendto_srom(dev,SROM_RD | SROM_SR, ioaddr);
+
+#ifdef DEBUG_SROM
+       printf(" EEPROM result is 0x%5.5x.\n", retval);
+#endif
+
+       return retval;
+}
+
+static int read_srom(struct eth_device *dev, u_long ioaddr, int index)
+{
+       int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
+
+       return do_eeprom_cmd(dev, ioaddr,
+                            (((SROM_READ_CMD << ee_addr_size) | index) << 16)
+                            | 0xffff, 3 + ee_addr_size + 16);
+}
+
+#ifdef UPDATE_SROM
+static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value)
+{
+       int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
+       int i;
+       unsigned short newval;
+
+       udelay(10*1000); /* test-only */
+
+#ifdef DEBUG_SROM
+       printf("ee_addr_size=%d.\n", ee_addr_size);
+       printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index);
+#endif
+
+       /* Enable programming modes. */
+       do_eeprom_cmd(dev, ioaddr, (0x4f << (ee_addr_size-4)), 3+ee_addr_size);
+
+       /* Do the actual write. */
+       do_eeprom_cmd(dev, ioaddr,
+                     (((SROM_WRITE_CMD<<ee_addr_size)|index) << 16) | new_value,
+                     3 + ee_addr_size + 16);
+
+       /* Poll for write finished. */
+       sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+       for (i = 0; i < 10000; i++)                     /* Typical 2000 ticks */
+               if (getfrom_srom(dev, ioaddr) & EE_DATA_READ)
+                       break;
+
+#ifdef DEBUG_SROM
+       printf(" Write finished after %d ticks.\n", i);
+#endif
+
+       /* Disable programming. */
+       do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size-4)), 3 + ee_addr_size);
+
+       /* And read the result. */
+       newval = do_eeprom_cmd(dev, ioaddr,
+                              (((SROM_READ_CMD<<ee_addr_size)|index) << 16)
+                              | 0xffff, 3 + ee_addr_size + 16);
+#ifdef DEBUG_SROM
+       printf("  New value at offset %d is %4.4x.\n", index, newval);
+#endif
+       return 1;
+}
+#endif
+
+static void read_hw_addr(struct eth_device *dev, bd_t *bis)
+{
+       u_short tmp, *p = (short *)(&dev->enetaddr[0]);
+       int i, j = 0;
+
+       for (i = 0; i < (ETH_ALEN >> 1); i++) {
+               tmp = read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1) + i));
+               *p = le16_to_cpu(tmp);
+               j += *p++;
+       }
+
+       if ((j == 0) || (j == 0x2fffd)) {
+               memset (dev->enetaddr, 0, ETH_ALEN);
+#ifdef DEBUG
+               printf("Warning: can't read HW address from SROM.\n");
+#endif
+               goto Done;
+       }
+
+       return;
+
+Done:
+#ifdef UPDATE_SROM
+       update_srom(dev, bis);
+#endif
+       return;
+}
+
+#ifdef UPDATE_SROM
+static void update_srom(struct eth_device *dev, bd_t *bis)
+{
+       int i;
+       static unsigned short eeprom[0x40] = {
+               0x140b, 0x6610, 0x0000, 0x0000,         /* 00 */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 04 */
+               0x00a3, 0x0103, 0x0000, 0x0000,         /* 08 */
+               0x0000, 0x1f00, 0x0000, 0x0000,         /* 0c */
+               0x0108, 0x038d, 0x0000, 0x0000,         /* 10 */
+               0xe078, 0x0001, 0x0040, 0x0018,         /* 14 */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 18 */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 1c */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 20 */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 24 */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 28 */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 2c */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 30 */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 34 */
+               0x0000, 0x0000, 0x0000, 0x0000,         /* 38 */
+               0x0000, 0x0000, 0x0000, 0x4e07,         /* 3c */
+       };
+
+       /* Ethernet Addr... */
+       eeprom[0x0a] = ((bis->bi_enetaddr[1] & 0xff) << 8) | (bis->bi_enetaddr[0] & 0xff);
+       eeprom[0x0b] = ((bis->bi_enetaddr[3] & 0xff) << 8) | (bis->bi_enetaddr[2] & 0xff);
+       eeprom[0x0c] = ((bis->bi_enetaddr[5] & 0xff) << 8) | (bis->bi_enetaddr[4] & 0xff);
+
+       for (i=0; i<0x40; i++)
+       {
+               write_srom(dev, DE4X5_APROM, i, eeprom[i]);
+       }
+}
+#endif
+
+#endif
diff --git a/drivers/i8042.c b/drivers/i8042.c
new file mode 100644 (file)
index 0000000..ce24fc9
--- /dev/null
@@ -0,0 +1,655 @@
+/*
+ * (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
+ */
+
+/* i8042.c - Intel 8042 keyboard driver routines */
+
+/* includes */
+
+#include <common.h>
+
+#ifdef CONFIG_I8042_KBD
+
+#include <i8042.h>
+
+/* defines */
+
+#ifdef CONFIG_CONSOLE_CURSOR
+extern void console_cursor (int state);
+static int blinkCount = CFG_CONSOLE_BLINK_COUNT;
+static int cursor_state = 0;
+#endif
+
+/* locals */
+
+static int  kbd_input    = -1;          /* no input yet */
+static int  kbd_mapping  = KBD_US;      /* default US keyboard */
+static int  kbd_flags    = NORMAL;      /* after reset */
+static int  kbd_state    = 0;           /* unshift code */
+
+static void kbd_conv_char (unsigned char scan_code);
+static void kbd_led_set (void);
+static void kbd_normal (unsigned char scan_code);
+static void kbd_shift (unsigned char scan_code);
+static void kbd_ctrl (unsigned char scan_code);
+static void kbd_num (unsigned char scan_code);
+static void kbd_caps (unsigned char scan_code);
+static void kbd_scroll (unsigned char scan_code);
+static void kbd_alt (unsigned char scan_code);
+static int  kbd_input_empty (void);
+static int  kbd_reset (void);
+
+static unsigned char kbd_fct_map [144] =
+    { /* kbd_fct_map table for scan code */
+    0,   AS,   AS,   AS,   AS,   AS,   AS,   AS, /* scan  0- 7 */
+   AS,   AS,   AS,   AS,   AS,   AS,   AS,   AS, /* scan  8- F */
+   AS,   AS,   AS,   AS,   AS,   AS,   AS,   AS, /* scan 10-17 */
+   AS,   AS,   AS,   AS,   AS,   CN,   AS,   AS, /* scan 18-1F */
+   AS,   AS,   AS,   AS,   AS,   AS,   AS,   AS, /* scan 20-27 */
+   AS,   AS,   SH,   AS,   AS,   AS,   AS,   AS, /* scan 28-2F */
+   AS,   AS,   AS,   AS,   AS,   AS,   SH,   AS, /* scan 30-37 */
+   AS,   AS,   CP,   0,    0,    0,    0,     0, /* scan 38-3F */
+    0,   0,    0,    0,    0,    NM,   ST,   ES, /* scan 40-47 */
+   ES,   ES,   ES,   ES,   ES,   ES,   ES,   ES, /* scan 48-4F */
+   ES,   ES,   ES,   ES,   0,    0,    AS,    0, /* scan 50-57 */
+    0,   0,    0,    0,    0,    0,    0,     0, /* scan 58-5F */
+    0,   0,    0,    0,    0,    0,    0,     0, /* scan 60-67 */
+    0,   0,    0,    0,    0,    0,    0,     0, /* scan 68-6F */
+   AS,   0,    0,    AS,   0,    0,    AS,    0, /* scan 70-77 */
+    0,   AS,   0,    0,    0,    AS,   0,     0, /* scan 78-7F */
+   AS,   CN,   AS,   AS,   AK,   ST,   EX,   EX, /* enhanced   */
+   AS,   EX,   EX,   AS,   EX,   AS,   EX,   EX  /* enhanced   */
+    };
+
+static unsigned char kbd_key_map [2][5][144] =
+    {
+    { /* US keyboard */
+    { /* unshift code */
+    0,  0x1b,   '1',   '2',   '3',   '4',   '5',   '6',    /* scan  0- 7 */
+  '7',   '8',   '9',   '0',   '-',   '=',  0x08,  '\t',    /* scan  8- F */
+  'q',   'w',   'e',   'r',   't',   'y',   'u',   'i',    /* scan 10-17 */
+  'o',   'p',   '[',   ']',  '\r',   CN,    'a',   's',    /* scan 18-1F */
+  'd',   'f',   'g',   'h',   'j',   'k',   'l',   ';',    /* scan 20-27 */
+ '\'',   '`',   SH,   '\\',   'z',   'x',   'c',   'v',    /* scan 28-2F */
+  'b',   'n',   'm',   ',',   '.',   '/',   SH,    '*',    /* scan 30-37 */
+  ' ',   ' ',   CP,      0,     0,     0,     0,     0,    /* scan 38-3F */
+    0,     0,     0,     0,     0,   NM,    ST,    '7',    /* scan 40-47 */
+  '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',    /* scan 48-4F */
+  '2',   '3',   '0',   '.',     0,     0,     0,     0,    /* scan 50-57 */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 58-5F */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 60-67 */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 68-6F */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 70-77 */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 78-7F */
+  '\r',   CN,   '/',   '*',   ' ',    ST,   'F',   'A',    /* extended */
+    0,   'D',   'C',     0,   'B',     0,    '@',  'P'     /* extended */
+    },
+    { /* shift code */
+    0,  0x1b,   '!',   '@',   '#',   '$',   '%',   '^',    /* scan  0- 7 */
+  '&',   '*',   '(',   ')',   '_',   '+',  0x08,  '\t',    /* scan  8- F */
+  'Q',   'W',   'E',   'R',   'T',   'Y',   'U',   'I',    /* scan 10-17 */
+  'O',   'P',   '{',   '}',  '\r',   CN,    'A',   'S',    /* scan 18-1F */
+  'D',   'F',   'G',   'H',   'J',   'K',   'L',   ':',    /* scan 20-27 */
+  '"',   '~',   SH,    '|',   'Z',   'X',   'C',   'V',    /* scan 28-2F */
+  'B',   'N',   'M',   '<',   '>',   '?',   SH,    '*',    /* scan 30-37 */
+  ' ',   ' ',   CP,      0,     0,     0,     0,     0,    /* scan 38-3F */
+    0,     0,     0,     0,     0,   NM,    ST,    '7',    /* scan 40-47 */
+  '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',    /* scan 48-4F */
+  '2',   '3',   '0',   '.',     0,     0,     0,     0,    /* scan 50-57 */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 58-5F */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 60-67 */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 68-6F */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 70-77 */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 78-7F */
+  '\r',   CN,   '/',   '*',   ' ',    ST,   'F',   'A',    /* extended */
+    0,   'D',   'C',     0,   'B',     0,   '@',   'P'     /* extended */
+    },
+    { /* control code */
+ 0xff,  0x1b,  0xff,  0x00,  0xff,  0xff,  0xff,  0xff,    /* scan  0- 7 */
+ 0x1e,  0xff,  0xff,  0xff,  0x1f,  0xff,  0xff,  '\t',    /* scan  8- F */
+ 0x11,  0x17,  0x05,  0x12,  0x14,  0x19,  0x15,  0x09,    /* scan 10-17 */
+ 0x0f,  0x10,  0x1b,  0x1d,  '\r',   CN,   0x01,  0x13,    /* scan 18-1F */
+ 0x04,  0x06,  0x07,  0x08,  0x0a,  0x0b,  0x0c,  0xff,    /* scan 20-27 */
+ 0xff,  0x1c,   SH,   0xff,  0x1a,  0x18,  0x03,  0x16,    /* scan 28-2F */
+ 0x02,  0x0e,  0x0d,  0xff,  0xff,  0xff,   SH,   0xff,    /* scan 30-37 */
+ 0xff,  0xff,   CP,   0xff,  0xff,  0xff,  0xff,  0xff,    /* scan 38-3F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,   NM,    ST,   0xff,    /* scan 40-47 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,    /* scan 48-4F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,    /* scan 50-57 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,    /* scan 58-5F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,    /* scan 60-67 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,    /* scan 68-6F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,    /* scan 70-77 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,    /* scan 78-7F */
+  '\r',   CN,   '/',   '*',   ' ',    ST,  0xff,  0xff,    /* extended */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff     /* extended */
+    },
+    { /* non numeric code */
+    0,  0x1b,   '1',   '2',   '3',   '4',   '5',   '6',    /* scan  0- 7 */
+  '7',   '8',   '9',   '0',   '-',   '=',  0x08,  '\t',    /* scan  8- F */
+  'q',   'w',   'e',   'r',   't',   'y',   'u',   'i',    /* scan 10-17 */
+  'o',   'p',   '[',   ']',  '\r',   CN,    'a',   's',    /* scan 18-1F */
+  'd',   'f',   'g',   'h',   'j',   'k',   'l',   ';',    /* scan 20-27 */
+ '\'',   '`',   SH,   '\\',   'z',   'x',   'c',   'v',    /* scan 28-2F */
+  'b',   'n',   'm',   ',',   '.',   '/',   SH,    '*',    /* scan 30-37 */
+  ' ',   ' ',   CP,      0,     0,     0,     0,     0,    /* scan 38-3F */
+    0,     0,     0,     0,     0,   NM,    ST,    'w',    /* scan 40-47 */
+  'x',   'y',   'l',   't',   'u',   'v',   'm',   'q',    /* scan 48-4F */
+  'r',   's',   'p',   'n',     0,     0,     0,     0,    /* scan 50-57 */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 58-5F */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 60-67 */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 68-6F */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 70-77 */
+    0,     0,     0,     0,     0,     0,     0,     0,    /* scan 78-7F */
+  '\r',   CN,   '/',   '*',   ' ',    ST,   'F',   'A',    /* extended */
+    0,   'D',   'C',     0,   'B',     0,    '@',  'P'     /* extended */
+    },
+    { /* right alt mode - not used in US keyboard */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan  0 - 7 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan  8 - F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 10 -17 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 18 -1F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 20 -27 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 28 -2F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 30 -37 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 38 -3F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 40 -47 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 48 -4F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 50 -57 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 58 -5F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 60 -67 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 68 -6F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 70 -77 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 78 -7F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* extended    */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff  /* extended    */
+    }
+    },
+    { /* german keyboard */
+    { /* unshift code */
+    0,  0x1b,   '1',   '2',   '3',   '4',   '5',   '6', /* scan  0- 7 */
+  '7',   '8',   '9',   '0',  0xe1,  '\'',  0x08,  '\t', /* scan  8- F */
+  'q',   'w',   'e',   'r',   't',   'z',   'u',   'i', /* scan 10-17 */
+  'o',   'p',  0x81,   '+',  '\r',   CN,    'a',   's', /* scan 18-1F */
+  'd',   'f',   'g',   'h',   'j',   'k',   'l',  0x94, /* scan 20-27 */
+ 0x84,   '^',   SH,    '#',   'y',   'x',   'c',   'v', /* scan 28-2F */
+  'b',   'n',   'm',   ',',   '.',   '-',   SH,    '*', /* scan 30-37 */
+  ' ',   ' ',   CP,      0,     0,     0,     0,     0, /* scan 38-3F */
+    0,     0,     0,     0,     0,   NM,    ST,    '7', /* scan 40-47 */
+  '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1', /* scan 48-4F */
+  '2',   '3',   '0',   ',',     0,     0,   '<',     0, /* scan 50-57 */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 58-5F */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 60-67 */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 68-6F */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 70-77 */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 78-7F */
+  '\r',   CN,   '/',   '*',   ' ',    ST,   'F',   'A', /* extended */
+    0,   'D',   'C',     0,   'B',     0,    '@',  'P'  /* extended */
+    },
+    { /* shift code */
+    0,  0x1b,   '!',   '"',  0x15,   '$',   '%',   '&', /* scan  0- 7 */
+  '/',   '(',   ')',   '=',   '?',   '`',  0x08,  '\t', /* scan  8- F */
+  'Q',   'W',   'E',   'R',   'T',   'Z',   'U',   'I', /* scan 10-17 */
+  'O',   'P',  0x9a,   '*',  '\r',   CN,    'A',   'S', /* scan 18-1F */
+  'D',   'F',   'G',   'H',   'J',   'K',   'L',  0x99, /* scan 20-27 */
+ 0x8e,  0xf8,   SH,   '\'',   'Y',   'X',   'C',   'V', /* scan 28-2F */
+  'B',   'N',   'M',   ';',   ':',   '_',   SH,    '*', /* scan 30-37 */
+  ' ',   ' ',   CP,      0,     0,     0,     0,     0, /* scan 38-3F */
+    0,     0,     0,     0,     0,   NM,    ST,    '7', /* scan 40-47 */
+  '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1', /* scan 48-4F */
+  '2',   '3',   '0',   ',',     0,     0,   '>',     0, /* scan 50-57 */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 58-5F */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 60-67 */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 68-6F */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 70-77 */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 78-7F */
+  '\r',   CN,   '/',   '*',   ' ',    ST,   'F',   'A', /* extended */
+    0,   'D',   'C',     0,   'B',     0,   '@',   'P'  /* extended */
+    },
+    { /* control code */
+ 0xff,  0x1b,  0xff,  0x00,  0xff,  0xff,  0xff,  0xff, /* scan  0- 7 */
+ 0x1e,  0xff,  0xff,  0xff,  0x1f,  0xff,  0xff,  '\t', /* scan  8- F */
+ 0x11,  0x17,  0x05,  0x12,  0x14,  0x19,  0x15,  0x09, /* scan 10-17 */
+ 0x0f,  0x10,  0x1b,  0x1d,  '\r',   CN,   0x01,  0x13, /* scan 18-1F */
+ 0x04,  0x06,  0x07,  0x08,  0x0a,  0x0b,  0x0c,  0xff, /* scan 20-27 */
+ 0xff,  0x1c,   SH,   0xff,  0x1a,  0x18,  0x03,  0x16, /* scan 28-2F */
+ 0x02,  0x0e,  0x0d,  0xff,  0xff,  0xff,   SH,   0xff, /* scan 30-37 */
+ 0xff,  0xff,   CP,   0xff,  0xff,  0xff,  0xff,  0xff, /* scan 38-3F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,   NM,    ST,   0xff, /* scan 40-47 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 48-4F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 50-57 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 58-5F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 60-67 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 68-6F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 70-77 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 78-7F */
+  '\r',   CN,   '/',   '*',   ' ',    ST,  0xff,  0xff, /* extended */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff  /* extended */
+    },
+    { /* non numeric code */
+    0,  0x1b,   '1',   '2',   '3',   '4',   '5',   '6', /* scan  0- 7 */
+  '7',   '8',   '9',   '0',  0xe1,  '\'',  0x08,  '\t', /* scan  8- F */
+  'q',   'w',   'e',   'r',   't',   'z',   'u',   'i', /* scan 10-17 */
+  'o',   'p',  0x81,   '+',  '\r',   CN,    'a',   's', /* scan 18-1F */
+  'd',   'f',   'g',   'h',   'j',   'k',   'l',  0x94, /* scan 20-27 */
+ 0x84,   '^',   SH,      0,   'y',   'x',   'c',   'v', /* scan 28-2F */
+  'b',   'n',   'm',   ',',   '.',   '-',   SH,    '*', /* scan 30-37 */
+  ' ',   ' ',   CP,      0,     0,     0,     0,     0, /* scan 38-3F */
+    0,     0,     0,     0,     0,   NM,    ST,    'w', /* scan 40-47 */
+  'x',   'y',   'l',   't',   'u',   'v',   'm',   'q', /* scan 48-4F */
+  'r',   's',   'p',   'n',     0,     0,   '<',     0, /* scan 50-57 */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 58-5F */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 60-67 */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 68-6F */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 70-77 */
+    0,     0,     0,     0,     0,     0,     0,     0, /* scan 78-7F */
+  '\r',   CN,   '/',   '*',   ' ',    ST,   'F',   'A', /* extended */
+    0,   'D',   'C',     0,   'B',     0,    '@',  'P'  /* extended */
+    },
+    { /* Right alt mode - is used in German keyboard */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan  0 - 7 */
+  '{',   '[',   ']',   '}',  '\\',  0xff,  0xff,  0xff, /* scan  8 - F */
+  '@',  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 10 -17 */
+ 0xff,  0xff,  0xff,   '~',  0xff,  0xff,  0xff,  0xff, /* scan 18 -1F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 20 -27 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 28 -2F */
+ 0xff,  0xff,  0xe6,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 30 -37 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 38 -3F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 40 -47 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 48 -4F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,   '|',  0xff, /* scan 50 -57 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 58 -5F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 60 -67 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 68 -6F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 70 -77 */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* scan 78 -7F */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, /* extended    */
+ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff  /* extended    */
+    }
+    }
+    };
+
+static unsigned char ext_key_map [] =
+    {
+    0x1c,   /* keypad enter */
+    0x1d,   /* right control */
+    0x35,   /* keypad slash */
+    0x37,   /* print screen */
+    0x38,   /* right alt */
+    0x46,   /* break */
+    0x47,   /* editpad home */
+    0x48,   /* editpad up */
+    0x49,   /* editpad pgup */
+    0x4b,   /* editpad left */
+    0x4d,   /* editpad right */
+    0x4f,   /* editpad end */
+    0x50,   /* editpad dn */
+    0x51,   /* editpad pgdn */
+    0x52,   /* editpad ins */
+    0x53,   /* editpad del */
+    0x00    /* map end */
+    };
+
+/*******************************************************************************
+ *
+ * i8042_kbd_init - reset keyboard and init state flags
+ */
+int i8042_kbd_init (void)
+{
+    int keymap, try;
+    char *penv;
+
+    /* Init keyboard device (default US layout) */
+    keymap = KBD_US;
+    if ((penv = getenv ("keymap")) != NULL)
+    {
+        if (strncmp (penv, "de", 3) == 0)
+        keymap = KBD_GER;
+    }
+
+    for (try = 0; try < KBD_RESET_TRIES; try++)
+    {
+        if (kbd_reset() == 0)
+        {
+            kbd_mapping   = keymap;
+            kbd_flags     = NORMAL;
+            kbd_state     = 0;
+            kbd_led_set();
+            return 0;
+            }
+    }
+    return -1;
+}
+
+
+/*******************************************************************************
+ *
+ * i8042_tstc - test if keyboard input is available
+ *              option: cursor blinking if called in a loop
+ */
+int i8042_tstc (void)
+{
+    unsigned char scan_code = 0;
+
+#ifdef CONFIG_CONSOLE_CURSOR
+    if (--blinkCount == 0)
+    {
+        cursor_state ^= 1;
+        console_cursor (cursor_state);
+        blinkCount = CFG_CONSOLE_BLINK_COUNT;
+        udelay (10);
+    }
+#endif
+
+    if ((in8 (I8042_STATUS_REG) & 0x01) == 0)
+        return 0;
+    else
+    {
+        scan_code = in8 (I8042_DATA_REG);
+        if (scan_code == 0xfa)
+            return 0;
+
+        kbd_conv_char(scan_code);
+
+        if (kbd_input != -1)
+            return 1;
+    }
+    return 0;
+}
+
+
+/*******************************************************************************
+ *
+ * i8042_getc - wait till keyboard input is available
+ *              option: turn on/off cursor while waiting
+ */
+int i8042_getc (void)
+{
+    int ret_chr;
+    unsigned char scan_code;
+
+    while (kbd_input == -1)
+    {
+        while ((in8 (I8042_STATUS_REG) & 0x01) == 0)
+        {
+#ifdef CONFIG_CONSOLE_CURSOR
+            if (--blinkCount==0)
+            {
+                cursor_state ^= 1;
+                console_cursor (cursor_state);
+                blinkCount = CFG_CONSOLE_BLINK_COUNT;
+            }
+            udelay (10);
+#endif
+        }
+
+        scan_code = in8 (I8042_DATA_REG);
+
+        if (scan_code != 0xfa)
+        kbd_conv_char (scan_code);
+    }
+    ret_chr = kbd_input;
+    kbd_input = -1;
+    return ret_chr;
+}
+
+
+/******************************************************************************/
+
+static void kbd_conv_char (unsigned char scan_code)
+{
+    if (scan_code == 0xe0)
+    {
+        kbd_flags |= EXT;
+        return;
+    }
+
+    /* if high bit of scan_code, set break flag */
+    if (scan_code & 0x80)
+        kbd_flags |=  BRK;
+    else
+        kbd_flags &= ~BRK;
+
+    if ((scan_code == 0xe1) || (kbd_flags & E1))
+    {
+        if (scan_code == 0xe1)
+        {
+            kbd_flags ^= BRK;     /* reset the break flag */
+            kbd_flags ^= E1;      /* bitwise EXOR with E1 flag */
+        }
+        return;
+    }
+
+    scan_code &= 0x7f;
+
+    if (kbd_flags & EXT)
+    {
+        int i;
+
+        kbd_flags ^= EXT;
+        for (i=0; ext_key_map[i]; i++)
+        {
+            if (ext_key_map[i] == scan_code)
+            {
+                scan_code = 0x80 + i;
+                break;
+            }
+        }
+        /* not found ? */
+        if (!ext_key_map[i])
+            return;
+    }
+
+    switch (kbd_fct_map [scan_code])
+    {
+    case AS:  kbd_normal (scan_code);
+        break;
+    case SH:  kbd_shift (scan_code);
+        break;
+    case CN:  kbd_ctrl (scan_code);
+        break;
+    case NM:  kbd_num (scan_code);
+        break;
+    case CP:  kbd_caps (scan_code);
+        break;
+    case ST:  kbd_scroll (scan_code);
+        break;
+    case AK:  kbd_alt (scan_code);
+        break;
+    }
+    return;
+}
+
+
+/******************************************************************************/
+
+static void kbd_normal (unsigned char scan_code)
+{
+    unsigned char chr;
+
+    if ((kbd_flags & BRK) == NORMAL)
+    {
+       chr = kbd_key_map [kbd_mapping][kbd_state][scan_code];
+       if ((chr == 0xff) || (chr == 0x00))
+        {
+            return;
+        }
+
+        /* if caps lock convert upper to lower */
+        if (((kbd_flags & CAPS) == CAPS) && (chr >= 'a' && chr <= 'z'))
+       {
+           chr -= 'a' - 'A';
+       }
+       kbd_input = chr;
+    }
+}
+
+
+/******************************************************************************/
+
+static void kbd_shift (unsigned char scan_code)
+{
+    if ((kbd_flags & BRK) == BRK)
+    {
+        kbd_state = AS;
+        kbd_flags &= (~SHIFT);
+    }
+    else
+    {
+       kbd_state = SH;
+       kbd_flags |= SHIFT;
+    }
+}
+
+
+/******************************************************************************/
+
+static void kbd_ctrl (unsigned char scan_code)
+{
+    if ((kbd_flags & BRK) == BRK)
+    {
+       kbd_state = AS;
+       kbd_flags &= (~CTRL);
+    }
+    else
+    {
+       kbd_state = CN;
+       kbd_flags |= CTRL;
+    }
+}
+
+
+/******************************************************************************/
+
+static void kbd_caps (unsigned char scan_code)
+{
+    if ((kbd_flags & BRK) == NORMAL)
+    {
+       kbd_flags ^= CAPS;
+       kbd_led_set ();            /* update keyboard LED */
+    }
+}
+
+
+/******************************************************************************/
+
+static void kbd_num (unsigned char scan_code)
+{
+    if ((kbd_flags & BRK) == NORMAL)
+    {
+       kbd_flags ^= NUM;
+       kbd_state = (kbd_flags & NUM) ? AS : NM;
+       kbd_led_set ();            /* update keyboard LED */
+    }
+}
+
+
+/******************************************************************************/
+
+static void kbd_scroll (unsigned char scan_code)
+{
+    if ((kbd_flags & BRK) == NORMAL)
+    {
+        kbd_flags ^= STP;
+        kbd_led_set ();            /* update keyboard LED */
+        if (kbd_flags & STP)
+            kbd_input = 0x13;
+        else
+            kbd_input = 0x11;
+    }
+}
+
+/******************************************************************************/
+
+static void kbd_alt (unsigned char scan_code)
+{
+    if ((kbd_flags & BRK) == BRK)
+    {
+        kbd_state = AS;
+        kbd_flags &= (~ALT);
+    }
+    else
+    {
+        kbd_state = AK;
+        kbd_flags &= ALT;
+    }
+}
+
+
+/******************************************************************************/
+
+static void kbd_led_set (void)
+{
+    kbd_input_empty();
+    out8 (I8042_DATA_REG, 0xed);        /* SET LED command */
+    kbd_input_empty();
+    out8 (I8042_DATA_REG, (kbd_flags & 0x7));    /* LED bits only */
+}
+
+
+/******************************************************************************/
+
+static int kbd_input_empty (void)
+{
+    int kbdTimeout = KBD_TIMEOUT;
+
+    /* wait for input buf empty */
+    while ((in8 (I8042_STATUS_REG) & 0x02) && kbdTimeout--)
+        udelay(1000);
+
+    return kbdTimeout;
+}
+
+/******************************************************************************/
+
+static int kbd_reset (void)
+{
+    if (kbd_input_empty() == 0)
+        return -1;
+
+    out8 (I8042_DATA_REG, 0xff);
+
+    udelay(250000);
+
+    if (kbd_input_empty() == 0)
+        return -1;
+
+    out8 (I8042_DATA_REG, 0x60);
+
+    if (kbd_input_empty() == 0)
+        return -1;
+
+    out8 (I8042_DATA_REG, 0x45);
+
+
+    if (kbd_input_empty() == 0)
+        return -1;
+
+    out8 (I8042_COMMAND_REG, 0xae);
+
+    if (kbd_input_empty() == 0)
+        return -1;
+
+    return 0;
+}
+
+#endif /* CONFIG_I8042_KBD */
diff --git a/drivers/ns87308.c b/drivers/ns87308.c
new file mode 100644 (file)
index 0000000..cf4d359
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * (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 <config.h>
+
+#ifdef CFG_NS87308
+
+#include <ns87308.h>
+
+void initialise_ns87308 (void)
+{
+#ifdef CFG_NS87308_PS2MOD
+       unsigned char data;
+
+       /*
+        * Switch floppy drive to PS/2 mode.
+        */
+       read_pnp_config(SUPOERIO_CONF1, &data);
+       data &= 0xFB;
+       write_pnp_config(SUPOERIO_CONF1, data);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_KBC1)
+       PNP_SET_DEVICE_BASE(LDEV_KBC1, CFG_NS87308_KBC1_BASE);
+       write_pnp_config(LUN_CONFIG_REG, 0);
+       write_pnp_config(CBASE_HIGH, 0x00);
+       write_pnp_config(CBASE_LOW, 0x64);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_MOUSE)
+       PNP_ACTIVATE_DEVICE(LDEV_MOUSE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_RTC_APC)
+       PNP_SET_DEVICE_BASE(LDEV_RTC_APC, CFG_NS87308_RTC_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_FDC)
+       PNP_SET_DEVICE_BASE(LDEV_FDC, CFG_NS87308_FDC_BASE);
+       write_pnp_config(LUN_CONFIG_REG, 0x40);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_RARP)
+       PNP_SET_DEVICE_BASE(LDEV_PARP, CFG_NS87308_LPT_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_UART1)
+       PNP_SET_DEVICE_BASE(LDEV_UART1, CFG_NS87308_UART1_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_UART2)
+       PNP_SET_DEVICE_BASE(LDEV_UART2, CFG_NS87308_UART2_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_GPIO)
+       PNP_SET_DEVICE_BASE(LDEV_GPIO, CFG_NS87308_GPIO_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_POWRMAN)
+#ifndef CFG_NS87308_PWMAN_BASE
+       PNP_ACTIVATE_DEVICE(LDEV_POWRMAN);
+#else
+       PNP_SET_DEVICE_BASE(LDEV_POWRMAN, CFG_NS87308_PWMAN_BASE);
+
+       /*
+        * Enable all units
+        */
+       write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_FER1, 0x7d);
+       write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_FER2, 0x87);
+
+#ifdef CFG_NS87308_PMC1
+       write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_PMC1, CFG_NS87308_PMC1);
+#endif
+
+#ifdef CFG_NS87308_PMC2
+       write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_PMC2, CFG_NS87308_PMC2);
+#endif
+
+#ifdef CFG_NS87308_PMC3
+       write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_PMC3, CFG_NS87308_PMC3);
+#endif
+#endif
+#endif
+
+#ifdef CFG_NS87308_CS0_BASE
+       PNP_PGCS_CSLINE_BASE(0, CFG_NS87308_CS0_BASE);
+       PNP_PGCS_CSLINE_CONF(0, CFG_NS87308_CS0_CONF);
+#endif
+
+#ifdef CFG_NS87308_CS1_BASE
+       PNP_PGCS_CSLINE_BASE(1, CFG_NS87308_CS1_BASE);
+       PNP_PGCS_CSLINE_CONF(1, CFG_NS87308_CS1_CONF);
+#endif
+
+#ifdef CFG_NS87308_CS2_BASE
+       PNP_PGCS_CSLINE_BASE(2, CFG_NS87308_CS2_BASE);
+       PNP_PGCS_CSLINE_CONF(2, CFG_NS87308_CS2_CONF);
+#endif
+}
+
+#endif
diff --git a/drivers/pci.c b/drivers/pci.c
new file mode 100644 (file)
index 0000000..52584ce
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * (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
+ */
+
+/*
+ * PCI routines
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <command.h>
+#include <cmd_boot.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#ifdef DEBUG
+#define DEBUGF(x...) printf(x)
+#else
+#define DEBUGF(x...)
+#endif /* DEBUG */
+
+/*
+ *
+ */
+
+#define PCI_HOSE_OP(rw, size, type)                                            \
+int pci_hose_##rw##_config_##size(struct pci_controller *hose,                         \
+                                 pci_dev_t dev,                                \
+                                 int offset, type value)                       \
+{                                                                              \
+       return hose->rw##_##size(hose, dev, offset, value);                     \
+}
+
+PCI_HOSE_OP(read, byte, u8 *)
+PCI_HOSE_OP(read, word, u16 *)
+PCI_HOSE_OP(read, dword, u32 *)
+PCI_HOSE_OP(write, byte, u8)
+PCI_HOSE_OP(write, word, u16)
+PCI_HOSE_OP(write, dword, u32)
+
+#define PCI_OP(rw, size, type, error_code)                                     \
+int pci_##rw##_config_##size(pci_dev_t dev, int offset, type value)            \
+{                                                                              \
+       struct pci_controller *hose = pci_bus_to_hose(PCI_BUS(dev));            \
+                                                                               \
+       if (!hose)                                                              \
+       {                                                                       \
+               error_code;                                                     \
+               return -1;                                                      \
+       }                                                                       \
+                                                                               \
+       return pci_hose_##rw##_config_##size(hose, dev, offset, value);         \
+}
+
+PCI_OP(read, byte, u8 *, *value = 0xff)
+PCI_OP(read, word, u16 *, *value = 0xffff)
+PCI_OP(read, dword, u32 *, *value = 0xffffffff)
+PCI_OP(write, byte, u8, )
+PCI_OP(write, word, u16, )
+PCI_OP(write, dword, u32, )
+
+#define PCI_READ_VIA_DWORD_OP(size, type, off_mask)                            \
+int pci_hose_read_config_##size##_via_dword(struct pci_controller *hose,       \
+                                       pci_dev_t dev,                          \
+                                       int offset, type val)                   \
+{                                                                              \
+       u32 val32;                                                              \
+                                                                               \
+       if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0)   \
+               return -1;                                                      \
+                                                                               \
+       *val = (val32 >> ((offset & (int)off_mask) * 8));                       \
+                                                                               \
+       return 0;                                                               \
+}
+
+#define PCI_WRITE_VIA_DWORD_OP(size, type, off_mask, val_mask)                 \
+int pci_hose_write_config_##size##_via_dword(struct pci_controller *hose,      \
+                                            pci_dev_t dev,                     \
+                                            int offset, type val)              \
+{                                                                              \
+       u32 val32, mask, ldata;                                                 \
+                                                                               \
+       if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0)   \
+               return -1;                                                      \
+                                                                               \
+       mask = val_mask;                                                        \
+       ldata = (((unsigned long)val) & mask) << ((offset & (int)off_mask) * 8);\
+       mask <<= ((mask & (int)off_mask) * 8);                                  \
+       val32 = (val32 & ~mask) | ldata;                                        \
+                                                                               \
+       if (pci_hose_write_config_dword(hose, dev, offset & 0xfc, val32) < 0)   \
+               return -1;                                                      \
+                                                                               \
+       return 0;                                                               \
+}
+
+PCI_READ_VIA_DWORD_OP(byte, u8 *, 0x03)
+PCI_READ_VIA_DWORD_OP(word, u16 *, 0x02)
+PCI_WRITE_VIA_DWORD_OP(byte, u8, 0x03, 0x000000ff)
+PCI_WRITE_VIA_DWORD_OP(word, u16, 0x02, 0x0000ffff)
+
+/*
+ *
+ */
+
+static struct pci_controller* hose_head = NULL;
+
+void pci_register_hose(struct pci_controller* hose)
+{
+       struct pci_controller **phose = &hose_head;
+
+       while(*phose)
+               phose = &(*phose)->next;
+
+       hose->next = NULL;
+
+       *phose = hose;
+}
+
+struct pci_controller* pci_bus_to_hose(int bus)
+{
+       struct pci_controller *hose;
+
+       for (hose = hose_head; hose; hose = hose->next)
+               if (bus >= hose->first_busno &&
+                   bus <= hose->last_busno)
+                       return hose;
+
+       return NULL;
+}
+
+pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
+{
+       struct pci_controller * hose;
+       u16 vendor, device;
+       u8 header_type;
+       pci_dev_t bdf;
+       int i, bus, found_multi = 0;
+
+       for (hose = hose_head; hose; hose = hose->next)
+       {
+#if CFG_SCSI_SCAN_BUS_REVERSE
+               for (bus = hose->last_busno; bus >= hose->first_busno; bus--)
+#else
+               for (bus = hose->first_busno; bus <= hose->last_busno; bus++)
+#endif
+                       for (bdf = PCI_BDF(bus,0,0);
+#ifdef CONFIG_ELPPC
+                            bdf < PCI_BDF(bus,PCI_MAX_PCI_DEVICES-1,PCI_MAX_PCI_FUNCTIONS-1);
+#else
+                            bdf < PCI_BDF(bus+1,0,0);
+#endif
+                            bdf += PCI_BDF(0,0,1))
+                       {
+                               if (!PCI_FUNC(bdf))
+                               {
+                                       pci_read_config_byte(bdf,
+                                                            PCI_HEADER_TYPE,
+                                                            &header_type);
+
+                                       found_multi = header_type & 0x80;
+                               }
+                               else
+                               {
+                                       if (!found_multi)
+                                               continue;
+                               }
+
+                               pci_read_config_word(bdf,
+                                                    PCI_VENDOR_ID,
+                                                    &vendor);
+                               pci_read_config_word(bdf,
+                                                    PCI_DEVICE_ID,
+                                                    &device);
+
+                               for (i=0; ids[i].vendor != 0; i++)
+                                       if (vendor == ids[i].vendor &&
+                                           device == ids[i].device)
+                                       {
+                                               if (index <= 0)
+                                                       return bdf;
+
+                                               index--;
+                                       }
+                       }
+       }
+
+       return (-1);
+}
+
+pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
+{
+       static struct pci_device_id ids[2] = {{}, {0, 0}};
+
+       ids[0].vendor = vendor;
+       ids[0].device = device;
+
+       return pci_find_devices(ids, index);
+}
+
+/*
+ *
+ */
+
+unsigned long pci_hose_phys_to_bus(struct pci_controller* hose,
+                                  unsigned long phys_addr,
+                                  unsigned long flags)
+{
+       struct pci_region *res;
+       unsigned long bus_addr;
+       int i;
+
+       if (!hose)
+       {
+               printf("pci_hose_phys_to_bus: %s\n", "invalid hose");
+               goto Done;
+       }
+
+       for (i=0; i<hose->region_count; i++)
+       {
+               res = &hose->regions[i];
+
+               if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
+                       continue;
+
+               bus_addr = phys_addr - res->phys_start + res->bus_start;
+
+               if (bus_addr >= res->bus_start &&
+                   bus_addr <  res->bus_start + res->size)
+               {
+                       return bus_addr;
+               }
+       }
+
+       printf("pci_hose_phys_to_bus: %s\n", "invalid physical address");
+
+ Done:
+       return 0;
+}
+
+unsigned long pci_hose_bus_to_phys(struct pci_controller* hose,
+                                  unsigned long bus_addr,
+                                  unsigned long flags)
+{
+       struct pci_region *res;
+       int i;
+
+       if (!hose)
+       {
+               printf("pci_hose_bus_to_phys: %s\n", "invalid hose");
+               goto Done;
+       }
+
+       for (i=0; i<hose->region_count; i++)
+       {
+               res = &hose->regions[i];
+
+               if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
+                       continue;
+
+               if (bus_addr >= res->bus_start &&
+                   bus_addr <  res->bus_start + res->size)
+               {
+                       return bus_addr - res->bus_start + res->phys_start;
+               }
+       }
+
+       printf("pci_hose_bus_to_phys: %s\n", "invalid physical address");
+
+ Done:
+       return 0;
+}
+
+/*
+ *
+ */
+
+int pci_hose_config_device(struct pci_controller *hose,
+                          pci_dev_t dev,
+                          unsigned long io,
+                          unsigned long mem,
+                          unsigned long command)
+{
+       unsigned int bar_response, bar_size, bar_value, old_command;
+       unsigned char pin;
+       int bar, found_mem64;
+
+       DEBUGF("PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx\n", io, mem, command);
+
+       pci_hose_write_config_dword(hose, dev, PCI_COMMAND, 0);
+
+       for (bar = PCI_BASE_ADDRESS_0; bar < PCI_BASE_ADDRESS_5; bar += 4)
+       {
+               pci_hose_write_config_dword(hose, dev, bar, 0xffffffff);
+               pci_hose_read_config_dword(hose, dev, bar, &bar_response);
+
+               if (!bar_response)
+                       continue;
+
+               found_mem64 = 0;
+
+               /* Check the BAR type and set our address mask */
+               if (bar_response & PCI_BASE_ADDRESS_SPACE)
+               {
+                       bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1;
+                       bar_value = io;
+
+                       io = ((io - 1) | (bar_size - 1)) + 1;
+               }
+               else
+               {
+                       if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+                            PCI_BASE_ADDRESS_MEM_TYPE_64)
+                               found_mem64 = 1;
+
+                       bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+                       bar_value = mem;
+
+                       mem = ((mem - 1) | (bar_size - 1)) + 1;
+               }
+
+               /* Write it out and update our limit */
+               pci_hose_write_config_dword(hose, dev, bar, bar_value);
+
+               if (found_mem64)
+               {
+                       bar += 4;
+                       pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
+               }
+       }
+
+       /* Configure Cache Line Size Register */
+       pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+
+       /* Configure Latency Timer */
+       pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
+
+       /* Disable interrupt line, if device says it wants to use interrupts */
+       pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);
+       if (pin != 0)
+       {
+               pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 0xff);
+       }
+
+       pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command);
+       pci_hose_write_config_dword(hose, dev, PCI_COMMAND,
+                                   (old_command & 0xffff0000) | command );
+
+       return 0;
+}
+
+/*
+ *
+ */
+
+struct pci_config_table *pci_find_config(struct pci_controller *hose,
+                                        unsigned short class,
+                                        unsigned int vendor,
+                                        unsigned int device,
+                                        unsigned int bus,
+                                        unsigned int dev,
+                                        unsigned int func)
+{
+       struct pci_config_table *table;
+
+       for (table = hose->config_table; table && table->vendor; table++)
+       {
+               if ((table->vendor == PCI_ANY_ID || table->vendor == vendor) &&
+                   (table->device == PCI_ANY_ID || table->device == device) &&
+                   (table->class  == PCI_ANY_ID || table->class  == class)  &&
+                   (table->bus    == PCI_ANY_ID || table->bus    == bus)    &&
+                   (table->dev    == PCI_ANY_ID || table->dev    == dev)    &&
+                   (table->func   == PCI_ANY_ID || table->func   == func))
+               {
+                       return table;
+               }
+       }
+
+       return NULL;
+}
+
+void pci_cfgfunc_config_device(struct pci_controller *hose,
+                              pci_dev_t dev,
+                              struct pci_config_table *entry)
+{
+       pci_hose_config_device(hose, dev, entry->priv[0], entry->priv[1], entry->priv[2]);
+}
+
+void pci_cfgfunc_do_nothing(struct pci_controller *hose,
+                           pci_dev_t dev, struct pci_config_table *entry)
+{
+}
+
+/*
+ *
+ */
+
+extern void pciauto_config_init(struct pci_controller *hose);
+extern void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
+
+int pci_hose_scan_bus(struct pci_controller *hose, int bus)
+{
+       unsigned int sub_bus, found_multi=0;
+       unsigned short vendor, device, class;
+       unsigned char header_type;
+       struct pci_config_table *cfg;
+       pci_dev_t dev;
+
+       sub_bus = bus;
+
+       for (dev =  PCI_BDF(bus,0,0);
+            dev <  PCI_BDF(bus,PCI_MAX_PCI_DEVICES-1,PCI_MAX_PCI_FUNCTIONS-1);
+            dev += PCI_BDF(0,0,1))
+       {
+#ifndef CONFIG_405GP /* don't skip host bridge on ppc405gp */
+               /* Skip our host bridge */
+               if ( dev == PCI_BDF(hose->first_busno,0,0) )
+                       continue;
+#endif
+
+               if (PCI_FUNC(dev) && !found_multi)
+                       continue;
+
+               pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
+
+               pci_hose_read_config_word(hose, dev, PCI_VENDOR_ID, &vendor);
+
+               if (vendor != 0xffff && vendor != 0x0000)
+               {
+
+                       if (!PCI_FUNC(dev))
+                               found_multi = header_type & 0x80;
+
+                       DEBUGF("PCI Scan: Found Bus %d, Device %d, Function %d\n",
+                           PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev) );
+
+                       pci_hose_read_config_word(hose, dev, PCI_DEVICE_ID, &device);
+                       pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
+
+                       cfg = pci_find_config(hose, class, vendor, device,
+                                             PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));
+                       if (cfg)
+                               cfg->config_device(hose, dev, cfg);
+#ifdef CONFIG_PCI_PNP
+                       else
+                               pciauto_config_device(hose, dev);
+#endif
+                       if (hose->fixup_irq)
+                               hose->fixup_irq(hose, dev);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+                       /* Skip our host bridge */
+                       if ( dev != PCI_BDF(hose->first_busno,0,0) ) {
+                           unsigned char int_line;
+
+                           pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_LINE,
+                                                     &int_line);
+                           printf("        %02x  %02x  %04x  %04x  %04x  %02x\n",
+                                  PCI_BUS(dev), PCI_DEV(dev), vendor, device, class,
+                                  int_line);
+                       }
+#endif
+               }
+       }
+
+       return sub_bus;
+}
+
+int pci_hose_scan(struct pci_controller *hose)
+{
+#ifdef CONFIG_PCI_PNP
+       pciauto_config_init(hose);
+#endif
+       return pci_hose_scan_bus(hose, hose->first_busno);
+}
+
+#endif /* CONFIG_PCI */
diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c
new file mode 100644 (file)
index 0000000..f665ee6
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * arch/ppc/kernel/pci_auto.c
+ *
+ * PCI autoconfiguration library
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <pci.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DEBUGF(x...) printf(x)
+#else
+#define DEBUGF(x...)
+#endif /* DEBUG */
+
+#define        PCIAUTO_IDE_MODE_MASK           0x05
+
+/*
+ *
+ */
+
+void pciauto_region_init(struct pci_region* res)
+{
+       res->bus_lower = res->bus_start;
+}
+
+void pciauto_region_align(struct pci_region *res, unsigned long size)
+{
+       res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1;
+}
+
+int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar)
+{
+       unsigned long addr;
+
+       if (!res)
+       {
+               DEBUGF("No resource");
+               goto error;
+       }
+
+       addr = ((res->bus_lower - 1) | (size - 1)) + 1;
+
+       if (addr - res->bus_start + size > res->size)
+       {
+               DEBUGF("No room in resource");
+               goto error;
+       }
+
+       res->bus_lower = addr + size;
+
+       DEBUGF("address=0x%lx", addr);
+
+       *bar = addr;
+       return 0;
+
+ error:
+       *bar = 0xffffffff;
+       return -1;
+}
+
+/*
+ *
+ */
+
+void pciauto_setup_device(struct pci_controller *hose,
+                         pci_dev_t dev, int bars_num,
+                         struct pci_region *mem,
+                         struct pci_region *io)
+{
+       unsigned int bar_value, bar_response, bar_size;
+       unsigned int cmdstat = 0;
+       struct pci_region *bar_res;
+       int bar, bar_nr = 0;
+       int found_mem64 = 0;
+
+       pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat);
+       cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER;
+
+       for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_0 + (bars_num*4); bar += 4)
+       {
+               /* Tickle the BAR and get the response */
+               pci_hose_write_config_dword(hose, dev, bar, 0xffffffff);
+               pci_hose_read_config_dword(hose, dev, bar, &bar_response);
+
+               /* If BAR is not implemented go to the next BAR */
+               if (!bar_response)
+                       continue;
+
+               found_mem64 = 0;
+
+               /* Check the BAR type and set our address mask */
+               if (bar_response & PCI_BASE_ADDRESS_SPACE)
+               {
+                       bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1;
+                       bar_res = io;
+
+                       DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%x, ", bar_nr, bar_size);
+               }
+               else
+               {
+                       if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+                            PCI_BASE_ADDRESS_MEM_TYPE_64)
+                               found_mem64 = 1;
+
+                       bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+                       bar_res = mem;
+
+                       DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size);
+               }
+
+               if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0)
+               {
+                       /* Write it out and update our limit */
+                       pci_hose_write_config_dword(hose, dev, bar, bar_value);
+
+                       /*
+                        * If we are a 64-bit decoder then increment to the
+                        * upper 32 bits of the bar and force it to locate
+                        * in the lower 4GB of memory.
+                        */
+                       if (found_mem64)
+                       {
+                               bar += 4;
+                               pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
+                       }
+
+                       cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ?
+                               PCI_COMMAND_IO : PCI_COMMAND_MEMORY;
+               }
+
+               DEBUGF("\n");
+
+               bar_nr++;
+       }
+
+       pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat);
+       pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+       pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
+}
+
+static void pciauto_prescan_setup_bridge(struct pci_controller *hose,
+                                        pci_dev_t dev, int sub_bus)
+{
+       struct pci_region *pci_mem = hose->pci_mem;
+       struct pci_region *pci_io = hose->pci_io;
+       unsigned int cmdstat;
+
+       pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat);
+
+       /* Configure bus number registers */
+       pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev));
+       pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus + 1);
+       pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff);
+
+       if (pci_mem)
+       {
+               /* Round memory allocator to 1MB boundary */
+               pciauto_region_align(pci_mem, 0x100000);
+
+               /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+               pci_hose_write_config_word(hose, dev, PCI_MEMORY_BASE,
+                                       (pci_mem->bus_lower & 0xfff00000) >> 16);
+
+               cmdstat |= PCI_COMMAND_MEMORY;
+       }
+
+       if (pci_io)
+       {
+               /* Round I/O allocator to 4KB boundary */
+               pciauto_region_align(pci_io, 0x1000);
+
+               pci_hose_write_config_byte(hose, dev, PCI_IO_BASE,
+                                       (pci_io->bus_lower & 0x0000f000) >> 8);
+               pci_hose_write_config_word(hose, dev, PCI_IO_BASE_UPPER16,
+                                       (pci_io->bus_lower & 0xffff0000) >> 16);
+
+               cmdstat |= PCI_COMMAND_IO;
+       }
+
+       /* We don't support prefetchable memory for now, so disable */
+       pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000);
+       pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x1000);
+
+       /* Enable memory and I/O accesses, enable bus master */
+       pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat | PCI_COMMAND_MASTER);
+}
+
+static void pciauto_postscan_setup_bridge(struct pci_controller *hose,
+                                         pci_dev_t dev, int sub_bus)
+{
+       struct pci_region *pci_mem = hose->pci_mem;
+       struct pci_region *pci_io = hose->pci_io;
+
+       /* Configure bus number registers */
+       pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus);
+
+       if (pci_mem)
+       {
+               /* Round memory allocator to 1MB boundary */
+               pciauto_region_align(pci_mem, 0x100000);
+
+               pci_hose_write_config_word(hose, dev, PCI_MEMORY_LIMIT,
+                                       (pci_mem->bus_lower-1) >> 16);
+       }
+
+       if (pci_io)
+       {
+               /* Round I/O allocator to 4KB boundary */
+               pciauto_region_align(pci_io, 0x1000);
+
+               pci_hose_write_config_byte(hose, dev, PCI_IO_LIMIT,
+                                       ((pci_io->bus_lower-1) & 0x0000f000) >> 8);
+               pci_hose_write_config_word(hose, dev, PCI_IO_LIMIT_UPPER16,
+                                       ((pci_io->bus_lower-1) & 0xffff0000) >> 16);
+       }
+}
+
+/*
+ *
+ */
+
+void pciauto_config_init(struct pci_controller *hose)
+{
+       int i;
+
+       hose->pci_io = hose->pci_mem = NULL;
+
+       for (i=0; i<hose->region_count; i++)
+       {
+               switch(hose->regions[i].flags)
+               {
+               case PCI_REGION_IO:
+                       if (!hose->pci_io ||
+                           hose->pci_io->size < hose->regions[i].size)
+                               hose->pci_io = hose->regions + i;
+                       break;
+               case PCI_REGION_MEM:
+                       if (!hose->pci_mem ||
+                           hose->pci_mem->size < hose->regions[i].size)
+                               hose->pci_mem = hose->regions + i;
+                       break;
+               }
+       }
+
+
+
+       if (hose->pci_mem)
+       {
+               pciauto_region_init(hose->pci_mem);
+
+               DEBUGF("PCI Autoconfig: Memory region: [%lx-%lx]\n",
+                   hose->pci_mem->bus_start,
+                   hose->pci_mem->bus_start + hose->pci_mem->size - 1);
+       }
+
+       if (hose->pci_io)
+       {
+               pciauto_region_init(hose->pci_io);
+
+               DEBUGF("PCI Autoconfig: I/O region: [%lx-%lx]\n",
+                   hose->pci_io->bus_start,
+                   hose->pci_io->bus_start + hose->pci_io->size - 1);
+       }
+}
+
+void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
+{
+       unsigned int sub_bus;
+       unsigned short class;
+       unsigned char prg_iface;
+
+       pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
+
+       switch(class)
+       {
+       case PCI_CLASS_BRIDGE_PCI:
+               pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_io);
+
+               DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev));
+
+               pciauto_prescan_setup_bridge(hose, dev, PCI_BUS(dev));
+
+               sub_bus = pci_hose_scan_bus(hose, PCI_BUS(dev)+1);
+
+               pciauto_postscan_setup_bridge(hose, dev, sub_bus);
+               break;
+
+       case PCI_CLASS_STORAGE_IDE:
+               pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prg_iface);
+               if (!(prg_iface & PCIAUTO_IDE_MODE_MASK))
+                       {
+                               DEBUGF("PCI Autoconfig: Skipping legacy mode IDE controller\n");
+                               return;
+                       }
+
+               pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
+               break;
+
+       default:
+               pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
+               break;
+       }
+}
+
+#endif /* CONFIG_PCI */
diff --git a/drivers/pcnet.c b/drivers/pcnet.c
new file mode 100644 (file)
index 0000000..f69cd2c
--- /dev/null
@@ -0,0 +1,526 @@
+/*
+ * (C) Copyright 2002 Wolfgang Grandegger, wg@denx.de.
+ *
+ * This driver for AMD PCnet network controllers is derived from the
+ * Linux driver pcnet32.c written 1996-1999 by Thomas Bogendoerfer.
+ *
+ * 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>
+
+#if 0
+#define        PCNET_DEBUG_LEVEL       0 /* 0=off, 1=init, 2=rx/tx */
+#endif
+
+#if PCNET_DEBUG_LEVEL > 0
+#define        DEBUG1(fmt,args...)     printf (fmt ,##args)
+#if PCNET_DEBUG_LEVEL > 1
+#define        DEBUG2(fmt,args...)     printf (fmt ,##args)
+#else
+#define DEBUG2(fmt,args...)
+#endif
+#else
+#define DEBUG1(fmt,args...)
+#define DEBUG2(fmt,args...)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
+    && defined(CONFIG_PCNET)
+
+#if !defined(CONF_PCNET_79C973) && defined(CONF_PCNET_79C975)
+#error "Macro for PCnet chip version is not defined!"
+#endif
+
+/*
+ * Set the number of Tx and Rx buffers, using Log_2(# buffers).
+ * Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
+ * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
+ */
+#define PCNET_LOG_TX_BUFFERS   0
+#define PCNET_LOG_RX_BUFFERS   2
+
+#define TX_RING_SIZE           (1 << (PCNET_LOG_TX_BUFFERS))
+#define TX_RING_LEN_BITS       ((PCNET_LOG_TX_BUFFERS) << 12)
+
+#define RX_RING_SIZE           (1 << (PCNET_LOG_RX_BUFFERS))
+#define RX_RING_LEN_BITS       ((PCNET_LOG_RX_BUFFERS) << 4)
+
+#define PKT_BUF_SZ             1544
+
+/* The PCNET Rx and Tx ring descriptors. */
+struct pcnet_rx_head {
+    u32 base;
+    s16 buf_length;
+    s16 status;
+    u32 msg_length;
+    u32 reserved;
+};
+
+struct pcnet_tx_head {
+    u32 base;
+    s16 length;
+    s16 status;
+    u32 misc;
+    u32 reserved;
+};
+
+/* The PCNET 32-Bit initialization block, described in databook. */
+struct pcnet_init_block {
+    u16 mode;
+    u16 tlen_rlen;
+    u8 phys_addr[6];
+    u16 reserved;
+    u32 filter[2];
+    /* Receive and transmit ring base, along with extra bits. */
+    u32 rx_ring;
+    u32 tx_ring;
+    u32 reserved2;
+};
+
+typedef struct pcnet_priv {
+    struct pcnet_rx_head    rx_ring[RX_RING_SIZE];
+    struct pcnet_tx_head    tx_ring[TX_RING_SIZE];
+    struct pcnet_init_block init_block;
+    /* Receive Buffer space */
+    unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4];
+    int cur_rx;
+    int cur_tx;
+} pcnet_priv_t;
+
+static pcnet_priv_t *lp;
+
+/* Offsets from base I/O address for WIO mode */
+#define PCNET_RDP              0x10
+#define PCNET_RAP              0x12
+#define PCNET_RESET            0x14
+#define PCNET_BDP              0x16
+
+static u16 pcnet_read_csr (struct eth_device *dev, int index)
+{
+    outw (index, dev->iobase+PCNET_RAP);
+    return inw (dev->iobase+PCNET_RDP);
+}
+
+static void pcnet_write_csr (struct eth_device *dev, int index, u16 val)
+{
+    outw (index, dev->iobase+PCNET_RAP);
+    outw (val, dev->iobase+PCNET_RDP);
+}
+
+static u16 pcnet_read_bcr (struct eth_device *dev, int index)
+{
+    outw (index, dev->iobase+PCNET_RAP);
+    return inw (dev->iobase+PCNET_BDP);
+}
+
+static void pcnet_write_bcr (struct eth_device *dev, int index, u16 val)
+{
+    outw (index, dev->iobase+PCNET_RAP);
+    outw (val, dev->iobase+PCNET_BDP);
+}
+
+static void pcnet_reset (struct eth_device *dev)
+{
+    inw (dev->iobase+PCNET_RESET);
+}
+
+static int pcnet_check (struct eth_device *dev)
+{
+    outw (88, dev->iobase+PCNET_RAP);
+    return (inw (dev->iobase+PCNET_RAP) == 88);
+}
+
+static int  pcnet_init( struct eth_device* dev, bd_t *bis);
+static int  pcnet_send (struct eth_device* dev, volatile void *packet,
+                       int length);
+static int  pcnet_recv (struct eth_device* dev);
+static void pcnet_halt (struct eth_device* dev);
+static int  pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_num);
+
+#define PCI_TO_MEM(d,a) pci_phys_to_mem((pci_dev_t)d->priv, (u_long)(a))
+#define PCI_TO_MEM_LE(d,a) (u32)(cpu_to_le32(PCI_TO_MEM(d,a)))
+
+static struct pci_device_id supported[] = {
+       { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE },
+       { }
+};
+
+
+int pcnet_initialize(bd_t *bis)
+{
+    pci_dev_t devbusfn;
+    struct eth_device* dev;
+    u16 command, status;
+    int dev_nr = 0;
+
+    DEBUG1("\npcnet_initialize...\n");
+
+    for (dev_nr = 0; ; dev_nr++) {
+
+       /*
+        * Find the PCnet PCI device(s).
+        */
+       if ((devbusfn = pci_find_devices(supported, dev_nr)) < 0) {
+           break;
+       }
+
+       /*
+        * Allocate and pre-fill the device structure.
+        */
+       dev = (struct eth_device*) malloc(sizeof *dev);
+       dev->priv = (void *)devbusfn;
+       sprintf(dev->name, "pcnet#%d", dev_nr);
+
+       /*
+        * Setup the PCI device.
+        */
+       pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &dev->iobase);
+       dev->iobase &= ~0xf;
+
+       DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ",
+              dev->name, devbusfn, dev->iobase);
+
+       command = PCI_COMMAND_IO | PCI_COMMAND_MASTER;
+       pci_write_config_word(devbusfn, PCI_COMMAND, command);
+       pci_read_config_word(devbusfn, PCI_COMMAND, &status);
+       if ((status & command) != command) {
+           printf("%s: Couldn't enable IO access or Bus Mastering\n",
+                  dev->name);
+           free(dev);
+           continue;
+       }
+
+       pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40);
+
+       /*
+        * Probe the PCnet chip.
+        */
+       if (pcnet_probe(dev, bis, dev_nr) < 0) {
+           free(dev);
+           continue;
+       }
+
+       /*
+        * Setup device structure and register the driver.
+        */
+       dev->init   = pcnet_init;
+       dev->halt   = pcnet_halt;
+       dev->send   = pcnet_send;
+       dev->recv   = pcnet_recv;
+
+       eth_register(dev);
+    }
+
+    udelay(10 * 1000);
+
+    return dev_nr;
+}
+
+static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_nr)
+{
+    int chip_version;
+    char *chipname;
+#ifdef PCNET_HAS_PROM
+    int i;
+#endif
+
+    /* Reset the PCnet controller */
+    pcnet_reset(dev);
+
+    /* Check if register access is working */
+    if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) {
+       printf("%s: CSR register access check failed\n", dev->name);
+       return -1;
+    }
+
+    /* Identify the chip */
+    chip_version = pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev,89) << 16);
+    if ((chip_version & 0xfff) != 0x003)
+       return -1;
+    chip_version = (chip_version >> 12) & 0xffff;
+    switch (chip_version) {
+#ifdef CONFIG_PCNET_79C973
+    case 0x2625:
+       chipname = "PCnet/FAST III 79C973"; /* PCI */
+       break;
+#endif
+#ifdef CONFIG_PCNET_79C975
+    case 0x2627:
+       chipname = "PCnet/FAST III 79C975"; /* PCI */
+       break;
+#endif
+    default:
+       printf("%s: PCnet version %#x not supported\n",
+              dev->name, chip_version);
+       return -1;
+    }
+
+    DEBUG1("AMD %s\n", chipname);
+
+#ifdef PCNET_HAS_PROM
+    /*
+     * In most chips, after a chip reset, the ethernet address is read from
+     * the station address PROM at the base address and programmed into the
+     * "Physical Address Registers" CSR12-14.
+     */
+    for (i = 0; i < 3; i++) {
+       unsigned int val;
+       val = pcnet_read_csr(dev, i+12) & 0x0ffff;
+       /* There may be endianness issues here. */
+       dev->dev_addr[2*i] = val & 0x0ff;
+       dev->dev_addr[2*i+1] = (val >> 8) & 0x0ff;
+    }
+#endif /* PCNET_HAS_PROM */
+
+    return 0;
+}
+
+static int pcnet_init(struct eth_device* dev, bd_t *bis)
+{
+    int i, val;
+    u32 addr;
+
+    DEBUG1("%s: pcnet_init...\n", dev->name);
+
+    /* Switch pcnet to 32bit mode */
+    pcnet_write_bcr (dev, 20, 2);
+
+#ifdef CONFIG_PN62
+    /* Setup LED registers */
+    val = pcnet_read_bcr (dev, 2) | 0x1000;
+    pcnet_write_bcr (dev, 2, val);    /* enable LEDPE */
+    pcnet_write_bcr (dev, 4, 0x5080); /* 100MBit */
+    pcnet_write_bcr (dev, 5, 0x40c0); /* LNKSE */
+    pcnet_write_bcr (dev, 6, 0x4090); /* TX Activity */
+    pcnet_write_bcr (dev, 7, 0x4084); /* RX Activity */
+#endif
+
+    /* Set/reset autoselect bit */
+    val = pcnet_read_bcr (dev, 2) & ~2;
+    val |= 2;
+    pcnet_write_bcr (dev, 2, val);
+
+    /* Enable auto negotiate, setup, disable fd */
+    val = pcnet_read_bcr(dev, 32) & ~0x98;
+    val |= 0x20;
+    pcnet_write_bcr(dev, 32, val);
+
+    /*
+     * We only maintain one structure because the drivers will never
+     * be used concurrently. In 32bit mode the RX and TX ring entries
+     * must be aligned on 16-byte boundaries.
+     */
+    if (lp == NULL) {
+       addr = (u32)malloc(sizeof(pcnet_priv_t) + 0x10);
+       addr = (addr + 0xf) & ~0xf;
+       lp = (pcnet_priv_t *)addr;
+    }
+
+    lp->init_block.mode = cpu_to_le16(0x0000);
+    lp->init_block.filter[0] = 0x00000000;
+    lp->init_block.filter[1] = 0x00000000;
+
+    /*
+     * Initialize the Rx ring.
+     */
+    lp->cur_rx = 0;
+    for (i = 0; i < RX_RING_SIZE; i++) {
+       lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]);
+       lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ);
+       lp->rx_ring[i].status = cpu_to_le16(0x8000);
+       DEBUG1("Rx%d: base=0x%x buf_length=0x%x status=0x%x\n",
+              i, lp->rx_ring[i].base, lp->rx_ring[i].buf_length,
+              lp->rx_ring[i].status);
+    }
+
+    /*
+     * Initialize the Tx ring. The Tx buffer address is filled in as
+     * needed, but we do need to clear the upper ownership bit.
+     */
+    lp->cur_tx = 0;
+    for (i = 0; i < TX_RING_SIZE; i++) {
+       lp->tx_ring[i].base = 0;
+       lp->tx_ring[i].status = 0;
+    }
+
+    /*
+     * Setup Init Block.
+     */
+    DEBUG1("Init block at 0x%p: MAC", &lp->init_block);
+
+    for (i = 0; i < 6; i++) {
+       lp->init_block.phys_addr[i] = dev->enetaddr[i];
+       DEBUG1(" %02x", lp->init_block.phys_addr[i]);
+    }
+
+    lp->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS |
+                                          RX_RING_LEN_BITS);
+    lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring);
+    lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring);
+
+    DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n",
+          lp->init_block.tlen_rlen,
+          lp->init_block.rx_ring, lp->init_block.tx_ring);
+
+    /*
+     * Tell the controller where the Init Block is located.
+     */
+    addr = PCI_TO_MEM(dev, &lp->init_block);
+    pcnet_write_csr(dev, 1, addr & 0xffff);
+    pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff);
+
+    pcnet_write_csr (dev, 4, 0x0915);
+    pcnet_write_csr (dev, 0, 0x0001); /* start */
+
+    /* Wait for Init Done bit */
+    for (i = 10000; i > 0; i--) {
+       if (pcnet_read_csr (dev, 0) & 0x0100)
+           break;
+       udelay(10);
+    }
+    if (i <= 0) {
+       printf("%s: TIMEOUT: controller init failed\n", dev->name);
+       pcnet_reset (dev);
+       return 0;
+    }
+
+    /*
+     * Finally start network controller operation.
+     */
+    pcnet_write_csr (dev, 0, 0x0002);
+
+    return 1;
+}
+
+static int pcnet_send(struct eth_device* dev, volatile void *packet, int pkt_len)
+{
+    int i, status;
+    struct pcnet_tx_head *entry = &lp->tx_ring[lp->cur_tx];
+
+    DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len, packet);
+
+    /* Wait for completion by testing the OWN bit */
+    for (i = 1000; i > 0; i--) {
+       status = le16_to_cpu(entry->status);
+       if ((status & 0x8000) == 0)
+           break;
+       udelay(100);
+       DEBUG2(".");
+    }
+    if (i <= 0) {
+       printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n",
+              dev->name, lp->cur_tx, status);
+       pkt_len = 0;
+       goto failure;
+    }
+
+    /*
+     * Setup Tx ring. Caution: the write order is important here,
+     * set the status with the "ownership" bits last.
+     */
+    status = 0x8300;
+    entry->length = le16_to_cpu(-pkt_len);
+    entry->misc   = 0x00000000;
+    entry->base   = PCI_TO_MEM_LE(dev, packet);
+    entry->status = le16_to_cpu(status);
+
+    /* Trigger an immediate send poll. */
+    pcnet_write_csr (dev, 0, 0x0008);
+
+ failure:
+    if (++lp->cur_tx >= TX_RING_SIZE)
+       lp->cur_tx = 0;
+
+    DEBUG2("done\n");
+    return pkt_len;
+}
+
+static int pcnet_recv(struct eth_device* dev)
+{
+    struct pcnet_rx_head *entry;
+    int pkt_len = 0;
+    u16 status;
+
+    while (1) {
+       entry = &lp->rx_ring[lp->cur_rx];
+       /*
+        * If we own the next entry, it's a new packet. Send it up.
+        */
+       if (((status = le16_to_cpu(entry->status)) & 0x8000) != 0) {
+           break;
+       }
+       status >>= 8;
+
+       if (status != 0x03) {   /* There was an error. */
+
+           printf("%s: Rx%d", dev->name, lp->cur_rx);
+           DEBUG1(" (status=0x%x)", status);
+           if (status & 0x20) printf(" Frame");
+           if (status & 0x10) printf(" Overflow");
+           if (status & 0x08) printf(" CRC");
+           if (status & 0x04) printf(" Fifo");
+           printf(" Error\n");
+           entry->status &= le16_to_cpu(0x03ff);
+
+       } else {
+
+           pkt_len = (le32_to_cpu(entry->msg_length) & 0xfff) - 4;
+           if (pkt_len < 60) {
+               printf("%s: Rx%d: invalid packet length %d\n",
+                      dev->name, lp->cur_rx, pkt_len);
+           } else {
+               NetReceive(lp->rx_buf[lp->cur_rx], pkt_len);
+               DEBUG2("Rx%d: %d bytes from 0x%p\n",
+                      lp->cur_rx, pkt_len, lp->rx_buf[lp->cur_rx]);
+           }
+       }
+       entry->status |= cpu_to_le16(0x8000);
+
+       if (++lp->cur_rx >= RX_RING_SIZE)
+           lp->cur_rx = 0;
+    }
+    return pkt_len;
+}
+
+static void pcnet_halt(struct eth_device* dev)
+{
+    int i;
+
+    DEBUG1("%s: pcnet_halt...\n", dev->name);
+
+    /* Reset the PCnet controller */
+    pcnet_reset (dev);
+
+    /* Wait for Stop bit */
+    for (i = 1000; i > 0; i--) {
+       if (pcnet_read_csr (dev, 0) & 0x4)
+           break;
+       udelay(10);
+    }
+    if (i <= 0) {
+       printf("%s: TIMEOUT: controller reset failed\n", dev->name);
+    }
+}
+
+#endif
diff --git a/drivers/smiLynxEM.c b/drivers/smiLynxEM.c
new file mode 100644 (file)
index 0000000..75d5a31
--- /dev/null
@@ -0,0 +1,1059 @@
+/*
+ * (C) Copyright 1997-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
+ */
+
+/*
+ * smiLynxEM.c
+ *
+ * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
+ *
+ * modification history
+ * --------------------
+ * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
+ *
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_VIDEO_SMI_LYNXEM)
+
+#include <pci.h>
+#include <video_fb.h>
+
+/*
+ * Export Graphic Device
+ */
+GraphicDevice smi;
+
+/*
+ * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
+ */
+#define VIDEO_MEM_SIZE  0x400000
+
+/*
+ * Supported video modes for SMI Lynx E/EM/EM+
+ */
+#define VIDEO_MODES             7
+#define DUAL_800_600            0   /* SMI710:VGA1:75Hz     (pitch=1600) */
+                                    /*        VGA2:60/120Hz (pitch=1600) */
+                                    /* SMI810:VGA1:75Hz     (pitch=1600) */
+                                    /*        VGA2:75Hz     (pitch=1600) */
+#define DUAL_1024_768           1   /* VGA1:75Hz VGA2:73Hz (pitch=2048)  */
+#define SINGLE_800_600          2   /* VGA1:75Hz (pitch=800)             */
+#define SINGLE_1024_768         3   /* VGA1:75Hz (pitch=1024)            */
+#define SINGLE_1280_1024        4   /* VGA1:75Hz (pitch=1280)            */
+#define TV_MODE_CCIR            5   /* VGA1:50Hz (h=720;v=576;pitch=720) */
+#define TV_MODE_EIA             6   /* VGA1:60Hz (h=720;v=484;pitch=720) */
+
+
+/*
+ * ISA mapped regs
+ */
+#define SMI_INDX_C4             (pGD->isaBase + 0x03c4)    /* index reg */
+#define SMI_DATA_C5             (pGD->isaBase + 0x03c5)    /* data reg */
+#define SMI_INDX_D4             (pGD->isaBase + 0x03d4)    /* index reg */
+#define SMI_DATA_D5             (pGD->isaBase + 0x03d5)    /* data reg */
+#define SMI_INDX_CE             (pGD->isaBase + 0x03ce)    /* index reg */
+#define SMI_DATA_CF             (pGD->isaBase + 0x03cf)    /* data reg */
+#define SMI_LOCK_REG            (pGD->isaBase + 0x03c3)    /* unlock/lock ext crt reg */
+#define SMI_MISC_REG            (pGD->isaBase + 0x03c2)    /* misc reg */
+#define SMI_LUT_MASK            (pGD->isaBase + 0x03c6)    /* lut mask reg */
+#define SMI_LUT_START           (pGD->isaBase + 0x03c8)    /* lut start index */
+#define SMI_LUT_RGB             (pGD->isaBase + 0x03c9)    /* lut colors auto incr.*/
+
+
+/*
+ * Video processor control
+*/
+typedef struct {
+    unsigned int   control;
+    unsigned int   colorKey;
+    unsigned int   colorKeyMask;
+    unsigned int   start;
+    unsigned short offset;
+    unsigned short width;
+    unsigned int   fifoPrio;
+    unsigned int   fifoERL;
+    unsigned int   YUVtoRGB;
+} SmiVideoProc;
+
+/*
+ * Video window control
+ */
+typedef struct {
+    unsigned short top;
+    unsigned short left;
+    unsigned short bottom;
+    unsigned short right;
+    unsigned int   srcStart;
+    unsigned short width;
+    unsigned short offset;
+    unsigned char  hStretch;
+    unsigned char  vStretch;
+} SmiVideoWin;
+
+/*
+ * Capture port control
+ */
+typedef struct {
+    unsigned int   control;
+    unsigned short topClip;
+    unsigned short leftClip;
+    unsigned short srcHeight;
+    unsigned short srcWidth;
+    unsigned int   srcBufStart1;
+    unsigned int   srcBufStart2;
+    unsigned short srcOffset;
+    unsigned short fifoControl;
+} SmiCapturePort;
+
+
+
+/*
+ * Register values for common video modes
+ */
+static char SMI_SCR[22] = {
+    /* all modes */
+    0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0x00, 0x15, 0x90,
+    0x16, 0x10, 0x17, 0x2c, 0x18, 0xb1, 0x19, 0x20, 0x1a, 0x01
+};
+
+static char SMI_EXT_CRT[VIDEO_MODES][24] = {
+    { /* DUAL_800_600_8 */
+    0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+    0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+    },
+    { /* DUAL_1024_768_8 */
+    0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+    0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+    },
+    { /* SINGLE_800_600_8 */
+    0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+    0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+    },
+    { /* SINGLE_1024_768_8 */
+    0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+    0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+    },
+    { /* SINGLE_1280_1024_8 */
+    0x30, 0x09, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+    0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+    },
+    { /* TV_MODE_CCIR */
+    0x30, 0x80, 0x31, 0x2b, 0x32, 0x06, 0x33, 0x01, 0x34, 0x26, 0x35, 0x88,
+    0x36, 0x02, 0x38, 0x11, 0x39, 0x11, 0x3a, 0x20, 0x3e, 0xa3, 0x3f, 0x00
+    },
+    { /* TV_MODE_EIA */
+    0x30, 0x80, 0x31, 0x2b, 0x32, 0x06, 0x33, 0x00, 0x34, 0xf8, 0x35, 0x88,
+    0x36, 0x02, 0x38, 0x11, 0x39, 0x11, 0x3a, 0x20, 0x3e, 0xa3, 0x3f, 0x00
+    },
+};
+
+static char SMI_CRTCR[VIDEO_MODES][50] = {
+    { /* DUAL_800_600_8 */
+    0x00, 0x7f, 0x01, 0x63, 0x02, 0x63, 0x03, 0x00, 0x04, 0x68, 0x05, 0x12,
+    0x06, 0x6f, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+    0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x59, 0x11, 0x2c,
+    0x12, 0x57, 0x13, 0x64, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
+    0x18, 0xff
+    },
+    { /* DUAL_1024_768_8 */
+    0x00, 0x9f, 0x01, 0x7f, 0x02, 0x7f, 0x03, 0x00, 0x04, 0x82, 0x05, 0x0e,
+    0x06, 0x1e, 0x07, 0xf5, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+    0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x24,
+    0x12, 0xff, 0x13, 0x80, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3,
+    0x18, 0xff
+    },
+    { /* SINGLE_800_600_8 */
+    0x00, 0x7f, 0x01, 0x63, 0x02, 0x63, 0x03, 0x00, 0x04, 0x68, 0x05, 0x12,
+    0x06, 0x6f, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+    0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x59, 0x11, 0x2c,
+    0x12, 0x57, 0x13, 0x32, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
+    0x18, 0xff
+    },
+    { /* SINGLE_1024_768_8 */
+    0x00, 0x9f, 0x01, 0x7f, 0x02, 0x7f, 0x03, 0x00, 0x04, 0x82, 0x05, 0x0e,
+    0x06, 0x1e, 0x07, 0xf5, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+    0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x24,
+    0x12, 0xff, 0x13, 0x40, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3,
+    0x18, 0xff
+    },
+    { /* SINGLE_1280_1024_8 */
+    0x00, 0xce, 0x01, 0x9f, 0x02, 0x9f, 0x03, 0x00, 0x04, 0xa2, 0x05, 0x12,
+    0x06, 0x2a, 0x07, 0x5a, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+    0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x23,
+    0x12, 0xff, 0x13, 0x50, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3,
+    0x18, 0xff
+    },
+    { /* TV_MODE_CCIR */
+    0x00, 0x00, 0x01, 0x59, 0x02, 0x63, 0x03, 0x00, 0x04, 0x69, 0x05, 0x10,
+    0x06, 0x72, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+    0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x58, 0x11, 0x2c,
+    0x12, 0x57, 0x13, 0x2d, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
+    0x18, 0xff
+    },
+    { /* TV_MODE_EIA */
+    0x00, 0x00, 0x01, 0x59, 0x02, 0x63, 0x03, 0x00, 0x04, 0x69, 0x05, 0x10,
+    0x06, 0x72, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+    0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x58, 0x11, 0x2c,
+    0x12, 0x57, 0x13, 0x2d, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
+    0x18, 0xff
+    },
+};
+
+static char SMI_SEQR[10] = {
+    0x00, 0x03, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e
+};
+
+static char SMI_PCR[VIDEO_MODES][8] = {
+    { /* DUAL_800_600_8 */
+    0x20, 0x04, 0x21, 0x20, 0x22, 0x00, 0x23, 0x00
+    },
+    { /* DUAL_1024_768_8 */
+    0x20, 0x04, 0x21, 0x20, 0x22, 0x00, 0x23, 0x00
+    },
+    { /* SINGLE_800_600_8 */
+    0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+    },
+    { /* SINGLE_1024_768_8 */
+    0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+    },
+    { /* SINGLE_1280_1024_8 */
+    0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+    },
+    { /* TV_MODE_CCIR */
+    0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+    },
+    { /* TV_MODE_EIA */
+    0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+    },
+};
+
+static char SMI_MCR[VIDEO_MODES][6] = {
+    { /* DUAL_800_600_8 */
+    0x60, 0x01, 0x61, 0x00, 0x62, 0x7a
+    },
+    { /* DUAL_1024_768_8 */
+    0x60, 0x01, 0x61, 0x00, 0x62, 0x7a
+    },
+    { /* SINGLE_800_600_8 */
+    0x60, 0x00, 0x61, 0x00, 0x62, 0x34
+    },
+    { /* SINGLE_1024_768_8 */
+    0x60, 0x00, 0x61, 0x00, 0x62, 0xfe
+    },
+    { /* SINGLE_1280_1024_8 */
+    0x60, 0x00, 0x61, 0x00, 0x62, 0xfe
+    },
+    { /* TV_MODE_CCIR */
+    0x60, 0x00, 0x61, 0x00, 0x62, 0x34
+    },
+    { /* TV_MODE_EIA */
+    0x60, 0x00, 0x61, 0x00, 0x62, 0x34
+    },
+};
+
+static char SMI_CCR[VIDEO_MODES][18] = {
+    { /* DUAL_800_600_8 */
+    0x65, 0x34, 0x68, 0x50, 0x69, 0x05, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
+    0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
+    },
+    { /* DUAL_1024_768_8 */
+    0x65, 0x00, 0x68, 0x50, 0x69, 0x06, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x0b,
+    0x6d, 0x02, 0x6e, 0x0b, 0x6f, 0x02
+    },
+    { /* SINGLE_800_600_8 */
+    0x65, 0x34, 0x68, 0x40, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
+    0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
+    },
+    { /* SINGLE_1024_768_8 */
+    0x65, 0x00, 0x68, 0x50, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x0b,
+    0x6d, 0x02, 0x6e, 0x0b, 0x6f, 0x02
+    },
+    { /* SINGLE_1280_1024_8 */
+    0x65, 0x00, 0x68, 0x50, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0xd9,
+    0x6d, 0x17, 0x6e, 0xd9, 0x6f, 0x17
+    },
+    { /* TV_MODE_CCIR */
+    0x65, 0x07, 0x68, 0xc0, 0x69, 0x81, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
+    0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
+    },
+    { /* TV_MODE_EIA */
+    0x65, 0x07, 0x68, 0xc0, 0x69, 0x81, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
+    0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
+    },
+};
+
+static char SMI_SHVGA[VIDEO_MODES][24] = {
+    { /* DUAL_800_600_8 */
+    0x40, 0x7f, 0x41, 0x63, 0x42, 0x00, 0x43, 0x68, 0x44, 0x12, 0x45, 0x6f,
+    0x46, 0x57, 0x47, 0x00, 0x48, 0x59, 0x49, 0x0c, 0x4a, 0xa0, 0x4b, 0x20,
+    },
+    { /* DUAL_1024_768_8 */
+    0x40, 0x9f, 0x41, 0x7f, 0x42, 0x00, 0x43, 0x82, 0x44, 0x0e, 0x45, 0x1e,
+    0x46, 0xff, 0x47, 0x00, 0x48, 0x00, 0x49, 0x03, 0x4a, 0xe5, 0x4b, 0x20,
+    },
+    { /* SINGLE_800_600_8 */
+    0x40, 0x7f, 0x41, 0x63, 0x42, 0x00, 0x43, 0x68, 0x44, 0x12, 0x45, 0x6f,
+    0x46, 0x57, 0x47, 0x00, 0x48, 0x59, 0x49, 0x0c, 0x4a, 0xa0, 0x4b, 0x20,
+    },
+    { /* SINGLE_1024_768_8 */
+    0x40, 0x9f, 0x41, 0x7f, 0x42, 0x00, 0x43, 0x82, 0x44, 0x0e, 0x45, 0x1e,
+    0x46, 0xff, 0x47, 0x00, 0x48, 0x01, 0x49, 0x04, 0x4a, 0xa5, 0x4b, 0x20,
+    },
+    { /* SINGLE_1280_1024_8 */
+    0x40, 0xce, 0x41, 0x9f, 0x42, 0x00, 0x43, 0xa2, 0x44, 0x12, 0x45, 0x2a,
+    0x46, 0xff, 0x47, 0x00, 0x48, 0x01, 0x49, 0x03, 0x4a, 0x4a, 0x4b, 0x20,
+    },
+    { /* TV_MODE_CCIR */
+    0x40, 0x6d, 0x41, 0x59, 0x42, 0x00, 0x43, 0x60, 0x44, 0x09, 0x45, 0x38,
+    0x46, 0x25, 0x47, 0x05, 0x48, 0x2a, 0x49, 0x00, 0x4a, 0x4d, 0x4b, 0x00,
+    },
+    { /* TV_MODE_EIA */
+    0x40, 0x6d, 0x41, 0x59, 0x42, 0x00, 0x43, 0x60, 0x44, 0x09, 0x45, 0x06,
+    0x46, 0xf7, 0x47, 0x05, 0x48, 0xfa, 0x49, 0x00, 0x4a, 0x41, 0x4b, 0x00,
+    },
+};
+
+
+static char SMI_GPR[VIDEO_MODES][12] = {
+    { /* DUAL_800_600_8 */
+    0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+    },
+    { /* DUAL_1024_768_8 */
+    0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+    },
+    { /* SINGLE_800_600_8 */
+    0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+    },
+    { /* SINGLE_1024_768_8 */
+    0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+    },
+    { /* SINGLE_1280_1024_8 */
+    0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+    },
+    { /* TV_MODE_CCIR */
+    0x70, 0x82, 0x71, 0x8d, 0x72, 0x0c, 0x73, 0x32, 0x74, 0x09, 0x75, 0x28
+    },
+    { /* TV_MODE_EIA */
+    0x70, 0x82, 0x71, 0x8d, 0x72, 0x0c, 0x73, 0x32, 0x74, 0x09, 0x75, 0x28
+    },
+};
+
+static char SMI_HCR[VIDEO_MODES][22] = {
+    { /* DUAL_800_600_8 */
+    0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+    0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+    },
+    { /* DUAL_1024_768_8 */
+    0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+    0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+    },
+    { /* SINGLE_800_600_8 */
+    0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+    0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+    },
+    { /* SINGLE_1024_768_8 */
+    0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+    0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+    },
+    { /* SINGLE_1280_1024_8 */
+    0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+    0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+    },
+    { /* TV_MODE_CCIR */
+    0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+    0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+    },
+    { /* TV_MODE_EIA */
+    0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+    0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+    },
+};
+
+static char SMI_FPR[VIDEO_MODES][88] = {
+    { /* DUAL_800_600_8 */
+    0x30, 0x36, 0x31, 0x83, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x03,
+    0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
+    0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x41,
+    0x4b, 0xa0, 0x4c, 0x00,
+    0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x67, 0x55, 0x71,
+    0x56, 0x57, 0x57, 0x59, 0x58, 0x03, 0x59, 0x00, 0x5a, 0x4a,
+    0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+    0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+    0xa0, 0x44
+    },
+    { /* DUAL_1024_768_8 */
+    0x30, 0x3a, 0x31, 0x83, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00,
+    0x3f, 0x00, 0x40, 0x80, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00,
+    0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x41,
+    0x4b, 0xa0, 0x4c, 0x00,
+    0x50, 0x06, 0x51, 0x68, 0x52, 0xa7, 0x53, 0x7f, 0x54, 0x83, 0x55, 0x25,
+    0x56, 0xff, 0x57, 0x03, 0x58, 0x04, 0x59, 0x00, 0x5a, 0xc2,
+    0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+    0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+    0xa0, 0x44
+    },
+    { /* SINGLE_800_600_8 */
+    0x30, 0x36, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x03,
+    0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
+    0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00,
+    0x4b, 0xa0, 0x4c, 0x00,
+    0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x67, 0x55, 0x71,
+    0x56, 0x57, 0x57, 0x59, 0x58, 0x03, 0x59, 0x00, 0x5a, 0x4a,
+    0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+    0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+    0xa0, 0x44
+    },
+    { /* SINGLE_1024_768_8 */
+    0x30, 0x3a, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00,
+    0x3f, 0x00, 0x40, 0x80, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00,
+    0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x11,
+    0x4b, 0xa0, 0x4c, 0x00,
+    0x50, 0x06, 0x51, 0x68, 0x52, 0xa7, 0x53, 0x7f, 0x54, 0x83, 0x55, 0x24,
+    0x56, 0xff, 0x57, 0x03, 0x58, 0x04, 0x59, 0x00, 0x5a, 0xc2,
+    0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+    0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+    0xa0, 0x44
+    },
+    { /* SINGLE_1280_1024_8 */
+    0x30, 0x3e, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00,
+    0x3f, 0x00, 0x40, 0xa0, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00,
+    0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x11,
+    0x4b, 0xa0, 0x4c, 0x00,
+    0x50, 0x08, 0x51, 0x88, 0x52, 0xd3, 0x53, 0x9f, 0x54, 0xa3, 0x55, 0x2a,
+    0x56, 0xff, 0x57, 0x04, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x63,
+    0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+    0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+    0xa0, 0x44
+    },
+    { /* TV_MODE_CCIR */
+    0x30, 0x24, 0x31, 0x84, 0x32, 0x20, 0x33, 0x09, 0x34, 0xf0, 0x3e, 0x03,
+    0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
+    0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00,
+    0x4b, 0xa0, 0x4c, 0x00,
+    0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x68, 0x55, 0x73,
+    0x56, 0x57, 0x57, 0x58, 0x58, 0x04, 0x59, 0x57, 0x5a, 0x7b,
+    0xa1, 0x10, 0xa2, 0xab, 0xa3, 0x98, 0xa4, 0xc1, 0xa8, 0x8c, 0xa9, 0x05,
+    0xaa, 0x17, 0xab, 0x35, 0xac, 0x41, 0xad, 0x68, 0xae, 0x00, 0xaf, 0x00,
+    0xa0, 0x00
+    },
+    { /* TV_MODE_EIA */
+    0x30, 0x24, 0x31, 0x84, 0x32, 0x20, 0x33, 0x09, 0x34, 0xf0, 0x3e, 0x03,
+    0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
+    0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00,
+    0x4b, 0xa0, 0x4c, 0x00,
+    0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x68, 0x55, 0x73,
+    0x56, 0x57, 0x57, 0x58, 0x58, 0x04, 0x59, 0x57, 0x5a, 0x7b,
+    0xa1, 0x10, 0xa2, 0xab, 0xa3, 0x98, 0xa4, 0xc1, 0xa8, 0x8c, 0xa9, 0x05,
+    0xaa, 0x17, 0xab, 0x35, 0xac, 0x41, 0xad, 0x68, 0xae, 0x00, 0xaf, 0x00,
+    0xa0, 0x00
+    },
+};
+
+static char SMI_GCR[18] = {
+    0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
+    0x06, 0x05, 0x07, 0x0f, 0x08, 0xff
+};
+
+/*******************************************************************************
+*
+* Read SMI ISA register
+*/
+static char smiRead (unsigned short index, char reg)
+{
+    register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+    out8 ((pGD->isaBase + index), reg);
+    return (in8 (pGD->isaBase + index + 1));
+}
+
+/*******************************************************************************
+*
+* Write SMI ISA register
+*/
+static void smiWrite (unsigned short index, char reg, char val)
+{
+    register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+    out8 ((pGD->isaBase + index), reg);
+    out8 ((pGD->isaBase + index + 1), val);
+}
+
+/*******************************************************************************
+*
+* Write a table of SMI ISA register
+*/
+static void smiLoadRegs (
+    unsigned int iReg,
+    unsigned int dReg,
+    char         *regTab,
+    unsigned int tabSize
+    )
+{
+    register int i;
+
+    for (i=0; i<tabSize; i+=2)
+    {
+        out8 (iReg, regTab[i]);
+        out8 (dReg, regTab[i+1]);
+    }
+}
+
+/*******************************************************************************
+*
+* Init capture port registers
+*/
+static void smiInitCapturePort (void)
+{
+    SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
+    register GraphicDevice *pGD  = (GraphicDevice *)&smi;
+    register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
+
+    out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16)   | pCP->leftClip));
+    out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
+    out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
+    out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
+    out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
+    out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
+    out32r ((pGD->cprBase + 0x0000), pCP->control);
+}
+
+
+/*******************************************************************************
+*
+* Init video processor registers
+*/
+static void smiInitVideoProcessor (void)
+{
+    SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
+    SmiVideoWin  smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
+    register GraphicDevice *pGD = (GraphicDevice *)&smi;
+    register SmiVideoProc  *pVP = (SmiVideoProc *)&smiVP;
+    register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
+
+    pVP->width    = pGD->plnSizeX * pGD->gdfBytesPP;
+    pVP->control |= pGD->gdfIndex << 16;
+    pVWin->bottom = pGD->winSizeY - 1;
+    pVWin->right  = pGD->winSizeX - 1;
+    pVWin->width  = pVP->width;
+
+    /* color key */
+    out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
+
+     /* color key mask */
+    out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
+
+    /* data src start adrs */
+    out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
+
+    /* data width and offset */
+    out32r ((pGD->vprBase + 0x0010),
+        ((pVP->offset   / 8 * pGD->gdfBytesPP) << 16) |
+         (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
+
+    /* video window 1 */
+    out32r ((pGD->vprBase + 0x0014),
+        ((pVWin->top << 16) | pVWin->left));
+
+    out32r ((pGD->vprBase + 0x0018),
+        ((pVWin->bottom << 16) | pVWin->right));
+
+    out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
+
+    out32r ((pGD->vprBase + 0x0020),
+        (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
+
+    out32r ((pGD->vprBase + 0x0024),
+        (((pVWin->hStretch) << 8) | pVWin->vStretch));
+
+    /* video window 2 */
+    out32r ((pGD->vprBase + 0x0028),
+        ((pVWin->top << 16) | pVWin->left));
+
+    out32r ((pGD->vprBase + 0x002c),
+        ((pVWin->bottom << 16) | pVWin->right));
+
+    out32r ((pGD->vprBase + 0x0030),
+        pVWin->srcStart / 8);
+
+    out32r ((pGD->vprBase + 0x0034),
+        (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
+
+    out32r ((pGD->vprBase + 0x0038),
+        (((pVWin->hStretch) << 8) | pVWin->vStretch));
+
+    /* fifo prio control */
+    out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
+
+    /* fifo empty request levell */
+    out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
+
+    /* conversion constant */
+    out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
+
+    /* vpr control word */
+    out32r ((pGD->vprBase + 0x0000), pVP->control);
+}
+
+/******************************************************************************
+ *
+ * Init drawing engine registers
+ */
+static void smiInitDrawingEngine (void)
+{
+    GraphicDevice *pGD = (GraphicDevice *)&smi;
+    unsigned int val;
+
+    /* don't start now */
+    out32r ((pGD->dprBase + 0x000c), 0x000f0000);
+
+    /* set rop2 to copypen */
+    val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
+    out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
+
+    /* set clip rect */
+    out32r ((pGD->dprBase + 0x002c), 0);
+    out32r ((pGD->dprBase + 0x0030),
+        ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
+
+    /* src row pitch */
+    val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
+    out32r ((pGD->dprBase + 0x0010),
+        (val | pGD->plnSizeX * pGD->gdfBytesPP));
+
+    /* dst row pitch */
+    val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
+    out32r ((pGD->dprBase + 0x0010),
+        (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
+
+    /* window width src/dst */
+    out32r ((pGD->dprBase + 0x003c),
+        (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
+          (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
+    out16r ((pGD->dprBase + 0x001e), 0x0000);
+
+    /* src base adrs */
+    out32r ((pGD->dprBase + 0x0040),
+        (((pGD->frameAdrs/8) & 0x000fffff)));
+
+    /* dst base adrs */
+    out32r ((pGD->dprBase + 0x0044),
+        (((pGD->frameAdrs/8) & 0x000fffff)));
+
+    /* foreground color */
+    out32r ((pGD->dprBase + 0x0014), pGD->fg);
+
+    /* background color */
+    out32r ((pGD->dprBase + 0x0018), pGD->bg);
+
+    /* xcolor */
+    out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
+
+    /* xcolor mask */
+    out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
+
+    /* bit mask */
+    out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
+
+    /* load mono pattern */
+    out32r ((pGD->dprBase + 0x0034), 0);
+    out32r ((pGD->dprBase + 0x0038), 0);
+}
+
+static struct pci_device_id supported[] = {
+    { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
+    { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
+    { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
+    { }
+};
+
+
+/*******************************************************************************
+*
+* Init video chip with common Linux graphic modes (lilo)
+*/
+void *video_hw_init (void)
+{
+    GraphicDevice *pGD = (GraphicDevice *)&smi;
+    unsigned short device_id;
+    pci_dev_t devbusfn;
+    int videomode;
+    unsigned int pci_mem_base, *vm, i;
+    unsigned int gdfTab[] = { 1, 2, 2, 4, 3, 1 };
+    char *penv;
+    char *gdfModes[] =
+            {
+            "8 Bit Index Color",
+            "15 Bit 5-5-5 RGB",
+            "16 Bit 5-6-5 RGB",
+            "32 Bit X-8-8-8 RGB",
+            "24 Bit 8-8-8 RGB",
+            "8 Bit 3-3-2 RGB"
+            };
+    int vgaModes[16][2] =
+            {
+            {769, -1}, {771, 0x00002}, {773, 0x00003}, {775, 0x00004},
+            {784, -1}, {787, 0x10002}, {790, 0x10003}, {793, 0x10004},
+            {785, -1}, {788, 0x20002}, {791, 0x20003}, {794, 0x20004},
+            {786, -1}, {789, 0x40002}, {792, 0x40003}, {795, 0x40004}
+            };
+
+    /* Search for video chip */
+    printf("Video: ");
+
+    if ((devbusfn = pci_find_devices(supported, 0)) < 0)
+    {
+        printf ("Controller not found !\n");
+        return (NULL);
+    }
+
+    /* PCI setup */
+    pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
+    pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
+    pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
+    pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
+
+    /* Initialize the video controller */
+    if ((penv = getenv ("videomode")) != NULL)
+        videomode = (int)simple_strtoul (penv, NULL, 16);
+    else
+        videomode = 0x303;                    /* Default 800x600 8 bit index color */
+
+    /* Compare with common vga mode numbers */
+    for (i=0; i<16; i++)
+    {
+        if (vgaModes[i][0] == videomode)
+        {
+            if (vgaModes[i][1] == -1)
+            {
+                printf("Videomode not supported !\n");
+                return (NULL);                /* mode not supported */
+            }
+            pGD->mode = vgaModes[i][1];        /* use driver int. mode number */
+            break;
+        }
+    }
+
+    /* Extract graphic data format */
+    pGD->gdfIndex = (pGD->mode & 0x00070000) >> 16;
+    if (pGD->gdfIndex > 5)
+        pGD->gdfIndex = 0;
+    pGD->gdfBytesPP = gdfTab[pGD->gdfIndex];
+
+    /* Extract graphic resolution */
+    pGD->mode &= 0xf;
+
+    /* Exit for not supported resolutions */
+    if (((pGD->mode==DUAL_800_600) || (pGD->mode==DUAL_1024_768)) && (pGD->gdfBytesPP > 1))
+    {
+        printf ("Dual screen for 1BPP only !\n");
+        return (NULL);
+    }
+
+    if ((pGD->mode==SINGLE_1280_1024) && (pGD->gdfBytesPP==4))
+    {
+        printf ("Out of memory !\n");
+        return (NULL);
+    }
+
+    /* Set graphic parameters */
+    switch (pGD->mode)
+    {
+    case DUAL_800_600:
+            pGD->winSizeX = 800;
+            pGD->winSizeY = 600;
+            pGD->plnSizeX = 1600;
+            pGD->plnSizeY = 600;
+            sprintf (pGD->modeIdent, "Dual Screen 800x600 with %s", gdfModes[pGD->gdfIndex]);
+            break;
+    case DUAL_1024_768:
+            pGD->winSizeX = 1024;
+            pGD->winSizeY = 768;
+            pGD->plnSizeX = 2048;
+            pGD->plnSizeY = 768;
+            sprintf (pGD->modeIdent, "Dual Screen 1024x768 with %s", gdfModes[pGD->gdfIndex]);
+            break;
+    case SINGLE_800_600:
+            pGD->winSizeX = 800;
+            pGD->winSizeY = 600;
+            pGD->plnSizeX = 800;
+            pGD->plnSizeY = 600;
+            sprintf (pGD->modeIdent, "Single Screen 800x600 with %s", gdfModes[pGD->gdfIndex]);
+            break;
+    case SINGLE_1024_768:
+            pGD->winSizeX = 1024;
+            pGD->winSizeY = 768;
+            pGD->plnSizeX = 1024;
+            pGD->plnSizeY = 768;
+            sprintf (pGD->modeIdent,"Single Screen 1024x768 with %s", gdfModes[pGD->gdfIndex]);
+            break;
+    case TV_MODE_CCIR:
+            pGD->winSizeX = 720;
+            pGD->winSizeY = 576;
+            pGD->plnSizeX = 720;
+            pGD->plnSizeY = 576;
+            sprintf (pGD->modeIdent, "TV Mode CCIR with %s", gdfModes[pGD->gdfIndex]);
+            break;
+    case TV_MODE_EIA:
+            pGD->winSizeX = 720;
+            pGD->winSizeY = 484;
+            pGD->plnSizeX = 720;
+            pGD->plnSizeY = 484;
+            sprintf (pGD->modeIdent, "TV Mode EIA with %s", gdfModes[pGD->gdfIndex]);
+            break;
+    case SINGLE_1280_1024:
+            pGD->winSizeX = 1280;
+            pGD->winSizeY = 1024;
+            pGD->plnSizeX = 1280;
+            pGD->plnSizeY = 1024;
+            sprintf (pGD->modeIdent, "Single Screen 1280x1024 with %s", gdfModes[pGD->gdfIndex]);
+            break;
+    default:
+            printf("Videomode not supported !\n");
+            return (NULL);
+    }
+
+
+    pGD->isaBase = CFG_ISA_IO;
+    pGD->pciBase = pci_mem_base;
+    pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
+    pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
+    pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
+    pGD->frameAdrs = pci_mem_base;
+    pGD->memSize = VIDEO_MEM_SIZE;
+
+    /* Turn off display */
+    smiWrite (0x3c4, 0x01, 0x20);
+
+    /* Unlock ext. crt regs */
+    out8 (SMI_LOCK_REG, 0x40);
+
+    /* Set Register base to isa 3dx for 3?x regs (color mode) */
+    out8 (SMI_MISC_REG, 0x2b);
+
+    /* Unlock crt regs 0-7 */
+    smiWrite (0x3d4, 0x11, 0x0e);
+
+    /* Sytem Control Register */
+    smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+         SMI_SCR, sizeof(SMI_SCR));
+
+    /* extented CRT Register */
+    smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5,
+         SMI_EXT_CRT[pGD->mode], sizeof(SMI_EXT_CRT)/VIDEO_MODES);
+
+    /* Sequencer Register */
+    smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+         SMI_SEQR, sizeof(SMI_SEQR));
+
+    /* Power Control Register */
+    smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+         SMI_PCR[pGD->mode], sizeof(SMI_PCR)/VIDEO_MODES);
+
+    /* Memory Control Register */
+    smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+         SMI_MCR[pGD->mode], sizeof(SMI_MCR)/VIDEO_MODES);
+
+    /* Clock Control Register */
+    smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+         SMI_CCR[pGD->mode], sizeof(SMI_CCR)/VIDEO_MODES);
+
+    /* Shadow VGA Register */
+    smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5,
+         SMI_SHVGA[pGD->mode], sizeof(SMI_SHVGA)/VIDEO_MODES);
+
+    /* General Purpose Register */
+    smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+         SMI_GPR[pGD->mode], sizeof(SMI_GPR)/VIDEO_MODES);
+
+    /* Hardware Cusor Register */
+    smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+         SMI_HCR[pGD->mode], sizeof(SMI_HCR)/VIDEO_MODES);
+
+    /* Flat Panel Register */
+    smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+         SMI_FPR[pGD->mode], sizeof(SMI_FPR)/VIDEO_MODES);
+
+    /* CRTC Register */
+    smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5,
+         SMI_CRTCR[pGD->mode], sizeof(SMI_CRTCR)/VIDEO_MODES);
+
+    /* Graphics Controller Register */
+    smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF,
+         SMI_GCR, sizeof(SMI_GCR));
+
+    /* Patch memory and refresh settings for SMI710 */
+    if (device_id == PCI_DEVICE_ID_SMI_710)
+    {
+    unsigned char reg = smiRead (0x3c4, 0x62);
+
+    /* external memory disabled */
+    smiWrite (0x3c4, 0x62, (reg & 0xfb));
+    /* memory clock */
+    smiWrite (0x3c4, 0x6a, 0x75);
+    }
+
+    /* Patch memory and refresh settings for SMI712 */
+    if (device_id == PCI_DEVICE_ID_SMI_712)
+    {
+    unsigned char reg = smiRead (0x3c4, 0x62);
+
+    /* IL runs at MCLK; 64bit bus; external memory disabled */
+    smiWrite (0x3c4, 0x62, (reg | 0xc4));
+    /* memory clock */
+    smiWrite (0x3c4, 0x6a, 0x80);
+    }
+
+    /* Patch clock settings for SMI810 */
+    if (device_id == PCI_DEVICE_ID_SMI_810)
+    {
+    /* clock control */
+    smiWrite (0x3c4, 0x69, 0x03);
+    }
+
+    /* Video processor default setup */
+    smiInitVideoProcessor ();
+
+    /* Capture port default setup */
+    smiInitCapturePort ();
+
+    /* Drawing engine default setup */
+    smiInitDrawingEngine ();
+
+    /* Turn on display */
+    smiWrite (0x3c4, 0x01, 0x01);
+
+    /* Clear video memory */
+    i = pGD->memSize/4;
+    vm = (unsigned int *)pGD->pciBase;
+    while(i--)
+    *vm++ = 0;
+
+    printf("mode=%x - %s\n", videomode, pGD->modeIdent);
+    return ((void*)&smi);
+}
+
+/*******************************************************************************
+*
+* Drawing engine fill on screen region
+*/
+void video_hw_rectfill (
+    unsigned int bpp,             /* bytes per pixel */
+    unsigned int dst_x,           /* dest pos x */
+    unsigned int dst_y,           /* dest pos y */
+    unsigned int dim_x,           /* frame width */
+    unsigned int dim_y,           /* frame height */
+    unsigned int color            /* fill color */
+     )
+{
+    register GraphicDevice *pGD = (GraphicDevice *)&smi;
+    register unsigned int control;
+
+    dim_x *= bpp;
+
+    out32r ((pGD->dprBase + 0x0014), color);
+    out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
+    out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
+
+    control = 0x0000ffff &  in32r ((pGD->dprBase + 0x000c));
+
+    control |= 0x80010000;
+
+    out32r ((pGD->dprBase + 0x000c),  control);
+
+    /* Wait for drawing processor */
+    do
+    {
+    out8 ((pGD->isaBase + 0x3c4), 0x16);
+    } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
+}
+
+/*******************************************************************************
+*
+* Drawing engine bitblt with screen region
+*/
+void video_hw_bitblt (
+    unsigned int bpp,             /* bytes per pixel */
+    unsigned int src_x,           /* source pos x */
+    unsigned int src_y,           /* source pos y */
+    unsigned int dst_x,           /* dest pos x */
+    unsigned int dst_y,           /* dest pos y */
+    unsigned int dim_x,           /* frame width */
+    unsigned int dim_y            /* frame height */
+    )
+{
+    register GraphicDevice *pGD = (GraphicDevice *)&smi;
+    register unsigned int control;
+
+    dim_x *= bpp;
+
+    if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
+    {
+    out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
+    out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
+    control = 0x88000000;
+    }
+    else
+    {
+    out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
+    out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
+    control = 0x80000000;
+    }
+
+    out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
+    control |= (0x0000ffff &  in32r ((pGD->dprBase + 0x000c)));
+    out32r ((pGD->dprBase + 0x000c), control);
+
+    /* Wait for drawing processor */
+    do
+    {
+    out8 ((pGD->isaBase + 0x3c4), 0x16);
+    } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
+}
+
+/*******************************************************************************
+*
+* Set a RGB color in the LUT (8 bit index)
+*/
+void video_set_lut (
+    unsigned int index,           /* color number */
+    unsigned char r,              /* red */
+    unsigned char g,              /* green */
+    unsigned char b               /* blue */
+    )
+{
+    register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+    out8 (SMI_LUT_MASK,  0xff);
+
+    out8 (SMI_LUT_START, (char)index);
+
+    out8 (SMI_LUT_RGB, r>>2);    /* red */
+    udelay (10);
+    out8 (SMI_LUT_RGB, g>>2);    /* green */
+    udelay (10);
+    out8 (SMI_LUT_RGB, b>>2);    /* blue */
+    udelay (10);
+}
+
+#endif /* CONFIG_VIDEO_SMI_LYNXEM */
diff --git a/drivers/tigon3.c b/drivers/tigon3.c
new file mode 100644 (file)
index 0000000..5883744
--- /dev/null
@@ -0,0 +1,6222 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* 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, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+#include <common.h>
+#include "bcm570x_mm.h"
+#include <asm/types.h>
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \
+       defined(CONFIG_TIGON3)
+#ifdef CONFIG_BMW
+#include <mpc824x.h>
+#endif
+#include <malloc.h>
+#include <linux/byteorder/big_endian.h>
+
+#define EMBEDDED 1
+/******************************************************************************/
+/* Local functions. */
+/******************************************************************************/
+
+LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+
+static LM_STATUS LM_TranslateRequestedMediaType(
+    LM_REQUESTED_MEDIA_TYPE RequestedMediaType,
+    PLM_MEDIA_TYPE pMediaType, PLM_LINE_SPEED pLineSpeed,
+    PLM_DUPLEX_MODE pDuplexMode);
+
+static LM_STATUS LM_InitBcm540xPhy(PLM_DEVICE_BLOCK pDevice);
+
+__inline static LM_VOID LM_ServiceRxInterrupt(PLM_DEVICE_BLOCK pDevice);
+__inline static LM_VOID LM_ServiceTxInterrupt(PLM_DEVICE_BLOCK pDevice);
+
+static LM_STATUS LM_ForceAutoNegBcm540xPhy(PLM_DEVICE_BLOCK pDevice,
+    LM_REQUESTED_MEDIA_TYPE RequestedMediaType);
+static LM_STATUS LM_ForceAutoNeg(PLM_DEVICE_BLOCK pDevice,
+    LM_REQUESTED_MEDIA_TYPE RequestedMediaType);
+static LM_UINT32 GetPhyAdFlowCntrlSettings(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_SetFlowControl(PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd);
+#if INCLUDE_TBI_SUPPORT
+STATIC LM_STATUS LM_SetupFiberPhy(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_InitBcm800xPhy(PLM_DEVICE_BLOCK pDevice);
+#endif
+STATIC LM_STATUS LM_SetupCopperPhy(PLM_DEVICE_BLOCK pDevice);
+STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid(LM_UINT16 Svid, LM_UINT16 Ssid);
+STATIC LM_STATUS LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt,
+           LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize);
+STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number);
+STATIC LM_STATUS LM_ResetChip(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
+    PT3_SND_BD pSendBd);
+
+/******************************************************************************/
+/* External functions. */
+/******************************************************************************/
+
+LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice);
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_UINT32
+LM_RegRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register) {
+    LM_UINT32 Value32;
+
+#if PCIX_TARGET_WORKAROUND
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#endif
+    MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+    MM_ReadConfig32(pDevice, T3_PCI_REG_DATA_REG, &Value32);
+#if PCIX_TARGET_WORKAROUND
+    MM_RELEASE_UNDI_LOCK(pDevice);
+#endif
+
+    return Value32;
+} /* LM_RegRdInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_RegWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register,
+LM_UINT32 Value32) {
+
+#if PCIX_TARGET_WORKAROUND
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#endif
+    MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+    MM_WriteConfig32(pDevice, T3_PCI_REG_DATA_REG, Value32);
+#if PCIX_TARGET_WORKAROUND
+    MM_RELEASE_UNDI_LOCK(pDevice);
+#endif
+} /* LM_RegWrInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_UINT32
+LM_MemRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr) {
+    LM_UINT32 Value32;
+
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#ifdef BIG_ENDIAN_HOST
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    Value32 = REG_RD(pDevice, PciCfg.MemWindowData);
+    /*    Value32 = REG_RD(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4]); */
+#else
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    MM_ReadConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32);
+#endif
+    MM_RELEASE_UNDI_LOCK(pDevice);
+
+    return Value32;
+} /* LM_MemRdInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_MemWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr,
+LM_UINT32 Value32) {
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#ifdef BIG_ENDIAN_HOST
+    REG_WR(pDevice,PciCfg.MemWindowBaseAddr,MemAddr);
+    REG_WR(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4],Value32);
+#else
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, Value32);
+#endif
+    MM_RELEASE_UNDI_LOCK(pDevice);
+} /* LM_MemWrInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_QueueRxPackets(
+PLM_DEVICE_BLOCK pDevice) {
+    LM_STATUS Lmstatus;
+    PLM_PACKET pPacket;
+    PT3_RCV_BD pRcvBd;
+    LM_UINT32 StdBdAdded = 0;
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    LM_UINT32 JumboBdAdded = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    Lmstatus = LM_STATUS_SUCCESS;
+
+    pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+    while(pPacket) {
+        switch(pPacket->u.Rx.RcvProdRing) {
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+            case T3_JUMBO_RCV_PROD_RING:        /* Jumbo Receive Ring. */
+                /* Initialize the buffer descriptor. */
+                pRcvBd =
+                    &pDevice->pRxJumboBdVirt[pDevice->RxJumboProdIdx];
+                pRcvBd->Flags = RCV_BD_FLAG_END | RCV_BD_FLAG_JUMBO_RING;
+                pRcvBd->Len = (LM_UINT16) pDevice->RxJumboBufferSize;
+
+                /* Initialize the receive buffer pointer */
+#if 0 /* Jimmy, deleted in new */
+                pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low;
+                pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High;
+#endif
+                MM_MapRxDma(pDevice, pPacket, &pRcvBd->HostAddr);
+
+                /* The opaque field may point to an offset from a fix addr. */
+                pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR(pPacket) -
+                    MM_UINT_PTR(pDevice->pPacketDescBase));
+
+                /* Update the producer index. */
+                pDevice->RxJumboProdIdx = (pDevice->RxJumboProdIdx + 1) &
+                    T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK;
+
+                JumboBdAdded++;
+                break;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+            case T3_STD_RCV_PROD_RING:      /* Standard Receive Ring. */
+                /* Initialize the buffer descriptor. */
+                pRcvBd = &pDevice->pRxStdBdVirt[pDevice->RxStdProdIdx];
+                pRcvBd->Flags = RCV_BD_FLAG_END;
+                pRcvBd->Len = MAX_STD_RCV_BUFFER_SIZE;
+
+                /* Initialize the receive buffer pointer */
+#if 0  /* Jimmy, deleted in new replaced with MM_MapRxDma */
+                pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low;
+                pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High;
+#endif
+                MM_MapRxDma(pDevice, pPacket, &pRcvBd->HostAddr);
+
+                /* The opaque field may point to an offset from a fix addr. */
+                pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR(pPacket) -
+                    MM_UINT_PTR(pDevice->pPacketDescBase));
+
+                /* Update the producer index. */
+                pDevice->RxStdProdIdx = (pDevice->RxStdProdIdx + 1) &
+                    T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+
+                StdBdAdded++;
+                break;
+
+            case T3_UNKNOWN_RCV_PROD_RING:
+            default:
+                Lmstatus = LM_STATUS_FAILURE;
+                break;
+        } /* switch */
+
+        /* Bail out if there is any error. */
+        if(Lmstatus != LM_STATUS_SUCCESS)
+        {
+            break;
+        }
+
+        pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+    } /* while */
+
+    wmb();
+    /* Update the procedure index. */
+    if(StdBdAdded)
+    {
+        MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low, pDevice->RxStdProdIdx);
+    }
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    if(JumboBdAdded)
+    {
+        MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low,
+            pDevice->RxJumboProdIdx);
+    }
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    return Lmstatus;
+} /* LM_QueueRxPackets */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_VOID
+LM_NvramInit(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    /* Intialize clock period and state machine. */
+    Value32 = SEEPROM_ADDR_CLK_PERD(SEEPROM_CLOCK_PERIOD) |
+        SEEPROM_ADDR_FSM_RESET;
+    REG_WR(pDevice, Grc.EepromAddr, Value32);
+
+    for(j = 0; j < 100; j++)
+    {
+        MM_Wait(10);
+    }
+
+    /* Serial eeprom access using the Grc.EepromAddr/EepromData registers. */
+    Value32 = REG_RD(pDevice, Grc.LocalCtrl);
+    REG_WR(pDevice, Grc.LocalCtrl, Value32 | GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM);
+
+    /* Set the 5701 compatibility mode if we are using EEPROM. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+        T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+    {
+        Value32 = REG_RD(pDevice, Nvram.Config1);
+        if((Value32 & FLASH_INTERFACE_ENABLE) == 0)
+        {
+            /* Use the new interface to read EEPROM. */
+            Value32 &= ~FLASH_COMPAT_BYPASS;
+
+            REG_WR(pDevice, Nvram.Config1, Value32);
+        }
+    }
+} /* LM_NvRamInit */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_EepromRead(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 Offset,
+    LM_UINT32 *pData)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 Addr;
+    LM_UINT32 Dev;
+    LM_UINT32 j;
+
+    if(Offset > SEEPROM_CHIP_SIZE)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    Dev = Offset / SEEPROM_CHIP_SIZE;
+    Addr = Offset % SEEPROM_CHIP_SIZE;
+
+    Value32 = REG_RD(pDevice, Grc.EepromAddr);
+    Value32 &= ~(SEEPROM_ADDR_ADDRESS_MASK | SEEPROM_ADDR_DEV_ID_MASK |
+        SEEPROM_ADDR_RW_MASK);
+    REG_WR(pDevice, Grc.EepromAddr, Value32 | SEEPROM_ADDR_DEV_ID(Dev) |
+        SEEPROM_ADDR_ADDRESS(Addr) | SEEPROM_ADDR_START | SEEPROM_ADDR_READ);
+
+    for(j = 0; j < 1000; j++)
+    {
+        Value32 = REG_RD(pDevice, Grc.EepromAddr);
+        if(Value32 & SEEPROM_ADDR_COMPLETE)
+        {
+            break;
+        }
+        MM_Wait(10);
+    }
+
+    if(Value32 & SEEPROM_ADDR_COMPLETE)
+    {
+        Value32 = REG_RD(pDevice, Grc.EepromData);
+        *pData = Value32;
+
+        return LM_STATUS_SUCCESS;
+    }
+
+    return LM_STATUS_FAILURE;
+} /* LM_EepromRead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_NvramRead(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 Offset,
+    LM_UINT32 *pData)
+{
+    LM_UINT32 Value32;
+    LM_STATUS Status;
+    LM_UINT32 j;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+    {
+        Status = LM_EepromRead(pDevice, Offset, pData);
+    }
+    else
+    {
+        /* Determine if we have flash or EEPROM. */
+        Value32 = REG_RD(pDevice, Nvram.Config1);
+        if(Value32 & FLASH_INTERFACE_ENABLE)
+        {
+            if(Value32 & FLASH_SSRAM_BUFFERRED_MODE)
+            {
+                Offset = ((Offset/BUFFERED_FLASH_PAGE_SIZE) <<
+                    BUFFERED_FLASH_PAGE_POS) +
+                    (Offset % BUFFERED_FLASH_PAGE_SIZE);
+            }
+        }
+
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1);
+        for (j = 0; j < 1000; j++)
+        {
+            if (REG_RD(pDevice, Nvram.SwArb) & SW_ARB_GNT1)
+            {
+                break;
+            }
+            MM_Wait(20);
+        }
+        if (j == 1000)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        /* Read from flash or EEPROM with the new 5703/02 interface. */
+        REG_WR(pDevice, Nvram.Addr, Offset & NVRAM_ADDRESS_MASK);
+
+        REG_WR(pDevice, Nvram.Cmd, NVRAM_CMD_RD | NVRAM_CMD_DO_IT |
+            NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
+
+        /* Wait for the done bit to clear. */
+        for(j = 0; j < 500; j++)
+        {
+            MM_Wait(10);
+
+            Value32 = REG_RD(pDevice, Nvram.Cmd);
+            if(!(Value32 & NVRAM_CMD_DONE))
+            {
+                break;
+            }
+        }
+
+        /* Wait for the done bit. */
+        if(!(Value32 & NVRAM_CMD_DONE))
+        {
+            for(j = 0; j < 500; j++)
+            {
+                MM_Wait(10);
+
+                Value32 = REG_RD(pDevice, Nvram.Cmd);
+                if(Value32 & NVRAM_CMD_DONE)
+                {
+                    MM_Wait(10);
+
+                    *pData = REG_RD(pDevice, Nvram.ReadData);
+
+                    /* Change the endianess. */
+                    *pData = ((*pData & 0xff) << 24)| ((*pData & 0xff00) << 8)|
+                        ((*pData & 0xff0000) >> 8) | ((*pData >> 24) & 0xff);
+
+                    break;
+                }
+            }
+        }
+
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1);
+        if(Value32 & NVRAM_CMD_DONE)
+        {
+            Status = LM_STATUS_SUCCESS;
+        }
+        else
+        {
+            Status = LM_STATUS_FAILURE;
+        }
+    }
+
+    return Status;
+} /* LM_NvramRead */
+
+
+STATIC void
+LM_ReadVPD(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Vpd_arr[256/4];
+    LM_UINT8 *Vpd = (LM_UINT8 *) &Vpd_arr[0];
+    LM_UINT32 *Vpd_dptr = &Vpd_arr[0];
+    LM_UINT32 Value32;
+    unsigned int j;
+
+    /* Read PN from VPD */
+    for (j = 0; j < 256; j += 4, Vpd_dptr++ )
+    {
+        if (LM_NvramRead(pDevice, 0x100 + j, &Value32) != LM_STATUS_SUCCESS) {
+            printf("BCM570x: LM_ReadVPD: VPD read failed"
+                  " (no EEPROM onboard)\n");
+            return;
+        }
+        *Vpd_dptr = cpu_to_le32(Value32);
+    }
+    for (j = 0; j < 256; )
+    {
+        unsigned int Vpd_r_len;
+        unsigned int Vpd_r_end;
+
+        if ((Vpd[j] == 0x82) || (Vpd[j] == 0x91))
+        {
+            j = j + 3 + Vpd[j + 1] + (Vpd[j + 2] << 8);
+        }
+        else if (Vpd[j] == 0x90)
+        {
+            Vpd_r_len =  Vpd[j + 1] + (Vpd[j + 2] << 8);
+            j += 3;
+            Vpd_r_end = Vpd_r_len + j;
+            while (j < Vpd_r_end)
+            {
+                if ((Vpd[j] == 'P') && (Vpd[j + 1] == 'N'))
+                {
+                    unsigned int len = Vpd[j + 2];
+
+                    if (len <= 24)
+                    {
+                        memcpy(pDevice->PartNo, &Vpd[j + 3], len);
+                    }
+                    break;
+                }
+                else
+                {
+                    if (Vpd[j + 2] == 0)
+                    {
+                        break;
+                    }
+                    j = j + Vpd[j + 2];
+                }
+            }
+            break;
+        }
+        else {
+            break;
+        }
+    }
+}
+
+STATIC void
+LM_ReadBootCodeVersion(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32, offset, ver_offset;
+    int i;
+
+    if (LM_NvramRead(pDevice, 0x0, &Value32) != LM_STATUS_SUCCESS)
+        return;
+    if (Value32 != 0xaa559966)
+        return;
+    if (LM_NvramRead(pDevice, 0xc, &offset) != LM_STATUS_SUCCESS)
+        return;
+
+    offset = ((offset & 0xff) << 24)| ((offset & 0xff00) << 8)|
+        ((offset & 0xff0000) >> 8) | ((offset >> 24) & 0xff);
+    if (LM_NvramRead(pDevice, offset, &Value32) != LM_STATUS_SUCCESS)
+        return;
+    if ((Value32 == 0x0300000e) &&
+        (LM_NvramRead(pDevice, offset + 4, &Value32) == LM_STATUS_SUCCESS) &&
+        (Value32 == 0)) {
+
+        if (LM_NvramRead(pDevice, offset + 8, &ver_offset) != LM_STATUS_SUCCESS)
+            return;
+        ver_offset = ((ver_offset & 0xff0000) >> 8) |
+            ((ver_offset >> 24) & 0xff);
+        for (i = 0; i < 16; i += 4) {
+            if (LM_NvramRead(pDevice, offset + ver_offset + i, &Value32) !=
+                LM_STATUS_SUCCESS)
+            {
+                return;
+            }
+            *((LM_UINT32 *) &pDevice->BootCodeVer[i]) = cpu_to_le32(Value32);
+        }
+    }
+    else {
+        char c;
+
+        if (LM_NvramRead(pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS)
+            return;
+
+        i = 0;
+        c = ((Value32 & 0xff0000) >> 16);
+
+        if (c < 10) {
+            pDevice->BootCodeVer[i++] = c + '0';
+        }
+        else {
+            pDevice->BootCodeVer[i++] = (c / 10) + '0';
+            pDevice->BootCodeVer[i++] = (c % 10) + '0';
+        }
+        pDevice->BootCodeVer[i++] = '.';
+        c = (Value32 & 0xff000000) >> 24;
+        if (c < 10) {
+            pDevice->BootCodeVer[i++] = c + '0';
+        }
+        else {
+            pDevice->BootCodeVer[i++] = (c / 10) + '0';
+            pDevice->BootCodeVer[i++] = (c % 10) + '0';
+        }
+        pDevice->BootCodeVer[i] = 0;
+    }
+}
+
+STATIC void
+LM_GetBusSpeed(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 PciState = pDevice->PciState;
+    LM_UINT32 ClockCtrl;
+    char *SpeedStr = "";
+
+    if (PciState & T3_PCI_STATE_32BIT_PCI_BUS)
+    {
+        strcpy(pDevice->BusSpeedStr, "32-bit ");
+    }
+    else
+    {
+        strcpy(pDevice->BusSpeedStr, "64-bit ");
+    }
+    if (PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)
+    {
+        strcat(pDevice->BusSpeedStr, "PCI ");
+        if (PciState & T3_PCI_STATE_HIGH_BUS_SPEED)
+        {
+            SpeedStr = "66MHz";
+        }
+        else
+        {
+            SpeedStr = "33MHz";
+        }
+    }
+    else
+    {
+        strcat(pDevice->BusSpeedStr, "PCIX ");
+        if (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE)
+        {
+            SpeedStr = "133MHz";
+        }
+        else
+        {
+            ClockCtrl = REG_RD(pDevice, PciCfg.ClockCtrl) & 0x1f;
+            switch (ClockCtrl)
+            {
+            case 0:
+                SpeedStr = "33MHz";
+                break;
+
+            case 2:
+                SpeedStr = "50MHz";
+                break;
+
+            case 4:
+                SpeedStr = "66MHz";
+                break;
+
+            case 6:
+                SpeedStr = "100MHz";
+                break;
+
+            case 7:
+                SpeedStr = "133MHz";
+                break;
+            }
+        }
+    }
+    strcat(pDevice->BusSpeedStr, SpeedStr);
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine initializes default parameters and reads the PCI           */
+/*    configurations.                                                         */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_GetAdapterInfo(
+PLM_DEVICE_BLOCK pDevice)
+{
+    PLM_ADAPTER_INFO pAdapterInfo;
+    LM_UINT32 Value32;
+    LM_STATUS Status;
+    LM_UINT32 j;
+    LM_UINT32 EeSigFound;
+    LM_UINT32 EePhyTypeSerdes = 0;
+    LM_UINT32 EePhyLedMode = 0;
+    LM_UINT32 EePhyId = 0;
+
+    /* Get Device Id and Vendor Id */
+    Status = MM_ReadConfig32(pDevice, PCI_VENDOR_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->PciVendorId = (LM_UINT16) Value32;
+    pDevice->PciDeviceId = (LM_UINT16) (Value32 >> 16);
+
+    /* If we are not getting the write adapter, exit. */
+    if((Value32 != T3_PCI_ID_BCM5700) &&
+       (Value32 != T3_PCI_ID_BCM5701) &&
+       (Value32 != T3_PCI_ID_BCM5702) &&
+       (Value32 != T3_PCI_ID_BCM5702x) &&
+       (Value32 != T3_PCI_ID_BCM5702FE) &&
+       (Value32 != T3_PCI_ID_BCM5703) &&
+       (Value32 != T3_PCI_ID_BCM5703x) &&
+       (Value32 != T3_PCI_ID_BCM5704))
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    Status = MM_ReadConfig32(pDevice, PCI_REV_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->PciRevId = (LM_UINT8) Value32;
+
+    /* Get IRQ. */
+    Status = MM_ReadConfig32(pDevice, PCI_INT_LINE_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->Irq = (LM_UINT8) Value32;
+
+    /* Get interrupt pin. */
+    pDevice->IntPin = (LM_UINT8) (Value32 >> 8);
+
+    /* Get chip revision id. */
+    Status = MM_ReadConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, &Value32);
+    pDevice->ChipRevId = Value32 >> 16;
+
+    /* Get subsystem vendor. */
+    Status = MM_ReadConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->SubsystemVendorId = (LM_UINT16) Value32;
+
+    /* Get PCI subsystem id. */
+    pDevice->SubsystemId = (LM_UINT16) (Value32 >> 16);
+
+    /* Get the cache line size. */
+    MM_ReadConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG, &Value32);
+    pDevice->CacheLineSize = (LM_UINT8) Value32;
+    pDevice->SavedCacheLineReg = Value32;
+
+    if(pDevice->ChipRevId != T3_CHIP_ID_5703_A1 &&
+        pDevice->ChipRevId != T3_CHIP_ID_5703_A2 &&
+        pDevice->ChipRevId != T3_CHIP_ID_5704_A0)
+    {
+        pDevice->UndiFix = FALSE;
+    }
+#if !PCIX_TARGET_WORKAROUND
+    pDevice->UndiFix = FALSE;
+#endif
+    /* Map the memory base to system address space. */
+    if (!pDevice->UndiFix)
+    {
+        Status = MM_MapMemBase(pDevice);
+        if(Status != LM_STATUS_SUCCESS)
+        {
+            return Status;
+        }
+        /* Initialize the memory view pointer. */
+        pDevice->pMemView = (PT3_STD_MEM_MAP) pDevice->pMappedMemBase;
+    }
+
+#if PCIX_TARGET_WORKAROUND
+    /* store whether we are in PCI are PCI-X mode */
+    pDevice->EnablePciXFix = FALSE;
+
+    MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32);
+    if((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0)
+    {
+        /* Enable PCI-X workaround only if we are running on 5700 BX. */
+        if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+        {
+            pDevice->EnablePciXFix = TRUE;
+        }
+    }
+    if (pDevice->UndiFix)
+    {
+        pDevice->EnablePciXFix = TRUE;
+    }
+#endif
+    /* Bx bug: due to the "byte_enable bug" in PCI-X mode, the power */
+    /* management register may be clobbered which may cause the */
+    /* BCM5700 to go into D3 state.  While in this state, we will */
+    /* not have memory mapped register access.  As a workaround, we */
+    /* need to restore the device to D0 state. */
+    MM_ReadConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, &Value32);
+    Value32 |= T3_PM_PME_ASSERTED;
+    Value32 &= ~T3_PM_POWER_STATE_MASK;
+    Value32 |= T3_PM_POWER_STATE_D0;
+    MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, Value32);
+
+    /* read the current PCI command word */
+    MM_ReadConfig32(pDevice, PCI_COMMAND_REG, &Value32);
+
+    /* Make sure bus-mastering is enabled. */
+    Value32 |= PCI_BUSMASTER_ENABLE;
+
+#if PCIX_TARGET_WORKAROUND
+    /* if we are in PCI-X mode, also make sure mem-mapping and SERR#/PERR#
+        are enabled */
+    if (pDevice->EnablePciXFix == TRUE) {
+        Value32 |= (PCI_MEM_SPACE_ENABLE | PCI_SYSTEM_ERROR_ENABLE |
+                    PCI_PARITY_ERROR_ENABLE);
+    }
+    if (pDevice->UndiFix)
+    {
+        Value32 &= ~PCI_MEM_SPACE_ENABLE;
+    }
+
+#endif
+
+    if(pDevice->EnableMWI)
+    {
+        Value32 |= PCI_MEMORY_WRITE_INVALIDATE;
+    }
+    else {
+        Value32 &= (~PCI_MEMORY_WRITE_INVALIDATE);
+    }
+
+    /* Error out if mem-mapping is NOT enabled for PCI systems */
+    if (!(Value32 | PCI_MEM_SPACE_ENABLE))
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* save the value we are going to write into the PCI command word */
+    pDevice->PciCommandStatusWords = Value32;
+
+    Status = MM_WriteConfig32(pDevice, PCI_COMMAND_REG, Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* Set power state to D0. */
+    LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+
+#ifdef BIG_ENDIAN_PCI
+    pDevice->MiscHostCtrl =
+        MISC_HOST_CTRL_MASK_PCI_INT |
+        MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS |
+        MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP |
+        MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW;
+#else /* No CPU Swap modes for PCI IO */
+
+    /* Setup the mode registers. */
+    pDevice->MiscHostCtrl =
+        MISC_HOST_CTRL_MASK_PCI_INT |
+        MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP |
+#ifdef BIG_ENDIAN_HOST
+        MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP |
+#endif /* BIG_ENDIAN_HOST */
+        MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS |
+        MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW;
+#endif /* !BIG_ENDIAN_PCI */
+
+    /* write to PCI misc host ctr first in order to enable indirect accesses */
+    MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl);
+
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl);
+
+#ifdef BIG_ENDIAN_PCI
+    Value32 = GRC_MODE_WORD_SWAP_DATA|
+             GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+#else
+/* No CPU Swap modes for PCI IO */
+#ifdef BIG_ENDIAN_HOST
+    Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA |
+              GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+#else
+    Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA;
+#endif
+#endif /* !BIG_ENDIAN_PCI */
+
+    REG_WR(pDevice, Grc.Mode, Value32);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        REG_WR(pDevice, Grc.LocalCtrl, GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+            GRC_MISC_LOCAL_CTRL_GPIO_OE1);
+    }
+    MM_Wait(40);
+
+    /* Enable indirect memory access */
+    REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+
+    if (REG_RD(pDevice, PciCfg.ClockCtrl) & T3_PCI_44MHZ_CORE_CLOCK)
+    {
+        REG_WR(pDevice, PciCfg.ClockCtrl, T3_PCI_44MHZ_CORE_CLOCK |
+                T3_PCI_SELECT_ALTERNATE_CLOCK);
+        REG_WR(pDevice, PciCfg.ClockCtrl, T3_PCI_SELECT_ALTERNATE_CLOCK);
+        MM_Wait(40);  /* required delay is 27usec */
+    }
+    REG_WR(pDevice, PciCfg.ClockCtrl, 0);
+    REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0);
+
+#if PCIX_TARGET_WORKAROUND
+    MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32);
+    if ((pDevice->EnablePciXFix == FALSE) &&
+        ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0))
+    {
+        if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B0 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B2 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B5)
+        {
+            __raw_writel(0, &(pDevice->pMemView->uIntMem.MemBlock32K[0x300]));
+            __raw_writel(0, &(pDevice->pMemView->uIntMem.MemBlock32K[0x301]));
+            __raw_writel(0xffffffff, &(pDevice->pMemView->uIntMem.MemBlock32K[0x301]));
+            if (__raw_readl(&(pDevice->pMemView->uIntMem.MemBlock32K[0x300])))
+            {
+                pDevice->EnablePciXFix = TRUE;
+            }
+        }
+    }
+#endif
+#if 1
+    /*
+    *  This code was at the beginning of else block below, but that's
+    *  a bug if node address in shared memory.
+    */
+    MM_Wait(50);
+    LM_NvramInit(pDevice);
+#endif
+    /* Get the node address.  First try to get in from the shared memory. */
+    /* If the signature is not present, then get it from the NVRAM. */
+    Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_HIGH_MAILBOX);
+    if((Value32 >> 16) == 0x484b)
+    {
+
+        pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 8);
+        pDevice->NodeAddress[1] = (LM_UINT8) Value32;
+
+        Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_LOW_MAILBOX);
+
+        pDevice->NodeAddress[2] = (LM_UINT8) (Value32 >> 24);
+        pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 16);
+        pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 8);
+        pDevice->NodeAddress[5] = (LM_UINT8) Value32;
+
+        Status = LM_STATUS_SUCCESS;
+    }
+    else
+    {
+        Status = LM_NvramRead(pDevice, 0x7c, &Value32);
+        if(Status == LM_STATUS_SUCCESS)
+        {
+            pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 16);
+            pDevice->NodeAddress[1] = (LM_UINT8) (Value32 >> 24);
+
+            Status = LM_NvramRead(pDevice, 0x80, &Value32);
+
+            pDevice->NodeAddress[2] = (LM_UINT8) Value32;
+            pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 8);
+            pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 16);
+            pDevice->NodeAddress[5] = (LM_UINT8) (Value32 >> 24);
+        }
+    }
+
+    /* Assign a default address. */
+    if(Status != LM_STATUS_SUCCESS)
+    {
+#ifndef EMBEDDED
+        printk(KERN_ERR "Cannot get MAC addr from NVRAM. Using default.\n");
+#endif
+        pDevice->NodeAddress[0] = 0x00; pDevice->NodeAddress[1] = 0x10;
+        pDevice->NodeAddress[2] = 0x18; pDevice->NodeAddress[3] = 0x68;
+        pDevice->NodeAddress[4] = 0x61; pDevice->NodeAddress[5] = 0x76;
+    }
+
+    pDevice->PermanentNodeAddress[0] = pDevice->NodeAddress[0];
+    pDevice->PermanentNodeAddress[1] = pDevice->NodeAddress[1];
+    pDevice->PermanentNodeAddress[2] = pDevice->NodeAddress[2];
+    pDevice->PermanentNodeAddress[3] = pDevice->NodeAddress[3];
+    pDevice->PermanentNodeAddress[4] = pDevice->NodeAddress[4];
+    pDevice->PermanentNodeAddress[5] = pDevice->NodeAddress[5];
+
+    /* Initialize the default values. */
+    pDevice->NoTxPseudoHdrChksum = FALSE;
+    pDevice->NoRxPseudoHdrChksum = FALSE;
+    pDevice->NicSendBd = FALSE;
+    pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT;
+    pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT;
+    pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS;
+    pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS;
+    pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES;
+    pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES;
+    pDevice->RxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->TxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->RxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->TxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS;
+    pDevice->EnableMWI = FALSE;
+    pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+    pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+    pDevice->DisableAutoNeg = FALSE;
+    pDevice->PhyIntMode = T3_PHY_INT_MODE_AUTO;
+    pDevice->LinkChngMode = T3_LINK_CHNG_MODE_AUTO;
+    pDevice->LedMode = LED_MODE_AUTO;
+    pDevice->ResetPhyOnInit = TRUE;
+    pDevice->DelayPciGrant = TRUE;
+    pDevice->UseTaggedStatus = FALSE;
+    pDevice->OneDmaAtOnce = BAD_DEFAULT_VALUE;
+
+    pDevice->DmaMbufLowMark = T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO;
+    pDevice->RxMacMbufLowMark = T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO;
+    pDevice->MbufHighMark = T3_DEF_MBUF_HIGH_WMARK_JUMBO;
+
+    pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO;
+    pDevice->TaskOffloadCap = LM_TASK_OFFLOAD_NONE;
+    pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE;
+    pDevice->EnableTbi = FALSE;
+#if INCLUDE_TBI_SUPPORT
+    pDevice->PollTbiLink = BAD_DEFAULT_VALUE;
+#endif
+
+    switch (T3_ASIC_REV(pDevice->ChipRevId))
+    {
+    case T3_ASIC_REV_5704:
+        pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR;
+        pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE64;
+        break;
+    default:
+        pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR;
+        pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE96;
+        break;
+    }
+
+    pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+    pDevice->QueueRxPackets = TRUE;
+
+    pDevice->EnableWireSpeed = TRUE;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Make this is a known adapter. */
+    pAdapterInfo = LM_GetAdapterInfoBySsid(pDevice->SubsystemVendorId,
+        pDevice->SubsystemId);
+
+    pDevice->BondId = REG_RD(pDevice, Grc.MiscCfg) & GRC_MISC_BD_ID_MASK;
+    if (pDevice->BondId != GRC_MISC_BD_ID_5700 &&
+        pDevice->BondId != GRC_MISC_BD_ID_5701 &&
+        pDevice->BondId != GRC_MISC_BD_ID_5702FE &&
+        pDevice->BondId != GRC_MISC_BD_ID_5703 &&
+        pDevice->BondId != GRC_MISC_BD_ID_5703S &&
+        pDevice->BondId != GRC_MISC_BD_ID_5704 &&
+        pDevice->BondId != GRC_MISC_BD_ID_5704CIOBE)
+    {
+        return LM_STATUS_UNKNOWN_ADAPTER;
+    }
+
+    pDevice->SplitModeEnable = SPLIT_MODE_DISABLE;
+    if ((pDevice->ChipRevId == T3_CHIP_ID_5704_A0) &&
+        (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE))
+    {
+        pDevice->SplitModeEnable = SPLIT_MODE_ENABLE;
+        pDevice->SplitModeMaxReq = SPLIT_MODE_5704_MAX_REQ;
+    }
+
+    /* Get Eeprom info. */
+    Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_SIG_ADDR);
+    if (Value32 == T3_NIC_DATA_SIG)
+    {
+        EeSigFound = TRUE;
+        Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_NIC_CFG_ADDR);
+
+        /* Determine PHY type. */
+        switch (Value32 & T3_NIC_CFG_PHY_TYPE_MASK)
+        {
+            case T3_NIC_CFG_PHY_TYPE_COPPER:
+                EePhyTypeSerdes = FALSE;
+                break;
+
+            case T3_NIC_CFG_PHY_TYPE_FIBER:
+                EePhyTypeSerdes = TRUE;
+                break;
+
+            default:
+                EePhyTypeSerdes = FALSE;
+                break;
+        }
+
+        /* Determine PHY led mode. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            switch(Value32 & T3_NIC_CFG_LED_MODE_MASK)
+            {
+                case T3_NIC_CFG_LED_MODE_TRIPLE_SPEED:
+                    EePhyLedMode = LED_MODE_THREE_LINK;
+                    break;
+
+                case T3_NIC_CFG_LED_MODE_LINK_SPEED:
+                    EePhyLedMode = LED_MODE_LINK10;
+                    break;
+
+                default:
+                    EePhyLedMode = LED_MODE_AUTO;
+                    break;
+            }
+        }
+        else
+        {
+            switch(Value32 & T3_NIC_CFG_LED_MODE_MASK)
+            {
+                case T3_NIC_CFG_LED_MODE_OPEN_DRAIN:
+                    EePhyLedMode = LED_MODE_OPEN_DRAIN;
+                    break;
+
+                case T3_NIC_CFG_LED_MODE_OUTPUT:
+                    EePhyLedMode = LED_MODE_OUTPUT;
+                    break;
+
+                default:
+                    EePhyLedMode = LED_MODE_AUTO;
+                    break;
+            }
+        }
+        if(pDevice->ChipRevId == T3_CHIP_ID_5703_A1 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5703_A2)
+        {
+            /* Enable EEPROM write protection. */
+            if(Value32 & T3_NIC_EEPROM_WP)
+            {
+                pDevice->EepromWp = TRUE;
+            }
+        }
+
+        /* Get the PHY Id. */
+        Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_PHY_ID_ADDR);
+        if (Value32)
+        {
+            EePhyId = (((Value32 & T3_NIC_PHY_ID1_MASK) >> 16) &
+                PHY_ID1_OUI_MASK) << 10;
+
+            Value32 = Value32 & T3_NIC_PHY_ID2_MASK;
+
+            EePhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) |
+              (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK);
+        }
+        else
+        {
+            EePhyId = 0;
+        }
+    }
+    else
+    {
+        EeSigFound = FALSE;
+    }
+
+    /* Set the PHY address. */
+    pDevice->PhyAddr = PHY_DEVICE_ID;
+
+    /* Disable auto polling. */
+    pDevice->MiMode = 0xc0000;
+    REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+    MM_Wait(40);
+
+    /* Get the PHY id. */
+    LM_ReadPhy(pDevice, PHY_ID1_REG, &Value32);
+    pDevice->PhyId = (Value32 & PHY_ID1_OUI_MASK) << 10;
+
+    LM_ReadPhy(pDevice, PHY_ID2_REG, &Value32);
+    pDevice->PhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) |
+      (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK);
+
+    /* Set the EnableTbi flag to false if we have a copper PHY. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM5400_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5401_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5411_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5701_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5703_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM5704_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM8002_PHY_ID:
+            pDevice->EnableTbi = TRUE;
+            break;
+
+        default:
+
+            if (pAdapterInfo)
+            {
+                pDevice->PhyId = pAdapterInfo->PhyId;
+                pDevice->EnableTbi = pAdapterInfo->Serdes;
+            }
+            else if (EeSigFound)
+            {
+                pDevice->PhyId = EePhyId;
+                pDevice->EnableTbi = EePhyTypeSerdes;
+            }
+            break;
+    }
+
+    /* Bail out if we don't know the copper PHY id. */
+    if(UNKNOWN_PHY_ID(pDevice->PhyId) && !pDevice->EnableTbi)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+    {
+        if((pDevice->SavedCacheLineReg & 0xff00) < 0x4000)
+        {
+            pDevice->SavedCacheLineReg &= 0xffff00ff;
+            pDevice->SavedCacheLineReg |= 0x4000;
+        }
+    }
+    /* Change driver parameters. */
+    Status = MM_GetConfig(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+#if INCLUDE_5701_AX_FIX
+    if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+    {
+        pDevice->ResetPhyOnInit = TRUE;
+    }
+#endif
+
+    /* Save the current phy link status. */
+    if(!pDevice->EnableTbi)
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+        /* If we don't have link reset the PHY. */
+        if(!(Value32 & PHY_STATUS_LINK_PASS) || pDevice->ResetPhyOnInit)
+        {
+
+            LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+
+            for(j = 0; j < 100; j++)
+            {
+                MM_Wait(10);
+
+                LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+                if(Value32 && !(Value32 & PHY_CTRL_PHY_RESET))
+                {
+                    MM_Wait(40);
+                    break;
+                }
+            }
+
+
+#if INCLUDE_5701_AX_FIX
+            /* 5701_AX_BX bug:  only advertises 10mb speed. */
+            if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+                pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+            {
+
+                Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD |
+                    PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL |
+                    PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF;
+                Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+                LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+                pDevice->advertising = Value32;
+
+                Value32 = BCM540X_AN_AD_1000BASET_HALF |
+                    BCM540X_AN_AD_1000BASET_FULL | BCM540X_CONFIG_AS_MASTER |
+                    BCM540X_ENABLE_CONFIG_AS_MASTER;
+                LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+                pDevice->advertising1000 = Value32;
+
+                LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
+                    PHY_CTRL_RESTART_AUTO_NEG);
+            }
+#endif
+            if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+            {
+                LM_WritePhy(pDevice, 0x18, 0x0c00);
+                LM_WritePhy(pDevice, 0x17, 0x201f);
+                LM_WritePhy(pDevice, 0x15, 0x2aaa);
+            }
+            if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+            {
+                LM_WritePhy(pDevice, 0x1c, 0x8d68);
+                LM_WritePhy(pDevice, 0x1c, 0x8d68);
+            }
+            /* Enable Ethernet@WireSpeed. */
+            if(pDevice->EnableWireSpeed)
+            {
+                LM_WritePhy(pDevice, 0x18, 0x7007);
+                LM_ReadPhy(pDevice, 0x18, &Value32);
+                LM_WritePhy(pDevice, 0x18, Value32 | BIT_15 | BIT_4);
+            }
+        }
+    }
+
+    /* Turn off tap power management. */
+    if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+    {
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0c20);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+
+        MM_Wait(40);
+    }
+
+#if INCLUDE_TBI_SUPPORT
+    pDevice->IgnoreTbiLinkChange = FALSE;
+
+    if(pDevice->EnableTbi)
+    {
+        pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
+        pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+        if ((pDevice->PollTbiLink == BAD_DEFAULT_VALUE) ||
+            pDevice->DisableAutoNeg)
+        {
+            pDevice->PollTbiLink = FALSE;
+        }
+    }
+    else
+    {
+        pDevice->PollTbiLink = FALSE;
+    }
+#endif /* INCLUDE_TBI_SUPPORT */
+
+    /* UseTaggedStatus is only valid for 5701 and later. */
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        pDevice->UseTaggedStatus = FALSE;
+
+        pDevice->CoalesceMode = 0;
+    }
+    else
+    {
+        pDevice->CoalesceMode = HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT |
+            HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT;
+    }
+
+    /* Set the status block size. */
+    if(T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_AX &&
+        T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_BX)
+    {
+        pDevice->CoalesceMode |= HOST_COALESCE_32_BYTE_STATUS_MODE;
+    }
+
+    /* Check the DURING_INT coalescing ticks parameters. */
+    if(pDevice->UseTaggedStatus)
+    {
+        if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxCoalescingTicksDuringInt =
+                DEFAULT_RX_COALESCING_TICKS_DURING_INT;
+        }
+
+        if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxCoalescingTicksDuringInt =
+                DEFAULT_TX_COALESCING_TICKS_DURING_INT;
+        }
+
+        if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxMaxCoalescedFramesDuringInt =
+                DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT;
+        }
+
+        if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxMaxCoalescedFramesDuringInt =
+                DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT;
+        }
+    }
+    else
+    {
+        if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxCoalescingTicksDuringInt = 0;
+        }
+
+        if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxCoalescingTicksDuringInt = 0;
+        }
+
+        if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxMaxCoalescedFramesDuringInt = 0;
+        }
+
+        if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxMaxCoalescedFramesDuringInt = 0;
+        }
+    }
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    if(pDevice->RxMtu <= (MAX_STD_RCV_BUFFER_SIZE - 8 /* CRC */))
+    {
+        pDevice->RxJumboDescCnt = 0;
+        if(pDevice->RxMtu <= MAX_ETHERNET_PACKET_SIZE_NO_CRC)
+        {
+            pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+        }
+    }
+    else
+    {
+        pDevice->RxJumboBufferSize = (pDevice->RxMtu + 8 /* CRC + VLAN */ +
+            COMMON_CACHE_LINE_SIZE-1) & ~COMMON_CACHE_LINE_MASK;
+
+        if(pDevice->RxJumboBufferSize > MAX_JUMBO_RCV_BUFFER_SIZE)
+        {
+            pDevice->RxJumboBufferSize = DEFAULT_JUMBO_RCV_BUFFER_SIZE;
+            pDevice->RxMtu = pDevice->RxJumboBufferSize - 8 /* CRC + VLAN */;
+        }
+        pDevice->TxMtu = pDevice->RxMtu;
+
+    }
+#else
+    pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    pDevice->RxPacketDescCnt =
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+        pDevice->RxJumboDescCnt +
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+        pDevice->RxStdDescCnt;
+
+    if(pDevice->TxMtu < MAX_ETHERNET_PACKET_SIZE_NO_CRC)
+    {
+        pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+    }
+
+    if(pDevice->TxMtu > MAX_JUMBO_TX_BUFFER_SIZE)
+    {
+        pDevice->TxMtu = MAX_JUMBO_TX_BUFFER_SIZE;
+    }
+
+    /* Configure the proper ways to get link change interrupt. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO)
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+        }
+        else
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+        }
+    }
+    else if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        /* Auto-polling does not work on 5700_AX and 5700_BX. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+        }
+    }
+
+    /* Determine the method to get link change status. */
+    if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_AUTO)
+    {
+        /* The link status bit in the status block does not work on 5700_AX */
+        /* and 5700_BX chips. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+        }
+        else
+        {
+            pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_BLOCK;
+        }
+    }
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+    }
+
+    /* Configure PHY led mode. */
+    if(pDevice->LedMode == LED_MODE_AUTO)
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            if(pDevice->SubsystemVendorId == T3_SVID_DELL)
+            {
+                pDevice->LedMode = LED_MODE_LINK10;
+            }
+            else
+            {
+                pDevice->LedMode = LED_MODE_THREE_LINK;
+
+                if(EeSigFound && EePhyLedMode != LED_MODE_AUTO)
+                {
+                    pDevice->LedMode = EePhyLedMode;
+                }
+            }
+
+            /* bug? 5701 in LINK10 mode does not seem to work when */
+            /* PhyIntMode is LINK_READY. */
+            if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+#if INCLUDE_TBI_SUPPORT
+                pDevice->EnableTbi == FALSE &&
+#endif
+                pDevice->LedMode == LED_MODE_LINK10)
+            {
+                pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+                pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+            }
+
+            if(pDevice->EnableTbi)
+            {
+                pDevice->LedMode = LED_MODE_THREE_LINK;
+            }
+        }
+        else
+        {
+            if(EeSigFound && EePhyLedMode != LED_MODE_AUTO)
+            {
+                pDevice->LedMode = EePhyLedMode;
+            }
+            else
+            {
+                pDevice->LedMode = LED_MODE_OPEN_DRAIN;
+            }
+        }
+    }
+
+    /* Enable OneDmaAtOnce. */
+    if(pDevice->OneDmaAtOnce == BAD_DEFAULT_VALUE)
+    {
+        pDevice->OneDmaAtOnce = FALSE;
+    }
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_B0 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_B2)
+    {
+        pDevice->WolSpeed = WOL_SPEED_10MB;
+    }
+    else
+    {
+        pDevice->WolSpeed = WOL_SPEED_100MB;
+    }
+
+    /* Offloadings. */
+    pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+
+    /* Turn off task offloading on Ax. */
+    if(pDevice->ChipRevId == T3_CHIP_ID_5700_B0)
+    {
+        pDevice->TaskOffloadCap &= ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+            LM_TASK_OFFLOAD_TX_UDP_CHECKSUM);
+    }
+    pDevice->PciState = REG_RD(pDevice, PciCfg.PciState);
+    LM_ReadVPD(pDevice);
+    LM_ReadBootCodeVersion(pDevice);
+    LM_GetBusSpeed(pDevice);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_GetAdapterInfo */
+
+STATIC PLM_ADAPTER_INFO
+LM_GetAdapterInfoBySsid(
+    LM_UINT16 Svid,
+    LM_UINT16 Ssid)
+{
+    static LM_ADAPTER_INFO AdapterArr[] =
+    {
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A6, PHY_BCM5401_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A5, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700T6, PHY_BCM8002_PHY_ID, 1},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A9, 0, 1 },
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T1, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T8, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A7, 0, 1},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A10, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A12, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax1, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax2, PHY_BCM5701_PHY_ID, 0},
+
+        { T3_SVID_3COM, T3_SSID_3COM_3C996T, PHY_BCM5401_PHY_ID, 0 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C996BT, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C996SX, 0, 1 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C1000T, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C940BR01, PHY_BCM5701_PHY_ID, 0 },
+
+        { T3_SVID_DELL, T3_SSID_DELL_VIPER, PHY_BCM5401_PHY_ID, 0 },
+        { T3_SVID_DELL, T3_SSID_DELL_JAGUAR, PHY_BCM5401_PHY_ID, 0 },
+        { T3_SVID_DELL, T3_SSID_DELL_MERLOT, PHY_BCM5411_PHY_ID, 0 },
+        { T3_SVID_DELL, T3_SSID_DELL_SLIM_MERLOT, PHY_BCM5411_PHY_ID, 0 },
+
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE_2, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_CHANGELING, 0, 1 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780_2, PHY_BCM5701_PHY_ID, 0 },
+
+    };
+    LM_UINT32 j;
+
+    for(j = 0; j < sizeof(AdapterArr)/sizeof(LM_ADAPTER_INFO); j++)
+    {
+        if(AdapterArr[j].Svid == Svid && AdapterArr[j].Ssid == Ssid)
+        {
+            return &AdapterArr[j];
+        }
+    }
+
+    return NULL;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine sets up receive/transmit buffer descriptions queues.       */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_InitializeAdapter(
+PLM_DEVICE_BLOCK pDevice)
+{
+    LM_PHYSICAL_ADDRESS MemPhy;
+    PLM_UINT8 pMemVirt;
+    PLM_PACKET pPacket;
+    LM_STATUS Status;
+    LM_UINT32 Size;
+    LM_UINT32 j;
+
+    /* Set power state to D0. */
+    LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+
+    /* Intialize the queues. */
+    QQ_InitQueue(&pDevice->RxPacketReceivedQ.Container,
+        MAX_RX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->RxPacketFreeQ.Container,
+        MAX_RX_PACKET_DESC_COUNT);
+
+    QQ_InitQueue(&pDevice->TxPacketFreeQ.Container,MAX_TX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->TxPacketActiveQ.Container,MAX_TX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->TxPacketXmittedQ.Container,MAX_TX_PACKET_DESC_COUNT);
+
+    /* Allocate shared memory for: status block, the buffers for receive */
+    /* rings -- standard, mini, jumbo, and return rings. */
+    Size = T3_STATUS_BLOCK_SIZE + sizeof(T3_STATS_BLOCK) +
+        T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD) +
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+        T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD) +
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+        T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+
+    /* Memory for host based Send BD. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        Size += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT;
+    }
+
+    /* Allocate the memory block. */
+    Status = MM_AllocateSharedMemory(pDevice, Size, (PLM_VOID) &pMemVirt, &MemPhy, FALSE);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* Program DMA Read/Write */
+    if (pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS)
+    {
+        pDevice->DmaReadWriteCtrl = 0x763f000f;
+    }
+    else
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+        {
+            pDevice->DmaReadWriteCtrl = 0x761f0000;
+        }
+        else
+        {
+            pDevice->DmaReadWriteCtrl = 0x761b000f;
+        }
+        if(pDevice->ChipRevId == T3_CHIP_ID_5703_A1 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5703_A2)
+        {
+            pDevice->OneDmaAtOnce = TRUE;
+        }
+    }
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+    {
+        pDevice->DmaReadWriteCtrl &= 0xfffffff0;
+    }
+
+    if(pDevice->OneDmaAtOnce)
+    {
+        pDevice->DmaReadWriteCtrl |= DMA_CTRL_WRITE_ONE_DMA_AT_ONCE;
+    }
+    REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl);
+
+    if (LM_DmaTest(pDevice, pMemVirt, MemPhy, 0x400) != LM_STATUS_SUCCESS)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Status block. */
+    pDevice->pStatusBlkVirt = (PT3_STATUS_BLOCK) pMemVirt;
+    pDevice->StatusBlkPhy = MemPhy;
+    pMemVirt += T3_STATUS_BLOCK_SIZE;
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy, T3_STATUS_BLOCK_SIZE);
+
+    /* Statistics block. */
+    pDevice->pStatsBlkVirt = (PT3_STATS_BLOCK) pMemVirt;
+    pDevice->StatsBlkPhy = MemPhy;
+    pMemVirt += sizeof(T3_STATS_BLOCK);
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy, sizeof(T3_STATS_BLOCK));
+
+    /* Receive standard BD buffer. */
+    pDevice->pRxStdBdVirt = (PT3_RCV_BD) pMemVirt;
+    pDevice->RxStdBdPhy = MemPhy;
+
+    pMemVirt += T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy,
+        T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD));
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Receive jumbo BD buffer. */
+    pDevice->pRxJumboBdVirt = (PT3_RCV_BD) pMemVirt;
+    pDevice->RxJumboBdPhy = MemPhy;
+
+    pMemVirt += T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy,
+        T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD));
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Receive return BD buffer. */
+    pDevice->pRcvRetBdVirt = (PT3_RCV_BD) pMemVirt;
+    pDevice->RcvRetBdPhy = MemPhy;
+
+    pMemVirt += T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy,
+        T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD));
+
+    /* Set up Send BD. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        pDevice->pSendBdVirt = (PT3_SND_BD) pMemVirt;
+        pDevice->SendBdPhy = MemPhy;
+
+        pMemVirt += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT;
+        LM_INC_PHYSICAL_ADDRESS(&MemPhy,
+            sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT);
+    }
+    else
+    {
+        pDevice->pSendBdVirt = (PT3_SND_BD)
+            pDevice->pMemView->uIntMem.First32k.BufferDesc;
+        pDevice->SendBdPhy.High = 0;
+        pDevice->SendBdPhy.Low = T3_NIC_SND_BUFFER_DESC_ADDR;
+    }
+
+    /* Allocate memory for packet descriptors. */
+    Size = (pDevice->RxPacketDescCnt +
+        pDevice->TxPacketDescCnt) * MM_PACKET_DESC_SIZE;
+    Status = MM_AllocateMemory(pDevice, Size, (PLM_VOID *) &pPacket);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->pPacketDescBase = (PLM_VOID) pPacket;
+
+    /* Create transmit packet descriptors from the memory block and add them */
+    /* to the TxPacketFreeQ for each send ring. */
+    for(j = 0; j < pDevice->TxPacketDescCnt; j++)
+    {
+        /* Ring index. */
+        pPacket->Flags = 0;
+
+        /* Queue the descriptor in the TxPacketFreeQ of the 'k' ring. */
+        QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+
+        /* Get the pointer to the next descriptor.  MM_PACKET_DESC_SIZE */
+        /* is the total size of the packet descriptor including the */
+        /* os-specific extensions in the UM_PACKET structure. */
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+    } /* for(j.. */
+
+    /* Create receive packet descriptors from the memory block and add them */
+    /* to the RxPacketFreeQ.  Create the Standard packet descriptors. */
+    for(j = 0; j < pDevice->RxStdDescCnt; j++)
+    {
+        /* Receive producer ring. */
+        pPacket->u.Rx.RcvProdRing = T3_STD_RCV_PROD_RING;
+
+        /* Receive buffer size. */
+        pPacket->u.Rx.RxBufferSize = MAX_STD_RCV_BUFFER_SIZE;
+
+        /* Add the descriptor to RxPacketFreeQ. */
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        /* Get the pointer to the next descriptor.  MM_PACKET_DESC_SIZE */
+        /* is the total size of the packet descriptor including the */
+        /* os-specific extensions in the UM_PACKET structure. */
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+    } /* for */
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Create the Jumbo packet descriptors. */
+    for(j = 0; j < pDevice->RxJumboDescCnt; j++)
+    {
+        /* Receive producer ring. */
+        pPacket->u.Rx.RcvProdRing = T3_JUMBO_RCV_PROD_RING;
+
+        /* Receive buffer size. */
+        pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize;
+
+        /* Add the descriptor to RxPacketFreeQ. */
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        /* Get the pointer to the next descriptor.  MM_PACKET_DESC_SIZE */
+        /* is the total size of the packet descriptor including the */
+        /* os-specific extensions in the UM_PACKET structure. */
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+    } /* for */
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Initialize the rest of the packet descriptors. */
+    Status = MM_InitializeUmPackets(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    } /* if */
+
+    /* Default receive mask. */
+    pDevice->ReceiveMask = LM_ACCEPT_MULTICAST | LM_ACCEPT_BROADCAST |
+        LM_ACCEPT_UNICAST;
+
+    /* Make sure we are in the first 32k memory window or NicSendBd. */
+    REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0);
+
+    /* Initialize the hardware. */
+    Status = LM_ResetAdapter(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* We are done with initialization. */
+    pDevice->InitDone = TRUE;
+
+    return LM_STATUS_SUCCESS;
+} /* LM_InitializeAdapter */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This function Enables/Disables a given block.                          */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_CntrlBlock(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 mask,LM_UINT32 cntrl)
+{
+    LM_UINT32 j,i,data;
+    LM_UINT32 MaxWaitCnt;
+
+    MaxWaitCnt = 2;
+    j = 0;
+
+    for(i = 0 ; i < 32; i++)
+    {
+        if(!(mask & (1 << i)))
+            continue;
+
+        switch (1 << i)
+        {
+            case T3_BLOCK_DMA_RD:
+                data = REG_RD(pDevice, DmaRead.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~DMA_READ_MODE_ENABLE;
+                    REG_WR(pDevice, DmaRead.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, DmaRead.Mode) & DMA_READ_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, DmaRead.Mode, data | DMA_READ_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_DMA_COMP:
+                data = REG_RD(pDevice,DmaComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~DMA_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, DmaComp.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, DmaComp.Mode) & DMA_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, DmaComp.Mode, data | DMA_COMP_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_BD_INITIATOR:
+                data = REG_RD(pDevice, RcvBdIn.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_BD_IN_MODE_ENABLE;
+                    REG_WR(pDevice, RcvBdIn.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, RcvBdIn.Mode) & RCV_BD_IN_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, RcvBdIn.Mode,data | RCV_BD_IN_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_BD_COMP:
+                data = REG_RD(pDevice, RcvBdComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_BD_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, RcvBdComp.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, RcvBdComp.Mode) & RCV_BD_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, RcvBdComp.Mode,data | RCV_BD_COMP_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_DMA_WR:
+                data = REG_RD(pDevice, DmaWrite.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~DMA_WRITE_MODE_ENABLE;
+                    REG_WR(pDevice, DmaWrite.Mode,data);
+
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, DmaWrite.Mode) & DMA_WRITE_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, DmaWrite.Mode,data | DMA_WRITE_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_MSI_HANDLER:
+                data = REG_RD(pDevice, Msi.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~MSI_MODE_ENABLE;
+                    REG_WR(pDevice, Msi.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, Msi.Mode) & MSI_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, Msi.Mode, data |MSI_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_LIST_PLMT:
+                data = REG_RD(pDevice, RcvListPlmt.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_LIST_PLMT_MODE_ENABLE;
+                    REG_WR(pDevice, RcvListPlmt.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, RcvListPlmt.Mode) & RCV_LIST_PLMT_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, RcvListPlmt.Mode,data | RCV_LIST_PLMT_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_LIST_SELECTOR:
+                data = REG_RD(pDevice, RcvListSel.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_LIST_SEL_MODE_ENABLE;
+                    REG_WR(pDevice, RcvListSel.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, RcvListSel.Mode) & RCV_LIST_SEL_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, RcvListSel.Mode,data |RCV_LIST_SEL_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_DATA_INITIATOR:
+                data = REG_RD(pDevice, RcvDataBdIn.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_DATA_BD_IN_MODE_ENABLE;
+                    REG_WR(pDevice, RcvDataBdIn.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_BD_IN_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, RcvDataBdIn.Mode, data | RCV_DATA_BD_IN_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_RX_DATA_COMP:
+                data = REG_RD(pDevice, RcvDataComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~RCV_DATA_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, RcvDataComp.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, RcvDataComp.Mode,data | RCV_DATA_COMP_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_HOST_COALESING:
+                data = REG_RD(pDevice, HostCoalesce.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~HOST_COALESCE_ENABLE;
+                    REG_WR(pDevice, HostCoalesce.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, SndBdIn.Mode) & HOST_COALESCE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, HostCoalesce.Mode, data | HOST_COALESCE_ENABLE);
+                break;
+
+            case T3_BLOCK_MAC_RX_ENGINE:
+                if(cntrl == LM_DISABLE)
+                {
+                    pDevice->RxMode &= ~RX_MODE_ENABLE;
+                    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, MacCtrl.RxMode) & RX_MODE_ENABLE))
+                        {
+                            break;
+                        }
+                        MM_Wait(10);
+                    }
+                }
+                else
+                {
+                    pDevice->RxMode |= RX_MODE_ENABLE;
+                    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+                }
+                break;
+
+            case T3_BLOCK_MBUF_CLUSTER_FREE:
+                data = REG_RD(pDevice, MbufClusterFree.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~MBUF_CLUSTER_FREE_MODE_ENABLE;
+                    REG_WR(pDevice, MbufClusterFree.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, MbufClusterFree.Mode) & MBUF_CLUSTER_FREE_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, MbufClusterFree.Mode, data | MBUF_CLUSTER_FREE_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_SEND_BD_INITIATOR:
+                data = REG_RD(pDevice, SndBdIn.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~SND_BD_IN_MODE_ENABLE;
+                    REG_WR(pDevice, SndBdIn.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, SndBdIn.Mode) & SND_BD_IN_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndBdIn.Mode, data  | SND_BD_IN_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_SEND_BD_COMP:
+                data = REG_RD(pDevice, SndBdComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~SND_BD_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, SndBdComp.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, SndBdComp.Mode) & SND_BD_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndBdComp.Mode, data | SND_BD_COMP_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_SEND_BD_SELECTOR:
+                data = REG_RD(pDevice, SndBdSel.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~SND_BD_SEL_MODE_ENABLE;
+                    REG_WR(pDevice, SndBdSel.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, SndBdSel.Mode) & SND_BD_SEL_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndBdSel.Mode, data | SND_BD_SEL_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_SEND_DATA_INITIATOR:
+                data = REG_RD(pDevice, SndDataIn.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~T3_SND_DATA_IN_MODE_ENABLE;
+                    REG_WR(pDevice, SndDataIn.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, SndDataIn.Mode) & T3_SND_DATA_IN_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndDataIn.Mode,data | T3_SND_DATA_IN_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_SEND_DATA_COMP:
+                data = REG_RD(pDevice, SndDataComp.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~SND_DATA_COMP_MODE_ENABLE;
+                    REG_WR(pDevice, SndDataComp.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, SndDataComp.Mode) & SND_DATA_COMP_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, SndDataComp.Mode,data | SND_DATA_COMP_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_MAC_TX_ENGINE:
+                if(cntrl == LM_DISABLE)
+                {
+                    pDevice->TxMode &= ~TX_MODE_ENABLE;
+                    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, MacCtrl.TxMode) & TX_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                {
+                    pDevice->TxMode |= TX_MODE_ENABLE;
+                    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+                }
+                break;
+
+            case T3_BLOCK_MEM_ARBITOR:
+                data = REG_RD(pDevice, MemArbiter.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~T3_MEM_ARBITER_MODE_ENABLE;
+                    REG_WR(pDevice, MemArbiter.Mode, data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, MemArbiter.Mode) & T3_MEM_ARBITER_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, MemArbiter.Mode,data|T3_MEM_ARBITER_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_MBUF_MANAGER:
+                data = REG_RD(pDevice, BufMgr.Mode);
+                if (cntrl == LM_DISABLE)
+                {
+                    data &= ~BUFMGR_MODE_ENABLE;
+                    REG_WR(pDevice, BufMgr.Mode,data);
+                    for(j = 0; j < MaxWaitCnt; j++)
+                    {
+                        if(!(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE))
+                            break;
+                        MM_Wait(10);
+                    }
+                }
+                else
+                    REG_WR(pDevice, BufMgr.Mode,data |  BUFMGR_MODE_ENABLE);
+                break;
+
+            case T3_BLOCK_MAC_GLOBAL:
+                if(cntrl == LM_DISABLE)
+                {
+                    pDevice->MacMode &= ~(MAC_MODE_ENABLE_TDE |
+                        MAC_MODE_ENABLE_RDE |
+                        MAC_MODE_ENABLE_FHDE);
+                }
+                else
+                {
+                    pDevice->MacMode |= (MAC_MODE_ENABLE_TDE |
+                        MAC_MODE_ENABLE_RDE |
+                        MAC_MODE_ENABLE_FHDE);
+                }
+                REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+                break;
+
+            default:
+                return LM_STATUS_FAILURE;
+        } /* switch */
+
+        if(j >= MaxWaitCnt)
+        {
+            return LM_STATUS_FAILURE;
+        }
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This function reinitializes the adapter.                                */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_ResetAdapter(
+PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT16 Value16;
+    LM_UINT32 j, k;
+
+    /* Disable interrupt. */
+    LM_DisableInterrupt(pDevice);
+
+    /* May get a spurious interrupt */
+    pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED;
+
+    /* Disable transmit and receive DMA engines.  Abort all pending requests. */
+    if(pDevice->InitDone)
+    {
+        LM_Abort(pDevice);
+    }
+
+    pDevice->ShuttingDown = FALSE;
+
+    LM_ResetChip(pDevice);
+
+    /* Bug: Athlon fix for B3 silicon only.  This bit does not do anything */
+    /* in other chip revisions. */
+    if(pDevice->DelayPciGrant)
+    {
+        Value32 = REG_RD(pDevice, PciCfg.ClockCtrl);
+        REG_WR(pDevice, PciCfg.ClockCtrl, Value32 | BIT_31);
+    }
+
+    if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+        {
+            Value32 = REG_RD(pDevice, PciCfg.PciState);
+            Value32 |= T3_PCI_STATE_RETRY_SAME_DMA;
+            REG_WR(pDevice, PciCfg.PciState, Value32);
+        }
+    }
+
+    /* Enable TaggedStatus mode. */
+    if(pDevice->UseTaggedStatus)
+    {
+        pDevice->MiscHostCtrl |= MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE;
+    }
+
+    /* Restore PCI configuration registers. */
+    MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG,
+        pDevice->SavedCacheLineReg);
+    MM_WriteConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG,
+        (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+
+    /* Clear the statistics block. */
+    for(j = 0x0300; j < 0x0b00; j++)
+    {
+        MEM_WR_OFFSET(pDevice, j, 0);
+    }
+
+    /* Initialize the statistis Block */
+    pDevice->pStatusBlkVirt->Status = 0;
+    pDevice->pStatusBlkVirt->RcvStdConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvJumboConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvMiniConIdx = 0;
+
+    for(j = 0; j < 16; j++)
+    {
+       pDevice->pStatusBlkVirt->Idx[j].RcvProdIdx = 0;
+       pDevice->pStatusBlkVirt->Idx[j].SendConIdx = 0;
+    }
+
+    for(k = 0; k < T3_STD_RCV_RCB_ENTRY_COUNT ;k++)
+    {
+       pDevice->pRxStdBdVirt[k].HostAddr.High = 0;
+       pDevice->pRxStdBdVirt[k].HostAddr.Low = 0;
+    }
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Receive jumbo BD buffer. */
+    for(k = 0; k < T3_JUMBO_RCV_RCB_ENTRY_COUNT; k++)
+    {
+        pDevice->pRxJumboBdVirt[k].HostAddr.High = 0;
+        pDevice->pRxJumboBdVirt[k].HostAddr.Low = 0;
+    }
+#endif
+
+    REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl);
+
+    /* GRC mode control register. */
+#ifdef BIG_ENDIAN_PCI    /* Jimmy, this ifdef block deleted in new code! */
+    Value32 =
+        GRC_MODE_WORD_SWAP_DATA |
+        GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+        GRC_MODE_INT_ON_MAC_ATTN |
+        GRC_MODE_HOST_STACK_UP;
+#else
+    /* No CPU Swap modes for PCI IO */
+    Value32 =
+#ifdef BIG_ENDIAN_HOST
+        GRC_MODE_BYTE_SWAP_NON_FRAME_DATA |
+        GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+        GRC_MODE_BYTE_SWAP_DATA |
+        GRC_MODE_WORD_SWAP_DATA |
+#else
+        GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+        GRC_MODE_BYTE_SWAP_DATA |
+        GRC_MODE_WORD_SWAP_DATA |
+#endif
+        GRC_MODE_INT_ON_MAC_ATTN |
+        GRC_MODE_HOST_STACK_UP;
+#endif /* !BIG_ENDIAN_PCI */
+
+    /* Configure send BD mode. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        Value32 |= GRC_MODE_HOST_SEND_BDS;
+    }
+    else
+    {
+        Value32 |= GRC_MODE_4X_NIC_BASED_SEND_RINGS;
+    }
+
+    /* Configure pseudo checksum mode. */
+    if(pDevice->NoTxPseudoHdrChksum)
+    {
+        Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM;
+    }
+
+    if(pDevice->NoRxPseudoHdrChksum)
+    {
+        Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM;
+    }
+
+    REG_WR(pDevice, Grc.Mode, Value32);
+
+    /* Setup the timer prescalar register. */
+    REG_WR(pDevice, Grc.MiscCfg, 65 << 1);      /* Clock is alwasy 66Mhz. */
+
+    /* Set up the MBUF pool base address and size. */
+    REG_WR(pDevice, BufMgr.MbufPoolAddr, pDevice->MbufBase);
+    REG_WR(pDevice, BufMgr.MbufPoolSize, pDevice->MbufSize);
+
+    /* Set up the DMA descriptor pool base address and size. */
+    REG_WR(pDevice, BufMgr.DmaDescPoolAddr, T3_NIC_DMA_DESC_POOL_ADDR);
+    REG_WR(pDevice, BufMgr.DmaDescPoolSize, T3_NIC_DMA_DESC_POOL_SIZE);
+
+    /* Configure MBUF and Threshold watermarks */
+    /* Configure the DMA read MBUF low water mark. */
+    if(pDevice->DmaMbufLowMark)
+    {
+        REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+            pDevice->DmaMbufLowMark);
+    }
+    else
+    {
+        if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+        {
+            REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+                T3_DEF_DMA_MBUF_LOW_WMARK);
+        }
+        else
+        {
+            REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+                T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO);
+        }
+    }
+
+    /* Configure the MAC Rx MBUF low water mark. */
+    if(pDevice->RxMacMbufLowMark)
+    {
+        REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+            pDevice->RxMacMbufLowMark);
+    }
+    else
+    {
+        if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+        {
+            REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+                T3_DEF_RX_MAC_MBUF_LOW_WMARK);
+        }
+        else
+        {
+            REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+                T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO);
+        }
+    }
+
+    /* Configure the MBUF high water mark. */
+    if(pDevice->MbufHighMark)
+    {
+        REG_WR(pDevice, BufMgr.MbufHighWaterMark, pDevice->MbufHighMark);
+    }
+    else
+    {
+        if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+        {
+            REG_WR(pDevice, BufMgr.MbufHighWaterMark,
+                T3_DEF_MBUF_HIGH_WMARK);
+        }
+        else
+        {
+            REG_WR(pDevice, BufMgr.MbufHighWaterMark,
+                T3_DEF_MBUF_HIGH_WMARK_JUMBO);
+        }
+    }
+
+    REG_WR(pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK);
+    REG_WR(pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK);
+
+    /* Enable buffer manager. */
+    REG_WR(pDevice, BufMgr.Mode, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
+
+    for(j = 0 ;j < 2000; j++)
+    {
+        if(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE)
+            break;
+        MM_Wait(10);
+    }
+
+    if(j >= 2000)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Enable the FTQs. */
+    REG_WR(pDevice, Ftq.Reset, 0xffffffff);
+    REG_WR(pDevice, Ftq.Reset, 0);
+
+    /* Wait until FTQ is ready */
+    for(j = 0; j < 2000; j++)
+    {
+        if(REG_RD(pDevice, Ftq.Reset) == 0)
+            break;
+        MM_Wait(10);
+    }
+
+    if(j >= 2000)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Initialize the Standard Receive RCB. */
+    REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.High,
+        pDevice->RxStdBdPhy.High);
+    REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.Low,
+        pDevice->RxStdBdPhy.Low);
+    REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.u.MaxLen_Flags,
+        MAX_STD_RCV_BUFFER_SIZE << 16);
+
+    /* Initialize the Jumbo Receive RCB. */
+    REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags,
+        T3_RCB_FLAG_RING_DISABLED);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.High,
+        pDevice->RxJumboBdPhy.High);
+    REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.Low,
+        pDevice->RxJumboBdPhy.Low);
+
+    REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, 0);
+
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Initialize the Mini Receive RCB. */
+    REG_WR(pDevice, RcvDataBdIn.MiniRcvRcb.u.MaxLen_Flags,
+        T3_RCB_FLAG_RING_DISABLED);
+
+    {
+        REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.NicRingAddr,
+            (LM_UINT32) T3_NIC_STD_RCV_BUFFER_DESC_ADDR);
+        REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.NicRingAddr,
+            (LM_UINT32) T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR);
+    }
+
+    /* Receive BD Ring replenish threshold. */
+    REG_WR(pDevice, RcvBdIn.StdRcvThreshold, pDevice->RxStdDescCnt/8);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    REG_WR(pDevice, RcvBdIn.JumboRcvThreshold, pDevice->RxJumboDescCnt/8);
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Disable all the unused rings. */
+    for(j = 0; j < T3_MAX_SEND_RCB_COUNT; j++) {
+        MEM_WR(pDevice, SendRcb[j].u.MaxLen_Flags, T3_RCB_FLAG_RING_DISABLED);
+    } /* for */
+
+    /* Initialize the indices. */
+    pDevice->SendProdIdx = 0;
+    pDevice->SendConIdx = 0;
+
+    MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, 0);
+    MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, 0);
+
+    /* Set up host or NIC based send RCB. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.High,
+            pDevice->SendBdPhy.High);
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.Low,
+            pDevice->SendBdPhy.Low);
+
+        /* Set up the NIC ring address in the RCB. */
+        MEM_WR(pDevice, SendRcb[0].NicRingAddr,T3_NIC_SND_BUFFER_DESC_ADDR);
+
+        /* Setup the RCB. */
+        MEM_WR(pDevice, SendRcb[0].u.MaxLen_Flags,
+            T3_SEND_RCB_ENTRY_COUNT << 16);
+
+        for(k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++)
+        {
+            pDevice->pSendBdVirt[k].HostAddr.High = 0;
+            pDevice->pSendBdVirt[k].HostAddr.Low = 0;
+        }
+    }
+    else
+    {
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.High, 0);
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.Low, 0);
+        MEM_WR(pDevice, SendRcb[0].NicRingAddr,
+            pDevice->SendBdPhy.Low);
+
+        for(k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++)
+        {
+            __raw_writel(0, &(pDevice->pSendBdVirt[k].HostAddr.High));
+            __raw_writel(0, &(pDevice->pSendBdVirt[k].HostAddr.Low));
+            __raw_writel(0, &(pDevice->pSendBdVirt[k].u1.Len_Flags));
+            pDevice->ShadowSendBd[k].HostAddr.High = 0;
+            pDevice->ShadowSendBd[k].u1.Len_Flags = 0;
+        }
+    }
+    atomic_set(&pDevice->SendBdLeft, T3_SEND_RCB_ENTRY_COUNT-1);
+
+    /* Configure the receive return rings. */
+    for(j = 0; j < T3_MAX_RCV_RETURN_RCB_COUNT; j++)
+    {
+        MEM_WR(pDevice, RcvRetRcb[j].u.MaxLen_Flags, T3_RCB_FLAG_RING_DISABLED);
+    }
+
+    pDevice->RcvRetConIdx = 0;
+
+    MEM_WR(pDevice, RcvRetRcb[0].HostRingAddr.High,
+        pDevice->RcvRetBdPhy.High);
+    MEM_WR(pDevice, RcvRetRcb[0].HostRingAddr.Low,
+        pDevice->RcvRetBdPhy.Low);
+
+    /* Set up the NIC ring address in the RCB. */
+    /* Not very clear from the spec.  I am guessing that for Receive */
+    /* Return Ring, NicRingAddr is not used. */
+    MEM_WR(pDevice, RcvRetRcb[0].NicRingAddr, 0);
+
+    /* Setup the RCB. */
+    MEM_WR(pDevice, RcvRetRcb[0].u.MaxLen_Flags,
+        T3_RCV_RETURN_RCB_ENTRY_COUNT << 16);
+
+    /* Reinitialize RX ring producer index */
+    MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low, 0);
+    MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low, 0);
+    MB_REG_WR(pDevice, Mailbox.RcvMiniProdIdx.Low, 0);
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    pDevice->RxJumboProdIdx = 0;
+    pDevice->RxJumboQueuedCnt = 0;
+#endif
+
+    /* Reinitialize our copy of the indices. */
+    pDevice->RxStdProdIdx = 0;
+    pDevice->RxStdQueuedCnt = 0;
+
+#if T3_JUMBO_RCV_ENTRY_COUNT
+    pDevice->RxJumboProdIdx = 0;
+#endif /* T3_JUMBO_RCV_ENTRY_COUNT */
+
+    /* Configure the MAC address. */
+    LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+    /* Initialize the transmit random backoff seed. */
+    Value32 = (pDevice->NodeAddress[0] + pDevice->NodeAddress[1] +
+        pDevice->NodeAddress[2] + pDevice->NodeAddress[3] +
+        pDevice->NodeAddress[4] + pDevice->NodeAddress[5]) &
+        MAC_TX_BACKOFF_SEED_MASK;
+    REG_WR(pDevice, MacCtrl.TxBackoffSeed, Value32);
+
+    /* Receive MTU.  Frames larger than the MTU is marked as oversized. */
+    REG_WR(pDevice, MacCtrl.MtuSize, pDevice->RxMtu + 8);   /* CRC + VLAN. */
+
+    /* Configure Time slot/IPG per 802.3 */
+    REG_WR(pDevice, MacCtrl.TxLengths, 0x2620);
+
+    /*
+     * Configure Receive Rules so that packets don't match
+     * Programmble rule will be queued to Return Ring 1
+     */
+    REG_WR(pDevice, MacCtrl.RcvRuleCfg, RX_RULE_DEFAULT_CLASS);
+
+    /*
+     * Configure to have 16 Classes of Services (COS) and one
+     * queue per class.  Bad frames are queued to RRR#1.
+     * And frames don't match rules are also queued to COS#1.
+     */
+    REG_WR(pDevice, RcvListPlmt.Config, 0x181);
+
+    /* Enable Receive Placement Statistics */
+    REG_WR(pDevice, RcvListPlmt.StatsEnableMask,0xffffff);
+    REG_WR(pDevice, RcvListPlmt.StatsCtrl, RCV_LIST_STATS_ENABLE);
+
+    /* Enable Send Data Initator Statistics */
+    REG_WR(pDevice, SndDataIn.StatsEnableMask,0xffffff);
+    REG_WR(pDevice, SndDataIn.StatsCtrl,
+        T3_SND_DATA_IN_STATS_CTRL_ENABLE | \
+        T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE);
+
+    /* Disable the host coalescing state machine before configuring it's */
+    /* parameters. */
+    REG_WR(pDevice, HostCoalesce.Mode, 0);
+    for(j = 0; j < 2000; j++)
+    {
+        Value32 = REG_RD(pDevice, HostCoalesce.Mode);
+        if(!(Value32 & HOST_COALESCE_ENABLE))
+        {
+            break;
+        }
+        MM_Wait(10);
+    }
+
+    /* Host coalescing configurations. */
+    REG_WR(pDevice, HostCoalesce.RxCoalescingTicks, pDevice->RxCoalescingTicks);
+    REG_WR(pDevice, HostCoalesce.TxCoalescingTicks, pDevice->TxCoalescingTicks);
+    REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames,
+        pDevice->RxMaxCoalescedFrames);
+    REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames,
+        pDevice->TxMaxCoalescedFrames);
+    REG_WR(pDevice, HostCoalesce.RxCoalescedTickDuringInt,
+        pDevice->RxCoalescingTicksDuringInt);
+    REG_WR(pDevice, HostCoalesce.TxCoalescedTickDuringInt,
+        pDevice->TxCoalescingTicksDuringInt);
+    REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt,
+        pDevice->RxMaxCoalescedFramesDuringInt);
+    REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFramesDuringInt,
+        pDevice->TxMaxCoalescedFramesDuringInt);
+
+    /* Initialize the address of the status block.  The NIC will DMA */
+    /* the status block to this memory which resides on the host. */
+    REG_WR(pDevice, HostCoalesce.StatusBlkHostAddr.High,
+        pDevice->StatusBlkPhy.High);
+    REG_WR(pDevice, HostCoalesce.StatusBlkHostAddr.Low,
+        pDevice->StatusBlkPhy.Low);
+
+    /* Initialize the address of the statistics block.  The NIC will DMA */
+    /* the statistics to this block of memory. */
+    REG_WR(pDevice, HostCoalesce.StatsBlkHostAddr.High,
+        pDevice->StatsBlkPhy.High);
+    REG_WR(pDevice, HostCoalesce.StatsBlkHostAddr.Low,
+        pDevice->StatsBlkPhy.Low);
+
+    REG_WR(pDevice, HostCoalesce.StatsCoalescingTicks,
+        pDevice->StatsCoalescingTicks);
+
+    REG_WR(pDevice, HostCoalesce.StatsBlkNicAddr, 0x300);
+    REG_WR(pDevice, HostCoalesce.StatusBlkNicAddr,0xb00);
+
+    /* Enable Host Coalesing state machine */
+    REG_WR(pDevice, HostCoalesce.Mode, HOST_COALESCE_ENABLE |
+        pDevice->CoalesceMode);
+
+    /* Enable the Receive BD Completion state machine. */
+    REG_WR(pDevice, RcvBdComp.Mode, RCV_BD_COMP_MODE_ENABLE |
+        RCV_BD_COMP_MODE_ATTN_ENABLE);
+
+    /* Enable the Receive List Placement state machine. */
+    REG_WR(pDevice, RcvListPlmt.Mode, RCV_LIST_PLMT_MODE_ENABLE);
+
+    /* Enable the Receive List Selector state machine. */
+    REG_WR(pDevice, RcvListSel.Mode, RCV_LIST_SEL_MODE_ENABLE |
+        RCV_LIST_SEL_MODE_ATTN_ENABLE);
+
+    /* Enable transmit DMA, clear statistics. */
+    pDevice->MacMode =  MAC_MODE_ENABLE_TX_STATISTICS |
+        MAC_MODE_ENABLE_RX_STATISTICS | MAC_MODE_ENABLE_TDE |
+        MAC_MODE_ENABLE_RDE | MAC_MODE_ENABLE_FHDE;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+        MAC_MODE_CLEAR_RX_STATISTICS | MAC_MODE_CLEAR_TX_STATISTICS);
+
+    /* GRC miscellaneous local control register. */
+    pDevice->GrcLocalCtrl = GRC_MISC_LOCAL_CTRL_INT_ON_ATTN |
+        GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        pDevice->GrcLocalCtrl |= GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+            GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1;
+    }
+
+    REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl);
+    MM_Wait(40);
+
+    /* Reset RX counters. */
+    for(j = 0; j < sizeof(LM_RX_COUNTERS); j++)
+    {
+        ((PLM_UINT8) &pDevice->RxCounters)[j] = 0;
+    }
+
+    /* Reset TX counters. */
+    for(j = 0; j < sizeof(LM_TX_COUNTERS); j++)
+    {
+        ((PLM_UINT8) &pDevice->TxCounters)[j] = 0;
+    }
+
+    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
+
+    /* Enable the DMA Completion state machine. */
+    REG_WR(pDevice, DmaComp.Mode, DMA_COMP_MODE_ENABLE);
+
+    /* Enable the DMA Write state machine. */
+    Value32 = DMA_WRITE_MODE_ENABLE |
+        DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE |
+        DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE |
+        DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE |
+        DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE |
+        DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE |
+        DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE |
+        DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE |
+        DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE;
+    REG_WR(pDevice, DmaWrite.Mode, Value32);
+
+    if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+    {
+        if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+        {
+            Value16 = REG_RD(pDevice, PciCfg.PciXCommand);
+            Value16 &= ~(PCIX_CMD_MAX_SPLIT_MASK | PCIX_CMD_MAX_BURST_MASK);
+            Value16 |= ((PCIX_CMD_MAX_BURST_CPIOB << PCIX_CMD_MAX_BURST_SHL) &
+                PCIX_CMD_MAX_BURST_MASK);
+            if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE)
+            {
+                Value16 |= (pDevice->SplitModeMaxReq << PCIX_CMD_MAX_SPLIT_SHL)
+                   & PCIX_CMD_MAX_SPLIT_MASK;
+            }
+            REG_WR(pDevice, PciCfg.PciXCommand, Value16);
+        }
+    }
+
+    /* Enable the Read DMA state machine. */
+    Value32 = DMA_READ_MODE_ENABLE |
+        DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE |
+        DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE |
+        DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE |
+        DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE |
+        DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE |
+        DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE |
+        DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE |
+        DMA_READ_MODE_LONG_READ_ATTN_ENABLE;
+
+    if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE)
+    {
+        Value32 |= DMA_READ_MODE_SPLIT_ENABLE;
+    }
+    REG_WR(pDevice, DmaRead.Mode, Value32);
+
+    /* Enable the Receive Data Completion state machine. */
+    REG_WR(pDevice, RcvDataComp.Mode, RCV_DATA_COMP_MODE_ENABLE |
+        RCV_DATA_COMP_MODE_ATTN_ENABLE);
+
+    /* Enable the Mbuf Cluster Free state machine. */
+    REG_WR(pDevice, MbufClusterFree.Mode, MBUF_CLUSTER_FREE_MODE_ENABLE);
+
+    /* Enable the Send Data Completion state machine. */
+    REG_WR(pDevice, SndDataComp.Mode, SND_DATA_COMP_MODE_ENABLE);
+
+    /* Enable the Send BD Completion state machine. */
+    REG_WR(pDevice, SndBdComp.Mode, SND_BD_COMP_MODE_ENABLE |
+        SND_BD_COMP_MODE_ATTN_ENABLE);
+
+    /* Enable the Receive BD Initiator state machine. */
+    REG_WR(pDevice, RcvBdIn.Mode, RCV_BD_IN_MODE_ENABLE |
+        RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE);
+
+    /* Enable the Receive Data and Receive BD Initiator state machine. */
+    REG_WR(pDevice, RcvDataBdIn.Mode, RCV_DATA_BD_IN_MODE_ENABLE |
+        RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE);
+
+    /* Enable the Send Data Initiator state machine. */
+    REG_WR(pDevice, SndDataIn.Mode, T3_SND_DATA_IN_MODE_ENABLE);
+
+    /* Enable the Send BD Initiator state machine. */
+    REG_WR(pDevice, SndBdIn.Mode, SND_BD_IN_MODE_ENABLE |
+        SND_BD_IN_MODE_ATTN_ENABLE);
+
+    /* Enable the Send BD Selector state machine. */
+    REG_WR(pDevice, SndBdSel.Mode, SND_BD_SEL_MODE_ENABLE |
+        SND_BD_SEL_MODE_ATTN_ENABLE);
+
+#if INCLUDE_5701_AX_FIX
+    /* Load the firmware for the 5701_A0 workaround. */
+    if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0)
+    {
+        LM_LoadRlsFirmware(pDevice);
+    }
+#endif
+
+    /* Enable the transmitter. */
+    pDevice->TxMode = TX_MODE_ENABLE;
+    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+
+    /* Enable the receiver. */
+    pDevice->RxMode = RX_MODE_ENABLE;
+    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+
+    if (pDevice->RestoreOnWakeUp)
+    {
+        pDevice->RestoreOnWakeUp = FALSE;
+        pDevice->DisableAutoNeg = pDevice->WakeUpDisableAutoNeg;
+        pDevice->RequestedMediaType = pDevice->WakeUpRequestedMediaType;
+    }
+
+    /* Disable auto polling. */
+    pDevice->MiMode = 0xc0000;
+    REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+    {
+        Value32 = LED_CTRL_PHY_MODE_1;
+    }
+    else
+    {
+        if(pDevice->LedMode == LED_MODE_OUTPUT)
+        {
+            Value32 = LED_CTRL_PHY_MODE_2;
+        }
+        else
+        {
+            Value32 = LED_CTRL_PHY_MODE_1;
+        }
+    }
+    REG_WR(pDevice, MacCtrl.LedCtrl, Value32);
+
+    /* Activate Link to enable MAC state machine */
+    REG_WR(pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN);
+
+    if (pDevice->EnableTbi)
+    {
+        REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_RESET);
+        MM_Wait(10);
+        REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+        if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1)
+        {
+            REG_WR(pDevice, MacCtrl.SerdesCfg, 0x616000);
+        }
+    }
+    /* Setup the phy chip. */
+    LM_SetupPhy(pDevice);
+
+    if (!pDevice->EnableTbi) {
+        /* Clear CRC stats */
+        LM_ReadPhy(pDevice, 0x1e, &Value32);
+        LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000);
+        LM_ReadPhy(pDevice, 0x14, &Value32);
+    }
+
+    /* Set up the receive mask. */
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask);
+
+    /* Queue Rx packet buffers. */
+    if(pDevice->QueueRxPackets)
+    {
+        LM_QueueRxPackets(pDevice);
+    }
+
+    /* Enable interrupt to the host. */
+    if(pDevice->InitDone)
+    {
+        LM_EnableInterrupt(pDevice);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_ResetAdapter */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine disables the adapter from generating interrupts.           */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_DisableInterrupt(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl |
+        MISC_HOST_CTRL_MASK_PCI_INT);
+    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine enables the adapter to generate interrupts.                */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_EnableInterrupt(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl &
+        ~MISC_HOST_CTRL_MASK_PCI_INT);
+    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
+
+    if(pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED)
+    {
+        REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+            GRC_MISC_LOCAL_CTRL_SET_INT);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine puts a packet on the wire if there is a transmit DMA       */
+/*    descriptor available; otherwise the packet is queued for later          */
+/*    transmission.  If the second argue is NULL, this routine will put       */
+/*    the queued packet on the wire if possible.                              */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+#if 0
+LM_STATUS
+LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    LM_UINT32 FragCount;
+    PT3_SND_BD pSendBd;
+    PT3_SND_BD pShadowSendBd;
+    LM_UINT32 Value32, Len;
+    LM_UINT32 Idx;
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) {
+        return LM_5700SendPacket(pDevice, pPacket);
+    }
+
+    /* Update the SendBdLeft count. */
+    atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+    /* Initalize the send buffer descriptors. */
+    Idx = pDevice->SendProdIdx;
+
+    pSendBd = &pDevice->pSendBdVirt[Idx];
+
+    /* Next producer index. */
+    if (pDevice->NicSendBd == TRUE)
+    {
+        T3_64BIT_HOST_ADDR paddr;
+
+        pShadowSendBd = &pDevice->ShadowSendBd[Idx];
+        for(FragCount = 0; ; )
+        {
+            MM_MapTxDma(pDevice, pPacket, &paddr, &Len, FragCount);
+            /* Initialize the pointer to the send buffer fragment. */
+            if (paddr.High != pShadowSendBd->HostAddr.High)
+            {
+                __raw_writel(paddr.High, &(pSendBd->HostAddr.High));
+                pShadowSendBd->HostAddr.High = paddr.High;
+            }
+            __raw_writel(paddr.Low, &(pSendBd->HostAddr.Low));
+
+            /* Setup the control flags and send buffer size. */
+            Value32 = (Len << 16) | pPacket->Flags;
+
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+            FragCount++;
+            if (FragCount >= pPacket->u.Tx.FragCount)
+            {
+                Value32 |= SND_BD_FLAG_END;
+                if (Value32 != pShadowSendBd->u1.Len_Flags)
+                {
+                    __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
+                    pShadowSendBd->u1.Len_Flags = Value32;
+                }
+                if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) {
+                    __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag));
+                }
+                break;
+            }
+            else
+            {
+                if (Value32 != pShadowSendBd->u1.Len_Flags)
+                {
+                    __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
+                    pShadowSendBd->u1.Len_Flags = Value32;
+                }
+                if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) {
+                    __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag));
+                }
+            }
+
+            pSendBd++;
+            pShadowSendBd++;
+            if (Idx == 0)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+                pShadowSendBd = &pDevice->ShadowSendBd[0];
+            }
+        } /* for */
+
+        /* Put the packet descriptor in the ActiveQ. */
+        QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+        wmb();
+        MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+
+    }
+    else
+    {
+        for(FragCount = 0; ; )
+        {
+            /* Initialize the pointer to the send buffer fragment. */
+            MM_MapTxDma(pDevice, pPacket, &pSendBd->HostAddr, &Len, FragCount);
+
+            pSendBd->u2.VlanTag = pPacket->VlanTag;
+
+            /* Setup the control flags and send buffer size. */
+            Value32 = (Len << 16) | pPacket->Flags;
+
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+            FragCount++;
+            if (FragCount >= pPacket->u.Tx.FragCount)
+            {
+                pSendBd->u1.Len_Flags = Value32 | SND_BD_FLAG_END;
+                break;
+            }
+            else
+            {
+                pSendBd->u1.Len_Flags = Value32;
+            }
+            pSendBd++;
+            if (Idx == 0)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+        } /* for */
+
+        /* Put the packet descriptor in the ActiveQ. */
+        QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+        wmb();
+        MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+
+    }
+
+    /* Update the producer index. */
+    pDevice->SendProdIdx = Idx;
+
+    return LM_STATUS_SUCCESS;
+}
+#endif
+
+LM_STATUS
+LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    LM_UINT32 FragCount;
+    PT3_SND_BD pSendBd, pTmpSendBd, pShadowSendBd;
+    T3_SND_BD NicSendBdArr[MAX_FRAGMENT_COUNT];
+    LM_UINT32 StartIdx, Idx;
+
+    while (1)
+    {
+        /* Initalize the send buffer descriptors. */
+        StartIdx = Idx = pDevice->SendProdIdx;
+
+        if (pDevice->NicSendBd)
+        {
+            pTmpSendBd = pSendBd = &NicSendBdArr[0];
+        }
+        else
+        {
+            pTmpSendBd = pSendBd = &pDevice->pSendBdVirt[Idx];
+        }
+
+        /* Next producer index. */
+        for(FragCount = 0; ; )
+        {
+            LM_UINT32 Value32, Len;
+
+            /* Initialize the pointer to the send buffer fragment. */
+            MM_MapTxDma(pDevice, pPacket, &pSendBd->HostAddr, &Len, FragCount);
+
+            pSendBd->u2.VlanTag = pPacket->VlanTag;
+
+            /* Setup the control flags and send buffer size. */
+            Value32 = (Len << 16) | pPacket->Flags;
+
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+            FragCount++;
+            if (FragCount >= pPacket->u.Tx.FragCount)
+            {
+                pSendBd->u1.Len_Flags = Value32 | SND_BD_FLAG_END;
+                break;
+            }
+            else
+            {
+                pSendBd->u1.Len_Flags = Value32;
+            }
+            pSendBd++;
+            if ((Idx == 0) && !pDevice->NicSendBd)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+        } /* for */
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            if (LM_Test4GBoundary(pDevice, pPacket, pTmpSendBd) ==
+                LM_STATUS_SUCCESS)
+            {
+                if (MM_CoalesceTxBuffer(pDevice, pPacket) != LM_STATUS_SUCCESS)
+                {
+                    QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+                    return LM_STATUS_FAILURE;
+                }
+                continue;
+            }
+        }
+        break;
+    }
+    /* Put the packet descriptor in the ActiveQ. */
+    QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+    if (pDevice->NicSendBd)
+    {
+        pSendBd = &pDevice->pSendBdVirt[StartIdx];
+        pShadowSendBd = &pDevice->ShadowSendBd[StartIdx];
+
+        while (StartIdx != Idx)
+        {
+            LM_UINT32 Value32;
+
+            if ((Value32 = pTmpSendBd->HostAddr.High) !=
+                pShadowSendBd->HostAddr.High)
+            {
+                __raw_writel(Value32, &(pSendBd->HostAddr.High));
+                pShadowSendBd->HostAddr.High = Value32;
+            }
+
+            __raw_writel(pTmpSendBd->HostAddr.Low, &(pSendBd->HostAddr.Low));
+
+            if ((Value32 = pTmpSendBd->u1.Len_Flags) !=
+                pShadowSendBd->u1.Len_Flags)
+            {
+                __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
+                pShadowSendBd->u1.Len_Flags = Value32;
+            }
+
+            if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG)
+            {
+                __raw_writel(pTmpSendBd->u2.VlanTag, &(pSendBd->u2.VlanTag));
+            }
+
+            StartIdx = (StartIdx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+            if (StartIdx == 0)
+                pSendBd = &pDevice->pSendBdVirt[0];
+            else
+                pSendBd++;
+            pTmpSendBd++;
+        }
+        wmb();
+        MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+
+        if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+        {
+            MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+        }
+    }
+    else
+    {
+        wmb();
+        MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+
+        if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+        {
+            MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+        }
+    }
+
+    /* Update the SendBdLeft count. */
+    atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+    /* Update the producer index. */
+    pDevice->SendProdIdx = Idx;
+
+    return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS
+LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
+    PT3_SND_BD pSendBd)
+{
+    int FragCount;
+    LM_UINT32 Idx, Base, Len;
+
+    Idx = pDevice->SendProdIdx;
+    for(FragCount = 0; ; )
+    {
+        Len = pSendBd->u1.Len_Flags >> 16;
+        if (((Base = pSendBd->HostAddr.Low) > 0xffffdcc0) &&
+            (pSendBd->HostAddr.High == 0) &&
+            ((Base + 8 + Len) < Base))
+        {
+            return LM_STATUS_SUCCESS;
+        }
+        FragCount++;
+        if (FragCount >= pPacket->u.Tx.FragCount)
+        {
+            break;
+        }
+        pSendBd++;
+        if (!pDevice->NicSendBd)
+        {
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+            if (Idx == 0)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+        }
+    }
+    return LM_STATUS_FAILURE;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static unsigned long
+ComputeCrc32(
+unsigned char *pBuffer,
+unsigned long BufferSize) {
+    unsigned long Reg;
+    unsigned long Tmp;
+    unsigned long j, k;
+
+    Reg = 0xffffffff;
+
+    for(j = 0; j < BufferSize; j++)
+    {
+        Reg ^= pBuffer[j];
+
+        for(k = 0; k < 8; k++)
+        {
+            Tmp = Reg & 0x01;
+
+            Reg >>= 1;
+
+            if(Tmp)
+            {
+                Reg ^= 0xedb88320;
+            }
+        }
+    }
+
+    return ~Reg;
+} /* ComputeCrc32 */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine sets the receive control register according to ReceiveMask */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_SetReceiveMask(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Mask) {
+    LM_UINT32 ReceiveMask;
+    LM_UINT32 RxMode;
+    LM_UINT32 j, k;
+
+    ReceiveMask = Mask;
+
+    RxMode = pDevice->RxMode;
+
+    if(Mask & LM_ACCEPT_UNICAST)
+    {
+        Mask &= ~LM_ACCEPT_UNICAST;
+    }
+
+    if(Mask & LM_ACCEPT_MULTICAST)
+    {
+        Mask &= ~LM_ACCEPT_MULTICAST;
+    }
+
+    if(Mask & LM_ACCEPT_ALL_MULTICAST)
+    {
+        Mask &= ~LM_ACCEPT_ALL_MULTICAST;
+    }
+
+    if(Mask & LM_ACCEPT_BROADCAST)
+    {
+        Mask &= ~LM_ACCEPT_BROADCAST;
+    }
+
+    RxMode &= ~RX_MODE_PROMISCUOUS_MODE;
+    if(Mask & LM_PROMISCUOUS_MODE)
+    {
+        RxMode |= RX_MODE_PROMISCUOUS_MODE;
+        Mask &= ~LM_PROMISCUOUS_MODE;
+    }
+
+    RxMode &= ~(RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED);
+    if(Mask & LM_ACCEPT_ERROR_PACKET)
+    {
+        RxMode |= RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED;
+        Mask &= ~LM_ACCEPT_ERROR_PACKET;
+    }
+
+    /* Make sure all the bits are valid before committing changes. */
+    if(Mask)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Commit the new filter. */
+    pDevice->RxMode = RxMode;
+    REG_WR(pDevice, MacCtrl.RxMode, RxMode);
+
+    pDevice->ReceiveMask = ReceiveMask;
+
+    /* Set up the MC hash table. */
+    if(ReceiveMask & LM_ACCEPT_ALL_MULTICAST)
+    {
+        for(k = 0; k < 4; k++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[k], 0xffffffff);
+        }
+    }
+    else if(ReceiveMask & LM_ACCEPT_MULTICAST)
+    {
+        LM_UINT32 HashReg[4];
+
+        HashReg[0] = 0; HashReg[1] = 0; HashReg[2] = 0; HashReg[3] = 0;
+        for(j = 0; j < pDevice->McEntryCount; j++)
+        {
+            LM_UINT32 RegIndex;
+            LM_UINT32 Bitpos;
+            LM_UINT32 Crc32;
+
+            Crc32 = ComputeCrc32(pDevice->McTable[j], ETHERNET_ADDRESS_SIZE);
+
+            /* The most significant 7 bits of the CRC32 (no inversion), */
+            /* are used to index into one of the possible 128 bit positions. */
+            Bitpos = ~Crc32 & 0x7f;
+
+            /* Hash register index. */
+            RegIndex = (Bitpos & 0x60) >> 5;
+
+            /* Bit to turn on within a hash register. */
+            Bitpos &= 0x1f;
+
+            /* Enable the multicast bit. */
+            HashReg[RegIndex] |= (1 << Bitpos);
+        }
+
+        /* REV_AX has problem with multicast filtering where it uses both */
+        /* DA and SA to perform hashing. */
+        for(k = 0; k < 4; k++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[k], HashReg[k]);
+        }
+    }
+    else
+    {
+        /* Reject all multicast frames. */
+        for(j = 0; j < 4; j++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[j], 0);
+        }
+    }
+
+    /* By default, Tigon3 will accept broadcast frames.  We need to setup */
+    if(ReceiveMask & LM_ACCEPT_BROADCAST)
+    {
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule,
+            REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value,
+            REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule,
+            REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value,
+            REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK);
+    }
+    else
+    {
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule,
+            REJECT_BROADCAST_RULE1_RULE);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value,
+            REJECT_BROADCAST_RULE1_VALUE);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule,
+            REJECT_BROADCAST_RULE2_RULE);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value,
+            REJECT_BROADCAST_RULE2_VALUE);
+    }
+
+    /* disable the rest of the rules. */
+    for(j = RCV_LAST_RULE_IDX; j < 16; j++)
+    {
+        REG_WR(pDevice, MacCtrl.RcvRules[j].Rule, 0);
+        REG_WR(pDevice, MacCtrl.RcvRules[j].Value, 0);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_SetReceiveMask */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    Disable the interrupt and put the transmitter and receiver engines in   */
+/*    an idle state.  Also aborts all pending send requests and receive       */
+/*    buffers.                                                                */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_Abort(
+PLM_DEVICE_BLOCK pDevice)
+{
+    PLM_PACKET pPacket;
+    LM_UINT Idx;
+
+    LM_DisableInterrupt(pDevice);
+
+    /* Disable all the state machines. */
+    LM_CntrlBlock(pDevice,T3_BLOCK_MAC_RX_ENGINE,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_BD_INITIATOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_LIST_PLMT,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_LIST_SELECTOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_DATA_INITIATOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_DATA_COMP,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_RX_BD_COMP,LM_DISABLE);
+
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_SELECTOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_INITIATOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_DATA_INITIATOR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_DMA_RD,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_DATA_COMP,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_DMA_COMP,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_COMP,LM_DISABLE);
+
+    /* Clear TDE bit */
+    pDevice->MacMode &= ~MAC_MODE_ENABLE_TDE;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    LM_CntrlBlock(pDevice,T3_BLOCK_MAC_TX_ENGINE,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_HOST_COALESING,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_DMA_WR,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_MBUF_CLUSTER_FREE,LM_DISABLE);
+
+    /* Reset all FTQs */
+    REG_WR(pDevice, Ftq.Reset, 0xffffffff);
+    REG_WR(pDevice, Ftq.Reset, 0x0);
+
+    LM_CntrlBlock(pDevice,T3_BLOCK_MBUF_MANAGER,LM_DISABLE);
+    LM_CntrlBlock(pDevice,T3_BLOCK_MEM_ARBITOR,LM_DISABLE);
+
+    MM_ACQUIRE_INT_LOCK(pDevice);
+
+    /* Abort packets that have already queued to go out. */
+    pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+    while(pPacket)
+    {
+
+        pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED;
+        pDevice->TxCounters.TxPacketAbortedCnt++;
+
+        atomic_add(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+        QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+
+        pPacket = (PLM_PACKET)
+            QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+    }
+
+    /* Cleanup the receive return rings. */
+    LM_ServiceRxInterrupt(pDevice);
+
+    /* Don't want to indicate rx packets in Ndis miniport shutdown context. */
+    /* Doing so may cause system crash. */
+    if(!pDevice->ShuttingDown)
+    {
+        /* Indicate packets to the protocol. */
+        MM_IndicateTxPackets(pDevice);
+
+        /* Indicate received packets to the protocols. */
+        MM_IndicateRxPackets(pDevice);
+    }
+    else
+    {
+        /* Move the receive packet descriptors in the ReceivedQ to the */
+        /* free queue. */
+        for(; ;)
+        {
+            pPacket = (PLM_PACKET) QQ_PopHead(
+                &pDevice->RxPacketReceivedQ.Container);
+            if(pPacket == NULL)
+            {
+                break;
+            }
+            QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+        }
+    }
+
+    /* Clean up the Std Receive Producer ring. */
+    Idx = pDevice->pStatusBlkVirt->RcvStdConIdx;
+
+    while(Idx != pDevice->RxStdProdIdx) {
+        pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+            MM_UINT_PTR(pDevice->pRxStdBdVirt[Idx].Opaque));
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+    } /* while */
+
+    /* Reinitialize our copy of the indices. */
+    pDevice->RxStdProdIdx = 0;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Clean up the Jumbo Receive Producer ring. */
+    Idx = pDevice->pStatusBlkVirt->RcvJumboConIdx;
+
+    while(Idx != pDevice->RxJumboProdIdx) {
+        pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+            MM_UINT_PTR(pDevice->pRxJumboBdVirt[Idx].Opaque));
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        Idx = (Idx + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK;
+    } /* while */
+
+    /* Reinitialize our copy of the indices. */
+    pDevice->RxJumboProdIdx = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    MM_RELEASE_INT_LOCK(pDevice);
+
+    /* Initialize the statistis Block */
+    pDevice->pStatusBlkVirt->Status = 0;
+    pDevice->pStatusBlkVirt->RcvStdConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvJumboConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvMiniConIdx = 0;
+
+    return LM_STATUS_SUCCESS;
+} /* LM_Abort */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    Disable the interrupt and put the transmitter and receiver engines in   */
+/*    an idle state.  Aborts all pending send requests and receive buffers.   */
+/*    Also free all the receive buffers.                                      */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_Halt(
+PLM_DEVICE_BLOCK pDevice) {
+    PLM_PACKET pPacket;
+    LM_UINT32 EntryCnt;
+
+    LM_Abort(pDevice);
+
+    /* Get the number of entries in the queue. */
+    EntryCnt = QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container);
+
+    /* Make sure all the packets have been accounted for. */
+    for(EntryCnt = 0; EntryCnt < pDevice->RxPacketDescCnt; EntryCnt++)
+    {
+        pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+        if (pPacket == 0)
+            break;
+
+        MM_FreeRxBuffer(pDevice, pPacket);
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+    }
+
+    LM_ResetChip(pDevice);
+
+    /* Restore PCI configuration registers. */
+    MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG,
+        pDevice->SavedCacheLineReg);
+    LM_RegWrInd(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG,
+        (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+
+    /* Reprogram the MAC address. */
+    LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_Halt */
+
+
+STATIC LM_STATUS
+LM_ResetChip(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    /* Wait for access to the nvram interface before resetting.  This is */
+    /* a workaround to prevent EEPROM corruption. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+        T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+    {
+        /* Request access to the flash interface. */
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1);
+
+        for(j = 0; j < 100000; j++)
+        {
+            Value32 = REG_RD(pDevice, Nvram.SwArb);
+            if(Value32 & SW_ARB_GNT1)
+            {
+                break;
+            }
+            MM_Wait(10);
+        }
+    }
+
+    /* Global reset. */
+    REG_WR(pDevice, Grc.MiscCfg, GRC_MISC_CFG_CORE_CLOCK_RESET);
+    MM_Wait(40); MM_Wait(40); MM_Wait(40);
+
+    /* make sure we re-enable indirect accesses */
+    MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG,
+        pDevice->MiscHostCtrl);
+
+    /* Set MAX PCI retry to zero. */
+    Value32 = T3_PCI_STATE_PCI_ROM_ENABLE | T3_PCI_STATE_PCI_ROM_RETRY_ENABLE;
+    if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+        {
+            Value32 |= T3_PCI_STATE_RETRY_SAME_DMA;
+        }
+    }
+    MM_WriteConfig32(pDevice, T3_PCI_STATE_REG, Value32);
+
+    /* Restore PCI command register. */
+    MM_WriteConfig32(pDevice, PCI_COMMAND_REG,
+        pDevice->PciCommandStatusWords);
+
+    /* Disable PCI-X relaxed ordering bit. */
+    MM_ReadConfig32(pDevice, PCIX_CAP_REG, &Value32);
+    Value32 &= ~PCIX_ENABLE_RELAXED_ORDERING;
+    MM_WriteConfig32(pDevice, PCIX_CAP_REG, Value32);
+
+    /* Enable memory arbiter. */
+    REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+
+#ifdef BIG_ENDIAN_PCI      /* This from jfd */
+        Value32 = GRC_MODE_WORD_SWAP_DATA|
+                  GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+#else
+#ifdef BIG_ENDIAN_HOST
+    /* Reconfigure the mode register. */
+    Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA |
+              GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+              GRC_MODE_BYTE_SWAP_DATA |
+              GRC_MODE_WORD_SWAP_DATA;
+#else
+    /* Reconfigure the mode register. */
+    Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA;
+#endif
+#endif
+    REG_WR(pDevice, Grc.Mode, Value32);
+
+    /* Prevent PXE from restarting. */
+    MEM_WR_OFFSET(pDevice, 0x0b50, T3_MAGIC_NUM);
+
+    if(pDevice->EnableTbi) {
+        pDevice->MacMode = MAC_MODE_PORT_MODE_TBI;
+        REG_WR(pDevice, MacCtrl.Mode, MAC_MODE_PORT_MODE_TBI);
+    }
+    else {
+        REG_WR(pDevice, MacCtrl.Mode, 0);
+    }
+
+    /* Wait for the firmware to finish initialization. */
+    for(j = 0; j < 100000; j++)
+    {
+        MM_Wait(10);
+
+        Value32 = MEM_RD_OFFSET(pDevice, 0x0b50);
+        if(Value32 == ~T3_MAGIC_NUM)
+        {
+            break;
+        }
+    }
+    return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static void
+LM_ServiceTxInterrupt(
+PLM_DEVICE_BLOCK pDevice) {
+    PLM_PACKET pPacket;
+    LM_UINT32 HwConIdx;
+    LM_UINT32 SwConIdx;
+
+    HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx;
+
+    /* Get our copy of the consumer index.  The buffer descriptors */
+    /* that are in between the consumer indices are freed. */
+    SwConIdx = pDevice->SendConIdx;
+
+    /* Move the packets from the TxPacketActiveQ that are sent out to */
+    /* the TxPacketXmittedQ.  Packets that are sent use the */
+    /* descriptors that are between SwConIdx and HwConIdx. */
+    while(SwConIdx != HwConIdx)
+    {
+        /* Get the packet that was sent from the TxPacketActiveQ. */
+        pPacket = (PLM_PACKET) QQ_PopHead(
+            &pDevice->TxPacketActiveQ.Container);
+
+        /* Set the return status. */
+        pPacket->PacketStatus = LM_STATUS_SUCCESS;
+
+        /* Put the packet in the TxPacketXmittedQ for indication later. */
+        QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+
+        /* Move to the next packet's BD. */
+        SwConIdx = (SwConIdx + pPacket->u.Tx.FragCount) &
+            T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+        /* Update the number of unused BDs. */
+        atomic_add(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+        /* Get the new updated HwConIdx. */
+        HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx;
+    } /* while */
+
+    /* Save the new SwConIdx. */
+    pDevice->SendConIdx = SwConIdx;
+
+} /* LM_ServiceTxInterrupt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static void
+LM_ServiceRxInterrupt(
+PLM_DEVICE_BLOCK pDevice) {
+    PLM_PACKET pPacket;
+    PT3_RCV_BD pRcvBd;
+    LM_UINT32 HwRcvRetProdIdx;
+    LM_UINT32 SwRcvRetConIdx;
+
+    /* Loop thru the receive return rings for received packets. */
+    HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+
+    SwRcvRetConIdx = pDevice->RcvRetConIdx;
+    while(SwRcvRetConIdx != HwRcvRetProdIdx)
+    {
+        pRcvBd = &pDevice->pRcvRetBdVirt[SwRcvRetConIdx];
+
+        /* Get the received packet descriptor. */
+        pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+            MM_UINT_PTR(pRcvBd->Opaque));
+
+        /* Check the error flag. */
+        if(pRcvBd->ErrorFlag &&
+            pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII)
+        {
+            pPacket->PacketStatus = LM_STATUS_FAILURE;
+
+            pDevice->RxCounters.RxPacketErrCnt++;
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_BAD_CRC)
+            {
+                pDevice->RxCounters.RxErrCrcCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_COLL_DETECT)
+            {
+                pDevice->RxCounters.RxErrCollCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_LINK_LOST_DURING_PKT)
+            {
+                pDevice->RxCounters.RxErrLinkLostCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_PHY_DECODE_ERR)
+            {
+                pDevice->RxCounters.RxErrPhyDecodeCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_ODD_NIBBLED_RCVD_MII)
+            {
+                pDevice->RxCounters.RxErrOddNibbleCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_MAC_ABORT)
+            {
+                pDevice->RxCounters.RxErrMacAbortCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_LEN_LT_64)
+            {
+                pDevice->RxCounters.RxErrShortPacketCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_TRUNC_NO_RESOURCES)
+            {
+                pDevice->RxCounters.RxErrNoResourceCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_GIANT_FRAME_RCVD)
+            {
+                pDevice->RxCounters.RxErrLargePacketCnt++;
+            }
+        }
+        else
+        {
+            pPacket->PacketStatus = LM_STATUS_SUCCESS;
+            pPacket->PacketSize = pRcvBd->Len - 4;
+
+            pPacket->Flags = pRcvBd->Flags;
+            if(pRcvBd->Flags & RCV_BD_FLAG_VLAN_TAG)
+            {
+                pPacket->VlanTag = pRcvBd->VlanTag;
+            }
+
+            pPacket->u.Rx.TcpUdpChecksum = pRcvBd->TcpUdpCksum;
+        }
+
+        /* Put the packet descriptor containing the received packet */
+        /* buffer in the RxPacketReceivedQ for indication later. */
+        QQ_PushTail(&pDevice->RxPacketReceivedQ.Container, pPacket);
+
+        /* Go to the next buffer descriptor. */
+        SwRcvRetConIdx = (SwRcvRetConIdx + 1) &
+            T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK;
+
+        /* Get the updated HwRcvRetProdIdx. */
+        HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+    } /* while */
+
+    pDevice->RcvRetConIdx = SwRcvRetConIdx;
+
+    /* Update the receive return ring consumer index. */
+    MB_REG_WR(pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx);
+} /* LM_ServiceRxInterrupt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This is the interrupt event handler routine. It acknowledges all        */
+/*    pending interrupts and process all pending events.                      */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_ServiceInterrupts(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    int ServicePhyInt = FALSE;
+
+    /* Setup the phy chip whenever the link status changes. */
+    if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_USE_STATUS_REG)
+    {
+        Value32 = REG_RD(pDevice, MacCtrl.Status);
+        if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+        {
+            if (Value32 & MAC_STATUS_MI_INTERRUPT)
+            {
+                ServicePhyInt = TRUE;
+            }
+        }
+        else if(Value32 & MAC_STATUS_LINK_STATE_CHANGED)
+        {
+            ServicePhyInt = TRUE;
+        }
+    }
+    else
+    {
+        if(pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_LINK_CHANGED_STATUS)
+        {
+            pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+                (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+            ServicePhyInt = TRUE;
+        }
+    }
+#if INCLUDE_TBI_SUPPORT
+    if (pDevice->IgnoreTbiLinkChange == TRUE)
+    {
+        ServicePhyInt = FALSE;
+    }
+#endif
+    if (ServicePhyInt == TRUE)
+    {
+        LM_SetupPhy(pDevice);
+    }
+
+    /* Service receive and transmit interrupts. */
+    LM_ServiceRxInterrupt(pDevice);
+    LM_ServiceTxInterrupt(pDevice);
+
+    /* No spinlock for this queue since this routine is serialized. */
+    if(!QQ_Empty(&pDevice->RxPacketReceivedQ.Container))
+    {
+        /* Indicate receive packets. */
+        MM_IndicateRxPackets(pDevice);
+       /*       LM_QueueRxPackets(pDevice); */
+    }
+
+    /* No spinlock for this queue since this routine is serialized. */
+    if(!QQ_Empty(&pDevice->TxPacketXmittedQ.Container))
+    {
+        MM_IndicateTxPackets(pDevice);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_ServiceInterrupts */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastAdd(
+PLM_DEVICE_BLOCK pDevice,
+PLM_UINT8 pMcAddress) {
+    PLM_UINT8 pEntry;
+    LM_UINT32 j;
+
+    pEntry = pDevice->McTable[0];
+    for(j = 0; j < pDevice->McEntryCount; j++)
+    {
+        if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+        {
+            /* Found a match, increment the instance count. */
+            pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1;
+
+            return LM_STATUS_SUCCESS;
+        }
+
+        pEntry += LM_MC_ENTRY_SIZE;
+    }
+
+    if(pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    pEntry = pDevice->McTable[pDevice->McEntryCount];
+
+    COPY_ETH_ADDRESS(pMcAddress, pEntry);
+    pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1;
+
+    pDevice->McEntryCount++;
+
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_MulticastAdd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastDel(
+PLM_DEVICE_BLOCK pDevice,
+PLM_UINT8 pMcAddress) {
+    PLM_UINT8 pEntry;
+    LM_UINT32 j;
+
+    pEntry = pDevice->McTable[0];
+    for(j = 0; j < pDevice->McEntryCount; j++)
+    {
+        if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+        {
+            /* Found a match, decrement the instance count. */
+            pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1;
+
+            /* No more instance left, remove the address from the table. */
+            /* Move the last entry in the table to the delete slot. */
+            if(pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 &&
+                pDevice->McEntryCount > 1)
+            {
+
+                COPY_ETH_ADDRESS(
+                    pDevice->McTable[pDevice->McEntryCount-1], pEntry);
+                pEntry[LM_MC_INSTANCE_COUNT_INDEX] =
+                    pDevice->McTable[pDevice->McEntryCount-1]
+                    [LM_MC_INSTANCE_COUNT_INDEX];
+            }
+            pDevice->McEntryCount--;
+
+            /* Update the receive mask if the table is empty. */
+            if(pDevice->McEntryCount == 0)
+            {
+                LM_SetReceiveMask(pDevice,
+                    pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+            }
+
+            return LM_STATUS_SUCCESS;
+        }
+
+        pEntry += LM_MC_ENTRY_SIZE;
+    }
+
+    return LM_STATUS_FAILURE;
+} /* LM_MulticastDel */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastClear(
+PLM_DEVICE_BLOCK pDevice) {
+    pDevice->McEntryCount = 0;
+
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_MulticastClear */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetMacAddress(
+    PLM_DEVICE_BLOCK pDevice,
+    PLM_UINT8 pMacAddress)
+{
+    LM_UINT32 j;
+
+    for(j = 0; j < 4; j++)
+    {
+        REG_WR(pDevice, MacCtrl.MacAddr[j].High,
+            (pMacAddress[0] << 8) | pMacAddress[1]);
+        REG_WR(pDevice, MacCtrl.MacAddr[j].Low,
+            (pMacAddress[2] << 24) | (pMacAddress[3] << 16) |
+            (pMacAddress[4] << 8) | pMacAddress[5]);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    Sets up the default line speed, and duplex modes based on the requested */
+/*    media type.                                                             */
+/*                                                                            */
+/* Return:                                                                    */
+/*    None.                                                                   */
+/******************************************************************************/
+static LM_STATUS
+LM_TranslateRequestedMediaType(
+LM_REQUESTED_MEDIA_TYPE RequestedMediaType,
+PLM_MEDIA_TYPE pMediaType,
+PLM_LINE_SPEED pLineSpeed,
+PLM_DUPLEX_MODE pDuplexMode) {
+    *pMediaType = LM_MEDIA_TYPE_AUTO;
+    *pLineSpeed = LM_LINE_SPEED_UNKNOWN;
+    *pDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+
+    /* determine media type */
+    switch(RequestedMediaType) {
+        case LM_REQUESTED_MEDIA_TYPE_BNC:
+            *pMediaType = LM_MEDIA_TYPE_BNC;
+            *pLineSpeed = LM_LINE_SPEED_10MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_AUTO:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_10MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_10MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_100MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_100MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_UTP;
+            *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS:
+            *pMediaType = LM_MEDIA_TYPE_FIBER;
+            *pLineSpeed = LM_LINE_SPEED_100MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_FIBER;
+            *pLineSpeed = LM_LINE_SPEED_100MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS:
+            *pMediaType = LM_MEDIA_TYPE_FIBER;
+            *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_HALF;
+            break;
+
+        case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX:
+            *pMediaType = LM_MEDIA_TYPE_FIBER;
+            *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+            *pDuplexMode = LM_DUPLEX_MODE_FULL;
+            break;
+
+        default:
+            break;
+    } /* switch */
+
+    return LM_STATUS_SUCCESS;
+} /* LM_TranslateRequestedMediaType */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_LINK_ACTIVE                                                   */
+/*    LM_STATUS_LINK_DOWN                                                     */
+/******************************************************************************/
+static LM_STATUS
+LM_InitBcm540xPhy(
+PLM_DEVICE_BLOCK pDevice)
+{
+    LM_LINE_SPEED CurrentLineSpeed;
+    LM_DUPLEX_MODE CurrentDuplexMode;
+    LM_STATUS CurrentLinkStatus;
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+#if 1  /* jmb: bugfix -- moved here, out of code that sets initial pwr state */
+    LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x2);
+#endif
+    if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+        if(!pDevice->InitDone)
+        {
+            Value32 = 0;
+        }
+
+        if(!(Value32 & PHY_STATUS_LINK_PASS))
+        {
+            LM_WritePhy(pDevice, BCM5401_AUX_CTRL,  0x0c20);
+
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+
+            LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+            for(j = 0; j < 1000; j++)
+            {
+                MM_Wait(10);
+
+                LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+                if(Value32 & PHY_STATUS_LINK_PASS)
+                {
+                    MM_Wait(40);
+                    break;
+                }
+            }
+
+            if((pDevice->PhyId & PHY_ID_REV_MASK) == PHY_BCM5401_B0_REV)
+            {
+                if(!(Value32 & PHY_STATUS_LINK_PASS) &&
+                    (pDevice->OldLineSpeed == LM_LINE_SPEED_1000MBPS))
+                {
+                    LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+                    for(j = 0; j < 100; j++)
+                    {
+                        MM_Wait(10);
+
+                        LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+                        if(!(Value32 & PHY_CTRL_PHY_RESET))
+                        {
+                            MM_Wait(40);
+                            break;
+                        }
+                    }
+
+                    LM_WritePhy(pDevice, BCM5401_AUX_CTRL,  0x0c20);
+
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+                }
+            }
+        }
+    }
+    else if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+    {
+        /* Bug: 5701 A0, B0 TX CRC workaround. */
+        LM_WritePhy(pDevice, 0x15, 0x0a75);
+        LM_WritePhy(pDevice, 0x1c, 0x8c68);
+        LM_WritePhy(pDevice, 0x1c, 0x8d68);
+        LM_WritePhy(pDevice, 0x1c, 0x8c68);
+    }
+
+    /* Acknowledge interrupts. */
+    LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32);
+    LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32);
+
+    /* Configure the interrupt mask. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+    {
+        LM_WritePhy(pDevice, BCM540X_INT_MASK_REG, ~BCM540X_INT_LINK_CHANGE);
+    }
+
+    /* Configure PHY led mode. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701 ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700))
+    {
+        if(pDevice->LedMode == LED_MODE_THREE_LINK)
+        {
+            LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG,
+                BCM540X_EXT_CTRL_LINK3_LED_MODE);
+        }
+        else
+        {
+            LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 0);
+        }
+    }
+
+    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Get current link and duplex mode. */
+    for(j = 0; j < 100; j++)
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+        if(Value32 & PHY_STATUS_LINK_PASS)
+        {
+            break;
+        }
+        MM_Wait(40);
+    }
+
+    if(Value32 & PHY_STATUS_LINK_PASS)
+    {
+
+        /* Determine the current line and duplex settings. */
+        LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+        for(j = 0; j < 2000; j++)
+        {
+            MM_Wait(10);
+
+            LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+            if(Value32)
+            {
+                break;
+            }
+        }
+
+        switch(Value32 & BCM540X_AUX_SPEED_MASK)
+        {
+            case BCM540X_AUX_10BASET_HD:
+                CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+                break;
+
+            case BCM540X_AUX_10BASET_FD:
+                CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+                break;
+
+            case BCM540X_AUX_100BASETX_HD:
+                CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+                break;
+
+            case BCM540X_AUX_100BASETX_FD:
+                CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+                break;
+
+            case BCM540X_AUX_100BASET_HD:
+                CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+                break;
+
+            case BCM540X_AUX_100BASET_FD:
+                CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+                break;
+
+            default:
+
+                CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN;
+                CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+                break;
+        }
+
+        /* Make sure we are in auto-neg mode. */
+        for (j = 0; j < 200; j++)
+        {
+            LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+            if(Value32 && Value32 != 0x7fff)
+            {
+                break;
+            }
+
+            if(Value32 == 0 && pDevice->RequestedMediaType ==
+                LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS)
+            {
+                break;
+            }
+
+            MM_Wait(10);
+        }
+
+        /* Use the current line settings for "auto" mode. */
+        if(pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO ||
+            pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO)
+        {
+            if(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)
+            {
+                CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+
+                /* We may be exiting low power mode and the link is in */
+                /* 10mb.  In this case, we need to restart autoneg. */
+                LM_ReadPhy(pDevice, BCM540X_1000BASET_CTRL_REG, &Value32);
+                pDevice->advertising1000 = Value32;
+                /* 5702FE supports 10/100Mb only. */
+                if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5703 ||
+                    pDevice->BondId != GRC_MISC_BD_ID_5702FE)
+                {
+                    if(!(Value32 & (BCM540X_AN_AD_1000BASET_HALF |
+                        BCM540X_AN_AD_1000BASET_FULL)))
+                    {
+                        CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+                    }
+                }
+            }
+            else
+            {
+                CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+            }
+        }
+        else
+        {
+            /* Force line settings. */
+            /* Use the current setting if it matches the user's requested */
+            /* setting. */
+            LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+            if((pDevice->LineSpeed == CurrentLineSpeed) &&
+                (pDevice->DuplexMode == CurrentDuplexMode))
+            {
+                if ((pDevice->DisableAutoNeg &&
+                    !(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)) ||
+                    (!pDevice->DisableAutoNeg &&
+                    (Value32 & PHY_CTRL_AUTO_NEG_ENABLE)))
+                {
+                    CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+                }
+                else
+                {
+                    CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+                }
+            }
+            else
+            {
+                CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+            }
+        }
+
+        /* Save line settings. */
+        pDevice->LineSpeed = CurrentLineSpeed;
+        pDevice->DuplexMode = CurrentDuplexMode;
+        pDevice->MediaType = LM_MEDIA_TYPE_UTP;
+    }
+
+    return CurrentLinkStatus;
+} /* LM_InitBcm540xPhy */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetFlowControl(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 LocalPhyAd,
+    LM_UINT32 RemotePhyAd)
+{
+    LM_FLOW_CONTROL FlowCap;
+
+    /* Resolve flow control. */
+    FlowCap = LM_FLOW_CONTROL_NONE;
+
+    /* See Table 28B-3 of 802.3ab-1999 spec. */
+    if(pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE)
+    {
+        if(LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE)
+        {
+            if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+            {
+                if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+                        LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+                else if(RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+            }
+            else
+            {
+                if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+                        LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+            }
+        }
+        else if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+        {
+            if((RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) &&
+                (RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE))
+            {
+                FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+            }
+        }
+    }
+    else
+    {
+        FlowCap = pDevice->FlowControlCap;
+    }
+
+    /* Enable/disable rx PAUSE. */
+    pDevice->RxMode &= ~RX_MODE_ENABLE_FLOW_CONTROL;
+    if(FlowCap & LM_FLOW_CONTROL_RECEIVE_PAUSE &&
+        (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+        pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE))
+    {
+        pDevice->FlowControl |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+        pDevice->RxMode |= RX_MODE_ENABLE_FLOW_CONTROL;
+
+    }
+    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+
+    /* Enable/disable tx PAUSE. */
+    pDevice->TxMode &= ~TX_MODE_ENABLE_FLOW_CONTROL;
+    if(FlowCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE &&
+        (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+        pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE))
+    {
+        pDevice->FlowControl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+        pDevice->TxMode |= TX_MODE_ENABLE_FLOW_CONTROL;
+
+    }
+    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+#if INCLUDE_TBI_SUPPORT
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_InitBcm800xPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    Value32 = REG_RD(pDevice, MacCtrl.Status);
+
+    /* Reset the SERDES during init and when we have link. */
+    if(!pDevice->InitDone || Value32 & MAC_STATUS_PCS_SYNCED)
+    {
+        /* Set PLL lock range. */
+        LM_WritePhy(pDevice, 0x16, 0x8007);
+
+        /* Software reset. */
+        LM_WritePhy(pDevice, 0x00, 0x8000);
+
+        /* Wait for reset to complete. */
+        for(j = 0; j < 500; j++)
+        {
+            MM_Wait(10);
+        }
+
+        /* Config mode; seletct PMA/Ch 1 regs. */
+        LM_WritePhy(pDevice, 0x10, 0x8411);
+
+        /* Enable auto-lock and comdet, select txclk for tx. */
+        LM_WritePhy(pDevice, 0x11, 0x0a10);
+
+        LM_WritePhy(pDevice, 0x18, 0x00a0);
+        LM_WritePhy(pDevice, 0x16, 0x41ff);
+
+        /* Assert and deassert POR. */
+        LM_WritePhy(pDevice, 0x13, 0x0400);
+        MM_Wait(40);
+        LM_WritePhy(pDevice, 0x13, 0x0000);
+
+        LM_WritePhy(pDevice, 0x11, 0x0a50);
+        MM_Wait(40);
+        LM_WritePhy(pDevice, 0x11, 0x0a10);
+
+        /* Delay for signal to stabilize. */
+        for(j = 0; j < 15000; j++)
+        {
+            MM_Wait(10);
+        }
+
+        /* Deselect the channel register so we can read the PHY id later. */
+        LM_WritePhy(pDevice, 0x10, 0x8011);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_SetupFiberPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS CurrentLinkStatus;
+    AUTONEG_STATUS AnStatus = 0;
+    LM_UINT32 Value32;
+    LM_UINT32 Cnt;
+    LM_UINT32 j, k;
+
+    pDevice->MacMode &= ~(MAC_MODE_HALF_DUPLEX | MAC_MODE_PORT_MODE_MASK);
+
+    /* Initialize the send_config register. */
+    REG_WR(pDevice, MacCtrl.TxAutoNeg, 0);
+
+    /* Enable TBI and full duplex mode. */
+    pDevice->MacMode |= MAC_MODE_PORT_MODE_TBI;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    /* Initialize the BCM8002 SERDES PHY. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM8002_PHY_ID:
+            LM_InitBcm800xPhy(pDevice);
+            break;
+
+        default:
+            break;
+    }
+
+    /* Enable link change interrupt. */
+    REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+
+    /* Default to link down. */
+    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Get the link status. */
+    Value32 = REG_RD(pDevice, MacCtrl.Status);
+    if(Value32 & MAC_STATUS_PCS_SYNCED)
+    {
+        if((pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO) ||
+            (pDevice->DisableAutoNeg == FALSE))
+        {
+            /* auto-negotiation mode. */
+            /* Initialize the autoneg default capaiblities. */
+            AutonegInit(&pDevice->AnInfo);
+
+            /* Set the context pointer to point to the main device structure. */
+            pDevice->AnInfo.pContext = pDevice;
+
+            /* Setup flow control advertisement register. */
+            Value32 = GetPhyAdFlowCntrlSettings(pDevice);
+            if(Value32 & PHY_AN_AD_PAUSE_CAPABLE)
+            {
+                pDevice->AnInfo.mr_adv_sym_pause = 1;
+            }
+            else
+            {
+                pDevice->AnInfo.mr_adv_sym_pause = 0;
+            }
+
+            if(Value32 & PHY_AN_AD_ASYM_PAUSE)
+            {
+                pDevice->AnInfo.mr_adv_asym_pause = 1;
+            }
+            else
+            {
+                pDevice->AnInfo.mr_adv_asym_pause = 0;
+            }
+
+            /* Try to autoneg up to six times. */
+            if (pDevice->IgnoreTbiLinkChange)
+            {
+                Cnt = 1;
+            }
+            else
+            {
+                Cnt = 6;
+            }
+            for (j = 0; j < Cnt; j++)
+            {
+                REG_WR(pDevice, MacCtrl.TxAutoNeg, 0);
+
+                Value32 = pDevice->MacMode & ~MAC_MODE_PORT_MODE_MASK;
+                REG_WR(pDevice, MacCtrl.Mode, Value32);
+                MM_Wait(20);
+
+                REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                    MAC_MODE_SEND_CONFIGS);
+
+                MM_Wait(20);
+
+                pDevice->AnInfo.State = AN_STATE_UNKNOWN;
+                pDevice->AnInfo.CurrentTime_us = 0;
+
+                REG_WR(pDevice, Grc.Timer, 0);
+                for(k = 0; (pDevice->AnInfo.CurrentTime_us < 75000) &&
+                    (k < 75000); k++)
+                {
+                    AnStatus = Autoneg8023z(&pDevice->AnInfo);
+
+                    if((AnStatus == AUTONEG_STATUS_DONE) ||
+                        (AnStatus == AUTONEG_STATUS_FAILED))
+                    {
+                        break;
+                    }
+
+                    pDevice->AnInfo.CurrentTime_us = REG_RD(pDevice, Grc.Timer);
+
+                }
+                if((AnStatus == AUTONEG_STATUS_DONE) ||
+                    (AnStatus == AUTONEG_STATUS_FAILED))
+                {
+                    break;
+                }
+                if (j >= 1)
+                {
+                    if (!(REG_RD(pDevice, MacCtrl.Status) &
+                        MAC_STATUS_PCS_SYNCED)) {
+                        break;
+                    }
+                }
+            }
+
+            /* Stop sending configs. */
+            MM_AnTxIdle(&pDevice->AnInfo);
+
+            /* Resolve flow control settings. */
+            if((AnStatus == AUTONEG_STATUS_DONE) &&
+                pDevice->AnInfo.mr_an_complete && pDevice->AnInfo.mr_link_ok &&
+                pDevice->AnInfo.mr_lp_adv_full_duplex)
+                {
+                LM_UINT32 RemotePhyAd;
+                LM_UINT32 LocalPhyAd;
+
+                LocalPhyAd = 0;
+                if(pDevice->AnInfo.mr_adv_sym_pause)
+                {
+                    LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE;
+                }
+
+                if(pDevice->AnInfo.mr_adv_asym_pause)
+                {
+                    LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE;
+                }
+
+                RemotePhyAd = 0;
+                if(pDevice->AnInfo.mr_lp_adv_sym_pause)
+                {
+                    RemotePhyAd |= PHY_LINK_PARTNER_PAUSE_CAPABLE;
+                }
+
+                if(pDevice->AnInfo.mr_lp_adv_asym_pause)
+                {
+                    RemotePhyAd |= PHY_LINK_PARTNER_ASYM_PAUSE;
+                }
+
+                LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+
+                CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            }
+            for (j = 0; j < 30; j++)
+            {
+                MM_Wait(20);
+                REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+                    MAC_STATUS_CFG_CHANGED);
+                MM_Wait(20);
+                if ((REG_RD(pDevice, MacCtrl.Status) &
+                    (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0)
+                    break;
+            }
+            if (pDevice->PollTbiLink)
+            {
+                Value32 = REG_RD(pDevice, MacCtrl.Status);
+                if (Value32 & MAC_STATUS_RECEIVING_CFG)
+                {
+                    pDevice->IgnoreTbiLinkChange = TRUE;
+                }
+                else
+                {
+                    pDevice->IgnoreTbiLinkChange = FALSE;
+                }
+            }
+            Value32 = REG_RD(pDevice, MacCtrl.Status);
+            if (CurrentLinkStatus == LM_STATUS_LINK_DOWN &&
+                 (Value32 & MAC_STATUS_PCS_SYNCED) &&
+                 ((Value32 & MAC_STATUS_RECEIVING_CFG) == 0))
+            {
+                CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            }
+        }
+        else
+        {
+            /* We are forcing line speed. */
+            pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE;
+            LM_SetFlowControl(pDevice, 0, 0);
+
+            CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                MAC_MODE_SEND_CONFIGS);
+        }
+    }
+    /* Set the link polarity bit. */
+    pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+        (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+
+    for (j = 0; j < 100; j++)
+    {
+        REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+            MAC_STATUS_CFG_CHANGED);
+        MM_Wait(5);
+        if ((REG_RD(pDevice, MacCtrl.Status) &
+            (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0)
+            break;
+    }
+
+    Value32 = REG_RD(pDevice, MacCtrl.Status);
+    if((Value32 & MAC_STATUS_PCS_SYNCED) == 0)
+    {
+        CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+        if (pDevice->DisableAutoNeg == FALSE)
+        {
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                MAC_MODE_SEND_CONFIGS);
+            MM_Wait(1);
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+        }
+    }
+
+    /* Initialize the current link status. */
+    if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+    {
+        pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS;
+        pDevice->DuplexMode = LM_DUPLEX_MODE_FULL;
+        REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED |
+            LED_CTRL_1000MBPS_LED_ON);
+    }
+    else
+    {
+        pDevice->LineSpeed = LM_LINE_SPEED_UNKNOWN;
+        pDevice->DuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+        REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED |
+            LED_CTRL_OVERRIDE_TRAFFIC_LED);
+    }
+
+    /* Indicate link status. */
+    if (pDevice->LinkStatus != CurrentLinkStatus) {
+        pDevice->LinkStatus = CurrentLinkStatus;
+        MM_IndicateStatus(pDevice, CurrentLinkStatus);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+#endif /* INCLUDE_TBI_SUPPORT */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetupCopperPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS CurrentLinkStatus;
+    LM_UINT32 Value32;
+
+    /* Assume there is not link first. */
+    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Disable phy link change attention. */
+    REG_WR(pDevice, MacCtrl.MacEvent, 0);
+
+    /* Clear link change attention. */
+    REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+        MAC_STATUS_CFG_CHANGED);
+
+    /* Disable auto-polling for the moment. */
+    pDevice->MiMode = 0xc0000;
+    REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+    MM_Wait(40);
+
+    /* Determine the requested line speed and duplex. */
+    pDevice->OldLineSpeed = pDevice->LineSpeed;
+    LM_TranslateRequestedMediaType(pDevice->RequestedMediaType,
+        &pDevice->MediaType, &pDevice->LineSpeed, &pDevice->DuplexMode);
+
+    /* Initialize the phy chip. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM5400_PHY_ID:
+        case PHY_BCM5401_PHY_ID:
+        case PHY_BCM5411_PHY_ID:
+        case PHY_BCM5701_PHY_ID:
+        case PHY_BCM5703_PHY_ID:
+        case PHY_BCM5704_PHY_ID:
+            CurrentLinkStatus = LM_InitBcm540xPhy(pDevice);
+            break;
+
+        default:
+            break;
+    }
+
+    if(CurrentLinkStatus == LM_STATUS_LINK_SETTING_MISMATCH)
+    {
+        CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+    }
+
+    /* Setup flow control. */
+    pDevice->FlowControl = LM_FLOW_CONTROL_NONE;
+    if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+    {
+        LM_FLOW_CONTROL FlowCap;     /* Flow control capability. */
+
+        FlowCap = LM_FLOW_CONTROL_NONE;
+
+        if(pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
+        {
+            if(pDevice->DisableAutoNeg == FALSE ||
+                pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO ||
+                pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO)
+            {
+                LM_UINT32 ExpectedPhyAd;
+                LM_UINT32 LocalPhyAd;
+                LM_UINT32 RemotePhyAd;
+
+                LM_ReadPhy(pDevice, PHY_AN_AD_REG, &LocalPhyAd);
+               pDevice->advertising = LocalPhyAd;
+                LocalPhyAd &= (PHY_AN_AD_ASYM_PAUSE | PHY_AN_AD_PAUSE_CAPABLE);
+
+                ExpectedPhyAd = GetPhyAdFlowCntrlSettings(pDevice);
+
+                if(LocalPhyAd != ExpectedPhyAd)
+                {
+                    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+                }
+                else
+                {
+                    LM_ReadPhy(pDevice, PHY_LINK_PARTNER_ABILITY_REG,
+                        &RemotePhyAd);
+
+                    LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+                }
+            }
+            else
+            {
+                pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE;
+                LM_SetFlowControl(pDevice, 0, 0);
+            }
+        }
+    }
+
+    if(CurrentLinkStatus == LM_STATUS_LINK_DOWN)
+    {
+        LM_ForceAutoNeg(pDevice, pDevice->RequestedMediaType);
+
+        /* If we force line speed, we make get link right away. */
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        if(Value32 & PHY_STATUS_LINK_PASS)
+        {
+            CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+        }
+    }
+
+    /* GMII interface. */
+    pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK;
+    if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+    {
+        if(pDevice->LineSpeed == LM_LINE_SPEED_100MBPS ||
+            pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+        {
+            pDevice->MacMode |= MAC_MODE_PORT_MODE_MII;
+        }
+        else
+        {
+            pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+        }
+    }
+    else {
+        pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+    }
+
+    /* Set the MAC to operate in the appropriate duplex mode. */
+    pDevice->MacMode &= ~MAC_MODE_HALF_DUPLEX;
+    if(pDevice->DuplexMode == LM_DUPLEX_MODE_HALF)
+    {
+        pDevice->MacMode |= MAC_MODE_HALF_DUPLEX;
+    }
+
+    /* Set the link polarity bit. */
+    pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY;
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        if((pDevice->LedMode == LED_MODE_LINK10) ||
+             (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE &&
+             pDevice->LineSpeed == LM_LINE_SPEED_10MBPS))
+        {
+            pDevice->MacMode |= MAC_MODE_LINK_POLARITY;
+        }
+    }
+    else
+    {
+        if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+        {
+            pDevice->MacMode |= MAC_MODE_LINK_POLARITY;
+        }
+
+        /* Set LED mode. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = LED_CTRL_PHY_MODE_1;
+        }
+        else
+        {
+            if(pDevice->LedMode == LED_MODE_OUTPUT)
+            {
+                Value32 = LED_CTRL_PHY_MODE_2;
+            }
+            else
+            {
+                Value32 = LED_CTRL_PHY_MODE_1;
+            }
+        }
+        REG_WR(pDevice, MacCtrl.LedCtrl, Value32);
+    }
+
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    /* Enable auto polling. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        pDevice->MiMode |= MI_MODE_AUTO_POLLING_ENABLE;
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+    }
+
+    /* Enable phy link change attention. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+    {
+        REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_MI_INTERRUPT);
+    }
+    else
+    {
+        REG_WR(pDevice, MacCtrl.MacEvent,
+            MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+    }
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) &&
+        (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) &&
+        (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) &&
+        (((pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) &&
+          (pDevice->PciState & T3_PCI_STATE_BUS_SPEED_HIGH)) ||
+         !(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)))
+    {
+        MM_Wait(120);
+        REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+            MAC_STATUS_CFG_CHANGED);
+        MEM_WR_OFFSET(pDevice, T3_FIRMWARE_MAILBOX,
+            T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE);
+    }
+
+    /* Indicate link status. */
+    if (pDevice->LinkStatus != CurrentLinkStatus) {
+        pDevice->LinkStatus = CurrentLinkStatus;
+        MM_IndicateStatus(pDevice, CurrentLinkStatus);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_SetupCopperPhy */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetupPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS LmStatus;
+    LM_UINT32 Value32;
+
+#if INCLUDE_TBI_SUPPORT
+    if(pDevice->EnableTbi)
+    {
+        LmStatus = LM_SetupFiberPhy(pDevice);
+    }
+    else
+#endif /* INCLUDE_TBI_SUPPORT */
+    {
+        LmStatus = LM_SetupCopperPhy(pDevice);
+    }
+    if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+        {
+            Value32 = REG_RD(pDevice, PciCfg.PciState);
+            REG_WR(pDevice, PciCfg.PciState,
+                Value32 | T3_PCI_STATE_RETRY_SAME_DMA);
+        }
+    }
+    if ((pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) &&
+        (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF))
+    {
+        REG_WR(pDevice, MacCtrl.TxLengths, 0x26ff);
+    }
+    else
+    {
+        REG_WR(pDevice, MacCtrl.TxLengths, 0x2620);
+    }
+
+    return LmStatus;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_ReadPhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 PhyReg,
+PLM_UINT32 pData32) {
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode &
+            ~MI_MODE_AUTO_POLLING_ENABLE);
+        MM_Wait(40);
+    }
+
+    Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) |
+        ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) |
+        MI_COM_CMD_READ | MI_COM_START;
+
+    REG_WR(pDevice, MacCtrl.MiCom, Value32);
+
+    for(j = 0; j < 20; j++)
+    {
+        MM_Wait(25);
+
+        Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+
+        if(!(Value32 & MI_COM_BUSY))
+        {
+            MM_Wait(5);
+            Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+            Value32 &= MI_COM_PHY_DATA_MASK;
+            break;
+        }
+    }
+
+    if(Value32 & MI_COM_BUSY)
+    {
+        Value32 = 0;
+    }
+
+    *pData32 = Value32;
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+        MM_Wait(40);
+    }
+} /* LM_ReadPhy */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_WritePhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 PhyReg,
+LM_UINT32 Data32) {
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode &
+            ~MI_MODE_AUTO_POLLING_ENABLE);
+        MM_Wait(40);
+    }
+
+    Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) |
+        ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) |
+        (Data32 & MI_COM_PHY_DATA_MASK) | MI_COM_CMD_WRITE | MI_COM_START;
+
+    REG_WR(pDevice, MacCtrl.MiCom, Value32);
+
+    for(j = 0; j < 20; j++)
+    {
+        MM_Wait(25);
+
+        Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+
+        if(!(Value32 & MI_COM_BUSY))
+        {
+            MM_Wait(5);
+            break;
+        }
+    }
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+        MM_Wait(40);
+    }
+} /* LM_WritePhy */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetPowerState(
+PLM_DEVICE_BLOCK pDevice,
+LM_POWER_STATE PowerLevel) {
+    LM_UINT32 PmeSupport;
+    LM_UINT32 Value32;
+    LM_UINT32 PmCtrl;
+
+    /* make sureindirect accesses are enabled*/
+    MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl);
+
+    /* Clear the PME_ASSERT bit and the power state bits.  Also enable */
+    /* the PME bit. */
+    MM_ReadConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, &PmCtrl);
+
+    PmCtrl |= T3_PM_PME_ASSERTED;
+    PmCtrl &= ~T3_PM_POWER_STATE_MASK;
+
+    /* Set the appropriate power state. */
+    if(PowerLevel == LM_POWER_STATE_D0)
+    {
+
+        /* Bring the card out of low power mode. */
+        PmCtrl |= T3_PM_POWER_STATE_D0;
+        MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl);
+
+        REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl);
+        MM_Wait (40);
+#if 0   /* Bugfix by jmb...can't call WritePhy here because pDevice not fully initialized */
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x02);
+#endif
+
+        return LM_STATUS_SUCCESS;
+    }
+    else if(PowerLevel == LM_POWER_STATE_D1)
+    {
+        PmCtrl |= T3_PM_POWER_STATE_D1;
+    }
+    else if(PowerLevel == LM_POWER_STATE_D2)
+    {
+        PmCtrl |= T3_PM_POWER_STATE_D2;
+    }
+    else if(PowerLevel == LM_POWER_STATE_D3)
+    {
+        PmCtrl |= T3_PM_POWER_STATE_D3;
+    }
+    else
+    {
+        return LM_STATUS_FAILURE;
+    }
+    PmCtrl |= T3_PM_PME_ENABLE;
+
+    /* Mask out all interrupts so LM_SetupPhy won't be called while we are */
+    /* setting new line speed. */
+    Value32 = REG_RD(pDevice, PciCfg.MiscHostCtrl);
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, Value32 | MISC_HOST_CTRL_MASK_PCI_INT);
+
+    if(!pDevice->RestoreOnWakeUp)
+    {
+        pDevice->RestoreOnWakeUp = TRUE;
+        pDevice->WakeUpDisableAutoNeg = pDevice->DisableAutoNeg;
+        pDevice->WakeUpRequestedMediaType = pDevice->RequestedMediaType;
+    }
+
+    /* Force auto-negotiation to 10 line speed. */
+    pDevice->DisableAutoNeg = FALSE;
+    pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
+    LM_SetupPhy(pDevice);
+
+    /* Put the driver in the initial state, and go through the power down */
+    /* sequence. */
+    LM_Halt(pDevice);
+
+    MM_ReadConfig32(pDevice, T3_PCI_PM_CAP_REG, &PmeSupport);
+
+    if (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE)
+    {
+
+        /* Enable WOL. */
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x5a);
+        MM_Wait(40);
+
+        /* Set LED mode. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = LED_CTRL_PHY_MODE_1;
+        }
+        else
+        {
+            if(pDevice->LedMode == LED_MODE_OUTPUT)
+            {
+                Value32 = LED_CTRL_PHY_MODE_2;
+            }
+            else
+            {
+                Value32 = LED_CTRL_PHY_MODE_1;
+            }
+        }
+
+        Value32 = MAC_MODE_PORT_MODE_MII;
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            if(pDevice->LedMode == LED_MODE_LINK10 ||
+                pDevice->WolSpeed == WOL_SPEED_10MB)
+            {
+                Value32 |= MAC_MODE_LINK_POLARITY;
+            }
+        }
+        else
+        {
+            Value32 |= MAC_MODE_LINK_POLARITY;
+        }
+        REG_WR(pDevice, MacCtrl.Mode, Value32);
+        MM_Wait(40); MM_Wait(40); MM_Wait(40);
+
+        /* Always enable magic packet wake-up if we have vaux. */
+        if((PmeSupport & T3_PCI_PM_CAP_PME_D3COLD) &&
+            (pDevice->WakeUpModeCap & LM_WAKE_UP_MODE_MAGIC_PACKET))
+        {
+            Value32 |= MAC_MODE_DETECT_MAGIC_PACKET_ENABLE;
+        }
+
+        REG_WR(pDevice, MacCtrl.Mode, Value32);
+
+        /* Enable the receiver. */
+        REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_ENABLE);
+    }
+
+    /* Disable tx/rx clocks, and seletect an alternate clock. */
+    if(pDevice->WolSpeed == WOL_SPEED_100MB)
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+                T3_PCI_SELECT_ALTERNATE_CLOCK;
+        }
+        else
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK;
+        }
+        REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+
+        MM_Wait(40);
+
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+                T3_PCI_SELECT_ALTERNATE_CLOCK | T3_PCI_44MHZ_CORE_CLOCK;
+        }
+        else
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK |
+                T3_PCI_44MHZ_CORE_CLOCK;
+        }
+
+        REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+
+        MM_Wait(40);
+
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+                T3_PCI_44MHZ_CORE_CLOCK;
+        }
+        else
+        {
+            Value32 = T3_PCI_44MHZ_CORE_CLOCK;
+        }
+
+        REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+    }
+    else
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+                T3_PCI_SELECT_ALTERNATE_CLOCK |
+                T3_PCI_POWER_DOWN_PCI_PLL133;
+        }
+        else
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK |
+                T3_PCI_POWER_DOWN_PCI_PLL133;
+        }
+
+        REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+    }
+
+    MM_Wait(40);
+
+    if(!pDevice->EepromWp && (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE))
+    {
+        /* Switch adapter to auxilliary power. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+                MM_Wait(40);
+        }
+        else
+        {
+            /* GPIO0 = 0, GPIO1 = 1, GPIO2 = 1. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2);
+                MM_Wait(40);
+
+            /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 1. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2);
+                MM_Wait(40);
+
+            /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+                MM_Wait(40);
+        }
+    }
+
+    /* Set the phy to low power mode. */
+    /* Put the the hardware in low power mode. */
+    MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_SetPowerState */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+static LM_UINT32
+GetPhyAdFlowCntrlSettings(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+
+    Value32 = 0;
+
+    /* Auto negotiation flow control only when autonegotiation is enabled. */
+    if(pDevice->DisableAutoNeg == FALSE ||
+        pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO ||
+        pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO)
+    {
+        /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */
+        if((pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE) ||
+            ((pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
+            (pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)))
+        {
+            Value32 |= PHY_AN_AD_PAUSE_CAPABLE;
+        }
+        else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+        {
+            Value32 |= PHY_AN_AD_ASYM_PAUSE;
+        }
+        else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)
+        {
+            Value32 |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE;
+        }
+    }
+
+    return Value32;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_FAILURE                                                       */
+/*    LM_STATUS_SUCCESS                                                       */
+/*                                                                            */
+/******************************************************************************/
+static LM_STATUS
+LM_ForceAutoNegBcm540xPhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
+{
+    LM_MEDIA_TYPE MediaType;
+    LM_LINE_SPEED LineSpeed;
+    LM_DUPLEX_MODE DuplexMode;
+    LM_UINT32 NewPhyCtrl;
+    LM_UINT32 Value32;
+    LM_UINT32 Cnt;
+
+    /* Get the interface type, line speed, and duplex mode. */
+    LM_TranslateRequestedMediaType(RequestedMediaType, &MediaType, &LineSpeed,
+        &DuplexMode);
+
+    if (pDevice->RestoreOnWakeUp)
+    {
+        LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+        pDevice->advertising1000 = 0;
+        Value32 = PHY_AN_AD_10BASET_FULL | PHY_AN_AD_10BASET_HALF;
+        if (pDevice->WolSpeed == WOL_SPEED_100MB)
+        {
+            Value32 |= PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF;
+        }
+        Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+        Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+        LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+        pDevice->advertising = Value32;
+    }
+    /* Setup the auto-negotiation advertisement register. */
+    else if(LineSpeed == LM_LINE_SPEED_UNKNOWN)
+    {
+        /* Setup the 10/100 Mbps auto-negotiation advertisement register. */
+        Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD |
+            PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL |
+            PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF;
+        Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+        LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+        pDevice->advertising = Value32;
+
+        /* Advertise 1000Mbps */
+        Value32 = BCM540X_AN_AD_1000BASET_HALF | BCM540X_AN_AD_1000BASET_FULL;
+
+#if INCLUDE_5701_AX_FIX
+        /* Bug: workaround for CRC error in gigabit mode when we are in */
+        /* slave mode.  This will force the PHY to operate in */
+        /* master mode. */
+        if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+        {
+            Value32 |= BCM540X_CONFIG_AS_MASTER |
+                BCM540X_ENABLE_CONFIG_AS_MASTER;
+        }
+#endif
+
+        LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+        pDevice->advertising1000 = Value32;
+    }
+    else
+    {
+        if(LineSpeed == LM_LINE_SPEED_1000MBPS)
+        {
+            Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+            Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+            LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+            pDevice->advertising = Value32;
+
+            if(DuplexMode != LM_DUPLEX_MODE_FULL)
+            {
+                Value32 = BCM540X_AN_AD_1000BASET_HALF;
+            }
+            else
+            {
+                Value32 = BCM540X_AN_AD_1000BASET_FULL;
+            }
+
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+            pDevice->advertising1000 = Value32;
+        }
+        else if(LineSpeed == LM_LINE_SPEED_100MBPS)
+        {
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+            pDevice->advertising1000 = 0;
+
+            if(DuplexMode != LM_DUPLEX_MODE_FULL)
+            {
+                Value32 = PHY_AN_AD_100BASETX_HALF;
+            }
+            else
+            {
+                Value32 = PHY_AN_AD_100BASETX_FULL;
+            }
+
+            Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+            Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+            LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+            pDevice->advertising = Value32;
+        }
+        else if(LineSpeed == LM_LINE_SPEED_10MBPS)
+        {
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+            pDevice->advertising1000 = 0;
+
+            if(DuplexMode != LM_DUPLEX_MODE_FULL)
+            {
+                Value32 = PHY_AN_AD_10BASET_HALF;
+            }
+            else
+            {
+                Value32 = PHY_AN_AD_10BASET_FULL;
+            }
+
+            Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+            Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+            LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+            pDevice->advertising = Value32;
+        }
+    }
+
+    /* Force line speed if auto-negotiation is disabled. */
+    if(pDevice->DisableAutoNeg && LineSpeed != LM_LINE_SPEED_UNKNOWN)
+    {
+        /* This code path is executed only when there is link. */
+        pDevice->MediaType = MediaType;
+        pDevice->LineSpeed = LineSpeed;
+        pDevice->DuplexMode = DuplexMode;
+
+        /* Force line seepd. */
+        NewPhyCtrl = 0;
+        switch(LineSpeed)
+        {
+            case LM_LINE_SPEED_10MBPS:
+                NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_10MBPS;
+                break;
+            case LM_LINE_SPEED_100MBPS:
+                NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_100MBPS;
+                break;
+            case LM_LINE_SPEED_1000MBPS:
+                NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS;
+                break;
+            default:
+                NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS;
+                break;
+        }
+
+        if(DuplexMode == LM_DUPLEX_MODE_FULL)
+        {
+            NewPhyCtrl |= PHY_CTRL_FULL_DUPLEX_MODE;
+        }
+
+        /* Don't do anything if the PHY_CTRL is already what we wanted. */
+        LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+        if(Value32 != NewPhyCtrl)
+        {
+            /* Temporary bring the link down before forcing line speed. */
+            LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_LOOPBACK_MODE);
+
+            /* Wait for link to go down. */
+            for(Cnt = 0; Cnt < 15000; Cnt++)
+            {
+                MM_Wait(10);
+
+                LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+                LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+                if(!(Value32 & PHY_STATUS_LINK_PASS))
+                {
+                    MM_Wait(40);
+                    break;
+                }
+            }
+
+            LM_WritePhy(pDevice, PHY_CTRL_REG, NewPhyCtrl);
+            MM_Wait(40);
+        }
+    }
+    else
+    {
+        LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
+            PHY_CTRL_RESTART_AUTO_NEG);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_ForceAutoNegBcm540xPhy */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+static LM_STATUS
+LM_ForceAutoNeg(
+PLM_DEVICE_BLOCK pDevice,
+LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
+{
+    LM_STATUS LmStatus;
+
+    /* Initialize the phy chip. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM5400_PHY_ID:
+        case PHY_BCM5401_PHY_ID:
+        case PHY_BCM5411_PHY_ID:
+        case PHY_BCM5701_PHY_ID:
+        case PHY_BCM5703_PHY_ID:
+        case PHY_BCM5704_PHY_ID:
+            LmStatus = LM_ForceAutoNegBcm540xPhy(pDevice, RequestedMediaType);
+            break;
+
+        default:
+            LmStatus = LM_STATUS_FAILURE;
+            break;
+    }
+
+    return LmStatus;
+} /* LM_ForceAutoNeg */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS LM_LoadFirmware(PLM_DEVICE_BLOCK pDevice,
+                          PT3_FWIMG_INFO pFwImg,
+                          LM_UINT32 LoadCpu,
+                          LM_UINT32 StartCpu)
+{
+    LM_UINT32 i;
+    LM_UINT32 address;
+
+    if (LoadCpu & T3_RX_CPU_ID)
+    {
+        if (LM_HaltCpu(pDevice,T3_RX_CPU_ID) != LM_STATUS_SUCCESS)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        /* First of all clear scrach pad memory */
+        for (i = 0; i < T3_RX_CPU_SPAD_SIZE; i+=4)
+        {
+            LM_RegWrInd(pDevice,T3_RX_CPU_SPAD_ADDR+i,0);
+        }
+
+        /* Copy code first */
+        address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff);
+        for (i = 0; i <= pFwImg->Text.Length; i+=4)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Text.Buffer)[i/4]);
+        }
+
+        address = T3_RX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff);
+        for (i = 0; i <= pFwImg->ROnlyData.Length; i+=4)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->ROnlyData.Buffer)[i/4]);
+        }
+
+        address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff);
+        for (i= 0; i <= pFwImg->Data.Length; i+=4)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]);
+        }
+    }
+
+    if (LoadCpu & T3_TX_CPU_ID)
+    {
+        if (LM_HaltCpu(pDevice,T3_TX_CPU_ID) != LM_STATUS_SUCCESS)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        /* First of all clear scrach pad memory */
+        for (i = 0; i < T3_TX_CPU_SPAD_SIZE; i+=4)
+        {
+            LM_RegWrInd(pDevice,T3_TX_CPU_SPAD_ADDR+i,0);
+        }
+
+        /* Copy code first */
+        address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff);
+        for (i= 0; i <= pFwImg->Text.Length; i+=4)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Text.Buffer)[i/4]);
+        }
+
+        address = T3_TX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff);
+        for (i= 0; i <= pFwImg->ROnlyData.Length; i+=4)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->ROnlyData.Buffer)[i/4]);
+        }
+
+        address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff);
+        for (i= 0; i <= pFwImg->Data.Length; i+=4)
+        {
+            LM_RegWrInd(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]);
+        }
+    }
+
+    if (StartCpu & T3_RX_CPU_ID)
+    {
+        /* Start Rx CPU */
+        REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress);
+        for (i = 0 ; i < 5; i++)
+        {
+          if (pFwImg->StartAddress == REG_RD(pDevice,rxCpu.reg.PC))
+             break;
+
+          REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+          REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+          REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress);
+          MM_Wait(1000);
+        }
+
+        REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,rxCpu.reg.mode, 0);
+    }
+
+    if (StartCpu & T3_TX_CPU_ID)
+    {
+        /* Start Tx CPU */
+        REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress);
+        for (i = 0 ; i < 5; i++)
+        {
+          if (pFwImg->StartAddress == REG_RD(pDevice,txCpu.reg.PC))
+             break;
+
+          REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+          REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT);
+          REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress);
+          MM_Wait(1000);
+        }
+
+        REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,txCpu.reg.mode, 0);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number)
+{
+    LM_UINT32 i;
+
+    if (cpu_number == T3_RX_CPU_ID)
+    {
+        for (i = 0 ; i < 10000; i++)
+        {
+            REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+            REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+
+            if (REG_RD(pDevice,rxCpu.reg.mode) & CPU_MODE_HALT)
+              break;
+        }
+
+        REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+        MM_Wait(10);
+    }
+    else
+    {
+        for (i = 0 ; i < 10000; i++)
+        {
+            REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+            REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT);
+
+            if (REG_RD(pDevice,txCpu.reg.mode) & CPU_MODE_HALT)
+               break;
+        }
+    }
+
+  return (( i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS);
+}
+
+
+int
+LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec)
+{
+       LM_UINT32 Oldcfg;
+       int j;
+       int ret = 0;
+
+       if(BlinkDurationSec == 0)
+       {
+               return 0;
+        }
+       if(BlinkDurationSec > 120)
+        {
+               BlinkDurationSec = 120;
+       }
+
+       Oldcfg = REG_RD(pDevice, MacCtrl.LedCtrl);
+       for(j = 0; j < BlinkDurationSec * 2; j++)
+       {
+               if(j % 2)
+               {
+                       /* Turn on the LEDs. */
+                       REG_WR(pDevice, MacCtrl.LedCtrl,
+                               LED_CTRL_OVERRIDE_LINK_LED |
+                               LED_CTRL_1000MBPS_LED_ON |
+                               LED_CTRL_100MBPS_LED_ON |
+                               LED_CTRL_10MBPS_LED_ON |
+                               LED_CTRL_OVERRIDE_TRAFFIC_LED |
+                               LED_CTRL_BLINK_TRAFFIC_LED |
+                               LED_CTRL_TRAFFIC_LED);
+               }
+               else
+               {
+                       /* Turn off the LEDs. */
+                       REG_WR(pDevice, MacCtrl.LedCtrl,
+                               LED_CTRL_OVERRIDE_LINK_LED |
+                               LED_CTRL_OVERRIDE_TRAFFIC_LED);
+               }
+
+#ifndef EMBEDDED
+                current->state = TASK_INTERRUPTIBLE;
+                if (schedule_timeout(HZ/2) != 0) {
+                        ret = -EINTR;
+                        break;
+                }
+#else
+                udelay(100000);  /* 1s sleep */
+#endif
+       }
+       REG_WR(pDevice, MacCtrl.LedCtrl, Oldcfg);
+       return ret;
+}
+
+int t3_do_dma(PLM_DEVICE_BLOCK pDevice,
+                   LM_PHYSICAL_ADDRESS host_addr_phy, int length,
+                   int dma_read)
+{
+    T3_DMA_DESC dma_desc;
+    int i;
+    LM_UINT32 dma_desc_addr;
+    LM_UINT32 value32;
+
+    REG_WR(pDevice, BufMgr.Mode, 0);
+    REG_WR(pDevice, Ftq.Reset, 0);
+
+    dma_desc.host_addr.High = host_addr_phy.High;
+    dma_desc.host_addr.Low = host_addr_phy.Low;
+    dma_desc.nic_mbuf = 0x2100;
+    dma_desc.len = length;
+    dma_desc.flags = 0x00000004; /* Generate Rx-CPU event */
+
+    if (dma_read)
+    {
+        dma_desc.cqid_sqid = (T3_QID_RX_BD_COMP << 8) |
+            T3_QID_DMA_HIGH_PRI_READ;
+        REG_WR(pDevice, DmaRead.Mode, DMA_READ_MODE_ENABLE);
+    }
+    else
+    {
+        dma_desc.cqid_sqid = (T3_QID_RX_DATA_COMP << 8) |
+            T3_QID_DMA_HIGH_PRI_WRITE;
+        REG_WR(pDevice, DmaWrite.Mode, DMA_WRITE_MODE_ENABLE);
+    }
+
+    dma_desc_addr = T3_NIC_DMA_DESC_POOL_ADDR;
+
+    /* Writing this DMA descriptor to DMA memory */
+    for (i = 0; i < sizeof(T3_DMA_DESC); i += 4)
+    {
+        value32 = *((PLM_UINT32) (((PLM_UINT8) &dma_desc) + i));
+        MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, dma_desc_addr+i);
+        MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, cpu_to_le32(value32));
+    }
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, 0);
+
+    if (dma_read)
+        REG_WR(pDevice, Ftq.DmaHighReadFtqFifoEnqueueDequeue, dma_desc_addr);
+    else
+        REG_WR(pDevice, Ftq.DmaHighWriteFtqFifoEnqueueDequeue, dma_desc_addr);
+
+    for (i = 0; i < 40; i++)
+    {
+        if (dma_read)
+            value32 = REG_RD(pDevice, Ftq.RcvBdCompFtqFifoEnqueueDequeue);
+        else
+            value32 = REG_RD(pDevice, Ftq.RcvDataCompFtqFifoEnqueueDequeue);
+
+        if ((value32 & 0xffff) == dma_desc_addr)
+            break;
+
+        MM_Wait(10);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS
+LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt,
+           LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize)
+{
+    int j;
+    LM_UINT32 *ptr;
+    int dma_success = 0;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+        T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+    {
+        return LM_STATUS_SUCCESS;
+    }
+    while (!dma_success)
+    {
+        /* Fill data with incremental patterns */
+        ptr = (LM_UINT32 *)pBufferVirt;
+        for (j = 0; j < BufferSize/4; j++)
+            *ptr++ = j;
+
+        if (t3_do_dma(pDevice,BufferPhy,BufferSize, 1) == LM_STATUS_FAILURE)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        MM_Wait(40);
+        ptr = (LM_UINT32 *)pBufferVirt;
+        /* Fill data with zero */
+        for (j = 0; j < BufferSize/4; j++)
+            *ptr++ = 0;
+
+        if (t3_do_dma(pDevice,BufferPhy,BufferSize, 0) == LM_STATUS_FAILURE)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        MM_Wait(40);
+        /* Check for data */
+        ptr = (LM_UINT32 *)pBufferVirt;
+        for (j = 0; j < BufferSize/4; j++)
+        {
+            if (*ptr++ != j)
+            {
+                if ((pDevice->DmaReadWriteCtrl & DMA_CTRL_WRITE_BOUNDARY_MASK)
+                    == DMA_CTRL_WRITE_BOUNDARY_DISABLE)
+                {
+                    pDevice->DmaReadWriteCtrl = (pDevice->DmaReadWriteCtrl &
+                         ~DMA_CTRL_WRITE_BOUNDARY_MASK) |
+                          DMA_CTRL_WRITE_BOUNDARY_16;
+                    REG_WR(pDevice, PciCfg.DmaReadWriteCtrl,
+                           pDevice->DmaReadWriteCtrl);
+                    break;
+                 }
+                 else
+                 {
+                     return LM_STATUS_FAILURE;
+                 }
+            }
+        }
+        if (j == (BufferSize/4))
+            dma_success = 1;
+    }
+    return LM_STATUS_SUCCESS;
+}
+#endif /* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_TIGON3 */
diff --git a/drivers/tigon3.h b/drivers/tigon3.h
new file mode 100644 (file)
index 0000000..8d30ac9
--- /dev/null
@@ -0,0 +1,3469 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* 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, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*                                                                            */
+/******************************************************************************/
+
+#ifndef TIGON3_H
+#define TIGON3_H
+
+#include "bcm570x_lm.h"
+#if INCLUDE_TBI_SUPPORT
+#include "bcm570x_autoneg.h"
+#endif
+
+
+/* io defines */
+#if !defined(BIG_ENDIAN_HOST)
+#define readl(addr) \
+              (LONGSWAP((*(volatile unsigned int *)(addr))))
+#define writel(b,addr) \
+              ((*(volatile unsigned int *)(addr)) = (LONGSWAP(b)))
+#else
+#if 0 /* !defined(PPC603) */
+#define readl(addr) (*(volatile unsigned int*)(0xa0000000 + (unsigned long)(addr)))
+#define writel(b,addr) ((*(volatile unsigned int *) ((unsigned long)(addr) + 0xa0000000)) = (b))
+#else
+#if 1
+#define readl(addr) (*(volatile unsigned int*)(addr))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+#else
+extern int sprintf(char* buf, const char* f, ...);
+static __inline unsigned int readl(void* addr){
+    char buf[128];
+    unsigned int tmp = (*(volatile unsigned int*)(addr));
+    sprintf(buf,"%s:%s: read 0x%x from 0x%x\n",__FILE__,__LINE__,tmp,addr,0,0);
+    sysSerialPrintString(buf);
+    return tmp;
+}
+static __inline void writel(unsigned int b, unsigned int addr){
+    char buf[128];
+    ((*(volatile unsigned int *) (addr)) = (b));
+    sprintf(buf,"%s:%s: write 0x%x to 0x%x\n",__FILE__,__LINE__,b,addr,0,0);
+    sysSerialPrintString(buf);
+}
+#endif
+#endif /* PPC603 */
+#endif
+
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+/* Maxim number of packet descriptors used for sending packets. */
+#define MAX_TX_PACKET_DESC_COUNT            600
+#define DEFAULT_TX_PACKET_DESC_COUNT        2
+
+/* Maximum number of packet descriptors used for receiving packets. */
+#if T3_JUMBO_RCB_ENTRY_COUNT
+#define MAX_RX_PACKET_DESC_COUNT                                            \
+    (T3_STD_RCV_RCB_ENTRY_COUNT + T3_JUMBO_RCV_RCB_ENTRY_COUNT)
+#else
+#define MAX_RX_PACKET_DESC_COUNT            800
+#endif
+#define DEFAULT_RX_PACKET_DESC_COUNT        2
+
+/* Threshhold for double copying small tx packets.  0 will disable double */
+/* copying of small Tx packets. */
+#define DEFAULT_TX_COPY_BUFFER_SIZE         0
+#define MIN_TX_COPY_BUFFER_SIZE             64
+#define MAX_TX_COPY_BUFFER_SIZE             512
+
+/* Cache line. */
+#define COMMON_CACHE_LINE_SIZE              0x20
+#define COMMON_CACHE_LINE_MASK              (COMMON_CACHE_LINE_SIZE-1)
+
+/* Maximum number of fragment we can handle. */
+#ifndef MAX_FRAGMENT_COUNT
+#define MAX_FRAGMENT_COUNT                  32
+#endif
+
+/* B0 bug. */
+#define BCM5700_BX_MIN_FRAG_SIZE            10
+#define BCM5700_BX_MIN_FRAG_BUF_SIZE        16  /* nice aligned size. */
+#define BCM5700_BX_MIN_FRAG_BUF_SIZE_MASK   (BCM5700_BX_MIN_FRAG_BUF_SIZE-1)
+#define BCM5700_BX_TX_COPY_BUF_SIZE         (BCM5700_BX_MIN_FRAG_BUF_SIZE * \
+                                            MAX_FRAGMENT_COUNT)
+
+/* MAGIC number. */
+/* #define T3_MAGIC_NUM                        'KevT' */
+#define T3_FIRMWARE_MAILBOX                0x0b50
+#define T3_MAGIC_NUM                       0x4B657654
+#define T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE 0x4861764b
+
+#define T3_NIC_DATA_SIG_ADDR               0x0b54
+#define T3_NIC_DATA_SIG                    0x4b657654
+
+#define T3_NIC_DATA_NIC_CFG_ADDR           0x0b58
+#define T3_NIC_CFG_LED_MODE_UNKNOWN        BIT_NONE
+#define T3_NIC_CFG_LED_MODE_TRIPLE_SPEED   BIT_2
+#define T3_NIC_CFG_LED_MODE_LINK_SPEED     BIT_3
+#define T3_NIC_CFG_LED_MODE_OPEN_DRAIN     BIT_2
+#define T3_NIC_CFG_LED_MODE_OUTPUT         BIT_3
+#define T3_NIC_CFG_LED_MODE_MASK           (BIT_2 | BIT_3)
+#define T3_NIC_CFG_PHY_TYPE_UNKNOWN         BIT_NONE
+#define T3_NIC_CFG_PHY_TYPE_COPPER          BIT_4
+#define T3_NIC_CFG_PHY_TYPE_FIBER           BIT_5
+#define T3_NIC_CFG_PHY_TYPE_MASK            (BIT_4 | BIT_5)
+#define T3_NIC_CFG_ENABLE_WOL               BIT_6
+#define T3_NIC_CFG_ENABLE_ASF               BIT_7
+#define T3_NIC_EEPROM_WP                    BIT_8
+
+#define T3_NIC_DATA_PHY_ID_ADDR            0x0b74
+#define T3_NIC_PHY_ID1_MASK                0xffff0000
+#define T3_NIC_PHY_ID2_MASK                0x0000ffff
+
+#define T3_CMD_MAILBOX                      0x0b78
+#define T3_CMD_NICDRV_ALIVE                 0x01
+#define T3_CMD_NICDRV_PAUSE_FW              0x02
+#define T3_CMD_NICDRV_IPV4ADDR_CHANGE       0x03
+#define T3_CMD_NICDRV_IPV6ADDR_CHANGE       0x04
+#define T3_CMD_5703A0_FIX_DMAFW_DMAR        0x05
+#define T3_CMD_5703A0_FIX_DMAFW_DMAW        0x06
+
+#define T3_CMD_LENGTH_MAILBOX               0x0b7c
+#define T3_CMD_DATA_MAILBOX                 0x0b80
+
+#define T3_ASF_FW_STATUS_MAILBOX            0x0c00
+
+#define T3_DRV_STATE_MAILBOX                0x0c04
+#define T3_DRV_STATE_START                  0x01
+#define T3_DRV_STATE_UNLOAD                 0x02
+#define T3_DRV_STATE_WOL                    0x03
+#define T3_DRV_STATE_SUSPEND                0x04
+
+#define T3_FW_RESET_TYPE_MAILBOX            0x0c08
+
+#define T3_MAC_ADDR_HIGH_MAILBOX            0x0c14
+#define T3_MAC_ADDR_LOW_MAILBOX             0x0c18
+
+/******************************************************************************/
+/* Hardware constants. */
+/******************************************************************************/
+
+/* Number of entries in the send ring:  must be 512. */
+#define T3_SEND_RCB_ENTRY_COUNT             512
+#define T3_SEND_RCB_ENTRY_COUNT_MASK        (T3_SEND_RCB_ENTRY_COUNT-1)
+
+/* Number of send RCBs.  May be 1-16 but for now, only support one. */
+#define T3_MAX_SEND_RCB_COUNT               16
+
+/* Number of entries in the Standard Receive RCB.  Must be 512 entries. */
+#define T3_STD_RCV_RCB_ENTRY_COUNT          512
+#define T3_STD_RCV_RCB_ENTRY_COUNT_MASK     (T3_STD_RCV_RCB_ENTRY_COUNT-1)
+#define DEFAULT_STD_RCV_DESC_COUNT          200    /* Must be < 512. */
+#define MAX_STD_RCV_BUFFER_SIZE             0x600
+
+/* Number of entries in the Mini Receive RCB.  This value can either be */
+/* 0, 1024.  Currently Mini Receive RCB is disabled. */
+#ifndef T3_MINI_RCV_RCB_ENTRY_COUNT
+#define T3_MINI_RCV_RCB_ENTRY_COUNT         0
+#endif /* T3_MINI_RCV_RCB_ENTRY_COUNT */
+#define T3_MINI_RCV_RCB_ENTRY_COUNT_MASK    (T3_MINI_RCV_RCB_ENTRY_COUNT-1)
+#define MAX_MINI_RCV_BUFFER_SIZE            512
+#define DEFAULT_MINI_RCV_BUFFER_SIZE        64
+#define DEFAULT_MINI_RCV_DESC_COUNT         100    /* Must be < 1024. */
+
+/* Number of entries in the Jumbo Receive RCB.  This value must 256 or 0. */
+/* Currently, Jumbo Receive RCB is disabled. */
+#ifndef T3_JUMBO_RCV_RCB_ENTRY_COUNT
+#define T3_JUMBO_RCV_RCB_ENTRY_COUNT        0
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+#define T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK   (T3_JUMBO_RCV_RCB_ENTRY_COUNT-1)
+
+#define MAX_JUMBO_RCV_BUFFER_SIZE           (10 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_RCV_BUFFER_SIZE       (4 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_RCV_DESC_COUNT        128     /* Must be < 256. */
+
+#define MAX_JUMBO_TX_BUFFER_SIZE            (8 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_TX_BUFFER_SIZE        (4 * 1024) /* > 1514 */
+
+/* Number of receive return RCBs.  Maybe 1-16 but for now, only support one. */
+#define T3_MAX_RCV_RETURN_RCB_COUNT         16
+
+/* Number of entries in a Receive Return ring.  This value is either 1024 */
+/* or 2048. */
+#ifndef T3_RCV_RETURN_RCB_ENTRY_COUNT
+#define T3_RCV_RETURN_RCB_ENTRY_COUNT       1024
+#endif /* T3_RCV_RETURN_RCB_ENTRY_COUNT */
+#define T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK  (T3_RCV_RETURN_RCB_ENTRY_COUNT-1)
+
+
+/* Default coalescing parameters. */
+#define DEFAULT_RX_COALESCING_TICKS         100
+#define MAX_RX_COALESCING_TICKS             500
+#define DEFAULT_TX_COALESCING_TICKS         400
+#define MAX_TX_COALESCING_TICKS             500
+#define DEFAULT_RX_MAX_COALESCED_FRAMES     10
+#define MAX_RX_MAX_COALESCED_FRAMES         100
+#define ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES    5
+#define ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES    42
+#define ADAPTIVE_LO_RX_COALESCING_TICKS         50
+#define ADAPTIVE_HI_RX_COALESCING_TICKS         300
+#define ADAPTIVE_LO_PKT_THRESH              30000
+#define ADAPTIVE_HI_PKT_THRESH              74000
+#define DEFAULT_TX_MAX_COALESCED_FRAMES     40
+#define ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES    25
+#define ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES    75
+#define MAX_TX_MAX_COALESCED_FRAMES         100
+
+#define DEFAULT_RX_COALESCING_TICKS_DURING_INT          25
+#define DEFAULT_TX_COALESCING_TICKS_DURING_INT          25
+#define DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT      5
+#define DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT      5
+
+#define BAD_DEFAULT_VALUE                               0xffffffff
+
+#define DEFAULT_STATS_COALESCING_TICKS      1000000
+#define MAX_STATS_COALESCING_TICKS          3600000000U
+
+
+/* Receive BD Replenish thresholds. */
+#define DEFAULT_RCV_STD_BD_REPLENISH_THRESHOLD      4
+#define DEFAULT_RCV_JUMBO_BD_REPLENISH_THRESHOLD    4
+
+#define SPLIT_MODE_DISABLE                          0
+#define SPLIT_MODE_ENABLE                           1
+
+#define SPLIT_MODE_5704_MAX_REQ                     3
+
+/* Maximum physical fragment size. */
+#define MAX_FRAGMENT_SIZE                   (64 * 1024)
+
+
+/* Standard view. */
+#define T3_STD_VIEW_SIZE                    (64 * 1024)
+#define T3_FLAT_VIEW_SIZE                   (32 * 1024 * 1024)
+
+
+/* Buffer descriptor base address on the NIC's memory. */
+
+#define T3_NIC_SND_BUFFER_DESC_ADDR         0x4000
+#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR     0x6000
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR   0x7000
+
+#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR_EXT_MEM     0xc000
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR_EXT_MEM   0xd000
+#define T3_NIC_MINI_RCV_BUFFER_DESC_ADDR_EXT_MEM    0xe000
+
+#define T3_NIC_SND_BUFFER_DESC_SIZE         (T3_SEND_RCB_ENTRY_COUNT * \
+                                            sizeof(T3_SND_BD) / 4)
+
+#define T3_NIC_STD_RCV_BUFFER_DESC_SIZE     (T3_STD_RCV_RCB_ENTRY_COUNT * \
+                                            sizeof(T3_RCV_BD) / 4)
+
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_SIZE   (T3_JUMBO_RCV_RCB_ENTRY_COUNT * \
+                                            sizeof(T3_EXT_RCV_BD) / 4)
+
+
+/* MBUF pool. */
+#define T3_NIC_MBUF_POOL_ADDR               0x8000
+/* #define T3_NIC_MBUF_POOL_SIZE               0x18000 */
+#define T3_NIC_MBUF_POOL_SIZE96             0x18000
+#define T3_NIC_MBUF_POOL_SIZE64             0x10000
+
+
+#define T3_NIC_MBUF_POOL_ADDR_EXT_MEM       0x20000
+
+/* DMA descriptor pool */
+#define T3_NIC_DMA_DESC_POOL_ADDR           0x2000
+#define T3_NIC_DMA_DESC_POOL_SIZE           0x2000      /* 8KB. */
+
+#define T3_DEF_DMA_MBUF_LOW_WMARK           0x40
+#define T3_DEF_RX_MAC_MBUF_LOW_WMARK        0x20
+#define T3_DEF_MBUF_HIGH_WMARK              0x60
+
+#define T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO     304
+#define T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO  152
+#define T3_DEF_MBUF_HIGH_WMARK_JUMBO        380
+
+#define T3_DEF_DMA_DESC_LOW_WMARK           5
+#define T3_DEF_DMA_DESC_HIGH_WMARK          10
+
+/* Maximum size of giant TCP packet can be sent */
+#define T3_TCP_SEG_MAX_OFFLOAD_SIZE         64*1000
+#define T3_TCP_SEG_MIN_NUM_SEG              20
+
+#define T3_RX_CPU_ID    0x1
+#define T3_TX_CPU_ID    0x2
+#define T3_RX_CPU_SPAD_ADDR  0x30000
+#define T3_RX_CPU_SPAD_SIZE  0x4000
+#define T3_TX_CPU_SPAD_ADDR  0x34000
+#define T3_TX_CPU_SPAD_SIZE  0x4000
+
+typedef struct T3_DIR_ENTRY
+{
+  PLM_UINT8 Buffer;
+  LM_UINT32 Offset;
+  LM_UINT32 Length;
+} T3_DIR_ENTRY,*PT3_DIR_ENTRY;
+
+typedef struct T3_FWIMG_INFO
+{
+  LM_UINT32 StartAddress;
+  T3_DIR_ENTRY Text;
+  T3_DIR_ENTRY ROnlyData;
+  T3_DIR_ENTRY Data;
+  T3_DIR_ENTRY Sbss;
+  T3_DIR_ENTRY Bss;
+} T3_FWIMG_INFO, *PT3_FWIMG_INFO;
+
+
+
+/******************************************************************************/
+/* Tigon3 PCI Registers. */
+/******************************************************************************/
+#define T3_PCI_ID_BCM5700                   0x164414e4
+#define T3_PCI_ID_BCM5701                   0x164514e4
+#define T3_PCI_ID_BCM5702                   0x164614e4
+#define T3_PCI_ID_BCM5702x                  0x16A614e4
+#define T3_PCI_ID_BCM5703                   0x164714e4
+#define T3_PCI_ID_BCM5703x                  0x16A714e4
+#define T3_PCI_ID_BCM5702FE                 0x164D14e4
+#define T3_PCI_ID_BCM5704                   0x164814e4
+
+#define T3_PCI_VENDOR_ID                    (T3_PCI_ID & 0xffff)
+#define T3_PCI_DEVICE_ID                    (T3_PCI_ID >> 16)
+
+#define T3_PCI_MISC_HOST_CTRL_REG           0x68
+
+/* The most significant 16bit of register 0x68. */
+/* ChipId:4, ChipRev:4, MetalRev:8 */
+#define T3_CHIP_ID_5700_A0                  0x7000
+#define T3_CHIP_ID_5700_A1                  0x7001
+#define T3_CHIP_ID_5700_B0                  0x7100
+#define T3_CHIP_ID_5700_B1                  0x7101
+#define T3_CHIP_ID_5700_C0                  0x7200
+
+#define T3_CHIP_ID_5701_A0                  0x0000
+#define T3_CHIP_ID_5701_B0                  0x0100
+#define T3_CHIP_ID_5701_B2                  0x0102
+#define T3_CHIP_ID_5701_B5                  0x0105
+
+#define T3_CHIP_ID_5703_A0                  0x1000
+#define T3_CHIP_ID_5703_A1                  0x1001
+#define T3_CHIP_ID_5703_A2                  0x1002
+
+#define T3_CHIP_ID_5704_A0                  0x2000
+
+/* Chip Id. */
+#define T3_ASIC_REV(_ChipRevId)             ((_ChipRevId) >> 12)
+#define T3_ASIC_REV_5700                    0x07
+#define T3_ASIC_REV_5701                    0x00
+#define T3_ASIC_REV_5703                    0x01
+#define T3_ASIC_REV_5704                    0x02
+
+
+/* Chip id and revision. */
+#define T3_CHIP_REV(_ChipRevId)             ((_ChipRevId) >> 8)
+#define T3_CHIP_REV_5700_AX                 0x70
+#define T3_CHIP_REV_5700_BX                 0x71
+#define T3_CHIP_REV_5700_CX                 0x72
+#define T3_CHIP_REV_5701_AX                 0x00
+
+/* Metal revision. */
+#define T3_METAL_REV(_ChipRevId)            ((_ChipRevId) & 0xff)
+#define T3_METAL_REV_A0                     0x00
+#define T3_METAL_REV_A1                     0x01
+#define T3_METAL_REV_B0                     0x00
+#define T3_METAL_REV_B1                     0x01
+#define T3_METAL_REV_B2                     0x02
+
+#define T3_PCI_REG_CLOCK_CTRL               0x74
+
+#define T3_PCI_DISABLE_RX_CLOCK             BIT_10
+#define T3_PCI_DISABLE_TX_CLOCK             BIT_11
+#define T3_PCI_SELECT_ALTERNATE_CLOCK       BIT_12
+#define T3_PCI_POWER_DOWN_PCI_PLL133        BIT_15
+#define T3_PCI_44MHZ_CORE_CLOCK             BIT_18
+
+
+#define T3_PCI_REG_ADDR_REG                 0x78
+#define T3_PCI_REG_DATA_REG                 0x80
+
+#define T3_PCI_MEM_WIN_ADDR_REG             0x7c
+#define T3_PCI_MEM_WIN_DATA_REG             0x84
+
+#define T3_PCI_PM_CAP_REG                   0x48
+
+#define T3_PCI_PM_CAP_PME_D3COLD            BIT_31
+#define T3_PCI_PM_CAP_PME_D3HOT             BIT_30
+
+#define T3_PCI_PM_STATUS_CTRL_REG           0x4c
+
+#define T3_PM_POWER_STATE_MASK              (BIT_0 | BIT_1)
+#define T3_PM_POWER_STATE_D0                BIT_NONE
+#define T3_PM_POWER_STATE_D1                BIT_0
+#define T3_PM_POWER_STATE_D2                BIT_1
+#define T3_PM_POWER_STATE_D3                (BIT_0 | BIT_1)
+
+#define T3_PM_PME_ENABLE                    BIT_8
+#define T3_PM_PME_ASSERTED                  BIT_15
+
+
+/* PCI state register. */
+#define T3_PCI_STATE_REG                    0x70
+
+#define T3_PCI_STATE_FORCE_RESET            BIT_0
+#define T3_PCI_STATE_INT_NOT_ACTIVE         BIT_1
+#define T3_PCI_STATE_CONVENTIONAL_PCI_MODE  BIT_2
+#define T3_PCI_STATE_BUS_SPEED_HIGH         BIT_3
+#define T3_PCI_STATE_32BIT_PCI_BUS          BIT_4
+
+
+/* Broadcom subsystem/subvendor IDs. */
+#define T3_SVID_BROADCOM                            0x14e4
+
+#define T3_SSID_BROADCOM_BCM95700A6                 0x1644
+#define T3_SSID_BROADCOM_BCM95701A5                 0x0001
+#define T3_SSID_BROADCOM_BCM95700T6                 0x0002  /* BCM8002 */
+#define T3_SSID_BROADCOM_BCM95700A9                 0x0003  /* Agilent */
+#define T3_SSID_BROADCOM_BCM95701T1                 0x0005
+#define T3_SSID_BROADCOM_BCM95701T8                 0x0006
+#define T3_SSID_BROADCOM_BCM95701A7                 0x0007  /* Agilent */
+#define T3_SSID_BROADCOM_BCM95701A10                0x0008
+#define T3_SSID_BROADCOM_BCM95701A12                0x8008
+#define T3_SSID_BROADCOM_BCM95703Ax1                0x0009
+#define T3_SSID_BROADCOM_BCM95703Ax2                0x8009
+
+/* 3COM subsystem/subvendor IDs. */
+#define T3_SVID_3COM                                0x10b7
+
+#define T3_SSID_3COM_3C996T                         0x1000
+#define T3_SSID_3COM_3C996BT                        0x1006
+#define T3_SSID_3COM_3C996CT                        0x1002
+#define T3_SSID_3COM_3C997T                         0x1003
+#define T3_SSID_3COM_3C1000T                        0x1007
+#define T3_SSID_3COM_3C940BR01                      0x1008
+
+/* Fiber boards. */
+#define T3_SSID_3COM_3C996SX                        0x1004
+#define T3_SSID_3COM_3C997SX                        0x1005
+
+
+/* Dell subsystem/subvendor IDs. */
+
+#define T3_SVID_DELL                                0x1028
+
+#define T3_SSID_DELL_VIPER                          0x00d1
+#define T3_SSID_DELL_JAGUAR                         0x0106
+#define T3_SSID_DELL_MERLOT                         0x0109
+#define T3_SSID_DELL_SLIM_MERLOT                    0x010a
+
+/* Compaq subsystem/subvendor IDs */
+
+#define T3_SVID_COMPAQ                              0x0e11
+
+#define T3_SSID_COMPAQ_BANSHEE                      0x007c
+#define T3_SSID_COMPAQ_BANSHEE_2                    0x009a
+#define T3_SSID_COMPAQ_CHANGELING                   0x007d
+#define T3_SSID_COMPAQ_NC7780                       0x0085
+#define T3_SSID_COMPAQ_NC7780_2                     0x0099
+
+
+/******************************************************************************/
+/* MII registers. */
+/******************************************************************************/
+
+/* Control register. */
+#define PHY_CTRL_REG                                0x00
+
+#define PHY_CTRL_SPEED_MASK                         (BIT_6 | BIT_13)
+#define PHY_CTRL_SPEED_SELECT_10MBPS                BIT_NONE
+#define PHY_CTRL_SPEED_SELECT_100MBPS               BIT_13
+#define PHY_CTRL_SPEED_SELECT_1000MBPS              BIT_6
+#define PHY_CTRL_COLLISION_TEST_ENABLE              BIT_7
+#define PHY_CTRL_FULL_DUPLEX_MODE                   BIT_8
+#define PHY_CTRL_RESTART_AUTO_NEG                   BIT_9
+#define PHY_CTRL_ISOLATE_PHY                        BIT_10
+#define PHY_CTRL_LOWER_POWER_MODE                   BIT_11
+#define PHY_CTRL_AUTO_NEG_ENABLE                    BIT_12
+#define PHY_CTRL_LOOPBACK_MODE                      BIT_14
+#define PHY_CTRL_PHY_RESET                          BIT_15
+
+
+/* Status register. */
+#define PHY_STATUS_REG                              0x01
+
+#define PHY_STATUS_LINK_PASS                        BIT_2
+#define PHY_STATUS_AUTO_NEG_COMPLETE                BIT_5
+
+
+/* Phy Id registers. */
+#define PHY_ID1_REG                                 0x02
+#define PHY_ID1_OUI_MASK                            0xffff
+
+#define PHY_ID2_REG                                 0x03
+#define PHY_ID2_REV_MASK                            0x000f
+#define PHY_ID2_MODEL_MASK                          0x03f0
+#define PHY_ID2_OUI_MASK                            0xfc00
+
+
+/* Auto-negotiation advertisement register. */
+#define PHY_AN_AD_REG                               0x04
+
+#define PHY_AN_AD_ASYM_PAUSE                        BIT_11
+#define PHY_AN_AD_PAUSE_CAPABLE                     BIT_10
+#define PHY_AN_AD_10BASET_HALF                      BIT_5
+#define PHY_AN_AD_10BASET_FULL                      BIT_6
+#define PHY_AN_AD_100BASETX_HALF                    BIT_7
+#define PHY_AN_AD_100BASETX_FULL                    BIT_8
+#define PHY_AN_AD_PROTOCOL_802_3_CSMA_CD            0x01
+
+
+/* Auto-negotiation Link Partner Ability register. */
+#define PHY_LINK_PARTNER_ABILITY_REG                0x05
+
+#define PHY_LINK_PARTNER_ASYM_PAUSE                 BIT_11
+#define PHY_LINK_PARTNER_PAUSE_CAPABLE              BIT_10
+
+
+/* Auto-negotiation expansion register. */
+#define PHY_AN_EXPANSION_REG                        0x06
+
+
+
+/******************************************************************************/
+/* BCM5400 and BCM5401 phy info. */
+/******************************************************************************/
+
+#define PHY_DEVICE_ID           1
+
+/* OUI: bit 31-10;   Model#: bit 9-4;   Rev# bit 3-0. */
+#define PHY_UNKNOWN_PHY                             0x00000000
+#define PHY_BCM5400_PHY_ID                          0x60008040
+#define PHY_BCM5401_PHY_ID                          0x60008050
+#define PHY_BCM5411_PHY_ID                          0x60008070
+#define PHY_BCM5701_PHY_ID                          0x60008110
+#define PHY_BCM5703_PHY_ID                          0x60008160
+#define PHY_BCM5704_PHY_ID                          0x60008190
+#define PHY_BCM8002_PHY_ID                          0x60010140
+
+#define PHY_BCM5401_B0_REV                          0x1
+#define PHY_BCM5401_B2_REV                          0x3
+#define PHY_BCM5401_C0_REV                          0x6
+
+#define PHY_ID_OUI_MASK                             0xfffffc00
+#define PHY_ID_MODEL_MASK                           0x000003f0
+#define PHY_ID_REV_MASK                             0x0000000f
+#define PHY_ID_MASK                                 (PHY_ID_OUI_MASK |      \
+                                                    PHY_ID_MODEL_MASK)
+
+
+#define UNKNOWN_PHY_ID(x)   ((((x) & PHY_ID_MASK) != PHY_BCM5400_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5401_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5411_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5701_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5703_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5704_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM8002_PHY_ID))
+
+
+
+/* 1000Base-T control register. */
+#define BCM540X_1000BASET_CTRL_REG                  0x09
+
+#define BCM540X_AN_AD_1000BASET_HALF                BIT_8
+#define BCM540X_AN_AD_1000BASET_FULL                BIT_9
+#define BCM540X_CONFIG_AS_MASTER                    BIT_11
+#define BCM540X_ENABLE_CONFIG_AS_MASTER             BIT_12
+
+
+/* Extended control register. */
+#define BCM540X_EXT_CTRL_REG                        0x10
+
+#define BCM540X_EXT_CTRL_LINK3_LED_MODE             BIT_1
+#define BCM540X_EXT_CTRL_TBI                        BIT_15
+
+/* PHY extended status register. */
+#define BCM540X_EXT_STATUS_REG                      0x11
+
+#define BCM540X_EXT_STATUS_LINK_PASS                BIT_8
+
+
+/* DSP Coefficient Read/Write Port. */
+#define BCM540X_DSP_RW_PORT                         0x15
+
+
+/* DSP Coeficient Address Register. */
+#define BCM540X_DSP_ADDRESS_REG                     0x17
+
+#define BCM540X_DSP_TAP_NUMBER_MASK                 0x00
+#define BCM540X_DSP_AGC_A                           0x00
+#define BCM540X_DSP_AGC_B                           0x01
+#define BCM540X_DSP_MSE_PAIR_STATUS                 0x02
+#define BCM540X_DSP_SOFT_DECISION                   0x03
+#define BCM540X_DSP_PHASE_REG                       0x04
+#define BCM540X_DSP_SKEW                            0x05
+#define BCM540X_DSP_POWER_SAVER_UPPER_BOUND         0x06
+#define BCM540X_DSP_POWER_SAVER_LOWER_BOUND         0x07
+#define BCM540X_DSP_LAST_ECHO                       0x08
+#define BCM540X_DSP_FREQUENCY                       0x09
+#define BCM540X_DSP_PLL_BANDWIDTH                   0x0a
+#define BCM540X_DSP_PLL_PHASE_OFFSET                0x0b
+
+#define BCM540X_DSP_FILTER_DCOFFSET                 (BIT_10 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT3                    (BIT_8 | BIT_9 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT2                    (BIT_9 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT1                    (BIT_8 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT0                    BIT_11
+#define BCM540X_DSP_FILTER_NEXT3                    (BIT_8 | BIT_9 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT2                    (BIT_9 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT1                    (BIT_8 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT0                    BIT_10
+#define BCM540X_DSP_FILTER_ECHO                     (BIT_8 | BIT_9)
+#define BCM540X_DSP_FILTER_DFE                      BIT_9
+#define BCM540X_DSP_FILTER_FFE                      BIT_8
+
+#define BCM540X_DSP_CONTROL_ALL_FILTERS             BIT_12
+
+#define BCM540X_DSP_SEL_CH_0                        BIT_NONE
+#define BCM540X_DSP_SEL_CH_1                        BIT_13
+#define BCM540X_DSP_SEL_CH_2                        BIT_14
+#define BCM540X_DSP_SEL_CH_3                        (BIT_13 | BIT_14)
+
+#define BCM540X_CONTROL_ALL_CHANNELS                BIT_15
+
+
+/* Auxilliary Control Register (Shadow Register) */
+#define BCM5401_AUX_CTRL                            0x18
+
+#define BCM5401_SHADOW_SEL_MASK                     0x7
+#define BCM5401_SHADOW_SEL_NORMAL                   0x00
+#define BCM5401_SHADOW_SEL_10BASET                  0x01
+#define BCM5401_SHADOW_SEL_POWER_CONTROL            0x02
+#define BCM5401_SHADOW_SEL_IP_PHONE                 0x03
+#define BCM5401_SHADOW_SEL_MISC_TEST1               0x04
+#define BCM5401_SHADOW_SEL_MISC_TEST2               0x05
+#define BCM5401_SHADOW_SEL_IP_PHONE_SEED            0x06
+
+
+/* Shadow register selector == '000' */
+#define BCM5401_SHDW_NORMAL_DIAG_MODE               BIT_3
+#define BCM5401_SHDW_NORMAL_DISABLE_MBP             BIT_4
+#define BCM5401_SHDW_NORMAL_DISABLE_LOW_PWR         BIT_5
+#define BCM5401_SHDW_NORMAL_DISABLE_INV_PRF         BIT_6
+#define BCM5401_SHDW_NORMAL_DISABLE_PRF             BIT_7
+#define BCM5401_SHDW_NORMAL_RX_SLICING_NORMAL       BIT_NONE
+#define BCM5401_SHDW_NORMAL_RX_SLICING_4D           BIT_8
+#define BCM5401_SHDW_NORMAL_RX_SLICING_3LVL_1D      BIT_9
+#define BCM5401_SHDW_NORMAL_RX_SLICING_5LVL_1D      (BIT_8 | BIT_9)
+#define BCM5401_SHDW_NORMAL_TX_6DB_CODING           BIT_10
+#define BCM5401_SHDW_NORMAL_ENABLE_SM_DSP_CLOCK     BIT_11
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_4NS       BIT_NONE
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_5NS       BIT_12
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_3NS       BIT_13
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_0NS       (BIT_12 | BIT_13)
+#define BCM5401_SHDW_NORMAL_EXT_PACKET_LENGTH       BIT_14
+#define BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK       BIT_15
+
+
+/* Auxilliary status summary. */
+#define BCM540X_AUX_STATUS_REG                      0x19
+
+#define BCM540X_AUX_LINK_PASS                       BIT_2
+#define BCM540X_AUX_SPEED_MASK                      (BIT_8 | BIT_9 | BIT_10)
+#define BCM540X_AUX_10BASET_HD                      BIT_8
+#define BCM540X_AUX_10BASET_FD                      BIT_9
+#define BCM540X_AUX_100BASETX_HD                    (BIT_8 | BIT_9)
+#define BCM540X_AUX_100BASET4                       BIT_10
+#define BCM540X_AUX_100BASETX_FD                    (BIT_8 | BIT_10)
+#define BCM540X_AUX_100BASET_HD                     (BIT_9 | BIT_10)
+#define BCM540X_AUX_100BASET_FD                     (BIT_8 | BIT_9 | BIT_10)
+
+
+/* Interrupt status. */
+#define BCM540X_INT_STATUS_REG                      0x1a
+
+#define BCM540X_INT_LINK_CHANGE                     BIT_1
+#define BCM540X_INT_SPEED_CHANGE                    BIT_2
+#define BCM540X_INT_DUPLEX_CHANGE                   BIT_3
+#define BCM540X_INT_AUTO_NEG_PAGE_RX                BIT_10
+
+
+/* Interrupt mask register. */
+#define BCM540X_INT_MASK_REG                        0x1b
+
+
+
+/******************************************************************************/
+/* Register definitions. */
+/******************************************************************************/
+
+typedef volatile LM_UINT8 T3_8BIT_REGISTER, *PT3_8BIT_REGISTER;
+typedef volatile LM_UINT16 T3_16BIT_REGISTER, *PT3_16BIT_REGISTER;
+typedef volatile LM_UINT32 T3_32BIT_REGISTER, *PT3_32BIT_REGISTER;
+
+typedef struct {
+    /* Big endian format. */
+    T3_32BIT_REGISTER High;
+    T3_32BIT_REGISTER Low;
+} T3_64BIT_REGISTER, *PT3_64BIT_REGISTER;
+
+typedef T3_64BIT_REGISTER T3_64BIT_HOST_ADDR, *PT3_64BIT_HOST_ADDR;
+
+#define T3_NUM_OF_DMA_DESC    256
+#define T3_NUM_OF_MBUF        768
+
+typedef struct
+{
+  T3_64BIT_REGISTER host_addr;
+  T3_32BIT_REGISTER nic_mbuf;
+  T3_16BIT_REGISTER len;
+  T3_16BIT_REGISTER cqid_sqid;
+  T3_32BIT_REGISTER flags;
+  T3_32BIT_REGISTER opaque1;
+  T3_32BIT_REGISTER opaque2;
+  T3_32BIT_REGISTER opaque3;
+}T3_DMA_DESC, *PT3_DMA_DESC;
+
+
+
+/******************************************************************************/
+/* Ring control block. */
+/******************************************************************************/
+
+typedef struct {
+    T3_64BIT_REGISTER HostRingAddr;
+
+    union {
+        struct {
+#ifdef BIG_ENDIAN_HOST
+            T3_16BIT_REGISTER MaxLen;
+            T3_16BIT_REGISTER Flags;
+#else /* BIG_ENDIAN_HOST */
+            T3_16BIT_REGISTER Flags;
+            T3_16BIT_REGISTER MaxLen;
+#endif
+        } s;
+
+        T3_32BIT_REGISTER MaxLen_Flags;
+    } u;
+
+    T3_32BIT_REGISTER NicRingAddr;
+} T3_RCB, *PT3_RCB;
+
+#define T3_RCB_FLAG_USE_EXT_RECV_BD                     BIT_0
+#define T3_RCB_FLAG_RING_DISABLED                       BIT_1
+
+
+
+/******************************************************************************/
+/* Status block. */
+/******************************************************************************/
+
+/*
+ * Size of status block is actually 0x50 bytes.  Use 0x80 bytes for
+ * cache line alignment.
+ */
+#define T3_STATUS_BLOCK_SIZE                                    0x80
+
+typedef struct {
+    volatile LM_UINT32 Status;
+    #define STATUS_BLOCK_UPDATED                                BIT_0
+    #define STATUS_BLOCK_LINK_CHANGED_STATUS                    BIT_1
+    #define STATUS_BLOCK_ERROR                                  BIT_2
+
+    volatile LM_UINT32 StatusTag;
+
+#ifdef BIG_ENDIAN_HOST
+    volatile LM_UINT16 RcvStdConIdx;
+    volatile LM_UINT16 RcvJumboConIdx;
+
+    volatile LM_UINT16 Reserved2;
+    volatile LM_UINT16 RcvMiniConIdx;
+
+    struct {
+        volatile LM_UINT16 SendConIdx;   /* Send consumer index. */
+        volatile LM_UINT16 RcvProdIdx;   /* Receive producer index. */
+    } Idx[16];
+#else /* BIG_ENDIAN_HOST */
+    volatile LM_UINT16 RcvJumboConIdx;
+    volatile LM_UINT16 RcvStdConIdx;
+
+    volatile LM_UINT16 RcvMiniConIdx;
+    volatile LM_UINT16 Reserved2;
+
+    struct {
+        volatile LM_UINT16 RcvProdIdx;   /* Receive producer index. */
+        volatile LM_UINT16 SendConIdx;   /* Send consumer index. */
+    } Idx[16];
+#endif
+} T3_STATUS_BLOCK, *PT3_STATUS_BLOCK;
+
+
+
+/******************************************************************************/
+/* Receive buffer descriptors. */
+/******************************************************************************/
+
+typedef struct {
+    T3_64BIT_HOST_ADDR HostAddr;
+
+#ifdef BIG_ENDIAN_HOST
+    volatile LM_UINT16 Index;
+    volatile LM_UINT16 Len;
+
+    volatile LM_UINT16 Type;
+    volatile LM_UINT16 Flags;
+
+    volatile LM_UINT16 IpCksum;
+    volatile LM_UINT16 TcpUdpCksum;
+
+    volatile LM_UINT16 ErrorFlag;
+    volatile LM_UINT16 VlanTag;
+#else /* BIG_ENDIAN_HOST */
+    volatile LM_UINT16 Len;
+    volatile LM_UINT16 Index;
+
+    volatile LM_UINT16 Flags;
+    volatile LM_UINT16 Type;
+
+    volatile LM_UINT16 TcpUdpCksum;
+    volatile LM_UINT16 IpCksum;
+
+    volatile LM_UINT16 VlanTag;
+    volatile LM_UINT16 ErrorFlag;
+#endif
+
+    volatile LM_UINT32 Reserved;
+    volatile LM_UINT32 Opaque;
+} T3_RCV_BD, *PT3_RCV_BD;
+
+
+typedef struct {
+    T3_64BIT_HOST_ADDR HostAddr[3];
+
+#ifdef BIG_ENDIAN_HOST
+    LM_UINT16 Len1;
+    LM_UINT16 Len2;
+
+    LM_UINT16 Len3;
+    LM_UINT16 Reserved1;
+#else /* BIG_ENDIAN_HOST */
+    LM_UINT16 Len2;
+    LM_UINT16 Len1;
+
+    LM_UINT16 Reserved1;
+    LM_UINT16 Len3;
+#endif
+
+    T3_RCV_BD StdRcvBd;
+} T3_EXT_RCV_BD, *PT3_EXT_RCV_BD;
+
+
+/* Error flags. */
+#define RCV_BD_ERR_BAD_CRC                          0x0001
+#define RCV_BD_ERR_COLL_DETECT                      0x0002
+#define RCV_BD_ERR_LINK_LOST_DURING_PKT             0x0004
+#define RCV_BD_ERR_PHY_DECODE_ERR                   0x0008
+#define RCV_BD_ERR_ODD_NIBBLED_RCVD_MII             0x0010
+#define RCV_BD_ERR_MAC_ABORT                        0x0020
+#define RCV_BD_ERR_LEN_LT_64                        0x0040
+#define RCV_BD_ERR_TRUNC_NO_RESOURCES               0x0080
+#define RCV_BD_ERR_GIANT_FRAME_RCVD                 0x0100
+
+
+/* Buffer descriptor flags. */
+#define RCV_BD_FLAG_END                             0x0004
+#define RCV_BD_FLAG_JUMBO_RING                      0x0020
+#define RCV_BD_FLAG_VLAN_TAG                        0x0040
+#define RCV_BD_FLAG_FRAME_HAS_ERROR                 0x0400
+#define RCV_BD_FLAG_MINI_RING                       0x0800
+#define RCV_BD_FLAG_IP_CHKSUM_FIELD                 0x1000
+#define RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD            0x2000
+#define RCV_BD_FLAG_TCP_PACKET                      0x4000
+
+
+
+/******************************************************************************/
+/* Send buffer descriptor. */
+/******************************************************************************/
+
+typedef struct {
+    T3_64BIT_HOST_ADDR HostAddr;
+
+    union {
+        struct {
+#ifdef BIG_ENDIAN_HOST
+            LM_UINT16 Len;
+            LM_UINT16 Flags;
+#else /* BIG_ENDIAN_HOST */
+            LM_UINT16 Flags;
+            LM_UINT16 Len;
+#endif
+        } s1;
+
+        LM_UINT32 Len_Flags;
+    } u1;
+
+    union {
+        struct {
+#ifdef BIG_ENDIAN_HOST
+            LM_UINT16 Reserved;
+            LM_UINT16 VlanTag;
+#else /* BIG_ENDIAN_HOST */
+            LM_UINT16 VlanTag;
+            LM_UINT16 Reserved;
+#endif
+        } s2;
+
+        LM_UINT32 VlanTag;
+    } u2;
+} T3_SND_BD, *PT3_SND_BD;
+
+
+/* Send buffer descriptor flags. */
+#define SND_BD_FLAG_TCP_UDP_CKSUM                   0x0001
+#define SND_BD_FLAG_IP_CKSUM                        0x0002
+#define SND_BD_FLAG_END                             0x0004
+#define SND_BD_FLAG_IP_FRAG                         0x0008
+#define SND_BD_FLAG_IP_FRAG_END                     0x0010
+#define SND_BD_FLAG_VLAN_TAG                        0x0040
+#define SND_BD_FLAG_COAL_NOW                        0x0080
+#define SND_BD_FLAG_CPU_PRE_DMA                     0x0100
+#define SND_BD_FLAG_CPU_POST_DMA                    0x0200
+#define SND_BD_FLAG_INSERT_SRC_ADDR                 0x1000
+#define SND_BD_FLAG_CHOOSE_SRC_ADDR                 0x6000
+#define SND_BD_FLAG_DONT_GEN_CRC                    0x8000
+
+/* MBUFs */
+typedef struct T3_MBUF_FRAME_DESC {
+#ifdef BIG_ENDIAN_HOST
+  LM_UINT32 status_control;
+  union {
+    struct {
+      LM_UINT8 cqid;
+      LM_UINT8 reserved1;
+      LM_UINT16 length;
+    }s1;
+    LM_UINT32 word;
+  }u1;
+  union {
+    struct
+    {
+      LM_UINT16 ip_hdr_start;
+      LM_UINT16 tcp_udp_hdr_start;
+    }s2;
+
+    LM_UINT32 word;
+  }u2;
+
+  union {
+    struct {
+      LM_UINT16 data_start;
+      LM_UINT16 vlan_id;
+    }s3;
+
+    LM_UINT32 word;
+  }u3;
+
+  union {
+    struct {
+      LM_UINT16 ip_checksum;
+      LM_UINT16 tcp_udp_checksum;
+    }s4;
+
+    LM_UINT32 word;
+  }u4;
+
+  union {
+    struct {
+      LM_UINT16 pseudo_checksum;
+      LM_UINT16 checksum_status;
+    }s5;
+
+    LM_UINT32 word;
+  }u5;
+
+  union {
+    struct {
+      LM_UINT16 rule_match;
+      LM_UINT8 class;
+      LM_UINT8 rupt;
+    }s6;
+
+    LM_UINT32 word;
+  }u6;
+
+  union {
+    struct {
+      LM_UINT16 reserved2;
+      LM_UINT16 mbuf_num;
+    }s7;
+
+    LM_UINT32 word;
+  }u7;
+
+  LM_UINT32 reserved3;
+  LM_UINT32 reserved4;
+#else
+  LM_UINT32 status_control;
+  union {
+    struct {
+      LM_UINT16 length;
+      LM_UINT8  reserved1;
+      LM_UINT8  cqid;
+    }s1;
+    LM_UINT32 word;
+  }u1;
+  union {
+    struct
+    {
+      LM_UINT16 tcp_udp_hdr_start;
+      LM_UINT16 ip_hdr_start;
+    }s2;
+
+    LM_UINT32 word;
+  }u2;
+
+  union {
+    struct {
+      LM_UINT16 vlan_id;
+      LM_UINT16 data_start;
+    }s3;
+
+    LM_UINT32 word;
+  }u3;
+
+  union {
+    struct {
+      LM_UINT16 tcp_udp_checksum;
+      LM_UINT16 ip_checksum;
+    }s4;
+
+    LM_UINT32 word;
+  }u4;
+
+  union {
+    struct {
+      LM_UINT16 checksum_status;
+      LM_UINT16 pseudo_checksum;
+    }s5;
+
+    LM_UINT32 word;
+  }u5;
+
+  union {
+    struct {
+      LM_UINT8 rupt;
+      LM_UINT8 class;
+      LM_UINT16 rule_match;
+    }s6;
+
+    LM_UINT32 word;
+  }u6;
+
+  union {
+    struct {
+      LM_UINT16 mbuf_num;
+      LM_UINT16 reserved2;
+    }s7;
+
+    LM_UINT32 word;
+  }u7;
+
+  LM_UINT32 reserved3;
+  LM_UINT32 reserved4;
+#endif
+}T3_MBUF_FRAME_DESC,*PT3_MBUF_FRAME_DESC;
+
+typedef struct T3_MBUF_HDR {
+  union {
+    struct {
+      unsigned int C:1;
+      unsigned int F:1;
+      unsigned int reserved1:7;
+      unsigned int next_mbuf:16;
+      unsigned int length:7;
+    }s1;
+
+    LM_UINT32 word;
+  }u1;
+
+  LM_UINT32 next_frame_ptr;
+}T3_MBUF_HDR, *PT3_MBUF_HDR;
+
+typedef struct T3_MBUF
+{
+  T3_MBUF_HDR hdr;
+  union
+  {
+    struct {
+      T3_MBUF_FRAME_DESC frame_hdr;
+      LM_UINT32 data[20];
+    }s1;
+
+    struct {
+      LM_UINT32 data[30];
+    }s2;
+  }body;
+}T3_MBUF, *PT3_MBUF;
+
+#define T3_MBUF_BASE   (T3_NIC_MBUF_POOL_ADDR >> 7)
+#define T3_MBUF_END    ((T3_NIC_MBUF_POOL_ADDR + T3_NIC_MBUF_POOL_SIZE) >> 7)
+
+
+
+/******************************************************************************/
+/* Statistics block. */
+/******************************************************************************/
+
+typedef struct {
+    LM_UINT8 Reserved0[0x400-0x300];
+
+    /* Statistics maintained by Receive MAC. */
+    T3_64BIT_REGISTER ifHCInOctets;
+    T3_64BIT_REGISTER Reserved1;
+    T3_64BIT_REGISTER etherStatsFragments;
+    T3_64BIT_REGISTER ifHCInUcastPkts;
+    T3_64BIT_REGISTER ifHCInMulticastPkts;
+    T3_64BIT_REGISTER ifHCInBroadcastPkts;
+    T3_64BIT_REGISTER dot3StatsFCSErrors;
+    T3_64BIT_REGISTER dot3StatsAlignmentErrors;
+    T3_64BIT_REGISTER xonPauseFramesReceived;
+    T3_64BIT_REGISTER xoffPauseFramesReceived;
+    T3_64BIT_REGISTER macControlFramesReceived;
+    T3_64BIT_REGISTER xoffStateEntered;
+    T3_64BIT_REGISTER dot3StatsFramesTooLong;
+    T3_64BIT_REGISTER etherStatsJabbers;
+    T3_64BIT_REGISTER etherStatsUndersizePkts;
+    T3_64BIT_REGISTER inRangeLengthError;
+    T3_64BIT_REGISTER outRangeLengthError;
+    T3_64BIT_REGISTER etherStatsPkts64Octets;
+    T3_64BIT_REGISTER etherStatsPkts65Octetsto127Octets;
+    T3_64BIT_REGISTER etherStatsPkts128Octetsto255Octets;
+    T3_64BIT_REGISTER etherStatsPkts256Octetsto511Octets;
+    T3_64BIT_REGISTER etherStatsPkts512Octetsto1023Octets;
+    T3_64BIT_REGISTER etherStatsPkts1024Octetsto1522Octets;
+    T3_64BIT_REGISTER etherStatsPkts1523Octetsto2047Octets;
+    T3_64BIT_REGISTER etherStatsPkts2048Octetsto4095Octets;
+    T3_64BIT_REGISTER etherStatsPkts4096Octetsto8191Octets;
+    T3_64BIT_REGISTER etherStatsPkts8192Octetsto9022Octets;
+
+    T3_64BIT_REGISTER Unused1[37];
+
+    /* Statistics maintained by Transmit MAC. */
+    T3_64BIT_REGISTER ifHCOutOctets;
+    T3_64BIT_REGISTER Reserved2;
+    T3_64BIT_REGISTER etherStatsCollisions;
+    T3_64BIT_REGISTER outXonSent;
+    T3_64BIT_REGISTER outXoffSent;
+    T3_64BIT_REGISTER flowControlDone;
+    T3_64BIT_REGISTER dot3StatsInternalMacTransmitErrors;
+    T3_64BIT_REGISTER dot3StatsSingleCollisionFrames;
+    T3_64BIT_REGISTER dot3StatsMultipleCollisionFrames;
+    T3_64BIT_REGISTER dot3StatsDeferredTransmissions;
+    T3_64BIT_REGISTER Reserved3;
+    T3_64BIT_REGISTER dot3StatsExcessiveCollisions;
+    T3_64BIT_REGISTER dot3StatsLateCollisions;
+    T3_64BIT_REGISTER dot3Collided2Times;
+    T3_64BIT_REGISTER dot3Collided3Times;
+    T3_64BIT_REGISTER dot3Collided4Times;
+    T3_64BIT_REGISTER dot3Collided5Times;
+    T3_64BIT_REGISTER dot3Collided6Times;
+    T3_64BIT_REGISTER dot3Collided7Times;
+    T3_64BIT_REGISTER dot3Collided8Times;
+    T3_64BIT_REGISTER dot3Collided9Times;
+    T3_64BIT_REGISTER dot3Collided10Times;
+    T3_64BIT_REGISTER dot3Collided11Times;
+    T3_64BIT_REGISTER dot3Collided12Times;
+    T3_64BIT_REGISTER dot3Collided13Times;
+    T3_64BIT_REGISTER dot3Collided14Times;
+    T3_64BIT_REGISTER dot3Collided15Times;
+    T3_64BIT_REGISTER ifHCOutUcastPkts;
+    T3_64BIT_REGISTER ifHCOutMulticastPkts;
+    T3_64BIT_REGISTER ifHCOutBroadcastPkts;
+    T3_64BIT_REGISTER dot3StatsCarrierSenseErrors;
+    T3_64BIT_REGISTER ifOutDiscards;
+    T3_64BIT_REGISTER ifOutErrors;
+
+    T3_64BIT_REGISTER Unused2[31];
+
+    /* Statistics maintained by Receive List Placement. */
+    T3_64BIT_REGISTER COSIfHCInPkts[16];
+    T3_64BIT_REGISTER COSFramesDroppedDueToFilters;
+    T3_64BIT_REGISTER nicDmaWriteQueueFull;
+    T3_64BIT_REGISTER nicDmaWriteHighPriQueueFull;
+    T3_64BIT_REGISTER nicNoMoreRxBDs;
+    T3_64BIT_REGISTER ifInDiscards;
+    T3_64BIT_REGISTER ifInErrors;
+    T3_64BIT_REGISTER nicRecvThresholdHit;
+
+    T3_64BIT_REGISTER Unused3[9];
+
+    /* Statistics maintained by Send Data Initiator. */
+    T3_64BIT_REGISTER COSIfHCOutPkts[16];
+    T3_64BIT_REGISTER nicDmaReadQueueFull;
+    T3_64BIT_REGISTER nicDmaReadHighPriQueueFull;
+    T3_64BIT_REGISTER nicSendDataCompQueueFull;
+
+    /* Statistics maintained by Host Coalescing. */
+    T3_64BIT_REGISTER nicRingSetSendProdIndex;
+    T3_64BIT_REGISTER nicRingStatusUpdate;
+    T3_64BIT_REGISTER nicInterrupts;
+    T3_64BIT_REGISTER nicAvoidedInterrupts;
+    T3_64BIT_REGISTER nicSendThresholdHit;
+
+    LM_UINT8 Reserved4[0xb00-0x9c0];
+} T3_STATS_BLOCK, *PT3_STATS_BLOCK;
+
+
+
+/******************************************************************************/
+/* PCI configuration registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_16BIT_REGISTER VendorId;
+    T3_16BIT_REGISTER DeviceId;
+
+    T3_16BIT_REGISTER Command;
+    T3_16BIT_REGISTER Status;
+
+    T3_32BIT_REGISTER ClassCodeRevId;
+
+    T3_8BIT_REGISTER CacheLineSize;
+    T3_8BIT_REGISTER LatencyTimer;
+    T3_8BIT_REGISTER HeaderType;
+    T3_8BIT_REGISTER Bist;
+
+    T3_32BIT_REGISTER MemBaseAddrLow;
+    T3_32BIT_REGISTER MemBaseAddrHigh;
+
+    LM_UINT8 Unused1[20];
+
+    T3_16BIT_REGISTER SubsystemVendorId;
+    T3_16BIT_REGISTER SubsystemId;
+
+    T3_32BIT_REGISTER RomBaseAddr;
+
+    T3_8BIT_REGISTER PciXCapiblityPtr;
+    LM_UINT8 Unused2[7];
+
+    T3_8BIT_REGISTER IntLine;
+    T3_8BIT_REGISTER IntPin;
+    T3_8BIT_REGISTER MinGnt;
+    T3_8BIT_REGISTER MaxLat;
+
+    T3_8BIT_REGISTER PciXCapabilities;
+    T3_8BIT_REGISTER PmCapabilityPtr;
+    T3_16BIT_REGISTER PciXCommand;
+
+    T3_32BIT_REGISTER PciXStatus;
+
+    T3_8BIT_REGISTER PmCapabilityId;
+    T3_8BIT_REGISTER VpdCapabilityPtr;
+    T3_16BIT_REGISTER PmCapabilities;
+
+    T3_16BIT_REGISTER PmCtrlStatus;
+    #define PM_CTRL_PME_STATUS            BIT_15
+    #define PM_CTRL_PME_ENABLE            BIT_8
+    #define PM_CTRL_PME_POWER_STATE_D0    0
+    #define PM_CTRL_PME_POWER_STATE_D1    1
+    #define PM_CTRL_PME_POWER_STATE_D2    2
+    #define PM_CTRL_PME_POWER_STATE_D3H   3
+
+    T3_8BIT_REGISTER BridgeSupportExt;
+    T3_8BIT_REGISTER PmData;
+
+    T3_8BIT_REGISTER VpdCapabilityId;
+    T3_8BIT_REGISTER MsiCapabilityPtr;
+    T3_16BIT_REGISTER VpdAddrFlag;
+    #define VPD_FLAG_WRITE      (1 << 15)
+    #define VPD_FLAG_RW_MASK    (1 << 15)
+    #define VPD_FLAG_READ       0
+
+
+    T3_32BIT_REGISTER VpdData;
+
+    T3_8BIT_REGISTER MsiCapabilityId;
+    T3_8BIT_REGISTER NextCapabilityPtr;
+    T3_16BIT_REGISTER MsiCtrl;
+    #define MSI_CTRL_64BIT_CAP     (1 << 7)
+    #define MSI_CTRL_MSG_ENABLE(x) (x << 4)
+    #define MSI_CTRL_MSG_CAP(x)    (x << 1)
+    #define MSI_CTRL_ENABLE        (1 << 0)
+
+
+    T3_32BIT_REGISTER MsiAddrLow;
+    T3_32BIT_REGISTER MsiAddrHigh;
+
+    T3_16BIT_REGISTER MsiData;
+    T3_16BIT_REGISTER Unused3;
+
+    T3_32BIT_REGISTER MiscHostCtrl;
+    #define MISC_HOST_CTRL_CLEAR_INT                        BIT_0
+    #define MISC_HOST_CTRL_MASK_PCI_INT                     BIT_1
+    #define MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP          BIT_2
+    #define MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP          BIT_3
+    #define MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW          BIT_4
+    #define MISC_HOST_CTRL_ENABLE_CLK_REG_RW                BIT_5
+    #define MISC_HOST_CTRL_ENABLE_REG_WORD_SWAP             BIT_6
+    #define MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS           BIT_7
+    #define MISC_HOST_CTRL_ENABLE_INT_MASK_MODE             BIT_8
+    #define MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE        BIT_9
+
+    T3_32BIT_REGISTER DmaReadWriteCtrl;
+    #define DMA_CTRL_WRITE_BOUNDARY_MASK            (BIT_11 | BIT_12 | BIT_13)
+    #define DMA_CTRL_WRITE_BOUNDARY_DISABLE         0
+    #define DMA_CTRL_WRITE_BOUNDARY_16              BIT_11
+    #define DMA_CTRL_WRITE_BOUNDARY_32              BIT_12
+    #define DMA_CTRL_WRITE_BOUNDARY_64              (BIT_12 | BIT_11)
+    #define DMA_CTRL_WRITE_BOUNDARY_128             BIT_13
+    #define DMA_CTRL_WRITE_BOUNDARY_256             (BIT_13 | BIT_11)
+    #define DMA_CTRL_WRITE_BOUNDARY_512             (BIT_13 | BIT_12)
+    #define DMA_CTRL_WRITE_BOUNDARY_1024            (BIT_13 | BIT_12 | BIT_11)
+    #define DMA_CTRL_WRITE_ONE_DMA_AT_ONCE          BIT_14
+
+
+    T3_32BIT_REGISTER PciState;
+    #define T3_PCI_STATE_FORCE_PCI_RESET                    BIT_0
+    #define T3_PCI_STATE_INTERRUPT_NOT_ACTIVE               BIT_1
+    #define T3_PCI_STATE_NOT_PCI_X_BUS                      BIT_2
+    #define T3_PCI_STATE_HIGH_BUS_SPEED                     BIT_3
+    #define T3_PCI_STATE_32BIT_PCI_BUS                      BIT_4
+    #define T3_PCI_STATE_PCI_ROM_ENABLE                     BIT_5
+    #define T3_PCI_STATE_PCI_ROM_RETRY_ENABLE               BIT_6
+    #define T3_PCI_STATE_FLAT_VIEW                          BIT_8
+    #define T3_PCI_STATE_RETRY_SAME_DMA                     BIT_13
+
+    T3_32BIT_REGISTER ClockCtrl;
+    #define T3_PCI_CLKCTRL_TXCPU_CLK_DISABLE                BIT_11
+    #define T3_PCI_CLKCTRL_RXCPU_CLK_DISABLE                BIT_10
+    #define T3_PCI_CLKCTRL_CORE_CLK_DISABLE                 BIT_9
+
+    T3_32BIT_REGISTER RegBaseAddr;
+
+    T3_32BIT_REGISTER MemWindowBaseAddr;
+
+#ifdef NIC_CPU_VIEW
+  /* These registers are ONLY visible to NIC CPU */
+    T3_32BIT_REGISTER PowerConsumed;
+    T3_32BIT_REGISTER PowerDissipated;
+#else /* NIC_CPU_VIEW */
+    T3_32BIT_REGISTER RegData;
+    T3_32BIT_REGISTER MemWindowData;
+#endif /* !NIC_CPU_VIEW */
+
+    T3_32BIT_REGISTER ModeCtrl;
+
+    T3_32BIT_REGISTER MiscCfg;
+
+    T3_32BIT_REGISTER MiscLocalCtrl;
+
+    T3_32BIT_REGISTER Unused4;
+
+    /* NOTE: Big/Little-endian clarification needed.  Are these register */
+    /* in big or little endian formate. */
+    T3_64BIT_REGISTER StdRingProdIdx;
+    T3_64BIT_REGISTER RcvRetRingConIdx;
+    T3_64BIT_REGISTER SndProdIdx;
+
+    LM_UINT8 Unused5[80];
+} T3_PCI_CONFIGURATION, *PT3_PCI_CONFIGURATION;
+
+#define PCIX_CMD_MAX_SPLIT_MASK                         0x0070
+#define PCIX_CMD_MAX_SPLIT_SHL                          4
+#define PCIX_CMD_MAX_BURST_MASK                         0x000c
+#define PCIX_CMD_MAX_BURST_SHL                          2
+#define PCIX_CMD_MAX_BURST_CPIOB                        2
+
+/******************************************************************************/
+/* Mac control registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* MAC mode control. */
+    T3_32BIT_REGISTER Mode;
+    #define MAC_MODE_GLOBAL_RESET                       BIT_0
+    #define MAC_MODE_HALF_DUPLEX                        BIT_1
+    #define MAC_MODE_PORT_MODE_MASK                     (BIT_2 | BIT_3)
+    #define MAC_MODE_PORT_MODE_TBI                      (BIT_2 | BIT_3)
+    #define MAC_MODE_PORT_MODE_GMII                     BIT_3
+    #define MAC_MODE_PORT_MODE_MII                      BIT_2
+    #define MAC_MODE_PORT_MODE_NONE                     BIT_NONE
+    #define MAC_MODE_PORT_INTERNAL_LOOPBACK             BIT_4
+    #define MAC_MODE_TAGGED_MAC_CONTROL                 BIT_7
+    #define MAC_MODE_TX_BURSTING                        BIT_8
+    #define MAC_MODE_MAX_DEFER                          BIT_9
+    #define MAC_MODE_LINK_POLARITY                      BIT_10
+    #define MAC_MODE_ENABLE_RX_STATISTICS               BIT_11
+    #define MAC_MODE_CLEAR_RX_STATISTICS                BIT_12
+    #define MAC_MODE_FLUSH_RX_STATISTICS                BIT_13
+    #define MAC_MODE_ENABLE_TX_STATISTICS               BIT_14
+    #define MAC_MODE_CLEAR_TX_STATISTICS                BIT_15
+    #define MAC_MODE_FLUSH_TX_STATISTICS                BIT_16
+    #define MAC_MODE_SEND_CONFIGS                       BIT_17
+    #define MAC_MODE_DETECT_MAGIC_PACKET_ENABLE         BIT_18
+    #define MAC_MODE_ACPI_POWER_ON_ENABLE               BIT_19
+    #define MAC_MODE_ENABLE_MIP                         BIT_20
+    #define MAC_MODE_ENABLE_TDE                         BIT_21
+    #define MAC_MODE_ENABLE_RDE                         BIT_22
+    #define MAC_MODE_ENABLE_FHDE                        BIT_23
+
+    /* MAC status */
+    T3_32BIT_REGISTER Status;
+    #define MAC_STATUS_PCS_SYNCED                       BIT_0
+    #define MAC_STATUS_SIGNAL_DETECTED                  BIT_1
+    #define MAC_STATUS_RECEIVING_CFG                    BIT_2
+    #define MAC_STATUS_CFG_CHANGED                      BIT_3
+    #define MAC_STATUS_SYNC_CHANGED                     BIT_4
+    #define MAC_STATUS_PORT_DECODE_ERROR                BIT_10
+    #define MAC_STATUS_LINK_STATE_CHANGED               BIT_12
+    #define MAC_STATUS_MI_COMPLETION                    BIT_22
+    #define MAC_STATUS_MI_INTERRUPT                     BIT_23
+    #define MAC_STATUS_AP_ERROR                         BIT_24
+    #define MAC_STATUS_ODI_ERROR                        BIT_25
+    #define MAC_STATUS_RX_STATS_OVERRUN                 BIT_26
+    #define MAC_STATUS_TX_STATS_OVERRUN                 BIT_27
+
+    /* Event Enable */
+    T3_32BIT_REGISTER MacEvent;
+    #define MAC_EVENT_ENABLE_PORT_DECODE_ERR            BIT_10
+    #define MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN    BIT_12
+    #define MAC_EVENT_ENABLE_MI_COMPLETION              BIT_22
+    #define MAC_EVENT_ENABLE_MI_INTERRUPT               BIT_23
+    #define MAC_EVENT_ENABLE_AP_ERROR                   BIT_24
+    #define MAC_EVENT_ENABLE_ODI_ERROR                  BIT_25
+    #define MAC_EVENT_ENABLE_RX_STATS_OVERRUN           BIT_26
+    #define MAC_EVENT_ENABLE_TX_STATS_OVERRUN           BIT_27
+
+    /* Led control. */
+    T3_32BIT_REGISTER LedCtrl;
+    #define LED_CTRL_OVERRIDE_LINK_LED                  BIT_0
+    #define LED_CTRL_1000MBPS_LED_ON                    BIT_1
+    #define LED_CTRL_100MBPS_LED_ON                     BIT_2
+    #define LED_CTRL_10MBPS_LED_ON                      BIT_3
+    #define LED_CTRL_OVERRIDE_TRAFFIC_LED               BIT_4
+    #define LED_CTRL_BLINK_TRAFFIC_LED                  BIT_5
+    #define LED_CTRL_TRAFFIC_LED                        BIT_6
+    #define LED_CTRL_1000MBPS_LED_STATUS                BIT_7
+    #define LED_CTRL_100MBPS_LED_STATUS                 BIT_8
+    #define LED_CTRL_10MBPS_LED_STATUS                  BIT_9
+    #define LED_CTRL_TRAFFIC_LED_STATUS                 BIT_10
+    #define LED_CTRL_MAC_MODE                           BIT_NONE
+    #define LED_CTRL_PHY_MODE_1                         BIT_11
+    #define LED_CTRL_PHY_MODE_2                         BIT_12
+    #define LED_CTRL_BLINK_RATE_MASK                    0x7ff80000
+    #define LED_CTRL_OVERRIDE_BLINK_PERIOD              BIT_19
+    #define LED_CTRL_OVERRIDE_BLINK_RATE                BIT_31
+
+    /* MAC addresses. */
+    struct {
+        T3_32BIT_REGISTER High;             /* Upper 2 bytes. */
+        T3_32BIT_REGISTER Low;              /* Lower 4 bytes. */
+    } MacAddr[4];
+
+    /* ACPI Mbuf pointer. */
+    T3_32BIT_REGISTER AcpiMbufPtr;
+
+    /* ACPI Length and Offset. */
+    T3_32BIT_REGISTER AcpiLengthOffset;
+    #define ACPI_LENGTH_MASK                            0xffff
+    #define ACPI_OFFSET_MASK                            0x0fff0000
+    #define ACPI_LENGTH(x)                              x
+    #define ACPI_OFFSET(x)                              ((x) << 16)
+
+    /* Transmit random backoff. */
+    T3_32BIT_REGISTER TxBackoffSeed;
+    #define MAC_TX_BACKOFF_SEED_MASK                    0x3ff
+
+    /* Receive MTU */
+    T3_32BIT_REGISTER MtuSize;
+    #define MAC_RX_MTU_MASK                             0xffff
+
+    /* Gigabit PCS Test. */
+    T3_32BIT_REGISTER PcsTest;
+    #define MAC_PCS_TEST_DATA_PATTERN_MASK              0x0fffff
+    #define MAC_PCS_TEST_ENABLE                         BIT_20
+
+    /* Transmit Gigabit Auto-Negotiation. */
+    T3_32BIT_REGISTER TxAutoNeg;
+    #define MAC_AN_TX_AN_DATA_MASK                      0xffff
+
+    /* Receive Gigabit Auto-Negotiation. */
+    T3_32BIT_REGISTER RxAutoNeg;
+    #define MAC_AN_RX_AN_DATA_MASK                      0xffff
+
+    /* MI Communication. */
+    T3_32BIT_REGISTER MiCom;
+    #define MI_COM_CMD_MASK                             (BIT_26 | BIT_27)
+    #define MI_COM_CMD_WRITE                            BIT_26
+    #define MI_COM_CMD_READ                             BIT_27
+    #define MI_COM_READ_FAILED                          BIT_28
+    #define MI_COM_START                                BIT_29
+    #define MI_COM_BUSY                                 BIT_29
+
+    #define MI_COM_PHY_ADDR_MASK                        0x1f
+    #define MI_COM_FIRST_PHY_ADDR_BIT                   21
+
+    #define MI_COM_PHY_REG_ADDR_MASK                    0x1f
+    #define MI_COM_FIRST_PHY_REG_ADDR_BIT               16
+
+    #define MI_COM_PHY_DATA_MASK                        0xffff
+
+    /* MI Status. */
+    T3_32BIT_REGISTER MiStatus;
+    #define MI_STATUS_ENABLE_LINK_STATUS_ATTN           BIT_0
+
+    /* MI Mode. */
+    T3_32BIT_REGISTER MiMode;
+    #define MI_MODE_CLOCK_SPEED_10MHZ                   BIT_0
+    #define MI_MODE_USE_SHORT_PREAMBLE                  BIT_1
+    #define MI_MODE_AUTO_POLLING_ENABLE                 BIT_4
+    #define MI_MODE_CORE_CLOCK_SPEED_62MHZ              BIT_15
+
+    /* Auto-polling status. */
+    T3_32BIT_REGISTER AutoPollStatus;
+    #define AUTO_POLL_ERROR                             BIT_0
+
+    /* Transmit MAC mode. */
+    T3_32BIT_REGISTER TxMode;
+    #define TX_MODE_RESET                               BIT_0
+    #define TX_MODE_ENABLE                              BIT_1
+    #define TX_MODE_ENABLE_FLOW_CONTROL                 BIT_4
+    #define TX_MODE_ENABLE_BIG_BACKOFF                  BIT_5
+    #define TX_MODE_ENABLE_LONG_PAUSE                   BIT_6
+
+    /* Transmit MAC status. */
+    T3_32BIT_REGISTER TxStatus;
+    #define TX_STATUS_RX_CURRENTLY_XOFFED               BIT_0
+    #define TX_STATUS_SENT_XOFF                         BIT_1
+    #define TX_STATUS_SENT_XON                          BIT_2
+    #define TX_STATUS_LINK_UP                           BIT_3
+    #define TX_STATUS_ODI_UNDERRUN                      BIT_4
+    #define TX_STATUS_ODI_OVERRUN                       BIT_5
+
+    /* Transmit MAC length. */
+    T3_32BIT_REGISTER TxLengths;
+    #define TX_LEN_SLOT_TIME_MASK                       0xff
+    #define TX_LEN_IPG_MASK                             0x0f00
+    #define TX_LEN_IPG_CRS_MASK                         (BIT_12 | BIT_13)
+
+    /* Receive MAC mode. */
+    T3_32BIT_REGISTER RxMode;
+    #define RX_MODE_RESET                               BIT_0
+    #define RX_MODE_ENABLE                              BIT_1
+    #define RX_MODE_ENABLE_FLOW_CONTROL                 BIT_2
+    #define RX_MODE_KEEP_MAC_CONTROL                    BIT_3
+    #define RX_MODE_KEEP_PAUSE                          BIT_4
+    #define RX_MODE_ACCEPT_OVERSIZED                    BIT_5
+    #define RX_MODE_ACCEPT_RUNTS                        BIT_6
+    #define RX_MODE_LENGTH_CHECK                        BIT_7
+    #define RX_MODE_PROMISCUOUS_MODE                    BIT_8
+    #define RX_MODE_NO_CRC_CHECK                        BIT_9
+    #define RX_MODE_KEEP_VLAN_TAG                       BIT_10
+
+    /* Receive MAC status. */
+    T3_32BIT_REGISTER RxStatus;
+    #define RX_STATUS_REMOTE_TRANSMITTER_XOFFED         BIT_0
+    #define RX_STATUS_XOFF_RECEIVED                     BIT_1
+    #define RX_STATUS_XON_RECEIVED                      BIT_2
+
+    /* Hash registers. */
+    T3_32BIT_REGISTER HashReg[4];
+
+    /* Receive placement rules registers. */
+    struct {
+        T3_32BIT_REGISTER Rule;
+        T3_32BIT_REGISTER Value;
+    } RcvRules[16];
+
+    #define RCV_DISABLE_RULE_MASK                       0x7fffffff
+
+    #define RCV_RULE1_REJECT_BROADCAST_IDX              0x00
+    #define REJECT_BROADCAST_RULE1_RULE                 0xc2000000
+    #define REJECT_BROADCAST_RULE1_VALUE                0xffffffff
+
+    #define RCV_RULE2_REJECT_BROADCAST_IDX              0x01
+    #define REJECT_BROADCAST_RULE2_RULE                 0x86000004
+    #define REJECT_BROADCAST_RULE2_VALUE                0xffffffff
+
+#if INCLUDE_5701_AX_FIX
+    #define RCV_LAST_RULE_IDX                           0x04
+#else
+    #define RCV_LAST_RULE_IDX                           0x02
+#endif
+
+    T3_32BIT_REGISTER RcvRuleCfg;
+    #define RX_RULE_DEFAULT_CLASS                       (1 << 3)
+
+    LM_UINT8 Reserved1[140];
+
+    T3_32BIT_REGISTER SerdesCfg;
+    T3_32BIT_REGISTER SerdesStatus;
+
+    LM_UINT8 Reserved2[104];
+
+    volatile LM_UINT8 TxMacState[16];
+    volatile LM_UINT8 RxMacState[20];
+
+    LM_UINT8 Reserved3[476];
+
+    T3_32BIT_REGISTER RxStats[26];
+
+    LM_UINT8 Reserved4[24];
+
+    T3_32BIT_REGISTER TxStats[28];
+
+    LM_UINT8 Reserved5[784];
+} T3_MAC_CONTROL, *PT3_MAC_CONTROL;
+
+
+
+/******************************************************************************/
+/* Send data initiator control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define T3_SND_DATA_IN_MODE_RESET                       BIT_0
+    #define T3_SND_DATA_IN_MODE_ENABLE                      BIT_1
+    #define T3_SND_DATA_IN_MODE_STATS_OFLW_ATTN_ENABLE      BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define T3_SND_DATA_IN_STATUS_STATS_OFLW_ATTN           BIT_2
+
+    T3_32BIT_REGISTER StatsCtrl;
+    #define T3_SND_DATA_IN_STATS_CTRL_ENABLE                BIT_0
+    #define T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE         BIT_1
+    #define T3_SND_DATA_IN_STATS_CTRL_CLEAR                 BIT_2
+    #define T3_SND_DATA_IN_STATS_CTRL_FLUSH                 BIT_3
+    #define T3_SND_DATA_IN_STATS_CTRL_FORCE_ZERO            BIT_4
+
+    T3_32BIT_REGISTER StatsEnableMask;
+    T3_32BIT_REGISTER StatsIncMask;
+
+    LM_UINT8 Reserved[108];
+
+    T3_32BIT_REGISTER ClassOfServCnt[16];
+    T3_32BIT_REGISTER DmaReadQFullCnt;
+    T3_32BIT_REGISTER DmaPriorityReadQFullCnt;
+    T3_32BIT_REGISTER SdcQFullCnt;
+
+    T3_32BIT_REGISTER NicRingSetSendProdIdxCnt;
+    T3_32BIT_REGISTER StatusUpdatedCnt;
+    T3_32BIT_REGISTER InterruptsCnt;
+    T3_32BIT_REGISTER AvoidInterruptsCnt;
+    T3_32BIT_REGISTER SendThresholdHitCnt;
+
+    /* Unused space. */
+    LM_UINT8 Unused[800];
+} T3_SEND_DATA_INITIATOR, *PT3_SEND_DATA_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Send data completion control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_DATA_COMP_MODE_RESET                        BIT_0
+    #define SND_DATA_COMP_MODE_ENABLE                       BIT_1
+
+    /* Unused space. */
+    LM_UINT8 Unused[1020];
+} T3_SEND_DATA_COMPLETION, *PT3_SEND_DATA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Send BD Ring Selector Control Registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_BD_SEL_MODE_RESET                           BIT_0
+    #define SND_BD_SEL_MODE_ENABLE                          BIT_1
+    #define SND_BD_SEL_MODE_ATTN_ENABLE                     BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define SND_BD_SEL_STATUS_ERROR_ATTN                    BIT_2
+
+    T3_32BIT_REGISTER HwDiag;
+
+    /* Unused space. */
+    LM_UINT8 Unused1[52];
+
+    /* Send BD Ring Selector Local NIC Send BD Consumer Index. */
+    T3_32BIT_REGISTER NicSendBdSelConIdx[16];
+
+    /* Unused space. */
+    LM_UINT8 Unused2[896];
+} T3_SEND_BD_SELECTOR, *PT3_SEND_BD_SELECTOR;
+
+
+
+/******************************************************************************/
+/* Send BD initiator control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_BD_IN_MODE_RESET                            BIT_0
+    #define SND_BD_IN_MODE_ENABLE                           BIT_1
+    #define SND_BD_IN_MODE_ATTN_ENABLE                      BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define SND_BD_IN_STATUS_ERROR_ATTN                     BIT_2
+
+    /* Send BD initiator local NIC send BD producer index. */
+    T3_32BIT_REGISTER NicSendBdInProdIdx[16];
+
+    /* Unused space. */
+    LM_UINT8 Unused2[952];
+} T3_SEND_BD_INITIATOR, *PT3_SEND_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Send BD Completion Control. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_BD_COMP_MODE_RESET                          BIT_0
+    #define SND_BD_COMP_MODE_ENABLE                         BIT_1
+    #define SND_BD_COMP_MODE_ATTN_ENABLE                    BIT_2
+
+    /* Unused space. */
+    LM_UINT8 Unused2[1020];
+} T3_SEND_BD_COMPLETION, *PT3_SEND_BD_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive list placement control registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode. */
+    T3_32BIT_REGISTER Mode;
+    #define RCV_LIST_PLMT_MODE_RESET                        BIT_0
+    #define RCV_LIST_PLMT_MODE_ENABLE                       BIT_1
+    #define RCV_LIST_PLMT_MODE_CLASS0_ATTN_ENABLE           BIT_2
+    #define RCV_LIST_PLMT_MODE_MAPPING_OOR_ATTN_ENABLE      BIT_3
+    #define RCV_LIST_PLMT_MODE_STATS_OFLOW_ATTN_ENABLE      BIT_4
+
+    /* Status. */
+    T3_32BIT_REGISTER Status;
+    #define RCV_LIST_PLMT_STATUS_CLASS0_ATTN                BIT_2
+    #define RCV_LIST_PLMT_STATUS_MAPPING_ATTN               BIT_3
+    #define RCV_LIST_PLMT_STATUS_STATS_OFLOW_ATTN           BIT_4
+
+    /* Receive selector list lock register. */
+    T3_32BIT_REGISTER Lock;
+    #define RCV_LIST_SEL_LOCK_REQUEST_MASK                  0xffff
+    #define RCV_LIST_SEL_LOCK_GRANT_MASK                    0xffff0000
+
+    /* Selector non-empty bits. */
+    T3_32BIT_REGISTER NonEmptyBits;
+    #define RCV_LIST_SEL_NON_EMPTY_MASK                     0xffff
+
+    /* Receive list placement configuration register. */
+    T3_32BIT_REGISTER Config;
+
+    /* Receive List Placement statistics Control. */
+    T3_32BIT_REGISTER StatsCtrl;
+#define RCV_LIST_STATS_ENABLE                               BIT_0
+#define RCV_LIST_STATS_FAST_UPDATE                          BIT_1
+
+    /* Receive List Placement statistics Enable Mask. */
+    T3_32BIT_REGISTER StatsEnableMask;
+
+    /* Receive List Placement statistics Increment Mask. */
+    T3_32BIT_REGISTER StatsIncMask;
+
+    /* Unused space. */
+    LM_UINT8 Unused1[224];
+
+    struct {
+        T3_32BIT_REGISTER Head;
+        T3_32BIT_REGISTER Tail;
+        T3_32BIT_REGISTER Count;
+
+        /* Unused space. */
+        LM_UINT8 Unused[4];
+    } RcvSelectorList[16];
+
+    /* Local statistics counter. */
+    T3_32BIT_REGISTER ClassOfServCnt[16];
+
+    T3_32BIT_REGISTER DropDueToFilterCnt;
+    T3_32BIT_REGISTER DmaWriteQFullCnt;
+    T3_32BIT_REGISTER DmaHighPriorityWriteQFullCnt;
+    T3_32BIT_REGISTER NoMoreReceiveBdCnt;
+    T3_32BIT_REGISTER IfInDiscardsCnt;
+    T3_32BIT_REGISTER IfInErrorsCnt;
+    T3_32BIT_REGISTER RcvThresholdHitCnt;
+
+    /* Another unused space. */
+    LM_UINT8 Unused2[420];
+} T3_RCV_LIST_PLACEMENT, *PT3_RCV_LIST_PLACEMENT;
+
+
+
+/******************************************************************************/
+/* Receive Data and Receive BD Initiator Control. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode. */
+    T3_32BIT_REGISTER Mode;
+    #define RCV_DATA_BD_IN_MODE_RESET                   BIT_0
+    #define RCV_DATA_BD_IN_MODE_ENABLE                  BIT_1
+    #define RCV_DATA_BD_IN_MODE_JUMBO_BD_NEEDED         BIT_2
+    #define RCV_DATA_BD_IN_MODE_FRAME_TOO_BIG           BIT_3
+    #define RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE       BIT_4
+
+    /* Status. */
+    T3_32BIT_REGISTER Status;
+    #define RCV_DATA_BD_IN_STATUS_JUMBO_BD_NEEDED       BIT_2
+    #define RCV_DATA_BD_IN_STATUS_FRAME_TOO_BIG         BIT_3
+    #define RCV_DATA_BD_IN_STATUS_INVALID_RING_SIZE     BIT_4
+
+    /* Split frame minium size. */
+    T3_32BIT_REGISTER SplitFrameMinSize;
+
+    /* Unused space. */
+    LM_UINT8 Unused1[0x2440-0x240c];
+
+    /* Receive RCBs. */
+    T3_RCB JumboRcvRcb;
+    T3_RCB StdRcvRcb;
+    T3_RCB MiniRcvRcb;
+
+    /* Receive Data and Receive BD Ring Initiator Local NIC Receive */
+    /* BD Consumber Index. */
+    T3_32BIT_REGISTER NicJumboConIdx;
+    T3_32BIT_REGISTER NicStdConIdx;
+    T3_32BIT_REGISTER NicMiniConIdx;
+
+    /* Unused space. */
+    LM_UINT8 Unused2[4];
+
+    /* Receive Data and Receive BD Initiator Local Receive Return ProdIdx. */
+    T3_32BIT_REGISTER RcvDataBdProdIdx[16];
+
+    /* Receive Data and Receive BD Initiator Hardware Diagnostic. */
+    T3_32BIT_REGISTER HwDiag;
+
+    /* Unused space. */
+    LM_UINT8 Unused3[828];
+} T3_RCV_DATA_BD_INITIATOR, *PT3_RCV_DATA_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Receive Data Completion Control Registes. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_DATA_COMP_MODE_RESET                        BIT_0
+    #define RCV_DATA_COMP_MODE_ENABLE                       BIT_1
+    #define RCV_DATA_COMP_MODE_ATTN_ENABLE                  BIT_2
+
+    /* Unused spaced. */
+    LM_UINT8 Unused[1020];
+} T3_RCV_DATA_COMPLETION, *PT3_RCV_DATA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive BD Initiator Control. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_BD_IN_MODE_RESET                            BIT_0
+    #define RCV_BD_IN_MODE_ENABLE                           BIT_1
+    #define RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE    BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define RCV_BD_IN_STATUS_BD_IN_DIABLED_RCB_ATTN         BIT_2
+
+    T3_32BIT_REGISTER NicJumboRcvProdIdx;
+    T3_32BIT_REGISTER NicStdRcvProdIdx;
+    T3_32BIT_REGISTER NicMiniRcvProdIdx;
+
+    T3_32BIT_REGISTER MiniRcvThreshold;
+    T3_32BIT_REGISTER StdRcvThreshold;
+    T3_32BIT_REGISTER JumboRcvThreshold;
+
+    /* Unused space. */
+    LM_UINT8 Unused[992];
+} T3_RCV_BD_INITIATOR, *PT3_RCV_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Receive BD Completion Control Registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_BD_COMP_MODE_RESET                          BIT_0
+    #define RCV_BD_COMP_MODE_ENABLE                         BIT_1
+    #define RCV_BD_COMP_MODE_ATTN_ENABLE                    BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define RCV_BD_COMP_STATUS_ERROR_ATTN                   BIT_2
+
+    T3_32BIT_REGISTER  NicJumboRcvBdProdIdx;
+    T3_32BIT_REGISTER  NicStdRcvBdProdIdx;
+    T3_32BIT_REGISTER  NicMiniRcvBdProdIdx;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1004];
+} T3_RCV_BD_COMPLETION, *PT3_RCV_BD_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive list selector control register. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_LIST_SEL_MODE_RESET                         BIT_0
+    #define RCV_LIST_SEL_MODE_ENABLE                        BIT_1
+    #define RCV_LIST_SEL_MODE_ATTN_ENABLE                   BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define RCV_LIST_SEL_STATUS_ERROR_ATTN                  BIT_2
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_RCV_LIST_SELECTOR, *PT3_RCV_LIST_SELECTOR;
+
+
+
+/******************************************************************************/
+/* Mbuf cluster free registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+#define MBUF_CLUSTER_FREE_MODE_RESET    BIT_0
+#define MBUF_CLUSTER_FREE_MODE_ENABLE   BIT_1
+
+    T3_32BIT_REGISTER Status;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_MBUF_CLUSTER_FREE, *PT3_MBUF_CLUSTER_FREE;
+
+
+
+/******************************************************************************/
+/* Host coalescing control registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode. */
+    T3_32BIT_REGISTER Mode;
+    #define HOST_COALESCE_RESET                         BIT_0
+    #define HOST_COALESCE_ENABLE                        BIT_1
+    #define HOST_COALESCE_ATTN                          BIT_2
+    #define HOST_COALESCE_NOW                           BIT_3
+    #define HOST_COALESCE_FULL_STATUS_MODE              BIT_NONE
+    #define HOST_COALESCE_64_BYTE_STATUS_MODE           BIT_7
+    #define HOST_COALESCE_32_BYTE_STATUS_MODE           BIT_8
+    #define HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT    BIT_9
+    #define HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT    BIT_10
+    #define HOST_COALESCE_NO_INT_ON_COALESCE_NOW_MODE   BIT_11
+    #define HOST_COALESCE_NO_INT_ON_FORCE_DMAD_MODE     BIT_12
+
+    /* Status. */
+    T3_32BIT_REGISTER Status;
+    #define HOST_COALESCE_ERROR_ATTN                    BIT_2
+
+    /* Receive coalescing ticks. */
+    T3_32BIT_REGISTER RxCoalescingTicks;
+
+    /* Send coalescing ticks. */
+    T3_32BIT_REGISTER TxCoalescingTicks;
+
+    /* Receive max coalesced frames. */
+    T3_32BIT_REGISTER RxMaxCoalescedFrames;
+
+    /* Send max coalesced frames. */
+    T3_32BIT_REGISTER TxMaxCoalescedFrames;
+
+    /* Receive coalescing ticks during interrupt. */
+    T3_32BIT_REGISTER RxCoalescedTickDuringInt;
+
+    /* Send coalescing ticks during interrupt. */
+    T3_32BIT_REGISTER TxCoalescedTickDuringInt;
+
+    /* Receive max coalesced frames during interrupt. */
+    T3_32BIT_REGISTER RxMaxCoalescedFramesDuringInt;
+
+    /* Send max coalesced frames during interrupt. */
+    T3_32BIT_REGISTER TxMaxCoalescedFramesDuringInt;
+
+    /* Statistics tick. */
+    T3_32BIT_REGISTER StatsCoalescingTicks;
+
+    /* Unused space. */
+    LM_UINT8 Unused2[4];
+
+    /* Statistics host address. */
+    T3_64BIT_REGISTER StatsBlkHostAddr;
+
+    /* Status block host address.*/
+    T3_64BIT_REGISTER StatusBlkHostAddr;
+
+    /* Statistics NIC address. */
+    T3_32BIT_REGISTER StatsBlkNicAddr;
+
+    /* Statust block NIC address. */
+    T3_32BIT_REGISTER StatusBlkNicAddr;
+
+    /* Flow attention registers. */
+    T3_32BIT_REGISTER FlowAttn;
+
+    /* Unused space. */
+    LM_UINT8 Unused3[4];
+
+    T3_32BIT_REGISTER NicJumboRcvBdConIdx;
+    T3_32BIT_REGISTER NicStdRcvBdConIdx;
+    T3_32BIT_REGISTER NicMiniRcvBdConIdx;
+
+    /* Unused space. */
+    LM_UINT8 Unused4[36];
+
+    T3_32BIT_REGISTER NicRetProdIdx[16];
+    T3_32BIT_REGISTER NicSndBdConIdx[16];
+
+    /* Unused space. */
+    LM_UINT8 Unused5[768];
+} T3_HOST_COALESCING, *PT3_HOST_COALESCING;
+
+
+
+/******************************************************************************/
+/* Memory arbiter registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+#define T3_MEM_ARBITER_MODE_RESET       BIT_0
+#define T3_MEM_ARBITER_MODE_ENABLE      BIT_1
+
+    T3_32BIT_REGISTER Status;
+
+    T3_32BIT_REGISTER ArbTrapAddrLow;
+    T3_32BIT_REGISTER ArbTrapAddrHigh;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1008];
+} T3_MEM_ARBITER, *PT3_MEM_ARBITER;
+
+
+
+/******************************************************************************/
+/* Buffer manager control register. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define BUFMGR_MODE_RESET                           BIT_0
+    #define BUFMGR_MODE_ENABLE                          BIT_1
+    #define BUFMGR_MODE_ATTN_ENABLE                     BIT_2
+    #define BUFMGR_MODE_BM_TEST                         BIT_3
+    #define BUFMGR_MODE_MBUF_LOW_ATTN_ENABLE            BIT_4
+
+    T3_32BIT_REGISTER Status;
+    #define BUFMGR_STATUS_ERROR                         BIT_2
+    #define BUFMGR_STATUS_MBUF_LOW                      BIT_4
+
+    T3_32BIT_REGISTER MbufPoolAddr;
+    T3_32BIT_REGISTER MbufPoolSize;
+    T3_32BIT_REGISTER MbufReadDmaLowWaterMark;
+    T3_32BIT_REGISTER MbufMacRxLowWaterMark;
+    T3_32BIT_REGISTER MbufHighWaterMark;
+
+    T3_32BIT_REGISTER RxCpuMbufAllocReq;
+    #define BUFMGR_MBUF_ALLOC_BIT                     BIT_31
+    T3_32BIT_REGISTER RxCpuMbufAllocResp;
+    T3_32BIT_REGISTER TxCpuMbufAllocReq;
+    T3_32BIT_REGISTER TxCpuMbufAllocResp;
+
+    T3_32BIT_REGISTER DmaDescPoolAddr;
+    T3_32BIT_REGISTER DmaDescPoolSize;
+    T3_32BIT_REGISTER DmaLowWaterMark;
+    T3_32BIT_REGISTER DmaHighWaterMark;
+
+    T3_32BIT_REGISTER RxCpuDmaAllocReq;
+    T3_32BIT_REGISTER RxCpuDmaAllocResp;
+    T3_32BIT_REGISTER TxCpuDmaAllocReq;
+    T3_32BIT_REGISTER TxCpuDmaAllocResp;
+
+    T3_32BIT_REGISTER Hwdiag[3];
+
+    /* Unused space. */
+    LM_UINT8 Unused[936];
+} T3_BUFFER_MANAGER, *PT3_BUFFER_MANAGER;
+
+
+
+/******************************************************************************/
+/* Read DMA control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define DMA_READ_MODE_RESET                         BIT_0
+    #define DMA_READ_MODE_ENABLE                        BIT_1
+    #define DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE      BIT_2
+    #define DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE      BIT_3
+    #define DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE      BIT_4
+    #define DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE     BIT_5
+    #define DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE      BIT_6
+    #define DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE     BIT_7
+    #define DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE     BIT_8
+    #define DMA_READ_MODE_LONG_READ_ATTN_ENABLE         BIT_9
+    #define DMA_READ_MODE_SPLIT_ENABLE                  BIT_11
+    #define DMA_READ_MODE_SPLIT_RESET                   BIT_12
+
+    T3_32BIT_REGISTER Status;
+    #define DMA_READ_STATUS_TARGET_ABORT_ATTN           BIT_2
+    #define DMA_READ_STATUS_MASTER_ABORT_ATTN           BIT_3
+    #define DMA_READ_STATUS_PARITY_ERROR_ATTN           BIT_4
+    #define DMA_READ_STATUS_ADDR_OVERFLOW_ATTN          BIT_5
+    #define DMA_READ_STATUS_FIFO_OVERRUN_ATTN           BIT_6
+    #define DMA_READ_STATUS_FIFO_UNDERRUN_ATTN          BIT_7
+    #define DMA_READ_STATUS_FIFO_OVERREAD_ATTN          BIT_8
+    #define DMA_READ_STATUS_LONG_READ_ATTN              BIT_9
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_DMA_READ, *PT3_DMA_READ;
+
+typedef union T3_CPU
+{
+  struct
+  {
+    T3_32BIT_REGISTER mode;
+    #define CPU_MODE_HALT   BIT_10
+    #define CPU_MODE_RESET  BIT_0
+    T3_32BIT_REGISTER state;
+    T3_32BIT_REGISTER EventMask;
+    T3_32BIT_REGISTER reserved1[4];
+    T3_32BIT_REGISTER PC;
+    T3_32BIT_REGISTER Instruction;
+    T3_32BIT_REGISTER SpadUnderflow;
+    T3_32BIT_REGISTER WatchdogClear;
+    T3_32BIT_REGISTER WatchdogVector;
+    T3_32BIT_REGISTER WatchdogSavedPC;
+    T3_32BIT_REGISTER HardwareBp;
+    T3_32BIT_REGISTER reserved2[3];
+    T3_32BIT_REGISTER WatchdogSavedState;
+    T3_32BIT_REGISTER LastBrchAddr;
+    T3_32BIT_REGISTER SpadUnderflowSet;
+    T3_32BIT_REGISTER reserved3[(0x200-0x50)/4];
+    T3_32BIT_REGISTER Regs[32];
+    T3_32BIT_REGISTER reserved4[(0x400-0x280)/4];
+  }reg;
+}T3_CPU, *PT3_CPU;
+
+/******************************************************************************/
+/* Write DMA control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define DMA_WRITE_MODE_RESET                        BIT_0
+    #define DMA_WRITE_MODE_ENABLE                       BIT_1
+    #define DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE     BIT_2
+    #define DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE     BIT_3
+    #define DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE     BIT_4
+    #define DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE    BIT_5
+    #define DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE     BIT_6
+    #define DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE    BIT_7
+    #define DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE    BIT_8
+    #define DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE        BIT_9
+
+    T3_32BIT_REGISTER Status;
+    #define DMA_WRITE_STATUS_TARGET_ABORT_ATTN          BIT_2
+    #define DMA_WRITE_STATUS_MASTER_ABORT_ATTN          BIT_3
+    #define DMA_WRITE_STATUS_PARITY_ERROR_ATTN          BIT_4
+    #define DMA_WRITE_STATUS_ADDR_OVERFLOW_ATTN         BIT_5
+    #define DMA_WRITE_STATUS_FIFO_OVERRUN_ATTN          BIT_6
+    #define DMA_WRITE_STATUS_FIFO_UNDERRUN_ATTN         BIT_7
+    #define DMA_WRITE_STATUS_FIFO_OVERREAD_ATTN         BIT_8
+    #define DMA_WRITE_STATUS_LONG_READ_ATTN             BIT_9
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_DMA_WRITE, *PT3_DMA_WRITE;
+
+
+
+/******************************************************************************/
+/* Mailbox registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Interrupt mailbox registers. */
+    T3_64BIT_REGISTER Interrupt[4];
+
+    /* General mailbox registers. */
+    T3_64BIT_REGISTER General[8];
+
+    /* Reload statistics mailbox. */
+    T3_64BIT_REGISTER ReloadStat;
+
+    /* Receive BD ring producer index registers. */
+    T3_64BIT_REGISTER RcvStdProdIdx;
+    T3_64BIT_REGISTER RcvJumboProdIdx;
+    T3_64BIT_REGISTER RcvMiniProdIdx;
+
+    /* Receive return ring consumer index registers. */
+    T3_64BIT_REGISTER RcvRetConIdx[16];
+
+    /* Send BD ring host producer index registers. */
+    T3_64BIT_REGISTER SendHostProdIdx[16];
+
+    /* Send BD ring nic producer index registers. */
+    T3_64BIT_REGISTER SendNicProdIdx[16];
+}T3_MAILBOX, *PT3_MAILBOX;
+
+typedef struct {
+    T3_MAILBOX Mailbox;
+
+    /* Priority mailbox registers. */
+    T3_32BIT_REGISTER HighPriorityEventVector;
+    T3_32BIT_REGISTER HighPriorityEventMask;
+    T3_32BIT_REGISTER LowPriorityEventVector;
+    T3_32BIT_REGISTER LowPriorityEventMask;
+
+    /* Unused space. */
+    LM_UINT8 Unused[496];
+} T3_GRC_MAILBOX, *PT3_GRC_MAILBOX;
+
+
+/******************************************************************************/
+/* Flow through queues. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Reset;
+
+    LM_UINT8 Unused[12];
+
+    T3_32BIT_REGISTER DmaNormalReadFtqCtrl;
+    T3_32BIT_REGISTER DmaNormalReadFtqFullCnt;
+    T3_32BIT_REGISTER DmaNormalReadFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaNormalReadFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER DmaHighReadFtqCtrl;
+    T3_32BIT_REGISTER DmaHighReadFtqFullCnt;
+    T3_32BIT_REGISTER DmaHighReadFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaHighReadFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER DmaCompDiscardFtqCtrl;
+    T3_32BIT_REGISTER DmaCompDiscardFtqFullCnt;
+    T3_32BIT_REGISTER DmaCompDiscardFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaCompDiscardFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SendBdCompFtqCtrl;
+    T3_32BIT_REGISTER SendBdCompFtqFullCnt;
+    T3_32BIT_REGISTER SendBdCompFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SendBdCompFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SendDataInitiatorFtqCtrl;
+    T3_32BIT_REGISTER SendDataInitiatorFtqFullCnt;
+    T3_32BIT_REGISTER SendDataInitiatorFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SendDataInitiatorFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER DmaNormalWriteFtqCtrl;
+    T3_32BIT_REGISTER DmaNormalWriteFtqFullCnt;
+    T3_32BIT_REGISTER DmaNormalWriteFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaNormalWriteFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER DmaHighWriteFtqCtrl;
+    T3_32BIT_REGISTER DmaHighWriteFtqFullCnt;
+    T3_32BIT_REGISTER DmaHighWriteFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaHighWriteFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SwType1FtqCtrl;
+    T3_32BIT_REGISTER SwType1FtqFullCnt;
+    T3_32BIT_REGISTER SwType1FtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SwType1FtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SendDataCompFtqCtrl;
+    T3_32BIT_REGISTER SendDataCompFtqFullCnt;
+    T3_32BIT_REGISTER SendDataCompFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SendDataCompFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER HostCoalesceFtqCtrl;
+    T3_32BIT_REGISTER HostCoalesceFtqFullCnt;
+    T3_32BIT_REGISTER HostCoalesceFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER HostCoalesceFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER MacTxFtqCtrl;
+    T3_32BIT_REGISTER MacTxFtqFullCnt;
+    T3_32BIT_REGISTER MacTxFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER MacTxFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER MbufClustFreeFtqCtrl;
+    T3_32BIT_REGISTER MbufClustFreeFtqFullCnt;
+    T3_32BIT_REGISTER MbufClustFreeFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER MbufClustFreeFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER RcvBdCompFtqCtrl;
+    T3_32BIT_REGISTER RcvBdCompFtqFullCnt;
+    T3_32BIT_REGISTER RcvBdCompFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER RcvBdCompFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER RcvListPlmtFtqCtrl;
+    T3_32BIT_REGISTER RcvListPlmtFtqFullCnt;
+    T3_32BIT_REGISTER RcvListPlmtFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER RcvListPlmtFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER RcvDataBdInitiatorFtqCtrl;
+    T3_32BIT_REGISTER RcvDataBdInitiatorFtqFullCnt;
+    T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER RcvDataCompFtqCtrl;
+    T3_32BIT_REGISTER RcvDataCompFtqFullCnt;
+    T3_32BIT_REGISTER RcvDataCompFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER RcvDataCompFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SwType2FtqCtrl;
+    T3_32BIT_REGISTER SwType2FtqFullCnt;
+    T3_32BIT_REGISTER SwType2FtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SwType2FtqFifoWritePeek;
+
+    /* Unused space. */
+    LM_UINT8 Unused2[736];
+} T3_FTQ, *PT3_FTQ;
+
+
+
+/******************************************************************************/
+/* Message signaled interrupt registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+#define MSI_MODE_RESET       BIT_0
+#define MSI_MODE_ENABLE      BIT_1
+    T3_32BIT_REGISTER Status;
+
+    T3_32BIT_REGISTER MsiFifoAccess;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1012];
+} T3_MSG_SIGNALED_INT, *PT3_MSG_SIGNALED_INT;
+
+
+
+/******************************************************************************/
+/* DMA Completion registes. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define DMA_COMP_MODE_RESET                         BIT_0
+    #define DMA_COMP_MODE_ENABLE                        BIT_1
+
+    /* Unused space. */
+    LM_UINT8 Unused[1020];
+} T3_DMA_COMPLETION, *PT3_DMA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* GRC registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode control register. */
+    T3_32BIT_REGISTER Mode;
+    #define GRC_MODE_UPDATE_ON_COALESCING               BIT_0
+    #define GRC_MODE_BYTE_SWAP_NON_FRAME_DATA           BIT_1
+    #define GRC_MODE_WORD_SWAP_NON_FRAME_DATA           BIT_2
+    #define GRC_MODE_BYTE_SWAP_DATA                     BIT_4
+    #define GRC_MODE_WORD_SWAP_DATA                     BIT_5
+    #define GRC_MODE_SPLIT_HEADER_MODE                  BIT_8
+    #define GRC_MODE_NO_FRAME_CRACKING                  BIT_9
+    #define GRC_MODE_INCLUDE_CRC                        BIT_10
+    #define GRC_MODE_ALLOW_BAD_FRAMES                   BIT_11
+    #define GRC_MODE_NO_INTERRUPT_ON_SENDS              BIT_13
+    #define GRC_MODE_NO_INTERRUPT_ON_RECEIVE            BIT_14
+    #define GRC_MODE_FORCE_32BIT_PCI_BUS_MODE           BIT_15
+    #define GRC_MODE_HOST_STACK_UP                      BIT_16
+    #define GRC_MODE_HOST_SEND_BDS                      BIT_17
+    #define GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM         BIT_20
+    #define GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM         BIT_23
+    #define GRC_MODE_INT_ON_TX_CPU_ATTN                 BIT_24
+    #define GRC_MODE_INT_ON_RX_CPU_ATTN                 BIT_25
+    #define GRC_MODE_INT_ON_MAC_ATTN                    BIT_26
+    #define GRC_MODE_INT_ON_DMA_ATTN                    BIT_27
+    #define GRC_MODE_INT_ON_FLOW_ATTN                   BIT_28
+    #define GRC_MODE_4X_NIC_BASED_SEND_RINGS            BIT_29
+    #define GRC_MODE_MULTICAST_FRAME_ENABLE             BIT_30
+
+    /* Misc configuration register. */
+    T3_32BIT_REGISTER MiscCfg;
+    #define GRC_MISC_CFG_CORE_CLOCK_RESET               BIT_0
+    #define GRC_MISC_PRESCALAR_TIMER_MASK               0xfe
+    #define GRC_MISC_BD_ID_MASK                         0x0001e000
+    #define GRC_MISC_BD_ID_5700                         0x0001e000
+    #define GRC_MISC_BD_ID_5701                         0x00000000
+    #define GRC_MISC_BD_ID_5703                         0x00000000
+    #define GRC_MISC_BD_ID_5703S                        0x00002000
+    #define GRC_MISC_BD_ID_5702FE                       0x00004000
+    #define GRC_MISC_BD_ID_5704                         0x00000000
+    #define GRC_MISC_BD_ID_5704CIOBE                    0x00004000
+
+    /* Miscellaneous local control register. */
+    T3_32BIT_REGISTER LocalCtrl;
+    #define GRC_MISC_LOCAL_CTRL_INT_ACTIVE              BIT_0
+    #define GRC_MISC_LOCAL_CTRL_CLEAR_INT               BIT_1
+    #define GRC_MISC_LOCAL_CTRL_SET_INT                 BIT_2
+    #define GRC_MISC_LOCAL_CTRL_INT_ON_ATTN             BIT_3
+    #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT0             BIT_8
+    #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT1             BIT_9
+    #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT2             BIT_10
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE0                BIT_11
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE1                BIT_12
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE2                BIT_13
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0            BIT_14
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1            BIT_15
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2            BIT_16
+    #define GRC_MISC_LOCAL_CTRL_ENABLE_EXT_MEMORY       BIT_17
+    #define GRC_MISC_LOCAL_CTRL_BANK_SELECT             BIT_21
+    #define GRC_MISC_LOCAL_CTRL_SSRAM_TYPE              BIT_22
+
+    #define GRC_MISC_MEMSIZE_256K     0
+    #define GRC_MISC_MEMSIZE_512K     (1 << 18)
+    #define GRC_MISC_MEMSIZE_1024K    (2 << 18)
+    #define GRC_MISC_MEMSIZE_2048K    (3 << 18)
+    #define GRC_MISC_MEMSIZE_4096K    (4 << 18)
+    #define GRC_MISC_MEMSIZE_8192K    (5 << 18)
+    #define GRC_MISC_MEMSIZE_16M      (6 << 18)
+    #define GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM            BIT_24
+
+
+    T3_32BIT_REGISTER Timer;
+
+    T3_32BIT_REGISTER RxCpuEvent;
+    T3_32BIT_REGISTER RxTimerRef;
+    T3_32BIT_REGISTER RxCpuSemaphore;
+    T3_32BIT_REGISTER RemoteRxCpuAttn;
+
+    T3_32BIT_REGISTER TxCpuEvent;
+    T3_32BIT_REGISTER TxTimerRef;
+    T3_32BIT_REGISTER TxCpuSemaphore;
+    T3_32BIT_REGISTER RemoteTxCpuAttn;
+
+    T3_64BIT_REGISTER MemoryPowerUp;
+
+    T3_32BIT_REGISTER EepromAddr;
+    #define SEEPROM_ADDR_WRITE       0
+    #define SEEPROM_ADDR_READ        (1 << 31)
+    #define SEEPROM_ADDR_RW_MASK     0x80000000
+    #define SEEPROM_ADDR_COMPLETE    (1 << 30)
+    #define SEEPROM_ADDR_FSM_RESET   (1 << 29)
+    #define SEEPROM_ADDR_DEV_ID(x)   (x << 26)
+    #define SEEPROM_ADDR_DEV_ID_MASK 0x1c000000
+    #define SEEPROM_ADDR_START       (1 << 25)
+    #define SEEPROM_ADDR_CLK_PERD(x) (x << 16)
+    #define SEEPROM_ADDR_ADDRESS(x)  (x & 0xfffc)
+    #define SEEPROM_ADDR_ADDRESS_MASK 0x0000ffff
+
+    #define SEEPROM_CLOCK_PERIOD        60
+    #define SEEPROM_CHIP_SIZE           (64 * 1024)
+
+    T3_32BIT_REGISTER EepromData;
+    T3_32BIT_REGISTER EepromCtrl;
+
+    T3_32BIT_REGISTER MdiCtrl;
+    T3_32BIT_REGISTER SepromDelay;
+
+    /* Unused space. */
+    LM_UINT8 Unused[948];
+} T3_GRC, *PT3_GRC;
+
+
+/******************************************************************************/
+/* NVRAM control registers. */
+/******************************************************************************/
+
+typedef struct
+{
+    T3_32BIT_REGISTER Cmd;
+    #define NVRAM_CMD_RESET                             BIT_0
+    #define NVRAM_CMD_DONE                              BIT_3
+    #define NVRAM_CMD_DO_IT                             BIT_4
+    #define NVRAM_CMD_WR                                BIT_5
+    #define NVRAM_CMD_RD                                BIT_NONE
+    #define NVRAM_CMD_ERASE                             BIT_6
+    #define NVRAM_CMD_FIRST                             BIT_7
+    #define NVRAM_CMD_LAST                              BIT_8
+
+    T3_32BIT_REGISTER Status;
+    T3_32BIT_REGISTER WriteData;
+
+    T3_32BIT_REGISTER Addr;
+    #define NVRAM_ADDRESS_MASK                          0xffffff
+
+    T3_32BIT_REGISTER ReadData;
+
+    /* Flash config 1 register. */
+    T3_32BIT_REGISTER Config1;
+    #define FLASH_INTERFACE_ENABLE                      BIT_0
+    #define FLASH_SSRAM_BUFFERRED_MODE                  BIT_1
+    #define FLASH_PASS_THRU_MODE                        BIT_2
+    #define FLASH_BIT_BANG_MODE                         BIT_3
+    #define FLASH_COMPAT_BYPASS                         BIT_31
+
+    /* Buffered flash (Atmel: AT45DB011B) specific information */
+    #define BUFFERED_FLASH_PAGE_POS         9
+    #define BUFFERED_FLASH_BYTE_ADDR_MASK   ((1<<BUFFERED_FLASH_PAGE_POS) - 1)
+    #define BUFFERED_FLASH_PAGE_SIZE        264
+    #define BUFFERED_FLASH_PHY_PAGE_SIZE    512
+
+    T3_32BIT_REGISTER Config2;
+    T3_32BIT_REGISTER Config3;
+    T3_32BIT_REGISTER SwArb;
+    #define SW_ARB_REQ_SET0                             BIT_0
+    #define SW_ARB_REQ_SET1                             BIT_1
+    #define SW_ARB_REQ_SET2                             BIT_2
+    #define SW_ARB_REQ_SET3                             BIT_3
+    #define SW_ARB_REQ_CLR0                             BIT_4
+    #define SW_ARB_REQ_CLR1                             BIT_5
+    #define SW_ARB_REQ_CLR2                             BIT_6
+    #define SW_ARB_REQ_CLR3                             BIT_7
+    #define SW_ARB_GNT0                                 BIT_8
+    #define SW_ARB_GNT1                                 BIT_9
+    #define SW_ARB_GNT2                                 BIT_10
+    #define SW_ARB_GNT3                                 BIT_11
+    #define SW_ARB_REQ0                                 BIT_12
+    #define SW_ARB_REQ1                                 BIT_13
+    #define SW_ARB_REQ2                                 BIT_14
+    #define SW_ARB_REQ3                                 BIT_15
+
+    /* Unused space. */
+    LM_UINT8 Unused[988];
+} T3_NVRAM, *PT3_NVRAM;
+
+
+/******************************************************************************/
+/* NIC's internal memory. */
+/******************************************************************************/
+
+typedef struct {
+    /* Page zero for the internal CPUs. */
+    LM_UINT8 PageZero[0x100];               /* 0x0000 */
+
+    /* Send RCBs. */
+    T3_RCB SendRcb[16];                     /* 0x0100 */
+
+    /* Receive Return RCBs. */
+    T3_RCB RcvRetRcb[16];                   /* 0x0200 */
+
+    /* Statistics block. */
+    T3_STATS_BLOCK StatsBlk;                /* 0x0300 */
+
+    /* Status block. */
+    T3_STATUS_BLOCK StatusBlk;              /* 0x0b00 */
+
+    /* Reserved for software. */
+    LM_UINT8 Reserved[1200];                /* 0x0b50 */
+
+    /* Unmapped region. */
+    LM_UINT8 Unmapped[4096];                /* 0x1000 */
+
+    /* DMA descriptors. */
+    LM_UINT8 DmaDesc[8192];                 /* 0x2000 */
+
+    /* Buffer descriptors. */
+    LM_UINT8 BufferDesc[16384];             /* 0x4000 */
+} T3_FIRST_32K_SRAM, *PT3_FIRST_32K_SRAM;
+
+
+
+/******************************************************************************/
+/* Memory layout. */
+/******************************************************************************/
+
+typedef struct {
+    /* PCI configuration registers. */
+    T3_PCI_CONFIGURATION PciCfg;
+
+    /* Unused. */
+    LM_UINT8 Unused1[0x100];                            /* 0x0100 */
+
+    /* Mailbox . */
+    T3_MAILBOX Mailbox;                                 /* 0x0200 */
+
+    /* MAC control registers. */
+    T3_MAC_CONTROL MacCtrl;                             /* 0x0400 */
+
+    /* Send data initiator control registers. */
+    T3_SEND_DATA_INITIATOR SndDataIn;                   /* 0x0c00 */
+
+    /* Send data completion Control registers. */
+    T3_SEND_DATA_COMPLETION SndDataComp;                /* 0x1000 */
+
+    /* Send BD ring selector. */
+    T3_SEND_BD_SELECTOR SndBdSel;                       /* 0x1400 */
+
+    /* Send BD initiator control registers. */
+    T3_SEND_BD_INITIATOR SndBdIn;                       /* 0x1800 */
+
+    /* Send BD completion control registers. */
+    T3_SEND_BD_COMPLETION SndBdComp;                    /* 0x1c00 */
+
+    /* Receive list placement control registers. */
+    T3_RCV_LIST_PLACEMENT RcvListPlmt;                  /* 0x2000 */
+
+    /* Receive Data and Receive BD Initiator Control. */
+    T3_RCV_DATA_BD_INITIATOR RcvDataBdIn;               /* 0x2400 */
+
+    /* Receive Data Completion Control */
+    T3_RCV_DATA_COMPLETION RcvDataComp;                 /* 0x2800 */
+
+    /* Receive BD Initiator Control Registers. */
+    T3_RCV_BD_INITIATOR RcvBdIn;                        /* 0x2c00 */
+
+    /* Receive BD Completion Control Registers. */
+    T3_RCV_BD_COMPLETION RcvBdComp;                     /* 0x3000 */
+
+    /* Receive list selector control registers. */
+    T3_RCV_LIST_SELECTOR RcvListSel;                    /* 0x3400 */
+
+    /* Mbuf cluster free registers. */
+    T3_MBUF_CLUSTER_FREE MbufClusterFree;               /* 0x3800 */
+
+    /* Host coalescing control registers. */
+    T3_HOST_COALESCING HostCoalesce;                    /* 0x3c00 */
+
+    /* Memory arbiter control registers. */
+    T3_MEM_ARBITER MemArbiter;                          /* 0x4000 */
+
+    /* Buffer manger control registers. */
+    T3_BUFFER_MANAGER BufMgr;                           /* 0x4400 */
+
+    /* Read DMA control registers. */
+    T3_DMA_READ DmaRead;                                /* 0x4800 */
+
+    /* Write DMA control registers. */
+    T3_DMA_WRITE DmaWrite;                              /* 0x4c00 */
+
+    T3_CPU rxCpu;                                       /* 0x5000 */
+    T3_CPU txCpu;                                       /* 0x5400 */
+
+    /* Mailboxes. */
+    T3_GRC_MAILBOX GrcMailbox;                          /* 0x5800 */
+
+    /* Flow Through queues. */
+    T3_FTQ Ftq;                                         /* 0x5c00 */
+
+    /* Message signaled interrupt registes. */
+    T3_MSG_SIGNALED_INT Msi;                            /* 0x6000 */
+
+    /* DMA completion registers. */
+    T3_DMA_COMPLETION DmaComp;                          /* 0x6400 */
+
+    /* GRC registers. */
+    T3_GRC Grc;                                         /* 0x6800 */
+
+    /* Unused space. */
+    LM_UINT8 Unused2[1024];                             /* 0x6c00 */
+
+    /* NVRAM registers. */
+    T3_NVRAM Nvram;                                     /* 0x7000 */
+
+    /* Unused space. */
+    LM_UINT8 Unused3[3072];                             /* 0x7400 */
+
+    /* The 32k memory window into the NIC's */
+    /* internal memory.  The memory window is */
+    /* controlled by the Memory Window Base */
+    /* Address register.  This register is located */
+    /* in the PCI configuration space. */
+    union {                                             /* 0x8000 */
+        T3_FIRST_32K_SRAM First32k;
+
+        /* Use the memory window base address register to determine the */
+        /* MBUF segment. */
+        LM_UINT32 Mbuf[32768/4];
+        LM_UINT32 MemBlock32K[32768/4];
+    } uIntMem;
+} T3_STD_MEM_MAP, *PT3_STD_MEM_MAP;
+
+
+/******************************************************************************/
+/* Adapter info. */
+/******************************************************************************/
+
+typedef struct
+{
+    LM_UINT16 Svid;
+    LM_UINT16 Ssid;
+    LM_UINT32 PhyId;
+    LM_UINT32 Serdes;   /* 0 = copper PHY, 1 = Serdes */
+} LM_ADAPTER_INFO, *PLM_ADAPTER_INFO;
+
+
+/******************************************************************************/
+/* Packet queues. */
+/******************************************************************************/
+
+DECLARE_QUEUE_TYPE(LM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT);
+DECLARE_QUEUE_TYPE(LM_TX_PACKET_Q, MAX_TX_PACKET_DESC_COUNT);
+
+
+
+/******************************************************************************/
+/* Tx counters. */
+/******************************************************************************/
+
+typedef struct {
+    LM_COUNTER TxPacketGoodCnt;
+    LM_COUNTER TxBytesGoodCnt;
+    LM_COUNTER TxPacketAbortedCnt;
+    LM_COUNTER NoSendBdLeftCnt;
+    LM_COUNTER NoMapRegisterLeftCnt;
+    LM_COUNTER TooManyFragmentsCnt;
+    LM_COUNTER NoTxPacketDescCnt;
+} LM_TX_COUNTERS, *PLM_TX_COUNTERS;
+
+
+
+/******************************************************************************/
+/* Rx counters. */
+/******************************************************************************/
+
+typedef struct {
+    LM_COUNTER RxPacketGoodCnt;
+    LM_COUNTER RxBytesGoodCnt;
+    LM_COUNTER RxPacketErrCnt;
+    LM_COUNTER RxErrCrcCnt;
+    LM_COUNTER RxErrCollCnt;
+    LM_COUNTER RxErrLinkLostCnt;
+    LM_COUNTER RxErrPhyDecodeCnt;
+    LM_COUNTER RxErrOddNibbleCnt;
+    LM_COUNTER RxErrMacAbortCnt;
+    LM_COUNTER RxErrShortPacketCnt;
+    LM_COUNTER RxErrNoResourceCnt;
+    LM_COUNTER RxErrLargePacketCnt;
+} LM_RX_COUNTERS, *PLM_RX_COUNTERS;
+
+
+
+/******************************************************************************/
+/* Receive producer rings. */
+/******************************************************************************/
+
+typedef enum {
+    T3_UNKNOWN_RCV_PROD_RING    = 0,
+    T3_STD_RCV_PROD_RING        = 1,
+    T3_MINI_RCV_PROD_RING       = 2,
+    T3_JUMBO_RCV_PROD_RING      = 3
+} T3_RCV_PROD_RING, *PT3_RCV_PROD_RING;
+
+
+
+/******************************************************************************/
+/* Packet descriptor. */
+/******************************************************************************/
+
+#define LM_PACKET_SIGNATURE_TX              0x6861766b
+#define LM_PACKET_SIGNATURE_RX              0x6b766168
+
+typedef struct _LM_PACKET {
+    /* Set in LM. */
+    LM_STATUS PacketStatus;
+
+    /* Set in LM for Rx, in UM for Tx. */
+    LM_UINT32 PacketSize;
+
+    LM_UINT16 Flags;
+
+    LM_UINT16 VlanTag;
+
+    union {
+        /* Send info. */
+        struct {
+            /* Set up by UM. */
+            LM_UINT32 FragCount;
+
+        } Tx;
+
+        /* Receive info. */
+        struct {
+            /* This descriptor belongs to either Std, Mini, or Jumbo ring. */
+            T3_RCV_PROD_RING RcvProdRing;
+
+            /* Receive buffer size */
+            LM_UINT32 RxBufferSize;
+
+            /* Checksum information. */
+            LM_UINT16 IpChecksum;
+            LM_UINT16 TcpUdpChecksum;
+
+        } Rx;
+    } u;
+} LM_PACKET;
+
+
+
+/******************************************************************************/
+/* Tigon3 device block. */
+/******************************************************************************/
+
+typedef struct _LM_DEVICE_BLOCK {
+    int index; /* Device ID */
+    /* Memory view. */
+    PT3_STD_MEM_MAP pMemView;
+
+    /* Base address of the block of memory in which the LM_PACKET descriptors */
+    /* are allocated from. */
+    PLM_VOID pPacketDescBase;
+
+    LM_UINT32 MiscHostCtrl;
+    LM_UINT32 GrcLocalCtrl;
+    LM_UINT32 DmaReadWriteCtrl;
+    LM_UINT32 PciState;
+
+    /* Rx info */
+    LM_UINT32 RxStdDescCnt;
+    LM_UINT32 RxStdQueuedCnt;
+    LM_UINT32 RxStdProdIdx;
+
+    PT3_RCV_BD pRxStdBdVirt;
+    LM_PHYSICAL_ADDRESS RxStdBdPhy;
+
+    LM_UINT32 RxPacketDescCnt;
+    LM_RX_PACKET_Q RxPacketFreeQ;
+    LM_RX_PACKET_Q RxPacketReceivedQ;
+
+    /* Receive info. */
+    PT3_RCV_BD pRcvRetBdVirt;
+    LM_PHYSICAL_ADDRESS RcvRetBdPhy;
+    LM_UINT32 RcvRetConIdx;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    LM_UINT32 RxJumboDescCnt;
+    LM_UINT32 RxJumboBufferSize;
+    LM_UINT32 RxJumboQueuedCnt;
+
+    LM_UINT32 RxJumboProdIdx;
+
+    PT3_RCV_BD pRxJumboBdVirt;
+    LM_PHYSICAL_ADDRESS RxJumboBdPhy;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* These values are used by the upper module to inform the protocol */
+    /* of the maximum transmit/receive packet size. */
+    LM_UINT32 TxMtu;    /* Does not include CRC. */
+    LM_UINT32 RxMtu;    /* Does not include CRC. */
+
+    /* We need to shadow the EMAC, Rx, Tx mode registers.  With B0 silicon, */
+    /* we may have problems reading any MAC registers in 10mb mode. */
+    LM_UINT32 MacMode;
+    LM_UINT32 RxMode;
+    LM_UINT32 TxMode;
+
+    /* MiMode register. */
+    LM_UINT32 MiMode;
+
+    /* Host coalesce mode register. */
+    LM_UINT32 CoalesceMode;
+
+    /* Send info. */
+    LM_UINT32 TxPacketDescCnt;
+
+    /* Tx info. */
+    LM_TX_PACKET_Q TxPacketFreeQ;
+    LM_TX_PACKET_Q TxPacketActiveQ;
+    LM_TX_PACKET_Q TxPacketXmittedQ;
+
+    /* Pointers to SendBd. */
+    PT3_SND_BD pSendBdVirt;
+    LM_PHYSICAL_ADDRESS SendBdPhy;  /* Only valid for Host based Send BD. */
+
+    /* Send producer and consumer indices. */
+    LM_UINT32 SendProdIdx;
+    LM_UINT32 SendConIdx;
+
+    /* Number of BD left. */
+    atomic_t SendBdLeft;
+
+    T3_SND_BD ShadowSendBd[T3_SEND_RCB_ENTRY_COUNT];
+
+    /* Counters. */
+    LM_RX_COUNTERS RxCounters;
+    LM_TX_COUNTERS TxCounters;
+
+    /* Host coalescing parameters. */
+    LM_UINT32 RxCoalescingTicks;
+    LM_UINT32 TxCoalescingTicks;
+    LM_UINT32 RxMaxCoalescedFrames;
+    LM_UINT32 TxMaxCoalescedFrames;
+    LM_UINT32 StatsCoalescingTicks;
+    LM_UINT32 RxCoalescingTicksDuringInt;
+    LM_UINT32 TxCoalescingTicksDuringInt;
+    LM_UINT32 RxMaxCoalescedFramesDuringInt;
+    LM_UINT32 TxMaxCoalescedFramesDuringInt;
+
+    /* DMA water marks. */
+    LM_UINT32 DmaMbufLowMark;
+    LM_UINT32 RxMacMbufLowMark;
+    LM_UINT32 MbufHighMark;
+
+    /* Status block. */
+    PT3_STATUS_BLOCK pStatusBlkVirt;
+    LM_PHYSICAL_ADDRESS StatusBlkPhy;
+
+    /* Statistics block. */
+    PT3_STATS_BLOCK pStatsBlkVirt;
+    LM_PHYSICAL_ADDRESS StatsBlkPhy;
+
+    /* Current receive mask. */
+    LM_UINT32 ReceiveMask;
+
+    /* Task offload capabilities. */
+    LM_TASK_OFFLOAD TaskOffloadCap;
+
+    /* Task offload selected. */
+    LM_TASK_OFFLOAD TaskToOffload;
+
+    /* Wake up capability. */
+    LM_WAKE_UP_MODE WakeUpModeCap;
+
+    /* Wake up capability. */
+    LM_WAKE_UP_MODE WakeUpMode;
+
+    /* Flow control. */
+    LM_FLOW_CONTROL FlowControlCap;
+    LM_FLOW_CONTROL FlowControl;
+
+    /* Enable or disable PCI MWI. */
+    LM_UINT32 EnableMWI;
+
+    /* Enable 5701 tagged status mode. */
+    LM_UINT32 UseTaggedStatus;
+
+    /* NIC will not compute the pseudo header checksum.  The driver or OS */
+    /* must seed the checksum field with the pseudo checksum. */
+    LM_UINT32 NoTxPseudoHdrChksum;
+
+    /* The receive checksum in the BD does not include the pseudo checksum. */
+    /* The OS or the driver must calculate the pseudo checksum and add it to */
+    /* the checksum in the BD. */
+    LM_UINT32 NoRxPseudoHdrChksum;
+
+    /* Current node address. */
+    LM_UINT8 NodeAddress[8];
+
+    /* The adapter's node address. */
+    LM_UINT8 PermanentNodeAddress[8];
+
+    /* Adapter info. */
+    LM_UINT16 BusNum;
+    LM_UINT8 DevNum;
+    LM_UINT8 FunctNum;
+    LM_UINT16 PciVendorId;
+    LM_UINT16 PciDeviceId;
+    LM_UINT32 BondId;
+    LM_UINT8 Irq;
+    LM_UINT8 IntPin;
+    LM_UINT8 CacheLineSize;
+    LM_UINT8 PciRevId;
+#if PCIX_TARGET_WORKAROUND
+       LM_UINT32 EnablePciXFix;
+#endif
+    LM_UINT32 UndiFix;   /* new, jimmy */
+    LM_UINT32 PciCommandStatusWords;
+    LM_UINT32 ChipRevId;
+    LM_UINT16 SubsystemVendorId;
+    LM_UINT16 SubsystemId;
+#if 0  /* Jimmy, deleted in new driver */
+    LM_UINT32 MemBaseLow;
+    LM_UINT32 MemBaseHigh;
+    LM_UINT32 MemBaseSize;
+#endif
+    PLM_UINT8 pMappedMemBase;
+
+    /* Saved PCI configuration registers for restoring after a reset. */
+    LM_UINT32 SavedCacheLineReg;
+
+    /* Phy info. */
+    LM_UINT32 PhyAddr;
+    LM_UINT32 PhyId;
+
+    /* Requested phy settings. */
+    LM_REQUESTED_MEDIA_TYPE RequestedMediaType;
+
+    /* Disable auto-negotiation. */
+    LM_UINT32 DisableAutoNeg;
+
+    /* Ways for the MAC to get link change interrupt. */
+    LM_UINT32 PhyIntMode;
+    #define T3_PHY_INT_MODE_AUTO                        0
+    #define T3_PHY_INT_MODE_MI_INTERRUPT                1
+    #define T3_PHY_INT_MODE_LINK_READY                  2
+    #define T3_PHY_INT_MODE_AUTO_POLLING                3
+
+    /* Ways to determine link change status. */
+    LM_UINT32 LinkChngMode;
+    #define T3_LINK_CHNG_MODE_AUTO                      0
+    #define T3_LINK_CHNG_MODE_USE_STATUS_REG            1
+    #define T3_LINK_CHNG_MODE_USE_STATUS_BLOCK          2
+
+
+    /* LED mode. */
+    LM_UINT32 LedMode;
+
+    #define LED_MODE_AUTO                               0
+
+    /* 5700/01 LED mode. */
+    #define LED_MODE_THREE_LINK                         1
+    #define LED_MODE_LINK10                             2
+
+    /* 5703/02/04 LED mode. */
+    #define LED_MODE_OPEN_DRAIN                         1
+    #define LED_MODE_OUTPUT                             2
+
+    /* WOL Speed */
+    LM_UINT32 WolSpeed;
+    #define WOL_SPEED_10MB                              1
+    #define WOL_SPEED_100MB                             2
+
+    /* Reset the PHY on initialization. */
+    LM_UINT32 ResetPhyOnInit;
+
+    LM_UINT32 RestoreOnWakeUp;
+    LM_REQUESTED_MEDIA_TYPE WakeUpRequestedMediaType;
+    LM_UINT32 WakeUpDisableAutoNeg;
+
+    /* Current phy settings. */
+    LM_MEDIA_TYPE MediaType;
+    LM_LINE_SPEED LineSpeed;
+    LM_LINE_SPEED OldLineSpeed;
+    LM_DUPLEX_MODE DuplexMode;
+    LM_STATUS LinkStatus;
+    LM_UINT32 advertising;     /* Jimmy, new! */
+    LM_UINT32 advertising1000; /* Jimmy, new! */
+
+    /* Multicast address list. */
+    LM_UINT32 McEntryCount;
+    LM_UINT8 McTable[LM_MAX_MC_TABLE_SIZE][LM_MC_ENTRY_SIZE];
+
+    /* Use NIC or Host based send BD. */
+    LM_UINT32 NicSendBd;
+
+    /* Athlon fix. */
+    LM_UINT32 DelayPciGrant;
+
+    /* Enable OneDmaAtOnce */
+    LM_UINT32 OneDmaAtOnce;
+
+    /* Split Mode flags, Jimmy new */
+    LM_UINT32 SplitModeEnable;
+    LM_UINT32 SplitModeMaxReq;
+
+    /* Init flag. */
+    LM_BOOL InitDone;
+
+    /* Shutdown flag.  Set by the upper module. */
+    LM_BOOL ShuttingDown;
+
+    /* Flag to determine whether to call LM_QueueRxPackets or not in */
+    /* LM_ResetAdapter routine. */
+    LM_BOOL QueueRxPackets;
+
+    LM_UINT32 MbufBase;
+    LM_UINT32 MbufSize;
+
+    /* TRUE if we have a SERDES PHY. */
+    LM_UINT32 EnableTbi;
+
+    /* Ethernet@WireSpeed. */
+    LM_UINT32 EnableWireSpeed;
+
+    LM_UINT32 EepromWp;
+
+#if INCLUDE_TBI_SUPPORT
+    /* Autoneg state info. */
+    AN_STATE_INFO AnInfo;
+    LM_UINT32 PollTbiLink;
+    LM_UINT32 IgnoreTbiLinkChange;
+#endif
+    char PartNo[24];
+    char BootCodeVer[16];
+    char BusSpeedStr[24]; /* Jimmy, new! */
+    LM_UINT32 PhyCrcCount;
+} LM_DEVICE_BLOCK;
+
+
+#define T3_REG_CPU_VIEW               0xc0000000
+
+#define T3_BLOCK_DMA_RD               (1 << 0)
+#define T3_BLOCK_DMA_COMP             (1 << 1)
+#define T3_BLOCK_RX_BD_INITIATOR      (1 << 2)
+#define T3_BLOCK_RX_BD_COMP           (1 << 3)
+#define T3_BLOCK_DMA_WR               (1 << 4)
+#define T3_BLOCK_MSI_HANDLER          (1 << 5)
+#define T3_BLOCK_RX_LIST_PLMT         (1 << 6)
+#define T3_BLOCK_RX_LIST_SELECTOR     (1 << 7)
+#define T3_BLOCK_RX_DATA_INITIATOR    (1 << 8)
+#define T3_BLOCK_RX_DATA_COMP         (1 << 9)
+#define T3_BLOCK_HOST_COALESING       (1 << 10)
+#define T3_BLOCK_MAC_RX_ENGINE        (1 << 11)
+#define T3_BLOCK_MBUF_CLUSTER_FREE    (1 << 12)
+#define T3_BLOCK_SEND_BD_INITIATOR    (1 << 13)
+#define T3_BLOCK_SEND_BD_COMP         (1 << 14)
+#define T3_BLOCK_SEND_BD_SELECTOR     (1 << 15)
+#define T3_BLOCK_SEND_DATA_INITIATOR  (1 << 16)
+#define T3_BLOCK_SEND_DATA_COMP       (1 << 17)
+#define T3_BLOCK_MAC_TX_ENGINE        (1 << 18)
+#define T3_BLOCK_MEM_ARBITOR          (1 << 19)
+#define T3_BLOCK_MBUF_MANAGER         (1 << 20)
+#define T3_BLOCK_MAC_GLOBAL           (1 << 21)
+
+#define LM_ENABLE               1
+#define LM_DISABLE              2
+
+#define RX_CPU_EVT_SW0              0
+#define RX_CPU_EVT_SW1              1
+#define RX_CPU_EVT_RLP              2
+#define RX_CPU_EVT_SW3              3
+#define RX_CPU_EVT_RLS              4
+#define RX_CPU_EVT_SW4              5
+#define RX_CPU_EVT_RX_BD_COMP       6
+#define RX_CPU_EVT_SW5              7
+#define RX_CPU_EVT_RDI              8
+#define RX_CPU_EVT_DMA_WR           9
+#define RX_CPU_EVT_DMA_RD           10
+#define RX_CPU_EVT_SWQ              11
+#define RX_CPU_EVT_SW6              12
+#define RX_CPU_EVT_RDC              13
+#define RX_CPU_EVT_SW7              14
+#define RX_CPU_EVT_HOST_COALES      15
+#define RX_CPU_EVT_SW8              16
+#define RX_CPU_EVT_HIGH_DMA_WR      17
+#define RX_CPU_EVT_HIGH_DMA_RD      18
+#define RX_CPU_EVT_SW9              19
+#define RX_CPU_EVT_DMA_ATTN         20
+#define RX_CPU_EVT_LOW_P_MBOX       21
+#define RX_CPU_EVT_HIGH_P_MBOX      22
+#define RX_CPU_EVT_SW10             23
+#define RX_CPU_EVT_TX_CPU_ATTN      24
+#define RX_CPU_EVT_MAC_ATTN         25
+#define RX_CPU_EVT_RX_CPU_ATTN      26
+#define RX_CPU_EVT_FLOW_ATTN        27
+#define RX_CPU_EVT_SW11             28
+#define RX_CPU_EVT_TIMER            29
+#define RX_CPU_EVT_SW12             30
+#define RX_CPU_EVT_SW13             31
+
+/* RX-CPU event */
+#define RX_CPU_EVENT_SW_EVENT0      (1 << RX_CPU_EVT_SW0)
+#define RX_CPU_EVENT_SW_EVENT1      (1 << RX_CPU_EVT_SW1)
+#define RX_CPU_EVENT_RLP            (1 << RX_CPU_EVT_RLP)
+#define RX_CPU_EVENT_SW_EVENT3      (1 << RX_CPU_EVT_SW3)
+#define RX_CPU_EVENT_RLS            (1 << RX_CPU_EVT_RLS)
+#define RX_CPU_EVENT_SW_EVENT4      (1 << RX_CPU_EVT_SW4)
+#define RX_CPU_EVENT_RX_BD_COMP     (1 << RX_CPU_EVT_RX_BD_COMP)
+#define RX_CPU_EVENT_SW_EVENT5      (1 << RX_CPU_EVT_SW5)
+#define RX_CPU_EVENT_RDI            (1 << RX_CPU_EVT_RDI)
+#define RX_CPU_EVENT_DMA_WR         (1 << RX_CPU_EVT_DMA_WR)
+#define RX_CPU_EVENT_DMA_RD         (1 << RX_CPU_EVT_DMA_RD)
+#define RX_CPU_EVENT_SWQ            (1 << RX_CPU_EVT_SWQ)
+#define RX_CPU_EVENT_SW_EVENT6      (1 << RX_CPU_EVT_SW6)
+#define RX_CPU_EVENT_RDC            (1 << RX_CPU_EVT_RDC)
+#define RX_CPU_EVENT_SW_EVENT7      (1 << RX_CPU_EVT_SW7)
+#define RX_CPU_EVENT_HOST_COALES    (1 << RX_CPU_EVT_HOST_COALES)
+#define RX_CPU_EVENT_SW_EVENT8      (1 << RX_CPU_EVT_SW8)
+#define RX_CPU_EVENT_HIGH_DMA_WR    (1 << RX_CPU_EVT_HIGH_DMA_WR)
+#define RX_CPU_EVENT_HIGH_DMA_RD    (1 << RX_CPU_EVT_HIGH_DMA_RD)
+#define RX_CPU_EVENT_SW_EVENT9      (1 << RX_CPU_EVT_SW9)
+#define RX_CPU_EVENT_DMA_ATTN       (1 << RX_CPU_EVT_DMA_ATTN)
+#define RX_CPU_EVENT_LOW_P_MBOX     (1 << RX_CPU_EVT_LOW_P_MBOX)
+#define RX_CPU_EVENT_HIGH_P_MBOX    (1 << RX_CPU_EVT_HIGH_P_MBOX)
+#define RX_CPU_EVENT_SW_EVENT10     (1 << RX_CPU_EVT_SW10)
+#define RX_CPU_EVENT_TX_CPU_ATTN    (1 << RX_CPU_EVT_TX_CPU_ATTN)
+#define RX_CPU_EVENT_MAC_ATTN       (1 << RX_CPU_EVT_MAC_ATTN)
+#define RX_CPU_EVENT_RX_CPU_ATTN    (1 << RX_CPU_EVT_RX_CPU_ATTN)
+#define RX_CPU_EVENT_FLOW_ATTN      (1 << RX_CPU_EVT_FLOW_ATTN)
+#define RX_CPU_EVENT_SW_EVENT11     (1 << RX_CPU_EVT_SW11)
+#define RX_CPU_EVENT_TIMER          (1 << RX_CPU_EVT_TIMER)
+#define RX_CPU_EVENT_SW_EVENT12     (1 << RX_CPU_EVT_SW12)
+#define RX_CPU_EVENT_SW_EVENT13     (1 << RX_CPU_EVT_SW13)
+
+#define RX_CPU_MASK (RX_CPU_EVENT_SW_EVENT0 | \
+                    RX_CPU_EVENT_RLP | \
+                    RX_CPU_EVENT_RDI | \
+                    RX_CPU_EVENT_RDC)
+
+#define TX_CPU_EVT_SW0              0
+#define TX_CPU_EVT_SW1              1
+#define TX_CPU_EVT_SW2              2
+#define TX_CPU_EVT_SW3              3
+#define TX_CPU_EVT_TX_MAC           4
+#define TX_CPU_EVT_SW4              5
+#define TX_CPU_EVT_SBDC             6
+#define TX_CPU_EVT_SW5              7
+#define TX_CPU_EVT_SDI              8
+#define TX_CPU_EVT_DMA_WR           9
+#define TX_CPU_EVT_DMA_RD           10
+#define TX_CPU_EVT_SWQ              11
+#define TX_CPU_EVT_SW6              12
+#define TX_CPU_EVT_SDC              13
+#define TX_CPU_EVT_SW7              14
+#define TX_CPU_EVT_HOST_COALES      15
+#define TX_CPU_EVT_SW8              16
+#define TX_CPU_EVT_HIGH_DMA_WR      17
+#define TX_CPU_EVT_HIGH_DMA_RD      18
+#define TX_CPU_EVT_SW9              19
+#define TX_CPU_EVT_DMA_ATTN         20
+#define TX_CPU_EVT_LOW_P_MBOX       21
+#define TX_CPU_EVT_HIGH_P_MBOX      22
+#define TX_CPU_EVT_SW10             23
+#define TX_CPU_EVT_RX_CPU_ATTN      24
+#define TX_CPU_EVT_MAC_ATTN         25
+#define TX_CPU_EVT_TX_CPU_ATTN      26
+#define TX_CPU_EVT_FLOW_ATTN        27
+#define TX_CPU_EVT_SW11             28
+#define TX_CPU_EVT_TIMER            29
+#define TX_CPU_EVT_SW12             30
+#define TX_CPU_EVT_SW13             31
+
+
+/* TX-CPU event */
+#define TX_CPU_EVENT_SW_EVENT0      (1 << TX_CPU_EVT_SW0)
+#define TX_CPU_EVENT_SW_EVENT1      (1 << TX_CPU_EVT_SW1)
+#define TX_CPU_EVENT_SW_EVENT2      (1 << TX_CPU_EVT_SW2)
+#define TX_CPU_EVENT_SW_EVENT3      (1 << TX_CPU_EVT_SW3)
+#define TX_CPU_EVENT_TX_MAC         (1 << TX_CPU_EVT_TX_MAC)
+#define TX_CPU_EVENT_SW_EVENT4      (1 << TX_CPU_EVT_SW4)
+#define TX_CPU_EVENT_SBDC           (1 << TX_CPU_EVT_SBDC)
+#define TX_CPU_EVENT_SW_EVENT5      (1 << TX_CPU_EVT_SW5)
+#define TX_CPU_EVENT_SDI            (1 << TX_CPU_EVT_SDI)
+#define TX_CPU_EVENT_DMA_WR         (1 << TX_CPU_EVT_DMA_WR)
+#define TX_CPU_EVENT_DMA_RD         (1 << TX_CPU_EVT_DMA_RD)
+#define TX_CPU_EVENT_SWQ            (1 << TX_CPU_EVT_SWQ)
+#define TX_CPU_EVENT_SW_EVENT6      (1 << TX_CPU_EVT_SW6)
+#define TX_CPU_EVENT_SDC            (1 << TX_CPU_EVT_SDC)
+#define TX_CPU_EVENT_SW_EVENT7      (1 << TX_CPU_EVT_SW7)
+#define TX_CPU_EVENT_HOST_COALES    (1 << TX_CPU_EVT_HOST_COALES)
+#define TX_CPU_EVENT_SW_EVENT8      (1 << TX_CPU_EVT_SW8)
+#define TX_CPU_EVENT_HIGH_DMA_WR    (1 << TX_CPU_EVT_HIGH_DMA_WR)
+#define TX_CPU_EVENT_HIGH_DMA_RD    (1 << TX_CPU_EVT_HIGH_DMA_RD)
+#define TX_CPU_EVENT_SW_EVENT9      (1 << TX_CPU_EVT_SW9)
+#define TX_CPU_EVENT_DMA_ATTN       (1 << TX_CPU_EVT_DMA_ATTN)
+#define TX_CPU_EVENT_LOW_P_MBOX     (1 << TX_CPU_EVT_LOW_P_MBOX)
+#define TX_CPU_EVENT_HIGH_P_MBOX    (1 << TX_CPU_EVT_HIGH_P_MBOX)
+#define TX_CPU_EVENT_SW_EVENT10     (1 << TX_CPU_EVT_SW10)
+#define TX_CPU_EVENT_RX_CPU_ATTN    (1 << TX_CPU_EVT_RX_CPU_ATTN)
+#define TX_CPU_EVENT_MAC_ATTN       (1 << TX_CPU_EVT_MAC_ATTN)
+#define TX_CPU_EVENT_TX_CPU_ATTN    (1 << TX_CPU_EVT_TX_CPU_ATTN)
+#define TX_CPU_EVENT_FLOW_ATTN      (1 << TX_CPU_EVT_FLOW_ATTN)
+#define TX_CPU_EVENT_SW_EVENT11     (1 << TX_CPU_EVT_SW11)
+#define TX_CPU_EVENT_TIMER          (1 << TX_CPU_EVT_TIMER)
+#define TX_CPU_EVENT_SW_EVENT12     (1 << TX_CPU_EVT_SW12)
+#define TX_CPU_EVENT_SW_EVENT13     (1 << TX_CPU_EVT_SW13)
+
+
+#define TX_CPU_MASK (TX_CPU_EVENT_SW_EVENT0 | \
+                    TX_CPU_EVENT_SDI  | \
+                    TX_CPU_EVENT_SDC)
+
+
+#define T3_FTQ_TYPE1_UNDERFLOW_BIT   (1 << 29)
+#define T3_FTQ_TYPE1_PASS_BIT        (1 << 30)
+#define T3_FTQ_TYPE1_SKIP_BIT        (1 << 31)
+
+#define T3_FTQ_TYPE2_UNDERFLOW_BIT   (1 << 13)
+#define T3_FTQ_TYPE2_PASS_BIT        (1 << 14)
+#define T3_FTQ_TYPE2_SKIP_BIT        (1 << 15)
+
+#define T3_QID_DMA_READ               1
+#define T3_QID_DMA_HIGH_PRI_READ      2
+#define T3_QID_DMA_COMP_DX            3
+#define T3_QID_SEND_BD_COMP           4
+#define T3_QID_SEND_DATA_INITIATOR    5
+#define T3_QID_DMA_WRITE              6
+#define T3_QID_DMA_HIGH_PRI_WRITE     7
+#define T3_QID_SW_TYPE_1              8
+#define T3_QID_SEND_DATA_COMP         9
+#define T3_QID_HOST_COALESCING        10
+#define T3_QID_MAC_TX                 11
+#define T3_QID_MBUF_CLUSTER_FREE      12
+#define T3_QID_RX_BD_COMP             13
+#define T3_QID_RX_LIST_PLM            14
+#define T3_QID_RX_DATA_BD_INITIATOR   15
+#define T3_QID_RX_DATA_COMP           16
+#define T3_QID_SW_TYPE2               17
+
+LM_STATUS LM_LoadFirmware(PLM_DEVICE_BLOCK pDevice,
+                          PT3_FWIMG_INFO pFwImg,
+                          LM_UINT32 LoadCpu,
+                          LM_UINT32 StartCpu);
+
+/******************************************************************************/
+/* NIC register read/write macros. */
+/******************************************************************************/
+
+#if 0  /* Jimmy */
+/* MAC register access. */
+LM_UINT32 LM_RegRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register);
+LM_VOID LM_RegWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register,
+    LM_UINT32 Value32);
+
+/* MAC memory access. */
+LM_UINT32 LM_MemRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr);
+LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
+    LM_UINT32 Value32);
+
+#if PCIX_TARGET_WORKAROUND
+
+/* use memory-mapped accesses for mailboxes and reads, UNDI accesses
+   for writes to all other registers */
+#define REG_RD(pDevice, OffsetName)                              \
+    readl(&((pDevice)->pMemView->OffsetName))
+
+#define REG_WR(pDevice, OffsetName, Value32)                     \
+    (((OFFSETOF(T3_STD_MEM_MAP, OffsetName) >=0x200 ) &&         \
+      (OFFSETOF(T3_STD_MEM_MAP, OffsetName) <0x400)) ||                 \
+        ((pDevice)->EnablePciXFix == FALSE)) ?                  \
+    (void) writel(Value32, &((pDevice)->pMemView->OffsetName)) : \
+    LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32)
+
+#define MB_REG_RD(pDevice, OffsetName)                           \
+    readl(&((pDevice)->pMemView->OffsetName))
+
+#define MB_REG_WR(pDevice, OffsetName, Value32)                  \
+    writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#define REG_RD_OFFSET(pDevice, Offset)                           \
+    readl(&((LM_UINT8 *) (pDevice)->pMemView + Offset))
+
+#define REG_WR_OFFSET(pDevice, Offset, Value32)                  \
+       (((Offset >=0x200 ) && (Offset < 0x400)) ||              \
+        ((pDevice)->EnablePciXFix == FALSE)) ?                  \
+    (void) writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset)) : \
+    LM_RegWrInd(pDevice, Offset, Value32)
+
+#define MEM_RD(pDevice, AddrName)                                \
+    LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName))
+#define MEM_WR(pDevice, AddrName, Value32)                       \
+    LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32)
+
+#define MEM_RD_OFFSET(pDevice, Offset)                           \
+    LM_MemRdInd(pDevice, Offset)
+#define MEM_WR_OFFSET(pDevice, Offset, Value32)                  \
+    LM_MemWrInd(pDevice, Offset, Value32)
+
+#else /* normal target access path below */
+
+/* Register access. */
+#define REG_RD(pDevice, OffsetName)                                         \
+    readl(&((pDevice)->pMemView->OffsetName))
+#define REG_WR(pDevice, OffsetName, Value32)                                \
+    writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#define REG_RD_OFFSET(pDevice, Offset)                                      \
+    readl(((LM_UINT8 *) (pDevice)->pMemView + Offset))
+#define REG_WR_OFFSET(pDevice, Offset, Value32)                             \
+    writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset))
+
+
+/* There could be problem access the memory window directly.  For now, */
+/* we have to go through the PCI configuration register. */
+#define MEM_RD(pDevice, AddrName)                                           \
+    LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName))
+#define MEM_WR(pDevice, AddrName, Value32)                                  \
+    LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32)
+
+#define MEM_RD_OFFSET(pDevice, Offset)                                      \
+    LM_MemRdInd(pDevice, Offset)
+#define MEM_WR_OFFSET(pDevice, Offset, Value32)                             \
+    LM_MemWrInd(pDevice, Offset, Value32)
+
+#endif  /* PCIX_TARGET_WORKAROUND */
+
+#endif  /* Jimmy, merging */
+
+  /* Jimmy...rest of file is new stuff! */
+/******************************************************************************/
+/* NIC register read/write macros. */
+/******************************************************************************/
+
+/* MAC register access. */
+LM_UINT32 LM_RegRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register);
+LM_VOID LM_RegWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register,
+    LM_UINT32 Value32);
+
+/* MAC memory access. */
+LM_UINT32 LM_MemRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr);
+LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
+    LM_UINT32 Value32);
+
+#define MB_REG_WR(pDevice, OffsetName, Value32)                               \
+    ((pDevice)->UndiFix) ?                                                    \
+        LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600,     \
+            Value32) :                                                        \
+        (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#define MB_REG_RD(pDevice, OffsetName)                                        \
+    (((pDevice)->UndiFix) ?                                                   \
+        LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600) :   \
+        __raw_readl(&((pDevice)->pMemView->OffsetName)))
+
+#define REG_RD(pDevice, OffsetName)                                           \
+    (((pDevice)->UndiFix) ?                                                   \
+        LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)) :          \
+        __raw_readl(&((pDevice)->pMemView->OffsetName)))
+
+#if PCIX_TARGET_WORKAROUND
+
+#define REG_WR(pDevice, OffsetName, Value32)                                \
+        ((pDevice)->EnablePciXFix == FALSE) ?                              \
+    (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) :      \
+    LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32)
+
+#else
+
+#define REG_WR(pDevice, OffsetName, Value32)                                \
+    __raw_writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#endif
+
+#define MEM_RD(pDevice, AddrName)                                           \
+    LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName))
+#define MEM_WR(pDevice, AddrName, Value32)                                  \
+    LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32)
+
+#define MEM_RD_OFFSET(pDevice, Offset)                                      \
+    LM_MemRdInd(pDevice, Offset)
+#define MEM_WR_OFFSET(pDevice, Offset, Value32)                             \
+    LM_MemWrInd(pDevice, Offset, Value32)
+
+#endif /* TIGON3_H */
+
diff --git a/dtt/ds1621.c b/dtt/ds1621.c
new file mode 100644 (file)
index 0000000..5c25f64
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * (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
+ */
+
+/*
+ * Dallas Semiconductor's DS1621 Digital Thermometer and Thermostat.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DTT_DS1621
+#if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \
+        (CFG_EEPROM_PAGE_WRITE_BITS < 1)
+# error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than 1 to use CONFIG_DTT_DS1621"
+#endif
+#include <i2c.h>
+#include <dtt.h>
+
+/*
+ * Device code
+ */
+#define DTT_I2C_DEV_CODE 0x48                  /* Dallas Semi's DS1621 */
+
+int dtt_read(int sensor, int reg)
+{
+    int dlen;
+    uchar data[2];
+
+    /*
+     * Calculate sensor address and command.
+     *
+     */
+    sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* Calculate addr of ds1621*/
+
+    /*
+     * Prepare to handle 2 byte result.
+     */
+    if ((reg == DTT_READ_TEMP) ||
+       (reg == DTT_TEMP_HIGH) || (reg == DTT_TEMP_LOW))
+       dlen = 2;
+    else
+       dlen = 1;
+
+    /*
+     * Now try to read the register.
+     */
+    if (i2c_read(sensor, reg, 1, data, dlen) != 0)
+       return 1;
+
+    /*
+     * Handle 2 byte result.
+     */
+    if (dlen == 2)
+       return ((int)((short)data[1] + (((short)data[0]) << 8)));
+
+    return (int)data[0];
+} /* dtt_read() */
+
+
+int dtt_write(int sensor, int reg, int val)
+{
+    int dlen;
+    uchar data[2];
+
+    /*
+     * Calculate sensor address and register.
+     *
+     */
+    sensor = DTT_I2C_DEV_CODE + (sensor & sensor);
+
+    /*
+     * Handle various data sizes.
+     */
+    if ((reg == DTT_READ_TEMP) ||
+       (reg == DTT_TEMP_HIGH) || (reg == DTT_TEMP_LOW)) {
+       dlen = 2;
+       data[0] = (char)((val >> 8) & 0xff);    /* MSB first */
+       data[1] = (char)(val & 0xff);
+    }
+    else if ((reg == DTT_WRITE_START_CONV) || (reg == DTT_WRITE_STOP_CONV)) {
+       dlen = 0;
+       data[0] = (char)0;
+       data[1] = (char)0;
+    }
+    else {
+       dlen = 1;
+       data[0] = (char)(val & 0xff);
+    }
+
+    /*
+     * Write value to device.
+     */
+    if (i2c_write(sensor, reg, 1, data, dlen) != 0)
+       return 1;
+
+    return 0;
+} /* dtt_write() */
+
+
+static int _dtt_init(int sensor)
+{
+    int val;
+
+    /*
+     * Setup High Temp.
+     */
+    val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80;
+    if (dtt_write(sensor, DTT_TEMP_HIGH, val) != 0)
+       return 1;
+    udelay(50000);                             /* Max 50ms */
+
+    /*
+     * Setup Low Temp - hysteresis.
+     */
+    val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80;
+    if (dtt_write(sensor, DTT_TEMP_LOW, val) != 0)
+       return 1;
+    udelay(50000);                             /* Max 50ms */
+
+    /*
+     * Setup configuraton register
+     *
+     * Clear THF & TLF, Reserved = 1, Polarity = Active Low, One Shot = YES
+     *
+     * We run in polled mode, since there isn't any way to know if this
+     * lousy device is ready to provide temperature readings on power up.
+     */
+    val = 0x9;
+    if (dtt_write(sensor, DTT_CONFIG, val) != 0)
+       return 1;
+    udelay(50000);                             /* Max 50ms */
+
+    return 0;
+} /* _dtt_init() */
+
+
+int dtt_init (void)
+{
+    int i;
+    unsigned char sensors[] = CONFIG_DTT_SENSORS;
+
+    for (i = 0; i < sizeof(sensors); i++) {
+       if (_dtt_init(sensors[i]) != 0)
+           printf("DTT%d:  FAILED\n", i+1);
+       else
+           printf("DTT%d:  %i C\n", i+1, dtt_get_temp(sensors[i]));
+    }
+
+    return (0);
+} /* dtt_init() */
+
+
+int dtt_get_temp(int sensor)
+{
+    int i;
+
+    /*
+     * Start a conversion, may take up to 1 second.
+     */
+    dtt_write(sensor, DTT_WRITE_START_CONV, 0);
+    for (i = 0; i <= 10; i++) {
+       udelay(100000);
+       if (dtt_read(sensor, DTT_CONFIG) & 0x80)
+           break;
+    }
+
+    return (dtt_read(sensor, DTT_READ_TEMP) / 256);
+} /* dtt_get_temp() */
+
+
+#endif /* CONFIG_DTT_DS1621 */
+
diff --git a/dtt/lm75.c b/dtt/lm75.c
new file mode 100644 (file)
index 0000000..9930a8b
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * (C) Copyright 2001
+ * Bill Hunter,  Wave 7 Optics, williamhunter@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
+ */
+
+/*
+ * On Semiconductor's LM75 Temperature Sensor
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DTT_LM75
+#if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \
+       (CFG_EEPROM_PAGE_WRITE_BITS < 1)
+# error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than  1 to use CONFIG_DTT_LM75"
+#endif
+
+#include <i2c.h>
+#include <dtt.h>
+
+
+/*
+ * Device code
+ */
+#define DTT_I2C_DEV_CODE 0x48                  /* ON Semi's LM75 device */
+
+int dtt_read(int sensor, int reg)
+{
+    int dlen;
+    uchar data[2];
+
+    /*
+     * Validate 'reg' param
+     */
+    if((reg < 0) || (reg > 3))
+       return -1;
+
+    /*
+     * Calculate sensor address and register.
+     */
+    sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */
+
+    /*
+     * Prepare to handle 2 byte result.
+     */
+    if ((reg == DTT_READ_TEMP) ||
+       (reg == DTT_TEMP_HYST) ||
+       (reg == DTT_TEMP_SET))
+       dlen = 2;
+    else
+       dlen = 1;
+
+    /*
+     * Now try to read the register.
+     */
+    if (i2c_read(sensor, reg, 1, data, dlen) != 0)
+       return -1;
+
+    /*
+     * Handle 2 byte result.
+     */
+    if (dlen == 2)
+       return ((int)((short)data[1] + (((short)data[0]) << 8)));
+
+
+    return (int)data[0];
+} /* dtt_read() */
+
+
+int dtt_write(int sensor, int reg, int val)
+{
+    int dlen;
+    uchar data[2];
+
+    /*
+     * Validate 'reg' param
+     */
+    if ((reg < 0) || (reg > 3))
+       return 1;
+
+    /*
+     * Calculate sensor address and register.
+     */
+    sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */
+
+    /*
+     * Handle 2 byte values.
+     */
+    if ((reg == DTT_READ_TEMP) ||
+       (reg == DTT_TEMP_HYST) ||
+       (reg == DTT_TEMP_SET)) {
+       dlen = 2;
+       data[0] = (char)((val >> 8) & 0xff);    /* MSB first */
+       data[1] = (char)(val & 0xff);
+    } else {
+       dlen = 1;
+       data[0] = (char)(val & 0xff);
+    }
+
+    /*
+     * Write value to register.
+     */
+    if (i2c_write(sensor, reg, 1, data, dlen) != 0)
+       return 1;
+
+    return 0;
+} /* dtt_write() */
+
+
+static int _dtt_init(int sensor)
+{
+    int val;
+
+    /*
+     * Setup TSET ( trip point ) register
+     */
+    val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80; /* trip */
+    if (dtt_write(sensor, DTT_TEMP_SET, val) != 0)
+       return 1;
+
+    /*
+     * Setup THYST ( untrip point ) register - Hysteresis
+     */
+    val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80;
+    if (dtt_write(sensor, DTT_TEMP_HYST, val) != 0)
+       return 1;
+
+    /*
+     * Setup configuraton register
+     */
+    /* config = 6 sample integration, int mode, active low, and enable */
+    val = 0x18;
+    if (dtt_write(sensor, DTT_CONFIG, val) != 0)
+       return 1;
+
+    return 0;
+} /* _dtt_init() */
+
+
+int dtt_init (void)
+{
+    int i;
+    unsigned char sensors[] = CONFIG_DTT_SENSORS;
+    const char *const header = "DTT:   ";
+
+    for (i = 0; i < sizeof(sensors); i++) {
+       if (_dtt_init(sensors[i]) != 0)
+           printf("%s%d FAILED INIT\n", header, i+1);
+       else
+           printf("%s%d is %i C\n", header, i+1,
+                  dtt_get_temp(sensors[i]));
+    }
+
+    return (0);
+} /* dtt_init() */
+
+int dtt_get_temp(int sensor)
+{
+    return (dtt_read(sensor, DTT_READ_TEMP) / 256);
+} /* dtt_get_temp() */
+
+#endif /* CONFIG_DTT_LM75 */
+
diff --git a/include/altera.h b/include/altera.h
new file mode 100644 (file)
index 0000000..88f72db
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.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 <fpga.h>
+
+#ifndef _ALTERA_H_
+#define _ALTERA_H_
+
+/*
+ * Note that this is just  Altera FPGA interface boilerplate.
+ * There is no support for Altera devices yet.
+ *
+ * See include/xilinx.h for a working example.
+ */
+
+/* In your board's config.h file you should define CONFIG_FPGA as such:
+ *     #define CONFIG_FPGA     (CFG_ALTERA_xxx | CFG_ALTERA_IF_xxx )
+ */
+
+/* Altera Model definitions */
+#define CFG_ALTERA_xxxx                ( CFG_FPGA_ALTERA | CFG_FPGA_DEV( 0x1 ))
+/* Add new models here */
+
+/* Altera Interface definitions */
+#define CFG_ALTERA_IF_xxx              CFG_FPGA_IF( 0x1 )
+/* Add new interfaces here */
+
+typedef enum {                     /* typedef Altera_iface */
+    min_altera_iface_type,        /* insert all new types after this */
+/* Add new interfaces here */
+    max_altera_iface_type         /* insert all new types before this */
+} Altera_iface;                   /* end, typedef Altera_iface */
+
+typedef enum {                     /* typedef Altera_Family */
+    min_altera_type,              /* insert all new types after this */
+/* Add new models here */
+    max_altera_type               /* insert all new types before this */
+} Altera_Family;                  /* end, typedef Altera_Family */
+
+typedef struct {                   /* typedef Altera_desc */
+    Altera_Family    family;      /* part type */
+    Altera_iface     iface;       /* interface type */
+    size_t            size;        /* bytes of data part can accept */
+    void *            base;        /* base interface address */
+} Altera_desc;                    /* end, typedef Altera_desc */
+
+extern int altera_load( Altera_desc *desc, void *image, size_t size );
+extern int altera_dump( Altera_desc *desc, void *buf, size_t bsize );
+extern int altera_info( Altera_desc *desc );
+extern int altera_reloc( Altera_desc *desc, ulong reloc_off );
+
+#endif  /* _ALTERA_H_ */
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
new file mode 100644 (file)
index 0000000..4733858
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright 1995, Russell King.
+ * Various bits and pieces copyrights include:
+ *  Linus Torvalds (test_bit).
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ *
+ * Please note that the code in this file should never be included
+ * from user space.  Many of these are not implemented in assembler
+ * since they would be too costly.  Also, they require priviledged
+ * instructions (which are not available from user mode) to ensure
+ * that they are atomic.
+ */
+
+#ifndef __ASM_ARM_BITOPS_H
+#define __ASM_ARM_BITOPS_H
+
+#ifdef __KERNEL__
+
+#define smp_mb__before_clear_bit()     do { } while (0)
+#define smp_mb__after_clear_bit()      do { } while (0)
+
+/*
+ * Function prototypes to keep gcc -Wall happy.
+ */
+extern void set_bit(int nr, volatile void * addr);
+
+static inline void __set_bit(int nr, volatile void *addr)
+{
+       ((unsigned char *) addr)[nr >> 3] |= (1U << (nr & 7));
+}
+
+extern void clear_bit(int nr, volatile void * addr);
+
+static inline void __clear_bit(int nr, volatile void *addr)
+{
+       ((unsigned char *) addr)[nr >> 3] &= ~(1U << (nr & 7));
+}
+
+extern void change_bit(int nr, volatile void * addr);
+
+static inline void __change_bit(int nr, volatile void *addr)
+{
+       ((unsigned char *) addr)[nr >> 3] ^= (1U << (nr & 7));
+}
+
+extern int test_and_set_bit(int nr, volatile void * addr);
+
+static inline int __test_and_set_bit(int nr, volatile void *addr)
+{
+       unsigned int mask = 1 << (nr & 7);
+       unsigned int oldval;
+
+       oldval = ((unsigned char *) addr)[nr >> 3];
+       ((unsigned char *) addr)[nr >> 3] = oldval | mask;
+       return oldval & mask;
+}
+
+extern int test_and_clear_bit(int nr, volatile void * addr);
+
+static inline int __test_and_clear_bit(int nr, volatile void *addr)
+{
+       unsigned int mask = 1 << (nr & 7);
+       unsigned int oldval;
+
+       oldval = ((unsigned char *) addr)[nr >> 3];
+       ((unsigned char *) addr)[nr >> 3] = oldval & ~mask;
+       return oldval & mask;
+}
+
+extern int test_and_change_bit(int nr, volatile void * addr);
+
+static inline int __test_and_change_bit(int nr, volatile void *addr)
+{
+       unsigned int mask = 1 << (nr & 7);
+       unsigned int oldval;
+
+       oldval = ((unsigned char *) addr)[nr >> 3];
+       ((unsigned char *) addr)[nr >> 3] = oldval ^ mask;
+       return oldval & mask;
+}
+
+extern int find_first_zero_bit(void * addr, unsigned size);
+extern int find_next_zero_bit(void * addr, int size, int offset);
+
+/*
+ * This routine doesn't need to be atomic.
+ */
+static inline int test_bit(int nr, const void * addr)
+{
+    return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7));
+}
+
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+static inline unsigned long ffz(unsigned long word)
+{
+       int k;
+
+       word = ~word;
+       k = 31;
+       if (word & 0x0000ffff) { k -= 16; word <<= 16; }
+       if (word & 0x00ff0000) { k -= 8;  word <<= 8;  }
+       if (word & 0x0f000000) { k -= 4;  word <<= 4;  }
+       if (word & 0x30000000) { k -= 2;  word <<= 2;  }
+       if (word & 0x40000000) { k -= 1; }
+        return k;
+}
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+
+#define ffs(x) generic_ffs(x)
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+#define ext2_set_bit                   test_and_set_bit
+#define ext2_clear_bit                 test_and_clear_bit
+#define ext2_test_bit                  test_bit
+#define ext2_find_first_zero_bit       find_first_zero_bit
+#define ext2_find_next_zero_bit                find_next_zero_bit
+
+/* Bitmap functions for the minix filesystem. */
+#define minix_test_and_set_bit(nr,addr)        test_and_set_bit(nr,addr)
+#define minix_set_bit(nr,addr)         set_bit(nr,addr)
+#define minix_test_and_clear_bit(nr,addr)      test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr)                test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size)   find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ARM_BITOPS_H */
diff --git a/include/asm-arm/proc-armv/ptrace.h b/include/asm-arm/proc-armv/ptrace.h
new file mode 100644 (file)
index 0000000..51708b9
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *  linux/include/asm-arm/proc-armv/ptrace.h
+ *
+ *  Copyright (C) 1996-1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_PROC_PTRACE_H
+#define __ASM_PROC_PTRACE_H
+
+#include <linux/config.h>
+
+#define USR26_MODE     0x00
+#define FIQ26_MODE     0x01
+#define IRQ26_MODE     0x02
+#define SVC26_MODE     0x03
+#define USR_MODE       0x10
+#define FIQ_MODE       0x11
+#define IRQ_MODE       0x12
+#define SVC_MODE       0x13
+#define ABT_MODE       0x17
+#define UND_MODE       0x1b
+#define SYSTEM_MODE    0x1f
+#define MODE_MASK      0x1f
+#define T_BIT          0x20
+#define F_BIT          0x40
+#define I_BIT          0x80
+#define CC_V_BIT       (1 << 28)
+#define CC_C_BIT       (1 << 29)
+#define CC_Z_BIT       (1 << 30)
+#define CC_N_BIT       (1 << 31)
+#define PCMASK         0
+
+#ifndef __ASSEMBLY__
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+struct pt_regs {
+       long uregs[18];
+};
+
+#define ARM_cpsr       uregs[16]
+#define ARM_pc         uregs[15]
+#define ARM_lr         uregs[14]
+#define ARM_sp         uregs[13]
+#define ARM_ip         uregs[12]
+#define ARM_fp         uregs[11]
+#define ARM_r10                uregs[10]
+#define ARM_r9         uregs[9]
+#define ARM_r8         uregs[8]
+#define ARM_r7         uregs[7]
+#define ARM_r6         uregs[6]
+#define ARM_r5         uregs[5]
+#define ARM_r4         uregs[4]
+#define ARM_r3         uregs[3]
+#define ARM_r2         uregs[2]
+#define ARM_r1         uregs[1]
+#define ARM_r0         uregs[0]
+#define ARM_ORIG_r0    uregs[17]
+
+#ifdef __KERNEL__
+
+#define user_mode(regs)        \
+       (((regs)->ARM_cpsr & 0xf) == 0)
+
+#ifdef CONFIG_ARM_THUMB
+#define thumb_mode(regs) \
+       (((regs)->ARM_cpsr & T_BIT))
+#else
+#define thumb_mode(regs) (0)
+#endif
+
+#define processor_mode(regs) \
+       ((regs)->ARM_cpsr & MODE_MASK)
+
+#define interrupts_enabled(regs) \
+       (!((regs)->ARM_cpsr & I_BIT))
+
+#define fast_interrupts_enabled(regs) \
+       (!((regs)->ARM_cpsr & F_BIT))
+
+#define condition_codes(regs) \
+       ((regs)->ARM_cpsr & (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT))
+
+/* Are the current registers suitable for user mode?
+ * (used to maintain security in signal handlers)
+ */
+static inline int valid_user_regs(struct pt_regs *regs)
+{
+       if ((regs->ARM_cpsr & 0xf) == 0 &&
+           (regs->ARM_cpsr & (F_BIT|I_BIT)) == 0)
+               return 1;
+
+       /*
+        * Force CPSR to something logical...
+        */
+       regs->ARM_cpsr &= (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT|0x10);
+
+       return 0;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#endif
+
diff --git a/include/asm-arm/u-boot-arm.h b/include/asm-arm/u-boot-arm.h
new file mode 100644 (file)
index 0000000..355b1e4
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@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
+ */
+
+#ifndef _U_BOOT_ARM_H_
+#define _U_BOOT_ARM_H_ 1
+
+/* for the following variables, see start.S */
+extern ulong _armboot_start;   /* code start */
+extern ulong _armboot_end_data;        /* code + data end */
+extern ulong _armboot_end;     /* BSS end */
+extern ulong IRQ_STACK_START;  /* top of IRQ stack */
+extern ulong FIQ_STACK_START;  /* top of FIQ stack */
+extern ulong _armboot_real_end;        /* first usable RAM address */
+
+/* cpu/.../cpu.c */
+int    cpu_init(void);
+int    cleanup_before_linux(void);
+
+/* board/.../... */
+int    board_init(void);
+int    dram_init (void);
+
+/* ------------------------------------------------------------ */
+/* Here is a list of some prototypes which are incompatible to */
+/* the U-Boot implementation                                   */
+/* To be fixed!                                                        */
+/* ------------------------------------------------------------ */
+/* common/cmd_nvedit.c */
+void   setenv          (char *, char *);
+
+/* cpu/.../interrupt.c */
+void   reset_timer_masked      (void);
+ulong  get_timer_masked        (void);
+void   udelay_masked           (unsigned long usec);
+
+#endif /* _U_BOOT_ARM_H_ */
diff --git a/include/asm-arm/u-boot.h b/include/asm-arm/u-boot.h
new file mode 100644 (file)
index 0000000..c3b0e4a
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@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
+ */
+
+#ifndef _U_BOOT_H_
+#define _U_BOOT_H_     1
+
+typedef struct bd_info {
+    int                        bi_baudrate;    /* serial console baudrate */
+    unsigned long      bi_ip_addr;     /* IP Address */
+    unsigned char      bi_enetaddr[6]; /* Ethernet adress */
+    struct environment_s              *bi_env;
+    ulong              bi_arch_number; /* unique id for this board */
+    ulong              bi_boot_params; /* where this board expects params */
+    struct                             /* RAM configuration */
+    {
+       ulong start;
+       ulong size;
+    }                  bi_dram[CONFIG_NR_DRAM_BANKS];
+} bd_t;
+
+#define bi_env_data bi_env->data
+#define bi_env_crc  bi_env->crc
+
+#endif /* _U_BOOT_H_ */
diff --git a/include/cmd_bsp.h b/include/cmd_bsp.h
new file mode 100644 (file)
index 0000000..b39d50b
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * (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
+ */
+
+#ifndef _CMD_BSP_H_
+#define _CMD_BSP_H_
+
+#include <common.h>
+#include <command.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_BSP)
+
+/* ----- LWMON -----------------------------------------------------------------
+ */
+#if defined(CONFIG_LWMON)
+
+#define        CMD_TBL_BSP     MK_CMD_TBL_ENTRY(                                       \
+       "pic",  3,      4,      1,      do_pic,                                 \
+       "pic     - read and write PIC registers\n",                             \
+       "read  reg      - read PIC register `reg'\n"                            \
+       "pic write reg val  - write value `val' to PIC register `reg'\n"        \
+),  MK_CMD_TBL_ENTRY(                                                          \
+       "kbd",  3,      1,      1,      do_kbd,                                 \
+       "kbd     - read keyboard status\n",                                     \
+       NULL                                                                    \
+),  MK_CMD_TBL_ENTRY(                                                          \
+       "lsb",  3,      2,      1,      do_lsb,                                 \
+       "lsb     - check and set LSB switch\n",                                 \
+       "on  - switch LSB on\n"                                                 \
+       "lsb off - switch LSB off\n"                                            \
+       "lsb     - print current setting\n"                                     \
+),
+int do_pic (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_lsb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_LWMON */
+/* ----------------------------------------------------------------------------*/
+
+/* ----- PCU E -----------------------------------------------------------------
+ */
+#if defined(CONFIG_PCU_E)
+
+#define CMD_TBL_BSP    MK_CMD_TBL_ENTRY(                                       \
+       "puma", 4,      4,      1,      do_puma,                                \
+       "puma    - access PUMA FPGA\n",                                         \
+       "status - print PUMA status\n"                                          \
+       "puma load addr len - load PUMA configuration data\n"                   \
+),
+int do_puma (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_PCU_E */
+/* ----------------------------------------------------------------------------*/
+
+/* ----- CCM/SCM ---------------------------------------------------------------
+ */
+#if defined(CONFIG_CCM) || defined(CONFIG_SCM)
+
+#define CMD_TBL_BSP    MK_CMD_TBL_ENTRY(                                       \
+       "fpga", 4,      4,      1,      do_fpga,                                \
+       "fpga    - access FPGA(s)\n",                                           \
+       "fpga status [name] - print FPGA status\n"                              \
+       "fpga reset  [name] - reset FPGA\n"                                     \
+       "fpga load [name] addr - load FPGA configuration data\n"                \
+),
+int do_fpga (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_CCM, CONFIG_SCM */
+/* ----------------------------------------------------------------------------*/
+
+/* ----- PIP405 -----------------------------------------------------------------
+ */
+#if defined(CONFIG_PIP405)
+
+#define        CMD_TBL_BSP MK_CMD_TBL_ENTRY(                           \
+       "pip405",       4,      6,      1,      do_pip405,                      \
+       "pip405  - PIP405 specific Cmds\n",                                     \
+       "flash mem [SrcAddr] - updates U-Boot with image in memory\n"                                   \
+       "pip405 flash floppy [SrcAddr] - updates U-Boot with image from floppy\n"                                       \
+       "pip405 flash mps - updates U-Boot with image from MPS\n"                                       \
+),
+int do_pip405 (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_PIP405 */
+/* ----------------------------------------------------------------------------*/
+/* ----- MIP405 -----------------------------------------------------------------
+ */
+#if defined(CONFIG_MIP405)
+
+#define        CMD_TBL_BSP MK_CMD_TBL_ENTRY(                           \
+       "mip405",       4,      6,      1,      do_mip405,                      \
+       "mip405  - MIP405 specific Cmds\n",                                     \
+       "flash mem [SrcAddr] - updates U-Boot with image in memory\n"                                   \
+       "mip405 flash mps - updates U-Boot with image from MPS\n"                                       \
+),
+int do_mip405 (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_MIP405 */
+/* ----------------------------------------------------------------------------*/
+
+/* ----- DASA_SIM ---------------------------------------------------------------
+ */
+#if defined(CONFIG_DASA_SIM)
+
+#define        CMD_TBL_BSP MK_CMD_TBL_ENTRY(                                           \
+       "pci9054",      7,      3,      1,      do_pci9054,                     \
+       "pci9054 - PLX PCI9054 EEPROM access\n",                                \
+       "pci9054 info - print EEPROM values\n"                                  \
+       "pci9054 update - updates EEPROM with default values\n"                 \
+),
+int do_pci9054 (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_DASA_SIM */
+/* ----------------------------------------------------------------------------*/
+
+/* ----- HYMOD -----------------------------------------------------------------
+ */
+#if defined(CONFIG_HYMOD)
+
+#define        CMD_TBL_BSP     MK_CMD_TBL_ENTRY(                               \
+       "fpga", 4,      6,      1,      do_fpga,                        \
+       "fpga    - FPGA sub-system\n",                                  \
+       "load [type] addr size\n"                                       \
+       "  - write the configuration data at memory address `addr',\n"  \
+       "    size `size' bytes, into the FPGA of type `type' (either\n" \
+       "    `main' or `mezz', default `main'). e.g.\n"                 \
+       "        `fpga load 100000 7d8f'\n"                             \
+       "    loads the main FPGA with config data at address 100000\n"  \
+       "    HEX, size 7d8f HEX (32143 DEC) bytes\n"                    \
+       "fpga tftp file addr\n"                                         \
+       "  - transfers `file' from the tftp server into memory at\n"    \
+       "    address `addr', then writes the entire file contents\n"    \
+       "    into the main FPGA\n"                                      \
+       "fpga store addr\n"                                             \
+       "  - read configuration data from the main FPGA (the mezz\n"    \
+       "    FPGA is write-only), into address `addr'. There must be\n" \
+       "    enough memory available at `addr' to hold all the config\n"\
+       "    data - the size of which is determined by VC:???\n"        \
+       "fpga info\n"                                                   \
+       "  - print information about the Hymod FPGA, namely the\n"      \
+       "    memory addresses at which the four FPGA local bus\n"       \
+       "    address spaces appear in the physical address space\n"     \
+), MK_CMD_TBL_ENTRY(                                                   \
+       "eeclear", 4,   1,      0,      do_eecl,                        \
+       "eeclear - Clear the eeprom on a Hymod board \n",               \
+       "[type]\n"                                                      \
+       "  - write zeroes into the EEPROM on the board of type `type'\n"\
+       "    (`type' is either `main' or `mezz' - default `main')\n"    \
+       "    Note: the EEPROM write enable jumper must be installed\n"  \
+),
+int do_fpga (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_eecl (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_HYMOD */
+/* ----------------------------------------------------------------------------*/
+/* CRAY405 (L1) */
+#if defined (CONFIG_CRAYL1)
+#define        CMD_TBL_BSP MK_CMD_TBL_ENTRY(                                           \
+       "L1cmd",        5,      4,      1,      do_crayL1,                      \
+       "L1cmd  - L1 update, setup, commands \n",                               \
+       "L1cmd update - update flash images from host\n"                        \
+       "L1cmd boot - nfs or ramboot L1\n"                                      \
+),
+int do_crayL1 (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+#endif /* CONFIG_CRAY405 */
+/* ----------------------------------------------------------------------------*/
+
+#if defined (CONFIG_EVB64260)
+/* ----- EVB64260 -------------------------------------------------------------*/
+#ifdef CONFIG_ZUMA_V2
+#define CMD_TBL_BSP  ZUMA_TBL_ENTRY
+
+#define ZUMA_TBL_ENTRY MK_CMD_TBL_ENTRY(                               \
+       "zinit",         5,      1,      0,      do_zuma_init_pbb,      \
+       "zinit   - init zuma pbb\n",                                    \
+       "\n"                                                            \
+       "    - init zuma pbb\n"                                         \
+), MK_CMD_TBL_ENTRY(                                                   \
+       "zdtest",         6,      3,      1,      do_zuma_test_dma,     \
+       "zdtest  - run dma test\n",                                     \
+       "[cmd [count]]\n"                                               \
+       "    - run dma cmd (w=0,v=1,cp=2,cmp=3,wi=4,vi=5), count bytes\n" \
+), MK_CMD_TBL_ENTRY(                                                   \
+       "zminit",         5,      1,      0,      do_zuma_init_mbox,    \
+       "zminit  - init zuma mbox\n",                           \
+       "\n"                                                            \
+       "    - init zuma mbox\n"                                        \
+),
+
+int do_zuma_init_pbb  (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_zuma_test_dma  (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_zuma_init_mbox (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+void zuma_init_pbb(void);
+int zuma_mbox_init(void);
+int zuma_test_dma(int cmd, int size);
+#else
+#define CMD_TBL_BSP
+#endif /* ZUMA_NTL */
+
+#endif /* CONFIG_EVB64260 */
+/* ----------------------------------------------------------------------------*/
+
+/* -----W7O--------------------------------------------------------------------*/
+#if defined(CONFIG_W7O)
+
+#define CMD_TBL_BSP MK_CMD_TBL_ENTRY(                  \
+         "vpd",        3,      2,      1,      do_vpd, \
+         "vpd     - Read Vital Product Data\n",        \
+         "[dev_addr]\n"                                \
+         "        - Read VPD Data from default address, or device address 'dev_addr'.\n" \
+),
+
+extern int do_vpd (cmd_tbl_t *, int, int, char *[]);
+
+#endif /* CONFIG_W7O */
+/* ----------------------------------------------------------------------------*/
+
+/* ---- PCIPPC2 / PCIPPC6 -----------------------------------------------------*/
+#if defined(CONFIG_PCIPPC2) || defined(CONFIG_PCIPPC6)
+#if defined(CONFIG_WATCHDOG)
+
+#define CMD_TBL_BSP MK_CMD_TBL_ENTRY(                  \
+       "wd",   3,      2,      1,      do_wd,                                  \
+       "wd      - check and set watchdog\n",                                   \
+       "on   - switch watchDog on\n"                                                   \
+       "wd off  - switch watchdog off\n"                                               \
+       "wd      - print current status\n"                                      \
+),
+
+extern int do_wd (cmd_tbl_t *, int, int, char *[]);
+
+#else
+#define CMD_TBL_BSP
+#endif  /* CONFIG_WATCHDOG */
+
+#endif /* CONFIG_PCIPPC2 , CONFIG_PCIPPC6 */
+/* ----------------------------------------------------------------------------*/
+
+/* ----- PN62 -----------------------------------------------------------------*/
+#if defined(CONFIG_PN62)
+
+#define CMD_TBL_BSP MK_CMD_TBL_ENTRY(                          \
+       "loadpci",      5,      2,      1,      do_loadpci,     \
+       "loadpci - load binary file over PCI\n",                \
+       "[addr]\n"                                              \
+       "    - load binary file over PCI to address 'addr'\n"   \
+), MK_CMD_TBL_ENTRY(                                           \
+       "led"    ,      3,      3,      1,      do_led,         \
+       "led     - set LED 0..11 on the PN62 board\n",          \
+       "i fun\n"                                               \
+       "    - set 'i'th LED to function 'fun'\n"               \
+),
+
+extern int do_loadpci (cmd_tbl_t *, int, int, char *[]);
+extern int do_led (cmd_tbl_t *, int, int, char *[]);
+#endif /* CONFIG_PN62 */
+/* ----------------------------------------------------------------------------*/
+
+/* ----- TRAB ------------------------------------------------------------------
+ */
+#if defined(CONFIG_TRAB)
+
+#define        CMD_TBL_BSP     MK_CMD_TBL_ENTRY(                                       \
+       "kbd",  3,      1,      1,      do_kbd,                                 \
+       "kbd     - read keyboard status\n",                                     \
+       NULL                                                                    \
+),
+
+int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_TRAB */
+/* ----------------------------------------------------------------------------*/
+
+#else
+#define CMD_TBL_BSP
+#endif /* CFG_CMD_BSP */
+
+/* ----- R360MPI ---------------------------------------------------------------
+ */
+#if defined(CONFIG_R360MPI)
+
+#define        CMD_TBL_BSP     MK_CMD_TBL_ENTRY(                                       \
+       "kbd",  3,      1,      1,      do_kbd,                                 \
+       "kbd     - read keyboard status\n",                                     \
+       NULL                                                                    \
+),
+
+int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_R360MPI */
+/* ----------------------------------------------------------------------------*/
+
+#endif /* _CMD_BSP_H_ */
diff --git a/include/configs/BMW.h b/include/configs/BMW.h
new file mode 100644 (file)
index 0000000..edfd68f
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * (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
+ */
+
+/*
+ *
+ * Configuration settings for the CU824 board.
+ *
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC824X         1
+#define CONFIG_MPC8245         1
+#define CONFIG_BMW             1
+
+#define CONFIG_BCM570x         1 /* Use Broadcom BCM570x Ethernet Driver */
+#define        CONFIG_TIGON3           1
+
+#define CONFIG_CONS_INDEX      1
+#define CONFIG_BAUDRATE                9600
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_CLOCKS_IN_MHZ   1       /* clocks passsed to Linux in MHz       */
+
+#define CONFIG_BOOTCOMMAND     "bootm FF820000"        /* autoboot command     */
+#define CONFIG_BOOTDELAY       5
+
+#define CFG_MAX_DOC_DEVICE      1 /* Only use Onboard TSOP-16MB device */
+#define DOC_PASSIVE_PROBE       1
+#define CFG_DOC_SUPPORT_2000    1
+#define CFG_DOC_SUPPORT_MILLENNIUM 1
+#define CFG_DOC_SHORT_TIMEOUT    1
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | \
+                               CFG_CMD_DATE    | \
+                               CFG_CMD_DOC     | \
+                               CFG_CMD_ELF     | \
+                               0 )
+#if 0
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | CFG_CMD_DHCP | \
+                                CFG_CMD_PCI | CFG_CMD_DOC | CFG_CMD_DATE)
+
+#define CONFIG_PCI             1
+#define CONFIG_PCI_PNP         1       /* PCI plug-and-play */
+#endif
+
+/* This must be included AFTER the definition of CONFIG_COMMANDS (if any)
+ */
+#include <cmd_confdefs.h>
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=>"            /* Monitor Command Prompt       */
+#define CFG_CBSIZE     256             /* Console I/O Buffer Size      */
+
+/* Print Buffer Size
+ */
+#define CFG_PBSIZE     (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)
+
+#define CFG_MAXARGS    8               /* Max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR  0x00100000      /* Default load address         */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE     0x00000000
+
+#define CFG_FLASH_BASE0_PRELIM      0xFFF00000      /* FLASH bank on RCS#0 */
+#define CFG_FLASH_BASE1_PRELIM      0xFF800000      /* FLASH bank on RCS#1 */
+#define CFG_FLASH_BASE  CFG_MONITOR_BASE
+#define CFG_FLASH_BANKS                { CFG_FLASH_BASE0_PRELIM , CFG_FLASH_BASE1_PRELIM }
+
+/* even though FLASHP_BASE is FF800000, with 4MB is RCS0, the
+ * reset vector is actually located at FFB00100, but the 8245
+ * takes care of us.
+ */
+#define CFG_RESET_ADDRESS   0xFFF00100
+
+#define CFG_EUMB_ADDR      0xFC000000
+
+#define CFG_MONITOR_BASE    TEXT_BASE
+
+#define CFG_MONITOR_LEN            (256 << 10) /* Reserve 256 kB for Monitor   */
+#define CFG_MALLOC_LEN     (2048 << 10) /* Reserve 2MB for malloc()    */
+
+#define CFG_MEMTEST_START   0x00004000 /* memtest works on             */
+#define CFG_MEMTEST_END            0x04000000  /* 0 ... 32 MB in DRAM          */
+
+       /* Maximum amount of RAM.
+        */
+#define CFG_MAX_RAM_SIZE    0x04000000 /* 0 .. 64 MB of (S)DRAM */
+
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+#undef CFG_RAMBOOT
+#else
+#define CFG_RAMBOOT
+#endif
+
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area
+ */
+#define CFG_INIT_RAM_ADDR CFG_SDRAM_BASE + CFG_MONITOR_LEN
+#define CFG_INIT_RAM_END   0x2F00  /* End of used area in DPRAM  */
+#define CFG_GBL_DATA_SIZE  128  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET  (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET  CFG_GBL_DATA_OFFSET
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ * For the detail description refer to the MPC8240 user's manual.
+ */
+
+#define CONFIG_SYS_CLK_FREQ  33000000  /* external frequency to pll */
+#define CFG_HZ              1000
+
+#define CFG_ETH_DEV_FN      0x7800
+#define CFG_ETH_IOBASE      0x00104000
+
+       /* Bit-field values for MCCR1.
+        */
+#define CFG_ROMNAL         0xf
+#define CFG_ROMFAL         0x1f
+#define CFG_DBUS_SIZE       0x3
+
+       /* Bit-field values for MCCR2.
+        */
+#define CFG_TSWAIT         0x5             /* Transaction Start Wait States timer */
+#define CFG_REFINT         0x400           /* Refresh interval FIXME: was 0t430                */
+
+       /* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4.
+        */
+#define CFG_BSTOPRE        0           /* FIXME: was 192 */
+
+       /* Bit-field values for MCCR3.
+        */
+#define CFG_REFREC         2       /* Refresh to activate interval */
+
+       /* Bit-field values for MCCR4.
+        */
+#define CFG_PRETOACT       2       /* Precharge to activate interval FIXME: was 2      */
+#define CFG_ACTTOPRE       5       /* Activate to Precharge interval FIXME: was 5      */
+#define CFG_SDMODE_CAS_LAT  3      /* SDMODE CAS latancy */
+#define CFG_SDMODE_WRAP            0       /* SDMODE wrap type */
+#define CFG_SDMODE_BURSTLEN 3      /* SDMODE Burst length */
+#define CFG_ACTORW         0xa         /* FIXME was 2 */
+#define CFG_REGISTERD_TYPE_BUFFER 1
+
+#define CFG_PGMAX           0x0 /* how long the 8240 reatins the currently accessed page in memory FIXME: was 0x32*/
+
+#define CFG_SDRAM_DSCD 0x20    /* SDRAM data in sample clock delay - note bottom 3 bits MUST be 0 */
+
+/* Memory bank settings.
+ * Only bits 20-29 are actually used from these vales to set the
+ * start/end addresses. The upper two bits will always be 0, and the lower
+ * 20 bits will be 0x00000 for a start address, or 0xfffff for an end
+ * address. Refer to the MPC8240 book.
+ */
+
+#define CFG_BANK0_START            0x00000000
+#define CFG_BANK0_END      (CFG_MAX_RAM_SIZE - 1)
+#define CFG_BANK0_ENABLE    1
+#define CFG_BANK1_START            0x3ff00000
+#define CFG_BANK1_END      0x3fffffff
+#define CFG_BANK1_ENABLE    0
+#define CFG_BANK2_START            0x3ff00000
+#define CFG_BANK2_END      0x3fffffff
+#define CFG_BANK2_ENABLE    0
+#define CFG_BANK3_START            0x3ff00000
+#define CFG_BANK3_END      0x3fffffff
+#define CFG_BANK3_ENABLE    0
+#define CFG_BANK4_START            0x3ff00000
+#define CFG_BANK4_END      0x3fffffff
+#define CFG_BANK4_ENABLE    0
+#define CFG_BANK5_START            0x3ff00000
+#define CFG_BANK5_END      0x3fffffff
+#define CFG_BANK5_ENABLE    0
+#define CFG_BANK6_START            0x3ff00000
+#define CFG_BANK6_END      0x3fffffff
+#define CFG_BANK6_ENABLE    0
+#define CFG_BANK7_START            0x3ff00000
+#define CFG_BANK7_END      0x3fffffff
+#define CFG_BANK7_ENABLE    0
+
+#define CFG_ODCR           0xff
+
+#define CONFIG_PCI              1 /* Include PCI support */
+#undef CONFIG_PCI_PNP
+
+/* PCI Memory space(s) */
+#define PCI_MEM_SPACE1_START   0x80000000
+#define PCI_MEM_SPACE2_START   0xfd000000
+
+/* ROM Spaces */
+#include "../board/bmw/bmw.h"
+
+/* BAT configuration */
+#define CFG_IBAT0L  (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U  (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT1L  (0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT1U  (0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT2L  (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U  (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT3L  (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U  (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L  CFG_IBAT0L
+#define CFG_DBAT0U  CFG_IBAT0U
+#define CFG_DBAT1L  CFG_IBAT1L
+#define CFG_DBAT1U  CFG_IBAT1U
+#define CFG_DBAT2L  CFG_IBAT2L
+#define CFG_DBAT2U  CFG_IBAT2U
+#define CFG_DBAT3L  CFG_IBAT3L
+#define CFG_DBAT3U  CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ      (8 << 20)   /* Initial Memory map for Linux */
+
+/*
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    0       /* Max number of flash banks        */
+#define CFG_MAX_FLASH_SECT     64      /* Max number of sectors per  flash */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms) */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms) */
+
+/*
+ * Warining: environment is not EMBEDDED in the U-Boot code.
+ * It's stored in flash separately.
+ */
+#define CFG_ENV_IS_IN_NVRAM      1
+#define CONFIG_ENV_OVERWRITE     1
+#define CFG_NVRAM_ACCESS_ROUTINE 1
+#define CFG_ENV_ADDR           0x7c004000 /* right at the start of NVRAM  */
+#define CFG_ENV_SIZE           0x1ff0  /* Size of the Environment - 8K    */
+#define CFG_ENV_OFFSET         0       /* starting right at the beginning */
+
+/*
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#  define CFG_CACHELINE_SHIFT  5       /* log base 2 of the above value   */
+#endif
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                  */
+
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/CCM.h b/include/configs/CCM.h
new file mode 100644 (file)
index 0000000..0e0248d
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * (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
+ */
+
+/*
+ * configuration options, board specific, for Siemens Card Controller Module
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#undef CCM_80MHz                       /* define for 80 MHz CPU only */
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC860           1   /* This is a MPC860 CPU ... */
+#define CONFIG_CCM              1   /* on a Card Controller Module  */
+
+#define CONFIG_8xx_CONS_SMC1    1   /* Console is on SMC1       */
+#undef  CONFIG_8xx_CONS_SMC2
+#undef  CONFIG_8xx_CONS_NONE
+
+/*  ENVIRONMENT */
+
+#define CONFIG_BAUDRATE         19200         /* console baudrate in bps    */
+#define CONFIG_BOOTDELAY        2             /* autoboot after 2 seconds   */
+#define CONFIG_CLOCKS_IN_MHZ    1             /* clocks passsed to Linux in MHz */
+
+#define CONFIG_IPADDR           192.168.0.42
+#define CONFIG_NETMASK          255.255.255.0
+#define CONFIG_GATEWAYIP        0.0.0.0
+#define CONFIG_SERVERIP         192.168.0.254
+
+#define CONFIG_HOSTNAME         CCM
+
+#define CONFIG_LOADADDR         40180000
+
+#undef CONFIG_BOOTARGS
+
+#define CONFIG_BOOTCOMMAND      "setenv bootargs " \
+                                "mem=$(mem) " \
+                                "root=/dev/ram rw ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off " \
+                                "wt_8xx=timeout:3600; " \
+                                "bootm"
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#undef CFG_LOADS_BAUD_CHANGE   /* don't allow baudrate change  */
+
+#define        CONFIG_WATCHDOG         1       /* watchdog enabled             */
+
+#undef CONFIG_STATUS_LED               /* Status LED disabled          */
+
+#define        CONFIG_PRAM             512     /* reserve 512kB "protected RAM"*/
+
+#define        CONFIG_RTC_MPC8xx               /* use internal RTC of MPC8xx   */
+
+#define        CONFIG_SPI                      /* enable SPI driver            */
+#define        CONFIG_SPI_X                    /* 16 bit EEPROM addressing     */
+
+/* ----------------------------------------------------------------
+ * Offset to initial SPI buffers in DPRAM (used if the environment
+ * is in the SPI EEPROM): We need a 520 byte scratch DPRAM area to
+ * use at an early stage. It is used between the two initialization
+ * calls (spi_init_f() and spi_init_r()). The value 0xB00 makes it
+ * far enough from the start of the data area (as well as from the
+ * stack pointer).
+ * ---------------------------------------------------------------- */
+#define CFG_SPI_INIT_OFFSET            0xB00
+
+#define CFG_EEPROM_PAGE_WRITE_BITS     5       /* 32-byte page size    */
+
+
+#define CONFIG_MAC_PARTITION           /* nod used yet                 */
+#define CONFIG_DOS_PARTITION
+
+#define CONFIG_BOOTP_MASK      (CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_BOOTFILESIZE)
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_DHCP    | \
+                               CFG_CMD_DATE    | \
+                               CFG_CMD_EEPROM  | \
+                               CFG_CMD_BSP     )
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Miscellaneous configurable options
+ */
+#define        CFG_LONGHELP                    /* undef to save memory         */
+#define        CFG_PROMPT      "=> "           /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define        CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define        CFG_MAXARGS     16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x00100000      /* memtest works on     */
+#define CFG_MEMTEST_END                0x00F00000      /* 1 ... 15MB in DRAM   */
+
+#define        CFG_LOAD_ADDR           0x00100000      /* default load address */
+
+/* Ethernet hardware configuration done using port pins */
+#define CFG_PA_ETH_RESET       0x0200          /* PA  6        */
+#define CFG_PA_ETH_MDDIS       0x4000          /* PA  1        */
+#define CFG_PB_ETH_POWERDOWN   0x00000800      /* PB 20        */
+#define CFG_PB_ETH_CFG1                0x00000400      /* PB 21        */
+#define CFG_PB_ETH_CFG2                0x00000200      /* PB 22        */
+#define CFG_PB_ETH_CFG3                0x00000100      /* PB 23        */
+
+/* Ethernet settings:
+ * MDIO not disabled, autonegotiation, 10/100Mbps, half/full duplex
+ */
+#define CFG_ETH_MDDIS_VALUE    0
+#define CFG_ETH_CFG1_VALUE     1
+#define CFG_ETH_CFG2_VALUE     1
+#define CFG_ETH_CFG3_VALUE     1
+
+/* PUMA configuration */
+#define CFG_PC_PUMA_PROG       0x0200          /* PC  6        */
+#define CFG_PC_PUMA_DONE       0x0008          /* PC 12        */
+#define CFG_PC_PUMA_INIT       0x0004          /* PC 13        */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+/*-----------------------------------------------------------------------
+ * Internal Memory Mapped Register
+ */
+#define CFG_IMMR               0xF0000000
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR      CFG_IMMR
+#define        CFG_INIT_RAM_END        0x2F00  /* End of used area in DPRAM    */
+#define        CFG_GBL_DATA_SIZE       64  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define        CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+/*-----------------------------------------------------------------------
+ * Address accessed to reset the board - must not be mapped/assigned
+ */
+#define        CFG_RESET_ADDRESS       0xFEFFFFFF
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define        CFG_SDRAM_BASE          0x00000000
+#define CFG_FLASH_BASE         0x40000000
+#if defined(DEBUG)
+#define        CFG_MONITOR_LEN         (256 << 10)     /* Reserve 256 kB for Monitor   */
+#else
+#define        CFG_MONITOR_LEN         (192 << 10)     /* Reserve 192 kB for Monitor   */
+#endif
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define        CFG_MALLOC_LEN          (128 << 10)     /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define        CFG_BOOTMAPSZ           (8 << 20)       /* Initial Memory map for Linux */
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     67      /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#if 1
+/* Start port with environment in flash; switch to SPI EEPROM later */
+#define        CFG_ENV_IS_IN_FLASH     1
+#define        CFG_ENV_OFFSET          0x8000  /*   Offset   of Environment Sector     */
+#define        CFG_ENV_SIZE            0x4000  /* Total Size of Environment Sector     */
+#else
+/* Final version: environment in EEPROM */
+#define CFG_ENV_IS_IN_EEPROM   1
+#define CFG_ENV_OFFSET         2048
+#define CFG_ENV_SIZE           2048
+#endif
+
+/*-----------------------------------------------------------------------
+ * Hardware Information Block
+ */
+#define CFG_HWINFO_OFFSET      0x0003FFC0      /* offset of HW Info block */
+#define CFG_HWINFO_SIZE                0x00000040      /* size   of HW Info block */
+#define CFG_HWINFO_MAGIC       0x54514D38      /* 'TQM8' */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     16      /* For all MPC8xx CPUs                  */
+#define CFG_CACHELINE_SHIFT    4       /* log base 2 of the above value        */
+
+/*-----------------------------------------------------------------------
+ * SYPCR - System Protection Control                           11-9
+ * SYPCR can only be written once after reset!
+ *-----------------------------------------------------------------------
+ * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze
+ */
+#if defined(CONFIG_WATCHDOG)
+#define CFG_SYPCR      (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \
+                        SYPCR_SWE  | SYPCR_SWRI| SYPCR_SWP)
+#else
+#define CFG_SYPCR      (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP)
+#endif
+
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration                           11-6
+ *-----------------------------------------------------------------------
+ * we must activate GPL5 in the SIUMCR for CAN
+ */
+#define CFG_SIUMCR     (SIUMCR_DBGC11 | SIUMCR_DBPC00 | SIUMCR_MLRC01)
+
+/*-----------------------------------------------------------------------
+ * TBSCR - Time Base Status and Control                                11-26
+ *-----------------------------------------------------------------------
+ * Clear Reference Interrupt Status, Timebase freezing enabled
+ */
+#define CFG_TBSCR      (TBSCR_REFA | TBSCR_REFB | TBSCR_TBF)
+
+/*-----------------------------------------------------------------------
+ * RTCSC - Real-Time Clock Status and Control Register         11-27
+ *-----------------------------------------------------------------------
+ */
+#define CFG_RTCSC      (RTCSC_SEC | RTCSC_ALR | RTCSC_RTF| RTCSC_RTE)
+
+/*-----------------------------------------------------------------------
+ * PISCR - Periodic Interrupt Status and Control               11-31
+ *-----------------------------------------------------------------------
+ * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled
+ */
+#define CFG_PISCR      (PISCR_PS | PISCR_PITF)
+
+/*-----------------------------------------------------------------------
+ * PLPRCR - PLL, Low-Power, and Reset Control Register         15-30
+ *-----------------------------------------------------------------------
+ * Reset PLL lock status sticky bit, timer expired status bit and timer
+ * interrupt status bit
+ *
+ * If this is a 80 MHz CPU, set PLL multiplication factor to 5 (5*16=80)!
+ */
+#ifdef CCM_80MHz       /* for 80 MHz, we use a 16 MHz clock * 5 */
+#define CFG_PLPRCR                                                     \
+               ( (5-1)<<PLPRCR_MF_SHIFT | PLPRCR_TEXPS | PLPRCR_TMIST )
+#else                  /* up to 50 MHz we use a 1:1 clock */
+#define CFG_PLPRCR     (PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST)
+#endif /* CCM_80MHz */
+
+/*-----------------------------------------------------------------------
+ * SCCR - System Clock and reset Control Register              15-27
+ *-----------------------------------------------------------------------
+ * Set clock output, timebase and RTC source and divider,
+ * power management and some other internal clocks
+ */
+#define SCCR_MASK      SCCR_EBDF11
+#ifdef CCM_80MHz       /* for 80 MHz, we use a 16 MHz clock * 5 */
+#define CFG_SCCR       (/* SCCR_TBS  | */ \
+                        SCCR_COM00   | SCCR_DFSYNC00 | SCCR_DFBRG00  | \
+                        SCCR_DFNL000 | SCCR_DFNH000  | SCCR_DFLCD000 | \
+                        SCCR_DFALCD00)
+#else                  /* up to 50 MHz we use a 1:1 clock */
+#define CFG_SCCR       (SCCR_TBS     | \
+                        SCCR_COM00   | SCCR_DFSYNC00 | SCCR_DFBRG00  | \
+                        SCCR_DFNL000 | SCCR_DFNH000  | SCCR_DFLCD000 | \
+                        SCCR_DFALCD00)
+#endif /* CCM_80MHz */
+
+/*-----------------------------------------------------------------------
+ *
+ * Interrupt Levels
+ *-----------------------------------------------------------------------
+ */
+#define CFG_CPM_INTERRUPT      13      /* SIU_LEVEL6   */
+
+/*-----------------------------------------------------------------------
+ *
+ *-----------------------------------------------------------------------
+ *
+ */
+#define CFG_DER        0
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0x40000000      /* FLASH bank #0        */
+#define FLASH_BASE1_PRELIM     0x60000000      /* FLASH bank #0        */
+
+/* used to re-map FLASH both when starting from SRAM or FLASH:
+ * restrict access enough to keep SRAM working (if any)
+ * but not too much to meddle with FLASH accesses
+ */
+#define CFG_REMAP_OR_AM                0x80000000      /* OR addr mask */
+#define CFG_PRELIM_OR_AM       0xE0000000      /* OR addr mask */
+
+/* FLASH timing: ACS = 11, TRLX = 0, CSNT = 1, SCY = 5, EHTR = 1       */
+#define CFG_OR_TIMING_FLASH    (OR_CSNT_SAM  | OR_ACS_DIV2 | OR_BI | \
+                                OR_SCY_5_CLK | OR_EHTR)
+
+#define CFG_OR0_REMAP  (CFG_REMAP_OR_AM  | CFG_OR_TIMING_FLASH)
+#define CFG_OR0_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_FLASH)
+#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_V )
+
+#define CFG_OR1_REMAP  CFG_OR0_REMAP
+#define CFG_OR1_PRELIM CFG_OR0_PRELIM
+#define CFG_BR1_PRELIM ((FLASH_BASE1_PRELIM & BR_BA_MSK) | BR_V )
+
+/*
+ * BR2 and OR2 (SDRAM)
+ *
+ */
+#define SDRAM_BASE2_PRELIM     0x00000000      /* SDRAM bank #0        */
+#define SDRAM_BASE3_PRELIM     0x20000000      /* SDRAM bank #1        */
+#define        SDRAM_MAX_SIZE          0x04000000      /* max 64 MB per bank   */
+
+/* SDRAM timing: Multiplexed addresses, GPL5 output to GPL5_A (don't care)     */
+#define CFG_OR_TIMING_SDRAM    0x00000A00
+
+#define CFG_OR2_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_SDRAM )
+#define CFG_BR2_PRELIM ((SDRAM_BASE2_PRELIM & BR_BA_MSK) | BR_MS_UPMA | BR_V )
+
+/*
+ * BR3 and OR3 (CAN Controller)
+ */
+#define        CFG_CAN_BASE            0xC0000000      /* CAN mapped at 0xC0000000     */
+#define CFG_CAN_OR_AM          0xFFFF8000      /* 32 kB address mask           */
+#define CFG_OR3_CAN            (CFG_CAN_OR_AM | OR_G5LA | OR_BI)
+#define CFG_BR3_CAN            ((CFG_CAN_BASE & BR_BA_MSK) | \
+                                       BR_PS_8 | BR_MS_UPMB | BR_V )
+
+/*
+ * BR4/OR4: PUMA Config
+ *
+ * Memory controller will be used in 2 modes:
+ *
+ * - "read" mode:
+ *     BR4: 0x10100801         OR4: 0xffff8520
+ * - "load" mode (chip select on UPM B):
+ *     BR4: 0x101004c1         OR4: 0xffff8600
+ *
+ * Default initialization is in "read" mode
+ */
+#define PUMA_CONF_BASE         0x10100000      /* PUMA Config */
+#define PUMA_CONF_OR_AM                0xFFFF8000      /* 32 kB */
+#define        PUMA_CONF_LOAD_TIMING   (OR_ACS_DIV2     | OR_SCY_2_CLK)
+#define PUMA_CONF_READ_TIMING  (OR_G5LA | OR_BI | OR_SCY_2_CLK)
+
+#define PUMA_CONF_BR_LOAD      ((PUMA_CONF_BASE & BR_BA_MSK) | \
+                                       BR_PS_8  | BR_MS_UPMB | BR_V)
+#define PUMA_CONF_OR_LOAD      (PUMA_CONF_OR_AM | PUMA_CONF_LOAD_TIMING)
+
+#define PUMA_CONF_BR_READ      ((PUMA_CONF_BASE & BR_BA_MSK) | BR_PS_16 | BR_V)
+#define PUMA_CONF_OR_READ      (PUMA_CONF_OR_AM | PUMA_CONF_READ_TIMING)
+
+#define CFG_BR4_PRELIM         PUMA_CONF_BR_READ
+#define CFG_OR4_PRELIM         PUMA_CONF_OR_READ
+
+/*
+ * BR5/OR5: PUMA: SMA Bus 8 Bit
+ *     BR5: 0x10200401         OR5: 0xffe0010a
+ */
+#define PUMA_SMA8_BASE         0x10200000      /* PUMA SMA Bus 8 Bit */
+#define PUMA_SMA8_OR_AM                0xFFE00000      /* 2 MB */
+#define PUMA_SMA8_TIMING       (OR_BI | OR_SCY_0_CLK | OR_EHTR)
+
+#define CFG_BR5_PRELIM         ((PUMA_SMA8_BASE & BR_BA_MSK) | BR_PS_8 | BR_V)
+#define CFG_OR5_PRELIM         (PUMA_SMA8_OR_AM | PUMA_SMA8_TIMING | OR_SETA)
+
+/*
+ * BR6/OR6: PUMA: SMA Bus 16 Bit
+ *     BR6: 0x10600801         OR6: 0xffe0010a
+ */
+#define PUMA_SMA16_BASE                0x10600000      /* PUMA SMA Bus 16 Bit */
+#define PUMA_SMA16_OR_AM       0xFFE00000      /* 2 MB */
+#define PUMA_SMA16_TIMING      (OR_BI | OR_SCY_0_CLK | OR_EHTR)
+
+#define CFG_BR6_PRELIM         ((PUMA_SMA16_BASE & BR_BA_MSK) | BR_PS_16 | BR_V)
+#define CFG_OR6_PRELIM         (PUMA_SMA16_OR_AM | PUMA_SMA16_TIMING | OR_SETA)
+
+/*
+ * BR7/OR7: PUMA: external Flash
+ *     BR7: 0x10a00801         OR7: 0xfe00010a
+ */
+#define PUMA_FLASH_BASE                0x10A00000      /* PUMA external Flash */
+#define PUMA_FLASH_OR_AM       0xFE000000      /* 32 MB */
+#define PUMA_FLASH_TIMING      (OR_BI | OR_SCY_0_CLK | OR_EHTR)
+
+#define CFG_BR7_PRELIM         ((PUMA_FLASH_BASE & BR_BA_MSK) | BR_PS_16 | BR_V)
+#define CFG_OR7_PRELIM         (PUMA_FLASH_OR_AM | PUMA_FLASH_TIMING | OR_SETA)
+
+
+/*
+ * Memory Periodic Timer Prescaler
+ */
+
+/* periodic timer for refresh */
+#define CFG_MAMR_PTA   97              /* start with divider for 100 MHz       */
+
+/* refresh rate 15.6 us (= 64 ms / 4K = 62.4 / quad bursts) for <= 128 MBit    */
+#define CFG_MPTPR_2BK_4K       MPTPR_PTP_DIV16         /* setting for 2 banks  */
+#define CFG_MPTPR_1BK_4K       MPTPR_PTP_DIV32         /* setting for 1 bank   */
+
+/* refresh rate 7.8 us (= 64 ms / 8K = 31.2 / quad bursts) for 256 MBit                */
+#define CFG_MPTPR_2BK_8K       MPTPR_PTP_DIV8          /* setting for 2 banks  */
+#define CFG_MPTPR_1BK_8K       MPTPR_PTP_DIV16         /* setting for 1 bank   */
+
+/*
+ * MAMR settings for SDRAM
+ */
+
+/* 8 column SDRAM */
+#define CFG_MAMR_8COL  ((CFG_MAMR_PTA << MAMR_PTA_SHIFT)  | MAMR_PTAE      |   \
+                        MAMR_AMA_TYPE_0 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A11 |   \
+                        MAMR_RLFA_1X    | MAMR_WLFA_1X    | MAMR_TLFA_4X)
+/* 9 column SDRAM */
+#define CFG_MAMR_9COL  ((CFG_MAMR_PTA << MAMR_PTA_SHIFT)  | MAMR_PTAE      |   \
+                        MAMR_AMA_TYPE_1 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A10 |   \
+                        MAMR_RLFA_1X    | MAMR_WLFA_1X    | MAMR_TLFA_4X)
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define        BOOTFLAG_COLD   0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/CPCI405.h b/include/configs/CPCI405.h
new file mode 100644 (file)
index 0000000..6b98347
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_405GP           1       /* This is a PPC405 CPU         */
+#define CONFIG_4xx             1       /* ...member of PPC4xx family   */
+#define CONFIG_CPCI405         1       /* ...on a CPCI405 board        */
+
+#define CONFIG_BOARD_PRE_INIT   1       /* call board_pre_init()        */
+
+#define CONFIG_SYS_CLK_FREQ     33000000 /* external frequency to pll   */
+
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_BOOTDELAY       3       /* autoboot after 3 seconds     */
+
+#if 0
+#define CONFIG_PREBOOT                                                          \
+        "crc32 f0207004 ffc 0;"                                                 \
+        "if cmp 0 f0207000 1;"                                                  \
+        "then;echo Old CRC is correct;crc32 f0207004 ff4 f0207000;"             \
+        "else;echo Old CRC is bad;fi"
+#endif
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_RAMBOOTCOMMAND                                                  \
+       "setenv bootargs root=/dev/ram rw nfsroot=$(serverip):$(rootpath) "     \
+       "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;"    \
+       "bootm ffc00000 ffca0000"
+#define CONFIG_NFSBOOTCOMMAND                                                  \
+       "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) "     \
+       "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;"    \
+       "bootm ffc00000"
+#define CONFIG_BOOTCOMMAND CONFIG_RAMBOOTCOMMAND
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#define CFG_LOADS_BAUD_CHANGE  1       /* allow baudrate change        */
+
+#define CONFIG_MII             1       /* MII PHY management           */
+#define        CONFIG_PHY_ADDR         0       /* PHY address                  */
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_PCI     | \
+                               CFG_CMD_IRQ     | \
+                               CFG_CMD_IDE     | \
+                               CFG_CMD_ELF     | \
+                               CFG_CMD_EEPROM  )
+
+#define CONFIG_MAC_PARTITION
+#define CONFIG_DOS_PARTITION
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#undef  CONFIG_WATCHDOG                        /* watchdog disabled            */
+
+#define        CONFIG_SDRAM_BANK0      1       /* init onboard SDRAM bank 0    */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+
+#undef CFG_HUSH_PARSER                 /* use "hush" command parser    */
+#ifdef CFG_HUSH_PARSER
+#define        CFG_PROMPT_HUSH_PS2     "> "
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_DEVICE_NULLDEV      1       /* include nulldev device       */
+
+#define CFG_CONSOLE_INFO_QUIET  1       /* don't print console @ startup*/
+
+#define CFG_MEMTEST_START      0x0400000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0C00000       /* 4 ... 12 MB in DRAM  */
+
+#undef  CFG_EXT_SERIAL_CLOCK           /* no external serial clock used */
+#define CFG_IGNORE_405_UART_ERRATA_59   /* ignore ppc405gp errata #59   */
+#define CFG_BASE_BAUD       691200
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE      \
+        { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400,     \
+         57600, 115200, 230400, 460800, 921600 }
+
+#define CFG_LOAD_ADDR  0x100000        /* default load address */
+#define CFG_EXTBDINFO  1               /* To use extended board_into (bd_t) */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_ZERO_BOOTDELAY_CHECK    /* check for keypress on bootdelay==0 */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define PCI_HOST_ADAPTER 0              /* configure as pci adapter     */
+#define PCI_HOST_FORCE  1               /* configure as pci host        */
+#define PCI_HOST_AUTO   2               /* detected via arbiter enable  */
+
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST        PCI_HOST_AUTO   /* select pci host function     */
+#define CONFIG_PCI_PNP                 /* do pci plug-and-play         */
+                                        /* resource configuration       */
+
+#define CONFIG_PCI_SCAN_SHOW            /* print pci devices @ startup  */
+
+#define CFG_PCI_SUBSYS_VENDORID 0x12FE  /* PCI Vendor ID: esd gmbh      */
+#define CFG_PCI_SUBSYS_DEVICEID 0x0405  /* PCI Device ID: CPCI-405      */
+#define CFG_PCI_SUBSYS_DEVICEID2 0x0406 /* PCI Device ID: CPCI-405-A    */
+#define CFG_PCI_CLASSCODE       0x0b20  /* PCI Class Code: Processor/PPC*/
+#define CFG_PCI_PTM1LA  0x00000000      /* point to sdram               */
+#define CFG_PCI_PTM1MS  0xfc000001      /* 64MB, enable hard-wired to 1 */
+#define CFG_PCI_PTM1PCI 0x00000000      /* Host: use this pci address   */
+#define CFG_PCI_PTM2LA  0xffc00000      /* point to flash               */
+#define CFG_PCI_PTM2MS  0xffc00001      /* 4MB, enable                  */
+#define CFG_PCI_PTM2PCI 0x04000000      /* Host: use this pci address   */
+
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff
+ *-----------------------------------------------------------------------
+ */
+#undef  CONFIG_IDE_8xx_DIRECT               /* no pcmcia interface required */
+#undef  CONFIG_IDE_LED                  /* no led for ide supported     */
+#undef  CONFIG_IDE_RESET                /* no reset for ide supported   */
+
+#define        CFG_IDE_MAXBUS          1               /* max. 1 IDE busses    */
+#define        CFG_IDE_MAXDEVICE       (CFG_IDE_MAXBUS*1) /* max. 1 drives per IDE bus */
+
+#define        CFG_ATA_BASE_ADDR       0xF0100000
+#define        CFG_ATA_IDE0_OFFSET     0x0000
+
+#define CFG_ATA_DATA_OFFSET    0x0000  /* Offset for data I/O                  */
+#define        CFG_ATA_REG_OFFSET      0x0000  /* Offset for normal register accesses  */
+#define CFG_ATA_ALT_OFFSET     0x0000  /* Offset for alternate registers       */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFFD0000
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MONITOR_LEN                (192 * 1024)    /* Reserve 196 kB for Monitor   */
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     256     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#define CFG_FLASH_WORD_SIZE     unsigned short  /* flash word size (width)      */
+#define CFG_FLASH_ADDR0         0x5555  /* 1st address for flash config cycles  */
+#define CFG_FLASH_ADDR1         0x2AAA  /* 2nd address for flash config cycles  */
+/*
+ * The following defines are added for buggy IOP480 byte interface.
+ * All other boards should use the standard values (CPCI405 etc.)
+ */
+#define CFG_FLASH_READ0         0x0000  /* 0 is standard                        */
+#define CFG_FLASH_READ1         0x0001  /* 1 is standard                        */
+#define CFG_FLASH_READ2         0x0002  /* 2 is standard                        */
+
+#define CFG_FLASH_EMPTY_INFO            /* print 'E' for empty sector on flinfo */
+
+#if 1 /* Use NVRAM for environment variables */
+/*-----------------------------------------------------------------------
+ * NVRAM organization
+ */
+#define CFG_ENV_IS_IN_NVRAM    1       /* use NVRAM for environment vars       */
+#define CFG_NVRAM_BASE_ADDR    0xf0200000              /* NVRAM base address   */
+#define CFG_NVRAM_SIZE         (32*1024)               /* NVRAM size           */
+#define CFG_ENV_SIZE           0x1000          /* Size of Environment vars     */
+#define CFG_ENV_ADDR           \
+       (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-CFG_ENV_SIZE)       /* Env  */
+#define CFG_NVRAM_VXWORKS_OFFS 0x6900          /* Offset for VxWorks eth-addr  */
+
+#else /* Use EEPROM for environment variables */
+
+#define CFG_ENV_IS_IN_EEPROM    1       /* use EEPROM for environment vars */
+#define CFG_ENV_OFFSET          0x000   /* environment starts at the beginning of the EEPROM */
+#define CFG_ENV_SIZE            0x200   /* 512 bytes may be used for env vars */
+                                   /* total size of a CAT24WC08 is 1024 bytes */
+#endif
+
+/*-----------------------------------------------------------------------
+ * I2C EEPROM (CAT24WC08) for environment
+ */
+#define CONFIG_HARD_I2C                        /* I2c with hardware support */
+#define CFG_I2C_SPEED          400000  /* I2C speed and slave address */
+#define CFG_I2C_SLAVE          0x7F
+
+#define CFG_I2C_EEPROM_ADDR    0x50    /* EEPROM CAT28WC08             */
+#define CFG_I2C_EEPROM_ADDR_LEN        1       /* Bytes of address             */
+/* mask of address bits that overflow into the "EEPROM chip address"    */
+#define CFG_I2C_EEPROM_ADDR_OVERFLOW   0x07
+#define CFG_EEPROM_PAGE_WRITE_BITS 4   /* The Catalyst CAT24WC08 has   */
+                                       /* 16 byte page write mode using*/
+                                       /* last 4 bits of the address   */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10   /* and takes up to 10 msec */
+#define CFG_EEPROM_PAGE_WRITE_ENABLE
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE                8192    /* For IBM 405 CPUs                     */
+#define CFG_CACHELINE_SIZE     32      /* ...                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0xFF800000      /* FLASH bank #0        */
+#define FLASH_BASE1_PRELIM     0xFFC00000      /* FLASH bank #1        */
+
+/*-----------------------------------------------------------------------
+ * External Bus Controller (EBC) Setup
+ */
+
+/* Memory Bank 0 (Flash Bank 0) initialization                                  */
+#define CFG_EBC_PB0AP           0x92015480
+#define CFG_EBC_PB0CR           0xFFC5A000  /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 1 (Flash Bank 1) initialization                                  */
+#define CFG_EBC_PB1AP           0x92015480
+#define CFG_EBC_PB1CR           0xFF85A000  /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 2 (CAN0, 1, 2, Codeswitch) initialization                        */
+#define CFG_EBC_PB2AP           0x010053C0  /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB2CR           0xF0018000  /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 3 (CompactFlash IDE) initialization                              */
+#define CFG_EBC_PB3AP           0x010053C0  /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB3CR           0xF011A000  /* BAS=0xF01,BS=1MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 4 (NVRAM) initialization                                         */
+#define CFG_EBC_PB4AP           0x01005280  /* TWT=2,WBN=1,WBF=1,TH=1,SOR=1     */
+#define CFG_EBC_PB4CR           0xF0218000  /* BAS=0xF02,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 5 (Quart) initialization                                         */
+#define CFG_EBC_PB5AP           0x04005B80  /* TWT=8,WBN=1,WBF=1,TH=5,RE=1,SOR=1*/
+#define CFG_EBC_PB5CR           0xF0318000  /* BAS=0xF03,BS=1MB,BU=R/W,BW=8bit  */
+
+/*-----------------------------------------------------------------------
+ * FPGA stuff
+ */
+
+/* FPGA program pin configuration */
+#define CFG_FPGA_PRG            0x04000000  /* FPGA program pin (ppc output) */
+#define CFG_FPGA_CLK            0x02000000  /* FPGA clk pin (ppc output)     */
+#define CFG_FPGA_DATA           0x01000000  /* FPGA data pin (ppc output)    */
+#define CFG_FPGA_INIT           0x00400000  /* FPGA init pin (ppc input)     */
+#define CFG_FPGA_DONE           0x00800000  /* FPGA done pin (ppc input)     */
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in data cache)
+ */
+#if 1 /* test-only */
+#define CFG_INIT_DCACHE_CS      7       /* use cs # 7 for data cache memory    */
+
+#define CFG_INIT_RAM_ADDR       0x40000000  /* use data cache                  */
+#else
+#define CFG_INIT_RAM_ADDR      0x00df0000 /* inside of SDRAM                   */
+#endif
+#define CFG_INIT_RAM_END        0x2000  /* End of used area in RAM             */
+#define CFG_GBL_DATA_SIZE      128  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/CPCI4052.h b/include/configs/CPCI4052.h
new file mode 100644 (file)
index 0000000..0533827
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_405GP           1       /* This is a PPC405 CPU         */
+#define CONFIG_4xx             1       /* ...member of PPC4xx family   */
+#define CONFIG_CPCI405         1       /* ...on a CPCI405 board        */
+#define CONFIG_CPCI405_VER2     1       /* ...version 2                 */
+
+#define CONFIG_BOARD_PRE_INIT   1       /* call board_pre_init()        */
+
+#define CONFIG_SYS_CLK_FREQ     33333333 /* external frequency to pll   */
+
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_BOOTDELAY       3       /* autoboot after 3 seconds     */
+
+#if 0
+#define CONFIG_PREBOOT                                                          \
+        "crc32 f0207004 ffc 0;"                                                 \
+        "if cmp 0 f0207000 1;"                                                  \
+        "then;echo Old CRC is correct;crc32 f0207004 ff4 f0207000;"             \
+        "else;echo Old CRC is bad;fi"
+#endif
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_RAMBOOTCOMMAND                                                  \
+       "setenv bootargs root=/dev/ram rw nfsroot=$(serverip):$(rootpath) "     \
+       "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;"    \
+       "bootm ffc00000 ffca0000"
+#define CONFIG_NFSBOOTCOMMAND                                                  \
+       "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) "     \
+       "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;"    \
+       "bootm ffc00000"
+#define CONFIG_BOOTCOMMAND CONFIG_RAMBOOTCOMMAND
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#define CFG_LOADS_BAUD_CHANGE  1       /* allow baudrate change        */
+
+#define CONFIG_MII             1       /* MII PHY management           */
+#define        CONFIG_PHY_ADDR         0       /* PHY address                  */
+
+#define CONFIG_RTC_M48T35A     1               /* ST Electronics M48 timekeeper */
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_PCI     | \
+                               CFG_CMD_IRQ     | \
+                               CFG_CMD_IDE     | \
+                               CFG_CMD_ELF     | \
+                               CFG_CMD_DATE    | \
+                               CFG_CMD_JFFS2   | \
+                               CFG_CMD_I2C     | \
+                               CFG_CMD_EEPROM  )
+
+#define CONFIG_MAC_PARTITION
+#define CONFIG_DOS_PARTITION
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#undef  CONFIG_WATCHDOG                        /* watchdog disabled            */
+
+#define        CONFIG_SDRAM_BANK0      1       /* init onboard SDRAM bank 0    */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+
+#undef CFG_HUSH_PARSER                 /* use "hush" command parser    */
+#ifdef CFG_HUSH_PARSER
+#define        CFG_PROMPT_HUSH_PS2     "> "
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_DEVICE_NULLDEV      1       /* include nulldev device       */
+
+#define CFG_CONSOLE_INFO_QUIET  1       /* don't print console @ startup*/
+
+#define CFG_MEMTEST_START      0x0400000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0C00000       /* 4 ... 12 MB in DRAM  */
+
+#undef  CFG_EXT_SERIAL_CLOCK           /* no external serial clock used */
+#define CFG_IGNORE_405_UART_ERRATA_59   /* ignore ppc405gp errata #59   */
+#define CFG_BASE_BAUD       691200
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE      \
+        { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400,     \
+         57600, 115200, 230400, 460800, 921600 }
+
+#define CFG_LOAD_ADDR  0x100000        /* default load address */
+#define CFG_EXTBDINFO  1               /* To use extended board_into (bd_t) */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_ZERO_BOOTDELAY_CHECK    /* check for keypress on bootdelay==0 */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define PCI_HOST_ADAPTER 0              /* configure as pci adapter     */
+#define PCI_HOST_FORCE  1               /* configure as pci host        */
+#define PCI_HOST_AUTO   2               /* detected via arbiter enable  */
+
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST        PCI_HOST_AUTO   /* select pci host function     */
+#define CONFIG_PCI_PNP                 /* do pci plug-and-play         */
+                                        /* resource configuration       */
+
+#define CONFIG_PCI_SCAN_SHOW            /* print pci devices @ startup  */
+
+#define CFG_PCI_SUBSYS_VENDORID 0x12FE  /* PCI Vendor ID: esd gmbh      */
+#define CFG_PCI_SUBSYS_DEVICEID 0x0405  /* PCI Device ID: CPCI-405      */
+#define CFG_PCI_SUBSYS_DEVICEID2 0x0406 /* PCI Device ID: CPCI-405-A    */
+#define CFG_PCI_CLASSCODE       0x0b20  /* PCI Class Code: Processor/PPC*/
+#define CFG_PCI_PTM1LA  0x00000000      /* point to sdram               */
+#define CFG_PCI_PTM1MS  0xfc000001      /* 64MB, enable hard-wired to 1 */
+#define CFG_PCI_PTM1PCI 0x00000000      /* Host: use this pci address   */
+#define CFG_PCI_PTM2LA  0xffc00000      /* point to flash               */
+#define CFG_PCI_PTM2MS  0xffc00001      /* 4MB, enable                  */
+#define CFG_PCI_PTM2PCI 0x04000000      /* Host: use this pci address   */
+
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff
+ *-----------------------------------------------------------------------
+ */
+#undef  CONFIG_IDE_8xx_DIRECT               /* no pcmcia interface required */
+#undef  CONFIG_IDE_LED                  /* no led for ide supported     */
+#define CONFIG_IDE_RESET       1       /* reset for ide supported      */
+
+#define        CFG_IDE_MAXBUS          1               /* max. 1 IDE busses    */
+#define        CFG_IDE_MAXDEVICE       (CFG_IDE_MAXBUS*1) /* max. 1 drives per IDE bus */
+
+#define        CFG_ATA_BASE_ADDR       0xF0100000
+#define        CFG_ATA_IDE0_OFFSET     0x0000
+
+#define CFG_ATA_DATA_OFFSET    0x0000  /* Offset for data I/O                  */
+#define        CFG_ATA_REG_OFFSET      0x0000  /* Offset for normal register accesses  */
+#define CFG_ATA_ALT_OFFSET     0x0000  /* Offset for alternate registers       */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFFC0000
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MONITOR_LEN                (256 * 1024)    /* Reserve 256 kB for Monitor   */
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     256     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#define CFG_FLASH_WORD_SIZE     unsigned short  /* flash word size (width)      */
+#define CFG_FLASH_ADDR0         0x5555  /* 1st address for flash config cycles  */
+#define CFG_FLASH_ADDR1         0x2AAA  /* 2nd address for flash config cycles  */
+/*
+ * The following defines are added for buggy IOP480 byte interface.
+ * All other boards should use the standard values (CPCI405 etc.)
+ */
+#define CFG_FLASH_READ0         0x0000  /* 0 is standard                        */
+#define CFG_FLASH_READ1         0x0001  /* 1 is standard                        */
+#define CFG_FLASH_READ2         0x0002  /* 2 is standard                        */
+
+#define CFG_FLASH_EMPTY_INFO            /* print 'E' for empty sector on flinfo */
+
+#define CFG_JFFS2_FIRST_BANK    0           /* use for JFFS2 */
+#define CFG_JFFS2_NUM_BANKS     1           /* ! second bank contains U-Boot */
+
+#if 0 /* Use NVRAM for environment variables */
+/*-----------------------------------------------------------------------
+ * NVRAM organization
+ */
+#define CFG_ENV_IS_IN_NVRAM    1       /* use NVRAM for environment vars       */
+#define CFG_ENV_SIZE           0x0ff8          /* Size of Environment vars     */
+#define CFG_ENV_ADDR           \
+       (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-(CFG_ENV_SIZE+8))   /* Env  */
+
+#else /* Use EEPROM for environment variables */
+
+#define CFG_ENV_IS_IN_EEPROM    1       /* use EEPROM for environment vars */
+#define CFG_ENV_OFFSET          0x000   /* environment starts at the beginning of the EEPROM */
+#define CFG_ENV_SIZE            0x800   /* 2048 bytes may be used for env vars*/
+                                   /* total size of a CAT24WC16 is 2048 bytes */
+#endif
+
+#define CFG_NVRAM_BASE_ADDR    0xf0200000              /* NVRAM base address   */
+#define CFG_NVRAM_SIZE         (32*1024)               /* NVRAM size           */
+#define CFG_NVRAM_VXWORKS_OFFS 0x6900          /* Offset for VxWorks eth-addr  */
+
+/*-----------------------------------------------------------------------
+ * I2C EEPROM (CAT24WC16) for environment
+ */
+#define CONFIG_HARD_I2C                        /* I2c with hardware support */
+#define CFG_I2C_SPEED          400000  /* I2C speed and slave address */
+#define CFG_I2C_SLAVE          0x7F
+
+#define CFG_I2C_EEPROM_ADDR    0x50    /* EEPROM CAT28WC08             */
+#define CFG_I2C_EEPROM_ADDR_LEN        1       /* Bytes of address             */
+/* mask of address bits that overflow into the "EEPROM chip address"    */
+#define CFG_I2C_EEPROM_ADDR_OVERFLOW   0x07
+#define CFG_EEPROM_PAGE_WRITE_BITS 4   /* The Catalyst CAT24WC08 has   */
+                                       /* 16 byte page write mode using*/
+                                       /* last 4 bits of the address   */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10   /* and takes up to 10 msec */
+#define CFG_EEPROM_PAGE_WRITE_ENABLE
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE                16384   /* For IBM 405 CPUs, older 405 ppc's    */
+                                        /* have only 8kB, 16kB is save here     */
+#define CFG_CACHELINE_SIZE     32      /* ...                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0xFF800000      /* FLASH bank #0        */
+#define FLASH_BASE1_PRELIM     0xFFC00000      /* FLASH bank #1        */
+
+/*-----------------------------------------------------------------------
+ * External Bus Controller (EBC) Setup
+ */
+
+/* Memory Bank 0 (Flash Bank 0) initialization                                  */
+#define CFG_EBC_PB0AP           0x92015480
+#define CFG_EBC_PB0CR           0xFFC5A000  /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 1 (Flash Bank 1) initialization                                  */
+#define CFG_EBC_PB1AP           0x92015480
+#define CFG_EBC_PB1CR           0xFF85A000  /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 2 (CAN0, 1) initialization                                       */
+#define CFG_EBC_PB2AP           0x010053C0  /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB2CR           0xF0018000  /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 3 (CompactFlash IDE) initialization                              */
+#define CFG_EBC_PB3AP           0x010053C0  /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB3CR           0xF011A000  /* BAS=0xF01,BS=1MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 4 (NVRAM/RTC) initialization                                     */
+#define CFG_EBC_PB4AP           0x01005280  /* TWT=2,WBN=1,WBF=1,TH=1,SOR=1     */
+#define CFG_EBC_PB4CR           0xF0218000  /* BAS=0xF02,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 5 (optional Quart) initialization                                */
+#define CFG_EBC_PB5AP           0x04005B80  /* TWT=8,WBN=1,WBF=1,TH=5,RE=1,SOR=1*/
+#define CFG_EBC_PB5CR           0xF0318000  /* BAS=0xF03,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 6 (FPGA internal) initialization                                 */
+#define CFG_EBC_PB6AP           0x010053C0  /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB6CR           0xF041A000  /* BAS=0xF01,BS=1MB,BU=R/W,BW=16bit */
+#define CFG_FPGA_BASE_ADDR      0xF0400000
+
+/*-----------------------------------------------------------------------
+ * FPGA stuff
+ */
+/* FPGA internal regs */
+#define CFG_FPGA_MODE           0x00
+#define CFG_FPGA_STATUS         0x02
+#define CFG_FPGA_TS             0x04
+#define CFG_FPGA_TS_LOW         0x06
+#define CFG_FPGA_TS_CAP0        0x10
+#define CFG_FPGA_TS_CAP0_LOW    0x12
+#define CFG_FPGA_TS_CAP1        0x14
+#define CFG_FPGA_TS_CAP1_LOW    0x16
+#define CFG_FPGA_TS_CAP2        0x18
+#define CFG_FPGA_TS_CAP2_LOW    0x1a
+#define CFG_FPGA_TS_CAP3        0x1c
+#define CFG_FPGA_TS_CAP3_LOW    0x1e
+
+/* FPGA Mode Reg */
+#define CFG_FPGA_MODE_CF_RESET  0x0001
+#define CFG_FPGA_MODE_TS_IRQ_ENABLE 0x0100
+#define CFG_FPGA_MODE_TS_IRQ_CLEAR  0x1000
+#define CFG_FPGA_MODE_TS_CLEAR  0x2000
+
+/* FPGA Status Reg */
+#define CFG_FPGA_STATUS_DIP0    0x0001
+#define CFG_FPGA_STATUS_DIP1    0x0002
+#define CFG_FPGA_STATUS_DIP2    0x0004
+#define CFG_FPGA_STATUS_FLASH   0x0008
+#define CFG_FPGA_STATUS_TS_IRQ  0x1000
+
+#define CFG_FPGA_SPARTAN2       1           /* using Xilinx Spartan 2 now    */
+#define CFG_FPGA_MAX_SIZE       32*1024     /* 32kByte is enough for XC2S15  */
+
+/* FPGA program pin configuration */
+#define CFG_FPGA_PRG            0x04000000  /* FPGA program pin (ppc output) */
+#define CFG_FPGA_CLK            0x02000000  /* FPGA clk pin (ppc output)     */
+#define CFG_FPGA_DATA           0x01000000  /* FPGA data pin (ppc output)    */
+#define CFG_FPGA_INIT           0x00010000  /* FPGA init pin (ppc input)     */
+#define CFG_FPGA_DONE           0x00008000  /* FPGA done pin (ppc input)     */
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in data cache)
+ */
+#if 1 /* test-only */
+#define CFG_INIT_DCACHE_CS      7       /* use cs # 7 for data cache memory    */
+
+#define CFG_INIT_RAM_ADDR       0x40000000  /* use data cache                  */
+#else
+#define CFG_INIT_RAM_ADDR      0x00df0000 /* inside of SDRAM                   */
+#endif
+#define CFG_INIT_RAM_END        0x2000  /* End of used area in RAM             */
+#define CFG_GBL_DATA_SIZE      128  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/CPCIISER4.h b/include/configs/CPCIISER4.h
new file mode 100644 (file)
index 0000000..6c8d7f6
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_405GP           1       /* This is a PPC405 CPU         */
+#define CONFIG_4xx             1       /* ...member of PPC4xx family   */
+#define CONFIG_CPCIISER4       1       /* ...on a CPCIISER4 board      */
+
+#define CONFIG_BOARD_PRE_INIT   1       /* call board_pre_init()        */
+
+#define CONFIG_SYS_CLK_FREQ     25000000 /* external frequency to pll   */
+
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_BOOTDELAY       3       /* autoboot after 3 seconds     */
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_BOOTCOMMAND     "bootm fff00000"
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#define CFG_LOADS_BAUD_CHANGE  1       /* allow baudrate change        */
+
+#define CONFIG_MII             1       /* MII PHY management           */
+#define        CONFIG_PHY_ADDR         0       /* PHY address                  */
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_PCI     | \
+                               CFG_CMD_IRQ     | \
+                               CFG_CMD_ELF     | \
+                               CFG_CMD_EEPROM  )
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#undef CONFIG_WATCHDOG                 /* watchdog disabled            */
+
+#define        CONFIG_SDRAM_BANK0      1       /* init onboard SDRAM bank 0    */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_CONSOLE_INFO_QUIET  1       /* don't print console @ startup*/
+
+#define CFG_MEMTEST_START      0x0400000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0C00000       /* 4 ... 12 MB in DRAM  */
+
+#define CFG_EXT_SERIAL_CLOCK    1843200  /* use external serial clock   */
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE      \
+        { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400,     \
+         57600, 115200, 230400, 460800, 921600 }
+
+#define CFG_LOAD_ADDR  0x100000        /* default load address */
+#define CFG_EXTBDINFO  1               /* To use extended board_into (bd_t) */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_ZERO_BOOTDELAY_CHECK    /* check for keypress on bootdelay==0 */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define PCI_HOST_ADAPTER 0              /* configure ar pci adapter     */
+#define PCI_HOST_FORCE  1               /* configure as pci host        */
+#define PCI_HOST_AUTO   2               /* detected via arbiter enable  */
+
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST        PCI_HOST_AUTO   /* select pci host function     */
+#define CONFIG_PCI_PNP                 /* do pci plug-and-play         */
+                                        /* resource configuration       */
+
+#define CFG_PCI_SUBSYS_VENDORID 0x12FE  /* PCI Vendor ID: esd gmbh      */
+#define CFG_PCI_SUBSYS_DEVICEID 0x0404  /* PCI Device ID: CPCI-ISER4    */
+#define CFG_PCI_PTM1LA  0x00000000      /* point to sdram               */
+#define CFG_PCI_PTM1MS  0xff000001      /* 16MB, enable hard-wired to 1 */
+#define CFG_PCI_PTM1PCI 0x00000000      /* Host: use this pci address   */
+#define CFG_PCI_PTM2LA  0xffe00000      /* point to flash               */
+#define CFG_PCI_PTM2MS  0xffe00001      /* 2MB, enable                  */
+#define CFG_PCI_PTM2PCI 0x04000000      /* Host: use this pci address   */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFFC0000
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MONITOR_LEN                (256 * 1024)    /* Reserve 256 kB for Monitor   */
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    1       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     256     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#define CFG_FLASH_WORD_SIZE     unsigned short  /* flash word size (width)      */
+#define CFG_FLASH_ADDR0         0x5555  /* 1st address for flash config cycles  */
+#define CFG_FLASH_ADDR1         0x2AAA  /* 2nd address for flash config cycles  */
+/*
+ * The following defines are added for buggy IOP480 byte interface.
+ * All other boards should use the standard values (CPCI405 etc.)
+ */
+#define CFG_FLASH_READ0         0x0000  /* 0 is standard                        */
+#define CFG_FLASH_READ1         0x0001  /* 1 is standard                        */
+#define CFG_FLASH_READ2         0x0002  /* 2 is standard                        */
+
+#define CFG_FLASH_EMPTY_INFO            /* print 'E' for empty sector on flinfo */
+
+/*-----------------------------------------------------------------------
+ * I2C EEPROM (CAT24WC08) for environment
+ */
+#define CONFIG_HARD_I2C                        /* I2C with hardware support */
+#define CFG_I2C_SPEED          400000  /* I2C speed and slave address */
+#define CFG_I2C_SLAVE          0x7F
+
+#define CFG_I2C_EEPROM_ADDR    0x50    /* EEPROM CAT28WC08             */
+#define CFG_I2C_EEPROM_ADDR_LEN        1       /* Bytes of address             */
+/* mask of address bits that overflow into the "EEPROM chip address"    */
+#define CFG_I2C_EEPROM_ADDR_OVERFLOW   0x07
+#define CFG_EEPROM_PAGE_WRITE_BITS 4   /* The Catalyst CAT24WC08 has   */
+                                       /* 16 byte page write mode using*/
+                                       /* last 4 bits of the address   */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10   /* and takes up to 10 msec */
+#define CFG_EEPROM_PAGE_WRITE_ENABLE
+
+#define CFG_ENV_IS_IN_EEPROM    1       /* use EEPROM for environment vars */
+#define CFG_ENV_OFFSET          0x000   /* environment starts at the beginning of the EEPROM */
+#define CFG_ENV_SIZE            0x300   /* 768 bytes may be used for env vars */
+                                   /* total size of a CAT24WC08 is 1024 bytes */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE                8192    /* For IBM 405 CPUs                     */
+#define CFG_CACHELINE_SIZE     32      /* ...                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0xFFF00000      /* FLASH bank #0        */
+#define FLASH_BASE1_PRELIM     0               /* FLASH bank #1        */
+
+/*-----------------------------------------------------------------------
+ * External Bus Controller (EBC) Setup
+ */
+
+/* Memory Bank 0 (Flash Bank 0) initialization                                  */
+#define CFG_EBC_PB0AP           0x92015480
+#define CFG_EBC_PB0CR           0xFFC5A000  /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 1 (Uart 8bit) initialization                                     */
+#define CFG_EBC_PB1AP           0x01000480  /* TWT=2,TH=2,no Ready,BEM=0,SOR=1  */
+#define CFG_EBC_PB1CR           0xF0018000  /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 2 (Uart 32bit) initialization                                    */
+#define CFG_EBC_PB2AP           0x000004c0  /* no Ready, BEM=1                  */
+#define CFG_EBC_PB2CR           0xF011C000  /* BAS=0xF01,BS=1MB,BU=R/W,BW=32bit */
+
+/* Memory Bank 3 (FPGA Reset) initialization                                    */
+#define CFG_EBC_PB3AP           0x010004C0  /* no Ready, BEM=1                  */
+#define CFG_EBC_PB3CR           0xF021A000  /* BAS=0xF02,BS=1MB,BU=R/W,BW=16bit */
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR      0x00df0000 /* inside of SDRAM                   */
+#define CFG_INIT_RAM_END       0x0f00  /* End of used area in RAM             */
+#define CFG_GBL_DATA_SIZE      64  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET     CFG_GBL_DATA_OFFSET
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/CRAYL1.h b/include/configs/CRAYL1.h
new file mode 100644 (file)
index 0000000..b10d967
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * David Updegraff, Cray, Inc.  dave@cray.com: our 405 is walnut-lite..
+ *
+ * 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
+ */
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_CRAYL1
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_405GP           1       /* This is a PPC405 CPU */
+#define CONFIG_4xx                 1   /* ...member of PPC405 family */
+#define CONFIG_SYS_CLK_FREQ 25000000
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_BOOTDELAY       5       /* autoboot after 5 seconds     */
+#define CONFIG_MII                 1   /* MII PHY management */
+#define        CONFIG_PHY_ADDR         1       /* PHY address; handling of ENET */
+#define CONFIG_BOARD_PRE_INIT 1 /* setup for 405gp */
+#define CONFIG_MISC_INIT_R     1       /* so that a misc_init_r() is called */
+
+/* set PRAM to keep U-Boot out, mem= to keep linux out, and initrd_hi to
+ * keep possible initrd ramdisk decompression out.  This is in k (1024 bytes)
+ #define CONFIG_PRAM                   16
+ */
+#define        CONFIG_LOADADDR         0x100000
+#undef CONFIG_BOOTARGS
+
+/* the logic is that booting is driven by what env vars get set from DHCP.
+ * Normal DHCP sets things like serverip, rootpath, etc.
+ * if printenv
+ */
+#define        CFG_AUTOLOAD            "yes"
+#define CONFIG_BOOTCOMMAND     "dhcp;"\
+       "setenv bootargs devfs=mount;"\
+       "setenv bootargs ip=$ipaddr:$serverip:$gatewayip:$netmask:::off $bootargs;"\
+       "if printenv initrd;"\
+       "then;" \
+        "setenv initrd_hi $mem;"\
+        "tftp 1000000 $initrd;"\
+        "setenv bootargs root=/dev/ram0 rw cwsroot=$serverip:$rootpath $bootargs;"\
+        "bootm 100000 1000000;"\
+       "else;"\
+        "setenv bootargs root=/dev/nfs ro nfsroot=$serverip:$rootpath $bootargs;"\
+        "bootm 100000;"\
+       "fi;"
+
+#define CONFIG_EXTRA_ENV_SETTINGS ""
+
+/*
+ * ..during experiments..
+ #define CONFIG_SERVERIP         10.0.0.1
+ #define CONFIG_ETHADDR          00:40:a6:80:14:5
+ */
+#define CONFIG_HARD_I2C         1              /* hardware support for i2c */
+#define CFG_I2C_SPEED              400000      /* I2C speed and slave address  */
+#define CFG_I2C_SLAVE              0x7F
+#define CFG_I2C_EEPROM_ADDR     0x57
+#define CFG_I2C_EEPROM_ADDR_LEN 1
+#define CONFIG_IDENT_STRING     "Cray L1"
+#define CONFIG_ENV_OVERWRITE     1
+#define        CFG_HZ                       1000       /* decrementer freq: 1 ms ticks */
+#define CFG_HUSH_PARSER                        1
+#define CFG_PROMPT_HUSH_PS2            "> "
+
+
+#define CONFIG_COMMANDS         (\
+       CFG_CMD_BDI|\
+       CFG_CMD_IMI|\
+       CFG_CMD_FLASH|\
+       CFG_CMD_MEMORY|\
+       CFG_CMD_NET|\
+       CFG_CMD_ENV|\
+       CFG_CMD_CONSOLE|\
+       CFG_CMD_ASKENV|\
+       CFG_CMD_ECHO|\
+       CFG_CMD_IMMAP|\
+       CFG_CMD_REGINFO|\
+       CFG_CMD_DHCP|\
+       CFG_CMD_DATE|\
+       CFG_CMD_RUN|\
+       CFG_CMD_I2C|\
+       CFG_CMD_EEPROM|\
+       CFG_CMD_SETGETDCR)
+
+/*
+ * optional BOOTP / DHCP fields
+ */
+#define CONFIG_BOOTP_MASK (\
+       CONFIG_BOOTP_VENDOREX|\
+       CONFIG_BOOTP_SUBNETMASK|\
+       CONFIG_BOOTP_GATEWAY|\
+       CONFIG_BOOTP_DNS|\
+       CONFIG_BOOTP_HOSTNAME|\
+       CONFIG_BOOTP_BOOTFILESIZE|\
+       CONFIG_BOOTP_BOOTPATH)
+
+/*
+ * bauds.  Just to make it compile; in our case, I read the base_baud
+ * from the DCR anyway, so its kinda-tied to the above ref. clock which in turn
+ * drives the system clock.
+ */
+#define CFG_BASE_BAUD       403225
+#define CFG_BAUDRATE_TABLE  \
+    {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_PROMPT     "=> "                   /* Monitor Command Prompt       */
+#define        CFG_CBSIZE      256                             /* Console I/O Buffer Size      */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16                              /* max number of command args   */
+
+
+#define CFG_LOAD_ADDR          0x100000/* where to load what we get from TFTP */
+#define CFG_TFTP_LOADADDR      CFG_LOAD_ADDR
+#define CFG_EXTBDINFO          1       /* To use extended board_into (bd_t) */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFC00000
+#define CFG_MONITOR_BASE       TEXT_BASE
+
+#ifndef  CFG_HUSH_PARSER
+#define CFG_MONITOR_LEN                (128 * 1024)    /* Reserve 128 kB for Monitor   */
+#define CFG_ENV_OFFSET         0x3D0000
+#else
+#define CFG_MONITOR_LEN                (192 * 1024)    /* Reserve 192 kB for Monitor   */
+#define CFG_ENV_OFFSET         0x3FE000
+#endif
+
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS     1              /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT      64             /* max number of sectors on one chip    */
+#define CFG_FLASH_ERASE_TOUT 120000    /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT 500       /* Timeout for Flash Write (in ms)      */
+
+/* BEG ENVIRONNEMENT FLASH: needs to be a whole FlashSector  */
+#define CFG_ENV_IS_IN_FLASH    1       /* use FLASH for environment vars */
+#define        CFG_ENV_SIZE            0x1000   /* Total Size of Environment Sector    */
+#define CFG_ENV_SECT_SIZE      0x10000  /* see README - env sector total size  */
+
+/* Memory tests: U-Boot relocates itself to the top of Ram, so its at
+ * 32meg-(128k+some_malloc_space+copy-of-ENV sector)..
+ */
+#define CFG_SDRAM_SIZE         32              /* megs of ram */
+#define CFG_MEMTEST_START      0x2000  /* memtest works from the end of */
+                                                                       /* the exception vector table */
+                                                                       /* to the end of the DRAM  */
+                                                                       /* less monitor and malloc area */
+#define CFG_STACK_USAGE                0x10000 /* Reserve 64k for the stack usage */
+#define CFG_MEM_END_USAGE      ( CFG_MONITOR_LEN \
+                                + CFG_MALLOC_LEN \
+                                + CFG_ENV_SECT_SIZE \
+                                + CFG_STACK_USAGE )
+
+#define CFG_MEMTEST_END                (CFG_SDRAM_SIZE * 1024 * 1024 - CFG_MEM_END_USAGE)
+/* END ENVIRONNEMENT FLASH */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration.  Only used to ..?? clear it, I guess..
+ */
+#define CFG_DCACHE_SIZE                16384
+#define CFG_CACHELINE_SIZE     32
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     CFG_FLASH_BASE  /* FLASH bank #0        */
+
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in OnChipMem )
+ */
+#if 0
+#define CFG_INIT_RAM_ADDR       0x40000000  /* use data cache               */
+#define CFG_INIT_RAM_END        0x2000  /* End of used area in RAM             */
+#else
+#define CFG_TEMP_STACK_OCM     1
+#define CFG_OCM_DATA_ADDR      0xF0000000
+#define CFG_OCM_DATA_SIZE      0x1000
+#define CFG_INIT_RAM_ADDR      CFG_OCM_DATA_ADDR       /* inside of On Chip SRAM    */
+#define CFG_INIT_RAM_END       CFG_OCM_DATA_SIZE       /* End of On Chip SRAM       */
+#endif
+
+#define CFG_GBL_DATA_SIZE      64      /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET     CFG_GBL_DATA_OFFSET
+
+/*-----------------------------------------------------------------------
+ * Definitions for Serial Presence Detect EEPROM address
+ */
+#define EEPROM_WRITE_ADDRESS 0xA0
+#define EEPROM_READ_ADDRESS  0xA1
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/CU824.h b/include/configs/CU824.h
new file mode 100644 (file)
index 0000000..ed38ef6
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * (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
+ */
+
+/*
+ *
+ * Configuration settings for the CU824 board.
+ *
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC824X         1
+#define CONFIG_MPC8240         1
+#define CONFIG_CU824           1
+
+
+#define CONFIG_CONS_INDEX      1
+#define CONFIG_BAUDRATE                9600
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_CLOCKS_IN_MHZ   1       /* clocks passsed to Linux in MHz       */
+
+#define CONFIG_PREBOOT "echo;echo Type \"run flash_nfs\" to mount root filesystem over NFS;echo"
+
+#define CONFIG_BOOTCOMMAND     "bootm FE020000"        /* autoboot command     */
+#define CONFIG_BOOTDELAY       5
+
+#define CONFIG_BOOTP_MASK      (CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_BOOTFILESIZE)
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_DHCP    | \
+                               CFG_CMD_PCI     | \
+                               0/* CFG_CMD_DATE */     )
+
+/* This must be included AFTER the definition of CONFIG_COMMANDS (if any)
+ */
+#include <cmd_confdefs.h>
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+#define CFG_CBSIZE     256             /* Console I/O Buffer Size      */
+
+#if 1
+#define        CFG_HUSH_PARSER         1       /* use "hush" command parser    */
+#endif
+#ifdef CFG_HUSH_PARSER
+#define        CFG_PROMPT_HUSH_PS2     "> "
+#endif
+
+/* Print Buffer Size
+ */
+#define CFG_PBSIZE     (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)
+
+#define        CFG_MAXARGS     16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR  0x00100000      /* Default load address         */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE     0x00000000
+#define CFG_FLASH_BASE     0xFF000000
+
+#define CFG_RESET_ADDRESS   0xFFF00100
+
+#define CFG_EUMB_ADDR      0xFCE00000
+
+#define CFG_MONITOR_BASE    TEXT_BASE
+
+#define CFG_MONITOR_LEN            (256 << 10) /* Reserve 256 kB for Monitor   */
+#define CFG_MALLOC_LEN     (128 << 10) /* Reserve 128 kB for malloc()  */
+
+#define CFG_MEMTEST_START   0x00004000 /* memtest works on             */
+#define CFG_MEMTEST_END            0x02000000  /* 0 ... 32 MB in DRAM          */
+
+       /* Maximum amount of RAM.
+        */
+#define CFG_MAX_RAM_SIZE    0x10000000
+
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+#undef CFG_RAMBOOT
+#else
+#define CFG_RAMBOOT
+#endif
+
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area
+ */
+
+       /* Size in bytes reserved for initial data
+        */
+#define CFG_GBL_DATA_SIZE    128
+
+#define CFG_INIT_RAM_ADDR     0x40000000
+#define CFG_INIT_RAM_END      0x1000
+#define CFG_GBL_DATA_OFFSET  (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+
+/*
+ * NS16550 Configuration
+ */
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+
+#define CFG_NS16550_REG_SIZE   4
+
+#define CFG_NS16550_CLK                (14745600 / 2)
+
+#define CFG_NS16550_COM1       0xFE800080
+#define CFG_NS16550_COM2       0xFE8000C0
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ * For the detail description refer to the MPC8240 user's manual.
+ */
+
+#define CONFIG_SYS_CLK_FREQ  33000000
+#define CFG_HZ              1000
+
+       /* Bit-field values for MCCR1.
+        */
+#define CFG_ROMNAL         0
+#define CFG_ROMFAL         7
+
+       /* Bit-field values for MCCR2.
+        */
+#define CFG_REFINT         430     /* Refresh interval                 */
+
+       /* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4.
+        */
+#define CFG_BSTOPRE        192
+
+       /* Bit-field values for MCCR3.
+        */
+#define CFG_REFREC         2       /* Refresh to activate interval     */
+#define CFG_RDLAT          3       /* Data latancy from read command   */
+
+       /* Bit-field values for MCCR4.
+        */
+#define CFG_PRETOACT       2       /* Precharge to activate interval   */
+#define CFG_ACTTOPRE       5       /* Activate to Precharge interval   */
+#define CFG_SDMODE_CAS_LAT  2      /* SDMODE CAS latancy               */
+#define CFG_SDMODE_WRAP            0       /* SDMODE wrap type                 */
+#define CFG_SDMODE_BURSTLEN 2      /* SDMODE Burst length              */
+#define CFG_ACTORW         2
+#define CFG_REGISTERD_TYPE_BUFFER 1
+
+/* Memory bank settings.
+ * Only bits 20-29 are actually used from these vales to set the
+ * start/end addresses. The upper two bits will always be 0, and the lower
+ * 20 bits will be 0x00000 for a start address, or 0xfffff for an end
+ * address. Refer to the MPC8240 book.
+ */
+
+#define CFG_BANK0_START            0x00000000
+#define CFG_BANK0_END      (CFG_MAX_RAM_SIZE - 1)
+#define CFG_BANK0_ENABLE    1
+#define CFG_BANK1_START            0x3ff00000
+#define CFG_BANK1_END      0x3fffffff
+#define CFG_BANK1_ENABLE    0
+#define CFG_BANK2_START            0x3ff00000
+#define CFG_BANK2_END      0x3fffffff
+#define CFG_BANK2_ENABLE    0
+#define CFG_BANK3_START            0x3ff00000
+#define CFG_BANK3_END      0x3fffffff
+#define CFG_BANK3_ENABLE    0
+#define CFG_BANK4_START            0x3ff00000
+#define CFG_BANK4_END      0x3fffffff
+#define CFG_BANK4_ENABLE    0
+#define CFG_BANK5_START            0x3ff00000
+#define CFG_BANK5_END      0x3fffffff
+#define CFG_BANK5_ENABLE    0
+#define CFG_BANK6_START            0x3ff00000
+#define CFG_BANK6_END      0x3fffffff
+#define CFG_BANK6_ENABLE    0
+#define CFG_BANK7_START            0x3ff00000
+#define CFG_BANK7_END      0x3fffffff
+#define CFG_BANK7_ENABLE    0
+
+#define CFG_ODCR           0xff
+
+#define CFG_IBAT0L  (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U  (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT1L  (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT1U  (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
+
+#define CFG_IBAT2L  (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U  (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT3L  (0xFC000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U  (0xFC000000 | BATU_BL_64M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L  CFG_IBAT0L
+#define CFG_DBAT0U  CFG_IBAT0U
+#define CFG_DBAT1L  CFG_IBAT1L
+#define CFG_DBAT1U  CFG_IBAT1U
+#define CFG_DBAT2L  CFG_IBAT2L
+#define CFG_DBAT2U  CFG_IBAT2U
+#define CFG_DBAT3L  CFG_IBAT3L
+#define CFG_DBAT3U  CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ      (8 << 20)   /* Initial Memory map for Linux */
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* Max number of flash banks            */
+#define CFG_MAX_FLASH_SECT     39      /* Max number of sectors in one bank    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+       /* Warining: environment is not EMBEDDED in the U-Boot code.
+        * It's stored in flash separately.
+        */
+#define CFG_ENV_IS_IN_FLASH        1
+#if 0
+#define CFG_ENV_ADDR           0xFF008000
+#define CFG_ENV_SIZE           0x8000  /* Size of the Environment Sector       */
+#else
+#define CFG_ENV_ADDR           0xFFFC0000
+#define CFG_ENV_SIZE           0x4000  /* Size of the Environment              */
+#define CFG_ENV_OFFSET         0       /* starting right at the beginning      */
+#define CFG_ENV_SECT_SIZE      0x40000 /* Size of the Environment Sector       */
+#endif
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#  define CFG_CACHELINE_SHIFT  5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                      */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_PCI                     /* include pci support                  */
+#undef CONFIG_PCI_PNP
+
+#define CONFIG_NET_MULTI               /* Multi ethernet cards support         */
+
+#define CONFIG_TULIP
+#define CONFIG_TULIP_USE_IO
+
+#define CFG_ETH_DEV_FN      0x7800
+#define CFG_ETH_IOBASE      0x00104000
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/DU405.h b/include/configs/DU405.h
new file mode 100644 (file)
index 0000000..1bf40d9
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_405GP           1       /* This is a PPC405 CPU         */
+#define CONFIG_4xx             1       /* ...member of PPC4xx family   */
+#define CONFIG_DU405           1       /* ...on a DU405 board          */
+
+#define CONFIG_BOARD_PRE_INIT   1       /* call board_pre_init()        */
+
+#define CONFIG_SYS_CLK_FREQ     25000000 /* external frequency to pll   */
+
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_BOOTDELAY       3       /* autoboot after 3 seconds     */
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_BOOTCOMMAND     "bootm fff00000"
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#define CFG_LOADS_BAUD_CHANGE  1       /* allow baudrate change        */
+
+#define CONFIG_MII             1       /* MII PHY management           */
+#define        CONFIG_PHY_ADDR         0       /* PHY address                  */
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_PCI     | \
+                               CFG_CMD_IRQ     | \
+                               CFG_CMD_IDE     | \
+                               CFG_CMD_ELF     | \
+                               CFG_CMD_DATE    | \
+                               CFG_CMD_EEPROM  )
+
+#define CONFIG_MAC_PARTITION
+#define CONFIG_DOS_PARTITION
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#undef CONFIG_WATCHDOG                 /* watchdog disabled            */
+
+#define CONFIG_RTC_MC146818             /* BQ3285 is MC146818 compatible*/
+#define CFG_RTC_REG_BASE_ADDR   0xF0000080 /* RTC Base Address         */
+
+#define        CONFIG_SDRAM_BANK0      1       /* init onboard SDRAM bank 0    */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_CONSOLE_INFO_QUIET  1       /* don't print console @ startup*/
+
+#define CFG_MEMTEST_START      0x0400000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0C00000       /* 4 ... 12 MB in DRAM  */
+
+#define CFG_EXT_SERIAL_CLOCK    11059200  /* use external serial clock  */
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE      \
+        { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400,     \
+         57600, 115200, 230400, 460800, 921600 }
+
+#define CFG_LOAD_ADDR  0x100000        /* default load address */
+#define CFG_EXTBDINFO  1               /* To use extended board_into (bd_t) */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_ZERO_BOOTDELAY_CHECK    /* check for keypress on bootdelay==0 */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define PCI_HOST_ADAPTER 0              /* configure ar pci adapter     */
+#define PCI_HOST_FORCE  1               /* configure as pci host        */
+#define PCI_HOST_AUTO   2               /* detected via arbiter enable  */
+
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST        PCI_HOST_AUTO   /* select pci host function     */
+#define CONFIG_PCI_PNP                 /* do pci plug-and-play         */
+                                        /* resource configuration       */
+
+#define CFG_PCI_SUBSYS_VENDORID 0x12FE  /* PCI Vendor ID: esd gmbh      */
+#define CFG_PCI_SUBSYS_DEVICEID 0x0404  /* PCI Device ID: CPCI-ISER4    */
+#define CFG_PCI_PTM1LA  0x00000000      /* point to sdram               */
+#define CFG_PCI_PTM1MS  0xff000001      /* 16MB, enable hard-wired to 1 */
+#define CFG_PCI_PTM1PCI 0x00000000      /* Host: use this pci address   */
+#define CFG_PCI_PTM2LA  0xffe00000      /* point to flash               */
+#define CFG_PCI_PTM2MS  0xffe00001      /* 2MB, enable                  */
+#define CFG_PCI_PTM2PCI 0x04000000      /* Host: use this pci address   */
+
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff
+ *-----------------------------------------------------------------------
+ */
+#undef  CONFIG_IDE_8xx_DIRECT           /* no pcmcia interface required */
+#undef  CONFIG_IDE_LED                  /* no led for ide supported     */
+#undef  CONFIG_IDE_RESET                /* no reset for ide supported   */
+
+#define        CFG_IDE_MAXBUS          1               /* max. 1 IDE busses    */
+#define        CFG_IDE_MAXDEVICE       (CFG_IDE_MAXBUS*1) /* max. 1 drives per IDE bus */
+
+#define        CFG_ATA_BASE_ADDR       0xF0100000
+#define        CFG_ATA_IDE0_OFFSET     0x0000
+
+#define CFG_ATA_DATA_OFFSET    0x0000  /* Offset for data I/O                  */
+#define        CFG_ATA_REG_OFFSET      0x0000  /* Offset for normal register accesses  */
+#define CFG_ATA_ALT_OFFSET     0x0000  /* Offset for alternate registers       */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFFD0000
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MONITOR_LEN                (192 * 1024)    /* Reserve 192 kB for Monitor   */
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     256     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#define CFG_FLASH_WORD_SIZE     unsigned short  /* flash word size (width)      */
+#define CFG_FLASH_ADDR0         0x5555  /* 1st address for flash config cycles  */
+#define CFG_FLASH_ADDR1         0x2AAA  /* 2nd address for flash config cycles  */
+/*
+ * The following defines are added for buggy IOP480 byte interface.
+ * All other boards should use the standard values (CPCI405 etc.)
+ */
+#define CFG_FLASH_READ0         0x0000  /* 0 is standard                        */
+#define CFG_FLASH_READ1         0x0001  /* 1 is standard                        */
+#define CFG_FLASH_READ2         0x0002  /* 2 is standard                        */
+
+#define CFG_FLASH_EMPTY_INFO            /* print 'E' for empty sector on flinfo */
+
+/*-----------------------------------------------------------------------
+ * I2C EEPROM (CAT24WC08) for environment
+ */
+#define CONFIG_HARD_I2C                        /* I2c with hardware support */
+#define CFG_I2C_SPEED          400000  /* I2C speed and slave address */
+#define CFG_I2C_SLAVE          0x7F
+
+#define CFG_I2C_EEPROM_ADDR    0x50    /* EEPROM CAT28WC08             */
+#define CFG_I2C_EEPROM_ADDR_LEN        1       /* Bytes of address             */
+/* mask of address bits that overflow into the "EEPROM chip address"    */
+#define CFG_I2C_EEPROM_ADDR_OVERFLOW   0x07
+#define CFG_EEPROM_PAGE_WRITE_BITS 4   /* The Catalyst CAT24WC08 has   */
+                                       /* 16 byte page write mode using*/
+                                       /* last 4 bits of the address   */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10   /* and takes up to 10 msec */
+#define CFG_EEPROM_PAGE_WRITE_ENABLE
+
+#define CFG_ENV_IS_IN_EEPROM    1       /* use EEPROM for environment vars */
+#define CFG_ENV_OFFSET          0x000   /* environment starts at the beginning of the EEPROM */
+#define CFG_ENV_SIZE            0x400   /* 1024 bytes may be used for env vars */
+                                   /* total size of a CAT24WC08 is 1024 bytes */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE                8192    /* For IBM 405 CPUs                     */
+#define CFG_CACHELINE_SIZE     32      /* ...                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0xFF800000      /* FLASH bank #0        */
+#define FLASH_BASE1_PRELIM     0xFFC00000      /* FLASH bank #1        */
+
+/*-----------------------------------------------------------------------
+ * External Bus Controller (EBC) Setup
+ */
+
+#define FLASH0_BA       0xFFC00000          /* FLASH 0 Base Address             */
+#define FLASH1_BA       0xFF800000          /* FLASH 1 Base Address             */
+#define CAN_BA          0xF0000000          /* CAN Base Address                 */
+#define DUART_BA        0xF0300000          /* DUART Base Address               */
+#define CF_BA           0xF0100000          /* CompactFlash Base Address        */
+#define SRAM_BA         0xF0200000          /* SRAM Base Address                */
+#define DURAG_IO_BA     0xF0400000          /* DURAG Bus IO Base Address        */
+#define DURAG_MEM_BA    0xF0500000          /* DURAG Bus Mem Base Address       */
+
+#define FPGA_MODE_REG   (DUART_BA+0x80)     /* FPGA Mode Register               */
+
+/* Memory Bank 0 (Flash Bank 0) initialization                                  */
+#define CFG_EBC_PB0AP   0x92015480
+#define CFG_EBC_PB0CR   FLASH0_BA | 0x5A000 /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 1 (Flash Bank 1) initialization                                  */
+#define CFG_EBC_PB1AP   0x92015480
+#define CFG_EBC_PB1CR   FLASH1_BA | 0x5A000 /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 2 (CAN0) initialization                                          */
+#define CFG_EBC_PB2AP   0x010053C0   /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB2CR   CAN_BA | 0x18000    /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 3 (DUART) initialization                                         */
+#define CFG_EBC_PB3AP   0x010053C0   /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB3CR   DUART_BA | 0x18000  /* BAS=0xF03,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 4 (CompactFlash IDE) initialization                              */
+#define CFG_EBC_PB4AP   0x010053C0   /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB4CR   CF_BA | 0x1A000     /* BAS=0xF01,BS=1MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 5 (SRAM) initialization                                          */
+#define CFG_EBC_PB5AP   0x010053C0   /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB5CR   SRAM_BA | 0x1A000   /* BAS=0xF02,BS=1MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 6 (DURAG Bus IO Space) initialization                            */
+#define CFG_EBC_PB6AP   0x010053C0   /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB6CR   DURAG_IO_BA | 0x18000 /* BAS=0xF04,BS=1MB,BU=R/W,BW=8bit*/
+
+/* Memory Bank 7 (DURAG Bus Mem Space) initialization                           */
+#define CFG_EBC_PB7AP   0x010053C0   /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB7CR   DURAG_MEM_BA | 0x18000 /* BAS=0xF05,BS=1MB,BU=R/W,BW=8bit */
+
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+
+/* use on chip memory ( OCM ) for temperary stack until sdram is tested */
+#define CFG_TEMP_STACK_OCM        1
+
+/* On Chip Memory location */
+#define CFG_OCM_DATA_ADDR      0xF8000000
+#define CFG_OCM_DATA_SIZE      0x1000
+
+#define CFG_INIT_RAM_ADDR      CFG_OCM_DATA_ADDR /* inside of SDRAM            */
+#define CFG_INIT_RAM_END       CFG_OCM_DATA_SIZE /* End of used area in RAM    */
+#define CFG_GBL_DATA_SIZE      128  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/EVB64260.h b/include/configs/EVB64260.h
new file mode 100644 (file)
index 0000000..fa7e1f6
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <asm/processor.h>
+
+#ifndef __ASSEMBLY__
+#include <galileo/core.h>
+#endif
+
+#include "../board/evb64260/local.h"
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_EVB64260                1       /* this is an EVB64260 board    */
+#define CFG_GT_6426x        GT_64260 /* with a 64260 system controller */
+
+#define CONFIG_BAUDRATE                38400   /* console baudrate = 38400     */
+
+#undef CONFIG_ECC                      /* enable ECC support */
+/* #define CONFIG_EVB64260_750CX  1 */      /* Support the EVB-64260-750CX Board */
+
+/* which initialization functions to call for this board */
+#define CONFIG_MISC_INIT_R     1
+#define CONFIG_BOARD_PRE_INIT  1
+
+#ifndef CONFIG_EVB64260_750CX
+#define CFG_BOARD_NAME         "EVB64260"
+#else
+#define CFG_BOARD_NAME         "EVB64260-750CX"
+#endif
+
+#define CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2    "> "
+
+/*
+ * The following defines let you select what serial you want to use
+ * for your console driver.
+ *
+ * what to do:
+ * to use the DUART, undef CONFIG_MPSC.  If you have hacked a serial
+ * cable onto the second DUART channel, change the CFG_DUART port from 1
+ * to 0 below.
+ *
+ * to use the MPSC, #define CONFIG_MPSC.  If you have wired up another
+ * mpsc channel, change CONFIG_MPSC_PORT to the desired value.
+ */
+#define        CONFIG_MPSC
+#define CONFIG_MPSC_PORT       0
+
+#define CONFIG_NET_MULTI        /* attempt all available adapters */
+
+/* define this if you want to enable GT MAC filtering */
+#define CONFIG_GT_USE_MAC_HASH_TABLE
+
+#undef CONFIG_ETHER_PORT_MII   /* use RMII */
+
+#if 1
+#define CONFIG_BOOTDELAY       -1      /* autoboot disabled            */
+#else
+#define CONFIG_BOOTDELAY       5       /* autoboot after 5 seconds     */
+#endif
+#define CONFIG_ZERO_BOOTDELAY_CHECK
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_BOOTCOMMAND                                                  \
+       "bootp && "                                                  \
+       "setenv bootargs root=/dev/nfs rw nfsroot=$serverip:$rootpath " \
+       "ip=$ipaddr:$serverip:$gatewayip:" \
+       "$netmask:$hostname:eth0:none; && " \
+       "bootm"
+
+#define CONFIG_LOADS_ECHO      0       /* echo off for serial download */
+#define        CFG_LOADS_BAUD_CHANGE           /* allow baudrate changes       */
+
+#undef CONFIG_WATCHDOG                 /* watchdog disabled            */
+#undef CONFIG_ALTIVEC                  /* undef to disable             */
+
+#define CONFIG_BOOTP_MASK      (CONFIG_BOOTP_DEFAULT | \
+                                CONFIG_BOOTP_BOOTFILESIZE)
+
+
+#define CONFIG_COMMANDS        (CONFIG_CMD_DFL | CFG_CMD_ASKENV)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define        CFG_LONGHELP                    /* undef to save memory         */
+#define        CFG_PROMPT      "=> "           /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define        CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define        CFG_MAXARGS     16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x00400000      /* memtest works on     */
+#define CFG_MEMTEST_END                0x00C00000      /* 4 ... 12 MB in DRAM  */
+
+#define        CFG_LOAD_ADDR           0x00300000      /* default load address */
+
+#define        CFG_HZ                  1000            /* decr freq: 1ms ticks */
+#define CFG_BUS_HZ             100000000       /* 100 MHz              */
+#define CFG_BUS_CLK            CFG_BUS_HZ
+
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200, 230400 }
+
+#ifdef CONFIG_EVB64260_750CX
+#define CONFIG_750CX
+#define CFG_BROKEN_CL2
+#endif
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area
+ */
+#define CFG_INIT_RAM_ADDR      0x40000000
+#define        CFG_INIT_RAM_END        0x1000
+#define        CFG_GBL_DATA_SIZE       128  /* size in bytes reserved for init data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_RAM_LOCK
+
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define        CFG_SDRAM_BASE          0x00000000
+#define CFG_FLASH_BASE         0xfff00000
+#define CFG_RESET_ADDRESS      0xfff00100
+#define        CFG_MONITOR_LEN         (256 << 10)     /* Reserve 256 kB for Monitor */
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define        CFG_MALLOC_LEN          (256 << 10)     /* Reserve 256 kB for malloc */
+
+/* areas to map different things with the GT in physical space */
+#define CFG_DRAM_BANKS         4
+#define CFG_DFL_GT_REGS                0x14000000      /* boot time GT_REGS */
+
+/* What to put in the bats. */
+#define CFG_MISC_REGION_BASE   0xf0000000
+
+/* Peripheral Device section */
+#define CFG_GT_REGS            0xf8000000
+#define CFG_DEV_BASE           0xfc000000
+
+#define CFG_DEV0_SPACE         CFG_DEV_BASE
+#define CFG_DEV1_SPACE         (CFG_DEV0_SPACE + CFG_DEV0_SIZE)
+#define CFG_DEV2_SPACE         (CFG_DEV1_SPACE + CFG_DEV1_SIZE)
+#define CFG_DEV3_SPACE         (CFG_DEV2_SPACE + CFG_DEV2_SIZE)
+
+#define CFG_DEV0_SIZE           _8M /* evb64260 sram  @ 0xfc00.0000 */
+#define CFG_DEV1_SIZE           _8M /* evb64260 rtc   @ 0xfc80.0000 */
+#define CFG_DEV2_SIZE          _16M /* evb64260 duart @ 0xfd00.0000 */
+#define CFG_DEV3_SIZE          _16M /* evb64260 flash @ 0xfe00.0000 */
+
+#define CFG_DEV0_PAR           0x20205093
+#define CFG_DEV1_PAR           0xcfcfffff
+#define CFG_DEV2_PAR           0xc0059bd4
+#define CFG_8BIT_BOOT_PAR      0xc00b5e7c
+#define CFG_32BIT_BOOT_PAR     0xc4a8241c
+        /*   c    4    a      8     2     4    1      c                */
+        /* 33 22|2222|22 22|111 1|11 11|1 1  |    |            */
+        /* 10 98|7654|32 10|987 6|54 32|1 098|7 654|3 210      */
+        /* 11|00|0100|10 10|100|0 00|10 0|100 0|001 1|100      */
+        /*  3| 0|.... ..| 2| 4 |  0 |  4 |  8  |  3  | 4       */
+
+#if 0 /* Wrong?? NTL */
+#define CFG_MPP_CONTROL_0      0x53541717      /* InitAct EOT[4] DBurst TCEn[1] */
+                                               /* DMAAck[1:0] GNT0[1:0] */
+#else
+#define CFG_MPP_CONTROL_0      0x53547777      /* InitAct EOT[4] DBurst TCEn[1] */
+                                               /* REQ0[1:0] GNT0[1:0] */
+#endif
+#define CFG_MPP_CONTROL_1      0x44009911      /* TCEn[4] TCTcnt[4] GPP[13:12] */
+                                               /* DMAReq[4] DMAAck[4] WDNMI WDE */
+#if 0 /* Wrong?? NTL */
+#define CFG_MPP_CONTROL_2      0x40091818      /* TCTcnt[0] GPP[22:21] BClkIn */
+                                               /* DMAAck[1:0] GNT1[1:0] */
+#else
+#define CFG_MPP_CONTROL_2      0x40098888      /* TCTcnt[0] */
+                                               /* GPP[22] (RS232IntB or PCI1Int) */
+                                               /* GPP[21] (RS323IntA) */
+                                               /* BClkIn */
+                                               /* REQ1[1:0] GNT1[1:0] */
+#endif
+
+#if 0 /* Wrong?? NTL */
+# define CFG_MPP_CONTROL_3     0x00090066      /* GPP[31:29] BClkOut0 */
+                                               /* GPP[27:26] Int[1:0] */
+#else
+# define CFG_MPP_CONTROL_3     0x22090066      /* MREQ MGNT */
+                                                /* GPP[29]    (PCI1Int) */
+                                                /* BClkOut0 */
+                                                /* GPP[27]    (PCI0Int) */
+                                                /* GPP[26]    (RtcInt or PCI1Int) */
+                                                /* CPUInt[25:24] */
+#endif
+
+# define CFG_SERIAL_PORT_MUX   0x00000102      /* 0=hiZ  1=MPSC0 2=ETH 0 and 2 RMII */
+
+#if 0 /* Wrong?? - NTL */
+# define CFG_GPP_LEVEL_CONTROL 0x000002c6
+#else
+# define CFG_GPP_LEVEL_CONTROL 0x2c600000      /* 0010 1100 0110 0000 */
+                                                /* gpp[29] */
+                                               /* gpp[27:26] */
+                                                /* gpp[22:21] */
+
+# define CFG_SDRAM_CONFIG      0xd8e18200      /* 0x448 */
+                               /* idmas use buffer 1,1
+                                  comm use buffer 0
+                                  pci use buffer 1,1
+                                  cpu use buffer 0
+                                  normal load (see also ifdef HVL)
+                                  standard SDRAM (see also ifdef REG)
+                                  non staggered refresh */
+                               /* 31:26  25 23  20 19 18 16 */
+                               /* 110110 00 111 0  0  00 1 */
+                               /* refresh_count=0x200
+                                  phisical interleaving disable
+                                  virtual interleaving enable */
+                               /* 15 14 13:0 */
+                               /* 1  0  0x200 */
+#endif
+
+#define CFG_DUART_IO           CFG_DEV2_SPACE
+#define CFG_DUART_CHAN         1               /* channel to use for console */
+#define CFG_INIT_CHAN1
+#define CFG_INIT_CHAN2
+
+#define SRAM_BASE              CFG_DEV0_SPACE
+#define SRAM_SIZE              0x00100000              /* 1 MB of sram */
+
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+
+#define PCI_HOST_ADAPTER 0              /* configure ar pci adapter     */
+#define PCI_HOST_FORCE  1               /* configure as pci host        */
+#define PCI_HOST_AUTO   2               /* detected via arbiter enable  */
+
+#define CONFIG_PCI                      /* include pci support          */
+#define CONFIG_PCI_HOST PCI_HOST_FORCE  /* select pci host function     */
+#define CONFIG_PCI_PNP                  /* do pci plug-and-play         */
+
+/* PCI MEMORY MAP section */
+#define CFG_PCI0_MEM_BASE      0x80000000
+#define CFG_PCI0_MEM_SIZE      _128M
+#define CFG_PCI1_MEM_BASE      0x88000000
+#define CFG_PCI1_MEM_SIZE      _128M
+
+#define CFG_PCI0_0_MEM_SPACE   (CFG_PCI0_MEM_BASE)
+#define CFG_PCI1_0_MEM_SPACE   (CFG_PCI1_MEM_BASE)
+
+
+
+/* PCI I/O MAP section */
+#define CFG_PCI0_IO_BASE       0xfa000000
+#define CFG_PCI0_IO_SIZE       _16M
+#define CFG_PCI1_IO_BASE       0xfb000000
+#define CFG_PCI1_IO_SIZE       _16M
+
+#define CFG_PCI0_IO_SPACE      (CFG_PCI0_IO_BASE)
+#define CFG_PCI0_IO_SPACE_PCI  0x00000000
+#define CFG_PCI1_IO_SPACE      (CFG_PCI1_IO_BASE)
+#define CFG_PCI1_IO_SPACE_PCI  0x00000000
+
+/*
+ * NS16550 Configuration
+ */
+#define CFG_NS16550
+
+#define CFG_NS16550_REG_SIZE   -4
+
+#define CFG_NS16550_CLK                3686400
+
+#define CFG_NS16550_COM1       (CFG_DUART_IO + 0)
+#define CFG_NS16550_COM2       (CFG_DUART_IO + 0x20)
+
+/*----------------------------------------------------------------------
+ * Initial BAT mappings
+ */
+
+/* NOTES:
+ * 1) GUARDED and WRITE_THRU not allowed in IBATS
+ * 2) CACHEINHIBIT and WRITETHROUGH not allowed together in same BAT
+ */
+
+/* SDRAM */
+#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_CACHEINHIBIT)
+#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+#define CFG_DBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE)
+#define CFG_DBAT0U CFG_IBAT0U
+
+/* init ram */
+#define CFG_IBAT1L  (CFG_INIT_RAM_ADDR | BATL_PP_RW | BATL_MEMCOHERENCE)
+#define CFG_IBAT1U  (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
+#define CFG_DBAT1L  CFG_IBAT1L
+#define CFG_DBAT1U  CFG_IBAT1U
+
+/* PCI0, PCI1 in one BAT */
+#define CFG_IBAT2L BATL_NO_ACCESS
+#define CFG_IBAT2U CFG_DBAT2U
+#define CFG_DBAT2L (CFG_PCI0_MEM_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE)
+#define CFG_DBAT2U (CFG_PCI0_MEM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* GT regs, bootrom, all the devices, PCI I/O */
+#define CFG_IBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW)
+#define CFG_IBAT3U (CFG_MISC_REGION_BASE | BATU_VS | BATU_VP | BATU_BL_256M)
+#define CFG_DBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE)
+#define CFG_DBAT3U CFG_IBAT3U
+
+/* I2C speed and slave address (for compatability) defaults */
+#define CFG_I2C_SPEED  400000
+#define CFG_I2C_SLAVE  0x7F
+
+/* I2C addresses for the two DIMM SPD chips */
+#ifndef CONFIG_EVB64260_750CX
+#define DIMM0_I2C_ADDR 0x56
+#define DIMM1_I2C_ADDR 0x54
+#else /* CONFIG_EVB64260_750CX - only has 1 DIMM */
+#define DIMM0_I2C_ADDR  0x54
+#define DIMM1_I2C_ADDR 0x54
+#endif
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define        CFG_BOOTMAPSZ           (8<<20) /* Initial Memory map for Linux */
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks   */
+#define CFG_MAX_FLASH_SECT     67      /* max number of sectors on one chip */
+
+#define CFG_EXTRA_FLASH_DEVICE DEVICE3 /* extra flash at device 3 */
+#define CFG_EXTRA_FLASH_WIDTH  4       /* 32 bit */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms) */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms) */
+#define CFG_FLASH_CFI          1
+
+#define        CFG_ENV_IS_IN_FLASH     1
+#define        CFG_ENV_SIZE            0x1000  /* Total Size of Environment Sector */
+#define CFG_ENV_SECT_SIZE      0x10000
+#define CFG_ENV_ADDR    (CFG_FLASH_BASE+CFG_MONITOR_LEN-CFG_ENV_SECT_SIZE)
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32      /* For all MPC74xx CPUs          */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value */
+#endif
+
+/*-----------------------------------------------------------------------
+ * L2CR setup -- make sure this is right for your board!
+ * look in include/mpc74xx.h for the defines used here
+ */
+
+#define CFG_L2
+
+#ifdef CONFIG_750CX
+#define L2_INIT 0
+#else
+#define L2_INIT        (L2CR_L2SIZ_2M | L2CR_L2CLK_3 | L2CR_L2RAM_BURST | \
+                       L2CR_L2OH_5 | L2CR_L2CTL | L2CR_L2WT)
+#endif
+
+#define L2_ENABLE      (L2_INIT | L2CR_L2E)
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define        BOOTFLAG_COLD   0x01            /* Normal Power-On: Boot from FLASH */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                  */
+
+#define CFG_BOARD_ASM_INIT      1
+
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/MUSENKI.h b/include/configs/MUSENKI.h
new file mode 100644 (file)
index 0000000..03765a3
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * (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
+ */
+
+/*
+ *
+ * Configuration settings for the MUSENKI board.
+ *
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC824X         1
+#define CONFIG_MPC8245         1
+#define CONFIG_MUSENKI         1
+
+
+#define CONFIG_CONS_INDEX      1
+#define CONFIG_BAUDRATE                9600
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_BOOTDELAY       5
+
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any)      */
+
+#include <cmd_confdefs.h>
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#undef CFG_LONGHELP                    /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+#define CFG_CBSIZE     256             /* Console I/O Buffer Size      */
+
+/* Print Buffer Size
+ */
+#define CFG_PBSIZE     (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)
+#define CFG_MAXARGS    8               /* Max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR  0x00100000      /* Default load address         */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_PCI                     /* include pci support          */
+#undef CONFIG_PCI_PNP
+
+#define CONFIG_NET_MULTI               /* Multi ethernet cards support */
+
+#define CONFIG_TULIP
+
+#define PCI_ENET0_IOADDR               0x80000000
+#define PCI_ENET0_MEMADDR              0x80000000
+#define PCI_ENET1_IOADDR               0x81000000
+#define PCI_ENET1_MEMADDR              0x81000000
+
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE     0x00000000
+
+#define CFG_FLASH_BASE0_PRELIM      0xFF800000      /* FLASH bank on RCS#0 */
+#define CFG_FLASH_BASE1_PRELIM      0xFF000000      /* FLASH bank on RCS#1 */
+#define CFG_FLASH_BASE  CFG_FLASH_BASE0_PRELIM
+
+/* even though FLASHP_BASE is FF800000, with 4MB is RCS0, the
+ * reset vector is actually located at FFB00100, but the 8245
+ * takes care of us.
+ */
+#define CFG_RESET_ADDRESS   0xFFF00100
+
+#define CFG_EUMB_ADDR      0xFC000000
+
+#define CFG_MONITOR_BASE    TEXT_BASE
+#define CFG_MONITOR_LEN            (256 << 10) /* Reserve 256 kB for Monitor   */
+#define CFG_MALLOC_LEN     (128 << 10) /* Reserve 128 kB for malloc()  */
+
+#define CFG_MEMTEST_START   0x00004000 /* memtest works on             */
+#define CFG_MEMTEST_END            0x02000000  /* 0 ... 32 MB in DRAM          */
+
+       /* Maximum amount of RAM.
+        */
+#define CFG_MAX_RAM_SIZE    0x08000000 /* 0 .. 128 MB of (S)DRAM */
+
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+#undef CFG_RAMBOOT
+#else
+#define CFG_RAMBOOT
+#endif
+
+/*
+ * NS16550 Configuration
+ */
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+
+#define CFG_NS16550_REG_SIZE   1
+
+#define CFG_NS16550_CLK                get_bus_freq(0)
+
+#define CFG_NS16550_COM1       (CFG_EUMB_ADDR + 0x4500)
+#define CFG_NS16550_COM2       (CFG_EUMB_ADDR + 0x4600)
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area
+ */
+
+/* #define CFG_MONITOR_BASE        TEXT_BASE */
+/*#define CFG_GBL_DATA_SIZE    256*/
+#define CFG_GBL_DATA_SIZE      128
+#define CFG_INIT_RAM_ADDR     0x40000000
+#define CFG_INIT_RAM_END      0x1000
+#define CFG_GBL_DATA_OFFSET  (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ * For the detail description refer to the MPC8240 user's manual.
+ */
+
+#define CONFIG_SYS_CLK_FREQ  33333333  /* external frequency to pll */
+#define CFG_HZ              1000
+
+       /* Bit-field values for MCCR1.
+        */
+#define CFG_ROMNAL         7
+#define CFG_ROMFAL         11
+#define CFG_DBUS_SIZE       0x3
+
+       /* Bit-field values for MCCR2.
+        */
+#define CFG_TSWAIT         0x5             /* Transaction Start Wait States timer */
+#define CFG_REFINT         0x400           /* Refresh interval FIXME: was 0t430                */
+
+       /* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4.
+        */
+#define CFG_BSTOPRE        121
+
+       /* Bit-field values for MCCR3.
+        */
+#define CFG_REFREC         8       /* Refresh to activate interval */
+
+       /* Bit-field values for MCCR4.
+        */
+#define CFG_PRETOACT       3       /* Precharge to activate interval FIXME: was 2      */
+#define CFG_ACTTOPRE       5       /* Activate to Precharge interval FIXME: was 5      */
+#define CFG_ACTORW         3           /* FIXME was 2 */
+#define CFG_SDMODE_CAS_LAT  3      /* SDMODE CAS latancy */
+#define CFG_SDMODE_WRAP            0       /* SDMODE wrap type */
+#define CFG_REGISTERD_TYPE_BUFFER 1
+#define CFG_EXTROM         1
+#define CFG_REGDIMM        0
+
+#define CFG_PGMAX           0x32 /* how long the 8240 reatins the currently accessed page in memory FIXME: was 0x32*/
+
+#define CFG_SDRAM_DSCD 0x20    /* SDRAM data in sample clock delay - note bottom 3 bits MUST be 0 */
+
+/* Memory bank settings.
+ * Only bits 20-29 are actually used from these vales to set the
+ * start/end addresses. The upper two bits will always be 0, and the lower
+ * 20 bits will be 0x00000 for a start address, or 0xfffff for an end
+ * address. Refer to the MPC8240 book.
+ */
+
+#define CFG_BANK0_START            0x00000000
+#define CFG_BANK0_END      (CFG_MAX_RAM_SIZE - 1)
+#define CFG_BANK0_ENABLE    1
+#define CFG_BANK1_START            0x3ff00000
+#define CFG_BANK1_END      0x3fffffff
+#define CFG_BANK1_ENABLE    0
+#define CFG_BANK2_START            0x3ff00000
+#define CFG_BANK2_END      0x3fffffff
+#define CFG_BANK2_ENABLE    0
+#define CFG_BANK3_START            0x3ff00000
+#define CFG_BANK3_END      0x3fffffff
+#define CFG_BANK3_ENABLE    0
+#define CFG_BANK4_START            0x3ff00000
+#define CFG_BANK4_END      0x3fffffff
+#define CFG_BANK4_ENABLE    0
+#define CFG_BANK5_START            0x3ff00000
+#define CFG_BANK5_END      0x3fffffff
+#define CFG_BANK5_ENABLE    0
+#define CFG_BANK6_START            0x3ff00000
+#define CFG_BANK6_END      0x3fffffff
+#define CFG_BANK6_ENABLE    0
+#define CFG_BANK7_START            0x3ff00000
+#define CFG_BANK7_END      0x3fffffff
+#define CFG_BANK7_ENABLE    0
+
+#define CFG_ODCR           0xff
+
+#define CFG_IBAT0L  (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U  (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT1L  (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT1U  (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
+
+#define CFG_IBAT2L  (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U  (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT3L  (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U  (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L  CFG_IBAT0L
+#define CFG_DBAT0U  CFG_IBAT0U
+#define CFG_DBAT1L  CFG_IBAT1L
+#define CFG_DBAT1U  CFG_IBAT1U
+#define CFG_DBAT2L  CFG_IBAT2L
+#define CFG_DBAT2U  CFG_IBAT2U
+#define CFG_DBAT3L  CFG_IBAT3L
+#define CFG_DBAT3U  CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ      (8 << 20)   /* Initial Memory map for Linux */
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* Max number of flash banks            */
+#define CFG_MAX_FLASH_SECT     64      /* Max number of sectors per flash      */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms) */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms) */
+
+
+       /* Warining: environment is not EMBEDDED in the U-Boot code.
+        * It's stored in flash separately.
+        */
+#define CFG_ENV_IS_IN_FLASH        1
+#define CFG_ENV_ADDR           0xFFFF0000
+#define CFG_ENV_SIZE           0x00010000 /* Size of the Environment           */
+#define CFG_ENV_SECT_SIZE      0x20000 /* Size of the Environment Sector       */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#  define CFG_CACHELINE_SHIFT  5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                      */
+
+
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/MVS1.h b/include/configs/MVS1.h
new file mode 100644 (file)
index 0000000..d10fa8f
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC823          1       /* This is a MPC823 CPU         */
+#define CONFIG_MVS             1       /* ...on a MVsensor module      */
+#define CONFIG_MVS_16BIT_FLASH         /* ...with 16-bit flash access  */
+#define CONFIG_8xx_GCLK_FREQ   50000000/* ... and a 50 MHz CPU         */
+
+#define        CONFIG_CLOCKS_IN_MHZ    1       /* clocks passsed to Linux in MHz */
+
+#undef CONFIG_8xx_CONS_SMC1            /* Console is *NOT* on SMC1     */
+#define        CONFIG_8xx_CONS_SMC2    1       /* Console is on SMC2           */
+#undef CONFIG_8xx_CONS_NONE
+#define CONFIG_BAUDRATE                115200  /* console baudrate             */
+#define CONFIG_BOOTDELAY       5       /* autoboot after this many seconds     */
+
+#define CONFIG_PREBOOT         "echo;echo To mount root over NFS use \"run bootnet\";echo To mount root from FLASH use  \"run bootflash\";echo"
+#define        CONFIG_BOOTARGS         "root=/dev/mtdblock2 rw"
+#define CONFIG_BOOTCOMMAND                                             \
+    "bootp; "                                                          \
+    "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \
+    "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; "   \
+    "bootm"
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#undef CFG_LOADS_BAUD_CHANGE           /* don't allow baudrate change  */
+
+#define        CONFIG_WATCHDOG                 /* watchdog disabled/enabled    */
+
+#undef CONFIG_STATUS_LED               /* Status LED disabled/enabled  */
+
+#undef  CONFIG_CAN_DRIVER       /* CAN Driver support disabled  */
+
+#define CONFIG_BOOTP_MASK      (CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_VENDOREX )
+
+#undef CONFIG_MAC_PARTITION
+#undef CONFIG_DOS_PARTITION
+
+#define        CONFIG_RTC_MPC8xx               /* use internal RTC of MPC8xx   */
+
+/* MVsensor uses a really minimal U-Boot ! */
+#define CONFIG_COMMANDS               (CFG_CMD_LOADS   | \
+                               CFG_CMD_LOADB   | \
+                               CFG_CMD_IMI     | \
+                               CFG_CMD_FLASH   | \
+                               CFG_CMD_MEMORY  | \
+                               CFG_CMD_NET     | \
+                               CFG_CMD_DHCP    | \
+                               CFG_CMD_ENV     | \
+                               CFG_CMD_BOOTD   | \
+                               CFG_CMD_RUN     )
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#undef CFG_LONGHELP                    /* undef to save memory         */
+#define        CFG_PROMPT              "=> "   /* Monitor Command Prompt       */
+
+#undef  CFG_HUSH_PARSER                        /* Hush parse for U-Boot ?? */
+#ifdef  CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2     "> "
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define        CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define        CFG_MAXARGS     16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x0400000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0C00000       /* 4 ... 12 MB in DRAM  */
+
+#define        CFG_LOAD_ADDR           0x100000        /* default load address */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+/*-----------------------------------------------------------------------
+ * Internal Memory Mapped Register
+ */
+#define CFG_IMMR               0xFFF00000
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR      CFG_IMMR
+#define        CFG_INIT_RAM_END        0x2F00  /* End of used area in DPRAM    */
+#define        CFG_GBL_DATA_SIZE       64  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define        CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define        CFG_SDRAM_BASE          0x00000000
+#define CFG_FLASH_BASE         0x40000000
+
+#define        CFG_MONITOR_LEN         (128 << 10)     /* Reserve 192 kB for Monitor   */
+
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define        CFG_MALLOC_LEN          (128 << 10)     /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define        CFG_BOOTMAPSZ           (8 << 20)       /* Initial Memory map for Linux */
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    1       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     71      /* max number of sectors on one chip (for AMD320DB chip)        */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#define        CFG_ENV_IS_IN_FLASH     1
+
+/* 4MB flash - use bottom sectors of a bottom boot sector flash (16 bit access) */
+#define        CFG_ENV_OFFSET          0x8000  /* Offset of Environment Sector (bottom boot sector) */
+#define        CFG_ENV_SIZE            0x2000  /* Used Size of Environment Sector 8k   */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     16      /* For all MPC8xx CPUs                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    4       /* log base 2 of the above value        */
+#endif
+
+/*-----------------------------------------------------------------------
+ * SYPCR - System Protection Control                           11-9
+ * SYPCR can only be written once after reset!
+ *-----------------------------------------------------------------------
+ * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze
+ */
+#if defined(CONFIG_WATCHDOG)
+#define CFG_SYPCR   (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \
+             SYPCR_SWE  | SYPCR_SWRI| SYPCR_SWP)
+#else
+#define CFG_SYPCR   (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP)
+#endif
+
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration                           11-6
+ *-----------------------------------------------------------------------
+ * PCMCIA config., multi-function pin tri-state
+ */
+#define CFG_SIUMCR  (SIUMCR_DBGC00 | SIUMCR_DBPC00 | SIUMCR_MLRC01)
+
+/*-----------------------------------------------------------------------
+ * TBSCR - Time Base Status and Control                                11-26
+ *-----------------------------------------------------------------------
+ * Clear Reference Interrupt Status, Timebase freezing enabled
+ */
+#define CFG_TBSCR      (TBSCR_REFA | TBSCR_REFB | TBSCR_TBF)
+
+/*-----------------------------------------------------------------------
+ * RTCSC - Real-Time Clock Status and Control Register         11-27
+ *-----------------------------------------------------------------------
+ */
+#define CFG_RTCSC      (RTCSC_SEC | RTCSC_ALR | RTCSC_RTF| RTCSC_RTE)
+
+/*-----------------------------------------------------------------------
+ * PISCR - Periodic Interrupt Status and Control               11-31
+ *-----------------------------------------------------------------------
+ * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled
+ */
+#define CFG_PISCR      (PISCR_PS | PISCR_PITF)
+
+/*-----------------------------------------------------------------------
+ * PLPRCR - PLL, Low-Power, and Reset Control Register         15-30
+ *-----------------------------------------------------------------------
+ * Reset PLL lock status sticky bit, timer expired status bit and timer
+ * interrupt status bit
+ *
+ */
+#define CFG_PLPRCR     (PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST)
+
+/*-----------------------------------------------------------------------
+ * SCCR - System Clock and reset Control Register              15-27
+ *-----------------------------------------------------------------------
+ * Set clock output, timebase and RTC source and divider,
+ * power management and some other internal clocks
+ */
+#define SCCR_MASK      SCCR_EBDF11
+#define CFG_SCCR       (SCCR_TBS     | \
+                        SCCR_COM00   | SCCR_DFSYNC00 | SCCR_DFBRG00  | \
+                        SCCR_DFNL000 | SCCR_DFNH000  | SCCR_DFLCD000 | \
+                        SCCR_DFALCD00)
+
+/*-----------------------------------------------------------------------
+ * PCMCIA stuff
+ *-----------------------------------------------------------------------
+ *
+ */
+#define CFG_PCMCIA_MEM_ADDR    (0xE0000000)
+#define CFG_PCMCIA_MEM_SIZE    ( 64 << 20 )
+#define CFG_PCMCIA_DMA_ADDR    (0xE4000000)
+#define CFG_PCMCIA_DMA_SIZE    ( 64 << 20 )
+#define CFG_PCMCIA_ATTRB_ADDR  (0xE8000000)
+#define CFG_PCMCIA_ATTRB_SIZE  ( 64 << 20 )
+#define CFG_PCMCIA_IO_ADDR     (0xEC000000)
+#define CFG_PCMCIA_IO_SIZE     ( 64 << 20 )
+
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter)
+ *-----------------------------------------------------------------------
+ */
+
+#define        CONFIG_IDE_PCCARD       0       /* **DON'T** Use IDE with PC Card Adapter       */
+
+#undef CONFIG_IDE_PCMCIA               /* Direct IDE    not supported  */
+#undef CONFIG_IDE_LED                  /* LED   for ide not supported  */
+#undef CONFIG_IDE_RESET                /* reset for ide not supported  */
+
+#define CFG_IDE_MAXBUS         0       /* max. no. of IDE buses                        */
+#define CFG_IDE_MAXDEVICE      0       /* max. no. of drives per IDE bus       */
+
+
+#define CFG_ATA_IDE0_OFFSET    0x0000
+
+#define CFG_ATA_BASE_ADDR      CFG_PCMCIA_MEM_ADDR
+
+/* Offset for data I/O                 */
+#define CFG_ATA_DATA_OFFSET    (CFG_PCMCIA_MEM_SIZE + 0x320)
+
+/* Offset for normal register accesses */
+#define CFG_ATA_REG_OFFSET     (2 * CFG_PCMCIA_MEM_SIZE + 0x320)
+
+/* Offset for alternate registers      */
+#define CFG_ATA_ALT_OFFSET     0x0100
+
+/*-----------------------------------------------------------------------
+ *
+ *-----------------------------------------------------------------------
+ *
+ */
+/*#define      CFG_DER 0x2002000F*/
+#define CFG_DER        0
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0x40000000      /* FLASH bank #0        */
+#undef FLASH_BASE1_PRELIM
+
+/* used to re-map FLASH both when starting from SRAM or FLASH:
+ * restrict access enough to keep SRAM working (if any)
+ * but not too much to meddle with FLASH accesses
+ */
+#define CFG_REMAP_OR_AM                0x80000000      /* OR addr mask */
+#define CFG_PRELIM_OR_AM       0xE0000000      /* OR addr mask */
+
+
+/*
+ * FLASH timing:
+ */
+/* 50 MHz CPU - 50 MHz bus: ACS = 00, TRLX = 1, CSNT = 1, SCY = 2, EHTR = 1 */
+#define CFG_OR_TIMING_FLASH    (OR_ACS_DIV1  | OR_TRLX | OR_CSNT_SAM | \
+                                OR_SCY_2_CLK | OR_EHTR | OR_BI)
+/* FLASH timing: ACS = 11, TRLX = 0, CSNT = 1, SCY = 5, EHTR = 1       */
+/*
+#define CFG_OR_TIMING_FLASH    (OR_CSNT_SAM  | OR_ACS_DIV2 | OR_BI | \
+                                OR_SCY_5_CLK | OR_EHTR)
+*/
+
+#define CFG_OR0_REMAP  (CFG_REMAP_OR_AM  | CFG_OR_TIMING_FLASH)
+#define CFG_OR0_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_FLASH)
+#ifdef CONFIG_MVS_16BIT_FLASH
+#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_PS_16 | BR_V )
+#else
+#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_PS_32 | BR_V )
+#endif
+
+#undef CFG_OR1_REMAP
+#undef CFG_OR1_PRELIM
+#undef CFG_BR1_PRELIM
+/*
+ * BR2/3 and OR2/3 (SDRAM)
+ *
+ */
+#define SDRAM_BASE2_PRELIM     0x00000000      /* SDRAM bank #0        */
+#undef SDRAM_BASE3_PRELIM
+#define        SDRAM_MAX_SIZE          0x04000000      /* max 64 MB per bank   */
+
+/* SDRAM timing: Multiplexed addresses, GPL5 output to GPL5_A (don't care)     */
+#define CFG_OR_TIMING_SDRAM    0x00000A00
+
+#define CFG_OR2_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_SDRAM )
+#define CFG_BR2_PRELIM ((SDRAM_BASE2_PRELIM & BR_BA_MSK) | BR_MS_UPMA | BR_V )
+
+#undef CFG_OR3_PRELIM
+#undef CFG_BR3_PRELIM
+
+
+/*
+ * Memory Periodic Timer Prescaler
+ *
+ * The Divider for PTA (refresh timer) configuration is based on an
+ * example SDRAM configuration (64 MBit, one bank). The adjustment to
+ * the number of chip selects (NCS) and the actually needed refresh
+ * rate is done by setting MPTPR.
+ *
+ * PTA is calculated from
+ *     PTA = (gclk * Trefresh) / ((2 ^ (2 * DFBRG)) * PTP * NCS)
+ *
+ *     gclk      CPU clock (not bus clock!)
+ *     Trefresh  Refresh cycle * 4 (four word bursts used)
+ *
+ * 4096  Rows from SDRAM example configuration
+ * 1000  factor s -> ms
+ *   32  PTP (pre-divider from MPTPR) from SDRAM example configuration
+ *    4  Number of refresh cycles per period
+ *   64  Refresh cycle in ms per number of rows
+ * --------------------------------------------
+ * Divider = 4096 * 32 * 1000 / (4 * 64) = 512000
+ *
+ * 50 MHz => 50.000.000 / Divider =  98
+ * 66 Mhz => 66.000.000 / Divider = 129
+ * 80 Mhz => 80.000.000 / Divider = 156
+ */
+#define CFG_MAMR_PTA            98
+
+/* refresh rate 15.6 us (= 64 ms / 4K = 62.4 / quad bursts) for <= 128 MBit    */
+#define CFG_MPTPR_2BK_4K       MPTPR_PTP_DIV16         /* setting for 2 banks  */
+#define CFG_MPTPR_1BK_4K       MPTPR_PTP_DIV32         /* setting for 1 bank   */
+
+/* refresh rate 7.8 us (= 64 ms / 8K = 31.2 / quad bursts) for 256 MBit                */
+#define CFG_MPTPR_2BK_8K       MPTPR_PTP_DIV8          /* setting for 2 banks  */
+#define CFG_MPTPR_1BK_8K       MPTPR_PTP_DIV16         /* setting for 1 bank   */
+
+/*
+ * MAMR settings for SDRAM
+ */
+
+/* 8 column SDRAM */
+#define CFG_MAMR_8COL  ((CFG_MAMR_PTA << MAMR_PTA_SHIFT)  | MAMR_PTAE      |   \
+                        MAMR_AMA_TYPE_0 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A11 |   \
+                        MAMR_RLFA_1X    | MAMR_WLFA_1X    | MAMR_TLFA_4X)
+/* 9 column SDRAM */
+#define CFG_MAMR_9COL  ((CFG_MAMR_PTA << MAMR_PTA_SHIFT)  | MAMR_PTAE      |   \
+                        MAMR_AMA_TYPE_1 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A7 |    \
+                        MAMR_RLFA_1X    | MAMR_WLFA_1X    | MAMR_TLFA_4X)
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define        BOOTFLAG_COLD   0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/OCRTC.h b/include/configs/OCRTC.h
new file mode 100644 (file)
index 0000000..5971fb4
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_405GP           1       /* This is a PPC405 CPU         */
+#define CONFIG_4xx             1       /* ...member of PPC4xx family   */
+#define CONFIG_OCRTC                   1       /* ...on a OCRTC board          */
+
+#define CONFIG_BOARD_PRE_INIT   1       /* call board_pre_init()        */
+
+#define CONFIG_SYS_CLK_FREQ     33000000 /* external frequency to pll   */
+
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_BOOTDELAY       3       /* autoboot after 3 seconds     */
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_BOOTCOMMAND "go fff00100"
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#define CFG_LOADS_BAUD_CHANGE  1       /* allow baudrate change        */
+
+#define CONFIG_MII             1       /* MII PHY management           */
+#define        CONFIG_PHY_ADDR         0       /* PHY address                  */
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_PCI     | \
+                               CFG_CMD_IRQ     | \
+                               CFG_CMD_ASKENV  | \
+                               CFG_CMD_ELF     | \
+                               CFG_CMD_EEPROM  )
+
+#define CONFIG_MAC_PARTITION
+#define CONFIG_DOS_PARTITION
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#undef  CONFIG_WATCHDOG                        /* watchdog disabled            */
+
+#define        CONFIG_SDRAM_BANK0      1       /* init onboard SDRAM bank 0    */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_CONSOLE_INFO_QUIET  1       /* don't print console @ startup*/
+
+#define CFG_MEMTEST_START      0x0400000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0C00000       /* 4 ... 12 MB in DRAM  */
+
+#undef  CFG_EXT_SERIAL_CLOCK           /* no external serial clock used */
+#define CFG_IGNORE_405_UART_ERRATA_59   /* ignore ppc405gp errata #59   */
+#define CFG_BASE_BAUD       691200
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE      \
+        { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400,     \
+         57600, 115200, 230400, 460800, 921600 }
+
+#define CFG_LOAD_ADDR  0x100000        /* default load address */
+#define CFG_EXTBDINFO  1               /* To use extended board_into (bd_t) */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_ZERO_BOOTDELAY_CHECK    /* check for keypress on bootdelay==0 */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define PCI_HOST_ADAPTER 0              /* configure as pci adapter     */
+#define PCI_HOST_FORCE  1               /* configure as pci host        */
+#define PCI_HOST_AUTO   2               /* detected via arbiter enable  */
+
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST        PCI_HOST_AUTO   /* select pci host function     */
+#define CONFIG_PCI_PNP                 /* do pci plug-and-play         */
+                                        /* resource configuration       */
+
+#define CONFIG_PCI_SCAN_SHOW            /* print pci devices @ startup  */
+
+#define CFG_PCI_SUBSYS_VENDORID 0x12FE  /* PCI Vendor ID: esd gmbh      */
+#define CFG_PCI_SUBSYS_DEVICEID 0x0410  /* PCI Device ID: OCRTC         */
+#define CFG_PCI_CLASSCODE       0x0b20  /* PCI Class Code: Processor/PPC*/
+#define CFG_PCI_PTM1LA  0x00000000      /* point to sdram               */
+#define CFG_PCI_PTM1MS  0xfc000001      /* 64MB, enable hard-wired to 1 */
+#define CFG_PCI_PTM1PCI 0x00000000      /* Host: use this pci address   */
+#define CFG_PCI_PTM2LA  0xffc00000      /* point to flash               */
+#define CFG_PCI_PTM2MS  0xffc00001      /* 4MB, enable                  */
+#define CFG_PCI_PTM2PCI 0x04000000      /* Host: use this pci address   */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFFD0000
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MONITOR_LEN                (192 * 1024)    /* Reserve 192 kB for Monitor   */
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     256     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#define CFG_FLASH_WORD_SIZE     unsigned short  /* flash word size (width)      */
+#define CFG_FLASH_ADDR0         0x5555  /* 1st address for flash config cycles  */
+#define CFG_FLASH_ADDR1         0x2AAA  /* 2nd address for flash config cycles  */
+/*
+ * The following defines are added for buggy IOP480 byte interface.
+ * All other boards should use the standard values (CPCI405 etc.)
+ */
+#define CFG_FLASH_READ0         0x0000  /* 0 is standard                        */
+#define CFG_FLASH_READ1         0x0001  /* 1 is standard                        */
+#define CFG_FLASH_READ2         0x0002  /* 2 is standard                        */
+
+#define CFG_FLASH_EMPTY_INFO            /* print 'E' for empty sector on flinfo */
+
+#if 0 /* Use NVRAM for environment variables */
+/*-----------------------------------------------------------------------
+ * NVRAM organization
+ */
+#define CFG_ENV_IS_IN_NVRAM    1       /* use NVRAM for environment vars       */
+#define CFG_NVRAM_BASE_ADDR    0xf0200000              /* NVRAM base address   */
+#define CFG_NVRAM_SIZE         (32*1024)               /* NVRAM size           */
+#define CFG_ENV_SIZE           0x1000          /* Size of Environment vars     */
+#define CFG_ENV_ADDR           \
+       (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-CFG_ENV_SIZE)       /* Env  */
+#define CFG_NVRAM_VXWORKS_OFFS 0x6900          /* Offset for VxWorks eth-addr  */
+
+#else /* Use EEPROM for environment variables */
+
+#define CFG_ENV_IS_IN_EEPROM    1       /* use EEPROM for environment vars */
+#define CFG_ENV_OFFSET          0x000   /* environment starts at the beginning of the EEPROM */
+#define CFG_ENV_SIZE            0x300   /* 768 bytes may be used for env vars */
+                                   /* total size of a CAT24WC08 is 1024 bytes */
+#endif
+
+/*-----------------------------------------------------------------------
+ * I2C EEPROM (CAT24WC08) for environment
+ */
+#define CONFIG_HARD_I2C                        /* I2c with hardware support */
+#define CFG_I2C_SPEED          400000  /* I2C speed and slave address */
+#define CFG_I2C_SLAVE          0x7F
+
+#define CFG_I2C_EEPROM_ADDR    0x50    /* EEPROM CAT28WC08             */
+#define CFG_I2C_EEPROM_ADDR_LEN        1       /* Bytes of address             */
+/* mask of address bits that overflow into the "EEPROM chip address"    */
+#define CFG_I2C_EEPROM_ADDR_OVERFLOW   0x07
+#define CFG_EEPROM_PAGE_WRITE_BITS 4   /* The Catalyst CAT24WC08 has   */
+                                       /* 16 byte page write mode using*/
+                                       /* last 4 bits of the address   */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10   /* and takes up to 10 msec */
+#define CFG_EEPROM_PAGE_WRITE_ENABLE
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE                8192    /* For IBM 405 CPUs                     */
+#define CFG_CACHELINE_SIZE     32      /* ...                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0xFF800000      /* FLASH bank #0        */
+#define FLASH_BASE1_PRELIM     0xFFC00000      /* FLASH bank #1        */
+
+/*-----------------------------------------------------------------------
+ * External Bus Controller (EBC) Setup
+ */
+
+/* Memory Bank 0 (Flash Bank 0) initialization                                  */
+#define CFG_EBC_PB0AP           0x92015480
+#define CFG_EBC_PB0CR           0xFFC5A000  /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 1 (Flash Bank 1) initialization                                  */
+#define CFG_EBC_PB1AP           0x92015480
+#define CFG_EBC_PB1CR           0xFF85A000  /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 2 (PLD - FPGA-boot) initialization                               */
+#define CFG_EBC_PB2AP           0x02015480  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x0,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB2CR           0xF0018000  /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 3 (PLD - OSL) initialization                                     */
+#define CFG_EBC_PB3AP           0x02015480  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x0,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB3CR           0xF0118000  /* BAS=0xF01,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 4 (Spartan2 1) initialization                                    */
+#define CFG_EBC_PB4AP           0x02015580  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB4CR           0xF209C000  /* BAS=0xF20,BS=16MB,BU=R/W,BW=32bit*/
+
+/* Memory Bank 5 (Spartan2 2) initialization                                    */
+#define CFG_EBC_PB5AP           0x02015580  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB5CR           0xF309C000  /* BAS=0xF30,BS=16MB,BU=R/W,BW=32bit*/
+
+/* Memory Bank 6 (Virtex 1) initialization                                      */
+#define CFG_EBC_PB6AP           0x02015580  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB6CR           0xF409A000  /* BAS=0xF40,BS=16MB,BU=R/W,BW=16bit*/
+
+/* Memory Bank 7 (Virtex 2) initialization                                      */
+#define CFG_EBC_PB7AP           0x02015580  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB7CR           0xF509A000  /* BAS=0xF50,BS=16MB,BU=R/W,BW=16bit*/
+
+
+#define CFG_ETHERNET_MAC_ADDR   0x00000000      /* Pass Ethernet MAC to VxWorks */
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+
+/* use on chip memory ( OCM ) for temperary stack until sdram is tested */
+#define CFG_TEMP_STACK_OCM        1
+
+/* On Chip Memory location */
+#define CFG_OCM_DATA_ADDR      0xF8000000
+#define CFG_OCM_DATA_SIZE      0x1000
+
+#define CFG_INIT_RAM_ADDR      CFG_OCM_DATA_ADDR /* inside of SDRAM            */
+#define CFG_INIT_RAM_END       CFG_OCM_DATA_SIZE /* End of used area in RAM    */
+#define CFG_GBL_DATA_SIZE      128  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/ORSG.h b/include/configs/ORSG.h
new file mode 100644 (file)
index 0000000..7c161c6
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_405GP           1       /* This is a PPC405 CPU         */
+#define CONFIG_4xx             1       /* ...member of PPC4xx family   */
+#define CONFIG_ORSG            1       /* ...on a ORSG board           */
+
+#define CONFIG_BOARD_PRE_INIT   1       /* call board_pre_init()        */
+
+#define CONFIG_SYS_CLK_FREQ     33000000 /* external frequency to pll   */
+
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_BOOTDELAY       3       /* autoboot after 3 seconds     */
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_BOOTCOMMAND "go fff00100"
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#define CFG_LOADS_BAUD_CHANGE  1       /* allow baudrate change        */
+
+#define CONFIG_MII             1       /* MII PHY management           */
+#define        CONFIG_PHY_ADDR         0       /* PHY address                  */
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_PCI     | \
+                               CFG_CMD_IRQ     | \
+                               CFG_CMD_ASKENV  | \
+                               CFG_CMD_ELF     | \
+                               CFG_CMD_EEPROM  )
+
+#define CONFIG_MAC_PARTITION
+#define CONFIG_DOS_PARTITION
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#undef  CONFIG_WATCHDOG                        /* watchdog disabled            */
+
+#define        CONFIG_SDRAM_BANK0      1       /* init onboard SDRAM bank 0    */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_CONSOLE_INFO_QUIET  1       /* don't print console @ startup*/
+
+#define CFG_MEMTEST_START      0x0400000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0C00000       /* 4 ... 12 MB in DRAM  */
+
+#undef  CFG_EXT_SERIAL_CLOCK           /* no external serial clock used */
+#define CFG_IGNORE_405_UART_ERRATA_59   /* ignore ppc405gp errata #59   */
+#define CFG_BASE_BAUD       691200
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE      \
+        { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400,     \
+         57600, 115200, 230400, 460800, 921600 }
+
+#define CFG_LOAD_ADDR  0x100000        /* default load address */
+#define CFG_EXTBDINFO  1               /* To use extended board_into (bd_t) */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_ZERO_BOOTDELAY_CHECK    /* check for keypress on bootdelay==0 */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define PCI_HOST_ADAPTER 0              /* configure as pci adapter     */
+#define PCI_HOST_FORCE  1               /* configure as pci host        */
+#define PCI_HOST_AUTO   2               /* detected via arbiter enable  */
+
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST        PCI_HOST_ADAPTER /* select pci adapter          */
+#undef  CONFIG_PCI_PNP                 /* no pci plug-and-play         */
+                                        /* resource configuration       */
+
+#undef  CONFIG_PCI_SCAN_SHOW            /* print pci devices @ startup  */
+
+#define CFG_PCI_SUBSYS_VENDORID 0x12FE  /* PCI Vendor ID: esd gmbh      */
+#define CFG_PCI_SUBSYS_DEVICEID 0x0411  /* PCI Device ID: ORSG          */
+#define CFG_PCI_CLASSCODE       0x0b20  /* PCI Class Code: Processor/PPC*/
+#define CFG_PCI_PTM1LA  0x00000000      /* point to sdram               */
+#define CFG_PCI_PTM1MS  0xfc000001      /* 64MB, enable hard-wired to 1 */
+#define CFG_PCI_PTM1PCI 0x00000000      /* Host: use this pci address   */
+#define CFG_PCI_PTM2LA  0xffc00000      /* point to flash               */
+#define CFG_PCI_PTM2MS  0xffc00001      /* 4MB, enable                  */
+#define CFG_PCI_PTM2PCI 0x04000000      /* Host: use this pci address   */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFFD0000
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MONITOR_LEN                (192 * 1024)    /* Reserve 192 kB for Monitor   */
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     256     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#define CFG_FLASH_WORD_SIZE     unsigned short  /* flash word size (width)      */
+#define CFG_FLASH_ADDR0         0x5555  /* 1st address for flash config cycles  */
+#define CFG_FLASH_ADDR1         0x2AAA  /* 2nd address for flash config cycles  */
+/*
+ * The following defines are added for buggy IOP480 byte interface.
+ * All other boards should use the standard values (CPCI405 etc.)
+ */
+#define CFG_FLASH_READ0         0x0000  /* 0 is standard                        */
+#define CFG_FLASH_READ1         0x0001  /* 1 is standard                        */
+#define CFG_FLASH_READ2         0x0002  /* 2 is standard                        */
+
+#define CFG_FLASH_EMPTY_INFO            /* print 'E' for empty sector on flinfo */
+
+#if 0 /* Use NVRAM for environment variables */
+/*-----------------------------------------------------------------------
+ * NVRAM organization
+ */
+#define CFG_ENV_IS_IN_NVRAM    1       /* use NVRAM for environment vars       */
+#define CFG_NVRAM_BASE_ADDR    0xf0200000              /* NVRAM base address   */
+#define CFG_NVRAM_SIZE         (32*1024)               /* NVRAM size           */
+#define CFG_ENV_SIZE           0x1000          /* Size of Environment vars     */
+#define CFG_ENV_ADDR           \
+       (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-CFG_ENV_SIZE)       /* Env  */
+#define CFG_NVRAM_VXWORKS_OFFS 0x6900          /* Offset for VxWorks eth-addr  */
+
+#else /* Use EEPROM for environment variables */
+
+#define CFG_ENV_IS_IN_EEPROM    1       /* use EEPROM for environment vars */
+#define CFG_ENV_OFFSET          0x000   /* environment starts at the beginning of the EEPROM */
+#define CFG_ENV_SIZE            0x300   /* 768 bytes may be used for env vars */
+                                   /* total size of a CAT24WC08 is 1024 bytes */
+#endif
+
+/*-----------------------------------------------------------------------
+ * I2C EEPROM (CAT24WC08) for environment
+ */
+#define CONFIG_HARD_I2C                        /* I2c with hardware support */
+#define CFG_I2C_SPEED          400000  /* I2C speed and slave address */
+#define CFG_I2C_SLAVE          0x7F
+
+#define CFG_I2C_EEPROM_ADDR    0x50    /* EEPROM CAT28WC08             */
+#define CFG_I2C_EEPROM_ADDR_LEN        1       /* Bytes of address             */
+/* mask of address bits that overflow into the "EEPROM chip address"    */
+#define CFG_I2C_EEPROM_ADDR_OVERFLOW   0x07
+#define CFG_EEPROM_PAGE_WRITE_BITS 4   /* The Catalyst CAT24WC08 has   */
+                                       /* 16 byte page write mode using*/
+                                       /* last 4 bits of the address   */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10   /* and takes up to 10 msec */
+#define CFG_EEPROM_PAGE_WRITE_ENABLE
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE                8192    /* For IBM 405 CPUs                     */
+#define CFG_CACHELINE_SIZE     32      /* ...                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0xFF800000      /* FLASH bank #0        */
+#define FLASH_BASE1_PRELIM     0xFFC00000      /* FLASH bank #1        */
+
+/*-----------------------------------------------------------------------
+ * External Bus Controller (EBC) Setup
+ */
+
+/* Memory Bank 0 (Flash Bank 0) initialization                                  */
+#define CFG_EBC_PB0AP           0x92015480
+#define CFG_EBC_PB0CR           0xFFC5A000  /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 1 (Flash Bank 1) initialization                                  */
+#define CFG_EBC_PB1AP           0x92015480
+#define CFG_EBC_PB1CR           0xFF85A000  /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 2 (PLD - FPGA-boot) initialization                               */
+#define CFG_EBC_PB2AP           0x02015480  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x0,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB2CR           0xF0018000  /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 3 (PLD - OSL) initialization                                     */
+#define CFG_EBC_PB3AP           0x02015480  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x0,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB3CR           0xF0118000  /* BAS=0xF01,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 4 (Spartan2 1) initialization                                    */
+#define CFG_EBC_PB4AP           0x02015580  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB4CR           0xF209C000  /* BAS=0xF20,BS=16MB,BU=R/W,BW=32bit*/
+
+/* Memory Bank 5 (Spartan2 2) initialization                                    */
+#define CFG_EBC_PB5AP           0x02015580  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB5CR           0xF309C000  /* BAS=0xF30,BS=16MB,BU=R/W,BW=32bit*/
+
+/* Memory Bank 6 (Virtex 1) initialization                                      */
+#define CFG_EBC_PB6AP           0x02015580  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB6CR           0xF409A000  /* BAS=0xF40,BS=16MB,BU=R/W,BW=16bit*/
+
+/* Memory Bank 7 (Virtex 2) initialization                                      */
+#define CFG_EBC_PB7AP           0x02015580  /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */
+                                            /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/
+#define CFG_EBC_PB7CR           0xF509A000  /* BAS=0xF50,BS=16MB,BU=R/W,BW=16bit*/
+
+
+#define CFG_ETHERNET_MAC_ADDR   0x00000000      /* Pass Ethernet MAC to VxWorks */
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+
+/* use on chip memory ( OCM ) for temperary stack until sdram is tested */
+#define CFG_TEMP_STACK_OCM        1
+
+/* On Chip Memory location */
+#define CFG_OCM_DATA_ADDR      0xF8000000
+#define CFG_OCM_DATA_SIZE      0x1000
+
+#define CFG_INIT_RAM_ADDR      CFG_OCM_DATA_ADDR /* inside of SDRAM            */
+#define CFG_INIT_RAM_END       CFG_OCM_DATA_SIZE /* End of used area in RAM    */
+#define CFG_GBL_DATA_SIZE      128  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/OXC.h b/include/configs/OXC.h
new file mode 100644 (file)
index 0000000..7a60e4b
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * (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
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC824X         1
+#define CONFIG_MPC8240         1
+#define CONFIG_OXC             1
+
+#define CONFIG_BOARD_PRE_INIT  1       /* Call board_pre_init  */
+
+#define CONFIG_IDENT_STRING     " [oxc] "
+
+#define CONFIG_WATCHDOG                1
+#define CONFIG_SHOW_ACTIVITY   1
+#define CONFIG_SHOW_BOOT_PROGRESS 1
+
+#define CONFIG_CONS_INDEX      1
+#define CONFIG_BAUDRATE                9600
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | CFG_CMD_ELF)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any)      */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP           1               /* undef to save memory         */
+#define CFG_PROMPT             "=> "           /* Monitor Command Prompt       */
+#define CFG_CBSIZE             256             /* Console I/O Buffer Size      */
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)  /* Print Buffer Size    */
+#define CFG_MAXARGS            16              /* max number of command args   */
+#define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR          0x00100000      /* default load address         */
+#define CFG_HZ                 1000            /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_MISC_INIT_R     1               /* call misc_init_r() on init   */
+
+/*-----------------------------------------------------------------------
+ * Boot options
+ */
+
+#define CONFIG_SERVERIP                10.0.0.1
+#define CONFIG_GATEWAYIP       10.0.0.1
+#define CONFIG_NETMASK         255.255.255.0
+#define CONFIG_LOADADDR                0x10000
+#define CONFIG_BOOTFILE                "/mnt/ide0/p2/usr/tftp/oxc.elf"
+#define CONFIG_BOOTCOMMAND     "tftp 0x10000 ; bootelf 0x10000"
+#define CONFIG_BOOTDELAY       10
+
+#define CFG_OXC_GENERATE_IP    1               /* Generate IP automatically    */
+#define CFG_OXC_IPMASK         0x0A000000      /* 10.0.0.x                     */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ */
+
+#define CONFIG_PCI                             /* include pci support          */
+
+#define CONFIG_NET_MULTI                       /* Multi ethernet cards support */
+
+#define CONFIG_EEPRO100                                /* Ethernet Express PRO 100     */
+
+#define PCI_ENET0_IOADDR       0x80000000
+#define PCI_ENET0_MEMADDR      0x80000000
+#define        PCI_ENET1_IOADDR        0x81000000
+#define        PCI_ENET1_MEMADDR       0x81000000
+
+/*-----------------------------------------------------------------------
+ * FLASH
+ */
+
+#define CFG_FLASH_PRELIMBASE   0xFF800000
+#define CFG_FLASH_BASE         (0-flash_info[0].size)
+
+#define CFG_MAX_FLASH_BANKS    1       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     32      /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+/*-----------------------------------------------------------------------
+ * RAM
+ */
+
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_MAX_RAM_SIZE       0x10000000
+
+#define CFG_RESET_ADDRESS      0xFFF00100
+
+#define CFG_MONITOR_BASE       TEXT_BASE
+#define CFG_MONITOR_LEN                0x00030000
+
+#if (CFG_MONITOR_BASE < CFG_FLASH_PRELIMBASE)
+# define CFG_RAMBOOT           1
+#else
+# undef CFG_RAMBOOT
+#endif
+
+#define CFG_INIT_RAM_ADDR      0x40000000
+#define CFG_INIT_RAM_END       0x1000
+
+#define CFG_GBL_DATA_SIZE      128
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET     CFG_GBL_DATA_OFFSET
+
+#define CFG_MALLOC_LEN         (512 << 10)     /* Reserve 512 kB for malloc()  */
+
+#define CFG_MEMTEST_START      0x00000000      /* memtest works on             */
+#define CFG_MEMTEST_END                0x04000000      /* 0 ... 32 MB in DRAM          */
+
+/*-----------------------------------------------------------------------
+ * Memory mapping
+ */
+
+#define CFG_CPLD_BASE          0xff000000      /* CPLD registers */
+#define CFG_CPLD_WATCHDOG      (CFG_CPLD_BASE)                 /* Watchdog */
+#define CFG_CPLD_RESET         (CFG_CPLD_BASE + 0x040000)      /* Minor resets */
+#define CFG_UART_BASE          (CFG_CPLD_BASE + 0x700000)      /* debug UART */
+
+/*-----------------------------------------------------------------------
+ * NS16550 Configuration
+ */
+
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+#define CFG_NS16550_REG_SIZE   -4
+#define CFG_NS16550_CLK                1843200
+#define CFG_NS16550_COM1       CFG_UART_BASE
+
+/*-----------------------------------------------------------------------
+ * I2C Bus
+ */
+
+#define CONFIG_I2C             1               /* I2C support on ... */
+#define CONFIG_HARD_I2C                1               /* ... hardware one */
+#define CFG_I2C_SPEED          400000          /* I2C speed and slave address  */
+#define CFG_I2C_SLAVE          0x7F            /* I2C slave address */
+
+#define CFG_I2C_EXPANDER0_ADDR 0x20            /* PCF8574 expander 0 addrerr */
+#define CFG_I2C_EXPANDER1_ADDR 0x21            /* PCF8574 expander 1 addrerr */
+#define CFG_I2C_EXPANDER2_ADDR 0x26            /* PCF8574 expander 2 addrerr */
+
+/*-----------------------------------------------------------------------
+ * Environment
+ */
+
+#define CFG_ENV_IS_IN_FLASH    1
+#define CFG_ENV_ADDR           0xFFF30000      /* Offset of Environment Sector */
+#define CFG_ENV_SIZE           0x00010000      /* Total Size of Environment Sector */
+#define CONFIG_ENV_OVERWRITE    1              /* Allow modifying the environment */
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+#define CONFIG_SYS_CLK_FREQ  33000000  /* external frequency to pll */
+#define CONFIG_PLL_PCI_TO_MEM_MULTIPLIER  2
+
+#define CFG_EUMB_ADDR          0xFC000000
+
+/* MCCR1 */
+#define CFG_ROMNAL             0       /* rom/flash next access time           */
+#define CFG_ROMFAL             19      /* rom/flash access time                */
+
+/* MCCR2 */
+#define CFG_ASRISE             15      /* ASRISE=15 clocks                     */
+#define CFG_ASFALL             3       /* ASFALL=3 clocks                      */
+#define CFG_REFINT             1000    /* REFINT=1000 clocks                   */
+
+/* MCCR3 */
+#define CFG_BSTOPRE            0x35c   /* Burst To Precharge                   */
+#define CFG_REFREC             7       /* Refresh to activate interval         */
+#define CFG_RDLAT              4       /* data latency from read command       */
+
+/* MCCR4 */
+#define CFG_PRETOACT           2       /* Precharge to activate interval       */
+#define CFG_ACTTOPRE           5       /* Activate to Precharge interval       */
+#define CFG_ACTORW             2       /* Activate to R/W                      */
+#define CFG_SDMODE_CAS_LAT     3       /* SDMODE CAS latency                   */
+#define CFG_SDMODE_WRAP                0       /* SDMODE wrap type                     */
+#define CFG_SDMODE_BURSTLEN    3       /* SDMODE Burst length 2=4, 3=8         */
+#define CFG_REGISTERD_TYPE_BUFFER   1
+
+/* memory bank settings*/
+/*
+ * only bits 20-29 are actually used from these vales to set the
+ * start/end address the upper two bits will be 0, and the lower 20
+ * bits will be set to 0x00000 for a start address, or 0xfffff for an
+ * end address
+ */
+#define CFG_BANK0_START                0x00000000
+#define CFG_BANK0_END          (CFG_MAX_RAM_SIZE - 1)
+#define CFG_BANK0_ENABLE       1
+#define CFG_BANK1_START                0x00000000
+#define CFG_BANK1_END          0x00000000
+#define CFG_BANK1_ENABLE       0
+#define CFG_BANK2_START                0x00000000
+#define CFG_BANK2_END          0x00000000
+#define CFG_BANK2_ENABLE       0
+#define CFG_BANK3_START                0x00000000
+#define CFG_BANK3_END          0x00000000
+#define CFG_BANK3_ENABLE       0
+#define CFG_BANK4_START                0x00000000
+#define CFG_BANK4_END          0x00000000
+#define CFG_BANK4_ENABLE       0
+#define CFG_BANK5_START                0x00000000
+#define CFG_BANK5_END          0x00000000
+#define CFG_BANK5_ENABLE       0
+#define CFG_BANK6_START                0x00000000
+#define CFG_BANK6_END          0x00000000
+#define CFG_BANK6_ENABLE       0
+#define CFG_BANK7_START                0x00000000
+#define CFG_BANK7_END          0x00000000
+#define CFG_BANK7_ENABLE       0
+/*
+ * Memory bank enable bitmask, specifying which of the banks defined above
+ are actually present. MSB is for bank #7, LSB is for bank #0.
+ */
+#define CFG_BANK_ENABLE                0x01
+
+#define CFG_ODCR               0xff    /* configures line driver impedances,   */
+                                       /* see 8240 book for bit definitions    */
+#define CFG_PGMAX              0x32    /* how long the 8240 retains the        */
+                                       /* currently accessed page in memory    */
+                                       /* see 8240 book for details            */
+
+/* SDRAM 0 - 256MB */
+#define CFG_IBAT0L     (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U     (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* stack in DCACHE @ 1GB (no backing mem) */
+#define CFG_IBAT1L     (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT1U     (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
+
+/* PCI memory */
+#define CFG_IBAT2L     (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U     (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* Flash, config addrs, etc */
+#define CFG_IBAT3L     (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U     (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L     CFG_IBAT0L
+#define CFG_DBAT0U     CFG_IBAT0U
+#define CFG_DBAT1L     CFG_IBAT1L
+#define CFG_DBAT1U     CFG_IBAT1U
+#define CFG_DBAT2L     CFG_IBAT2L
+#define CFG_DBAT2U     CFG_IBAT2U
+#define CFG_DBAT3L     CFG_IBAT3L
+#define CFG_DBAT3U     CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32      /* For MPC8240 CPU                      */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#  define CFG_CACHELINE_SHIFT  5       /* log base 2 of the above value */
+#endif
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/PCI405.h b/include/configs/PCI405.h
new file mode 100644 (file)
index 0000000..3f9b8d4
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_405GP           1       /* This is a PPC405 CPU         */
+#define CONFIG_4xx             1       /* ...member of PPC4xx family   */
+#define CONFIG_PCI405          1       /* ...on a PCI405 board         */
+
+#define CONFIG_BOARD_PRE_INIT   1       /* call board_pre_init()        */
+#define CONFIG_MISC_INIT_R     1       /* call misc_init_r() on init   */
+
+#define CONFIG_SYS_CLK_FREQ     25000000 /* external frequency to pll   */
+
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_BOOTDELAY       3       /* autoboot after 3 seconds     */
+
+#if 0
+#define CONFIG_PREBOOT                                                          \
+        "crc32 f0207004 ffc 0;"                                                 \
+        "if cmp 0 f0207000 1;"                                                  \
+        "then;echo Old CRC is correct;crc32 f0207004 ff4 f0207000;"             \
+        "else;echo Old CRC is bad;fi"
+#endif
+
+#undef CONFIG_BOOTARGS
+#if 1
+#define CONFIG_BOOTCOMMAND                                                     \
+       "bootm fffc0000"
+#else
+#define CONFIG_BOOTCOMMAND                                                     \
+       "mw.l 0 ffffffff; mw.l 4 ffffffff;"                                     \
+        "while cmp 0 4 1; do echo Waiting for Host...;done;"                    \
+        "bootm 400000"
+#endif
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#define CFG_LOADS_BAUD_CHANGE  1       /* allow baudrate change        */
+
+#define CONFIG_MII             1       /* MII PHY management           */
+#define        CONFIG_PHY_ADDR         0       /* PHY address                  */
+
+#define CONFIG_RTC_M48T35A     1               /* ST Electronics M48 timekeeper */
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_PCI     | \
+                               CFG_CMD_IRQ     | \
+                               CFG_CMD_ELF     | \
+                               CFG_CMD_DATE    | \
+                               CFG_CMD_I2C     | \
+                               CFG_CMD_EEPROM  )
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#undef  CONFIG_WATCHDOG                        /* watchdog disabled            */
+
+#define        CONFIG_SDRAM_BANK0      1       /* init onboard SDRAM bank 0    */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+
+#define        CFG_HUSH_PARSER                 /* use "hush" command parser    */
+#ifdef CFG_HUSH_PARSER
+#define        CFG_PROMPT_HUSH_PS2     "> "
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_DEVICE_NULLDEV      1       /* include nulldev device       */
+
+#define CFG_CONSOLE_INFO_QUIET  1       /* don't print console @ startup*/
+
+#define CFG_MEMTEST_START      0x0400000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0C00000       /* 4 ... 12 MB in DRAM  */
+
+#undef  CFG_EXT_SERIAL_CLOCK           /* no external serial clock used */
+#define CFG_IGNORE_405_UART_ERRATA_59   /* ignore ppc405gp errata #59   */
+#define CFG_BASE_BAUD       691200
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE      \
+        { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400,     \
+         57600, 115200, 230400, 460800, 921600 }
+
+#define CFG_LOAD_ADDR  0x100000        /* default load address */
+#define CFG_EXTBDINFO  1               /* To use extended board_into (bd_t) */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_ZERO_BOOTDELAY_CHECK    /* check for keypress on bootdelay==0 */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define PCI_HOST_ADAPTER 0              /* configure as pci adapter     */
+#define PCI_HOST_FORCE  1               /* configure as pci host        */
+#define PCI_HOST_AUTO   2               /* detected via arbiter enable  */
+
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST        PCI_HOST_ADAPTER /* select pci host function    */
+#undef  CONFIG_PCI_PNP                 /* no pci plug-and-play         */
+                                        /* resource configuration       */
+
+#define CONFIG_PCI_SCAN_SHOW            /* print pci devices @ startup  */
+
+#define CFG_PCI_SUBSYS_VENDORID 0x12FE  /* PCI Vendor ID: esd gmbh      */
+#define CFG_PCI_SUBSYS_DEVICEID 0x0407  /* PCI Device ID: PCI-405       */
+#define CFG_PCI_CLASSCODE       0x0280  /* PCI Class Code: Network/Other*/
+#define CFG_PCI_PTM1LA  0x00000000      /* point to sdram               */
+#define CFG_PCI_PTM1MS  0xfc000001      /* 64MB, enable hard-wired to 1 */
+#define CFG_PCI_PTM1PCI 0x00000000      /* Host: use this pci address   */
+
+#if 0 /* test-only */
+#define CFG_PCI_PTM2LA  0xffc00000      /* point to flash               */
+#define CFG_PCI_PTM2MS  0xffc00001      /* 4MB, enable                  */
+#define CFG_PCI_PTM2PCI 0x04000000      /* Host: use this pci address   */
+#else
+#define CFG_PCI_PTM2LA  0xef600000      /* point to internal regs       */
+#define CFG_PCI_PTM2MS  0xef600001      /* 4MB, enable                  */
+#define CFG_PCI_PTM2PCI 0x04000000      /* Host: use this pci address   */
+#endif
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFFD0000
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MONITOR_LEN                (192 * 1024)    /* Reserve 196 kB for Monitor   */
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    1       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     256     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#define CFG_FLASH_WORD_SIZE     unsigned short  /* flash word size (width)      */
+#define CFG_FLASH_ADDR0         0x5555  /* 1st address for flash config cycles  */
+#define CFG_FLASH_ADDR1         0x2AAA  /* 2nd address for flash config cycles  */
+/*
+ * The following defines are added for buggy IOP480 byte interface.
+ * All other boards should use the standard values (CPCI405 etc.)
+ */
+#define CFG_FLASH_READ0         0x0000  /* 0 is standard                        */
+#define CFG_FLASH_READ1         0x0001  /* 1 is standard                        */
+#define CFG_FLASH_READ2         0x0002  /* 2 is standard                        */
+
+#define CFG_FLASH_EMPTY_INFO            /* print 'E' for empty sector on flinfo */
+
+#if 0 /* Use NVRAM for environment variables */
+/*-----------------------------------------------------------------------
+ * NVRAM organization
+ */
+#define CFG_ENV_IS_IN_NVRAM    1       /* use NVRAM for environment vars       */
+#define CFG_ENV_SIZE           0x0ff8          /* Size of Environment vars     */
+#define CFG_ENV_ADDR           \
+       (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-(CFG_ENV_SIZE+8))   /* Env  */
+
+#else /* Use EEPROM for environment variables */
+
+#define CFG_ENV_IS_IN_EEPROM    1       /* use EEPROM for environment vars */
+#define CFG_ENV_OFFSET          0x000   /* environment starts at the beginning of the EEPROM */
+#define CFG_ENV_SIZE            0x400   /* 1024 bytes may be used for env vars*/
+                                   /* total size of a CAT24WC08 is 1024 bytes */
+#endif
+
+#define CFG_NVRAM_BASE_ADDR    0xf0200000              /* NVRAM base address   */
+#define CFG_NVRAM_SIZE         (32*1024)               /* NVRAM size           */
+
+/*-----------------------------------------------------------------------
+ * I2C EEPROM (CAT24WC16) for environment
+ */
+#define CONFIG_HARD_I2C                        /* I2c with hardware support */
+#define CFG_I2C_SPEED          400000  /* I2C speed and slave address */
+#define CFG_I2C_SLAVE          0x7F
+
+#define CFG_I2C_EEPROM_ADDR    0x50    /* EEPROM CAT28WC08             */
+#define CFG_I2C_EEPROM_ADDR_LEN        1       /* Bytes of address             */
+/* mask of address bits that overflow into the "EEPROM chip address"    */
+#define CFG_I2C_EEPROM_ADDR_OVERFLOW   0x07
+#define CFG_EEPROM_PAGE_WRITE_BITS 4   /* The Catalyst CAT24WC08 has   */
+                                       /* 16 byte page write mode using*/
+                                       /* last 4 bits of the address   */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10   /* and takes up to 10 msec */
+#define CFG_EEPROM_PAGE_WRITE_ENABLE
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE                8192    /* For IBM 405 CPUs                     */
+#define CFG_CACHELINE_SIZE     32      /* ...                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0xFFE00000      /* FLASH bank #0        */
+
+/*-----------------------------------------------------------------------
+ * External Bus Controller (EBC) Setup
+ */
+
+/* Memory Bank 0 (Flash Bank 0) initialization                                  */
+#define CFG_EBC_PB0AP           0x92015480
+#define CFG_EBC_PB0CR           0xFFC5A000  /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */
+
+/* Memory Bank 1 (NVRAM/RTC) initialization                                     */
+#define CFG_EBC_PB1AP           0x01005280  /* TWT=2,WBN=1,WBF=1,TH=1,SOR=1     */
+#define CFG_EBC_PB1CR           0xF0218000  /* BAS=0xF02,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 2 (CAN0, 1) initialization                                       */
+#define CFG_EBC_PB2AP           0x010053C0  /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB2CR           0xF0018000  /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit  */
+
+/* Memory Bank 3 (FPGA internal) initialization                                 */
+#define CFG_EBC_PB3AP           0x010053C0  /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */
+#define CFG_EBC_PB3CR           0xF041C000  /* BAS=0xF01,BS=1MB,BU=R/W,BW=32bit */
+#define CFG_FPGA_BASE_ADDR      0xF0400000
+
+/*-----------------------------------------------------------------------
+ * FPGA stuff
+ */
+/* FPGA internal regs */
+#define CFG_FPGA_MODE           0x00
+#define CFG_FPGA_STATUS         0x02
+#define CFG_FPGA_TS             0x04
+#define CFG_FPGA_TS_LOW         0x06
+#define CFG_FPGA_TS_CAP0        0x10
+#define CFG_FPGA_TS_CAP0_LOW    0x12
+#define CFG_FPGA_TS_CAP1        0x14
+#define CFG_FPGA_TS_CAP1_LOW    0x16
+#define CFG_FPGA_TS_CAP2        0x18
+#define CFG_FPGA_TS_CAP2_LOW    0x1a
+#define CFG_FPGA_TS_CAP3        0x1c
+#define CFG_FPGA_TS_CAP3_LOW    0x1e
+
+/* FPGA Mode Reg */
+#define CFG_FPGA_MODE_CF_RESET  0x0001
+#define CFG_FPGA_MODE_TS_IRQ_ENABLE 0x0100
+#define CFG_FPGA_MODE_TS_IRQ_CLEAR  0x1000
+#define CFG_FPGA_MODE_TS_CLEAR  0x2000
+
+/* FPGA Status Reg */
+#define CFG_FPGA_STATUS_DIP0    0x0001
+#define CFG_FPGA_STATUS_DIP1    0x0002
+#define CFG_FPGA_STATUS_DIP2    0x0004
+#define CFG_FPGA_STATUS_FLASH   0x0008
+#define CFG_FPGA_STATUS_TS_IRQ  0x1000
+
+#define CFG_FPGA_SPARTAN2       1           /* using Xilinx Spartan 2 now    */
+#define CFG_FPGA_MAX_SIZE       32*1024     /* 32kByte is enough for XC2S15  */
+
+/* FPGA program pin configuration */
+#define CFG_FPGA_PRG            0x04000000  /* FPGA program pin (ppc output) */
+#define CFG_FPGA_CLK            0x02000000  /* FPGA clk pin (ppc output)     */
+#define CFG_FPGA_DATA           0x01000000  /* FPGA data pin (ppc output)    */
+#define CFG_FPGA_INIT           0x00400000  /* FPGA init pin (ppc input)     */
+#define CFG_FPGA_DONE           0x00800000  /* FPGA done pin (ppc input)     */
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in data cache)
+ */
+#if 1 /* test-only */
+#define CFG_INIT_DCACHE_CS      7       /* use cs # 7 for data cache memory    */
+
+#define CFG_INIT_RAM_ADDR       0x40000000  /* use data cache                  */
+#else
+#define CFG_INIT_RAM_ADDR      0x00df0000 /* inside of SDRAM                   */
+#endif
+#define CFG_INIT_RAM_END        0x2000  /* End of used area in RAM             */
+#define CFG_GBL_DATA_SIZE      128  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/PIP405.h b/include/configs/PIP405.h
new file mode 100644 (file)
index 0000000..a5fc8d9
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/***********************************************************
+ * High Level Configuration Options
+ * (easy to change)
+ ***********************************************************/
+#define CONFIG_405GP           1       /* This is a PPC405 CPU         */
+#define CONFIG_4xx             1       /* ...member of PPC4xx family   */
+#define CONFIG_PIP405          1       /* ...on a PIP405 board         */
+/***********************************************************
+ * Clock
+ ***********************************************************/
+#define CONFIG_SYS_CLK_FREQ    33000000 /* external frequency to pll   */
+
+/***********************************************************
+ * Command definitions
+ ***********************************************************/
+#define CONFIG_COMMANDS                \
+                      (CONFIG_CMD_DFL  | \
+                       CFG_CMD_IDE     | \
+                       CFG_CMD_DHCP    | \
+                       CFG_CMD_PCI     | \
+                       CFG_CMD_CACHE   | \
+                       CFG_CMD_IRQ     | \
+                       CFG_CMD_EEPROM  | \
+                       CFG_CMD_I2C     | \
+                       CFG_CMD_REGINFO | \
+                       CFG_CMD_FDC     | \
+                       CFG_CMD_SCSI    | \
+                       CFG_CMD_DATE    | \
+                       CFG_CMD_ELF     | \
+                       CFG_CMD_USB     | \
+                       CFG_CMD_MII     | \
+                       CFG_CMD_SDRAM   | \
+                       CFG_CMD_DOC     | \
+                       CFG_CMD_SAVES   | \
+                       CFG_CMD_BSP     )
+/* this must be included AFTER the definition of CONFIG_COMMANDS  (if any) */
+#include <cmd_confdefs.h>
+
+#define         CFG_HUSH_PARSER
+#define         CFG_PROMPT_HUSH_PS2 "> "
+/**************************************************************
+ * I2C Stuff:
+ * the PIP405 is equiped with an Atmel 24C128/256 EEPROM at address
+ * 0x53.
+ * Caution: on the same bus is the SPD (Serial Presens Detect
+ * EEPROM of the SDRAM
+ * The Atmel EEPROM uses 16Bit addressing.
+ ***************************************************************/
+#define CONFIG_HARD_I2C                        /* I2c with hardware support */
+#define CFG_I2C_SPEED          50000   /* I2C speed and slave address */
+#define CFG_I2C_SLAVE          0x7F
+
+#define CFG_I2C_EEPROM_ADDR    0x53
+#define CFG_I2C_EEPROM_ADDR_LEN        2
+#define CFG_ENV_IS_IN_EEPROM    1       /* use EEPROM for environment vars */
+#define CFG_ENV_OFFSET          0x000   /* environment starts at the beginning of the EEPROM */
+#define CFG_ENV_SIZE            0x800   /* 2 kBytes may be used for env vars */
+
+#undef CFG_I2C_EEPROM_ADDR_OVERFLOW
+#define CFG_EEPROM_PAGE_WRITE_BITS 6   /* The Atmel 24C128/256 has     */
+                                       /* 64 byte page write mode using*/
+                                       /* last 6 bits of the address   */
+#define CFG_EEPROM_PAGE_WRITE_ENABLE   /* enable Page write */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10      /* and takes up to 10 msec */
+
+
+/***************************************************************
+ * Definitions for Serial Presence Detect EEPROM address
+ * (to get SDRAM settings)
+ ***************************************************************/
+#define SPD_EEPROM_ADDRESS      0x50
+
+#define CONFIG_BOARD_PRE_INIT
+/**************************************************************
+ * Environment definitions
+ **************************************************************/
+#define CONFIG_BAUDRATE                9600    /* STD Baudrate */
+
+
+#define CONFIG_BOOTDELAY       5
+/* autoboot (do NOT change this set environment variable "bootdelay" to -1 instead) */
+#define CONFIG_BOOT_RETRY_TIME -10     /* feature is avaiable but not enabled */
+#define CONFIG_ZERO_BOOTDELAY_CHECK    /* check console even if bootdelay = 0 */
+
+
+#define CONFIG_BOOTCOMMAND     "diskboot 200000 0:1; bootm" /* autoboot command                */
+#define CONFIG_BOOTARGS                "console=ttyS0,9600 root=/dev/hda5" /* boot arguments */
+
+#define CONFIG_IPADDR          10.0.0.100
+#define CONFIG_SERVERIP                10.0.0.1
+#define CONFIG_PREBOOT
+/***************************************************************
+ * defines if the console is stored in the environment
+ ***************************************************************/
+#define CFG_CONSOLE_IS_IN_ENV  /* stdin, stdout and stderr are in evironment */
+/***************************************************************
+ * defines if an overwrite_console function exists
+ *************************************************************/
+#define CFG_CONSOLE_OVERWRITE_ROUTINE
+#define CFG_CONSOLE_INFO_QUIET
+/***************************************************************
+ * defines if the overwrite_console should be stored in the
+ * environment
+ **************************************************************/
+#undef CFG_CONSOLE_ENV_OVERWRITE
+
+/**************************************************************
+ * loads config
+ *************************************************************/
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#define CFG_LOADS_BAUD_CHANGE  1       /* allow baudrate change        */
+
+
+/***********************************************************
+ * Miscellaneous configurable options
+ **********************************************************/
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CBSIZE     1024            /* Console I/O Buffer Size      */
+#else
+#define CFG_CBSIZE     256             /* Console I/O Buffer Size      */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x0100000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0C00000       /* 1 ... 12 MB in DRAM  */
+
+#undef CFG_EXT_SERIAL_CLOCK           /* no external serial clock used */
+#define CFG_BASE_BAUD       691200
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE     \
+       { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400,     \
+        57600, 115200, 230400, 460800, 921600 }
+
+#define CFG_LOAD_ADDR          0x200000        /* default load address */
+#define CFG_EXTBDINFO          1       /* To use extended board_into (bd_t) */
+
+#define CFG_HZ         1000            /* decrementer freq: 1 ms ticks */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define PCI_HOST_ADAPTER 0              /* configure ar pci adapter     */
+#define PCI_HOST_FORCE  1               /* configure as pci host        */
+#define PCI_HOST_AUTO   2               /* detected via arbiter enable  */
+
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST PCI_HOST_FORCE /* configure as pci-host        */
+#define CONFIG_PCI_PNP                 /* pci plug-and-play            */
+                                       /* resource configuration       */
+#define CFG_PCI_SUBSYS_VENDORID 0x0000 /* PCI Vendor ID: to-do!!!      */
+#define CFG_PCI_SUBSYS_DEVICEID 0x0000 /* PCI Device ID: to-do!!!      */
+#define CFG_PCI_PTM1LA 0x00000000      /* point to sdram               */
+#define CFG_PCI_PTM1MS 0x80000001      /* 2GB, enable hard-wired to 1  */
+#define CFG_PCI_PTM1PCI 0x00000000      /* Host: use this pci address   */
+#define CFG_PCI_PTM2LA 0x00000000      /* disabled                     */
+#define CFG_PCI_PTM2MS 0x00000000      /* disabled                     */
+#define CFG_PCI_PTM2PCI 0x00000000      /* Host: use this pci address   */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFF80000
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MONITOR_LEN                (512 * 1024)    /* Reserve 512 kB for Monitor   */
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    1       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     256     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE                8192    /* For IBM 405 CPUs                     */
+#define CFG_CACHELINE_SIZE     32      /* ...                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Init Memory Controller:
+ */
+
+#define FLASH_BASE0_PRELIM     0xFFC00000      /* FLASH bank #0        */
+#define FLASH_BASE1_PRELIM     0               /* FLASH bank #1        */
+
+/* Configuration Port location */
+#define CONFIG_PORT_ADDR       0xF4000000
+#define MULTI_PURPOSE_SOCKET_ADDR 0xF8000000
+
+
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in On Chip SRAM)
+ */
+#define CFG_TEMP_STACK_OCM     1
+#define CFG_OCM_DATA_ADDR      0xF0000000
+#define CFG_OCM_DATA_SIZE      0x1000
+#define CFG_INIT_RAM_ADDR      CFG_OCM_DATA_ADDR       /* inside of On Chip SRAM    */
+#define CFG_INIT_RAM_END       CFG_OCM_DATA_SIZE       /* End of On Chip SRAM         */
+#define CFG_GBL_DATA_SIZE      64              /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET     CFG_GBL_DATA_OFFSET
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+
+/***********************************************************************
+ * External peripheral base address
+ ***********************************************************************/
+#define CFG_ISA_IO_BASE_ADDRESS 0xE8000000
+
+/***********************************************************************
+ * Last Stage Init
+ ***********************************************************************/
+#define CONFIG_LAST_STAGE_INIT
+/************************************************************
+ * Ethernet Stuff
+ ***********************************************************/
+#define CONFIG_MII             1       /* MII PHY management           */
+#define CONFIG_PHY_ADDR                1       /* PHY address                  */
+#define CONFIG_CS8952_PHY      1       /* its a CS8952 PHY             */
+/************************************************************
+ * RTC
+ ***********************************************************/
+#define CONFIG_RTC_MC146818
+#undef CONFIG_WATCHDOG                 /* watchdog disabled            */
+
+/************************************************************
+ * IDE/ATA stuff
+ ************************************************************/
+#define CFG_IDE_MAXBUS         2   /* max. 2 IDE busses        */
+#define CFG_IDE_MAXDEVICE      (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */
+
+#define CFG_ATA_BASE_ADDR      CFG_ISA_IO_BASE_ADDRESS /* base address */
+#define CFG_ATA_IDE0_OFFSET    0x01F0  /* ide0 offste */
+#define CFG_ATA_IDE1_OFFSET    0x0170  /* ide1 offset */
+#define CFG_ATA_DATA_OFFSET    0       /* data reg offset      */
+#define CFG_ATA_REG_OFFSET     0       /* reg offset */
+#define CFG_ATA_ALT_OFFSET     0x200   /* alternate register offset */
+
+#undef CONFIG_IDE_8xx_DIRECT           /* no pcmcia interface required */
+#undef CONFIG_IDE_LED                  /* no led for ide supported     */
+#define CONFIG_IDE_RESET               /* reset for ide supported...   */
+#define CONFIG_IDE_RESET_ROUTINE       /* with a special reset function */
+
+/************************************************************
+ * ATAPI support (experimental)
+ ************************************************************/
+#define CONFIG_ATAPI                   /* enable ATAPI Support */
+
+/************************************************************
+ * SCSI support (experimental) only SYM53C8xx supported
+ ************************************************************/
+#define CONFIG_SCSI_SYM53C8XX
+#define CFG_SCSI_MAX_LUN       8       /* number of supported LUNs */
+#define CFG_SCSI_MAX_SCSI_ID   7       /* maximum SCSI ID (0..6) */
+#define CFG_SCSI_MAX_DEVICE    CFG_SCSI_MAX_SCSI_ID * CFG_SCSI_MAX_LUN /* maximum Target devices */
+#define CFG_SCSI_SPIN_UP_TIME  2
+
+/************************************************************
+ * Disk-On-Chip configuration
+ ************************************************************/
+#define CFG_MAX_DOC_DEVICE     1       /* Max number of DOC devices            */
+#define CFG_DOC_SHORT_TIMEOUT
+#define CFG_DOC_SUPPORT_2000
+#define CFG_DOC_SUPPORT_MILLENNIUM
+
+/************************************************************
+ * DISK Partition support
+ ************************************************************/
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_ISO_PARTITION /* Experimental */
+
+/************************************************************
+ * Keyboard support
+ ************************************************************/
+#define CONFIG_ISA_KEYBOARD
+
+/************************************************************
+ * Video support
+ ************************************************************/
+#define CONFIG_VIDEO                   /*To enable video controller support */
+#define CONFIG_VIDEO_CT69000
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_CONSOLE_EXTRA_INFO
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_VIDEO_SW_CURSOR
+#define CONFIG_VIDEO_ONBOARD           /* Video controller is on-board */
+
+/************************************************************
+ * USB support
+ ************************************************************/
+#define CONFIG_USB_UHCI
+#define CONFIG_USB_KEYBOARD
+#define CONFIG_USB_STORAGE
+
+/* Enable needed helper functions */
+#define CFG_DEVICE_DEREGISTER          /* needs device_deregister */
+
+/************************************************************
+ * Debug support
+ ************************************************************/
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CONFIG_KGDB_BAUDRATE   230400  /* speed to run kgdb serial port */
+#define CONFIG_KGDB_SER_INDEX  2       /* which serial port to use */
+#endif
+
+/************************************************************
+ * Ident
+ ************************************************************/
+#define VERSION_TAG "released"
+#define CONFIG_IDENT_STRING "\n(c) 2002 by MPL AG Switzerland, MEV-10066-001 " VERSION_TAG
+
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/PN62.h b/include/configs/PN62.h
new file mode 100644 (file)
index 0000000..0750116
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * (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
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC824X         1
+#define CONFIG_MPC8240         1
+#define CONFIG_PN62            1
+
+#define CONFIG_CONS_INDEX      1
+
+
+#define REMOVE_COMMANDS         ( CFG_CMD_AUTOSCRIPT | \
+                                 CFG_CMD_LOADS | \
+                                 CFG_CMD_ENV | \
+                                 CFG_CMD_FLASH )
+
+#define CONFIG_COMMANDS                ( (CONFIG_CMD_DFL & ~REMOVE_COMMANDS) |\
+                                 CFG_CMD_PCI |\
+                                 CFG_CMD_BSP)
+
+#define CONFIG_BAUDRATE                19200   /* console baudrate             */
+
+#define CONFIG_BOOTDELAY       1       /* autoboot after n seconds     */
+
+#define        CONFIG_CLOCKS_IN_MHZ    1       /* clocks passsed to Linux in MHz */
+
+#define CONFIG_SERVERIP                10.0.0.201
+#define CONFIG_IPADDR          10.0.0.200
+#define CONFIG_ROOTPATH                /opt/eldk/ppc_82xx
+#define CONFIG_NETMASK         255.255.255.0
+#undef CONFIG_BOOTARGS
+#if 0
+/* Boot Linux with NFS root filesystem */
+#define CONFIG_BOOTCOMMAND \
+                       "setenv verify y;" \
+                               "setenv bootargs console=ttyS0,19200 mem=31M quiet " \
+                       "root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \
+                       "ip=$(ipaddr):$(serverip)::$(netmask):pn62:eth0:off;" \
+                       "loadp 100000; bootm"
+                       /* "tftpboot 100000 pImage; bootm" */
+#else
+/* Boot Linux with RAMdisk based filesystem (initrd, BusyBox) */
+#define CONFIG_BOOTCOMMAND \
+                       "setenv verify n;" \
+                               "setenv bootargs console=ttyS0,19200 mem=31M quiet " \
+                       "root=/dev/ram rw " \
+                       "ip=$(ipaddr):$(serverip)::$(netmask):pn62:eth0:off;" \
+                       "loadp 200000; bootm"
+#endif
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any)      */
+#include <cmd_confdefs.h>
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP           1               /* undef to save memory         */
+#define CFG_PROMPT             "=> "           /* Monitor Command Prompt       */
+#define CFG_CBSIZE             256             /* Console I/O Buffer Size      */
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)  /* Print Buffer Size    */
+#define CFG_MAXARGS            16              /* max number of command args   */
+#define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR          0x00100000      /* default load address         */
+#define CFG_HZ                 1000            /* decrementer freq: 1 ms ticks */
+
+#define CONFIG_PRAM            1024            /* reserve 1 MB protected RAM   */
+
+#define CONFIG_MISC_INIT_R     1               /* call misc_init_r() on init   */
+
+#define CONFIG_SHOW_BOOT_PROGRESS 1            /* Show boot progress on LEDs   */
+
+/*
+ * PCI stuff
+ */
+#define CONFIG_PCI                             /* include pci support          */
+#define CONFIG_PCI_PNP                         /* we need Plug 'n Play         */
+#if 0
+#define CONFIG_PCI_SCAN_SHOW                   /* show PCI auto-scan at boot   */
+#endif
+
+/*
+ * Networking stuff
+ */
+#define CONFIG_NET_MULTI                               /* Multi ethernet cards support */
+
+#define CONFIG_PCNET                           /* there are 2 AMD PCnet 79C973 */
+#define CONFIG_PCNET_79C973
+
+#define _IO_BASE               0xfe000000      /* points to PCI I/O space      */
+
+
+/*
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_MAX_RAM_SIZE       0x10000000
+
+#define CFG_RESET_ADDRESS      0xfff00100
+
+#undef CFG_RAMBOOT
+#define CFG_MONITOR_LEN                0x00030000
+#define CFG_MONITOR_BASE       TEXT_BASE
+
+/*#define CFG_GBL_DATA_SIZE    256*/
+#define CFG_GBL_DATA_SIZE      128
+
+#define CFG_INIT_RAM_ADDR      0x40000000
+#define CFG_INIT_RAM_END       0x1000
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+
+
+#define CFG_NO_FLASH           1               /* There is no FLASH memory     */
+
+#define CFG_ENV_IS_NOWHERE     1               /* Store ENV in memory only     */
+#define CFG_ENV_OFFSET         0x00004000      /* Offset of Environment Sector */
+#define CFG_ENV_SIZE           0x00002000      /* Total Size of Environment Sector */
+
+#define CFG_MALLOC_LEN         (512 << 10)     /* Reserve 512 kB for malloc()  */
+
+#define CFG_MEMTEST_START      0x00004000      /* memtest works on             */
+#define CFG_MEMTEST_END                0x01f00000      /* 0 ... 32 MB in DRAM          */
+
+/*
+ * Serial port configuration
+ */
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+
+#define CFG_NS16550_REG_SIZE   1
+
+#define CFG_NS16550_CLK                1843200
+
+#define CFG_NS16550_COM1       0xff800008
+#define CFG_NS16550_COM2       0xff800000
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+#define CONFIG_SYS_CLK_FREQ  33333333  /* external frequency to pll */
+#define CONFIG_PLL_PCI_TO_MEM_MULTIPLIER  3
+
+#define CFG_EUMB_ADDR          0xFCE00000
+
+/* MCCR1 */
+#define CFG_ROMNAL             3       /* rom/flash next access time           */
+#define CFG_ROMFAL             7       /* rom/flash access time                */
+
+/* MCCR2 */
+#define CFG_ASRISE             6       /* ASRISE in clocks                     */
+#define CFG_ASFALL             12      /* ASFALL in clocks                     */
+#define CFG_REFINT             5600    /* REFINT in clocks                     */
+
+/* MCCR3 */
+#define CFG_BSTOPRE            0x3cf   /* Burst To Precharge                   */
+#define CFG_REFREC             2       /* Refresh to activate interval         */
+#define CFG_RDLAT              3       /* data latency from read command       */
+
+/* MCCR4 */
+#define CFG_PRETOACT           1       /* Precharge to activate interval       */
+#define CFG_ACTTOPRE           3       /* Activate to Precharge interval       */
+#define CFG_ACTORW             2       /* Activate to R/W                      */
+#define CFG_SDMODE_CAS_LAT     2       /* SDMODE CAS latency                   */
+#define CFG_SDMODE_WRAP                0       /* SDMODE Wrap type                     */
+#define CFG_SDMODE_BURSTLEN    2       /* SDMODE Burst length 2=4, 3=8         */
+#define CFG_REGISTERD_TYPE_BUFFER   1
+
+/* Memory bank settings:
+ *
+ * only bits 20-29 are actually used from these vales to set the
+ * start/qend address the upper two bits will be 0, and the lower 20
+ * bits will be set to 0x00000 for a start address, or 0xfffff for an
+ * end address
+ */
+#define CFG_BANK0_START                0x00000000
+#define CFG_BANK0_END          (CFG_MAX_RAM_SIZE - 1)
+#define CFG_BANK0_ENABLE       1
+#define CFG_BANK1_START                0x00000000
+#define CFG_BANK1_END          0x00000000
+#define CFG_BANK1_ENABLE       0
+#define CFG_BANK2_START                0x00000000
+#define CFG_BANK2_END          0x00000000
+#define CFG_BANK2_ENABLE       0
+#define CFG_BANK3_START                0x00000000
+#define CFG_BANK3_END          0x00000000
+#define CFG_BANK3_ENABLE       0
+#define CFG_BANK4_START                0x00000000
+#define CFG_BANK4_END          0x00000000
+#define CFG_BANK4_ENABLE       0
+#define CFG_BANK5_START                0x00000000
+#define CFG_BANK5_END          0x00000000
+#define CFG_BANK5_ENABLE       0
+#define CFG_BANK6_START                0x00000000
+#define CFG_BANK6_END          0x00000000
+#define CFG_BANK6_ENABLE       0
+#define CFG_BANK7_START                0x00000000
+#define CFG_BANK7_END          0x00000000
+#define CFG_BANK7_ENABLE       0
+
+/*
+ * Memory bank enable bitmask, specifying which of the banks defined above
+ * are actually present. MSB is for bank #7, LSB is for bank #0.
+ */
+#define CFG_BANK_ENABLE                0x01
+
+#define CFG_ODCR               0xff    /* configures line driver impedances,   */
+                                       /* see 8240 book for bit definitions    */
+#define CFG_PGMAX              0x32    /* how long the 8240 retains the        */
+                                       /* currently accessed page in memory    */
+                                       /* see 8240 book for details            */
+
+/* SDRAM 0 - 256MB */
+#define CFG_IBAT0L     (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U     (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_IBAT1L     (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT1U     (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
+
+/* PCI memory space */
+#define CFG_IBAT2L     (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U     (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* Config addrs, etc */
+#define CFG_IBAT3L     (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U     (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L     CFG_IBAT0L
+#define CFG_DBAT0U     CFG_IBAT0U
+#define CFG_DBAT1L     CFG_IBAT1L
+#define CFG_DBAT1U     CFG_IBAT1U
+#define CFG_DBAT2L     CFG_IBAT2L
+#define CFG_DBAT2U     CFG_IBAT2U
+#define CFG_DBAT3L     CFG_IBAT3L
+#define CFG_DBAT3U     CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+
+/*
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32      /* For MPC8240 CPU                      */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#  define CFG_CACHELINE_SHIFT  5       /* log base 2 of the above value */
+#endif
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                      */
+
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/Sandpoint8240.h b/include/configs/Sandpoint8240.h
new file mode 100644 (file)
index 0000000..0bef321
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * (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
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC824X         1
+#define CONFIG_MPC8240         1
+#define CONFIG_SANDPOINT       1
+
+#if 0
+#define USE_DINK32             1
+#else
+#undef USE_DINK32
+#endif
+
+#define CONFIG_CONS_INDEX      1
+#define CONFIG_BAUDRATE                115200
+#define CONFIG_DRAM_SPEED      100             /* MHz                          */
+
+#define CONFIG_COMMANDS                ( (CONFIG_CMD_DFL & ~CFG_CMD_AUTOSCRIPT) | \
+                                 CFG_CMD_ELF    | \
+                                 CFG_CMD_I2C    | \
+                                 CFG_CMD_SDRAM  | \
+                                 CFG_CMD_EEPROM | \
+                                 CFG_CMD_PCI )
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any)      */
+#include <cmd_confdefs.h>
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP           1               /* undef to save memory         */
+#define CFG_PROMPT             "=> "           /* Monitor Command Prompt       */
+#define CFG_CBSIZE             256             /* Console I/O Buffer Size      */
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)  /* Print Buffer Size    */
+#define CFG_MAXARGS            16              /* max number of command args   */
+#define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR          0x00100000      /* default load address         */
+#define CFG_HZ                 1000            /* decrementer freq: 1 ms ticks */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_PCI                             /* include pci support          */
+#undef CONFIG_PCI_PNP
+
+#define CONFIG_NET_MULTI                       /* Multi ethernet cards support */
+
+#define CONFIG_EEPRO100
+
+#define PCI_ENET0_IOADDR       0x80000000
+#define PCI_ENET0_MEMADDR      0x80000000
+#define        PCI_ENET1_IOADDR        0x81000000
+#define        PCI_ENET1_MEMADDR       0x81000000
+
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_MAX_RAM_SIZE       0x10000000
+
+#define CFG_RESET_ADDRESS      0xFFF00100
+
+#if defined (USE_DINK32)
+#define CFG_MONITOR_LEN                0x00030000
+#define CFG_MONITOR_BASE       0x00090000
+#define CFG_RAMBOOT            1
+#define CFG_INIT_RAM_ADDR      (CFG_MONITOR_BASE + CFG_MONITOR_LEN)
+#define CFG_INIT_RAM_END       0x10000
+#define CFG_GBL_DATA_SIZE      256  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET     CFG_GBL_DATA_OFFSET
+#else
+#undef CFG_RAMBOOT
+#define CFG_MONITOR_LEN                0x00030000
+#define CFG_MONITOR_BASE       TEXT_BASE
+
+/*#define CFG_GBL_DATA_SIZE    256*/
+#define CFG_GBL_DATA_SIZE      128
+
+#define CFG_INIT_RAM_ADDR     0x40000000
+#define CFG_INIT_RAM_END      0x1000
+#define CFG_GBL_DATA_OFFSET  (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+
+#endif
+
+#define CFG_FLASH_BASE         0xFFF00000
+#if 0
+#define CFG_FLASH_SIZE         (512 * 1024)    /* sandpoint has tiny eeprom    */
+#else
+#define CFG_FLASH_SIZE         (1024 * 1024)   /* Unity has onboard 1MByte flash */
+#endif
+#define CFG_ENV_IS_IN_FLASH    1
+#define CFG_ENV_OFFSET         0x00004000      /* Offset of Environment Sector */
+#define CFG_ENV_SIZE           0x00002000      /* Total Size of Environment Sector */
+
+#define CFG_MALLOC_LEN         (512 << 10)     /* Reserve 512 kB for malloc()  */
+
+#define CFG_MEMTEST_START      0x00000000      /* memtest works on             */
+#define CFG_MEMTEST_END                0x04000000      /* 0 ... 32 MB in DRAM          */
+
+#define CFG_EUMB_ADDR          0xFC000000
+
+#define CFG_ISA_MEM            0xFD000000
+#define CFG_ISA_IO             0xFE000000
+
+#define CFG_FLASH_RANGE_BASE   0xFF000000      /* flash memory address range   */
+#define CFG_FLASH_RANGE_SIZE   0x01000000
+#define FLASH_BASE0_PRELIM     0xFFF00000      /* sandpoint flash              */
+#define FLASH_BASE1_PRELIM     0xFF000000      /* PMC onboard flash            */
+
+/*
+ * select i2c support configuration
+ *
+ * Supported configurations are {none, software, hardware} drivers.
+ * If the software driver is chosen, there are some additional
+ * configuration items that the driver uses to drive the port pins.
+ */
+#define CONFIG_HARD_I2C                1               /* To enable I2C support        */
+#undef  CONFIG_SOFT_I2C                                /* I2C bit-banged               */
+#define CFG_I2C_SPEED          400000          /* I2C speed and slave address  */
+#define CFG_I2C_SLAVE          0x7F
+
+#ifdef CONFIG_SOFT_I2C
+#error "Soft I2C is not configured properly.  Please review!"
+#define I2C_PORT               3               /* Port A=0, B=1, C=2, D=3 */
+#define I2C_ACTIVE             (iop->pdir |=  0x00010000)
+#define I2C_TRISTATE           (iop->pdir &= ~0x00010000)
+#define I2C_READ               ((iop->pdat & 0x00010000) != 0)
+#define I2C_SDA(bit)           if(bit) iop->pdat |=  0x00010000; \
+                               else    iop->pdat &= ~0x00010000
+#define I2C_SCL(bit)           if(bit) iop->pdat |=  0x00020000; \
+                               else    iop->pdat &= ~0x00020000
+#define I2C_DELAY              udelay(5)       /* 1/4 I2C clock duration */
+#endif /* CONFIG_SOFT_I2C */
+
+
+#define CFG_I2C_EEPROM_ADDR    0x57            /* EEPROM IS24C02               */
+#define CFG_I2C_EEPROM_ADDR_LEN        1               /* Bytes of address             */
+#define CFG_EEPROM_PAGE_WRITE_BITS     3       /* write page size              */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10      /* takes up to 10 msec          */
+
+
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+#define CFG_FLASH_BANKS                { FLASH_BASE0_PRELIM , FLASH_BASE1_PRELIM }
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+
+
+#define CFG_WINBOND_83C553     1       /*has a winbond bridge                  */
+#define CFG_USE_WINBOND_IDE    0       /*use winbond 83c553 internal IDE ctrlr */
+#define CFG_WINBOND_ISA_CFG_ADDR    0x80005800 /*pci-isa bridge config addr    */
+#define CFG_WINBOND_IDE_CFG_ADDR    0x80005900 /*ide config addr               */
+
+#define CFG_IDE_MAXBUS         2   /* max. 2 IDE busses        */
+#define CFG_IDE_MAXDEVICE      (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */
+
+/*
+ * NS87308 Configuration
+ */
+#define CFG_NS87308                    /* Nat Semi super-io controller on ISA bus */
+
+#define CFG_NS87308_BADDR_10   1
+
+#define CFG_NS87308_DEVS       ( CFG_NS87308_UART1   | \
+                                 CFG_NS87308_UART2   | \
+                                 CFG_NS87308_POWRMAN | \
+                                 CFG_NS87308_RTC_APC )
+
+#undef  CFG_NS87308_PS2MOD
+
+#define CFG_NS87308_CS0_BASE   0x0076
+#define CFG_NS87308_CS0_CONF   0x30
+#define CFG_NS87308_CS1_BASE   0x0075
+#define CFG_NS87308_CS1_CONF   0x30
+#define CFG_NS87308_CS2_BASE   0x0074
+#define CFG_NS87308_CS2_CONF   0x30
+
+/*
+ * NS16550 Configuration
+ */
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+
+#define CFG_NS16550_REG_SIZE   1
+
+#define CFG_NS16550_CLK                1843200
+
+#define CFG_NS16550_COM1       (CFG_ISA_IO + CFG_NS87308_UART1_BASE)
+#define CFG_NS16550_COM2       (CFG_ISA_IO + CFG_NS87308_UART2_BASE)
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+#define CONFIG_SYS_CLK_FREQ  33000000  /* external frequency to pll */
+#define CONFIG_PLL_PCI_TO_MEM_MULTIPLIER  2
+
+#define CFG_ROMNAL             7       /*rom/flash next access time            */
+#define CFG_ROMFAL             11      /*rom/flash access time                 */
+
+#define CFG_REFINT     430     /* no of clock cycles between CBR refresh cycles */
+
+/* the following are for SDRAM only*/
+#define CFG_BSTOPRE    121     /* Burst To Precharge, sets open page interval */
+#define CFG_REFREC             8       /* Refresh to activate interval         */
+#define CFG_RDLAT              4       /* data latency from read command       */
+#define CFG_PRETOACT           3       /* Precharge to activate interval       */
+#define CFG_ACTTOPRE           5       /* Activate to Precharge interval       */
+#define CFG_ACTORW             3       /* Activate to R/W                      */
+#define CFG_SDMODE_CAS_LAT     3       /* SDMODE CAS latency                   */
+#define CFG_SDMODE_WRAP                0       /* SDMODE wrap type                     */
+#define CFG_SDMODE_BURSTLEN    2       /* SDMODE Burst length 2=4, 3=8         */
+
+#define CFG_REGISTERD_TYPE_BUFFER   1
+
+/* memory bank settings*/
+/*
+ * only bits 20-29 are actually used from these vales to set the
+ * start/end address the upper two bits will be 0, and the lower 20
+ * bits will be set to 0x00000 for a start address, or 0xfffff for an
+ * end address
+ */
+#define CFG_BANK0_START                0x00000000
+#define CFG_BANK0_END          (CFG_MAX_RAM_SIZE - 1)
+#define CFG_BANK0_ENABLE       1
+#define CFG_BANK1_START                0x3ff00000
+#define CFG_BANK1_END          0x3fffffff
+#define CFG_BANK1_ENABLE       0
+#define CFG_BANK2_START                0x3ff00000
+#define CFG_BANK2_END          0x3fffffff
+#define CFG_BANK2_ENABLE       0
+#define CFG_BANK3_START                0x3ff00000
+#define CFG_BANK3_END          0x3fffffff
+#define CFG_BANK3_ENABLE       0
+#define CFG_BANK4_START                0x00000000
+#define CFG_BANK4_END          0x00000000
+#define CFG_BANK4_ENABLE       0
+#define CFG_BANK5_START                0x00000000
+#define CFG_BANK5_END          0x00000000
+#define CFG_BANK5_ENABLE       0
+#define CFG_BANK6_START                0x00000000
+#define CFG_BANK6_END          0x00000000
+#define CFG_BANK6_ENABLE       0
+#define CFG_BANK7_START                0x00000000
+#define CFG_BANK7_END          0x00000000
+#define CFG_BANK7_ENABLE       0
+/*
+ * Memory bank enable bitmask, specifying which of the banks defined above
+ are actually present. MSB is for bank #7, LSB is for bank #0.
+ */
+#define CFG_BANK_ENABLE                0x01
+
+#define CFG_ODCR               0xff    /* configures line driver impedances,   */
+                                       /* see 8240 book for bit definitions    */
+#define CFG_PGMAX              0x32    /* how long the 8240 retains the        */
+                                       /* currently accessed page in memory    */
+                                       /* see 8240 book for details            */
+
+/* SDRAM 0 - 256MB */
+#define CFG_IBAT0L     (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U     (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* stack in DCACHE @ 1GB (no backing mem) */
+#if defined(USE_DINK32)
+#define CFG_IBAT1L     (0x40000000 | BATL_PP_00 )
+#define CFG_IBAT1U     (0x40000000 | BATU_BL_128K )
+#else
+#define CFG_IBAT1L     (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT1U     (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
+#endif
+
+/* PCI memory */
+#define CFG_IBAT2L     (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U     (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* Flash, config addrs, etc */
+#define CFG_IBAT3L     (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U     (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L     CFG_IBAT0L
+#define CFG_DBAT0U     CFG_IBAT0U
+#define CFG_DBAT1L     CFG_IBAT1L
+#define CFG_DBAT1U     CFG_IBAT1U
+#define CFG_DBAT2L     CFG_IBAT2L
+#define CFG_DBAT2U     CFG_IBAT2U
+#define CFG_DBAT3L     CFG_IBAT3L
+#define CFG_DBAT3U     CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     20      /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32      /* For MPC8240 CPU                      */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#  define CFG_CACHELINE_SHIFT  5       /* log base 2 of the above value */
+#endif
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                      */
+
+
+/* values according to the manual */
+
+#define CONFIG_DRAM_50MHZ      1
+#define CONFIG_SDRAM_50MHZ
+
+#undef NR_8259_INTS
+#define NR_8259_INTS           1
+
+
+#define CONFIG_DISK_SPINUP_TIME 1000000
+
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/Sandpoint8245.h b/include/configs/Sandpoint8245.h
new file mode 100644 (file)
index 0000000..aa45675
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * (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
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC824X         1
+#define CONFIG_MPC8245         1
+#define CONFIG_SANDPOINT       1
+
+#if 0
+#define USE_DINK32             1
+#else
+#undef USE_DINK32
+#endif
+
+#define CONFIG_CONS_INDEX     3               /* set to '3' for on-chip DUART */
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_DRAM_SPEED      100             /* MHz                          */
+
+#define CONFIG_COMMANDS                ( CONFIG_CMD_DFL | \
+                                 CFG_CMD_ELF    | \
+                                 CFG_CMD_I2C    | \
+                                 CFG_CMD_EEPROM | \
+                                 CFG_CMD_PCI )
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any)      */
+#include <cmd_confdefs.h>
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP           1               /* undef to save memory         */
+#define CFG_PROMPT             "=> "           /* Monitor Command Prompt       */
+#define CFG_CBSIZE             256             /* Console I/O Buffer Size      */
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)  /* Print Buffer Size    */
+#define CFG_MAXARGS            16              /* max number of command args   */
+#define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR          0x00100000      /* default load address         */
+#define CFG_HZ                 1000            /* decrementer freq: 1 ms ticks */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_PCI                             /* include pci support          */
+#undef CONFIG_PCI_PNP
+
+#define CONFIG_NET_MULTI                       /* Multi ethernet cards support */
+
+#define CONFIG_EEPRO100
+#define CONFIG_NATSEMI
+#define CONFIG_NS8382X
+
+#define PCI_ENET0_IOADDR       0x80000000
+#define PCI_ENET0_MEMADDR      0x80000000
+#define        PCI_ENET1_IOADDR        0x81000000
+#define        PCI_ENET1_MEMADDR       0x81000000
+
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_MAX_RAM_SIZE       0x10000000
+
+#define CFG_RESET_ADDRESS      0xFFF00100
+
+#if defined (USE_DINK32)
+#define CFG_MONITOR_LEN                0x00030000
+#define CFG_MONITOR_BASE       0x00090000
+#define CFG_RAMBOOT            1
+#define CFG_INIT_RAM_ADDR      (CFG_MONITOR_BASE + CFG_MONITOR_LEN)
+#define CFG_INIT_RAM_END       0x10000
+#define CFG_GBL_DATA_SIZE      256  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET     CFG_GBL_DATA_OFFSET
+#else
+#undef CFG_RAMBOOT
+#define CFG_MONITOR_LEN                0x00030000
+#define CFG_MONITOR_BASE       TEXT_BASE
+
+/*#define CFG_GBL_DATA_SIZE    256*/
+#define CFG_GBL_DATA_SIZE      128
+
+#define CFG_INIT_RAM_ADDR     0x40000000
+#define CFG_INIT_RAM_END      0x1000
+#define CFG_GBL_DATA_OFFSET  (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+
+#endif
+
+#define CFG_FLASH_BASE         0xFFF00000
+#if 0
+#define CFG_FLASH_SIZE         (512 * 1024)    /* sandpoint has tiny eeprom    */
+#else
+#define CFG_FLASH_SIZE         (1024 * 1024)   /* Unity has onboard 1MByte flash */
+#endif
+#define CFG_ENV_IS_IN_FLASH    1
+#define CFG_ENV_OFFSET         0x00004000      /* Offset of Environment Sector */
+#define CFG_ENV_SIZE           0x00002000      /* Total Size of Environment Sector */
+
+#define CFG_MALLOC_LEN         (512 << 10)     /* Reserve 512 kB for malloc()  */
+
+#define CFG_MEMTEST_START      0x00000000      /* memtest works on             */
+#define CFG_MEMTEST_END                0x04000000      /* 0 ... 32 MB in DRAM          */
+
+#define CFG_EUMB_ADDR          0xFC000000
+
+#define CFG_ISA_MEM            0xFD000000
+#define CFG_ISA_IO             0xFE000000
+
+#define CFG_FLASH_RANGE_BASE   0xFF000000      /* flash memory address range   */
+#define CFG_FLASH_RANGE_SIZE   0x01000000
+#define FLASH_BASE0_PRELIM     0xFFF00000      /* sandpoint flash              */
+#define FLASH_BASE1_PRELIM     0xFF000000      /* PMC onboard flash            */
+
+/*
+ * select i2c support configuration
+ *
+ * Supported configurations are {none, software, hardware} drivers.
+ * If the software driver is chosen, there are some additional
+ * configuration items that the driver uses to drive the port pins.
+ */
+#define CONFIG_HARD_I2C                1               /* To enable I2C support        */
+#undef  CONFIG_SOFT_I2C                                /* I2C bit-banged               */
+#define CFG_I2C_SPEED          400000          /* I2C speed and slave address  */
+#define CFG_I2C_SLAVE          0x7F
+
+#ifdef CONFIG_SOFT_I2C
+#error "Soft I2C is not configured properly.  Please review!"
+#define I2C_PORT               3               /* Port A=0, B=1, C=2, D=3 */
+#define I2C_ACTIVE             (iop->pdir |=  0x00010000)
+#define I2C_TRISTATE           (iop->pdir &= ~0x00010000)
+#define I2C_READ               ((iop->pdat & 0x00010000) != 0)
+#define I2C_SDA(bit)           if(bit) iop->pdat |=  0x00010000; \
+                               else    iop->pdat &= ~0x00010000
+#define I2C_SCL(bit)           if(bit) iop->pdat |=  0x00020000; \
+                               else    iop->pdat &= ~0x00020000
+#define I2C_DELAY              udelay(5)       /* 1/4 I2C clock duration */
+#endif /* CONFIG_SOFT_I2C */
+
+#define CFG_I2C_EEPROM_ADDR    0x57            /* EEPROM IS24C02               */
+#define CFG_I2C_EEPROM_ADDR_LEN        1               /* Bytes of address             */
+#define CFG_EEPROM_PAGE_WRITE_BITS     3
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10      /* and takes up to 10 msec */
+
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+#define CFG_FLASH_BANKS                { FLASH_BASE0_PRELIM , FLASH_BASE1_PRELIM }
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+
+
+#define CFG_WINBOND_83C553     1       /*has a winbond bridge                  */
+#define CFG_USE_WINBOND_IDE    0       /*use winbond 83c553 internal IDE ctrlr */
+#define CFG_WINBOND_ISA_CFG_ADDR    0x80005800 /*pci-isa bridge config addr    */
+#define CFG_WINBOND_IDE_CFG_ADDR    0x80005900 /*ide config addr               */
+
+#define CFG_IDE_MAXBUS         2   /* max. 2 IDE busses        */
+#define CFG_IDE_MAXDEVICE      (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */
+
+/*
+ * NS87308 Configuration
+ */
+#define CFG_NS87308                    /* Nat Semi super-io controller on ISA bus */
+
+#define CFG_NS87308_BADDR_10   1
+
+#define CFG_NS87308_DEVS       ( CFG_NS87308_UART1   | \
+                                 CFG_NS87308_UART2   | \
+                                 CFG_NS87308_POWRMAN | \
+                                 CFG_NS87308_RTC_APC )
+
+#undef  CFG_NS87308_PS2MOD
+
+#define CFG_NS87308_CS0_BASE   0x0076
+#define CFG_NS87308_CS0_CONF   0x30
+#define CFG_NS87308_CS1_BASE   0x0075
+#define CFG_NS87308_CS1_CONF   0x30
+#define CFG_NS87308_CS2_BASE   0x0074
+#define CFG_NS87308_CS2_CONF   0x30
+
+/*
+ * NS16550 Configuration
+ */
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+
+#define CFG_NS16550_REG_SIZE   1
+
+#define CFG_NS16550_CLK                1843200
+
+#define CFG_NS16550_COM1       (CFG_ISA_IO + CFG_NS87308_UART1_BASE)
+#define CFG_NS16550_COM2       (CFG_ISA_IO + CFG_NS87308_UART2_BASE)
+#define CFG_NS16550_COM3       (CFG_EUMB_ADDR + 0x4500)
+#define CFG_NS16550_COM4       (CFG_EUMB_ADDR + 0x4600)
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+#define CONFIG_SYS_CLK_FREQ  33333333  /* external frequency to pll */
+
+#define CFG_ROMNAL             7       /*rom/flash next access time            */
+#define CFG_ROMFAL             11      /*rom/flash access time                 */
+
+#define CFG_REFINT     430     /* no of clock cycles between CBR refresh cycles */
+
+/* the following are for SDRAM only*/
+#define CFG_BSTOPRE    121     /* Burst To Precharge, sets open page interval */
+#define CFG_REFREC             8       /* Refresh to activate interval         */
+#define CFG_RDLAT              4       /* data latency from read command       */
+#define CFG_PRETOACT           3       /* Precharge to activate interval       */
+#define CFG_ACTTOPRE           5       /* Activate to Precharge interval       */
+#define CFG_ACTORW             3       /* Activate to R/W                      */
+#define CFG_SDMODE_CAS_LAT     3       /* SDMODE CAS latency                   */
+#define CFG_SDMODE_WRAP                0       /* SDMODE wrap type                     */
+#if 0
+#define CFG_SDMODE_BURSTLEN    2       /* OBSOLETE!  SDMODE Burst length 2=4, 3=8              */
+#endif
+
+#define CFG_REGISTERD_TYPE_BUFFER   1
+#define CFG_EXTROM 1
+#define CFG_REGDIMM 0
+
+
+/* memory bank settings*/
+/*
+ * only bits 20-29 are actually used from these vales to set the
+ * start/end address the upper two bits will be 0, and the lower 20
+ * bits will be set to 0x00000 for a start address, or 0xfffff for an
+ * end address
+ */
+#define CFG_BANK0_START                0x00000000
+#define CFG_BANK0_END          (CFG_MAX_RAM_SIZE - 1)
+#define CFG_BANK0_ENABLE       1
+#define CFG_BANK1_START                0x3ff00000
+#define CFG_BANK1_END          0x3fffffff
+#define CFG_BANK1_ENABLE       0
+#define CFG_BANK2_START                0x3ff00000
+#define CFG_BANK2_END          0x3fffffff
+#define CFG_BANK2_ENABLE       0
+#define CFG_BANK3_START                0x3ff00000
+#define CFG_BANK3_END          0x3fffffff
+#define CFG_BANK3_ENABLE       0
+#define CFG_BANK4_START                0x00000000
+#define CFG_BANK4_END          0x00000000
+#define CFG_BANK4_ENABLE       0
+#define CFG_BANK5_START                0x00000000
+#define CFG_BANK5_END          0x00000000
+#define CFG_BANK5_ENABLE       0
+#define CFG_BANK6_START                0x00000000
+#define CFG_BANK6_END          0x00000000
+#define CFG_BANK6_ENABLE       0
+#define CFG_BANK7_START                0x00000000
+#define CFG_BANK7_END          0x00000000
+#define CFG_BANK7_ENABLE       0
+/*
+ * Memory bank enable bitmask, specifying which of the banks defined above
+ are actually present. MSB is for bank #7, LSB is for bank #0.
+ */
+#define CFG_BANK_ENABLE                0x01
+
+#define CFG_ODCR               0xff    /* configures line driver impedances,   */
+                                       /* see 8240 book for bit definitions    */
+#define CFG_PGMAX              0x32    /* how long the 8240 retains the        */
+                                       /* currently accessed page in memory    */
+                                       /* see 8240 book for details            */
+
+/* SDRAM 0 - 256MB */
+#define CFG_IBAT0L     (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U     (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* stack in DCACHE @ 1GB (no backing mem) */
+#if defined(USE_DINK32)
+#define CFG_IBAT1L     (0x40000000 | BATL_PP_00 )
+#define CFG_IBAT1U     (0x40000000 | BATU_BL_128K )
+#else
+#define CFG_IBAT1L     (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT1U     (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
+#endif
+
+/* PCI memory */
+#define CFG_IBAT2L     (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U     (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* Flash, config addrs, etc */
+#define CFG_IBAT3L     (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U     (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L     CFG_IBAT0L
+#define CFG_DBAT0U     CFG_IBAT0U
+#define CFG_DBAT1L     CFG_IBAT1L
+#define CFG_DBAT1U     CFG_IBAT1U
+#define CFG_DBAT2L     CFG_IBAT2L
+#define CFG_DBAT2U     CFG_IBAT2U
+#define CFG_DBAT3L     CFG_IBAT3L
+#define CFG_DBAT3U     CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     20      /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32      /* For MPC8240 CPU                      */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#  define CFG_CACHELINE_SHIFT  5       /* log base 2 of the above value */
+#endif
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                      */
+
+
+/* values according to the manual */
+
+#define CONFIG_DRAM_50MHZ      1
+#define CONFIG_SDRAM_50MHZ
+
+#undef NR_8259_INTS
+#define NR_8259_INTS           1
+
+
+#define CONFIG_DISK_SPINUP_TIME 1000000
+
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/ZUMA.h b/include/configs/ZUMA.h
new file mode 100644 (file)
index 0000000..4978f7e
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <asm/processor.h>
+
+#define CFG_GT_6426x        GT_64260 /* with a 64260 system controller */
+#define CONFIG_ETHER_PORT_MII  /* use two MII ports */
+#define CONFIG_INTEL_LXT97X    /* Intel LXT97X phy */
+
+#ifndef __ASSEMBLY__
+#include <galileo/core.h>
+#endif
+
+#include "../board/evb64260/local.h"
+
+#define CONFIG_EVB64260                1       /* this is an EVB64260 board    */
+#define CONFIG_ZUMA_V2         1       /* always define this for ZUMA v2 */
+
+/* #define CONFIG_ZUMA_V2_OLD  1 */    /* backwards compat for old V2 board */
+
+#define CONFIG_BAUDRATE                38400   /* console baudrate = 38400     */
+
+#define CONFIG_ECC                     /* enable ECC support */
+
+#define CONFIG_750CX                   /* we have a 750CX/CXe (override local.h) */
+
+/* which initialization functions to call for this board */
+#define CONFIG_MISC_INIT_R
+#define CONFIG_BOARD_PRE_INIT
+#define CFG_BOARD_ASM_INIT
+
+#define CFG_BOARD_NAME         "Zuma APv2"
+
+#define CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2    "> "
+
+/*
+ * The following defines let you select what serial you want to use
+ * for your console driver.
+ *
+ * what to do:
+ * to use the DUART, undef CONFIG_MPSC.         If you have hacked a serial
+ * cable onto the second DUART channel, change the CFG_DUART port from 1
+ * to 0 below.
+ *
+ * to use the MPSC, #define CONFIG_MPSC.  If you have wired up another
+ * mpsc channel, change CONFIG_MPSC_PORT to the desired value.
+ */
+#define CONFIG_MPSC
+
+#define CONFIG_MPSC_PORT       0
+
+#define CONFIG_NET_MULTI        /* attempt all available adapters */
+
+/* define this if you want to enable GT MAC filtering */
+#define CONFIG_GT_USE_MAC_HASH_TABLE
+
+#if 1
+#define CONFIG_BOOTDELAY       -1      /* autoboot disabled            */
+#else
+#define CONFIG_BOOTDELAY       5       /* autoboot after 5 seconds     */
+#endif
+#define CONFIG_ZERO_BOOTDELAY_CHECK
+
+#undef CONFIG_BOOTARGS
+
+#define CONFIG_BOOTCOMMAND                                                     \
+       "tftpboot && "                                                          \
+       "setenv bootargs root=/dev/nfs rw nfsroot=$serverip:$rootpath " \
+       "ip=$ipaddr:$serverip:$gatewayip:"                              \
+       "$netmask:$hostname:eth0:none panic=5 && bootm"
+
+#define CONFIG_LOADS_ECHO      0       /* echo off for serial download */
+#define CFG_LOADS_BAUD_CHANGE          /* allow baudrate changes       */
+
+#undef CONFIG_WATCHDOG                 /* watchdog disabled            */
+#undef CONFIG_ALTIVEC                  /* undef to disable             */
+
+#define CONFIG_BOOTP_MASK      (CONFIG_BOOTP_DEFAULT | \
+                                CONFIG_BOOTP_BOOTFILESIZE)
+
+#define CONFIG_MII             /* enable MII commands */
+
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | \
+                                CFG_CMD_ASKENV | \
+                                CFG_CMD_BSP    | \
+                                CFG_CMD_JFFS2  | \
+                                CFG_CMD_MII    | \
+                                CFG_CMD_DATE)
+
+/* Flash banks JFFS2 should use */
+#define CFG_JFFS2_FIRST_BANK   1
+#define CFG_JFFS2_NUM_BANKS    2
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CBSIZE     1024            /* Console I/O Buffer Size      */
+#else
+#define CFG_CBSIZE     256             /* Console I/O Buffer Size      */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS    16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x00400000      /* memtest works on     */
+#define CFG_MEMTEST_END                0x00C00000      /* 4 ... 12 MB in DRAM  */
+
+#define CFG_LOAD_ADDR          0x00300000      /* default load address */
+
+#define CFG_HZ                 1000            /* decr freq: 1ms ticks */
+
+#define CFG_BUS_HZ             133000000       /* 133 MHz              */
+
+#define CFG_BUS_CLK            CFG_BUS_HZ
+
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200, 230400 }
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area
+ */
+#define CFG_INIT_RAM_ADDR      0x40000000
+#define CFG_INIT_RAM_END       0x1000
+#define CFG_GBL_DATA_SIZE      128  /* size in bytes reserved for init data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_RAM_LOCK
+
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xfff00000
+#define CFG_RESET_ADDRESS      0xfff00100
+#define CFG_MONITOR_LEN                (256 << 10)     /* Reserve 256 kB for Monitor */
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MALLOC_LEN         (256 << 10)     /* Reserve 256 kB for malloc */
+
+/* areas to map different things with the GT in physical space */
+#define CFG_DRAM_BANKS         4
+#define CFG_DFL_GT_REGS                0x14000000      /* boot time GT_REGS */
+
+/* What to put in the bats. */
+#define CFG_MISC_REGION_BASE   0xf0000000
+
+/* Peripheral Device section */
+#define CFG_GT_REGS            0xf8000000      /* later mapped GT_REGS */
+#define CFG_DEV_BASE           0xf0000000
+#define CFG_DEV0_SIZE          _64M /* zuma flash @ 0xf000.0000*/
+#define CFG_DEV1_SIZE           _8M /* zuma IDE   @ 0xf400.0000 */
+#define CFG_DEV2_SIZE           _8M /* unused */
+#define CFG_DEV3_SIZE           _8M /* unused */
+
+#define CFG_DEV0_PAR           0xc498243c
+       /*     c    4     9     8     2     4     3     c */
+       /* 33 22|2222|22 22|111 1|11 11|1 1  |     |      */
+       /* 10 98|7654|32 10|987 6|54 32|1 098|7 654|3 210 */
+       /* 11|00|0100|10 01|100|0 00|10 0|100 0|011 1|100 */
+       /*  3| 0|.... ..| 1| 4 |  0 |  4 |   8 |   7 | 4  */
+
+#define CFG_DEV1_PAR           0xc01b6ac5
+       /*     c    0     1     b     6     a     c     5 */
+       /* 33 22|2222|22 22|111 1|11 11|1 1  |     |      */
+       /* 10 98|7654|32 10|987 6|54 32|1 098|7 654|3 210 */
+       /* 11|00|0000|00 01|101|1 01|10 1|010 1|100 0|101 */
+       /*  3| 0|.... ..| 1| 5 |  5 |  5 |   5 |   8 | 5  */
+
+
+
+#define CFG_8BIT_BOOT_PAR      0xc00b5e7c
+
+#define CFG_MPP_CONTROL_0      0x00007777 /* GPP[7:4] : REQ0[1:0] GNT0[1:0] */
+#define CFG_MPP_CONTROL_1      0x00000000 /* GPP[15:12] : GPP[11:8] */
+#define CFG_MPP_CONTROL_2      0x00008888 /* GPP[23:20] : REQ1[1:0] GNT1[1:0] */
+#define CFG_MPP_CONTROL_3      0x00000000 /* GPP[31:28] (int[3:0]) */
+                                          /* GPP[27:24] (27 is int4, rest are GPP) */
+
+#define CFG_SERIAL_PORT_MUX    0x00001101 /* 11=MPSC1/MPSC0 01=ETH,  0=only MII */
+#define CFG_GPP_LEVEL_CONTROL  0xf8000000 /* interrupt inputs: GPP[31:27] */
+
+#define CFG_SDRAM_CONFIG       0xe4e18200      /* 0x448 */
+                               /* idmas use buffer 1,1
+                                  comm use buffer 1
+                                  pci use buffer 0,0 (pci1->0 pci0->0)
+                                  cpu use buffer 1 (R*18)
+                                  normal load (see also ifdef HVL)
+                                  standard SDRAM (see also ifdef REG)
+                                  non staggered refresh */
+                               /* 31:26  25 23  20 19 18 16 */
+                               /* 111001 00 111 0  0  00 1 */
+
+                               /* refresh count=0x200
+                                  phy interleave disable (by default,
+                                  set later by dram config..)
+                                  virt interleave enable */
+                               /* 15 14 13:0 */
+                               /* 1  0  0x200 */
+
+#define CFG_DEV0_SPACE         CFG_DEV_BASE
+#define CFG_DEV1_SPACE         (CFG_DEV0_SPACE + CFG_DEV0_SIZE)
+#define CFG_DEV2_SPACE         (CFG_DEV1_SPACE + CFG_DEV1_SIZE)
+#define CFG_DEV3_SPACE         (CFG_DEV2_SPACE + CFG_DEV2_SIZE)
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ */
+
+#define PCI_HOST_ADAPTER       0       /* configure ar pci adapter     */
+#define PCI_HOST_FORCE         1       /* configure as pci host        */
+#define PCI_HOST_AUTO          2       /* detected via arbiter enable  */
+
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function     */
+#define CONFIG_PCI_PNP                 /* do pci plug-and-play         */
+
+/* PCI MEMORY MAP section */
+#define CFG_PCI0_MEM_BASE      0x80000000
+#define CFG_PCI0_MEM_SIZE      _128M
+#define CFG_PCI1_MEM_BASE      0x88000000
+#define CFG_PCI1_MEM_SIZE      _128M
+
+#define CFG_PCI0_0_MEM_SPACE   (CFG_PCI0_MEM_BASE)
+#define CFG_PCI1_0_MEM_SPACE   (CFG_PCI1_MEM_BASE)
+
+/* PCI I/O MAP section */
+#define CFG_PCI0_IO_BASE       0xfa000000
+#define CFG_PCI0_IO_SIZE       _16M
+#define CFG_PCI1_IO_BASE       0xfb000000
+#define CFG_PCI1_IO_SIZE       _16M
+
+#define CFG_PCI0_IO_SPACE      (CFG_PCI0_IO_BASE)
+#define CFG_PCI0_IO_SPACE_PCI  0x00000000
+#define CFG_PCI1_IO_SPACE      (CFG_PCI1_IO_BASE)
+#define CFG_PCI1_IO_SPACE_PCI  0x00000000
+
+
+/*----------------------------------------------------------------------
+ * Initial BAT mappings
+ */
+
+/* NOTES:
+ * 1) GUARDED and WRITE_THRU not allowed in IBATS
+ * 2) CACHEINHIBIT and WRITETHROUGH not allowed together in same BAT
+ */
+
+/* SDRAM */
+#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_CACHEINHIBIT)
+#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+#define CFG_DBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE)
+#define CFG_DBAT0U CFG_IBAT0U
+
+/* init ram */
+#define CFG_IBAT1L  (CFG_INIT_RAM_ADDR | BATL_PP_RW | BATL_MEMCOHERENCE)
+#define CFG_IBAT1U  (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
+#define CFG_DBAT1L  CFG_IBAT1L
+#define CFG_DBAT1U  CFG_IBAT1U
+
+/* PCI0, PCI1 memory space (starting at PCI0 base, mapped in one BAT) */
+#define CFG_IBAT2L BATL_NO_ACCESS
+#define CFG_IBAT2U CFG_DBAT2U
+#define CFG_DBAT2L (CFG_PCI0_MEM_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE)
+#define CFG_DBAT2U (CFG_PCI0_MEM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* GT regs, bootrom, all the devices, PCI I/O */
+#define CFG_IBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW)
+#define CFG_IBAT3U (CFG_MISC_REGION_BASE | BATU_VS | BATU_VP | BATU_BL_256M)
+#define CFG_DBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE)
+#define CFG_DBAT3U CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8<<20) /* Initial Memory map for Linux */
+
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    3       /* max number of memory banks   */
+#define CFG_MAX_FLASH_SECT     130     /* max number of sectors on one chip */
+
+#define CFG_EXTRA_FLASH_DEVICE DEVICE0 /* extra flash at device 0 */
+#define CFG_EXTRA_FLASH_WIDTH  2       /* 16 bit */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms) */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms) */
+#define CFG_FLASH_CFI          1
+
+#define CFG_ENV_IS_IN_FLASH    1
+#define CFG_ENV_SIZE           0x1000  /* Total Size of Environment Sector */
+#define CFG_ENV_SECT_SIZE      0x10000 /* see README - env sect real size */
+#define CFG_ENV_ADDR           (0xfff80000 - CFG_ENV_SECT_SIZE)
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32      /* For all MPC74xx CPUs          */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    5       /* log base 2 of the above value */
+#endif
+
+/*-----------------------------------------------------------------------
+ * L2CR setup -- make sure this is right for your board!
+ * look in include/mpc74xx.h for the defines used here
+ */
+
+#define CFG_L2
+
+#ifdef CONFIG_750CX
+#define L2_INIT                0
+#else
+#define L2_INIT                (L2CR_L2SIZ_2M | L2CR_L2CLK_3 | L2CR_L2RAM_BURST | \
+                       L2CR_L2OH_5 | L2CR_L2CTL | L2CR_L2WT)
+#endif
+
+#define L2_ENABLE      (L2_INIT | L2CR_L2E)
+
+/*------------------------------------------------------------------------
+ * Real time clock
+ */
+#define CONFIG_RTC_DS1302
+
+
+/*------------------------------------------------------------------------
+ * Galileo I2C driver
+ */
+#define CONFIG_GT_I2C
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                  */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/shannon.h b/include/configs/shannon.h
new file mode 100644 (file)
index 0000000..c281707
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Configuation settings for the Shannon/TuxScreen/IS2630 WebPhone Board.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * If we are developing, we might want to start armboot from ram
+ * so we MUST NOT initialize critical regs like mem-timing ...
+ */
+
+/*
+ * we just run in non-critical mode now, because we use the Inferno-Loader to
+ * bring us to live
+ */
+#define CONFIG_INFERNO                 /* we are using the inferno bootldr */
+#undef CONFIG_INIT_CRITICAL            /* undef for developing */
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_SA1100          1       /* This is an SA1100 CPU        */
+#define CONFIG_SHANNON         1       /* on an SHANNON/TuxScreen Board      */
+
+#undef CONFIG_USE_IRQ                  /* we don't need IRQ/FIQ stuff */
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_MALLOC_SIZE     (CFG_ENV_SIZE + 128*1024)
+
+/*
+ * Hardware drivers
+ */
+#define CONFIG_DRIVER_3C589    1
+
+/*
+ * select serial console configuration
+ */
+#define CONFIG_SERIAL3          1      /* we use SERIAL 3  */
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_BAUDRATE                115200
+
+#if 0 /* XXX - cannot test IDE anyway, so disabled for now - wd */
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | \
+                                CFG_CMD_PCMCIA | \
+                                CFG_CMD_IDE)
+#endif /* 0 */
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#define CONFIG_BOOTDELAY       3
+#define CONFIG_BOOTARGS        "root=ramfs devfs=mount console=ttySA0,115200"
+#define CONFIG_NETMASK          255.255.0.0
+#define CONFIG_BOOTCOMMAND     "help"
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CONFIG_KGDB_BAUDRATE   230400          /* speed to run kgdb serial port */
+#define CONFIG_KGDB_SER_INDEX  2               /* which serial port to use */
+#endif
+
+/*
+ * Miscellaneous configurable options
+ */
+#define        CFG_LONGHELP                            /* undef to save memory         */
+#define        CFG_PROMPT              "TuxScreen # "  /* Monitor Command Prompt       */
+#define        CFG_CBSIZE              256             /* Console I/O Buffer Size      */
+#define        CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define        CFG_MAXARGS             16              /* max number of command args   */
+#define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0xc0400000      /* memtest works on     */
+#define CFG_MEMTEST_END                0xc0800000      /* 4 ... 8 MB in DRAM   */
+
+#undef  CFG_CLKS_IN_HZ         /* everything, incl board info, in Hz */
+
+#define        CFG_LOAD_ADDR           0xd0000000      /* default load address */
+
+#define        CFG_HZ                  3686400         /* incrementer freq: 3.6864 MHz */
+#define CFG_CPUSPEED           0x09            /* 190 MHz for Shannon */
+
+                                               /* valid baudrates */
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_DOS_PARTITION   1               /* DOS partitiion support */
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE       (128*1024)      /* regular stack */
+#ifdef CONFIG_USE_IRQ
+#define CONFIG_STACKSIZE_IRQ   (4*1024)        /* IRQ stack */
+#define CONFIG_STACKSIZE_FIQ   (4*1024)        /* FIQ stack */
+#endif
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+/* BE CAREFUL */
+#define CONFIG_NR_DRAM_BANKS   4          /* we have 4 banks of EDORAM */
+#define PHYS_SDRAM_1           0xc0000000 /* RAM Bank #1 */
+#define PHYS_SDRAM_1_SIZE      0x00400000 /* 4 MB */
+#define PHYS_SDRAM_2           0xc8000000 /* RAM Bank #2 */
+#define PHYS_SDRAM_2_SIZE      0x00400000 /* 4 MB */
+#define PHYS_SDRAM_3            0xd0000000 /* RAM Bank #3 */
+#define PHYS_SDRAM_3_SIZE       0x00400000 /* 4 MB */
+#define PHYS_SDRAM_4            0xd8000000 /* RAM Bank #4 */
+#define PHYS_SDRAM_4_SIZE       0x00400000 /* 4 MB */
+
+
+#define PHYS_FLASH_1           0x00000000 /* Flash Bank #1 */
+#define PHYS_FLASH_SIZE                0x00400000 /* 4 MB */
+
+#define CFG_FLASH_BASE         PHYS_FLASH_1
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+#define CFG_MAX_FLASH_BANKS    1       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     (31+4)  /* max number of sectors on one chip    */
+
+/* timeout values are in ticks */
+#define CFG_FLASH_ERASE_TOUT   (2*CFG_HZ) /* Timeout for Flash Erase */
+#define CFG_FLASH_WRITE_TOUT   (2*CFG_HZ) /* Timeout for Flash Write */
+
+#define        CFG_ENV_IS_IN_FLASH     1
+#ifdef CONFIG_INFERNO
+/* we take the last sector, 128 KB in size, but we only use 4 KB of it for stack reasons */
+#define CFG_ENV_ADDR           (PHYS_FLASH_1 + 0x003E0000)     /* Addr of Environment Sector   */
+#define CFG_ENV_SIZE           0x4000  /* Total Size of Environment Sector     */
+#else
+#define CFG_ENV_ADDR           (PHYS_FLASH_1 + 0x1C000)        /* Addr of Environment Sector   */
+#define CFG_ENV_SIZE           0x4000  /* Total Size of Environment Sector     */
+#endif
+
+/*-----------------------------------------------------------------------
+ * PCMCIA stuff
+ *-----------------------------------------------------------------------
+ *
+ */
+
+/* we pick the upper one */
+
+#define CONFIG_PCMCIA_SLOT_A
+
+#define CFG_PCMCIA_IO_ADDR     (0x20000000)
+#define CFG_PCMCIA_IO_SIZE     ( 64 << 20 )
+#define CFG_PCMCIA_DMA_ADDR    (0x24000000)
+#define CFG_PCMCIA_DMA_SIZE    ( 64 << 20 )
+#define CFG_PCMCIA_ATTRB_ADDR  (0x2C000000)
+#define CFG_PCMCIA_ATTRB_SIZE  ( 64 << 20 )
+#define CFG_PCMCIA_MEM_ADDR    (0x28000000)
+#define CFG_PCMCIA_MEM_SIZE    ( 64 << 20 )
+
+/* in fact, MEM and ATTRB are swapped - has to be corrected soon in cmd_pcmcia or so */
+
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter)
+ *-----------------------------------------------------------------------
+ */
+
+#define        CONFIG_IDE_PCCARD       1       /* Use IDE with PC Card Adapter */
+
+#undef CONFIG_IDE_PCMCIA               /* Direct IDE    not supported  */
+#undef CONFIG_IDE_LED                  /* LED   for ide not supported  */
+#undef CONFIG_IDE_RESET                /* reset for ide not supported  */
+
+#define CFG_IDE_MAXBUS         1       /* max. 1 IDE bus               */
+#define CFG_IDE_MAXDEVICE      1       /* max. 1 drive per IDE bus     */
+
+#define CFG_ATA_IDE0_OFFSET    0x0000
+
+/* it's simple, all regs are in I/O space */
+#define CFG_ATA_BASE_ADDR      CFG_PCMCIA_ATTRB_ADDR
+
+/* Offset for data I/O                 */
+#define CFG_ATA_DATA_OFFSET    (CFG_ATA_BASE_ADDR)
+
+/* Offset for normal register accesses */
+#define CFG_ATA_REG_OFFSET     (CFG_ATA_BASE_ADDR)
+
+/* Offset for alternate registers      */
+#define CFG_ATA_ALT_OFFSET     (CFG_ATA_BASE_ADDR)
+
+/*-----------------------------------------------------------------------
+ */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/trab.h b/include/configs/trab.h
new file mode 100644 (file)
index 0000000..7096767
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn <gj@denx.de>
+ *
+ * Configuation settings for the TRAB board.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * If we are developing, we might want to start armboot from ram
+ * so we MUST NOT initialize critical regs like mem-timing ...
+ */
+#define CONFIG_INIT_CRITICAL           /* undef for developing */
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_ARM920T         1       /* This is an arm920t CPU       */
+#define CONFIG_S3C2400         1       /* in a SAMSUNG S3C2400 SoC     */
+#define CONFIG_TRAB            1       /* on a TRAB Board      */
+#undef CONFIG_TRAB_50MHZ               /* run the CPU at 50 MHz */
+
+/* input clock of PLL */
+#define CONFIG_PLL_INPUT_FREQ  12000000 /* TRAB has 12 MHz input clock */
+
+#undef CONFIG_USE_IRQ                  /* we don't need IRQ/FIQ stuff */
+
+#define CONFIG_CMDLINE_TAG      1      /* enable passing of ATAGs      */
+#define CONFIG_SETUP_MEMORY_TAGS 1
+#define CONFIG_INITRD_TAG       1
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_MALLOC_SIZE     (CFG_ENV_SIZE + 128*1024)
+
+/*
+ * Hardware drivers
+ */
+#define CONFIG_DRIVER_CS8900   1       /* we have a CS8900 on-board */
+#define CS8900_BASE            0x07000300 /* agrees with WIN CE PA */
+#define CS8900_BUS16           1 /* the Linux driver does accesses as shorts */
+
+#define CONFIG_VFD             1       /* VFD linear frame buffer driver */
+#define VFD_TEST_LOGO          1       /* output a test logo to the VFDs */
+
+/*
+ * select serial console configuration
+ */
+#define CONFIG_SERIAL1          1      /* we use SERIAL 1 on TRAB */
+
+#define CONFIG_HWFLOW                  /* include RTS/CTS flow control support */
+
+#define CONFIG_MODEM_SUPPORT   1       /* enable modem initialization stuff */
+
+#define        CONFIG_MODEM_KEY_MAGIC  "23"    /* hold down these keys to enable modem */
+
+/*
+ * The following enables modem debugging stuff. The dbg() and
+ * 'char screen[1024]' are used for debug printfs. Unfortunately,
+ * it is usable only from BDI
+ */
+#undef CONFIG_MODEM_SUPPORT_DEBUG
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_BAUDRATE                115200
+
+#define        CONFIG_TIMESTAMP        1       /* Print timestamp info for images */
+
+#ifdef CONFIG_HWFLOW
+#define CONFIG_COMMANDS_ADD_HWFLOW     CFG_CMD_HWFLOW
+#else
+#define        CONFIG_COMMANDS_ADD_HWFLOW      0
+#endif
+
+#ifdef CONFIG_VFD
+#define CONFIG_COMMANDS_ADD_VFD                CFG_CMD_VFD
+#else
+#define CONFIG_COMMANDS_ADD_VFD                0
+#endif
+
+#ifndef USE_920T_MMU
+#define CONFIG_COMMANDS                ((CONFIG_CMD_DFL & ~CFG_CMD_CACHE) | \
+                                CFG_CMD_BSP                    | \
+                                CONFIG_COMMANDS_ADD_HWFLOW     | \
+                                CONFIG_COMMANDS_ADD_VFD        )
+#else
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL                 | \
+                                CFG_CMD_BSP                    | \
+                                CONFIG_COMMANDS_ADD_HWFLOW     | \
+                                CONFIG_COMMANDS_ADD_VFD        )
+#endif
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+
+#define CONFIG_BOOTDELAY       5
+#define CONFIG_PREBOOT         "echo;echo *** booting ***;echo"
+#define CONFIG_BOOTARGS        "console=ttyS0"
+#define CONFIG_ETHADDR         00:D0:93:00:61:11
+#define CONFIG_NETMASK          255.255.255.0
+#define CONFIG_IPADDR          192.168.3.27
+#define CONFIG_SERVERIP                192.168.3.1
+#define CONFIG_BOOTCOMMAND     "run flash_nfs"
+#define        CONFIG_EXTRA_ENV_SETTINGS       \
+       "nfs_args=setenv bootargs root=/dev/nfs rw " \
+               "nfsroot=$(serverip):$(rootpath)\0" \
+       "rootpath=/opt/eldk/arm_920TDI\0" \
+       "ram_args=setenv bootargs root=/dev/ram rw\0" \
+       "add_net=setenv bootargs $(bootargs) ethaddr=$(ethaddr) " \
+               "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off\0" \
+       "add_misc=setenv bootargs $(bootargs) console=ttyS0 panic=1\0" \
+       "load=tftp 0xC100000 /tftpboot/TRAB/u-boot.bin\0" \
+       "update=protect off 1:0-7;era 1:0-7;cp.b 0xc100000 0 $(filesize);" \
+               "setenv filesize;saveenv\0" \
+       "loadfile=/tftpboot/TRAB/pImage\0" \
+       "loadaddr=c400000\0" \
+       "net_load=tftpboot $(loadaddr) $(loadfile)\0" \
+       "net_nfs=run net_load nfs_args add_net add_misc;bootm\0" \
+       "kernel_addr=00040000\0" \
+       "flash_nfs=run nfs_args add_net add_misc;bootm $(kernel_addr)\0" \
+       "mdm_init1=ATZ\0" \
+       "mdm_init2=ATS0=1\0" \
+       "mdm_flow_control=rts/cts\0"
+
+#if 0  /* disabled for development */
+#define        CONFIG_AUTOBOOT_KEYED           /* Enable password protection   */
+#define CONFIG_AUTOBOOT_PROMPT "\nEnter password - autoboot in %d sec...\n"
+#define CONFIG_AUTOBOOT_DELAY_STR      "system"        /* 1st password */
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CONFIG_KGDB_BAUDRATE   115200          /* speed to run kgdb serial port */
+/* what's this ? it's not used anywhere */
+#define CONFIG_KGDB_SER_INDEX  1               /* which serial port to use */
+#endif
+
+/*
+ * Miscellaneous configurable options
+ */
+#define        CFG_LONGHELP                            /* undef to save memory         */
+#define        CFG_PROMPT              "TRAB # "       /* Monitor Command Prompt       */
+#define        CFG_CBSIZE              256             /* Console I/O Buffer Size      */
+#define        CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define        CFG_MAXARGS             16              /* max number of command args   */
+#define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x0c000000      /* memtest works on     */
+#define CFG_MEMTEST_END                0x0d000000      /* 16 MB in DRAM        */
+
+#undef  CFG_CLKS_IN_HZ         /* everything, incl board info, in Hz */
+
+#define        CFG_LOAD_ADDR           0x0cf00000      /* default load address */
+
+#ifdef CONFIG_TRAB_50MHZ
+/* the PWM TImer 4 uses a counter of 15625 for 10 ms, so we need */
+/* it to wrap 100 times (total 1562500) to get 1 sec. */
+/* this should _really_ be calculated !! */
+#define        CFG_HZ                  1562500
+#else
+/* the PWM TImer 4 uses a counter of 10390 for 10 ms, so we need */
+/* it to wrap 100 times (total 1039000) to get 1 sec. */
+/* this should _really_ be calculated !! */
+#define        CFG_HZ                  1039000
+#endif
+
+/* valid baudrates */
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_MISC_INIT_R             /* have misc_init_r() function  */
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE       (128*1024)      /* regular stack */
+#ifdef CONFIG_USE_IRQ
+#define CONFIG_STACKSIZE_IRQ   (4*1024)        /* IRQ stack */
+#define CONFIG_STACKSIZE_FIQ   (4*1024)        /* FIQ stack */
+#endif
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS   1          /* we have 1 bank of DRAM */
+#define PHYS_SDRAM_1           0x0c000000 /* SDRAM Bank #1 */
+#define PHYS_SDRAM_1_SIZE      0x01000000 /* 16 MB */
+
+#define PHYS_FLASH_1           0x00000000 /* Flash Bank #1 */
+#define PHYS_FLASH_SIZE                0x00800000 /* 8 MB */
+
+/* The following #defines are needed to get flash environment right */
+#define        CFG_MONITOR_BASE        PHYS_FLASH_1
+#define        CFG_MONITOR_LEN         (256 << 10)
+
+#define CFG_FLASH_BASE         PHYS_FLASH_1
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+#define CFG_MAX_FLASH_BANKS    1       /* max number of memory banks */
+#define CFG_MAX_FLASH_SECT     (71)    /* max number of sectors on one chip */
+
+/* timeout values are in ticks */
+#define CFG_FLASH_ERASE_TOUT   (2*CFG_HZ) /* Timeout for Flash Erase */
+#define CFG_FLASH_WRITE_TOUT   (2*CFG_HZ) /* Timeout for Flash Write */
+
+#define        CFG_ENV_IS_IN_FLASH     1
+
+/* Address and size of Primary Environment Sector      */
+#define CFG_ENV_ADDR           (PHYS_FLASH_1 + 0x4000)
+#define CFG_ENV_SIZE           0x4000
+
+/* Address and size of Redundant Environment Sector    */
+#define CFG_ENV_OFFSET_REDUND  (CFG_ENV_ADDR+CFG_ENV_SIZE)
+#define CFG_ENV_SIZE_REDUND    (CFG_ENV_SIZE)
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/utx8245.h b/include/configs/utx8245.h
new file mode 100644 (file)
index 0000000..5aec47a
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (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
+ */
+
+/*
+ *
+ * Configuration settings for the utx8245 board.
+ *
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC824X         1
+#define CONFIG_MPC8245         1
+#define CONFIG_UTX8245         1
+#define DEBUG                          1
+
+#define CONFIG_CONS_INDEX      1
+#define CONFIG_BAUDRATE                57600
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_BOOTDELAY       5
+#define CONFIG_AUTOBOOT_PROMPT         "autoboot in %d seconds\n"
+#define CONFIG_BOOTCOMMAND     "bootm FF920000 FF800000"       /* autoboot command     */
+#define CONFIG_BOOTARGS                "root=/dev/ram console=ttyS0,57600" /* RAMdisk */
+#define CONFIG_ETHADDR         41:52:4c:61:00:01       /* MAC address */
+#define CONFIG_SERVERIP                10.8.17.105
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_COMMANDS                (CFG_CMD_DFL | CFG_CMD_BDI | CFG_CMD_PCI \
+                                                               | CFG_CMD_FLASH | CFG_CMD_MEMORY \
+                                                               | CFG_CMD_ENV | CFG_CMD_CONSOLE \
+                                                               | CFG_CMD_LOADS | CFG_CMD_LOADB \
+                                                               | CFG_CMD_IMI | CFG_CMD_CACHE \
+                                                               | CFG_CMD_RUN | CFG_CMD_ECHO \
+                                                               | CFG_CMD_REGINFO | CFG_CMD_NET\
+                                                               | CFG_CMD_DHCP)
+
+/* This must be included AFTER the definition of CONFIG_COMMANDS (if any)
+ */
+#include <cmd_confdefs.h>
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define CFG_PROMPT     "=> "           /* Monitor Command Prompt       */
+#define CFG_CBSIZE     256             /* Console I/O Buffer Size      */
+
+/* Print Buffer Size */
+#define CFG_PBSIZE     (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)
+
+#define        CFG_MAXARGS     16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR  0x00100000      /* Default load address         */
+
+
+/*-----------------------------------------------------------------------
+ * PCI configuration
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_PCI                             /* include pci support          */
+#undef CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+#define CONFIG_NET_MULTI
+#define CONFIG_EEPRO100
+
+#define PCI_ENET0_IOADDR       0x80000000
+#define PCI_ENET0_MEMADDR      0x80000000
+#define PCI_FIREWIRE_IOADDR    0x81000000
+#define PCI_FIREWIRE_MEMADDR   0x81000000
+
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE     0x00000000
+#define CFG_MAX_RAM_SIZE    0x10000000 /* amount of SDRAM  */
+
+
+/* even though FLASHP_BASE is FF800000, with 2MB on RCS0, the
+ * reset vector is actually located at FF800100, but the 8245
+ * takes care of us.
+ */
+#define CFG_RESET_ADDRESS   0xFFF00100
+
+#define CFG_EUMB_ADDR      0xFC000000
+
+#define CFG_MONITOR_BASE    TEXT_BASE
+
+#define CFG_MONITOR_LEN            (256 << 10) /* Reserve 256 kB for Monitor   */
+#define CFG_MALLOC_LEN     (128 << 10) /* Reserve 128 kB for malloc()  */
+
+/*#define CFG_DRAM_TEST                1 */
+#define CFG_MEMTEST_START   0x00003000 /* memtest works on     0...256 MB      */
+#define CFG_MEMTEST_END            0x0ff8ffa8  /* in SDRAM, skips exception */
+                                                                               /* vectors and U-Boot */
+
+
+/*--------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area
+ *------------------------------------------------------------------*/
+#define CFG_GBL_DATA_SIZE    128       /* Size in bytes reserved for */
+                                                                       /* initial data */
+#define CFG_INIT_RAM_ADDR     0x40000000
+#define CFG_INIT_RAM_END      0x1000
+#define CFG_GBL_DATA_OFFSET  (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+
+/*--------------------------------------------------------------------
+ * NS16550 Configuration
+ *------------------------------------------------------------------*/
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+
+#define CFG_NS16550_REG_SIZE   1
+
+#define CFG_NS16550_CLK                get_bus_freq(0)
+
+#define CFG_NS16550_COM1       (CFG_EUMB_ADDR + 0x4500)
+#define CFG_NS16550_COM2       (CFG_EUMB_ADDR + 0x4600)
+
+/*--------------------------------------------------------------------
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ * For the detail description refer to the MPC8240 user's manual.
+ *------------------------------------------------------------------*/
+
+#define CONFIG_SYS_CLK_FREQ  33000000
+#define CFG_HZ                         1000
+
+#define CFG_ETH_DEV_FN      0x7800
+#define CFG_ETH_IOBASE      0x00104000
+
+
+/*--------------------------------------------------------------------
+ *     Memory Control Configuration Register values
+ *     - see sec. 4.12 of MPC8245 UM
+ *------------------------------------------------------------------*/
+
+/* MCCR1 */
+#define CFG_ROMNAL         0
+#define CFG_ROMFAL         2                   /* (tacc=70ns)*mem_freq - 2 */
+#define CFG_BANK0_ROW  2                       /* SDRAM bank 7-0 row address */
+#define CFG_BANK1_ROW  2                       /*      bit count */
+#define CFG_BANK2_ROW  0
+#define CFG_BANK3_ROW  0
+#define CFG_BANK4_ROW  0
+#define CFG_BANK5_ROW  0
+#define CFG_BANK6_ROW  0
+#define CFG_BANK7_ROW  0
+
+/* MCCR2, refresh interval clock cycles */
+#define CFG_REFINT         480     /* 33 MHz SDRAM clock was 480 */
+
+/* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4 */
+#define CFG_BSTOPRE        1023        /* burst to precharge[0..9], */
+                                                               /* sets open page interval */
+
+/* MCCR3 */
+#define CFG_REFREC         5       /* Refresh to activate interval, trc */
+
+/* MCCR4 */
+#define CFG_PRETOACT       2       /* trp */
+#define CFG_ACTTOPRE       7       /* trcd + (burst length - 1) + tdrl */
+#define CFG_SDMODE_CAS_LAT  3      /* SDMODE CAS latancy */
+#define CFG_SDMODE_WRAP            0       /* SDMODE wrap type, sequential */
+#define CFG_ACTORW             2               /* trcd min */
+#define CFG_DBUS_SIZE2         1               /* set for 8-bit RCS1, clear for 32,64 */
+#define CFG_REGISTERD_TYPE_BUFFER 1
+#define CFG_EXTROM         1
+#define CFG_REGDIMM        0
+
+/* calculate according to formula in sec. 6-22 of 8245 UM */
+#define CFG_PGMAX           50         /* how long the 8245 retains the */
+                                                                       /* currently accessed page in memory */
+                                                                       /* was 45 */
+
+#define CFG_SDRAM_DSCD 0x20    /* SDRAM data in sample clock delay - note */
+                                                               /* bottom 3 bits MUST be 0 */
+
+#define CFG_DLL_MAX_DELAY      0x04
+#define CFG_DLL_EXTEND 0x80
+#define CFG_PCI_HOLD_DEL 0x20
+
+
+/* Memory bank settings.
+ * Only bits 20-29 are actually used from these values to set the
+ * start/end addresses. The upper two bits will always be 0, and the lower
+ * 20 bits will be 0x00000 for a start address, or 0xfffff for an end
+ * address. Refer to the MPC8245 user manual.
+ */
+
+#define CFG_BANK0_START            0x00000000
+#define CFG_BANK0_END      (CFG_MAX_RAM_SIZE/2 - 1)
+#define CFG_BANK0_ENABLE    1
+#define CFG_BANK1_START            CFG_MAX_RAM_SIZE/2
+#define CFG_BANK1_END      (CFG_MAX_RAM_SIZE - 1)
+#define CFG_BANK1_ENABLE    1
+#define CFG_BANK2_START            0x3ff00000          /* not available in this design */
+#define CFG_BANK2_END      0x3fffffff
+#define CFG_BANK2_ENABLE    0
+#define CFG_BANK3_START            0x3ff00000
+#define CFG_BANK3_END      0x3fffffff
+#define CFG_BANK3_ENABLE    0
+#define CFG_BANK4_START            0x3ff00000
+#define CFG_BANK4_END      0x3fffffff
+#define CFG_BANK4_ENABLE    0
+#define CFG_BANK5_START            0x3ff00000
+#define CFG_BANK5_END      0x3fffffff
+#define CFG_BANK5_ENABLE    0
+#define CFG_BANK6_START            0x3ff00000
+#define CFG_BANK6_END      0x3fffffff
+#define CFG_BANK6_ENABLE    0
+#define CFG_BANK7_START            0x3ff00000
+#define CFG_BANK7_END      0x3fffffff
+#define CFG_BANK7_ENABLE    0
+
+/*--------------------------------------------------------------------
+ * 4.4 - Output Driver Control Register
+ *------------------------------------------------------------------*/
+#define CFG_ODCR           0xe5
+
+/*--------------------------------------------------------------------
+ * 4.8 - Error Handling Registers
+ *------------------------------------------------------------------*/
+#define CFG_ERRENR1    0x11    /* enable SDRAM refresh overflow error */
+
+/* SDRAM 0-256 MB */
+#define CFG_IBAT0L  (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U  (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* stack in dcache */
+#define CFG_IBAT1L  (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT1U  (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
+
+/* PCI memory */
+#define CFG_IBAT2L  (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U  (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+/* Flash, config addrs, etc. */
+#define CFG_IBAT3L  (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U  (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L  CFG_IBAT0L
+#define CFG_DBAT0U  CFG_IBAT0U
+#define CFG_DBAT1L  CFG_IBAT1L
+#define CFG_DBAT1U  CFG_IBAT1U
+#define CFG_DBAT2L  CFG_IBAT2L
+#define CFG_DBAT2U  CFG_IBAT2U
+#define CFG_DBAT3L  CFG_IBAT3L
+#define CFG_DBAT3U  CFG_IBAT3U
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ      (8 << 20)   /* Initial Memory map for Linux */
+
+/*-----------------------------------------------------------------------
+ * FLASH organization (AMD AM29LV116D)
+ */
+#define CFG_FLASH_BASE     0xFF800000
+
+#define CFG_MAX_FLASH_BANKS    1       /* Max number of flash banks */
+#define CFG_MAX_FLASH_SECT     35      /* Max number of sectors in one bank */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500             /* Timeout for Flash Write (in ms)      */
+
+       /* Warning: environment is not EMBEDDED in the U-Boot code.
+        * It's stored in flash separately.
+        */
+#define CFG_ENV_IS_IN_FLASH        1
+
+#define CFG_ENV_ADDR           0xFF9FA000      /* flash sector SA33 */
+#define CFG_ENV_SIZE           0x2000          /* Size of the Environment */
+#define CFG_ENV_OFFSET         0                       /* starting right at the beginning */
+#define CFG_ENV_SECT_SIZE      0x2000          /* Size of the Environment Sector */
+
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+#undef CFG_RAMBOOT
+#else
+#define CFG_RAMBOOT
+#endif
+
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     32
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#  define CFG_CACHELINE_SHIFT  5       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                      */
+
+
+#endif /* __CONFIG_H */
diff --git a/include/dtt.h b/include/dtt.h
new file mode 100644 (file)
index 0000000..f3d95ff
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * (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
+ */
+
+/*
+ * Digital Thermometers and Thermostats.
+ */
+#ifndef _DTT_H_
+#define _DTT_H_
+
+#if defined(CONFIG_DTT_LM75) || defined(CONFIG_DTT_DS1621)
+#define CONFIG_DTT                             /* We have a DTT */
+
+#define DTT_COMMERCIAL_MAX_TEMP        70              /* 0 - +70 C */
+#define DTT_INDUSTRIAL_MAX_TEMP        85              /* -40 - +85 C */
+#define DTT_AUTOMOTIVE_MAX_TEMP        105             /* -40 - +105 C */
+#ifndef CFG_DTT_MAX_TEMP
+#define CFG_DTT_MAX_TEMP DTT_COMMERCIAL_MAX_TEMP
+#endif
+#ifndef CFG_DTT_HYSTERESIS
+#define CFG_DTT_HYSTERESIS     5               /* 5 C */
+#endif
+
+extern int dtt_init (void);
+extern int dtt_read(int sensor, int reg);
+extern int dtt_write(int sensor, int reg, int val);
+extern int dtt_get_temp(int sensor);
+#endif
+
+#if defined(CONFIG_DTT_LM75)
+#define DTT_READ_TEMP          0x0
+#define DTT_CONFIG             0x1
+#define DTT_TEMP_HYST          0x2
+#define DTT_TEMP_SET           0x3
+#endif
+
+#if defined(CONFIG_DTT_DS1621)
+#define DTT_READ_TEMP          0xAA
+#define DTT_READ_COUNTER       0xA8
+#define DTT_READ_SLOPE         0xA9
+#define DTT_WRITE_START_CONV   0xEE
+#define DTT_WRITE_STOP_CONV    0x22
+#define DTT_TEMP_HIGH          0xA1
+#define DTT_TEMP_LOW           0xA2
+#define DTT_CONFIG             0xAC
+#endif
+
+#endif /* _DTT_H_ */
diff --git a/include/environment.h b/include/environment.h
new file mode 100644 (file)
index 0000000..fe8465b
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * (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
+ */
+
+#ifndef _ENVIRONMENT_H_
+#define _ENVIRONMENT_H_        1
+
+/**************************************************************************
+ *
+ * The "environment" is stored as a list of '\0' terminated
+ * "name=value" strings. The end of the list is marked by a double
+ * '\0'. New entries are always added at the end. Deleting an entry
+ * shifts the remaining entries to the front. Replacing an entry is a
+ * combination of deleting the old value and adding the new one.
+ *
+ * The environment is preceeded by a 32 bit CRC over the data part.
+ *
+ **************************************************************************
+ */
+
+#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_OFFSET
+#  define CFG_ENV_OFFSET (CFG_ENV_ADDR - CFG_FLASH_BASE)
+# endif
+# if !defined(CFG_ENV_ADDR_REDUND) && defined(CFG_ENV_OFFSET_REDUND)
+#  define CFG_ENV_ADDR_REDUND  (CFG_FLASH_BASE + CFG_ENV_OFFSET_REDUND)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
+# endif
+# if defined(CFG_ENV_ADDR_REDUND) && !defined(CFG_ENV_SIZE_REDUND)
+#  define CFG_ENV_SIZE_REDUND  CFG_ENV_SIZE
+# endif
+# if (CFG_ENV_ADDR >= CFG_MONITOR_BASE) && \
+     (CFG_ENV_ADDR+CFG_ENV_SIZE) <= (CFG_MONITOR_BASE + CFG_MONITOR_LEN)
+#  define ENV_IS_EMBEDDED      1
+# endif
+# if defined(CFG_ENV_ADDR_REDUND) || defined(CFG_ENV_OFFSET_REDUND)
+#  define CFG_REDUNDAND_ENVIRONMENT    1
+# endif
+#endif /* CFG_ENV_IS_IN_FLASH */
+
+
+#ifdef CFG_REDUNDAND_ENVIRONMENT
+# define ENV_HEADER_SIZE       (sizeof(unsigned long) + 1)
+#else
+# define ENV_HEADER_SIZE       (sizeof(unsigned long))
+#endif
+
+
+#define ENV_SIZE (CFG_ENV_SIZE - ENV_HEADER_SIZE)
+
+typedef        struct environment_s {
+       unsigned long   crc;            /* CRC32 over data bytes        */
+#ifdef CFG_REDUNDAND_ENVIRONMENT
+       unsigned char   flags;          /* active/obsolete flags        */
+#endif
+       unsigned char   data[ENV_SIZE]; /* Environment data             */
+} env_t;
+
+#endif /* _ENVIRONMENT_H_ */
diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h
new file mode 100644 (file)
index 0000000..cff850f
--- /dev/null
@@ -0,0 +1,180 @@
+#ifndef _LINUX_BYTEORDER_GENERIC_H
+#define _LINUX_BYTEORDER_GENERIC_H
+
+/*
+ * linux/byteorder_generic.h
+ * Generic Byte-reordering support
+ *
+ * Francois-Rene Rideau <fare@tunes.org> 19970707
+ *    gathered all the good ideas from all asm-foo/byteorder.h into one file,
+ *    cleaned them up.
+ *    I hope it is compliant with non-GCC compilers.
+ *    I decided to put __BYTEORDER_HAS_U64__ in byteorder.h,
+ *    because I wasn't sure it would be ok to put it in types.h
+ *    Upgraded it to 2.1.43
+ * Francois-Rene Rideau <fare@tunes.org> 19971012
+ *    Upgraded it to 2.1.57
+ *    to please Linus T., replaced huge #ifdef's between little/big endian
+ *    by nestedly #include'd files.
+ * Francois-Rene Rideau <fare@tunes.org> 19971205
+ *    Made it to 2.1.71; now a facelift:
+ *    Put files under include/linux/byteorder/
+ *    Split swab from generic support.
+ *
+ * TODO:
+ *   = Regular kernel maintainers could also replace all these manual
+ *    byteswap macros that remain, disseminated among drivers,
+ *    after some grep or the sources...
+ *   = Linus might want to rename all these macros and files to fit his taste,
+ *    to fit his personal naming scheme.
+ *   = it seems that a few drivers would also appreciate
+ *    nybble swapping support...
+ *   = every architecture could add their byteswap macro in asm/byteorder.h
+ *    see how some architectures already do (i386, alpha, ppc, etc)
+ *   = cpu_to_beXX and beXX_to_cpu might some day need to be well
+ *    distinguished throughout the kernel. This is not the case currently,
+ *    since little endian, big endian, and pdp endian machines needn't it.
+ *    But this might be the case for, say, a port of Linux to 20/21 bit
+ *    architectures (and F21 Linux addict around?).
+ */
+
+/*
+ * The following macros are to be defined by <asm/byteorder.h>:
+ *
+ * Conversion of long and short int between network and host format
+ *     ntohl(__u32 x)
+ *     ntohs(__u16 x)
+ *     htonl(__u32 x)
+ *     htons(__u16 x)
+ * It seems that some programs (which? where? or perhaps a standard? POSIX?)
+ * might like the above to be functions, not macros (why?).
+ * if that's true, then detect them, and take measures.
+ * Anyway, the measure is: define only ___ntohl as a macro instead,
+ * and in a separate file, have
+ * unsigned long inline ntohl(x){return ___ntohl(x);}
+ *
+ * The same for constant arguments
+ *     __constant_ntohl(__u32 x)
+ *     __constant_ntohs(__u16 x)
+ *     __constant_htonl(__u32 x)
+ *     __constant_htons(__u16 x)
+ *
+ * Conversion of XX-bit integers (16- 32- or 64-)
+ * between native CPU format and little/big endian format
+ * 64-bit stuff only defined for proper architectures
+ *     cpu_to_[bl]eXX(__uXX x)
+ *     [bl]eXX_to_cpu(__uXX x)
+ *
+ * The same, but takes a pointer to the value to convert
+ *     cpu_to_[bl]eXXp(__uXX x)
+ *     [bl]eXX_to_cpup(__uXX x)
+ *
+ * The same, but change in situ
+ *     cpu_to_[bl]eXXs(__uXX x)
+ *     [bl]eXX_to_cpus(__uXX x)
+ *
+ * See asm-foo/byteorder.h for examples of how to provide
+ * architecture-optimized versions
+ *
+ */
+
+
+#if defined(__KERNEL__)
+/*
+ * inside the kernel, we can use nicknames;
+ * outside of it, we must avoid POSIX namespace pollution...
+ */
+#define cpu_to_le64 __cpu_to_le64
+#define le64_to_cpu __le64_to_cpu
+#define cpu_to_le32 __cpu_to_le32
+#define le32_to_cpu __le32_to_cpu
+#define cpu_to_le16 __cpu_to_le16
+#define le16_to_cpu __le16_to_cpu
+#define cpu_to_be64 __cpu_to_be64
+#define be64_to_cpu __be64_to_cpu
+#define cpu_to_be32 __cpu_to_be32
+#define be32_to_cpu __be32_to_cpu
+#define cpu_to_be16 __cpu_to_be16
+#define be16_to_cpu __be16_to_cpu
+#define cpu_to_le64p __cpu_to_le64p
+#define le64_to_cpup __le64_to_cpup
+#define cpu_to_le32p __cpu_to_le32p
+#define le32_to_cpup __le32_to_cpup
+#define cpu_to_le16p __cpu_to_le16p
+#define le16_to_cpup __le16_to_cpup
+#define cpu_to_be64p __cpu_to_be64p
+#define be64_to_cpup __be64_to_cpup
+#define cpu_to_be32p __cpu_to_be32p
+#define be32_to_cpup __be32_to_cpup
+#define cpu_to_be16p __cpu_to_be16p
+#define be16_to_cpup __be16_to_cpup
+#define cpu_to_le64s __cpu_to_le64s
+#define le64_to_cpus __le64_to_cpus
+#define cpu_to_le32s __cpu_to_le32s
+#define le32_to_cpus __le32_to_cpus
+#define cpu_to_le16s __cpu_to_le16s
+#define le16_to_cpus __le16_to_cpus
+#define cpu_to_be64s __cpu_to_be64s
+#define be64_to_cpus __be64_to_cpus
+#define cpu_to_be32s __cpu_to_be32s
+#define be32_to_cpus __be32_to_cpus
+#define cpu_to_be16s __cpu_to_be16s
+#define be16_to_cpus __be16_to_cpus
+#endif
+
+
+/*
+ * Handle ntohl and suches. These have various compatibility
+ * issues - like we want to give the prototype even though we
+ * also have a macro for them in case some strange program
+ * wants to take the address of the thing or something..
+ *
+ * Note that these used to return a "long" in libc5, even though
+ * long is often 64-bit these days.. Thus the casts.
+ *
+ * They have to be macros in order to do the constant folding
+ * correctly - if the argument passed into a inline function
+ * it is no longer constant according to gcc..
+ */
+
+#undef ntohl
+#undef ntohs
+#undef htonl
+#undef htons
+
+/*
+ * Do the prototypes. Somebody might want to take the
+ * address or some such sick thing..
+ */
+#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
+extern __u32                   ntohl(__u32);
+extern __u32                   htonl(__u32);
+#else
+extern unsigned long int       ntohl(unsigned long int);
+extern unsigned long int       htonl(unsigned long int);
+#endif
+extern unsigned short int      ntohs(unsigned short int);
+extern unsigned short int      htons(unsigned short int);
+
+
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+
+#define ___htonl(x) __cpu_to_be32(x)
+#define ___htons(x) __cpu_to_be16(x)
+#define ___ntohl(x) __be32_to_cpu(x)
+#define ___ntohs(x) __be16_to_cpu(x)
+
+#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
+#define htonl(x) ___htonl(x)
+#define ntohl(x) ___ntohl(x)
+#else
+#define htonl(x) ((unsigned long)___htonl(x))
+#define ntohl(x) ((unsigned long)___ntohl(x))
+#endif
+#define htons(x) ___htons(x)
+#define ntohs(x) ___ntohs(x)
+
+#endif /* OPTIMIZE */
+
+
+#endif /* _LINUX_BYTEORDER_GENERIC_H */
diff --git a/include/mpc824x.h b/include/mpc824x.h
new file mode 100644 (file)
index 0000000..0cd7898
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ * Copyright Rob Taylor, Flying Pig Systems Ltd. 2000.
+ * Copyright (C) 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
+ */
+
+#ifndef __MPC824X_H__
+#define __MPC824X_H__
+
+#include <config.h>
+
+/* CPU Types */
+#define CPU_TYPE_601           0x01            /* PPC 601       CPU */
+#define CPU_TYPE_602           0x02            /* PPC 602       CPU */
+#define CPU_TYPE_603           0x03            /* PPC 603       CPU */
+#define CPU_TYPE_603E          0x06            /* PPC 603e      CPU */
+#define CPU_TYPE_603P          0x07            /* PPC 603p      CPU */
+#define CPU_TYPE_604           0x04            /* PPC 604       CPU */
+#define CPU_TYPE_604E          0x09            /* PPC 604e      CPU */
+#define CPU_TYPE_604R          0x0a            /* PPC 604r      CPU */
+#define CPU_TYPE_750           0x08            /* PPC 750       CPU */
+#define CPU_TYPE_8240          0x81            /* PPC 8240      CPU */
+#define CPU_TYPE_8245          0x8081          /* PPC 8245/8241 CPU */
+#define _CACHE_ALIGN_SIZE      32              /* cache line size */
+
+/* spr976 - DMISS data tlb miss address register
+ * spr977 - DCMP data tlb miss compare register
+ * spr978 - HASH1 PTEG1 address register
+ * spr980 - HASH2 PTEG2 address register
+ * IMISS  - instruction tlb miss address register
+ * ICMP          - instruction TLB mis compare register
+ * RPA   - real page address register
+ * HID0          - hardware implemntation register
+ * HID2          - instruction address breakpoint register
+ */
+
+/* Kahlua/MPC8240 defines */
+#define VEN_DEV_ID             0x00021057      /* Vendor and Dev. ID for MPC106 */
+#define KAHLUA_ID              0x00031057      /* Vendor & Dev Id for Kahlua's PCI */
+#define KAHLUA2_ID             0x00061057      /* 8245 is aka Kahlua-2 */
+#define BMC_BASE               0x80000000      /* Kahlua ID in PCI Memory space */
+#define CHRP_REG_ADDR          0xfec00000      /* MPC107 Config, Map B */
+#define CHRP_REG_DATA          0xfee00000      /* MPC107 Config, Map B */
+#define CHRP_ISA_MEM_PHYS      0xfd000000
+#define CHRP_ISA_MEM_BUS       0x00000000
+#define CHRP_ISA_MEM_SIZE      0x01000000
+#define CHRP_ISA_IO_PHYS       0xfe000000
+#define CHRP_ISA_IO_BUS                0x00000000
+#define CHRP_ISA_IO_SIZE       0x00800000
+#define CHRP_PCI_IO_PHYS       0xfe800000
+#define CHRP_PCI_IO_BUS                0x00800000
+#define CHRP_PCI_IO_SIZE       0x00400000
+#define CHRP_PCI_MEM_PHYS      0x80000000
+#define CHRP_PCI_MEM_BUS       0x80000000
+#define CHRP_PCI_MEM_SIZE      0x7d000000
+#define        CHRP_PCI_MEMORY_PHYS    0x00000000
+#define        CHRP_PCI_MEMORY_BUS     0x00000000
+#define CHRP_PCI_MEMORY_SIZE   0x40000000
+#define PREP_REG_ADDR          0x80000cf8      /* MPC107 Config, Map A */
+#define PREP_REG_DATA          0x80000cfc      /* MPC107 Config, Map A */
+#define PREP_ISA_IO_PHYS       0x80000000
+#define PREP_ISA_IO_BUS                0x00000000
+#define PREP_ISA_IO_SIZE       0x00800000
+#define PREP_PCI_IO_PHYS       0x81000000
+#define PREP_PCI_IO_BUS                0x01000000
+#define PREP_PCI_IO_SIZE       0x3e800000
+#define PREP_PCI_MEM_PHYS      0xc0000000
+#define PREP_PCI_MEM_BUS       0x00000000
+#define PREP_PCI_MEM_SIZE      0x3f000000
+#define        PREP_PCI_MEMORY_PHYS    0x00000000
+#define        PREP_PCI_MEMORY_BUS     0x80000000
+#define        PREP_PCI_MEMORY_SIZE    0x80000000
+#define MPC107_PCI_CMD         0x80000004      /* MPC107 PCI cmd reg */
+#define MPC107_PCI_STAT        0x80000006      /* MPC107 PCI status reg */
+#define PROC_INT1_ADR          0x800000a8      /* MPC107 Processor i/f cfg1 */
+#define PROC_INT2_ADR          0x800000ac      /* MPC107 Processor i/f cfg2 */
+#define MEM_CONT1_ADR          0x800000f0      /* MPC107 Memory control config. 1 */
+#define MEM_CONT2_ADR          0x800000f4      /* MPC107 Memory control config. 2 */
+#define MEM_CONT3_ADR          0x800000f8      /* MPC107 Memory control config. 3 */
+#define MEM_CONT4_ADR          0x800000fc      /* MPC107 Memory control config. 4 */
+#define MEM_ERREN1_ADR         0x800000c0      /* MPC107 Memory error enable 1 */
+#define MEM_START1_ADR         0x80000080      /* MPC107 Memory starting addr */
+#define MEM_START2_ADR         0x80000084      /* MPC107 Memory starting addr-lo */
+#define XMEM_START1_ADR        0x80000088      /* MPC107 Extended mem. start addr-hi*/
+#define XMEM_START2_ADR        0x8000008c      /* MPC107 Extended mem. start addr-lo*/
+#define MEM_END1_ADR           0x80000090      /* MPC107 Memory ending address */
+#define MEM_END2_ADR           0x80000094      /* MPC107 Memory ending addr-lo */
+#define XMEM_END1_ADR          0x80000098      /* MPC107 Extended mem. end addrs-hi */
+#define XMEM_END2_ADR          0x8000009c      /* MPC107 Extended mem. end addrs-lo*/
+#define OUT_DRV_CONT           0x80000073      /* MPC107 Output Driver Control reg */
+#define MEM_EN_ADR             0x800000a0      /* Memory bank enable */
+#define PAGE_MODE              0x800000a3      /* MPC107 Page Mode Counter/Timer */
+
+/*-----------------------------------------------------------------------
+ * Exception offsets (PowerPC standard)
+ */
+#define EXC_OFF_RESERVED0      0x0000  /* Reserved */
+#define EXC_OFF_SYS_RESET      0x0100  /* System reset */
+#define EXC_OFF_MACH_CHCK      0x0200  /* Machine Check */
+#define EXC_OFF_DATA_STOR      0x0300  /* Data Storage */
+#define EXC_OFF_INS_STOR       0x0400  /* Instruction Storage */
+#define EXC_OFF_EXTERNAL       0x0500  /* External */
+#define EXC_OFF_ALIGN          0x0600  /* Alignment */
+#define EXC_OFF_PROGRAM                0x0700  /* Program */
+#define EXC_OFF_FPUNAVAIL      0x0800  /* Floating-point Unavailable */
+#define EXC_OFF_DECR           0x0900  /* Decrementer */
+#define EXC_OFF_RESERVED1      0x0A00  /* Reserved */
+#define EXC_OFF_RESERVED2      0x0B00  /* Reserved */
+#define EXC_OFF_SYS_CALL       0x0C00  /* System Call */
+#define EXC_OFF_TRACE          0x0D00  /* Trace */
+#define EXC_OFF_FPUNASSIST     0x0E00  /* Floating-point Assist */
+
+       /* 0x0E10 - 0x0FFF are marked reserved in The PowerPC Architecture book */
+       /* these found in DINK code  - may not apply to 8240*/
+#define EXC_OFF_PMI            0x0F00  /* Performance Monitoring Interrupt */
+#define EXC_OFF_VMXUI          0x0F20  /* VMX (AltiVec) Unavailable Interrupt */
+
+       /* 0x1000 - 0x2FFF are implementation specific */
+       /* these found in DINK code  - may not apply to 8240 */
+#define EXC_OFF_ITME           0x1000  /* Instruction Translation Miss Exception */
+#define EXC_OFF_DLTME          0x1100  /* Data Load Translation Miss Exception */
+#define EXC_OFF_DSTME          0x1200  /* Data Store Translation Miss Exception */
+#define EXC_OFF_IABE           0x1300  /* Instruction Addr Breakpoint Exception */
+#define EXC_OFF_SMIE           0x1400  /* System Management Interrupt Exception */
+#define EXC_OFF_JMDDI          0x1600  /* Java Mode denorm detect Interr -- WTF??*/
+#define EXC_OFF_RMTE           0x2000  /* Run Mode or Trace Exception */
+
+#define MAP_A_CONFIG_ADDR_HIGH 0x8000  /* Upper half of CONFIG_ADDR for Map A */
+#define MAP_A_CONFIG_ADDR_LOW  0x0CF8  /* Lower half of CONFIG_ADDR for Map A */
+#define MAP_A_CONFIG_DATA_HIGH 0x8000  /* Upper half of CONFIG_DAT for Map A */
+#define MAP_A_CONFIG_DATA_LOW  0x0CFC  /* Lower half of CONFIG_DAT for Map A */
+#define MAP_B_CONFIG_ADDR_HIGH 0xfec0  /* Upper half of CONFIG_ADDR for Map B */
+#define MAP_B_CONFIG_ADDR_LOW  0x0000  /* Lower half of CONFIG_ADDR for Map B */
+#define MAP_B_CONFIG_DATA_HIGH 0xfee0  /* Upper half of CONFIG_DAT for Map B */
+#define MAP_B_CONFIG_DATA_LOW  0x0000  /* Lower half of CONFIG_DAT for Map B */
+
+
+#if defined(CFG_ADDR_MAP_A)
+#define CONFIG_ADDR_HIGH    MAP_A_CONFIG_ADDR_HIGH  /* Upper half of CONFIG_ADDR */
+#define CONFIG_ADDR_LOW            MAP_A_CONFIG_ADDR_LOW   /* Lower half of CONFIG_ADDR */
+#define CONFIG_DATA_HIGH    MAP_A_CONFIG_DATA_HIGH  /* Upper half of CONFIG_DAT */
+#define CONFIG_DATA_LOW            MAP_A_CONFIG_DATA_LOW   /* Lower half of CONFIG_DAT */
+#else /* Assume Map B, default */
+#define CONFIG_ADDR_HIGH    MAP_B_CONFIG_ADDR_HIGH  /* Upper half of CONFIG_ADDR */
+#define CONFIG_ADDR_LOW            MAP_B_CONFIG_ADDR_LOW   /* Lower half of CONFIG_ADDR */
+#define CONFIG_DATA_HIGH    MAP_B_CONFIG_DATA_HIGH  /* Upper half of CONFIG_DAT */
+#define CONFIG_DATA_LOW            MAP_B_CONFIG_DATA_LOW   /* Lower half of CONFIG_DAT */
+#endif
+
+#define CONFIG_ADDR    (CONFIG_ADDR_HIGH << 16 | CONFIG_ADDR_LOW)
+
+#define CONFIG_DATA    (CONFIG_DATA_HIGH << 16 | CONFIG_DATA_LOW)
+
+/* Macros to write to config registers. addr should be a constant in all cases */
+
+#define CONFIG_WRITE_BYTE( addr, data ) \
+  __asm__ __volatile__( \
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stb %3, %4(%2)\n \
+    sync " \
+  : /* no output */ \
+  : "r" (CONFIG_ADDR), "r" ((addr) & ~3), \
+    "b" (CONFIG_DATA), "r" (data), \
+    "n" ((addr) & 3));
+
+#define CONFIG_WRITE_HALFWORD( addr, data ) \
+  __asm__ __volatile__( \
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    sthbrx %3, %4, %2\n \
+    sync " \
+  : /* no output */ \
+  : "r" (CONFIG_ADDR), "r" ((addr) & ~3), \
+    "r" (CONFIG_DATA), "r" (data), \
+    "b" ((addr) & 3));
+
+/* this assumes it's writeing on word boundaries*/
+#define CONFIG_WRITE_WORD( addr, data ) \
+  __asm__ __volatile__( \
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stwbrx %3, 0, %2\n \
+    sync " \
+  : /* no output */ \
+  : "r" (CONFIG_ADDR), "r" (addr), \
+    "r" (CONFIG_DATA), "r" (data));
+
+/* Configuration register reads*/
+
+#define CONFIG_READ_BYTE( addr, reg ) \
+  __asm__ ( \
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lbz          %0, %4(%3)\n \
+    sync " \
+  : "=r" (reg) \
+  : "r" ((addr) & ~3), "r" (CONFIG_ADDR), \
+    "b" (CONFIG_DATA), "n" ((addr) & 3));
+
+
+#define CONFIG_READ_HALFWORD( addr, reg ) \
+  __asm__ ( \
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lhbrx %0, %4, %3\n \
+    sync " \
+  : "=r" (reg) \
+  : "r" ((addr) & ~3), "r" (CONFIG_ADDR), \
+    "r" (CONFIG_DATA), \
+    "b" ((addr) & 3));
+
+/* this assumes it's reading on word boundaries*/
+#define CONFIG_READ_WORD( addr, reg ) \
+  __asm__ ( \
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lwbrx %0, 0, %3\n \
+    sync " \
+  : "=r" (reg) \
+  : "r" (addr), "r" (CONFIG_ADDR),\
+    "r" (CONFIG_DATA));
+
+/*
+ *  configuration register 'addresses'.
+ *  These are described in chaper 5 of the 8240 users manual.
+ *  Where the register has an abreviation in the manual, this has
+ *  been usaed here, otherwise a name in keeping with the norm has
+ *  been invented.
+ *  Note that some of these registers aren't documented in the manual.
+ */
+
+#define PCICR          0x80000004  /* PCI Command Register */
+#define PCISR          0x80000006  /* PCI Status Register */
+#define REVID          0x80000008  /* CPU revision id */
+#define PIR            0x80000009  /* PCI Programming Interface Register */
+#define PBCCR          0x8000000b  /* PCI Base Class Code Register */
+#define PCLSR          0x8000000c  /* Processor Cache Line Size Register */
+#define PLTR           0x8000000d  /* PCI Latancy Timer Register */
+#define PHTR           0x8000000e  /* PCI Header Type Register */
+#define BISTCTRL       0x8000000f  /* BIST Control */
+#define LMBAR          0x80000010  /* Local Base Addres Register */
+#define PCSRBAR                0x80000014  /* PCSR Base Address Register */
+#define ILR            0x8000003c  /* PCI Interrupt Line Register */
+#define IPR            0x8000003d  /* Interrupt Pin Register */
+#define MINGNT         0x8000003e  /* MIN GNI */
+#define MAXLAT         0x8000003f  /* MAX LAT */
+#define PCIACR         0x80000046  /* PCI Arbiter Control Register */
+#define PMCR1          0x80000070  /* Power management config. 1 */
+#define PMCR2          0x80000072  /* Power management config. 2 */
+#define ODCR           0x80000073  /* Output Driver Control Register */
+#define CLKDCR         0x80000074  /* CLK Driver Control Register */
+#if defined(CONFIG_MPC8245) || defined(CONFIG_MPC8241)
+#define MIOCR1         0x80000076  /* Miscellaneous I/O Control Register 1 */
+#define MIOCR2         0x80000077  /* Miscellaneous I/O Control Register 2 */
+#endif
+#define EUMBBAR                0x80000078  /* Embedded Utilities Memory Block Base Address Register */
+#define EUMBBAR_VAL    0x80500000  /* PCI Relocation offset for EUMB region */
+#define EUMBSIZE       0x00100000  /* Size of EUMB region */
+
+#define MSAR1          0x80000080  /* Memory Starting Address Register 1 */
+#define MSAR2          0x80000084  /* Memory Starting Address Register 2 */
+#define EMSAR1         0x80000088  /* Extended Memory Starting Address Register 1*/
+#define EMSAR2         0x8000008c  /* Extended Memory Starting Address Register 2*/
+#define MEAR1          0x80000090  /* Memory Ending Address Register 1 */
+#define MEAR2          0x80000094  /* Memory Ending Address Register 2 */
+#define EMEAR1         0x80000098  /* Extended Memory Ending Address Register 1 */
+#define EMEAR2         0x8000009c  /* Extended Memory Ending Address Register 2 */
+#define MBER           0x800000a0  /* Memory bank Enable Register*/
+#define MPMR           0x800000a3  /* Memory Page Mode Register (stores PGMAX) */
+#define PICR1          0x800000a8  /* Processor Interface Configuration Register 1 */
+#define PICR2          0x800000ac  /* Processor Interface Configuration Register 2 */
+#define ECCSBECR       0x800000b8  /* ECC Single-Bit Error Counter Register */
+#define ECCSBETR       0x800000b8  /* ECC Single-Bit Error Trigger Register */
+#define ERRENR1                0x800000c0  /* Error Enableing Register 1 */
+#define ERRENR2                0x800000c4  /* Error Enableing Register 2 */
+#define ERRDR1         0x800000c1  /* Error Detection Register 1 */
+#define IPBESR         0x800000c3  /* Internal Processor Error Status Register */
+#define ERRDR2         0x800000c5  /* Error Detection Register 2 */
+#define PBESR          0x800000c7  /* PCI Bus Error Status Register */
+#define PBEAR          0x800000c8  /* Processor/PCI Bus Error Status Register */
+#define AMBOR          0x800000e0  /* Address Map B Options Register */
+#define MCCR1          0x800000f0  /* Memory Control Configuration Register 1 */
+#define MCCR2          0x800000f4  /* Memory Control Configuration Register 2 */
+#define MCCR3          0x800000f8  /* Memory Control Configuration Register 3 */
+#define MCCR4          0x800000fc  /* Memory Control Configuration Register 4 */
+
+/* some values for some of the above */
+
+#define PICR1_CF_APARK         0x00000008
+#define PICR1_LE_MODE          0x00000020
+#define PICR1_ST_GATH_EN       0x00000040
+#if defined(CONFIG_MPC8240)
+#define PICR1_EN_PCS           0x00000080 /* according to dink code, sets the 8240 to handle pci config space */
+#elif defined(CONFIG_MPC8245) || defined(CONFIG_MPC8241)
+#define PICR1_NO_BUSW_CK       0x00000080 /* no bus width check for flash writes */
+#define PICR1_DEC              0x00000100 /* Time Base enable on 8245/8241 */
+#define ERCR1                  0x800000d0  /* Extended ROM Configuration Register 1 */
+#define ERCR2                  0x800000d4  /* Extended ROM Configuration Register 2 */
+#define ERCR3                  0x800000d8  /* Extended ROM Configuration Register 3 */
+#define ERCR4                  0x800000dc  /* Extended ROM Configuration Register 4 */
+#define MIOCR1                 0x80000076  /* Miscellaneous I/O Control Register 1 */
+#define MIOCR1_ADR_X           0x80000074  /* Miscellaneous I/O Control Register 1 */
+#define MIOCR1_SHIFT           2
+#define MIOCR2                 0x80000077  /* Miscellaneous I/O Control Register 2 */
+#define MIOCR2_ADR_X           0x80000074  /* Miscellaneous I/O Control Register 1 */
+#define MIOCR2_SHIFT           3
+#define ODCR_ADR_X             0x80000070      /* Output Driver Control register */
+#define ODCR_SHIFT              3
+#define PMCR2_ADR              0x80000072      /* Power Mgmnt Cfg 2 register */
+#define PMCR2_ADR_X            0x80000070
+#define PMCR2_SHIFT             3
+#define PMCR1_ADR              0x80000070      /* Power Mgmnt Cfg 1 reister */
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+#define PICR1_CF_DPARK         0x00000200
+#define PICR1_MCP_EN           0x00000800
+#define PICR1_FLASH_WR_EN      0x00001000
+#ifdef CONFIG_MPC8240
+#define PICR1_ADDRESS_MAP      0x00010000
+#define PIRC1_MSK              0xff000000
+#endif
+#define PICR1_PROC_TYPE_MSK    0x00060000
+#define PICR1_PROC_TYPE_603E   0x00040000
+#define PICR1_RCS0             0x00100000
+
+#define PICR2_CF_SNOOP_WS_MASK 0x000c0000
+#define PICR2_CF_SNOOP_WS_0WS  0x00000000
+#define PICR2_CF_SNOOP_WS_1WS  0x00040000
+#define PICR2_CF_SNOOP_WS_2WS  0x00080000
+#define PICR2_CF_SNOOP_WS_3WS  0x000c0000
+#define PICR2_CF_APHASE_WS_MASK 0x0000000c
+#define PICR2_CF_APHASE_WS_0WS 0x00000000
+#define PICR2_CF_APHASE_WS_1WS 0x00000004
+#define PICR2_CF_APHASE_WS_2WS 0x00000008
+#define PICR2_CF_APHASE_WS_3WS 0x0000000c
+
+#define MCCR1_ROMNAL_SHIFT     28
+#define MCCR1_ROMNAL_MSK       0xf0000000
+#define MCCR1_ROMFAL_SHIFT     23
+#define MCCR1_ROMFAL_MSK       0x0f800000
+#define MCCR1_DBUS_SIZE0        0x00400000
+#define MCCR1_BURST            0x00100000
+#define MCCR1_MEMGO            0x00080000
+#define MCCR1_SREN             0x00040000
+#if defined(CONFIG_MPC8240)
+#define MCCR1_RAM_TYPE         0x00020000
+#elif defined(CONFIG_MPC8245) || defined(CONFIG_MPC8241)
+#define MCCR1_SDRAM_EN         0x00020000
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+#define MCCR1_PCKEN            0x00010000
+#define MCCR1_BANK1ROW_SHIFT   2
+#define MCCR1_BANK2ROW_SHIFT   4
+#define MCCR1_BANK3ROW_SHIFT   6
+#define MCCR1_BANK4ROW_SHIFT   8
+#define MCCR1_BANK5ROW_SHIFT   10
+#define MCCR1_BANK6ROW_SHIFT   12
+#define MCCR1_BANK7ROW_SHIFT   14
+
+#define MCCR2_TS_WAIT_TIMER_MSK 0xe0000000
+#define MCCR2_TS_WAIT_TIMER_SHIFT 29
+#define MCCR2_ASRISE_MSK       0x1e000000
+#define MCCR2_ASRISE_SHIFT     25
+#define MCCR2_ASFALL_MSK       0x01e00000
+#define MCCR2_ASFALL_SHIFT     21
+
+#define MCCR2_INLINE_PAR_NOT_ECC    0x00100000
+#define MCCR2_WRITE_PARITY_CHK 0x00080000
+#define MCCR2_INLFRD_PARECC_CHK_EN  0x00040000
+#ifdef CONFIG_MPC8240
+#define MCCR2_ECC_EN           0x00020000
+#define MCCR2_EDO              0x00010000
+#endif
+#define MCCR2_REFINT_MSK       0x0000fffc
+#define MCCR2_REFINT_SHIFT     2
+#define MCCR2_RSV_PG           0x00000002
+#define MCCR2_PMW_PAR          0x00000001
+
+#define MCCR3_BSTOPRE2TO5_MSK  0xf0000000 /*BSTOPRE[2-5]*/
+#define MCCR3_BSTOPRE2TO5_SHIFT 28
+#define MCCR3_REFREC_MSK       0x0f000000
+#define MCCR3_REFREC_SHIFT     24
+#ifdef CONFIG_MPC8240
+#define MCCR3_RDLAT_MSK                0x00f00000
+#define MCCR3_RDLAT_SHIFT      20
+#define MCCR3_CPX              0x00010000
+#define MCCR3_RAS6P_MSK                0x00078000
+#define MCCR3_RAS6P_SHIFT      15
+#define MCCR3_CAS5_MSK         0x00007000
+#define MCCR3_CAS5_SHIFT       12
+#define MCCR3_CP4_MSK          0x00000e00
+#define MCCR3_CP4_SHIFT                9
+#define MCCR3_CAS3_MSK         0x000001c0
+#define MCCR3_CAS3_SHIFT       6
+#define MCCR3_RCD2_MSK         0x00000038
+#define MCCR3_RCD2_SHIFT       3
+#define MCCR3_RP1_MSK          0x00000007
+#define MCCR3_RP1_SHIFT                0
+#endif
+
+#define MCCR4_PRETOACT_MSK     0xf0000000
+#define MCCR4_PRETOACT_SHIFT   28
+#define MCCR4_ACTTOPRE_MSK     0x0f000000
+#define MCCR4_ACTTOPRE_SHIFT   24
+#define MCCR4_WMODE            0x00800000
+#define MCCR4_INLINE           0x00400000
+#if defined(CONFIG_MPC8240)
+#define MCCR4_BIT21            0x00200000 /* this include cos DINK code sets it- unknown function*/
+#elif defined(CONFIG_MPC8245) || defined(CONFIG_MPC8241)
+#define MCCR4_EXTROM           0x00200000 /* enables Extended ROM space */
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+#define MCCR4_REGISTERED       0x00100000
+#define MCCR4_BSTOPRE0TO1_MSK  0x000c0000 /*BSTOPRE[0-1]*/
+#define MCCR4_BSTOPRE0TO1_SHIFT 18
+#define MCCR4_REGDIMM          0x00008000
+#define MCCR4_SDMODE_MSK       0x00007f00
+#define MCCR4_SDMODE_SHIFT     8
+#define MCCR4_ACTTORW_MSK      0x000000f0
+#define MCCR4_ACTTORW_SHIFT    4
+#define MCCR4_BSTOPRE6TO9_MSK  0x0000000f /*BSTOPRE[6-9]*/
+#define MCCR4_BSTOPRE6TO9_SHIFT 0
+#define MCCR4_DBUS_SIZE2_SHIFT 17
+
+#define MICR_ADDR_MASK         0x0ff00000
+#define MICR_ADDR_SHIFT                20
+#define MICR_EADDR_MASK                0x30000000
+#define MICR_EADDR_SHIFT       28
+
+#define BATU_BEPI_MSK          0xfffe0000
+#define BATU_BL_MSK            0x00001ffc
+
+#define BATU_BL_128K           0x00000000
+#define BATU_BL_256K           0x00000004
+#define BATU_BL_512K           0x0000000c
+#define BATU_BL_1M             0x0000001c
+#define BATU_BL_2M             0x0000003c
+#define BATU_BL_4M             0x0000007c
+#define BATU_BL_8M             0x000000fc
+#define BATU_BL_16M            0x000001fc
+#define BATU_BL_32M            0x000003fc
+#define BATU_BL_64M            0x000007fc
+#define BATU_BL_128M           0x00000ffc
+#define BATU_BL_256M           0x00001ffc
+
+#define BATU_VS                        0x00000002
+#define BATU_VP                        0x00000001
+
+#define BATL_BRPN_MSK          0xfffe0000
+#define BATL_WIMG_MSK          0x00000078
+
+#define BATL_WRITETHROUGH      0x00000040
+#define BATL_CACHEINHIBIT      0x00000020
+#define BATL_MEMCOHERENCE      0x00000010
+#define BATL_GUARDEDSTORAGE    0x00000008
+
+#define BATL_PP_MSK            0x00000003
+#define BATL_PP_00             0x00000000 /* No access */
+#define BATL_PP_01             0x00000001 /* Read-only */
+#define BATL_PP_10             0x00000002 /* Read-write */
+#define BATL_PP_11             0x00000003
+
+/*
+ * I'd attempt to do defines for the PP bits, but it's use is a bit
+ * too complex, see the PowerPC Operating Environment Architecture
+ * section in the PowerPc arch book, chapter 4.
+ */
+
+/*eumb and epic config*/
+
+#define EPIC_FPR               0x00041000
+#define EPIC_GCR               0x00041020
+#define EPIC_EICR              0x00041030
+#define EPIC_EVI               0x00041080
+#define EPIC_PI                        0x00041090
+#define EPIC_SVR               0x000410E0
+#define EPIC_TFRR              0x000410F0
+
+/*
+ * Note the information for these is rather mangled in the 8240 manual.
+ * These are guesses.
+ */
+
+#define EPIC_GTCCR0            0x00041100
+#define EPIC_GTCCR1            0x00041140
+#define EPIC_GTCCR2            0x00041180
+#define EPIC_GTCCR3            0x000411C0
+#define EPIC_GTBCR0            0x00041110
+#define EPIC_GTBCR1            0x00041150
+#define EPIC_GTBCR2            0x00041190
+#define EPIC_GTBCR3            0x000411D0
+#define EPIC_GTVPR0            0x00041120
+#define EPIC_GTVPR1            0x00041160
+#define EPIC_GTVPR2            0x000411a0
+#define EPIC_GTVPR3            0x000411e0
+#define EPIC_GTDR0             0x00041130
+#define EPIC_GTDR1             0x00041170
+#define EPIC_GTDR2             0x000411b0
+#define EPIC_GTDR3             0x000411f0
+
+#define EPIC_IVPR0             0x00050200
+#define EPIC_IVPR1             0x00050220
+#define EPIC_IVPR2             0x00050240
+#define EPIC_IVPR3             0x00050260
+#define EPIC_IVPR4             0x00050280
+
+#define EPIC_SVPR0             0x00050200
+#define EPIC_SVPR1             0x00050220
+#define EPIC_SVPR2             0x00050240
+#define EPIC_SVPR3             0x00050260
+#define EPIC_SVPR4             0x00050280
+#define EPIC_SVPR5             0x000502A0
+#define EPIC_SVPR6             0x000502C0
+#define EPIC_SVPR7             0x000502E0
+#define EPIC_SVPR8             0x00050300
+#define EPIC_SVPR9             0x00050320
+#define EPIC_SVPRa             0x00050340
+#define EPIC_SVPRb             0x00050360
+#define EPIC_SVPRc             0x00050380
+#define EPIC_SVPRd             0x000503A0
+#define EPIC_SVPRe             0x000503C0
+#define EPIC_SVPRf             0x000503E0
+
+/* MPC8240 Byte Swap/PCI Support Macros */
+#define BYTE_SWAP_16_BIT(x)    ( (((x) & 0x00ff) << 8) | ( (x) >> 8) )
+#define LONGSWAP(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\
+                    (((x) & 0x00ff0000) >>  8) | (((x) & 0xff000000) >> 24) )
+#define PCISWAP(x)   LONGSWAP(x)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * MPC107 Support
+ *
+ */
+unsigned int mpc824x_mpc107_getreg(unsigned int regNum);
+void mpc824x_mpc107_setreg(unsigned int regNum, unsigned int regVal);
+void mpc824x_mpc107_write8(unsigned int address, unsigned char data);
+void mpc824x_mpc107_write16(unsigned int address, unsigned short data);
+void mpc824x_mpc107_write32(unsigned int address, unsigned int data);
+unsigned char mpc824x_mpc107_read8(unsigned int address);
+unsigned short mpc824x_mpc107_read16(unsigned int address);
+unsigned int mpc824x_mpc107_read32(unsigned int address);
+unsigned int mpc824x_eummbar_read(unsigned int regNum);
+void mpc824x_eummbar_write(unsigned int regNum, unsigned int regVal);
+
+#ifdef CONFIG_PCI
+struct pci_controller;
+void pci_cpm824x_init(struct pci_controller* hose);
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __MPC824X_H__ */
diff --git a/include/pci.h b/include/pci.h
new file mode 100644 (file)
index 0000000..4875375
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * (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
+ * aloong with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PCI_H
+#define _PCI_H
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID          0x00    /* 16 bits */
+#define PCI_DEVICE_ID          0x02    /* 16 bits */
+#define PCI_COMMAND            0x04    /* 16 bits */
+#define  PCI_COMMAND_IO                0x1     /* Enable response in I/O space */
+#define  PCI_COMMAND_MEMORY    0x2     /* Enable response in Memory space */
+#define  PCI_COMMAND_MASTER    0x4     /* Enable bus mastering */
+#define  PCI_COMMAND_SPECIAL   0x8     /* Enable response to special cycles */
+#define  PCI_COMMAND_INVALIDATE 0x10   /* Use memory write and invalidate */
+#define  PCI_COMMAND_VGA_PALETTE 0x20  /* Enable palette snooping */
+#define  PCI_COMMAND_PARITY    0x40    /* Enable parity checking */
+#define  PCI_COMMAND_WAIT      0x80    /* Enable address/data stepping */
+#define  PCI_COMMAND_SERR      0x100   /* Enable SERR */
+#define  PCI_COMMAND_FAST_BACK 0x200   /* Enable back-to-back writes */
+
+#define PCI_STATUS             0x06    /* 16 bits */
+#define  PCI_STATUS_CAP_LIST   0x10    /* Support Capability List */
+#define  PCI_STATUS_66MHZ      0x20    /* Support 66 Mhz PCI 2.1 bus */
+#define  PCI_STATUS_UDF                0x40    /* Support User Definable Features [obsolete] */
+#define  PCI_STATUS_FAST_BACK  0x80    /* Accept fast-back to back */
+#define  PCI_STATUS_PARITY     0x100   /* Detected parity error */
+#define  PCI_STATUS_DEVSEL_MASK 0x600  /* DEVSEL timing */
+#define  PCI_STATUS_DEVSEL_FAST 0x000
+#define  PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define  PCI_STATUS_DEVSEL_SLOW 0x400
+#define  PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define  PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define  PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define  PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define  PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION     0x08    /* High 24 bits are class, low 8
+                                          revision */
+#define PCI_REVISION_ID                0x08    /* Revision ID */
+#define PCI_CLASS_PROG         0x09    /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE       0x0a    /* Device class */
+#define PCI_CLASS_CODE         0x0b    /* Device class code */
+#define PCI_CLASS_SUB_CODE     0x0a    /* Device sub-class code */
+
+#define PCI_CACHE_LINE_SIZE    0x0c    /* 8 bits */
+#define PCI_LATENCY_TIMER      0x0d    /* 8 bits */
+#define PCI_HEADER_TYPE                0x0e    /* 8 bits */
+#define  PCI_HEADER_TYPE_NORMAL 0
+#define  PCI_HEADER_TYPE_BRIDGE 1
+#define  PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_BIST               0x0f    /* 8 bits */
+#define PCI_BIST_CODE_MASK     0x0f    /* Return result */
+#define PCI_BIST_START         0x40    /* 1 to start BIST, 2 secs or less */
+#define PCI_BIST_CAPABLE       0x80    /* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of
+ * 0xffffffff to the register, and reading it back.  Only
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0     0x10    /* 32 bits */
+#define PCI_BASE_ADDRESS_1     0x14    /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2     0x18    /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3     0x1c    /* 32 bits */
+#define PCI_BASE_ADDRESS_4     0x20    /* 32 bits */
+#define PCI_BASE_ADDRESS_5     0x24    /* 32 bits */
+#define  PCI_BASE_ADDRESS_SPACE 0x01   /* 0 = memory, 1 = I/O */
+#define  PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define  PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define  PCI_BASE_ADDRESS_MEM_TYPE_32  0x00    /* 32 bit address */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_1M  0x02    /* Below 1M [obsolete] */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_64  0x04    /* 64 bit address */
+#define  PCI_BASE_ADDRESS_MEM_PREFETCH 0x08    /* prefetchable? */
+#define  PCI_BASE_ADDRESS_MEM_MASK     (~0x0fUL)
+#define  PCI_BASE_ADDRESS_IO_MASK      (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS                0x28
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define PCI_SUBSYSTEM_ID       0x2e
+#define PCI_ROM_ADDRESS                0x30    /* Bits 31..11 are address, 10..1 reserved */
+#define  PCI_ROM_ADDRESS_ENABLE 0x01
+#define PCI_ROM_ADDRESS_MASK   (~0x7ffUL)
+
+#define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE     0x3c    /* 8 bits */
+#define PCI_INTERRUPT_PIN      0x3d    /* 8 bits */
+#define PCI_MIN_GNT            0x3e    /* 8 bits */
+#define PCI_MAX_LAT            0x3f    /* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS                0x18    /* Primary bus number */
+#define PCI_SECONDARY_BUS      0x19    /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS    0x1a    /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER  0x1b    /* Latency timer for secondary interface */
+#define PCI_IO_BASE            0x1c    /* I/O range behind the bridge */
+#define PCI_IO_LIMIT           0x1d
+#define  PCI_IO_RANGE_TYPE_MASK 0x0f   /* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16  0x00
+#define  PCI_IO_RANGE_TYPE_32  0x01
+#define  PCI_IO_RANGE_MASK     ~0x0f
+#define PCI_SEC_STATUS         0x1e    /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE                0x20    /* Memory range behind */
+#define PCI_MEMORY_LIMIT       0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define  PCI_MEMORY_RANGE_MASK ~0x0f
+#define PCI_PREF_MEMORY_BASE   0x24    /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT  0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define  PCI_PREF_RANGE_TYPE_32 0x00
+#define  PCI_PREF_RANGE_TYPE_64 0x01
+#define  PCI_PREF_RANGE_MASK   ~0x0f
+#define PCI_PREF_BASE_UPPER32  0x28    /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16    0x30    /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16   0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1       0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL     0x3e
+#define  PCI_BRIDGE_CTL_PARITY 0x01    /* Enable parity detection on secondary interface */
+#define  PCI_BRIDGE_CTL_SERR   0x02    /* The same for SERR forwarding */
+#define  PCI_BRIDGE_CTL_NO_ISA 0x04    /* Disable bridging of ISA ports */
+#define  PCI_BRIDGE_CTL_VGA    0x08    /* Forward VGA addresses */
+#define  PCI_BRIDGE_CTL_MASTER_ABORT 0x20  /* Report master aborts */
+#define  PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define  PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+#define PCI_CB_CAPABILITY_LIST 0x14
+/* 0x15 reserved */
+#define PCI_CB_SEC_STATUS      0x16    /* Secondary status */
+#define PCI_CB_PRIMARY_BUS     0x18    /* PCI bus number */
+#define PCI_CB_CARD_BUS                0x19    /* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS 0x1a    /* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER   0x1b    /* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0   0x1c
+#define PCI_CB_MEMORY_LIMIT_0  0x20
+#define PCI_CB_MEMORY_BASE_1   0x24
+#define PCI_CB_MEMORY_LIMIT_1  0x28
+#define PCI_CB_IO_BASE_0       0x2c
+#define PCI_CB_IO_BASE_0_HI    0x2e
+#define PCI_CB_IO_LIMIT_0      0x30
+#define PCI_CB_IO_LIMIT_0_HI   0x32
+#define PCI_CB_IO_BASE_1       0x34
+#define PCI_CB_IO_BASE_1_HI    0x36
+#define PCI_CB_IO_LIMIT_1      0x38
+#define PCI_CB_IO_LIMIT_1_HI   0x3a
+#define  PCI_CB_IO_RANGE_MASK  ~0x03
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL  0x3e
+#define  PCI_CB_BRIDGE_CTL_PARITY      0x01    /* Similar to standard bridge control register */
+#define  PCI_CB_BRIDGE_CTL_SERR                0x02
+#define  PCI_CB_BRIDGE_CTL_ISA         0x04
+#define  PCI_CB_BRIDGE_CTL_VGA         0x08
+#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
+#define  PCI_CB_BRIDGE_CTL_CB_RESET    0x40    /* CardBus reset */
+#define  PCI_CB_BRIDGE_CTL_16BIT_INT   0x80    /* Enable interrupt for 16-bit cards */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define  PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define PCI_CB_SUBSYSTEM_ID    0x42
+#define PCI_CB_LEGACY_MODE_BASE 0x44   /* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID                0       /* Capability ID */
+#define  PCI_CAP_ID_PM         0x01    /* Power Management */
+#define  PCI_CAP_ID_AGP                0x02    /* Accelerated Graphics Port */
+#define  PCI_CAP_ID_VPD                0x03    /* Vital Product Data */
+#define  PCI_CAP_ID_SLOTID     0x04    /* Slot Identification */
+#define  PCI_CAP_ID_MSI                0x05    /* Message Signalled Interrupts */
+#define  PCI_CAP_ID_CHSWP      0x06    /* CompactPCI HotSwap */
+#define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
+#define PCI_CAP_FLAGS          2       /* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF         4
+
+/* Power Management Registers */
+
+#define  PCI_PM_CAP_VER_MASK   0x0007  /* Version */
+#define  PCI_PM_CAP_PME_CLOCK  0x0008  /* PME clock required */
+#define  PCI_PM_CAP_AUX_POWER  0x0010  /* Auxilliary power support */
+#define  PCI_PM_CAP_DSI                0x0020  /* Device specific initialization */
+#define  PCI_PM_CAP_D1         0x0200  /* D1 power state support */
+#define  PCI_PM_CAP_D2         0x0400  /* D2 power state support */
+#define  PCI_PM_CAP_PME                0x0800  /* PME pin supported */
+#define PCI_PM_CTRL            4       /* PM control and status register */
+#define  PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
+#define  PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
+#define  PCI_PM_CTRL_DATA_SEL_MASK     0x1e00  /* Data select (??) */
+#define  PCI_PM_CTRL_DATA_SCALE_MASK   0x6000  /* Data scale (??) */
+#define  PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS  6       /* PPB support extensions (??) */
+#define  PCI_PM_PPB_B2_B3      0x40    /* Stop clock when in D3hot (??) */
+#define  PCI_PM_BPCC_ENABLE    0x80    /* Bus power/clock control enable (??) */
+#define PCI_PM_DATA_REGISTER   7       /* (??) */
+#define PCI_PM_SIZEOF          8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION                2       /* BCD version number */
+#define PCI_AGP_RFU            3       /* Rest of capability flags */
+#define PCI_AGP_STATUS         4       /* Status register */
+#define  PCI_AGP_STATUS_RQ_MASK 0xff000000     /* Maximum number of requests - 1 */
+#define  PCI_AGP_STATUS_SBA    0x0200  /* Sideband addressing supported */
+#define  PCI_AGP_STATUS_64BIT  0x0020  /* 64-bit addressing supported */
+#define  PCI_AGP_STATUS_FW     0x0010  /* FW transfers supported */
+#define  PCI_AGP_STATUS_RATE4  0x0004  /* 4x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE2  0x0002  /* 2x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE1  0x0001  /* 1x transfer rate supported */
+#define PCI_AGP_COMMAND                8       /* Control register */
+#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of requests */
+#define  PCI_AGP_COMMAND_SBA   0x0200  /* Sideband addressing enabled */
+#define  PCI_AGP_COMMAND_AGP   0x0100  /* Allow processing of AGP transactions */
+#define  PCI_AGP_COMMAND_64BIT 0x0020  /* Allow processing of 64-bit addresses */
+#define  PCI_AGP_COMMAND_FW    0x0010  /* Force FW transfers */
+#define  PCI_AGP_COMMAND_RATE4 0x0004  /* Use 4x rate */
+#define  PCI_AGP_COMMAND_RATE2 0x0002  /* Use 4x rate */
+#define  PCI_AGP_COMMAND_RATE1 0x0001  /* Use 4x rate */
+#define PCI_AGP_SIZEOF         12
+
+/* Slot Identification */
+
+#define PCI_SID_ESR            2       /* Expansion Slot Register */
+#define  PCI_SID_ESR_NSLOTS    0x1f    /* Number of expansion slots available */
+#define  PCI_SID_ESR_FIC       0x20    /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR     3       /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS          2       /* Various flags */
+#define  PCI_MSI_FLAGS_64BIT   0x80    /* 64-bit addresses allowed */
+#define  PCI_MSI_FLAGS_QSIZE   0x70    /* Message queue size configured */
+#define  PCI_MSI_FLAGS_QMASK   0x0e    /* Maximum queue size available */
+#define  PCI_MSI_FLAGS_ENABLE  0x01    /* MSI feature enabled */
+#define PCI_MSI_RFU            3       /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO     4       /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI     8       /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32                8       /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64                12      /* 16 bits of data for 64-bit devices */
+
+#define PCI_MAX_PCI_DEVICES    32
+#define PCI_MAX_PCI_FUNCTIONS  8
+
+/* Include the ID list */
+
+#include <pci_ids.h>
+
+struct pci_region {
+       unsigned long bus_start;                /* Start on the bus */
+       unsigned long phys_start;               /* Start in physical address space */
+       unsigned long size;                     /* Size */
+       unsigned long flags;                    /* Resource flags */
+
+       unsigned long bus_lower;
+};
+
+#define PCI_REGION_MEM         0x00000000      /* PCI memory space */
+#define PCI_REGION_IO          0x00000001      /* PCI IO space */
+#define PCI_REGION_TYPE                0x00000001
+
+#define PCI_REGION_MEMORY      0x00000100      /* System memory */
+#define PCI_REGION_RO          0x00000200      /* Read-only memory */
+
+extern __inline__ void pci_set_region(struct pci_region *reg,
+                                     unsigned long bus_start,
+                                     unsigned long phys_start,
+                                     unsigned long size,
+                                     unsigned long flags) {
+       reg->bus_start  = bus_start;
+       reg->phys_start = phys_start;
+       reg->size       = size;
+       reg->flags      = flags;
+}
+
+typedef int pci_dev_t;
+
+#define PCI_BUS(d)     (((d) >> 16) & 0xff)
+#define PCI_DEV(d)     (((d) >> 11) & 0x1f)
+#define PCI_FUNC(d)    (((d) >> 8) & 0x7)
+#define PCI_BDF(b,d,f) ((b) << 16 | (d) << 11 | (f) << 8)
+
+#define PCI_ANY_ID (~0)
+
+struct pci_device_id {
+       unsigned int vendor, device;            /* Vendor and device ID or PCI_ANY_ID */
+};
+
+struct pci_controller;
+
+struct pci_config_table {
+       unsigned int vendor, device;            /* Vendor and device ID or PCI_ANY_ID */
+       unsigned int class;                     /* Class ID, or  PCI_ANY_ID */
+       unsigned int bus;                       /* Bus number, or PCI_ANY_ID */
+       unsigned int dev;                       /* Device number, or PCI_ANY_ID */
+       unsigned int func;                      /* Function number, or PCI_ANY_ID */
+
+       void (*config_device)(struct pci_controller* hose, pci_dev_t dev,
+                             struct pci_config_table *);
+       unsigned long priv[3];
+};
+
+extern void pci_cfgfunc_nothing(struct pci_controller* hose, pci_dev_t dev,
+                               struct pci_config_table *);
+extern void pci_cfgfunc_config_device(struct pci_controller* hose, pci_dev_t dev,
+                                     struct pci_config_table *);
+
+#define MAX_PCI_REGIONS                7
+
+/*
+ * Structure of a PCI controller (host bridge)
+ */
+struct pci_controller {
+       struct pci_controller *next;
+
+       int first_busno;
+       int last_busno;
+
+       volatile unsigned int *cfg_addr;
+       volatile unsigned char *cfg_data;
+
+       struct pci_region regions[MAX_PCI_REGIONS];
+       int region_count;
+
+       struct pci_config_table *config_table;
+
+       void (*fixup_irq)(struct pci_controller *, pci_dev_t);
+
+       /* Low-level architecture-dependent routines */
+       int (*read_byte)(struct pci_controller*, pci_dev_t, int where, u8 *);
+       int (*read_word)(struct pci_controller*, pci_dev_t, int where, u16 *);
+       int (*read_dword)(struct pci_controller*, pci_dev_t, int where, u32 *);
+       int (*write_byte)(struct pci_controller*, pci_dev_t, int where, u8);
+       int (*write_word)(struct pci_controller*, pci_dev_t, int where, u16);
+       int (*write_dword)(struct pci_controller*, pci_dev_t, int where, u32);
+
+       /* Used by auto config */
+       struct pci_region *pci_mem, *pci_io;
+
+       /* Used by ppc405 autoconfig*/
+       struct pci_region *pci_fb;
+};
+
+extern __inline__ void pci_set_ops(struct pci_controller *hose,
+                                  int (*read_byte)(struct pci_controller*,
+                                                   pci_dev_t, int where, u8 *),
+                                  int (*read_word)(struct pci_controller*,
+                                                   pci_dev_t, int where, u16 *),
+                                  int (*read_dword)(struct pci_controller*,
+                                                    pci_dev_t, int where, u32 *),
+                                  int (*write_byte)(struct pci_controller*,
+                                                    pci_dev_t, int where, u8),
+                                  int (*write_word)(struct pci_controller*,
+                                                    pci_dev_t, int where, u16),
+                                  int (*write_dword)(struct pci_controller*,
+                                                     pci_dev_t, int where, u32)) {
+       hose->read_byte   = read_byte;
+       hose->read_word   = read_word;
+       hose->read_dword  = read_dword;
+       hose->write_byte  = write_byte;
+       hose->write_word  = write_word;
+       hose->write_dword = write_dword;
+}
+
+extern void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data);
+
+extern unsigned long pci_hose_bus_to_phys(struct pci_controller* hose,
+                                         unsigned long addr, unsigned long flags);
+extern unsigned long pci_hose_phys_to_bus(struct pci_controller* hose,
+                                         unsigned long addr, unsigned long flags);
+
+#define pci_phys_to_bus(dev, addr, flags) \
+       pci_hose_phys_to_bus(pci_bus_to_hose(PCI_BUS(dev)), (addr), (flags))
+#define pci_bus_to_phys(dev, addr, flags) \
+       pci_hose_bus_to_phys(pci_bus_to_hose(PCI_BUS(dev)), (addr), (flags))
+
+#define pci_phys_to_mem(dev, addr)     pci_phys_to_bus((dev), (addr), PCI_REGION_MEM)
+#define pci_mem_to_phys(dev, addr)     pci_bus_to_phys((dev), (addr), PCI_REGION_MEM)
+#define pci_phys_to_io(dev, addr)      pci_phys_to_bus((dev), (addr), PCI_REGION_IO)
+#define pci_io_to_phys(dev, addr)      pci_bus_to_phys((dev), (addr), PCI_REGION_IO)
+
+extern int pci_hose_read_config_byte(struct pci_controller *hose,
+                                    pci_dev_t dev, int where, u8 *val);
+extern int pci_hose_read_config_word(struct pci_controller *hose,
+                                    pci_dev_t dev, int where, u16 *val);
+extern int pci_hose_read_config_dword(struct pci_controller *hose,
+                                     pci_dev_t dev, int where, u32 *val);
+extern int pci_hose_write_config_byte(struct pci_controller *hose,
+                                     pci_dev_t dev, int where, u8 val);
+extern int pci_hose_write_config_word(struct pci_controller *hose,
+                                     pci_dev_t dev, int where, u16 val);
+extern int pci_hose_write_config_dword(struct pci_controller *hose,
+                                      pci_dev_t dev, int where, u32 val);
+
+extern int pci_read_config_byte(pci_dev_t dev, int where, u8 *val);
+extern int pci_read_config_word(pci_dev_t dev, int where, u16 *val);
+extern int pci_read_config_dword(pci_dev_t dev, int where, u32 *val);
+extern int pci_write_config_byte(pci_dev_t dev, int where, u8 val);
+extern int pci_write_config_word(pci_dev_t dev, int where, u16 val);
+extern int pci_write_config_dword(pci_dev_t dev, int where, u32 val);
+
+extern int pci_hose_read_config_byte_via_dword(struct pci_controller *hose,
+                                              pci_dev_t dev, int where, u8 *val);
+extern int pci_hose_read_config_word_via_dword(struct pci_controller *hose,
+                                              pci_dev_t dev, int where, u16 *val);
+extern int pci_hose_write_config_byte_via_dword(struct pci_controller *hose,
+                                               pci_dev_t dev, int where, u8 val);
+extern int pci_hose_write_config_word_via_dword(struct pci_controller *hose,
+                                               pci_dev_t dev, int where, u16 val);
+
+extern void pci_register_hose(struct pci_controller* hose);
+extern struct pci_controller* pci_bus_to_hose(int bus);
+
+extern int pci_hose_scan(struct pci_controller *hose);
+extern int pci_hose_scan_bus(struct pci_controller *hose, int bus);
+
+extern void pciauto_region_init(struct pci_region* res);
+extern void pciauto_region_align(struct pci_region *res, unsigned long size);
+extern int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar);
+extern void pciauto_setup_device(struct pci_controller *hose,
+                                pci_dev_t dev, int bars_num,
+                                struct pci_region *mem,
+                                struct pci_region *io);
+void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
+
+extern pci_dev_t pci_find_device (unsigned int vendor, unsigned int device, int index);
+extern pci_dev_t pci_find_devices (struct pci_device_id *ids, int index);
+
+extern int pci_hose_config_device(struct pci_controller *hose,
+                                 pci_dev_t dev,
+                                 unsigned long io,
+                                 unsigned long mem,
+                                 unsigned long command);
+
+#ifdef CONFIG_MPC824X
+extern void pci_mpc824x_init (struct pci_controller *hose);
+#endif
+
+#endif /* _PCI_H */
diff --git a/include/smiLynxEM.h b/include/smiLynxEM.h
new file mode 100644 (file)
index 0000000..cdd2f24
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * (C) Copyright 1997-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
+ */
+
+/*
+ * smiLynxEM.h
+ * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
+ *
+ *
+ *  modification history
+ *  --------------------
+ *  04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
+ */
+
+#ifndef _SMI_LYNX_EM_H_
+#define _SMI_LYNX_EM_H_
+
+/*
+ * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
+ */
+#define VIDEO_MEM_SIZE  0x400000
+
+/*
+ * Supported video modes for SMI Lynx E/EM/EM+
+ */
+#define VIDEO_MODES             7
+#define DUAL_800_600            0   /* SMI710:VGA1:75Hz     (pitch=1600) */
+                                    /*        VGA2:60/120Hz (pitch=1600) */
+                                    /* SMI810:VGA1:75Hz     (pitch=1600) */
+                                    /*        VGA2:75Hz     (pitch=1600) */
+#define DUAL_1024_768           1   /* VGA1:75Hz VGA2:73Hz (pitch=2048)  */
+#define SINGLE_800_600          2   /* VGA1:75Hz (pitch=800)             */
+#define SINGLE_1024_768         3   /* VGA1:75Hz (pitch=1024)            */
+#define SINGLE_1280_1024        4   /* VGA1:75Hz (pitch=1280)            */
+#define TV_MODE_CCIR            5   /* VGA1:50Hz (h=720;v=576;pitch=720) */
+#define TV_MODE_EIA             6   /* VGA1:60Hz (h=720;v=484;pitch=720) */
+
+
+/*
+ * ISA mapped regs
+ */
+#define SMI_INDX_C4             (pGD->isaBase + 0x03c4)    /* index reg */
+#define SMI_DATA_C5             (pGD->isaBase + 0x03c5)    /* data reg */
+#define SMI_INDX_D4             (pGD->isaBase + 0x03d4)    /* index reg */
+#define SMI_DATA_D5             (pGD->isaBase + 0x03d5)    /* data reg */
+#define SMI_INDX_CE             (pGD->isaBase + 0x03ce)    /* index reg */
+#define SMI_DATA_CF             (pGD->isaBase + 0x03cf)    /* data reg */
+#define SMI_LOCK_REG            (pGD->isaBase + 0x03c3)    /* unlock/lock ext crt reg */
+#define SMI_MISC_REG            (pGD->isaBase + 0x03c2)    /* misc reg */
+#define SMI_LUT_MASK            (pGD->isaBase + 0x03c6)    /* lut mask reg */
+#define SMI_LUT_START           (pGD->isaBase + 0x03c8)    /* lut start index */
+#define SMI_LUT_RGB             (pGD->isaBase + 0x03c9)    /* lut colors auto incr.*/
+
+
+/*
+ * Video processor control
+ */
+typedef struct {
+    unsigned int   control;
+    unsigned int   colorKey;
+    unsigned int   colorKeyMask;
+    unsigned int   start;
+    unsigned short offset;
+    unsigned short width;
+    unsigned int   fifoPrio;
+    unsigned int   fifoERL;
+    unsigned int   YUVtoRGB;
+} SmiVideoProc;
+
+/*
+ * Video window control
+ */
+typedef struct {
+    unsigned short top;
+    unsigned short left;
+    unsigned short bottom;
+    unsigned short right;
+    unsigned int   srcStart;
+    unsigned short width;
+    unsigned short offset;
+    unsigned char  hStretch;
+    unsigned char  vStretch;
+} SmiVideoWin;
+
+/*
+ * Capture port control
+ */
+typedef struct {
+    unsigned int   control;
+    unsigned short topClip;
+    unsigned short leftClip;
+    unsigned short srcHeight;
+    unsigned short srcWidth;
+    unsigned int   srcBufStart1;
+    unsigned int   srcBufStart2;
+    unsigned short srcOffset;
+    unsigned short fifoControl;
+} SmiCapturePort;
+
+
+/******************************************************************************/
+/* Export Graphic Driver Control                                              */
+/******************************************************************************/
+
+typedef struct {
+    unsigned int isaBase;
+    unsigned int pciBase;
+    unsigned int dprBase;
+    unsigned int vprBase;
+    unsigned int cprBase;
+    unsigned int frameAdrs;
+    unsigned int memSize;
+    unsigned int mode;
+    unsigned int gdfIndex;
+    unsigned int gdfBytesPP;
+    unsigned int fg;
+    unsigned int bg;
+    unsigned int plnSizeX;
+    unsigned int plnSizeY;
+    unsigned int winSizeX;
+    unsigned int winSizeY;
+    char modeIdent[80];
+} GraphicDevice;
+
+extern GraphicDevice smi;
+
+
+/******************************************************************************/
+/* Export Graphic Functions                                                   */
+/******************************************************************************/
+
+void *video_hw_init (void);       /* returns GraphicDevice struct or NULL */
+
+void video_hw_bitblt (
+    unsigned int bpp,             /* bytes per pixel */
+    unsigned int src_x,           /* source pos x */
+    unsigned int src_y,           /* source pos y */
+    unsigned int dst_x,           /* dest pos x */
+    unsigned int dst_y,           /* dest pos y */
+    unsigned int dim_x,           /* frame width */
+    unsigned int dim_y            /* frame height */
+    );
+
+void video_hw_rectfill (
+    unsigned int bpp,             /* bytes per pixel */
+    unsigned int dst_x,           /* dest pos x */
+    unsigned int dst_y,           /* dest pos y */
+    unsigned int dim_x,           /* frame width */
+    unsigned int dim_y,           /* frame height */
+    unsigned int color            /* fill color */
+     );
+
+void video_set_lut (
+    unsigned int index,           /* color number */
+    unsigned char r,              /* red */
+    unsigned char g,              /* green */
+    unsigned char b               /* blue */
+    );
+
+#endif /*_SMI_LYNX_EM_H_ */
diff --git a/include/spartan2.h b/include/spartan2.h
new file mode 100644 (file)
index 0000000..42806e3
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.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 _SPARTAN2_H_
+#define _SPARTAN2_H_
+
+#include <xilinx.h>
+
+extern int Spartan2_load( Xilinx_desc *desc, void *image, size_t size );
+extern int Spartan2_dump( Xilinx_desc *desc, void *buf, size_t bsize );
+extern int Spartan2_info( Xilinx_desc *desc );
+extern int Spartan2_reloc( Xilinx_desc *desc, ulong reloc_off );
+
+/* Slave Parallel Implementation function table */
+typedef struct {
+       Xilinx_pre_fn   pre;
+       Xilinx_pgm_fn   pgm;
+       Xilinx_init_fn  init;
+       Xilinx_err_fn   err;
+       Xilinx_done_fn  done;
+       Xilinx_clk_fn   clk;
+       Xilinx_cs_fn    cs;
+       Xilinx_wr_fn    wr;
+       Xilinx_rdata_fn rdata;
+       Xilinx_wdata_fn wdata;
+       Xilinx_busy_fn  busy;
+       Xilinx_abort_fn abort;
+       Xilinx_post_fn  post;
+       int             relocated;
+} Xilinx_Spartan2_Slave_Parallel_fns;
+
+/* Slave Serial Implementation function table */
+typedef struct {
+       Xilinx_pgm_fn   pgm;
+       Xilinx_clk_fn   clk;
+       Xilinx_rdata_fn rdata;
+       Xilinx_wdata_fn wdata;
+       int             relocated;
+} Xilinx_Spartan2_Slave_Serial_fns;
+
+/* Device Image Sizes
+ *********************************************************************/
+/* Spartan-II (2.5V) */
+#define XILINX_XC2S15_SIZE     197728/8
+#define XILINX_XC2S30_SIZE     336800/8
+#define XILINX_XC2S50_SIZE     559232/8
+#define XILINX_XC2S100_SIZE    781248/8
+#define XILINX_XC2S150_SIZE    1040128/8
+
+/* Descriptor Macros
+ *********************************************************************/
+/* Spartan-II devices */
+#define XILINX_XC2S15_DESC(iface, fn_table, cookie) \
+{ Xilinx_Spartan2, iface, XILINX_XC2S15_SIZE, fn_table, cookie }
+
+#define XILINX_XC2S30_DESC(iface, fn_table, cookie) \
+{ Xilinx_Spartan2, iface, XILINX_XC2S30_SIZE, fn_table, cookie }
+
+#define XILINX_XC2S50_DESC(iface, fn_table, cookie) \
+{ Xilinx_Spartan2, iface, XILINX_XC2S50_SIZE, fn_table, cookie }
+
+#define XILINX_XC2S100_DESC(iface, fn_table, cookie) \
+{ Xilinx_Spartan2, iface, XILINX_XC2S100_SIZE, fn_table, cookie }
+
+#define XILINX_XC2S150_DESC(iface, fn_table, cookie) \
+{ Xilinx_Spartan2, iface, XILINX_XC2S150_SIZE, fn_table, cookie }
+
+#endif /* _SPARTAN2_H_ */
+
diff --git a/include/status_led.h b/include/status_led.h
new file mode 100644 (file)
index 0000000..9b2de3e
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * (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
+ */
+
+/*
+ * The purpose of this code is to signal the operational status of a
+ * target which usually boots over the network; while running in
+ * PCBoot, a status LED is blinking. As soon as a valid BOOTP reply
+ * message has been received, the LED is turned off. The Linux
+ * kernel, once it is running, will start blinking the LED again,
+ * with another frequency.
+ */
+
+#ifndef _STATUS_LED_H_
+#define        _STATUS_LED_H_
+
+#ifdef CONFIG_STATUS_LED
+
+#define STATUS_LED_OFF         0
+#define STATUS_LED_BLINKING    1
+#define STATUS_LED_ON          2
+
+void status_led_tick (unsigned long timestamp);
+void status_led_set  (int led, int state);
+
+/*****  TQM8xxL  ********************************************************/
+#if defined(CONFIG_TQM8xxL)
+# define STATUS_LED_PAR                im_cpm.cp_pbpar
+# define STATUS_LED_DIR                im_cpm.cp_pbdir
+# define STATUS_LED_ODR                im_cpm.cp_pbodr
+# define STATUS_LED_DAT                im_cpm.cp_pbdat
+
+# define STATUS_LED_BIT                0x00000001
+# define STATUS_LED_PERIOD     (CFG_HZ / 2)
+# define STATUS_LED_STATE      STATUS_LED_BLINKING
+
+# define STATUS_LED_ACTIVE     1               /* LED on for bit == 1  */
+
+# define STATUS_LED_BOOT       0               /* LED 0 used for boot status */
+
+/*****  MVS v1  **********************************************************/
+#elif (defined(CONFIG_MVS) && CONFIG_MVS < 2)
+# define STATUS_LED_PAR                im_ioport.iop_pdpar
+# define STATUS_LED_DIR                im_ioport.iop_pddir
+# undef  STATUS_LED_ODR
+# define STATUS_LED_DAT                im_ioport.iop_pddat
+
+# define STATUS_LED_BIT                0x00000001
+# define STATUS_LED_PERIOD     (CFG_HZ / 2)
+# define STATUS_LED_STATE      STATUS_LED_BLINKING
+
+# define STATUS_LED_ACTIVE     1               /* LED on for bit == 1  */
+
+# define STATUS_LED_BOOT       0               /* LED 0 used for boot status */
+
+/*****  ETX_094  ********************************************************/
+#elif defined(CONFIG_ETX094)
+
+# define STATUS_LED_PAR                im_ioport.iop_pdpar
+# define STATUS_LED_DIR                im_ioport.iop_pddir
+# undef  STATUS_LED_ODR
+# define STATUS_LED_DAT                im_ioport.iop_pddat
+
+# define STATUS_LED_BIT                0x00000001
+# define STATUS_LED_PERIOD     (CFG_HZ / 2)
+# define STATUS_LED_STATE      STATUS_LED_BLINKING
+
+# define STATUS_LED_ACTIVE     0               /* LED on for bit == 0  */
+
+# define STATUS_LED_BOOT       0               /* LED 0 used for boot status */
+
+/*****  GEN860T  *********************************************************/
+#elif defined(CONFIG_GEN860T)
+
+# define STATUS_LED_PAR                        im_ioport.iop_papar
+# define STATUS_LED_DIR                        im_ioport.iop_padir
+# define STATUS_LED_ODR                        im_ioport.iop_paodr
+# define STATUS_LED_DAT                        im_ioport.iop_padat
+
+# define STATUS_LED_BIT                        0x0800  /* Red LED 0 is on PA.4 */
+# define STATUS_LED_PERIOD             (CFG_HZ / 2)
+# define STATUS_LED_STATE              STATUS_LED_BLINKING
+# define STATUS_LED_BIT1               0x0400  /* Grn LED 1 is on PA.5 */
+# define STATUS_LED_PERIOD1            (CFG_HZ / 2)
+# define STATUS_LED_STATE1             STATUS_LED_BLINKING
+# define STATUS_LED_BIT2               0x0080  /* Red LED 2 is on PA.8 */
+# define STATUS_LED_PERIOD2            (CFG_HZ / 2)
+# define STATUS_LED_STATE2             STATUS_LED_BLINKING
+# define STATUS_LED_BIT3               0x0040  /* Grn LED 3 is on PA.9 */
+# define STATUS_LED_PERIOD3            (CFG_HZ / 2)
+# define STATUS_LED_STATE3             STATUS_LED_BLINKING
+
+# define STATUS_LED_ACTIVE             1       /* LED on for bit == 1  */
+# define STATUS_LED_BOOT               0       /* Boot status on LED 1 */
+
+/*****  IVMS8  **********************************************************/
+#elif defined(CONFIG_IVMS8)
+
+# define STATUS_LED_PAR                im_cpm.cp_pbpar
+# define STATUS_LED_DIR                im_cpm.cp_pbdir
+# define STATUS_LED_ODR                im_cpm.cp_pbodr
+# define STATUS_LED_DAT                im_cpm.cp_pbdat
+
+# define STATUS_LED_BIT                0x00000010      /* LED 0 is on PB.27    */
+# define STATUS_LED_PERIOD     (1 * CFG_HZ)
+# define STATUS_LED_STATE      STATUS_LED_OFF
+# define STATUS_LED_BIT1       0x00000020      /* LED 1 is on PB.26    */
+# define STATUS_LED_PERIOD1    (1 * CFG_HZ)
+# define STATUS_LED_STATE1     STATUS_LED_OFF
+/* IDE LED usable for other purposes, too */
+# define STATUS_LED_BIT2       0x00000008      /* LED 2 is on PB.28    */
+# define STATUS_LED_PERIOD2    (1 * CFG_HZ)
+# define STATUS_LED_STATE2     STATUS_LED_OFF
+
+# define STATUS_LED_ACTIVE     1               /* LED on for bit == 1  */
+
+# define STATUS_ILOCK_SWITCH   0x00800000      /* ILOCK switch in IRQ4 */
+
+# define STATUS_ILOCK_PERIOD   (CFG_HZ / 10)   /* about every 100 ms   */
+
+# define STATUS_LED_YELLOW     0
+# define STATUS_LED_GREEN      1
+# define STATUS_LED_BOOT       2               /* IDE LED used for boot status */
+
+/*****  IVML24  *********************************************************/
+#elif defined(CONFIG_IVML24)
+
+# define STATUS_LED_PAR                im_cpm.cp_pbpar
+# define STATUS_LED_DIR                im_cpm.cp_pbdir
+# define STATUS_LED_ODR                im_cpm.cp_pbodr
+# define STATUS_LED_DAT                im_cpm.cp_pbdat
+
+# define STATUS_LED_BIT                0x00000010      /* LED 0 is on PB.27    */
+# define STATUS_LED_PERIOD     (1 * CFG_HZ)
+# define STATUS_LED_STATE      STATUS_LED_OFF
+# define STATUS_LED_BIT1       0x00000020      /* LED 1 is on PB.26    */
+# define STATUS_LED_PERIOD1    (1 * CFG_HZ)
+# define STATUS_LED_STATE1     STATUS_LED_OFF
+/* IDE LED usable for other purposes, too */
+# define STATUS_LED_BIT2       0x00000008      /* LED 2 is on PB.28    */
+# define STATUS_LED_PERIOD2    (1 * CFG_HZ)
+# define STATUS_LED_STATE2     STATUS_LED_OFF
+
+# define STATUS_LED_ACTIVE     1               /* LED on for bit == 1  */
+
+# define STATUS_ILOCK_SWITCH   0x00004000      /* ILOCK is on PB.17    */
+
+# define STATUS_ILOCK_PERIOD   (CFG_HZ / 10)   /* about every 100 ms   */
+
+# define STATUS_LED_YELLOW     0
+# define STATUS_LED_GREEN      1
+# define STATUS_LED_BOOT       2               /* IDE LED used for boot status */
+
+/*****  LANTEC  *********************************************************/
+#elif defined(CONFIG_LANTEC)
+
+# define STATUS_LED_PAR                im_ioport.iop_pdpar
+# define STATUS_LED_DIR                im_ioport.iop_pddir
+# undef  STATUS_LED_ODR
+# define STATUS_LED_DAT                im_ioport.iop_pddat
+
+# if CONFIG_LATEC < 2
+#  define STATUS_LED_BIT       0x1000
+# else
+#  define STATUS_LED_BIT       0x0800
+# endif
+# define STATUS_LED_PERIOD     (CFG_HZ / 2)
+# define STATUS_LED_STATE      STATUS_LED_BLINKING
+
+# define STATUS_LED_ACTIVE     0               /* LED on for bit == 0 */
+
+# define STATUS_LED_BOOT       0               /* LED 0 used for boot status */
+
+/*****  PCU E  and  CCM  ************************************************/
+#elif (defined(CONFIG_PCU_E) || defined(CONFIG_CCM))
+
+# define STATUS_LED_PAR                im_cpm.cp_pbpar
+# define STATUS_LED_DIR                im_cpm.cp_pbdir
+# define STATUS_LED_ODR                im_cpm.cp_pbodr
+# define STATUS_LED_DAT                im_cpm.cp_pbdat
+
+# define STATUS_LED_BIT                0x00010000      /* green LED is on PB.15 */
+# define STATUS_LED_PERIOD     (CFG_HZ / 2)
+# define STATUS_LED_STATE      STATUS_LED_BLINKING
+
+# define STATUS_LED_ACTIVE     1               /* LED on for bit == 1 */
+
+# define STATUS_LED_BOOT       0               /* LED 0 used for boot status */
+
+/*****  ICU862   ********************************************************/
+#elif defined(CONFIG_ICU862)
+
+# define STATUS_LED_PAR                im_ioport.iop_papar
+# define STATUS_LED_DIR                im_ioport.iop_padir
+# define STATUS_LED_ODR                im_ioport.iop_paodr
+# define STATUS_LED_DAT                im_ioport.iop_padat
+
+# define STATUS_LED_BIT                0x4000          /* LED 0 is on PA.1 */
+# define STATUS_LED_PERIOD     (CFG_HZ / 2)
+# define STATUS_LED_STATE      STATUS_LED_BLINKING
+# define STATUS_LED_BIT1       0x1000          /* LED 1 is on PA.3 */
+# define STATUS_LED_PERIOD1    (CFG_HZ)
+# define STATUS_LED_STATE1     STATUS_LED_OFF
+
+# define STATUS_LED_ACTIVE     1               /* LED on for bit == 1  */
+
+# define STATUS_LED_BOOT       0               /* LED 0 used for boot status */
+
+/*****  Someone else defines these  *************************************/
+#elif defined(STATUS_LED_PAR)
+
+  /*
+   * ADVICE: Define in your board configuration file rather than
+   * filling this file up with lots of custom board stuff.
+   */
+
+/*****  NetVia   ********************************************************/
+#elif defined(CONFIG_NETVIA)
+
+#define STATUS_LED_PAR         im_ioport.iop_pdpar
+#define STATUS_LED_DIR         im_ioport.iop_pddir
+#undef  STATUS_LED_ODR
+#define STATUS_LED_DAT         im_ioport.iop_pddat
+
+# define STATUS_LED_BIT                0x0080                  /* PD.8 */
+# define STATUS_LED_PERIOD     (CFG_HZ / 2)
+# define STATUS_LED_STATE      STATUS_LED_BLINKING
+
+# define STATUS_LED_BIT1       0x0040                  /* PD.9 */
+# define STATUS_LED_PERIOD1    (CFG_HZ / 2)
+# define STATUS_LED_STATE1     STATUS_LED_OFF
+
+# define STATUS_LED_ACTIVE     0               /* LED on for bit == 0  */
+# define STATUS_LED_BOOT       0               /* LED 0 used for boot status */
+
+/************************************************************************/
+#else
+# error Status LED configuration missing
+#endif
+/************************************************************************/
+
+#endif /* CONFIG_STATUS_LED    */
+
+#endif /* _STATUS_LED_H_       */
diff --git a/include/video_fb.h b/include/video_fb.h
new file mode 100644 (file)
index 0000000..a9e4275
--- /dev/null
@@ -0,0 +1,115 @@
+                                                                                    /*
+ * (C) Copyright 1997-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
+ */
+
+/*
+ * smiLynxEM.h
+ * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
+ *
+ *
+ *  modification history
+ *  --------------------
+ *  04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
+ */
+
+#ifndef _VIDEO_FB_H_
+#define _VIDEO_FB_H_
+
+#define CONSOLE_BG_COL            0x00
+#define CONSOLE_FG_COL            0xa0
+
+/*
+ * Graphic Data Format (GDF) bits for VIDEO_DATA_FORMAT
+ */
+#define GDF__8BIT_INDEX         0
+#define GDF_15BIT_555RGB        1
+#define GDF_16BIT_565RGB        2
+#define GDF_32BIT_X888RGB       3
+#define GDF_24BIT_888RGB        4
+#define GDF__8BIT_332RGB        5
+
+/******************************************************************************/
+/* Export Graphic Driver Control                                              */
+/******************************************************************************/
+
+typedef struct {
+    unsigned int isaBase;
+    unsigned int pciBase;
+    unsigned int dprBase;
+    unsigned int vprBase;
+    unsigned int cprBase;
+    unsigned int frameAdrs;
+    unsigned int memSize;
+    unsigned int mode;
+    unsigned int gdfIndex;
+    unsigned int gdfBytesPP;
+    unsigned int fg;
+    unsigned int bg;
+    unsigned int plnSizeX;
+    unsigned int plnSizeY;
+    unsigned int winSizeX;
+    unsigned int winSizeY;
+    char modeIdent[80];
+} GraphicDevice;
+
+
+/******************************************************************************/
+/* Export Graphic Functions                                                   */
+/******************************************************************************/
+
+void *video_hw_init (void);       /* returns GraphicDevice struct or NULL */
+
+#ifdef VIDEO_HW_BITBLT
+void video_hw_bitblt (
+    unsigned int bpp,             /* bytes per pixel */
+    unsigned int src_x,           /* source pos x */
+    unsigned int src_y,           /* source pos y */
+    unsigned int dst_x,           /* dest pos x */
+    unsigned int dst_y,           /* dest pos y */
+    unsigned int dim_x,           /* frame width */
+    unsigned int dim_y            /* frame height */
+    );
+#endif
+
+#ifdef VIDEO_HW_RECTFILL
+void video_hw_rectfill (
+    unsigned int bpp,             /* bytes per pixel */
+    unsigned int dst_x,           /* dest pos x */
+    unsigned int dst_y,           /* dest pos y */
+    unsigned int dim_x,           /* frame width */
+    unsigned int dim_y,           /* frame height */
+    unsigned int color            /* fill color */
+     );
+#endif
+
+void video_set_lut (
+    unsigned int index,           /* color number */
+    unsigned char r,              /* red */
+    unsigned char g,              /* green */
+    unsigned char b               /* blue */
+    );
+#ifdef CONFIG_VIDEO_HW_CURSOR
+void video_set_hw_cursor(int x, int y); /* x y in pixel */
+void video_init_hw_cursor(int font_width, int font_height);
+#endif
+
+#endif /*_VIDEO_FB_H_ */
diff --git a/include/virtex2.h b/include/virtex2.h
new file mode 100644 (file)
index 0000000..f59227b
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * (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
+ *
+ */
+
+#ifndef _VIRTEX2_H_
+#define _VIRTEX2_H_
+
+#include <xilinx.h>
+
+extern int Virtex2_load( Xilinx_desc *desc, void *image, size_t size );
+extern int Virtex2_dump( Xilinx_desc *desc, void *buf, size_t bsize );
+extern int Virtex2_info( Xilinx_desc *desc );
+extern int Virtex2_reloc( Xilinx_desc *desc, ulong reloc_off );
+
+/*
+ * Slave SelectMap Implementation function table.
+ */
+typedef struct {
+       Xilinx_pre_fn   pre;
+       Xilinx_pgm_fn   pgm;
+       Xilinx_init_fn  init;
+       Xilinx_err_fn   err;
+       Xilinx_done_fn  done;
+       Xilinx_clk_fn   clk;
+       Xilinx_cs_fn    cs;
+       Xilinx_wr_fn    wr;
+       Xilinx_rdata_fn rdata;
+       Xilinx_wdata_fn wdata;
+       Xilinx_busy_fn  busy;
+       Xilinx_abort_fn abort;
+       Xilinx_post_fn  post;
+       int             relocated;
+} Xilinx_Virtex2_Slave_SelectMap_fns;
+
+/* Slave Serial Implementation function table */
+typedef struct {
+       Xilinx_pgm_fn   pgm;
+       Xilinx_clk_fn   clk;
+       Xilinx_rdata_fn rdata;
+       Xilinx_wdata_fn wdata;
+       int             relocated;
+} Xilinx_Virtex2_Slave_Serial_fns;
+
+/* Device Image Sizes (in bytes)
+ *********************************************************************/
+#define XILINX_XC2V40_SIZE             (338208 / 8)
+#define XILINX_XC2V80_SIZE             (597408 / 8)
+#define XILINX_XC2V250_SIZE            (1591584 / 8)
+#define XILINX_XC2V500_SIZE            (2557857 / 8)
+#define XILINX_XC2V1000_SIZE   (3749408 / 8)
+#define XILINX_XC2V1500_SIZE   (5166240 / 8)
+#define XILINX_XC2V2000_SIZE   (6808352 / 8)
+#define XILINX_XC2V3000_SIZE   (9589408 / 8)
+#define XILINX_XC2V4000_SIZE   (14220192 / 8)
+#define XILINX_XC2V6000_SIZE   (19752096 / 8)
+#define XILINX_XC2V8000_SIZE   (26185120 / 8)
+#define XILINX_XC2V10000_SIZE  (33519264 / 8)
+
+/* Descriptor Macros
+ *********************************************************************/
+#define XILINX_XC2V40_DESC(iface, fn_table, cookie)    \
+{ Xilinx_Virtex2, iface, XILINX_XC2V40_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V80_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V80_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V250_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V250_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V500_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V500_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V1000_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V1000_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V1500_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V1500_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V2000_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V2000_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V3000_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V3000_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V4000_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V4000_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V6000_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V6000_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V8000_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V8000_SIZE, fn_table, cookie }
+
+#define XILINX_XC2V10000_DESC(iface, fn_table, cookie) \
+{ Xilinx_Virtex2, iface, XILINX_XC2V10000_SIZE, fn_table, cookie }
+
+#endif /* _VIRTEX2_H_ */
+
+/* vim: set ts=4 tw=78: */
diff --git a/include/xilinx.h b/include/xilinx.h
new file mode 100644 (file)
index 0000000..b87cfe2
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.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 <fpga.h>
+
+#ifndef _XILINX_H_
+#define _XILINX_H_
+
+/* Xilinx Model definitions
+ *********************************************************************/
+#define CFG_SPARTAN2                   CFG_FPGA_DEV( 0x1 )
+#define CFG_VIRTEX_E                   CFG_FPGA_DEV( 0x2 )
+#define CFG_VIRTEX2                            CFG_FPGA_DEV( 0x4 )
+#define CFG_XILINX_SPARTAN2    (CFG_FPGA_XILINX | CFG_SPARTAN2)
+#define CFG_XILINX_VIRTEX_E    (CFG_FPGA_XILINX | CFG_VIRTEX_E)
+#define CFG_XILINX_VIRTEX2             (CFG_FPGA_XILINX | CFG_VIRTEX2)
+/* XXX - Add new models here */
+
+
+/* Xilinx Interface definitions
+ *********************************************************************/
+#define CFG_XILINX_IF_SS       CFG_FPGA_IF( 0x1 )      /* slave serial         */
+#define CFG_XILINX_IF_MS       CFG_FPGA_IF( 0x2 )      /* master serial        */
+#define CFG_XILINX_IF_SP       CFG_FPGA_IF( 0x4 )      /* slave parallel       */
+#define CFG_XILINX_IF_JTAG     CFG_FPGA_IF( 0x8 )      /* jtag                         */
+#define CFG_XILINX_IF_MSM      CFG_FPGA_IF( 0x10 )     /* master selectmap     */
+#define CFG_XILINX_IF_SSM      CFG_FPGA_IF( 0x20 )     /* slave selectmap      */
+
+/* Xilinx types
+ *********************************************************************/
+typedef enum {                                 /* typedef Xilinx_iface */
+       min_xilinx_iface_type,          /* low range check value */
+    slave_serial,                              /* serial data and external clock */
+    master_serial,                             /* serial data w/ internal clock (not used) */
+    slave_parallel,                            /* parallel data w/ external latch */
+    jtag_mode,                                 /* jtag/tap serial (not used ) */
+       master_selectmap,                       /* master SelectMap (virtex2)           */
+       slave_selectmap,                        /* slave SelectMap (virtex2)            */
+    max_xilinx_iface_type              /* insert all new types before this */
+} Xilinx_iface;                                        /* end, typedef Xilinx_iface */
+
+typedef enum {                                 /* typedef Xilinx_Family */
+       min_xilinx_type,                        /* low range check value */
+    Xilinx_Spartan2,                   /* Spartan-II Family */
+    Xilinx_VirtexE,                            /* Virtex-E Family */
+    Xilinx_Virtex2,                            /* Virtex2 Family */
+    max_xilinx_type                            /* insert all new types before this */
+} Xilinx_Family;                               /* end, typedef Xilinx_Family */
+
+typedef struct {                               /* typedef Xilinx_desc */
+    Xilinx_Family    family;   /* part type */
+    Xilinx_iface     iface;            /* interface type */
+    size_t           size;             /* bytes of data part can accept */
+       void *           iface_fns;     /* interface function table */
+    int              cookie;   /* implementation specific cookie */
+} Xilinx_desc;                                 /* end, typedef Xilinx_desc */
+
+/* Generic Xilinx Functions
+ *********************************************************************/
+extern int xilinx_load( Xilinx_desc *desc, void *image, size_t size );
+extern int xilinx_dump( Xilinx_desc *desc, void *buf, size_t bsize );
+extern int xilinx_info( Xilinx_desc *desc );
+extern int xilinx_reloc( Xilinx_desc *desc, ulong reloc_offset );
+
+/* Board specific implementation specific function types
+ *********************************************************************/
+typedef int (*Xilinx_pgm_fn)( int assert_pgm, int flush, int cookie );
+typedef int (*Xilinx_init_fn)( int cookie );
+typedef int (*Xilinx_err_fn)( int cookie );
+typedef int (*Xilinx_done_fn)( int cookie );
+typedef int (*Xilinx_clk_fn)( int assert_clk, int flush, int cookie );
+typedef int (*Xilinx_cs_fn)( int assert_cs, int flush, int cookie );
+typedef int (*Xilinx_wr_fn)( int assert_write, int flush, int cookie );
+typedef int (*Xilinx_rdata_fn)( unsigned char *data, int cookie );
+typedef int (*Xilinx_wdata_fn)( unsigned char data, int flush, int cookie );
+typedef int (*Xilinx_busy_fn)( int cookie );
+typedef int (*Xilinx_abort_fn)( int cookie );
+typedef int (*Xilinx_pre_fn)( int cookie );
+typedef int (*Xilinx_post_fn)( int cookie );
+
+#endif  /* _XILINX_H_ */
diff --git a/lib_arm/_udivsi3.S b/lib_arm/_udivsi3.S
new file mode 100644 (file)
index 0000000..19454c1
--- /dev/null
@@ -0,0 +1,77 @@
+/* # 1 "libgcc1.S" */
+@ libgcc1 routines for ARM cpu.
+@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
+dividend       .req    r0
+divisor                .req    r1
+result         .req    r2
+curbit         .req    r3
+ip             .req    r12
+sp             .req    r13
+lr             .req    r14
+pc             .req    r15
+       .text
+       .globl   __udivsi3
+       .type  __udivsi3       ,function
+       .align  0
+ __udivsi3      :
+       cmp     divisor, #0
+       beq     Ldiv0
+       mov     curbit, #1
+       mov     result, #0
+       cmp     dividend, divisor
+       bcc     Lgot_result
+Loop1:
+       @ Unless the divisor is very big, shift it up in multiples of
+       @ four bits, since this is the amount of unwinding in the main
+       @ division loop.  Continue shifting until the divisor is
+       @ larger than the dividend.
+       cmp     divisor, #0x10000000
+       cmpcc   divisor, dividend
+       movcc   divisor, divisor, lsl #4
+       movcc   curbit, curbit, lsl #4
+       bcc     Loop1
+Lbignum:
+       @ For very big divisors, we must shift it a bit at a time, or
+       @ we will be in danger of overflowing.
+       cmp     divisor, #0x80000000
+       cmpcc   divisor, dividend
+       movcc   divisor, divisor, lsl #1
+       movcc   curbit, curbit, lsl #1
+       bcc     Lbignum
+Loop3:
+       @ Test for possible subtractions, and note which bits
+       @ are done in the result.  On the final pass, this may subtract
+       @ too much from the dividend, but the result will be ok, since the
+       @ "bit" will have been shifted out at the bottom.
+       cmp     dividend, divisor
+       subcs   dividend, dividend, divisor
+       orrcs   result, result, curbit
+       cmp     dividend, divisor, lsr #1
+       subcs   dividend, dividend, divisor, lsr #1
+       orrcs   result, result, curbit, lsr #1
+       cmp     dividend, divisor, lsr #2
+       subcs   dividend, dividend, divisor, lsr #2
+       orrcs   result, result, curbit, lsr #2
+       cmp     dividend, divisor, lsr #3
+       subcs   dividend, dividend, divisor, lsr #3
+       orrcs   result, result, curbit, lsr #3
+       cmp     dividend, #0                    @ Early termination?
+       movnes  curbit, curbit, lsr #4          @ No, any more bits to do?
+       movne   divisor, divisor, lsr #4
+       bne     Loop3
+Lgot_result:
+       mov     r0, result
+       mov     pc, lr
+Ldiv0:
+       str     lr, [sp, #-4]!
+       bl       __div0       (PLT)
+       mov     r0, #0                  @ about as wrong as it could be
+       ldmia   sp!, {pc}
+       .size  __udivsi3       , . -  __udivsi3
+/* # 235 "libgcc1.S" */
+/* # 320 "libgcc1.S" */
+/* # 421 "libgcc1.S" */
+/* # 433 "libgcc1.S" */
+/* # 456 "libgcc1.S" */
+/* # 500 "libgcc1.S" */
+/* # 580 "libgcc1.S" */
diff --git a/lib_arm/_umodsi3.S b/lib_arm/_umodsi3.S
new file mode 100644 (file)
index 0000000..899ffbf
--- /dev/null
@@ -0,0 +1,88 @@
+/* # 1 "libgcc1.S" */
+@ libgcc1 routines for ARM cpu.
+@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
+/* # 145 "libgcc1.S" */
+dividend       .req    r0
+divisor                .req    r1
+overdone       .req    r2
+curbit         .req    r3
+ip             .req    r12
+sp             .req    r13
+lr             .req    r14
+pc             .req    r15
+       .text
+       .globl   __umodsi3
+       .type  __umodsi3       ,function
+       .align 0
+ __umodsi3      :
+       cmp     divisor, #0
+       beq     Ldiv0
+       mov     curbit, #1
+       cmp     dividend, divisor
+       movcc   pc, lr
+Loop1:
+       @ Unless the divisor is very big, shift it up in multiples of
+       @ four bits, since this is the amount of unwinding in the main
+       @ division loop.  Continue shifting until the divisor is
+       @ larger than the dividend.
+       cmp     divisor, #0x10000000
+       cmpcc   divisor, dividend
+       movcc   divisor, divisor, lsl #4
+       movcc   curbit, curbit, lsl #4
+       bcc     Loop1
+Lbignum:
+       @ For very big divisors, we must shift it a bit at a time, or
+       @ we will be in danger of overflowing.
+       cmp     divisor, #0x80000000
+       cmpcc   divisor, dividend
+       movcc   divisor, divisor, lsl #1
+       movcc   curbit, curbit, lsl #1
+       bcc     Lbignum
+Loop3:
+       @ Test for possible subtractions.  On the final pass, this may
+       @ subtract too much from the dividend, so keep track of which
+       @ subtractions are done, we can fix them up afterwards...
+       mov     overdone, #0
+       cmp     dividend, divisor
+       subcs   dividend, dividend, divisor
+       cmp     dividend, divisor, lsr #1
+       subcs   dividend, dividend, divisor, lsr #1
+       orrcs   overdone, overdone, curbit, ror #1
+       cmp     dividend, divisor, lsr #2
+       subcs   dividend, dividend, divisor, lsr #2
+       orrcs   overdone, overdone, curbit, ror #2
+       cmp     dividend, divisor, lsr #3
+       subcs   dividend, dividend, divisor, lsr #3
+       orrcs   overdone, overdone, curbit, ror #3
+       mov     ip, curbit
+       cmp     dividend, #0                    @ Early termination?
+       movnes  curbit, curbit, lsr #4          @ No, any more bits to do?
+       movne   divisor, divisor, lsr #4
+       bne     Loop3
+       @ Any subtractions that we should not have done will be recorded in
+       @ the top three bits of "overdone".  Exactly which were not needed
+       @ are governed by the position of the bit, stored in ip.
+       @ If we terminated early, because dividend became zero,
+       @ then none of the below will match, since the bit in ip will not be
+       @ in the bottom nibble.
+       ands    overdone, overdone, #0xe0000000
+       moveq   pc, lr                          @ No fixups needed
+       tst     overdone, ip, ror #3
+       addne   dividend, dividend, divisor, lsr #3
+       tst     overdone, ip, ror #2
+       addne   dividend, dividend, divisor, lsr #2
+       tst     overdone, ip, ror #1
+       addne   dividend, dividend, divisor, lsr #1
+       mov     pc, lr
+Ldiv0:
+       str     lr, [sp, #-4]!
+       bl       __div0       (PLT)
+       mov     r0, #0                  @ about as wrong as it could be
+       ldmia   sp!, {pc}
+       .size  __umodsi3       , . -  __umodsi3
+/* # 320 "libgcc1.S" */
+/* # 421 "libgcc1.S" */
+/* # 433 "libgcc1.S" */
+/* # 456 "libgcc1.S" */
+/* # 500 "libgcc1.S" */
+/* # 580 "libgcc1.S" */
diff --git a/lib_arm/armlinux.c b/lib_arm/armlinux.c
new file mode 100644 (file)
index 0000000..e5b8faa
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * 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 <cmd_boot.h>
+#include <image.h>
+#include <zlib.h>
+#include <asm/byteorder.h>
+
+#include <asm/setup.h>
+#define tag_size(type)  ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
+#define tag_next(t)     ((struct tag *)((u32 *)(t) + (t)->hdr.size))
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_VFD)
+static void setup_start_tag(bd_t *bd);
+static void setup_memory_tags(bd_t *bd);
+static void setup_commandline_tag(bd_t *bd, char *commandline);
+#if 0
+static void setup_ramdisk_tag(bd_t *bd);
+#endif
+static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end);
+static void setup_end_tag(bd_t *bd);
+#if defined (CONFIG_VFD)
+static void setup_videolfb_tag(gd_t *gd);
+#endif
+
+
+static struct tag *params;
+#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
+
+extern image_header_t header;           /* from cmd_bootm.c */
+
+
+void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
+               ulong addr, ulong *len_ptr, int   verify)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+    ulong len = 0, checksum;
+    ulong initrd_start, initrd_end;
+    ulong data;
+    void (*theKernel)(int zero, int arch);
+    image_header_t *hdr = &header;
+    bd_t *bd = gd->bd;
+#ifdef CONFIG_CMDLINE_TAG
+    char *commandline = getenv("bootargs");
+#endif
+
+    theKernel = (void (*)(int, int))ntohl(hdr->ih_ep);
+
+    /*
+     * Check if there is an initrd image
+     */
+    if (argc >= 3) {
+       addr = simple_strtoul(argv[2], NULL, 16);
+
+       printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
+
+       /* Copy header so we can blank CRC field for re-calculation */
+       memcpy (&header, (char *)addr, sizeof(image_header_t));
+
+       if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+           printf ("Bad Magic Number\n");
+           do_reset (cmdtp, flag, argc, argv);
+       }
+
+       data = (ulong)&header;
+       len  = sizeof(image_header_t);
+
+       checksum = ntohl(hdr->ih_hcrc);
+       hdr->ih_hcrc = 0;
+
+       if (crc32 (0, (char *)data, len) != checksum) {
+           printf ("Bad Header Checksum\n");
+           do_reset (cmdtp, flag, argc, argv);
+       }
+
+       print_image_hdr (hdr);
+
+       data = addr + sizeof(image_header_t);
+       len  = ntohl(hdr->ih_size);
+
+       if (verify) {
+           ulong csum = 0;
+
+           printf ("   Verifying Checksum ... ");
+           csum = crc32 (0, (char *)data, len);
+           if (csum != ntohl(hdr->ih_dcrc)) {
+               printf ("Bad Data CRC\n");
+               do_reset (cmdtp, flag, argc, argv);
+           }
+           printf ("OK\n");
+       }
+
+       if ((hdr->ih_os   != IH_OS_LINUX)       ||
+           (hdr->ih_arch != IH_CPU_ARM)        ||
+           (hdr->ih_type != IH_TYPE_RAMDISK)   ) {
+           printf ("No Linux ARM Ramdisk Image\n");
+           do_reset (cmdtp, flag, argc, argv);
+       }
+
+       /*
+        * Now check if we have a multifile image
+        */
+    } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
+       ulong tail    = ntohl(len_ptr[0]) % 4;
+       int i;
+
+       /* skip kernel length and terminator */
+       data = (ulong)(&len_ptr[2]);
+       /* skip any additional image length fields */
+       for (i=1; len_ptr[i]; ++i)
+         data += 4;
+       /* add kernel length, and align */
+       data += ntohl(len_ptr[0]);
+       if (tail) {
+           data += 4 - tail;
+       }
+
+       len   = ntohl(len_ptr[1]);
+
+    } else {
+       /*
+        * no initrd image
+        */
+       data = 0;
+    }
+
+#ifdef DEBUG
+    if (!data) {
+       printf ("No initrd\n");
+    }
+#endif
+
+    if (data) {
+       initrd_start = data;
+       initrd_end   = initrd_start + len;
+    } else {
+       initrd_start = 0;
+       initrd_end = 0;
+    }
+
+#ifdef DEBUG
+    printf ("## Transferring control to Linux (at address %08lx) ...\n",
+           (ulong)theKernel);
+#endif
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_VFD)
+    setup_start_tag(bd);
+#ifdef CONFIG_SETUP_MEMORY_TAGS
+    setup_memory_tags(bd);
+#endif
+#ifdef CONFIG_CMDLINE_TAG
+    setup_commandline_tag(bd, commandline);
+#endif
+#ifdef CONFIG_INITRD_TAG
+    setup_initrd_tag(bd, initrd_start, initrd_end);
+#endif
+#if 0
+    setup_ramdisk_tag(bd);
+#endif
+#if defined (CONFIG_VFD)
+    setup_videolfb_tag(gd);
+#endif
+    setup_end_tag(bd);
+#endif
+
+    /* we assume that the kernel is in place */
+    printf("\nStarting kernel ...\n\n");
+
+    cleanup_before_linux();
+
+    theKernel(0, bd->bi_arch_number);
+}
+
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_VFD)
+static void setup_start_tag(bd_t *bd)
+{
+    params = (struct tag *)bd->bi_boot_params;
+
+    params->hdr.tag = ATAG_CORE;
+    params->hdr.size = tag_size(tag_core);
+
+    params->u.core.flags = 0;
+    params->u.core.pagesize = 0;
+    params->u.core.rootdev = 0;
+
+    params = tag_next(params);
+}
+
+
+static void setup_memory_tags(bd_t *bd)
+{
+    int i;
+
+    for(i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+       params->hdr.tag = ATAG_MEM;
+       params->hdr.size = tag_size(tag_mem32);
+
+       params->u.mem.start = bd->bi_dram[i].start;
+       params->u.mem.size = bd->bi_dram[i].size;
+
+       params = tag_next(params);
+    }
+}
+
+
+static void setup_commandline_tag(bd_t *bd, char *commandline)
+{
+    char *p;
+
+    /* eat leading white space */
+    for(p = commandline; *p == ' '; p++)
+      ;
+
+    /* skip non-existent command lines so the kernel will still
+     * use its default command line.
+     */
+    if(*p == '\0')
+      return;
+
+    params->hdr.tag = ATAG_CMDLINE;
+    params->hdr.size = (sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2;
+
+    strcpy(params->u.cmdline.cmdline, p);
+
+    params = tag_next(params);
+}
+
+
+#ifndef ATAG_INITRD2
+#define ATAG_INITRD2    0x54420005
+#endif
+static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end)
+{
+    /* an ATAG_INITRD node tells the kernel where the compressed
+     * ramdisk can be found. ATAG_RDIMG is a better name, actually.
+     */
+    params->hdr.tag = ATAG_INITRD2;
+    params->hdr.size = tag_size(tag_initrd);
+
+    params->u.initrd.start = initrd_start;
+    params->u.initrd.size = initrd_end - initrd_start;
+
+    params = tag_next(params);
+}
+
+
+#if 0
+static void setup_ramdisk_tag(bd_t *bd)
+{
+    /* an ATAG_RAMDISK node tells the kernel how large the
+     * decompressed ramdisk will become.
+     */
+    params->hdr.tag = ATAG_RAMDISK;
+    params->hdr.size = tag_size(tag_ramdisk);
+
+    params->u.ramdisk.start = 0;
+    /*params->u.ramdisk.size = RAMDISK_SIZE; */
+    params->u.ramdisk.flags = 1;       /* automatically load ramdisk */
+
+    params = tag_next(params);
+}
+#endif /* 0 */
+
+#if defined (CONFIG_VFD)
+static void setup_videolfb_tag(gd_t *gd)
+{
+    /* An ATAG_VIDEOLFB node tells the kernel where and how large
+     * the framebuffer for video was allocated (among other things).
+     * Note that a _physical_ address is passed !
+     *
+     * We only use it to pass the address and size, the other entries
+     * in the tag_videolfb are not of interest.
+     */
+    params->hdr.tag = ATAG_VIDEOLFB;
+    params->hdr.size = tag_size(tag_videolfb);
+
+    params->u.videolfb.lfb_base = (u32)gd->fb_base;
+    /* 7168 = 256*4*56/8 - actually 2 pages (8192 bytes) are allocated */
+    params->u.videolfb.lfb_size = 7168;
+
+    params = tag_next(params);
+}
+#endif
+
+static void setup_end_tag(bd_t *bd)
+{
+    params->hdr.tag = ATAG_NONE;
+    params->hdr.size = 0;
+}
+
+#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
diff --git a/lib_arm/board.c b/lib_arm/board.c
new file mode 100644 (file)
index 0000000..e58529f
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (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>
+#include <command.h>
+#include <devices.h>
+#include <version.h>
+#include <net.h>
+
+
+const char version_string[] =
+       U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")";
+
+#ifdef CONFIG_DRIVER_CS8900
+extern void cs8900_get_enetaddr (uchar * addr);
+#endif
+
+/*
+ * Begin and End of memory area for malloc(), and current "brk"
+ */
+static ulong mem_malloc_start = 0;
+static ulong mem_malloc_end = 0;
+static ulong mem_malloc_brk = 0;
+
+static void mem_malloc_init (ulong dest_addr)
+{
+       mem_malloc_start = dest_addr;
+       mem_malloc_end = dest_addr + CONFIG_MALLOC_SIZE;
+       mem_malloc_brk = mem_malloc_start;
+
+       memset ((void *) mem_malloc_start, 0,
+                       mem_malloc_end - mem_malloc_start);
+}
+
+void *sbrk (ptrdiff_t increment)
+{
+       ulong old = mem_malloc_brk;
+       ulong new = old + increment;
+
+       if ((new < mem_malloc_start) || (new > mem_malloc_end)) {
+               return (NULL);
+       }
+       mem_malloc_brk = new;
+
+       return ((void *) old);
+}
+
+/************************************************************************
+ * Init Utilities                                                      *
+ ************************************************************************
+ * Some of this code should be moved into the core functions,
+ * or dropped completely,
+ * but let's get it working (again) first...
+ */
+
+static int init_baudrate (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       uchar tmp[64];  /* long enough for environment variables */
+       int i = getenv_r ("baudrate", tmp, sizeof (tmp));
+
+       gd->baudrate = (i > 0)
+                       ? (int) simple_strtoul (tmp, NULL, 10)
+                       : CONFIG_BAUDRATE;
+
+       return (0);
+}
+
+static int display_banner (void)
+{
+
+       printf ("\n\n%s\n\n", version_string);
+       printf ("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",
+               _armboot_start, _armboot_end_data, _armboot_end);
+#ifdef CONFIG_MODEM_SUPPORT
+       puts ("Modem Support enabled\n");
+#endif
+#ifdef CONFIG_USE_IRQ
+       printf ("IRQ Stack: %08lx\n", IRQ_STACK_START);
+       printf ("FIQ Stack: %08lx\n", FIQ_STACK_START);
+#endif
+       return (0);
+}
+
+/*
+ * WARNING: this code looks "cleaner" than the PowerPC version, but
+ * has the disadvantage that you either get nothing, or everything.
+ * On PowerPC, you might see "DRAM: " before the system hangs - which
+ * gives a simple yet clear indication which part of the
+ * initialization if failing.
+ */
+static int display_dram_config (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+       int i;
+
+       puts ("DRAM Configuration:\n");
+
+       for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
+               printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
+               print_size (gd->bd->bi_dram[i].size, "\n");
+       }
+
+       return (0);
+}
+
+static void display_flash_config (ulong size)
+{
+       puts ("Flash: ");
+       print_size (size, "\n");
+}
+
+
+
+/*
+ * Breath some life into the board...
+ *
+ * Initialize an SMC for serial comms, and carry out some hardware
+ * tests.
+ *
+ * The first part of initialization is running from Flash memory;
+ * its main purpose is to initialize the RAM so that we
+ * can relocate the monitor code to RAM.
+ */
+
+/*
+ * All attempts to come up with a "common" initialization sequence
+ * that works for all boards and architectures failed: some of the
+ * requirements are just _too_ different. To get rid of the resulting
+ * mess of board dependend #ifdef'ed code we now make the whole
+ * initialization sequence configurable to the user.
+ *
+ * The requirements for any new initalization function is simple: it
+ * receives a pointer to the "global data" structure as it's only
+ * argument, and returns an integer return code, where 0 means
+ * "continue" and != 0 means "fatal error, hang the system".
+ */
+typedef int (init_fnc_t) (void);
+
+init_fnc_t *init_sequence[] = {
+       cpu_init,               /* basic cpu dependent setup */
+       board_init,             /* basic board dependent setup */
+       interrupt_init,         /* set up exceptions */
+       env_init,               /* initialize environment */
+       init_baudrate,          /* initialze baudrate settings */
+       serial_init,            /* serial communications setup */
+       display_banner,
+       dram_init,              /* configure available RAM banks */
+       display_dram_config,
+
+       NULL,
+};
+
+void start_armboot (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       ulong size;
+       gd_t gd_data;
+       bd_t bd_data;
+       init_fnc_t **init_fnc_ptr;
+#ifdef CONFIG_VFD
+       unsigned long addr;
+#endif
+
+       /* Pointer is writable since we allocated a register for it */
+       gd = &gd_data;
+       memset (gd, 0, sizeof (gd_t));
+       gd->bd = &bd_data;
+       memset (gd->bd, 0, sizeof (bd_t));
+
+       for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+               if ((*init_fnc_ptr)() != 0) {
+                       hang ();
+               }
+       }
+
+       /* configure available FLASH banks */
+       size = flash_init ();
+       display_flash_config (size);
+
+#ifdef CONFIG_VFD
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+       /*
+        * reserve memory for VFD display (always full pages)
+        */
+       /* armboot_real_end is defined in the board-specific linker script */
+       addr = (_armboot_real_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+       size = vfd_setmem (addr);
+       gd->fb_base = addr;
+       /* round to the next page boundary */
+       addr += size;
+       addr = (addr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+       mem_malloc_init (addr);
+#else
+       /* armboot_real_end is defined in the board-specific linker script */
+       mem_malloc_init (_armboot_real_end);
+#endif /* CONFIG_VFD */
+
+#ifdef CONFIG_VFD
+       /* must do this after the framebuffer is allocated */
+       drv_vfd_init();
+#endif
+       /* initialize environment */
+       env_relocate ();
+
+       /* IP Address */
+       bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+       /* MAC Address */
+       {
+               int i;
+               ulong reg;
+               char *s, *e;
+               uchar tmp[64];
+
+               i = getenv_r ("ethaddr", tmp, sizeof (tmp));
+               s = (i > 0) ? tmp : NULL;
+
+               for (reg = 0; reg < 6; ++reg) {
+                       bd_data.bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
+                       if (s)
+                               s = (*e) ? e + 1 : e;
+               }
+       }
+
+#if defined(CONFIG_MISC_INIT_R)
+       /* miscellaneous platform dependent initialisations */
+       misc_init_r ();
+#endif
+
+       /* enable exceptions */
+       enable_interrupts ();
+
+#ifdef CONFIG_DRIVER_CS8900
+       if (!getenv ("ethaddr")) {
+               cs8900_get_enetaddr (gd->bd->bi_enetaddr);
+       }
+#endif
+
+#ifdef BOARD_POST_INIT
+       board_post_init ();
+#endif
+
+       /* main_loop() can return to retry autoboot, if so just run it again. */
+       for (;;) {
+               main_loop ();
+       }
+
+       /* NOTREACHED - no way out of command loop except booting */
+}
+
+void hang (void)
+{
+       puts ("### ERROR ### Please RESET the board ###\n");
+       for (;;);
+}
+
+#ifdef CONFIG_MODEM_SUPPORT
+/* called from main loop (common/main.c) */
+extern void  dbg(const char *fmt, ...);
+int mdm_init (void)
+{
+       char env_str[16];
+       char *init_str;
+       int i;
+       extern char console_buffer[];
+       static inline void mdm_readline(char *buf, int bufsiz);
+       extern void enable_putc(void);
+       extern int hwflow_onoff(int);
+
+       enable_putc(); /* enable serial_putc() */
+
+#ifdef CONFIG_HWFLOW
+       init_str = getenv("mdm_flow_control");
+       if (init_str && (strcmp(init_str, "rts/cts") == 0))
+               hwflow_onoff (1);
+       else
+               hwflow_onoff(-1);
+#endif
+
+       for (i = 1;;i++) {
+               sprintf(env_str, "mdm_init%d", i);
+               if ((init_str = getenv(env_str)) != NULL) {
+                       serial_puts(init_str);
+                       serial_puts("\n");
+                       for(;;) {
+                               mdm_readline(console_buffer, CFG_CBSIZE);
+                               dbg("ini%d: [%s]", i, console_buffer);
+
+                               if ((strcmp(console_buffer, "OK") == 0) ||
+                                       (strcmp(console_buffer, "ERROR") == 0)) {
+                                       dbg("ini%d: cmd done", i);
+                                       break;
+                               } else /* in case we are originating call ... */
+                                       if (strncmp(console_buffer, "CONNECT", 7) == 0) {
+                                               dbg("ini%d: connect", i);
+                                               return 0;
+                                       }
+                       }
+               } else
+                       break; /* no init string - stop modem init */
+
+               udelay(100000);
+       }
+
+       udelay(100000);
+
+       /* final stage - wait for connect */
+       for(;i > 1;) { /* if 'i' > 1 - wait for connection
+                                 message from modem */
+               mdm_readline(console_buffer, CFG_CBSIZE);
+               dbg("ini_f: [%s]", console_buffer);
+               if (strncmp(console_buffer, "CONNECT", 7) == 0) {
+                       dbg("ini_f: connected");
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
+/* 'inline' - We have to do it fast */
+static inline void mdm_readline(char *buf, int bufsiz)
+{
+       char c;
+       char *p;
+       int n;
+
+       n = 0;
+       p = buf;
+       for(;;) {
+               c = serial_getc();
+
+               /*              dbg("(%c)", c); */
+
+               switch(c) {
+               case '\r':
+                       break;
+               case '\n':
+                       *p = '\0';
+                       return;
+
+               default:
+                       if(n++ > bufsiz) {
+                               *p = '\0';
+                               return; /* sanity check */
+                       }
+                       *p = c;
+                       p++;
+                       break;
+               }
+       }
+}
+#endif /* CONFIG_MODEM_SUPPORT */
diff --git a/lib_generic/string.c b/lib_generic/string.c
new file mode 100644 (file)
index 0000000..1e1e2e3
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ *
+ * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
+ * -  Added strsep() which will replace strtok() soon (because strsep() is
+ *    reentrant and should be faster). Use only strsep() in new code, please.
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <malloc.h>
+
+#ifdef CONFIG_ARM
+#undef  __HAVE_ARCH_MEMCMP
+#undef  __HAVE_ARCH_MEMCPY
+#undef  __HAVE_ARCH_MEMMOVE
+#undef  __HAVE_ARCH_MEMSET
+#undef  __HAVE_ARCH_BCOPY
+#undef  __HAVE_ARCH_STRCAT
+#undef  __HAVE_ARCH_STRCHR
+#undef  __HAVE_ARCH_STRCMP
+#undef  __HAVE_ARCH_STRCPY
+#undef  __HAVE_ARCH_STRLEN
+#undef  __HAVE_ARCH_STRNCPY
+#else
+#define __HAVE_ARCH_MEMCMP
+#define __HAVE_ARCH_MEMCPY
+#define __HAVE_ARCH_MEMMOVE
+#define __HAVE_ARCH_MEMSET
+#define __HAVE_ARCH_BCOPY
+#define __HAVE_ARCH_STRCAT
+#define __HAVE_ARCH_STRCMP
+#define __HAVE_ARCH_STRCPY
+#define __HAVE_ARCH_STRLEN
+#define __HAVE_ARCH_STRNCPY
+#endif
+
+#ifndef __HAVE_ARCH_STRNICMP
+/**
+ * strnicmp - Case insensitive, length-limited string comparison
+ * @s1: One string
+ * @s2: The other string
+ * @len: the maximum number of characters to compare
+ */
+int strnicmp(const char *s1, const char *s2, size_t len)
+{
+       /* Yes, Virginia, it had better be unsigned */
+       unsigned char c1, c2;
+
+       c1 = 0; c2 = 0;
+       if (len) {
+               do {
+                       c1 = *s1; c2 = *s2;
+                       s1++; s2++;
+                       if (!c1)
+                               break;
+                       if (!c2)
+                               break;
+                       if (c1 == c2)
+                               continue;
+                       c1 = tolower(c1);
+                       c2 = tolower(c2);
+                       if (c1 != c2)
+                               break;
+               } while (--len);
+       }
+       return (int)c1 - (int)c2;
+}
+#endif
+
+char * ___strtok;
+
+#ifndef __HAVE_ARCH_STRCPY
+/**
+ * strcpy - Copy a %NUL terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ */
+char * strcpy(char * dest,const char *src)
+{
+       char *tmp = dest;
+
+       while ((*dest++ = *src++) != '\0')
+               /* nothing */;
+       return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCPY
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
+ * However, the result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ */
+char * strncpy(char * dest,const char *src,size_t count)
+{
+       char *tmp = dest;
+
+       while (count-- && (*dest++ = *src++) != '\0')
+               /* nothing */;
+
+       return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCAT
+/**
+ * strcat - Append one %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ */
+char * strcat(char * dest, const char * src)
+{
+       char *tmp = dest;
+
+       while (*dest)
+               dest++;
+       while ((*dest++ = *src++) != '\0')
+               ;
+
+       return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCAT
+/**
+ * strncat - Append a length-limited, %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ * @count: The maximum numbers of bytes to copy
+ *
+ * Note that in contrast to strncpy, strncat ensures the result is
+ * terminated.
+ */
+char * strncat(char *dest, const char *src, size_t count)
+{
+       char *tmp = dest;
+
+       if (count) {
+               while (*dest)
+                       dest++;
+               while ((*dest++ = *src++)) {
+                       if (--count == 0) {
+                               *dest = '\0';
+                               break;
+                       }
+               }
+       }
+
+       return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCMP
+/**
+ * strcmp - Compare two strings
+ * @cs: One string
+ * @ct: Another string
+ */
+int strcmp(const char * cs,const char * ct)
+{
+       register signed char __res;
+
+       while (1) {
+               if ((__res = *cs - *ct++) != 0 || !*cs++)
+                       break;
+       }
+
+       return __res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCMP
+/**
+ * strncmp - Compare two length-limited strings
+ * @cs: One string
+ * @ct: Another string
+ * @count: The maximum number of bytes to compare
+ */
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+       register signed char __res = 0;
+
+       while (count) {
+               if ((__res = *cs - *ct++) != 0 || !*cs++)
+                       break;
+               count--;
+       }
+
+       return __res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCHR
+/**
+ * strchr - Find the first occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strchr(const char * s, int c)
+{
+       for(; *s != (char) c; ++s)
+               if (*s == '\0')
+                       return NULL;
+       return (char *) s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRRCHR
+/**
+ * strrchr - Find the last occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strrchr(const char * s, int c)
+{
+       const char *p = s + strlen(s);
+       do {
+           if (*p == (char)c)
+               return (char *)p;
+       } while (--p >= s);
+       return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRLEN
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char * s)
+{
+       const char *sc;
+
+       for (sc = s; *sc != '\0'; ++sc)
+               /* nothing */;
+       return sc - s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNLEN
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char * s, size_t count)
+{
+       const char *sc;
+
+       for (sc = s; count-- && *sc != '\0'; ++sc)
+               /* nothing */;
+       return sc - s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRDUP
+char * strdup(const char *s)
+{
+       char *new;
+
+       if ((s == NULL) ||
+           ((new = malloc (strlen(s) + 1)) == NULL) ) {
+               return NULL;
+       }
+
+       strcpy (new, s);
+       return new;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSPN
+/**
+ * strspn - Calculate the length of the initial substring of @s which only
+ *     contain letters in @accept
+ * @s: The string to be searched
+ * @accept: The string to search for
+ */
+size_t strspn(const char *s, const char *accept)
+{
+       const char *p;
+       const char *a;
+       size_t count = 0;
+
+       for (p = s; *p != '\0'; ++p) {
+               for (a = accept; *a != '\0'; ++a) {
+                       if (*p == *a)
+                               break;
+               }
+               if (*a == '\0')
+                       return count;
+               ++count;
+       }
+
+       return count;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRPBRK
+/**
+ * strpbrk - Find the first occurrence of a set of characters
+ * @cs: The string to be searched
+ * @ct: The characters to search for
+ */
+char * strpbrk(const char * cs,const char * ct)
+{
+       const char *sc1,*sc2;
+
+       for( sc1 = cs; *sc1 != '\0'; ++sc1) {
+               for( sc2 = ct; *sc2 != '\0'; ++sc2) {
+                       if (*sc1 == *sc2)
+                               return (char *) sc1;
+               }
+       }
+       return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRTOK
+/**
+ * strtok - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * WARNING: strtok is deprecated, use strsep instead.
+ */
+char * strtok(char * s,const char * ct)
+{
+       char *sbegin, *send;
+
+       sbegin  = s ? s : ___strtok;
+       if (!sbegin) {
+               return NULL;
+       }
+       sbegin += strspn(sbegin,ct);
+       if (*sbegin == '\0') {
+               ___strtok = NULL;
+               return( NULL );
+       }
+       send = strpbrk( sbegin, ct);
+       if (send && *send != '\0')
+               *send++ = '\0';
+       ___strtok = send;
+       return (sbegin);
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSEP
+/**
+ * strsep - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * strsep() updates @s to point after the token, ready for the next call.
+ *
+ * It returns empty tokens, too, behaving exactly like the libc function
+ * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
+ * Same semantics, slimmer shape. ;)
+ */
+char * strsep(char **s, const char *ct)
+{
+       char *sbegin = *s, *end;
+
+       if (sbegin == NULL)
+               return NULL;
+
+       end = strpbrk(sbegin, ct);
+       if (end)
+               *end++ = '\0';
+       *s = end;
+
+       return sbegin;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMSET
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void * memset(void * s,int c,size_t count)
+{
+       char *xs = (char *) s;
+
+       while (count--)
+               *xs++ = c;
+
+       return s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_BCOPY
+/**
+ * bcopy - Copy one area of memory to another
+ * @src: Where to copy from
+ * @dest: Where to copy to
+ * @count: The size of the area.
+ *
+ * Note that this is the same as memcpy(), with the arguments reversed.
+ * memcpy() is the standard, bcopy() is a legacy BSD function.
+ *
+ * You should not use this function to access IO space, use memcpy_toio()
+ * or memcpy_fromio() instead.
+ */
+char * bcopy(const char * src, char * dest, int count)
+{
+       char *tmp = dest;
+
+       while (count--)
+               *tmp++ = *src++;
+
+       return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCPY
+/**
+ * memcpy - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * You should not use this function to access IO space, use memcpy_toio()
+ * or memcpy_fromio() instead.
+ */
+void * memcpy(void * dest,const void *src,size_t count)
+{
+       char *tmp = (char *) dest, *s = (char *) src;
+
+       while (count--)
+               *tmp++ = *s++;
+
+       return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMMOVE
+/**
+ * memmove - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * Unlike memcpy(), memmove() copes with overlapping areas.
+ */
+void * memmove(void * dest,const void *src,size_t count)
+{
+       char *tmp, *s;
+
+       if (dest <= src) {
+               tmp = (char *) dest;
+               s = (char *) src;
+               while (count--)
+                       *tmp++ = *s++;
+               }
+       else {
+               tmp = (char *) dest + count;
+               s = (char *) src + count;
+               while (count--)
+                       *--tmp = *--s;
+               }
+
+       return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCMP
+/**
+ * memcmp - Compare two areas of memory
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ */
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+       const unsigned char *su1, *su2;
+       int res = 0;
+
+       for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+               if ((res = *su1 - *su2) != 0)
+                       break;
+       return res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMSCAN
+/**
+ * memscan - Find a character in an area of memory.
+ * @addr: The memory area
+ * @c: The byte to search for
+ * @size: The size of the area.
+ *
+ * returns the address of the first occurrence of @c, or 1 byte past
+ * the area if @c is not found
+ */
+void * memscan(void * addr, int c, size_t size)
+{
+       unsigned char * p = (unsigned char *) addr;
+
+       while (size) {
+               if (*p == c)
+                       return (void *) p;
+               p++;
+               size--;
+       }
+       return (void *) p;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSTR
+/**
+ * strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+char * strstr(const char * s1,const char * s2)
+{
+       int l1, l2;
+
+       l2 = strlen(s2);
+       if (!l2)
+               return (char *) s1;
+       l1 = strlen(s1);
+       while (l1 >= l2) {
+               l1--;
+               if (!memcmp(s1,s2,l2))
+                       return (char *) s1;
+               s1++;
+       }
+       return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCHR
+/**
+ * memchr - Find a character in an area of memory.
+ * @s: The memory area
+ * @c: The byte to search for
+ * @n: The size of the area.
+ *
+ * returns the address of the first occurrence of @c, or %NULL
+ * if @c is not found
+ */
+void *memchr(const void *s, int c, size_t n)
+{
+       const unsigned char *p = s;
+       while (n-- != 0) {
+               if ((unsigned char)c == *p++) {
+                       return (void *)(p-1);
+               }
+       }
+       return NULL;
+}
+
+#endif
diff --git a/net/eth.c b/net/eth.c
new file mode 100644 (file)
index 0000000..3b06440
--- /dev/null
+++ b/net/eth.c
@@ -0,0 +1,292 @@
+/*
+ * (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 <command.h>
+#include <net.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI)
+
+#ifdef CFG_GT_6426x
+extern int gt6426x_eth_initialize(bd_t *bis);
+#endif
+
+extern int eepro100_initialize(bd_t*);
+extern int natsemi_initialize(bd_t*);
+extern int ns8382x_initialize(bd_t*);
+extern int dc21x4x_initialize(bd_t*);
+extern int pcnet_initialize(bd_t*);
+extern int fec_initialize(bd_t*);
+extern int scc_initialize(bd_t*);
+
+static struct eth_device *eth_devices, *eth_current;
+
+struct eth_device *eth_get_dev(void)
+{
+       return eth_current;
+}
+
+int eth_get_dev_index (void)
+{
+       struct eth_device *dev;
+       int num = 0;
+
+       if (!eth_devices) {
+               return (-1);
+       }
+
+       for (dev = eth_devices; dev; dev = dev->next) {
+               if (dev == eth_current)
+                       break;
+               ++num;
+       }
+
+       if (dev) {
+               return (num);
+       }
+
+       return (0);
+}
+
+int eth_register(struct eth_device* dev)
+{
+       struct eth_device *d;
+
+       if (!eth_devices) {
+               eth_current = eth_devices = dev;
+       } else {
+               for (d=eth_devices; d->next!=eth_devices; d=d->next);
+               d->next = dev;
+       }
+
+       dev->state = ETH_STATE_INIT;
+       dev->next  = eth_devices;
+
+       return 0;
+}
+
+int eth_initialize(bd_t *bis)
+{
+       unsigned char enetvar[32], env_enetaddr[6];
+       int i, eth_number = 0;
+       char *tmp, *end;
+
+       eth_devices = NULL;
+       eth_current = NULL;
+
+#ifdef CONFIG_EEPRO100
+       eepro100_initialize(bis);
+#endif
+#ifdef CONFIG_TULIP
+       dc21x4x_initialize(bis);
+#endif
+#ifdef CONFIG_PCNET
+       pcnet_initialize(bis);
+#endif
+#ifdef CFG_GT_6426x
+       gt6426x_eth_initialize(bis);
+#endif
+#ifdef CONFIG_NATSEMI
+       natsemi_initialize(bis);
+#endif
+#ifdef CONFIG_NS8382X
+       ns8382x_initialize(bis);
+#endif
+#ifdef SCC_ENET
+       scc_initialize(bis);
+#endif
+#ifdef FEC_ENET
+       fec_initialize(bis);
+#endif
+
+       if (!eth_devices) {
+               puts ("No ethernet found.\n");
+       } else {
+               struct eth_device *dev = eth_devices;
+               char *ethprime = getenv ("ethprime");
+
+               do {
+                       if (eth_number)
+                               puts (", ");
+
+                       printf("%s", dev->name);
+
+                       if (ethprime && strcmp (dev->name, ethprime) == 0) {
+                               eth_current = dev;
+                               puts (" [PRIME]");
+                       }
+
+                       sprintf(enetvar, eth_number ? "eth%daddr" : "ethaddr", eth_number);
+                       tmp = getenv (enetvar);
+
+                       for (i=0; i<6; i++) {
+                               env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
+                               if (tmp)
+                                       tmp = (*end) ? end+1 : end;
+                       }
+
+                       if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6)) {
+                               if (memcmp(dev->enetaddr, "\0\0\0\0\0\0", 6) &&
+                                   memcmp(dev->enetaddr, env_enetaddr, 6))
+                               {
+                                       printf("\nWarning: %s HW address don't match:\n", dev->name);
+                                       printf("Address in SROM is         "
+                                              "%02X:%02X:%02X:%02X:%02X:%02X\n",
+                                              dev->enetaddr[0], dev->enetaddr[1],
+                                              dev->enetaddr[2], dev->enetaddr[3],
+                                              dev->enetaddr[4], dev->enetaddr[5]);
+                                       printf("Address in environment is  "
+                                              "%02X:%02X:%02X:%02X:%02X:%02X\n",
+                                              env_enetaddr[0], env_enetaddr[1],
+                                              env_enetaddr[2], env_enetaddr[3],
+                                              env_enetaddr[4], env_enetaddr[5]);
+                               }
+
+                               memcpy(dev->enetaddr, env_enetaddr, 6);
+                       }
+
+                       eth_number++;
+                       dev = dev->next;
+               } while(dev != eth_devices);
+
+               putc ('\n');
+       }
+
+       return eth_number;
+}
+
+void eth_set_enetaddr(int num, char *addr) {
+       struct eth_device *dev;
+       unsigned char enetaddr[6];
+       char *end;
+       int i;
+
+#ifdef DEBUG
+       printf("eth_set_enetaddr(num=%d, addr=%s)\n", num, addr);
+#endif
+       if (!eth_devices)
+               return;
+
+       for (i=0; i<6; i++) {
+               enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
+               if (addr)
+                       addr = (*end) ? end+1 : end;
+       }
+
+       dev = eth_devices;
+       while(num-- > 0) {
+               dev = dev->next;
+
+               if (dev == eth_devices)
+                       return;
+       }
+
+#ifdef DEBUG
+       printf("Setting new HW address on %s\n", dev->name);
+       printf("New Address is             "
+              "%02X:%02X:%02X:%02X:%02X:%02X\n",
+              dev->enetaddr[0], dev->enetaddr[1],
+              dev->enetaddr[2], dev->enetaddr[3],
+              dev->enetaddr[4], dev->enetaddr[5]);
+#endif
+
+       memcpy(dev->enetaddr, enetaddr, 6);
+}
+
+int eth_init(bd_t *bis)
+{
+       struct eth_device* old_current;
+
+       if (!eth_current)
+               return 0;
+
+       old_current = eth_current;
+       do {
+#ifdef DEBUG
+               printf("Trying %s\n", eth_current->name);
+#endif
+
+               if (eth_current->init(eth_current, bis)) {
+                       eth_current->state = ETH_STATE_ACTIVE;
+
+                       printf("%s configured\n", eth_current->name);
+                       return 1;
+               }
+
+#ifdef DEBUG
+               puts ("FAIL\n");
+#endif
+
+               eth_try_another(0);
+       } while (old_current != eth_current);
+
+       return 0;
+}
+
+void eth_halt(void)
+{
+       if (!eth_current)
+               return;
+
+       eth_current->halt(eth_current);
+
+       eth_current->state = ETH_STATE_PASSIVE;
+}
+
+int eth_send(volatile void *packet, int length)
+{
+       if (!eth_current)
+               return -1;
+
+       return eth_current->send(eth_current, packet, length);
+}
+
+int eth_rx(void)
+{
+       if (!eth_current)
+               return -1;
+
+       return eth_current->recv(eth_current);
+}
+
+void eth_try_another(int first_restart)
+{
+       static struct eth_device *first_failed = NULL;
+
+       if (!eth_current)
+               return;
+
+       if (first_restart)
+       {
+               first_failed = eth_current;
+       }
+
+       eth_current = eth_current->next;
+
+       if (first_failed == eth_current)
+       {
+               NetRestartWrap = 1;
+       }
+}
+
+#endif
diff --git a/post/cache_8xx.S b/post/cache_8xx.S
new file mode 100644 (file)
index 0000000..4c1c295
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ *  Copyright (C) 2002 Wolfgang Denk <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>
+
+#ifdef CONFIG_POST
+#if defined(CONFIG_MPC823) || \
+    defined(CONFIG_MPC850) || \
+    defined(CONFIG_MPC855) || \
+    defined(CONFIG_MPC860) || \
+    defined(CONFIG_MPC824X)
+
+#include <post.h>
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/cache.h>
+
+#if CONFIG_POST & CFG_POST_CACHE
+
+       .text
+
+cache_post_dinvalidate:
+       lis     r10, IDC_INVALL@h
+       mtspr   DC_CST, r10
+       blr
+
+cache_post_iinvalidate:
+       lis     r10, IDC_INVALL@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+cache_post_ddisable:
+       lis     r10, IDC_DISABLE@h
+       mtspr   DC_CST, r10
+       blr
+
+cache_post_dwb:
+       lis     r10, IDC_ENABLE@h
+       mtspr   DC_CST, r10
+       lis     r10, DC_CFWT@h
+       mtspr   DC_CST, r10
+       blr
+
+cache_post_dwt:
+       lis     r10, IDC_ENABLE@h
+       mtspr   DC_CST, r10
+       lis     r10, DC_SFWT@h
+       mtspr   DC_CST, r10
+       blr
+
+cache_post_idisable:
+       lis     r10, IDC_DISABLE@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+cache_post_ienable:
+       lis     r10, IDC_ENABLE@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+cache_post_iunlock:
+       lis     r10, IDC_UNALL@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+cache_post_ilock:
+       mtspr   IC_ADR, r3
+       lis     r10, IDC_LDLCK@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+/*
+ * turn on the data cache
+ * switch the data cache to write-back or write-through mode
+ * invalidate the data cache
+ * write the negative pattern to a cached area
+ * read the area
+ *
+ * The negative pattern must be read at the last step
+ */
+       .global cache_post_test1
+cache_post_test1:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       stwu    r3, -4(r1)
+       stwu    r4, -4(r1)
+
+       bl      cache_post_dwb
+       bl      cache_post_dinvalidate
+
+       /* Write the negative pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0xff
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       /* Read the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       lwz     r4, 4(r1)
+       subi    r4, r4, 1
+       li      r3, 0
+1:
+       lbzu    r0, 1(r4)
+       cmpli   cr0, r0, 0xff
+       beq     2f
+       li      r3, -1
+       b       3f
+2:
+       bdnz    1b
+3:
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       addi    r1, r1, 8
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+/*
+ * turn on the data cache
+ * switch the data cache to write-back or write-through mode
+ * invalidate the data cache
+ * write the zero pattern to a cached area
+ * turn off the data cache
+ * write the negative pattern to the area
+ * turn on the data cache
+ * read the area
+ *
+ * The negative pattern must be read at the last step
+ */
+       .global cache_post_test2
+cache_post_test2:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       stwu    r3, -4(r1)
+       stwu    r4, -4(r1)
+
+       bl      cache_post_dwb
+       bl      cache_post_dinvalidate
+
+       /* Write the zero pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_ddisable
+
+       /* Write the negative pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0xff
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_dwb
+
+       /* Read the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       lwz     r4, 4(r1)
+       subi    r4, r4, 1
+       li      r3, 0
+1:
+       lbzu    r0, 1(r4)
+       cmpli   cr0, r0, 0xff
+       beq     2f
+       li      r3, -1
+       b       3f
+2:
+       bdnz    1b
+3:
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       addi    r1, r1, 8
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+/*
+ * turn on the data cache
+ * switch the data cache to write-through mode
+ * invalidate the data cache
+ * write the zero pattern to a cached area
+ * flush the data cache
+ * write the negative pattern to the area
+ * turn off the data cache
+ * read the area
+ *
+ * The negative pattern must be read at the last step
+ */
+       .global cache_post_test3
+cache_post_test3:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       stwu    r3, -4(r1)
+       stwu    r4, -4(r1)
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       /* Write the zero pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_dwt
+       bl      cache_post_dinvalidate
+
+       /* Write the negative pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0xff
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       /* Read the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       lwz     r4, 4(r1)
+       subi    r4, r4, 1
+       li      r3, 0
+1:
+       lbzu    r0, 1(r4)
+       cmpli   cr0, r0, 0xff
+       beq     2f
+       li      r3, -1
+       b       3f
+2:
+       bdnz    1b
+3:
+
+       addi    r1, r1, 8
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+/*
+ * turn on the data cache
+ * switch the data cache to write-back mode
+ * invalidate the data cache
+ * write the negative pattern to a cached area
+ * flush the data cache
+ * write the zero pattern to the area
+ * invalidate the data cache
+ * read the area
+ *
+ * The negative pattern must be read at the last step
+ */
+       .global cache_post_test4
+cache_post_test4:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       stwu    r3, -4(r1)
+       stwu    r4, -4(r1)
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       /* Write the negative pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0xff
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_dwb
+       bl      cache_post_dinvalidate
+
+       /* Write the zero pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       /* Read the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       lwz     r4, 4(r1)
+       subi    r4, r4, 1
+       li      r3, 0
+1:
+       lbzu    r0, 1(r4)
+       cmpli   cr0, r0, 0xff
+       beq     2f
+       li      r3, -1
+       b       3f
+2:
+       bdnz    1b
+3:
+
+       addi    r1, r1, 8
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+cache_post_test5_1:
+       li      r3, 0
+cache_post_test5_2:
+       li      r3, -1
+
+/*
+ * turn on the instruction cache
+ * unlock the entire instruction cache
+ * invalidate the instruction cache
+ * lock a branch instruction in the instruction cache
+ * replace the branch instruction with "nop"
+ * jump to the branch instruction
+ * check that the branch instruction was executed
+*/
+       .global cache_post_test5
+cache_post_test5:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       bl      cache_post_ienable
+       bl      cache_post_iunlock
+       bl      cache_post_iinvalidate
+
+       /* Compute r9 = cache_post_test5_reloc */
+       bl      cache_post_test5_reloc
+cache_post_test5_reloc:
+       mflr    r9
+
+       /* Copy the test instruction to cache_post_test5_data */
+       lis     r3, (cache_post_test5_1 - cache_post_test5_reloc)@h
+       ori     r3, r3, (cache_post_test5_1 - cache_post_test5_reloc)@l
+       add     r3, r3, r9
+       lis     r4, (cache_post_test5_data - cache_post_test5_reloc)@h
+       ori     r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l
+       add     r4, r4, r9
+       lwz     r0, 0(r3)
+       stw     r0, 0(r4)
+
+       bl      cache_post_iinvalidate
+
+       /* Lock the branch instruction */
+       lis     r3, (cache_post_test5_data - cache_post_test5_reloc)@h
+       ori     r3, r3, (cache_post_test5_data - cache_post_test5_reloc)@l
+       add     r3, r3, r9
+       bl      cache_post_ilock
+
+       /* Replace the test instruction */
+       lis     r3, (cache_post_test5_2 - cache_post_test5_reloc)@h
+       ori     r3, r3, (cache_post_test5_2 - cache_post_test5_reloc)@l
+       add     r3, r3, r9
+       lis     r4, (cache_post_test5_data - cache_post_test5_reloc)@h
+       ori     r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l
+       add     r4, r4, r9
+       lwz     r0, 0(r3)
+       stw     r0, 0(r4)
+
+       bl      cache_post_iinvalidate
+
+       /* Execute to the test instruction */
+cache_post_test5_data:
+       nop
+
+       bl      cache_post_iunlock
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+cache_post_test6_1:
+       li      r3, -1
+cache_post_test6_2:
+       li      r3, 0
+
+/*
+ * turn on the instruction cache
+ * unlock the entire instruction cache
+ * invalidate the instruction cache
+ * lock a branch instruction in the instruction cache
+ * replace the branch instruction with "nop"
+ * jump to the branch instruction
+ * check that the branch instruction was executed
+ */
+       .global cache_post_test6
+cache_post_test6:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       bl      cache_post_ienable
+       bl      cache_post_iunlock
+       bl      cache_post_iinvalidate
+
+       /* Compute r9 = cache_post_test6_reloc */
+       bl      cache_post_test6_reloc
+cache_post_test6_reloc:
+       mflr    r9
+
+       /* Copy the test instruction to cache_post_test6_data */
+       lis     r3, (cache_post_test6_1 - cache_post_test6_reloc)@h
+       ori     r3, r3, (cache_post_test6_1 - cache_post_test6_reloc)@l
+       add     r3, r3, r9
+       lis     r4, (cache_post_test6_data - cache_post_test6_reloc)@h
+       ori     r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l
+       add     r4, r4, r9
+       lwz     r0, 0(r3)
+       stw     r0, 0(r4)
+
+       bl      cache_post_iinvalidate
+
+       /* Replace the test instruction */
+       lis     r3, (cache_post_test6_2 - cache_post_test6_reloc)@h
+       ori     r3, r3, (cache_post_test6_2 - cache_post_test6_reloc)@l
+       add     r3, r3, r9
+       lis     r4, (cache_post_test6_data - cache_post_test6_reloc)@h
+       ori     r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l
+       add     r4, r4, r9
+       lwz     r0, 0(r3)
+       stw     r0, 0(r4)
+
+       bl      cache_post_iinvalidate
+
+       /* Execute to the test instruction */
+cache_post_test6_data:
+       nop
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+#endif /* CONFIG_MPC823 || MPC850 || MPC855 || MPC860 || MPC824X */
+#endif /* CONFIG_POST & CFG_POST_CACHE */
+#endif /* CONFIG_POST */
diff --git a/post/cpu.c b/post/cpu.c
new file mode 100644 (file)
index 0000000..6b8fc6e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ *
+ * This test checks the arithmetic logic unit (ALU) of CPU.
+ * It tests independently various groups of instructions using
+ * run-time modification of the code to reduce the memory footprint.
+ * For more details refer to post/cpu/ *.c files.
+ */
+
+#ifdef CONFIG_POST
+
+#include <watchdog.h>
+#include <post.h>
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern int cpu_post_test_cmp (void);
+extern int cpu_post_test_cmpi (void);
+extern int cpu_post_test_two (void);
+extern int cpu_post_test_twox (void);
+extern int cpu_post_test_three (void);
+extern int cpu_post_test_threex (void);
+extern int cpu_post_test_threei (void);
+extern int cpu_post_test_andi (void);
+extern int cpu_post_test_srawi (void);
+extern int cpu_post_test_rlwnm (void);
+extern int cpu_post_test_rlwinm (void);
+extern int cpu_post_test_rlwimi (void);
+extern int cpu_post_test_store (void);
+extern int cpu_post_test_load (void);
+extern int cpu_post_test_cr (void);
+extern int cpu_post_test_b (void);
+extern int cpu_post_test_multi (void);
+extern int cpu_post_test_string (void);
+extern int cpu_post_test_complex (void);
+
+ulong cpu_post_makecr (long v)
+{
+       ulong cr = 0;
+
+       if (v < 0)
+               cr |= 0x80000000;
+       if (v > 0)
+               cr |= 0x40000000;
+       if (v == 0)
+               cr |= 0x20000000;
+
+       return cr;
+}
+
+int cpu_post_test (int flags)
+{
+       int ic = icache_status ();
+       int ret = 0;
+
+       if (ic)
+               icache_disable ();
+
+       if (ret == 0)
+               ret = cpu_post_test_cmp ();
+       if (ret == 0)
+               ret = cpu_post_test_cmpi ();
+       if (ret == 0)
+               ret = cpu_post_test_two ();
+       if (ret == 0)
+               ret = cpu_post_test_twox ();
+       if (ret == 0)
+               ret = cpu_post_test_three ();
+       if (ret == 0)
+               ret = cpu_post_test_threex ();
+       if (ret == 0)
+               ret = cpu_post_test_threei ();
+       WATCHDOG_RESET();
+       if (ret == 0)
+               ret = cpu_post_test_andi ();
+       if (ret == 0)
+               ret = cpu_post_test_srawi ();
+       if (ret == 0)
+               ret = cpu_post_test_rlwnm ();
+       if (ret == 0)
+               ret = cpu_post_test_rlwinm ();
+       if (ret == 0)
+               ret = cpu_post_test_rlwimi ();
+       if (ret == 0)
+               ret = cpu_post_test_store ();
+       if (ret == 0)
+               ret = cpu_post_test_load ();
+       WATCHDOG_RESET();
+       if (ret == 0)
+               ret = cpu_post_test_cr ();
+       if (ret == 0)
+               ret = cpu_post_test_b ();
+       if (ret == 0)
+               ret = cpu_post_test_multi ();
+       if (ret == 0)
+               ret = cpu_post_test_string ();
+       if (ret == 0)
+               ret = cpu_post_test_complex ();
+
+       if (ic)
+               icache_enable ();
+
+       return ret;
+}
+
+#endif /* CONFIG_POST & CFG_POST_CPU */
+#endif /* CONFIG_POST */
diff --git a/post/cpu/b.c b/post/cpu/b.c
new file mode 100644 (file)
index 0000000..1ae22cc
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ * Branch instructions:                b, bl, bc
+ *
+ * The first 2 instructions (b, bl) are verified by jumping
+ * to a fixed address and checking whether control was transfered
+ * to that very point. For the bl instruction the value of the
+ * link register is checked as well (using mfspr).
+ * To verify the bc instruction various combinations of the BI/BO
+ * fields, the CTR and the condition register values are
+ * checked. The list of such combinations is pre-built and
+ * linked in U-Boot at build time.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
+extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump,
+    ulong cr);
+
+static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi,
+    int pjump, int dec, int link, ulong pctr, ulong cr)
+{
+    int ret = 0;
+    ulong lr = 0;
+    ulong ctr = pctr;
+    ulong jump;
+
+    unsigned long code[] =
+    {
+       ASM_MTCR(6),
+       ASM_MFLR(6),
+       ASM_MTCTR(3),
+       ASM_MTLR(4),
+       ASM_LI(5, 1),
+       ASM_3O(cmd, bo, bi, 8),
+       ASM_LI(5, 0),
+       ASM_MFCTR(3),
+       ASM_MFLR(4),
+       ASM_MTLR(6),
+       ASM_BLR,
+    };
+
+    cpu_post_exec_31 (code, &ctr, &lr, &jump, cr);
+
+    if (ret == 0)
+       ret = pjump == jump ? 0 : -1;
+    if (ret == 0)
+    {
+       if (dec)
+           ret = pctr == ctr + 1 ? 0 : -1;
+       else
+           ret = pctr == ctr ? 0 : -1;
+    }
+    if (ret == 0)
+    {
+       if (link)
+            ret = lr == (ulong) code + 24 ? 0 : -1;
+       else
+           ret = lr == 0 ? 0 : -1;
+    }
+
+    return ret;
+}
+
+int cpu_post_test_b (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    if (ret == 0)
+    {
+       ulong code[] =
+       {
+          ASM_MFLR(4),
+          ASM_MTLR(3),
+          ASM_B(4),
+          ASM_MFLR(3),
+          ASM_MTLR(4),
+          ASM_BLR,
+       };
+       ulong res;
+
+       cpu_post_exec_11 (code, &res, 0);
+
+       ret = res == 0 ? 0 : -1;
+
+       if (ret != 0)
+       {
+            post_log ("Error at b1 test !\n");
+       }
+    }
+
+    if (ret == 0)
+    {
+       ulong code[] =
+       {
+          ASM_MFLR(4),
+          ASM_MTLR(3),
+          ASM_BL(4),
+          ASM_MFLR(3),
+          ASM_MTLR(4),
+          ASM_BLR,
+       };
+       ulong res;
+
+       cpu_post_exec_11 (code, &res, 0);
+
+       ret = res == (ulong)code + 12 ? 0 : -1;
+
+       if (ret != 0)
+       {
+            post_log ("Error at b2 test !\n");
+       }
+    }
+
+    if (ret == 0)
+    {
+        ulong cc, cd;
+       int cond;
+       ulong ctr;
+       int link;
+
+       i = 0;
+
+       for (cc = 0; cc < 4 && ret == 0; cc++)
+       {
+           for (cd = 0; cd < 4 && ret == 0; cd++)
+           {
+               for (link = 0; link <= 1 && ret == 0; link++)
+               {
+                   for (cond = 0; cond <= 1 && ret == 0; cond++)
+                   {
+                       for (ctr = 1; ctr <= 2 && ret == 0; ctr++)
+                       {
+                           int dec = cd < 2;
+                           int cr = cond ? 0x80000000 : 0x00000000;
+                           int jumpc = cc >= 2 ||
+                                       (cc == 0 && !cond) ||
+                                       (cc == 1 && cond);
+                           int jumpd = cd >= 2 ||
+                                       (cd == 0 && ctr != 1) ||
+                                       (cd == 1 && ctr == 1);
+                           int jump = jumpc && jumpd;
+
+                           ret = cpu_post_test_bc (link ? OP_BCL : OP_BC,
+                               (cc << 3) + (cd << 1), 0, jump, dec, link,
+                               ctr, cr);
+
+                           if (ret != 0)
+                           {
+                               post_log ("Error at b3 test %d !\n", i);
+                           }
+
+                           i++;
+                       }
+                   }
+               }
+           }
+       }
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/cpu/cmp.c b/post/cpu/cmp.c
new file mode 100644 (file)
index 0000000..789a24c
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ * Integer compare instructions:       cmpw, cmplw
+ *
+ * To verify these instructions the test runs them with
+ * different combinations of operands, reads the condition
+ * register value and compares it with the expected one.
+ * The test contains a pre-built table
+ * containing the description of each test case: the instruction,
+ * the values of the operands, the condition field to save
+ * the result in and the expected result.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2);
+
+static struct cpu_post_cmp_s
+{
+    ulong cmd;
+    ulong op1;
+    ulong op2;
+    ulong cr;
+    ulong res;
+} cpu_post_cmp_table[] =
+{
+    {
+       OP_CMPW,
+       123,
+       123,
+       2,
+       0x02
+    },
+    {
+       OP_CMPW,
+       123,
+       133,
+       3,
+       0x08
+    },
+    {
+       OP_CMPW,
+       123,
+       -133,
+       4,
+       0x04
+    },
+    {
+       OP_CMPLW,
+       123,
+       123,
+       2,
+       0x02
+    },
+    {
+       OP_CMPLW,
+       123,
+       -133,
+       3,
+       0x08
+    },
+    {
+       OP_CMPLW,
+       123,
+       113,
+       4,
+       0x04
+    },
+};
+static unsigned int cpu_post_cmp_size =
+    sizeof (cpu_post_cmp_table) / sizeof (struct cpu_post_cmp_s);
+
+int cpu_post_test_cmp (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    for (i = 0; i < cpu_post_cmp_size && ret == 0; i++)
+    {
+       struct cpu_post_cmp_s *test = cpu_post_cmp_table + i;
+       unsigned long code[] =
+       {
+           ASM_2C(test->cmd, test->cr, 3, 4),
+           ASM_MFCR(3),
+           ASM_BLR
+       };
+       ulong res;
+
+       cpu_post_exec_12 (code, & res, test->op1, test->op2);
+
+       ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at cmp test %d !\n", i);
+       }
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/cpu/cmpi.c b/post/cpu/cmpi.c
new file mode 100644 (file)
index 0000000..e0c2aaf
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ * Integer compare instructions:       cmpwi, cmplwi
+ *
+ * To verify these instructions the test runs them with
+ * different combinations of operands, reads the condition
+ * register value and compares it with the expected one.
+ * The test contains a pre-built table
+ * containing the description of each test case: the instruction,
+ * the values of the operands, the condition field to save
+ * the result in and the expected result.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
+
+static struct cpu_post_cmpi_s
+{
+    ulong cmd;
+    ulong op1;
+    ushort op2;
+    ulong cr;
+    ulong res;
+} cpu_post_cmpi_table[] =
+{
+    {
+       OP_CMPWI,
+       123,
+       123,
+       2,
+       0x02
+    },
+    {
+       OP_CMPWI,
+       123,
+       133,
+       3,
+       0x08
+    },
+    {
+       OP_CMPWI,
+       123,
+       -133,
+       4,
+       0x04
+    },
+    {
+       OP_CMPLWI,
+       123,
+       123,
+       2,
+       0x02
+    },
+    {
+       OP_CMPLWI,
+       123,
+       -133,
+       3,
+       0x08
+    },
+    {
+       OP_CMPLWI,
+       123,
+       113,
+       4,
+       0x04
+    },
+};
+static unsigned int cpu_post_cmpi_size =
+    sizeof (cpu_post_cmpi_table) / sizeof (struct cpu_post_cmpi_s);
+
+int cpu_post_test_cmpi (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    for (i = 0; i < cpu_post_cmpi_size && ret == 0; i++)
+    {
+       struct cpu_post_cmpi_s *test = cpu_post_cmpi_table + i;
+       unsigned long code[] =
+       {
+           ASM_1IC(test->cmd, test->cr, 3, test->op2),
+           ASM_MFCR(3),
+           ASM_BLR
+       };
+       ulong res;
+
+       cpu_post_exec_11 (code, & res, test->op1);
+
+       ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at cmpi test %d !\n", i);
+       }
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/cpu/cr.c b/post/cpu/cr.c
new file mode 100644 (file)
index 0000000..8e38729
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ * Condition register istructions:     mtcr, mfcr, mcrxr,
+ *                                     crand, crandc, cror, crorc, crxor,
+ *                                     crnand, crnor, creqv, mcrf
+ *
+ * The mtcrf/mfcr instructions is tested by loading different
+ * values into the condition register (mtcrf), moving its value
+ * to a general-purpose register (mfcr) and comparing this value
+ * with the expected one.
+ * The mcrxr instruction is tested by loading a fixed value
+ * into the XER register (mtspr), moving XER value to the
+ * condition register (mcrxr), moving it to a general-purpose
+ * register (mfcr) and comparing the value of this register with
+ * the expected one.
+ * The rest of instructions is tested by loading a fixed
+ * value into the condition register (mtcrf), executing each
+ * instruction several times to modify all 4-bit condition
+ * fields, moving the value of the conditional register to a
+ * general-purpose register (mfcr) and comparing it with the
+ * expected one.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
+extern void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3);
+
+static ulong cpu_post_cr_table1[] =
+{
+    0xaaaaaaaa,
+    0x55555555,
+};
+static unsigned int cpu_post_cr_size1 =
+    sizeof (cpu_post_cr_table1) / sizeof (ulong);
+
+static struct cpu_post_cr_s2 {
+    ulong xer;
+    ulong cr;
+} cpu_post_cr_table2[] =
+{
+    {
+       0xa0000000,
+       1
+    },
+    {
+       0x40000000,
+       5
+    },
+};
+static unsigned int cpu_post_cr_size2 =
+    sizeof (cpu_post_cr_table2) / sizeof (struct cpu_post_cr_s2);
+
+static struct cpu_post_cr_s3 {
+    ulong cr;
+    ulong cs;
+    ulong cd;
+    ulong res;
+} cpu_post_cr_table3[] =
+{
+    {
+       0x01234567,
+       0,
+       4,
+       0x01230567
+    },
+    {
+       0x01234567,
+       7,
+       0,
+       0x71234567
+    },
+};
+static unsigned int cpu_post_cr_size3 =
+    sizeof (cpu_post_cr_table3) / sizeof (struct cpu_post_cr_s3);
+
+static struct cpu_post_cr_s4 {
+    ulong cmd;
+    ulong cr;
+    ulong op1;
+    ulong op2;
+    ulong op3;
+    ulong res;
+} cpu_post_cr_table4[] =
+{
+    {
+       OP_CRAND,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRAND,
+       0x0000ffff,
+       16,
+       17,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CRANDC,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRANDC,
+       0x0000ffff,
+       16,
+       0,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CROR,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CROR,
+       0x0000ffff,
+       0,
+       1,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRORC,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRORC,
+       0x0000ffff,
+       0,
+       0,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CRXOR,
+       0x0000ffff,
+       0,
+       0,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRXOR,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CRNAND,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CRNAND,
+       0x0000ffff,
+       16,
+       17,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRNOR,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRNOR,
+       0x0000ffff,
+       0,
+       1,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CREQV,
+       0x0000ffff,
+       0,
+       0,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CREQV,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+};
+static unsigned int cpu_post_cr_size4 =
+    sizeof (cpu_post_cr_table4) / sizeof (struct cpu_post_cr_s4);
+
+int cpu_post_test_cr (void)
+{
+    int ret = 0;
+    unsigned int i;
+    unsigned long cr_sav;
+
+    asm ( "mfcr %0" : "=r" (cr_sav) : );
+
+    for (i = 0; i < cpu_post_cr_size1 && ret == 0; i++)
+    {
+       ulong cr = cpu_post_cr_table1[i];
+       ulong res;
+
+       unsigned long code[] =
+       {
+           ASM_MTCR(3),
+           ASM_MFCR(3),
+           ASM_BLR,
+       };
+
+       cpu_post_exec_11 (code, &res, cr);
+
+       ret = res == cr ? 0 : -1;
+
+       if (ret != 0)
+       {
+            post_log ("Error at cr1 test %d !\n", i);
+       }
+    }
+
+    for (i = 0; i < cpu_post_cr_size2 && ret == 0; i++)
+    {
+       struct cpu_post_cr_s2 *test = cpu_post_cr_table2 + i;
+       ulong res;
+       ulong xer;
+
+       unsigned long code[] =
+       {
+           ASM_MTXER(3),
+           ASM_MCRXR(test->cr),
+           ASM_MFCR(3),
+           ASM_MFXER(4),
+           ASM_BLR,
+       };
+
+       cpu_post_exec_21x (code, &res, &xer, test->xer);
+
+       ret = xer == 0 && ((res << (4 * test->cr)) & 0xe0000000) == test->xer ?
+             0 : -1;
+
+       if (ret != 0)
+       {
+            post_log ("Error at cr2 test %d !\n", i);
+       }
+    }
+
+    for (i = 0; i < cpu_post_cr_size3 && ret == 0; i++)
+    {
+       struct cpu_post_cr_s3 *test = cpu_post_cr_table3 + i;
+       ulong res;
+
+       unsigned long code[] =
+       {
+           ASM_MTCR(3),
+           ASM_MCRF(test->cd, test->cs),
+           ASM_MFCR(3),
+           ASM_BLR,
+       };
+
+       cpu_post_exec_11 (code, &res, test->cr);
+
+       ret = res == test->res ? 0 : -1;
+
+       if (ret != 0)
+       {
+            post_log ("Error at cr3 test %d !\n", i);
+       }
+    }
+
+    for (i = 0; i < cpu_post_cr_size4 && ret == 0; i++)
+    {
+       struct cpu_post_cr_s4 *test = cpu_post_cr_table4 + i;
+       ulong res;
+
+       unsigned long code[] =
+       {
+           ASM_MTCR(3),
+           ASM_12F(test->cmd, test->op3, test->op1, test->op2),
+           ASM_MFCR(3),
+           ASM_BLR,
+       };
+
+       cpu_post_exec_11 (code, &res, test->cr);
+
+       ret = res == test->res ? 0 : -1;
+
+       if (ret != 0)
+       {
+            post_log ("Error at cr4 test %d !\n", i);
+       }
+    }
+
+    asm ( "mtcr %0" : : "r" (cr_sav));
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/cpu/three.c b/post/cpu/three.c
new file mode 100644 (file)
index 0000000..c2d7476
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ * Ternary instructions                instr rD,rA,rB
+ *
+ * Arithmetic instructions:    add, addc, adde, subf, subfc, subfe,
+ *                             mullw, mulhw, mulhwu, divw, divwu
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
+    ulong op2);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_three_s
+{
+    ulong cmd;
+    ulong op1;
+    ulong op2;
+    ulong res;
+} cpu_post_three_table[] =
+{
+    {
+       OP_ADD,
+       100,
+       200,
+       300
+    },
+    {
+       OP_ADD,
+       100,
+       -200,
+       -100
+    },
+    {
+       OP_ADDC,
+       100,
+       200,
+       300
+    },
+    {
+       OP_ADDC,
+       100,
+       -200,
+       -100
+    },
+    {
+       OP_ADDE,
+       100,
+       200,
+       300
+    },
+    {
+       OP_ADDE,
+       100,
+       -200,
+       -100
+    },
+    {
+       OP_SUBF,
+       100,
+       200,
+       100
+    },
+    {
+       OP_SUBF,
+       300,
+       200,
+       -100
+    },
+    {
+       OP_SUBFC,
+       100,
+       200,
+       100
+    },
+    {
+       OP_SUBFC,
+       300,
+       200,
+       -100
+    },
+    {
+       OP_SUBFE,
+       100,
+       200,
+       200 + ~100
+    },
+    {
+       OP_SUBFE,
+       300,
+       200,
+       200 + ~300
+    },
+    {
+       OP_MULLW,
+       200,
+       300,
+       200 * 300
+    },
+    {
+       OP_MULHW,
+       0x10000000,
+       0x10000000,
+       0x1000000
+    },
+    {
+       OP_MULHWU,
+       0x80000000,
+       0x80000000,
+       0x40000000
+    },
+    {
+       OP_DIVW,
+       -20,
+       5,
+       -4
+    },
+    {
+       OP_DIVWU,
+       0x8000,
+       0x200,
+       0x40
+    },
+};
+static unsigned int cpu_post_three_size =
+    sizeof (cpu_post_three_table) / sizeof (struct cpu_post_three_s);
+
+int cpu_post_test_three (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_three_size && ret == 0; i++)
+    {
+       struct cpu_post_three_s *test = cpu_post_three_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int reg2 = (reg + 2) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_12(test->cmd, reg2, reg1, reg0),
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_12(test->cmd, reg2, reg1, reg0) | BIT_C,
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at three test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at three test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/cpu/threei.c b/post/cpu/threei.c
new file mode 100644 (file)
index 0000000..79f0178
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ * Ternary instructions                instr rA,rS,UIMM
+ *
+ * Logic instructions:         ori, oris, xori, xoris
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_threei_s
+{
+    ulong cmd;
+    ulong op1;
+    ushort op2;
+    ulong res;
+} cpu_post_threei_table[] =
+{
+    {
+       OP_ORI,
+       0x80000000,
+       0xffff,
+       0x8000ffff
+    },
+    {
+       OP_ORIS,
+       0x00008000,
+       0xffff,
+       0xffff8000
+    },
+    {
+       OP_XORI,
+       0x8000ffff,
+       0xffff,
+       0x80000000
+    },
+    {
+       OP_XORIS,
+       0x00008000,
+       0xffff,
+       0xffff8000
+    },
+};
+static unsigned int cpu_post_threei_size =
+    sizeof (cpu_post_threei_table) / sizeof (struct cpu_post_threei_s);
+
+int cpu_post_test_threei (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_threei_size && ret == 0; i++)
+    {
+       struct cpu_post_threei_s *test = cpu_post_threei_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11IX(test->cmd, reg1, reg0, test->op2),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           cr = 0;
+           cpu_post_exec_21 (code, & cr, & res, test->op1);
+
+           ret = res == test->res && cr == 0 ? 0 : -1;
+
+           if (ret != 0)
+           {
+               post_log ("Error at threei test %d !\n", i);
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/cpu/threex.c b/post/cpu/threex.c
new file mode 100644 (file)
index 0000000..2c72063
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ * Ternary instructions                instr rA,rS,rB
+ *
+ * Logic instructions:         or, orc, xor, nand, nor, eqv
+ * Shift instructions:         slw, srw, sraw
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
+    ulong op2);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_threex_s
+{
+    ulong cmd;
+    ulong op1;
+    ulong op2;
+    ulong res;
+} cpu_post_threex_table[] =
+{
+    {
+       OP_OR,
+       0x1234,
+       0x5678,
+       0x1234 | 0x5678
+    },
+    {
+       OP_ORC,
+       0x1234,
+       0x5678,
+       0x1234 | ~0x5678
+    },
+    {
+       OP_XOR,
+       0x1234,
+       0x5678,
+       0x1234 ^ 0x5678
+    },
+    {
+       OP_NAND,
+       0x1234,
+       0x5678,
+       ~(0x1234 & 0x5678)
+    },
+    {
+       OP_NOR,
+       0x1234,
+       0x5678,
+       ~(0x1234 | 0x5678)
+    },
+    {
+       OP_EQV,
+       0x1234,
+       0x5678,
+       ~(0x1234 ^ 0x5678)
+    },
+    {
+       OP_SLW,
+       0x80,
+       16,
+       0x800000
+    },
+    {
+       OP_SLW,
+       0x80,
+       32,
+       0
+    },
+    {
+       OP_SRW,
+       0x800000,
+       16,
+       0x80
+    },
+    {
+       OP_SRW,
+       0x800000,
+       32,
+       0
+    },
+    {
+       OP_SRAW,
+       0x80000000,
+       3,
+       0xf0000000
+    },
+    {
+       OP_SRAW,
+       0x8000,
+       3,
+       0x1000
+    },
+};
+static unsigned int cpu_post_threex_size =
+    sizeof (cpu_post_threex_table) / sizeof (struct cpu_post_threex_s);
+
+int cpu_post_test_threex (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_threex_size && ret == 0; i++)
+    {
+       struct cpu_post_threex_s *test = cpu_post_threex_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int reg2 = (reg + 2) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_12X(test->cmd, reg2, reg1, reg0),
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_12X(test->cmd, reg2, reg1, reg0) | BIT_C,
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at threex test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at threex test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/cpu/two.c b/post/cpu/two.c
new file mode 100644 (file)
index 0000000..6075714
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ * Binary instructions         instr rD,rA
+ *
+ * Logic instructions:         neg
+ * Arithmetic instructions:    addme, addze, subfme, subfze
+
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_two_s
+{
+    ulong cmd;
+    ulong op;
+    ulong res;
+} cpu_post_two_table[] =
+{
+    {
+       OP_NEG,
+       3,
+       -3
+    },
+    {
+       OP_NEG,
+       5,
+       -5
+    },
+    {
+        OP_ADDME,
+       6,
+       5
+    },
+    {
+        OP_ADDZE,
+       5,
+       5
+    },
+    {
+        OP_SUBFME,
+       6,
+       ~6 - 1
+    },
+    {
+        OP_SUBFZE,
+       5,
+       ~5
+    },
+};
+static unsigned int cpu_post_two_size =
+    sizeof (cpu_post_two_table) / sizeof (struct cpu_post_two_s);
+
+int cpu_post_test_two (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_two_size && ret == 0; i++)
+    {
+       struct cpu_post_two_s *test = cpu_post_two_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11(test->cmd, reg1, reg0),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11(test->cmd, reg1, reg0) | BIT_C,
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_21 (code, & cr, & res, test->op);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at two test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_21 (codecr, & cr, & res, test->op);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at two test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/cpu/twox.c b/post/cpu/twox.c
new file mode 100644 (file)
index 0000000..48d9954
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * (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 <common.h>
+
+/*
+ * CPU test
+ * Binary instructions         instr rA,rS
+ *
+ * Logic instructions:         cntlzw
+ * Arithmetic instructions:    extsb, extsh
+
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_twox_s
+{
+    ulong cmd;
+    ulong op;
+    ulong res;
+} cpu_post_twox_table[] =
+{
+    {
+       OP_EXTSB,
+       3,
+       3
+    },
+    {
+       OP_EXTSB,
+       0xff,
+       -1
+    },
+    {
+       OP_EXTSH,
+       3,
+       3
+    },
+    {
+       OP_EXTSH,
+       0xff,
+       0xff
+    },
+    {
+       OP_EXTSH,
+       0xffff,
+       -1
+    },
+    {
+       OP_CNTLZW,
+       0x000fffff,
+       12
+    },
+};
+static unsigned int cpu_post_twox_size =
+    sizeof (cpu_post_twox_table) / sizeof (struct cpu_post_twox_s);
+
+int cpu_post_test_twox (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_twox_size && ret == 0; i++)
+    {
+       struct cpu_post_twox_s *test = cpu_post_twox_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11X(test->cmd, reg1, reg0),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11X(test->cmd, reg1, reg0) | BIT_C,
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_21 (code, & cr, & res, test->op);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at twox test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_21 (codecr, & cr, & res, test->op);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at twox test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/ether.c b/post/ether.c
new file mode 100644 (file)
index 0000000..5b42ca7
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ * (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 <common.h>
+
+/*
+ * Ethernet test
+ *
+ * The Serial Communication Controllers (SCC) listed in ctlr_list array below
+ * are tested in the loopback ethernet mode.
+ * The controllers are configured accordingly and several packets
+ * are transmitted. The configurable test parameters are:
+ *   MIN_PACKET_LENGTH - minimum size of packet to transmit
+ *   MAX_PACKET_LENGTH - maximum size of packet to transmit
+ *   TEST_NUM - number of tests
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+
+#if defined(CONFIG_8xx)
+#include <commproc.h>
+#elif defined(CONFIG_MPC8260)
+#include <asm/cpm_8260.h>
+#else
+#error "Apparently a bad configuration, please fix."
+#endif
+
+#include <command.h>
+#include <net.h>
+
+#if CONFIG_POST & CFG_POST_ETHER
+
+#define MIN_PACKET_LENGTH      64
+#define MAX_PACKET_LENGTH      256
+#define TEST_NUM               1
+
+#define CTLR_SCC 0
+
+extern void spi_init_f (void);
+extern void spi_init_r (void);
+
+/* The list of controllers to test */
+#if defined(CONFIG_MPC823)
+static int ctlr_list[][2] = { {CTLR_SCC, 1} };
+#else
+static int ctlr_list[][2] = { };
+#endif
+
+#define CTRL_LIST_SIZE (sizeof(ctlr_list) / sizeof(ctlr_list[0]))
+
+static struct {
+       void (*init) (int index);
+       int (*send) (int index, volatile void *packet, int length);
+       int (*recv) (int index, void *packet, int length);
+} ctlr_proc[1];
+
+static char *ctlr_name[1] = { "SCC" };
+
+static int used_by_uart[1] = { -1 };
+static int used_by_ether[1] = { -1 };
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH  1520
+
+#define TX_BUF_CNT 2
+
+#define TOUT_LOOP 100
+
+static char txbuf[DBUF_LENGTH];
+
+static uint rxIdx;             /* index of the current RX buffer */
+static uint txIdx;             /* index of the current TX buffer */
+
+/*
+  * SCC Ethernet Tx and Rx buffer descriptors allocated at the
+  *  immr->udata_bd address on Dual-Port RAM
+  * Provide for Double Buffering
+  */
+
+typedef volatile struct CommonBufferDescriptor {
+       cbd_t rxbd[PKTBUFSRX];          /* Rx BD */
+       cbd_t txbd[TX_BUF_CNT];         /* Tx BD */
+} RTXBD;
+
+static RTXBD *rtx;
+
+  /*
+   * SCC callbacks
+   */
+
+static void scc_init (int scc_index)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+       bd_t *bd = gd->bd;
+
+       static int proff[] =
+                       { PROFF_SCC1, PROFF_SCC2, PROFF_SCC3, PROFF_SCC4 };
+       static unsigned int cpm_cr[] =
+                       { CPM_CR_CH_SCC1, CPM_CR_CH_SCC2, CPM_CR_CH_SCC3,
+CPM_CR_CH_SCC4 };
+
+       int i;
+       scc_enet_t *pram_ptr;
+
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+
+       immr->im_cpm.cp_scc[scc_index].scc_gsmrl &=
+                       ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+#if defined(CONFIG_FADS)
+#if defined(CONFIG_MPC860T)
+       /* The FADS860T doesn't use the MODEM_EN or DATA_VOICE signals. */
+       *((uint *) BCSR4) &= ~BCSR4_ETHLOOP;
+       *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL;
+       *((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#else
+       *((uint *) BCSR4) &= ~(BCSR4_ETHLOOP | BCSR4_MODEM_EN);
+       *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL | BCSR4_DATA_VOICE;
+       *((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#endif
+#endif
+
+       pram_ptr = (scc_enet_t *) & (immr->im_cpm.cp_dparam[proff[scc_index]]);
+
+       rxIdx = 0;
+       txIdx = 0;
+
+#ifdef CFG_ALLOC_DPRAM
+       rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +
+                                        dpram_alloc_align (sizeof (RTXBD), 8));
+#else
+       rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_SCC_BASE);
+#endif
+
+#if 0
+
+#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD))
+       /* Configure port A pins for Txd and Rxd.
+        */
+       immr->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD);
+       immr->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
+       immr->im_ioport.iop_paodr &= ~PA_ENET_TXD;
+#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD))
+       /* Configure port B pins for Txd and Rxd.
+        */
+       immr->im_cpm.cp_pbpar |= (PB_ENET_RXD | PB_ENET_TXD);
+       immr->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD);
+       immr->im_cpm.cp_pbodr &= ~PB_ENET_TXD;
+#else
+#error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined
+#endif
+
+#if defined(PC_ENET_LBK)
+       /* Configure port C pins to disable External Loopback
+        */
+       immr->im_ioport.iop_pcpar &= ~PC_ENET_LBK;
+       immr->im_ioport.iop_pcdir |= PC_ENET_LBK;
+       immr->im_ioport.iop_pcso &= ~PC_ENET_LBK;
+       immr->im_ioport.iop_pcdat &= ~PC_ENET_LBK;      /* Disable Loopback */
+#endif /* PC_ENET_LBK */
+
+       /* Configure port C pins to enable CLSN and RENA.
+        */
+       immr->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+       immr->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+       immr->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA);
+
+       /* Configure port A for TCLK and RCLK.
+        */
+       immr->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK);
+       immr->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
+
+       /*
+        * Configure Serial Interface clock routing -- see section 16.7.5.3
+        * First, clear all SCC bits to zero, then set the ones we want.
+        */
+
+       immr->im_cpm.cp_sicr &= ~SICR_ENET_MASK;
+       immr->im_cpm.cp_sicr |= SICR_ENET_CLKRT;
+#else
+       /*
+        * SCC2 receive clock is BRG2
+        * SCC2 transmit clock is BRG3
+        */
+       immr->im_cpm.cp_brgc2 = 0x0001000C;
+       immr->im_cpm.cp_brgc3 = 0x0001000C;
+
+       immr->im_cpm.cp_sicr &= ~0x00003F00;
+       immr->im_cpm.cp_sicr |=  0x00000a00;
+#endif /* 0 */
+
+
+       /*
+        * Initialize SDCR -- see section 16.9.23.7
+        * SDMA configuration register
+        */
+       immr->im_siu_conf.sc_sdcr = 0x01;
+
+
+       /*
+        * Setup SCC Ethernet Parameter RAM
+        */
+
+       pram_ptr->sen_genscc.scc_rfcr = 0x18;   /* Normal Operation and Mot byte ordering */
+       pram_ptr->sen_genscc.scc_tfcr = 0x18;   /* Mot byte ordering, Normal access */
+
+       pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH;   /* max. ET package len 1520 */
+
+       pram_ptr->sen_genscc.scc_rbase = (unsigned int) (&rtx->rxbd[0]);        /* Set RXBD tbl start at Dual Port */
+       pram_ptr->sen_genscc.scc_tbase = (unsigned int) (&rtx->txbd[0]);        /* Set TXBD tbl start at Dual Port */
+
+       /*
+        * Setup Receiver Buffer Descriptors (13.14.24.18)
+        * Settings:
+        *     Empty, Wrap
+        */
+
+       for (i = 0; i < PKTBUFSRX; i++) {
+               rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+               rtx->rxbd[i].cbd_datlen = 0;    /* Reset */
+               rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
+       }
+
+       rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+       /*
+        * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
+        * Settings:
+        *    Add PADs to Short FRAMES, Wrap, Last, Tx CRC
+        */
+
+       for (i = 0; i < TX_BUF_CNT; i++) {
+               rtx->txbd[i].cbd_sc =
+                               (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+               rtx->txbd[i].cbd_datlen = 0;    /* Reset */
+               rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
+       }
+
+       rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+       /*
+        * Enter Command:  Initialize Rx Params for SCC
+        */
+
+       do {                            /* Spin until ready to issue command    */
+               __asm__ ("eieio");
+       } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+       /* Issue command */
+       immr->im_cpm.cp_cpcr =
+                       ((CPM_CR_INIT_RX << 8) | (cpm_cr[scc_index] << 4) |
+                        CPM_CR_FLG);
+       do {                            /* Spin until command processed     */
+               __asm__ ("eieio");
+       } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+       /*
+        * Ethernet Specific Parameter RAM
+        *     see table 13-16, pg. 660,
+        *     pg. 681 (example with suggested settings)
+        */
+
+       pram_ptr->sen_cpres = ~(0x0);   /* Preset CRC */
+       pram_ptr->sen_cmask = 0xdebb20e3;       /* Constant Mask for CRC */
+       pram_ptr->sen_crcec = 0x0;      /* Error Counter CRC (unused) */
+       pram_ptr->sen_alec = 0x0;       /* Alignment Error Counter (unused) */
+       pram_ptr->sen_disfc = 0x0;      /* Discard Frame Counter (unused) */
+       pram_ptr->sen_pads = 0x8888;    /* Short Frame PAD Characters */
+
+       pram_ptr->sen_retlim = 15;      /* Retry Limit Threshold */
+       pram_ptr->sen_maxflr = 1518;    /* MAX Frame Length Register */
+       pram_ptr->sen_minflr = 64;      /* MIN Frame Length Register */
+
+       pram_ptr->sen_maxd1 = DBUF_LENGTH;      /* MAX DMA1 Length Register */
+       pram_ptr->sen_maxd2 = DBUF_LENGTH;      /* MAX DMA2 Length Register */
+
+       pram_ptr->sen_gaddr1 = 0x0;     /* Group Address Filter 1 (unused) */
+       pram_ptr->sen_gaddr2 = 0x0;     /* Group Address Filter 2 (unused) */
+       pram_ptr->sen_gaddr3 = 0x0;     /* Group Address Filter 3 (unused) */
+       pram_ptr->sen_gaddr4 = 0x0;     /* Group Address Filter 4 (unused) */
+
+#define ea bd->bi_enetaddr
+       pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
+       pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
+       pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+
+       pram_ptr->sen_pper = 0x0;       /* Persistence (unused) */
+       pram_ptr->sen_iaddr1 = 0x0;     /* Individual Address Filter 1 (unused) */
+       pram_ptr->sen_iaddr2 = 0x0;     /* Individual Address Filter 2 (unused) */
+       pram_ptr->sen_iaddr3 = 0x0;     /* Individual Address Filter 3 (unused) */
+       pram_ptr->sen_iaddr4 = 0x0;     /* Individual Address Filter 4 (unused) */
+       pram_ptr->sen_taddrh = 0x0;     /* Tmp Address (MSB) (unused) */
+       pram_ptr->sen_taddrm = 0x0;     /* Tmp Address (unused) */
+       pram_ptr->sen_taddrl = 0x0;     /* Tmp Address (LSB) (unused) */
+
+       /*
+        * Enter Command:  Initialize Tx Params for SCC
+        */
+
+       do {                            /* Spin until ready to issue command    */
+               __asm__ ("eieio");
+       } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+       /* Issue command */
+       immr->im_cpm.cp_cpcr =
+                       ((CPM_CR_INIT_TX << 8) | (cpm_cr[scc_index] << 4) |
+                        CPM_CR_FLG);
+       do {                            /* Spin until command processed     */
+               __asm__ ("eieio");
+       } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+       /*
+        * Mask all Events in SCCM - we use polling mode
+        */
+       immr->im_cpm.cp_scc[scc_index].scc_sccm = 0;
+
+       /*
+        * Clear Events in SCCE -- Clear bits by writing 1's
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_scce = ~(0x0);
+
+
+       /*
+        * Initialize GSMR High 32-Bits
+        * Settings:  Normal Mode
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_gsmrh = 0;
+
+       /*
+        * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive
+        * Settings:
+        *     TCI = Invert
+        *     TPL =  48 bits
+        *     TPP = Repeating 10's
+        *     LOOP = Loopback
+        *     MODE = Ethernet
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_gsmrl = (SCC_GSMRL_TCI |
+                                                                                               SCC_GSMRL_TPL_48 |
+                                                                                               SCC_GSMRL_TPP_10 |
+                                                                                               SCC_GSMRL_DIAG_LOOP |
+                                                                                               SCC_GSMRL_MODE_ENET);
+
+       /*
+        * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_dsr = 0xd555;
+
+       /*
+        * Initialize the PSMR
+        * Settings:
+        *  CRC = 32-Bit CCITT
+        *  NIB = Begin searching for SFD 22 bits after RENA
+        *  LPB = Loopback Enable (Needed when FDE is set)
+        */
+       immr->im_cpm.cp_scc[scc_index].scc_psmr = SCC_PSMR_ENCRC |
+                       SCC_PSMR_NIB22 | SCC_PSMR_LPB;
+
+#if 0
+       /*
+        * Configure Ethernet TENA Signal
+        */
+
+#if (defined(PC_ENET_TENA) && !defined(PB_ENET_TENA))
+       immr->im_ioport.iop_pcpar |= PC_ENET_TENA;
+       immr->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
+#elif (defined(PB_ENET_TENA) && !defined(PC_ENET_TENA))
+       immr->im_cpm.cp_pbpar |= PB_ENET_TENA;
+       immr->im_cpm.cp_pbdir |= PB_ENET_TENA;
+#else
+#error Configuration Error: exactly ONE of PB_ENET_TENA, PC_ENET_TENA must be defined
+#endif
+
+#if defined(CONFIG_ADS) && defined(CONFIG_MPC860)
+       /*
+        * Port C is used to control the PHY,MC68160.
+        */
+       immr->im_ioport.iop_pcdir |=
+                       (PC_ENET_ETHLOOP | PC_ENET_TPFLDL | PC_ENET_TPSQEL);
+
+       immr->im_ioport.iop_pcdat |= PC_ENET_TPFLDL;
+       immr->im_ioport.iop_pcdat &= ~(PC_ENET_ETHLOOP | PC_ENET_TPSQEL);
+       *((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#endif /* MPC860ADS */
+
+#if defined(CONFIG_AMX860)
+       /*
+        * Port B is used to control the PHY,MC68160.
+        */
+       immr->im_cpm.cp_pbdir |=
+                       (PB_ENET_ETHLOOP | PB_ENET_TPFLDL | PB_ENET_TPSQEL);
+
+       immr->im_cpm.cp_pbdat |= PB_ENET_TPFLDL;
+       immr->im_cpm.cp_pbdat &= ~(PB_ENET_ETHLOOP | PB_ENET_TPSQEL);
+
+       immr->im_ioport.iop_pddir |= PD_ENET_ETH_EN;
+       immr->im_ioport.iop_pddat &= ~PD_ENET_ETH_EN;
+#endif /* AMX860 */
+
+#endif /* 0 */
+
+#ifdef CONFIG_RPXCLASSIC
+       *((uchar *) BCSR0) &= ~BCSR0_ETHLPBK;
+       *((uchar *) BCSR0) |= (BCSR0_ETHEN | BCSR0_COLTEST | BCSR0_FULLDPLX);
+#endif
+
+#ifdef CONFIG_RPXLITE
+       *((uchar *) BCSR0) |= BCSR0_ETHEN;
+#endif
+
+#ifdef CONFIG_MBX
+       board_ether_init ();
+#endif
+
+       /*
+        * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_gsmrl |=
+                       (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+       /*
+        * Work around transmit problem with first eth packet
+        */
+#if defined (CONFIG_FADS)
+       udelay (10000);                         /* wait 10 ms */
+#elif defined (CONFIG_AMX860) || defined(CONFIG_RPXCLASSIC)
+       udelay (100000);                        /* wait 100 ms */
+#endif
+}
+
+static int scc_send (int index, volatile void *packet, int length)
+{
+       int i, j = 0;
+
+       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) {
+               udelay (1);             /* will also trigger Wd if needed */
+               j++;
+       }
+       if (j >= TOUT_LOOP)
+               printf ("TX not ready\n");
+       rtx->txbd[txIdx].cbd_bufaddr = (uint) packet;
+       rtx->txbd[txIdx].cbd_datlen = length;
+       rtx->txbd[txIdx].cbd_sc |=
+                       (BD_ENET_TX_READY | BD_ENET_TX_LAST | BD_ENET_TX_WRAP);
+       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) {
+               udelay (1);             /* will also trigger Wd if needed */
+               j++;
+       }
+       if (j >= TOUT_LOOP)
+               printf ("TX timeout\n");
+       i = (rtx->txbd[txIdx].
+                cbd_sc & BD_ENET_TX_STATS) /* return only status bits */ ;
+       return i;
+}
+
+static int scc_recv (int index, void *packet, int max_length)
+{
+       int length = -1;
+
+       if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+               goto Done;              /* nothing received */
+       }
+
+       if (!(rtx->rxbd[rxIdx].cbd_sc & 0x003f)) {
+               length = rtx->rxbd[rxIdx].cbd_datlen - 4;
+               memcpy (packet,
+                               (void *) (NetRxPackets[rxIdx]),
+                               length < max_length ? length : max_length);
+       }
+
+       /* Give the buffer back to the SCC. */
+       rtx->rxbd[rxIdx].cbd_datlen = 0;
+
+       /* wrap around buffer index when necessary */
+       if ((rxIdx + 1) >= PKTBUFSRX) {
+               rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
+                               (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+               rxIdx = 0;
+       } else {
+               rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+               rxIdx++;
+       }
+
+  Done:
+       return length;
+}
+
+  /*
+   * Test routines
+   */
+
+static void packet_fill (char *packet, int length)
+{
+       char c = (char) length;
+       int i;
+
+       packet[0] = 0xFF;
+       packet[1] = 0xFF;
+       packet[2] = 0xFF;
+       packet[3] = 0xFF;
+       packet[4] = 0xFF;
+       packet[5] = 0xFF;
+
+       for (i = 6; i < length; i++) {
+               packet[i] = c++;
+       }
+}
+
+static int packet_check (char *packet, int length)
+{
+       char c = (char) length;
+       int i;
+
+       for (i = 6; i < length; i++) {
+               if (packet[i] != c++)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int test_ctlr (int ctlr, int index)
+{
+       int res = -1;
+       char packet_send[MAX_PACKET_LENGTH];
+       char packet_recv[MAX_PACKET_LENGTH];
+       int length;
+       int i;
+       int l;
+
+       ctlr_proc[ctlr].init (index);
+
+       for (i = 0; i < TEST_NUM; i++) {
+               for (l = MIN_PACKET_LENGTH; l <= MAX_PACKET_LENGTH; l++) {
+                       packet_fill (packet_send, l);
+
+                       ctlr_proc[ctlr].send (index, packet_send, l);
+
+                       length = ctlr_proc[ctlr].recv (index, packet_recv,
+                                                       MAX_PACKET_LENGTH);
+
+                       if (length != l || packet_check (packet_recv, length) < 0) {
+                               goto Done;
+                       }
+               }
+       }
+
+       res = 0;
+
+  Done:
+
+#if !defined(CONFIG_8xx_CONS_NONE)
+       if (used_by_uart[ctlr] == index) {
+               serial_init ();
+       }
+#endif
+
+#if defined(SCC_ENET)
+       if (used_by_ether[ctlr] == index) {
+               DECLARE_GLOBAL_DATA_PTR;
+
+               eth_init (gd->bd);
+       }
+#endif
+
+       /*
+        * SCC2 Ethernet parameter RAM space overlaps
+        * the SPI parameter RAM space. So we need to restore
+        * the SPI configuration after SCC2 ethernet test.
+        */
+#if defined(CONFIG_SPI)
+       if (ctlr == CTLR_SCC && index == 1) {
+               spi_init_f ();
+               spi_init_r ();
+       }
+#endif
+
+       if (res != 0) {
+               post_log ("ethernet %s%d test failed\n", ctlr_name[ctlr],
+                                 index + 1);
+       }
+
+       return res;
+}
+
+int ether_post_test (int flags)
+{
+       int res = 0;
+       int i;
+
+#if defined(CONFIG_8xx_CONS_SCC1)
+       used_by_uart[CTLR_SCC] = 0;
+#elif defined(CONFIG_8xx_CONS_SCC2)
+       used_by_uart[CTLR_SCC] = 1;
+#elif defined(CONFIG_8xx_CONS_SCC3)
+       used_by_uart[CTLR_SCC] = 2;
+#elif defined(CONFIG_8xx_CONS_SCC4)
+       used_by_uart[CTLR_SCC] = 3;
+#endif
+
+#if defined(SCC_ENET)
+       used_by_ether[CTLR_SCC] = SCC_ENET;
+#endif
+
+       ctlr_proc[CTLR_SCC].init = scc_init;
+       ctlr_proc[CTLR_SCC].send = scc_send;
+       ctlr_proc[CTLR_SCC].recv = scc_recv;
+
+       for (i = 0; i < CTRL_LIST_SIZE; i++) {
+               if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) {
+                       res = -1;
+               }
+       }
+
+       return res;
+}
+
+#endif /* CONFIG_POST & CFG_POST_ETHER */
+
+#endif /* CONFIG_POST */
diff --git a/post/memory.c b/post/memory.c
new file mode 100644 (file)
index 0000000..7d55a6d
--- /dev/null
@@ -0,0 +1,481 @@
+/*
+ * (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 <common.h>
+
+/* Memory test
+ *
+ * General observations:
+ * o The recommended test sequence is to test the data lines: if they are
+ *   broken, nothing else will work properly.  Then test the address
+ *   lines.  Finally, test the cells in the memory now that the test
+ *   program knows that the address and data lines work properly.
+ *   This sequence also helps isolate and identify what is faulty.
+ *
+ * o For the address line test, it is a good idea to use the base
+ *   address of the lowest memory location, which causes a '1' bit to
+ *   walk through a field of zeros on the address lines and the highest
+ *   memory location, which causes a '0' bit to walk through a field of
+ *   '1's on the address line.
+ *
+ * o Floating buses can fool memory tests if the test routine writes
+ *   a value and then reads it back immediately.  The problem is, the
+ *   write will charge the residual capacitance on the data bus so the
+ *   bus retains its state briefely.  When the test program reads the
+ *   value back immediately, the capacitance of the bus can allow it
+ *   to read back what was written, even though the memory circuitry
+ *   is broken.  To avoid this, the test program should write a test
+ *   pattern to the target location, write a different pattern elsewhere
+ *   to charge the residual capacitance in a differnt manner, then read
+ *   the target location back.
+ *
+ * o Always read the target location EXACTLY ONCE and save it in a local
+ *   variable.  The problem with reading the target location more than
+ *   once is that the second and subsequent reads may work properly,
+ *   resulting in a failed test that tells the poor technician that
+ *   "Memory error at 00000000, wrote aaaaaaaa, read aaaaaaaa" which
+ *   doesn't help him one bit and causes puzzled phone calls.  Been there,
+ *   done that.
+ *
+ * Data line test:
+ * ---------------
+ * This tests data lines for shorts and opens by forcing adjacent data
+ * to opposite states. Because the data lines could be routed in an
+ * arbitrary manner the must ensure test patterns ensure that every case
+ * is tested. By using the following series of binary patterns every
+ * combination of adjacent bits is test regardless of routing.
+ *
+ *     ...101010101010101010101010
+ *     ...110011001100110011001100
+ *     ...111100001111000011110000
+ *     ...111111110000000011111111
+ *
+ * Carrying this out, gives us six hex patterns as follows:
+ *
+ *     0xaaaaaaaaaaaaaaaa
+ *     0xcccccccccccccccc
+ *     0xf0f0f0f0f0f0f0f0
+ *     0xff00ff00ff00ff00
+ *     0xffff0000ffff0000
+ *     0xffffffff00000000
+ *
+ * To test for short and opens to other signals on our boards, we
+ * simply test with the 1's complemnt of the paterns as well, resulting
+ * in twelve patterns total.
+ *
+ * After writing a test pattern. a special pattern 0x0123456789ABCDEF is
+ * written to a different address in case the data lines are floating.
+ * Thus, if a byte lane fails, you will see part of the special
+ * pattern in that byte lane when the test runs.  For example, if the
+ * xx__xxxxxxxxxxxx byte line fails, you will see aa23aaaaaaaaaaaa
+ * (for the 'a' test pattern).
+ *
+ * Address line test:
+ * ------------------
+ *  This function performs a test to verify that all the address lines
+ *  hooked up to the RAM work properly.  If there is an address line
+ *  fault, it usually shows up as two different locations in the address
+ *  map (related by the faulty address line) mapping to one physical
+ *  memory storage location.  The artifact that shows up is writing to
+ *  the first location "changes" the second location.
+ *
+ * To test all address lines, we start with the given base address and
+ * xor the address with a '1' bit to flip one address line.  For each
+ * test, we shift the '1' bit left to test the next address line.
+ *
+ * In the actual code, we start with address sizeof(ulong) since our
+ * test pattern we use is a ulong and thus, if we tried to test lower
+ * order address bits, it wouldn't work because our pattern would
+ * overwrite itself.
+ *
+ * Example for a 4 bit address space with the base at 0000:
+ *   0000 <- base
+ *   0001 <- test 1
+ *   0010 <- test 2
+ *   0100 <- test 3
+ *   1000 <- test 4
+ * Example for a 4 bit address space with the base at 0010:
+ *   0010 <- base
+ *   0011 <- test 1
+ *   0000 <- (below the base address, skipped)
+ *   0110 <- test 2
+ *   1010 <- test 3
+ *
+ * The test locations are successively tested to make sure that they are
+ * not "mirrored" onto the base address due to a faulty address line.
+ * Note that the base and each test location are related by one address
+ * line flipped.  Note that the base address need not be all zeros.
+ *
+ * Memory tests 1-4:
+ * -----------------
+ * These tests verify RAM using sequential writes and reads
+ * to/from RAM. There are several test cases that use different patterns to
+ * verify RAM. Each test case fills a region of RAM with one pattern and
+ * then reads the region back and compares its contents with the pattern.
+ * The following patterns are used:
+ *
+ *  1a) zero pattern (0x00000000)
+ *  1b) negative pattern (0xffffffff)
+ *  1c) checkerboard pattern (0x55555555)
+ *  1d) checkerboard pattern (0xaaaaaaaa)
+ *  2)  bit-flip pattern ((1 << (offset % 32))
+ *  3)  address pattern (offset)
+ *  4)  address pattern (~offset)
+ *
+ * Being run in normal mode, the test verifies only small 4Kb
+ * regions of RAM around each 1Mb boundary. For example, for 64Mb
+ * RAM the following areas are verified: 0x00000000-0x00000800,
+ * 0x000ff800-0x00100800, 0x001ff800-0x00200800, ..., 0x03fff800-
+ * 0x04000000. If the test is run in power-fail mode, it verifies
+ * the whole RAM.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include <watchdog.h>
+
+#if CONFIG_POST & CFG_POST_MEMORY
+
+/*
+ * Define INJECT_*_ERRORS for testing error detection in the presence of
+ * _good_ hardware.
+ */
+#undef  INJECT_DATA_ERRORS
+#undef  INJECT_ADDRESS_ERRORS
+
+#ifdef INJECT_DATA_ERRORS
+#warning "Injecting data line errors for testing purposes"
+#endif
+
+#ifdef INJECT_ADDRESS_ERRORS
+#warning "Injecting address line errors for testing purposes"
+#endif
+
+
+/*
+ * This function performs a double word move from the data at
+ * the source pointer to the location at the destination pointer.
+ * This is helpful for testing memory on processors which have a 64 bit
+ * wide data bus.
+ *
+ * On those PowerPC with FPU, use assembly and a floating point move:
+ * this does a 64 bit move.
+ *
+ * For other processors, let the compiler generate the best code it can.
+ */
+static void move64(unsigned long long *src, unsigned long long *dest)
+{
+#if defined(CONFIG_MPC8260) || defined(CONFIG_MPC824X)
+       asm ("lfd  0, 0(3)\n\t" /* fpr0   =  *scr       */
+        "stfd 0, 0(4)"         /* *dest  =  fpr0       */
+        : : : "fr0" );         /* Clobbers fr0         */
+    return;
+#else
+       *dest = *src;
+#endif
+}
+
+/*
+ * This is 64 bit wide test patterns.  Note that they reside in ROM
+ * (which presumably works) and the tests write them to RAM which may
+ * not work.
+ *
+ * The "otherpattern" is written to drive the data bus to values other
+ * than the test pattern.  This is for detecting floating bus lines.
+ *
+ */
+const static unsigned long long pattern[] = {
+    0xaaaaaaaaaaaaaaaa,
+    0xcccccccccccccccc,
+    0xf0f0f0f0f0f0f0f0,
+    0xff00ff00ff00ff00,
+    0xffff0000ffff0000,
+    0xffffffff00000000,
+    0x00000000ffffffff,
+    0x0000ffff0000ffff,
+    0x00ff00ff00ff00ff,
+    0x0f0f0f0f0f0f0f0f,
+    0x3333333333333333,
+    0x5555555555555555};
+const unsigned long long otherpattern = 0x0123456789abcdef;
+
+
+static int memory_post_dataline(unsigned long long * pmem)
+{
+       unsigned long long temp64;
+       int num_patterns = sizeof(pattern)/ sizeof(pattern[0]);
+       int i;
+       unsigned int hi, lo, pathi, patlo;
+       int ret = 0;
+
+       for ( i = 0; i < num_patterns; i++) {
+               move64((unsigned long long *)&(pattern[i]), pmem++);
+               /*
+                * Put a different pattern on the data lines: otherwise they
+                * may float long enough to read back what we wrote.
+                */
+               move64((unsigned long long *)&otherpattern, pmem--);
+               move64(pmem, &temp64);
+
+#ifdef INJECT_DATA_ERRORS
+               temp64 ^= 0x00008000;
+#endif
+
+               if (temp64 != pattern[i]){
+                       pathi = (pattern[i]>>32) & 0xffffffff;
+                       patlo = pattern[i] & 0xffffffff;
+
+                       hi = (temp64>>32) & 0xffffffff;
+                       lo = temp64 & 0xffffffff;
+
+                       post_log ("Memory (date line) error at %08x, "
+                                 "wrote %08x%08x, read %08x%08x !\n",
+                                         pmem, pathi, patlo, hi, lo);
+                       ret = -1;
+               }
+       }
+       return ret;
+}
+
+static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size)
+{
+       ulong *target;
+       ulong *end;
+       ulong readback;
+       ulong xor;
+       int   ret = 0;
+
+       end = base + size;
+       xor = 0;
+       for(xor = sizeof(ulong); xor > 0; xor <<= 1) {
+               target = (ulong *)((ulong)testaddr ^ xor);
+               if((target >= base) && (target < end)) {
+                       *testaddr = ~*target;
+                       readback  = *target;
+
+#ifdef INJECT_ADDRESS_ERRORS
+                       if(xor == 0x00008000) {
+                               readback = *testaddr;
+                       }
+#endif
+                       if(readback == *testaddr) {
+                               post_log ("Memory (address line) error at %08x<->%08x, "
+                                       "XOR value %08x !\n",
+                                       testaddr, target, xor);
+                               ret = -1;
+                       }
+               }
+       }
+       return ret;
+}
+
+static int memory_post_test1 (unsigned long start,
+                             unsigned long size,
+                             unsigned long val)
+{
+       unsigned long i;
+       ulong *mem = (ulong *) start;
+       ulong readback;
+       int ret = 0;
+
+       for (i = 0; i < size / sizeof (ulong); i++) {
+               mem[i] = val;
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+               readback = mem[i];
+               if (readback != val) {
+                       post_log ("Memory error at %08x, "
+                                 "wrote %08x, read %08x !\n",
+                                         mem + i, val, readback);
+
+                       ret = -1;
+                       break;
+               }
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       return ret;
+}
+
+static int memory_post_test2 (unsigned long start, unsigned long size)
+{
+       unsigned long i;
+       ulong *mem = (ulong *) start;
+       ulong readback;
+       int ret = 0;
+
+       for (i = 0; i < size / sizeof (ulong); i++) {
+               mem[i] = 1 << (i % 32);
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+               readback = mem[i];
+               if (readback != (1 << (i % 32))) {
+                       post_log ("Memory error at %08x, "
+                                 "wrote %08x, read %08x !\n",
+                                         mem + i, 1 << (i % 32), readback);
+
+                       ret = -1;
+                       break;
+               }
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       return ret;
+}
+
+static int memory_post_test3 (unsigned long start, unsigned long size)
+{
+       unsigned long i;
+       ulong *mem = (ulong *) start;
+       ulong readback;
+       int ret = 0;
+
+       for (i = 0; i < size / sizeof (ulong); i++) {
+               mem[i] = i;
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+               readback = mem[i];
+               if (readback != i) {
+                       post_log ("Memory error at %08x, "
+                                 "wrote %08x, read %08x !\n",
+                                         mem + i, i, readback);
+
+                       ret = -1;
+                       break;
+               }
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       return ret;
+}
+
+static int memory_post_test4 (unsigned long start, unsigned long size)
+{
+       unsigned long i;
+       ulong *mem = (ulong *) start;
+       ulong readback;
+       int ret = 0;
+
+       for (i = 0; i < size / sizeof (ulong); i++) {
+               mem[i] = ~i;
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+               readback = mem[i];
+               if (readback != ~i) {
+                       post_log ("Memory error at %08x, "
+                                 "wrote %08x, read %08x !\n",
+                                         mem + i, ~i, readback);
+
+                       ret = -1;
+                       break;
+               }
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       return ret;
+}
+
+static int memory_post_tests (unsigned long start, unsigned long size)
+{
+       int ret = 0;
+
+       if (ret == 0)
+               ret = memory_post_dataline ((long long *)start);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_addrline ((long *)start, (long *)start, size);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_addrline ((long *)(start + size - 8),
+                                           (long *)start, size);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test1 (start, size, 0x00000000);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test1 (start, size, 0xffffffff);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test1 (start, size, 0x55555555);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test1 (start, size, 0xaaaaaaaa);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test2 (start, size);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test3 (start, size);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test4 (start, size);
+       WATCHDOG_RESET ();
+
+       return ret;
+}
+
+int memory_post_test (int flags)
+{
+       int ret = 0;
+       DECLARE_GLOBAL_DATA_PTR;
+       bd_t *bd = gd->bd;
+       unsigned long memsize = (bd->bi_memsize >= 256 << 20 ?
+                                256 << 20 : bd->bi_memsize) - (1 << 20);
+
+
+       if (flags & POST_POWERFAIL) {
+               ret = memory_post_tests (CFG_SDRAM_BASE, memsize);
+       } else {                        /* POST_POWERNORMAL */
+
+               unsigned long i;
+
+               for (i = 0; i < (memsize >> 20) && ret == 0; i++) {
+                       if (ret == 0)
+                               ret = memory_post_tests (i << 20, 0x800);
+                       if (ret == 0)
+                               ret = memory_post_tests ((i << 20) + 0xff800, 0x800);
+               }
+       }
+
+       return ret;
+}
+
+#endif /* CONFIG_POST & CFG_POST_MEMORY */
+#endif /* CONFIG_POST */
diff --git a/rtc/ds1556.c b/rtc/ds1556.c
new file mode 100644 (file)
index 0000000..dd9ea5e
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * (C) Copyright 2002
+ * ARIO Data Networks, Inc. dchiu@ariodata.com
+ *
+ * modified for DS1556:
+ * Frank Panno <fpanno@delphintech.com>, Delphin Technology AG
+ *
+ * Based on MontaVista DS1743 code and U-Boot mc146818 code
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for the DS1556 RTC
+ */
+
+/*#define      RTC_DEBUG */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+
+#if defined(CONFIG_RTC_DS1556) && (CONFIG_COMMANDS & CFG_CMD_DATE)
+
+static uchar rtc_read( unsigned int addr );
+static void  rtc_write( unsigned int addr, uchar val);
+static uchar bin2bcd   (unsigned int n);
+static unsigned bcd2bin(uchar c);
+
+#define RTC_BASE               ( CFG_NVRAM_SIZE + CFG_NVRAM_BASE_ADDR )
+
+#define RTC_YEAR               ( RTC_BASE + 0xf )
+#define RTC_MONTH              ( RTC_BASE + 0xe )
+#define RTC_DAY_OF_MONTH       ( RTC_BASE + 0xd )
+#define RTC_DAY_OF_WEEK                ( RTC_BASE + 0xc )
+#define RTC_HOURS              ( RTC_BASE + 0xb )
+#define RTC_MINUTES            ( RTC_BASE + 0xa )
+#define RTC_SECONDS            ( RTC_BASE + 0x9 )
+#define RTC_CENTURY            ( RTC_BASE + 0x8 )
+
+#define RTC_CONTROLA           RTC_CENTURY
+#define RTC_CONTROLB           RTC_SECONDS
+#define RTC_CONTROLC           RTC_BASE
+
+#define RTC_CA_WRITE           0x80
+#define RTC_CA_READ            0x40
+
+#define RTC_CB_OSC_DISABLE     0x80
+
+#define RTC_CC_BATTERY_FLAG    0x10
+#define RTC_CC_FREQ_TEST       0x40
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get( struct rtc_time *tmp )
+{
+       uchar sec, min, hour;
+       uchar mday, wday, mon, year;
+
+       int century;
+
+       uchar reg_a;
+
+       reg_a = rtc_read( RTC_CONTROLA );
+       /* lock clock registers for read */
+       rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ ));
+
+       sec     = rtc_read( RTC_SECONDS );
+       min     = rtc_read( RTC_MINUTES );
+       hour    = rtc_read( RTC_HOURS );
+       mday    = rtc_read( RTC_DAY_OF_MONTH );
+       wday    = rtc_read( RTC_DAY_OF_WEEK );
+       mon     = rtc_read( RTC_MONTH );
+       year    = rtc_read( RTC_YEAR );
+       century = rtc_read( RTC_CENTURY );
+
+       /* unlock clock registers after read */
+       rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ ));
+
+#ifdef RTC_DEBUG
+       printf( "Get RTC year: %02x mon/cent: %02x mon: %02x mday: %02x wday: %02x "
+               "hr: %02x min: %02x sec: %02x\n",
+               year, century, mon, mday, wday,
+               hour, min, sec );
+#endif
+       tmp->tm_sec  = bcd2bin( sec  & 0x7F );
+       tmp->tm_min  = bcd2bin( min  & 0x7F );
+       tmp->tm_hour = bcd2bin( hour & 0x3F );
+       tmp->tm_mday = bcd2bin( mday & 0x3F );
+       tmp->tm_mon  = bcd2bin( mon & 0x1F );
+       tmp->tm_wday = bcd2bin( wday & 0x07 );
+
+       /* glue year from century and year in century */
+       tmp->tm_year = bcd2bin( year ) +
+               ( bcd2bin( century & 0x3F ) * 100 );
+
+       tmp->tm_yday = 0;
+       tmp->tm_isdst= 0;
+#ifdef RTC_DEBUG
+       printf( "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+               tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+               tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
+#endif
+}
+
+void rtc_set( struct rtc_time *tmp )
+{
+       uchar reg_a;
+#ifdef RTC_DEBUG
+       printf( "Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+               tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+               tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+#endif
+       /* lock clock registers for write */
+       reg_a = rtc_read( RTC_CONTROLA );
+       rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE ));
+
+       rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon ));
+
+       rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday ));
+       rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday ));
+       rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour ));
+       rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min ));
+       rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec ));
+
+       /* break year up into century and year in century */
+       rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 ));
+       rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 ));
+
+       /* unlock clock registers after read */
+       rtc_write( RTC_CONTROLA, ( reg_a  & ~RTC_CA_WRITE ));
+}
+
+void rtc_reset (void)
+{
+       uchar reg_a, reg_b, reg_c;
+
+       reg_a = rtc_read( RTC_CONTROLA );
+       reg_b = rtc_read( RTC_CONTROLB );
+
+       if ( reg_b & RTC_CB_OSC_DISABLE )
+       {
+               printf( "real-time-clock was stopped. Now starting...\n" );
+               reg_a |= RTC_CA_WRITE;
+               reg_b &= ~RTC_CB_OSC_DISABLE;
+
+               rtc_write( RTC_CONTROLA, reg_a );
+               rtc_write( RTC_CONTROLB, reg_b );
+       }
+
+       /* make sure read/write clock register bits are cleared */
+       reg_a &= ~( RTC_CA_WRITE | RTC_CA_READ );
+       rtc_write( RTC_CONTROLA, reg_a );
+
+       reg_c = rtc_read( RTC_CONTROLC );
+       if (( reg_c & RTC_CC_BATTERY_FLAG ) == 0 )
+               printf( "RTC battery low. Clock setting may not be reliable.\n" );
+}
+
+/* ------------------------------------------------------------------------- */
+
+static uchar rtc_read( unsigned int addr )
+{
+       uchar val = *(volatile unsigned char*)(addr);
+#ifdef RTC_DEBUG
+       printf( "rtc_read: %x:%x\n", addr, val );
+#endif
+       return( val );
+}
+
+static void rtc_write( unsigned int addr, uchar val )
+{
+#ifdef RTC_DEBUG
+       printf( "rtc_write: %x:%x\n", addr, val );
+#endif
+       *(volatile unsigned char*)(addr) = val;
+}
+
+static unsigned bcd2bin (uchar n)
+{
+       return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
+}
+
+static unsigned char bin2bcd (unsigned int n)
+{
+       return (((n / 10) << 4) | (n % 10));
+}
+
+#endif /* CONFIG_RTC_DS1556 && CFG_CMD_DATE */