[coreboot-gerrit] New patch to review for coreboot: 294e775 tegra124: Correct cpu power on sequence and CPUPWRGOOD_TIME

Marc Jones (marc.jones@se-eng.com) gerrit at coreboot.org
Wed Feb 11 01:14:01 CET 2015


Marc Jones (marc.jones at se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/8414

-gerrit

commit 294e775ae43cc6238c78cfb8a98c0b3596632c93
Author: Jimmy Zhang <jimmzhang at nvidia.com>
Date:   Wed Jul 2 17:45:18 2014 -0700

    tegra124: Correct cpu power on sequence and CPUPWRGOOD_TIME
    
    Based on TRM, cpu clock enabling and reset vector setting should
    all be done properly before ungating cpu power partition. Otherwise,
    with current code, a race condition could occur where cpu starts but
    reset vector has not been set.
    
    BUG=chrome-os-partner:30064
    BRANCH=none
    TEST=run nyan_big reboot test. No issue is experienced.
    
    Original-Signed-off-by: Jimmy Zhang <jimmzhang at nvidia.com>
    Original-Change-Id: I571e128693bb2763ee673bd183b8cf60921dc475
    Original-Reviewed-on: https://chromium-review.googlesource.com/206682
    Original-Tested-by: Jimmy Zhang <jimmzhang at nvidia.com>
    Original-Reviewed-by: Julius Werner <jwerner at chromium.org>
    Original-Commit-Queue: Jimmy Zhang <jimmzhang at nvidia.com>
    (cherry picked from commit 106480ff32406c899a24544fdfab858db5afd1d9)
    Signed-off-by: Marc Jones <marc.jones at se-eng.com>
    
    Change-Id: I3da6018dd68e4c15d2c58db566a9745b0b26c365
---
 src/soc/nvidia/tegra124/bootblock.c         | 11 ++++++-----
 src/soc/nvidia/tegra124/clock.c             | 15 ++++++++++-----
 src/soc/nvidia/tegra124/include/soc/clock.h |  9 ++++++++-
 src/soc/nvidia/tegra124/power.c             | 30 +++++++++++++++--------------
 src/soc/nvidia/tegra124/power.h             |  3 +--
 5 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/src/soc/nvidia/tegra124/bootblock.c b/src/soc/nvidia/tegra124/bootblock.c
index 5f1e850..5900149 100644
--- a/src/soc/nvidia/tegra124/bootblock.c
+++ b/src/soc/nvidia/tegra124/bootblock.c
@@ -17,6 +17,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <assert.h>
 #include <arch/exception.h>
 #include <bootblock_common.h>
 #include <cbfs.h>
@@ -69,16 +70,16 @@ void main(void)
 			  PINMUX_PWR_INT_N_FUNC_PMICINTR |
 			  PINMUX_INPUT_ENABLE);
 
-	power_enable_cpu_rail();
-	power_ungate_cpu();
-
 	if (IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE))
 		entry = (void *)verstage_vboot_main;
 	else
 		entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/romstage");
 
-	if (entry)
-		clock_cpu0_config_and_reset(entry);
+	ASSERT(entry);
+	clock_cpu0_config(entry);
+
+	power_enable_and_ungate_cpu();
+	clock_cpu0_remove_reset();
 
 	clock_halt_avp();
 }
diff --git a/src/soc/nvidia/tegra124/clock.c b/src/soc/nvidia/tegra124/clock.c
index af2f96a..e3c0e71 100644
--- a/src/soc/nvidia/tegra124/clock.c
+++ b/src/soc/nvidia/tegra124/clock.c
@@ -480,7 +480,7 @@ void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
 	udelay(IO_STABILIZATION_DELAY);
 }
 
-void clock_cpu0_config_and_reset(void *entry)
+void clock_cpu0_config(void *entry)
 {
 	void * const evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100;
 
@@ -511,7 +511,10 @@ void clock_cpu0_config_and_reset(void *entry)
 	setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_CPU);
 	setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPUG);
 	setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPULP);
+}
 
+void clock_cpu0_remove_reset(void)
+{
 	// Disable the reset on the non-CPU parts of the fast cluster.
 	write32(CRC_RST_CPUG_CLR_NONCPU,
 		&clk_rst->rst_cpug_cmplx_clr);
@@ -559,10 +562,12 @@ void clock_init(void)
 
 	/* Typical ratios are 1:2:2 or 1:2:3 sclk:hclk:pclk (See: APB DMA
 	 * features section in the TRM). */
-	write32(1 << HCLK_DIVISOR_SHIFT | 0 << PCLK_DIVISOR_SHIFT,
-		&clk_rst->clk_sys_rate);	/* pclk = hclk = sclk/2 */
-	write32(CLK_DIVIDER(TEGRA_PLLC_KHZ, 300000) << PLL_OUT_RATIO_SHIFT |
-		PLL_OUT_CLKEN | PLL_OUT_RSTN, &clk_rst->pllc_out);
+	write32(TEGRA_HCLK_RATIO << HCLK_DIVISOR_SHIFT |
+		TEGRA_PCLK_RATIO << PCLK_DIVISOR_SHIFT,
+		&clk_rst->clk_sys_rate);
+	write32(CLK_DIVIDER(TEGRA_PLLC_KHZ, TEGRA_SCLK_KHZ) <<
+		PLL_OUT_RATIO_SHIFT | PLL_OUT_CLKEN |
+		PLL_OUT_RSTN, &clk_rst->pllc_out);
 	write32(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT |
 		SCLK_SOURCE_PLLC_OUT1 << SCLK_RUN_SHIFT,
 		&clk_rst->sclk_brst_pol);		/* sclk = 300 MHz */
diff --git a/src/soc/nvidia/tegra124/include/soc/clock.h b/src/soc/nvidia/tegra124/include/soc/clock.h
index ffe9a4e..82b2ad8 100644
--- a/src/soc/nvidia/tegra124/include/soc/clock.h
+++ b/src/soc/nvidia/tegra124/include/soc/clock.h
@@ -277,6 +277,12 @@ enum clock_source {  /* Careful: Not true for all sources, always check TRM! */
 #define TEGRA_PLLD_KHZ   (925000)
 #define TEGRA_PLLU_KHZ   (960000)
 
+#define TEGRA_SCLK_KHZ   (300000)
+#define TEGRA_HCLK_RATIO 1
+#define TEGRA_HCLK_KHZ   (TEGRA_SCLK_KHZ / (1 + TEGRA_HCLK_RATIO))
+#define TEGRA_PCLK_RATIO 0
+#define TEGRA_PCLK_KHZ   (TEGRA_HCLK_KHZ / (1 + TEGRA_PCLK_RATIO))
+
 int clock_get_osc_khz(void);
 int clock_get_pll_input_khz(void);
 u32 clock_display(u32 frequency);
@@ -285,7 +291,8 @@ void clock_external_output(int clk_id);
 void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
 		 u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source,
 		 u32 same_freq);
-void clock_cpu0_config_and_reset(void * entry);
+void clock_cpu0_config(void * entry);
+void clock_cpu0_remove_reset(void);
 void clock_halt_avp(void);
 void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x);
 void clock_reset_l(u32 l);
diff --git a/src/soc/nvidia/tegra124/power.c b/src/soc/nvidia/tegra124/power.c
index 760d058..ec44a0f 100644
--- a/src/soc/nvidia/tegra124/power.c
+++ b/src/soc/nvidia/tegra124/power.c
@@ -21,6 +21,7 @@
 #include <arch/io.h>
 #include <console/console.h>
 #include <soc/addressmap.h>
+#include <soc/clock.h>
 
 #include "pmc.h"
 #include "power.h"
@@ -32,6 +33,11 @@ static int partition_powered(int id)
 	return read32(&pmc->pwrgate_status) & (0x1 << id);
 }
 
+static int partition_clamp_on(int id)
+{
+	return read32(&pmc->clamp_status) & (0x1 << id);
+}
+
 static void power_ungate_partition(uint32_t id)
 {
 	printk(BIOS_INFO, "Ungating power partition %d.\n", id);
@@ -51,34 +57,30 @@ static void power_ungate_partition(uint32_t id)
 		// Wait for the partition to be powered.
 		while (!partition_powered(id))
 			;
+
+		// Wait for clamp off.
+		while (partition_clamp_on(id))
+			;
 	}
 
 	printk(BIOS_INFO, "Ungated power partition %d.\n", id);
 }
 
-void power_enable_cpu_rail(void)
+void power_enable_and_ungate_cpu(void)
 {
-	// Set the power gate timer multiplier to 8 (why 8?).
-	uint32_t pwrgate_timer_mult = read32(&pmc->pwrgate_timer_mult);
-	pwrgate_timer_mult |= (0x3 << 0);
-
 	/*
-	 * From U-Boot:
-	 * Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz),
-	 * set it for 5ms as per SysEng (102MHz/5mS = 510000).
+	 * Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (150MHz),
+	 * set it for 5ms as per SysEng (5ms * PCLK_KHZ * 1000 / 1s).
 	 */
-	write32(510000, &pmc->cpupwrgood_timer);
-
-	power_ungate_partition(POWER_PARTID_CRAIL);
+	write32((TEGRA_PCLK_KHZ * 5), &pmc->cpupwrgood_timer);
 
 	uint32_t cntrl = read32(&pmc->cntrl);
 	cntrl &= ~PMC_CNTRL_CPUPWRREQ_POLARITY;
 	cntrl |= PMC_CNTRL_CPUPWRREQ_OE;
 	write32(cntrl, &pmc->cntrl);
-}
 
-void power_ungate_cpu(void)
-{
+	power_ungate_partition(POWER_PARTID_CRAIL);
+
 	// Ungate power to the non-core parts of the fast cluster.
 	power_ungate_partition(POWER_PARTID_C0NC);
 
diff --git a/src/soc/nvidia/tegra124/power.h b/src/soc/nvidia/tegra124/power.h
index 130ed25..995e737 100644
--- a/src/soc/nvidia/tegra124/power.h
+++ b/src/soc/nvidia/tegra124/power.h
@@ -22,9 +22,8 @@
 
 // This function does not enable the external power to the rail, it enables
 // the rail itself internal to the SOC.
-void power_enable_cpu_rail(void);
+void power_enable_and_ungate_cpu(void);
 
-void power_ungate_cpu(void);
 
 // power_reset_status returns one of the following possible sources for the
 // most recent reset.



More information about the coreboot-gerrit mailing list