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