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