summaryrefslogtreecommitdiff
path: root/recipes/u-boot/u-boot-2009.03/hipox
diff options
context:
space:
mode:
authorSteffen Sledz <sledz@dresearch.de>2009-04-15 14:59:55 +0200
committerSteffen Sledz <sledz@dresearch.de>2009-04-15 14:59:55 +0200
commit617ed6a71a2e445a937f5ac8c878d28f56d87889 (patch)
tree5f1136a86ee918de7235a1d97c47782ffd797614 /recipes/u-boot/u-boot-2009.03/hipox
parent883da3d9544c4340cd83cfe688b7551bbaf43ba4 (diff)
hipox: HIPOX machine uses u-boot-2009.03 for NOR/NAND combi boot
Diffstat (limited to 'recipes/u-boot/u-boot-2009.03/hipox')
-rw-r--r--recipes/u-boot/u-boot-2009.03/hipox/00-hipox.patch7034
1 files changed, 7034 insertions, 0 deletions
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
index 0000000000..fbb8039635
--- /dev/null
+++ b/recipes/u-boot/u-boot-2009.03/hipox/00-hipox.patch
@@ -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);