diff options
Diffstat (limited to 'arch/arm/mach-tegra/sleep-t3.S')
-rw-r--r-- | arch/arm/mach-tegra/sleep-t3.S | 150 |
1 files changed, 149 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/sleep-t3.S b/arch/arm/mach-tegra/sleep-t3.S index 23e96c605b96..4ee73d581a08 100644 --- a/arch/arm/mach-tegra/sleep-t3.S +++ b/arch/arm/mach-tegra/sleep-t3.S @@ -95,6 +95,16 @@ #define PMC_PLLM_WB0_OVERRIDE 0x1dc #define CLK_RESET_CLK_SOURCE_MSELECT 0x3b4 +#define CLK_RESET_CLK_ENB_H_SET 0x328 +#define CLK_RESET_CLK_ENB_H_CLR 0x32c +#define CLK_RESET_CLK_RST_DEV_H_SET 0x308 +#define CLK_RESET_CLK_RST_DEV_H_CLR 0x30c + +#define I2C_CNFG 0x0 +#define I2C_ADDR0 0x4 +#define I2C_DATA1 0xc +#define I2C_DATA2 0x10 +#define I2C_STATUS 0x1c #define MSELECT_CLKM (0x3 << 30) @@ -348,6 +358,66 @@ ENTRY(tegra3_lp1_reset) mov32 r4, ((1<<28) | (8)) @ burst policy is PLLX str r4, [r0, #CLK_RESET_CCLK_BURST] +#ifdef CONFIG_TEGRA_LP1_950 +lp1_voltset: + /* Restore the Core voltage to high on LP1 resume */ + /* Reset(Enable/Disable) the DVC-I2C Controller*/ + mov r1, #(1 << 15) + str r1, [r0, #CLK_RESET_CLK_RST_DEV_H_SET] + + /* Wait for 2us */ + mov32 r7, TEGRA_TMRUS_BASE + wait_for_us r1, r7, r9 + add r1, r1, #2 + wait_until r1, r7, r9 + + mov r1, #(1 << 15) + str r1, [r0, #CLK_RESET_CLK_RST_DEV_H_CLR] + + /* Enable the DVC-I2C Controller */ + mov r1, #(1 << 15) + str r1, [r0, #CLK_RESET_CLK_ENB_H_SET] + + + /* Same I2C transaction protocol as suspend */ + ldr r1, lp1_register_pmuslave_addr + cmp r1, #0 + beq lp1_voltskip_resume + + ldr r4, lp1_register_i2c_base_addr + str r1, [r4, #I2C_ADDR0] + + mov32 r1, 0x2 + str r1, [r4, #I2C_CNFG] + + ldr r1, lp1_register_core_highvolt + str r1, [r4, #I2C_DATA1] + + mov32 r1, 0 + str r1, [r4, #I2C_DATA2] + + mov32 r1, 0xA02 + str r1, [r4, #I2C_CNFG] + + wait_for_us r1, r7, r9 + mov32 r3, 0x7D0 /* Wait for 2ms and try transaction again */ + add r0, r1, r3 +loop_i2c_status_resume: + add r1, r1, #0xFA /* Check status every 250us */ + wait_until r1, r7, r9 + cmp r0, r1 + beq lp1_voltset + + ldr r3, [r4, #I2C_STATUS] + cmp r3, #0 + bne loop_i2c_status_resume + +lp1_voltskip_resume: + /* Disable the DVC-I2C Controller */ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_ENB_H_CLR] +#endif + #if defined (CONFIG_CACHE_L2X0) /* power up L2 */ ldr r0, [r2, #PMC_PWRGATE_STATUS] @@ -492,6 +562,21 @@ tegra3_sdram_pad_address: tegra3_sdram_pad_size: .word tegra3_sdram_pad_address - tegra3_sdram_pad_save +#ifdef CONFIG_TEGRA_LP1_950 + .globl lp1_register_pmuslave_addr + .globl lp1_register_i2c_base_addr + .globl lp1_register_core_lowvolt + .globl lp1_register_core_highvolt +lp1_register_pmuslave_addr: + .word 0 +lp1_register_i2c_base_addr: + .word 0 +lp1_register_core_lowvolt: + .word 0 +lp1_register_core_highvolt: + .word 0 +#endif + /* * tegra3_tear_down_core * @@ -526,9 +611,72 @@ tegra3_cpu_clk32k: str r0, [r4, #PMC_PLLM_WB0_OVERRIDE] mov pc, lr +lp1_clocks_prepare: + /* Prepare to set the Core to the lowest voltage if supported. + * Start by setting the I2C clocks to make the I2C transfer */ +#ifdef CONFIG_TEGRA_LP1_950 + /* Set up the PWR I2C GPIOs with the right masks*/ + + /* Reset(Set/Clr) the DVC-I2C Controller*/ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_RST_DEV_H_SET] + + /* Wait for 2us */ + wait_for_us r1, r7, r9 + mov32 r0, 0x7D0 + add r1, r1, r0 + wait_until r1, r7, r9 + + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_RST_DEV_H_CLR] + + /* Enable the DVC-I2C Controller */ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_ENB_H_SET] + + /* I2C transfer protocol: + * 4 packets: Slaveaddr + WriteConfigure + Data1 + Data2 */ + ldr r0, lp1_register_pmuslave_addr + cmp r0, #0 + beq lp1_volt_skip + ldr r1, lp1_register_i2c_base_addr + str r0, [r1, #I2C_ADDR0] + + mov32 r0, 0x2 + str r0, [r1, #I2C_CNFG] + + ldr r0, lp1_register_core_lowvolt + str r0, [r1, #I2C_DATA1] + + mov32 r0, 0 + str r0, [r1, #I2C_DATA2] + + /* Send I2C transaction */ + mov32 r0, 0xA02 + str r0, [r1, #I2C_CNFG] + + /* Check the transaction status before proceeding */ + wait_for_us r2, r7, r9 + mov32 r3, 0x7D0 /* Wait for 2ms for I2C transaction */ + add r3, r2, r3 +loop_i2c_status_suspend: + add r2, r2, #0xFA /* Check status every 250us */ + cmp r3, r2 + beq lp1_volt_skip /* Waited for 2ms, I2C transaction didn't take place */ + wait_until r2, r7, r9 + + ldr r0, [r1, #I2C_STATUS] + cmp r0, #0 + bne loop_i2c_status_suspend +lp1_volt_skip: + + /* Disable the DVC-I2C Controller */ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_ENB_H_CLR] + +#endif /* start by jumping to clkm to safely disable PLLs, then jump * to clks */ -lp1_clocks_prepare: mov r0, #(1 << 28) str r0, [r5, #CLK_RESET_SCLK_BURST] str r0, [r5, #CLK_RESET_CCLK_BURST] |