diff options
author | Steffen Sledz <sledz@DResearch.DE> | 2008-11-17 11:25:57 +0100 |
---|---|---|
committer | Robert Schuster <rschus@entw2.(none)> | 2008-11-17 13:36:24 +0100 |
commit | cba4dd0420896326f1e9438408ce64977bcfaa1f (patch) | |
tree | 85458b255d5c07c805860a1f16e91bc48bf6b175 /packages/u-boot | |
parent | 1143644394a99d16c8d04ad9a34b4110f16a458b (diff) |
oxe810.conf: New machine configuration.
linux 2.6.24: Added patch to support oxe810.
u-boot 1.1.2: Added patch to support oxe810.
Diffstat (limited to 'packages/u-boot')
-rw-r--r-- | packages/u-boot/u-boot-1.1.2/oxe810.patch | 7257 |
1 files changed, 7257 insertions, 0 deletions
diff --git a/packages/u-boot/u-boot-1.1.2/oxe810.patch b/packages/u-boot/u-boot-1.1.2/oxe810.patch new file mode 100644 index 0000000000..f1fff14822 --- /dev/null +++ b/packages/u-boot/u-boot-1.1.2/oxe810.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: |