summaryrefslogtreecommitdiff
path: root/recipes/u-boot/u-boot-1.1.2/oxnas.patch
diff options
context:
space:
mode:
authorDenys Dmytriyenko <denis@denix.org>2009-03-17 14:32:59 -0400
committerDenys Dmytriyenko <denis@denix.org>2009-03-17 14:32:59 -0400
commit709c4d66e0b107ca606941b988bad717c0b45d9b (patch)
tree37ee08b1eb308f3b2b6426d5793545c38396b838 /recipes/u-boot/u-boot-1.1.2/oxnas.patch
parentfa6cd5a3b993f16c27de4ff82b42684516d433ba (diff)
rename packages/ to recipes/ per earlier agreement
See links below for more details: http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326 http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816 Signed-off-by: Denys Dmytriyenko <denis@denix.org> Acked-by: Mike Westerhof <mwester@dls.net> Acked-by: Philip Balister <philip@balister.org> Acked-by: Khem Raj <raj.khem@gmail.com> Acked-by: Marcin Juszkiewicz <hrw@openembedded.org> Acked-by: Koen Kooi <koen@openembedded.org> Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'recipes/u-boot/u-boot-1.1.2/oxnas.patch')
-rw-r--r--recipes/u-boot/u-boot-1.1.2/oxnas.patch7257
1 files changed, 7257 insertions, 0 deletions
diff --git a/recipes/u-boot/u-boot-1.1.2/oxnas.patch b/recipes/u-boot/u-boot-1.1.2/oxnas.patch
new file mode 100644
index 0000000000..f1fff14822
--- /dev/null
+++ b/recipes/u-boot/u-boot-1.1.2/oxnas.patch
@@ -0,0 +1,7257 @@
+diff -Nurd u-boot-1.1.2/board/oxnas/config.mk u-boot-1.1.2-oxe810/board/oxnas/config.mk
+--- u-boot-1.1.2/board/oxnas/config.mk 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/board/oxnas/config.mk 2008-06-11 17:55:18.000000000 +0200
+@@ -0,0 +1,26 @@
++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 ?= 64 # Memory size in megabytes if probing is not enabled
++MEM_ODT ?= 150
++
++USE_SATA ?= 1
++USE_SATA_ENV ?= 1
++USE_FLASH ?= 1
++
++LINUX_ROOT_RAIDED ?= 1
++
++USE_EXTERNAL_UART ?= 0
++INTERNAL_UART ?= 2
++
++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)
+diff -Nurd u-boot-1.1.2/board/oxnas/eth.c u-boot-1.1.2-oxe810/board/oxnas/eth.c
+--- u-boot-1.1.2/board/oxnas/eth.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/board/oxnas/eth.c 2008-06-11 17:55:18.000000000 +0200
+@@ -0,0 +1,1666 @@
++/*
++ * (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 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-1.1.2/board/oxnas/ide-810.c u-boot-1.1.2-oxe810/board/oxnas/ide-810.c
+--- u-boot-1.1.2/board/oxnas/ide-810.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/board/oxnas/ide-810.c 2008-06-11 17:55: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 oxnas_dma_mode {
++ OXNAS_DMA_MODE_FIXED,
++ OXNAS_DMA_MODE_INC
++} oxnas_dma_mode_t;
++
++typedef enum oxnas_dma_direction {
++ OXNAS_DMA_TO_DEVICE,
++ OXNAS_DMA_FROM_DEVICE
++} oxnas_dma_direction_t;
++
++/* The available buses to which the DMA controller is attached */
++typedef enum oxnas_dma_transfer_bus
++{
++ OXNAS_DMA_SIDE_A,
++ OXNAS_DMA_SIDE_B
++} oxnas_dma_transfer_bus_t;
++
++/* Direction of data flow between the DMA controller's pair of interfaces */
++typedef enum oxnas_dma_transfer_direction
++{
++ OXNAS_DMA_A_TO_A,
++ OXNAS_DMA_B_TO_A,
++ OXNAS_DMA_A_TO_B,
++ OXNAS_DMA_B_TO_B
++} oxnas_dma_transfer_direction_t;
++
++/* The available data widths */
++typedef enum oxnas_dma_transfer_width
++{
++ OXNAS_DMA_TRANSFER_WIDTH_8BITS,
++ OXNAS_DMA_TRANSFER_WIDTH_16BITS,
++ OXNAS_DMA_TRANSFER_WIDTH_32BITS
++} oxnas_dma_transfer_width_t;
++
++/* The mode of the DMA transfer */
++typedef enum oxnas_dma_transfer_mode
++{
++ OXNAS_DMA_TRANSFER_MODE_SINGLE,
++ OXNAS_DMA_TRANSFER_MODE_BURST
++} oxnas_dma_transfer_mode_t;
++
++/* The available transfer targets */
++typedef enum oxnas_dma_dreq
++{
++ OXNAS_DMA_DREQ_SATA = 0,
++ OXNAS_DMA_DREQ_MEMORY = 15
++} oxnas_dma_dreq_t;
++
++typedef struct oxnas_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;
++} oxnas_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 oxnas_dma_device_settings_t oxnas_sata_dma_settings = {
++ .address_ = SATA_DATA_BASE_PA,
++ .fifo_size_ = 16,
++ .dreq_ = OXNAS_DMA_DREQ_SATA,
++ .read_eot_ = 0,
++ .read_final_eot_ = 1,
++ .write_eot_ = 0,
++ .write_final_eot_ = 1,
++ .bus_ = OXNAS_DMA_SIDE_A,
++ .width_ = OXNAS_DMA_TRANSFER_WIDTH_32BITS,
++ .transfer_mode_ = OXNAS_DMA_TRANSFER_MODE_BURST,
++ .address_mode_ = OXNAS_DMA_MODE_FIXED,
++ .address_really_fixed_ = 0
++};
++
++oxnas_dma_device_settings_t oxnas_ram_dma_settings = {
++ .address_ = 0,
++ .fifo_size_ = 0,
++ .dreq_ = OXNAS_DMA_DREQ_MEMORY,
++ .read_eot_ = 1,
++ .read_final_eot_ = 1,
++ .write_eot_ = 1,
++ .write_final_eot_ = 1,
++ .bus_ = OXNAS_DMA_SIDE_B,
++ .width_ = OXNAS_DMA_TRANSFER_WIDTH_32BITS,
++ .transfer_mode_ = OXNAS_DMA_TRANSFER_MODE_BURST,
++ .address_mode_ = OXNAS_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[CFG_IDE_MAXDEVICE];
++
++#include <ata.h>
++
++unsigned char oxnas_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 (!(oxnas_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 oxnas_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("oxnas_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("oxnas_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(
++ oxnas_dma_device_settings_t* src_settings,
++ oxnas_dma_device_settings_t* dst_settings)
++{
++ unsigned long ctrl_status;
++ oxnas_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_ == OXNAS_DMA_SIDE_A) {
++ // Set the burst/single mode for bus A based on src device's settings
++ if (src_settings->transfer_mode_ == OXNAS_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_ == OXNAS_DMA_SIDE_A) {
++ direction = OXNAS_DMA_A_TO_A;
++ } else {
++ direction = OXNAS_DMA_A_TO_B;
++
++ // Set the burst/single mode for bus B based on dst device's settings
++ if (dst_settings->transfer_mode_ == OXNAS_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_ == OXNAS_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_ == OXNAS_DMA_SIDE_A) {
++ direction = OXNAS_DMA_B_TO_A;
++
++ // Set the burst/single mode for bus A based on dst device's settings
++ if (dst_settings->transfer_mode_ == OXNAS_DMA_TRANSFER_MODE_BURST) {
++ ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_A;
++ } else {
++ ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_A;
++ }
++ } else {
++ direction = OXNAS_DMA_B_TO_B;
++ }
++ }
++ ctrl_status |= (direction << DMA_CTRL_STATUS_DIR_SHIFT);
++
++ // Setup source address mode fixed or increment
++ if (src_settings->address_mode_ == OXNAS_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_ == OXNAS_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(
++ oxnas_dma_device_settings_t* src_settings,
++ oxnas_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
++ oxnas_dma_device_settings_t mem_settings = oxnas_ram_dma_settings;
++ mem_settings.address_ = (unsigned long)buffer;
++ mem_settings.address_mode_ = OXNAS_DMA_MODE_INC;
++
++ *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) = encode_control_status(&mem_settings, &oxnas_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) = oxnas_sata_dma_settings.address_;
++ *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BYTE_CNT) = encode_final_eot(&mem_settings, &oxnas_sata_dma_settings, num_bytes);
++
++ dma_start();
++}
++
++static void dma_start_read(ulong* buffer, int num_bytes)
++{
++ // Assemble complete memory settings
++ oxnas_dma_device_settings_t mem_settings = oxnas_ram_dma_settings;
++ mem_settings.address_ = (unsigned long)buffer;
++ mem_settings.address_mode_ = OXNAS_DMA_MODE_INC;
++
++ *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) = encode_control_status(&oxnas_sata_dma_settings, &mem_settings);
++ *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_SRC_ADR) = oxnas_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(&oxnas_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 oxnas_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("oxnas_sata_output_data() Wait for ATA no-error timed-out\n");
++ }
++}
++
++void oxnas_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("oxnas_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 (oxnas_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 < CFG_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 < CFG_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 */
++ oxnas_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 < CFG_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-1.1.2/board/oxnas/Makefile u-boot-1.1.2-oxe810/board/oxnas/Makefile
+--- u-boot-1.1.2/board/oxnas/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/board/oxnas/Makefile 2008-06-11 17:55: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 := oxnas.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-1.1.2/board/oxnas/oxnas.c u-boot-1.1.2-oxe810/board/oxnas/oxnas.c
+--- u-boot-1.1.2/board/oxnas/oxnas.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/board/oxnas/oxnas.c 2008-06-11 17:55:18.000000000 +0200
+@@ -0,0 +1,280 @@
++/*
++ * (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>
++
++#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_OXNAS;
++ 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_OXNAS_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_OXNAS_ENABLE_PCI
++
++#ifdef CONFIG_OXNAS_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_OXNAS_MANUAL_STATIC_ARBITRATION
++
++#ifdef CONFIG_OXNAS_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_OXNAS_FEEDBACK_PCI_CLKS
++
++#ifndef CFG_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 // !CFG_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_OXNAS_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_OXNAS_UART1
++
++#ifdef CONFIG_OXNAS_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_OXNAS_UART2
++
++#ifdef CONFIG_OXNAS_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_OXNAS_UART3
++
++#ifdef CONFIG_OXNAS_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_OXNAS_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 = CFG_SRAM_BASE;
++ gd->bd->bi_sramsize = CFG_SRAM_SIZE;
++
++ return 0;
++}
++
++int reset_cpu(void)
++{
++ 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);
++
++ return 0;
++}
+diff -Nurd u-boot-1.1.2/board/oxnas/platform-800.S u-boot-1.1.2-oxe810/board/oxnas/platform-800.S
+--- u-boot-1.1.2/board/oxnas/platform-800.S 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/board/oxnas/platform-800.S 2008-06-11 17:55: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 OXNAS_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, =OXNAS_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 // OXNAS_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-1.1.2/board/oxnas/platform-810.S u-boot-1.1.2-oxe810/board/oxnas/platform-810.S
+--- u-boot-1.1.2/board/oxnas/platform-810.S 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/board/oxnas/platform-810.S 2008-06-11 17:55:18.000000000 +0200
+@@ -0,0 +1,477 @@
++/*
++ * 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 &= 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-1.1.2/board/oxnas/u-boot.lds u-boot-1.1.2-oxe810/board/oxnas/u-boot.lds
+--- u-boot-1.1.2/board/oxnas/u-boot.lds 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/board/oxnas/u-boot.lds 2008-06-11 17:55: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-1.1.2/common/cmd_ext2.c u-boot-1.1.2-oxe810/common/cmd_ext2.c
+--- u-boot-1.1.2/common/cmd_ext2.c 2004-12-16 18:34:53.000000000 +0100
++++ u-boot-1.1.2-oxe810/common/cmd_ext2.c 2008-06-11 17:55:30.000000000 +0200
+@@ -223,7 +223,7 @@
+ PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part);
+
+ if (part != 0) {
+- if (get_partition_info (&dev_desc[dev], part, &info)) {
++ if (get_partition_info (dev_desc, part, &info)) {
+ printf ("** Bad partition %d **\n", part);
+ return(1);
+ }
+diff -Nurd u-boot-1.1.2/common/cmd_ide.c u-boot-1.1.2-oxe810/common/cmd_ide.c
+--- u-boot-1.1.2/common/cmd_ide.c 2004-12-31 10:32:50.000000000 +0100
++++ u-boot-1.1.2-oxe810/common/cmd_ide.c 2008-06-11 17:55:30.000000000 +0200
+@@ -193,6 +193,13 @@
+ static void set_pcmcia_timing (int pmode);
+ #endif
+
++#ifdef CONFIG_OXNAS
++extern unsigned char oxnas_sata_inb(int dev, int port);
++extern void oxnas_sata_outb(int dev, int port, unsigned char val);
++extern void oxnas_sata_output_data(int dev, ulong *sect_buf, int words);
++extern void oxnas_sata_input_data(int dev, ulong *sect_buf, int words);
++#endif // CONFIG_OXNAS
++
+ /* ------------------------------------------------------------------------- */
+
+ int do_ide (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+@@ -491,175 +498,103 @@
+ return rcode;
+ }
+
+-/* ------------------------------------------------------------------------- */
+
+-void ide_init (void)
++static int ide_probe(int device)
+ {
++ int found = 0;
++
++ /* Select device */
++ udelay(100000); /* 100 ms */
++ ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
++ udelay(100000); /* 100 ms */
+
+-#ifdef CONFIG_IDE_8xx_DIRECT
+- DECLARE_GLOBAL_DATA_PTR;
+- volatile immap_t *immr = (immap_t *)CFG_IMMR;
+- volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
+-#endif
+ unsigned char c;
+- int i, bus;
+-#ifdef CONFIG_AMIGAONEG3SE
+- unsigned int max_bus_scan;
+- unsigned int ata_reset_time;
+- char *s;
++ int i = 0;
++ do {
++ udelay(10000); /* 10 ms */
++
++ c = ide_inb(device, ATA_STATUS);
++ if (++i > (ATA_RESET_TIME * 100)) {
++ PRINTF("ide_probe() timeout\n");
++ ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */
++ return found;
++ }
++ if ((i >= 100) && ((i%100) == 0)) {
++ putc ('.');
++ }
++ } while (c & ATA_STAT_BUSY);
++
++ if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
++ PRINTF("ide_probe() status = 0x%02X ", c);
++#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */
++ } else if ((c & ATA_STAT_READY) == 0) {
++ PRINTF("ide_probe() status = 0x%02X ", c);
+ #endif
+-#ifdef CONFIG_IDE_8xx_PCCARD
+- extern int pcmcia_on (void);
+- extern int ide_devices_found; /* Initialized in check_ide_device() */
+-#endif /* CONFIG_IDE_8xx_PCCARD */
++ } else {
++ found = 1;
++ }
+
+-#ifdef CONFIG_IDE_PREINIT
+- extern int ide_preinit (void);
+- WATCHDOG_RESET();
++ return found;
++}
+
+- if (ide_preinit ()) {
+- puts ("ide_preinit failed\n");
++void ide_init(void)
++{
++ static int ide_init_called = 0;
++ int i, bus;
++
++ if (ide_init_called) {
+ return;
+ }
+-#endif /* CONFIG_IDE_PREINIT */
+-
+-#ifdef CONFIG_IDE_8xx_PCCARD
+- extern int pcmcia_on (void);
+- extern int ide_devices_found; /* Initialized in check_ide_device() */
++ ide_init_called = 1;
+
++#ifdef CONFIG_IDE_PREINIT
++ extern int ide_preinit(void);
+ WATCHDOG_RESET();
+
+- ide_devices_found = 0;
+- /* initialize the PCMCIA IDE adapter card */
+- pcmcia_on();
+- if (!ide_devices_found)
++ printf("Initialising disks\n");
++ if (ide_preinit()) {
++ puts ("ide_preinit failed\n");
+ return;
+- udelay (1000000); /* 1 s */
+-#endif /* CONFIG_IDE_8xx_PCCARD */
++ }
++#endif /* CONFIG_IDE_PREINIT */
+
+ WATCHDOG_RESET();
+
+-#ifdef CONFIG_IDE_8xx_DIRECT
+- /* Initialize PIO timing tables */
+- for (i=0; i <= IDE_MAX_PIO_MODE; ++i) {
+- pio_config_clk[i].t_setup = PCMCIA_MK_CLKS(pio_config_ns[i].t_setup,
+- gd->bus_clk);
+- pio_config_clk[i].t_length = PCMCIA_MK_CLKS(pio_config_ns[i].t_length,
+- gd->bus_clk);
+- pio_config_clk[i].t_hold = PCMCIA_MK_CLKS(pio_config_ns[i].t_hold,
+- gd->bus_clk);
+- PRINTF ("PIO Mode %d: setup=%2d ns/%d clk"
+- " len=%3d ns/%d clk"
+- " hold=%2d ns/%d clk\n",
+- i,
+- pio_config_ns[i].t_setup, pio_config_clk[i].t_setup,
+- pio_config_ns[i].t_length, pio_config_clk[i].t_length,
+- pio_config_ns[i].t_hold, pio_config_clk[i].t_hold);
+- }
+-#endif /* CONFIG_IDE_8xx_DIRECT */
+-
+ /* Reset the IDE just to be sure.
+ * Light LED's to show
+ */
+- ide_led ((LED_IDE1 | LED_IDE2), 1); /* LED's on */
+- ide_reset (); /* ATAPI Drives seems to need a proper IDE Reset */
+-
+-#ifdef CONFIG_IDE_8xx_DIRECT
+- /* PCMCIA / IDE initialization for common mem space */
+- pcmp->pcmc_pgcrb = 0;
+-
+- /* start in PIO mode 0 - most relaxed timings */
+- pio_mode = 0;
+- set_pcmcia_timing (pio_mode);
+-#endif /* CONFIG_IDE_8xx_DIRECT */
++ ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */
++ ide_reset(); /* ATAPI Drives seems to need a proper IDE Reset */
+
+ /*
+ * Wait for IDE to get ready.
+ * According to spec, this can take up to 31 seconds!
+ */
+-#ifndef CONFIG_AMIGAONEG3SE
+- for (bus=0; bus<CFG_IDE_MAXBUS; ++bus) {
+- int dev = bus * (CFG_IDE_MAXDEVICE / CFG_IDE_MAXBUS);
+-#else
+- s = getenv("ide_maxbus");
+- if (s)
+- max_bus_scan = simple_strtol(s, NULL, 10);
+- else
+- max_bus_scan = CFG_IDE_MAXBUS;
+-
+- for (bus=0; bus<max_bus_scan; ++bus) {
+- int dev = bus * (CFG_IDE_MAXDEVICE / max_bus_scan);
+-#endif
+-
+-#ifdef CONFIG_IDE_8xx_PCCARD
+- /* Skip non-ide devices from probing */
+- if ((ide_devices_found & (1 << bus)) == 0) {
+- ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
+- continue;
+- }
+-#endif
+- printf ("Bus %d: ", bus);
+-
+- ide_bus_ok[bus] = 0;
+-
+- /* Select device
+- */
+- udelay (100000); /* 100 ms */
+- ide_outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
+- udelay (100000); /* 100 ms */
+-#ifdef CONFIG_AMIGAONEG3SE
+- ata_reset_time = ATA_RESET_TIME;
+- s = getenv("ide_reset_timeout");
+- if (s) ata_reset_time = 2*simple_strtol(s, NULL, 10);
+-#endif
+- i = 0;
+- do {
+- udelay (10000); /* 10 ms */
+-
+- c = ide_inb (dev, ATA_STATUS);
+- i++;
+-#ifdef CONFIG_AMIGAONEG3SE
+- if (i > (ata_reset_time * 100)) {
+-#else
+- if (i > (ATA_RESET_TIME * 100)) {
+-#endif
+- puts ("** Timeout **\n");
+- ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
+-#ifdef CONFIG_AMIGAONEG3SE
+- /* If this is the second bus, the first one was OK */
+- if (bus != 0) {
+- ide_bus_ok[bus] = 0;
+- goto skip_bus;
+- }
+-#endif
+- return;
+- }
+- if ((i >= 100) && ((i%100)==0)) {
+- putc ('.');
+- }
+- } while (c & ATA_STAT_BUSY);
++ printf("Detecting SATA busses:\n");
++ for (bus=0; bus < CFG_IDE_MAXBUS; ++bus) {
++ printf("Bus %d: ", bus);
+
+- if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
+- puts ("not available ");
+- PRINTF ("Status = 0x%02X ", c);
+-#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */
+- } else if ((c & ATA_STAT_READY) == 0) {
+- puts ("not available ");
+- PRINTF ("Status = 0x%02X ", c);
+-#endif
+- } else {
+- puts ("OK ");
+- ide_bus_ok[bus] = 1;
+- }
+- WATCHDOG_RESET();
+- }
++ /* Try to discover if bus is present by probing first device on bus */
++ int device = bus * (CFG_IDE_MAXDEVICE / CFG_IDE_MAXBUS);
++ ide_bus_ok[bus] = ide_probe(device);
++ if (ide_bus_ok[bus]) {
++ puts("Found first device OK\n");
++ } else {
++ WATCHDOG_RESET();
++
++ /* Try second device on bus */
++ ide_bus_ok[bus] = ide_probe(++device);
++ if (ide_bus_ok[bus]) {
++ puts("Found second device OK\n");
++ } else {
++ puts("No devices found\n");
++ }
++ }
+
+-#ifdef CONFIG_AMIGAONEG3SE
+- skip_bus:
+-#endif
+- putc ('\n');
++ WATCHDOG_RESET();
++ }
+
+- ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
++ ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */
+
+ curr_device = -1;
+ for (i=0; i<CFG_IDE_MAXDEVICE; ++i) {
+@@ -675,13 +610,12 @@
+ ide_dev_desc[i].block_read=ide_read;
+ if (!ide_bus_ok[IDE_BUS(i)])
+ continue;
+- ide_led (led, 1); /* LED on */
++ ide_led(led, 1); /* LED on */
+ ide_ident(&ide_dev_desc[i]);
+- ide_led (led, 0); /* LED off */
++ ide_led(led, 0); /* LED off */
+ dev_print(&ide_dev_desc[i]);
+-/* ide_print (i); */
+ if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
+- init_part (&ide_dev_desc[i]); /* initialize partition type */
++ init_part(&ide_dev_desc[i]); /* initialize partition type */
+ if (curr_device < 0)
+ curr_device = i;
+ }
+@@ -689,6 +623,11 @@
+ WATCHDOG_RESET();
+ }
+
++int is_device_present(int device_number)
++{
++ return ide_dev_desc[device_number].part_type != PART_TYPE_UNKNOWN;
++}
++
+ /* ------------------------------------------------------------------------- */
+
+ block_dev_desc_t * ide_get_dev(int dev)
+@@ -798,6 +737,11 @@
+ EIEIO;
+ *((uchar *)(ATA_CURR_BASE(dev)+port)) = val;
+ }
++#elif defined(CONFIG_OXNAS)
++static void __inline__ ide_outb(int dev, int port, unsigned char val)
++{
++ oxnas_sata_outb(dev, port, val);
++}
+ #else /* ! __PPC__ */
+ static void __inline__
+ ide_outb(int dev, int port, unsigned char val)
+@@ -819,6 +763,11 @@
+ dev, port, (ATA_CURR_BASE(dev)+port), val);
+ return (val);
+ }
++#elif defined(CONFIG_OXNAS)
++static unsigned char __inline__ ide_inb(int dev, int port)
++{
++ return oxnas_sata_inb(dev, port);
++}
+ #else /* ! __PPC__ */
+ static unsigned char __inline__
+ ide_inb(int dev, int port)
+@@ -921,6 +870,11 @@
+ }
+ #endif /* CONFIG_HMI10 */
+ }
++#elif defined(CONFIG_OXNAS)
++static void output_data(int dev, ulong *sect_buf, int words)
++{
++ oxnas_sata_output_data(dev, sect_buf, words);
++}
+ #else /* ! __PPC__ */
+ static void
+ output_data(int dev, ulong *sect_buf, int words)
+@@ -968,6 +922,11 @@
+ }
+ #endif /* CONFIG_HMI10 */
+ }
++#elif defined(CONFIG_OXNAS)
++static void input_data(int dev, ulong *sect_buf, int words)
++{
++ oxnas_sata_input_data(dev, sect_buf, words);
++}
+ #else /* ! __PPC__ */
+ static void
+ input_data(int dev, ulong *sect_buf, int words)
+@@ -1001,10 +960,36 @@
+
+ /* -------------------------------------------------------------------------
+ */
++#ifdef CONFIG_OXNAS
++static void byte_swap_and_trim(char* buf)
++{
++ char *src = buf;
++
++ // Swap bytes in 16-bit words
++ while ((*src != '\0') && (*(src+1) != '\0')) {
++ char tmp = *(src+1);
++ *(src+1) = *src;
++ *src = tmp;
++ src += 2;
++ }
++
++ // Trim leading spaces
++ src = buf;
++ while (*src == ' ') {
++ ++src;
++ }
++ if (src != buf) {
++ memcpy(buf, src, strlen(src));
++ buf[strlen(buf) - (src-buf)] = '\0';
++ }
++}
++#endif // CONFIG_OXNAS
++
+ static void ide_ident (block_dev_desc_t *dev_desc)
+ {
+ ulong iobuf[ATA_SECTORWORDS];
+ unsigned char c;
++ unsigned int i;
+ hd_driveid_t *iop = (hd_driveid_t *)iobuf;
+
+ #ifdef CONFIG_AMIGAONEG3SE
+@@ -1023,6 +1008,10 @@
+ device=dev_desc->dev;
+ printf (" Device %d: ", device);
+
++ for ( i=0; i < ATA_SECTORWORDS; ++i) {
++ iobuf[i] = 0;
++ }
++
+ #ifdef CONFIG_AMIGAONEG3SE
+ s = getenv("ide_maxbus");
+ if (s) {
+@@ -1110,20 +1099,22 @@
+
+ input_swap_data (device, iobuf, ATA_SECTORWORDS);
+
+- ident_cpy (dev_desc->revision, iop->fw_rev, sizeof(dev_desc->revision));
+- ident_cpy (dev_desc->vendor, iop->model, sizeof(dev_desc->vendor));
+- ident_cpy (dev_desc->product, iop->serial_no, sizeof(dev_desc->product));
++ ident_cpy(dev_desc->revision, iop->fw_rev, sizeof(dev_desc->revision));
++ ident_cpy(dev_desc->vendor, iop->model, sizeof(dev_desc->vendor));
++ ident_cpy(dev_desc->product, iop->serial_no, sizeof(dev_desc->product));
++
+ #ifdef __LITTLE_ENDIAN
+ /*
+- * firmware revision and model number have Big Endian Byte
++ * firmware revision, model number and product have Big Endian Byte
+ * order in Word. Convert both to little endian.
+ *
+ * See CF+ and CompactFlash Specification Revision 2.0:
+ * 6.2.1.6: Identfy Drive, Table 39 for more details
+ */
+
+- strswab (dev_desc->revision);
+- strswab (dev_desc->vendor);
++ byte_swap_and_trim(dev_desc->revision);
++ byte_swap_and_trim(dev_desc->vendor);
++ byte_swap_and_trim(dev_desc->product);
+ #endif /* __LITTLE_ENDIAN */
+
+ if ((iop->config & 0x0080)==0x0080)
+diff -Nurd u-boot-1.1.2/common/cmd_ledfail.c u-boot-1.1.2-oxe810/common/cmd_ledfail.c
+--- u-boot-1.1.2/common/cmd_ledfail.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/common/cmd_ledfail.c 2008-06-11 17:55:30.000000000 +0200
+@@ -0,0 +1,58 @@
++
++#include <common.h>
++#include <command.h>
++
++#if (CONFIG_COMMANDS & CFG_CMD_LEDFAIL)
++#define FAILURE_LED (1 << (34-32))
++
++#define GPIO_B 0x44100000
++#define WARN_GPIO_OUT_REG (GPIO_B + 0x10)
++#define WARN_GPIO_OUT_ENABLE_SET (GPIO_B + 0x1C)
++#define WARN_GPIO_OUT_ENABLE_CLR (GPIO_B + 0x20)
++
++static void ledfail_light(void)
++{
++ printf("Light LED\n");
++ /* Light the failure LED - assumes active low drive */
++ u_int32_t led_state = *((volatile u_int32_t *)WARN_GPIO_OUT_REG);
++ led_state = led_state & ~FAILURE_LED;
++ *((volatile u_int32_t *)WARN_GPIO_OUT_REG) = led_state;
++
++ /* Enable GPIO for output */
++ *((volatile u_int32_t *)WARN_GPIO_OUT_ENABLE_SET) = FAILURE_LED;
++}
++
++static void ledfail_extinguish(void)
++{
++ printf("Extinguish LED\n");
++ /* Extinguish the failure LED - assumes active low drive */
++ u_int32_t led_state = *((volatile u_int32_t *)WARN_GPIO_OUT_REG);
++ led_state = led_state | FAILURE_LED;
++ *((volatile u_int32_t *)WARN_GPIO_OUT_REG) = led_state;
++
++ /* Clear the failure bit output enable in GPIO's */
++ *((volatile u_int32_t *)WARN_GPIO_OUT_ENABLE_CLR) = FAILURE_LED;
++}
++
++int do_ledfail(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
++{
++ if (argc != 2) {
++ printf ("Usage:\n%s\n", cmdtp->usage);
++ return 1;
++ }
++
++ ulong arg = simple_strtoul(argv[1], NULL, 10);
++ switch (arg) {
++ case 0:
++ ledfail_extinguish();
++ break;
++ case 1:
++ ledfail_light();
++ break;
++ }
++
++ return 0;
++}
++
++U_BOOT_CMD(ledfail, 2, 2, do_ledfail, "ledfail - Extinguish (0) or light (1) failure LED\n", NULL);
++#endif /* CFG_CMD_LEDFAIL */
+diff -Nurd u-boot-1.1.2/common/cmd_mem.c u-boot-1.1.2-oxe810/common/cmd_mem.c
+--- u-boot-1.1.2/common/cmd_mem.c 2004-12-16 18:42:39.000000000 +0100
++++ u-boot-1.1.2-oxe810/common/cmd_mem.c 2008-06-11 17:55:30.000000000 +0200
+@@ -731,13 +731,17 @@
+ if (argc > 1) {
+ start = (ulong *)simple_strtoul(argv[1], NULL, 16);
+ } else {
+- start = (ulong *)CFG_MEMTEST_START;
++ DECLARE_GLOBAL_DATA_PTR;
++
++ start = (ulong *)(gd->bd->bi_dram[0].start);
+ }
+
+ if (argc > 2) {
+ end = (ulong *)simple_strtoul(argv[2], NULL, 16);
+ } else {
+- end = (ulong *)(CFG_MEMTEST_END);
++ DECLARE_GLOBAL_DATA_PTR;
++
++ end = (ulong *)(start + gd->bd->bi_dram[0].size);
+ }
+
+ if (argc > 3) {
+diff -Nurd u-boot-1.1.2/common/cmd_nvedit.c u-boot-1.1.2-oxe810/common/cmd_nvedit.c
+--- u-boot-1.1.2/common/cmd_nvedit.c 2004-09-30 00:55:14.000000000 +0200
++++ u-boot-1.1.2-oxe810/common/cmd_nvedit.c 2008-06-11 17:55:30.000000000 +0200
+@@ -55,8 +55,9 @@
+ !defined(CFG_ENV_IS_IN_FLASH) && \
+ !defined(CFG_ENV_IS_IN_DATAFLASH) && \
+ !defined(CFG_ENV_IS_IN_NAND) && \
++ !defined(CFG_ENV_IS_IN_DISK) && \
+ !defined(CFG_ENV_IS_NOWHERE)
+-# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|NOWHERE}
++# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|DISK|NOWHERE}
+ #endif
+
+ #define XMK_STR(x) #x
+@@ -483,7 +484,7 @@
+ * or NULL if not found
+ */
+
+-char *getenv (uchar *name)
++char *getenv (const uchar *name)
+ {
+ int i, nxt;
+
+@@ -530,7 +531,9 @@
+ return (-1);
+ }
+
+-#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) || \
++#if defined(CFG_ENV_IS_IN_NVRAM) || \
++ defined(CFG_ENV_IS_IN_EEPROM) || \
++ defined(CFG_ENV_IS_IN_DISK) || \
+ ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == \
+ (CFG_CMD_ENV|CFG_CMD_FLASH))
+ int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+@@ -586,7 +589,9 @@
+ " - delete environment variable 'name'\n"
+ );
+
+-#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) || \
++#if defined(CFG_ENV_IS_IN_NVRAM) || \
++ defined(CFG_ENV_IS_IN_EEPROM) || \
++ defined(CFG_ENV_IS_IN_DISK) || \
+ ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == \
+ (CFG_CMD_ENV|CFG_CMD_FLASH))
+ U_BOOT_CMD(
+diff -Nurd u-boot-1.1.2/common/env_common.c u-boot-1.1.2-oxe810/common/env_common.c
+--- u-boot-1.1.2/common/env_common.c 2004-06-09 16:58:14.000000000 +0200
++++ u-boot-1.1.2-oxe810/common/env_common.c 2008-06-11 17:55:30.000000000 +0200
+@@ -42,7 +42,7 @@
+ extern void disable_nvram(void);
+ #endif
+
+-#undef DEBUG_ENV
++//#undef DEBUG_ENV
+ #ifdef DEBUG_ENV
+ #define DEBUGF(fmt,args...) printf(fmt ,##args)
+ #else
+diff -Nurd u-boot-1.1.2/common/env_disk.c u-boot-1.1.2-oxe810/common/env_disk.c
+--- u-boot-1.1.2/common/env_disk.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/common/env_disk.c 2008-06-11 17:55:30.000000000 +0200
+@@ -0,0 +1,152 @@
++/*
++ * (C) Copyright 2006
++ * 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>
++
++#if defined(CFG_ENV_IS_IN_DISK)
++
++#include <command.h>
++#include <environment.h>
++#include <ide.h>
++
++extern int is_device_present(int device_number);
++
++/* Point to the environment as held in SRAM */
++env_t *env_ptr = NULL;
++
++char *env_name_spec = "Disk";
++
++/* The default environment compiled into U-Boot */
++extern uchar default_environment[];
++
++uchar env_get_char_spec(int index)
++{
++ DECLARE_GLOBAL_DATA_PTR;
++
++ return *((uchar *)(gd->env_addr + index));
++}
++
++#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
++
++void env_relocate_spec(void)
++{
++ /* Compute the CRC of the environment in SRAM, copied from disk at boot */
++ env_t *sram_env = (env_t*)CFG_ENV_ADDR;
++ ulong crc = crc32(0, sram_env->data, CFG_ENV_SIZE - offsetof(env_t, data));
++
++ /* Copy the SRAM environment and CRC to the working environment */
++ memcpy(env_ptr->data, sram_env->data, CFG_ENV_SIZE - offsetof(env_t, data));
++ env_ptr->crc = crc;
++}
++
++int saveenv(void)
++{
++ /* Compute the CRC of the working environment */
++ env_ptr->crc = crc32(0, env_ptr->data, CFG_ENV_SIZE - offsetof(env_t, data));
++
++ /* Copy the working environment to the reserved area on each disk device */
++ int status = 1;
++ int i;
++ for (i=0; i < CFG_IDE_MAXDEVICE; ++i) {
++ if (!is_device_present(i)) {
++ continue;
++ }
++
++ /* Write environment to the main environment area on disk */
++ unsigned long written = ide_write(i, CFG_ENV_DISK_SECTOR, CFG_ENV_SIZE/512, (ulong*)env_ptr);
++ if (written != CFG_ENV_SIZE/512) {
++ printf("Saving environment to disk %d primary image failed\n", i);
++ status = 0;
++ } else {
++ /* Write environment to the redundant environment area on disk */
++ written = ide_write(i, CFG_ENV_DISK_REDUNDANT_SECTOR, CFG_ENV_SIZE/512, (ulong*)env_ptr);
++ if (written != CFG_ENV_SIZE/512) {
++ printf("Saving environment to disk %d secondary image failed\n", i);
++ status = 0;
++ }
++ }
++ }
++
++ return status;
++}
++
++static int check_sram_env_integrity(void)
++{
++ DECLARE_GLOBAL_DATA_PTR;
++
++ env_t *sram_env = (env_t*)CFG_ENV_ADDR;
++ ulong crc = crc32(0, sram_env->data, CFG_ENV_SIZE - offsetof(env_t, data));
++
++ if (crc == sram_env->crc) {
++ gd->env_addr = (ulong)sram_env->data;
++ gd->env_valid = 1;
++ }
++
++ return gd->env_valid;
++}
++
++int env_init(void)
++{
++ DECLARE_GLOBAL_DATA_PTR;
++
++ /* Have not yet found a valid environment */
++ gd->env_valid = 0;
++
++ /* Need SATA available to load environment from alternate disk locations */
++ ide_init();
++
++ int i;
++ for (i=0; i < CFG_IDE_MAXDEVICE; ++i) {
++ if (!is_device_present(i)) {
++ continue;
++ }
++
++ /* Read environment from the primary environment area on disk */
++ unsigned long read = ide_read(i, CFG_ENV_DISK_SECTOR, CFG_ENV_SIZE/512, (ulong*)CFG_ENV_ADDR);
++ if (read == CFG_ENV_SIZE/512) {
++ /* Check integrity of primary environment data */
++ if (check_sram_env_integrity()) {
++ printf("Environment successfully read from disk %d primary image\n", i);
++ break;
++ }
++ }
++
++ /* Read environment from the secondary environment area on disk */
++ read = ide_read(i, CFG_ENV_DISK_REDUNDANT_SECTOR, CFG_ENV_SIZE/512, (ulong*)CFG_ENV_ADDR);
++ if (read == CFG_ENV_SIZE/512) {
++ /* Check integrity of secondary environment data */
++ if (check_sram_env_integrity()) {
++ printf("Environment successfully read from disk %d secondary image\n", i);
++ break;
++ }
++ }
++ }
++
++ if (!gd->env_valid) {
++ printf("Failed to read valid environment from disk, using built-in default\n");
++ gd->env_addr = (ulong)default_environment;
++ gd->env_valid = 0;
++ }
++
++ return 0;
++}
++#endif // CFG_ENV_IS_IN_DISK
+diff -Nurd u-boot-1.1.2/common/main.c u-boot-1.1.2-oxe810/common/main.c
+--- u-boot-1.1.2/common/main.c 2004-04-23 22:32:06.000000000 +0200
++++ u-boot-1.1.2-oxe810/common/main.c 2008-06-11 17:55:30.000000000 +0200
+@@ -182,7 +182,7 @@
+ else {
+ for (i = 0; i < presskey_max - 1; i ++)
+ presskey [i] = presskey [i + 1];
+-
++do_recovery
+ presskey [i] = getc();
+ }
+ }
+@@ -369,6 +369,149 @@
+ install_auto_complete();
+ #endif
+
++
++#if defined(CONFIG_OXNAS)
++ /* Set the memory size given to Linux */
++ {
++ DECLARE_GLOBAL_DATA_PTR;
++
++ /* Get a copy of the bootargs string from the runtime environment */
++ char tempBuf[1024];
++ char* cmd_string = strcpy(&tempBuf[0], getenv("bootargs"));
++
++ /* Find the extent of memory token in the bootargs string */
++ char* mem_token = strstr(cmd_string, "mem=");
++ char* mem_token_end = mem_token;
++ while ((*mem_token_end != ' ') &&
++ (*mem_token_end != '\0')) {
++ ++mem_token_end;
++ }
++
++ if ((*mem_token_end == '\0') && (mem_token != mem_token_end)) {
++ /* Memory token is last in bootargs string */
++ if (mem_token != cmd_string) {
++ /* Is not the only token, so erase token and previous space" */
++ *(mem_token-1) = '\0';
++ } else {
++ /* Is the only token, so no previous space to erase */
++ *mem_token = '\0';
++ }
++ } else {
++ /* Memory token is at intermediate location in bootargs string */
++ if (*mem_token_end == ' ') {
++ ++mem_token_end;
++ }
++
++ /* Form the bootargs string without the memory token present */
++ strcpy(mem_token, mem_token_end);
++ }
++
++ /* How many MB of SDRAM are present */
++ int megabytes = gd->bd->bi_dram[0].size >> 20;
++
++ /* Append the memory token to the bootargs string */
++ switch (megabytes) {
++ case 64:
++ cmd_string = strcat(cmd_string, " mem=64M");
++ break;
++ case 128:
++ cmd_string = strcat(cmd_string, " mem=128M");
++ break;
++ case 256:
++ cmd_string = strcat(cmd_string, " mem=256M");
++ break;
++ default:
++ printf("Unsupported memory size, defaulting to 64M\n");
++ cmd_string = strcat(cmd_string, " mem=64M");
++ }
++
++ /* Save the revised bootargs string to the runtime environment */
++ setenv("bootargs", cmd_string);
++ }
++
++/* Upgrade, recovery and power button monitor code
++*/
++ int do_recovery = 0; /* default no recovery */
++
++ /* Read the upgrade flag from disk into memory */
++ ide_init();
++ run_command("ide read 48700000 ff 1", 0);
++
++ char upgrade_mode = *(volatile char*)0x48700000;
++ char recovery_mode = *(volatile char*)0x48700001;
++ char controlled_pd_mode = *(volatile char*)0x48700002;
++
++ if (recovery_mode == RECOVERY_MAGIC) {
++ do_recovery = 1; /* perform recovery */
++ }
++
++ if (controlled_pd_mode == CONTROLLED_POWER_DOWN_MAGIC) {
++ /* System in controlled pwer down mode */
++
++ /* Read the SRAM location for normal boot flag */
++ char sram_data = *(volatile char*)(CFG_SRAM_BASE + CFG_SRAM_SIZE - POWER_ON_FLAG_SRAM_OFFSET);
++ char tempBuf[1024];
++ char* cmd_string = strcpy(&tempBuf[0], getenv("bootargs"));
++
++ if (sram_data == CONTROLLED_POWER_UP_MAGIC) {
++ /* The system has to remain in power down state */
++
++ /* Set appropriate boot args */
++ cmd_string = strcat(cmd_string, " powermode=controlledpup");
++ printf("Controlled Power UP requested\n");
++ } else {
++ /* The system is moving to power up state from power down state */
++ cmd_string = strcat(cmd_string, " powermode=controlledpdown");
++ printf("Controlled Power DOWN requested\n");
++ }
++ setenv("bootargs", cmd_string);
++ }
++
++ /* branch off inot recovery or upadate */
++ if (upgrade_mode == UPGRADE_MAGIC) {
++ /* Script to select first disk */
++ parse_string_outer("set select0 ide dev 0", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
++
++ /* Script to select second disk */
++ parse_string_outer("set select1 ide dev 1", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
++
++ /* Script for loading 256KB of upgrade rootfs image from hidden sectors */
++ parse_string_outer("set loadf ide read 48700000 1770 200", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
++
++ /* Script for loading 2MB of upgrade kernel image from hidden sectors */
++ parse_string_outer("set loadk ide read 48800000 1970 1000", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
++
++ /* Script to light failure LED */
++ parse_string_outer("set lightled ledfail 1", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
++
++ /* Script to extinguish failure LED */
++ parse_string_outer("set extinguishled ledfail 0", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
++
++ /* Script for booting Linux kernel image with mkimage-wrapped initrd */
++ parse_string_outer("set boot bootm 48800000 48700000", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
++
++ /* Set Linux bootargs to use rootfs in initial ramdisk */
++ parse_string_outer("set bootargs mem=32M console=ttyS0,115200 root=/dev/ram0", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
++
++ /* Validate, load and boot the first validate set of initrd and kernel
++ Theres alot of combos here due to disk/backup/fk arrangments, it'll
++ no doubt work on the first or second one though. */
++ parse_string_outer("run select0 loadf loadk boot || "
++ "run lightled select1 loadf loadk extinguishled boot || "
++ "run lightled select0 loadf select1 loadk extinguishled boot || "
++ "run lightled select1 loadf select0 loadk extinguishled boot || "
++ "run lightled ", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
++ } else if (do_recovery) {
++ printf ("\nRecovery mode selected\n");
++
++ char tempBuf[1024];
++ char* cmd_string = strcpy(&tempBuf[0], getenv("bootargs"));
++ cmd_string = strcat(cmd_string, " adminmode=recovery");
++ setenv("bootargs", cmd_string);
++ }
++
++#endif // CONFIG_OXNAS
++
+ #ifdef CONFIG_PREBOOT
+ if ((p = getenv ("preboot")) != NULL) {
+ # ifdef CONFIG_AUTOBOOT_KEYED
+diff -Nurd u-boot-1.1.2/common/Makefile u-boot-1.1.2-oxe810/common/Makefile
+--- u-boot-1.1.2/common/Makefile 2004-12-16 18:35:57.000000000 +0100
++++ u-boot-1.1.2-oxe810/common/Makefile 2008-06-11 17:55:30.000000000 +0200
+@@ -40,9 +40,10 @@
+ cmd_nand.o cmd_net.o cmd_nvedit.o \
+ cmd_pci.o cmd_pcmcia.o cmd_portio.o \
+ cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_universe.o cmd_usb.o cmd_vfd.o \
++ cmd_ledfail.o \
+ command.o console.o devices.o dlmalloc.o docecc.o \
+ environment.o env_common.o \
+- env_nand.o env_dataflash.o env_flash.o env_eeprom.o env_nvram.o env_nowhere.o exports.o \
++ env_nand.o env_dataflash.o env_flash.o env_eeprom.o env_nvram.o env_nowhere.o env_disk.o exports.o \
+ flash.o fpga.o \
+ hush.o kgdb.o lcd.o lists.o lynxkdi.o \
+ memsize.o miiphybb.o miiphyutil.o \
+diff -Nurd u-boot-1.1.2/cpu/arm926ejs/config.mk u-boot-1.1.2-oxe810/cpu/arm926ejs/config.mk
+--- u-boot-1.1.2/cpu/arm926ejs/config.mk 2003-08-30 00:00:47.000000000 +0200
++++ u-boot-1.1.2-oxe810/cpu/arm926ejs/config.mk 2008-06-11 17:55:03.000000000 +0200
+@@ -21,7 +21,6 @@
+ # MA 02111-1307 USA
+ #
+
+-PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \
+- -mshort-load-bytes -msoft-float
++PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8
+
+-PLATFORM_CPPFLAGS += -mapcs-32 -march=armv4
++PLATFORM_CPPFLAGS += -march=armv5te
+diff -Nurd u-boot-1.1.2/cpu/arm926ejs/interrupts.c u-boot-1.1.2-oxe810/cpu/arm926ejs/interrupts.c
+--- u-boot-1.1.2/cpu/arm926ejs/interrupts.c 2004-03-23 22:43:08.000000000 +0100
++++ u-boot-1.1.2-oxe810/cpu/arm926ejs/interrupts.c 2008-06-11 17:55:03.000000000 +0200
+@@ -41,7 +41,12 @@
+ #include <asm/proc-armv/ptrace.h>
+
+ extern void reset_cpu(ulong addr);
++
++#ifdef CONFIG_OXNAS
++#define TIMER_LOAD_VAL 0xffffUL
++#else // CONFIG_OXNAS
+ #define TIMER_LOAD_VAL 0xffffffff
++#endif // CONFIG_OXNAS
+
+ /* macro to read the 32 bit timer */
+ #ifdef CONFIG_OMAP
+@@ -53,6 +58,9 @@
+ #ifdef CONFIG_VERSATILE
+ #define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+4))
+ #endif
++#ifdef CONFIG_OXNAS
++#define READ_TIMER ((*(volatile ushort *)(CFG_TIMERBASE+4)) & 0xFFFFUL) /* RPS timer value register has only 16 defined bits */
++#endif
+
+ #ifdef CONFIG_USE_IRQ
+ /* enable IRQ interrupts */
+@@ -212,6 +220,16 @@
+ *(volatile ulong *)(CFG_TIMERBASE + 4) = CFG_TIMER_RELOAD; /* TimerValue */
+ *(volatile ulong *)(CFG_TIMERBASE + 8) = 0x8C;
+ #endif /* CONFIG_VERSATILE */
++#ifdef CONFIG_OXNAS
++ // Setup timer 1 load value
++ *(volatile ulong*)(CFG_TIMERBASE + 0) = TIMER_LOAD_VAL;
++
++ // Setup timer 1 prescaler, periodic operation and start it
++ *(volatile ulong*)(CFG_TIMERBASE + 8) =
++ (TIMER_PRESCALE_ENUM << TIMER_PRESCALE_BIT) |
++ (TIMER_MODE_PERIODIC << TIMER_MODE_BIT) |
++ (TIMER_ENABLE_ENABLE << TIMER_ENABLE_BIT);
++#endif /* CONFIG_OXNAS */
+
+ /* init the timestamp and lastdec value */
+ reset_timer_masked();
+diff -Nurd u-boot-1.1.2/cpu/arm926ejs/start.S u-boot-1.1.2-oxe810/cpu/arm926ejs/start.S
+--- u-boot-1.1.2/cpu/arm926ejs/start.S 2004-06-09 02:11:01.000000000 +0200
++++ u-boot-1.1.2-oxe810/cpu/arm926ejs/start.S 2008-06-11 17:55:03.000000000 +0200
+@@ -94,6 +94,11 @@
+ _TEXT_BASE:
+ .word TEXT_BASE
+
++#ifdef CONFIG_OXNAS
++_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_OXNAS
++ /*
++ * 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!
+@@ -143,21 +160,21 @@
+ bl cpu_init_crit
+ #endif
+
+-relocate: /* relocate U-Boot to RAM */
+- adr r0, _start /* r0 <- current position of code */
+- ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
+- cmp r0, r1 /* don't reloc during debug */
+- beq stack_setup
++relocate: /* relocate U-Boot to RAM */
++ adr r0, _start /* current position of code */
++ ldr r1, _TEXT_BASE /* relocated position of code */
++ cmp r0, r1
++ beq stack_setup
+
+ ldr r2, _armboot_start
+ ldr r3, _bss_start
+- sub r2, r3, r2 /* r2 <- size of armboot */
+- add r2, r0, r2 /* r2 <- source end address */
++ sub r2, r3, r2 /* r2 <- size of armboot */
++ add r2, r0, r2 /* r2 <- source end address */
+
+ copy_loop:
+- ldmia r0!, {r3-r10} /* copy from source address [r0] */
+- stmia r1!, {r3-r10} /* copy to target address [r1] */
+- cmp r0, r2 /* until source end addreee [r2] */
++ ldmia r0!, {r3-r10} /* copy from source address [r0] */
++ stmia r1!, {r3-r10} /* copy to target address [r1] */
++ cmp r0, r2 /* until source end addreee [r2] */
+ ble copy_loop
+
+ /* Set up the stack */
+@@ -212,7 +229,7 @@
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
+ bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
+- orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
++ orr r0, r0, #0x00000002 /* set bit 1 (A) Align */
+ orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
+ mcr p15, 0, r0, c1, c0, 0
+
+@@ -391,6 +408,7 @@
+
+ #endif
+
++#ifndef CONFIG_OXNAS
+ .align 5
+ .globl reset_cpu
+ reset_cpu:
+@@ -405,3 +423,4 @@
+
+ rstctl1:
+ .word 0xfffece10
++#endif // !CONFIG_OXNAS
+diff -Nurd u-boot-1.1.2/drivers/cfi_flash.c u-boot-1.1.2-oxe810/drivers/cfi_flash.c
+--- u-boot-1.1.2/drivers/cfi_flash.c 2004-12-18 23:35:45.000000000 +0100
++++ u-boot-1.1.2-oxe810/drivers/cfi_flash.c 2008-06-11 17:55:31.000000000 +0200
+@@ -1056,7 +1056,11 @@
+ }
+ tmp = flash_read_long (info, 0,
+ FLASH_OFFSET_ERASE_REGIONS +
++#ifdef FORCE_TOP_BOOT_FLASH
++ (num_erase_regions - 1 - i) * 4);
++#else
+ i * 4);
++#endif
+ erase_region_size =
+ (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
+ tmp >>= 16;
+@@ -1104,6 +1108,7 @@
+ cfiptr_t ctladdr;
+ cfiptr_t cptr;
+ int flag;
++ ulong start;
+
+ ctladdr.cp = flash_make_addr (info, 0, 0);
+ cptr.cp = (uchar *) dest;
+@@ -1151,6 +1156,15 @@
+ break;
+ case FLASH_CFI_16BIT:
+ cptr.wp[0] = cword.w;
++ /* Wait for write to complete */
++ start = get_timer (0);
++ while (cptr.wp[0] != cword.w) {
++ printf(".");
++ if (get_timer (start) > info->erase_blk_tout * CFG_HZ) {
++ printf ("Flash write timeout!");;
++ }
++ }
++ printf("\n");
+ break;
+ case FLASH_CFI_32BIT:
+ cptr.lp[0] = cword.l;
+diff -Nurd u-boot-1.1.2/drivers/ns16550.c u-boot-1.1.2-oxe810/drivers/ns16550.c
+--- u-boot-1.1.2/drivers/ns16550.c 2004-06-07 01:13:57.000000000 +0200
++++ u-boot-1.1.2-oxe810/drivers/ns16550.c 2008-06-11 17:55:31.000000000 +0200
+@@ -14,8 +14,25 @@
+ #define MCRVAL (MCR_DTR | MCR_RTS) /* RTS/DTR */
+ #define FCRVAL (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR) /* Clear & enable FIFOs */
+
++#ifdef USE_UART_FRACTIONAL_DIVIDER
++static int oxnas_fractional_divider(NS16550_t com_port, int baud_divisor)
++{
++ // Baud rate is passed around x16
++ int real_divisor = baud_divisor >> 4;
++ // Top three bits of 8-bit dlf register hold the number of eigths
++ // for the fractional part of the divide ratio
++ com_port->dlf = (unsigned char)(((baud_divisor - (real_divisor << 4)) << 4) & 0xFF);
++ // Return the x1 divider for the normal divider register
++ return real_divisor;
++}
++#endif // USE_UART_FRACTIONAL_DIVIDER
++
+ void NS16550_init (NS16550_t com_port, int baud_divisor)
+ {
++#ifdef USE_UART_FRACTIONAL_DIVIDER
++ baud_divisor = oxnas_fractional_divider(com_port, baud_divisor);
++#endif // USE_UART_FRACTIONAL_DIVIDER
++
+ com_port->ier = 0x00;
+ #ifdef CONFIG_OMAP1510
+ com_port->mdr1 = 0x7; /* mode select reset TL16C750*/
+@@ -33,6 +50,10 @@
+
+ void NS16550_reinit (NS16550_t com_port, int baud_divisor)
+ {
++#ifdef USE_UART_FRACTIONAL_DIVIDER
++ baud_divisor = oxnas_fractional_divider(com_port, baud_divisor);
++#endif // USE_UART_FRACTIONAL_DIVIDER
++
+ com_port->ier = 0x00;
+ com_port->lcr = LCR_BKSE;
+ com_port->dll = baud_divisor & 0xff;
+diff -Nurd u-boot-1.1.2/drivers/serial.c u-boot-1.1.2-oxe810/drivers/serial.c
+--- u-boot-1.1.2/drivers/serial.c 2003-08-30 00:00:47.000000000 +0200
++++ u-boot-1.1.2-oxe810/drivers/serial.c 2008-06-11 17:55:31.000000000 +0200
+@@ -59,7 +59,13 @@
+ return (26); /* return 26 for base divisor */
+ }
+ #endif
+- return (CFG_NS16550_CLK / 16 / gd->baudrate);
++
++#ifdef USE_UART_FRACTIONAL_DIVIDER
++ return (((CFG_NS16550_CLK << 4) / gd->baudrate) + 8) >> 4;
++#endif // USE_UART_FRACTIONAL_DIVIDER
++
++ // Round to nearest integer
++ return (((CFG_NS16550_CLK / gd->baudrate) + 8 ) / 16);
+ }
+
+ int serial_init (void)
+diff -Nurd u-boot-1.1.2/examples/Makefile u-boot-1.1.2-oxe810/examples/Makefile
+--- u-boot-1.1.2/examples/Makefile 2004-10-10 23:27:33.000000000 +0200
++++ u-boot-1.1.2-oxe810/examples/Makefile 2008-06-11 17:55:30.000000000 +0200
+@@ -30,7 +30,8 @@
+ endif
+
+ ifeq ($(ARCH),arm)
+-LOAD_ADDR = 0xc100000
++#LOAD_ADDR = 0xc100000
++LOAD_ADDR = 0x4C004000
+ endif
+
+ ifeq ($(ARCH),mips)
+@@ -58,6 +59,11 @@
+ SREC = hello_world.srec
+ BIN = hello_world.bin hello_world
+
++ifeq ($(ARCH),arm)
++SREC += mem_test.srec
++BIN += mem_test.bin mem_test
++endif
++
+ ifeq ($(ARCH),i386)
+ SREC += 82559_eeprom.srec
+ BIN += 82559_eeprom.bin 82559_eeprom
+@@ -115,10 +121,10 @@
+ $(LD) -g $(EX_LDFLAGS) -Ttext $(LOAD_ADDR) \
+ -o $@ -e $(<:.o=) $< $(LIB) \
+ -L$(gcclibdir) -lgcc
+-%.srec: %
++%.srec: %.o
+ $(OBJCOPY) -O srec $< $@ 2>/dev/null
+
+-%.bin: %
++%.bin: %.o
+ $(OBJCOPY) -O binary $< $@ 2>/dev/null
+
+ #########################################################################
+diff -Nurd u-boot-1.1.2/examples/mem_test.c u-boot-1.1.2-oxe810/examples/mem_test.c
+--- u-boot-1.1.2/examples/mem_test.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/examples/mem_test.c 2008-06-11 17:55:30.000000000 +0200
+@@ -0,0 +1,1322 @@
++/*
++ * (C) Copyright 2006
++ * Oxford Semiconductor Ltd, www.oxsemi.com
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/********************* OPTIONS ********************************************************/
++
++#define ARM
++/*
++#define QUIET
++#define SHORT
++*/
++
++/********************* TEST DEFINITIONS ********************************************************/
++
++
++#define NUM_PATTYPES 5
++#define PATTYPE_A5 0
++#define PATTYPE_5A 1
++#define PATTYPE_NO_FF 2
++#define PATTYPE_INCR 3
++#define PATTYPE_DECR 4
++
++/* Number of words in a block (to ensure that neither data not ~data is 0xFFxx) */
++
++#ifdef SHORT
++ #define BLOCKWORDS (254*4)
++ #define BLOCKSIZE (256*4)
++#else
++ #define BLOCKWORDS (254*256*4)
++ #define BLOCKSIZE (256*256*4)
++#endif
++
++#ifdef ARM
++ #include <common.h>
++ #include <exports.h>
++
++ #define SDRAM_BASE 0x48000000
++ #define SDRAM_TOP 0x49000000
++ #define SDRAM_BLOCK 0x10000
++// #define SDRAM_WRITE(ADDR, DATA) printf("Write 0x%08x to 0x%08x\n", (DATA), (ADDR));
++// #define SDRAM_READ(ADDR, VAR) printf("Read from 0x%08x\n", (ADDR));
++// #define SDRAM_WRITE(ADDR, DATA) printf("Write 0x%08x to 0x%08x\n", (DATA), (ADDR)); (*((volatile unsigned int *)(ADDR)) = (DATA))
++// #define SDRAM_READ(ADDR, VAR) printf("Read from 0x%08x\n", (ADDR)); (*(VAR) = *((volatile unsigned int *)(ADDR)))
++ #define SDRAM_WRITE(ADDR, DATA) (*((volatile unsigned int *)(ADDR)) = (DATA))
++ #define SDRAM_READ(ADDR, VAR) (*(VAR) = *((volatile unsigned int *)(ADDR)))
++#else
++ #include <stdio.h>
++ #include <stdlib.h>
++ /* Not so much space - just 2 blocks from addr 0... */
++ #define SDRAM_BASE 0
++ #define SDRAM_TOP (2 * BLOCKSIZE)
++ #define SDRAM_BLOCK 0x10000
++ #ifdef QUIET
++ #define SDRAM_WRITE(ADDR, DATA) array[ADDR] = (DATA)
++ #define SDRAM_READ(ADDR, VAR) *((volatile unsigned int *)(VAR)) = array[ADDR]
++ #else
++ #define SDRAM_WRITE(ADDR, DATA) printf("WRITE(%08x)=%08x\n", ADDR, DATA); array[ADDR] = (DATA)
++ #define SDRAM_READ(ADDR, VAR) printf("READ (%08x)=%08x\n", ADDR, array[ADDR]); *((volatile unsigned int *)(VAR)) = array[ADDR]
++ #endif
++ unsigned volatile int array[SDRAM_TOP];
++#endif
++
++
++#define SYSCTRL_PRIMSEL_LO 0x4500000C
++#define SYSCTRL_SECSEL_LO 0x45000014
++#define SYSCTRL_TERSEL_LO 0x4500008C
++#define SYSCTRL_PRIMSEL_HI 0x45000010
++#define SYSCTRL_SECSEL_HI 0x45000018
++#define SYSCTRL_TERSEL_HI 0x45000090
++
++/* GPIO */
++#define GPIOB_IO_VAL 0x44100000
++#define GPIOB_OE_VAL 0x44100004
++#define GPIOB_SET_OE 0x4410001C
++#define GPIOB_CLEAR_OE 0x44100020
++#define GPIOB_OUTPUT_VAL 0x44100010
++#define GPIOB_SET_OUTPUT 0x44100014
++#define GPIOB_CLEAR_OUTPUT 0x44100018
++#define GPIOB_BIT_34 0x00000004
++
++void configure_caches(void);
++void report_err(unsigned int address, unsigned int bad_data, unsigned int correct_data, unsigned int iteration);
++
++/********************* TYPES.H ********************************************************/
++
++typedef unsigned int UINT, *PUINT;
++/*
++#ifndef __MY_BASIC_TYPES_H
++#define __MY_BASIC_TYPES_H
++
++typedef signed char CHAR, *PCHAR;
++typedef unsigned char BYTE, UCHAR, *PBYTE, *PUCHAR;
++typedef signed short SHORT, *PSHORT;
++typedef unsigned short WORD, USHORT, *PWORD, *PUSHORT;
++typedef signed long LONG, *PLONG;
++typedef unsigned long DWORD, *PDWORD;
++typedef int BOOL, *PBOOL;
++typedef unsigned int UINT, *PUINT;
++typedef void VOID, *PVOID;
++
++typedef float SINGLE,*PSINGLE;
++typedef double DOUBLE,*PDOUBLE;
++
++
++#define FALSE 0
++#define TRUE 1
++
++#endif
++*/
++
++/********************* CHIP.H ********************************************************/
++
++// Address Map
++#define BOOT_ROM_BASE 0x00000000
++#define USBHS_BASE 0x00200000
++#define GMAC_BASE 0x00400000
++#define PCI_BASE 0x00600000
++#define PCI_DATA_BASE 0x00800000
++#define STATIC0_BASE 0x01000000
++#define STATIC1_BASE 0x01400000
++#define STATIC2_BASE 0x01800000
++#define STATIC_BASE 0x01C00000
++#define SATA_DATA_BASE 0x02000000
++#define DPE_DATA_BASE 0x03000000
++#define GPIOA_BASE 0x04000000
++#define GPIOB_BASE 0x04100000
++#define UARTA_BASE 0x04200000
++#define UARTB_BASE 0x04300000
++#define I2C_MASTER_BASE 0x04400000
++#define AUDIO_BASE 0x04500000
++#define FAN_BASE 0x04600000
++#define PWM_BASE 0x04700000
++#define IR_RX_BASE 0x04800000
++#define UARTC_BASE 0x04900000
++#define UARTD_BASE 0x04A00000
++#define SYS_CTRL_BASE 0x05000000
++#define RPSA_BASE 0x05300000
++#define ARM_RPS_BASE RPSA_BASE
++#define RPSC_BASE 0x05400000
++#define AHB_MON_BASE 0x05500000
++#define DMA_BASE 0x05600000
++#define DPE_BASE 0x05700000
++#define IBIW_BASE 0x05780000
++#define DDR_BASE 0x05800000
++#define SATA0_BASE 0x05900000
++#define SATA1_BASE 0x05980000
++#define DMA_CHKSUM_BASE 0x05A00000
++#define COPRO_BASE 0x05B00000
++#define SGDMA_BASE 0x05C00000
++#define DDR_DATA_BASE 0x08000000
++#define SRAM_BASE 0x0C000000
++#define SRAM0_BASE 0x0C000000
++#define SRAM1_BASE 0x0C002000
++#define SRAM2_BASE 0x0C004000
++#define SRAM3_BASE 0x0C006000
++
++// Virtual peripheral for TB sync
++#define TB_SYNC_BASE 0x05F00100
++
++
++/********************* DMA.H ********************************************************/
++
++
++// DMA Control register settings
++
++#define DMA_FAIR_SHARE (1<<0)
++#define DMA_IN_PROGRESS (1<<1)
++
++#define DMA_SDREQ_SATA (0<<2)
++#define DMA_SDREQ_DPE_OUT (2<<2)
++#define DMA_SDREQ_UARTA_RX (4<<2)
++#define DMA_SDREQ_AUDIO_RX (6<<2)
++#define DMA_SDREQ_MEM (0xF<<2)
++
++#define DMA_DDREQ_SATA (0<<6)
++#define DMA_DDREQ_DPE_IN (1<<6)
++#define DMA_DDREQ_UARTA_TX (3<<6)
++#define DMA_DDREQ_AUDIO_TX (5<<6)
++#define DMA_DDREQ_MEM (0xF<<6)
++
++#define DMA_INTERRUPT (1 << 10)
++#define DMA_NEXT_FREE (1 << 11)
++#define DMA_CH_RESET (1 << 12)
++
++#define DMA_DIR_ATOA (0 << 13)
++#define DMA_DIR_BTOA (1 << 13)
++#define DMA_DIR_ATOB (2 << 13)
++#define DMA_DIR_BTOB (3 << 13)
++
++#define DMA_BURST_A (1 << 17)
++#define DMA_BURST_B (1 << 18)
++
++#define DMA_SWIDTH_8 (0 << 19)
++#define DMA_SWIDTH_16 (1 << 19)
++#define DMA_SWIDTH_32 (2 << 19)
++
++#define DMA_DWIDTH_8 (0 << 22)
++#define DMA_DWIDTH_16 (1 << 22)
++#define DMA_DWIDTH_32 (2 << 22)
++
++#define DMA_PAUSE (1 << 25)
++#define DMA_INT_ENABLE (1 << 26)
++#define DMA_STARVE_LO_PRIORITY (1 << 29)
++#define DMA_NEW_INT_CLEAR (1 << 30)
++
++#define DMA_FIXED_SADDR ((0 << 15) | (1 << 27))
++#define DMA_INCR_SADDR ((1 << 15) | (0 << 27))
++#define DMA_SEMI_FIXED_SADDR ((0 << 15) | (0 << 27))
++
++#define DMA_FIXED_DADDR ((0 << 16) | (1 << 28))
++#define DMA_INCR_DADDR ((1 << 16) | (0 << 28))
++#define DMA_SEMI_FIXED_DADDR ((0 << 16) | (0 << 28))
++
++#define DMA_BASE_CTRL (DMA_BURST_A | DMA_BURST_B | DMA_INT_ENABLE | DMA_NEW_INT_CLEAR)
++
++// Common base setups
++
++#define DMA_CTRL_A32TOA32 ( DMA_BASE_CTRL | DMA_DIR_ATOA | DMA_SWIDTH_32 | DMA_DWIDTH_32 )
++#define DMA_CTRL_B32TOA32 ( DMA_BASE_CTRL | DMA_DIR_BTOA | DMA_SWIDTH_32 | DMA_DWIDTH_32 )
++#define DMA_CTRL_A32TOB32 ( DMA_BASE_CTRL | DMA_DIR_ATOB | DMA_SWIDTH_32 | DMA_DWIDTH_32 )
++#define DMA_CTRL_B32TOB32 ( DMA_BASE_CTRL | DMA_DIR_BTOB | DMA_SWIDTH_32 | DMA_DWIDTH_32 )
++
++#define DMA_CTRL_A8TOB32 ( DMA_BASE_CTRL | DMA_DIR_ATOB | DMA_SWIDTH_8 | DMA_DWIDTH_32 )
++#define DMA_CTRL_B32TOA8 ( DMA_BASE_CTRL | DMA_DIR_BTOA | DMA_SWIDTH_32 | DMA_DWIDTH_8 )
++#define DMA_CTRL_A32TOB8 ( DMA_BASE_CTRL | DMA_DIR_ATOB | DMA_SWIDTH_32 | DMA_DWIDTH_8 )
++
++// Most likely transactions
++
++#define DMA_CTRL_MEM_TO_MEM_AA ( DMA_CTRL_A32TOA32 | DMA_SDREQ_MEM | DMA_DDREQ_MEM | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_MEM_TO_MEM_AB ( DMA_CTRL_A32TOB32 | DMA_SDREQ_MEM | DMA_DDREQ_MEM | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_MEM_TO_MEM_BB ( DMA_CTRL_B32TOB32 | DMA_SDREQ_MEM | DMA_DDREQ_MEM | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_MEM_TO_MEM_BA ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM | DMA_DDREQ_MEM | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_MEM_TO_MEM ( DMA_CTRL_MEM_TO_MEM_AB )
++
++//DMA A-A
++#define DMA_CTRL_SATA_TO_MEM_AA ( DMA_CTRL_A32TOA32 | DMA_SDREQ_SATA | DMA_DDREQ_MEM | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_MEM_TO_SATA_AA ( DMA_CTRL_A32TOA32 | DMA_SDREQ_MEM | DMA_DDREQ_SATA | DMA_INCR_SADDR | DMA_INCR_DADDR )
++
++#define DMA_CTRL_SATA_TO_MEM ( DMA_CTRL_A32TOB32 | DMA_SDREQ_SATA | DMA_DDREQ_MEM | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_MEM_TO_SATA ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM | DMA_DDREQ_SATA | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_SATA_TO_DPE ( DMA_CTRL_A32TOA32 | DMA_SDREQ_SATA | DMA_DDREQ_DPE_IN | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_DPE_TO_SATA ( DMA_CTRL_A32TOA32 | DMA_SDREQ_DPE_OUT | DMA_DDREQ_SATA | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_MEM_TO_DPE ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM | DMA_DDREQ_DPE_IN | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_DPE_TO_MEM ( DMA_CTRL_A32TOB32 | DMA_SDREQ_DPE_OUT | DMA_DDREQ_MEM | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_PCI_TO_MEM ( DMA_CTRL_A32TOB32 | DMA_SDREQ_MEM | DMA_DDREQ_MEM | DMA_INCR_SADDR | DMA_INCR_DADDR )
++
++#define DMA_CTRL_MEM_TO_PCI ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM | DMA_DDREQ_MEM | DMA_INCR_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_MEM_TO_AUDIO ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM | DMA_DDREQ_AUDIO_TX | DMA_INCR_SADDR | DMA_FIXED_DADDR )
++#define DMA_CTRL_AUDIO_TO_MEM ( DMA_CTRL_A32TOB32 | DMA_SDREQ_AUDIO_RX | DMA_DDREQ_MEM | DMA_FIXED_SADDR | DMA_INCR_DADDR )
++#define DMA_CTRL_MEM_TO_UART ( DMA_CTRL_B32TOA8 | DMA_SDREQ_MEM | DMA_DDREQ_UARTA_TX | DMA_INCR_SADDR | DMA_FIXED_DADDR )
++#define DMA_CTRL_UART_TO_MEM ( DMA_CTRL_A8TOB32 | DMA_SDREQ_UARTA_RX | DMA_DDREQ_MEM | DMA_FIXED_SADDR | DMA_INCR_DADDR )
++
++// Byte count register flags
++
++#define DMA_HBURST_EN (1<<28)
++#define DMA_WR_BUFFERABLE (1<<29)
++#define DMA_WR_EOT (1<<30)
++#define DMA_RD_EOT (1<<31)
++
++
++// Pause the DMA channel specified
++void PauseDMA( UINT channel );
++
++// UnPause the DMA channel specified
++void UnPauseDMA( UINT channel );
++
++// Configure a DMA
++void SetupDMA( UINT channel,
++ UINT src_addr,
++ UINT dest_addr,
++ UINT byte_count,
++ UINT control,
++ UINT flags );
++
++// Wait while the given DMA channel is busy
++void WaitWhileDMABusy( UINT channel );
++
++// Perform a memory to memory copy
++void DMAMemCopy ( UINT channel,
++ UINT src_addr,
++ UINT dest_addr,
++ UINT byte_count );
++
++
++/****************************** MAIN ***********************************************/
++#ifdef ARM
++int mem_test(int argc, char* argv[])
++#else
++int main(int argc, char* argv[])
++#endif
++{
++ unsigned int i;
++ unsigned int iteration;
++ unsigned int block_base;
++ unsigned int datapattern;
++ unsigned int correct_data;
++ unsigned volatile int read_data;
++ unsigned int pattype, starting_pattype;
++ unsigned int end_addr;
++ unsigned int row, col, bank;
++
++#ifdef ARM
++ /* Print the ABI version */
++ app_startup(argv);
++ printf ("Example expects ABI version %d\n", XF_VERSION);
++ printf ("Actual U-Boot ABI version %d\n", (int)get_version());
++
++ printf("GPIO34 is output, low\n");
++ * (volatile unsigned int *) GPIOB_CLEAR_OUTPUT = GPIOB_BIT_34;
++ * (volatile unsigned int *) GPIOB_SET_OE = GPIOB_BIT_34;
++#endif
++
++// configure_caches();
++//printf("Caches enabled\n");
++
++ /* ******************************************************************* */
++ printf("DMA TEST.\n" );
++ /* ******************************************************************* */
++
++
++ #define DMA0_CTRL_STAT 0x45A00000
++ #define DMA0_SRC_BASE 0x45A00004
++ #define DMA0_DEST_BASE 0x45A00008
++ #define DMA0_BYTE_COUNT 0x45A0000C
++ #define DMA0_CURRENT_BYTE 0x45A00018
++
++ printf("Test to top of 1st SDRAM" );
++ #define BLOCK_BYTES 0x20000
++ #define SDRAM_STOP SDRAM_TOP
++
++ for (iteration=0; 1; iteration++) {
++
++ if ((iteration % 5)==0)
++ printf("Iteration %d\n", iteration );
++
++// printf("Write pattern into first block.\n" );
++ end_addr = SDRAM_BASE + BLOCK_BYTES;
++ for (i=SDRAM_BASE; i < end_addr; i=i+4) {
++ SDRAM_WRITE( i, i);
++ }
++
++// printf("Clear last block and a few blocks more - easy to see on LA.\n" );
++ end_addr = SDRAM_BASE + (BLOCK_BYTES << 3);
++ for (i=SDRAM_STOP - BLOCK_BYTES; i < end_addr; i=i+4) {
++ SDRAM_WRITE( i, 0);
++ }
++
++ end_addr = SDRAM_STOP - BLOCK_BYTES;
++ for (i=SDRAM_BASE; i < end_addr; i=i+BLOCK_BYTES) {
++
++// printf("DMA transfer from %08x to %08x.\n", i, i + BLOCK_BYTES );
++#ifdef ARM
++ DMAMemCopy ( 0, i, i + BLOCK_BYTES, BLOCK_BYTES );
++#endif
++// printf("...pending.\n" );
++#ifdef ARM
++ WaitWhileDMABusy( 0 );
++#endif
++// printf("...complete.\n" );
++ }
++
++// printf("Verify pattern in last block.\n" );
++ end_addr = SDRAM_STOP;
++ correct_data = SDRAM_BASE;
++ for (i=SDRAM_STOP - BLOCK_BYTES; i < end_addr; i=i+4) {
++ SDRAM_READ( i, &read_data);
++ if (read_data != correct_data)
++ {
++ /* Expand out the report_err function to avoid the stack operations. */
++ #ifdef ARM
++ /* ASSERT GPIO */
++ * (volatile unsigned int *) GPIOB_SET_OUTPUT = GPIOB_BIT_34;
++ #endif
++
++ /* REPORT ERROR */
++ printf("Wrong on [%08x]= %08x should be %08x on iteration %d\n", i, read_data, correct_data, iteration );
++
++ /* WRITE TO ANOTHER LOCATION */
++ SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
++
++ /* READ AGAIN */
++ SDRAM_READ(i, &read_data);
++ if (read_data != correct_data)
++ printf("Again 1 [%08x]= %08x should be %08x\n", i, read_data, correct_data );
++
++ /* WRITE TO ANOTHER LOCATION */
++ SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
++
++ /* READ AGAIN */
++ SDRAM_READ(i, &read_data);
++ if (read_data != correct_data)
++ printf("Again 2 [%08x]= %08x should be %08x\n", i, read_data, correct_data );
++
++ /* WRITE TO ANOTHER LOCATION */
++ SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
++
++ /* READ AGAIN */
++ SDRAM_READ(i, &read_data);
++ if (read_data != correct_data)
++ printf("Again 3 [%08x]= %08x should be %08x\n", i, read_data, correct_data );
++
++ row = (((i >> 26) & 0x1) << 13) | (((i >> 23) & 0x3) << 11) | ((i >> 10) & 0x7FF); /* [26], [24:23], [20:10]*/
++ col = (((i >> 27) & 0x1) << 10) | (((i >> 25) & 0x1) << 9) | (((i >> 22) & 0x1) << 8); /* [27], [25], [22]... */
++ col |= (((i >> 6) & 0xF) << 4) | (((i >> 21) & 0x1) << 3) | (((i >> 1) & 0x3) << 1); /* ...[9:8], [21], [3:2], '0' */
++ col |= 0x800; /* bit 11 set for auto-precharge */
++ bank = (i >> 4) & 0x3; /* [5:4] */
++ printf("Bank %08x\n", bank );
++ printf("Row %08x\n", row );
++ printf("Column %08x\n", col );
++ #ifdef ARM
++ /* DEASSERT GPIO */
++ * (volatile unsigned int *) GPIOB_CLEAR_OUTPUT = GPIOB_BIT_34;
++ #endif
++ }
++
++
++ correct_data += 4;
++ }
++ }
++
++
++ /* ******************************************************************* */
++ printf("MEM_TEST2\n");
++ /* ******************************************************************* */
++
++
++ pattype=0;
++ iteration=0;
++
++ for (;;) {
++ /* FOR EACH 64Kword==256KB BLOCK IN 16Mword=64MB (2 OFF 16M16) MEMORY... */
++
++#ifdef SHORT
++ if ((iteration % 5)==0)
++ printf("Iteration %d\n", iteration );
++#else
++ if ((iteration % 1000)==0)
++ printf("Iteration %d\n", iteration );
++#endif
++
++ /* WRITE DATA BLOCKS */
++ starting_pattype = pattype; /* Record for later */
++
++ for (block_base=SDRAM_BASE; block_base < SDRAM_TOP; block_base=block_base + BLOCKSIZE) {
++ switch (pattype) {
++ case PATTYPE_A5 :
++ /* Write alternating 1s and 0s... */
++ end_addr = block_base + BLOCKWORDS;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_WRITE( i, 0xaa55aa55);
++ }
++ break;
++ case PATTYPE_5A :
++ /* Write alternating 1s and 0s (inverse of above)... */
++ end_addr = block_base + BLOCKWORDS;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_WRITE( i, 0x55aa55aa);
++ }
++ break;
++ case PATTYPE_NO_FF :
++ /* Write data=address with bit[n+16]=~bit[n]... */
++ datapattern = 0x0100FEFF;
++ /* In range 0x0100...0xFEFF so that
++ a. temp[15:8] is never 0xFF
++ b. Inverse of temp[15:8] is never 0xFF
++ */
++ end_addr = block_base + BLOCKWORDS;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_WRITE( i, datapattern);
++ datapattern = datapattern + 0xFFFF;
++ }
++ break;
++ case PATTYPE_INCR :
++ /* Write data=address... */
++ end_addr = block_base + BLOCKSIZE;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_WRITE( i, i);
++ }
++ break;
++ case PATTYPE_DECR :
++ /* Write data=~address... */
++ end_addr = block_base + BLOCKSIZE;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_WRITE( i, ~i);
++ }
++ break;
++ }
++ }
++
++ /* VERIFY DATA BLOCKS */
++ pattype = starting_pattype; /* Reset to same as for writes */
++
++ for (block_base=SDRAM_BASE; block_base < SDRAM_TOP; block_base=block_base + BLOCKSIZE) {
++ switch (pattype) {
++ case PATTYPE_A5 :
++ correct_data = 0xaa55aa55;
++ end_addr = block_base + BLOCKWORDS;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_READ( i, &read_data);
++ if (read_data != correct_data)
++ report_err(i, read_data, correct_data, iteration);
++ }
++ break;
++ case PATTYPE_5A :
++ correct_data = 0x55aa55aa;
++ end_addr = block_base + BLOCKWORDS;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_READ( i, &read_data);
++ if (read_data != correct_data)
++ report_err(i, read_data, correct_data, iteration);
++ }
++ break;
++ case PATTYPE_NO_FF :
++ correct_data = 0x0100FEFF;
++ end_addr = block_base + BLOCKWORDS;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_READ( i, &read_data);
++ if (read_data != correct_data)
++ report_err(i, read_data, correct_data, iteration);
++ correct_data = correct_data + 0xFFFF;
++ }
++ break;
++ case PATTYPE_INCR :
++ end_addr = block_base + BLOCKSIZE;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_READ( i, &read_data);
++ if (read_data != i)
++ report_err(i, read_data, i, iteration);
++ }
++ break;
++ case PATTYPE_DECR :
++ end_addr = block_base + BLOCKSIZE;
++ for (i=block_base; i < end_addr; i=i+4) {
++ SDRAM_READ( i, &read_data);
++ if (read_data != ~i)
++ report_err(i, read_data, ~i, iteration);
++ }
++ break;
++ }
++ }
++
++ pattype = pattype + 1;
++ if (pattype >= NUM_PATTYPES) { pattype = 0; }
++ ++iteration;
++ }
++
++ return 0;
++}
++
++/********************* REPORT ERROR FUNC ********************************************************/
++
++void report_err(unsigned int address, unsigned int bad_data, unsigned int correct_data, unsigned int iteration)
++{
++ volatile unsigned int readvalue;
++
++#ifdef ARM
++ /* ASSERT GPIO */
++ * (volatile unsigned int *) GPIOB_SET_OUTPUT = GPIOB_BIT_34;
++#endif
++
++ /* REPORT ERROR */
++ printf("Wrong on [%08x]= %08x should be %08x on iteration %d\n", address, bad_data, correct_data, iteration );
++
++ /* WRITE TO ANOTHER LOCATION */
++ SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
++
++ /* READ AGAIN */
++ SDRAM_READ(address, &readvalue);
++ if (readvalue != correct_data)
++ printf("Again 1 [%08x]= %08x should be %08x\n", address, readvalue, correct_data );
++
++ /* WRITE TO ANOTHER LOCATION */
++ SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
++
++ /* READ AGAIN */
++ SDRAM_READ(address, &readvalue);
++ if (readvalue != correct_data)
++ printf("Again 2 [%08x]= %08x should be %08x\n", address, readvalue, correct_data );
++
++ /* WRITE TO ANOTHER LOCATION */
++ SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
++
++ /* READ AGAIN */
++ SDRAM_READ(address, &readvalue);
++ if (readvalue != correct_data)
++ printf("Again 3 [%08x]= %08x should be %08x\n", address, readvalue, correct_data );
++
++#ifdef ARM
++ /* DEASSERT GPIO */
++ * (volatile unsigned int *) GPIOB_CLEAR_OUTPUT = GPIOB_BIT_34;
++#endif
++
++} /* end of report_err */
++
++
++
++
++/********************* DMA.C FUNCTIONS ********************************************************/
++
++void ResetDMA( UINT channel ) {
++
++ // Clear and abort the dma channel
++
++ volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
++ dma[0] = (1 << 12);
++ dma[0] &= ~(1 << 12);
++}
++
++
++
++
++void PauseDMA( UINT channel ) {
++
++ // Pause the DMA channel specified
++
++ volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
++ UINT rd;
++
++ rd = dma[0];
++
++ rd |= DMA_PAUSE;
++
++ dma[0] = rd;
++}
++
++
++
++
++void UnPauseDMA( UINT channel ) {
++
++ // UnPause the DMA channel specified
++
++ volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
++ UINT rd;
++
++ rd = dma[0];
++
++ rd &= ~DMA_PAUSE;
++
++ dma[0] = rd;
++}
++
++
++
++
++void SetupDMA( UINT channel,
++ UINT src_addr,
++ UINT dest_addr,
++ UINT byte_count,
++ UINT control,
++ UINT flags ) {
++
++ // Configure a DMA
++
++ volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
++
++ dma[0] = control;
++ dma[1] = src_addr;
++ dma[2] = dest_addr;
++ dma[3] = byte_count | (flags & 0xF0000000);
++}
++
++// EXAMPLE:
++//
++// DMA 2kB from SRAM to SATA core with a write EOT set, and HBURST enabled, using DMA channel 2
++// Then wait for the DMA to complete
++//
++// SetupDMA ( 2 , 0x4C001100, BASE_SATA, 2048, DMA_CTRL_MEM_TO_SATA, WR_EOT | DMA_HBURST_EN );
++// WaitWhileDMABusy( 2 );
++
++int DMABusy(UINT channel)
++{
++ volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
++ return (dma[0] & DMA_IN_PROGRESS ? 1 : 0);
++}
++
++
++void WaitWhileDMABusy( UINT channel ) // Wait while the given DMA channel is busy
++{
++ volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
++ while (dma[0] & DMA_IN_PROGRESS) ; // Do Nothing
++}
++
++void DMAClearIRQ(UINT channel)
++{
++ volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
++ dma[4] = 1; // write any value to offset 0x10 (16 / 4 => 4)
++
++}
++
++void DMAMemCopy ( UINT channel,
++ UINT src_addr,
++ UINT dest_addr,
++ UINT byte_count ) {
++
++ // Perform a memory to memory copy
++
++ volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
++
++ // Choose fastest configuration possible for required transfer
++
++ if (src_addr < SRAM_BASE) {
++ if (dest_addr < SRAM_BASE) {
++ dma[0] = DMA_CTRL_MEM_TO_MEM_AA; // Src and Dest must use A
++ } else {
++ dma[0] = DMA_CTRL_MEM_TO_MEM_AB; // Src must use A
++ }
++ } else {
++ if (dest_addr < SRAM_BASE) {
++ dma[0] = DMA_CTRL_MEM_TO_MEM_BA; // Dest must use A
++ } else {
++ dma[0] = DMA_CTRL_MEM_TO_MEM_AB; // No restriction
++ }
++ }
++
++ dma[1] = src_addr;
++ dma[2] = dest_addr;
++ dma[3] = byte_count | DMA_WR_BUFFERABLE | DMA_HBURST_EN;
++
++ WaitWhileDMABusy( channel );
++}
++
++
++
++
++
++
++
++#define CP15R1_M_ENABLE 0x0001 // MMU Enable
++#define CP15R1_A_ENABLE 0x0002 // Address alignment fault enable
++#define CP15R1_C_ENABLE 0x0004 // (data) cache enable
++#define CP15R1_W_ENABLE 0x0008 // write buffer enable
++#define CP15R1_PROG32 0x0010 // PROG32
++#define CP15R1_DATA32 0x0020 // DATA32
++#define CP15R1_L_ENABLE 0x0040 // Late abort on earlier CPUs
++#define CP15R1_BIGEND 0x0080 // Big-endian (=1), little-endian (=0)
++#define CP15R1_SYSTEM 0x0100 // System bit, modifies MMU protections
++#define CP15R1_ROM 0x0200 // ROM bit, modifies MMU protections
++#define CP15R1_F 0x0400 // Should Be Zero
++#define CP15R1_Z_ENABLE 0x0800 // Branch prediction enable on 810
++#define CP15R1_I_ENABLE 0x1000 // Instruction cache enable
++#define CP15R1_RESERVED 0x00000078
++#define CP15R2_RESERVED 0xFFFFC000
++
++#define NUM_DOMAINS 16
++
++#define DAV_NO_ACCESS 0
++#define DAV_CLIENT 1
++#define DAV_RESERVED 2
++#define DAV_MANAGER 3
++#define NUM_DOMAIN_ACCESS_VALUES 4
++
++#define AP_LEVEL_0 0
++#define AP_LEVEL_1 0
++#define AP_LEVEL_2 0
++#define AP_LEVEL_3 0
++#define NUM_ACCESS_PERMISSIONS 4
++
++#define FAULT_ID 0
++
++#define FLD_COURSE_ID 1
++#define FLD_SECTION_ID 2
++#define FLD_FINE_ID 3
++
++#define FD_USER_DATA_BIT 2
++
++#define FD_USER_DATA_NUM_BITS 30
++
++#define SD_BUFFERABLE_BIT 2
++#define SD_CACHEABLE_BIT 3
++#define SD_IMP_BIT 4
++#define SD_DOMAIN_BIT 5
++#define SD_AP_BIT 10
++#define SD_ADDRESS_BIT 20
++
++#define SD_DOMAIN_NUM_BITS 4
++#define SD_AP_NUM_BITS 2
++
++void CoPro15Regs_SetCP15Reg1(const unsigned long mask) {
++ asm volatile(
++ "MOV r0, %0;"
++ "MRC p15, 0, r1, c1, c0, 0;"
++ "ORR r1,r1,r0;"
++ "MCR p15, 0, r1, c1, c0, 0;"
++ :
++ : "r" (mask | CP15R1_RESERVED)
++ : "r0","r1");
++}
++
++void CoPro15Regs_ClearCP15Reg1(const unsigned long mask) {
++ asm volatile(
++ "MOV r0, %0;"
++ "MRC p15, 0, r1, c1, c0, 0;"
++ "BIC r1,r1,r0;"
++ "MCR p15, 0, r1, c1, c0, 0;"
++ :
++ : "r" (mask)
++ : "r0","r1");
++}
++
++unsigned long CoPro15Regs_GetCP15Reg1(const unsigned long mask) {
++ unsigned long value;
++ asm volatile(
++ "MRC p15, 0, r1, c1, c0, 0;"
++ "MOV r0, %1;"
++ "BIC %0,r1,r0; "
++ : "=r" (value)
++ : "r" (mask)
++ : "r0","r1");
++ return value;
++}
++
++unsigned long CoPro15Regs_GetCP15Reg2(void) {
++ unsigned long value;
++ asm volatile(
++ "MRC p15, 0, r0, c2, c0, 0;"
++ "MOV %0, r0;"
++ : "=r" (value)
++ :
++ : "r0");
++ return value & CP15R2_RESERVED;
++}
++
++unsigned long CoPro15Regs_GetCP15Reg3(void) {
++ unsigned long value;
++ asm volatile(
++ "MRC p15, 0, r0, c3, c0, 0;"
++ "MOV %0, r0;"
++ : "=r" (value)
++ :
++ : "r0");
++ return value;
++}
++
++void CoPro15Regs_SetCP15Reg3(unsigned long value) {
++ asm volatile(
++ "MOV r0, %0;"
++ "MCR p15, 0, r0, c3, c0, 0;"
++ :
++ : "r" (value)
++ : "r0");
++}
++
++void CoPro15Regs_SetCP15Reg2(unsigned long value) {
++ asm volatile(
++ "MOV r0, %0;"
++ "MCR p15, 0, r0, c2, c0, 0;"
++ :
++ : "r" (value & CP15R2_RESERVED)
++ : "r0");
++}
++
++void Cache_CleanDataCache(void)
++{
++ // Clean the data cache - usually precedes a data cache invalidation.
++ // Forces the data cache content to be written to main memory - only
++ // required if using write-back data cache
++ asm volatile(
++ "MOV r3,pc;"
++ "LDR r1, =0;"
++ " MOV r4,pc;"
++ " LDR r0, =0;"
++ " ORR r2, r1, r0;"
++ " MCR p15, 0, r2, c7, c10, 2 ;" // I (BHC) think that this should be c10, 2 not c14, 1 -- See ARM ARM
++ " ADD r0, r0, #0x10;"
++ " CMP r0,#0x40;"
++ " BXNE r4;"
++ " ADD r1, r1, #0x04000000;"
++ " CMP r1, #0x0;"
++ "BXNE r3;"
++ :
++ :
++ : "r0","r1","r2","r3","r4");
++}
++
++void Cache_DrainWriteBuffer(void)
++{
++ // Forces the write buffer to update to main memory
++ asm volatile(
++ "LDR r1, =0;"
++ "MCR p15, 0, r1, c7, c10, 4 ;"
++ :
++ :
++ : "r1");
++}
++
++void Cache_FlushPrefetchBuffer(void)
++{
++ // Forces the CPU to flush the instruction prefetch buffer
++ asm volatile(
++ "LDR r1, =0;"
++ "MCR p15, 0, r1, c7, c5, 4 ;"
++ :
++ :
++ : "r1");
++}
++
++void Cache_InvalidateDataCache(void)
++{
++ asm volatile(
++ "LDR r1, =0;"
++ "MCR p15, 0, r1, c7, c6, 0;"
++ :
++ :
++ : "r1");
++}
++
++void Cache_InvalidateInstructionCache(void)
++{
++ asm volatile(
++ "LDR r1, =0;"
++ "MCR p15, 0, r1, c7, c5, 0;"
++ :
++ :
++ : "r1");
++}
++
++void Cache_InstOn(void)
++{
++ // Invalidate the instruction cache, in case there's anything
++ // left from when it was last enabled
++ Cache_InvalidateInstructionCache();
++
++ // Enable the instruction cache
++ CoPro15Regs_SetCP15Reg1(CP15R1_I_ENABLE);
++}
++
++void Cache_InstOff(void)
++{
++ // Disable the instruction cache
++ CoPro15Regs_ClearCP15Reg1(CP15R1_I_ENABLE);
++}
++
++void Cache_DataOn(void)
++{
++ // Invalidate the data cache, in case there's anything left from when
++ // it was last enabled
++ Cache_InvalidateDataCache();
++
++ // Enable the data cache
++ CoPro15Regs_SetCP15Reg1(CP15R1_C_ENABLE);
++}
++
++void Cache_DataOff(void)
++{
++ // Ensure all data in data cache or write buffer is written to memory
++ Cache_CleanDataCache();
++ Cache_DrainWriteBuffer();
++
++ // Disable the data cache
++ CoPro15Regs_ClearCP15Reg1(CP15R1_C_ENABLE);
++}
++
++void Cache_WriteBufferOn(void)
++{
++ // Enable the write buffer
++ CoPro15Regs_SetCP15Reg1(CP15R1_W_ENABLE);
++}
++
++void Cache_WriteBufferOff(void)
++{
++ // Ensure all data in the write buffer is written to memory
++ Cache_DrainWriteBuffer();
++
++ // Disable the write buffer
++ CoPro15Regs_ClearCP15Reg1(CP15R1_W_ENABLE);
++}
++
++int MMU_SetDomainAccessValue(
++ int domainNumber,
++ int value) {
++ int status = 0;
++ if ((value < NUM_DOMAIN_ACCESS_VALUES) && (domainNumber < NUM_DOMAINS))
++ {
++ // Insert the 2-bit domain field into the slot for the specified domain
++ unsigned long registerContents = CoPro15Regs_GetCP15Reg3();
++ registerContents &= ~(3UL << (2*domainNumber));
++ registerContents |= ((unsigned long)value << (2*domainNumber));
++ CoPro15Regs_SetCP15Reg3(registerContents);
++ status = 1;
++ }
++ return status;
++}
++
++void MMU_SetAlignmentChecked(int alignmentChecked) {
++ alignmentChecked ? CoPro15Regs_SetCP15Reg1(CP15R1_A_ENABLE) : CoPro15Regs_ClearCP15Reg1(CP15R1_A_ENABLE);
++}
++
++void MMU_SetEnabled(int enabled) {
++ enabled ? CoPro15Regs_SetCP15Reg1(CP15R1_M_ENABLE) : CoPro15Regs_ClearCP15Reg1(CP15R1_M_ENABLE);
++}
++void MMU_InvalidateDataTLB(void)
++{
++ asm volatile(
++ "MCR p15, 0, r0, c8, c6, 0;"
++ :
++ :
++ : "r0");
++}
++
++void MMU_InvalidateInstructionTLB(void)
++{
++ asm volatile(
++ "MCR p15, 0, r0, c8, c5, 0;"
++ :
++ :
++ : "r0");
++}
++
++void MMU_SetROMPermission(int rOM_Permitted) {
++ rOM_Permitted ? CoPro15Regs_SetCP15Reg1(CP15R1_ROM) : CoPro15Regs_ClearCP15Reg1(CP15R1_ROM);
++}
++
++void MMU_SetSystemPermission(int systemPermitted) {
++ systemPermitted ? CoPro15Regs_SetCP15Reg1(CP15R1_SYSTEM) : CoPro15Regs_ClearCP15Reg1(CP15R1_SYSTEM);
++}
++
++void MMU_SetTranslationTableBaseAddress(unsigned long *baseAddress) {
++ CoPro15Regs_SetCP15Reg2((unsigned long)baseAddress);
++}
++
++unsigned long SetBit(
++ unsigned long source,
++ int state,
++ int offset)
++{
++ source = state ? (source | (1UL << offset)) :
++ (source & ~(1UL << offset));
++ return source;
++}
++
++unsigned long SetField(
++ unsigned long source,
++ unsigned long newFieldContents,
++ int offset,
++ int length)
++{
++ unsigned long mask = (1UL << length) - 1;
++ source &= ~(mask << offset);
++ source |= ((newFieldContents & mask) << offset);
++ return source;
++}
++
++unsigned long FD_SetUserData(
++ unsigned long userData,
++ unsigned long descriptor)
++{
++ return SetField(descriptor, userData, FD_USER_DATA_BIT, FD_USER_DATA_NUM_BITS);
++}
++
++unsigned long FLPT_CreateFaultDescriptor(unsigned long userData)
++{
++ unsigned long descriptor = FAULT_ID;
++ descriptor = FD_SetUserData(userData, descriptor);
++ return descriptor;
++}
++
++void FLPT_InsertFaultDescriptor(
++ unsigned long *tableBaseAdr,
++ int index,
++ unsigned long descriptor)
++{
++ *(tableBaseAdr + index) = descriptor;
++}
++
++unsigned long SD_SetAccessPermission(
++ int ap,
++ unsigned long descriptor)
++{
++ return SetField(descriptor, ap, SD_AP_BIT, SD_AP_NUM_BITS);
++}
++
++unsigned long SD_SetBaseAddress(
++ unsigned long baseAddress,
++ unsigned long descriptor)
++{
++ unsigned long mask = ~0UL << SD_ADDRESS_BIT;
++ baseAddress &= mask;
++ descriptor &= ~mask;
++ descriptor |= baseAddress;
++ return descriptor;
++}
++
++unsigned long SD_SetBufferable(
++ int bufferable,
++ unsigned long descriptor)
++{
++ return SetBit(descriptor, bufferable, SD_BUFFERABLE_BIT);
++}
++
++unsigned long SD_SetCacheable(
++ int cacheable,
++ unsigned long descriptor)
++{
++ return SetBit(descriptor, cacheable, SD_CACHEABLE_BIT);
++}
++
++unsigned long SD_SetDomain(
++ int domain,
++ unsigned long descriptor)
++{
++ return SetField(descriptor, domain, SD_DOMAIN_BIT, SD_DOMAIN_NUM_BITS);
++}
++
++unsigned long SD_SetImplementationDefined(
++ unsigned long implementationDefined,
++ unsigned long descriptor)
++{
++ return SetBit(descriptor, implementationDefined, SD_IMP_BIT);
++}
++
++unsigned long FLPT_CreateSectionDescriptor(
++ unsigned long baseAddress,
++ unsigned char domain,
++ int implementationDefined,
++ int ap,
++ int bufferable,
++ int cacheable)
++{
++ unsigned long descriptor = FLD_SECTION_ID;
++ descriptor = SD_SetAccessPermission(ap, descriptor);
++ descriptor = SD_SetBaseAddress(baseAddress, descriptor);
++ descriptor = SD_SetBufferable(bufferable, descriptor);
++ descriptor = SD_SetCacheable(cacheable, descriptor);
++ descriptor = SD_SetDomain(domain, descriptor);
++ descriptor = SD_SetImplementationDefined(implementationDefined, descriptor);
++ return descriptor;
++}
++
++void FLPT_InsertSectionDescriptor(
++ unsigned long *tableBaseAdr,
++ int index,
++ unsigned long descriptor)
++{
++ *(tableBaseAdr + index) = descriptor;
++}
++
++void FLPT_Zeroise(
++ unsigned long *base_adr,
++ int numberOfdescriptors) {
++ unsigned long faultDescriptor = FLPT_CreateFaultDescriptor(0);
++ int i;
++ for (i=0; i < numberOfdescriptors; i++) {
++ FLPT_InsertFaultDescriptor(base_adr, i, faultDescriptor);
++ }
++}
++
++void configure_caches(void)
++{
++ // Disable caches
++// Cache_DataOff();
++printf("1");
++ Cache_InstOff();
++// Cache_WriteBufferOff();
++
++ // Disable MMU
++printf("2");
++ MMU_SetEnabled(0);
++printf("3");
++ MMU_InvalidateDataTLB();
++printf("4");
++ MMU_InvalidateInstructionTLB();
++
++ // Setup the MMU
++printf("5");
++ MMU_SetAlignmentChecked(1);
++printf("6");
++ MMU_SetROMPermission(0);
++printf("7");
++ MMU_SetSystemPermission(1);
++
++ // Allow client access to all protection domains
++ int i;
++ for (i=0; i < NUM_DOMAINS; i++) {
++ MMU_SetDomainAccessValue(i, DAV_CLIENT);
++ }
++printf("8");
++
++ // Allocate first level page table, which we'll populate only with section
++ // descriptors, which cover 1MB each. Table must be aligned to a 16KB
++ // boundary.
++ // We'll put it 4KB into the SRAM and it will occupy:
++ // 64 entries for SDRAM
++ // 1 entry for SRAM
++ // 16 entries for APB bridge A
++ // 16 entries for APB bridge B
++ // The largest memory address we need to map is that of the SRAM at
++ // 0x4c000000 -> (4c000000/2^20)*4 = offset 1300h from table start ->
++ // require at least 1300h/4 +1 entries in table = 1217
++ unsigned long *firstLevelPageTableBaseAdr = (unsigned long*)SRAM_BASE;
++ FLPT_Zeroise(firstLevelPageTableBaseAdr, 4096);
++printf("9");
++
++ // Map entire adr space uncached, unbuffered, read/write, virtual == physical
++ unsigned megabytesPresent = 4096;
++ unsigned index = 0;
++ for (i=0; i < megabytesPresent; i++) {
++ FLPT_InsertSectionDescriptor(
++ firstLevelPageTableBaseAdr,
++ index,
++ FLPT_CreateSectionDescriptor(
++ index * 1024 * 1024, // Base address
++ 0, // Domain number
++ 0, // Implementation defined
++ AP_LEVEL_1, // Access permissions
++ 0, // Bufferable
++ 0)); // Cacheable
++
++ ++index;
++ }
++printf("10");
++
++ // Map SDRAM as cached and buffered, read/write, virtual == physical
++ megabytesPresent = 64;
++ index = PHYS_SDRAM_1_PA / (1024 * 1024);
++ for (i=0; i < megabytesPresent; i++) {
++ FLPT_InsertSectionDescriptor(
++ firstLevelPageTableBaseAdr,
++ index,
++ FLPT_CreateSectionDescriptor(
++ index * 1024 * 1024, // Base address
++ 0, // Domain number
++ 0, // Implementation defined
++ AP_LEVEL_1, // Access permissions
++ 1, // Bufferable
++ 1)); // Cacheable
++
++ ++index;
++ }
++printf("11");
++
++ // Map SRAM as cached and buffered, read/write, virtual == physical
++ megabytesPresent = 1; // Actually only 32KB
++ index = SRAM_BASE / (1024 * 1024);
++ for (i=0; i < megabytesPresent; i++) {
++ FLPT_InsertSectionDescriptor(
++ firstLevelPageTableBaseAdr,
++ index,
++ FLPT_CreateSectionDescriptor(
++ index * 1024 * 1024, // Base address
++ 0, // Domain number
++ 0, // Implementation defined
++ AP_LEVEL_1, // Access permissions
++ 1, // Bufferable
++ 1)); // Cacheable
++
++ ++index;
++ }
++printf("12");
++
++ // Map APB bridge A address space as uncached, unbuffered, read/write,
++ // virtual == physical
++ megabytesPresent = 16;
++ index = APB_BRIDGE_A_BASE_PA / (1024 * 1024);
++ for (i=0; i < megabytesPresent; i++) {
++ FLPT_InsertSectionDescriptor(
++ firstLevelPageTableBaseAdr,
++ index,
++ FLPT_CreateSectionDescriptor(
++ index * 1024 * 1024, // Base address
++ 0, // Domain number
++ 0, // Implementation defined
++ AP_LEVEL_1, // Access permissions
++ 0, // Bufferable
++ 0)); // Cacheable
++
++ ++index;
++ }
++printf("13");
++
++ // Map APB bridge B address space as uncached, unbuffered, read/write,
++ // virtual == physical
++ megabytesPresent = 16;
++ index = APB_BRIDGE_B_BASE_PA / (1024 * 1024);
++ for (i=0; i < megabytesPresent; i++) {
++ FLPT_InsertSectionDescriptor(
++ firstLevelPageTableBaseAdr,
++ index,
++ FLPT_CreateSectionDescriptor(
++ index * 1024 * 1024, // Base address
++ 0, // Domain number
++ 0, // Implementation defined
++ AP_LEVEL_1, // Access permissions
++ 0, // Bufferable
++ 0)); // Cacheable
++
++ ++index;
++ }
++printf("14");
++
++ // Load base address of first level page table
++ MMU_SetTranslationTableBaseAddress(firstLevelPageTableBaseAdr);
++printf("15");
++
++ // Enable MMU
++ MMU_SetEnabled(1);
++printf("16");
++
++ // Enable caches
++ Cache_DataOn();
++printf("17");
++ Cache_InstOn();
++printf("18");
++ Cache_WriteBufferOn();
++printf("19");
++}
++
+diff -Nurd u-boot-1.1.2/include/asm-arm/barrier.h u-boot-1.1.2-oxe810/include/asm-arm/barrier.h
+--- u-boot-1.1.2/include/asm-arm/barrier.h 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/include/asm-arm/barrier.h 2008-06-11 17:55:08.000000000 +0200
+@@ -0,0 +1,25 @@
++#if !defined(__BARRIER_H__)
++#define __BARRIER_H__
++
++static inline void rmb(void)
++{
++ asm volatile ("" : : : "memory");
++}
++
++/*
++ * wmb() Would normally need to ensure shared memory regions are marked as
++ * non-cacheable and non-bufferable, then the work to be done by wmb() is
++ * to ensure the compiler and any possible CPU out of order writes are
++ * flushed to memory, however we have no data cache and as far as I'm
++ * aware we can't use the MMU to set page properties, so in our case wmb()
++ * must cause the compiler to flush.
++ */
++
++static inline void wmb(void)
++{
++ // Cause the compiler to flush any registers containing pending write data
++ // to memory
++ asm volatile ("" : : : "memory");
++
++}
++#endif // #if !defined(__BARRIER_H__)
+diff -Nurd u-boot-1.1.2/include/asm-arm/global_data.h u-boot-1.1.2-oxe810/include/asm-arm/global_data.h
+--- u-boot-1.1.2/include/asm-arm/global_data.h 2003-10-10 12:05:43.000000000 +0200
++++ u-boot-1.1.2-oxe810/include/asm-arm/global_data.h 2008-06-11 17:55:08.000000000 +0200
+@@ -61,6 +61,7 @@
+ #define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */
+ #define GD_FLG_SILENT 0x00004 /* Silent mode */
+
+-#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
++#define DECLARE_GLOBAL_DATA_PTR register gd_t* volatile gd asm ("r8");
+
+ #endif /* __ASM_GBL_DATA_H */
++
+diff -Nurd u-boot-1.1.2/include/asm-arm/mach-types.h u-boot-1.1.2-oxe810/include/asm-arm/mach-types.h
+--- u-boot-1.1.2/include/asm-arm/mach-types.h 2004-10-10 20:41:14.000000000 +0200
++++ u-boot-1.1.2-oxe810/include/asm-arm/mach-types.h 2008-06-11 17:55:08.000000000 +0200
+@@ -624,6 +624,7 @@
+ #define MACH_TYPE_RMS100 611
+ #define MACH_TYPE_KB9200 612
+ #define MACH_TYPE_SX1 613
++#define MACH_TYPE_OXNAS 1152
+
+ #ifdef CONFIG_ARCH_EBSA110
+ # ifdef machine_arch_type
+@@ -7945,6 +7946,18 @@
+ # define machine_is_sx1() (0)
+ #endif
+
++#ifdef CONFIG_MACH_OXNAS
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_OXNAS
++# endif
++# define machine_is_oxnas() (machine_arch_type == MACH_TYPE_OXNAS)
++#else
++# define machine_is_oxnas() (0)
++#endif
++
+ /*
+ * These have not yet been registered
+ */
+diff -Nurd u-boot-1.1.2/include/asm-arm/u-boot.h u-boot-1.1.2-oxe810/include/asm-arm/u-boot.h
+--- u-boot-1.1.2/include/asm-arm/u-boot.h 2002-11-03 01:33:10.000000000 +0100
++++ u-boot-1.1.2-oxe810/include/asm-arm/u-boot.h 2008-06-11 17:55:08.000000000 +0200
+@@ -41,6 +41,8 @@
+ 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 */
+ } bd_t;
+
+ #define bi_env_data bi_env->data
+diff -Nurd u-boot-1.1.2/include/ata.h u-boot-1.1.2-oxe810/include/ata.h
+--- u-boot-1.1.2/include/ata.h 2004-03-14 23:25:50.000000000 +0100
++++ u-boot-1.1.2-oxe810/include/ata.h 2008-06-11 17:55:11.000000000 +0200
+@@ -80,7 +80,12 @@
+ /*
+ * Device / Head Register Bits
+ */
++#ifdef CONFIG_OXNAS
++#define ATA_DEVICE(x) (0)
++#else
+ #define ATA_DEVICE(x) ((x & 1)<<4)
++#endif // CONFIG_OXNAS
++
+ #define ATA_LBA 0xE0
+
+ /*
+diff -Nurd u-boot-1.1.2/include/cmd_confdefs.h u-boot-1.1.2-oxe810/include/cmd_confdefs.h
+--- u-boot-1.1.2/include/cmd_confdefs.h 2004-12-16 18:59:53.000000000 +0100
++++ u-boot-1.1.2-oxe810/include/cmd_confdefs.h 2008-06-11 17:55:11.000000000 +0200
+@@ -92,6 +92,7 @@
+ #define CFG_CMD_XIMG 0x0400000000000000ULL /* Load part of Multi Image */
+ #define CFG_CMD_UNIVERSE 0x0800000000000000ULL /* Tundra Universe Support */
+ #define CFG_CMD_EXT2 0x1000000000000000ULL /* EXT2 Support */
++#define CFG_CMD_LEDFAIL 0x2000000000000000ULL /* OXNAS Failure LED support */
+
+ #define CFG_CMD_ALL 0xFFFFFFFFFFFFFFFFULL /* ALL commands */
+
+diff -Nurd u-boot-1.1.2/include/common.h u-boot-1.1.2-oxe810/include/common.h
+--- u-boot-1.1.2/include/common.h 2004-12-13 10:49:01.000000000 +0100
++++ u-boot-1.1.2-oxe810/include/common.h 2008-06-11 17:55:11.000000000 +0200
+@@ -204,7 +204,7 @@
+ /* common/cmd_nvedit.c */
+ int env_init (void);
+ void env_relocate (void);
+-char *getenv (uchar *);
++char *getenv (const uchar *);
+ int getenv_r (uchar *name, uchar *buf, unsigned len);
+ int saveenv (void);
+ #ifdef CONFIG_PPC /* ARM version to be fixed! */
+diff -Nurd u-boot-1.1.2/include/configs/oxnas.h u-boot-1.1.2-oxe810/include/configs/oxnas.h
+--- u-boot-1.1.2/include/configs/oxnas.h 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-1.1.2-oxe810/include/configs/oxnas.h 2008-06-12 13:57:57.000000000 +0200
+@@ -0,0 +1,593 @@
++/*
++ * (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))
++
++#define CFG_FLASH_EMPTY_INFO
++
++/**
++ * Architecture
++ */
++#define CONFIG_ARM926EJS 1
++#define CONFIG_OXNAS 1
++#define CONFIG_OXNAS_ENABLE_PCI /* Enables PCI clock and takes out of reset - needed if require access to static bus */
++#define CONFIG_OXNAS_FEEDBACK_PCI_CLKS /* Feedback PCI clock out 3 to drive PCI core clock - needed if require access to static bus */
++#define CONFIG_OXNAS_MANUAL_STATIC_ARBITRATION
++#if (USE_SATA == 1)
++#define CONFIG_OXNAS_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 CFG_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 CFG_CLKS_IN_HZ
++
++#define CFG_HUSH_PARSER 1
++#define CFG_PROMPT_HUSH_PS2 "> "
++
++/* Miscellaneous configurable options */
++#define CFG_LONGHELP /* undef to save memory */
++#ifdef CFG_HUSH_PARSER
++#define CFG_PROMPT "$ " /* Monitor Command Prompt */
++#else
++#define CFG_PROMPT "# " /* Monitor Command Prompt */
++#endif
++#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
++
++/* Print Buffer Size */
++#define CFG_PBSIZE ((CFG_CBSIZE)+sizeof(CFG_PROMPT)+16)
++#define CFG_MAXARGS 16 /* max number of command args */
++#define CFG_BARGSIZE (CFG_CBSIZE) /* Boot Argument Buffer Size */
++
++#define 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
++#define CFG_SRAM_BASE ((PHYS_SDRAM_1_PA) + (PHYS_SDRAM_1_MAX_SIZE))
++#if (NAS_VERSION == 810)
++#define CFG_SRAM_SIZE (128 * 1024)
++#endif // NAS_VERSION
++
++#define INITIALISE_SDRAM
++
++/* Default location from which bootm etc will load */
++#define CFG_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 CFG_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 CFG_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_2_OE ((GPIO_2_PA) + 0x4)
++#define GPIO_2_SET_OE ((GPIO_2_PA) + 0x1C)
++#define GPIO_2_CLR_OE ((GPIO_2_PA) + 0x20)
++
++/**
++ * 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 CFG_NS16550 1
++#define CFG_NS16550_SERIAL 1
++#define CFG_NS16550_REG_SIZE 1
++
++#if (USE_EXTERNAL_UART != 0)
++#define CFG_NS16550_CLK 16000000
++#define CFG_NS16550_COM1 (EXT_UART_BASE)
++#else // USE_EXTERNAL_UART
++#define CFG_NS16550_CLK (NOMINAL_SYSCLK)
++#define USE_UART_FRACTIONAL_DIVIDER
++#if (INTERNAL_UART == 1)
++#define CONFIG_OXNAS_UART1
++#define CFG_NS16550_COM1 (UART_1_BASE)
++#elif (INTERNAL_UART == 2)
++#define CONFIG_OXNAS_UART2
++#define CFG_NS16550_COM1 (UART_2_BASE)
++#elif (INTERNAL_UART == 3)
++#define CONFIG_OXNAS_UART3
++#define CFG_NS16550_COM1 (UART_3_BASE)
++#else
++#define CONFIG_OXNAS_UART4
++#define CFG_NS16550_COM1 (UART_4_BASE)
++#endif // CONFIG_OXNAS_UART
++#endif // USE_EXTERNAL_UART
++
++#define CONFIG_CONS_INDEX 1
++#define CONFIG_BAUDRATE 115200
++#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/**
++ * Monitor commands
++ */
++#define BASE_COMMANDS (CFG_CMD_IMI | \
++ CFG_CMD_IMLS | \
++ CFG_CMD_BDI | \
++ CFG_CMD_NET | \
++ CFG_CMD_PING | \
++ CFG_CMD_ENV | \
++ CFG_CMD_RUN | \
++ CFG_CMD_MEMORY)
++
++#ifdef CFG_NO_FLASH
++#define FLASH_COMMANDS (BASE_COMMANDS)
++#else
++#define FLASH_COMMANDS (BASE_COMMANDS | CFG_CMD_FLASH)
++#endif // CFG_NO_FLASH
++
++#ifdef CONFIG_OXNAS_USE_SATA
++#define SATA_COMMANDS (FLASH_COMMANDS | CFG_CMD_IDE | CFG_CMD_EXT2 | CFG_CMD_LEDFAIL)
++#else
++#define SATA_COMMANDS (FLASH_COMMANDS)
++#endif // CONFIG_OXNAS_USE_SATA
++
++#define CONFIG_COMMANDS SATA_COMMANDS
++
++/* 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
++#define CONFIG_BOOTARGS LINUX_ROOT_DEVICE " console=ttyS0,115200 elevator=cfq gmac.mac_adr=0x00,0x30,0xe0,0x00,0x00,0x01"
++
++#ifdef CONFIG_OXNAS_USE_SATA
++#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 12c 1644\0" \
++ "load2=ide read 0x48500000 2a6e 1644\0" \
++ "lightled=ledfail 1\0" \
++ "extinguishled=ledfail 0\0" \
++ "boot=bootm 48500000\0"
++#else // CONFIG_OXNAS_USE_SATA
++#define CONFIG_BOOTDELAY 15
++#define CONFIG_BOOTCOMMAND "bootm 0x41020000"
++#endif // CONFIG_OXNAS_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 CFG_AUTOLOAD "n"
++#define CONFIG_NET_RETRY_COUNT 30
++
++/**
++ * Flash support
++ */
++#ifndef CFG_NO_FLASH
++
++#define FORCE_TOP_BOOT_FLASH 1
++
++#define CFG_FLASH_CFI 1
++#define CFG_FLASH_CFI_DRIVER 1
++
++#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 CFG_MAX_FLASH_SECT (NUM_FLASH_MAIN_BLOCKS + NUM_FLASH_PARAM_BLOCKS)
++
++#define CFG_MAX_FLASH_BANKS 1 /* Assume counts flash devices */
++#define FLASH_BASE_OFF 0
++#define CFG_FLASH_BASE ((STATIC_CS0_BASE_PA) + (FLASH_BASE_OFF))
++#define PHYS_FLASH_1 (CFG_FLASH_BASE)
++
++#define CFG_FLASH_ERASE_TOUT (20*CFG_HZ) /* Timeout for Flash Erase */
++#define CFG_FLASH_WRITE_TOUT (20*CFG_HZ) /* Timeout for Flash Write */
++#define CFG_FLASH_WRITE_ATTEMPTS 5
++
++#define STATIC_BUS_FLASH_CONFIG 0x4f1f3f3f /* Slow ASIC settings */
++
++#endif // !CFG_NO_FLASH
++
++/**
++ * Environment organization
++ */
++#ifdef ENV_ON_SATA
++
++/* Environment on SATA disk */
++#define SIZE_TO_SECTORS(x) ((x) / 512)
++#define CFG_ENV_IS_IN_DISK
++#define CFG_ENV_SIZE (8*1024)
++#define ENVIRONMENT_OFFSET ((CFG_SRAM_SIZE) - (CFG_ENV_SIZE) - 1024)
++#define CFG_ENV_ADDR ((CFG_SRAM_BASE) + (ENVIRONMENT_OFFSET))
++#define ROM_LOADER_LOAD_START_SECTOR 1
++#define CFG_ENV_DISK_SECTOR ((ROM_LOADER_LOAD_START_SECTOR) + SIZE_TO_SECTORS(ENVIRONMENT_OFFSET))
++#define ROM_LOADER_LOAD_REDUNDANT_START_SECTOR 10608
++#define CFG_ENV_DISK_REDUNDANT_SECTOR ((ROM_LOADER_LOAD_REDUNDANT_START_SECTOR) + SIZE_TO_SECTORS(ENVIRONMENT_OFFSET))
++
++#else
++/** 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. CFG_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 CFG_ENV_IS_IN_FLASH
++/* Environment in flash device parameter blocks */
++#define CFG_ENV_SECT_SIZE (8*1024)
++/* First parameter block for environment */
++#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
++/* Second parameter block for backup environment */
++#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE)
++/* Main environment occupies first parameter block */
++#define CFG_ENV_ADDR ((CFG_FLASH_BASE)+((NUM_FLASH_MAIN_BLOCKS)*(FLASH_MAIN_BLOCK_SIZE)))
++/* Backup environment occupies second parameter block */
++#define CFG_ENV_ADDR_REDUND ((CFG_ENV_ADDR)+(CFG_ENV_SIZE))
++
++#endif // ENV_ON_SATA
++
++#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 oxnas_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
++
++/* Size of malloc() pool */
++#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024)
++#define CFG_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 (CFG_SRAM_BASE)
++
++/**
++ * Disk related stuff
++ */
++#define CONFIG_LBA48
++#define CONFIG_DOS_PARTITION
++#define CFG_IDE_MAXDEVICE 2
++#define CFG_IDE_MAXBUS 1
++#define CONFIG_IDE_PREINIT
++#undef CONFIG_IDE_RESET
++#undef CONFIG_IDE_LED
++#define CFG_ATA_DATA_OFFSET 0
++#define CFG_ATA_REG_OFFSET 0
++#define CFG_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-1.1.2/include/_exports.h u-boot-1.1.2-oxe810/include/_exports.h
+--- u-boot-1.1.2/include/_exports.h 2003-09-12 17:35:33.000000000 +0200
++++ u-boot-1.1.2-oxe810/include/_exports.h 2008-06-11 17:55:11.000000000 +0200
+@@ -12,6 +12,7 @@
+ EXPORT_FUNC(get_timer)
+ EXPORT_FUNC(vprintf)
+ EXPORT_FUNC(do_reset)
++EXPORT_FUNC(raise)
+ #if (CONFIG_COMMANDS & CFG_CMD_I2C)
+ EXPORT_FUNC(i2c_write)
+ EXPORT_FUNC(i2c_read)
+diff -Nurd u-boot-1.1.2/include/flash.h u-boot-1.1.2-oxe810/include/flash.h
+--- u-boot-1.1.2/include/flash.h 2004-12-16 19:01:48.000000000 +0100
++++ u-boot-1.1.2-oxe810/include/flash.h 2008-06-11 17:55:11.000000000 +0200
+@@ -207,6 +207,7 @@
+ #define ATM_ID_BV1614 0x000000C0 /* 49BV1614 ID */
+ #define ATM_ID_BV1614A 0x000000C8 /* 49BV1614A ID */
+ #define ATM_ID_BV6416 0x000000D6 /* 49BV6416 ID */
++#define ATM_ID_BV322 0x000000c9 /* 49BV322A ID */
+
+ #define FUJI_ID_29F800BA 0x22582258 /* MBM29F800BA ID (8M) */
+ #define FUJI_ID_29F800TA 0x22D622D6 /* MBM29F800TA ID (8M) */
+@@ -405,6 +406,7 @@
+ #define FLASH_MAN_INTEL 0x00300000
+ #define FLASH_MAN_MT 0x00400000
+ #define FLASH_MAN_SHARP 0x00500000
++#define FLASH_MAN_ATM 0x00070000 /* Atmel */
+
+
+ #define FLASH_TYPEMASK 0x0000FFFF /* extract FLASH type information */
+diff -Nurd u-boot-1.1.2/include/ns16550.h u-boot-1.1.2-oxe810/include/ns16550.h
+--- u-boot-1.1.2/include/ns16550.h 2004-06-07 01:13:57.000000000 +0200
++++ u-boot-1.1.2-oxe810/include/ns16550.h 2008-06-11 17:55:11.000000000 +0200
+@@ -19,6 +19,10 @@
+ unsigned char lsr; /* 5 */
+ unsigned char msr; /* 6 */
+ unsigned char scr; /* 7 */
++#if defined(CONFIG_OXNAS)
++ unsigned char ext; /* 8 */
++ unsigned char dlf; /* 9 */
++#endif
+ #if defined(CONFIG_OMAP730)
+ unsigned char mdr1; /* 8 */
+ unsigned char reg9; /* 9 */
+diff -Nurd u-boot-1.1.2/lib_arm/board.c u-boot-1.1.2-oxe810/lib_arm/board.c
+--- u-boot-1.1.2/lib_arm/board.c 2004-08-02 00:48:22.000000000 +0200
++++ u-boot-1.1.2-oxe810/lib_arm/board.c 2008-06-11 17:55:06.000000000 +0200
+@@ -39,6 +39,9 @@
+ #include "../drivers/lan91c96.h"
+ #endif
+
++DECLARE_GLOBAL_DATA_PTR
++
++
+ #if (CONFIG_COMMANDS & CFG_CMD_NAND)
+ void nand_init (void);
+ #endif
+@@ -106,7 +109,6 @@
+
+ static int init_baudrate (void)
+ {
+- DECLARE_GLOBAL_DATA_PTR;
+
+ uchar tmp[64]; /* long enough for environment variables */
+ int i = getenv_r ("baudrate", tmp, sizeof (tmp));
+@@ -142,16 +144,18 @@
+ */
+ static int display_dram_config (void)
+ {
+- DECLARE_GLOBAL_DATA_PTR;
+ int i;
+
+ puts ("RAM Configuration:\n");
+
+ for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
+- printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
++ printf ("\tBank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
+ print_size (gd->bd->bi_dram[i].size, "\n");
+ }
+
++ puts("SRAM Configuration:\n");
++ printf("\t%dKB at 0x%08x\n", gd->bd->bi_sramsize >> 10, gd->bd->bi_sramstart);
++
+ return (0);
+ }
+
+@@ -191,6 +195,12 @@
+ cpu_init, /* basic cpu dependent setup */
+ board_init, /* basic board dependent setup */
+ interrupt_init, /* set up exceptions */
++#ifdef CONFIG_OXNAS
++ /* Need early console to see SATA env. load messages */
++ init_baudrate, /* initialze baudrate settings */
++ serial_init, /* serial communications setup */
++ console_init_f, /* stage 1 init of console */
++#endif // CONFIG_OXNAS
+ env_init, /* initialize environment */
+ init_baudrate, /* initialze baudrate settings */
+ serial_init, /* serial communications setup */
+@@ -206,7 +216,6 @@
+
+ void start_armboot (void)
+ {
+- DECLARE_GLOBAL_DATA_PTR;
+
+ ulong size;
+ init_fnc_t **init_fnc_ptr;
+@@ -232,9 +241,11 @@
+ }
+ }
+
++#ifndef CFG_NO_FLASH
+ /* configure available FLASH banks */
+ size = flash_init ();
+ display_flash_config (size);
++#endif // CFG_NO_FLASH
+
+ #ifdef CONFIG_VFD
+ # ifndef PAGE_SIZE
+@@ -354,6 +365,12 @@
+ {
+ puts ("### ERROR ### Please RESET the board ###\n");
+ for (;;);
++}
++
++void raise (int n)
++{
++ puts ("### ERROR ### Please RESET the board ###\n");
++ for (;;);
+ }
+
+ #ifdef CONFIG_MODEM_SUPPORT
+diff -Nurd u-boot-1.1.2/MAKEALL u-boot-1.1.2-oxe810/MAKEALL
+--- u-boot-1.1.2/MAKEALL 2004-12-31 10:32:48.000000000 +0100
++++ u-boot-1.1.2-oxe810/MAKEALL 2008-06-11 17:55:31.000000000 +0200
+@@ -154,7 +154,7 @@
+ lpd7a400 mx1ads mx1fs2 omap1510inn \
+ omap1610h2 omap1610inn omap730p2 scb9328 \
+ smdk2400 smdk2410 trab VCMA9 \
+- versatile \
++ versatile oxnas \
+ "
+
+ #########################################################################
+diff -Nurd u-boot-1.1.2/Makefile u-boot-1.1.2-oxe810/Makefile
+--- u-boot-1.1.2/Makefile 2004-12-19 10:58:11.000000000 +0100
++++ u-boot-1.1.2-oxe810/Makefile 2008-06-11 17:55:31.000000000 +0200
+@@ -1296,6 +1296,9 @@
+ SX1_config : unconfig
+ @./mkconfig $(@:_config=) arm arm925t sx1
+
++oxnas_config : unconfig
++ @./mkconfig $(@:_config=) arm arm926ejs oxnas
++
+ # TRAB default configuration: 8 MB Flash, 32 MB RAM
+ trab_config \
+ trab_bigram_config \
+@@ -1561,11 +1564,12 @@
+ clean:
+ find . -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
+ rm -f examples/hello_world examples/timer \
+ examples/eepro100_eeprom examples/sched \
+- examples/mem_to_mem_idma2intr examples/82559_eeprom
++ examples/mem_to_mem_idma2intr examples/82559_eeprom \
++ examples/mem_test
+ rm -f tools/img2srec tools/mkimage tools/envcrc tools/gen_eth_addr
+ rm -f tools/mpc86x_clk tools/ncb
+ rm -f tools/easylogo/easylogo tools/bmp_logo
+diff -Nurd u-boot-1.1.2/net/net.c u-boot-1.1.2-oxe810/net/net.c
+--- u-boot-1.1.2/net/net.c 2004-10-12 00:51:14.000000000 +0200
++++ u-boot-1.1.2-oxe810/net/net.c 2008-06-11 17:55:11.000000000 +0200
+@@ -225,7 +225,7 @@
+ return;
+
+ t = get_timer(0);
+-
++
+ /* check for arp timeout */
+ if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ) {
+ NetArpWaitTry++;
+@@ -235,6 +235,7 @@
+ NetArpWaitTry = 0;
+ NetStartAgain();
+ } else {
++ puts ("\nARP Resend request\n");
+ NetArpWaitTimerStart = t;
+ ArpRequest();
+ }
+@@ -738,7 +739,7 @@
+ #if defined(CONFIG_NET_MULTI)
+ printf ("Using %s device\n", eth_get_name());
+ #endif /* CONFIG_NET_MULTI */
+- NetSetTimeout (10 * CFG_HZ, PingTimeout);
++ NetSetTimeout (30 * CFG_HZ, PingTimeout);
+ NetSetHandler (PingHandler);
+
+ PingSend();
+@@ -1384,7 +1385,7 @@
+ */
+ /* XXX point to ip packet */
+ (*packetHandler)((uchar *)ip, 0, 0, 0);
+- break;
++ return;/**break; BHC Changed to remove second invocation of ping handler below */
+ #endif
+ default:
+ return;
+@@ -1492,10 +1493,11 @@
+ NetCksum(uchar * ptr, int len)
+ {
+ ulong xsum;
++ ushort *s = ptr;
+
+ xsum = 0;
+ while (len-- > 0)
+- xsum += *((ushort *)ptr)++;
++ xsum += *s++;
+ xsum = (xsum & 0xffff) + (xsum >> 16);
+ xsum = (xsum & 0xffff) + (xsum >> 16);
+ return (xsum & 0xffff);
+diff -Nurd u-boot-1.1.2/net/tftp.c u-boot-1.1.2-oxe810/net/tftp.c
+--- u-boot-1.1.2/net/tftp.c 2004-04-15 23:48:55.000000000 +0200
++++ u-boot-1.1.2-oxe810/net/tftp.c 2008-06-11 17:55:11.000000000 +0200
+@@ -106,6 +106,7 @@
+ volatile uchar * pkt;
+ volatile uchar * xp;
+ int len = 0;
++ volatile ushort * s;
+
+ /*
+ * We will always be sending some sort of packet, so
+@@ -117,7 +118,9 @@
+
+ case STATE_RRQ:
+ xp = pkt;
+- *((ushort *)pkt)++ = htons(TFTP_RRQ);
++ s = (ushort *)pkt;
++ *s++ = htons(TFTP_RRQ);
++ pkt = (uchar *)s;
+ strcpy ((char *)pkt, tftp_filename);
+ pkt += strlen(tftp_filename) + 1;
+ strcpy ((char *)pkt, "octet");
+@@ -135,15 +138,19 @@
+ case STATE_DATA:
+ case STATE_OACK:
+ xp = pkt;
+- *((ushort *)pkt)++ = htons(TFTP_ACK);
+- *((ushort *)pkt)++ = htons(TftpBlock);
++ s = (ushort *)pkt;
++ *s++ = htons(TFTP_ACK);
++ *s++ = htons(TftpBlock);
++ pkt = (uchar *)s;
+ len = pkt - xp;
+ break;
+
+ case STATE_TOO_LARGE:
+ xp = pkt;
+- *((ushort *)pkt)++ = htons(TFTP_ERROR);
+- *((ushort *)pkt)++ = htons(3);
++ s = (ushort *)pkt;
++ *s++ = htons(TFTP_ERROR);
++ *s++ = htons(3);
++ pkt = (uchar *)s;
+ strcpy ((char *)pkt, "File too large");
+ pkt += 14 /*strlen("File too large")*/ + 1;
+ len = pkt - xp;
+@@ -151,8 +158,10 @@
+
+ case STATE_BAD_MAGIC:
+ xp = pkt;
+- *((ushort *)pkt)++ = htons(TFTP_ERROR);
+- *((ushort *)pkt)++ = htons(2);
++ s = (ushort *)pkt;
++ *s++ = htons(TFTP_ERROR);
++ *s++ = htons(2);
++ pkt = (uchar *)s;
+ strcpy ((char *)pkt, "File has bad magic");
+ pkt += 18 /*strlen("File has bad magic")*/ + 1;
+ len = pkt - xp;
+@@ -167,6 +176,7 @@
+ TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
+ {
+ ushort proto;
++ ushort *s;
+
+ if (dest != TftpOurPort) {
+ return;
+@@ -180,7 +190,9 @@
+ }
+ len -= 2;
+ /* warning: don't use increment (++) in ntohs() macros!! */
+- proto = *((ushort *)pkt)++;
++ s = (ushort *)pkt;
++ proto = *s++;
++ pkt = (uchar *)s;
+ switch (ntohs(proto)) {
+
+ case TFTP_RRQ: