diff options
author | Scott Williams <scwilliams@nvidia.com> | 2010-12-07 11:19:20 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-04-26 15:48:38 -0700 |
commit | 5e5807fa30957aeac0a6ce727e9ce98c79ec6b8b (patch) | |
tree | 65e08bdaeede5b93cc2db9c9ef9ed8e79c07703f /arch/arm/mach-tegra/headsmp-t3.S | |
parent | 464936c9afcab046e38fb8f7851627a7ac0520de (diff) |
[ARM/tegra] Add Tegra3 support
Bug 764354
Original-Change-Id: I8a390eb4dae87dceacb97461f23d13554868b046
Reviewed-on: http://git-master/r/12228
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Tested-by: Scott Williams <scwilliams@nvidia.com>
Change-Id: I8e6b8303898796419fb5a759cd16edff9aeac081
Diffstat (limited to 'arch/arm/mach-tegra/headsmp-t3.S')
-rw-r--r-- | arch/arm/mach-tegra/headsmp-t3.S | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/headsmp-t3.S b/arch/arm/mach-tegra/headsmp-t3.S new file mode 100644 index 000000000000..5554f3634aee --- /dev/null +++ b/arch/arm/mach-tegra/headsmp-t3.S @@ -0,0 +1,210 @@ +/* + * arch/arm/mach-tegra/headsmp-t2.S + * + * SMP initialization routines for Tegra3 SoCs + * + * Copyright (c) 2009-2010, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/linkage.h> +#include <linux/init.h> + +#include <asm/assembler.h> +#include <asm/domain.h> +#include <asm/ptrace.h> +#include <asm/cache.h> + +#include <mach/iomap.h> +#include <mach/io.h> + +#include "power-macros.S" + +#define TTB_FLAGS 0x6A @ IRGN_WBWA, OC_RGN_WBWA, S, NOS + +#define DEBUG_HOTPLUG_STARTUP 0 /* Nonzero for hotplug startup debug */ +#define DEBUG_LP2_STARTUP 0 /* Nonzero for LP2 startup debug */ + +#define PMC_DPD_SAMPLE 0x20 +#define PMC_DPD_ENABLE 0x24 +#define PMC_SCRATCH39 0x138 +#define CLK_RESET_PLLX_BASE 0xe0 +#define CLK_RESET_PLLX_MISC 0xe4 +#define CLK_RESET_PLLP_BASE 0xa0 +#define CLK_RESET_PLLP_OUTA 0xa4 +#define CLK_RESET_PLLP_OUTB 0xa8 +#define CLK_RESET_PLLP_MISC 0xac + +/* .section ".cpuinit.text", "ax"*/ + +/* + * __restart_plls + * + * Loads the saved PLLX and PLLP parameters into the PLLs, to + * allow them to stabilize while the rest of the CPU state is restored. + * Should be called after the MMU is enabled. Jumps directly + * to __cortex_a9_restore + */ + .align L1_CACHE_SHIFT +__restart_plls: + mov32 r0, tegra_sctx + mov32 r3, (TEGRA_CLK_RESET_BASE-IO_PPSB_PHYS+IO_PPSB_VIRT) + mov32 r4, (TEGRA_TMRUS_BASE-IO_PPSB_PHYS+IO_PPSB_VIRT) + + ldr r1, [r0, #0x0] @ pllx_misc + ldr r2, [r0, #0x4] @ pllx_base + str r1, [r3, #CLK_RESET_PLLX_MISC] + str r2, [r3, #CLK_RESET_PLLX_BASE] + + ldr r1, [r0, #0x8] @ pllp_misc + ldr r2, [r0, #0xc] @ pllp_base + str r1, [r3, #CLK_RESET_PLLP_MISC] + str r2, [r3, #CLK_RESET_PLLP_BASE] + + ldr r1, [r0, #0x10] @ pllp_outa + ldr r2, [r0, #0x14] @ pllp_outb + str r1, [r3, #CLK_RESET_PLLP_OUTA] + str r2, [r3, #CLK_RESET_PLLP_OUTB] + + /* record the time that PLLX and PLLP will be stable */ + ldr r1, [r4] + add r1, r1, #300 + str r1, [r0, #0x18] @ pll_timeout + /* FIXME: need to record actual power transition here */ + mov r0, #0 + b __cortex_a9_l2x0_restart +ENDPROC(__restart_plls) + +/* + * tegra_lp2_startup + * + * Secondary CPU boot vector when restarting the master CPU following + * an LP2 idle transition. Re-enable coresight access, re-enable + * MMU, re-start PLLX, restore processor context. + */ + .align L1_CACHE_SHIFT +ENTRY(tegra_lp2_startup) +#if DEBUG_LP2_STARTUP + b . +#endif + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 + + mov32 r0, TEGRA_TMRUS_BASE + ldr r1, [r0] + mov32 r0, TEGRA_PMC_BASE + str r1, [r0, #PMC_SCRATCH39] @ save off exact lp2 exit time + mov r1, #0 + str r1, [r0, #PMC_DPD_SAMPLE] + str r1, [r0, #PMC_DPD_ENABLE] + + bl __invalidate_cpu_state + bl __enable_coresite_access + +#ifdef DEBUG + cpu_id r0 + cmp r0, #0 + bne . @ should only come here for CPU0 +#endif + + @ Clear the flow controller flags for this CPU. + mov32 r2, TEGRA_FLOW_CTRL_BASE+8 @ CPU0 CSR + ldr r1, [r2] + orr r1, r1, #(1 << 15) | (1 << 14) @ write to clear event & intr + movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps + bic r1, r1, r0 + str r1, [r2] + + mrc p15, 0, r0, c1, c0, 1 + orr r0, r0, #(1 << 6) | (1 << 0) @ re-enable coherency + mcr p15, 0, r0, c1, c0, 1 + + /* enable SCU */ + mov32 r0, TEGRA_ARM_PERIF_BASE + ldr r1, [r0] + orr r1, r1, #1 + str r1, [r0] + + adr r4, __tegra_lp2_data + ldmia r4, {r5, r7, r12} + mov r1, r12 @ ctx_restore = __cortex_a9_restore + sub r4, r4, r5 + ldr r0, [r7, r4] @ pgdir = tegra_pgd_phys + b __return_to_virtual +ENDPROC(tegra_lp2_startup) + .type __tegra_lp2_data, %object +__tegra_lp2_data: + .long . + .long tegra_pgd_phys + .long __restart_plls + .size __tegra_lp2_data, . - __tegra_lp2_data + +#ifdef CONFIG_HOTPLUG_CPU +/* + * tegra_hotplug_startup + * + * Secondary CPU boot vector when restarting a CPU following a + * hot-unplug. Uses the page table created by smp_prepare_cpus and + * stored in tegra_pgd_phys as the safe page table for + * __return_to_virtual, and jumps directly to __cortex_a9_restore. + */ + .align L1_CACHE_SHIFT +ENTRY(tegra_hotplug_startup) +#if DEBUG_HOTPLUG_STARTUP + b . +#endif + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 + bl __invalidate_cpu_state + enable_coresite r1 + cpu_id r0 + subs r1, r0, #1 +#ifdef DEBUG + /* !!!CHECKME!!! THIS MAY NOW BE OBSOLETE */ + bmi . @ should never come here for CPU0 +#endif + mov r3, r1, lsl #3 + add r3, r3, #0x18 @ CPUn CSR offset, n>0 + mov32 r2, TEGRA_FLOW_CTRL_BASE + + @ Clear the flow controller flags for this CPU. + ldr r1, [r2, r3] + orr r1, r1, #(1 << 15) | (1 << 14) @ write to clear event & intr + movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps + bic r1, r1, r0 + str r1, [r2, r3] + + /* most of the below is a retread of what happens in __v7_setup and + * secondary_startup, to get the MMU re-enabled and to branch + * to secondary_kernel_startup */ + mrc p15, 0, r0, c1, c0, 1 + orr r0, r0, #(1 << 6) | (1 << 0) @ re-enable coherency + mcr p15, 0, r0, c1, c0, 1 + + adr r4, __tegra_hotplug_data + ldmia r4, {r5, r7, r12} + mov r1, r12 @ ctx_restore = __cortex_a9_restore + sub r4, r4, r5 + ldr r0, [r7, r4] @ pgdir = secondary_data.pgdir + b __return_to_virtual +ENDPROC(tegra_hotplug_startup) + + + .type __tegra_hotplug_data, %object +__tegra_hotplug_data: + .long . + .long tegra_pgd_phys + .long __cortex_a9_restore + .size __tegra_hotplug_data, . - __tegra_hotplug_data +#endif |