diff options
-rw-r--r-- | arch/arm/mach-tegra/common.c | 59 | ||||
-rw-r--r-- | arch/arm/mach-tegra/headsmp.S | 91 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pm.c | 30 | ||||
-rw-r--r-- | arch/arm/mach-tegra/reset.h | 38 | ||||
-rw-r--r-- | arch/arm/mach-tegra/sleep-t20.S | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/sleep-t30.S | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/sleep.S | 26 | ||||
-rw-r--r-- | arch/arm/mach-tegra/sleep.h | 3 |
8 files changed, 195 insertions, 54 deletions
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 61362d17768c..2a76e6279969 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -470,30 +470,11 @@ void tegra_init_cache(bool init) #else #ifdef CONFIG_TEGRA_SILICON_PLATFORM if (is_lp_cluster()) { -#ifdef CONFIG_ARCH_TEGRA_14x_SOC - tag_latency = 0x110; - data_latency = 0x331; -#else - tag_latency = 0x221; - data_latency = 0x221; -#endif + tag_latency = tegra_cpu_c1_l2_tag_latency; + data_latency = tegra_cpu_c1_l2_data_latency; } else { -#ifdef CONFIG_ARCH_TEGRA_14x_SOC - tag_latency = 0x111; - data_latency = 0x441; -#else - u32 speedo; - /* relax l2-cache latency for speedos 4,5,6 (T33's chips) */ - speedo = tegra_cpu_speedo_id(); - if (speedo == 4 || speedo == 5 || speedo == 6 || - speedo == 12 || speedo == 13) { - tag_latency = 0x442; - data_latency = 0x552; - } else { - tag_latency = 0x441; - data_latency = 0x551; - } -#endif + tag_latency = tegra_cpu_c0_l2_tag_latency; + data_latency = tegra_cpu_c0_l2_data_latency; } #else tag_latency = 0x770; @@ -712,6 +693,9 @@ void __init tegra20_init_early(void) #ifdef CONFIG_ARCH_TEGRA_3x_SOC void __init tegra30_init_early(void) { + u32 speedo; + u32 tag_latency, data_latency; + #ifndef CONFIG_SMP /* For SMP system, initializing the reset handler here is too late. For non-SMP systems, the function that calls the reset @@ -721,6 +705,27 @@ void __init tegra30_init_early(void) tegra_apb_io_init(); tegra_perf_init(); tegra_init_fuse(); + /* + * Store G/LP cluster L2 latencies to IRAM and DRAM + */ + tegra_cpu_c1_l2_tag_latency = 0x221; + tegra_cpu_c1_l2_data_latency = 0x221; + writel_relaxed(0x221, tegra_cpu_c1_l2_tag_latency_iram); + writel_relaxed(0x221, tegra_cpu_c1_l2_data_latency_iram); + /* relax l2-cache latency for speedos 4,5,6 (T33's chips) */ + speedo = tegra_cpu_speedo_id(); + if (speedo == 4 || speedo == 5 || speedo == 6 || + speedo == 12 || speedo == 13) { + tag_latency = 0x442; + data_latency = 0x552; + } else { + tag_latency = 0x441; + data_latency = 0x551; + } + tegra_cpu_c0_l2_tag_latency = tag_latency; + tegra_cpu_c0_l2_data_latency = data_latency; + writel_relaxed(tag_latency, tegra_cpu_c0_l2_tag_latency_iram); + writel_relaxed(data_latency, tegra_cpu_c0_l2_data_latency_iram); tegra_init_cache(true); tegra_pmc_init(); tegra_powergate_init(); @@ -780,6 +785,14 @@ void __init tegra14x_init_early(void) tegra14x_init_dvfs(); tegra_common_init_clock(); tegra_clk_init_from_table(tegra14x_clk_init_table); + tegra_cpu_c1_l2_tag_latency = 0x110; + tegra_cpu_c1_l2_data_latency = 0x331; + writel_relaxed(0x110, tegra_cpu_c1_l2_tag_latency_iram); + writel_relaxed(0x331, tegra_cpu_c1_l2_data_latency_iram); + tegra_cpu_c0_l2_tag_latency = 0x111; + tegra_cpu_c0_l2_data_latency = 0x441; + writel_relaxed(0x111, tegra_cpu_c0_l2_tag_latency_iram); + writel_relaxed(0x441, tegra_cpu_c0_l2_data_latency_iram); tegra_init_cache(true); tegra_pmc_init(); tegra_powergate_init(); diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S index 72b1fc778ae1..4a39cc63d181 100644 --- a/arch/arm/mach-tegra/headsmp.S +++ b/arch/arm/mach-tegra/headsmp.S @@ -24,6 +24,7 @@ #include <asm/assembler.h> #include <asm/cache.h> #include <asm/page.h> +#include <asm/hardware/cache-l2x0.h> #include "flowctrl.h" #include "iomap.h" @@ -35,6 +36,9 @@ #define DEBUG_CPU_RESET_HANDLER 0 /* Non-zero enables debug code */ +#define RESET_DATA_PHYS (TEGRA_RESET_HANDLER_BASE \ + + __tegra_cpu_reset_handler_data - __tegra_cpu_reset_handler_start) + #define RESET_DATA(x) ((TEGRA_RESET_##x)*4) #ifdef CONFIG_SMP @@ -100,7 +104,7 @@ ENTRY(tegra_resume) movw r0, #0x3FFD @ enable, enable_ext, cluster_switch, immed, & bitmaps bic r1, r1, r0 str r1, [r2] -#endif +#endif /* !CONFIG_ARCH_TEGRA_2x_SOC */ #if defined(CONFIG_HAVE_ARM_SCU) /* enable SCU */ @@ -108,7 +112,7 @@ ENTRY(tegra_resume) ldr r1, [r0] orr r1, r1, #1 str r1, [r0] -#endif +#endif /* CONFIG_HAVE_ARM_SCU */ #ifdef CONFIG_TRUSTED_FOUNDATIONS #ifndef CONFIG_ARCH_TEGRA_11x_SOC @@ -117,15 +121,73 @@ ENTRY(tegra_resume) adr r1, tegra_resume_smc_entry_time str r0, [r1] - /* wake up (should have specified args?) */ + /* wake up */ + mov r0, #0x00000003 bl tegra_generic_smc mov32 r1, TEGRA_TMRUS_BASE ldr r0, [r1] adr r1, tegra_resume_smc_exit_time str r0, [r1] +#endif /* !CONFIG_ARCH_TEGRA_11x_SOC */ +#endif /* CONFIG_TRUSTED_FOUNDATIONS */ + +#ifdef CONFIG_CACHE_L2X0 +#if !defined(CONFIG_TRUSTED_FOUNDATIONS) && !defined(CONFIG_ARCH_TEGRA_14x_SOC) + adr r0, tegra_resume_l2_init + ldr r1, [r0] + tst r1, #1 + beq no_l2_init + /* Enable L2 */ + bic r1, #1 + str r1, [r0] + mov32 r3, TEGRA_ARM_PL310_BASE +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) + mov32 r0, 0x331 /* tag latency */ + mov32 r1, 0x441 /* data latency */ +#elif defined(CONFIG_ARCH_TEGRA_3x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC) +#ifdef CONFIG_TEGRA_SILICON_PLATFORM + mov32 r0, TEGRA_FLOW_CTRL_BASE + 0x2c /* FLOW_CTRL_CLUSTER_CONTROL */ + mov32 r2, RESET_DATA_PHYS + ldr r1, [r0] + tst r1, #1 /* 0 == G, 1 == LP */ + ldrne r0, [r2, #RESET_DATA(C1_L2_TAG_LATENCY)] + ldrne r1, [r2, #RESET_DATA(C1_L2_DATA_LATENCY)] + ldreq r0, [r2, #RESET_DATA(C0_L2_TAG_LATENCY)] + ldreq r1, [r2, #RESET_DATA(C0_L2_DATA_LATENCY)] +#else /* !CONFIG_TEGRA_SILICON_PLATFORM */ + mov32 r0, #0x770 /* tag latency */ + mov32 r1, #0x770 /* data latency */ +#endif /* ?CONFIG_TEGRA_SILICON_PLATFORM */ +#endif /* CONFIG_ARCH_TEGRA_3x_SOC || CONFIG_ARCH_TEGRA_14x_SOC */ + str r0, [r3, #L2X0_TAG_LATENCY_CTRL] + str r1, [r3, #L2X0_DATA_LATENCY_CTRL] +#ifndef CONFIG_TEGRA_FPGA_PLATFORM +#ifdef CONFIG_ARCH_TEGRA_14x_SOC + mov32 r0, 0x40000007 /* Enable double line fill */ +#else + mov r0, #7 #endif -#endif + str r0, [r3, #L2X0_PREFETCH_CTRL] +#endif /* !CONFIG_TEGRA_FPGA_PLATFORM */ + mov r0, #3 + str r0, [r3, #L2X0_POWER_CTRL] + /* figure out aux ctrl */ + ldr r2, [r3, #L2X0_CACHE_TYPE] + and r2, r2, #0x700 + lsl r2, r2, #(17-8) + mov32 r4, 0x7C400001 + orr r2, r2, r4 + ldr r4, [r3, #L2X0_AUX_CTRL] + mov32 r5, 0x8200c3fe + and r4, r4, r5 + orr r2, r2, r4 + str r2, [r3, #L2X0_AUX_CTRL] + mov r2, #1 + str r2, [r3, #L2X0_CTRL] +#endif /* ?CONFIG_TRUSTED_FOUNDATIONS */ +#endif /* CONFIG_CACHE_L2X0 */ +no_l2_init: b cpu_resume ENDPROC(tegra_resume) @@ -134,7 +196,7 @@ ENDPROC(tegra_resume) #ifndef CONFIG_ARCH_TEGRA_11x_SOC .globl tegra_resume_smc_entry_time .globl tegra_resume_smc_exit_time -#endif +#endif /* !CONFIG_ARCH_TEGRA_11x_SOC */ .globl tegra_resume_entry_time .globl tegra_resume_timestamps_end tegra_resume_timestamps_start: @@ -143,13 +205,17 @@ tegra_resume_smc_entry_time: .long 0 tegra_resume_smc_exit_time: .long 0 -#endif +#endif /* !CONFIG_ARCH_TEGRA_11x_SOC */ tegra_resume_entry_time: .long 0 tegra_resume_timestamps_end: -ENTRY(__tegra_resume_timestamps_end) -#endif -#endif +#endif /* CONFIG_TRUSTED_FOUNDATIONS */ +#ifdef CONFIG_CACHE_L2X0 + .globl tegra_resume_l2_init +tegra_resume_l2_init: + .long 0 +#endif /* CONFIG_CACHE_L2X0 */ +#endif /* CONFIG_PM_SLEEP */ /* * __invalidate_cpu_state @@ -448,6 +514,11 @@ __tegra_cpu_reset_handler_data: .rept TEGRA_RESET_DATA_SIZE .long 0 .endr - .size __tegra_cpu_reset_handler_data, . - __tegra_cpu_reset_handler_data + .size __tegra_cpu_reset_handler_data, \ + . - __tegra_cpu_reset_handler_data .align L1_CACHE_SHIFT ENTRY(__tegra_cpu_reset_handler_end) + + .globl __tegra_cpu_reset_handler_data_offset + .equ __tegra_cpu_reset_handler_data_offset, \ + __tegra_cpu_reset_handler_data - __tegra_cpu_reset_handler_start diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 8078b578d72b..f49a8ac6c2cb 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -599,9 +599,6 @@ unsigned int tegra_idle_power_down_last(unsigned int sleep_time, { u32 reg; unsigned int remain; -#if defined(CONFIG_CACHE_L2X0) && !defined(CONFIG_ARCH_TEGRA_14x_SOC) - pgd_t *pgd; -#endif /* Only the last cpu down does the final suspend steps */ reg = readl(pmc + PMC_CTRL); @@ -673,27 +670,23 @@ unsigned int tegra_idle_power_down_last(unsigned int sleep_time, cpu_cluster_pm_enter(); suspend_cpu_complex(flags); tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_prolog); -#ifdef CONFIG_CACHE_L2X0 +#if defined(CONFIG_CACHE_L2X0) +#if defined(CONFIG_TRUSTED_FOUNDATIONS) flush_cache_all(); -#ifdef CONFIG_ARCH_TEGRA_14x_SOC - outer_flush_all(); -#else - /* - * No need to flush complete L2. Cleaning kernel and IO mappings - * is enough for the LP code sequence that has L2 disabled but - * MMU on. - */ - pgd = cpu_get_pgd(); - outer_clean_range(__pa(pgd + USER_PTRS_PER_PGD), - __pa(pgd + PTRS_PER_PGD)); -#endif outer_disable(); +#elif !defined(CONFIG_ARCH_TEGRA_14x_SOC) + tegra_resume_l2_init = 1; + __cpuc_flush_dcache_area(&tegra_resume_l2_init, sizeof(unsigned long)); + outer_flush_range(__pa(&tegra_resume_l2_init), + __pa(&tegra_resume_l2_init) + sizeof(unsigned long)); #endif +#endif + tegra_sleep_cpu(PHYS_OFFSET - PAGE_OFFSET); -#ifdef CONFIG_ARCH_TEGRA_14x_SOC +#if defined(CONFIG_ARCH_TEGRA_14x_SOC) tegra_init_cache(true); -#else +#elif defined(CONFIG_TRUSTED_FOUNDATIONS) tegra_init_cache(false); #endif @@ -1048,7 +1041,6 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags) #endif flush_cache_all(); - outer_flush_all(); outer_disable(); if (mode == TEGRA_SUSPEND_LP2) diff --git a/arch/arm/mach-tegra/reset.h b/arch/arm/mach-tegra/reset.h index 44a671160e57..413fdfbab082 100644 --- a/arch/arm/mach-tegra/reset.h +++ b/arch/arm/mach-tegra/reset.h @@ -25,7 +25,11 @@ #define TEGRA_RESET_STARTUP_SECONDARY 3 #define TEGRA_RESET_STARTUP_LP2 4 #define TEGRA_RESET_STARTUP_LP1 5 -#define TEGRA_RESET_DATA_SIZE 6 +#define TEGRA_RESET_C0_L2_TAG_LATENCY 6 +#define TEGRA_RESET_C0_L2_DATA_LATENCY 7 +#define TEGRA_RESET_C1_L2_TAG_LATENCY 8 +#define TEGRA_RESET_C1_L2_DATA_LATENCY 9 +#define TEGRA_RESET_DATA_SIZE 10 #ifndef __ASSEMBLY__ @@ -52,6 +56,38 @@ void tegra_secondary_startup(void); (u32)__tegra_cpu_reset_handler_start)))) #endif +#define tegra_cpu_c0_l2_tag_latency \ + __tegra_cpu_reset_handler_data[TEGRA_RESET_C0_L2_TAG_LATENCY] + +#define tegra_cpu_c0_l2_tag_latency_iram \ + ((u32 *)(IO_ADDRESS(TEGRA_RESET_HANDLER_BASE + \ + ((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_C0_L2_TAG_LATENCY] \ + - (u32)__tegra_cpu_reset_handler_start)))) + +#define tegra_cpu_c0_l2_data_latency \ + __tegra_cpu_reset_handler_data[TEGRA_RESET_C0_L2_DATA_LATENCY] + +#define tegra_cpu_c0_l2_data_latency_iram \ + ((u32 *)(IO_ADDRESS(TEGRA_RESET_HANDLER_BASE + \ + ((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_C0_L2_DATA_LATENCY] \ + - (u32)__tegra_cpu_reset_handler_start)))) + +#define tegra_cpu_c1_l2_tag_latency \ + __tegra_cpu_reset_handler_data[TEGRA_RESET_C1_L2_TAG_LATENCY] + +#define tegra_cpu_c1_l2_tag_latency_iram \ + ((u32 *)(IO_ADDRESS(TEGRA_RESET_HANDLER_BASE + \ + ((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_C1_L2_TAG_LATENCY] \ + - (u32)__tegra_cpu_reset_handler_start)))) + +#define tegra_cpu_c1_l2_data_latency \ + __tegra_cpu_reset_handler_data[TEGRA_RESET_C1_L2_DATA_LATENCY] + +#define tegra_cpu_c1_l2_data_latency_iram \ + ((u32 *)(IO_ADDRESS(TEGRA_RESET_HANDLER_BASE + \ + ((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_C1_L2_DATA_LATENCY] \ + - (u32)__tegra_cpu_reset_handler_start)))) + #define tegra_cpu_reset_handler_offset \ ((u32)__tegra_cpu_reset_handler - \ (u32)__tegra_cpu_reset_handler_start) diff --git a/arch/arm/mach-tegra/sleep-t20.S b/arch/arm/mach-tegra/sleep-t20.S index b189e573ecdb..ca540dd51599 100644 --- a/arch/arm/mach-tegra/sleep-t20.S +++ b/arch/arm/mach-tegra/sleep-t20.S @@ -177,6 +177,7 @@ ENTRY(tegra2_sleep_core_finish) sub r1, r1, r2 mov32 r2, TEGRA_IRAM_CODE_AREA add r1, r1, r2 + mov r11, #0 b tegra_turn_off_mmu ENDPROC(tegra2_sleep_core_finish) diff --git a/arch/arm/mach-tegra/sleep-t30.S b/arch/arm/mach-tegra/sleep-t30.S index 47874ba86156..41c524e42daf 100644 --- a/arch/arm/mach-tegra/sleep-t30.S +++ b/arch/arm/mach-tegra/sleep-t30.S @@ -266,6 +266,7 @@ ENTRY(tegra3_sleep_core_finish) sub r1, r1, r2 mov32 r2, TEGRA_IRAM_CODE_AREA add r1, r1, r2 + mov r11, #0 b tegra_turn_off_mmu ENDPROC(tegra3_sleep_core_finish) diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S index b634d0e75927..0fa40cc407dd 100644 --- a/arch/arm/mach-tegra/sleep.S +++ b/arch/arm/mach-tegra/sleep.S @@ -36,11 +36,13 @@ #include <asm/glue-cache.h> #include <asm/glue-proc.h> #include <asm/cp15.h> +#include <asm/hardware/cache-l2x0.h> #include "iomap.h" #include "sleep.h" #include "flowctrl.h" +#include "reset.h" #define CLK_RESET_CCLK_BURST 0x20 #define CLK_RESET_CCLK_DIVIDER 0x24 @@ -230,6 +232,7 @@ ENTRY(tegra_sleep_cpu_finish) mov32 r1, tegra3_tear_down_cpu #endif add r1, r1, r0 + mov r11, #1 b tegra_turn_off_mmu ENDPROC(tegra_sleep_cpu_finish) @@ -238,6 +241,7 @@ ENDPROC(tegra_sleep_cpu_finish) * * r0 = v2p * r1 = physical address to jump to with mmu off + * r11 = L2 disable/flush */ ENTRY(tegra_turn_off_mmu) /* @@ -275,6 +279,7 @@ tegra_pgd_phys_address: * tegra_shut_off_mmu * * r0 = physical address to jump to with mmu off + * r11 = L2 disable/flush * * called with VA=PA mapping * turns off MMU, icache, dcache and branch prediction @@ -287,7 +292,26 @@ tegra_shut_off_mmu: dsb mcr p15, 0, r3, c1, c0, 0 isb - mov pc, r0 +#if defined(CONFIG_CACHE_L2X0) && !defined(CONFIG_TRUSTED_FOUNDATIONS) + tst r11, #1 + beq 2f + mov32 r1, TEGRA_ARM_PL310_BASE +#ifdef CONFIG_ARCH_TEGRA_14x_SOC + /* need to flush the L2 */ + ldr r2, [r1, #L2X0_AUX_CTRL] + mov r2, #0xff + tst r2, #(1 << 16) @ associativity + orrne r2, #0xff00 + str r2, [r1, #L2X0_CLEAN_INV_WAY] +1: ldr r3, [r1, #L2X0_CLEAN_INV_WAY] + tst r3, r2 + bne 1b +#endif /* CONFIG_ARCH_TEGRA_14x_SOC */ + /* Disable L2 */ + mov r2, #0 + str r2, [r1, #L2X0_CTRL] +#endif /* CONFIG_CACHE_L2X0 && !CONFIG_TRUSTED_FOUNDATIONS */ +2: mov pc, r0 /* * tegra_cpu_clk32k diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index 5e72ade42bf8..1311acfcdf2c 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -328,6 +328,9 @@ extern unsigned long tegra_resume_smc_exit_time; #endif extern unsigned long tegra_resume_entry_time; #endif +#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_PM_SLEEP) +extern unsigned long tegra_resume_l2_init; +#endif static inline void *tegra_iram_start(void) { |