summaryrefslogtreecommitdiff
path: root/board/omap3430labrador/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/omap3430labrador/mem.c')
-rw-r--r--board/omap3430labrador/mem.c414
1 files changed, 414 insertions, 0 deletions
diff --git a/board/omap3430labrador/mem.c b/board/omap3430labrador/mem.c
new file mode 100644
index 0000000000..b0f4125dc4
--- /dev/null
+++ b/board/omap3430labrador/mem.c
@@ -0,0 +1,414 @@
+/*
+ * (C) Copyright 2004-2006
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/arch/cpu.h>
+#include <asm/io.h>
+#include <asm/arch/bits.h>
+#include <asm/arch/clocks.h>
+#include <asm/arch/mem.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/sys_info.h>
+#include <environment.h>
+#include <command.h>
+
+/****** DATA STRUCTURES ************/
+
+/* Only One NAND allowed on board at a time.
+ * The GPMC CS Base for the same
+ */
+unsigned int nand_cs_base = 0;
+unsigned int onenand_cs_base = 0;
+unsigned int boot_flash_base = 0;
+unsigned int boot_flash_off = 0;
+unsigned int boot_flash_sec = 0;
+volatile unsigned int boot_flash_env_addr = 0;
+/* help common/env_flash.c */
+#ifdef ENV_IS_VARIABLE
+
+ulong NOR_FLASH_BANKS_LIST[CFG_MAX_FLASH_BANKS];
+
+int NOR_MAX_FLASH_BANKS = 0 ; /* max number of flash banks */
+
+uchar(*boot_env_get_char_spec) (int index);
+int (*boot_env_init) (void);
+int (*boot_saveenv) (void);
+void (*boot_env_relocate_spec) (void);
+
+/* StrataNor */
+extern uchar flash_env_get_char_spec(int index);
+extern int flash_env_init(void);
+extern int flash_saveenv(void);
+extern void flash_env_relocate_spec(void);
+extern char *flash_env_name_spec;
+
+/* 16 bit NAND */
+extern uchar nand_env_get_char_spec(int index);
+extern int nand_env_init(void);
+extern int nand_saveenv(void);
+extern void nand_env_relocate_spec(void);
+extern char *nand_env_name_spec;
+
+/* Global fellows */
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+u8 is_nand = 0;
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_FLASH)
+u8 is_flash = 0;
+#endif
+
+char *env_name_spec = 0;
+/* update these elsewhere */
+env_t *env_ptr = 0;
+
+#if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_FLASH)) == (CFG_CMD_ENV|CFG_CMD_FLASH))
+extern env_t *flash_addr;
+#endif
+
+#endif /* ENV_IS_VARIABLE */
+
+static u32 gpmc_enet[GPMC_MAX_REG] = {
+ LAB_ENET_GPMC_CONFIG1,
+ LAB_ENET_GPMC_CONFIG2,
+ LAB_ENET_GPMC_CONFIG3,
+ LAB_ENET_GPMC_CONFIG4,
+ LAB_ENET_GPMC_CONFIG5,
+ LAB_ENET_GPMC_CONFIG6, 0
+};
+
+static u32 gpmc_stnor[GPMC_MAX_REG] = {
+ STNOR_GPMC_CONFIG1,
+ STNOR_GPMC_CONFIG2,
+ STNOR_GPMC_CONFIG3,
+ STNOR_GPMC_CONFIG4,
+ STNOR_GPMC_CONFIG5,
+ STNOR_GPMC_CONFIG6, 0
+};
+
+static u32 gpmc_m_nand[GPMC_MAX_REG] = {
+ M_NAND_GPMC_CONFIG1,
+ M_NAND_GPMC_CONFIG2,
+ M_NAND_GPMC_CONFIG3,
+ M_NAND_GPMC_CONFIG4,
+ M_NAND_GPMC_CONFIG5,
+ M_NAND_GPMC_CONFIG6, 0
+};
+
+/********** Functions ****/
+
+/* ENV Functions */
+#ifdef ENV_IS_VARIABLE
+uchar env_get_char_spec(int index)
+{
+ if (!boot_env_get_char_spec) {
+ puts("ERROR!! env_get_char_spec not available\n");
+ } else
+ return boot_env_get_char_spec(index);
+ return 0;
+}
+int env_init(void)
+{
+ if (!boot_env_init) {
+ puts("ERROR!! boot_env_init not available\n");
+ } else
+ return boot_env_init();
+ return -1;
+}
+int saveenv(void)
+{
+ if (!boot_saveenv) {
+ puts("ERROR!! boot_saveenv not available\n");
+ } else
+ return boot_saveenv();
+ return -1;
+}
+void env_relocate_spec(void)
+{
+ if (!boot_env_relocate_spec) {
+ puts("ERROR!! boot_env_relocate_spec not available\n");
+ } else
+ boot_env_relocate_spec();
+}
+#endif
+
+
+/**************************************************************************
+ * make_cs1_contiguous() - for es2 and above remap cs1 behind cs0 to allow
+ * command line mem=xyz use all memory with out discontinuous support
+ * compiled in. Could do it at the ATAG, but there really is two banks...
+ * Called as part of 2nd phase DDR init.
+ **************************************************************************/
+void make_cs1_contiguous(void)
+{
+ u32 size, a_add_low, a_add_high;
+
+ size = get_sdr_cs_size(SDRC_CS0_OSET);
+ size /= SZ_32M; /* find size to offset CS1 */
+ a_add_high = (size & 3) << 8; /* set up low field */
+ a_add_low = (size & 0x3C) >> 2; /* set up high field */
+ __raw_writel((a_add_high | a_add_low), SDRC_CS_CFG);
+
+}
+
+/********************************************************
+ * mem_ok() - test used to see if timings are correct
+ * for a part. Helps in guessing which part
+ * we are currently using.
+ *******************************************************/
+u32 mem_ok(void)
+{
+ u32 val1, val2, orig1, orig2, addr;
+ u32 pattern = 0x12345678;
+
+ addr = OMAP34XX_SDRC_CS0;
+
+ orig1 = __raw_readl(addr + 0x400); /* try to save original value */
+ orig2 = __raw_readl(addr);
+ __raw_writel(0x0, addr + 0x400); /* clear pos A */
+ __raw_writel(pattern, addr); /* pattern to pos B */
+ __raw_writel(0x0, addr + 4); /* remove pattern off the bus */
+ val1 = __raw_readl(addr + 0x400); /* get pos A value */
+ val2 = __raw_readl(addr); /* get val2 */
+
+ if ((val1 != 0) || (val2 != pattern)) /* see if pos A value changed */
+ return (0);
+ else {
+ /* restore original values and return pass */
+ __raw_writel(orig1, addr + 0x400);
+ __raw_writel(orig2, addr);
+ return (1);
+ }
+}
+
+/********************************************************
+ * sdrc_init() - init the sdrc chip selects CS0 and CS1
+ * - early init routines, called from flash or
+ * SRAM.
+ *******************************************************/
+void sdrc_init(void)
+{
+#define EARLY_INIT 1
+ do_sdrc_init(SDRC_CS0_OSET, EARLY_INIT); /* only init up first bank here */
+}
+
+/*************************************************************************
+ * do_sdrc_init(): initialize the SDRAM for use.
+ * -code sets up SDRAM basic SDRC timings for CS0
+ * -optimal settings can be placed here, or redone after i2c
+ * inspection of board info
+ *
+ * - code called ones in C-Stack only context for CS0 and a possible 2nd
+ * time depending on memory configuration from stack+global context
+ **************************************************************************/
+void do_sdrc_init(u32 offset, u32 early)
+{
+ u32 common = 0, cs0 = 0, pmask = 0, pass_type, mtype, mono = 0;
+
+ if (offset == SDRC_CS0_OSET)
+ cs0 = common = 1; /* int regs shared between both chip select */
+
+ pass_type = IP_DDR;
+
+ /* If this is a 2nd pass init of a CS1, make it contiguous with CS0 */
+ if (!early && (((mtype = get_mem_type()) == DDR_COMBO)
+ || (mtype == DDR_STACKED))) {
+ if (mtype == DDR_COMBO) {
+ pmask = BIT2; /* if shared CKE don't use */
+ pass_type = COMBO_DDR; /* CS1 config */
+ __raw_writel((__raw_readl(SDRC_POWER)) & ~pmask,
+ SDRC_POWER);
+ }
+ make_cs1_contiguous();
+ }
+
+next_mem_type:
+ if (common) { /* do a SDRC reset between types to clear regs */
+ __raw_writel(SOFTRESET, SDRC_SYSCONFIG); /* reset sdrc */
+ wait_on_value(BIT0, BIT0, SDRC_STATUS, 12000000); /* wait on reset */
+ __raw_writel(0, SDRC_SYSCONFIG); /* clear soft reset */
+ __raw_writel(SDP_SDRC_SHARING, SDRC_SHARING);
+ /* If its a 3430 ES1.0 silicon, configure WAKEUPPROC to 1 as
+ per Errata 1.22 */
+ /* Need to change the condition to silicon and rev check */
+ if(1)
+ __raw_writel((__raw_readl(SDRC_POWER)) | WAKEUPPROC
+ , SDRC_POWER);
+#ifdef POWER_SAVE
+ __raw_writel(__raw_readl(SMS_SYSCONFIG) | SMART_IDLE,
+ SMS_SYSCONFIG);
+ __raw_writel(SDP_SDRC_SHARING | SMART_IDLE, SDRC_SHARING);
+ __raw_writel((__raw_readl(SDRC_POWER) | BIT6), SDRC_POWER);
+#endif
+ }
+
+ /* set MDCFG_0 values */
+ if ((pass_type == IP_DDR) || (pass_type == STACKED)) {
+ __raw_writel(SDP_SDRC_MDCFG_0_DDR, SDRC_MCFG_0 + offset);
+ if (mono) /* Stacked with memory on CS1 only */
+ __raw_writel(SDP_SDRC_MDCFG_MONO_DDR, SDRC_MCFG_0 + offset);
+ } else if (pass_type == COMBO_DDR) { /* (combo-CS0/CS1) */
+ __raw_writel(SDP_COMBO_MDCFG_0_DDR, SDRC_MCFG_0 + offset);
+ } else if (pass_type == IP_SDR) { /* ip sdr-CS0 */
+ __raw_writel(SDP_SDRC_MDCFG_0_SDR, SDRC_MCFG_0 + offset);
+ }
+
+ /* Set ACTIM values */
+ if (cs0) {
+ __raw_writel(SDP_SDRC_ACTIM_CTRLA_0, SDRC_ACTIM_CTRLA_0);
+ __raw_writel(SDP_SDRC_ACTIM_CTRLB_0, SDRC_ACTIM_CTRLB_0);
+ } else {
+ __raw_writel(SDP_SDRC_ACTIM_CTRLA_0, SDRC_ACTIM_CTRLA_1);
+ __raw_writel(SDP_SDRC_ACTIM_CTRLB_0, SDRC_ACTIM_CTRLB_1);
+ }
+ __raw_writel(SDP_SDRC_RFR_CTRL, SDRC_RFR_CTRL + offset);
+
+ /* init sequence for mDDR/mSDR using manual commands (DDR is different) */
+ __raw_writel(CMD_NOP, SDRC_MANUAL_0 + offset);
+ sdelay(5000); /* supposed to be 100us per design spec for mddr/msdr */
+ __raw_writel(CMD_PRECHARGE, SDRC_MANUAL_0 + offset);
+ __raw_writel(CMD_AUTOREFRESH, SDRC_MANUAL_0 + offset);
+ __raw_writel(CMD_AUTOREFRESH, SDRC_MANUAL_0 + offset);
+
+ /* Set MR0 values */
+ if (pass_type == IP_SDR)
+ __raw_writel(SDP_SDRC_MR_0_SDR, SDRC_MR_0 + offset);
+ else
+ __raw_writel(SDP_SDRC_MR_0_DDR, SDRC_MR_0 + offset);
+
+ /* setup 343x DLL values (DDR only) */
+ if (common && (pass_type != IP_SDR)) {
+ __raw_writel(SDP_SDRC_DLLAB_CTRL, SDRC_DLLA_CTRL);
+ sdelay(0x2000); /* give time to lock, at least 1000 L3 */
+ }
+ sdelay(0x1000);
+
+ if (mono) /* Used if Stacked memory is on CS1 only */
+ make_cs1_contiguous(); /* make CS1 appear at CS0 */
+
+ if (mem_ok())
+ return; /* STACKED, other configured type */
+ ++pass_type; /* IPDDR->COMBODDR->IPSDR for CS0 */
+ goto next_mem_type;
+}
+
+void enable_gpmc_config(u32 * gpmc_config, u32 gpmc_base, u32 base, u32 size)
+{
+ __raw_writel(0, GPMC_CONFIG7 + gpmc_base);
+ sdelay(1000);
+ /* Delay for settling */
+ __raw_writel(gpmc_config[0], GPMC_CONFIG1 + gpmc_base);
+ __raw_writel(gpmc_config[1], GPMC_CONFIG2 + gpmc_base);
+ __raw_writel(gpmc_config[2], GPMC_CONFIG3 + gpmc_base);
+ __raw_writel(gpmc_config[3], GPMC_CONFIG4 + gpmc_base);
+ __raw_writel(gpmc_config[4], GPMC_CONFIG5 + gpmc_base);
+ __raw_writel(gpmc_config[5], GPMC_CONFIG6 + gpmc_base);
+ /* Enable the config */
+ __raw_writel((((size & 0xF) << 8) | ((base >> 24) & 0x3F) |
+ (1 << 6)), GPMC_CONFIG7 + gpmc_base);
+ sdelay(2000);
+}
+
+/*****************************************************
+ * gpmc_init(): init gpmc bus
+ * Init GPMC for x16, MuxMode (SDRAM in x32).
+ * This code can only be executed from SRAM or SDRAM.
+ *****************************************************/
+void gpmc_init(void)
+{
+/* putting a blanket check on GPMC based on ZeBu for now */
+ u32 mux = 0, mwidth;
+ u32 *gpmc_config = NULL;
+ u32 gpmc_base = 0;
+ u32 base = 0;
+ u32 size = 0;
+ u32 f_off = CFG_MONITOR_LEN;
+ u32 f_sec = 0;
+ u32 config = 0;
+ unsigned char *config_sel = NULL;
+ u32 i=0;
+
+ mux = BIT9;
+ mwidth = get_gpmc0_width();
+
+ /* global settings */
+ __raw_writel(0x10, GPMC_SYSCONFIG); /* smart idle */
+ __raw_writel(0x0, GPMC_IRQENABLE); /* isr's sources masked */
+ __raw_writel(0, GPMC_TIMEOUT_CONTROL); /* timeout disable */
+
+ config = __raw_readl(GPMC_CONFIG);
+ config &= (~0xf00);
+ __raw_writel(config, GPMC_CONFIG);
+
+ /* Disable the GPMC0 config set by ROM code
+ * It conflicts with our MPDB (both at 0x08000000)
+ */
+ __raw_writel(0 , GPMC_CONFIG7 + GPMC_CONFIG_CS0);
+ sdelay(1000);
+
+ /* CS 0 */
+ gpmc_config = gpmc_m_nand;
+ gpmc_base = GPMC_CONFIG_CS0 + (0 * GPMC_CONFIG_WIDTH);
+ base = PISMO1_NAND_BASE;
+ size = PISMO1_NAND_SIZE;
+ enable_gpmc_config(gpmc_config, gpmc_base, base, size);
+
+ f_off = SMNAND_ENV_OFFSET;
+ f_sec = SZ_128K;
+ is_nand = 1;
+ nand_cs_base = gpmc_base;
+
+ /* env setup */
+ boot_flash_base = base;
+ boot_flash_off = f_off;
+ boot_flash_sec = f_sec;
+ boot_flash_env_addr = f_off;
+
+#ifdef ENV_IS_VARIABLE
+ boot_env_get_char_spec = nand_env_get_char_spec;
+ boot_env_init = nand_env_init;
+ boot_saveenv = nand_saveenv;
+ boot_env_relocate_spec = nand_env_relocate_spec;
+ env_ptr = 0; /* This gets filled elsewhere!! */
+ env_name_spec = nand_env_name_spec;
+#endif
+ /* CS 1 */
+ gpmc_config = gpmc_enet;
+ gpmc_base = GPMC_CONFIG_CS0 + (1 * GPMC_CONFIG_WIDTH);
+ enable_gpmc_config(gpmc_config, gpmc_base, DEBUG_BASE, DBG_MPDB_SIZE);
+
+#ifdef OPTIONAL_NOR
+ /* CS 2 (fixme -- sizes for optional s-nor)*/
+ gpmc_config = gpmc_stnor;
+ gpmc_config[0] |= mux | TYPE_NOR | mwidth;
+ gpmc_base = GPMC_CONFIG_CS0 + (2 * GPMC_CONFIG_WIDTH);
+ enable_gpmc_config(gpmc_config, gpmc_base, DEBUG_BASE, DBG_MPDB_SIZE);
+
+ /* handle flash probe setup */
+ f_sec = SZ_128K;
+ NOR_MAX_FLASH_BANKS = 2;
+ size = PISMO1_NOR_SIZE;
+ for(i=0; i < NOR_MAX_FLASH_BANKS; i++)
+ NOR_FLASH_BANKS_LIST[i] =
+ FLASH_BASE_SDPV1 + PHYS_FLASH_SIZE*i;
+ }
+#endif
+}