summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/tegra20/cpu.c78
-rw-r--r--include/configs/colibri_t20.h2
-rw-r--r--scripts/config_whitelist.txt1
3 files changed, 80 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/tegra20/cpu.c b/arch/arm/mach-tegra/tegra20/cpu.c
index 7fbc2e2865..3a0587b41c 100644
--- a/arch/arm/mach-tegra/tegra20/cpu.c
+++ b/arch/arm/mach-tegra/tegra20/cpu.c
@@ -5,16 +5,66 @@
*/
#include <common.h>
-#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pmu.h>
#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/clk_rst.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("enable_cpu_power_rail entry\n");
+
+#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);
@@ -28,8 +78,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("t20_init_clocks entry\n");
+
+ /* 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();
diff --git a/include/configs/colibri_t20.h b/include/configs/colibri_t20.h
index d84850a28f..36359fc0a1 100644
--- a/include/configs/colibri_t20.h
+++ b/include/configs/colibri_t20.h
@@ -14,6 +14,8 @@
#undef CONFIG_SYS_DCACHE_OFF /* breaks L4T kernel boot */
#define CONFIG_ARCH_MISC_INIT
+#define CONFIG_TEGRA_EARLY_TPS6586X
+
/* High-level configuration options */
#define CONFIG_DISPLAY_BOARDINFO_LATE /* Calls show_board_info() */
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 30c9e5cbd8..5d5ecdc845 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -7911,6 +7911,7 @@ CONFIG_TAM3517_SW3_SETTINGS
CONFIG_TCA642X
CONFIG_TEGRA_BOARD_STRING
CONFIG_TEGRA_CLOCK_SCALING
+CONFIG_TEGRA_EARLY_TPS6586X
CONFIG_TEGRA_ENABLE_UARTA
CONFIG_TEGRA_ENABLE_UARTB
CONFIG_TEGRA_ENABLE_UARTC