summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv7
diff options
context:
space:
mode:
authorSricharan <r.sricharan@ti.com>2011-11-15 09:50:03 -0500
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2011-11-15 22:25:50 +0100
commit78f455c055ddf55a1a2dd6ae5e2d060ed2e5bd0e (patch)
treec124c8e56d72e9e46f70516fa9dd3dabdac22d9a /arch/arm/cpu/armv7
parentbb772a594493092adfb18a56889e0bce855eed99 (diff)
omap4/5: Add support for booting with CH.
Configuration header(CH) is 512 byte header attached to an OMAP boot image that will help ROM code to initialize clocks, SDRAM etc and copy U-Boot directly into SDRAM. CH can help us in by-passing SPL and directly boot U-boot, hence it's an alternative for SPL. However, we intend to support both CH and SPL for OMAP4/5. Initialization done through CH is limited and is not equivalent to that done by SPL. So U-Boot has to distinguish between the two cases and handle them accordingly. This patch takes care of doing this. Signed-off-by: sricharan <r.sricharan@ti.com> Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
Diffstat (limited to 'arch/arm/cpu/armv7')
-rw-r--r--arch/arm/cpu/armv7/omap-common/clocks-common.c59
-rw-r--r--arch/arm/cpu/armv7/omap-common/hwinit-common.c24
-rw-r--r--arch/arm/cpu/armv7/omap-common/lowlevel_init.S29
-rw-r--r--arch/arm/cpu/armv7/omap-common/spl.c9
-rw-r--r--arch/arm/cpu/armv7/omap4/clocks.c44
-rw-r--r--arch/arm/cpu/armv7/omap5/clocks.c40
6 files changed, 164 insertions, 41 deletions
diff --git a/arch/arm/cpu/armv7/omap-common/clocks-common.c b/arch/arm/cpu/armv7/omap-common/clocks-common.c
index c726093fd2..f64a10bfcb 100644
--- a/arch/arm/cpu/armv7/omap-common/clocks-common.c
+++ b/arch/arm/cpu/armv7/omap-common/clocks-common.c
@@ -115,17 +115,46 @@ static inline void wait_for_lock(u32 *const base)
}
}
+inline u32 check_for_lock(u32 *const base)
+{
+ struct dpll_regs *const dpll_regs = (struct dpll_regs *)base;
+ u32 lock = readl(&dpll_regs->cm_idlest_dpll) & ST_DPLL_CLK_MASK;
+
+ return lock;
+}
+
static void do_setup_dpll(u32 *const base, const struct dpll_params *params,
- u8 lock)
+ u8 lock, char *dpll)
{
- u32 temp;
+ u32 temp, M, N;
struct dpll_regs *const dpll_regs = (struct dpll_regs *)base;
+ temp = readl(&dpll_regs->cm_clksel_dpll);
+
+ if (check_for_lock(base)) {
+ /*
+ * The Dpll has already been locked by rom code using CH.
+ * Check if M,N are matching with Ideal nominal opp values.
+ * If matches, skip the rest otherwise relock.
+ */
+ M = (temp & CM_CLKSEL_DPLL_M_MASK) >> CM_CLKSEL_DPLL_M_SHIFT;
+ N = (temp & CM_CLKSEL_DPLL_N_MASK) >> CM_CLKSEL_DPLL_N_SHIFT;
+ if ((M != (params->m)) || (N != (params->n))) {
+ debug("\n %s Dpll locked, but not for ideal M = %d,"
+ "N = %d values, current values are M = %d,"
+ "N= %d" , dpll, params->m, params->n,
+ M, N);
+ } else {
+ /* Dpll locked with ideal values for nominal opps. */
+ debug("\n %s Dpll already locked with ideal"
+ "nominal opp values", dpll);
+ goto setup_post_dividers;
+ }
+ }
+
bypass_dpll(base);
/* Set M & N */
- temp = readl(&dpll_regs->cm_clksel_dpll);
-
temp &= ~CM_CLKSEL_DPLL_M_MASK;
temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK;
@@ -138,6 +167,7 @@ static void do_setup_dpll(u32 *const base, const struct dpll_params *params,
if (lock)
do_lock_dpll(base);
+setup_post_dividers:
setup_post_dividers(base, params);
/* Wait till the DPLL locks */
@@ -216,7 +246,8 @@ void configure_mpu_dpll(void)
}
params = get_mpu_dpll_params();
- do_setup_dpll(&prcm->cm_clkmode_dpll_mpu, params, DPLL_LOCK);
+
+ do_setup_dpll(&prcm->cm_clkmode_dpll_mpu, params, DPLL_LOCK, "mpu");
debug("MPU DPLL locked\n");
}
@@ -235,7 +266,8 @@ static void setup_dplls(void)
* Core DPLL will be locked after setting up EMIF
* using the FREQ_UPDATE method(freq_update_core())
*/
- do_setup_dpll(&prcm->cm_clkmode_dpll_core, params, DPLL_NO_LOCK);
+ do_setup_dpll(&prcm->cm_clkmode_dpll_core, params, DPLL_NO_LOCK,
+ "core");
/* Set the ratios for CORE_CLK, L3_CLK, L4_CLK */
temp = (CLKSEL_CORE_X2_DIV_1 << CLKSEL_CORE_SHIFT) |
(CLKSEL_L3_CORE_DIV_2 << CLKSEL_L3_SHIFT) |
@@ -246,13 +278,14 @@ static void setup_dplls(void)
/* lock PER dpll */
params = get_per_dpll_params();
do_setup_dpll(&prcm->cm_clkmode_dpll_per,
- params, DPLL_LOCK);
+ params, DPLL_LOCK, "per");
debug("PER DPLL locked\n");
/* MPU dpll */
configure_mpu_dpll();
}
+#ifdef CONFIG_SYS_CLOCKS_ENABLE_ALL
static void setup_non_essential_dplls(void)
{
u32 sys_clk_khz, abe_ref_clk;
@@ -267,7 +300,7 @@ static void setup_non_essential_dplls(void)
CM_BYPCLK_DPLL_IVA_CLKSEL_MASK, DPLL_IVA_CLKSEL_CORE_X2_DIV_2);
params = get_iva_dpll_params();
- do_setup_dpll(&prcm->cm_clkmode_dpll_iva, params, DPLL_LOCK);
+ do_setup_dpll(&prcm->cm_clkmode_dpll_iva, params, DPLL_LOCK, "iva");
/*
* USB:
@@ -287,7 +320,7 @@ static void setup_non_essential_dplls(void)
sd_div << CM_CLKSEL_DPLL_DPLL_SD_DIV_SHIFT);
/* Now setup the dpll with the regular function */
- do_setup_dpll(&prcm->cm_clkmode_dpll_usb, params, DPLL_LOCK);
+ do_setup_dpll(&prcm->cm_clkmode_dpll_usb, params, DPLL_LOCK, "usb");
/* Configure ABE dpll */
params = get_abe_dpll_params();
@@ -315,8 +348,9 @@ static void setup_non_essential_dplls(void)
CM_ABE_PLL_REF_CLKSEL_CLKSEL_MASK,
abe_ref_clk << CM_ABE_PLL_REF_CLKSEL_CLKSEL_SHIFT);
/* Lock the dpll */
- do_setup_dpll(&prcm->cm_clkmode_dpll_abe, params, DPLL_LOCK);
+ do_setup_dpll(&prcm->cm_clkmode_dpll_abe, params, DPLL_LOCK, "abe");
}
+#endif
void do_scale_tps62361(u32 reg, u32 volt_mv)
{
@@ -561,10 +595,15 @@ void prcm_init(void)
enable_basic_clocks();
scale_vcores();
setup_dplls();
+#ifdef CONFIG_SYS_CLOCKS_ENABLE_ALL
setup_non_essential_dplls();
enable_non_essential_clocks();
+#endif
break;
default:
break;
}
+
+ if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context())
+ enable_basic_uboot_clocks();
}
diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
index 5cf4e2bb2c..f65705db12 100644
--- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c
+++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
@@ -31,9 +31,18 @@
#include <asm/arch/sys_proto.h>
#include <asm/sizes.h>
#include <asm/emif.h>
+#include <asm/omap_common.h>
DECLARE_GLOBAL_DATA_PTR;
+/*
+ * This is used to verify if the configuration header
+ * was executed by rom code prior to control of transfer
+ * to the bootloader. SPL is responsible for saving and
+ * passing the boot_params pointer to the u-boot.
+ */
+struct omap_boot_parameters boot_params __attribute__ ((section(".data")));
+
#ifdef CONFIG_SPL_BUILD
/*
* We use static variables because global data is not ready yet.
@@ -41,12 +50,11 @@ DECLARE_GLOBAL_DATA_PTR;
* We would not typically need to save these parameters in regular
* U-Boot. This is needed only in SPL at the moment.
*/
-u32 omap_bootdevice = BOOT_DEVICE_MMC1;
u32 omap_bootmode = MMCSD_MODE_FAT;
u32 omap_boot_device(void)
{
- return omap_bootdevice;
+ return (u32) (boot_params.omap_bootdevice);
}
u32 omap_boot_mode(void)
@@ -71,12 +79,16 @@ static void set_mux_conf_regs(void)
set_muxconf_regs_essential();
break;
case OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL:
+#ifdef CONFIG_SYS_ENABLE_PADS_ALL
set_muxconf_regs_non_essential();
+#endif
break;
case OMAP_INIT_CONTEXT_UBOOT_FROM_NOR:
case OMAP_INIT_CONTEXT_UBOOT_AFTER_CH:
set_muxconf_regs_essential();
+#ifdef CONFIG_SYS_ENABLE_PADS_ALL
set_muxconf_regs_non_essential();
+#endif
break;
}
}
@@ -103,6 +115,13 @@ void omap_rev_string(char *omap_rev_string)
minor_rev);
}
+#ifdef CONFIG_SPL_BUILD
+static void init_boot_params(void)
+{
+ boot_params_ptr = (u32 *) &boot_params;
+}
+#endif
+
/*
* Routine: s_init
* Description: Does early system init of watchdog, muxing, andclocks
@@ -131,6 +150,7 @@ void s_init(void)
#ifdef CONFIG_SPL_BUILD
/* For regular u-boot sdram_init() is called from dram_init() */
sdram_init();
+ init_boot_params();
#endif
}
diff --git a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
index 68732987ae..35f38acf5d 100644
--- a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
@@ -27,7 +27,7 @@
*/
#include <asm/arch/omap.h>
-#ifdef CONFIG_SPL_BUILD
+
.global save_boot_params
save_boot_params:
/*
@@ -43,21 +43,40 @@ save_boot_params:
cmp r2, r0
blt 1f
+ /*
+ * store the boot params passed from rom code or saved
+ * and passed by SPL
+ */
+ cmp r0, #0
+ beq 1f
+ ldr r1, =boot_params
+ str r0, [r1]
+#ifdef CONFIG_SPL_BUILD
/* Store the boot device in omap_boot_device */
- ldr r2, [r0, #BOOT_DEVICE_OFFSET] @ r1 <- value of boot device
+ ldrb r2, [r0, #BOOT_DEVICE_OFFSET] @ r1 <- value of boot device
and r2, #BOOT_DEVICE_MASK
- ldr r3, =omap_bootdevice
- str r2, [r3] @ omap_boot_device <- r1
+ ldr r3, =boot_params
+ strb r2, [r3, #BOOT_DEVICE_OFFSET] @ omap_boot_device <- r1
+ /* boot mode is passed only for devices that can raw/fat mode */
+ cmp r2, #2
+ blt 2f
+ cmp r2, #7
+ bgt 2f
/* Store the boot mode (raw/FAT) in omap_boot_mode */
ldr r2, [r0, #DEV_DESC_PTR_OFFSET] @ get the device descriptor ptr
ldr r2, [r2, #DEV_DATA_PTR_OFFSET] @ get the pDeviceData ptr
ldr r2, [r2, #BOOT_MODE_OFFSET] @ get the boot mode
ldr r3, =omap_bootmode
str r2, [r3]
+#endif
+2:
+ ldrb r2, [r0, #CH_FLAGS_OFFSET]
+ ldr r3, =boot_params
+ strb r2, [r3, #CH_FLAGS_OFFSET]
1:
bx lr
-#endif
+
.globl lowlevel_init
lowlevel_init:
diff --git a/arch/arm/cpu/armv7/omap-common/spl.c b/arch/arm/cpu/armv7/omap-common/spl.c
index 2c59d2b36b..d6d7d65ecf 100644
--- a/arch/arm/cpu/armv7/omap-common/spl.c
+++ b/arch/arm/cpu/armv7/omap-common/spl.c
@@ -38,6 +38,7 @@
DECLARE_GLOBAL_DATA_PTR;
+u32* boot_params_ptr = NULL;
struct spl_image_info spl_image;
/* Define global data structure pointer to it*/
@@ -92,12 +93,16 @@ void spl_parse_image_header(const struct image_header *header)
static void jump_to_image_no_args(void)
{
- typedef void (*image_entry_noargs_t)(void)__attribute__ ((noreturn));
+ typedef void (*image_entry_noargs_t)(u32 *)__attribute__ ((noreturn));
image_entry_noargs_t image_entry =
(image_entry_noargs_t) spl_image.entry_point;
debug("image entry point: 0x%X\n", spl_image.entry_point);
- image_entry();
+ /* Pass the saved boot_params from rom code */
+#if defined(CONFIG_VIRTIO) || defined(CONFIG_ZEBU)
+ image_entry = 0x80100000;
+#endif
+ image_entry((u32 *)&boot_params_ptr);
}
void jump_to_image_no_args(void) __attribute__ ((noreturn));
diff --git a/arch/arm/cpu/armv7/omap4/clocks.c b/arch/arm/cpu/armv7/omap4/clocks.c
index a1098d4035..0886f92431 100644
--- a/arch/arm/cpu/armv7/omap4/clocks.c
+++ b/arch/arm/cpu/armv7/omap4/clocks.c
@@ -333,30 +333,23 @@ void enable_basic_clocks(void)
};
u32 *const clk_modules_hw_auto_essential[] = {
+ &prcm->cm_memif_emif_1_clkctrl,
+ &prcm->cm_memif_emif_2_clkctrl,
+ &prcm->cm_l4cfg_l4_cfg_clkctrl,
&prcm->cm_wkup_gpio1_clkctrl,
&prcm->cm_l4per_gpio2_clkctrl,
&prcm->cm_l4per_gpio3_clkctrl,
&prcm->cm_l4per_gpio4_clkctrl,
&prcm->cm_l4per_gpio5_clkctrl,
&prcm->cm_l4per_gpio6_clkctrl,
- &prcm->cm_memif_emif_1_clkctrl,
- &prcm->cm_memif_emif_2_clkctrl,
- &prcm->cm_l3init_hsusbotg_clkctrl,
- &prcm->cm_l3init_usbphy_clkctrl,
- &prcm->cm_l4cfg_l4_cfg_clkctrl,
0
};
u32 *const clk_modules_explicit_en_essential[] = {
- &prcm->cm_l4per_gptimer2_clkctrl,
+ &prcm->cm_wkup_gptimer1_clkctrl,
&prcm->cm_l3init_hsmmc1_clkctrl,
&prcm->cm_l3init_hsmmc2_clkctrl,
- &prcm->cm_l4per_mcspi1_clkctrl,
- &prcm->cm_wkup_gptimer1_clkctrl,
- &prcm->cm_l4per_i2c1_clkctrl,
- &prcm->cm_l4per_i2c2_clkctrl,
- &prcm->cm_l4per_i2c3_clkctrl,
- &prcm->cm_l4per_i2c4_clkctrl,
+ &prcm->cm_l4per_gptimer2_clkctrl,
&prcm->cm_wkup_wdtimer2_clkctrl,
&prcm->cm_l4per_uart3_clkctrl,
0
@@ -386,6 +379,33 @@ void enable_basic_clocks(void)
1);
}
+void enable_basic_uboot_clocks(void)
+{
+ u32 *const clk_domains_essential[] = {
+ 0
+ };
+
+ u32 *const clk_modules_hw_auto_essential[] = {
+ &prcm->cm_l3init_hsusbotg_clkctrl,
+ &prcm->cm_l3init_usbphy_clkctrl,
+ 0
+ };
+
+ u32 *const clk_modules_explicit_en_essential[] = {
+ &prcm->cm_l4per_mcspi1_clkctrl,
+ &prcm->cm_l4per_i2c1_clkctrl,
+ &prcm->cm_l4per_i2c2_clkctrl,
+ &prcm->cm_l4per_i2c3_clkctrl,
+ &prcm->cm_l4per_i2c4_clkctrl,
+ 0
+ };
+
+ do_enable_clocks(clk_domains_essential,
+ clk_modules_hw_auto_essential,
+ clk_modules_explicit_en_essential,
+ 1);
+}
+
/*
* Enable non-essential clock domains, modules and
* do some additional special settings needed
diff --git a/arch/arm/cpu/armv7/omap5/clocks.c b/arch/arm/cpu/armv7/omap5/clocks.c
index 28d3bcd8ee..dd882a202e 100644
--- a/arch/arm/cpu/armv7/omap5/clocks.c
+++ b/arch/arm/cpu/armv7/omap5/clocks.c
@@ -273,30 +273,26 @@ void enable_basic_clocks(void)
};
u32 *const clk_modules_hw_auto_essential[] = {
+ &prcm->cm_memif_emif_1_clkctrl,
+ &prcm->cm_memif_emif_2_clkctrl,
+ &prcm->cm_l4cfg_l4_cfg_clkctrl,
&prcm->cm_wkup_gpio1_clkctrl,
&prcm->cm_l4per_gpio2_clkctrl,
&prcm->cm_l4per_gpio3_clkctrl,
&prcm->cm_l4per_gpio4_clkctrl,
&prcm->cm_l4per_gpio5_clkctrl,
&prcm->cm_l4per_gpio6_clkctrl,
- &prcm->cm_memif_emif_1_clkctrl,
- &prcm->cm_memif_emif_2_clkctrl,
- &prcm->cm_l4cfg_l4_cfg_clkctrl,
0
};
u32 *const clk_modules_explicit_en_essential[] = {
- &prcm->cm_l4per_gptimer2_clkctrl,
+ &prcm->cm_wkup_gptimer1_clkctrl,
&prcm->cm_l3init_hsmmc1_clkctrl,
&prcm->cm_l3init_hsmmc2_clkctrl,
- &prcm->cm_l4per_mcspi1_clkctrl,
- &prcm->cm_wkup_gptimer1_clkctrl,
- &prcm->cm_l4per_i2c1_clkctrl,
- &prcm->cm_l4per_i2c2_clkctrl,
- &prcm->cm_l4per_i2c3_clkctrl,
- &prcm->cm_l4per_i2c4_clkctrl,
+ &prcm->cm_l4per_gptimer2_clkctrl,
&prcm->cm_wkup_wdtimer2_clkctrl,
&prcm->cm_l4per_uart3_clkctrl,
+ &prcm->cm_l4per_i2c1_clkctrl,
0
};
@@ -320,6 +316,30 @@ void enable_basic_clocks(void)
1);
}
+void enable_basic_uboot_clocks(void)
+{
+ u32 *const clk_domains_essential[] = {
+ 0
+ };
+
+ u32 *const clk_modules_hw_auto_essential[] = {
+ 0
+ };
+
+ u32 *const clk_modules_explicit_en_essential[] = {
+ &prcm->cm_l4per_mcspi1_clkctrl,
+ &prcm->cm_l4per_i2c2_clkctrl,
+ &prcm->cm_l4per_i2c3_clkctrl,
+ &prcm->cm_l4per_i2c4_clkctrl,
+ 0
+ };
+
+ do_enable_clocks(clk_domains_essential,
+ clk_modules_hw_auto_essential,
+ clk_modules_explicit_en_essential,
+ 1);
+}
+
/*
* Enable non-essential clock domains, modules and
* do some additional special settings needed