From f4db39ecb6319affd10b5a10212d7af3148ca731 Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Thu, 12 Jul 2018 11:22:51 +0200 Subject: apalis-tk1: remove non-esential power rails on boot When mainline kernels reboot TK1 they use SW_RESET, that reset mode does not reset PMIC. Some rails need to be off for RAM Re-repair to work correctly. Signed-off-by: Dominik Sliwa Acked-by: Marcel Ziswiler Acked-by: Stefan Agner --- arch/arm/mach-tegra/tegra124/cpu.c | 45 ++++++++++++++++++++++++++++++++++ board/toradex/apalis-tk1/as3722_init.c | 23 +++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/arch/arm/mach-tegra/tegra124/cpu.c b/arch/arm/mach-tegra/tegra124/cpu.c index d5e68f252a..8aa09ad1d4 100644 --- a/arch/arm/mach-tegra/tegra124/cpu.c +++ b/arch/arm/mach-tegra/tegra124/cpu.c @@ -233,6 +233,45 @@ static bool is_partition_powered(u32 partid) return !!(reg & (1 << partid)); } +static void unpower_partition(u32 partid) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + debug("%s: part ID = %08X\n", __func__, partid); + /* Is the partition on? */ + if (is_partition_powered(partid)) { + /* Yes, toggle the partition power state (ON -> OFF) */ + debug("power_partition, toggling state\n"); + writel(START_CP | partid, &pmc->pmc_pwrgate_toggle); + + /* Wait for the power to come down */ + while (is_partition_powered(partid)) + ; + + /* Give I/O signals time to stabilize */ + udelay(IO_STABILIZATION_DELAY); + } +} + +void unpower_cpus(void) +{ + debug("%s entry: G cluster\n", __func__); + + /* Power down the fast cluster rail partition */ + debug("%s: CRAIL\n", __func__); + unpower_partition(CRAIL); + + /* Power down the fast cluster non-CPU partition */ + debug("%s: C0NC\n", __func__); + unpower_partition(C0NC); + + /* Power down the fast cluster CPU0 partition */ + debug("%s: CE0\n", __func__); + unpower_partition(CE0); + + debug("%s: done\n", __func__); +} + static void power_partition(u32 partid) { struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; @@ -279,6 +318,12 @@ void start_cpu(u32 reset_vector) debug("%s entry, reset_vector = %x\n", __func__, reset_vector); + /* + * High power clusters are on after software reset, + * it may interfere with tegra124_ram_repair. + * unpower them. + */ + unpower_cpus(); tegra124_init_clocks(); /* Set power-gating timer multiplier */ diff --git a/board/toradex/apalis-tk1/as3722_init.c b/board/toradex/apalis-tk1/as3722_init.c index 4917034e1a..6911f79d14 100644 --- a/board/toradex/apalis-tk1/as3722_init.c +++ b/board/toradex/apalis-tk1/as3722_init.c @@ -44,6 +44,29 @@ void pmic_enable_cpu_vdd(void) udelay(10 * 1000); #endif + /* + * Make sure all non-fused regulators are down. + * That way we're in known state after software reboot from linux + */ + tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2); + tegra_i2c_ll_write_data(0x0003, I2C_SEND_2_BYTES); + udelay(10 * 1000); + tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2); + tegra_i2c_ll_write_data(0x0004, I2C_SEND_2_BYTES); + udelay(10 * 1000); + tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2); + tegra_i2c_ll_write_data(0x001b, I2C_SEND_2_BYTES); + udelay(10 * 1000); + tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2); + tegra_i2c_ll_write_data(0x0014, I2C_SEND_2_BYTES); + udelay(10 * 1000); + tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2); + tegra_i2c_ll_write_data(0x001a, I2C_SEND_2_BYTES); + udelay(10 * 1000); + tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2); + tegra_i2c_ll_write_data(0x0019, I2C_SEND_2_BYTES); + udelay(10 * 1000); + debug("%s: Setting VDD_CPU to 1.0V via AS3722 reg 0/4D\n", __func__); /* * Bring up VDD_CPU via the AS3722 PMIC on the PWR I2C bus. -- cgit v1.2.3