[U-Boot] [PATCH 1/3] arm: tegra20: implement early pmic rail configuration

Marcel Ziswiler marcel.ziswiler at toradex.com
Thu Aug 20 09:52:41 CEST 2015


Implement early TPS6586X PMIC rail configuration setting SM0 being
VDD_CORE_1.2V to 1.2 volts and SM1 being VDD_CPU_1.0V to 1.0 volts.

While those are PMIC power-up defaults the SoC might have been reset
separately with certain rails being left at lower DVFS states which
is e.g. the case upon watchdog reset while otherwise nearly idling.

Signed-off-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>
---

 arch/arm/mach-tegra/tegra20/cpu.c | 76 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-tegra/tegra20/cpu.c b/arch/arm/mach-tegra/tegra20/cpu.c
index 67f49d7..aa05e1b 100644
--- a/arch/arm/mach-tegra/tegra20/cpu.c
+++ b/arch/arm/mach-tegra/tegra20/cpu.c
@@ -15,16 +15,64 @@
  */
 
 #include <common.h>
-#include <asm/io.h>
+#include <asm/arch/clock.h>
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/pmc.h>
+#include <asm/arch-tegra/tegra_i2c.h>
+#include <asm/io.h>
 #include "../cpu.h"
 
+#define I2C_SEND_2_BYTES		0x0a02
+#define TPS6586X_I2C_ADDR		(0x34<<1)
+#define TPS6586X_VCC1_REG		0x20
+#define TPS6586X_SM1V1_REG		0x23
+#define TPS6586X_SM0V1_REG		0x26
+
+/* Tegra20-specific DVC init code */
+void tegra_i2c_ll_init(void)
+{
+	struct dvc_ctlr *reg = (struct dvc_ctlr *)TEGRA_DVC_BASE;
+
+	writel(DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK, &reg->ctrl3);
+}
+
+void tegra_i2c_ll_write(uint offset, uint8_t data)
+{
+	struct dvc_ctlr *reg = (struct dvc_ctlr *)TEGRA_DVC_BASE;
+
+	writel(TPS6586X_I2C_ADDR, &reg->cmd_addr0);
+	writel(2, &reg->cnfg);
+
+	writel((data << 8) | (offset & 0xff), &reg->cmd_data1);
+	writel(I2C_SEND_2_BYTES, &reg->cnfg);
+}
+
 static void enable_cpu_power_rail(void)
 {
 	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
 	u32 reg;
 
+	debug("%s entry\n", __func__);
+
+#ifdef CONFIG_TEGRA_EARLY_TPS6586X
+	tegra_i2c_ll_init();
+
+	/* Set SM0 being VDD_CORE_1.2V to 1.2 volts */
+	tegra_i2c_ll_write(TPS6586X_SM0V1_REG, 0x13);
+
+	udelay(1000);
+
+	/* Set SM1 being VDD_CPU_1.0V to 1.0 volts */
+	tegra_i2c_ll_write(TPS6586X_SM1V1_REG, 0x0b);
+
+	udelay(1000);
+
+	/* Make sure primary voltages are selected and ramped towards */
+	tegra_i2c_ll_write(TPS6586X_VCC1_REG, 0x05);
+
+	udelay(10 * 1000);
+#endif
+
 	reg = readl(&pmc->pmc_cntrl);
 	reg |= CPUPWRREQ_OE;
 	writel(reg, &pmc->pmc_cntrl);
@@ -38,8 +86,34 @@ static void enable_cpu_power_rail(void)
 	udelay(3750);
 }
 
+/* T20 requires some special clock initialization, incl. setting up DVC I2C */
+void t20_init_clocks(void)
+{
+	debug("%s entry\n", __func__);
+
+	/* Put i2c in reset and enable clocks */
+	reset_set_enable(PERIPH_ID_DVC_I2C, 1);
+	clock_set_enable(PERIPH_ID_DVC_I2C, 1);
+
+	/*
+	 * Our high-level clock routines are not available prior to
+	 * relocation. We use the low-level functions which require a
+	 * hard-coded divisor. Use CLK_M with divide by (n + 1 = 16)
+	 */
+	clock_ll_set_source_divisor(PERIPH_ID_DVC_I2C, 3, 15);
+
+	/* Give clocks time to stabilize, then take i2c out of reset */
+	udelay(1000);
+
+	reset_set_enable(PERIPH_ID_DVC_I2C, 0);
+}
+
 void start_cpu(u32 reset_vector)
 {
+	debug("%s entry, reset_vector = %x\n", __func__, reset_vector);
+
+	t20_init_clocks();
+
 	/* Enable VDD_CPU */
 	enable_cpu_power_rail();
 
-- 
2.4.3



More information about the U-Boot mailing list