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 +#include +#include +#include + +//#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 + +#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 + +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, +# +# 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 + +#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 +#include + +/* 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 +#include + +/* 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, + * + * 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 (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 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 +#include + +#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 + +#if defined(CFG_ENV_IS_IN_DISK) + +#include +#include +#include + +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 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 + #include + + #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 + #include + /* 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 + +/** + * 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; ibd->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: