hipox: HIPOX machine uses u-boot-2009.03 for NOR/NAND combi boot
authorSteffen Sledz <sledz@dresearch.de>
Wed, 15 Apr 2009 12:59:55 +0000 (14:59 +0200)
committerSteffen Sledz <sledz@dresearch.de>
Wed, 15 Apr 2009 12:59:55 +0000 (14:59 +0200)
conf/checksums.ini
conf/machine/hipox.conf
recipes/linux/linux-2.6.24/hipox/hipox.patch
recipes/u-boot/u-boot-2009.03/hipox/00-hipox.patch [new file with mode: 0644]
recipes/u-boot/u-boot_2009.03.bb [new file with mode: 0644]

index ad93c75..c9a1707 100644 (file)
@@ -22818,6 +22818,10 @@ sha256=5cd64b5ac52720a7f60015e01696422277ecc459e89dce8b16d457f30a9409ab
 md5=cb11d3d74eee4d31124523d90d8c31fa
 sha256=0c0afa2816482e087987f71958b656ff0c122032f5e3897a8d17daca5bc14115
 
+[ftp://ftp.denx.de/pub/u-boot/u-boot-2009.03.tar.bz2]
+md5=285e2184d2efef50e0fe43b71d2a7b11
+sha256=a2889bee9c45575b284564dbc27cf3dc6cb9833d4ff643976a1b3dba2d763f86
+
 [http://linux.omap.com/pub/bootloader/2430sdp/source/u-boot-SEP1106.tar.gz]
 md5=49c07dec9e1be69fd01d46f47ec03731
 sha256=a090786113b02647413ebc15888af269f2e6d50f73cbb94b0619cc1702911dae
index 728ad2b..f3a31cf 100644 (file)
@@ -12,7 +12,7 @@ PREFERRED_PROVIDER_virtual/kernel = "linux"
 
 KERNEL_IMAGETYPE = "uImage"
 
-PREFERRED_VERSION_u-boot = "1.1.2"
+PREFERRED_VERSION_u-boot = "2009.03"
 UBOOT_LOADADDRESS = "0x48008000"
 UBOOT_ENTRYPOINT = "0x48008000"
 UBOOT_ARCH = "arm"
index 686876f..e2d8575 100644 (file)
@@ -23398,7 +23398,7 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/hipox.c linux-2.6.24-oxe810/arch/arm
 +#endif // CONFIG_HIPOX_SATA_POWER_2
 +}
 +
-+MACHINE_START(OXNAS, "Oxsemi NAS")
++MACHINE_START(HIPOX, "OXE810 based HydraIP")
 +    /* Maintainer: Oxford Semiconductor Ltd */
 +#ifdef CONFIG_ARCH_HIPOX_UART1
 +    .phys_io = UART_1_BASE_PA,
diff --git a/recipes/u-boot/u-boot-2009.03/hipox/00-hipox.patch b/recipes/u-boot/u-boot-2009.03/hipox/00-hipox.patch
new file mode 100644 (file)
index 0000000..fbb8039
--- /dev/null
@@ -0,0 +1,7034 @@
+diff -Nurd u-boot-2009.03.orig/Makefile u-boot-2009.03/Makefile
+--- u-boot-2009.03.orig/Makefile       2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/Makefile    2009-04-15 11:08:18.000000000 +0200
+@@ -2842,6 +2842,10 @@
+       fi;
+       @$(MKCONFIG) SX1 arm arm925t sx1
++hipox_config : unconfig
++      @ln -s -f ./u-boot-arm926ejs.lds ./board/hipox/u-boot.lds
++      @$(MKCONFIG) hipox arm arm926ejs hipox;
++
+ # TRAB default configuration: 8 MB Flash, 32 MB RAM
+ xtract_trab = $(subst _bigram,,$(subst _bigflash,,$(subst _old,,$(subst _config,,$1))))
+@@ -3486,7 +3490,7 @@
+       @rm -f $(obj)api_examples/demo $(TIMESTAMP_FILE) $(VERSION_FILE)
+       @find $(OBJTREE) -type f \
+               \( -name 'core' -o -name '*.bak' -o -name '*~' \
+-              -o -name '*.o'  -o -name '*.a'  \) -print \
++              -o -name '*.o'  -o -name '*.a'  -o -name .depend \) -print \
+               | xargs rm -f
+ clobber:      clean
+diff -Nurd u-boot-2009.03.orig/board/hipox/Makefile u-boot-2009.03/board/hipox/Makefile
+--- u-boot-2009.03.orig/board/hipox/Makefile   1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/Makefile        2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,51 @@
++#
++# (C) Copyright 2000-2004
++# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++#
++# (C) Copyright 2004
++# ARM Ltd.
++# Philippe Robin, <philippe.robin@arm.com>
++#
++# See file CREDITS for list of people who contributed to this
++# project.
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2 of
++# the License, or (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++# MA 02111-1307 USA
++#
++
++include $(TOPDIR)/config.mk
++
++LIB   = lib$(BOARD).a
++
++OBJS  := hipox.o eth.o ide-$(NAS_VERSION).o
++SOBJS := platform-$(NAS_VERSION).o
++
++$(LIB):       $(OBJS) $(SOBJS)
++      $(AR) crv $@ $^
++
++clean:
++      rm -f $(SOBJS) $(OBJS)
++
++distclean:    clean
++      rm -f $(LIB) core *.bak .depend
++
++#########################################################################
++
++.depend:      Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
++              $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
++
++-include .depend
++
++#########################################################################
+diff -Nurd u-boot-2009.03.orig/board/hipox/config.mk u-boot-2009.03/board/hipox/config.mk
+--- u-boot-2009.03.orig/board/hipox/config.mk  1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/config.mk       2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,29 @@
++TEXT_BASE = 0x48d00000
++CROSS_COMPILE = arm-linux-
++
++PLL400 ?= 733333333
++RPSCLK ?=  25000000
++
++NAS_VERSION ?= 810
++FPGA ?= 0
++FPGA_ARM_CLK ?= 25000000
++
++PROBE_MEM_SIZE ?= 1
++MEM_SIZE ?= 128       # Memory size in megabytes if probing is not enabled
++MEM_ODT ?= 150
++
++USE_SATA ?= 1
++USE_SATA_ENV ?= 0
++USE_FLASH ?= 1
++USE_NAND ?= 1
++
++LINUX_ROOT_RAIDED ?= 0
++
++USE_EXTERNAL_UART ?= 0
++INTERNAL_UART ?= 2
++
++USE_LEON_TIME_COUNT ?= 1 # uses leon counted time to update system time on power-up
++
++TEST_BRD ?= 0 # Only significant for OX800
++
++PLATFORM_CPPFLAGS += -DLINUX_ROOT_RAIDED=$(LINUX_ROOT_RAIDED) -DMEM_ODT=$(MEM_ODT) -DPROBE_MEM_SIZE=$(PROBE_MEM_SIZE) -DNAS_VERSION=$(NAS_VERSION) -DFPGA=$(FPGA) -DFPGA_ARM_CLK=$(FPGA_ARM_CLK) -DINTERNAL_UART=$(INTERNAL_UART) -DUSE_EXTERNAL_UART=$(USE_EXTERNAL_UART) -DMEM_SIZE=$(MEM_SIZE) -DPLL400=$(PLL400) -DRPSCLK=$(RPSCLK) -DTEST_BRD=$(TEST_BRD) -DUSE_SATA=$(USE_SATA) -DUSE_SATA_ENV=$(USE_SATA_ENV) -DUSE_FLASH=$(USE_FLASH) -DUSE_LEON_TIME_COUNT=$(USE_LEON_TIME_COUNT) -DCONFIG_HIPOX_USE_NAND=$(USE_NAND)
+diff -Nurd u-boot-2009.03.orig/board/hipox/eth.c u-boot-2009.03/board/hipox/eth.c
+--- u-boot-2009.03.orig/board/hipox/eth.c      1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/eth.c   2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,1668 @@
++/*
++ * (C) Copyright 2005
++ * Oxford Semiconductor Ltd
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <malloc.h>
++#include <net.h>
++//#include <asm/barrier.h>
++
++#define wmb() asm volatile (""   : : :"memory")
++
++//#define DEBUG_GMAC_INIT
++
++// The number of bytes wasted at the start of a received packet buffer in order
++// to ensure the IP header will be aligned to a 32-bit boundary
++static const int ETHER_FRAME_ALIGN_WASTAGE = 2;
++static const int EXTRA_RX_SKB_SPACE = 32;   // Otherwise GMAC spans over >1 skb
++static const int ETHER_MTU  = 1500;
++
++static const u32 MAC_BASE_OFFSET = 0x0000;
++static const u32 DMA_BASE_OFFSET = 0x1000;
++
++static const int NUM_TX_DMA_DESCRIPTORS = 1;
++static const int NUM_RX_DMA_DESCRIPTORS = 32;
++
++/* Generic MII registers. */
++#define MII_BMCR            0x00      /* Basic mode control register */
++#define MII_BMSR            0x01      /* Basic mode status register  */
++#define MII_PHYSID1         0x02      /* PHYS ID 1                   */
++#define MII_PHYSID2         0x03      /* PHYS ID 2                   */
++#define MII_ADVERTISE       0x04      /* Advertisement control reg   */
++#define MII_LPA             0x05      /* Link partner ability reg    */
++#define MII_EXPANSION       0x06      /* Expansion register          */
++#define MII_CTRL1000        0x09      /* 1000BASE-T control          */
++#define MII_STAT1000        0x0a      /* 1000BASE-T status           */
++#define MII_ESTATUS         0x0f      /* Extended Status */
++
++/* Basic mode control register. */
++#define BMCR_RESV          0x003f  /* Unused...                   */
++#define BMCR_SPEED1000                0x0040  /* MSB of Speed (1000)         */
++#define BMCR_CTST          0x0080  /* Collision test              */
++#define BMCR_FULLDPLX      0x0100  /* Full duplex                 */
++#define BMCR_ANRESTART     0x0200  /* Auto negotiation restart    */
++#define BMCR_ISOLATE       0x0400  /* Disconnect DP83840 from MII */
++#define BMCR_PDOWN         0x0800  /* Powerdown the DP83840       */
++#define BMCR_ANENABLE      0x1000  /* Enable auto negotiation     */
++#define BMCR_SPEED100      0x2000  /* Select 100Mbps              */
++#define BMCR_LOOPBACK      0x4000  /* TXD loopback bits           */
++#define BMCR_RESET         0x8000  /* Reset the DP83840           */
++
++/* Basic mode status register. */
++#define BMSR_ERCAP         0x0001  /* Ext-reg capability          */
++#define BMSR_JCD           0x0002  /* Jabber detected             */
++#define BMSR_LSTATUS       0x0004  /* Link status                 */
++#define BMSR_ANEGCAPABLE   0x0008  /* Able to do auto-negotiation */
++#define BMSR_RFAULT        0x0010  /* Remote fault detected       */
++#define BMSR_ANEGCOMPLETE  0x0020  /* Auto-negotiation complete   */
++#define BMSR_RESV          0x00c0  /* Unused...                   */
++#define BMSR_ESTATEN          0x0100  /* Extended Status in R15 */
++#define BMSR_100FULL2         0x0200  /* Can do 100BASE-T2 HDX */
++#define BMSR_100HALF2         0x0400  /* Can do 100BASE-T2 FDX */
++#define BMSR_10HALF        0x0800  /* Can do 10mbps, half-duplex  */
++#define BMSR_10FULL        0x1000  /* Can do 10mbps, full-duplex  */
++#define BMSR_100HALF       0x2000  /* Can do 100mbps, half-duplex */
++#define BMSR_100FULL       0x4000  /* Can do 100mbps, full-duplex */
++#define BMSR_100BASE4      0x8000  /* Can do 100mbps, 4k packets  */
++
++/* 1000BASE-T Status register */
++#define LPA_1000LOCALRXOK     0x2000  /* Link partner local receiver status */
++#define LPA_1000REMRXOK       0x1000  /* Link partner remote receiver status */
++#define LPA_1000FULL          0x0800  /* Link partner 1000BASE-T full duplex */
++#define LPA_1000HALF          0x0400  /* Link partner 1000BASE-T half duplex */
++#define PHY_TYPE_NONE                                 0
++#define PHY_TYPE_MICREL_KS8721BL              0x00221619
++#define PHY_TYPE_VITESSE_VSC8201XVZ   0x000fc413
++#define PHY_TYPE_REALTEK_RTL8211BGR   0x001cc912
++#define PHY_TYPE_LSI_ET1011C                  0x0282f013
++
++/* Specific PHY values */
++#define VSC8201_MII_ACSR                      0x1c    // Vitesse VCS8201 gigabit PHY Auxillary Control and Status register
++#define VSC8201_MII_ACSR_MDPPS_BIT    2               // Mode/Duplex Pin Priority Select
++
++#define ET1011C_MII_CONFIG    0x16
++#define ET1011C_MII_CONFIG_IFMODESEL  0
++#define ET1011C_MII_CONFIG_IFMODESEL_NUM_BITS 3
++#define ET1011C_MII_CONFIG_SYSCLKEN   4
++#define ET1011C_MII_CONFIG_TXCLKEN            5
++#define ET1011C_MII_CONFIG_TBI_RATESEL        8
++#define ET1011C_MII_CONFIG_CRS_TX_EN  15
++
++#define ET1011C_MII_CONFIG_IFMODESEL_GMII_MII         0
++#define ET1011C_MII_CONFIG_IFMODESEL_TBI                      1
++#define ET1011C_MII_CONFIG_IFMODESEL_GMII_MII_GTX     2
++
++#define ET1011C_MII_LED2 0x1c
++#define ET1011C_MII_LED2_LED_TXRX             12
++#define ET1011C_MII_LED2_LED_NUM_BITS 4
++
++#define ET1011C_MII_LED2_LED_TXRX_ON          0xe
++#define ET1011C_MII_LED2_LED_TXRX_ACTIVITY    0x7
++
++// Some typedefs to cope with std Linux types
++typedef void sk_buff_t;
++
++// The in-memory descriptor structures
++typedef struct gmac_dma_desc
++{
++    /** The encoded status field of the GMAC descriptor */
++    u32 status;
++    /** The encoded length field of GMAC descriptor */
++    u32 length;
++    /** Buffer 1 pointer field of GMAC descriptor */
++    u32 buffer1;
++    /** Buffer 2 pointer or next descriptor pointer field of GMAC descriptor */
++    u32 buffer2;
++    /** Not used for U-Boot */
++    u32 skb;
++} __attribute ((packed)) gmac_dma_desc_t;
++
++typedef struct gmac_desc_list_info
++{
++    gmac_dma_desc_t* base_ptr;
++    int              num_descriptors;
++    int              empty_count;
++    int              full_count;
++    int              r_index;
++    int              w_index;
++} gmac_desc_list_info_t;
++
++// Private data structure for the GMAC driver
++typedef struct gmac_priv
++{
++    /** Base address of GMAC MAC registers */
++    u32                     macBase;
++    /** Base address of GMAC DMA registers */
++    u32                     dmaBase;
++
++    /** The number of descriptors in the gmac_dma_desc_t array holding both the
++     *  TX and RX descriptors. The TX descriptors reside at the start of the
++     *  array */
++    unsigned                total_num_descriptors;
++
++    /** The address of the start of the descriptor array */
++    gmac_dma_desc_t        *desc_base_addr;
++
++    /** Descriptor list management */
++    gmac_desc_list_info_t   tx_gmac_desc_list_info;
++    gmac_desc_list_info_t   rx_gmac_desc_list_info;
++
++      /** PHY info */
++      u32                                              phy_type;
++      u32                                              phy_addr;
++      int                                              phy_id;
++      int                                              link_is_1000M;
++} gmac_priv_t;
++
++/**
++ * MAC register indices
++ */
++typedef enum gmac_mac_regs {
++    MAC_CONFIG_REG       = 0,
++    MAC_FRAME_FILTER_REG = 1,
++    MAC_HASH_HIGH_REG    = 2,
++    MAC_HASH_LOW_REG     = 3,
++    MAC_GMII_ADR_REG     = 4,
++    MAC_GMII_DATA_REG    = 5,
++    MAC_FLOW_CNTL_REG    = 6,
++    MAC_VLAN_TAG_REG     = 7,
++    MAC_VERSION_REG      = 8,
++    MAC_ADR0_HIGH_REG    = 16,
++    MAC_ADR0_LOW_REG     = 17,
++    MAC_ADR1_HIGH_REG    = 18,
++    MAC_ADR1_LOW_REG     = 19,
++    MAC_ADR2_HIGH_REG    = 20,
++    MAC_ADR2_LOW_REG     = 21,
++    MAC_ADR3_HIGH_REG    = 22,
++    MAC_ADR3_LOW_REG     = 23,
++    MAC_ADR4_HIGH_REG    = 24,
++    MAC_ADR4_LOW_REG     = 25,
++    MAC_ADR5_HIGH_REG    = 26,
++    MAC_ADR5_LOW_REG     = 27,
++    MAC_ADR6_HIGH_REG    = 28,
++    MAC_ADR6_LOW_REG     = 29,
++    MAC_ADR7_HIGH_REG    = 30,
++    MAC_ADR7_LOW_REG     = 31,
++    MAC_ADR8_HIGH_REG    = 32,
++    MAC_ADR8_LOW_REG     = 33,
++    MAC_ADR9_HIGH_REG    = 34,
++    MAC_ADR9_LOW_REG     = 35,
++    MAC_ADR10_HIGH_REG   = 36,
++    MAC_ADR10_LOW_REG    = 37,
++    MAC_ADR11_HIGH_REG   = 38,
++    MAC_ADR11_LOW_REG    = 39,
++    MAC_ADR12_HIGH_REG   = 40,
++    MAC_ADR12_LOW_REG    = 41,
++    MAC_ADR13_HIGH_REG   = 42,
++    MAC_ADR13_LOW_REG    = 43,
++    MAC_ADR14_HIGH_REG   = 44,
++    MAC_ADR14_LOW_REG    = 45,
++    MAC_ADR15_HIGH_REG   = 46,
++    MAC_ADR15_LOW_REG    = 47
++} gmac_mac_regs_t;
++
++
++/**
++ * MAC register field definitions
++ */
++typedef enum gmac_config_reg {
++    MAC_CONFIG_WD_BIT  = 23,
++    MAC_CONFIG_JD_BIT  = 22,
++    MAC_CONFIG_BE_BIT  = 21,
++    MAC_CONFIG_JE_BIT  = 20,
++    MAC_CONFIG_IFG_BIT = 17,
++    MAC_CONFIG_PS_BIT  = 15,
++    MAC_CONFIG_DO_BIT  = 13,
++    MAC_CONFIG_LM_BIT  = 12,
++    MAC_CONFIG_DM_BIT  = 11,
++    MAC_CONFIG_IPC_BIT = 10,
++    MAC_CONFIG_DR_BIT  = 9,
++    MAC_CONFIG_ACS_BIT = 7,
++    MAC_CONFIG_BL_BIT  = 5,
++    MAC_CONFIG_DC_BIT  = 4,
++    MAC_CONFIG_TE_BIT  = 3,
++    MAC_CONFIG_RE_BIT  = 2
++} gmac_config_reg_t;
++
++#define MAC_CONFIG_IFG_NUM_BITS 3
++#define MAC_CONFIG_BL_NUM_BITS 2
++
++typedef enum gmac_frame_filter_reg {
++    MAC_FRAME_FILTER_RA_BIT   = 31,
++    MAC_FRAME_FILTER_SAF_BIT  = 9,
++    MAC_FRAME_FILTER_SAIF_BIT = 8,
++    MAC_FRAME_FILTER_PCF_BIT  = 6,
++    MAC_FRAME_FILTER_DBF_BIT  = 5,
++    MAC_FRAME_FILTER_PM_BIT   = 4,
++    MAC_FRAME_FILTER_DAIF_BIT = 3,
++    MAC_FRAME_FILTER_HMC_BIT  = 2,
++    MAC_FRAME_FILTER_HUC_BIT  = 1,
++    MAC_FRAME_FILTER_PR_BIT   = 0
++} gmac_frame_filter_reg_t;
++
++#define MAC_FRAME_FILTER_PCF_NUM_BITS 2
++
++typedef enum gmac_hash_table_high_reg {
++    MAC_HASH_HIGH_HTH_BIT = 0
++} gmac_hash_table_high_reg_t;
++
++typedef enum gmac_hash_table_low_reg {
++    MAC_HASH_LOW_HTL_BIT = 0
++} gmac_hash_table_low_reg_t;
++
++typedef enum gmac_gmii_address_reg {
++    MAC_GMII_ADR_PA_BIT = 11,
++    MAC_GMII_ADR_GR_BIT = 6,
++    MAC_GMII_ADR_CR_BIT = 2,
++    MAC_GMII_ADR_GW_BIT = 1,
++    MAC_GMII_ADR_GB_BIT = 0
++} gmac_gmii_address_reg_t;
++
++#define MAC_GMII_ADR_PA_NUM_BITS 5
++#define MAC_GMII_ADR_GR_NUM_BITS 5
++#define MAC_GMII_ADR_CR_NUM_BITS 3
++
++typedef enum gmac_gmii_data_reg {
++    MAC_GMII_DATA_GD_BIT = 0
++} gmac_gmii_data_reg_t;
++
++#define MAC_GMII_DATA_GD_NUM_BITS 16
++
++typedef enum gmac_flow_control_reg {
++    MAC_FLOW_CNTL_PT_BIT      = 16,
++    MAC_FLOW_CNTL_PLT_BIT     = 4,
++    MAC_FLOW_CNTL_UP_BIT      = 3,
++    MAC_FLOW_CNTL_RFE_BIT     = 2,
++    MAC_FLOW_CNTL_TFE_BIT     = 1,
++    MAC_FLOW_CNTL_FCB_BPA_BIT = 0
++} gmac_flow_control_reg_t;
++
++#define MAC_FLOW_CNTL_PT_NUM_BITS 16
++#define MAC_FLOW_CNTL_PLT_NUM_BITS 2
++
++typedef enum gmac_vlan_tag_reg {
++    MAC_VLAN_TAG_LV_BIT = 0
++} gmac_vlan_tag_reg_t;
++
++#define MAC_VLAN_TAG_LV_NUM_BITS 16
++
++typedef enum gmac_version_reg {
++    MAC_VERSION_UD_BIT = 8,
++    MAC_VERSION_SD_BIT = 0
++} gmac_version_reg_t;
++
++#define MAC_VERSION_UD_NUM_BITS 8
++#define MAC_VERSION_SD_NUM_BITS 8
++
++typedef enum gmac_mac_adr_0_high_reg {
++    MAC_ADR0_HIGH_MO_BIT = 31,
++    MAC_ADR0_HIGH_A_BIT  = 0
++} gmac_mac_adr_0_high_reg_t;
++
++#define MAC_ADR0_HIGH_A_NUM_BITS 16
++
++typedef enum gmac_mac_adr_0_low_reg {
++    MAC_ADR0_LOW_A_BIT = 0
++} gmac_mac_adr_0_low_reg_t;
++
++typedef enum gmac_mac_adr_1_high_reg {
++    MAC_ADR1_HIGH_AE_BIT  = 31,
++    MAC_ADR1_HIGH_SA_BIT  = 30,
++    MAC_ADR1_HIGH_MBC_BIT = 24,
++    MAC_ADR1_HIGH_A_BIT   = 0
++} gmac_mac_adr_1_high_reg_t;
++
++#define MAC_ADR1_HIGH_MBC_NUM_BITS 6
++#define MAC_ADR1_HIGH_A_NUM_BITS 16
++
++typedef enum gmac_mac_adr_1_low_reg {
++    MAC_ADR1_LOW_A_BIT = 0
++} gmac_mac_adr_1_low_reg_t;
++
++
++/**
++ * MMC register indices - registers accessed via the MAC accessor functions
++ */
++typedef enum gmac_mmc_regs {
++    MMC_CONTROL_REG = 64,
++    MMC_RX_INT_REG  = 65,
++    MMC_TX_INT_REG  = 66,
++    MMC_RX_MASK_REG = 67,
++    MMC_TX_MASK_REG = 68
++} gmac_mmc_regs_t;
++
++/**
++ * DMA register indices
++ */
++typedef enum gmac_dma_regs {
++    DMA_BUS_MODE_REG        = 0,
++    DMA_TX_POLL_REG         = 1,
++    DMA_RX_POLL_REG         = 2,
++    DMA_RX_DESC_ADR_REG     = 3,
++    DMA_TX_DESC_ADR_REG     = 4,
++    DMA_STATUS_REG          = 5,
++    DMA_OP_MODE_REG         = 6,
++    DMA_INT_ENABLE_REG      = 7,
++    DMA_MISSED_OVERFLOW_REG = 8,
++    DMA_CUR_TX_DESC_REG     = 18,
++    DMA_CUR_RX_DESC_REG     = 19,
++    DMA_CUR_TX_ADR_REG      = 20,
++    DMA_CUR_RX_ADR_REG      = 21
++} gmac_dma_regs_t;
++
++/**
++ * DMA register field definitions
++ */
++
++typedef enum gmac_dma_bus_mode_reg {
++    DMA_BUS_MODE_FB_BIT  = 16,
++    DMA_BUS_MODE_PR_BIT  = 14,
++    DMA_BUS_MODE_PBL_BIT = 8,
++    DMA_BUS_MODE_DSL_BIT = 2,
++    DMA_BUS_MODE_DA_BIT  = 1,
++    DMA_BUS_MODE_SWR_BIT = 0
++} gmac_dma_bus_mode_reg_t;
++
++#define DMA_BUS_MODE_PR_NUM_BITS 2
++#define DMA_BUS_MODE_PBL_NUM_BITS 6
++#define DMA_BUS_MODE_DSL_NUM_BITS 5
++
++typedef enum gmac_dma_tx_poll_demand_reg {
++    DMA_TX_POLL_TPD_BIT = 0
++} gmac_dma_tx_poll_demand_reg_t;
++
++typedef enum gmac_dma_rx_poll_demand_reg {
++    DMA_RX_POLL_RPD_BIT = 0
++} gmac_dma_rx_poll_demand_reg_t;
++
++typedef enum gmac_dma_rx_desc_list_adr_reg {
++    DMA_RX_DESC_ADR_SRL_BIT = 0
++} gmac_dma_rx_desc_list_adr_reg_t;
++
++typedef enum gmac_dma_tx_desc_list_adr_reg {
++    DMA_TX_DESC_ADR_STL_BIT = 0
++} gmac_dma_tx_desc_list_adr_reg_t;
++
++typedef enum gmac_dma_status_reg {
++    DMA_STATUS_GPI_BIT = 28,
++    DMA_STATUS_GMI_BIT = 27,
++    DMA_STATUS_GLI_BIT = 26,
++    DMA_STATUS_EB_BIT  = 23,
++    DMA_STATUS_TS_BIT  = 20,
++    DMA_STATUS_RS_BIT  = 17,
++    DMA_STATUS_NIS_BIT = 16,
++    DMA_STATUS_AIS_BIT = 15,
++    DMA_STATUS_ERI_BIT = 14,
++    DMA_STATUS_FBE_BIT = 13,
++    DMA_STATUS_ETI_BIT = 10,
++    DMA_STATUS_RWT_BIT = 9,
++    DMA_STATUS_RPS_BIT = 8,
++    DMA_STATUS_RU_BIT  = 7,
++    DMA_STATUS_RI_BIT  = 6,
++    DMA_STATUS_UNF_BIT = 5,
++    DMA_STATUS_OVF_BIT = 4,
++    DMA_STATUS_TJT_BIT = 3,
++    DMA_STATUS_TU_BIT  = 2,
++    DMA_STATUS_TPS_BIT = 1,
++    DMA_STATUS_TI_BIT  = 0
++} gmac_dma_status_reg_t;
++
++#define DMA_STATUS_EB_NUM_BITS 3
++#define DMA_STATUS_TS_NUM_BITS 3
++#define DMA_STATUS_RS_NUM_BITS 3
++
++typedef enum gmac_dma_op_mode_reg {
++    DMA_OP_MODE_SF_BIT  = 21,
++    DMA_OP_MODE_FTF_BIT = 20,
++    DMA_OP_MODE_TTC_BIT = 14,
++    DMA_OP_MODE_ST_BIT  = 13,
++    DMA_OP_MODE_RFD_BIT = 11,
++    DMA_OP_MODE_RFA_BIT = 9,
++    DMA_OP_MODE_EFC_BIT = 8,
++    DMA_OP_MODE_FEF_BIT = 7,
++    DMA_OP_MODE_FUF_BIT = 6,
++    DMA_OP_MODE_RTC_BIT = 3,
++    DMA_OP_MODE_OSF_BIT = 2,
++    DMA_OP_MODE_SR_BIT  = 1
++} gmac_dma_op_mode_reg_t;
++
++#define DMA_OP_MODE_TTC_NUM_BITS 3
++#define DMA_OP_MODE_RFD_NUM_BITS 2
++#define DMA_OP_MODE_RFA_NUM_BITS 2
++#define DMA_OP_MODE_RTC_NUM_BITS 2
++
++typedef enum gmac_dma_intr_enable_reg {
++    DMA_INT_ENABLE_NI_BIT  = 16,
++    DMA_INT_ENABLE_AI_BIT  = 15,
++    DMA_INT_ENABLE_ERE_BIT = 14,
++    DMA_INT_ENABLE_FBE_BIT = 13,
++    DMA_INT_ENABLE_ETE_BIT = 10,
++    DMA_INT_ENABLE_RW_BIT  = 9,
++    DMA_INT_ENABLE_RS_BIT  = 8,
++    DMA_INT_ENABLE_RU_BIT  = 7,
++    DMA_INT_ENABLE_RI_BIT  = 6,
++    DMA_INT_ENABLE_UN_BIT  = 5,
++    DMA_INT_ENABLE_OV_BIT  = 4,
++    DMA_INT_ENABLE_TJ_BIT  = 3,
++    DMA_INT_ENABLE_TU_BIT  = 2,
++    DMA_INT_ENABLE_TS_BIT  = 1,
++    DMA_INT_ENABLE_TI_BIT  = 0
++} gmac_dma_intr_enable_reg_t;
++
++typedef enum gmac_dma_missed_overflow_reg {
++    DMA_MISSED_OVERFLOW_OFOC_BIT  = 28,    // Overflow bit for FIFO Overflow Counter
++    DMA_MISSED_OVERFLOW_AMFC_BIT  = 17,    // Application Missed Frames Count
++    DMA_MISSED_OVERFLOW_OAMFO_BIT = 16,    // Overflow bit for Application Missed Frames Count
++    DMA_MISSED_OVERFLOW_CMFC_BIT  = 0      // Controller Missed Frames Count
++} gmac_dma_missed_overflow_reg_t;
++
++#define DMA_MISSED_OVERFLOW_OAMFO_NUM_BITS 11
++#define DMA_MISSED_OVERFLOW_CMFC_NUM_BITS 16
++
++typedef enum gmac_dma_current_tx_desc_reg {
++    DMA_CUR_TX_DESC_A_BIT = 0
++} gmac_dma_current_tx_desc_reg_t;
++
++typedef enum gmac_dma_current_rx_desc_reg {
++    DMA_CUR_RX_DESC_A_BIT = 0
++} gmac_dma_current_rx_desc_reg_t;
++
++typedef enum gmac_dma_current_tx_adr_reg {
++    DMA_CUR_TX_ADR_A_BIT = 0
++} gmac_dma_current_tx_adr_reg_t;
++
++typedef enum gmac_dma_current_rx_adr_reg {
++    DMA_CUR_RX_ADR_A_BIT = 0
++} gmac_dma_current_rx_adr_reg_t;
++
++/**
++ * Descriptor support
++ */
++/** Descriptor status word field definitions */
++typedef enum desc_status {
++  descOwnByDma          = 0x80000000,   /* descriptor is owned by DMA engine  */
++
++  descFrameLengthMask   = 0x3FFF0000,   /* Receive descriptor frame length */
++  descFrameLengthShift  = 16,
++
++  descError             = 0x00008000,   /* Error summary bit  - OR of the following bits:    v  */
++
++  descRxTruncated       = 0x00004000,   /* Rx - no more descriptors for receive frame        E  */
++
++  descRxLengthError     = 0x00001000,   /* Rx - frame size not matching with length field */
++  descRxDamaged         = 0x00000800,   /* Rx - frame was damaged due to buffer overflow     E  */
++  descRxFirst           = 0x00000200,   /* Rx - first descriptor of the frame                   */
++  descRxLast            = 0x00000100,   /* Rx - last descriptor of the frame                    */
++  descRxLongFrame       = 0x00000080,   /* Rx - frame is longer than 1518 bytes              E  */
++  descRxCollision       = 0x00000040,   /* Rx - late collision occurred during reception     E  */
++  descRxFrameEther      = 0x00000020,   /* Rx - Frame type - Ethernet, otherwise 802.3          */
++  descRxWatchdog        = 0x00000010,   /* Rx - watchdog timer expired during reception      E  */
++  descRxMiiError        = 0x00000008,   /* Rx - error reported by MII interface              E  */
++  descRxDribbling       = 0x00000004,   /* Rx - frame contains noninteger multiple of 8 bits    */
++  descRxCrc             = 0x00000002,   /* Rx - CRC error                                    E  */
++
++  descTxTimeout         = 0x00004000,   /* Tx - Transmit jabber timeout                      E  */
++  descTxLostCarrier     = 0x00000800,   /* Tx - carrier lost during tramsmission             E  */
++  descTxNoCarrier       = 0x00000400,   /* Tx - no carrier signal from the tranceiver        E  */
++  descTxLateCollision   = 0x00000200,   /* Tx - transmission aborted due to collision        E  */
++  descTxExcCollisions   = 0x00000100,   /* Tx - transmission aborted after 16 collisions     E  */
++  descTxVLANFrame       = 0x00000080,   /* Tx - VLAN-type frame                                 */
++  descTxCollMask        = 0x00000078,   /* Tx - Collision count                                 */
++  descTxCollShift       = 3,
++  descTxExcDeferral     = 0x00000004,   /* Tx - excessive deferral                           E  */
++  descTxUnderflow       = 0x00000002,   /* Tx - late data arrival from the memory            E  */
++  descTxDeferred        = 0x00000001,   /* Tx - frame transmision deferred                      */
++} desc_status_t;
++
++/** Descriptor length word field definitions */
++typedef enum desc_length {
++  descTxIntEnable       = 0x80000000,   /* Tx - interrupt on completion                         */
++  descTxLast            = 0x40000000,   /* Tx - Last segment of the frame                       */
++  descTxFirst           = 0x20000000,   /* Tx - First segment of the frame                      */
++  descTxDisableCrc      = 0x04000000,   /* Tx - Add CRC disabled (first segment only)           */
++
++  descEndOfRing         = 0x02000000,   /* End of descriptors ring                              */
++  descChain             = 0x01000000,   /* Second buffer address is chain address               */
++  descTxDisablePadd     = 0x00800000,   /* disable padding, added by - reyaz */
++
++  descSize2Mask         = 0x003FF800,   /* Buffer 2 size                                        */
++  descSize2Shift        = 11,
++  descSize1Mask         = 0x000007FF,   /* Buffer 1 size                                        */
++  descSize1Shift        = 0,
++} desc_length_t;
++
++typedef enum rx_desc_status {
++    RX_DESC_STATUS_OWN_BIT  = 31,
++    RX_DESC_STATUS_AFM_BIT  = 30,
++    RX_DESC_STATUS_FL_BIT   = 16,
++    RX_DESC_STATUS_ES_BIT   = 15,
++    RX_DESC_STATUS_DE_BIT   = 14,
++    RX_DESC_STATUS_SAF_BIT  = 13,
++    RX_DESC_STATUS_LE_BIT   = 12,
++    RX_DESC_STATUS_OE_BIT   = 11,
++    RX_DESC_STATUS_IPC_BIT  = 10,
++    RX_DESC_STATUS_FS_BIT   = 9,
++    RX_DESC_STATUS_LS_BIT   = 8,
++    RX_DESC_STATUS_VLAN_BIT = 7,
++    RX_DESC_STATUS_LC_BIT   = 6,
++    RX_DESC_STATUS_FT_BIT   = 5,
++    RX_DESC_STATUS_RWT_BIT  = 4,
++    RX_DESC_STATUS_RE_BIT   = 3,
++    RX_DESC_STATUS_DRE_BIT  = 2,
++    RX_DESC_STATUS_CE_BIT   = 1,
++    RX_DESC_STATUS_MAC_BIT  = 0
++} rx_desc_status_t;
++
++#define RX_DESC_STATUS_FL_NUM_BITS 14
++
++typedef enum rx_desc_length {
++    RX_DESC_LENGTH_DIC_BIT  = 31,
++    RX_DESC_LENGTH_RER_BIT  = 25,
++    RX_DESC_LENGTH_RCH_BIT  = 24,
++    RX_DESC_LENGTH_RBS2_BIT = 11,
++    RX_DESC_LENGTH_RBS1_BIT = 0,
++} rx_desc_length_t;
++
++#define RX_DESC_LENGTH_RBS2_NUM_BITS 11
++#define RX_DESC_LENGTH_RBS1_NUM_BITS 11
++
++typedef enum tx_desc_status {
++    TX_DESC_STATUS_OWN_BIT  = 31,
++    TX_DESC_STATUS_ES_BIT   = 15,
++    TX_DESC_STATUS_JT_BIT   = 14,
++    TX_DESC_STATUS_FF_BIT   = 13,
++    TX_DESC_STATUS_LOC_BIT  = 11,
++    TX_DESC_STATUS_NC_BIT   = 10,
++    TX_DESC_STATUS_LC_BIT   = 9,
++    TX_DESC_STATUS_EC_BIT   = 8,
++    TX_DESC_STATUS_VF_BIT   = 7,
++    TX_DESC_STATUS_CC_BIT   = 3,
++    TX_DESC_STATUS_ED_BIT   = 2,
++    TX_DESC_STATUS_UF_BIT   = 1,
++    TX_DESC_STATUS_DB_BIT   = 0
++} tx_desc_status_t;
++
++#define TX_DESC_STATUS_CC_NUM_BITS 4
++
++typedef enum tx_desc_length {
++    TX_DESC_LENGTH_IC_BIT   = 31,
++    TX_DESC_LENGTH_LS_BIT   = 30,
++    TX_DESC_LENGTH_FS_BIT   = 29,
++    TX_DESC_LENGTH_DC_BIT   = 26,
++    TX_DESC_LENGTH_TER_BIT  = 25,
++    TX_DESC_LENGTH_TCH_BIT  = 24,
++    TX_DESC_LENGTH_DP_BIT   = 23,
++    TX_DESC_LENGTH_TBS2_BIT = 11,
++    TX_DESC_LENGTH_TBS1_BIT = 0
++} tx_desc_length_t;
++
++#define TX_DESC_LENGTH_TBS2_NUM_BITS 11
++#define TX_DESC_LENGTH_TBS1_NUM_BITS 11
++
++/** Return the number of descriptors available for the CPU to fill with new
++ *  packet info */
++static inline int available_for_write(gmac_desc_list_info_t* desc_list)
++{
++    return desc_list->empty_count;
++}
++
++/** Return non-zero if there is a descriptor available with a packet with which
++ *  the GMAC DMA has finished */
++static inline int tx_available_for_read(gmac_desc_list_info_t* desc_list)
++{
++    return desc_list->full_count &&
++           !((desc_list->base_ptr + desc_list->r_index)->status & (1UL << TX_DESC_STATUS_OWN_BIT));
++}
++
++/** Return non-zero if there is a descriptor available with a packet with which
++ *  the GMAC DMA has finished */
++static inline int rx_available_for_read(gmac_desc_list_info_t* desc_list)
++{
++    return desc_list->full_count &&
++           !((desc_list->base_ptr + desc_list->r_index)->status & (1UL << RX_DESC_STATUS_OWN_BIT));
++}
++
++/**
++ * @param A u32 containing the status from a received frame's DMA descriptor
++ * @return An int which is non-zero if a valid received frame is fully contained
++ *  within the descriptor from whence the status came
++ */
++static inline int is_rx_valid(u32 status)
++{
++    return !(status & descError)  &&
++           (status & descRxFirst) &&
++           (status & descRxLast);
++}
++
++static inline int is_rx_dribbling(u32 status)
++{
++    return status & descRxDribbling;
++}
++
++static inline u32 get_rx_length(u32 status)
++{
++    return (status & descFrameLengthMask) >> descFrameLengthShift;
++}
++
++static inline int is_rx_collision_error(u32 status)
++{
++    return status & (descRxDamaged | descRxCollision);
++}
++
++static inline int is_rx_crc_error(u32 status)
++{
++    return status & descRxCrc;
++}
++
++static inline int is_rx_frame_error(u32 status)
++{
++    return status & descRxDribbling;
++}
++
++static inline int is_rx_length_error(u32 status)
++{
++    return status & descRxLengthError;
++}
++
++static inline int is_rx_long_frame(u32 status)
++{
++    return status & descRxLongFrame;
++}
++
++static inline int is_tx_valid(u32 status)
++{
++    return !(status & descError);
++}
++
++static inline int is_tx_collision_error(u32 status)
++{
++    return (status & descTxCollMask) >> descTxCollShift;
++}
++
++static inline int is_tx_aborted(u32 status)
++{
++    return status & (descTxLateCollision | descTxExcCollisions);
++}
++
++static inline int is_tx_carrier_error(u32 status)
++{
++    return status & (descTxLostCarrier | descTxNoCarrier);
++}
++
++/**
++ * GMAC private metadata
++ */
++static gmac_priv_t priv_data;
++static gmac_priv_t* priv = &priv_data;
++
++/**
++ * Descriptor list management
++ */
++
++static void init_rx_descriptor(
++    gmac_dma_desc_t* desc,
++    int              end_of_ring,
++    int              disable_ioc)
++{
++    desc->status = 0;
++    desc->length = 0;
++    if (disable_ioc) {
++        desc->length |= (1UL << RX_DESC_LENGTH_DIC_BIT);
++    }
++    if (end_of_ring) {
++        desc->length |= (1UL << RX_DESC_LENGTH_RER_BIT);
++    }
++    desc->buffer1 = 0;
++    desc->buffer2 = 0;
++    desc->skb = 0;
++}
++
++static void init_tx_descriptor(
++    gmac_dma_desc_t* desc,
++    int              end_of_ring,
++    int              enable_ioc,
++    int              disable_crc,
++    int              disable_padding)
++{
++    desc->status = 0;
++    desc->length = 0;
++    if (enable_ioc) {
++        desc->length |= (1UL << TX_DESC_LENGTH_IC_BIT);
++    }
++    if (disable_crc) {
++        desc->length |= (1UL << TX_DESC_LENGTH_DC_BIT);
++    }
++    if (disable_padding) {
++        desc->length |= (1UL << TX_DESC_LENGTH_DP_BIT);
++    }
++    if (end_of_ring) {
++        desc->length |= (1UL << TX_DESC_LENGTH_TER_BIT);
++    }
++    desc->buffer1 = 0;
++    desc->buffer2 = 0;
++    desc->skb = 0;
++}
++
++static void init_rx_desc_list(
++    gmac_desc_list_info_t* desc_list,
++    gmac_dma_desc_t*       base_ptr,
++    int                    num_descriptors)
++{
++    int i;
++    
++    desc_list->base_ptr = base_ptr;
++    desc_list->num_descriptors = num_descriptors;
++    desc_list->empty_count = num_descriptors;
++    desc_list->full_count = 0;
++    desc_list->r_index = 0;
++    desc_list->w_index = 0;
++
++    for (i=0; i < (num_descriptors - 1); i++) {
++        init_rx_descriptor(base_ptr + i, 0, 0);
++    }
++    init_rx_descriptor(base_ptr + i, 1, 0);
++}
++
++static void init_tx_desc_list(
++    gmac_desc_list_info_t* desc_list,
++    gmac_dma_desc_t*       base_ptr,
++    int                    num_descriptors)
++{
++    int i;
++    
++    desc_list->base_ptr = base_ptr;
++    desc_list->num_descriptors = num_descriptors;
++    desc_list->empty_count = num_descriptors;
++    desc_list->full_count = 0;
++    desc_list->r_index = 0;
++    desc_list->w_index = 0;
++
++    for (i=0; i < (num_descriptors - 1); i++) {
++        init_tx_descriptor(base_ptr + i, 0, 1, 0, 0);
++    }
++    init_tx_descriptor(base_ptr + i, 1, 1, 0, 0);
++}
++
++static void rx_take_ownership(gmac_desc_list_info_t* desc_list)
++{
++    int i;
++    for (i=0; i < desc_list->num_descriptors; i++) {
++        (desc_list->base_ptr + i)->status &= ~(1UL << RX_DESC_STATUS_OWN_BIT);
++    }
++}
++
++static void tx_take_ownership(gmac_desc_list_info_t* desc_list)
++{
++    int i;
++    for (i=0; i < desc_list->num_descriptors; i++) {
++        (desc_list->base_ptr + i)->status &= ~(1UL << TX_DESC_STATUS_OWN_BIT);
++    }
++}
++
++static int set_tx_descriptor(
++    gmac_priv_t* priv,
++    dma_addr_t   dma_address,
++    u32          length,
++    sk_buff_t*   skb)
++{
++    int index;
++    gmac_dma_desc_t* tx;
++
++    // Are sufficicent descriptors available for writing by the CPU?
++    if (!available_for_write(&priv->tx_gmac_desc_list_info)) {
++        return -1;
++    }
++
++    // Get the index of the next TX descriptor available for writing by the CPU
++    index = priv->tx_gmac_desc_list_info.w_index;
++
++    // Get a pointer to the next TX descriptor available for writing by the CPU
++    tx = priv->tx_gmac_desc_list_info.base_ptr + index;
++
++    // Initialise the TX descriptor length field for the passed single buffer,
++    // without destroying any fields we wish to be persistent
++
++    // No chained second buffer
++    tx->length &= ~(1UL << TX_DESC_LENGTH_TCH_BIT);
++    // Single descriptor holds entire packet
++    tx->length |= ((1UL << TX_DESC_LENGTH_LS_BIT) | (1UL << TX_DESC_LENGTH_FS_BIT));
++    // Zero the second buffer length field
++    tx->length &= ~(((1UL << TX_DESC_LENGTH_TBS2_NUM_BITS) - 1) << TX_DESC_LENGTH_TBS2_BIT);
++    // Zero the first buffer length field
++    tx->length &= ~(((1UL << TX_DESC_LENGTH_TBS1_NUM_BITS) - 1) << TX_DESC_LENGTH_TBS1_BIT);
++    // Fill in the first buffer length
++    tx->length |= (length << TX_DESC_LENGTH_TBS1_BIT);
++
++    // Initialise the first buffer pointer to the single passed buffer
++    tx->buffer1 = dma_address;
++
++    // Remember the socket buffer associated with the single passed buffer
++    tx->skb = (u32)skb;
++
++    // Update the index of the next descriptor available for writing by the CPU
++    priv->tx_gmac_desc_list_info.w_index = (tx->length & (1UL << TX_DESC_LENGTH_TER_BIT)) ? 0 : index + 1;
++
++    // make sure all memory updates are complete before releasing the GMAC on the data.
++    wmb();
++    
++    // Hand TX descriptor to the GMAC DMA by setting the status bit.
++    tx->status = (1UL << TX_DESC_STATUS_OWN_BIT);
++
++    // Account for the number of descriptors used to hold the new packet
++    --priv->tx_gmac_desc_list_info.empty_count;
++    ++priv->tx_gmac_desc_list_info.full_count;
++
++    return index;
++}
++
++static int get_tx_descriptor(
++    gmac_priv_t* priv,
++    u32*         status,
++    dma_addr_t*  dma_address,
++    u32*         length,
++    sk_buff_t**  skb)
++{
++    int index;
++    gmac_dma_desc_t *tx;
++
++    // Is there at least one descriptor with which the GMAC DMA has finished?
++    if (!tx_available_for_read(&priv->tx_gmac_desc_list_info)) {
++        return -1;
++    }
++
++    // Get the index of the descriptor released the longest time ago by the
++    // GMAC DMA 
++    index = priv->tx_gmac_desc_list_info.r_index;
++
++    // Get a pointer to the descriptor released the longest time ago by the
++    // GMAC DMA 
++    tx = priv->tx_gmac_desc_list_info.base_ptr + index;
++
++    // Extract the status field
++    if (status) {
++        *status = tx->status;
++    }
++
++    // Extract the length field - only cope with the first buffer associated
++    // with the descriptor
++    if (length) {
++        *length = (tx->length >> TX_DESC_LENGTH_TBS1_BIT) &
++                  ((1UL << TX_DESC_LENGTH_TBS1_NUM_BITS) - 1);
++    }
++
++    // Extract the pointer to the buffer containing the packet - only cope with
++    // the first buffer associated with the descriptor
++    if (dma_address) {
++        *dma_address = tx->buffer1;
++    }
++
++    // Extract the pointer to the socket buffer associated with the packet
++    if (skb) {
++        *skb = (sk_buff_t*)(tx->skb);
++    }
++
++    // Update the index of the next descriptor with which the GMAC DMA may have
++    // finished
++    priv->tx_gmac_desc_list_info.r_index = (tx->length & (1UL << TX_DESC_LENGTH_TER_BIT)) ? 0 : index + 1;
++
++    // Account for the number of descriptors freed to hold new packets
++    ++priv->tx_gmac_desc_list_info.empty_count;
++    --priv->tx_gmac_desc_list_info.full_count;
++
++    return index;
++}
++
++int set_rx_descriptor(
++    gmac_priv_t* priv,
++    dma_addr_t   dma_address,
++    u32          length,
++    sk_buff_t*   skb)
++{
++    int index;
++    gmac_dma_desc_t* rx;
++    int num_descriptors_required;
++
++    // Currently only support using a single descriptor to describe each packet
++    // queued with the GMAc DMA
++    num_descriptors_required = 1;
++
++    // Are sufficicent descriptors available for writing by the CPU?
++    if (available_for_write(&priv->rx_gmac_desc_list_info) < num_descriptors_required) {
++        index = -1;
++    } else {
++        // Get the index of the next RX descriptor available for writing by the CPU
++        index = priv->rx_gmac_desc_list_info.w_index;
++
++        // Get a pointer to the next RX descriptor available for writing by the CPU
++        rx = priv->rx_gmac_desc_list_info.base_ptr + index;
++
++        // Initialise the RX descriptor length field for the passed single buffer,
++        // without destroying any fields we wish to be persistent
++
++        // No chained second buffer
++        rx->length &= ~(1UL << RX_DESC_LENGTH_RCH_BIT);
++        // Zero the second buffer length field
++        rx->length &= ~(((1UL << RX_DESC_LENGTH_RBS2_NUM_BITS) - 1) << RX_DESC_LENGTH_RBS2_BIT);
++        // Zero the first buffer length field
++        rx->length &= ~(((1UL << RX_DESC_LENGTH_RBS1_NUM_BITS) - 1) << RX_DESC_LENGTH_RBS1_BIT);
++        // Fill in the first buffer length
++        rx->length |= (length << RX_DESC_LENGTH_RBS1_BIT);
++
++        // Initialise the first buffer pointer to the single passed buffer
++        rx->buffer1 = dma_address;
++
++        // Remember the socket buffer associated with the single passed buffer
++        rx->skb = (u32)skb;
++        
++        wmb();
++        
++        // Initialise RX descriptor status to be owned by the GMAC DMA
++        rx->status = (1UL << RX_DESC_STATUS_OWN_BIT);
++
++        // Update the index of the next descriptor available for writing by the CPU
++        priv->rx_gmac_desc_list_info.w_index = (rx->length & (1UL << RX_DESC_LENGTH_RER_BIT)) ? 0 : index + 1;
++
++        // Account for the number of descriptors used to hold the new packet
++        priv->rx_gmac_desc_list_info.empty_count -= num_descriptors_required;
++        priv->rx_gmac_desc_list_info.full_count  += num_descriptors_required;
++    }
++
++    return index;
++}
++
++int get_rx_descriptor(
++    gmac_priv_t* priv,
++    u32*         status,
++    dma_addr_t*  dma_address,
++    u32*         length,
++    sk_buff_t**  skb)
++{
++    int index;
++    gmac_dma_desc_t *rx;
++    int num_descriptors_required;
++
++    // Is there at least one descriptor with which the GMAC DMA has finished?
++    if (!rx_available_for_read(&priv->rx_gmac_desc_list_info)) {
++        return -1;
++    }
++
++    // Currently can only cope with packets entirely contained within a single
++    // descriptor
++    num_descriptors_required = 1;
++
++    // Get the index of the descriptor released the longest time ago by the
++    // GMAC DMA 
++    index = priv->rx_gmac_desc_list_info.r_index;
++
++    // Get a pointer to the descriptor released the longest time ago by the
++    // GMAC DMA 
++    rx = priv->rx_gmac_desc_list_info.base_ptr + index;
++
++    // Extract the status field
++    if (status) {
++        *status = rx->status;
++    }
++
++    // Extract the length field - only cope with the first buffer associated
++    // with the descriptor
++    if (length) {
++        *length = (rx->length >> RX_DESC_LENGTH_RBS1_BIT) &
++                  ((1UL << RX_DESC_LENGTH_RBS1_NUM_BITS) - 1);
++    }
++
++    // Extract the pointer to the buffer containing the packet - only cope with
++    // the first buffer associated with the descriptor
++    if (dma_address) {
++        *dma_address = rx->buffer1;
++    }
++
++    // Extract the pointer to the socket buffer associated with the packet
++    if (skb) {
++        *skb = (sk_buff_t*)(rx->skb);
++    }
++
++    wmb();
++    // Update the index of the next descriptor with which the GMAC DMA may have
++    // finished
++    priv->rx_gmac_desc_list_info.r_index = (rx->length & (1UL << RX_DESC_LENGTH_RER_BIT)) ? 0 : index + 1;
++
++    // Account for the number of descriptors freed to hold new packets
++    priv->rx_gmac_desc_list_info.empty_count += num_descriptors_required;
++    priv->rx_gmac_desc_list_info.full_count  -= num_descriptors_required;
++
++    return index;
++}
++
++/**
++ * GMAC register access functions
++ */
++
++/**
++ * MAC register access functions
++ */
++
++/**
++ * @param priv A gmac_priv_t* pointing to private device data
++ * @param reg_num An int specifying the index of the MAC register to access
++ */
++static inline u32 mac_reg_read(gmac_priv_t* priv, int reg_num)
++{
++    return *(volatile u32*)(priv->macBase + (reg_num << 2));
++}
++
++/**
++ * @param priv A gmac_priv_t* pointing to private device data
++ * @param reg_num An int specifying the index of the MAC register to access
++ */
++static inline void mac_reg_write(gmac_priv_t* priv, int reg_num, u32 value)
++{
++    *(volatile u32*)(priv->macBase + (reg_num << 2)) = value;
++   
++}
++
++/**
++ * @param priv A gmac_priv_t* pointing to private device data
++ * @param reg_num An int specifying the index of the MAC register to access
++ * @param bits_to_clear A u32 specifying which bits of the specified register to
++ *  clear. A set bit in this parameter will cause the matching bit in the
++ *  register to be cleared
++ */
++static inline void mac_reg_clear_mask(gmac_priv_t* priv, int reg_num, u32 bits_to_clear)
++{
++    mac_reg_write(priv, reg_num, mac_reg_read(priv, reg_num) & ~bits_to_clear);
++}
++
++/**
++ * @param priv A gmac_priv_t* pointing to private device data
++ * @param reg_num An int specifying the index of the MAC register to access
++ * @param bits_to_set A u32 specifying which bits of the specified register to
++ *  set. A set bit in this parameter will cause the matching bit in the register
++ *  to be set
++ */
++static inline void mac_reg_set_mask(gmac_priv_t* priv, int reg_num, u32 bits_to_set)
++{
++    mac_reg_write(priv, reg_num, mac_reg_read(priv, reg_num) | bits_to_set);
++}
++
++
++/**
++ * DMA register access functions
++ */
++
++/**
++ * @param priv A gmac_priv_t* pointing to private device data
++ * @param reg_num An int specifying the index of the DMA register to access
++ */
++static inline u32 dma_reg_read(gmac_priv_t* priv, int reg_num)
++{
++    return *(volatile u32*)(priv->dmaBase + (reg_num << 2));
++}
++
++/**
++ * @param priv A gmac_priv_t* pointing to private device data
++ * @param reg_num An int specifying the index of the DMA register to access
++ */
++static inline void dma_reg_write(gmac_priv_t* priv, int reg_num, u32 value)
++{
++    *(volatile u32*)(priv->dmaBase + (reg_num << 2)) = value;
++    wmb();
++}
++
++/**
++ * @param priv A gmac_priv_t* pointing to private device data
++ * @param reg_num An int specifying the index of the DMA register to access
++ * @param bits_to_clear A u32 specifying which bits of the specified register to
++ *  clear. A set bit in this parameter will cause the matching bit in the
++ *  register to be cleared
++ * @return An u32 containing the new value written to the register
++ */
++static inline u32 dma_reg_clear_mask(gmac_priv_t* priv, int reg_num, u32 bits_to_clear)
++{
++    u32 new_value = dma_reg_read(priv, reg_num) & ~bits_to_clear;
++    dma_reg_write(priv, reg_num, new_value);
++    return new_value;
++}
++
++/**
++ * @param priv A gmac_priv_t* pointing to private device data
++ * @param reg_num An int specifying the index of the DMA register to access
++ * @param bits_to_set A u32 specifying which bits of the specified register to
++ *  set. A set bit in this parameter will cause the matching bit in the register
++ *  to be set
++ * @return An u32 containing the new value written to the register
++ */
++static inline u32 dma_reg_set_mask(gmac_priv_t* priv, int reg_num, u32 bits_to_set)
++{
++    u32 new_value = dma_reg_read(priv, reg_num) | bits_to_set;
++    dma_reg_write(priv, reg_num, new_value);
++    return new_value;
++}
++
++static void eth_down(void)
++{
++    // Stop transmitter, take ownership of all tx descriptors
++    dma_reg_clear_mask(priv, DMA_OP_MODE_REG, DMA_OP_MODE_ST_BIT);
++    if (priv->desc_base_addr) {
++        tx_take_ownership(&priv->tx_gmac_desc_list_info);
++    }
++
++    // Stop receiver, take ownership of all rx descriptors
++    dma_reg_clear_mask(priv, DMA_OP_MODE_REG, DMA_OP_MODE_SR_BIT);
++    if (priv->desc_base_addr) {
++        rx_take_ownership(&priv->rx_gmac_desc_list_info);
++    }
++
++    // Free descriptor resources. The TX descriptor will not have a packet
++    // buffer attached, as this is provided by the stack when transmission is
++    // required and ownership is not retained by the descriptor, as the stack
++    // waits for transmission to complete via polling
++    if (priv->desc_base_addr) {
++        // Free receive descriptors, accounting for buffer offset used to
++        // ensure IP header alignment
++        while (1) {
++            dma_addr_t dma_address;
++            if (get_rx_descriptor(priv, 0, &dma_address, 0, 0) < 0) {
++                break;
++            }
++            free((void*)(dma_address - ETHER_FRAME_ALIGN_WASTAGE));
++        }
++
++        // Free DMA descriptors' storage
++        free(priv->desc_base_addr);
++
++        // Remember that we've freed the descriptors memory
++        priv->desc_base_addr = 0;
++    }
++}
++
++/*
++ * Reads a register from the MII Management serial interface
++ */
++int phy_read(int phyaddr, int phyreg)
++{
++    int data = 0;
++    u32 addr = (phyaddr << MAC_GMII_ADR_PA_BIT) |
++               (phyreg << MAC_GMII_ADR_GR_BIT) |
++               (5 << MAC_GMII_ADR_CR_BIT) |
++               (1UL << MAC_GMII_ADR_GB_BIT);
++
++    mac_reg_write(priv, MAC_GMII_ADR_REG, addr);
++
++    for (;;) {
++        if (!(mac_reg_read(priv, MAC_GMII_ADR_REG) & (1UL << MAC_GMII_ADR_GB_BIT))) {
++            // Successfully read from PHY
++            data = mac_reg_read(priv, MAC_GMII_DATA_REG) & 0xFFFF;
++            break;
++        }
++    }
++
++#ifdef DEBUG_GMAC_INIT
++    printf("phy_read() phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", phyaddr, phyreg, data);
++#endif // DEBUG_GMAC_INIT
++
++    return data;
++}
++
++/*
++ * Writes a register to the MII Management serial interface
++ */
++void phy_write(int phyaddr, int phyreg, int phydata)
++{
++    u32 addr = (phyaddr << MAC_GMII_ADR_PA_BIT) |
++               (phyreg << MAC_GMII_ADR_GR_BIT) |
++               (5 << MAC_GMII_ADR_CR_BIT) |
++               (1UL << MAC_GMII_ADR_GW_BIT) |
++               (1UL << MAC_GMII_ADR_GB_BIT);
++
++    mac_reg_write(priv, MAC_GMII_DATA_REG, phydata);
++    mac_reg_write(priv, MAC_GMII_ADR_REG, addr);
++
++    for (;;) {
++        if (!(mac_reg_read(priv, MAC_GMII_ADR_REG) & (1UL << MAC_GMII_ADR_GB_BIT))) {
++            break;
++        }
++    }
++
++#ifdef DEBUG_GMAC_INIT
++    printf("phy_write() phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", phyaddr, phyreg, phydata);
++#endif // DEBUG_GMAC_INIT
++}
++
++/*
++ * Finds and reports the PHY address
++ */
++int phy_detect(void)
++{
++      int found = 0;
++    int phyaddr;
++
++    // Scan all 32 PHY addresses if necessary
++    priv->phy_type = 0;
++    for (phyaddr = 1; phyaddr < 33; ++phyaddr) {
++        unsigned int id1, id2;
++
++        // Read the PHY identifiers
++        id1 = phy_read(phyaddr & 31, MII_PHYSID1);
++        id2 = phy_read(phyaddr & 31, MII_PHYSID2);
++
++#ifdef DEBUG_GMAC_INIT
++        printf("phy_detect() PHY adr = %u -> phy_id1=0x%x, phy_id2=0x%x\n", phyaddr, id1, id2);
++#endif // DEBUG_GMAC_INIT
++
++        // Make sure it is a valid identifier
++        if (id1 != 0x0000 && id1 != 0xffff && id1 != 0x8000 &&
++            id2 != 0x0000 && id2 != 0xffff && id2 != 0x8000) {
++#ifdef DEBUG_GMAC_INIT
++            printf("phy_detect() Found PHY at address = %u\n", phyaddr);
++#endif // DEBUG_GMAC_INIT
++
++            priv->phy_id   = phyaddr & 31;
++            priv->phy_type = id1 << 16 | id2;
++            priv->phy_addr = phyaddr;
++
++                      found = 1;
++            break;
++        }
++    }
++
++      return found;
++}
++
++void start_phy_reset(void)
++{
++    // Ask the PHY to reset
++    phy_write(priv->phy_addr, MII_BMCR, BMCR_RESET);
++}
++
++int is_phy_reset_complete(void)
++{
++    int complete = 0;
++    int bmcr;
++
++    // Read back the status until it indicates reset, or we timeout
++    bmcr = phy_read(priv->phy_addr, MII_BMCR);
++    if (!(bmcr & BMCR_RESET)) {
++        complete = 1;
++    }
++
++    return complete;
++}
++
++void set_phy_type_rgmii(void)
++{
++      // Use sysctrl to switch MAC link lines into either (G)MII or RGMII mode
++    *(volatile u32*)SYS_CTRL_GMAC_CTRL |= (1UL << SYS_CTRL_GMAC_RGMII);
++}
++
++void phy_initialise(void)
++{
++      switch (priv->phy_type) {
++              case PHY_TYPE_VITESSE_VSC8201XVZ:
++                      {
++                              // Allow s/w to override mode/duplex pin settings
++                              u32 acsr = phy_read(priv->phy_id, VSC8201_MII_ACSR);
++
++                              printf("PHY is Vitesse VSC8201XVZ\n");
++                              acsr |= (1UL << VSC8201_MII_ACSR_MDPPS_BIT);
++                              phy_write(priv->phy_id, VSC8201_MII_ACSR, acsr);
++                      }
++                      break;
++              case PHY_TYPE_REALTEK_RTL8211BGR:
++                      printf("PHY is Realtek RTL8211BGR\n");
++                      set_phy_type_rgmii();
++                      break;
++              case PHY_TYPE_LSI_ET1011C:
++                      {
++                              u32 phy_reg;
++
++                              printf("PHY is LSI ET1011C\n");
++
++                              // Configure clocks
++                              phy_reg = phy_read(priv->phy_id, ET1011C_MII_CONFIG);
++                              phy_reg &= ~(((1UL << ET1011C_MII_CONFIG_IFMODESEL_NUM_BITS) - 1) << ET1011C_MII_CONFIG_IFMODESEL);
++                              phy_reg |= (ET1011C_MII_CONFIG_IFMODESEL_GMII_MII << ET1011C_MII_CONFIG_IFMODESEL);
++                              phy_reg |= ((1UL << ET1011C_MII_CONFIG_SYSCLKEN) |
++                              (1UL << ET1011C_MII_CONFIG_TXCLKEN) |
++                                                         (1UL << ET1011C_MII_CONFIG_TBI_RATESEL) |
++                                                         (1UL << ET1011C_MII_CONFIG_CRS_TX_EN));
++                              phy_write(priv->phy_id, ET1011C_MII_CONFIG, phy_reg);
++
++                              // Enable Tx/Rx LED
++                              phy_reg = phy_read(priv->phy_id, ET1011C_MII_LED2);
++                              phy_reg &= ~(((1UL << ET1011C_MII_LED2_LED_NUM_BITS) - 1) << ET1011C_MII_LED2_LED_TXRX);
++                              phy_reg |= (ET1011C_MII_LED2_LED_TXRX_ACTIVITY << ET1011C_MII_LED2_LED_TXRX);
++                              phy_write(priv->phy_id, ET1011C_MII_LED2, phy_reg);
++                      }
++                      break;
++      }
++}
++
++int detect_link_speed(void)
++{
++      u32 lpa2 = phy_read(priv->phy_id, MII_STAT1000);
++
++      if (((lpa2 & LPA_1000FULL)) ||
++              ((lpa2 & LPA_1000HALF))) {
++              priv->link_is_1000M = 1;
++      } else {
++              priv->link_is_1000M = 0;
++      }
++
++      return 0;
++}
++
++int is_autoneg_complete(void)
++{
++    return phy_read(priv->phy_addr, MII_BMSR) & BMSR_ANEGCOMPLETE;
++}
++
++int is_link_ok(void)
++{
++      return phy_read(priv->phy_id, MII_BMSR) & BMSR_LSTATUS;
++}
++
++int eth_init(bd_t *bd)
++{
++    u32  version;
++    u32  reg_contents;
++    u8  *mac_addr;
++    int  desc;
++
++    // Set hardware device base addresses
++    priv->macBase = (MAC_BASE_PA + MAC_BASE_OFFSET);
++    priv->dmaBase = (MAC_BASE_PA + DMA_BASE_OFFSET);
++
++#ifdef DEBUG_GMAC_INIT
++    printf("eth_init(): About to reset MAC core\n");
++#endif // DEBUG_GMAC_INIT
++    // Ensure the MAC block is properly reset
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_MAC_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_MAC_BIT);
++
++    // Enable the clock to the MAC block
++    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_MAC_BIT);
++
++    version = mac_reg_read(priv, MAC_VERSION_REG);
++#ifdef DEBUG_GMAC_INIT
++    printf("eth_init(): GMAC Synopsis version = 0x%x, vendor version = 0x%x\n", version & 0xff, (version >> 8) & 0xff);
++#endif // DEBUG_GMAC_INIT
++
++    // Use simple mux for 25/125 Mhz clock switching
++    *(volatile u32*)SYS_CTRL_GMAC_CTRL |= (1UL << SYS_CTRL_GMAC_SIMPLE_MAX);
++
++    // Enable GMII_GTXCLK to follow GMII_REFCLK - required for gigabit PHY
++    *(volatile u32*)SYS_CTRL_GMAC_CTRL |= (1UL << SYS_CTRL_GMAC_CKEN_GTX);
++
++    // Disable all GMAC interrupts
++    dma_reg_write(priv, DMA_INT_ENABLE_REG, 0);
++
++    // Reset the entire GMAC
++    dma_reg_write(priv, DMA_BUS_MODE_REG, 1UL << DMA_BUS_MODE_SWR_BIT);
++
++    // Wait for the reset operation to complete
++      printf("Wait GMAC to reset");
++    while (dma_reg_read(priv, DMA_BUS_MODE_REG) & (1UL << DMA_BUS_MODE_SWR_BIT)) {
++              udelay(250000);
++              printf(".");
++    }
++      printf("\n");
++
++      // Attempt to discover link speed from the PHY
++      if (!phy_detect()) {
++              printf("No PHY found\n");
++      } else {
++              // Ensure the PHY is in a sensible state by resetting it
++              start_phy_reset();
++
++              // Read back the status until it indicates reset, or we timeout
++              printf("Wait for PHY reset");
++              while (!is_phy_reset_complete()) {
++                      udelay(250000);
++                      printf(".");
++              }
++              printf("\n");
++
++              // Setup the PHY based on its type
++              phy_initialise();
++
++              printf("Wait for link to come up");
++              while (!is_link_ok()) {
++                      udelay(250000);
++                      printf(".");
++              }
++              printf("Link up\n");
++
++              // Wait for PHY to have completed autonegotiation
++              printf("Wait for auto-negotiation to complete");
++              while (!is_autoneg_complete()) {
++                      udelay(250000);
++                      printf(".");
++              }
++              printf("\n");
++
++              // Interrogate the PHY for the link speed
++              if (detect_link_speed()) {
++                      printf("Failed to detect link speed\n");
++              } else {
++                      printf("Link is %s\n", priv->link_is_1000M ? "1000M" : "10M/100M");
++              }
++      }
++
++    // Form the MAC config register contents
++    reg_contents = 0;
++      if (!priv->link_is_1000M) {
++              reg_contents |= (1UL << MAC_CONFIG_PS_BIT); // Gigabit
++      }
++    reg_contents |= (1UL << MAC_CONFIG_DM_BIT); // Full duplex
++    reg_contents |= ((1UL << MAC_CONFIG_TE_BIT) |
++                     (1UL << MAC_CONFIG_RE_BIT));
++    mac_reg_write(priv, MAC_CONFIG_REG, reg_contents);
++
++    // Form the MAC frame filter register contents
++    reg_contents = 0;
++    mac_reg_write(priv, MAC_FRAME_FILTER_REG, reg_contents);
++
++    // Form the hash table registers contents
++    mac_reg_write(priv, MAC_HASH_HIGH_REG, 0);
++    mac_reg_write(priv, MAC_HASH_LOW_REG, 0);
++
++    // Form the MAC flow control register contents
++    reg_contents = 0;
++    reg_contents |= ((1UL << MAC_FLOW_CNTL_RFE_BIT) |
++                     (1UL << MAC_FLOW_CNTL_TFE_BIT));
++    mac_reg_write(priv, MAC_FLOW_CNTL_REG, reg_contents);
++
++    // Form the MAC VLAN tag register contents
++    reg_contents = 0;
++    mac_reg_write(priv, MAC_VLAN_TAG_REG, reg_contents);
++
++    // Form the MAC addr0 high and low registers contents from the character
++    // string representation from the environment
++    mac_addr = getenv("ethaddr");
++#ifdef DEBUG_GMAC_INIT
++    printf("eth_init(): Mac addr = %s\n", mac_addr);
++#endif // DEBUG_GMAC_INIT
++    reg_contents  =  simple_strtoul(mac_addr+0, 0, 16);
++    reg_contents |= (simple_strtoul(mac_addr+3, 0, 16) << 8);
++    reg_contents |= (simple_strtoul(mac_addr+6, 0, 16) << 16);
++    reg_contents |= (simple_strtoul(mac_addr+9, 0, 16) << 24);
++    mac_reg_write(priv, MAC_ADR0_LOW_REG, reg_contents);
++    reg_contents  =  simple_strtoul(mac_addr+12, 0, 16);
++    reg_contents |= (simple_strtoul(mac_addr+15, 0, 16) << 8);
++    mac_reg_write(priv, MAC_ADR0_HIGH_REG, reg_contents);
++
++    // Disable all MMC interrupt sources
++    mac_reg_write(priv, MMC_RX_MASK_REG, ~0UL);
++    mac_reg_write(priv, MMC_TX_MASK_REG, ~0UL);
++
++    // Remember how large the unified descriptor array is to be
++    priv->total_num_descriptors = NUM_RX_DMA_DESCRIPTORS + NUM_TX_DMA_DESCRIPTORS;
++
++    // Need a consistent DMA mapping covering all the memory occupied by DMA
++    // unified descriptor array, as both CPU and DMA engine will be reading and
++    // writing descriptor fields.
++    priv->desc_base_addr = (gmac_dma_desc_t*)malloc(sizeof(gmac_dma_desc_t) * priv->total_num_descriptors);
++    if (!priv->desc_base_addr) {
++       printf("eth_init(): Failed to allocate memory for DMA descriptors\n");
++        goto err_out;
++    }
++
++    // Initialise the structures managing the TX descriptor list
++    init_tx_desc_list(&priv->tx_gmac_desc_list_info,
++                      priv->desc_base_addr,
++                      NUM_TX_DMA_DESCRIPTORS);
++
++    // Initialise the structures managing the RX descriptor list
++    init_rx_desc_list(&priv->rx_gmac_desc_list_info,
++                      priv->desc_base_addr + NUM_TX_DMA_DESCRIPTORS,
++                      priv->total_num_descriptors - NUM_TX_DMA_DESCRIPTORS);
++
++    // Prepare receive descriptors
++    desc = 0;
++    while (available_for_write(&priv->rx_gmac_desc_list_info)) {
++        // Allocate a new buffer for the descriptor which is large enough for
++        // any packet received from the link
++        dma_addr_t dma_address = (dma_addr_t)malloc(ETHER_MTU + ETHER_FRAME_ALIGN_WASTAGE + EXTRA_RX_SKB_SPACE);
++        if (!dma_address) {
++            printf("eth_init(): No memory for socket buffer\n");
++            break;
++        }
++
++        desc = set_rx_descriptor(priv,
++                                 dma_address + ETHER_FRAME_ALIGN_WASTAGE,
++                                 ETHER_MTU + EXTRA_RX_SKB_SPACE,
++                                 0);
++
++        if (desc < 0) {
++            // Release the buffer
++            free((void*)dma_address);
++
++            printf("eth_init(): Error, no RX descriptor available\n");
++            goto err_out;
++        }
++    }
++
++    // Initialise the GMAC DMA bus mode register
++    dma_reg_write(priv, DMA_BUS_MODE_REG, ((0UL << DMA_BUS_MODE_FB_BIT)   |
++                                           (0UL << DMA_BUS_MODE_PR_BIT)   |
++                                           (32UL << DMA_BUS_MODE_PBL_BIT) | // AHB burst size
++                                           (1UL << DMA_BUS_MODE_DSL_BIT)  | 
++                                           (0UL << DMA_BUS_MODE_DA_BIT)));
++
++    // Write the address of the start of the tx descriptor array
++    dma_reg_write(priv, DMA_TX_DESC_ADR_REG, (u32)priv->desc_base_addr);
++
++    // Write the address of the start of the rx descriptor array
++    dma_reg_write(priv, DMA_RX_DESC_ADR_REG,
++        (u32)(priv->desc_base_addr + priv->tx_gmac_desc_list_info.num_descriptors));
++
++    // Clear any pending interrupt requests
++    dma_reg_write(priv, DMA_STATUS_REG, dma_reg_read(priv, DMA_STATUS_REG));
++
++    // Initialise the GMAC DMA operation mode register, starting both the
++    // transmitter and receiver
++    dma_reg_write(priv, DMA_OP_MODE_REG, ((1UL << DMA_OP_MODE_SF_BIT)  |    // Store and forward
++                                          (0UL << DMA_OP_MODE_TTC_BIT) |    // Tx threshold
++                                          (1UL << DMA_OP_MODE_ST_BIT)  |    // Enable transmitter
++                                          (0UL << DMA_OP_MODE_RTC_BIT) |    // Rx threshold
++                                          (1UL << DMA_OP_MODE_SR_BIT)));    // Enable receiver
++
++    // Success
++    return 1;
++
++err_out:
++    eth_down();
++
++    return 0;
++}
++
++void eth_halt(void)
++{
++    eth_down();
++
++    // Disable the clock to the MAC block
++    *(volatile u32*)(SYS_CTRL_CKEN_CLR_CTRL) = (1UL << SYS_CTRL_CKEN_MAC_BIT);
++}
++
++int eth_rx(void)
++{
++    static const int MAX_LOOPS = 2000;   // 2 seconds
++
++    int length = 0;
++    dma_addr_t dma_address;
++    u32 desc_status;
++    int loops = 0;
++
++    // Look for the first available received packet
++    while (loops++ < MAX_LOOPS) {
++        if (get_rx_descriptor(priv, &desc_status, &dma_address, 0, 0) >= 0) {
++            if (is_rx_valid(desc_status)) {
++                // Get the length of the packet within the buffer
++                length = get_rx_length(desc_status);
++
++                // Pass packet up the network stack - will block until processing is
++                // completed
++                NetReceive((uchar*)dma_address, length);
++            } else {
++                printf("eth_rx() Received packet has bad desc_status = 0x%08x\n", desc_status);
++            }
++
++            // Re-initialise the RX descriptor with its buffer - relies on always
++            // setting an RX descriptor directly after getting it
++            if (set_rx_descriptor(priv, dma_address, ETHER_MTU + EXTRA_RX_SKB_SPACE, 0) < 0) {
++                 printf("eth_rx(): Failed to set RX descriptor\n");
++            }
++
++            break;
++        }
++
++        // Wait a bit before trying again to get a descriptor
++        udelay(1000);   // 1mS
++    }
++
++    return length;
++}
++
++int eth_send(volatile void *packet, int length)
++{
++    // Transmit the new packet
++    while (1) {
++        // Get the TX descriptor
++        if (set_tx_descriptor(priv, (dma_addr_t)packet, length, 0) >= 0) {
++            // Tell the GMAC to poll for the updated descriptor
++            dma_reg_write(priv, DMA_TX_POLL_REG, 0);
++            break;
++        }
++
++        // Wait a bit before trying again to get a descriptor
++        udelay(1000);   // 1mS
++    }
++
++    // Wait for the packet buffer to be finished with
++    while (get_tx_descriptor(priv, 0, 0, 0, 0) < 0) {
++        // Wait a bit before examining the descriptor again
++        udelay(1000);   // 1mS
++    }
++
++    return length;
++}
++
+diff -Nurd u-boot-2009.03.orig/board/hipox/hipox.c u-boot-2009.03/board/hipox/hipox.c
+--- u-boot-2009.03.orig/board/hipox/hipox.c    1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/hipox.c 2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,385 @@
++/*
++ * (C) Copyright 2005
++ * Oxford Semiconductor Ltd
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <asm/io.h>
++
++#if defined(CONFIG_SHOW_BOOT_PROGRESS)
++void show_boot_progress(int progress)
++{
++    printf("Boot reached stage %d\n", progress);
++}
++#endif
++
++static inline void delay(unsigned long loops)
++{
++    __asm__ volatile ("1:\n"
++        "subs %0, %1, #1\n"
++        "bne 1b":"=r" (loops):"0" (loops));
++}
++
++/*
++ * Miscellaneous platform dependent initialisations
++ */
++
++/** Expected Intel 28F320B3T CFI info */
++//    mfr_id:                 MANUFACTURER_INTEL, -> 0x0089
++//    dev_id:                 I28F320B3T,         -> 0x8896
++//    name:                   "Intel 28F320B3T",
++//    DevSize:                SIZE_4MiB,              -> 22
++//    CmdSet:                 P_ID_INTEL_STD,     -> 0x0003
++//    NumEraseRegions:        2,
++//    regions: {                            -> #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
++//        ERASEINFO(0x10000, 63),
++//        ERASEINFO(0x02000, 8),
++//    }
++
++#define FLASH_WORD_SIZE unsigned short
++
++int board_init(void)
++{
++    DECLARE_GLOBAL_DATA_PTR;
++
++    gd->bd->bi_arch_number = MACH_TYPE_HIPOX;
++    gd->bd->bi_boot_params = PHYS_SDRAM_1_PA + 0x100;
++    gd->flags = 0;
++
++    icache_enable();
++
++    /* Block reset Static core */
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_STATIC_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_STATIC_BIT);
++
++    /* Enable clock to Static core */
++    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_STATIC_BIT);
++
++#ifdef CONFIG_HIPOX_ENABLE_PCI
++    /* Block reset PCI core */
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_PCI_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_PCI_BIT);
++
++    /* Enable clock to PCI core */
++    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_PCI_BIT);
++#endif // CONFIG_HIPOX_ENABLE_PCI
++
++#ifdef CONFIG_HIPOX_MANUAL_STATIC_ARBITRATION
++    /* Assert manual static bus PCI arbitration request */
++    *(volatile u32*)SYS_CTRL_PCI_CTRL1 |= (1UL << SYS_CTRL_PCI_CTRL1_PCI_STATIC_RQ_BIT);
++#endif // CONFIG_HIPOX_MANUAL_STATIC_ARBITRATION
++
++#ifdef CONFIG_HIPOX_FEEDBACK_PCI_CLKS
++    /* Set PCI feedback clk GPIO pin as an output */
++    *(volatile u32*)GPIO_1_SET_OE |= 0x800;
++
++    /* Enable PCI feedback clk onto GPIO pin */
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 |= 0x00000800;
++#endif // CONFIG_HIPOX_FEEDBACK_PCI_CLKS
++
++#ifndef CONFIG_SYS_NO_FLASH
++    /* Enable static bus onto GPIOs, only CS0 as CS1 conflicts with UART2 */
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 |= 0x002FF000;
++
++    /* Setup the static bus CS0 to access FLASH */
++    *(volatile u32*)STATIC_CONTROL_BANK0 = STATIC_BUS_FLASH_CONFIG;
++#endif // !CONFIG_SYS_NO_FLASH
++
++    /* Set 33MHz PCI clock */
++    *(volatile u32*)SYS_CTRL_CKCTRL_CTRL_ADDR = 5;
++    /* Enable full speed RPS clock */
++    *(volatile u32*)SYS_CTRL_CKCTRL_CTRL_ADDR &= ~(1UL << SYS_CTRL_CKCTRL_SLOW_BIT);
++
++#if (USE_EXTERNAL_UART == 0)
++#ifdef CONFIG_HIPOX_UART1
++    /* Block reset UART1 */
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART1_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART1_BIT);
++
++    /* Setup pin mux'ing for first internal UART */
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x80000000;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x80000000;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x80000000; // Route UART1 SOUT onto external pins
++
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_1 &= ~0x00000001;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_1  &= ~0x00000001;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_1 |=  0x00000001; // Route UART1 SIN onto external pins
++
++    *(volatile u32*)GPIO_1_SET_OE |= 0x80000000;                // Make UART1 SOUT an o/p
++    *(volatile u32*)GPIO_2_CLR_OE |= 0x00000001;                // Make UART1 SIN an i/p
++#endif // CONFIG_HIPOX_UART1
++
++#ifdef CONFIG_HIPOX_UART2
++    // Block reset UART2
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART2_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART2_BIT);
++
++    /* Setup pin mux'ing for second internal UART */
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x00500000;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x00500000;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x00500000; // Route UART2 SOUT and SIN onto external pins
++
++    *(volatile u32*)GPIO_1_SET_OE |= 0x00100000;                // Make UART2 SOUT an o/p
++    *(volatile u32*)GPIO_1_CLR_OE |= 0x00400000;                // Make UART2 SIN an i/p
++#endif // CONFIG_HIPOX_UART2
++
++#ifdef CONFIG_HIPOX_UART3
++    // Block reset UART3
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART3_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART3_BIT);
++
++    // Route UART3 SIN/SOUT onto external pin
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x000000C0;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x000000C0;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x000000C0;
++
++    // Setup GPIO line directions for UART3 SIN/SOUT
++    *(volatile u32*)GPIO_1_SET_OE   |= 0x00000080;
++    *(volatile u32*)GPIO_1_CLR_OE |= 0x00000040;
++#endif // CONFIG_ARCH_HIPOX_UART3
++
++#ifdef CONFIG_HIPOX_UART4
++    // Block reset UART4
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART4_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART4_BIT);
++
++    // Enable UART4 to override PCI functions onto GPIOs
++    *(volatile u32*)SYS_CTRL_UART_CTRL |= (1UL << SYS_CTRL_UART4_NOT_PCI_MODE);
++#endif // CONFIG_HIPOX_UART4
++#endif // !USE_EXTERNAL_UART
++
++    return 0;
++}
++
++int board_late_init()
++{
++    return 0;
++}
++
++int misc_init_r(void)
++{
++    return 0;
++}
++
++int dram_init(void)
++{
++#ifdef PROBE_MEM_SIZE
++      /* Determine the amount of SDRAM the DDR controller is configured for */
++      volatile unsigned long * const ddr_config_reg_adr = (volatile unsigned long *)(0x45800000);
++      static const int DDR_SIZE_BIT = 17;
++      static const int DDR_SIZE_NUM_BITS = 4;
++      static const unsigned long DDR_SIZE_MASK = (((1UL << DDR_SIZE_NUM_BITS) - 1) << DDR_SIZE_BIT);
++
++      unsigned long ddr_config_reg = *ddr_config_reg_adr;
++      int ddr_size_pow2 = (ddr_config_reg & DDR_SIZE_MASK) >> DDR_SIZE_BIT;
++
++    DECLARE_GLOBAL_DATA_PTR;
++
++    gd->bd->bi_dram[0].size  = (1 << ddr_size_pow2) * 1024 * 1024;
++
++      if ((gd->bd->bi_dram[0].size >> 20) == 256) {
++              /* Do we really have 256M, or are we working around the DDR controller's
++               * problem with 128M size? */
++              volatile unsigned long * const PROBE_ADR_1 = (volatile unsigned long * const)PHYS_SDRAM_1_PA;
++              volatile unsigned long * const PROBE_ADR_2 = (volatile unsigned long * const)(PHYS_SDRAM_1_PA + (128*1024*1024));
++              static const unsigned long PROBE_VAL_1 = 0xdeadbeef;
++              static const unsigned long PROBE_VAL_2 = 0x12345678;
++
++              *PROBE_ADR_1 = PROBE_VAL_1;
++              *PROBE_ADR_2 = PROBE_VAL_2;
++              if (*PROBE_ADR_1 != PROBE_VAL_1) {
++                      gd->bd->bi_dram[0].size  = 128*1024*1024;
++              }
++      }
++#else // PROBE_MEM_SIZE
++    gd->bd->bi_dram[0].size = MEM_SIZE;
++#endif // PROBE_MEM_SIZE
++
++    gd->bd->bi_dram[0].start = PHYS_SDRAM_1_PA;
++
++      gd->bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;
++      gd->bd->bi_sramsize = CONFIG_SYS_SRAM_SIZE;
++
++    return 0;
++}
++
++void reset_cpu (ulong addr)
++{
++    printf("Resetting Oxsemi NAS...");
++
++    // Assert reset to cores as per power on defaults
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL =
++        (1UL << SYS_CTRL_RSTEN_COPRO_BIT)    |
++        (1UL << SYS_CTRL_RSTEN_USBHS_BIT)    |
++        (1UL << SYS_CTRL_RSTEN_USBHSPHY_BIT) |
++        (1UL << SYS_CTRL_RSTEN_MAC_BIT)      |
++        (1UL << SYS_CTRL_RSTEN_PCI_BIT)      |
++        (1UL << SYS_CTRL_RSTEN_DMA_BIT)      |
++        (1UL << SYS_CTRL_RSTEN_DPE_BIT)      |
++        (1UL << SYS_CTRL_RSTEN_SATA_BIT)     |
++        (1UL << SYS_CTRL_RSTEN_SATA_LINK_BIT) |
++        (1UL << SYS_CTRL_RSTEN_SATA_PHY_BIT) |
++        (1UL << SYS_CTRL_RSTEN_STATIC_BIT)   |
++        (1UL << SYS_CTRL_RSTEN_UART1_BIT)    |
++        (1UL << SYS_CTRL_RSTEN_UART2_BIT)    |
++        (1UL << SYS_CTRL_RSTEN_MISC_BIT)     |
++        (1UL << SYS_CTRL_RSTEN_I2S_BIT)      |
++        (1UL << SYS_CTRL_RSTEN_AHB_MON_BIT)  |
++        (1UL << SYS_CTRL_RSTEN_UART3_BIT)    |
++        (1UL << SYS_CTRL_RSTEN_UART4_BIT)    |
++        (1UL << SYS_CTRL_RSTEN_SGDMA_BIT);
++
++    // Release reset to cores as per power on defaults
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_GPIO_BIT);
++
++    // Disable clocks to cores as per power-on defaults
++    *(volatile u32*)SYS_CTRL_CKEN_CLR_CTRL =
++        (1UL << SYS_CTRL_CKEN_COPRO_BIT) |
++        (1UL << SYS_CTRL_CKEN_DMA_BIT)   |
++        (1UL << SYS_CTRL_CKEN_DPE_BIT)   |
++        (1UL << SYS_CTRL_CKEN_SATA_BIT)  |
++        (1UL << SYS_CTRL_CKEN_I2S_BIT)   |
++        (1UL << SYS_CTRL_CKEN_USBHS_BIT) |
++        (1UL << SYS_CTRL_CKEN_MAC_BIT)   |
++        (1UL << SYS_CTRL_CKEN_STATIC_BIT);
++
++    // Enable clocks to cores as per power-on defaults
++    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_PCI_BIT);
++
++    // Set sys-control pin mux'ing as per power-on defaults
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 = 0x800UL;
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_1 = 0x0UL;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  = 0x0UL;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_1  = 0x0UL;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 = 0x0UL;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_1 = 0x0UL;
++
++    // No need to save any state, as the ROM loader can determine whether reset
++    // is due to power cycling or programatic action, just hit the (self-
++    // clearing) CPU reset bit of the block reset register
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL =  (1UL << SYS_CTRL_RSTEN_ARM_BIT);
++}
++
++#ifdef CONFIG_CMD_NAND
++#include <linux/mtd/nand.h>
++
++static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
++{
++      struct nand_chip *this = mtdinfo->priv;
++
++      if (ctrl & NAND_CTRL_CHANGE) {
++              ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
++
++              IO_ADDR_W = CONFIG_SYS_NAND_BASE;
++
++#ifdef CONFIG_HIPOX_NAND_GPIO33
++              if (ctrl & NAND_NCE)
++                      *((volatile u32 *)GPIO_2_SET) = 0x00000002; // assert CS-NAND
++              else
++                      *((volatile u32 *)GPIO_2_CLR) = 0x00000002; // deassert CS-NAND
++#else
++              if (ctrl & NAND_NCE)
++                      *((volatile u32 *)GPIO_1_CLR) = 0x20000000; // assert CS-NAND
++              else
++                      *((volatile u32 *)GPIO_1_SET) = 0x20000000; // deassert CS-NAND
++#endif
++
++              if (ctrl & NAND_CLE)
++                      IO_ADDR_W = CONFIG_SYS_NAND_COMMAND_LATCH;
++              if (ctrl & NAND_ALE)
++                      IO_ADDR_W = CONFIG_SYS_NAND_ADDRESS_LATCH;
++
++              this->IO_ADDR_W = (void *)IO_ADDR_W;
++
++      }
++
++      if (cmd != NAND_CMD_NONE)
++              writeb(cmd, this->IO_ADDR_W);
++}
++
++static void oxe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
++{
++      uint32_t save_bank0_timing;
++
++      struct nand_chip *chip = mtd->priv;
++   volatile uint8_t *io = chip->IO_ADDR_R;
++
++      // change read access timing
++      save_bank0_timing = *(volatile u32*)STATIC_CONTROL_BANK0;
++      *(volatile u32*)STATIC_CONTROL_BANK0 = 0x4f1f3f04; // 27 ns
++
++   while(len-- > 0)
++      *buf++ = *io;
++
++      // restore timing
++      *(volatile u32*)STATIC_CONTROL_BANK0 = save_bank0_timing;
++}
++
++int board_nand_init(struct nand_chip *nand)
++{
++#ifdef CONFIG_HIPOX_NAND_GPIO33
++      // use GPIO 33, active high
++
++      *((volatile u32 *)GPIO_2_CLR) = 0x00000002;
++      *((volatile u32 *)GPIO_2_SET_OE) = 0x00000002;
++
++      // unselect alternate functions
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_1 &= ~0x00000002;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_1  &= ~0x00000002;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_1 &= ~0x00000002;
++
++      // assert CS-NAND
++      *((volatile u32 *)GPIO_2_SET) = 0x00000002;
++#else
++      // use GPIO 29, active low
++
++      *((volatile u32 *)GPIO_1_SET) = 0x20000000;
++      *((volatile u32 *)GPIO_1_SET_OE) = 0x20000000;
++
++      // unselect alternate functions
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x20000000;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x20000000;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 &= ~0x20000000;
++
++      // assert CS-NAND
++      *((volatile u32 *)GPIO_1_CLR) = 0x20000000;
++#endif
++
++      // reset NAND unit
++      *((volatile u8 *)(CONFIG_SYS_NAND_COMMAND_LATCH)) = 0xff;       // reset command
++      udelay(500);
++
++#ifdef CONFIG_HIPOX_NAND_GPIO33
++      // deassert CS-NAND
++      *((volatile u32 *)GPIO_2_CLR) = 0x00000002;
++#else
++      // deassert CS-NAND
++      *((volatile u32 *)GPIO_1_SET) = 0x20000000;
++#endif
++
++      nand->chip_delay = 50;
++      nand->ecc.mode = NAND_ECC_SOFT;
++      nand->cmd_ctrl = nand_hwcontrol;
++      nand->read_buf = oxe_read_buf;
++
++      return 0;
++}
++#endif
+diff -Nurd u-boot-2009.03.orig/board/hipox/ide-810.c u-boot-2009.03/board/hipox/ide-810.c
+--- u-boot-2009.03.orig/board/hipox/ide-810.c  1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/ide-810.c       2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,892 @@
++/*
++ * (C) Copyright 2005
++ * Oxford Semiconductor Ltd
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,`
++ * MA 02111-1307 USA
++ */
++#include <common.h>
++
++#define SATA_DMA_CHANNEL 0
++
++#define DMA_CTRL_STATUS      (0x0)
++#define DMA_BASE_SRC_ADR     (0x4)
++#define DMA_BASE_DST_ADR     (0x8)
++#define DMA_BYTE_CNT         (0xC)
++#define DMA_CURRENT_SRC_ADR  (0x10)
++#define DMA_CURRENT_DST_ADR  (0x14)
++#define DMA_CURRENT_BYTE_CNT (0x18)
++#define DMA_INTR_ID          (0x1C)
++#define DMA_INTR_CLEAR_REG   (DMA_CURRENT_SRC_ADR)
++
++#define DMA_CALC_REG_ADR(channel, register) ((volatile u32*)(DMA_BASE_PA + ((channel) << 5) + (register)))
++
++#define DMA_CTRL_STATUS_FAIR_SHARE_ARB            (1 << 0)
++#define DMA_CTRL_STATUS_IN_PROGRESS               (1 << 1)
++#define DMA_CTRL_STATUS_SRC_DREQ_MASK             (0x0000003C)
++#define DMA_CTRL_STATUS_SRC_DREQ_SHIFT            (2)
++#define DMA_CTRL_STATUS_DEST_DREQ_MASK            (0x000003C0)
++#define DMA_CTRL_STATUS_DEST_DREQ_SHIFT           (6)
++#define DMA_CTRL_STATUS_INTR                      (1 << 10)
++#define DMA_CTRL_STATUS_NXT_FREE                  (1 << 11)
++#define DMA_CTRL_STATUS_RESET                     (1 << 12)
++#define DMA_CTRL_STATUS_DIR_MASK                  (0x00006000)
++#define DMA_CTRL_STATUS_DIR_SHIFT                 (13)
++#define DMA_CTRL_STATUS_SRC_ADR_MODE              (1 << 15)
++#define DMA_CTRL_STATUS_DEST_ADR_MODE             (1 << 16)
++#define DMA_CTRL_STATUS_TRANSFER_MODE_A           (1 << 17)
++#define DMA_CTRL_STATUS_TRANSFER_MODE_B           (1 << 18)
++#define DMA_CTRL_STATUS_SRC_WIDTH_MASK            (0x00380000)
++#define DMA_CTRL_STATUS_SRC_WIDTH_SHIFT           (19)
++#define DMA_CTRL_STATUS_DEST_WIDTH_MASK           (0x01C00000)
++#define DMA_CTRL_STATUS_DEST_WIDTH_SHIFT          (22)
++#define DMA_CTRL_STATUS_PAUSE                     (1 << 25)
++#define DMA_CTRL_STATUS_INTERRUPT_ENABLE          (1 << 26)
++#define DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED      (1 << 27)
++#define DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED (1 << 28)
++#define DMA_CTRL_STATUS_STARVE_LOW_PRIORITY       (1 << 29)
++#define DMA_CTRL_STATUS_INTR_CLEAR_ENABLE         (1 << 30)
++
++#define DMA_BYTE_CNT_MASK        ((1 << 21) - 1)
++#define DMA_BYTE_CNT_WR_EOT_MASK (1 << 30)
++#define DMA_BYTE_CNT_RD_EOT_MASK (1 << 31)
++
++#define MAKE_FIELD(value, num_bits, bit_num) (((value) & ((1 << (num_bits)) - 1)) << (bit_num))
++
++typedef enum hipox_dma_mode {
++    HIPOX_DMA_MODE_FIXED,
++    HIPOX_DMA_MODE_INC
++} hipox_dma_mode_t;
++
++typedef enum hipox_dma_direction {
++    HIPOX_DMA_TO_DEVICE,
++    HIPOX_DMA_FROM_DEVICE
++} hipox_dma_direction_t;
++
++/* The available buses to which the DMA controller is attached */
++typedef enum hipox_dma_transfer_bus
++{
++    HIPOX_DMA_SIDE_A,
++    HIPOX_DMA_SIDE_B
++} hipox_dma_transfer_bus_t;
++
++/* Direction of data flow between the DMA controller's pair of interfaces */
++typedef enum hipox_dma_transfer_direction
++{
++    HIPOX_DMA_A_TO_A,
++    HIPOX_DMA_B_TO_A,
++    HIPOX_DMA_A_TO_B,
++    HIPOX_DMA_B_TO_B
++} hipox_dma_transfer_direction_t;
++
++/* The available data widths */
++typedef enum hipox_dma_transfer_width
++{
++    HIPOX_DMA_TRANSFER_WIDTH_8BITS,
++    HIPOX_DMA_TRANSFER_WIDTH_16BITS,
++    HIPOX_DMA_TRANSFER_WIDTH_32BITS
++} hipox_dma_transfer_width_t;
++
++/* The mode of the DMA transfer */
++typedef enum hipox_dma_transfer_mode
++{
++    HIPOX_DMA_TRANSFER_MODE_SINGLE,
++    HIPOX_DMA_TRANSFER_MODE_BURST
++} hipox_dma_transfer_mode_t;
++
++/* The available transfer targets */
++typedef enum hipox_dma_dreq
++{
++    HIPOX_DMA_DREQ_SATA   = 0,
++    HIPOX_DMA_DREQ_MEMORY = 15
++} hipox_dma_dreq_t;
++
++typedef struct hipox_dma_device_settings {
++    unsigned long address_;
++    unsigned      fifo_size_;   // Chained transfers must take account of FIFO offset at end of previous transfer
++    unsigned char dreq_;
++    unsigned      read_eot_:1;
++    unsigned      read_final_eot_:1;
++    unsigned      write_eot_:1;
++    unsigned      write_final_eot_:1;
++    unsigned      bus_:1;
++    unsigned      width_:2;
++    unsigned      transfer_mode_:1;
++    unsigned      address_mode_:1;
++    unsigned      address_really_fixed_:1;
++} hipox_dma_device_settings_t;
++
++static const int MAX_NO_ERROR_LOOPS  = 100000;  /* 1 second in units of 10uS */
++static const int MAX_DMA_XFER_LOOPS  = 300000;  /* 30 seconds in units of 100uS */
++static const int MAX_DMA_ABORT_LOOPS = 10000;   /* 0.1 second in units of 10uS */
++static const int MAX_SRC_READ_LOOPS  = 10000;   /* 0.1 second in units of 10uS */
++static const int MAX_SRC_WRITE_LOOPS = 10000;   /* 0.1 second in units of 10uS */
++static const int MAX_NOT_BUSY_LOOPS  = 10000;   /* 1 second in units of 100uS */
++
++/* The internal SATA drive on which we should attempt to find partitions */
++static volatile u32* sata_regs_base[2] = 
++{
++    (volatile u32*)SATA_0_REGS_BASE,
++    (volatile u32*)SATA_1_REGS_BASE,
++    
++};
++static u32 wr_sata_orb1[2] = { 0, 0 };
++static u32 wr_sata_orb2[2] = { 0, 0 };
++static u32 wr_sata_orb3[2] = { 0, 0 };
++static u32 wr_sata_orb4[2] = { 0, 0 };
++
++static hipox_dma_device_settings_t hipox_sata_dma_settings = {
++    .address_              = SATA_DATA_BASE_PA,
++    .fifo_size_            = 16,
++    .dreq_                 = HIPOX_DMA_DREQ_SATA,
++    .read_eot_             = 0,
++    .read_final_eot_       = 1,
++    .write_eot_            = 0,
++    .write_final_eot_      = 1,
++    .bus_                  = HIPOX_DMA_SIDE_A,
++    .width_                = HIPOX_DMA_TRANSFER_WIDTH_32BITS,
++    .transfer_mode_        = HIPOX_DMA_TRANSFER_MODE_BURST,
++    .address_mode_         = HIPOX_DMA_MODE_FIXED,
++    .address_really_fixed_ = 0
++};
++
++hipox_dma_device_settings_t hipox_ram_dma_settings = {
++    .address_              = 0,
++    .fifo_size_            = 0,
++    .dreq_                 = HIPOX_DMA_DREQ_MEMORY,
++    .read_eot_             = 1,
++    .read_final_eot_       = 1,
++    .write_eot_            = 1,
++    .write_final_eot_      = 1,
++    .bus_                  = HIPOX_DMA_SIDE_B,
++    .width_                = HIPOX_DMA_TRANSFER_WIDTH_32BITS,
++    .transfer_mode_        = HIPOX_DMA_TRANSFER_MODE_BURST,
++    .address_mode_         = HIPOX_DMA_MODE_FIXED,
++    .address_really_fixed_ = 1
++};
++
++static void xfer_wr_shadow_to_orbs(int device)
++{
++    *(sata_regs_base[device] + SATA_ORB1_OFF) = wr_sata_orb1[device];
++    *(sata_regs_base[device] + SATA_ORB2_OFF) = wr_sata_orb2[device];
++    *(sata_regs_base[device] + SATA_ORB3_OFF) = wr_sata_orb3[device];
++    *(sata_regs_base[device] + SATA_ORB4_OFF) = wr_sata_orb4[device];
++}
++
++static inline void device_select(int device)
++{
++    /* master/slave has no meaning to SATA core */
++}
++
++static int disk_present[CONFIG_SYS_IDE_MAXDEVICE];
++
++#include <ata.h>
++
++unsigned char inline ide_inb(int device, int port)
++{
++    unsigned char val = 0;
++
++    /* Only permit accesses to disks found to be present during ide_preinit() */
++    if (!disk_present[device]) {
++        return ATA_STAT_FAULT;
++    }
++
++    device_select(device);
++
++    switch (port) {
++        case ATA_PORT_CTL:
++            val = (*(sata_regs_base[device] + SATA_ORB4_OFF) & (0xFFUL << SATA_CTL_BIT)) >> SATA_CTL_BIT;
++            break;
++        case ATA_PORT_FEATURE:
++            val = (*(sata_regs_base[device] + SATA_ORB2_OFF) & (0xFFUL << SATA_FEATURE_BIT)) >> SATA_FEATURE_BIT;
++            break;
++        case ATA_PORT_NSECT:
++            val = (*(sata_regs_base[device] + SATA_ORB2_OFF) & (0xFFUL << SATA_NSECT_BIT)) >> SATA_NSECT_BIT;
++            break;
++        case ATA_PORT_LBAL:
++            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_LBAL_BIT)) >> SATA_LBAL_BIT;
++            break;
++        case ATA_PORT_LBAM:
++            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_LBAM_BIT)) >> SATA_LBAM_BIT;
++            break;
++        case ATA_PORT_LBAH:
++            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_LBAH_BIT)) >> SATA_LBAH_BIT;
++            break;
++        case ATA_PORT_DEVICE:
++            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_HOB_LBAH_BIT)) >> SATA_HOB_LBAH_BIT;
++            val |= (*(sata_regs_base[device] + SATA_ORB1_OFF) & (0xFFUL << SATA_DEVICE_BIT)) >> SATA_DEVICE_BIT;
++            break;
++        case ATA_PORT_COMMAND:
++            val = (*(sata_regs_base[device] + SATA_ORB2_OFF) & (0xFFUL << SATA_COMMAND_BIT)) >> SATA_COMMAND_BIT;
++            val |= ATA_STAT_DRQ ;
++            break;
++        default:
++            printf("ide_inb() Unknown port = %d\n", port);
++            break;
++    }
++
++//    printf("inb: %d:%01x => %02x\n", device, port, val);
++
++    return val;
++}
++
++/**
++ * Possible that ATA status will not become no-error, so must have timeout
++ * @returns An int which is zero on error
++ */
++static inline int wait_no_error(int device)
++{
++    int status = 0;
++
++      /* Check for ATA core error */
++      if (*(sata_regs_base[device] + SATA_INT_STATUS_OFF) & (1 << SATA_INT_STATUS_ERROR_BIT)) {
++              printf("wait_no_error() SATA core flagged error\n");
++      } else {
++              int loops = MAX_NO_ERROR_LOOPS;
++              do {
++                      /* Check for ATA device error */
++                      if (!(ide_inb(device, ATA_PORT_COMMAND) & (1 << ATA_STATUS_ERR_BIT))) {
++                              status = 1;
++                              break;
++                      }
++                      udelay(10);
++              } while (--loops);
++
++              if (!loops) {
++                      printf("wait_no_error() Timed out of wait for SATA no-error condition\n");
++              }
++      }
++
++    return status;
++}
++
++/**
++ * Expect SATA command to always finish, perhaps with error
++ * @returns An int which is zero on error
++ */
++static inline int wait_sata_command_not_busy(int device)
++{
++    /* Wait for data to be available */
++    int status = 0;
++    int loops = MAX_NOT_BUSY_LOOPS;
++    do {
++        if (!(*(sata_regs_base[device] + SATA_COMMAND_OFF) & (1 << SATA_CMD_BUSY_BIT) )) {
++            status = 1;
++            break;
++        }
++        udelay(100);
++    } while (--loops);
++
++    if (!loops) {
++        printf("wait_sata_command_not_busy() Timed out of wait for SATA command to finish\n");
++    }
++
++    return status;
++}
++
++void inline ide_outb(int device, int port, unsigned char val)
++{
++    typedef enum send_method {
++        SEND_NONE,
++        SEND_SIMPLE,
++        SEND_CMD,
++        SEND_CTL,
++    } send_method_t;
++
++    /* Only permit accesses to disks found to be present during ide_preinit() */
++    if (!disk_present[device]) {
++        return;
++    }
++    
++//    printf("outb: %d:%01x <= %02x\n", device, port, val);
++
++    device_select(device);
++
++    send_method_t send_regs = SEND_NONE;
++    switch (port) {
++        case ATA_PORT_CTL:
++            wr_sata_orb4[device] &= ~(0xFFUL << SATA_CTL_BIT);
++            wr_sata_orb4[device] |= (val << SATA_CTL_BIT);
++            send_regs = SEND_CTL;
++            break;
++        case ATA_PORT_FEATURE:
++            wr_sata_orb2[device] &= ~(0xFFUL << SATA_FEATURE_BIT);
++            wr_sata_orb2[device] |= (val << SATA_FEATURE_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_NSECT:
++            wr_sata_orb2[device] &= ~(0xFFUL << SATA_NSECT_BIT);
++            wr_sata_orb2[device] |= (val << SATA_NSECT_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_LBAL:
++            wr_sata_orb3[device] &= ~(0xFFUL << SATA_LBAL_BIT);
++            wr_sata_orb3[device] |= (val << SATA_LBAL_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_LBAM:
++            wr_sata_orb3[device] &= ~(0xFFUL << SATA_LBAM_BIT);
++            wr_sata_orb3[device] |= (val << SATA_LBAM_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_LBAH:
++            wr_sata_orb3[device] &= ~(0xFFUL << SATA_LBAH_BIT);
++            wr_sata_orb3[device] |= (val << SATA_LBAH_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_DEVICE:
++            wr_sata_orb1[device] &= ~(0xFFUL << SATA_DEVICE_BIT);
++            wr_sata_orb1[device] |= ((val & 0xf0) << SATA_DEVICE_BIT);
++            wr_sata_orb3[device] &= ~(0xFFUL << SATA_HOB_LBAH_BIT);
++            wr_sata_orb3[device] |= ((val & 0x0f) << SATA_HOB_LBAH_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_COMMAND:
++            wr_sata_orb2[device] &= ~(0xFFUL << SATA_COMMAND_BIT);
++            wr_sata_orb2[device] |= (val << SATA_COMMAND_BIT);
++            send_regs = SEND_CMD;
++            break;
++        default:
++            printf("ide_outb() Unknown port = %d\n", port);
++    }
++
++    u32 command;
++    switch (send_regs) {
++        case SEND_CMD:
++            wait_sata_command_not_busy(device);
++            command = *(sata_regs_base[device] + SATA_COMMAND_OFF);
++            command &= ~SATA_OPCODE_MASK;
++            command |= SATA_CMD_WRITE_TO_ORB_REGS;
++            xfer_wr_shadow_to_orbs(device);
++            wait_sata_command_not_busy(device);
++            *(sata_regs_base[device] + SATA_COMMAND_OFF) = command;
++            if (!wait_no_error(device)) {
++                printf("hipox_sata_outb() Wait for ATA no-error timed-out\n");
++            }
++            break;
++        case SEND_CTL:
++            wait_sata_command_not_busy(device);
++            command = *(sata_regs_base[device] + SATA_COMMAND_OFF);
++            command &= ~SATA_OPCODE_MASK;
++            command |= SATA_CMD_WRITE_TO_ORB_REGS_NO_COMMAND;
++            xfer_wr_shadow_to_orbs(device);
++            wait_sata_command_not_busy(device);
++            *(sata_regs_base[device] + SATA_COMMAND_OFF) = command;
++            if (!wait_no_error(device)) {
++                printf("hipox_sata_outb() Wait for ATA no-error timed-out\n");
++            }
++            break;
++        default:
++            break;
++    }
++}
++
++static u32 encode_start(u32 ctrl_status)
++{
++    return ctrl_status & ~DMA_CTRL_STATUS_PAUSE;
++}
++
++static void dma_start(void)
++{
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) =
++        encode_start(*(DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)));
++}
++
++static unsigned long encode_control_status(
++    hipox_dma_device_settings_t* src_settings,
++    hipox_dma_device_settings_t* dst_settings)
++{
++    unsigned long ctrl_status;
++    hipox_dma_transfer_direction_t direction;
++
++    ctrl_status  = DMA_CTRL_STATUS_PAUSE;                                       // Paused
++    ctrl_status |= DMA_CTRL_STATUS_FAIR_SHARE_ARB;                              // High priority
++    ctrl_status |= (src_settings->dreq_ << DMA_CTRL_STATUS_SRC_DREQ_SHIFT);     // Dreq
++    ctrl_status |= (dst_settings->dreq_ << DMA_CTRL_STATUS_DEST_DREQ_SHIFT);    // Dreq
++    ctrl_status &= ~DMA_CTRL_STATUS_RESET;                                      // !RESET
++
++    // Use new interrupt clearing register
++    ctrl_status |= DMA_CTRL_STATUS_INTR_CLEAR_ENABLE;
++
++    // Setup the transfer direction and burst/single mode for the two DMA busses
++    if (src_settings->bus_ == HIPOX_DMA_SIDE_A) {
++        // Set the burst/single mode for bus A based on src device's settings
++        if (src_settings->transfer_mode_ == HIPOX_DMA_TRANSFER_MODE_BURST) {
++            ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_A;
++        } else {
++            ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_A;
++        }
++
++        if (dst_settings->bus_ == HIPOX_DMA_SIDE_A) {
++            direction = HIPOX_DMA_A_TO_A;
++        } else {
++            direction = HIPOX_DMA_A_TO_B;
++
++            // Set the burst/single mode for bus B based on dst device's settings
++            if (dst_settings->transfer_mode_ == HIPOX_DMA_TRANSFER_MODE_BURST) {
++                ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_B;
++            } else {
++                ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_B;
++            }
++        }
++    } else {
++        // Set the burst/single mode for bus B based on src device's settings
++        if (src_settings->transfer_mode_ == HIPOX_DMA_TRANSFER_MODE_BURST) {
++            ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_B;
++        } else {
++            ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_B;
++        }
++
++        if (dst_settings->bus_ == HIPOX_DMA_SIDE_A) {
++            direction = HIPOX_DMA_B_TO_A;
++            
++            // Set the burst/single mode for bus A based on dst device's settings
++            if (dst_settings->transfer_mode_ == HIPOX_DMA_TRANSFER_MODE_BURST) {
++                ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_A;
++            } else {
++                ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_A;
++            }
++        } else {
++            direction = HIPOX_DMA_B_TO_B;
++        }
++    }
++    ctrl_status |= (direction << DMA_CTRL_STATUS_DIR_SHIFT);
++
++    // Setup source address mode fixed or increment
++    if (src_settings->address_mode_ == HIPOX_DMA_MODE_FIXED) {
++        // Fixed address
++        ctrl_status &= ~(DMA_CTRL_STATUS_SRC_ADR_MODE);
++        
++        // Set up whether fixed address is _really_ fixed
++        if (src_settings->address_really_fixed_) {
++            ctrl_status |= DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED;
++        } else {
++            ctrl_status &= ~DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED;
++        }        
++    } else {
++        // Incrementing address
++        ctrl_status |= DMA_CTRL_STATUS_SRC_ADR_MODE;
++        ctrl_status &= ~DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED;
++    }
++
++    // Setup destination address mode fixed or increment
++    if (dst_settings->address_mode_ == HIPOX_DMA_MODE_FIXED) {
++        // Fixed address
++        ctrl_status &= ~(DMA_CTRL_STATUS_DEST_ADR_MODE);
++        
++        // Set up whether fixed address is _really_ fixed
++        if (dst_settings->address_really_fixed_) {
++            ctrl_status |= DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED;
++        } else {
++            ctrl_status &= ~DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED;
++        }
++    } else {
++        // Incrementing address
++        ctrl_status |= DMA_CTRL_STATUS_DEST_ADR_MODE;
++        ctrl_status &= ~DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED;
++    }
++
++    // Set up the width of the transfers on the DMA buses
++    ctrl_status |= (src_settings->width_ << DMA_CTRL_STATUS_SRC_WIDTH_SHIFT);
++    ctrl_status |= (dst_settings->width_ << DMA_CTRL_STATUS_DEST_WIDTH_SHIFT);
++
++    // Setup the priority arbitration scheme
++    ctrl_status &= ~DMA_CTRL_STATUS_STARVE_LOW_PRIORITY;    // !Starve low priority
++
++    return ctrl_status;
++}
++
++static u32 encode_final_eot(
++    hipox_dma_device_settings_t* src_settings,
++    hipox_dma_device_settings_t* dst_settings,
++    unsigned long length)
++{
++    // Write the length, with EOT configuration for a final transfer
++    unsigned long encoded = length;
++    if (dst_settings->write_final_eot_) {
++        encoded |= DMA_BYTE_CNT_WR_EOT_MASK;
++    } else {
++        encoded &= ~DMA_BYTE_CNT_WR_EOT_MASK;
++    }
++    if (src_settings->read_final_eot_) {
++        encoded |= DMA_BYTE_CNT_RD_EOT_MASK;
++    } else {
++        encoded &= ~DMA_BYTE_CNT_RD_EOT_MASK;
++    }
++    return encoded;
++}
++
++static void dma_start_write(ulong* buffer, int num_bytes)
++{
++    // Assemble complete memory settings
++    hipox_dma_device_settings_t mem_settings = hipox_ram_dma_settings;
++    mem_settings.address_ = (unsigned long)buffer;
++    mem_settings.address_mode_ = HIPOX_DMA_MODE_INC;
++
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)  = encode_control_status(&mem_settings, &hipox_sata_dma_settings);
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_SRC_ADR) = mem_settings.address_;
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_DST_ADR) = hipox_sata_dma_settings.address_;
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BYTE_CNT)     = encode_final_eot(&mem_settings, &hipox_sata_dma_settings, num_bytes);
++
++    dma_start();
++}
++
++static void dma_start_read(ulong* buffer, int num_bytes)
++{
++    // Assemble complete memory settings
++    hipox_dma_device_settings_t mem_settings = hipox_ram_dma_settings;
++    mem_settings.address_ = (unsigned long)buffer;
++    mem_settings.address_mode_ = HIPOX_DMA_MODE_INC;
++
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)  = encode_control_status(&hipox_sata_dma_settings, &mem_settings);
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_SRC_ADR) = hipox_sata_dma_settings.address_;
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_DST_ADR) = mem_settings.address_;
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BYTE_CNT)     = encode_final_eot(&hipox_sata_dma_settings, &mem_settings, num_bytes);
++
++    dma_start();
++}
++
++static inline int dma_busy(void)
++{
++    return (*DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)) & DMA_CTRL_STATUS_IN_PROGRESS;
++}
++
++static int wait_dma_not_busy(int device)
++{
++    unsigned int cleanup_required = 0;
++
++      /* Poll for DMA completion */
++      int loops = MAX_DMA_XFER_LOOPS;
++      do {
++              if (!dma_busy()) {
++                      break;
++              }
++              udelay(100);
++      } while (--loops);
++
++      if (!loops) {
++              printf("wait_dma_not_busy() Timed out of wait for DMA not busy\n");
++              cleanup_required = 1;
++      }
++
++    if (cleanup_required) {
++        /* Abort DMA to make sure it has finished. */
++        unsigned long ctrl_status = *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS);
++        ctrl_status |= DMA_CTRL_STATUS_RESET;
++        *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) = ctrl_status;
++
++        // Wait for the channel to become idle - should be quick as should
++        // finish after the next AHB single or burst transfer
++        loops = MAX_DMA_ABORT_LOOPS;
++        do {
++            if (!(*DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) & DMA_CTRL_STATUS_IN_PROGRESS)) {
++                break;
++            }
++            udelay(10);
++        } while (--loops);
++
++        if (!loops) {
++            printf("wait_dma_not_busy() Timed out of wait for DMA channel abort\n");
++        } else {
++                      /* Successfully cleanup the DMA channel */
++                      cleanup_required = 0;
++              }
++
++        // Deassert reset for the channel
++        ctrl_status = *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS);
++        ctrl_status &= ~DMA_CTRL_STATUS_RESET;
++        *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) = ctrl_status;
++    }
++
++      return !cleanup_required;
++}
++
++/**
++ * Possible that ATA status will not become not-busy, so must have timeout
++ */
++static unsigned int wait_not_busy(int device, unsigned long timeout_secs)
++{
++    int busy = 1;
++    unsigned long loops = (timeout_secs * 1000) / 50;
++    do {
++        // Test the ATA status register BUSY flag
++        if (!((*(sata_regs_base[device] + SATA_ORB2_OFF) >> SATA_COMMAND_BIT) & (1UL << ATA_STATUS_BSY_BIT))) {
++            /* Not busy, so stop polling */
++            busy = 0;
++            break;
++        }
++
++        // Wait for 50mS before sampling ATA status register again
++        udelay(50000);
++    } while (--loops);
++
++    return busy;
++}
++
++void hipox_sata_output_data(int device, ulong *sect_buf, int words)
++{
++    /* Only permit accesses to disks found to be present during ide_preinit() */
++    if (!disk_present[device]) {
++        return;
++    }
++
++    /* Select the required internal SATA drive */
++    device_select(device);
++
++    /* Start the DMA channel sending data from the passed buffer to the SATA core */
++    dma_start_write(sect_buf, words << 2);
++
++      /* Don't know why we need this delay, but without it the wait for DMA not 
++         busy times soemtimes out, e.g. when saving environment to second disk */
++      udelay(1000);
++
++    /* Wait for DMA to finish */
++    if (!wait_dma_not_busy(device)) {
++              printf("Timed out of wait for DMA channel for SATA device %d to have in-progress clear\n", device);
++      }
++
++      /* Sata core should finish after DMA */
++      if (wait_not_busy(device, 30)) {
++              printf("Timed out of wait for SATA device %d to have BUSY clear\n", device);
++      }
++      if (!wait_no_error(device)) {
++              printf("hipox_sata_output_data() Wait for ATA no-error timed-out\n");
++      }
++}
++
++void hipox_sata_input_data(int device, ulong *sect_buf, int words)
++{
++    /* Only permit accesses to disks found to be present during ide_preinit() */
++    if (!disk_present[device]) {
++        return;
++    }
++
++    /* Select the required internal SATA drive */
++    device_select(device);
++
++    /* Start the DMA channel receiving data from the SATA core into the passed buffer */
++    dma_start_read(sect_buf, words << 2);
++
++      /* Sata core should finish before DMA */
++      if (wait_not_busy(device, 30)) {
++              printf("Timed out of wait for SATA device %d to have BUSY clear\n", device);
++      }
++      if (!wait_no_error(device)) {
++              printf("hipox_sata_output_data() Wait for ATA no-error timed-out\n");
++      }
++
++    /* Wait for DMA to finish */
++    if (!wait_dma_not_busy(device)) {
++              printf("Timed out of wait for DMA channel for SATA device %d to have in-progress clear\n", device);
++      }
++}
++
++static u32 scr_read(int device, unsigned int sc_reg)
++{
++    /* Setup adr of required register. std regs start eight into async region */    
++    *(sata_regs_base[device] + SATA_LINK_RD_ADDR) = sc_reg*4 + SATA_STD_ASYNC_REGS_OFF;
++
++    /* Wait for data to be available */
++    int loops = MAX_SRC_READ_LOOPS;
++    do {
++        if (*(sata_regs_base[device] + SATA_LINK_CONTROL) & 1UL) {
++            break;
++        }
++        udelay(10);
++    } while (--loops);
++
++    if (!loops) {
++        printf("scr_read() Timed out of wait for read completion\n");
++    }
++
++    /* Read the data from the async register */
++    return *(sata_regs_base[device] + SATA_LINK_DATA);
++}
++
++static void scr_write(int device, unsigned int sc_reg, u32 val)
++{
++    /* Setup the data for the write */
++    *(sata_regs_base[device] + SATA_LINK_DATA) = val;
++
++    /* Setup adr of required register. std regs start eight into async region */    
++    *(sata_regs_base[device] + SATA_LINK_WR_ADDR) = sc_reg*4 + SATA_STD_ASYNC_REGS_OFF;
++
++    /* Wait for data to be written */
++    int loops = MAX_SRC_WRITE_LOOPS;
++    do {
++        if (*(sata_regs_base[device] + SATA_LINK_CONTROL) & 1UL) {
++            break;
++        }
++        udelay(10);
++    } while (--loops);
++
++    if (!loops) {
++        printf("scr_write() Timed out of wait for write completion\n");
++    }
++}
++
++#define PHY_LOOP_COUNT  25  /* Wait for upto 5 seconds for PHY to be found */
++static int phy_reset(int device)
++{
++#ifdef FPGA
++    /* The FPGA thinks it can do 3G when infact only 1.5G is possible, so limit
++    it to Gen-1 SATA (1.5G) */ 
++    scr_write(device, SATA_SCR_CONTROL, 0x311);  /* Issue phy wake & core reset */
++    scr_read(device, SATA_SCR_STATUS);           /* Dummy read; flush */
++    udelay(1000);
++    scr_write(device, SATA_SCR_CONTROL, 0x310);  /* Issue phy wake & clear core reset */
++#else
++    scr_write(device, SATA_SCR_CONTROL, 0x301);  /* Issue phy wake & core reset */
++    scr_read(device, SATA_SCR_STATUS);           /* Dummy read; flush */
++    udelay(1000);
++    scr_write(device, SATA_SCR_CONTROL, 0x300);  /* Issue phy wake & clear core reset */
++#endif
++    /* Wait for upto 5 seconds for PHY to become ready */
++    int phy_status = 0;
++    int loops = 0;
++    do {
++        udelay(200000);
++        if ((scr_read(device, SATA_SCR_STATUS) & 0xf) != 1) {
++            phy_status = 1;
++            break;
++        }
++        printf("No SATA PHY found\n");
++    } while (++loops < PHY_LOOP_COUNT);
++
++    if (phy_status) {
++        udelay(500000); /* wait half a second */
++    }
++    return phy_status;
++}
++
++#define FIS_LOOP_COUNT  25  /* Wait for upto 5 seconds for FIS to be received */
++static int wait_FIS(int device)
++{
++    int status = 0;
++    int loops = 0;
++
++    do {
++        udelay(200000);
++        if    (ide_inb(device, ATA_PORT_NSECT) > 0) {
++            status = 1;
++            break;
++        }
++    } while (++loops < FIS_LOOP_COUNT);
++
++    return status;
++}
++
++int ide_preinit(void)
++{
++    int num_disks_found = 0;
++
++    /* Initialise records of which disks are present to all present */
++    int i;
++    for (i=0; i < CONFIG_SYS_IDE_MAXDEVICE; i++) {
++        disk_present[i] = 1;
++    }
++
++//udelay(1000000);
++    /* Enable clocks to SATA and DMA cores */
++    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_SATA_BIT);
++    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_DMA_BIT);
++    
++    /* Block reset SATA and DMA cores */
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_SATA_BIT) |
++                                              (1UL << SYS_CTRL_RSTEN_SATA_LINK_BIT) |
++                                              (1UL << SYS_CTRL_RSTEN_SATA_PHY_BIT) |
++                                              (1UL << SYS_CTRL_RSTEN_DMA_BIT);
++    udelay(50);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_SATA_PHY_BIT);
++    udelay(50);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_SATA_LINK_BIT) |
++                                              (1UL << SYS_CTRL_RSTEN_SATA_BIT);
++    udelay(50);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_DMA_BIT);
++    udelay(50);
++//udelay(1000000);
++
++    /* disable and clear core interrupts */
++    *((unsigned long*)SATA_HOST_REGS_BASE + SATA_INT_ENABLE_CLR_OFF) = ~0UL;
++    *((unsigned long*)SATA_HOST_REGS_BASE + SATA_INT_CLR_OFF) = ~0UL;
++
++    int device;
++    for (device = 0; device < CONFIG_SYS_IDE_MAXDEVICE; device++) {
++        int found = 0;
++        int retries = 1;
++
++        /* Disable SATA interrupts */
++        *(sata_regs_base[device] + SATA_INT_ENABLE_CLR_OFF) = ~0UL;
++
++        /* Clear any pending SATA interrupts */
++        *(sata_regs_base[device] + SATA_INT_CLR_OFF) = ~0UL;
++
++        do {
++            /* clear sector count register for FIS detection */
++            ide_outb(device, ATA_PORT_NSECT, 0);
++    
++            /* Get the PHY working */
++            if (!phy_reset(device)) {
++                printf("SATA PHY not ready for device %d\n", device);
++                break;
++            }
++
++            if (!wait_FIS(device)) {
++                printf("No FIS received from device %d\n", device);
++            } else {
++                if ((scr_read(device, SATA_SCR_STATUS) & 0xf) == 0x3) {
++                    if (wait_not_busy(device, 30)) {
++                        printf("Timed out of wait for SATA device %d to have BUSY clear\n", device);
++                    } else {
++                        ++num_disks_found;
++                        found = 1;
++                    }
++                } else {
++                    printf("No SATA device %d found, PHY status = 0x%08x\n",
++                            device, scr_read(device, SATA_SCR_STATUS));
++                }
++                break;
++            }
++        } while (retries--) ;
++
++        /* Record whether disk is present, so won't attempt to access it later */
++        disk_present[device] = found;
++    }
++
++    /* post disk detection clean-up */
++    for (device = 0; device < CONFIG_SYS_IDE_MAXDEVICE; device++) {
++        if ( disk_present[device] ) {
++            /* set as ata-5 (28-bit) */
++            *(sata_regs_base[device] + SATA_DRIVE_CONTROL_OFF) = 0UL;
++            
++            /* clear phy/link errors */
++            scr_write(device, SATA_SCR_ERROR, ~0);
++            
++            /* clear host errors */
++            *(sata_regs_base[device] + SATA_CONTROL_OFF) |= SATA_SCTL_CLR_ERR;
++            
++            /* clear interrupt register as this clears the error bit in the IDE 
++            status register */
++            *(sata_regs_base[device] + SATA_INT_CLR_OFF) = ~0UL;
++        }
++    }    
++    
++
++    return !num_disks_found;
++}
++
+diff -Nurd u-boot-2009.03.orig/board/hipox/ide-820.c u-boot-2009.03/board/hipox/ide-820.c
+--- u-boot-2009.03.orig/board/hipox/ide-820.c  1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/ide-820.c       2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,892 @@
++/*
++ * (C) Copyright 2005
++ * Oxford Semiconductor Ltd
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,`
++ * MA 02111-1307 USA
++ */
++#include <common.h>
++
++#define SATA_DMA_CHANNEL 0
++
++#define DMA_CTRL_STATUS      (0x0)
++#define DMA_BASE_SRC_ADR     (0x4)
++#define DMA_BASE_DST_ADR     (0x8)
++#define DMA_BYTE_CNT         (0xC)
++#define DMA_CURRENT_SRC_ADR  (0x10)
++#define DMA_CURRENT_DST_ADR  (0x14)
++#define DMA_CURRENT_BYTE_CNT (0x18)
++#define DMA_INTR_ID          (0x1C)
++#define DMA_INTR_CLEAR_REG   (DMA_CURRENT_SRC_ADR)
++
++#define DMA_CALC_REG_ADR(channel, register) ((volatile u32*)(DMA_BASE_PA + ((channel) << 5) + (register)))
++
++#define DMA_CTRL_STATUS_FAIR_SHARE_ARB            (1 << 0)
++#define DMA_CTRL_STATUS_IN_PROGRESS               (1 << 1)
++#define DMA_CTRL_STATUS_SRC_DREQ_MASK             (0x0000003C)
++#define DMA_CTRL_STATUS_SRC_DREQ_SHIFT            (2)
++#define DMA_CTRL_STATUS_DEST_DREQ_MASK            (0x000003C0)
++#define DMA_CTRL_STATUS_DEST_DREQ_SHIFT           (6)
++#define DMA_CTRL_STATUS_INTR                      (1 << 10)
++#define DMA_CTRL_STATUS_NXT_FREE                  (1 << 11)
++#define DMA_CTRL_STATUS_RESET                     (1 << 12)
++#define DMA_CTRL_STATUS_DIR_MASK                  (0x00006000)
++#define DMA_CTRL_STATUS_DIR_SHIFT                 (13)
++#define DMA_CTRL_STATUS_SRC_ADR_MODE              (1 << 15)
++#define DMA_CTRL_STATUS_DEST_ADR_MODE             (1 << 16)
++#define DMA_CTRL_STATUS_TRANSFER_MODE_A           (1 << 17)
++#define DMA_CTRL_STATUS_TRANSFER_MODE_B           (1 << 18)
++#define DMA_CTRL_STATUS_SRC_WIDTH_MASK            (0x00380000)
++#define DMA_CTRL_STATUS_SRC_WIDTH_SHIFT           (19)
++#define DMA_CTRL_STATUS_DEST_WIDTH_MASK           (0x01C00000)
++#define DMA_CTRL_STATUS_DEST_WIDTH_SHIFT          (22)
++#define DMA_CTRL_STATUS_PAUSE                     (1 << 25)
++#define DMA_CTRL_STATUS_INTERRUPT_ENABLE          (1 << 26)
++#define DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED      (1 << 27)
++#define DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED (1 << 28)
++#define DMA_CTRL_STATUS_STARVE_LOW_PRIORITY       (1 << 29)
++#define DMA_CTRL_STATUS_INTR_CLEAR_ENABLE         (1 << 30)
++
++#define DMA_BYTE_CNT_MASK        ((1 << 21) - 1)
++#define DMA_BYTE_CNT_WR_EOT_MASK (1 << 30)
++#define DMA_BYTE_CNT_RD_EOT_MASK (1 << 31)
++
++#define MAKE_FIELD(value, num_bits, bit_num) (((value) & ((1 << (num_bits)) - 1)) << (bit_num))
++
++typedef enum hipox_dma_mode {
++    HIPOX_DMA_MODE_FIXED,
++    HIPOX_DMA_MODE_INC
++} hipox_dma_mode_t;
++
++typedef enum hipox_dma_direction {
++    HIPOX_DMA_TO_DEVICE,
++    HIPOX_DMA_FROM_DEVICE
++} hipox_dma_direction_t;
++
++/* The available buses to which the DMA controller is attached */
++typedef enum hipox_dma_transfer_bus
++{
++    HIPOX_DMA_SIDE_A,
++    HIPOX_DMA_SIDE_B
++} hipox_dma_transfer_bus_t;
++
++/* Direction of data flow between the DMA controller's pair of interfaces */
++typedef enum hipox_dma_transfer_direction
++{
++    HIPOX_DMA_A_TO_A,
++    HIPOX_DMA_B_TO_A,
++    HIPOX_DMA_A_TO_B,
++    HIPOX_DMA_B_TO_B
++} hipox_dma_transfer_direction_t;
++
++/* The available data widths */
++typedef enum hipox_dma_transfer_width
++{
++    HIPOX_DMA_TRANSFER_WIDTH_8BITS,
++    HIPOX_DMA_TRANSFER_WIDTH_16BITS,
++    HIPOX_DMA_TRANSFER_WIDTH_32BITS
++} hipox_dma_transfer_width_t;
++
++/* The mode of the DMA transfer */
++typedef enum hipox_dma_transfer_mode
++{
++    HIPOX_DMA_TRANSFER_MODE_SINGLE,
++    HIPOX_DMA_TRANSFER_MODE_BURST
++} hipox_dma_transfer_mode_t;
++
++/* The available transfer targets */
++typedef enum hipox_dma_dreq
++{
++    HIPOX_DMA_DREQ_SATA   = 0,
++    HIPOX_DMA_DREQ_MEMORY = 15
++} hipox_dma_dreq_t;
++
++typedef struct hipox_dma_device_settings {
++    unsigned long address_;
++    unsigned      fifo_size_;   // Chained transfers must take account of FIFO offset at end of previous transfer
++    unsigned char dreq_;
++    unsigned      read_eot_:1;
++    unsigned      read_final_eot_:1;
++    unsigned      write_eot_:1;
++    unsigned      write_final_eot_:1;
++    unsigned      bus_:1;
++    unsigned      width_:2;
++    unsigned      transfer_mode_:1;
++    unsigned      address_mode_:1;
++    unsigned      address_really_fixed_:1;
++} hipox_dma_device_settings_t;
++
++static const int MAX_NO_ERROR_LOOPS  = 100000;  /* 1 second in units of 10uS */
++static const int MAX_DMA_XFER_LOOPS  = 300000;  /* 30 seconds in units of 100uS */
++static const int MAX_DMA_ABORT_LOOPS = 10000;   /* 0.1 second in units of 10uS */
++static const int MAX_SRC_READ_LOOPS  = 10000;   /* 0.1 second in units of 10uS */
++static const int MAX_SRC_WRITE_LOOPS = 10000;   /* 0.1 second in units of 10uS */
++static const int MAX_NOT_BUSY_LOOPS  = 10000;   /* 1 second in units of 100uS */
++
++/* The internal SATA drive on which we should attempt to find partitions */
++static volatile u32* sata_regs_base[2] = 
++{
++    (volatile u32*)SATA_0_REGS_BASE,
++    (volatile u32*)SATA_1_REGS_BASE,
++    
++};
++static u32 wr_sata_orb1[2] = { 0, 0 };
++static u32 wr_sata_orb2[2] = { 0, 0 };
++static u32 wr_sata_orb3[2] = { 0, 0 };
++static u32 wr_sata_orb4[2] = { 0, 0 };
++
++static hipox_dma_device_settings_t hipox_sata_dma_settings = {
++    .address_              = SATA_DATA_BASE_PA,
++    .fifo_size_            = 16,
++    .dreq_                 = HIPOX_DMA_DREQ_SATA,
++    .read_eot_             = 0,
++    .read_final_eot_       = 1,
++    .write_eot_            = 0,
++    .write_final_eot_      = 1,
++    .bus_                  = HIPOX_DMA_SIDE_A,
++    .width_                = HIPOX_DMA_TRANSFER_WIDTH_32BITS,
++    .transfer_mode_        = HIPOX_DMA_TRANSFER_MODE_BURST,
++    .address_mode_         = HIPOX_DMA_MODE_FIXED,
++    .address_really_fixed_ = 0
++};
++
++hipox_dma_device_settings_t hipox_ram_dma_settings = {
++    .address_              = 0,
++    .fifo_size_            = 0,
++    .dreq_                 = HIPOX_DMA_DREQ_MEMORY,
++    .read_eot_             = 1,
++    .read_final_eot_       = 1,
++    .write_eot_            = 1,
++    .write_final_eot_      = 1,
++    .bus_                  = HIPOX_DMA_SIDE_B,
++    .width_                = HIPOX_DMA_TRANSFER_WIDTH_32BITS,
++    .transfer_mode_        = HIPOX_DMA_TRANSFER_MODE_BURST,
++    .address_mode_         = HIPOX_DMA_MODE_FIXED,
++    .address_really_fixed_ = 1
++};
++
++static void xfer_wr_shadow_to_orbs(int device)
++{
++    *(sata_regs_base[device] + SATA_ORB1_OFF) = wr_sata_orb1[device];
++    *(sata_regs_base[device] + SATA_ORB2_OFF) = wr_sata_orb2[device];
++    *(sata_regs_base[device] + SATA_ORB3_OFF) = wr_sata_orb3[device];
++    *(sata_regs_base[device] + SATA_ORB4_OFF) = wr_sata_orb4[device];
++}
++
++static inline void device_select(int device)
++{
++    /* master/slave has no meaning to SATA core */
++}
++
++static int disk_present[CONFIG_SYS_IDE_MAXDEVICE];
++
++#include <ata.h>
++
++unsigned char hipox_sata_inb(int device, int port)
++{
++    unsigned char val = 0;
++
++    /* Only permit accesses to disks found to be present during ide_preinit() */
++    if (!disk_present[device]) {
++        return ATA_STAT_FAULT;
++    }
++
++    device_select(device);
++
++    switch (port) {
++        case ATA_PORT_CTL:
++            val = (*(sata_regs_base[device] + SATA_ORB4_OFF) & (0xFFUL << SATA_CTL_BIT)) >> SATA_CTL_BIT;
++            break;
++        case ATA_PORT_FEATURE:
++            val = (*(sata_regs_base[device] + SATA_ORB2_OFF) & (0xFFUL << SATA_FEATURE_BIT)) >> SATA_FEATURE_BIT;
++            break;
++        case ATA_PORT_NSECT:
++            val = (*(sata_regs_base[device] + SATA_ORB2_OFF) & (0xFFUL << SATA_NSECT_BIT)) >> SATA_NSECT_BIT;
++            break;
++        case ATA_PORT_LBAL:
++            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_LBAL_BIT)) >> SATA_LBAL_BIT;
++            break;
++        case ATA_PORT_LBAM:
++            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_LBAM_BIT)) >> SATA_LBAM_BIT;
++            break;
++        case ATA_PORT_LBAH:
++            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_LBAH_BIT)) >> SATA_LBAH_BIT;
++            break;
++        case ATA_PORT_DEVICE:
++            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_HOB_LBAH_BIT)) >> SATA_HOB_LBAH_BIT;
++            val |= (*(sata_regs_base[device] + SATA_ORB1_OFF) & (0xFFUL << SATA_DEVICE_BIT)) >> SATA_DEVICE_BIT;
++            break;
++        case ATA_PORT_COMMAND:
++            val = (*(sata_regs_base[device] + SATA_ORB2_OFF) & (0xFFUL << SATA_COMMAND_BIT)) >> SATA_COMMAND_BIT;
++            val |= ATA_STAT_DRQ ;
++            break;
++        default:
++            printf("ide_inb() Unknown port = %d\n", port);
++            break;
++    }
++
++//    printf("inb: %d:%01x => %02x\n", device, port, val);
++
++    return val;
++}
++
++/**
++ * Possible that ATA status will not become no-error, so must have timeout
++ * @returns An int which is zero on error
++ */
++static inline int wait_no_error(int device)
++{
++    int status = 0;
++
++      /* Check for ATA core error */
++      if (*(sata_regs_base[device] + SATA_INT_STATUS_OFF) & (1 << SATA_INT_STATUS_ERROR_BIT)) {
++              printf("wait_no_error() SATA core flagged error\n");
++      } else {
++              int loops = MAX_NO_ERROR_LOOPS;
++              do {
++                      /* Check for ATA device error */
++                      if (!(hipox_sata_inb(device, ATA_PORT_COMMAND) & (1 << ATA_STATUS_ERR_BIT))) {
++                              status = 1;
++                              break;
++                      }
++                      udelay(10);
++              } while (--loops);
++
++              if (!loops) {
++                      printf("wait_no_error() Timed out of wait for SATA no-error condition\n");
++              }
++      }
++
++    return status;
++}
++
++/**
++ * Expect SATA command to always finish, perhaps with error
++ * @returns An int which is zero on error
++ */
++static inline int wait_sata_command_not_busy(int device)
++{
++    /* Wait for data to be available */
++    int status = 0;
++    int loops = MAX_NOT_BUSY_LOOPS;
++    do {
++        if (!(*(sata_regs_base[device] + SATA_COMMAND_OFF) & (1 << SATA_CMD_BUSY_BIT) )) {
++            status = 1;
++            break;
++        }
++        udelay(100);
++    } while (--loops);
++
++    if (!loops) {
++        printf("wait_sata_command_not_busy() Timed out of wait for SATA command to finish\n");
++    }
++
++    return status;
++}
++
++void hipox_sata_outb(int device, int port, unsigned char val)
++{
++    typedef enum send_method {
++        SEND_NONE,
++        SEND_SIMPLE,
++        SEND_CMD,
++        SEND_CTL,
++    } send_method_t;
++
++    /* Only permit accesses to disks found to be present during ide_preinit() */
++    if (!disk_present[device]) {
++        return;
++    }
++    
++//    printf("outb: %d:%01x <= %02x\n", device, port, val);
++
++    device_select(device);
++
++    send_method_t send_regs = SEND_NONE;
++    switch (port) {
++        case ATA_PORT_CTL:
++            wr_sata_orb4[device] &= ~(0xFFUL << SATA_CTL_BIT);
++            wr_sata_orb4[device] |= (val << SATA_CTL_BIT);
++            send_regs = SEND_CTL;
++            break;
++        case ATA_PORT_FEATURE:
++            wr_sata_orb2[device] &= ~(0xFFUL << SATA_FEATURE_BIT);
++            wr_sata_orb2[device] |= (val << SATA_FEATURE_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_NSECT:
++            wr_sata_orb2[device] &= ~(0xFFUL << SATA_NSECT_BIT);
++            wr_sata_orb2[device] |= (val << SATA_NSECT_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_LBAL:
++            wr_sata_orb3[device] &= ~(0xFFUL << SATA_LBAL_BIT);
++            wr_sata_orb3[device] |= (val << SATA_LBAL_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_LBAM:
++            wr_sata_orb3[device] &= ~(0xFFUL << SATA_LBAM_BIT);
++            wr_sata_orb3[device] |= (val << SATA_LBAM_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_LBAH:
++            wr_sata_orb3[device] &= ~(0xFFUL << SATA_LBAH_BIT);
++            wr_sata_orb3[device] |= (val << SATA_LBAH_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_DEVICE:
++            wr_sata_orb1[device] &= ~(0xFFUL << SATA_DEVICE_BIT);
++            wr_sata_orb1[device] |= ((val & 0xf0) << SATA_DEVICE_BIT);
++            wr_sata_orb3[device] &= ~(0xFFUL << SATA_HOB_LBAH_BIT);
++            wr_sata_orb3[device] |= ((val & 0x0f) << SATA_HOB_LBAH_BIT);
++            send_regs = SEND_SIMPLE;
++            break;
++        case ATA_PORT_COMMAND:
++            wr_sata_orb2[device] &= ~(0xFFUL << SATA_COMMAND_BIT);
++            wr_sata_orb2[device] |= (val << SATA_COMMAND_BIT);
++            send_regs = SEND_CMD;
++            break;
++        default:
++            printf("ide_outb() Unknown port = %d\n", port);
++    }
++
++    u32 command;
++    switch (send_regs) {
++        case SEND_CMD:
++            wait_sata_command_not_busy(device);
++            command = *(sata_regs_base[device] + SATA_COMMAND_OFF);
++            command &= ~SATA_OPCODE_MASK;
++            command |= SATA_CMD_WRITE_TO_ORB_REGS;
++            xfer_wr_shadow_to_orbs(device);
++            wait_sata_command_not_busy(device);
++            *(sata_regs_base[device] + SATA_COMMAND_OFF) = command;
++            if (!wait_no_error(device)) {
++                printf("hipox_sata_outb() Wait for ATA no-error timed-out\n");
++            }
++            break;
++        case SEND_CTL:
++            wait_sata_command_not_busy(device);
++            command = *(sata_regs_base[device] + SATA_COMMAND_OFF);
++            command &= ~SATA_OPCODE_MASK;
++            command |= SATA_CMD_WRITE_TO_ORB_REGS_NO_COMMAND;
++            xfer_wr_shadow_to_orbs(device);
++            wait_sata_command_not_busy(device);
++            *(sata_regs_base[device] + SATA_COMMAND_OFF) = command;
++            if (!wait_no_error(device)) {
++                printf("hipox_sata_outb() Wait for ATA no-error timed-out\n");
++            }
++            break;
++        default:
++            break;
++    }
++}
++
++static u32 encode_start(u32 ctrl_status)
++{
++    return ctrl_status & ~DMA_CTRL_STATUS_PAUSE;
++}
++
++static void dma_start(void)
++{
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) =
++        encode_start(*(DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)));
++}
++
++static unsigned long encode_control_status(
++    hipox_dma_device_settings_t* src_settings,
++    hipox_dma_device_settings_t* dst_settings)
++{
++    unsigned long ctrl_status;
++    hipox_dma_transfer_direction_t direction;
++
++    ctrl_status  = DMA_CTRL_STATUS_PAUSE;                                       // Paused
++    ctrl_status |= DMA_CTRL_STATUS_FAIR_SHARE_ARB;                              // High priority
++    ctrl_status |= (src_settings->dreq_ << DMA_CTRL_STATUS_SRC_DREQ_SHIFT);     // Dreq
++    ctrl_status |= (dst_settings->dreq_ << DMA_CTRL_STATUS_DEST_DREQ_SHIFT);    // Dreq
++    ctrl_status &= ~DMA_CTRL_STATUS_RESET;                                      // !RESET
++
++    // Use new interrupt clearing register
++    ctrl_status |= DMA_CTRL_STATUS_INTR_CLEAR_ENABLE;
++
++    // Setup the transfer direction and burst/single mode for the two DMA busses
++    if (src_settings->bus_ == HIPOX_DMA_SIDE_A) {
++        // Set the burst/single mode for bus A based on src device's settings
++        if (src_settings->transfer_mode_ == HIPOX_DMA_TRANSFER_MODE_BURST) {
++            ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_A;
++        } else {
++            ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_A;
++        }
++
++        if (dst_settings->bus_ == HIPOX_DMA_SIDE_A) {
++            direction = HIPOX_DMA_A_TO_A;
++        } else {
++            direction = HIPOX_DMA_A_TO_B;
++
++            // Set the burst/single mode for bus B based on dst device's settings
++            if (dst_settings->transfer_mode_ == HIPOX_DMA_TRANSFER_MODE_BURST) {
++                ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_B;
++            } else {
++                ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_B;
++            }
++        }
++    } else {
++        // Set the burst/single mode for bus B based on src device's settings
++        if (src_settings->transfer_mode_ == HIPOX_DMA_TRANSFER_MODE_BURST) {
++            ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_B;
++        } else {
++            ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_B;
++        }
++
++        if (dst_settings->bus_ == HIPOX_DMA_SIDE_A) {
++            direction = HIPOX_DMA_B_TO_A;
++            
++            // Set the burst/single mode for bus A based on dst device's settings
++            if (dst_settings->transfer_mode_ == HIPOX_DMA_TRANSFER_MODE_BURST) {
++                ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_A;
++            } else {
++                ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_A;
++            }
++        } else {
++            direction = HIPOX_DMA_B_TO_B;
++        }
++    }
++    ctrl_status |= (direction << DMA_CTRL_STATUS_DIR_SHIFT);
++
++    // Setup source address mode fixed or increment
++    if (src_settings->address_mode_ == HIPOX_DMA_MODE_FIXED) {
++        // Fixed address
++        ctrl_status &= ~(DMA_CTRL_STATUS_SRC_ADR_MODE);
++        
++        // Set up whether fixed address is _really_ fixed
++        if (src_settings->address_really_fixed_) {
++            ctrl_status |= DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED;
++        } else {
++            ctrl_status &= ~DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED;
++        }        
++    } else {
++        // Incrementing address
++        ctrl_status |= DMA_CTRL_STATUS_SRC_ADR_MODE;
++        ctrl_status &= ~DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED;
++    }
++
++    // Setup destination address mode fixed or increment
++    if (dst_settings->address_mode_ == HIPOX_DMA_MODE_FIXED) {
++        // Fixed address
++        ctrl_status &= ~(DMA_CTRL_STATUS_DEST_ADR_MODE);
++        
++        // Set up whether fixed address is _really_ fixed
++        if (dst_settings->address_really_fixed_) {
++            ctrl_status |= DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED;
++        } else {
++            ctrl_status &= ~DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED;
++        }
++    } else {
++        // Incrementing address
++        ctrl_status |= DMA_CTRL_STATUS_DEST_ADR_MODE;
++        ctrl_status &= ~DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED;
++    }
++
++    // Set up the width of the transfers on the DMA buses
++    ctrl_status |= (src_settings->width_ << DMA_CTRL_STATUS_SRC_WIDTH_SHIFT);
++    ctrl_status |= (dst_settings->width_ << DMA_CTRL_STATUS_DEST_WIDTH_SHIFT);
++
++    // Setup the priority arbitration scheme
++    ctrl_status &= ~DMA_CTRL_STATUS_STARVE_LOW_PRIORITY;    // !Starve low priority
++
++    return ctrl_status;
++}
++
++static u32 encode_final_eot(
++    hipox_dma_device_settings_t* src_settings,
++    hipox_dma_device_settings_t* dst_settings,
++    unsigned long length)
++{
++    // Write the length, with EOT configuration for a final transfer
++    unsigned long encoded = length;
++    if (dst_settings->write_final_eot_) {
++        encoded |= DMA_BYTE_CNT_WR_EOT_MASK;
++    } else {
++        encoded &= ~DMA_BYTE_CNT_WR_EOT_MASK;
++    }
++    if (src_settings->read_final_eot_) {
++        encoded |= DMA_BYTE_CNT_RD_EOT_MASK;
++    } else {
++        encoded &= ~DMA_BYTE_CNT_RD_EOT_MASK;
++    }
++    return encoded;
++}
++
++static void dma_start_write(ulong* buffer, int num_bytes)
++{
++    // Assemble complete memory settings
++    hipox_dma_device_settings_t mem_settings = hipox_ram_dma_settings;
++    mem_settings.address_ = (unsigned long)buffer;
++    mem_settings.address_mode_ = HIPOX_DMA_MODE_INC;
++
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)  = encode_control_status(&mem_settings, &hipox_sata_dma_settings);
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_SRC_ADR) = mem_settings.address_;
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_DST_ADR) = hipox_sata_dma_settings.address_;
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BYTE_CNT)     = encode_final_eot(&mem_settings, &hipox_sata_dma_settings, num_bytes);
++
++    dma_start();
++}
++
++static void dma_start_read(ulong* buffer, int num_bytes)
++{
++    // Assemble complete memory settings
++    hipox_dma_device_settings_t mem_settings = hipox_ram_dma_settings;
++    mem_settings.address_ = (unsigned long)buffer;
++    mem_settings.address_mode_ = HIPOX_DMA_MODE_INC;
++
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)  = encode_control_status(&hipox_sata_dma_settings, &mem_settings);
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_SRC_ADR) = hipox_sata_dma_settings.address_;
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_DST_ADR) = mem_settings.address_;
++    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BYTE_CNT)     = encode_final_eot(&hipox_sata_dma_settings, &mem_settings, num_bytes);
++
++    dma_start();
++}
++
++static inline int dma_busy(void)
++{
++    return (*DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)) & DMA_CTRL_STATUS_IN_PROGRESS;
++}
++
++static int wait_dma_not_busy(int device)
++{
++    unsigned int cleanup_required = 0;
++
++      /* Poll for DMA completion */
++      int loops = MAX_DMA_XFER_LOOPS;
++      do {
++              if (!dma_busy()) {
++                      break;
++              }
++              udelay(100);
++      } while (--loops);
++
++      if (!loops) {
++              printf("wait_dma_not_busy() Timed out of wait for DMA not busy\n");
++              cleanup_required = 1;
++      }
++
++    if (cleanup_required) {
++        /* Abort DMA to make sure it has finished. */
++        unsigned long ctrl_status = *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS);
++        ctrl_status |= DMA_CTRL_STATUS_RESET;
++        *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) = ctrl_status;
++
++        // Wait for the channel to become idle - should be quick as should
++        // finish after the next AHB single or burst transfer
++        loops = MAX_DMA_ABORT_LOOPS;
++        do {
++            if (!(*DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) & DMA_CTRL_STATUS_IN_PROGRESS)) {
++                break;
++            }
++            udelay(10);
++        } while (--loops);
++
++        if (!loops) {
++            printf("wait_dma_not_busy() Timed out of wait for DMA channel abort\n");
++        } else {
++                      /* Successfully cleanup the DMA channel */
++                      cleanup_required = 0;
++              }
++
++        // Deassert reset for the channel
++        ctrl_status = *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS);
++        ctrl_status &= ~DMA_CTRL_STATUS_RESET;
++        *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) = ctrl_status;
++    }
++
++      return !cleanup_required;
++}
++
++/**
++ * Possible that ATA status will not become not-busy, so must have timeout
++ */
++static unsigned int wait_not_busy(int device, unsigned long timeout_secs)
++{
++    int busy = 1;
++    unsigned long loops = (timeout_secs * 1000) / 50;
++    do {
++        // Test the ATA status register BUSY flag
++        if (!((*(sata_regs_base[device] + SATA_ORB2_OFF) >> SATA_COMMAND_BIT) & (1UL << ATA_STATUS_BSY_BIT))) {
++            /* Not busy, so stop polling */
++            busy = 0;
++            break;
++        }
++
++        // Wait for 50mS before sampling ATA status register again
++        udelay(50000);
++    } while (--loops);
++
++    return busy;
++}
++
++void hipox_sata_output_data(int device, ulong *sect_buf, int words)
++{
++    /* Only permit accesses to disks found to be present during ide_preinit() */
++    if (!disk_present[device]) {
++        return;
++    }
++
++    /* Select the required internal SATA drive */
++    device_select(device);
++
++    /* Start the DMA channel sending data from the passed buffer to the SATA core */
++    dma_start_write(sect_buf, words << 2);
++
++      /* Don't know why we need this delay, but without it the wait for DMA not 
++         busy times soemtimes out, e.g. when saving environment to second disk */
++      udelay(1000);
++
++    /* Wait for DMA to finish */
++    if (!wait_dma_not_busy(device)) {
++              printf("Timed out of wait for DMA channel for SATA device %d to have in-progress clear\n", device);
++      }
++
++      /* Sata core should finish after DMA */
++      if (wait_not_busy(device, 30)) {
++              printf("Timed out of wait for SATA device %d to have BUSY clear\n", device);
++      }
++      if (!wait_no_error(device)) {
++              printf("hipox_sata_output_data() Wait for ATA no-error timed-out\n");
++      }
++}
++
++void hipox_sata_input_data(int device, ulong *sect_buf, int words)
++{
++    /* Only permit accesses to disks found to be present during ide_preinit() */
++    if (!disk_present[device]) {
++        return;
++    }
++
++    /* Select the required internal SATA drive */
++    device_select(device);
++
++    /* Start the DMA channel receiving data from the SATA core into the passed buffer */
++    dma_start_read(sect_buf, words << 2);
++
++      /* Sata core should finish before DMA */
++      if (wait_not_busy(device, 30)) {
++              printf("Timed out of wait for SATA device %d to have BUSY clear\n", device);
++      }
++      if (!wait_no_error(device)) {
++              printf("hipox_sata_output_data() Wait for ATA no-error timed-out\n");
++      }
++
++    /* Wait for DMA to finish */
++    if (!wait_dma_not_busy(device)) {
++              printf("Timed out of wait for DMA channel for SATA device %d to have in-progress clear\n", device);
++      }
++}
++
++static u32 scr_read(int device, unsigned int sc_reg)
++{
++    /* Setup adr of required register. std regs start eight into async region */    
++    *(sata_regs_base[device] + SATA_LINK_RD_ADDR) = sc_reg*4 + SATA_STD_ASYNC_REGS_OFF;
++
++    /* Wait for data to be available */
++    int loops = MAX_SRC_READ_LOOPS;
++    do {
++        if (*(sata_regs_base[device] + SATA_LINK_CONTROL) & 1UL) {
++            break;
++        }
++        udelay(10);
++    } while (--loops);
++
++    if (!loops) {
++        printf("scr_read() Timed out of wait for read completion\n");
++    }
++
++    /* Read the data from the async register */
++    return *(sata_regs_base[device] + SATA_LINK_DATA);
++}
++
++static void scr_write(int device, unsigned int sc_reg, u32 val)
++{
++    /* Setup the data for the write */
++    *(sata_regs_base[device] + SATA_LINK_DATA) = val;
++
++    /* Setup adr of required register. std regs start eight into async region */    
++    *(sata_regs_base[device] + SATA_LINK_WR_ADDR) = sc_reg*4 + SATA_STD_ASYNC_REGS_OFF;
++
++    /* Wait for data to be written */
++    int loops = MAX_SRC_WRITE_LOOPS;
++    do {
++        if (*(sata_regs_base[device] + SATA_LINK_CONTROL) & 1UL) {
++            break;
++        }
++        udelay(10);
++    } while (--loops);
++
++    if (!loops) {
++        printf("scr_write() Timed out of wait for write completion\n");
++    }
++}
++
++#define PHY_LOOP_COUNT  25  /* Wait for upto 5 seconds for PHY to be found */
++static int phy_reset(int device)
++{
++#ifdef FPGA
++    /* The FPGA thinks it can do 3G when infact only 1.5G is possible, so limit
++    it to Gen-1 SATA (1.5G) */ 
++    scr_write(device, SATA_SCR_CONTROL, 0x311);  /* Issue phy wake & core reset */
++    scr_read(device, SATA_SCR_STATUS);           /* Dummy read; flush */
++    udelay(1000);
++    scr_write(device, SATA_SCR_CONTROL, 0x310);  /* Issue phy wake & clear core reset */
++#else
++    scr_write(device, SATA_SCR_CONTROL, 0x301);  /* Issue phy wake & core reset */
++    scr_read(device, SATA_SCR_STATUS);           /* Dummy read; flush */
++    udelay(1000);
++    scr_write(device, SATA_SCR_CONTROL, 0x300);  /* Issue phy wake & clear core reset */
++#endif
++    /* Wait for upto 5 seconds for PHY to become ready */
++    int phy_status = 0;
++    int loops = 0;
++    do {
++        udelay(200000);
++        if ((scr_read(device, SATA_SCR_STATUS) & 0xf) != 1) {
++            phy_status = 1;
++            break;
++        }
++        printf("No SATA PHY found\n");
++    } while (++loops < PHY_LOOP_COUNT);
++
++    if (phy_status) {
++        udelay(500000); /* wait half a second */
++    }
++    return phy_status;
++}
++
++#define FIS_LOOP_COUNT  25  /* Wait for upto 5 seconds for FIS to be received */
++static int wait_FIS(int device)
++{
++    int status = 0;
++    int loops = 0;
++
++    do {
++        udelay(200000);
++        if    (hipox_sata_inb(device, ATA_PORT_NSECT) > 0) {
++            status = 1;
++            break;
++        }
++    } while (++loops < FIS_LOOP_COUNT);
++
++    return status;
++}
++
++int ide_preinit(void)
++{
++    int num_disks_found = 0;
++
++    /* Initialise records of which disks are present to all present */
++    int i;
++    for (i=0; i < CONFIG_SYS_IDE_MAXDEVICE; i++) {
++        disk_present[i] = 1;
++    }
++
++//udelay(1000000);
++    /* Enable clocks to SATA and DMA cores */
++    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_SATA_BIT);
++    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_DMA_BIT);
++    
++    /* Block reset SATA and DMA cores */
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_SATA_BIT) |
++                                              (1UL << SYS_CTRL_RSTEN_SATA_LINK_BIT) |
++                                              (1UL << SYS_CTRL_RSTEN_SATA_PHY_BIT) |
++                                              (1UL << SYS_CTRL_RSTEN_DMA_BIT);
++    udelay(50);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_SATA_PHY_BIT);
++    udelay(50);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_SATA_LINK_BIT) |
++                                              (1UL << SYS_CTRL_RSTEN_SATA_BIT);
++    udelay(50);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_DMA_BIT);
++    udelay(50);
++//udelay(1000000);
++
++    /* disable and clear core interrupts */
++    *((unsigned long*)SATA_HOST_REGS_BASE + SATA_INT_ENABLE_CLR_OFF) = ~0UL;
++    *((unsigned long*)SATA_HOST_REGS_BASE + SATA_INT_CLR_OFF) = ~0UL;
++
++    int device;
++    for (device = 0; device < CONFIG_SYS_IDE_MAXDEVICE; device++) {
++        int found = 0;
++        int retries = 1;
++
++        /* Disable SATA interrupts */
++        *(sata_regs_base[device] + SATA_INT_ENABLE_CLR_OFF) = ~0UL;
++
++        /* Clear any pending SATA interrupts */
++        *(sata_regs_base[device] + SATA_INT_CLR_OFF) = ~0UL;
++
++        do {
++            /* clear sector count register for FIS detection */
++            hipox_sata_outb(device, ATA_PORT_NSECT, 0);
++    
++            /* Get the PHY working */
++            if (!phy_reset(device)) {
++                printf("SATA PHY not ready for device %d\n", device);
++                break;
++            }
++
++            if (!wait_FIS(device)) {
++                printf("No FIS received from device %d\n", device);
++            } else {
++                if ((scr_read(device, SATA_SCR_STATUS) & 0xf) == 0x3) {
++                    if (wait_not_busy(device, 30)) {
++                        printf("Timed out of wait for SATA device %d to have BUSY clear\n", device);
++                    } else {
++                        ++num_disks_found;
++                        found = 1;
++                    }
++                } else {
++                    printf("No SATA device %d found, PHY status = 0x%08x\n",
++                            device, scr_read(device, SATA_SCR_STATUS));
++                }
++                break;
++            }
++        } while (retries--) ;
++
++        /* Record whether disk is present, so won't attempt to access it later */
++        disk_present[device] = found;
++    }
++
++    /* post disk detection clean-up */
++    for (device = 0; device < CONFIG_SYS_IDE_MAXDEVICE; device++) {
++        if ( disk_present[device] ) {
++            /* set as ata-5 (28-bit) */
++            *(sata_regs_base[device] + SATA_DRIVE_CONTROL_OFF) = 0UL;
++            
++            /* clear phy/link errors */
++            scr_write(device, SATA_SCR_ERROR, ~0);
++            
++            /* clear host errors */
++            *(sata_regs_base[device] + SATA_CONTROL_OFF) |= SATA_SCTL_CLR_ERR;
++            
++            /* clear interrupt register as this clears the error bit in the IDE 
++            status register */
++            *(sata_regs_base[device] + SATA_INT_CLR_OFF) = ~0UL;
++        }
++    }    
++    
++
++    return !num_disks_found;
++}
++
+diff -Nurd u-boot-2009.03.orig/board/hipox/platform-800.S u-boot-2009.03/board/hipox/platform-800.S
+--- u-boot-2009.03.orig/board/hipox/platform-800.S     1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/platform-800.S  2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,254 @@
++/*
++ * Board specific setup info
++ *
++ * (C) Copyright 2005
++ * Oxford Semiconductor Ltd
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <config.h>
++#include <version.h>
++
++/* use estimate of processor speed to calculate number of cycles delay */
++/* delay count is nominal (PLL200 frequency x delay time) / loop count 
++ * expressing 200us as 200/1000000 and re-arranging gives the expression below
++ */
++ 
++#define DELAY_200US   ((NOMINAL_ARMCLK / (5 * 1000000)) * 200) 
++/* this is 8 cycles of ? so choose 8 resulting in 40 cycles */
++#define DELAY_1S   ((DELAY_200US) * 5000)
++#define DELAY_8       8
++#define DELAY_200     200
++
++.globl platformsetup
++platformsetup:
++/* register allocations
++ * r0 - delay counter and scratch
++ * r1 - address register
++ * r2 - data register
++ * r3 - index to table pointer
++ * r4 - iteration counter.
++ * 
++ * r5 - hold return address.
++ * lr - (R14) link register
++ * pc - (R15) program counter.
++ */
++
++#ifdef INITIALISE_SDRAM
++/*
++ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
++ * Controller function is linked to execute in SDRAM must be in ROM if not
++ * there. Check for wrong place.
++ */
++      adrl r0, platformsetup          /* Relative location of function start.*/
++      ldr  r1, _platformsetup
++      cmp  r0, r1
++      moveq pc, lr
++#else
++      mov pc, lr
++#endif
++
++      /* Establish a working setup for the SDRAM */
++      mov r6, lr
++
++#ifdef HIPOX_OVERCLOCK
++      /* Delay so the broken JTAG can get control */
++      ldr r0, =DELAY_1S
++      bl delay
++
++      /* Configure the PLL to run faster */
++      ldr r1, =SYS_CTRL_PLLSYS_CTRL
++      ldr r2, =SYS_CTRL_PLLSYS_KEY_CTRL
++
++      /* 0xBEADFACE -> PLL_KEY */
++      /* Bypass PLL */
++      ldr r3, [r1]
++      ldr r5, =0x20000
++      orr r3, r3, r5
++      ldr r4, =0xbeadface
++      str r4, [r2]
++      str r3, [r1]
++
++      /* 0xBEADFACE -> PLL_KEY */
++      /* Set m,p and s for PLL at 400MHz */
++      ldr r5, =0xffff0000
++      and r3, r3, r5
++      ldr r5, =HIPOX_OVERCLOCK
++      orr r3, r3, r5
++      str r4, [r2]
++      str r3, [r1]
++
++      /* Wait at least 300uS */
++      ldr r0, =DELAY_200US
++      bl delay
++      ldr r0, =DELAY_200US
++      bl delay
++
++      /* 0xBEADFACE -> PLL_KEY */
++      /* Disable PLL bypass */
++      ldr r5, =0xfffdffff
++      and r3, r3, r5
++      str r4, [r2]
++      str r3, [r1]
++#endif // HIPOX_OVERCLOCK
++
++      /* Assert reset to the DDR core */
++      ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
++      ldr r1, =1
++      ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++      mov r1, r1, LSL r2
++      str r1, [r0]
++
++      /* Deassert reset to the DDR core */
++      ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
++      str r1, [r0]
++
++      /* Turn on the DDR core clock */
++      ldr r0, =SYS_CTRL_CKEN_SET_CTRL
++      ldr r1, =1
++      ldr r2, =SYS_CTRL_CKEN_DDR_BIT
++      mov r1, r1, LSL r2
++      str r1, [r0]
++
++      /* Start using the initialisation value list */
++      adrl r3, init_table
++
++      /* Copy next 6 entries from DDR init table*/
++      ldr r4, =6
++loop0:
++      ldmia r3!, {r1, r2}
++      str r2, [r1]
++      subs r4, r4, #1
++      bne loop0
++
++      /* Delay for 200uS while DRAM controller stabilises. */
++      ldr r0, =DELAY_200US
++      bl delay
++
++#if !TEST_BRD
++      /* Copy next entry */
++      ldr r4, =1
++loopx:        
++      ldmia r3!, {r1, r2}
++      str r2, [r1]
++      subs r4, r4, #1
++      bne loopx
++
++      /* Delay for 200uS while DRAM controller stabilises. */
++      ldr r0, =DELAY_200US
++      bl delay
++#endif // TEST_BRD
++
++      /* Copy next entry */
++      ldr r4, =1
++loop1:        
++      ldmia r3!, {r1, r2}
++      str r2, [r1]
++      subs r4, r4, #1
++      bne loop1
++
++      /* Delay for 200uS while DRAM controller stabilises. */
++      ldr r0, =DELAY_200US
++      bl delay
++
++      /* Copy next entry */
++      ldr r4, =1
++loop2:        
++      ldmia r3!, {r1, r2}
++      str r2, [r1]
++      subs r4, r4, #1
++      bne loop2
++
++      /* Delay for 200uS while DRAM controller stabilises. */
++      ldr r0, =DELAY_200US
++      bl delay
++
++      /* Copy next entry */
++      ldr r4, =1
++loop3:        
++      ldmia r3!, {r1, r2}
++      str r2, [r1]
++      subs r4, r4, #1
++      bne loop3
++
++      /* Delay for 200uS while DRAM controller stabilises. */
++      ldr r0, =DELAY_200US
++      bl delay
++
++      /* Copy next 5 entries */
++      ldr r4, =5
++loop4:        
++      ldmia r3!, {r1, r2}
++      str r2, [r1]
++      subs r4, r4, #1
++      bne loop4
++
++      /* SDRAM initialised so now exit. */
++      mov lr, r6
++      mov pc, lr
++
++/*
++ *  delay()
++ *
++ *  uses 1 + r0 * 5 cycles
++ */
++delay:
++      nop
++      nop
++      nop
++      subs r0, r0, #1
++      bne delay
++      mov pc, lr
++
++_platformsetup:
++      .word platformsetup
++
++init_table:
++      /* Table of address, data for loading into the DRAM controller */
++      /* Configure for a single DDR device */
++      .word 0x4500002C, 0x08
++      .word 0x45000038, 0x400
++      .word 0x45800000, 0x80100000
++      .word 0x45800004, 0x8000ffff    // Enable DDR core and all clients
++      .word 0x45800024, 0x1e4
++      .word 0x45800014, 0xe0000001    // DLL to automatic with starting value=1
++/* 200uS delay */
++#if !TEST_BRD
++      .word 0x45800014, 0xa0000003    // DLL to automatic with offset value=3
++/* 200uS delay */
++#endif // TEST_BRD
++#if (MEM_SIZE == 32)
++      .word 0x45800000, 0x801B030C
++#else
++      .word 0x45800000, 0x801D030C
++#endif // MEM_SIZE
++/* 200uS delay */
++      .word 0x4580000c, 0x80280400
++/* 200uS delay */
++      .word 0x4580000c, 0x80210000
++/* 200uS delay */
++      .word 0x4580000c, 0x80200063
++      .word 0x45800028, 0x0000001f    // Enable all arbiter features
++      .word 0x45800018, 0x00000000    // Disable all monitoring
++      .word 0x45800010, 0xffffffff    // Disable all read buffering, due to h/w bug
++      .word 0x4580002C, 0x00000000    // Do NOT disable HPROT, ie want write coherency
++
++.ltorg
++
+diff -Nurd u-boot-2009.03.orig/board/hipox/platform-810-466-timings.S u-boot-2009.03/board/hipox/platform-810-466-timings.S
+--- u-boot-2009.03.orig/board/hipox/platform-810-466-timings.S 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/platform-810-466-timings.S      2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,473 @@
++/*
++ * Board specific setup info
++ *
++ * (C) Copyright 2005
++ * Oxford Semiconductor Ltd
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <config.h>
++#include <version.h>
++
++/* use estimate of processor speed to calculate number of cycles delay */
++/* delay count is nominal (PLL200 frequency x delay time) / loop count 
++ * expressing 200us as 200/1000000 and re-arranging gives the expression below
++ */
++ 
++#define DELAY_200US   ((NOMINAL_ARMCLK  / (5 * 1000000)) * 200)  
++#define DELAY_300US   ((NOMINAL_ARMCLK  / (5 * 1000000)) * 300)  
++/* this is 8 cycles of ? so choose 8 resulting in 40 cycles */
++#define DELAY_1S   ((DELAY_200US) * 5000)
++#define DELAY_8       8
++#define DELAY_200     200
++
++
++.globl platformsetup
++platformsetup:
++/* register allocations
++ * r0 - delay counter and scratch
++ * r1 - address register
++ * r2 - data register
++ * r3 - index to table pointer
++ * r4 - iteration counter.
++ * 
++ * r5 - hold return address.
++ * lr - (R14) link register
++ * pc - (R15) program counter.
++ */
++
++#ifdef INITIALISE_SDRAM
++/*
++ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
++ * Controller function is linked to execute in SDRAM must be in ROM if not
++ * there. Check for wrong place.
++ */
++    adrl r0, platformsetup      /* Relative location of function start.*/
++    ldr  r1, _platformsetup
++    cmp  r0, r1
++    moveq pc, lr
++#else
++    mov pc, lr
++#endif
++
++#if (FPGA == 1)
++    /* Establish a working setup for the SDRAM */
++    mov r6, lr
++
++    /* Assert reset to the DDR core */
++    ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Deassert reset to the DDR core */
++    ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
++    str r1, [r0]
++
++    /* Turn on the DDR core clock */
++    ldr r0, =SYS_CTRL_CKEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_CKEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Start using the initialisation value list */
++    adrl r3, init_table
++
++    /* Copy first 6 entries */
++    ldr r4, =6
++loop0:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop0
++
++    /* Delay for 200uS while DRAM controller stabilises. */
++    ldr r0, =DELAY_200US
++    bl delay
++
++    /* Copy next 4 entries */
++    ldr r4, =4
++loop1:  
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop1
++
++    /* Wait at least 200 clock cycles. */
++    ldr r0, =DELAY_200
++    bl delay
++
++    /* Copy next 2 entries */
++    ldr r4, =2
++loop2:  
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop2
++
++    /* Wait at least 8 clock  cycles. */
++    ldr r0, =DELAY_8
++    bl delay
++
++    /* Copy next 9 entries */
++    ldr r4, =9
++loop3:  
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop3
++
++    /* SDRAM initialised so now exit. */
++    mov lr, r6
++    mov pc, lr
++
++/*
++ *  delay()
++ *
++ *  uses 1 + r0 * 5 cycles
++ */
++delay:
++    nop
++    nop
++    nop
++    subs r0, r0, #1
++    bne delay
++    mov pc, lr
++
++_platformsetup:
++    .word platformsetup
++#else // ASIC, (DDR-2)
++/*
++ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
++ * Controller function is linked to execute in SDRAM must be in ROM if not
++ * there. Check for wrong place.
++ */
++    /* Establish a working setup for the SDRAM */
++    mov r6, lr
++
++#ifdef OVERCLOCK
++    /* 
++      change clock speed on chip 
++    */
++
++    /* read SYS_CTRL_PLLSYS_CTRL into r3*/
++    mov r5, #0x45000000
++    ldr r3, [r5, #72]
++
++    /* load the value at dllkey (0xbeadface) into r7 */
++    adrl r7, dllkey
++    ldr r7, [r7]
++
++    /* pll_sys |= 0x20000; */
++    orr r3, r3, #131072 /* 0x20000 */
++
++    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
++    str r7, [r5, #108]
++
++    /* write pll_sys (bypass pll)*/
++    str r3, [r5, #72]
++
++    /* pll_sys mask out lower 26 bits */
++    mov r4, r3, lsr #26
++    mov r4, r4, lsl #26
++
++    /* pll_sys |= (26 bits of (m,p and s)) */
++    ldr r3, =OVERCLOCK
++    orr r4, r4, r3
++
++    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
++    str r7, [r5, #108]
++
++    /* write pll_sys (with new pll speeds) */    
++    str r4, [r5, #72]
++
++    /* delay 300us */
++    ldr r0, =DELAY_300US
++    bl delay
++
++    /* clear bypass pll bit */
++    bic r4, r4, #131072 /* 0x20000 */
++
++    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
++    str r7, [r5, #108]
++
++    /* write pll_sys (with new pll speeds and pll un-bypassed) */    
++    str r4, [r5, #72]
++#endif /* OVERCLOCK */
++  
++    /* Turn on the DDR core and phy clocks */
++    ldr r0, =SYS_CTRL_CKEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_CKEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_CKEN_DDR_PHY_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Assert reset to the DDR core and phy */
++    ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_PHY_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Deassert reset to the DDR core and phy*/
++    ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_PHY_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Start using the initialisation value list */
++    adrl r3, init_table
++
++    /* Copy first 14 entries of DDR core setup (section A)*/
++    ldr r4, =14
++loop0:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop0
++
++    /* Delay for 200uS while DDR controller stabilises. */
++    ldr r0, =DELAY_200US
++    bl delay
++
++    /* Copy next 13 entries of DDR device commands (section B)*/
++    ldr r4, =13
++loop1:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++
++    /* Wait at least 200 clock cycles between ram chip command writes */
++    ldr r0, =DELAY_200
++    bl delay
++
++    subs r4, r4, #1
++    bne loop1
++
++    /* Copy final DDR controller setup to set memory size/banks (section C)*/
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++
++#if (PROBE_MEM_SIZE == 1)
++    /* Load the probe values into SDRAM */
++    adrl r3, probe_table
++    mov r4, #4
++.globl pl1
++pl1:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne pl1
++
++    /* Get the current contents of the DDR controller core's config register */
++    adrl r1, ddr_config_reg
++    ldr r1, [r1]
++    ldr r1, [r1]
++
++    /* Zero the number of banks field - bit 23*/
++    mov r2, #1
++    bic r1, r1, r2, lsl #23
++
++    /* Zero the size field - bits 17-20 inclusive */
++    mov r2, #15
++    bic r1, r1, r2, lsl #17
++
++    /* First probe location tells us the SDRAM size */
++    adrl r3, probe_table
++    ldr r0, [r3]
++    ldr r0, [r0]
++
++    /* Is size 64MB? */
++    ldr r2, [r3, #28] /* Get probe value 4 */
++    cmp r0, r2
++    moveq r4, #6
++    orreq r1, r1, r4, lsl #17
++    beq pl2
++
++    /* Is 128M or 256M so set banks to 8 */
++    mov r4, #1
++    orr r1, r1, r4, lsl #23
++
++    /* Is size 128MB? */
++    ldr r2, [r3, #20] /* Get probe value 3 */
++    cmp r0, r2
++//    moveq r4, #7
++    moveq r4, #8      /* DDR controller does not work at 128M, use 256M instead
++    orreq r1, r1, r4, lsl #17
++    beq pl2
++
++    /* Must be 256MB, or something is very wrong */
++    mov r4, #8
++    orr r1, r1, r4, lsl #17
++
++pl2:
++    /* Write the revised contents to the DDR controller core's config register */
++    adrl r2, ddr_config_reg
++    ldr r2, [r2]
++    str r1, [r2]
++#endif
++
++    /* SDRAM setup complete */
++    mov lr, r6
++    mov pc, lr
++
++/*
++ *  delay()
++ *
++ *  uses 1 + r0 * 5 cycles
++ */
++delay:
++    nop
++    nop
++    nop
++    subs r0, r0, #1
++    bne delay
++    mov pc, lr
++
++_platformsetup:
++    .word platformsetup
++#endif
++
++
++init_table:
++#if (FPGA == 1)
++    /* Table of address, data for loading into the DRAM controller on FPGA */
++    .word 0x45800000, 0x000d0000    // Enable the DDR in SDR mode and width 32 bits
++    .word 0x45800034, 0x04442032    // SDR mode timings - #0
++    .word 0x45800038, 0x570A0907    // SDR mode timings - #1
++    .word 0x4580003C, 0x00000002    // SDR mode timings - #2
++    .word 0x45800004, 0x80000000    // Enable DDR core, but not clients yet
++    .word 0x45800014, 0x80000001    // Enable CK and set DLL mode to manual
++/* 200uS delay */
++    .word 0x4580000c, 0x80200000    // Assert CKE for all further commands
++    .word 0x4580000c, 0x80280400    // Issue precharge to all banks
++    .word 0x4580000c, 0x80200000    // NOP, as only DDR has real command here
++    .word 0x4580000c, 0x80200022    // Set burst length 4, sequential CAS 2
++/* 200uS delay */
++    .word 0x4580000c, 0x80280400    // Issue precharge to all banks
++    .word 0x4580000c, 0x80240000    // Issue auto-refresh command, CKE not asserted
++/* 200uS delay */
++    .word 0x4580000c, 0x80240000    // Issue auto-refresh command, CKE not asserted
++    .word 0x4580000c, 0x80200000    // Assert CKE for all further commands
++    .word 0x4580000c, 0x80200022        // Set burst length 4, sequential CAS 2
++    .word 0x45800000, 0x000d0186    // SDR, size and width and refresh rate, assuming
++                        // 25Mhz clk to SDR, divide down to get 15.625uS
++                    // refresh rate
++    .word 0x45800024, 0x00000124    // Set I/O drive strengths
++    .word 0x45800028, 0x0000001f    // Enable all arbiter features
++    .word 0x45800018, 0x00000000    // Disable all monitoring
++    .word 0x45800010, 0xFFFFFFFF    // Disable all read buffering
++    .word 0x45800004, 0x800000ff    // Enable all client interfaces
++#else   // ASIC DDR-2
++    // SECTION A - DDR controller core configuration
++    .word 0x45800000, 0x802d0591    // enable in ddr-2 mode 16 bit wide
++    .word 0x45800034, 0x04442033    // ddr-2 mode timings 
++    .word 0x45800038, 0x98110d2f    // ddr-2 mode timings
++    .word 0x4580003c, 0x00000c34    // ddr-2 mode timings
++    .word 0x45800054, 0x00072000    // phy-3 settings
++    .word 0x45800050, 0x00022828    // phy-2 settings, start
++    .word 0x45800050, 0x00032828    // phy-2 settings, on
++    .word 0x45800028, 0x0000001f    // Enable all arbiter features
++    .word 0x45800018, 0x00000000    // Disable all monitoring
++    .word 0x45800010, 0xffff0000    // Enable all read buffering
++    .word 0x4580002c, 0x00ff00fd    // no burst accl, no hprot on arm data
++    .word 0x45800040, 0x00000000    // enable burst and read cache
++    .word 0x45800044, 0xffff0000    // enable write behind prot, disable timeout     
++    .word 0x45800004, 0x8000ffff    // Enable all client interfaces
++/* 200uS delay after configuring DDR controller core */
++
++    // SECTION B - Memory device configuration
++    .word 0x4580000c, 0x807c0000    // exit something or other
++    .word 0x4580000c, 0x803c0000    // nop - wake up
++    .word 0x4580000c, 0x80280400    // precharge all
++    .word 0x4580000c, 0x80220000    // emr2
++    .word 0x4580000c, 0x80230000    // emr3
++
++#if (MEM_ODT == 150)
++    .word 0x4580000c, 0x80210042    // enable dll, odt to 150
++#elif (MEM_ODT == 75)
++    .word 0x4580000c, 0x80210006    // enable dll, odt to 75
++#elif (MEM_ODT == 50)
++    .word 0x4580000c, 0x80210046    // enable dll, odt to 50
++#else
++#error Unsupported memory on-die termination, set MEM_ODT to 50, 75, or 150
++#endif
++
++    .word 0x4580000c, 0x80200743    // set WR CL BL and reset dll
++    .word 0x4580000c, 0x80280400    // precharge all
++    .word 0x4580000c, 0x80240000    // auto refresh
++    .word 0x4580000c, 0x80240000    // auto refresh
++    .word 0x4580000c, 0x80200743    // set WR CL BL and reset dll
++
++#if (MEM_ODT == 150)
++    .word 0x4580000c, 0x802103c2    // enable OCD
++    .word 0x4580000c, 0x80210042    // disable OCD
++#elif (MEM_ODT == 75)
++    .word 0x4580000c, 0x80210386    // enable OCD
++    .word 0x4580000c, 0x80210006    // disable OCD
++#elif (MEM_ODT == 50)
++    .word 0x4580000c, 0x802103c6    // enable OCD
++    .word 0x4580000c, 0x80210046    // disable OCD
++#else
++#error Unsupported memory on-die termination, set MEM_ODT to 50, 75, or 150
++#endif
++
++    // SECTION C - Final memory size/bank configuration
++#if (PROBE_MEM_SIZE == 1)
++    .word 0x45800000, 0x80b10591    // 256M, 8 banks, 1425 clocks for 7.8us refresh.
++#elif (MEM_SIZE == 64)
++    .word 0x45800000, 0x802d0591    // 64M,  4 banks, 1425 clocks for 7.8us refresh.
++#elif (MEM_SIZE == 128)
++    .word 0x45800000, 0x80af0591    // 128M, 8 banks, 1425 clocks for 7.8us refresh.
++#elif (MEM_SIZE == 256)
++    .word 0x45800000, 0x80b10591    // 256M, 8 banks, 1425 clocks for 7.8us refresh.
++#else
++#error Unsupported memory size, set MEM_SIZE to 64, 128 or 256
++#endif
++
++#endif  // FPGA or ASIC
++dllkey:
++    .word 0xbeadface
++
++ddr_config_reg:
++    .word 0x45800000
++
++probe_table:
++    .word 0x48000000, 0x12345678
++    .word 0x48000040, 0xdeadbeef
++    .word 0x50000000, 0xfafafafa
++    .word 0x50000040, 0xabcdef01
++
++.ltorg
++
+diff -Nurd u-boot-2009.03.orig/board/hipox/platform-810.S u-boot-2009.03/board/hipox/platform-810.S
+--- u-boot-2009.03.orig/board/hipox/platform-810.S     1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/platform-810.S  2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,473 @@
++/*
++ * Board specific setup info
++ *
++ * (C) Copyright 2005
++ * Oxford Semiconductor Ltd
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <config.h>
++#include <version.h>
++
++/* use estimate of processor speed to calculate number of cycles delay */
++/* delay count is nominal (PLL200 frequency x delay time) / loop count 
++ * expressing 200us as 200/1000000 and re-arranging gives the expression below
++ */
++ 
++#define DELAY_200US   ((NOMINAL_ARMCLK  / (5 * 1000000)) * 200)  
++#define DELAY_300US   ((NOMINAL_ARMCLK  / (5 * 1000000)) * 300)  
++/* this is 8 cycles of ? so choose 8 resulting in 40 cycles */
++#define DELAY_1S   ((DELAY_200US) * 5000)
++#define DELAY_8       8
++#define DELAY_200     200
++
++
++.globl lowlevel_init
++lowlevel_init:
++/* register allocations
++ * r0 - delay counter and scratch
++ * r1 - address register
++ * r2 - data register
++ * r3 - index to table pointer
++ * r4 - iteration counter.
++ * 
++ * r5 - hold return address.
++ * lr - (R14) link register
++ * pc - (R15) program counter.
++ */
++
++#ifdef INITIALISE_SDRAM
++/*
++ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
++ * Controller function is linked to execute in SDRAM must be in ROM if not
++ * there. Check for wrong place.
++ */
++    adrl r0, lowlevel_init      /* Relative location of function start.*/
++    ldr  r1, _lowlevel_init
++    cmp  r0, r1
++    moveq pc, lr
++#else
++    mov pc, lr
++#endif
++
++#if (FPGA == 1)
++    /* Establish a working setup for the SDRAM */
++    mov r6, lr
++
++    /* Assert reset to the DDR core */
++    ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Deassert reset to the DDR core */
++    ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
++    str r1, [r0]
++
++    /* Turn on the DDR core clock */
++    ldr r0, =SYS_CTRL_CKEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_CKEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Start using the initialisation value list */
++    adrl r3, init_table
++
++    /* Copy first 6 entries */
++    ldr r4, =6
++loop0:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop0
++
++    /* Delay for 200uS while DRAM controller stabilises. */
++    ldr r0, =DELAY_200US
++    bl delay
++
++    /* Copy next 4 entries */
++    ldr r4, =4
++loop1:  
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop1
++
++    /* Wait at least 200 clock cycles. */
++    ldr r0, =DELAY_200
++    bl delay
++
++    /* Copy next 2 entries */
++    ldr r4, =2
++loop2:  
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop2
++
++    /* Wait at least 8 clock  cycles. */
++    ldr r0, =DELAY_8
++    bl delay
++
++    /* Copy next 9 entries */
++    ldr r4, =9
++loop3:  
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop3
++
++    /* SDRAM initialised so now exit. */
++    mov lr, r6
++    mov pc, lr
++
++/*
++ *  delay()
++ *
++ *  uses 1 + r0 * 5 cycles
++ */
++delay:
++    nop
++    nop
++    nop
++    subs r0, r0, #1
++    bne delay
++    mov pc, lr
++
++_lowlevel_init:
++    .word lowlevel_init
++#else // ASIC, (DDR-2)
++/*
++ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
++ * Controller function is linked to execute in SDRAM must be in ROM if not
++ * there. Check for wrong place.
++ */
++    /* Establish a working setup for the SDRAM */
++    mov r6, lr
++
++#ifdef OVERCLOCK
++    /* 
++      change clock speed on chip 
++    */
++
++    /* read SYS_CTRL_PLLSYS_CTRL into r3*/
++    mov r5, #0x45000000
++    ldr r3, [r5, #72]
++
++    /* load the value at dllkey (0xbeadface) into r7 */
++    adrl r7, dllkey
++    ldr r7, [r7]
++
++    /* pll_sys |= 0x20000; */
++    orr r3, r3, #131072 /* 0x20000 */
++
++    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
++    str r7, [r5, #108]
++
++    /* write pll_sys (bypass pll)*/
++    str r3, [r5, #72]
++
++    /* pll_sys mask out lower 26 bits */
++    mov r4, r3, lsr #26
++    mov r4, r4, lsl #26
++
++    /* pll_sys |= (26 bits of (m,p and s)) */
++    ldr r3, =OVERCLOCK
++    orr r4, r4, r3
++
++    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
++    str r7, [r5, #108]
++
++    /* write pll_sys (with new pll speeds) */    
++    str r4, [r5, #72]
++
++    /* delay 300us */
++    ldr r0, =DELAY_300US
++    bl delay
++
++    /* clear bypass pll bit */
++    bic r4, r4, #131072 /* 0x20000 */
++
++    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
++    str r7, [r5, #108]
++
++    /* write pll_sys (with new pll speeds and pll un-bypassed) */    
++    str r4, [r5, #72]
++#endif /* OVERCLOCK */
++  
++    /* Turn on the DDR core and phy clocks */
++    ldr r0, =SYS_CTRL_CKEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_CKEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_CKEN_DDR_PHY_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Assert reset to the DDR core and phy */
++    ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_PHY_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Deassert reset to the DDR core and phy*/
++    ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_PHY_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Start using the initialisation value list */
++    adrl r3, init_table
++
++    /* Copy first 14 entries of DDR core setup (section A)*/
++    ldr r4, =14
++loop0:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop0
++
++    /* Delay for 200uS while DDR controller stabilises. */
++    ldr r0, =DELAY_200US
++    bl delay
++
++    /* Copy next 13 entries of DDR device commands (section B)*/
++    ldr r4, =13
++loop1:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++
++    /* Wait at least 200 clock cycles between ram chip command writes */
++    ldr r0, =DELAY_200
++    bl delay
++
++    subs r4, r4, #1
++    bne loop1
++
++    /* Copy final DDR controller setup to set memory size/banks (section C)*/
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++
++#if (PROBE_MEM_SIZE == 1)
++    /* Load the probe values into SDRAM */
++    adrl r3, probe_table
++    mov r4, #4
++.globl pl1
++pl1:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne pl1
++
++    /* Get the current contents of the DDR controller core's config register */
++    adrl r1, ddr_config_reg
++    ldr r1, [r1]
++    ldr r1, [r1]
++
++    /* Zero the number of banks field - bit 23*/
++    mov r2, #1
++    bic r1, r1, r2, lsl #23
++
++    /* Zero the size field - bits 17-20 inclusive */
++    mov r2, #15
++    bic r1, r1, r2, lsl #17
++
++    /* First probe location tells us the SDRAM size */
++    adrl r3, probe_table
++    ldr r0, [r3]
++    ldr r0, [r0]
++
++    /* Is size 64MB? */
++    ldr r2, [r3, #28] /* Get probe value 4 */
++    cmp r0, r2
++    moveq r4, #6
++    orreq r1, r1, r4, lsl #17
++    beq pl2
++
++    /* Is 128M or 256M so set banks to 8 */
++    mov r4, #1
++    orr r1, r1, r4, lsl #23
++
++    /* Is size 128MB? */
++    ldr r2, [r3, #20] /* Get probe value 3 */
++    cmp r0, r2
++//    moveq r4, #7
++    moveq r4, #8      /* DDR controller does not work at 128M, use 256M instead
++    orreq r1, r1, r4, lsl #17
++    beq pl2
++
++    /* Must be 256MB, or something is very wrong */
++    mov r4, #8
++    orr r1, r1, r4, lsl #17
++
++pl2:
++    /* Write the revised contents to the DDR controller core's config register */
++    adrl r2, ddr_config_reg
++    ldr r2, [r2]
++    str r1, [r2]
++#endif
++
++    /* SDRAM setup complete */
++    mov lr, r6
++    mov pc, lr
++
++/*
++ *  delay()
++ *
++ *  uses 1 + r0 * 5 cycles
++ */
++delay:
++    nop
++    nop
++    nop
++    subs r0, r0, #1
++    bne delay
++    mov pc, lr
++
++_lowlevel_init:
++    .word lowlevel_init
++#endif
++
++
++init_table:
++#if (FPGA == 1)
++    /* Table of address, data for loading into the DRAM controller on FPGA */
++    .word 0x45800000, 0x000d0000    // Enable the DDR in SDR mode and width 32 bits
++    .word 0x45800034, 0x04442032    // SDR mode timings - #0
++    .word 0x45800038, 0x570A0907    // SDR mode timings - #1
++    .word 0x4580003C, 0x00000002    // SDR mode timings - #2
++    .word 0x45800004, 0x80000000    // Enable DDR core, but not clients yet
++    .word 0x45800014, 0x80000001    // Enable CK and set DLL mode to manual
++/* 200uS delay */
++    .word 0x4580000c, 0x80200000    // Assert CKE for all further commands
++    .word 0x4580000c, 0x80280400    // Issue precharge to all banks
++    .word 0x4580000c, 0x80200000    // NOP, as only DDR has real command here
++    .word 0x4580000c, 0x80200022    // Set burst length 4, sequential CAS 2
++/* 200uS delay */
++    .word 0x4580000c, 0x80280400    // Issue precharge to all banks
++    .word 0x4580000c, 0x80240000    // Issue auto-refresh command, CKE not asserted
++/* 200uS delay */
++    .word 0x4580000c, 0x80240000    // Issue auto-refresh command, CKE not asserted
++    .word 0x4580000c, 0x80200000    // Assert CKE for all further commands
++    .word 0x4580000c, 0x80200022        // Set burst length 4, sequential CAS 2
++    .word 0x45800000, 0x000d0186    // SDR, size and width and refresh rate, assuming
++                        // 25Mhz clk to SDR, divide down to get 15.625uS
++                    // refresh rate
++    .word 0x45800024, 0x00000124    // Set I/O drive strengths
++    .word 0x45800028, 0x0000001f    // Enable all arbiter features
++    .word 0x45800018, 0x00000000    // Disable all monitoring
++    .word 0x45800010, 0xFFFFFFFF    // Disable all read buffering
++    .word 0x45800004, 0x800000ff    // Enable all client interfaces
++#else   // ASIC DDR-2
++    // SECTION A - DDR controller core configuration
++    .word 0x45800000, 0x802d0591    // enable in ddr-2 mode 16 bit wide
++    .word 0x45800034, 0x04442032    // ddr-2 mode timings 
++    .word 0x45800038, 0x870f0b25    // ddr-2 mode timings
++    .word 0x4580003c, 0x00000a23    // ddr-2 mode timings
++    .word 0x45800054, 0x00072000    // phy-3 settings
++    .word 0x45800050, 0x00022828    // phy-2 settings, start
++    .word 0x45800050, 0x00032828    // phy-2 settings, on
++    .word 0x45800028, 0x0000001f    // Enable all arbiter features
++    .word 0x45800018, 0x00000000    // Disable all monitoring
++    .word 0x45800010, 0xffff0000    // Enable all read buffering
++    .word 0x4580002c, 0x00ff00fd    // no burst accl, no hprot on arm data
++    .word 0x45800040, 0x00000000    // enable burst and read cache
++    .word 0x45800044, 0xffff0000    // enable write behind prot, disable timeout     
++    .word 0x45800004, 0x8000ffff    // Enable all client interfaces
++/* 200uS delay after configuring DDR controller core */
++
++    // SECTION B - Memory device configuration
++    .word 0x4580000c, 0x807c0000    // exit something or other
++    .word 0x4580000c, 0x803c0000    // nop - wake up
++    .word 0x4580000c, 0x80280400    // precharge all
++    .word 0x4580000c, 0x80220000    // emr2
++    .word 0x4580000c, 0x80230000    // emr3
++
++#if (MEM_ODT == 150)
++    .word 0x4580000c, 0x80210042    // enable dll, odt to 150
++#elif (MEM_ODT == 75)
++    .word 0x4580000c, 0x80210006    // enable dll, odt to 75
++#elif (MEM_ODT == 50)
++    .word 0x4580000c, 0x80210046    // enable dll, odt to 50
++#else
++#error Unsupported memory on-die termination, set MEM_ODT to 50, 75, or 150
++#endif
++
++    .word 0x4580000c, 0x80200733    // set WR CL BL and reset dll
++    .word 0x4580000c, 0x80280400    // precharge all
++    .word 0x4580000c, 0x80240000    // auto refresh
++    .word 0x4580000c, 0x80240000    // auto refresh
++    .word 0x4580000c, 0x80200733    // set WR CL BL and reset dll
++
++#if (MEM_ODT == 150)
++    .word 0x4580000c, 0x802103c2    // enable OCD
++    .word 0x4580000c, 0x80210042    // disable OCD
++#elif (MEM_ODT == 75)
++    .word 0x4580000c, 0x80210386    // enable OCD
++    .word 0x4580000c, 0x80210006    // disable OCD
++#elif (MEM_ODT == 50)
++    .word 0x4580000c, 0x802103c6    // enable OCD
++    .word 0x4580000c, 0x80210046    // disable OCD
++#else
++#error Unsupported memory on-die termination, set MEM_ODT to 50, 75, or 150
++#endif
++
++    // SECTION C - Final memory size/bank configuration
++#if (PROBE_MEM_SIZE == 1)
++    .word 0x45800000, 0x80b10591    // 256M, 8 banks, 1425 clocks for 7.8us refresh.
++#elif (MEM_SIZE == 64)
++    .word 0x45800000, 0x802d0591    // 64M,  4 banks, 1425 clocks for 7.8us refresh.
++#elif (MEM_SIZE == 128)
++    .word 0x45800000, 0x80af0591    // 128M, 8 banks, 1425 clocks for 7.8us refresh.
++#elif (MEM_SIZE == 256)
++    .word 0x45800000, 0x80b10591    // 256M, 8 banks, 1425 clocks for 7.8us refresh.
++#else
++#error Unsupported memory size, set MEM_SIZE to 64, 128 or 256
++#endif
++
++#endif  // FPGA or ASIC
++dllkey:
++    .word 0xbeadface
++
++ddr_config_reg:
++    .word 0x45800000
++
++probe_table:
++    .word 0x48000000, 0x12345678
++    .word 0x48000040, 0xdeadbeef
++    .word 0x50000000, 0xfafafafa
++    .word 0x50000040, 0xabcdef01
++
++.ltorg
++
+diff -Nurd u-boot-2009.03.orig/board/hipox/platform-820.S u-boot-2009.03/board/hipox/platform-820.S
+--- u-boot-2009.03.orig/board/hipox/platform-820.S     1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/platform-820.S  2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,477 @@
++/*
++ * Board specific setup info
++ *
++ * (C) Copyright 2008
++ * Oxford Semiconductor Ltd
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <config.h>
++#include <version.h>
++
++/* use estimate of processor speed to calculate number of cycles delay */
++/* delay count is nominal (PLL200 frequency x delay time) / loop count 
++ * expressing 200us as 200/1000000 and re-arranging gives the expression below
++ */
++ 
++#define DELAY_200US   ((NOMINAL_ARMCLK  / (5 * 1000000)) * 200)  
++#define DELAY_300US   ((NOMINAL_ARMCLK  / (5 * 1000000)) * 300)  
++/* this is 8 cycles of ? so choose 8 resulting in 40 cycles */
++#define DELAY_1S   ((DELAY_200US) * 5000)
++#define DELAY_8       8
++#define DELAY_200     200
++
++
++.globl platformsetup
++platformsetup:
++/* register allocations
++ * r0 - delay counter and scratch
++ * r1 - address register
++ * r2 - data register
++ * r3 - index to table pointer
++ * r4 - iteration counter.
++ * 
++ * r5 - hold return address.
++ * lr - (R14) link register
++ * pc - (R15) program counter.
++ */
++
++#ifdef INITIALISE_SDRAM
++/*
++ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
++ * Controller function is linked to execute in SDRAM must be in ROM if not
++ * there. Check for wrong place.
++ */
++    adrl r0, platformsetup      /* Relative location of function start.*/
++    ldr  r1, _platformsetup
++    cmp  r0, r1
++    moveq pc, lr
++#else
++    mov pc, lr
++#endif
++
++#if (FPGA == 1)
++    /* Establish a working setup for the SDRAM */
++    mov r6, lr
++
++    /* Assert reset to the DDR core */
++    ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Deassert reset to the DDR core */
++    ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
++    str r1, [r0]
++
++    /* Turn on the DDR core clock */
++    ldr r0, =SYS_CTRL_CKEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_CKEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Start using the initialisation value list */
++    adrl r3, init_table
++
++    /* Copy first 6 entries */
++    ldr r4, =6
++loop0:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop0
++
++    /* Delay for 200uS while DRAM controller stabilises. */
++    ldr r0, =DELAY_200US
++    bl delay
++
++    /* Copy next 4 entries */
++    ldr r4, =4
++loop1:  
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop1
++
++    /* Wait at least 200 clock cycles. */
++    ldr r0, =DELAY_200
++    bl delay
++
++    /* Copy next 2 entries */
++    ldr r4, =2
++loop2:  
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop2
++
++    /* Wait at least 8 clock  cycles. */
++    ldr r0, =DELAY_8
++    bl delay
++
++    /* Copy next 9 entries */
++    ldr r4, =9
++loop3:  
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop3
++
++    /* SDRAM initialised so now exit. */
++    mov lr, r6
++    mov pc, lr
++
++/*
++ *  delay()
++ *
++ *  uses 1 + r0 * 5 cycles
++ */
++delay:
++    nop
++    nop
++    nop
++    subs r0, r0, #1
++    bne delay
++    mov pc, lr
++
++_platformsetup:
++    .word platformsetup
++#else // ASIC, (DDR-2)
++/*
++ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
++ * Controller function is linked to execute in SDRAM must be in ROM if not
++ * there. Check for wrong place.
++ */
++    /* Establish a working setup for the SDRAM */
++    mov r6, lr
++
++#ifdef OVERCLOCK
++    /* 
++      change clock speed on chip 
++    */
++    
++    /* read SYS_CTRL_PLLSYS_CTRL into r3*/
++    mov r5, #0x45000000
++    ldr r3, [r5, #72]
++    
++    /* load the value at dllkey (0xbeadface) into r7 */
++    adrl r7, dllkey
++    ldr r7, [r7]
++    
++    /* pll_sys |= 0x20000; */
++    orr r3, r3, #131072 /* 0x20000 */
++    
++    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
++    str r7, [r5, #108]
++
++    /* write pll_sys (bypass pll)*/
++    str r3, [r5, #72]
++    
++    /* pll_sys &= 0xff000000; */
++    mov r4, r3, lsr #16
++    mov r4, r4, lsl #16
++    
++    /* pll_sys |= 0x00F00061  */
++    orr r4, r4, #15728640   /* 0xf00000 */
++    orr r4, r4, #97 /* 0x61 */
++#if 0
++    orr r4, r4, #7864320    /* 0x780000 */
++    orr r4, r4, #96 /* 0x60 */
++#endif
++    
++    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
++    str r7, [r5, #108]
++
++    /* write pll_sys (with new pll speeds) */    
++    str r4, [r5, #72]
++
++    /* delay 300us */
++    ldr r0, =DELAY_300US
++    bl delay
++
++    /* clear bypass pll bit */
++    bic r4, r4, #131072 /* 0x20000 */
++
++    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
++    str r7, [r5, #108]
++
++    /* write pll_sys (with new pll speeds and pll un-bypassed) */    
++    str r4, [r5, #72]
++#endif /* OVERCLOCK */
++  
++    /* Turn on the DDR core and phy clocks */
++    ldr r0, =SYS_CTRL_CKEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_CKEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_CKEN_DDR_PHY_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Assert reset to the DDR core and phy */
++    ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_PHY_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Deassert reset to the DDR core and phy*/
++    ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_PHY_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++    ldr r1, =1
++    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
++    mov r1, r1, LSL r2
++    str r1, [r0]
++
++    /* Start using the initialisation value list */
++    adrl r3, init_table
++
++    /* Copy first 14 entries of DDR core setup (section A)*/
++    ldr r4, =14
++loop0:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne loop0
++
++    /* Delay for 200uS while DDR controller stabilises. */
++    ldr r0, =DELAY_200US
++    bl delay
++
++    /* Copy next 13 entries of DDR device commands (section B)*/
++    ldr r4, =13
++loop1:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++
++    /* Wait at least 200 clock cycles between ram chip command writes */
++    ldr r0, =DELAY_200
++    bl delay
++
++    subs r4, r4, #1
++    bne loop1
++
++    /* Copy final DDR controller setup to set memory size/banks (section C)*/
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++
++#if (PROBE_MEM_SIZE == 1)
++    /* Load the probe values into SDRAM */
++    adrl r3, probe_table
++    mov r4, #4
++.globl pl1
++pl1:
++    ldmia r3!, {r1, r2}
++    str r2, [r1]
++    subs r4, r4, #1
++    bne pl1
++
++    /* Get the current contents of the DDR controller core's config register */
++    adrl r1, ddr_config_reg
++    ldr r1, [r1]
++    ldr r1, [r1]
++
++    /* Zero the number of banks field - bit 23*/
++    mov r2, #1
++    bic r1, r1, r2, lsl #23
++
++    /* Zero the size field - bits 17-20 inclusive */
++    mov r2, #15
++    bic r1, r1, r2, lsl #17
++
++    /* First probe location tells us the SDRAM size */
++    adrl r3, probe_table
++    ldr r0, [r3]
++    ldr r0, [r0]
++
++    /* Is size 64MB? */
++    ldr r2, [r3, #28] /* Get probe value 4 */
++    cmp r0, r2
++    moveq r4, #6
++    orreq r1, r1, r4, lsl #17
++    beq pl2
++
++    /* Is 128M or 256M so set banks to 8 */
++    mov r4, #1
++    orr r1, r1, r4, lsl #23
++
++    /* Is size 128MB? */
++    ldr r2, [r3, #20] /* Get probe value 3 */
++    cmp r0, r2
++//    moveq r4, #7
++    moveq r4, #8      /* DDR controller does not work at 128M, use 256M instead
++    orreq r1, r1, r4, lsl #17
++    beq pl2
++
++    /* Must be 256MB, or something is very wrong */
++    mov r4, #8
++    orr r1, r1, r4, lsl #17
++
++pl2:
++    /* Write the revised contents to the DDR controller core's config register */
++    adrl r2, ddr_config_reg
++    ldr r2, [r2]
++    str r1, [r2]
++#endif
++
++    /* SDRAM setup complete */
++    mov lr, r6
++    mov pc, lr
++
++/*
++ *  delay()
++ *
++ *  uses 1 + r0 * 5 cycles
++ */
++delay:
++    nop
++    nop
++    nop
++    subs r0, r0, #1
++    bne delay
++    mov pc, lr
++
++_platformsetup:
++    .word platformsetup
++#endif
++
++
++init_table:
++#if (FPGA == 1)
++    /* Table of address, data for loading into the DRAM controller on FPGA */
++    .word 0x45800000, 0x000d0000    // Enable the DDR in SDR mode and width 32 bits
++    .word 0x45800034, 0x04442032    // SDR mode timings - #0
++    .word 0x45800038, 0x570A0907    // SDR mode timings - #1
++    .word 0x4580003C, 0x00000002    // SDR mode timings - #2
++    .word 0x45800004, 0x80000000    // Enable DDR core, but not clients yet
++    .word 0x45800014, 0x80000001    // Enable CK and set DLL mode to manual
++/* 200uS delay */
++    .word 0x4580000c, 0x80200000    // Assert CKE for all further commands
++    .word 0x4580000c, 0x80280400    // Issue precharge to all banks
++    .word 0x4580000c, 0x80200000    // NOP, as only DDR has real command here
++    .word 0x4580000c, 0x80200022    // Set burst length 4, sequential CAS 2
++/* 200uS delay */
++    .word 0x4580000c, 0x80280400    // Issue precharge to all banks
++    .word 0x4580000c, 0x80240000    // Issue auto-refresh command, CKE not asserted
++/* 200uS delay */
++    .word 0x4580000c, 0x80240000    // Issue auto-refresh command, CKE not asserted
++    .word 0x4580000c, 0x80200000    // Assert CKE for all further commands
++    .word 0x4580000c, 0x80200022        // Set burst length 4, sequential CAS 2
++    .word 0x45800000, 0x000d0186    // SDR, size and width and refresh rate, assuming
++                        // 25Mhz clk to SDR, divide down to get 15.625uS
++                    // refresh rate
++    .word 0x45800024, 0x00000124    // Set I/O drive strengths
++    .word 0x45800028, 0x0000001f    // Enable all arbiter features
++    .word 0x45800018, 0x00000000    // Disable all monitoring
++    .word 0x45800010, 0xFFFFFFFF    // Disable all read buffering
++    .word 0x45800004, 0x800000ff    // Enable all client interfaces
++#else   // ASIC DDR-2
++    // SECTION A - DDR controller core configuration
++    .word 0x45800000, 0x802d0591    // enable in ddr-2 mode 16 bit wide
++    .word 0x45800034, 0x04442032    // ddr-2 mode timings 
++    .word 0x45800038, 0x870f0b25    // ddr-2 mode timings
++    .word 0x4580003c, 0x00000a23    // ddr-2 mode timings
++    .word 0x45800054, 0x00072000    // phy-3 settings
++    .word 0x45800050, 0x00022828    // phy-2 settings, start
++    .word 0x45800050, 0x00032828    // phy-2 settings, on
++    .word 0x45800028, 0x0000001f    // Enable all arbiter features
++    .word 0x45800018, 0x00000000    // Disable all monitoring
++    .word 0x45800010, 0xffff0000    // Enable all read buffering
++    .word 0x4580002c, 0x00ff00fd    // no burst accl, no hprot on arm data
++    .word 0x45800040, 0x00000000    // enable burst and read cache
++    .word 0x45800044, 0xffff0000    // enable write behind prot, disable timeout     
++    .word 0x45800004, 0x8000ffff    // Enable all client interfaces
++/* 200uS delay after configuring DDR controller core */
++
++    // SECTION B - Memory device configuration
++    .word 0x4580000c, 0x807c0000    // exit something or other
++    .word 0x4580000c, 0x803c0000    // nop - wake up
++    .word 0x4580000c, 0x80280400    // precharge all
++    .word 0x4580000c, 0x80220000    // emr2
++    .word 0x4580000c, 0x80230000    // emr3
++
++#if (MEM_ODT == 150)
++    .word 0x4580000c, 0x80210042    // enable dll, odt to 150
++#elif (MEM_ODT == 75)
++    .word 0x4580000c, 0x80210006    // enable dll, odt to 75
++#elif (MEM_ODT == 50)
++    .word 0x4580000c, 0x80210046    // enable dll, odt to 50
++#else
++#error Unsupported memory on-die termination, set MEM_ODT to 50, 75, or 150
++#endif
++
++    .word 0x4580000c, 0x80200733    // set WR CL BL and reset dll
++    .word 0x4580000c, 0x80280400    // precharge all
++    .word 0x4580000c, 0x80240000    // auto refresh
++    .word 0x4580000c, 0x80240000    // auto refresh
++    .word 0x4580000c, 0x80200733    // set WR CL BL and reset dll
++
++#if (MEM_ODT == 150)
++    .word 0x4580000c, 0x802103c2    // enable OCD
++    .word 0x4580000c, 0x80210042    // disable OCD
++#elif (MEM_ODT == 75)
++    .word 0x4580000c, 0x80210386    // enable OCD
++    .word 0x4580000c, 0x80210006    // disable OCD
++#elif (MEM_ODT == 50)
++    .word 0x4580000c, 0x802103c6    // enable OCD
++    .word 0x4580000c, 0x80210046    // disable OCD
++#else
++#error Unsupported memory on-die termination, set MEM_ODT to 50, 75, or 150
++#endif
++
++    // SECTION C - Final memory size/bank configuration
++#if (PROBE_MEM_SIZE == 1)
++    .word 0x45800000, 0x80b10591    // 256M, 8 banks, 1425 clocks for 7.8us refresh.
++#elif (MEM_SIZE == 64)
++    .word 0x45800000, 0x802d0591    // 64M,  4 banks, 1425 clocks for 7.8us refresh.
++#elif (MEM_SIZE == 128)
++    .word 0x45800000, 0x80af0591    // 128M, 8 banks, 1425 clocks for 7.8us refresh.
++#elif (MEM_SIZE == 256)
++    .word 0x45800000, 0x80b10591    // 256M, 8 banks, 1425 clocks for 7.8us refresh.
++#else
++#error Unsupported memory size, set MEM_SIZE to 64, 128 or 256
++#endif
++
++#endif  // FPGA or ASIC
++dllkey:
++    .word 0xbeadface
++
++ddr_config_reg:
++    .word 0x45800000
++
++probe_table:
++    .word 0x48000000, 0x12345678
++    .word 0x48000040, 0xdeadbeef
++    .word 0x50000000, 0xfafafafa
++    .word 0x50000040, 0xabcdef01
++
++.ltorg
++
+diff -Nurd u-boot-2009.03.orig/board/hipox/u-boot-arm11.lds u-boot-2009.03/board/hipox/u-boot-arm11.lds
+--- u-boot-2009.03.orig/board/hipox/u-boot-arm11.lds   1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/u-boot-arm11.lds        2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,50 @@
++/*
++ * (C) Copyright 2002
++ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
++OUTPUT_ARCH(arm)
++ENTRY(_start)
++SECTIONS
++{
++      . = 0x00000000;
++      . = ALIGN(4);
++      .text   :
++      {
++        cpu/arm11/start.o     (.text)
++        *(.text)
++      }
++      .rodata : { *(.rodata) }
++      . = ALIGN(4);
++      .data : { *(.data) }
++      . = ALIGN(4);
++      .got : { *(.got) }
++
++      __u_boot_cmd_start = .;
++      .u_boot_cmd : { *(.u_boot_cmd) }
++      __u_boot_cmd_end = .;
++
++      . = ALIGN(4);
++      __bss_start = .;
++      .bss : { *(.bss) }
++      _end = .;
++}
+diff -Nurd u-boot-2009.03.orig/board/hipox/u-boot-arm926ejs.lds u-boot-2009.03/board/hipox/u-boot-arm926ejs.lds
+--- u-boot-2009.03.orig/board/hipox/u-boot-arm926ejs.lds       1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/board/hipox/u-boot-arm926ejs.lds    2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,50 @@
++/*
++ * (C) Copyright 2002
++ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
++OUTPUT_ARCH(arm)
++ENTRY(_start)
++SECTIONS
++{
++      . = 0x00000000;
++      . = ALIGN(4);
++      .text   :
++      {
++        cpu/arm926ejs/start.o (.text)
++        *(.text)
++      }
++      .rodata : { *(.rodata) }
++      . = ALIGN(4);
++      .data : { *(.data) }
++      . = ALIGN(4);
++      .got : { *(.got) }
++
++      __u_boot_cmd_start = .;
++      .u_boot_cmd : { *(.u_boot_cmd) }
++      __u_boot_cmd_end = .;
++
++      . = ALIGN(4);
++      __bss_start = .;
++      .bss : { *(.bss) }
++      _end = .;
++}
+diff -Nurd u-boot-2009.03.orig/common/cmd_ide.c u-boot-2009.03/common/cmd_ide.c
+--- u-boot-2009.03.orig/common/cmd_ide.c       2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/common/cmd_ide.c    2009-04-15 11:08:18.000000000 +0200
+@@ -165,6 +165,13 @@
+ #define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
++#ifdef CONFIG_HIPOX
++extern unsigned char ide_inb(int dev, int port);
++extern void ide_outb(int dev, int port, unsigned char val);
++extern void hipox_sata_output_data(int dev, ulong *sect_buf, int words);
++extern void hipox_sata_input_data(int dev, ulong *sect_buf, int words);
++#endif // CONFIG_HIPOX
++
+ static void input_data(int dev, ulong *sect_buf, int words);
+ static void output_data(int dev, ulong *sect_buf, int words);
+ static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
+@@ -525,6 +532,7 @@
+ /* ------------------------------------------------------------------------- */
++#ifndef CONFIG_HIPOX
+ void inline
+ __ide_outb(int dev, int port, unsigned char val)
+ {
+@@ -546,6 +554,7 @@
+ }
+ unsigned char inline ide_inb(int dev, int port)
+                       __attribute__((weak, alias("__ide_inb")));
++#endif
+ #ifdef CONFIG_TUNE_PIO
+ int inline
+@@ -965,7 +974,11 @@
+ static void
+ output_data(int dev, ulong *sect_buf, int words)
+ {
++#ifdef CONFIG_HIPOX
++      hipox_sata_output_data(dev, sect_buf, words);
++#else
+       outsw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, words<<1);
++#endif
+ }
+ #endif        /* __PPC__ */
+@@ -1023,7 +1036,11 @@
+ static void
+ input_data(int dev, ulong *sect_buf, int words)
+ {
++#ifdef CONFIG_HIPOX
++      hipox_sata_input_data(dev, sect_buf, words);
++#else
+       insw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, words << 1);
++#endif
+ }
+ #endif        /* __PPC__ */
+diff -Nurd u-boot-2009.03.orig/common/main.c u-boot-2009.03/common/main.c
+--- u-boot-2009.03.orig/common/main.c  2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/common/main.c       2009-04-15 11:08:18.000000000 +0200
+@@ -48,7 +48,7 @@
+  * Board-specific Platform code can reimplement show_boot_progress () if needed
+  */
+ void inline __show_boot_progress (int val) {}
+-void inline show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress")));
++void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress")));
+ #if defined(CONFIG_BOOT_RETRY_TIME) && defined(CONFIG_RESET_TO_RETRY)
+ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);             /* for do_reset() prototype */
+diff -Nurd u-boot-2009.03.orig/cpu/arm926ejs/interrupts.c u-boot-2009.03/cpu/arm926ejs/interrupts.c
+--- u-boot-2009.03.orig/cpu/arm926ejs/interrupts.c     2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/cpu/arm926ejs/interrupts.c  2009-04-15 11:08:18.000000000 +0200
+@@ -38,20 +38,312 @@
+ #include <common.h>
+ #include <arm926ejs.h>
++#include <asm/proc-armv/ptrace.h>
++
++extern void reset_cpu(ulong addr);
++
++#ifdef CONFIG_HIPOX
++#define TIMER_LOAD_VAL 0xffffUL
++#else // CONFIG_HIPOX
++#define TIMER_LOAD_VAL 0xffffffff
++#endif // CONFIG_HIPOX
++
++/* macro to read the 32 bit timer */
++#ifdef CONFIG_OMAP
++#define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_TIMERBASE+8))
++#endif
+ #ifdef CONFIG_INTEGRATOR
++#define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_TIMERBASE+4))
++#endif
++#ifdef CONFIG_VERSATILE
++#define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_TIMERBASE+4))
++#endif
++#ifdef CONFIG_HIPOX
++#define READ_TIMER ((*(volatile ushort *)(CONFIG_SYS_TIMERBASE+4)) & 0xFFFFUL)  /* RPS timer value register has only 16 defined bits */
++#endif
++
++#ifdef CONFIG_USE_IRQ
++/* enable IRQ interrupts */
++void enable_interrupts (void)
++{
++      unsigned long temp;
++      __asm__ __volatile__("mrs %0, cpsr\n"
++                           "bic %0, %0, #0x80\n"
++                           "msr cpsr_c, %0"
++                           : "=r" (temp)
++                           :
++                           : "memory");
++}
+-      /* Timer functionality supplied by Integrator board (AP or CP) */
++/*
++ * disable IRQ/FIQ interrupts
++ * returns true if interrupts had been enabled before we disabled them
++ */
++int disable_interrupts (void)
++{
++      unsigned long old,temp;
++      __asm__ __volatile__("mrs %0, cpsr\n"
++                           "orr %1, %0, #0xc0\n"
++                           "msr cpsr_c, %1"
++                           : "=r" (old), "=r" (temp)
++                           :
++                           : "memory");
++      return (old & 0x80) == 0;
++}
+ #else
++void enable_interrupts (void)
++{
++      return;
++}
++int disable_interrupts (void)
++{
++      return 0;
++}
++#endif
++
++
++void bad_mode (void)
++{
++      panic ("Resetting CPU ...\n");
++      reset_cpu (0);
++}
++
++void show_regs (struct pt_regs *regs)
++{
++      unsigned long flags;
++      const char *processor_modes[] = {
++      "USER_26",      "FIQ_26",       "IRQ_26",       "SVC_26",
++      "UK4_26",       "UK5_26",       "UK6_26",       "UK7_26",
++      "UK8_26",       "UK9_26",       "UK10_26",      "UK11_26",
++      "UK12_26",      "UK13_26",      "UK14_26",      "UK15_26",
++      "USER_32",      "FIQ_32",       "IRQ_32",       "SVC_32",
++      "UK4_32",       "UK5_32",       "UK6_32",       "ABT_32",
++      "UK8_32",       "UK9_32",       "UK10_32",      "UND_32",
++      "UK12_32",      "UK13_32",      "UK14_32",      "SYS_32",
++      };
++
++      flags = condition_codes (regs);
++
++      printf ("pc : [<%08lx>]    lr : [<%08lx>]\n"
++              "sp : %08lx  ip : %08lx  fp : %08lx\n",
++              instruction_pointer (regs),
++              regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
++      printf ("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
++              regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
++      printf ("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
++              regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
++      printf ("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
++              regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
++      printf ("Flags: %c%c%c%c",
++              flags & CC_N_BIT ? 'N' : 'n',
++              flags & CC_Z_BIT ? 'Z' : 'z',
++              flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v');
++      printf ("  IRQs %s  FIQs %s  Mode %s%s\n",
++              interrupts_enabled (regs) ? "on" : "off",
++              fast_interrupts_enabled (regs) ? "on" : "off",
++              processor_modes[processor_mode (regs)],
++              thumb_mode (regs) ? " (T)" : "");
++}
++
++void do_undefined_instruction (struct pt_regs *pt_regs)
++{
++      printf ("undefined instruction\n");
++      show_regs (pt_regs);
++      bad_mode ();
++}
++
++void do_software_interrupt (struct pt_regs *pt_regs)
++{
++      printf ("software interrupt\n");
++      show_regs (pt_regs);
++      bad_mode ();
++}
++
++void do_prefetch_abort (struct pt_regs *pt_regs)
++{
++      printf ("prefetch abort\n");
++      show_regs (pt_regs);
++      bad_mode ();
++}
++
++void do_data_abort (struct pt_regs *pt_regs)
++{
++      printf ("data abort\n");
++      show_regs (pt_regs);
++      bad_mode ();
++}
++
++void do_not_used (struct pt_regs *pt_regs)
++{
++      printf ("not used\n");
++      show_regs (pt_regs);
++      bad_mode ();
++}
++
++void do_fiq (struct pt_regs *pt_regs)
++{
++      printf ("fast interrupt request\n");
++      show_regs (pt_regs);
++      bad_mode ();
++}
++
++void do_irq (struct pt_regs *pt_regs)
++{
++      printf ("interrupt request\n");
++      show_regs (pt_regs);
++      bad_mode ();
++}
++
++static ulong timestamp;
++static ulong lastdec;
+ /* nothing really to do with interrupts, just starts up a counter. */
+ int interrupt_init (void)
+ {
+-      extern void timer_init(void);
++#ifdef CONFIG_OMAP
++      int32_t val;
+-      timer_init();
++      /* Start the decrementer ticking down from 0xffffffff */
++      *((int32_t *) (CONFIG_SYS_TIMERBASE + LOAD_TIM)) = TIMER_LOAD_VAL;
++      val = MPUTIM_ST | MPUTIM_AR | MPUTIM_CLOCK_ENABLE | (CONFIG_SYS_PVT << MPUTIM_PTV_BIT);
++      *((int32_t *) (CONFIG_SYS_TIMERBASE + CNTL_TIMER)) = val;
++#endif        /* CONFIG_OMAP */
++#ifdef CONFIG_INTEGRATOR
++      /* Load timer with initial value */
++      *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0) = TIMER_LOAD_VAL;
++      /* Set timer to be enabled, free-running, no interrupts, 256 divider */
++      *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = 0x8C;
++#endif        /* CONFIG_INTEGRATOR */
++#ifdef CONFIG_VERSATILE
++      *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0) = CONFIG_SYS_TIMER_RELOAD;        /* TimerLoad */
++      *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 4) = CONFIG_SYS_TIMER_RELOAD;        /* TimerValue */
++      *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = 0x8C;
++#endif        /* CONFIG_VERSATILE */
++#ifdef CONFIG_HIPOX
++    // Setup timer 1 load value
++    *(volatile ulong*)(CONFIG_SYS_TIMERBASE + 0) = TIMER_LOAD_VAL;
+-      return 0;
++    // Setup timer 1 prescaler, periodic operation and start it
++    *(volatile ulong*)(CONFIG_SYS_TIMERBASE + 8) =
++        (TIMER_PRESCALE_ENUM << TIMER_PRESCALE_BIT) |
++        (TIMER_MODE_PERIODIC << TIMER_MODE_BIT) |
++        (TIMER_ENABLE_ENABLE << TIMER_ENABLE_BIT);
++#endif        /* CONFIG_HIPOX */
++
++      /* init the timestamp and lastdec value */
++      reset_timer_masked();
++
++      return (0);
+ }
+-#endif /* CONFIG_INTEGRATOR */
++/*
++ * timer without interrupts
++ */
++
++void reset_timer (void)
++{
++      reset_timer_masked ();
++}
++
++ulong get_timer (ulong base)
++{
++      return get_timer_masked () - base;
++}
++
++void set_timer (ulong t)
++{
++      timestamp = t;
++}
++
++/* delay x useconds AND perserve advance timstamp value */
++void udelay (unsigned long usec)
++{
++      ulong tmo, tmp;
++
++      if(usec >= 1000){               /* if "big" number, spread normalization to seconds */
++              tmo = usec / 1000;      /* start to normalize for usec to ticks per sec */
++              tmo *= CONFIG_SYS_HZ;          /* find number of "ticks" to wait to achieve target */
++              tmo /= 1000;            /* finish normalize. */
++      }else{                          /* else small number, don't kill it prior to HZ multiply */
++              tmo = usec * CONFIG_SYS_HZ;
++              tmo /= (1000*1000);
++      }
++
++      tmp = get_timer (0);            /* get current timestamp */
++      if( (tmo + tmp + 1) < tmp )     /* if setting this fordward will roll time stamp */
++              reset_timer_masked ();  /* reset "advancing" timestamp to 0, set lastdec value */
++      else
++              tmo += tmp;             /* else, set advancing stamp wake up time */
++
++      while (get_timer_masked () < tmo)/* loop till event */
++              /*NOP*/;
++}
++
++void reset_timer_masked (void)
++{
++      /* reset time */
++      lastdec = READ_TIMER;  /* capure current decrementer value time */
++      timestamp = 0;         /* start "advancing" time stamp from 0 */
++}
++
++ulong get_timer_masked (void)
++{
++      ulong now = READ_TIMER;         /* current tick value */
++
++      if (lastdec >= now) {           /* normal mode (non roll) */
++              /* normal mode */
++              timestamp += lastdec - now; /* move stamp fordward with absoulte diff ticks */
++      } else {                        /* we have overflow of the count down timer */
++              /* nts = ts + ld + (TLV - now)
++               * ts=old stamp, ld=time that passed before passing through -1
++               * (TLV-now) amount of time after passing though -1
++               * nts = new "advancing time stamp"...it could also roll and cause problems.
++               */
++              timestamp += lastdec + TIMER_LOAD_VAL - now;
++      }
++      lastdec = now;
++
++      return timestamp;
++}
++
++/* waits specified delay value and resets timestamp */
++void udelay_masked (unsigned long usec)
++{
++      ulong tmo;
++
++      if(usec >= 1000){               /* if "big" number, spread normalization to seconds */
++              tmo = usec / 1000;      /* start to normalize for usec to ticks per sec */
++              tmo *= CONFIG_SYS_HZ;          /* find number of "ticks" to wait to achieve target */
++              tmo /= 1000;            /* finish normalize. */
++      }else{                          /* else small number, don't kill it prior to HZ multiply */
++              tmo = usec * CONFIG_SYS_HZ;
++              tmo /= (1000*1000);
++      }
++
++      reset_timer_masked ();  /* set "advancing" timestamp to 0, set lastdec vaule */
++
++      while (get_timer_masked () < tmo) /* wait for time stamp to overtake tick number.*/
++              /*NOP*/;
++}
++
++/*
++ * This function is derived from PowerPC code (read timebase as long long).
++ * On ARM it just returns the timer value.
++ */
++unsigned long long get_ticks(void)
++{
++      return get_timer(0);
++}
++
++/*
++ * This function is derived from PowerPC code (timebase clock frequency).
++ * On ARM it returns the number of timer ticks per second.
++ */
++ulong get_tbclk (void)
++{
++      ulong tbclk;
++
++      tbclk = CONFIG_SYS_HZ;
++      return tbclk;
++}
+diff -Nurd u-boot-2009.03.orig/cpu/arm926ejs/start.S u-boot-2009.03/cpu/arm926ejs/start.S
+--- u-boot-2009.03.orig/cpu/arm926ejs/start.S  2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/cpu/arm926ejs/start.S       2009-04-15 11:08:18.000000000 +0200
+@@ -94,6 +94,11 @@
+ _TEXT_BASE:
+       .word   TEXT_BASE
++#ifdef CONFIG_HIPOX
++_EXCEPTION_BASE:
++      .word   EXCEPTION_BASE
++#endif
++
+ .globl _armboot_start
+ _armboot_start:
+       .word _start
+@@ -135,6 +140,18 @@
+       orr     r0,r0,#0xd3
+       msr     cpsr,r0
++#ifdef CONFIG_HIPOX
++      /*
++       * Copy exception table to relocated address in internal SRAM
++       */
++      adr     r0, _start                              /* Address of exception table in flash */
++      ldr     r1, _EXCEPTION_BASE             /* Relocated address of exception table */
++      ldmia   r0!, {r3-r10}           /* Copy exception table and jump values from */
++      stmia   r1!, {r3-r10}           /* FLASH to relocated address */
++      ldmia   r0!, {r3-r10}
++      stmia   r1!, {r3-r10}
++#endif
++
+       /*
+        * we do sys-critical inits only at reboot,
+        * not when booting from ram!
+diff -Nurd u-boot-2009.03.orig/drivers/mtd/cfi_flash.c u-boot-2009.03/drivers/mtd/cfi_flash.c
+--- u-boot-2009.03.orig/drivers/mtd/cfi_flash.c        2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/drivers/mtd/cfi_flash.c     2009-04-15 11:08:18.000000000 +0200
+@@ -1883,6 +1883,7 @@
+               /* Do manufacturer-specific fixups */
+               switch (info->manufacturer_id) {
+               case 0x0001:
++              case 0x00da: // Winbond
+                       flash_fixup_amd(info, &qry);
+                       break;
+               case 0x001f:
+diff -Nurd u-boot-2009.03.orig/drivers/mtd/cfi_mtd.c u-boot-2009.03/drivers/mtd/cfi_mtd.c
+--- u-boot-2009.03.orig/drivers/mtd/cfi_mtd.c  2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/drivers/mtd/cfi_mtd.c       2009-04-15 11:08:18.000000000 +0200
+@@ -141,22 +141,12 @@
+       int sect_size = 0;
+       int sect;
++      /*
++              * Select the largest sector size as erasesize (e.g. for UBI)
++      */
+       for (sect = 0; sect < fi->sector_count; sect++) {
+-              if (!sect_size) {
++              if (flash_sector_size(fi, sect) > sect_size)
+                       sect_size = flash_sector_size(fi, sect);
+-                      continue;
+-              }
+-
+-              if (sect_size != flash_sector_size(fi, sect)) {
+-                      sect_size = 0;
+-                      break;
+-              }
+-      }
+-
+-      if (!sect_size) {
+-              puts("cfi-mtd: devices with multiple sector sizes are"
+-                                                      "not supported\n");
+-              return -EINVAL;
+       }
+       mtd->erasesize = sect_size;
+diff -Nurd u-boot-2009.03.orig/drivers/mtd/nand/nand_base.c u-boot-2009.03/drivers/mtd/nand/nand_base.c
+--- u-boot-2009.03.orig/drivers/mtd/nand/nand_base.c   2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/drivers/mtd/nand/nand_base.c        2009-04-15 11:08:18.000000000 +0200
+@@ -50,14 +50,14 @@
+ #include <linux/leds.h>
+ #include <asm/io.h>
+-#ifdef CONFIG_MTD_PARTITIONS
+-#include <linux/mtd/partitions.h>
+-#endif
+-
+ #endif
+ #include <common.h>
++#ifdef CONFIG_MTD_PARTITIONS
++#include <linux/mtd/partitions.h>
++#endif
++
+ #define ENOTSUPP      524     /* Operation is not supported */
+ #include <malloc.h>
+diff -Nurd u-boot-2009.03.orig/include/asm-arm/mach-types.h u-boot-2009.03/include/asm-arm/mach-types.h
+--- u-boot-2009.03.orig/include/asm-arm/mach-types.h   2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/include/asm-arm/mach-types.h        2009-04-15 11:08:18.000000000 +0200
+@@ -1990,6 +1990,7 @@
+ #define MACH_TYPE_BLAZE                2004
+ #define MACH_TYPE_LINKSTATION_LS_HGL   2005
+ #define MACH_TYPE_HTCVENUS             2006
++#define MACH_TYPE_HIPOX                2151
+ #ifdef CONFIG_ARCH_EBSA110
+ # ifdef machine_arch_type
+@@ -25727,6 +25728,19 @@
+ # define machine_is_htcvenus()        (0)
+ #endif
++#ifdef CONFIG_MACH_HIPOX
++# ifdef machine_arch_type
++#  undef machine_arch_type
++#  define machine_arch_type   __machine_arch_type
++# else
++#  define machine_arch_type   MACH_TYPE_HIPOX
++# endif
++# define machine_is_hipox()   (machine_arch_type == MACH_TYPE_HIPOX)
++#else
++# define machine_is_hipox()   (0)
++#endif
++
++
+ /*
+  * These have not yet been registered
+  */
+diff -Nurd u-boot-2009.03.orig/include/asm-arm/u-boot.h u-boot-2009.03/include/asm-arm/u-boot.h
+--- u-boot-2009.03.orig/include/asm-arm/u-boot.h       2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/include/asm-arm/u-boot.h    2009-04-15 11:08:18.000000000 +0200
+@@ -48,6 +48,9 @@
+       ulong start;
+       ulong size;
+     }                 bi_dram[CONFIG_NR_DRAM_BANKS];
++   unsigned long  bi_sramstart;  /* start of SRAM memory */
++   unsigned long  bi_sramsize;   /* size   of SRAM memory */
++
+ #ifdef CONFIG_HAS_ETH1
+     /* second onboard ethernet port */
+     unsigned char   bi_enet1addr[6];
+diff -Nurd u-boot-2009.03.orig/include/ata.h u-boot-2009.03/include/ata.h
+--- u-boot-2009.03.orig/include/ata.h  2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/include/ata.h       2009-04-15 11:08:18.000000000 +0200
+@@ -82,7 +82,11 @@
+ /*
+  * Device / Head Register Bits
+  */
++#ifdef CONFIG_HIPOX
++#define ATA_DEVICE(x) (0)
++#else
+ #define ATA_DEVICE(x) ((x & 1)<<4)
++#endif
+ #define ATA_LBA               0xE0
+ /*
+diff -Nurd u-boot-2009.03.orig/include/configs/hipox.h u-boot-2009.03/include/configs/hipox.h
+--- u-boot-2009.03.orig/include/configs/hipox.h        1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2009.03/include/configs/hipox.h     2009-04-15 11:08:18.000000000 +0200
+@@ -0,0 +1,705 @@
++/*
++ * (C) Copyright 2005
++ * Oxford Semiconductor Ltd
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public 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
++
++//#define readb(p)  (*(volatile u8 *)(p))
++//#define readl(p)  (*(volatile u32 *)(p))
++//#define writeb(v, p) (*(volatile u8 *)(p)= (v))
++//#define writel(v, p) (*(volatile u32*)(p)=(v))
++
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DHCP
++#define CONFIG_CMD_DIAG
++#define CONFIG_CMD_PING
++
++/**
++ * Architecture
++ */
++#if (NAS_VERSION == 820)
++    #define CONFIG_ARM11        1
++#else
++    #define CONFIG_ARM926EJS    1
++#endif
++#define CONFIG_HIPOX        1
++#define CONFIG_HIPOX_ENABLE_PCI         /* Enables PCI clock and takes out of reset - needed if require access to static bus */
++#define CONFIG_HIPOX_FEEDBACK_PCI_CLKS  /* Feedback PCI clock out 3 to drive PCI core clock - needed if require access to static bus */
++#define CONFIG_HIPOX_MANUAL_STATIC_ARBITRATION
++#if (USE_SATA == 1)
++#define CONFIG_HIPOX_USE_SATA           /* Define to include support for SATA disks */
++#if (USE_SATA_ENV == 1)
++#define ENV_ON_SATA                     /* Define to have the U-Boot env. stored on SATA disk */
++#endif // USE_SATA_ENV
++#endif // USE_SATA
++#if (USE_FLASH == 0)
++#define CONFIG_SYS_NO_FLASH             /* Define to NOT include flash support on static bus*/
++#endif //USE_FLASH
++
++/* Won't be using any interrupts */
++#undef CONFIG_USE_IRQ
++
++/* Everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ
++
++#define CONFIG_SYS_HUSH_PARSER                1
++#define CONFIG_SYS_PROMPT_HUSH_PS2    "> "
++
++/* Miscellaneous configurable options */
++#define CONFIG_SYS_LONGHELP                           /* undef to save memory         */
++#ifdef CONFIG_SYS_HUSH_PARSER
++#define CONFIG_SYS_PROMPT             "$ "            /* Monitor Command Prompt */
++#else
++#define CONFIG_SYS_PROMPT             "# "            /* Monitor Command Prompt */
++#endif
++#define CONFIG_SYS_CBSIZE      256             /* Console I/O Buffer Size  */
++
++/* Print Buffer Size */
++#define CONFIG_SYS_PBSIZE      ((CONFIG_SYS_CBSIZE)+sizeof(CONFIG_SYS_PROMPT)+16)
++#define CONFIG_SYS_MAXARGS     16              /* max number of command args   */
++#define CONFIG_SYS_BARGSIZE    (CONFIG_SYS_CBSIZE)    /* Boot Argument Buffer Size    */
++
++#define CONFIG_CMDLINE_TAG          1   /* enable passing of ATAGs  */
++#define CONFIG_SETUP_MEMORY_TAGS    1
++#define CONFIG_MISC_INIT_R          1   /* call misc_init_r during start up */
++#define CONFIG_INITRD_TAG           1   /* allow initrd tag to be generated */
++
++/* May want to do some setup prior to relocation */
++//#define CONFIG_INIT_CRITICAL
++
++/* ARM specific late initialisation */
++#define BOARD_LATE_INIT
++
++/**
++ * Stack sizes
++ *
++ * The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE        (128*1024)  /* regular stack */
++#ifdef CONFIG_USE_IRQ
++#define CONFIG_STACKSIZE_IRQ    (4*1024)    /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ    (4*1024)    /* FIQ stack */
++#endif
++
++/**
++ * RAM
++ */
++#define CONFIG_NR_DRAM_BANKS    1           /* We have 1 bank of SDRAM */
++#define PHYS_SDRAM_1_PA         0x48000000  /* SDRAM Bank #1 */
++#if (NAS_VERSION == 810)
++#define PHYS_SDRAM_1_MAX_SIZE  (256 * 1024 * 1024)
++#endif // NAS_VERSION
++
++#if (NAS_VERSION == 820)
++#define PHYS_SDRAM_1_MAX_SIZE  (256 * 1024 * 1024)
++#endif // NAS_VERSION
++#define CONFIG_SYS_SRAM_BASE  ((PHYS_SDRAM_1_PA) + (PHYS_SDRAM_1_MAX_SIZE))
++
++#if (NAS_VERSION == 810)
++#define CONFIG_SYS_SRAM_SIZE                   (128 * 1024)
++#endif // NAS_VERSION
++
++#if (NAS_VERSION == 820)
++#define CONFIG_SYS_SRAM_SIZE                   (128 * 1024)
++#endif // NAS_VERSION
++
++#define INITIALISE_SDRAM
++
++#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1_PA
++#define CONFIG_SYS_MEMTEST_END  (CONFIG_SYS_MEMTEST_START + PHYS_SDRAM_1_MAX_SIZE)
++
++/*
++ * PLLSYS = ((PLLSYS_S << 0) | (PLLSYS_P << 4) | (PLLSYS_M << 16))
++ *
++ * Default S = 0
++ *               P = 6
++ *         M = 176 -> 733.33 MHz
++ */
++//#define OVERCLOCK 12583008  /* S=0, P=6, M=192 -> 800MHz */
++//#define OVERCLOCK 12845152  /* S=0, P=6, M=196 -> 816.66MHz */
++//#define OVERCLOCK 13107296  /* S=0, P=6, M=200 -> 833.33MHz */
++//#define OVERCLOCK 13631584  /* S=0, P=6, M=208 -> 866.66MHz */
++//#define OVERCLOCK 14155872  /* S=0, P=6, M=216 -> 900MHz */
++//#define OVERCLOCK 14680160  /* S=0, P=6, M=224 -> 933.33MHz */
++//#define OVERCLOCK 18350176  /* S=0, P=6, M=280 -> 1000MHz */
++
++/* Default location from which bootm etc will load */
++#define CONFIG_SYS_LOAD_ADDR   (PHYS_SDRAM_1_PA)
++
++/**
++ * Core addresses
++ */
++#define MAC_BASE_PA             0x40400000
++#define STATIC_CS0_BASE_PA      0x41000000
++#define STATIC_CS1_BASE_PA      0x41400000
++#define STATIC_CS2_BASE_PA      0x41800000
++#define STATIC_CONTROL_BASE_PA  0x41C00000
++#define SATA_DATA_BASE_PA       0x42000000
++
++#define APB_BRIDGE_A_BASE_PA    0x44000000
++#define APB_BRIDGE_B_BASE_PA    0x45000000
++
++#define GPIO_1_PA               ((APB_BRIDGE_A_BASE_PA) + 0x0)
++#define GPIO_2_PA               ((APB_BRIDGE_A_BASE_PA) + 0x100000)
++
++#define SYS_CONTROL_BASE_PA     ((APB_BRIDGE_B_BASE_PA) + 0x0)
++#define DMA_BASE_PA             ((APB_BRIDGE_B_BASE_PA) + 0x600000)
++#define RPS_BASE                ((APB_BRIDGE_B_BASE_PA) + 0x300000)
++
++/* Static bus registers */
++#define STATIC_CONTROL_VERSION  ((STATIC_CONTROL_BASE_PA) + 0x0)
++#define STATIC_CONTROL_BANK0    ((STATIC_CONTROL_BASE_PA) + 0x4)
++#define STATIC_CONTROL_BANK1    ((STATIC_CONTROL_BASE_PA) + 0x8)
++#define STATIC_CONTROL_BANK2    ((STATIC_CONTROL_BASE_PA) + 0xC)
++
++/* Clock to the ARM/DDR */
++#if (FPGA == 0)
++#define NOMINAL_ARMCLK  ((PLL400) / 2)
++#define NOMINAL_SYSCLK  ((PLL400) / 4)
++#else // !FPGA
++#define NOMINAL_ARMCLK  (FPGA_ARM_CLK)
++#define NOMINAL_SYSCLK  ((PLL400) / 4)
++#endif // !FPGA
++
++/**
++ * Timer
++ */
++#define CONFIG_SYS_TIMERBASE            ((RPS_BASE) + 0x200)
++#define TIMER_PRESCALE_BIT       2
++#define TIMER_PRESCALE_1_ENUM    0
++#define TIMER_PRESCALE_16_ENUM   1
++#define TIMER_PRESCALE_256_ENUM  2
++#define TIMER_MODE_BIT           6
++#define TIMER_MODE_FREE_RUNNING  0
++#define TIMER_MODE_PERIODIC      1
++#define TIMER_ENABLE_BIT         7
++#define TIMER_ENABLE_DISABLE     0
++#define TIMER_ENABLE_ENABLE      1
++
++#define TIMER_PRESCALE_ENUM      (TIMER_PRESCALE_256_ENUM)
++#define CONFIG_SYS_HZ                   ((RPSCLK) / 256)
++
++/**
++ * GPIO
++ */
++#define GPIO_1_OE       ((GPIO_1_PA) + 0x4)
++#define GPIO_1_SET_OE   ((GPIO_1_PA) + 0x1C)
++#define GPIO_1_CLR_OE   ((GPIO_1_PA) + 0x20)
++
++#define GPIO_1_SET   ((GPIO_1_PA) + 0x14)
++#define GPIO_1_CLR   ((GPIO_1_PA) + 0x18)
++
++#define GPIO_2_OE       ((GPIO_2_PA) + 0x4)
++#define GPIO_2_SET_OE   ((GPIO_2_PA) + 0x1C)
++#define GPIO_2_CLR_OE   ((GPIO_2_PA) + 0x20)
++
++#define GPIO_2_SET   ((GPIO_2_PA) + 0x14)
++#define GPIO_2_CLR   ((GPIO_2_PA) + 0x18)
++
++/**
++ * Serial Configuration
++ */
++#define EXT_UART_BASE       0x28000000
++
++#define UART_1_BASE (APB_BRIDGE_A_BASE_PA + 0x200000)
++#define UART_2_BASE (APB_BRIDGE_A_BASE_PA + 0x300000)
++#define UART_3_BASE (APB_BRIDGE_A_BASE_PA + 0x900000)
++#define UART_4_BASE (APB_BRIDGE_A_BASE_PA + 0xA00000)
++
++#define CONFIG_SYS_NS16550          1
++#define CONFIG_SYS_NS16550_SERIAL   1
++#define CONFIG_SYS_NS16550_REG_SIZE 1
++
++#if (USE_EXTERNAL_UART != 0)
++#define CONFIG_SYS_NS16550_CLK      16000000
++#define CONFIG_SYS_NS16550_COM1     (EXT_UART_BASE)
++#else // USE_EXTERNAL_UART
++#define CONFIG_SYS_NS16550_CLK      (NOMINAL_SYSCLK)
++#define USE_UART_FRACTIONAL_DIVIDER
++#if (INTERNAL_UART == 1)
++#define CONFIG_HIPOX_UART1
++#define CONFIG_SYS_NS16550_COM1     (UART_1_BASE)
++#elif (INTERNAL_UART == 2)
++#define CONFIG_HIPOX_UART2
++#define CONFIG_SYS_NS16550_COM1     (UART_2_BASE)
++#elif (INTERNAL_UART == 3)
++#define CONFIG_HIPOX_UART3
++#define CONFIG_SYS_NS16550_COM1     (UART_3_BASE)
++#else
++#define CONFIG_HIPOX_UART4
++#define CONFIG_SYS_NS16550_COM1     (UART_4_BASE)
++#endif // CONFIG_HIPOX_UART
++#endif // USE_EXTERNAL_UART
++
++#define CONFIG_CONS_INDEX    1
++#define CONFIG_BAUDRATE      115200
++#define CONFIG_SYS_BAUDRATE_TABLE   { 9600, 19200, 38400, 57600, 115200 }
++
++#ifdef CONFIG_HIPOX_USE_SATA
++
++#define CONFIG_CMD_FAT
++#define CONFIG_CMD_IDE
++#define CONFIG_CMD_EXT2
++
++// extern void hipox_sata_output_data(int dev, unsigned long *sect_buf, int words);
++// extern void hipox_sata_input_data(int dev, unsigned long *sect_buf, int words);
++
++#define outsw(p,d,l)       hipox_sata_output_data(p,d,l)
++#define insw(p,d,l)        hipox_sata_input_data(p,d,l)
++
++#endif
++
++#ifndef CONFIG_SYS_NO_FLASH
++
++// configure this for HIPOX with NAND-CS on GPIO33
++#undef CONFIG_HIPOX_NAND_GPIO33
++
++#define CONFIG_CMD_NAND
++#define CONFIG_CMD_JFFS2
++#define CONFIG_JFFS2_CMDLINE
++
++#define CONFIG_JFFS2_NAND 1
++#define CONFIG_JFFS2_NAND_OFF 0x800000
++#define CONFIG_JFFS2_NAND_SIZE 0x3800000
++#define CONFIG_JFFS2_NAND_DEV 0
++
++#endif
++
++// number of pages to duplicate to allow for erorros in NAND flash, 2 for SLC more for MLC
++#define       CONFIG_PAGE_REPLICATION 2
++// number of blocks to duplicate to allow for errors in NAND flash, 2 for SLC more for MLC
++#define       CONFIG_BLOCK_REPLICATION 2
++
++// space to allocate for kernel image, i.e. maximum kernel size
++#define       CONFIG_FLASH_KERNEL_SPACE       3 * 1024 * 1024 // 3MB
++
++
++/* This must be included AFTER the definition of CONFIG_COMMANDS */
++// #include <cmd_confdefs.h>
++
++/**
++ * Booting
++ */
++#if (LINUX_ROOT_RAIDED == 1)
++#define LINUX_ROOT_DEVICE "root=/dev/md1"
++#else
++#define LINUX_ROOT_DEVICE "root=/dev/sda1"
++#endif
++
++#if 0
++#define CONFIG_BOOTARGS LINUX_ROOT_DEVICE " console=ttyS0,115200 elevator=cfq mac_adr=0x00,0x30,0xe0,0x00,0x00,0x01"
++#define CONFIG_BOOTDELAY      2
++#define CONFIG_BOOTCOMMAND    "run select0 load boot || run select0 load2 boot || run lightled select1 load extinguishled boot || run lightled select1 load2 extinguishled boot || lightled"
++#define CONFIG_EXTRA_ENV_SETTINGS \
++    "select0=ide dev 0\0" \
++    "select1=ide dev 1\0" \
++    "load=ide read 0x48500000 122 1644\0" \
++    "load2=ide read 0x48500000 e000 1644\0" \
++      "lightled=ledfail 1\0" \
++      "extinguishled=ledfail 0\0" \
++    "boot=bootm 48500000\0"
++#elif 0
++#define CONFIG_BOOTDELAY      2
++#define CONFIG_BOOTARGS "console=ttyS0,115200 elevator=cfq mac_adr=0x00,0x30,0xe0,0x00,0x00,0x01 root=ubi0:rootfs ubi.mtd=2,2048 rootfstype=ubifs"
++#define CONFIG_BOOTCOMMAND    "run boot"
++#define CONFIG_EXTRA_ENV_SETTINGS \
++    "boot=nboot 48500000 0 0 && bootm 48500000\0"
++#else
++#define CONFIG_BOOTDELAY      2
++#define CONFIG_BOOTCOMMAND    "bootm 0x41040000"
++#endif // CONFIG_HIPOX_USE_SATA
++
++//#define CONFIG_SHOW_BOOT_PROGRESS   1
++
++/**
++ * Networking
++ */
++#define CONFIG_ETHADDR      00:30:e0:00:00:01
++#define CONFIG_NETMASK      255.255.0.0
++#define CONFIG_IPADDR       172.31.0.128
++#define CONFIG_SERVERIP     172.31.0.100
++#define CONFIG_BOOTFILE     "uImage"
++#define CONFIG_SYS_AUTOLOAD        "n"
++#define CONFIG_NET_RETRY_COUNT 30
++
++/**
++ * Flash support
++ */
++#ifndef CONFIG_SYS_NO_FLASH
++
++#define CONFIG_SYS_FLASH_EMPTY_INFO
++
++#define CONFIG_SYS_FLASH_CFI
++#define CONFIG_FLASH_CFI_DRIVER
++#define CONFIG_FLASH_CFI_MTD
++#define CONFIG_MTD_PARTITIONS
++#define CONFIG_CMD_UBI
++#define CONFIG_RBTREE
++
++#define MTDIDS_DEFAULT "nand0=MT29FXX"
++#define MTDPARTS_DEFAULT   "mtdparts=MT29FXX:"  \
++                  "32m(boot),"  \
++                  "224m(system)"
++
++#define NUM_FLASH_MAIN_BLOCKS   63          /* For Intel 28F320B3T */
++#define NUM_FLASH_PARAM_BLOCKS  8           /* For Intel 28F320B3T */
++#define FLASH_MAIN_BLOCK_SIZE   (64*1024)   /* For Intel 28F320B3T family */
++#define FLASH_PARAM_BLOCK_SIZE  (8*1024)    /* For Intel 28F320B3T family */
++
++/* Assuming counts main blocks and parameter blocks, as the Intel/AMD detection */
++/* I'm intending to copy would seem to indicate */
++#define CONFIG_SYS_MAX_FLASH_SECT      (NUM_FLASH_MAIN_BLOCKS + NUM_FLASH_PARAM_BLOCKS)
++
++#define CONFIG_SYS_MAX_FLASH_BANKS     1           /* Assume counts flash devices */
++#define FLASH_BASE_OFF          0
++#define CONFIG_SYS_FLASH_BASE          ((STATIC_CS0_BASE_PA) + (FLASH_BASE_OFF))
++#define PHYS_FLASH_1            (CONFIG_SYS_FLASH_BASE)
++
++#define CONFIG_SYS_FLASH_ERASE_TOUT    (20*CONFIG_SYS_HZ)     /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT    (20*CONFIG_SYS_HZ)     /* Timeout for Flash Write */
++#define CONFIG_SYS_FLASH_WRITE_ATTEMPTS 5
++
++#define STATIC_BUS_FLASH_CONFIG 0x4f1f3f0d  /* fast ASIC settings, 70ns */
++
++#endif // !CONFIG_SYS_NO_FLASH
++
++/**
++ * Environment organization
++ */
++#ifdef ENV_ON_SATA
++
++/* Environment on SATA disk */
++#define SIZE_TO_SECTORS(x) ((x) / 512)
++#define CONFIG_ENV_IS_IN_DISK
++#define CONFIG_ENV_SIZE                       (8*1024)
++#define ENVIRONMENT_OFFSET            ((CONFIG_SYS_SRAM_SIZE) - (CONFIG_ENV_SIZE) - 1024)
++#define CONFIG_ENV_ADDR                       ((CONFIG_SYS_SRAM_BASE) + (ENVIRONMENT_OFFSET))
++#define ROM_LOADER_LOAD_START_SECTOR 1
++#define CONFIG_ENV_DISK_SECTOR        ((ROM_LOADER_LOAD_START_SECTOR) + SIZE_TO_SECTORS(ENVIRONMENT_OFFSET))
++#define ROM_LOADER_LOAD_REDUNDANT_START_SECTOR 10608
++#define CONFIG_ENV_DISK_REDUNDANT_SECTOR ((ROM_LOADER_LOAD_REDUNDANT_START_SECTOR) + SIZE_TO_SECTORS(ENVIRONMENT_OFFSET))
++
++#else // ENV_ON_SATA
++
++#if (USE_FLASH == 1)
++/** Flash based environment
++ *
++ *  It appears that all flash env start/size info. has to be pre-defined. How
++ *  this is supposed to work when the flash detection code could cope with all
++ *  sorts of different flash is hard to see.
++ *  It appears from the README that with bottom/top boot flashes with smaller
++ *  parameter blocks available, the environment code will only use a single
++ *  one of these smaller sectors for the environment, i.e. CONFIG__ENV_SECT_SIZE
++ *  is the size of the environment. I hope this isn't really true. The defines
++ *  below may well not work if this is the truth
++ */
++#define CONFIG_ENV_IS_IN_FLASH
++#endif // (USE_FLASH == 1)
++
++/* Environment in flash device parameter blocks */
++#define CONFIG_ENV_SECT_SIZE   (8*1024)
++/* First parameter block for environment */
++#define CONFIG_ENV_SIZE        CONFIG_ENV_SECT_SIZE
++/* Second parameter block for backup environment */
++#define CONFIG_ENV_SIZE_REDUND (CONFIG_ENV_SIZE)
++/* Main environment occupies first parameter block */
++#define CONFIG_ENV_ADDR        ((CONFIG_SYS_FLASH_BASE)+(NUM_FLASH_MAIN_BLOCKS)*(FLASH_MAIN_BLOCK_SIZE))
++/* Backup environment occupies second parameter block */
++#define CONFIG_ENV_ADDR_REDUND ((CONFIG_ENV_ADDR)+(CONFIG_ENV_SECT_SIZE))
++#endif
++
++#define CONFIG_ENV_OVERWRITE
++
++/* Magic number that indicates rebooting into upgrade mode */
++#define UPGRADE_MAGIC 0x31    /* ASCII '1' */
++
++/* Magic number that indicates user recovery on reboot */
++/* Also defined in hipox_user_recovery.agent */
++#define RECOVERY_MAGIC 0x31    /* ASCII '1' */
++
++/* Magic number that indicates controlled power down on reboot */
++/* Also defined in controlled_power_down.sh in init.d */
++#define CONTROLLED_POWER_DOWN_MAGIC 0x31  /* ASCII '1' */
++
++/* This flag is set in SRAM location by Co Proc */
++#define CONTROLLED_POWER_UP_MAGIC  0x31 /* ASCII '1' */
++/* 9k + a quad from top */
++/* Be carefule on changing the location of this flag
++ * u-boot has other things to write in SRAM too
++ */
++#define POWER_ON_FLAG_SRAM_OFFSET     9220
++#if (USE_LEON_TIME_COUNT == 1)
++#define MS_TIME_COUNT_SRAM_OFFSET     (POWER_ON_FLAG_SRAM_OFFSET + 4)
++#endif
++
++/* Size of malloc() pool */
++#define CONFIG_SYS_MALLOC_LEN      (2048 << 10)
++#define CONFIG_SYS_GBL_DATA_SIZE   128 /* size in bytes reserved for initial data */
++
++/**
++ * ASM startup control
++ */
++/* Start of address within SRAM of loader's exception table. */
++/* ROM-based exception table will redirect to here */
++#define EXCEPTION_BASE  (CONFIG_SYS_SRAM_BASE)
++
++/*
++ * NAND FLash support
++ */
++
++/*
++#define       NAND_ChipID_UNKNOWN     0
++#define       CFG_MAX_NAND_DEVICE     1
++#define       NAND_MAX_FLOORS 1
++#define       NAND_MAX_CHIPS  1
++#define       SECTORSIZE      (2 * 1024)
++#define       ADDR_COLUMN     1
++#define       ADDR_PAGE       2
++#define       ADDR_COLUMN_PAGE        3
++#define       CFG_NAND_BASE   STATIC_CS1_BASE_PA
++#define       NAND_WAIT_READY(nand)   udelay(25);
++#define       NAND_CTL_CLRALE(n)
++#define       NAND_CTL_SETALE(n)
++#define       NAND_CTL_CLRCLE(n)
++#define       NAND_CTL_SETCLE(n)
++#define       NAND_ENABLE_CE(n)
++#define       NAND_DISABLE_CE(n)
++#define       WRITE_NAND_COMMAND(d,adr)       *(volatile __u8 *)((unsigned long)adr + 0x4000) = (__u8)(d)
++#define       WRITE_NAND_ADDRESS(d,adr)       *(volatile __u8 *)((unsigned long)adr + 0x8000) = (__u8)(d)
++#define WRITE_NAND(d,adr)     *(volatile __u8 *)((unsigned long)adr) = (__u8)d
++#define READ_NAND(adr)        ((volatile unsigned char)(*(volatile __u8 *)(unsigned long)adr))
++*/
++#define       CONFIG_SYS_NAND_BASE    STATIC_CS0_BASE_PA
++#define       CONFIG_SYS_NAND_ADDRESS_LATCH   CONFIG_SYS_NAND_BASE + 0x8000
++#define       CONFIG_SYS_NAND_COMMAND_LATCH   CONFIG_SYS_NAND_BASE + 0x4000
++#define       CONFIG_SYS_MAX_NAND_DEVICE      1
++//#define     writeb(v,a)     *(volatile __u8 *)((unsigned long)a) = (__u8)v
++//#define     writew(v,a)     *(volatile __u16 *)((unsigned long)a) = (__u16)v
++//#define     readb(a)        ((volatile unsigned char)(*(volatile __u8 *)(unsigned long)a))
++//#define     readw(a)        ((volatile __u16)(*(volatile __u8 *)(unsigned long)a))
++// #define    show_boot_progress(n)
++
++/**
++ * Disk related stuff
++ */
++#define CONFIG_LBA48
++#define CONFIG_DOS_PARTITION
++#define CONFIG_SYS_IDE_MAXDEVICE   2
++#define CONFIG_SYS_IDE_MAXBUS      1
++#define CONFIG_IDE_PREINIT
++#undef CONFIG_IDE_RESET
++#undef CONFIG_IDE_LED
++#define CONFIG_SYS_ATA_BASE_ADDR SATA_DATA_BASE_PA
++#define CONFIG_SYS_ATA_DATA_OFFSET 0
++#define CONFIG_SYS_ATA_REG_OFFSET  0
++#define CONFIG_SYS_ATA_ALT_OFFSET  0
++
++/**
++ * System block reset and clock control
++ */
++#define SYS_CTRL_USB11_CTRL           (SYS_CONTROL_BASE_PA + 0x00)
++#define SYS_CTRL_PCI_CTRL0            (SYS_CONTROL_BASE_PA + 0x04)
++#define SYS_CTRL_PCI_CTRL1            (SYS_CONTROL_BASE_PA + 0x08)
++#define SYS_CTRL_GPIO_PRIMSEL_CTRL_0  (SYS_CONTROL_BASE_PA + 0x0C)
++#define SYS_CTRL_GPIO_PRIMSEL_CTRL_1  (SYS_CONTROL_BASE_PA + 0x10)
++#define SYS_CTRL_GPIO_SECSEL_CTRL_0   (SYS_CONTROL_BASE_PA + 0x14)
++#define SYS_CTRL_GPIO_SECSEL_CTRL_1   (SYS_CONTROL_BASE_PA + 0x18)
++#define SYS_CTRL_GPIO_TERTSEL_CTRL_0  (SYS_CONTROL_BASE_PA + 0x8C)
++#define SYS_CTRL_GPIO_TERTSEL_CTRL_1  (SYS_CONTROL_BASE_PA + 0x90)
++#define SYS_CTRL_USB11_STAT           (SYS_CONTROL_BASE_PA + 0x1c)
++#define SYS_CTRL_PCI_STAT             (SYS_CONTROL_BASE_PA + 0x20)
++#define SYS_CTRL_CKEN_SET_CTRL        (SYS_CONTROL_BASE_PA + 0x2C)
++#define SYS_CTRL_CKEN_CLR_CTRL        (SYS_CONTROL_BASE_PA + 0x30)
++#define SYS_CTRL_RSTEN_SET_CTRL       (SYS_CONTROL_BASE_PA + 0x34)
++#define SYS_CTRL_RSTEN_CLR_CTRL       (SYS_CONTROL_BASE_PA + 0x38)
++#define SYS_CTRL_PLLSYS_CTRL          (SYS_CONTROL_BASE_PA + 0x48)
++#define SYS_CTRL_PLLSYS_KEY_CTRL      (SYS_CONTROL_BASE_PA + 0x6C)
++#define SYS_CTRL_GMAC_CTRL            (SYS_CONTROL_BASE_PA + 0x78)
++#define SYS_CTRL_UART_CTRL            (SYS_CONTROL_BASE_PA + 0x94)
++
++#define SYS_CTRL_CKEN_COPRO_BIT  0
++#define SYS_CTRL_CKEN_DMA_BIT    1
++#define SYS_CTRL_CKEN_DPE_BIT    2
++#define SYS_CTRL_CKEN_DDR_BIT    3
++#define SYS_CTRL_CKEN_SATA_BIT   4
++#define SYS_CTRL_CKEN_I2S_BIT    5
++#define SYS_CTRL_CKEN_USBHS_BIT  6
++#define SYS_CTRL_CKEN_MAC_BIT    7
++#define SYS_CTRL_CKEN_PCI_BIT    8
++#define SYS_CTRL_CKEN_STATIC_BIT 9
++#define SYS_CTRL_CKEN_DDR_PHY_BIT 10
++
++#define SYS_CTRL_RSTEN_ARM_BIT          0
++#define SYS_CTRL_RSTEN_COPRO_BIT        1
++#define SYS_CTRL_RSTEN_USBHS_BIT        4
++#define SYS_CTRL_RSTEN_USBHSPHY_BIT     5
++#define SYS_CTRL_RSTEN_MAC_BIT          6
++#define SYS_CTRL_RSTEN_PCI_BIT          7
++#define SYS_CTRL_RSTEN_DMA_BIT          8
++#define SYS_CTRL_RSTEN_DPE_BIT          9
++#define SYS_CTRL_RSTEN_DDR_BIT          10
++#define SYS_CTRL_RSTEN_SATA_BIT         11
++#define SYS_CTRL_RSTEN_SATA_LINK_BIT    12
++#define SYS_CTRL_RSTEN_SATA_PHY_BIT     13
++#define SYS_CTRL_RSTEN_STATIC_BIT       15
++#define SYS_CTRL_RSTEN_GPIO_BIT         16
++#define SYS_CTRL_RSTEN_UART1_BIT        17
++#define SYS_CTRL_RSTEN_UART2_BIT        18
++#define SYS_CTRL_RSTEN_MISC_BIT         19
++#define SYS_CTRL_RSTEN_I2S_BIT          20
++#define SYS_CTRL_RSTEN_AHB_MON_BIT      21
++#define SYS_CTRL_RSTEN_UART3_BIT        22
++#define SYS_CTRL_RSTEN_UART4_BIT        23
++#define SYS_CTRL_RSTEN_SGDMA_BIT        24
++#define SYS_CTRL_RSTEN_DDR_PHY_BIT      25
++#define SYS_CTRL_RSTEN_BUS_BIT          31
++
++#define SYS_CTRL_GMAC_RGMII         2
++#define SYS_CTRL_GMAC_SIMPLE_MAX    1
++#define SYS_CTRL_GMAC_CKEN_GTX      0
++
++#define SYS_CTRL_CKCTRL_CTRL_ADDR     (SYS_CONTROL_BASE_PA + 0x64)
++
++#define SYS_CTRL_CKCTRL_PCI_DIV_BIT 0
++#define SYS_CTRL_CKCTRL_SLOW_BIT    8
++
++#define SYS_CTRL_UART2_DEQ_EN       0
++#define SYS_CTRL_UART3_DEQ_EN       1
++#define SYS_CTRL_UART3_IQ_EN        2
++#define SYS_CTRL_UART4_IQ_EN        3
++#define SYS_CTRL_UART4_NOT_PCI_MODE 4
++
++#define SYS_CTRL_PCI_CTRL1_PCI_STATIC_RQ_BIT 11
++
++/**
++ * SATA related definitions
++ */
++#define ATA_PORT_CTL        0
++#define ATA_PORT_FEATURE    1
++#define ATA_PORT_NSECT      2
++#define ATA_PORT_LBAL       3
++#define ATA_PORT_LBAM       4
++#define ATA_PORT_LBAH       5
++#define ATA_PORT_DEVICE     6
++#define ATA_PORT_COMMAND    7
++
++#define SATA_0_REGS_BASE    (APB_BRIDGE_B_BASE_PA + 0x900000)
++#define SATA_1_REGS_BASE    (APB_BRIDGE_B_BASE_PA + 0x910000)
++#define SATA_HOST_REGS_BASE (APB_BRIDGE_B_BASE_PA + 0x9e0000)
++
++/* The offsets to the SATA registers */
++#define SATA_ORB1_OFF           0
++#define SATA_ORB2_OFF           1
++#define SATA_ORB3_OFF           2
++#define SATA_ORB4_OFF           3
++#define SATA_ORB5_OFF           4
++
++#define SATA_FIS_ACCESS         11
++#define SATA_INT_STATUS_OFF     12  /* Read only */
++#define SATA_INT_CLR_OFF        12  /* Write only */
++#define SATA_INT_ENABLE_OFF     13  /* Read only */
++#define SATA_INT_ENABLE_SET_OFF 13  /* Write only */
++#define SATA_INT_ENABLE_CLR_OFF 14  /* Write only */
++#define SATA_VERSION_OFF        15
++#define SATA_CONTROL_OFF        23
++#define SATA_COMMAND_OFF        24
++#define SATA_PORT_CONTROL_OFF   25
++#define SATA_DRIVE_CONTROL_OFF  26
++
++/* The offsets to the link registers that are access in an asynchronous manner */
++#define SATA_LINK_DATA     28
++#define SATA_LINK_RD_ADDR  29
++#define SATA_LINK_WR_ADDR  30
++#define SATA_LINK_CONTROL  31
++
++/* SATA interrupt status register fields */
++#define SATA_INT_STATUS_EOC_RAW_BIT     ( 0 + 16)
++#define SATA_INT_STATUS_ERROR_BIT       ( 2 + 16)
++#define SATA_INT_STATUS_EOADT_RAW_BIT   ( 1 + 16)
++
++/* SATA core command register commands */
++#define SATA_CMD_WRITE_TO_ORB_REGS              2
++#define SATA_CMD_WRITE_TO_ORB_REGS_NO_COMMAND   4
++
++#define SATA_CMD_BUSY_BIT 7
++
++#define SATA_SCTL_CLR_ERR 0x00000316UL
++
++#define SATA_OPCODE_MASK 0x3
++
++#define SATA_LBAL_BIT    0
++#define SATA_LBAM_BIT    8
++#define SATA_LBAH_BIT    16
++#define SATA_HOB_LBAH_BIT 24
++#define SATA_DEVICE_BIT  24
++#define SATA_NSECT_BIT   0
++#define SATA_FEATURE_BIT 16
++#define SATA_COMMAND_BIT 24
++#define SATA_CTL_BIT     24
++
++/* ATA status (7) register field definitions */
++#define ATA_STATUS_BSY_BIT     7
++#define ATA_STATUS_DRDY_BIT    6
++#define ATA_STATUS_DF_BIT      5
++#define ATA_STATUS_DRQ_BIT     3
++#define ATA_STATUS_ERR_BIT     0
++
++/* ATA device (6) register field definitions */
++#define ATA_DEVICE_FIXED_MASK 0xA0
++#define ATA_DEVICE_DRV_BIT 4
++#define ATA_DEVICE_DRV_NUM_BITS 1
++#define ATA_DEVICE_LBA_BIT 6
++
++/* ATA control (0) register field definitions */
++#define ATA_CTL_SRST_BIT   2
++
++/* ATA Command register initiated commands */
++#define ATA_CMD_INIT    0x91
++#define ATA_CMD_IDENT   0xEC
++
++#define SATA_STD_ASYNC_REGS_OFF 0x20
++#define SATA_SCR_STATUS      0
++#define SATA_SCR_ERROR       1
++#define SATA_SCR_CONTROL     2
++#define SATA_SCR_ACTIVE      3
++#define SATA_SCR_NOTIFICAION 4
++
++#define SATA_BURST_BUF_FORCE_EOT_BIT        0
++#define SATA_BURST_BUF_DATA_INJ_ENABLE_BIT  1
++#define SATA_BURST_BUF_DIR_BIT              2
++#define SATA_BURST_BUF_DATA_INJ_END_BIT     3
++#define SATA_BURST_BUF_FIFO_DIS_BIT         4
++#define SATA_BURST_BUF_DIS_DREQ_BIT         5
++#define SATA_BURST_BUF_DREQ_BIT             6
++
++/* Button on GPIO 32 */
++#define RECOVERY_BUTTON         (0x00000001 << 0)
++#define RECOVERY_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_1
++#define RECOVERY_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_1
++#define RECOVERY_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_1
++#define RECOVERY_CLR_OE_REG     GPIO_2_CLR_OE
++#define RECOVERY_DEBOUNCE_REG   GPIO_2_INPUT_DEBOUNCE_ENABLE
++#define RECOVERY_DATA           GPIO_2_PA
++
++#endif // CONFIG_H
+diff -Nurd u-boot-2009.03.orig/lib_arm/board.c u-boot-2009.03/lib_arm/board.c
+--- u-boot-2009.03.orig/lib_arm/board.c        2009-04-15 11:05:24.000000000 +0200
++++ u-boot-2009.03/lib_arm/board.c     2009-04-15 11:08:18.000000000 +0200
+@@ -201,6 +201,10 @@
+       }
+       puts("DRAM:  ");
+       print_size(size, "\n");
++
++   puts("SRAM:  ");
++   printf("%ld KB at 0x%08lx\n", (long)(gd->bd->bi_sramsize >> 10),
++      (unsigned long)gd->bd->bi_sramstart);
+ #endif
+       return (0);
diff --git a/recipes/u-boot/u-boot_2009.03.bb b/recipes/u-boot/u-boot_2009.03.bb
new file mode 100644 (file)
index 0000000..11f2a0e
--- /dev/null
@@ -0,0 +1,20 @@
+PR = "r1"
+require u-boot.inc
+
+DEFAULT_PREFERENCE = "-1"
+DEFAULT_PREFERENCE_hipox = "1"
+
+SRC_URI = "ftp://ftp.denx.de/pub/u-boot/u-boot-${PV}.tar.bz2 "
+
+SRC_URI_append_hipox = "file://00-hipox.patch;patch=1 "
+
+TARGET_LDFLAGS = ""
+
+UBOOT_MACHINE_hipox  = "hipox_config"
+
+inherit base
+
+do_compile () {
+       oe_runmake ${UBOOT_MACHINE}
+       oe_runmake all
+}