import u-boot-1.1.4-list-2.1.0.diff linkstation
authorDobrica Pavlinusic <dpavlin@brr.lan>
Wed, 25 Jul 2007 07:36:34 +0000 (02:36 -0500)
committerDobrica Pavlinusic <dpavlin@brr.lan>
Wed, 25 Jul 2007 07:36:34 +0000 (02:36 -0500)
14 files changed:
board/linkstation/INSTALL [new file with mode: 0644]
board/linkstation/Makefile [new file with mode: 0644]
board/linkstation/avr.c [new file with mode: 0644]
board/linkstation/bootls.c [new file with mode: 0644]
board/linkstation/config.mk [new file with mode: 0644]
board/linkstation/early_init.S [new file with mode: 0644]
board/linkstation/firminfo.h [new file with mode: 0644]
board/linkstation/flash.c [new file with mode: 0644]
board/linkstation/hwctl.c [new file with mode: 0644]
board/linkstation/ide.c [new file with mode: 0644]
board/linkstation/linkstation.c [new file with mode: 0644]
board/linkstation/nc.sh [new file with mode: 0644]
board/linkstation/u-boot.lds [new file with mode: 0644]
include/configs/linkstation.h [new file with mode: 0644]

diff --git a/board/linkstation/INSTALL b/board/linkstation/INSTALL
new file mode 100644 (file)
index 0000000..38f5917
--- /dev/null
@@ -0,0 +1,631 @@
+
+                     Installing U-Boot for LinkStation
+
+                       For U-Boot port version 2.1.0
+                             16 September 2006
+
+   Copyright (c) 2006 Mihai Georgian
+
+   Permission is granted to copy, distribute and/or modify this document under
+   the terms of the [1]GNU Free Documentation License, Version 1.2 or any later
+   version  published  by the Free Software Foundation; with no Invariant
+   Sections, no Front-Cover Texts, and no Back-Cover Texts. The full text of
+   the license can be obtained by clicking on the above link.
+
+   No  liability  for  the contents of this document can be accepted. The
+   information in this document is provided in good faith but no warranty can
+   be made for its accuracy and the author does not take any responsibility.
+   Use the concepts, examples and information at your own risk. There may be
+   errors and inaccuracies, that could be damaging to your system.
+
+   Use of a term in this document should not be regarded as affecting the
+   validity of any trademark or service mark. Naming of particular products or
+   brands should not be seen as endorsements.
+     _________________________________________________________________
+
+   WARNING
+
+   Flashing the LinkStation with unauthorised firmare voids your warranty. When
+   installing firmware on an embedded computer things can and, sometimes, do go
+   wrong. The power can go down in the middle of the flash operation or the
+   flash write can fail rendering your LinkStation unusable. Please read this
+   entire page carefully before attempting to install U-Boot. 
+
+   If you are not prepared to lose your LinkStation, do not attempt to install
+                                     U-Boot 
+
+  Introduction
+
+   U-Boot  for  the  LinkStation is distributed as a source patch against
+   u-boot-1.1.4. To compile it you will need either a cross toolchain installed
+   on your PC or native development tools installed on your LinkStation. These
+   instructions assume that you are running Linux on a X86 PC and that you are
+   using a cross toolchain.
+
+   To allow testing of U-Boot on your LinkStation without burning it into
+   flash, a kernel module named uloader.o is provided. Uloader allows you to
+   use Linux to load a RAM build of U-Boot and start it. The RAM build of
+   U-Boot is very close to the ROM build. The only differences are the absence
+   of the basic initialisation code (which cannot run from RAM) and the link
+   address. It is strongly recommended that you test U-Boot on your LinkStation
+   using a RAM build before building the ROM version and attempting to burn it
+   into flash. Once you have the RAM build up and running you can use it to
+   install (burn) the ROM version.
+
+  Supported Hardware
+
+   The LinkStation port of U-Boot described in this document supports the
+   following PowerPC based models:
+    1. LinkStation version 1 (model HD-HLAN-1)
+    2. KuroBox standard
+    3. LinkStation HG (model HD-HGLAN)
+    4. KuroBox HG
+
+   This version of U-Boot will certainly not work on the the LinkStation
+   version 2 (model HD-HLAN-2) as the LinkStation version 2 is based on a MIPS
+   processor. The MIPS processor is completely different from the PowerPC
+   processor and attempting to flash a LinkStation version 2 with PowerPC
+      firmware it is guaranteed to make it completely unusable. 
+
+  Get telnet Access
+
+   Try to connect to your LinkStation using telnet. If you see the telnet
+   command prompt, read [2]CGI Exploit (PowerPC) original method of Hacking the
+   LinkStation about how to get telnet access.
+
+   If the above method doesn't work for you, read [3]Turn your LinkStation into
+   a Kuro Box (PowerPC) for other methods to get telnet access.
+
+   The above methods do not work for the LinkStation HG. For this model, the
+   only solution is to load a telnet-enabled version of the firmware. Read the
+   pages about [4]OpenLink and the [5]firmware flasher
+
+   You can also try to flash [6]a modified version of the original firmware.
+
+  Install the Serial Console
+
+   Installing the serial console is not an absolute requirement and it will
+   void your warranty. U-Boot can be installed and controlled without it.
+   However, the serial console will give you the best control over both U-Boot
+                                   and Linux. 
+
+   Read [7]Add a Serial port to the PowerPC Linkstation to learn how to install
+   the serial console.
+
+  Install netcat (nc)
+
+   If you haven't installed the serial console you will need to install netcat
+   (nc). Netcat is a networking utility which reads and writes data across
+   network connections, using the TCP/IP protocol. It comes standard with most
+   Linux  distributions. For more information, visit the netcat home page
+   [8]http://netcat.sourceforge.net or [9]http://www.vulnwatch.org/netcat for
+   the Windows version.
+
+  Get the ELDK
+
+   If you don't have a cross toolchain installed, download the DENX Embedded
+   Linux Development Kit (ELDK) from
+   [10]http://ftp.sunet.se/pub/Linux/distributions/eldk/3.1.1/ppc-linux-x86/iso
+   /ppc-2005-03-07.iso, install it and spend some time getting familiar with
+   it.
+
+  Preparation
+
+   Create the build directory and set the environment variable UBOOT_BUILD to
+   the path to it
+   # mkdir <your_build_directory>
+   # export UBOOT_BUILD=<your_build_directory>
+   # cd $UBOOT_BUILD
+   Download the tarball for u-boot-1.1.4 from
+   [11]ftp://ftp.denx.de/pub/u-boot/u-boot-1.1.4.tar.bz2
+   Download the LinkStation patch, [12]u-boot-1.1.4-list-2.1.0.diff.gz 
+   Download the uloader module for your LinkStation / KuroBox model.
+     * For    the    LinkStation   1   /   KuroBox   standard,   download
+       [13]uloader-2.4.17.tar.gz 
+     * For the LinkStation HG / KuroBox HG, download [14]uloader-2.4.20.tar.gz 
+
+   Untar u-boot-1.1.4 and apply the patch.
+   # tar xjf u-boot-1.1.4.tar.bz2
+   # cd u-boot-1.1.4
+   # gunzip ../u-boot-1.1.4-list-2.01.diff.gz | patch -p1
+
+   Untar the uloader archive for your LinkStation / KuroBox model. The archive
+   contains  the  source  code, a binary module compiled for the original
+   LinkStation kernel and a simple bash script to load and start a RAM build of
+   U-Boot.
+
+   The binary in uloader-2.4.17.tar.gz has been compiled against
+   2.4.17_mvl21-sandpoint. Use only on the LinkStation 1 / KuroBox standard.
+   The binary in uloader-2.4.20.tar.gz has been compiled against
+   2.4.20_mvl31-ppc_linkstation. Use only on the LinkStation HG / KuroBog HG.
+   If you have a different kernel version, you may need to recompile the module
+   for your kernel. Compiling the module requires a fully configured kernel
+   source tree. It is recommended to use the same gcc version as the one used
+   to compile the kernel. There is a small but important difference between the
+   two uloader source archives. The difference is the U-Boot load address. If
+   you compile uloader for the LinkStation 1 / KuroBox standard, use the
+   sources in uloader-2.4.17.tar.gz. If you compile for the LinkStation HG /
+   KuroBox HG, use the sources in uloader-2.4.20.tar.gz. In both cases you
+   need to modify the Makefile to match your development environment. 
+
+   LinkStation 1 / KuroBox standard
+   # cd ..
+   # tar xzf uloader-2.4.17.tar.gz
+   # cd u-boot-1.1.4
+
+   LinkStation HG / KuroBox HG
+   # cd ..
+   # tar xzf uloader-2.4.20.tar.gz
+   # cd u-boot-1.1.4
+
+   Source your ELDK environment
+   # . <path_to_your_ELDK>/config_6xx
+
+  Configure
+
+   Edit include/configs/linkstation.h and set the following variables for your
+   environment:
+
+   CONFIG_IPADDR_LS    -  the IP address of your LinkStation while running
+                          U-Boot (mandatory). The default address is
+                          192.168.11.150.
+   CONFIG_SERVERIP_LS  -  the IP address of the NFS/TFTP/DHCP/BOOTP server,
+                          normally the address of your Linux PC (mandatory).
+                          The default address is 192.168.11.149.
+   CONFIG_NCIP_LS      -  the address of the computer running netcat (nc),
+                          normally the address of your Linux PC (optional).
+                          If the define is missing, CONFIG_NCIP_LS will be
+                          set to the same value as CONFIG_SERVERIP_LS
+
+  RAM Build
+
+   For LinkStation 1 / KuroBox standard run:
+   make linkstation_HDLAN_RAM_config
+   make linkstation_HDLAN_RAM
+
+   The name of the resulting binary is u-boot-hd.ram.bin
+
+   For LinkStation HG / KuroBox HG run:
+   make linkstation_HGLAN_RAM_config
+   make linkstation_HGLAN_RAM
+
+   The name of the resulting binary is u-boot-hg.ram.bin
+
+  Net Console
+
+   The net console is the U-Boot driver which uses the UDP protocol with a
+   default port of 6666 to send the console output to and receive the console
+   input from a remote computer. You need to run netcat on the remote computer
+   to  communicate  with  the  U-Boot  net  console. The communication is
+   bidirectional.  Netcat  will display on your screen the console output
+   received from U-Boot and will send your keyboard input back to U-Boot.
+
+   If U-Boot cannot contact the remote computer, it switches the console to the
+   serial port. To show that it changed the console, U-Boot makes the HDD LED
+   blink with the pattern corresponding to the serial console (see The Reset
+   Button below). The timeout period is 20 sec.
+
+  Minimal Console
+
+   U-Boot for the LinkStation is designed to allow some control over the boot
+   process even in the absence of a console. For this, it uses the power button
+   (the big button at the front) and the reset button (the small red button at
+   the back).
+
+   Before installing U-Boot, when the LinkStation is switched on, the power LED
+   starts  blinking,  the original boot loader starts executing and, very
+   quickly, it starts booting the kernel from flash. If U-Boot is installed,
+   the power LED will change from blinking quickly to blinking very slowly. The
+   blink pattern is the same as the one used to indicate sleep mode in normal
+   operation. When the power LED starts blinking slowly at boot, U-Boot has
+   taken over and it is counting down the boot delay before booting the kernel.
+   The default boot delay is 10 sec. From the moment when the power LED starts
+   blinking slowly and for the duration of the boot delay, you can control the
+   boot process with the power and reset buttons.
+
+    The Power Button
+
+   If you push the power button and keep it pressed for more than 1 sec, the
+   boot  process will stop and the LinkStation will wait for a command. A
+   stopped boot process is indicated by the power LED being lit solid. The
+   effect is the same a pressing 's' on the console.
+
+   A long push of the power button acts as a toggle. If the boot delay count
+   down is in progress, a long push of the power button stops the boot process.
+   If the boot process is stopped (U-Boot is at the command prompt, even if you
+   can't see it), a long push of the power button restarts the boot process
+   resetting the boot delay to its original value. The restart of the boot
+   process is indicated by the power LED blinking slowly.
+
+   By default U-Boot supports three pre-configured boot commands:
+    1. The  first boot command will attempt to load and boot a file named
+       boot/vmlinux.UBoot from the first hard disk partition, /dev/hda1. The
+       file can be in any of the U-Boot bootable formats but uImage is the
+       preferred format. If the file is missing or corrupted, U-Boot will fall
+       back to booting the original kernel from flash.
+    2. The second boot command will boot the original kernel from flash.
+       Please note that the original kernel for the LinkStation 1 / KuroBox
+       standard has a bug in the function that calibrates the decrementer and
+       it will stop for up to 180 sec during boot. This bug is not an U-Boot
+       bug  but  a  kernel bug which is uncovered by the fact that U-Boot
+       activates the decrementer where the original boot loader does not.
+       The original kernel for LinkStation HG / KuroBox HG does not suffer from
+       the above problem.
+    3. The third boot command will attempt to boot in emergency mode (EM). It
+       does this by passing the argument root=/dev/ram0 to the kernel.
+       LinkStation / LinkStation HG owners should avoid booting in EM mode as
+       the root password for this mode on the LinkStation is unknown. 
+       The original kernel for the LinkStation / KuroBox standard and for some
+       of the earlier LinkStation HG / KuroBox HG models ignores the root
+       argument. These models will boot normally from the on-board flash when
+       the  EM  boot command is used. Read the section on EM mode if your
+       LinkStation HG / KuroBox HG has a kernel that doesn't boot in EM mode
+       using this boot command.
+
+   You can cycle through the boot commands with the power button.
+
+   To see which of the three commands U-Boot is going to execute, press the
+   power  button quickly. The HDD LED (the third from the top) will start
+   blinking. The number of times the LED blinks, shows the number of the active
+   boot command. For example, a pattern short on - short off - short on - long
+   off, means that the boot command number 2 is active. U-Boot will repeat the
+   blinking cycle for a total duration of about 5 sec counting from the moment
+   the power button is released.
+
+   A short press of the power button while the HDD LED is blinking will advance
+   the boot command to the next one.
+
+   Changing the boot command does not change the boot status. If the boot is
+   stopped, it will not be restarted. If the boot is in progress, it will not
+   be stopped but the boot delay will be reset to the original value.
+
+    The Reset Button
+
+   Two  consoles are currently configured, the serial console and the net
+   console. The first console is the serial console and the second console is
+   the net console (nc). The net console is the default console.
+
+   The reset button can be used, similarly to the power button, to switch
+   consoles. A press on the reset button (here, it doesn't matter how long you
+   keep the button pressed) displays the currently active console using the HDD
+   LED. Repeatedly pressing the reset button while the HDD LED is blinking will
+   toggle between the two consoles. The blinking pattern is different from the
+   one showing the boot command. The pattern which shows that the second (net)
+   console is active is short off - short on - short off - long on. U-Boot will
+   repeat the blinking cycle for a total duration of about 5 sec counting from
+   the moment the reset button is released.
+
+  Load and Test
+
+   Mount the LinkStation SMB public share and copy the following files to it:
+
+   For LinkStation 1 / KuroBox standard
+   # mount -t smbfs -o password="" //<your_linkstation_name_or_ip>/share/mnt
+   # cp u-boot-hd.ram.bin /mnt
+   # cp ../uloader-2.4.17/uloader.o /mnt
+   # cp ../uloader-2.4.17/u-boot-load-hd.sh /mnt
+   # umount /mmt
+
+   For LinkStation HG / KuroBox HG
+   # mount -t smbfs -o password="" //<your_linkstation_name_or_ip>/share/mnt
+   # cp u-boot-hg.ram.bin /mnt
+   # cp ../uloader-2.4.20/uloader.o /mnt
+   # cp ../uloader-2.4.20/u-boot-load-hg.sh /mnt
+   # umount /mmt
+
+   If you installed the serial port, open another window and use minicom to
+   connect to your LinkStation serial console. The serial port settings are
+   57600,N,8, the same as the settings used by the original Linux kernel.
+
+   Start netcat to communicate with the U-Boot net console. Open another window
+   and run board/linkstation/nc.sh. Nc.sh is a simple script which invokes
+   netcat with the correct options. To quit nc, press ^T (control-T).
+   # cd $UBOOT_BUILD/u-boot-1.1.4
+   # board/linkstation/nc.sh <ip_of_your_linkstation>
+
+   Where <ip_of_your_linkstation> is CONFIG_IPADDR_LS (see Configure U-Boot
+   above). When you run nc.sh nothing will be written to the screen. This is
+   normal as Linux is not using the net console.
+
+   From your original window, use telnet to connect to the LinkStation and
+   launch U-Boot. Replace lshg in the example below with the name / IP address
+   of your LinkStation. Replace myroot with the login you created when you
+   gained  telnet  access.  For  LinkStation  1  /  KuroBox standard, use
+   u-boot-load-hd.sh instead of u-boot-load-hg.sh. Type the commands shown in
+   bold.
+   # telnet lshg
+   Trying 192.168.0.58...
+   Connected to lshg.
+   Escape character is '^]'.
+   BUFFALO INC. Link Station series HD-HGLAN (IEMITSU)
+   HD-HGLAN6C5 login: myroot
+   Linux (none) 2.4.20_mvl31-ppc_linkstation #3 Thu May 19 13:34:18 JST 2005
+   ppc unknown
+   root@HD-HGLAN6C5:~# cd /mnt/share
+   root@HD-HGLAN6C5:/mnt/share# ./u-boot-load-hg.sh
+   root@HD-HGLAN6C5:/mnt/share# exit
+   Connection closed by foreign host.
+   #
+
+   If you have a serial console you should see the initial U-Boot startup
+   messages. Even if the default console is the net console, U-Boot still sends
+   the console output to the serial port until it initialises the network
+   controller.
+   U-Boot 1.1.4 LiSt 2.1.0 (Sep 12 2006 - 23:09:44) LinkStation HG / KuroBox HG
+   CPU: MPC8245 Revision 1.4 at 262.144 MHz: 16 kB I-Cache 16 kB D-Cache
+   DRAM: 128 MB
+   FLASH: 4 MB
+   *** Warning - bad CRC, using default environment
+           00  0b  10ec  8169  0200  ff
+           00  0c  1283  8212  0180  ff
+           00  0e  1033  0035  0c03  ff
+           00  0e  1033  0035  0c03  ff
+           00  0e  1033  00e0  0c03  ff
+   Net:   RTL8169#0
+
+   Watch the net console window. After a few seconds, time needed by U-Boot to
+   initialise the network controller and the IDE controller you should see the
+   U-Boot messages.
+   U-Boot 1.1.4 LiSt 2.1.0 (Sep 12 2006 - 23:09:44) LinkStation HG / KuroBox HG
+   IDE:    Bus 0: OK
+     Device 0: Model: Maxtor 7Y250P0 Firm: YAR41BW0 Ser#: Y62W8PDE
+               Type: Hard Disk
+               Supports 48-bit addressing
+               Capacity: 239372.4 MB = 233.7 GB (490234752 x 512)
+   Boot in 10 seconds ('s' to stop)...
+
+   Press 's' on your keyboard to stop the boot process.
+
+   If  you  want  to  use the serial console, watch the power LED of your
+   LinkStation. When it starts blinking very slowly, use the power button to
+   stop the boot process. Wait for the power LED to go dim and press and hold
+   the power button until the LED lights up brightly indicating that the boot
+   process has stopped. Now press the reset button twice and you should see the
+   U-Boot command prompt (=>) in your minicom window. You can now control
+   U-Boot from the minicom window.
+
+   Using u-boot-load-hd.sh / u-boot-load-hg.sh leads to the above results on
+   devices with the original software. On some LinkStations with modified
+   software, reboot has been modified to send a reboot command to the AVR.
+   This is indicated by the fast blinking of the power LED immediately after
+   running u-boot-load-hd.sh / u-boot-load-hg.sh. Once the AVR receives a
+   reboot command, the reboot process cannot be stopped. The AVR will reboot
+   the LinkStation 5 min after receiving the reboot command.
+   If you find yourself in the above situation you can still test U-Boot by
+   booting your LinkStation with the AVR disabled. Press and hold the reset
+   button and then press the power button. All LEDs will start flashing but
+   your LinkStation will boot normally. Now you can use the procedure
+   described above with one caveat: the AVR being disabled, pressing the
+   buttons will have no effect so you will not be able to test the behaviour
+   of the minimal console. 
+
+   Once  you  get  the  U-Boot command prompt, start testing it. Read the
+   [15]U-Boot documentation and try each command you are interested in.
+
+   Keep in mind that U-Boot interprets all input number as hex numbers. If, for
+   example, you type 256, U-Boot will interpret it as 598 decimal.
+
+   When you are testing memory write commands, do not attempt to write to the
+   first MB of memory (0x00000000 to 0x00100000) as you will be overwriting the
+   exception vectors and U-Boot will crash.
+
+   An important command is flinfo which displays information about the flash
+   chip. If the information displayed is correct for your flash, test the flash
+   erase and flash write commands. To do this, you will need to find an empty
+   sector, one for which each byte is 0xFF. Hint: check the last flash sector
+   first, chances are that it's empty. When you are testing commands that write
+   to the flash, always remember that you can write a single byte but you can
+   only erase whole sectors.
+
+   Be very careful not to write to the flash memory range 0xFFC00000 to
+   0xFFF7FFFF. This area contains the Linux kernel, the initial RAM disk used
+   for EM mode, the bootloader and the configuration sector (which holds the
+   "OKOK" or "NGNG" pattern). The range 0xFFF80000 to 0xFFFFFFFF is the user
+   area and, in most cases, is empty. Always check using the U-Boot command md
+   (memory display) if the flash area you intend to use is empty (all bytes are
+   0xFF). For more information about the flash organisation, read
+   [16]PPCFlashROM for the LinkStation 1 / KuroBox standard or [17]HGFlashROM
+   for the LinkStation HG / KuroBox HG. 
+
+  ROM Build
+
+   Once you are happy with the RAM build, you are ready for the ROM build.
+
+   For LinkStation 1 / KuroBox standard run:
+   make linkstation_HDLAN_config
+   make linkstation_HDLAN
+
+   The name of the resulting binary is u-boot-hd.flash.bin
+
+   For LinkStation HG / KuroBox HG run:
+   make linkstation_HGLAN_config
+   make linkstation_HGLAN
+
+   The name of the resulting binary is u-boot-hg.flash.bin
+
+  Install
+
+   Do not attempt to flash from U-Boot if the power LED is blinking. Your
+   LinkStation is likely to reboot and you will end up with a "brick" 
+   Test the flash commands thoroughly before deciding to burn U-Boot into
+   flash. Write at least 128 kB to the flash to test potential timeout
+   problems 
+   The flash routines in this version of U-Boot for the LinkStation should be
+   able to identify and handle any CFI flash which uses the AMD standard
+   command set. However, they were tested only on a LinkStation with a Fujitsu
+   MBM29PL32TM flash chip and on a LinkStation HG with a ST Micro M29DW324DB
+   flash chip. 
+   Be very careful not to flash your hardware with the wrong U-Boot build.
+   Flashing any RAM build or flashing a ROM build for the LinkStation 1 /
+   KuroBox standard into the LinkStation HG / KuroBox HG or viceversa will
+   "brick" your device. This is especially true if you are flashing from Linux
+      as U-Boot has safety checks to avoid flashing the wrong build. 
+
+    Flashing U-Boot from U-Boot
+
+   The RAM build of U-Boot can be used to load and flash the ROM build. This is
+   the preferred method.
+
+   Boot your LinkStation normally. Open a telnet session and create a directory
+   to hold the U-Boot flash image.
+   root@linkstation:~# cd /mnt/share
+   root@linkstation:/mnt/share# mkdir u-boot
+
+   Copy the U-Boot flash image to your LinkStation SMB share in the directory
+   u-boot.
+
+   Load the RAM build of U-Boot and at the U-Boot command prompt type:
+   => run upgrade
+
+   U-Boot will attempt to load the ROM build from the directory share/u-boot/
+   on the third partition of the hard drive. If the load is successful, it will
+   do the following:
+    1. unprotect the bootloader area;
+    2. erase the bootloader area;
+    3. copy the loaded file to the bootloader area;
+    4. verify the copy;
+
+   Here is the output of run upgrade
+   => run upgrade
+   Loading 0:3:share/u-boot/u-boot-hg.flash.bin
+   174668 bytes read
+   Un-Protected 3 sectors
+   Flash erase: first = 55 @ 0xfff00000
+                last  = 57 @ 0xfff20000
+   Flash erase: Done
+   Erased 3 sectors
+   Copy to Flash... done
+   Total of 174668 bytes were the same
+   =>
+
+   When the above sequence finishes, U-Boot returns to the command prompt (=>).
+
+   Depending on your flash chip, the flash operation can take a long time. Wait
+   patiently and do not try to power down or otherwise interrupt the flash or
+      you will end up with a "brick". 
+
+   Reboot:
+   => reset
+
+   The  power  LED should start blinking slowly and, if you have a serial
+   console, you should see the U-Boot startup messages. Your LinkStation is now
+   running U-Boot.
+
+    Flashing U-Boot from Linux
+
+   Connect to your LinkStation using either the serial port or telnet.
+
+   For LinkStation 1 / KuroBox standard run:
+   # cd /mnt/share/u-boot
+   # dd if=u-boot-hd.flash.bin of=/dev/fl2 bs=1k
+   # cmp u-boot.bin /dev/fl2
+
+   For LinkStation HG / KuroBox HG run:
+   # cd /mnt/share/u-boot
+   # dd if=u-boot-hg.flash.bin of=/dev/mtd1 bs=1k
+   # cmp u-boot.bin /dev/mtd1
+
+   The above commands for LinkStation HG / KuroBox HG will work on devices with
+   the original kernel version 2.4.20 but might to work on earlier devices
+   using kernel version 2.4.17. Please check which device corresponds to the
+   bootloader partition on your hardware.
+
+    If the Flash Fails
+
+   If the flash was not written correctly but U-Boot returns at the command
+   prompt, try to re-run run upgrade.
+
+   If the same happens when you attempt to install U-Boot from Linux, try to dd
+   again.
+
+   If your flash fails completely, for example due to a power failure, all is
+   not  completely  lost. You can still use a JTAG cable to re-flash your
+   Linkstation. Unfortunately, this is a relatively complicated and expensive
+   solution as it involves acquiring or building the JTAG cable and soldering
+   the header for it on the LinkStation motherboard. For more information on
+   how   to  use  a  JTAG  cable  with  the  LinkStation  you  can  visit
+   [18]www.linkstationwiki.net and [19]www.kurobox.com/mwiki.
+
+  EM Mode
+
+             Warning for the LinkStation / LinkStation HG users
+
+   Do not attempt to boot into EM mode using the method described here. The
+   password for the EM mode is unknown for all LinkStation models.
+
+   Once you have U-Boot installed in the on-board flash, you can boot in EM
+   mode even if the third boot command described above doesn't work.
+
+   Stop the boot countdown by pressing 's' in your net console window and, at
+   the U-Boot command prompt, run:
+   => run writeng
+   => run flboot
+
+   The above commands write "NGNG" to 0xFFF70000 and boot from the on-board
+   flash. To revert to normal boot by writing "OKOK" to 0xFFF70000, run:
+   => run writeok
+   => boot
+
+  Advanced configuration
+
+   The  initial  U-Boot  configuration can be changed by editing the file
+   include/configs/linkstation.h.
+
+   In all the examples below, please note the backslash-zero (\0) at the end of
+   the strings and the space-backslash ( \) at the end of each lines and do not
+   change them. 
+
+    Change the name of the default boot file
+
+   Search for the lines containing:
+   "hdpart=0:1\0" \
+   "hdfile=boot/vmlinux.UBoot\0" \
+
+   and  change  them  to the values you want. Partition 0:1 means disk 0,
+   partition 1. Obviously, you can only change the partition number as there is
+   only one disk. The name of the file must be given relative to the root of
+   the partition.
+
+    Change the default console to the serial console
+
+   Search for the lines containing:
+   "stdin=nc\0" \
+   "stdout=nc\0" \
+   "stderr=nc\0" \
+
+   and change them to:
+   "stdin=serial\0" \
+   "stdout=serial\0" \
+   "stderr=serial\0" \
+
+    Change the default boot command to boot from flash
+
+   Search for the lines containing:
+   "bootcmd1=run hdboot;run flboot\0" \
+   "bootcmd2=run flboot\0" \
+
+   and change them to:
+   "bootcmd1=run flboot\0" \
+   "bootcmd2=run hdboot;run flboot\0" \
+
+References
+
+   1. http://www.linuxnotincluded.org.uk/fdl.txt
+   2. http://www.linkstationwiki.net/index.php?title=CGI_Exploit_%28PowerPC%29_original_method_of_Hacking_the_LinkStation
+   3. http://www.linkstationwiki.net/index.php?title=Turn_your_LinkStation_into_a_Kuro_Box_%28PowerPC%29
+   4. http://linkstationwiki.net/index.php?title=OpenLink
+   5. http://linkstationwiki.net/index.php?title=The_LinkStation_firmware_flasher
+   6. http://downloads.linkstationwiki.net/snapshots/HD-HGLAN_149_100_telnet.zip
+   7. http://www.linkstationwiki.net/index.php?title=Add_a_Serial_port_to_the_PowerPC_Linkstation
+   8. http://netcat.sourceforge.net/
+   9. http://www.vulnwatch.org/netcat
+  10. http://ftp.sunet.se/pub/Linux/distributions/eldk/3.1.1/ppc-linux-x86/iso/ppc-2005-03-07.iso
+  11. ftp://ftp.denx.de/pub/u-boot/u-boot-1.1.4.tar.bz2
+  12. http://www.linuxnotincluded.org.uk/linkstation/downloads/u-boot-1.1.4-list-2.1.0.diff.gz
+  13. http://www.linuxnotincluded.org.uk/linkstation/downloads/uloader-2.4.17.tar.gz
+  14. http://www.linuxnotincluded.org.uk/linkstation/downloads/uloader-2.4.20.tar.gz
+  15. http://www.denx.de/wiki/DULG/Manual
+  16. http://linkstationwiki.net/index.php?title=Information/PPCFlashROM
+  17. http://linkstationwiki.net/index.php?title=Information/HGFlashROM
+  18. http://www.linkstationwiki.net/
+  19. http://www.kurobox.com/mwiki
diff --git a/board/linkstation/Makefile b/board/linkstation/Makefile
new file mode 100644 (file)
index 0000000..15e54ba
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# (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 $(TOPDIR)/config.mk
+
+LIB    = lib$(BOARD).a
+
+OBJS   = $(BOARD).o flash.o ide.o hwctl.o bootls.o avr.o
+SOBJS  = early_init.o
+
+$(LIB):        .depend $(OBJS) $(SOBJS)
+       $(AR) crv $@ $(OBJS) $(SOBJS)
+
+#########################################################################
+
+.depend:       Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/linkstation/avr.c b/board/linkstation/avr.c
new file mode 100644 (file)
index 0000000..4615a98
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * avr.c
+ *
+ * AVR functions
+ *
+ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <ns16550.h>
+#include <console.h>
+
+/* Button codes from the AVR */
+#define PWRR                           0x20    /* Power button release */
+#define PWRP                           0x21    /* Power button push    */
+#define RESR                           0x22    /* Reset button release */
+#define RESP                           0x23    /* Reset button push    */
+#define AVRINIT                                0x33    /* Init complete                */
+#define AVRRESET                       0x31    /* Reset request                */
+
+/* LED commands */
+#define PWRBLINKSTRT           '['             /* Blink power LED              */
+#define PWRBLINKSTOP           'Z'             /* Solid power LED              */
+#define HDDLEDON                       'W'             /* HDD LED on                   */
+#define HDDLEDOFF                      'V'             /* HDD LED off                  */
+#define HDDBLINKSTRT           'Y'             /* HDD LED start blink  */
+#define HDDBLINKSTOP           'X'             /* HDD LED stop blink   */
+
+/* Timings for LEDs blinking to show choice */
+#define PULSETIME                      250             /* msecs                                */
+#define LONGPAUSE                      (5 * PULSETIME)
+
+/* Button press times */
+#define PUSHHOLD                       1000    /* msecs                                */
+#define NOBUTTON                       (6 * (LONGPAUSE+PULSETIME))
+
+/* Boot and console choices */
+#define MAX_BOOT_CHOICE                3
+
+static char *consoles[] = {
+       "serial",
+#if defined(CONFIG_NETCONSOLE)
+       "nc",
+#endif
+};
+#define MAX_CONS_CHOICE        (sizeof(consoles)/sizeof(char *))
+
+#if !defined(CONFIG_NETCONSOLE)
+#define DEF_CONS_CHOICE                0
+#else
+#define DEF_CONS_CHOICE                1
+#endif
+
+#define perror(fmt,args...)     printf("%s: ",__FUNCTION__);printf(fmt,##args)
+
+extern void miconCntl_SendCmd(unsigned char dat);
+extern void miconCntl_DisWDT(void);
+
+static int boot_stop;
+
+static int boot_choice = 1;
+static int cons_choice = DEF_CONS_CHOICE;
+
+static char envbuffer[16];
+
+void init_AVR_DUART (void)
+{
+       NS16550_t AVR_port = (NS16550_t) CFG_NS16550_COM2;
+       int clock_divisor = CFG_NS16550_CLK / 16 / 9600;
+
+       /*
+        * AVR port init sequence taken from
+        * the original Linkstation init code
+        * Normal U-Boot serial reinit doesn't
+        * work because the AVR uses even parity
+        */
+       AVR_port->lcr = 0x00;
+       AVR_port->ier = 0x00;
+       AVR_port->lcr = LCR_BKSE;
+       AVR_port->dll = clock_divisor & 0xff;
+       AVR_port->dlm = (clock_divisor >> 8) & 0xff;
+       AVR_port->lcr = LCR_WLS_8 | LCR_PEN | LCR_EPS;
+       AVR_port->mcr = 0x00;
+       AVR_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR;
+
+       miconCntl_DisWDT();
+
+       boot_stop = 0;
+       miconCntl_SendCmd(PWRBLINKSTRT);
+}
+
+void hw_watchdog_reset (void)
+{
+}
+
+static inline int avr_tstc(void)
+{
+       return (NS16550_tstc((NS16550_t)CFG_NS16550_COM2));
+}
+
+static inline char avr_getc(void)
+{
+       return (NS16550_getc((NS16550_t)CFG_NS16550_COM2));
+}
+
+static int push_timeout(char button_code)
+{
+       ulong push_start = get_timer(0);
+       while (get_timer(push_start) <= PUSHHOLD)
+               if (avr_tstc() && avr_getc() == button_code)
+                       return 0;
+       return 1;
+}
+
+static void next_boot_choice(void)
+{
+       ulong return_start;
+       ulong pulse_start;
+       int on_times;
+       int button_on;
+       int led_state;
+       char c;
+       
+       button_on = 0;
+       return_start = get_timer(0);
+
+       on_times = boot_choice;
+       led_state = 0;
+       miconCntl_SendCmd(HDDLEDOFF);
+       pulse_start = get_timer(0);
+
+       while (get_timer(return_start) <= NOBUTTON || button_on)
+       {
+               if (avr_tstc()) {
+                       c = avr_getc();
+                       if (c == PWRP)
+                               button_on = 1;
+                       else if (c == PWRR) {
+                               button_on = 0;
+                               return_start = get_timer(0);
+                               if (++boot_choice > MAX_BOOT_CHOICE)
+                                       boot_choice = 1;
+                               sprintf(envbuffer, "bootcmd%d", boot_choice);
+                               if (getenv(envbuffer)) {
+                                       sprintf(envbuffer, "run bootcmd%d", boot_choice);
+                                       setenv("bootcmd", envbuffer);
+                               }
+                               on_times = boot_choice;
+                               led_state = 1;
+                               miconCntl_SendCmd(HDDLEDON);
+                               pulse_start = get_timer(0);
+                       } else {
+                               perror("Unexpected code: 0x%02X\n", c);
+                       }
+               }
+               if (on_times && get_timer(pulse_start) > PULSETIME) {
+                       if (led_state == 1) {
+                               --on_times;
+                               led_state = 0;
+                               miconCntl_SendCmd(HDDLEDOFF);
+                       } else {
+                               led_state = 1;
+                               miconCntl_SendCmd(HDDLEDON);
+                       }
+                       pulse_start = get_timer(0);
+               }
+               if (!on_times && get_timer(pulse_start) > LONGPAUSE) {
+                       on_times = boot_choice;
+                       led_state = 1;
+                       miconCntl_SendCmd(HDDLEDON);
+                       pulse_start = get_timer(0);
+               }
+       }
+       if (led_state)
+               miconCntl_SendCmd(HDDLEDOFF);
+}
+
+void next_cons_choice(int console)
+{
+       ulong return_start;
+       ulong pulse_start;
+       int on_times;
+       int button_on;
+       int led_state;
+       char c;
+       device_t *idev;
+       device_t *odev;
+       
+       button_on = 0;
+       cons_choice = console;
+       return_start = get_timer(0);
+
+       on_times = cons_choice+1;
+       led_state = 1;
+       miconCntl_SendCmd(HDDLEDON);
+       pulse_start = get_timer(0);
+
+       while (get_timer(return_start) <= NOBUTTON || button_on)
+       {
+               if (avr_tstc()) {
+                       c = avr_getc();
+                       if (c == RESP)
+                               button_on = 1;
+                       else if (c == RESR) {
+                               button_on = 0;
+                               return_start = get_timer(0);
+                               cons_choice = (cons_choice + 1) % MAX_CONS_CHOICE;
+                               idev = search_device(DEV_FLAGS_INPUT,  consoles[cons_choice]);
+                               odev = search_device(DEV_FLAGS_OUTPUT, consoles[cons_choice]);
+                               console_setfile (stdin,  idev);
+                               console_setfile (stdout, odev);
+                               console_setfile (stderr, odev);
+                               on_times = cons_choice+1;
+                               led_state = 0;
+                               miconCntl_SendCmd(HDDLEDOFF);
+                               pulse_start = get_timer(0);
+                       } else {
+                               perror("Unexpected code: 0x%02X\n", c);
+                       }
+               }
+               if (on_times && get_timer(pulse_start) > PULSETIME) {
+                       if (led_state == 0) {
+                               --on_times;
+                               led_state = 1;
+                               miconCntl_SendCmd(HDDLEDON);
+                       } else {
+                               led_state = 0;
+                               miconCntl_SendCmd(HDDLEDOFF);
+                       }
+                       pulse_start = get_timer(0);
+               }
+               if (!on_times && get_timer(pulse_start) > LONGPAUSE) {
+                       on_times = cons_choice+1;
+                       led_state = 0;
+                       miconCntl_SendCmd(HDDLEDOFF);
+                       pulse_start = get_timer(0);
+               }
+       }
+       if (led_state);
+               miconCntl_SendCmd(HDDLEDOFF);
+}
+
+int avr_input(void)
+{
+       char avr_button;
+       int ret;
+
+       if (!avr_tstc())
+               return 0;
+
+       avr_button = avr_getc();
+       switch (avr_button) {
+               case PWRP:
+                       if (push_timeout(PWRR)) {
+                               /* Timeout before power button release */
+                               boot_stop = ~boot_stop;
+                               if (boot_stop)
+                                       miconCntl_SendCmd(PWRBLINKSTOP);
+                               else
+                                       miconCntl_SendCmd(PWRBLINKSTRT);
+                               /* Wait for power button release */
+                               while (avr_getc() != PWRR)
+                                       ;
+                       }
+                       else
+                               /* Power button released */
+                               next_boot_choice();
+                       break;
+               case RESP:
+                       /* Wait for Reset button release */
+                       while (avr_getc() != RESR)
+                               ;
+                       next_cons_choice(cons_choice);
+                       break;
+               case AVRINIT:
+                       return 0;
+               default:
+                       perror("Unexpected code: 0x%02X\n", avr_button);
+                       return 0;
+       }
+       if (boot_stop)
+               return (-3);
+       else
+               return (-2);
+}
+
+void avr_StopBoot(void)
+{
+       boot_stop = ~0;
+       miconCntl_SendCmd(PWRBLINKSTOP);
+}
+
+/* vim: set ts=4: */
diff --git a/board/linkstation/bootls.c b/board/linkstation/bootls.c
new file mode 100644 (file)
index 0000000..e961776
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * bootls.c
+ *
+ * Boot a Linkstation kernel of type firmimg.bin
+ *
+ * U-Boot loader code for Linkstation kernel. A file of type firmimg.bin
+ * consists of a header, immediately followed by a compressed kernel image,
+ * followed by a compressed initrd image.
+ *
+ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Derived from:
+ *
+ * arch/ppc/common/misc-simple.c (linux-2.4.17_mvl21-sandpoint)
+ * Author: Matt Porter <mporter@mvista.com>
+ * Derived from arch/ppc/boot/prep/misc.c
+ * 2001 (c) MontaVista, Software, Inc.
+ *
+ * common/cmd_bootm.c (u-boot-1.1.4)
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+
+#include "firminfo.h"
+
+#define _ALIGN(addr,size)       (((addr)+size-1)&(~(size-1)))
+
+struct bi_record {
+       unsigned long tag;              /* tag ID */
+       unsigned long size;             /* size of record (in bytes) */
+       unsigned long data[0];  /* data */
+};
+
+#define BI_FIRST       0x1010  /* first record - marker */
+#define BI_LAST                0x1011  /* last record - marker */
+
+extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+extern int gunzip(void *, int, unsigned char *, int *);
+
+/*
+ * output BYTE data
+ */
+static inline void outb(volatile unsigned char *addr, int val)
+{
+       asm volatile("eieio");
+       asm volatile("stb%U0%X0 %1,%0; sync; isync" : "=m" (*addr) : "r" (val));
+}
+
+unsigned long checksum_check(unsigned char* addr, unsigned long size)
+{
+       long *laddr = (long *)addr;
+       unsigned long sum = 0,remain = 0;
+       int i;
+       while(size>=4) {
+               sum += *laddr;
+               laddr++;
+               size -= 4;
+       }
+       addr = (unsigned char*)laddr;
+       for(i=0;i<4;++i) {
+               remain = remain << 8;
+               if(size>i) remain += *addr;
+               addr++;
+               }
+       sum += remain;
+       return sum;
+}
+
+void do_boot_lskernel (cmd_tbl_t *cmdtp,
+                                       int flag,
+                                       int argc,
+                                       char *argv[],
+                                       unsigned long load_addr,
+                                       unsigned long *len_ptr,
+                                       int verify)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       char                    *zimage_start;
+       int                     zimage_size;
+       unsigned long   initrd_start;
+       unsigned long   initrd_end;
+       unsigned long   sp;
+       unsigned long   cmd_start;
+       unsigned long   cmd_end;
+       char                    *cmdline;
+       char                    *s;
+       bd_t                    *kbd;
+       void                    (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
+       unsigned long   iflag;
+       struct firminfo *info = (struct firminfo *)load_addr;
+       struct bi_record *rec;
+
+       int                             i;
+       char                    *flashstr="FLASH";
+
+       for (i=0; i <= 4; i++)
+               if (info->subver[i] != flashstr[i]) {
+                       puts ("Not a Linkstation kernel\n");
+                       return;
+               }
+
+       printf("\n******* Product Information *******\n");
+       printf("----------------------------------\n");
+
+       printf("Product Name: %s\n", info->firmname);
+       printf("         VER: %d.%02d\n", info->ver_major, info->ver_minor);
+       printf("        Date: %d/%d/%d %d:%d:%d\n",
+                       info->year+1900, info->mon, info->day,
+                       info->hour,info->min,info->sec);
+       printf("----------------------------------\n");
+       
+       if (verify) {
+               printf("Verifying checksum... ");
+               if (checksum_check((unsigned char*)info, info->size) != 0) {
+                       printf("Failed!: checksum %08X, expecting 0\n",
+                                       checksum_check((unsigned char*)info, info->size));
+                       return; /* Returns on error */
+               } else
+                       printf("OK\n");
+       }
+
+       zimage_start = (char*)info + info->kernel_offset;
+       zimage_size  = (int)info->kernel_size;
+       iflag = disable_interrupts();
+       puts("Uncompressing kernel...");
+       if (gunzip(0, 0x400000, zimage_start, &zimage_size) != 0) {
+               puts ("Failed! MUST reset board to recover\n");
+               do_reset (cmdtp, flag, argc, argv);
+       } else
+               puts("done.\n");
+
+       /*
+        * Allocate space for command line and board info - the
+        * address should be as high as possible within the reach of
+        * the kernel (see CFG_BOOTMAPSZ settings), but in unused
+        * memory, which means far enough below the current stack
+        * pointer.
+        */
+
+       asm( "mr %0,1": "=r"(sp) : );
+       debug ("## Current stack ends at 0x%08lX ", sp);
+       sp -= 2048;             /* just to be sure */
+       if (sp > CFG_BOOTMAPSZ)
+               sp = CFG_BOOTMAPSZ;
+       sp &= ~0xF;
+       debug ("=> set upper limit to 0x%08lX\n", sp);
+
+       cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF);
+       if ((s = getenv("bootargs")) == NULL)
+               s = "root=/dev/hda1";
+       strcpy (cmdline, s);
+       cmd_start    = (ulong)&cmdline[0];
+       cmd_end      = cmd_start + strlen(cmdline);
+       debug ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end);
+
+       kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF);
+       *kbd = *(gd->bd);
+       if ((s = getenv ("clocks_in_mhz")) != NULL) {
+               /* convert all clock information to MHz */
+               kbd->bi_intfreq /= 1000000L;
+               kbd->bi_busfreq /= 1000000L;
+       }
+
+       kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))0x4;
+
+       if (info->initrd_size > 0) {
+               initrd_start = (unsigned long)((char*)info + info->initrd_offset);
+               initrd_end   = initrd_start + info->initrd_size;
+               if(initrd_start > 0xffc00000 && initrd_end < 0xffefffff) {
+                       unsigned long nsp;
+                       unsigned long data;
+
+                       data = initrd_start;
+                       /*
+                        * the inital ramdisk does not need to be within
+                        * CFG_BOOTMAPSZ as it is not accessed until after
+                        * the mm system is initialised.
+                        *
+                        * do the stack bottom calculation again and see if
+                        * the initrd will fit just below the monitor stack
+                        * bottom without overwriting the area allocated
+                        * above for command line args and board info.
+                        */
+                       asm( "mr %0,1": "=r"(nsp) : );
+                       nsp -= 2048;                    /* just to be sure */
+                       nsp &= ~0xF;
+                       nsp -= info->initrd_size;
+                       nsp &= ~(4096 - 1);             /* align on page */
+                       initrd_start = nsp;
+                       initrd_end = initrd_start + info->initrd_size;
+                       printf ("Loading Ramdisk at 0x%08lX, end 0x%08lX ... ",
+                                       initrd_start, initrd_end);
+                       memmove ((void *)initrd_start, (void *)data, info->initrd_size);
+                       puts ("OK\n");
+               }
+       } else {
+               initrd_start = 0;
+               initrd_end   = 0;
+       }
+
+       /*
+        * The kernel looks for this structure even if
+        * the information in it is replaced by the
+        * Linkstation kernel
+     */ 
+       rec = (struct bi_record *)_ALIGN((unsigned long)zimage_size +
+                                       (1 << 20) - 1,(1 << 20));
+       rec->tag = BI_FIRST;
+       rec->size = sizeof(struct bi_record);
+       rec = (struct bi_record *)((unsigned long)rec + rec->size);
+       rec->tag = BI_LAST;
+       rec->size = sizeof(struct bi_record);
+
+#if defined(CONFIG_HLAN) || defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+       // kernel load done.
+       outb(0x80004500, 0x49); // send signal
+       outb(0x80004500, 0x49); // send signal
+       outb(0x80004500, 0x49); // send signal
+       outb(0x80004500, 0x49); // send signal
+#endif
+#if defined(CONFIG_HGLAN)
+       // full speed 
+       udelay(10000);  /* 10 msec */
+       outb(0x80004500, 0x5D); // send signal
+       outb(0x80004500, 0x5D); // send signal
+       outb(0x80004500, 0x5D); // send signal
+       outb(0x80004500, 0x5D); // send signal
+#endif
+#if defined(CONFIG_HTGL)
+       // LINK/ACT led controll
+       outb(0x80004500, 0x61); // a
+       outb(0x80004500, 0x61); // a
+       outb(0x80004500, 0x39); // 9
+       outb(0x80004500, 0x31); // 1
+       outb(0x80004500, 0x39); // 9
+       outb(0x80004500, 0x30); // 0
+       outb(0x80004500, 0x92); // 1000Mbps down
+       outb(0x80004500, 0x92); // 1000Mbps down
+
+       udelay(10000);  /* 10 msec */
+       outb(0x80004500, 0x61); // a
+       outb(0x80004500, 0x61); // a
+       outb(0x80004500, 0x39); // 9
+       outb(0x80004500, 0x30); // 0
+       outb(0x80004500, 0x39); // 9
+       outb(0x80004500, 0x30); // 0
+       outb(0x80004500, 0x90); // 100Mbps down
+       outb(0x80004500, 0x90); // 100Mbps down
+
+       udelay(10000);  /* 10 msec */
+       outb(0x80004500, 0x61); // a
+       outb(0x80004500, 0x61); // a
+       outb(0x80004500, 0x38); // 8
+       outb(0x80004500, 0x46); // F
+       outb(0x80004500, 0x39); // 9
+       outb(0x80004500, 0x30); // 0
+       outb(0x80004500, 0x8E); // 10Mbps down
+       outb(0x80004500, 0x8E); // 10Mbps down
+
+       udelay(10000);  /* 10 msec */
+       outb(0x80004500, 0x5F); // _
+       outb(0x80004500, 0x5F); // _
+#endif
+
+/*
+ * This is what the original boot loader sends
+ * just before jumping to the kernel start
+ */
+       outb(0xFF000001, 0xFF);
+
+       puts("Booting the kernel\n");
+
+       /*
+        * Linux Kernel Parameters:
+        *   r3: ptr to board info data
+        *   r4: initrd_start or 0 if no initrd
+        *   r5: initrd_end - unused if r4 is 0
+        *   r6: Start of command line string
+        *   r7: End   of command line string
+       */
+       (*kernel)((bd_t *)0xFF000001, initrd_start, initrd_end, cmd_start, cmd_end);
+}
+
+/* vim: set ts=4: */
diff --git a/board/linkstation/config.mk b/board/linkstation/config.mk
new file mode 100644 (file)
index 0000000..bdf611d
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2001-2003
+# 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
+#
+
+# LinkStation/LinkStation-HG:
+#
+#       Valid values for TEXT_BASE are:
+#
+#      Standard configuration - all models
+#       0xFFF00000   boot from flash
+#
+#      Test configuration (boot from RAM using uloader.o)
+#      LinkStation HD-HLAN and KuroBox Standard
+#       0x03F00000   boot from RAM
+#      LinkStation HD-HGLAN and KuroBox HG
+#       0x07F00000   boot from RAM
+#
+
+sinclude $(TOPDIR)/board/$(BOARDDIR)/config.tmp
+
+ifndef TEXT_BASE
+# For flash image - all models
+TEXT_BASE = 0xFFF00000
+# For RAM image
+# HLAN and LAN
+#TEXT_BASE = 0x03F00000
+# HGLAN and HGTL
+#TEXT_BASE = 0x07F00000
+endif
+
+PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
diff --git a/board/linkstation/early_init.S b/board/linkstation/early_init.S
new file mode 100644 (file)
index 0000000..8eb16d3
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * board/linkstation/early_init.S
+ *
+ * Begin at some arbitrary location in RAM or Flash
+ *  Initialize core registers
+ *  Configure memory controller (Not executing from RAM)
+ *  Initialize UARTs
+ *  Simple RAM test (currently suspended)
+ *
+ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Modified for U-Boot from arch/ppc/boot/linkstation/head.S from
+ * the GPL code for the Buffalo Terastation, derived in its turn from:
+ *
+ * arch/ppc/boot/sandpoint/head.S
+ *
+ * Initial board bringup code for Motorola SPS Sandpoint test platform
+ *
+ * Author: Mark A. Greer
+ *        mgreer@mvista.com
+ * Derived from arch/ppc/boot/pcore/head.S (mporter@mvista.com)
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ */
+
+#include <config.h>
+#include <ppc_asm.tmpl>
+#include <mpc824x.h>
+#include <ppc_defs.h>
+#include <asm/cache.h> 
+
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
+#define RAM_SIZE        0x04000000
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+#define RAM_SIZE        0x08000000
+#endif
+
+#define UART1           0x80004500
+#define UART1_IER       0x80004501
+#define UART1_FCR       0x80004502
+#define UART1_LCR       0x80004503
+#define UART1_DCR       0x80004511
+#define UART2           0x80004600
+#define UART2_IER       0x80004601
+#define UART2_FCR       0x80004602
+#define UART2_LCR       0x80004603
+#define UART2_DCR       0x80004611
+
+#define WM32(address,data) \
+       lis     r3, address@h; \
+       ori     r3, r3, address@l; \
+       lis     r4, data@h; \
+       ori     r4, r4, data@l; \
+       stw     r4, 0x0000(r3); \
+       sync;  \
+       isync;
+
+#define WM16(address,data) \
+       lis     r3, address@h; \
+       ori     r3, r3, address@l; \
+       li      r4, data; \
+       sth     r4, 0x0000(r3); \
+       sync;  \
+       isync;
+
+#define WM8(address,data) \
+       lis     r3, address@h; \
+       ori     r3, r3, address@l; \
+       li      r4, data; \
+       stb     r4, 0(r3); \
+       sync;  \
+       isync;
+
+       .text
+
+       .globl  early_init_f
+early_init_f:
+/*
+ * Configure core registers
+ */
+
+       /* Establish default MSR value, exception prefix 0xFFF */
+       li      r3,MSR_IP|MSR_FP
+       mtmsr   r3
+
+       /* Clear BATS */
+       li      r8,0
+       mtspr   DBAT0U,r8
+       mtspr   DBAT0L,r8
+       mtspr   DBAT1U,r8
+       mtspr   DBAT1L,r8
+       mtspr   DBAT2U,r8
+       mtspr   DBAT2L,r8
+       mtspr   DBAT3U,r8
+       mtspr   DBAT3L,r8
+       mtspr   IBAT0U,r8
+       mtspr   IBAT0L,r8
+       mtspr   IBAT1U,r8
+       mtspr   IBAT1L,r8
+       mtspr   IBAT2U,r8
+       mtspr   IBAT2L,r8
+       mtspr   IBAT3U,r8
+       mtspr   IBAT3L,r8
+       isync
+       sync
+       sync
+
+       /* Set segment registers */
+       lis     r8, 0x0000
+       isync
+       mtsr    SR0,r8
+       mtsr    SR1,r8
+       mtsr    SR2,r8
+       mtsr    SR3,r8
+       mtsr    SR4,r8
+       mtsr    SR5,r8
+       mtsr    SR6,r8
+       mtsr    SR7,r8
+       mtsr    SR8,r8
+       mtsr    SR9,r8
+       mtsr    SR10,r8
+       mtsr    SR11,r8
+       mtsr    SR12,r8
+       mtsr    SR13,r8
+       mtsr    SR14,r8
+       mtsr    SR15,r8
+       isync
+       sync
+       sync
+
+       /* Disable L1 icache/dcache */
+       li      r4,0x0000
+       isync
+       mtspr   HID0,r4
+       sync
+       isync
+       
+       /* Flash Invalidate L1 icache/dcache */
+       
+       ori     r4,r4,0x8000
+       ori     r8,r4,0x0800
+       isync
+       mtspr   HID0,r8
+       sync
+       isync
+       
+       /* Older cores need to manually clear ICFI bit */
+       
+       mtspr   HID0,r4
+       sync
+       isync
+
+#if !defined(CFG_RAMBOOT)
+melco_config_start:
+       /* --- CPU Configration registor setting for LinkStation --- */
+       WM32(0x80041020,0x000000a0) /* Reset EPIC */
+
+       /* errata for latency timer */
+       WM32(0xFEC00000,0x0d000080)
+       WM8(0xFEE00001,0x20)
+       /* cash size */
+       WM32(0xFEC00000,0x0c000080)
+       WM8(0xFEE00000,0x08)
+       /*  PCI configuration command register */
+       WM32(0xFEC00000,0x04000080)
+       WM16(0xFEE00000,0x0600)
+       /* Processor interface configuration register 1 */
+       WM32(0xFEC00000,0xa8000080)
+       /* WM32(0xFEE00000,0xd8131400) */
+       lis     r3, 0xFEE00000@h 
+       ori     r3, r3, 0xFEE00000@l
+       
+       lwz r5, 0(r3)  /* load PCIR1 Config */
+       lis r4, 0x0
+       ori r4, r4, 0x1000
+       and r5, r4, r5  /* Get Bit20(RCS0) */
+               
+       lis     r4, 0xd8130400@h
+       ori     r4, r4, 0xd8130400@l
+       or  r4, r4, r5   /* Save (RCS0) */
+       
+       stw     r4, 0x0000(r3)
+       sync
+       isync
+       
+       /* Processor interface configuration register 2 */
+       WM32(0xFEC00000,0xac000080)
+       WM32(0xFEE00000,0x00000004)
+       /* Embeded Utility Memory Block Base Address register */
+       WM32(0xFEC00000,0x78000080)
+       WM32(0xFEE00000,0x00000080)
+       /* Address map B option register */
+       WM32(0xFEC00000,0xe0000080)
+       WM8(0xFEE00000,0x20) /* DLL_RESET on */
+       
+       /* Address map B option register */
+       WM32(0xFEC00000,0xe0000080)
+       WM8(0xFEE00000,0xc0)
+       /* PCI arbiter control register */
+       WM32(0xFEC00000,0x46000080)
+       WM16(0xFEE00002,0x00c0)
+
+       /* Added to use the high drive strength for the memory selects & addressing */
+       WM32(0xFEC00000,0x73000080)
+               /* WM8(0xFEE00003,0x15) */  /*0x17*/
+               /* Motorola Errata refer to User's Manual Errata#19 */
+               /* WM8(0xFEE00003,0xD5) */
+       WM8(0xFEE00003,0x95)
+
+       /* set miscellaneous I/O control register 1 */
+       WM32(0xFEC00000,0x76000080)
+       WM8(0xFEE00002,0x00) /*0x02*/
+       /* set miscellaneous I/O control register 2 */
+       WM32(0xFEC00000,0x77000080)
+       WM8(0xFEE00003,0x30)  /* 0x30 */
+
+       /* init memory controller */
+       WM32(0xFEC00000,0x80000080)
+       WM32(0xFEE00000,0x00FFFFFF)
+
+       WM32(0xFEC00000,0x84000080)
+       WM32(0xFEE00000,0xFFFFFFFF)
+       
+       WM32(0xFEC00000,0x90000080)
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
+       WM32(0xFEE00000,0x3FFFFFFF) /* 64MB */
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+       WM32(0xFEE00000,0x7FFFFFFF) /* 128MB */
+#endif
+
+       WM32(0xFEC00000,0x94000080)
+       WM32(0xFEE00000,0xFFFFFFFF)
+       
+       WM32(0xFEC00000,0x88000080)
+       WM32(0xFEE00000,0x00030303)
+       /* EMSAR2 */
+       WM32(0xFEC00000,0x8C000080)
+       WM32(0xFEE00000,0x03030303)
+       /* select EMSER1 */
+       WM32(0xFEC00000,0x98000080)
+       WM32(0xFEE00000,0x00030303)
+       /* select EMSER2 */
+       WM32(0xFEC00000,0x9C000080)
+       WM32(0xFEE00000,0x03030303)
+
+       /* MMCR1 */
+       WM32(0xFEC00000,0xf0000080)
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
+       WM32(0xFEE00000,0x0200E005)     /* bank 0 13xnx4 */
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+       WM32(0xFEE00000,0x0200E005)     /* bank 0 13xnx4 */
+#endif
+       /* MCCR2 */
+       WM32(0xFEC00000,0xf4000080)
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
+       WM32(0xFEE00000,0xe0150000) /* 100MHz Memory bus */
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+       WM32(0xFEE00000,0x80150000) /* 133MHz Memory bus */
+#endif
+       /* MCCR3 */
+       WM32(0xFEC00000,0xf8000080)     
+       WM32(0xFEE00000,0x00000077)     /* BSTOPRE_M =7 / REFREC=8 */
+
+       /* MCCR4 */
+       WM32(0xFEC00000,0xfc000080)
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
+       WM32(0xFEE00000,0x29233222)     /* CAS latency=2, burst length=8, Ext Rom=eable */
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+       WM32(0xFEE00000,0x29323222)     /* CAS latency=3, burst length=4, Ext Rom=eable */
+#endif
+
+       /* Output driver control register */
+       WM32(0xFEC00000,0x73000080)
+       WM8(0xFEE00003,0x15)                    /*  for all 40 ohm */
+       /* CLK driver Control Register */
+       WM32(0xFEC00000,0x74000080)
+       WM16(0xFEE00000,0x7078)
+       /* select MBEN */
+       WM32(0xFEC00000,0xa0000080)
+       WM8(0xFEE00000, 0x01)
+       /* MPM */
+       WM32(0xFEC00000,0xa3000080)
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
+       WM8(0xFEE00003,0xF2)    /* PGMAX = 242 */
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+       WM8(0xFEE00003,0xC9)    /* PGMAX = 201 */
+#endif
+       /* ERCR s */
+       WM32(0xFEC00000,0xd0000080) /*  ; select ERCR1 */
+       WM32(0xFEE00000,0xffffff85)
+       WM32(0xFEC00000,0xd4000080) /*  ; select ERCR2 */
+       WM32(0xFEE00000,0xffffff05)
+       WM32(0xFEC00000,0xd8000080) /*  ; select ERCR3 */
+       WM32(0xFEE00000,0x0000f80f)
+       WM32(0xFEC00000,0xdc000080) /*  ; select ERCR4 */
+       WM32(0xFEE00000,0x0e000000)
+
+       /* MCCR1 */
+       WM32(0xFEC00000,0xf0000080)
+       WM32(0xFEE00000,0x0200E805)  /* 11 + 3 clock wait MEMGO on */
+
+       /* Init UART for AVR */
+       WM8(UART1_LCR,0x00) /* clear LCR */
+       WM8(UART1_IER,0x00) /* disable interrupt */
+       WM8(UART1_LCR,0x80) /* set LCR[DLAB] bit */
+       WM8(UART1_DCR,0x01) /* set DUART mode */
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
+       WM8(UART1,    0x8B) /* set DLL(baudrate 9600bps, 100MHz) */
+       WM8(UART1_IER,0x02) /* set DLM(baudrate 9600bps, 100MHz) */
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+       WM8(UART1,    0x61) /* set DLL(baudrate 9600bps, 133MHz) */
+       WM8(UART1_IER,0x03) /* set DLM(baudrate 9600bps, 133MHz) */
+#endif
+       WM8(UART1_LCR,0x1b) /* set 8data, 1stop, even parity */
+       WM8(UART1,    0x00) /* clear MCR */
+       WM8(UART1_FCR,0x07) /* clear & enable FIFO */
+
+       /* Init UART for CONSOLE */
+       WM8(UART2_LCR,0x00) /* clear LCR */
+       WM8(UART2_IER,0x00) /* disable interrupt */
+       WM8(UART2_LCR,0x80) /* set LCR[DLAB] bit */
+       WM8(UART1_DCR,0x01) /* set DUART mode */
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
+       WM8(UART2,    0x6C) /* set DLL(baudrate 57600bps, 100MHz) */
+       WM8(UART2_IER,0x00) /* set DLM(baudrate 57600bps, 100MHz) */
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+       WM8(UART2,    0x90) /* set DLL(baudrate 57600bps, 133MHz) */
+       WM8(UART2_IER,0x00) /* set DLM(baudrate 57600bps, 133MHz) */
+#endif
+       WM8(UART2_LCR,0x03) /* set 8data, 1stop, non parity */
+       WM8(UART2,    0x00) /* clear MCR */
+       WM8(UART2_FCR,0x07) /* clear & enable FIFO */
+#endif /* !defined (CFG_RAMBOOT)
+
+       /* PCI Command Register initialize */
+       lis r3, 0x8000
+       ori r3, r3, 0x0004
+       lis r4, 0xFEC0
+       ori r4, r4, 0x0000
+       stwbrx r4, 0, r3
+       sync
+       isync
+
+       li r6, 0x0006
+       lis r5, 0xFEE0
+       ori r5, r5, 0x0000
+       sthbrx r5, 0, r6
+       sync
+       isync
+
+#if !defined(CFG_RAMBOOT)
+check_ram:
+       /* Wait 1 sec  for AVR become enable */
+       li      r3,1000
+       mulli   r3,r3,1000
+       mulli   r4,r3,1000      /* nanoseconds */
+       addi    r4,r4,39
+       li      r5,40           /* 40ns if for 100 Mhz bus */
+       divw    r4,r4,r5        /* BUS ticks */
+1:     mftbu   r5
+       mftb    r6
+       mftbu   r7
+       cmp     0,r5,r7
+       bne     1b              /* Get [synced] base time */
+       addc    r9,r6,r4        /* Compute end time */
+       addze   r8,r5
+2:     mftbu   r5
+       cmp     0,r5,r8
+       blt     2b
+       bgt     3f
+       mftb    r6
+       cmp     0,r6,r9
+       blt     2b
+#if 1
+3:
+#else
+       /* Check RAM */
+       /* set start address(0x00000000) */
+3:     xor r4,r4,r4
+       lis r5,     RAM_SIZE@h
+       ori r5, r5, RAM_SIZE@l
+       lis r6,     0xaaaa  /* mask pattern a */
+       ori r6, r6, 0xaaaa
+       lis r7,     0x5555  /* mask pattern b */
+       ori r7, r7, 0x5555
+       lis r8,     0x0000  /* check step size */
+       ori r8, r8, 0x0100
+check_ram_loop:        
+       cmp 0,r4,r5
+       beq  check_ram_end
+       stw r6,0(r4)
+       isync
+       lwz r3,0(r4)
+       isync
+       cmp 0,r3,r6
+       bne ram_error
+       stw r7,0x00fc(r4)
+       isync
+       lwz r3,0x00fc(r4)
+       isync
+       cmp 0,r3,r7
+       bne ram_error
+       add r4,r4,r8
+       b   check_ram_loop
+ram_error:
+#if defined(CONFIG_LAN)
+       WM8(UART1,0x39)  /* ram error */
+#elif defined(CONFIG_HGLAN) ||defined(CONFIG_HLAN) || defined(CONFIG_HTGL)
+       WM8(UART1,0x6F)  /* ram error */
+#endif
+       b   ram_error
+check_ram_end:
+#endif /* #if 1 */
+#endif /* !defined (CFG_RAMBOOT) */
+
+/* The instruction cache is enabled and the data cache is disabled */
+       blr
diff --git a/board/linkstation/firminfo.h b/board/linkstation/firminfo.h
new file mode 100644 (file)
index 0000000..5169535
--- /dev/null
@@ -0,0 +1,27 @@
+#define FIRMNAME_MAX   31
+#define SUBVERSION_MAX 31
+#define FIRMINFO_VER 1
+
+struct firminfo {
+               unsigned long info_ver;
+               unsigned long  firmid;
+               char           firmname[FIRMNAME_MAX+1];
+               char           subver[SUBVERSION_MAX+1];
+               unsigned short ver_major;
+               unsigned short ver_minor;
+               unsigned short build;
+               char           year;
+               char           mon;
+               char           day;
+               char           hour;
+               char           min;
+               char           sec;
+               unsigned long size;
+               unsigned long chksum;
+               
+               unsigned long kernel_offset;
+               unsigned long kernel_size;
+               unsigned long initrd_offset;
+               unsigned long initrd_size;
+       } __attribute((aligned(4)));
+// ----------------------------------------------------
diff --git a/board/linkstation/flash.c b/board/linkstation/flash.c
new file mode 100644 (file)
index 0000000..5efff59
--- /dev/null
@@ -0,0 +1,893 @@
+/*
+ * flash.c
+ *
+ * Flash device interface for LinkStation
+ * Supports CFI flash devices using the AMD standard command set
+ *
+ * Copyright (C) 2006 Mihai Georgin <u-boot@linuxnotincluded.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on the MTD code from the Linux kernel
+ * 
+ * Based on include/melco/flashd.c (linux-2.4.17_mvl21-sandpoint)
+ * Copyright (C) 2001-2004  BUFFALO INC.
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <mpc824x.h>
+
+#if 0
+#define DEBUG_CFI
+#endif
+
+#undef  debug
+#ifdef  DEBUG_CFI
+#define debug(fmt,args...)      printf(fmt,##args)
+#else
+#define debug(fmt,args...)
+#endif  /* DEBUG_CFI */
+
+#if CFG_MAX_FLASH_BANKS > 1
+#error Only 1 flash bank supported
+#endif
+
+#define perror(fmt,args...)            printf("%s: ",__FUNCTION__);printf(fmt,##args)
+
+#define MAX_ERASE_REGIONS              4
+
+#define P_ID_NONE                          0
+#define P_ID_INTEL_EXT             1
+#define P_ID_AMD_STD               2
+#define P_ID_INTEL_STD             3
+#define P_ID_AMD_EXT               4
+#define P_ID_MITSUBISHI_STD      256
+#define P_ID_MITSUBISHI_EXT      257
+#define P_ID_RESERVED          65535
+
+#define CFI_DEVICETYPE_X8       (8 / 8)
+#define CFI_DEVICETYPE_X16     (16 / 8)
+
+#define FLASH_DATA_MASK                0xFF
+
+#define FUJ_MANUFACT_LS                (FUJ_MANUFACT    & FLASH_DATA_MASK)
+#define STM_MANUFACT_LS                (STM_MANUFACT    & FLASH_DATA_MASK)
+#define MX_MANUFACT_LS         (MX_MANUFACT     & FLASH_DATA_MASK)
+
+/* Unknown manufacturer */
+#define FLASH_MAN_UNKNOWN      0xFFFF0000
+
+/* Fujitsu MBM29PL320MT which is using the same */
+/* codes as the AMD Am29LV320MT "mirror" flash */
+#define AMD_ID_MIRROR_LS       (AMD_ID_MIRROR   & FLASH_DATA_MASK)
+#define AMD_ID_LV320T_2_LS     (AMD_ID_LV320T_2 & FLASH_DATA_MASK)
+#define AMD_ID_LV320T_3_LS     (AMD_ID_LV320T_3 & FLASH_DATA_MASK)
+
+/* ST Micro M29W320DT and M29W320DB */
+#define STM_ID_29W320DT_LS     (STM_ID_29W320DT & FLASH_DATA_MASK)
+#define STM_ID_29W320DB_LS     (STM_ID_29W320DB & FLASH_DATA_MASK)
+
+/* ST Micro M29DW324DT and M29DW324DB */
+#define STM_ID_29W324DT_LS     (STM_ID_29W324DT & FLASH_DATA_MASK)
+#define STM_ID_29W324DB_LS     (STM_ID_29W324DB & FLASH_DATA_MASK)
+
+/* Macronix MX29LV320T */
+#define MX_ID_LV320T_LS                (MX_ID_LV320T    & FLASH_DATA_MASK)
+
+/* Basic Query Structure */
+struct cfi_ident {
+  __u8  qry[3];
+  __u16 P_ID;
+  __u16 P_ADR;
+  __u16 A_ID;
+  __u16 A_ADR;
+  __u8  VccMin;
+  __u8  VccMax;
+  __u8  VppMin;
+  __u8  VppMax;
+  __u8  WordWriteTimeoutTyp;
+  __u8  BufWriteTimeoutTyp;
+  __u8  BlockEraseTimeoutTyp;
+  __u8  ChipEraseTimeoutTyp;
+  __u8  WordWriteTimeoutMax;
+  __u8  BufWriteTimeoutMax;
+  __u8  BlockEraseTimeoutMax;
+  __u8  ChipEraseTimeoutMax;
+  __u8  DevSize;
+  __u16 InterfaceDesc;
+  __u16 MaxBufWriteSize;
+  __u8  NumEraseRegions;
+  __u32 EraseRegionInfo[MAX_ERASE_REGIONS];
+} __attribute__((packed));
+
+struct cfi_private {
+       __u32 base;
+       int device_type;
+       int addr_unlock1;
+       int addr_unlock2;
+       struct cfi_ident *cfiq;
+       int mfr;
+       int id[3]; /* Supports AMD MirrorBit flash */
+       char *flash_name;
+       int  wrd_wr_time;
+       int  buf_wr_time;
+       int  erase_time;
+       int (*blk_erase)(flash_info_t *info, int s_first, int s_last);
+       int (*blk_write)(flash_info_t *info, __u8 *buf, __u32 addr, int sz);
+};
+
+static inline __u8 cfi_read8(__u32 addr)
+{
+       return (*(volatile __u8 *)(addr));
+}
+
+static inline void cfi_write8(__u8 val, __u32 addr)
+{
+       *(volatile __u8 *)(addr) = val;
+       sync();
+}
+
+/*
+ * Sends a CFI command to a bank of flash for the given type.
+ * Returns the offset to the sent command
+ */
+static inline __u32 cfi_cmd(__u8 cmd, __u32 cmd_addr, __u32 base, int type)
+{
+       __u32 addr;
+
+       addr = base + cmd_addr * type;
+       if (cmd_addr * type == 0x554)
+               ++addr;
+
+       cfi_write8(cmd, addr);
+
+       return addr - base;
+}
+
+static inline __u8 cfi_read_query(__u32 addr)
+{
+       return cfi_read8(addr);
+}
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+static struct cfi_private cfis;
+static struct cfi_ident   cfi_idents;
+static struct cfi_private *cfi;
+
+static int cfi_probe_chip(struct cfi_private *cfi);
+static unsigned long cfi_amdstd_setup(struct cfi_private *cfi, int primary);
+static void print_cfi_ident(struct cfi_ident *);
+static int flash_amdstd_erase(flash_info_t *info, int s_first, int s_last);
+static int flash_amdstd_wbuff(flash_info_t *info, __u8 *buf, __u32 addr,int sz);
+static int flash_amdstd_wubyp(flash_info_t *info, __u8 *buf, __u32 addr,int sz);
+static int flash_amdstd_write(flash_info_t *info, __u8 *buf, __u32 addr,int sz);
+
+
+
+unsigned long flash_init(void)
+{
+       unsigned long flash_size;
+       __u16 type;
+
+       debug("%s\n", __FUNCTION__);
+
+       cfi = &cfis;
+       memset(cfi, 0, sizeof(struct cfi_private));
+
+       cfi->base = CFG_FLASH_BASE;
+
+       /* Identify CFI chip */
+       /* Probe for X8 device first */
+       cfi->device_type = CFI_DEVICETYPE_X8;
+       if (cfi_probe_chip(cfi)) {
+               /* The probe didn't like it */
+               /* so probe for X16/X8 device */
+               cfi->device_type = CFI_DEVICETYPE_X16;
+               if (cfi_probe_chip(cfi)) {
+                       /* The probe didn't like it */
+                       return 0UL;
+               }
+       }               
+
+       /* Check if it is AMD standard cmd set */
+       type = cfi->cfiq->P_ID;
+       if (type == P_ID_AMD_STD)
+               flash_size = cfi_amdstd_setup(cfi, 1);
+       else {
+               perror("Primary cmd set is not AMD std. Trying alternate.\n");
+               flash_size = 0;
+       }
+       if (!flash_size) {
+               type = cfi->cfiq->A_ID;
+               if (type == P_ID_AMD_STD)
+                       flash_size = cfi_amdstd_setup(cfi, 0);
+               else {
+                       perror("Alternate cmd set is not AMD std.\n");
+                       return 0UL;
+               }
+       }
+
+       if (flash_size && flash_size == 4*1024*1024) {
+               /* Flash protection ON by default */
+               flash_protect(FLAG_PROTECT_SET, cfi->base, cfi->base+flash_size-1, flash_info);
+
+               return flash_size;
+       }
+
+       if (flash_size) {
+               perror("Unsupported flash size: %d\n", flash_size);
+       } else {
+               perror("Vendor Command Set not supported\n");
+               printf("Primary: 0x%04X, Alternate: 0x%04X\n",
+                               cfi->cfiq->P_ID, cfi->cfiq->A_ID);
+       }
+       return 0UL;
+}
+
+void flash_print_info(flash_info_t *info)
+{
+       int i;
+
+       debug("%s\n", __FUNCTION__);
+
+       printf("Flash chip: %s\n\n",
+                  cfi->flash_name?cfi->flash_name:"UNKNOWN");
+       print_cfi_ident(cfi->cfiq);
+       printf("\nActual values used by U-Boot:\n");
+       printf("Word   write timeout: %6d ms\n", cfi->wrd_wr_time);
+       printf("Buffer write timeout: %6d ms\n", cfi->buf_wr_time);
+       printf("Sector erase timeout: %6d ms\n", cfi->erase_time);
+       printf("\nSize: %ld MiB 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))
+                       printf ("\n   ");
+               printf (" %08lX%s", info->start[i], info->protect[i]?" (RO)" : " (RW)");
+       }
+       printf ("\n");
+}
+
+int flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+       return (*(cfi->blk_erase))(info, s_first, s_last);
+}
+
+int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+       return (*(cfi->blk_write))(info, src, addr, cnt);
+}
+
+static int cfi_probe_chip(struct cfi_private *cfi)
+{
+       int ofs_factor = cfi->device_type;
+       __u32 base = cfi->base;
+       int num_erase_regions, scount;
+       int i;
+
+       debug("%s\n", __FUNCTION__);
+
+       cfi_cmd(0xF0, 0x00, base, cfi->device_type);
+       cfi_cmd(0x98, 0x55, base, cfi->device_type);
+
+       if (cfi_read8(base + ofs_factor * 0x10) != 'Q' ||
+           cfi_read8(base + ofs_factor * 0x11) != 'R' ||
+           cfi_read8(base + ofs_factor * 0x12) != 'Y') {
+               debug("Not a CFI flash\n");
+               /* Put the chip back into read array mode */
+               cfi_cmd(0xF0, 0x00, base, cfi->device_type);
+               return -1;
+       }
+
+       num_erase_regions = cfi_read_query(base + 0x2C * ofs_factor);
+       if (!num_erase_regions) {
+               perror("No erase regions\n");
+               /* Put the chip back into read read array mode */
+               cfi_cmd(0xF0, 0x00, base, cfi->device_type);
+               return -1;
+       }
+       if (num_erase_regions > MAX_ERASE_REGIONS) {
+               perror("Number of erase regions (%d) > MAX_ERASE_REGIONS (%d)\n",
+                               num_erase_regions, MAX_ERASE_REGIONS);
+               /* Put the chip back into read read array mode */
+               cfi_cmd(0xF0, 0x00, base, cfi->device_type);
+               return -1;
+       }
+
+       cfi->cfiq = &cfi_idents;
+       memset(cfi->cfiq, 0, sizeof(struct cfi_ident)); 
+       debug("cfi->cfiq: 0x%08X\n", cfi->cfiq);
+       
+       /* Read the CFI info structure */
+       for (i=0; i < sizeof(struct cfi_ident) + num_erase_regions * 4; i++)
+               ((__u8 *)cfi->cfiq)[i] = cfi_read_query(base + (0x10 + i) * ofs_factor);
+       
+       /* Do any necessary byteswapping */
+       cfi->cfiq->P_ID            = __le16_to_cpu(cfi->cfiq->P_ID);
+       cfi->cfiq->P_ADR           = __le16_to_cpu(cfi->cfiq->P_ADR);
+       cfi->cfiq->A_ID            = __le16_to_cpu(cfi->cfiq->A_ID);
+       cfi->cfiq->A_ADR           = __le16_to_cpu(cfi->cfiq->A_ADR);
+       cfi->cfiq->InterfaceDesc   = __le16_to_cpu(cfi->cfiq->InterfaceDesc);
+       cfi->cfiq->MaxBufWriteSize = __le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
+
+#if 0
+       /* Dump the information therein */
+       print_cfi_ident(cfi->cfiq);
+#endif
+
+       scount = 0;
+       for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
+               cfi->cfiq->EraseRegionInfo[i] = __le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
+               scount += (cfi->cfiq->EraseRegionInfo[i] & 0xFFFF) + 1;
+               debug("  Erase Region #%d: sector size 0x%4.4X bytes, %d sectors\n",
+                      i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xFF, 
+                      (cfi->cfiq->EraseRegionInfo[i] & 0xFFFF) + 1);
+       }
+       /* Put it back into Read Mode */
+       cfi_cmd(0xF0, 0, base, cfi->device_type);
+
+       if (scount > CFG_MAX_FLASH_SECT) {
+               perror("Number of sectors (%d) > CFG_MAX_FLASH_SECT (%d)\n",
+                               scount, CFG_MAX_FLASH_SECT);
+               return -1;
+       }
+
+       debug("Found x%d device in 8-bit mode\n", cfi->device_type*8);
+       
+       return 0;
+}
+
+static char *vendorname(__u16 vendor) 
+{
+       switch (vendor) {
+       case P_ID_NONE:
+               return "None";
+       case P_ID_INTEL_EXT:
+               return "Intel/Sharp Extended";
+       case P_ID_AMD_STD:
+               return "AMD/Fujitsu Standard";
+       case P_ID_INTEL_STD:
+               return "Intel/Sharp Standard";
+       case P_ID_AMD_EXT:
+               return "AMD/Fujitsu Extended";
+       case P_ID_MITSUBISHI_STD:
+               return "Mitsubishi Standard";
+       case P_ID_MITSUBISHI_EXT:
+               return "Mitsubishi Extended";
+       case P_ID_RESERVED:
+               return "Not Allowed / Reserved for Future Use";
+       default:
+               return "Unknown";
+       }
+}
+
+static void print_cfi_ident(struct cfi_ident *cfip)
+{
+       printf("CFI Query Results:\n");
+       printf("Primary Vendor Command Set: 0x%4.4X (%s)\n",
+                       cfip->P_ID, vendorname(cfip->P_ID));
+       if (cfip->P_ADR)
+               printf("Primary Algorithm Table at 0x%4.4X\n", cfip->P_ADR);
+       else
+               printf("No Primary Algorithm Table\n");
+       
+       printf("Alternate Vendor Command Set: 0x%4.4X (%s)\n",
+               cfip->A_ID, vendorname(cfip->A_ID));
+       if (cfip->A_ADR)
+               printf("Alternate Algorithm Table at 0x%4.4X\n", cfip->A_ADR);
+       else
+               printf("No Alternate Algorithm Table\n");
+               
+       printf("Vcc Min.: %d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xF);
+       printf("Vcc Max.: %d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xF);
+       if (cfip->VppMin) {
+               printf("Vpp Min.: %d.%d V\n", cfip->VppMin >> 4, cfip->VppMin & 0xF);
+               printf("Vpp Max.: %d.%d V\n", cfip->VppMax >> 4, cfip->VppMax & 0xF);
+       }
+       else
+               printf("No Vpp line\n");
+       
+       printf("Typical byte/word write timeout: %d us\n",
+                       1<<cfip->WordWriteTimeoutTyp);
+       printf("Maximum byte/word write timeout: %d us\n",
+                       (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
+       
+       if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
+               printf("Typical full buffer write timeout: %d us\n",
+                               1<<cfip->BufWriteTimeoutTyp);
+               printf("Maximum full buffer write timeout: %d us\n",
+                               (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
+       }
+       else
+               printf("Full buffer write not supported\n");
+       
+       printf("Typical block erase timeout: %d ms\n",
+                       1<<cfip->BlockEraseTimeoutTyp);
+       printf("Maximum block erase timeout: %d ms\n",
+                       (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
+       if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
+               printf("Typical chip erase timeout: %d ms\n",
+                               1<<cfip->ChipEraseTimeoutTyp); 
+               printf("Maximum chip erase timeout: %d ms\n",
+                               (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
+       }
+       else
+               printf("Chip erase not supported\n");
+       
+       printf("Device size: 0x%X bytes (%d MiB)\n",
+                       1 << cfip->DevSize, 1 << (cfip->DevSize - 20));
+       printf("Flash Device Interface description: 0x%4.4X\n",cfip->InterfaceDesc);
+       switch(cfip->InterfaceDesc) {
+       case 0:
+               printf("  - x8-only asynchronous interface\n");
+               break;
+       case 1:
+               printf("  - x16-only asynchronous interface\n");
+               break;
+       case 2:
+               printf("  - x8 / x16 via BYTE# with asynchronous interface\n");
+               break;
+       case 3:
+               printf("  - x32-only asynchronous interface\n");
+               break;
+       case 65535:
+               printf("  - Not Allowed / Reserved\n");
+               break;
+       default:
+               printf("  - Unknown\n");
+               break;
+       }
+       printf("Max. bytes in buffer write: %d\n", 1 << cfip->MaxBufWriteSize);
+       printf("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions);
+}
+
+static unsigned long cfi_amdstd_setup(struct cfi_private *cfi, int primary)
+{
+       flash_info_t *info = &flash_info[0];
+       __u32 base         = cfi->base;
+       int ofs_factor     = cfi->device_type;
+       __u32 addr_et      = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
+       __u8 major, minor, bootloc;
+       __u32 offset, ernum, ersize;
+       int i, j;
+
+       /* Put the chip into read array mode */
+       cfi_cmd(0xF0, 0x00, base, cfi->device_type);
+       /* Autoselect */
+       cfi_cmd(0xAA, 0x555, base, cfi->device_type);
+       cfi_cmd(0x55, 0x2AA, base, cfi->device_type);
+       cfi_cmd(0x90, 0x555, base, cfi->device_type);
+       /* Read manufacturer and device id */
+       cfi->mfr = cfi_read_query(base + 0x00 * ofs_factor);
+       if ((cfi->id[0] = cfi_read_query(base + 0x01 * ofs_factor)) == 0x7E) {   
+                cfi->id[1] = cfi_read_query(base + 0x0E * ofs_factor);
+                cfi->id[2] = cfi_read_query(base + 0x0F * ofs_factor);
+       }
+       /* Put the chip into read array mode */
+       cfi_cmd(0xF0, 0x00, base, cfi->device_type);
+
+       /* Put the chip into read query mode */
+       cfi_cmd(0x98, 0x55, base, cfi->device_type);
+       /* Find the boot block location and swap the erase regions as necessary */
+       major = cfi_read_query(base + (addr_et + 3) * ofs_factor);
+       minor = cfi_read_query(base + (addr_et + 4) * ofs_factor);
+       debug(" Amd/Fujitsu Extended Query Table v%c.%c at 0x%4.4X\n",
+              major, minor, addr_et);
+
+       if (((major << 8) | minor) < 0x3131) {
+               /* CFI version 1.0 => don't trust bootloc */
+               if (cfi->id[0] & 0x80) {
+                       printf("Device ID is 0x%02X. Assuming broken CFI table.\n",
+                                       cfi->id[0]);
+                       bootloc = 3;    /* top boot */
+               } else
+                       bootloc = 2;    /* bottom boot */
+       } else
+               bootloc = cfi_read_query(base + (addr_et + 0xF) * ofs_factor);
+
+       if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) {
+               debug("Top boot block. Swapping erase regions.\n");
+               for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
+                       int j = (cfi->cfiq->NumEraseRegions-1)-i;
+                       __u32 swap;
+                       
+                       swap = cfi->cfiq->EraseRegionInfo[i];
+                       cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j];
+                       cfi->cfiq->EraseRegionInfo[j] = swap;
+               }
+       }
+
+       /* Put the chip into read array mode */
+       cfi_cmd(0xF0, 0x00, base, cfi->device_type);
+
+       switch (cfi->device_type) {
+       case CFI_DEVICETYPE_X8:
+               /* X8 chip */
+               cfi->addr_unlock1 = 0x555; 
+               cfi->addr_unlock2 = 0x2AA; 
+               break;
+       case CFI_DEVICETYPE_X16:
+               /* X16 chip in X8 mode */
+               cfi->addr_unlock1 = 0xAAA;
+               cfi->addr_unlock2 = 0x555;
+               break;
+       default:
+               perror("Unsupported device type %d\n", cfi->device_type);
+               return 0UL;
+       }
+
+       cfi->wrd_wr_time  = 1 << cfi->cfiq->WordWriteTimeoutTyp;
+       cfi->wrd_wr_time *= 1 << cfi->cfiq->WordWriteTimeoutMax;
+       /* Word write time is in us, convert to ms */
+       cfi->wrd_wr_time  = cfi->wrd_wr_time / 1000 + 1;
+       if (cfi->wrd_wr_time == 1)
+               /* Account for the timer resolution which is 1 ms */
+               cfi->wrd_wr_time = 2;
+       cfi->buf_wr_time  = 1 << cfi->cfiq->BufWriteTimeoutTyp;
+       cfi->buf_wr_time *= 1 << cfi->cfiq->BufWriteTimeoutMax;
+       /* Buffer write time is in us, convert to ms */
+       cfi->buf_wr_time  = cfi->buf_wr_time / 1000 + 1;
+       if (cfi->buf_wr_time == 1)
+               /* Account for the timer resolution which is 1 ms */
+               cfi->buf_wr_time = 2;
+       cfi->erase_time   = 1 << cfi->cfiq->BlockEraseTimeoutTyp;
+       cfi->erase_time  *= 1 << cfi->cfiq->BlockEraseTimeoutMax;
+       
+       info->size = (1 << cfi->cfiq->DevSize);
+       
+       info->sector_count = 0;
+       offset = CFG_FLASH_BASE;
+       for (i=0; i < cfi->cfiq->NumEraseRegions; i++) {
+               ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xFF);
+               ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xFFFF) + 1;
+               
+               for (j=0; j < ernum; j++) {
+                       info->start[info->sector_count + j] = offset;
+                       offset += ersize;
+               }
+
+               info->sector_count += ernum;
+       }
+
+       switch (cfi->mfr) {
+       case FUJ_MANUFACT_LS:
+               info->flash_id = FLASH_MAN_FUJ;
+               switch (cfi->id[0]) {
+               case AMD_ID_MIRROR_LS:
+                       if (cfi->id[1] == AMD_ID_LV320T_2_LS &&
+                           cfi->id[2] == AMD_ID_LV320T_3_LS) {
+                               info->flash_id += FLASH_AMLV320T;
+                               cfi->blk_write = flash_amdstd_wbuff;
+                               cfi->flash_name = "FUJITSU MBM29PL32TM";
+                       } else
+                               info->flash_id += FLASH_UNKNOWN;
+                       break;
+               default:
+                       info->flash_id += FLASH_UNKNOWN;
+                       break;
+               }
+               break;
+       case STM_MANUFACT_LS:
+               info->flash_id = FLASH_MAN_STM;
+               switch (cfi->id[0]) {
+               case STM_ID_29W320DT_LS:
+                       info->flash_id += FLASH_STMW320DT;
+                       cfi->blk_write = flash_amdstd_wubyp;
+                       cfi->flash_name = "STMICRO M29W320DT";
+                       break;
+               case STM_ID_29W320DB_LS:
+                       info->flash_id += FLASH_STMW320DB;
+                       cfi->blk_write = flash_amdstd_wubyp;
+                       cfi->flash_name = "STMICRO M29W320DB";
+                       break;
+               case STM_ID_29W324DT_LS:
+                       info->flash_id += FLASH_STMW324DT;
+                       cfi->blk_write = flash_amdstd_wubyp;
+                       cfi->flash_name = "STMICRO M29W324DT";
+                       break;
+               case STM_ID_29W324DB_LS:
+                       info->flash_id += FLASH_STMW324DB;
+                       cfi->blk_write = flash_amdstd_wubyp;
+                       cfi->flash_name = "STMICRO M29W324DB";
+                       break;
+               default:
+                       info->flash_id += FLASH_UNKNOWN;
+                       break;
+               }
+               break;
+       case MX_MANUFACT_LS:
+               info->flash_id = FLASH_MAN_MX;
+               switch (cfi->id[0]) {
+               case MX_ID_LV320T_LS:
+                       info->flash_id += FLASH_MXLV320T;
+                       cfi->blk_write = flash_amdstd_write;
+                       cfi->flash_name = "MXIC MX29LV320T";
+                       break;
+               default:
+                       info->flash_id += FLASH_UNKNOWN;
+                       break;
+               }
+               break;
+       default:
+               info->flash_id = FLASH_AMD_COMP;
+               break;
+       }
+
+       if ((info->flash_id & FLASH_TYPEMASK) == FLASH_UNKNOWN) {
+               /* Unknown but supported CFI flash */
+               cfi->flash_name = NULL;
+               if (cfi->cfiq->MaxBufWriteSize)
+                       cfi->blk_write = flash_amdstd_wbuff;
+               else
+                       cfi->blk_write = flash_amdstd_write;
+       }
+
+       cfi->blk_erase = flash_amdstd_erase;
+
+       return info->size;
+}
+
+#define BIT(x) (1<<x)
+/*
+ * Check the flash command state
+ */
+static int flash_amdstd_state(__u32 addr, __u32 target, int timeout)
+{
+       __u32 start_time = get_timer(0);
+       __u32 data;
+
+       debug("%s\n", __FUNCTION__);
+
+       do {
+               data = cfi_read8(addr);
+               if((data & BIT(7)) == (target & BIT(7)))
+                       return 0;
+               if(data & BIT(5)) {
+                       data = cfi_read8(addr);
+                       if((data & BIT(7)) == (target & BIT(7))) 
+                               return 0;
+                       else
+                               return -1;
+               }
+       } while (get_timer(start_time) < timeout);
+       return -1;
+}
+
+/*
+ * Verify data written to flash
+ */
+static int flash_amdstd_vrfy(flash_info_t *info, __u8 *buf, __u32 addr, int sz)
+{
+       __u32 base = cfi->base;
+       __u8  *faddr;
+       long  i;
+
+       debug("%s\n", __FUNCTION__);
+
+       faddr = (__u8 *)addr;
+       for(i=0; i < sz; i++) {
+               if(faddr[i] != buf[i]) {
+                       printf("Flash Write verify fail at %08x. ", &faddr[i]);
+                       printf("Expecting: %02X, Actual: %02X\n", faddr[i], buf[i]);
+                       printf("Retrying...");
+                       cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+                       cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
+                       cfi_cmd(0xA0, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+                       cfi_write8(buf[i], (__u32)&faddr[i]);
+                       if (flash_amdstd_state((__u32)&faddr[i], buf[i], cfi->wrd_wr_time)) {
+                               printf("failed again\n");
+                               cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
+                               return 1;
+                       } else
+                               printf("suceeded\n");
+               }
+       }
+       return 0;
+}
+
+/*
+ * Erase flash sectors
+ */
+static int flash_amdstd_erase(flash_info_t *info, int s_first, int s_last)
+{
+       int prot, sect, nsect, flag;
+       __u32 l_sect;
+       __u32 base = cfi->base;
+
+       debug("%s\n", __FUNCTION__);
+
+       if (!info->size) {
+               printf ("Flash erase: Can't erase unsupported flash\n");
+               return 1;
+       }
+
+       if (s_first < 0 || s_first > s_last    ||
+           s_first > (info->sector_count - 1) ||
+               s_last  > (info->sector_count - 1)) {
+               printf ("Flash erase: no sectors to erase\n");
+               return 1;
+       }
+
+       printf("\nFlash erase: first = %d @ 0x%08lx\n",
+               s_first, info->start[s_first]);
+       printf("             last  = %d @ 0x%08lx\n", s_last, info->start[s_last]);
+
+       nsect = s_last - s_first + 1;
+       for (prot = 0, sect=s_first; sect<=s_last; ++sect)
+               if (info->protect[sect])
+                       prot++;
+       if (prot) {
+               if (prot == nsect) {
+                       printf("Warning: All requested sectors are protected!\n");
+                       printf("         No sectors to erase\n");
+                       return 1;
+               }
+               else
+                       printf("Warning: %d protected sectors will not be erased!\n", prot);
+       }
+       cfi_cmd(0xF0, 0x00, base, CFI_DEVICETYPE_X8);
+       udelay(1000);
+
+       /* Disable interrupts which might cause a timeout here */
+       flag = disable_interrupts();
+
+       cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+       cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
+       cfi_cmd(0x80, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+       cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+       cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
+       for (sect = s_first; sect <= s_last; sect++)
+               if (!info->protect[sect]) {
+                       l_sect = info->start[sect];
+                       cfi_write8(0x30, l_sect);
+               }
+       /* Erase begins 50us after the last sector address */
+       udelay(50);
+
+       /* All erase commands sent, enable interrupts */
+       if (flag)
+               enable_interrupts();
+
+       if (flash_amdstd_state(l_sect, 0xff, cfi->erase_time * nsect)) {
+               printf("Flash erase: Timeout\n");
+               cfi_cmd(0xF0, 0x00, base, CFI_DEVICETYPE_X8);
+               return 1;
+       }
+       printf("Flash erase: Done\n");
+       return 0;
+}
+
+/*
+ * Write to flash using Write Buffer programming
+ */
+static int flash_amdstd_wbuff(flash_info_t *info, __u8 *buf, __u32 addr, int sz)
+{
+       __u32 base = cfi->base;
+       __u32 wbufsz;
+       __u32 size, wsize, waddr, saddr;
+       __u8 *wbuf;
+       int i;
+
+       debug("%s\n", __FUNCTION__);
+
+       size = sz;
+       wbuf = buf;
+       wbufsz = 1 << cfi->cfiq->MaxBufWriteSize;
+
+       waddr = (addr + wbufsz - 1) & ~(wbufsz - 1);
+       if (waddr > addr)
+               wsize = waddr-addr;
+       else
+               wsize = wbufsz;
+       if (wsize > size)
+               wsize = size;
+       waddr = addr;
+
+       while (size > 0) {
+               for (i = 0; i < info->sector_count; i++)
+                       if (waddr < info->start[i])
+                               break;
+               saddr = info->start[i-1];
+
+               cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+               cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
+               cfi_write8(0x25, saddr);
+               cfi_write8(wsize-1, saddr);
+               for (i = 0; i < wsize; i++)
+                       cfi_write8(*wbuf++, waddr++);
+               cfi_write8(0x29, saddr);
+
+       if (flash_amdstd_state(waddr-1, *(wbuf-1), cfi->buf_wr_time)) {
+                       printf("Flash write buffer: Timeout\n");
+                       cfi_cmd(0xF0, 0x00, base, CFI_DEVICETYPE_X8);
+                       return 1;
+               }
+
+               size -= wsize;
+               if ((wsize = wbufsz) > size)
+                       wsize = size;
+       }
+                       
+       return flash_amdstd_vrfy(info, buf, addr, sz);
+}
+
+/*
+ * Write to flash using Unlock Bypass command sequence
+ */
+static int flash_amdstd_wubyp(flash_info_t *info, __u8 *buf, __u32 addr, int sz)
+{
+       __u32 base = cfi->base;
+       __u32 waddr;
+       long  i;
+
+       debug("%s\n", __FUNCTION__);
+
+       waddr = addr;
+
+       cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+       cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
+       cfi_cmd(0x20, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+
+       for(i=0; i < sz; i++) {
+               cfi_write8(0xA0, waddr);
+               cfi_write8(buf[i], waddr);
+               if (flash_amdstd_state(waddr, buf[i], cfi->wrd_wr_time)) {
+                       printf("Flash unlock bypass write: Timeout\n");
+                       cfi_cmd(0x90, 0, base, CFI_DEVICETYPE_X8);
+                       cfi_cmd(0x00, 0, base, CFI_DEVICETYPE_X8);
+                       cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
+                       return 1;
+               }
+               waddr++;
+       }
+       cfi_cmd(0x90, 0, base, CFI_DEVICETYPE_X8);
+       cfi_cmd(0x00, 0, base, CFI_DEVICETYPE_X8);
+       cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
+
+       return flash_amdstd_vrfy(info, buf, addr, sz);
+}
+
+/*
+ * Write to flash using Word/Byte Program command sequence
+ */
+static int flash_amdstd_write(flash_info_t *info, __u8 *buf, __u32 addr, int sz)
+{
+       __u32 base = cfi->base;
+       __u32 waddr;
+       long  i;
+
+       debug("%s\n", __FUNCTION__);
+
+       waddr = addr;
+
+       cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
+       for (i = 0; i < sz; i++) {
+               cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+               cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
+               cfi_cmd(0xA0, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
+               cfi_write8(buf[i], waddr);
+               if (flash_amdstd_state(waddr, buf[i], cfi->wrd_wr_time)) {
+                       printf("Flash write: Timeout\n");
+                       cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
+                       return 1;
+               }
+               waddr++;
+       }
+       cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
+
+       return flash_amdstd_vrfy(info, buf, addr, sz);
+}
+
+/* vim: set ts=4: */
diff --git a/board/linkstation/hwctl.c b/board/linkstation/hwctl.c
new file mode 100644 (file)
index 0000000..93b7e05
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * hwctl.c
+ *
+ * LinkStation HW Control Driver
+ *
+ * Copyright (C) 2001-2004  BUFFALO INC.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by reference.
+ * Drivers based on or derived from this code fall under the GPL and must
+ * retain the authorship, copyright and license notice.  This file is not
+ * a complete program and may only be used when the entire operating
+ * system is licensed under the GPL.
+ *
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+
+#define mdelay(n)      udelay((n)*1000)
+
+#define AVR_PORT CFG_NS16550_COM2
+extern void udelay(unsigned long usec);
+
+
+// output BYTE data
+static inline void out_b(volatile unsigned char *addr, int val)
+{
+       __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
+}
+
+#if 0
+// PWR,DISK_FULL/STATUS,DIAG LED controll
+void blink_led(unsigned char state)
+{
+#ifdef CONFIG_HTGL
+       switch (state)
+       {
+               case FLASH_CLEAR_START:
+               case FLASH_UPDATE_START:
+                       out_b(AVR_PORT, 0x61);
+                       out_b(AVR_PORT, 0x61);
+                       out_b(AVR_PORT, 0x38);
+                       out_b(AVR_PORT, 0x30);
+                       out_b(AVR_PORT, 0x34);
+                       out_b(AVR_PORT, 0x31);
+                       mdelay(10);
+                       out_b(AVR_PORT, 0x61);
+                       out_b(AVR_PORT, 0x61);
+                       out_b(AVR_PORT, 0x38);
+                       out_b(AVR_PORT, 0x31);
+                       out_b(AVR_PORT, 0x34);
+                       out_b(AVR_PORT, 0x31);
+                       mdelay(10);
+                       out_b(AVR_PORT, 0x71);
+                       out_b(AVR_PORT, 0x71);
+//                     out_b(AVR_PORT, 0x71);
+//                     out_b(AVR_PORT, 0x71);
+                       mdelay(10);
+                       out_b(AVR_PORT, 0x73);
+                       out_b(AVR_PORT, 0x73);
+//                     out_b(AVR_PORT, 0x73);
+//                     out_b(AVR_PORT, 0x73);
+                       mdelay(10);
+                       break;
+               case FLASH_CLEAR_END:
+               case FLASH_UPDATE_END:
+                       out_b(AVR_PORT, 0x70);
+                       out_b(AVR_PORT, 0x70);
+//                     out_b(AVR_PORT, 0x70);
+//                     out_b(AVR_PORT, 0x70);
+                       mdelay(10);
+                       out_b(AVR_PORT, 0x72);
+                       out_b(AVR_PORT, 0x72);
+//                     out_b(AVR_PORT, 0x72);
+//                     out_b(AVR_PORT, 0x72);
+                       mdelay(10);
+                       break;
+               case RAID_RESYNC_START:
+                       break;
+               case RAID_RESYNC_END:
+                       break;
+               default:
+                       out_b(AVR_PORT, state);
+                       out_b(AVR_PORT, state);
+                       out_b(AVR_PORT, state);
+                       out_b(AVR_PORT, state);
+                       break;
+       }
+#else
+       out_b(AVR_PORT, state);
+       out_b(AVR_PORT, state);
+       out_b(AVR_PORT, state);
+       out_b(AVR_PORT, state);
+#endif
+
+}
+#endif
+
+// 2005.5.10 BUFFALO add
+//--------------------------------------------------------------
+static inline void miconCntl_SendUart(unsigned char dat)
+{
+       out_b((char *)AVR_PORT, dat);
+       udelay(1000);
+}
+
+//--------------------------------------------------------------
+void miconCntl_SendCmd(unsigned char dat)
+{
+       int i;
+       
+       for (i=0; i<4; i++){
+               miconCntl_SendUart(dat);
+       }
+}
+
+//--------------------------------------------------------------
+void miconCntl_FanLow(void)
+{
+       debug("%s\n",__FUNCTION__);
+#ifdef CONFIG_HTGL
+       miconCntl_SendCmd(0x5C);
+#endif
+}
+//--------------------------------------------------------------
+void miconCntl_FanHigh(void)
+{
+       debug("%s\n",__FUNCTION__);
+#ifdef CONFIG_HTGL
+       miconCntl_SendCmd(0x5D);
+#endif
+}
+
+//--------------------------------------------------------------
+//1000Mbps
+void miconCntl_Eth1000M(int up)
+{
+       debug("%s (%d)\n",__FUNCTION__,up);
+#ifdef CONFIG_HTGL
+       if (up){
+               miconCntl_SendCmd(0x93);
+       }else{
+               miconCntl_SendCmd(0x92);
+       }
+#else
+       if (up){
+               miconCntl_SendCmd(0x5D);
+       }else{
+               miconCntl_SendCmd(0x5C);
+       }
+#endif
+}
+//--------------------------------------------------------------
+//100Mbps
+void miconCntl_Eth100M(int up)
+{
+       debug("%s (%d)\n",__FUNCTION__,up);
+#ifdef CONFIG_HTGL
+       if (up){
+               miconCntl_SendCmd(0x91);
+       }else{
+               miconCntl_SendCmd(0x90);
+       }
+#else
+       if (up){
+               miconCntl_SendCmd(0x5C);
+       }
+#endif
+}
+//--------------------------------------------------------------
+//10Mbps
+void miconCntl_Eth10M(int up)
+{
+       debug("%s (%d)\n",__FUNCTION__,up);
+#ifdef CONFIG_HTGL
+       if (up){
+               miconCntl_SendCmd(0x8F);
+       }else{
+               miconCntl_SendCmd(0x8E);
+       }
+#else
+       if (up){
+               miconCntl_SendCmd(0x5C);
+       }
+#endif
+}
+//--------------------------------------------------------------
+//��������
+void miconCntl_5f(void)
+{
+       debug("%s\n",__FUNCTION__);
+       miconCntl_SendCmd(0x5F);
+       mdelay(100);
+}
+
+//--------------------------------------------------------------
+// "reboot start" signal
+void miconCntl_Reboot(void)
+{
+       debug("%s\n",__FUNCTION__);
+       miconCntl_SendCmd(0x43);
+}
+#if 0
+//--------------------------------------------------------------
+// Raid recovery start
+void miconCntl_RadiRecovery(void)
+{
+       debug("%s\n",__FUNCTION__);
+#ifdef CONFIG_HTGL
+       miconCntl_SendUart(0x61); // a
+       miconCntl_SendUart(0x61); // a
+       miconCntl_SendUart(0x38); // 8
+       miconCntl_SendUart(0x30); // 0
+       miconCntl_SendUart(0x34); // 4
+       miconCntl_SendUart(0x31); // 1
+       miconCntl_SendCmd(0x71); // q
+#endif
+}
+//--------------------------------------------------------------
+// Raid recovery finish
+void miconCntl_RadiRecoveryFin(void)
+{
+       debug("%s\n",__FUNCTION__);
+#ifdef CONFIG_HTGL
+       miconCntl_SendCmd(0x70);
+#endif
+}
+#endif
+
+// ---------------------------------------------------------------
+// Disable watchdog timer
+void miconCntl_DisWDT(void)
+{
+       debug("%s\n",__FUNCTION__);
+       miconCntl_SendCmd(0x41); // A
+       miconCntl_SendCmd(0x46); // F
+       miconCntl_SendCmd(0x4A); // J
+       miconCntl_SendCmd(0x3E); // >
+       miconCntl_SendCmd(0x56); // V
+       miconCntl_SendCmd(0x3E); // >
+       miconCntl_SendCmd(0x5A); // Z
+       miconCntl_SendCmd(0x56); // V
+       miconCntl_SendCmd(0x4B); // K
+}
+// ---------------------------------------------------------------
+// U-Boot calls this function
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       disable_interrupts();
+       miconCntl_Reboot();
+       while (1)
+               miconCntl_SendUart(0x47);       /* Wait for reboot */
+
+}
+
+/* vim: set ts=4: */
diff --git a/board/linkstation/ide.c b/board/linkstation/ide.c
new file mode 100644 (file)
index 0000000..008ae52
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * (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
+ *
+ */
+/* ide.c - ide support functions */
+
+
+#include <common.h>
+
+#ifdef CFG_CMD_IDE
+#include <ata.h>
+#include <ide.h>
+#include <pci.h>
+
+#define IT8212_PCI_CpuCONTROL                  0x5e
+#define IT8212_PCI_PciModeCONTROL              0x50
+#define IT8212_PCI_IdeIoCONFIG                 0x40
+#define IT8212_PCI_IdeBusSkewCONTROL   0x4c
+#define IT8212_PCI_IdeDrivingCURRENT   0x42
+
+extern ulong ide_bus_offset[CFG_IDE_MAXBUS];
+extern struct pci_controller hose;
+
+int ide_preinit (void)
+{
+       int status;
+       pci_dev_t devbusfn;
+       int l;
+
+       status = 1;
+       for (l = 0; l < CFG_IDE_MAXBUS; l++) {
+               ide_bus_offset[l] = -ATA_STATUS;
+       }
+       devbusfn = pci_find_device (PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680, 0);
+       if (devbusfn == -1)
+               devbusfn = pci_find_device (PCI_VENDOR_ID_ITE,PCI_DEVICE_ID_ITE_8212,0);
+       if (devbusfn != -1) {
+               status = 0;
+
+               pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0,
+                                                          (u32 *) &ide_bus_offset[0]);
+               ide_bus_offset[0] &= 0xfffffffe;
+               ide_bus_offset[0] = pci_hose_bus_to_phys(&hose,
+                                                                                                ide_bus_offset[0] & 0xfffffffe,
+                                                                                                PCI_REGION_IO);
+               pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_2,
+                                                          (u32 *) &ide_bus_offset[1]);
+               ide_bus_offset[1] &= 0xfffffffe;
+               ide_bus_offset[1] = pci_hose_bus_to_phys(&hose,
+                                                                                                ide_bus_offset[1] & 0xfffffffe,
+                                                                                                PCI_REGION_IO);
+       }
+
+       if (pci_find_device (PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212, 0) != -1) {
+               pci_write_config_byte(devbusfn, IT8212_PCI_CpuCONTROL, 0x01);
+               pci_write_config_byte(devbusfn, IT8212_PCI_PciModeCONTROL, 0x00);
+               pci_write_config_word(devbusfn, PCI_COMMAND, 0x0047);
+#ifdef CONFIG_IT8212_SECONDARY_ENABLE
+               pci_write_config_word(devbusfn, IT8212_PCI_IdeIoCONFIG, 0xA0F3);
+#else
+               pci_write_config_word(devbusfn, IT8212_PCI_IdeIoCONFIG, 0x8031);
+#endif
+               pci_write_config_dword(devbusfn, IT8212_PCI_IdeBusSkewCONTROL, 0x02040204);
+// __LS_COMMENT__ BUFFALO changed 2004.11.10  changed for EMI
+        pci_write_config_byte(devbusfn, IT8212_PCI_IdeDrivingCURRENT, 0x36); // 10mA
+//      pci_write_config_byte(dev, IT8212_PCI_IdeDrivingCURRENT, 0x09); // 4mA
+//      pci_write_config_byte(dev, IT8212_PCI_IdeDrivingCURRENT, 0x12); // 6mA
+//      pci_write_config_byte(dev, IT8212_PCI_IdeDrivingCURRENT, 0x24); // 6mA,2mA
+//      pci_write_config_byte(dev, IT8212_PCI_IdeDrivingCURRENT, 0x2D); // 8mA,4mA
+        pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x00);
+       }
+
+       return (status);
+}
+
+void ide_set_reset (int flag) {
+       return;
+}
+
+#endif /* of CONFIG_CMDS_IDE */
+
+/* vim: set ts=4: */
diff --git a/board/linkstation/linkstation.c b/board/linkstation/linkstation.c
new file mode 100644 (file)
index 0000000..cfa4057
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * linkstation.c
+ *
+ * Misc LinkStation specific functions
+ *
+ * Copyright (C) 2006 Mihai Georgin <u-boot@linuxnotincluded.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 <version.h>
+#include <common.h>
+#include <mpc824x.h>
+#include <asm/io.h>
+#include <ns16550.h>
+
+#ifdef CONFIG_PCI
+#include <pci.h>
+#endif
+
+extern void init_AVR_DUART(void);
+extern void hw_watchdog_reset(void);
+
+int checkboard (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+       ulong busfreq = get_bus_freq (0);
+       char buf[32];
+       char *p;
+       bd_t *bd = gd->bd;
+
+       init_AVR_DUART();
+       hw_watchdog_reset();
+
+       if ((p = getenv ("console_nr")) != NULL) {
+               unsigned long con_nr = simple_strtoul (p, NULL, 10) & 3;
+
+               bd->bi_baudrate &= ~3;
+               bd->bi_baudrate |= con_nr & 3;
+       }
+       return 0;
+}
+
+long int initdram (int board_type)
+{
+       return (get_ram_size(CFG_SDRAM_BASE, CFG_MAX_RAM_SIZE));
+}
+
+/*
+ * Initialize PCI Devices
+ */
+#ifdef CONFIG_PCI
+
+#ifndef CONFIG_PCI_PNP
+
+static struct pci_config_table pci_linkstation_config_table[] = {
+       /* vendor, device, class */
+       /* bus, dev, func */
+       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_ANY_ID, 0x0b, 0,          /* AN983B or RTL8110S  */
+                                                               /* ethernet controller */
+         pci_cfgfunc_config_device, { PCI_ETH_IOADDR,
+                                      PCI_ETH_MEMADDR,
+                                      PCI_COMMAND_IO |
+                                      PCI_COMMAND_MEMORY |
+                                      PCI_COMMAND_MASTER }},
+       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_ANY_ID, 0x0c, 0,          /* SII680 or IT8211AF */
+                                                               /* ide controller     */
+         pci_cfgfunc_config_device, { PCI_IDE_IOADDR,
+                                      PCI_IDE_MEMADDR,
+                                      PCI_COMMAND_IO |
+                                      PCI_COMMAND_MEMORY |
+                                      PCI_COMMAND_MASTER }},
+       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_ANY_ID, 0x0e, 0,          /* D720101 USB controller, 1st USB 1.1 */
+         pci_cfgfunc_config_device, { PCI_USB0_IOADDR,
+                                      PCI_USB0_MEMADDR,
+                                      PCI_COMMAND_MEMORY |
+                                      PCI_COMMAND_MASTER }},
+       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_ANY_ID, 0x0e, 1,          /* D720101 USB controller, 2nd USB 1.1 */
+         pci_cfgfunc_config_device, { PCI_USB1_IOADDR,
+                                      PCI_USB1_MEMADDR,
+                                      PCI_COMMAND_MEMORY |
+                                      PCI_COMMAND_MASTER }},
+       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_ANY_ID, 0x0e, 2,          /* D720101 USB controller, USB 2.0 */
+         pci_cfgfunc_config_device, { PCI_USB2_IOADDR,
+                                      PCI_USB2_MEMADDR,
+                                      PCI_COMMAND_MEMORY |
+                                      PCI_COMMAND_MASTER }},
+       { }
+};
+#endif
+
+struct pci_controller hose = {
+#ifndef CONFIG_PCI_PNP
+       config_table:pci_linkstation_config_table,
+#endif
+};
+
+void pci_init_board (void)
+{
+       pci_mpc824x_init (&hose);
+
+       /* Reset USB 1.1 */
+       out_le32(PCI_USB0_MEMADDR+8, 1);
+       out_le32(PCI_USB1_MEMADDR+8, 1);
+
+}
+#endif /* CONFIG_PCI */
+
+/* vim: set ts=4: */
diff --git a/board/linkstation/nc.sh b/board/linkstation/nc.sh
new file mode 100644 (file)
index 0000000..7d552d0
--- /dev/null
@@ -0,0 +1,10 @@
+#! /bin/bash
+
+[ $# = 1 ] || { echo "Usage: $0 target_ip" >&2 ; exit 1 ; }
+TARGET_IP=$1
+
+stty -icanon -echo intr ^T
+#nc -u -l -p 6666 < /dev/null &
+nc -u -p 6666 -v -v ${TARGET_IP} 6666
+stty icanon echo intr ^C
+
diff --git a/board/linkstation/u-boot.lds b/board/linkstation/u-boot.lds
new file mode 100644 (file)
index 0000000..78ff35c
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * (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
+ */
+
+OUTPUT_ARCH(powerpc)
+/*
+SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); SEARCH_DIR(/usr/lib/gcc-lib/ppc-linux/3.3.3);
+*/
+/* 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/mpc824x/start.o                (.text)
+    lib_ppc/board.o            (.text)
+    lib_ppc/ppcstring.o                (.text)
+    lib_generic/vsprintf.o     (.text)
+    lib_generic/crc32.o                (.text)
+    lib_generic/zlib.o         (.text)
+
+    . = DEFINED(env_offset) ? env_offset : .;
+    common/environment.o       (.text)
+
+    *(.text)
+
+    *(.fixup)
+    *(.got1)
+    . = ALIGN(16);
+    *(.rodata)
+    *(.rodata1)
+    *(.rodata.str1.4)
+    *(.eh_frame)
+  }
+  .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 = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  . = .;
+  __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/include/configs/linkstation.h b/include/configs/linkstation.h
new file mode 100644 (file)
index 0000000..b616e5e
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 0
+#define DEBUG
+#endif
+
+/*-----------------------------------------------------------------------
+ * User configurable settings:
+ *   Mandatory settings:
+ *     CONFIG_IPADDR_LS                - the IP address of the LinkStation
+ *     CONFIG_SERVERIP_LS      - the address of the server for NFS/TFTP/DHCP/BOOTP
+ *   Optional settins:
+ *     CONFIG_NCIP_LS          - the adress of the computer running net console
+ *                                                       if not configured, it will be set to
+ *                                                       CONFIG_SERVERIP_LS
+ */
+
+#define CONFIG_IPADDR_LS       192.168.11.150
+#define CONFIG_SERVERIP_LS     192.168.11.149
+
+#if !defined(CONFIG_IPADDR_LS) || !defined(CONFIG_SERVERIP_LS)
+#error Both CONFIG_IPADDR_LS and CONFIG_SERVERIP_LS must be defined
+#endif
+
+#if !defined(CONFIG_NCIP_LS)
+#define CONFIG_NCIP_LS         CONFIG_SERVERIP_LS
+#endif
+
+/*----------------------------------------------------------------------
+ * DO NOT CHANGE ANYTHING BELOW, UNLESS YOU KNOW WHAT YOU ARE DOING
+ *---------------------------------------------------------------------*/
+
+#define CONFIG_MPC8245         1
+#define CONFIG_LINKSTATION     1
+
+/*---------------------------------------
+ * Supported models
+ *
+ * LinkStation HDLAN /KuroBox Standard (CONFIG_HLAN)
+ * LinkStation old model               (CONFIG_LAN) - totally untested
+ * LinkStation HGLAN / KuroBox HG      (CONFIG_HGLAN)
+ *
+ * Models not supported yet
+ * TeraStatin                          (CONFIG_HTGL)
+ */
+
+#if defined(CONFIG_HLAN) || defined(CONFIG_LAN)
+#define CONFIG_IDENT_STRING            " LinkStation / KuroBox"
+#elif defined(CONFIG_HGLAN)
+#define CONFIG_IDENT_STRING            " LinkStation HG / KuroBox HG"
+#elif defined(CONFIG_HTGL)
+#define CONFIG_IDENT_STRING            " TeraStation"
+#else
+#error No LinkStation model defined
+#endif
+
+#define CONFIG_BOOTDELAY       10
+#define CONFIG_ZERO_BOOTDELAY_CHECK
+#undef CONFIG_BOOT_RETRY_TIME
+
+#define CONFIG_AUTOBOOT_KEYED
+#define CONFIG_AUTOBOOT_PROMPT         "Boot in %02d seconds ('s' to stop)..."
+#define CONFIG_AUTOBOOT_STOP_STR       "s"
+
+#define CONFIG_COMMANDS           (CFG_CMD_BDI         | \
+                                                       CFG_CMD_LOADS   | \
+                                                       CFG_CMD_LOADB   | \
+                                                       CFG_CMD_FLASH   | \
+                                                       CFG_CMD_MEMORY  | \
+                                                       CFG_CMD_NET             | \
+                                                       CFG_CMD_ENV             | \
+                                                       CFG_CMD_IDE             | \
+                                                       CFG_CMD_PCI             | \
+                                                       CFG_CMD_BOOTD   | \
+                                                       CFG_CMD_CONSOLE | \
+                                                       CFG_CMD_RUN             | \
+                                                       CFG_CMD_ECHO    | \
+                                                       CFG_CMD_DHCP    | \
+                                                       CFG_CMD_PING    | \
+                                                       CFG_CMD_NFS             | \
+                                                       CFG_CMD_EXT2    )
+#define CONFIG_BOOTP_MASK   CONFIG_BOOTP_ALL
+
+/* 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      */
+
+#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  0x00800000      /* Default load address: 8 MB   */
+
+//#define CONFIG_BOOTCOMMAND   "run nfsboot"
+#define CONFIG_BOOTCOMMAND     "run bootcmd1"
+#define CONFIG_BOOTARGS                        "root=/dev/hda1"
+#define CONFIG_NFSBOOTCOMMAND          "bootp;run nfsargs;bootm"
+
+#define CFG_CONSOLE_IS_IN_ENV
+
+#define XMK_STR(x)             #x
+#define MK_STR(x)              XMK_STR(x)
+
+#if defined(CONFIG_HLAN) || defined(CONFIG_LAN)
+#define UBFILE                 "share/u-boot/u-boot-hd.flash.bin"
+#elif defined(CONFIG_HGLAN)
+#define UBFILE                 "share/u-boot/u-boot-hg.flash.bin"
+#elif defined(CONFIG_HTGL)
+#define UBFILE                 "share/u-boot/u-boot-ht.flash.bin"
+#else
+#error No LinkStation model defined
+#endif
+
+#define CONFIG_EXTRA_ENV_SETTINGS                              \
+    "autoload=no\0"                                                            \
+       "stdin=nc\0"                                                            \
+       "stdout=nc\0"                                                           \
+       "stderr=nc\0"                                                           \
+       "ipaddr="MK_STR(CONFIG_IPADDR_LS)"\0"           \
+       "netmask=255.255.255.0\0"                                       \
+       "serverip="MK_STR(CONFIG_SERVERIP_LS)"\0"       \
+       "ncip="MK_STR(CONFIG_NCIP_LS)"\0"                       \
+       "netretry=no\0"                                                         \
+       "nc=setenv stdin nc;setenv stdout nc;setenv stderr nc\0"        \
+       "ser=setenv stdin serial;setenv stdout serial;setenv stderr serial\0"   \
+    "ldaddr=800000\0"                                                  \
+    "hdpart=0:1\0"                                                             \
+    "hdfile=boot/vmlinux.UBoot\0"                              \
+    "hdload=echo Loading ${hdpart}:${hdfile};ext2load ide ${hdpart} ${ldaddr} ${hdfile}\0"     \
+    "boothd=setenv bootargs root=/dev/hda1;bootm ${ldaddr}\0"  \
+    "hdboot=run hdload boothd\0"                               \
+    "flboot=setenv bootargs root=/dev/hda1;bootm ffc00000\0"   \
+    "emboot=setenv bootargs root=/dev/ram0;bootm ffc00000\0"   \
+       "nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath} "     \
+       "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off\0"   \
+       "bootretry=30\0"                                                        \
+       "bootcmd1=run hdboot;run flboot\0"                      \
+       "bootcmd2=run flboot\0"                                         \
+       "bootcmd3=run emboot\0"                                         \
+       "writeng=protect off fff70000 fff7ffff;era fff70000 fff7ffff;mw.l 800000 4e474e47 1;cp.b 800000 fff70000 4\0" \
+       "writeok=protect off fff70000 fff7ffff;era fff70000 fff7ffff;mw.l 800000 4f4b4f4b 1;cp.b 800000 fff70000 4\0" \
+       "ubpart=0:3\0"                                                          \
+       "ubfile="UBFILE"\0"                                                     \
+       "ubload=echo Loading ${ubpart}:${ubfile};ext2load ide ${ubpart} ${ldaddr} ${ubfile}\0" \
+       "ubsaddr=fff00000\0"                                            \
+       "ubeaddr=fff2ffff\0"                                            \
+       "ubflash=protect off ${ubsaddr} ${ubeaddr};era ${ubsaddr} ${ubeaddr};cp.b ${ldaddr} ${ubsaddr} ${filesize};cmp.b ${ldaddr} ${ubsaddr} ${filesize}\0" \
+       "upgrade=run ubload ubflash\0"
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ */
+#define CONFIG_PCI
+#undef  CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+
+#ifndef CONFIG_PCI_PNP
+/* Keep the following defines in sync with the BAT mappings */
+
+#define PCI_ETH_IOADDR      0xbfff00
+#define PCI_ETH_MEMADDR     0xbffffc00
+#define PCI_IDE_IOADDR      0xbffed0
+#define PCI_IDE_MEMADDR     0xbffffb00
+#define PCI_USB0_IOADDR     0
+#define PCI_USB0_MEMADDR    0xbfffe000
+#define PCI_USB1_IOADDR     0
+#define PCI_USB1_MEMADDR    0xbfffd000
+#define PCI_USB2_IOADDR     0
+#define PCI_USB2_MEMADDR    0xbfffcf00
+
+#endif
+
+/*-----------------------------------------------------------------------
+ * Ethernet stuff
+ */
+#define CONFIG_NET_MULTI
+
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
+#define CONFIG_TULIP
+#define CONFIG_TULIP_USE_IO
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+#define CONFIG_RTL8169
+#endif
+
+#define CONFIG_NET_RETRY_COUNT         5
+
+#define CONFIG_NETCONSOLE
+
+/*-----------------------------------------------------------------------
+ * 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
+
+#define CFG_RESET_ADDRESS      0xFFF00100
+#define CFG_EUMB_ADDR          0x80000000
+#define CFG_PCI_MEM_ADDR               0xB0000000
+#define CFG_MISC_REGION_ADDR   0xFE000000
+
+#define CFG_MONITOR_LEN        0x00040000      /* 256 kB */
+#define CFG_MALLOC_LEN         (512 << 10) /* Reserve some kB for malloc() */
+
+#define CFG_MEMTEST_START      0x00100000      /* memtest works on             */
+#define CFG_MEMTEST_END                0x00800000      /* 1M ... 8M in DRAM    */
+
+/* Maximum amount of RAM */
+#if defined(CONFIG_HLAN) || defined(CONFIG_LAN)
+#define CFG_MAX_RAM_SIZE       0x04000000      /* 64MB of SDRAM  */
+#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
+#define CFG_MAX_RAM_SIZE       0x08000000      /* 128MB of SDRAM */
+#else
+#error Unknown LinkStation type
+#endif
+
+/*-----------------------------------------------------------------------
+ * Change TEXT_BASE in bord/linkstation/config.mk to get a RAM build
+ *
+ * RAM based builds are for testing purposes. A Linux module, uloader.o,
+ * exists to load U-Boot and pass control to it
+ *
+ * Always do "make clean" after changing the build type
+ */
+#if CFG_MONITOR_BASE < CFG_FLASH_BASE
+#define CFG_RAMBOOT
+#endif
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area
+ */
+#if 1 /* RAM is available when the first C function is called */
+#define CFG_INIT_RAM_ADDR              (CFG_SDRAM_BASE + CFG_MAX_RAM_SIZE - 0x1000)
+#else
+#define CFG_INIT_RAM_ADDR              0x40000000
+#endif
+#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)
+
+/*----------------------------------------------------------------------
+ * Serial configuration
+ */
+#define CONFIG_CONS_INDEX      1
+#define CONFIG_BAUDRATE                57600
+#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                get_bus_freq(0)
+
+#define CFG_NS16550_COM1       (CFG_EUMB_ADDR + 0x4600)        /* Console port */
+#define CFG_NS16550_COM2       (CFG_EUMB_ADDR + 0x4500)        /* AVR port */
+
+/*
+ * 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 MPC8245 user's manual.
+ *
+ * Unless indicated otherwise, the values are
+ * taken from the orignal Linkstation boot code
+ *
+ * Most of the low level configuration setttings are normally used
+ * in cpu/mpc824x/cpu_init.c which is NOT used by this implementation.
+ * Low level initialisation is done in board/linkstation/early_init.S
+ * The values below are included for reference purpose only
+ */
+
+/* FIXME: 32.768 MHz is the crystal frequency but */
+/* the real frequency is lower by about 0.75%     */
+#define CONFIG_SYS_CLK_FREQ  32768000
+#define CFG_HZ                  1000
+
+/* Bit-field values for MCCR1.  */
+#define CFG_ROMNAL      0
+#define CFG_ROMFAL      11
+
+#define CFG_BANK0_ROW  2       /* Only bank 0 used: 13 x n x 4 */
+#define CFG_BANK1_ROW  0
+#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
+
+/* Bit-field values for MCCR2.  */
+#define CFG_TSWAIT      0
+#define CFG_REFINT      1400
+
+/* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4.  */
+#define CFG_BSTOPRE     121
+
+/* Bit-field values for MCCR3.  */
+#define CFG_REFREC      7
+
+/* Bit-field values for MCCR4.  */
+#define CFG_PRETOACT    2
+#define CFG_ACTTOPRE    5              /* Original value was 2 */
+#define CFG_ACTORW      2
+#define CFG_SDMODE_CAS_LAT  2  /* For 100MHz bus. Use 3 for 133MHz */
+#define CFG_REGISTERD_TYPE_BUFFER 1
+#define CFG_EXTROM      1              /* Original setting but there is no EXTROM */
+#define CFG_REGDIMM     0
+#define CFG_DBUS_SIZE2  1
+#define CFG_SDMODE_WRAP 0
+
+#define CFG_PGMAX       0x32   /* All boards use this setting. Original 0x92 */
+#define CFG_SDRAM_DSCD  0x30
+
+/* 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           0x95                /* 0x15 or 0x95 ? */
+
+/*----------------------------------------------------------------------
+ * Initial BAT mappings
+ */
+
+/* NOTES:
+ * 1) GUARDED and WRITETHROUGH not allowed in IBATS
+ * 2) CACHEINHIBIT and WRITETHROUGH not allowed together in same BAT
+ */
+
+/* SDRAM */
+#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_128M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L CFG_IBAT0L
+#define CFG_DBAT0U CFG_IBAT0U
+
+/* EUMB: 1MB of address space */
+#define CFG_IBAT1L (CFG_EUMB_ADDR | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT1U (CFG_EUMB_ADDR | BATU_BL_1M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT1L (CFG_IBAT1L | BATL_GUARDEDSTORAGE)
+#define CFG_DBAT1U CFG_IBAT1U
+
+/* PCI Mem: 256MB of address space */
+#define CFG_IBAT2L  (CFG_PCI_MEM_ADDR | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U  (CFG_PCI_MEM_ADDR | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT2L  (CFG_IBAT2L | BATL_GUARDEDSTORAGE)
+#define CFG_DBAT2U  CFG_IBAT2U
+
+/* PCI and local ROM/Flash: last 32MB of address space */
+#define CFG_IBAT3L (CFG_MISC_REGION_ADDR | BATL_PP_10 | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U (CFG_MISC_REGION_ADDR | BATU_BL_32M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT3L (CFG_IBAT3L | 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.
+ *
+ * FIXME: This doesn't appear to be true for the newer kernels
+ * which map more that 8 MB
+ */
+#define CFG_BOOTMAPSZ      (8 << 20)   /* Initial Memory map for Linux */
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#undef  CFG_FLASH_PROTECTION
+#define CFG_MAX_FLASH_BANKS            1       /* Max number of flash banks            */
+#define CFG_MAX_FLASH_SECT             72      /* Max number of sectors per flash      */
+
+#define CFG_FLASH_ERASE_TOUT   12000
+#define CFG_FLASH_WRITE_TOUT   1000
+
+
+#define CFG_ENV_IS_IN_FLASH
+/*
+ * The original LinkStation flash organisation uses
+ * 448 kB (0xFFF00000 - 0xFFF6FFFF) for the boot loader
+ * We use the last sector of this area to store the environment
+ * which leaves max. 384 kB for the U-Boot itself
+ */
+#define CFG_ENV_ADDR           0xFFF60000
+#define CFG_ENV_SIZE           0x00010000
+#define CFG_ENV_SECT_SIZE      0x00010000
+
+/*-----------------------------------------------------------------------
+ * 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
+
+/*-----------------------------------------------------------------------
+ * IDE/ATA definitions
+ */
+#undef  CONFIG_IDE_LED                                 /* No IDE LED                                   */
+#define CONFIG_IDE_RESET                               /* no reset for ide supported   */
+#define CONFIG_IDE_PREINIT                             /* check for units                              */
+#define CONFIG_LBA48                                   /* 48 bit LBA supported                 */
+
+#if defined(CONFIG_LAN) || defined(CONFIG_HLAN) || defined(CONFIG_HGLAN)
+#define CFG_IDE_MAXBUS                 1               /* Scan only 1 IDE bus                  */
+#define CFG_IDE_MAXDEVICE              1               /* Only 1 drive per IDE bus             */
+#elif defined(CONFIG_HGTL)
+#define CFG_IDE_MAXBUS                 2               /* Max. 2 IDE busses                    */
+#define CFG_IDE_MAXDEVICE              2               /* max. 2 drives per IDE bus    */
+#else
+#error Config IDE: Unknown LinkStation type
+#endif
+
+#define CFG_ATA_BASE_ADDR              0
+
+#define CFG_ATA_DATA_OFFSET            0               /* Offset for data I/O                  */
+#define CFG_ATA_REG_OFFSET             0               /* Offset for normal registers  */
+#define CFG_ATA_ALT_OFFSET             0               /* Offset for alternate registers */
+
+/*-----------------------------------------------------------------------
+ * Partitions and file system
+ */
+#define CONFIG_DOS_PARTITION
+
+/*-----------------------------------------------------------------------
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM          0x02    /* Software reboot                      */
+
+#endif /* __CONFIG_H */
+
+/* vim: set ts=4: */