aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-02-05 15:10:18 -0500
committerOlof Johansson <olof@lixom.net>2013-02-05 15:10:18 -0500
commitf0390669d13b0a1592fc7906445b4f6c8ec5af23 (patch)
tree4a27ffbd016d24f54ba1e3a38d46a386ab924bc6 /arch/arm/mach-tegra
parentb60decad7791694a36ad218cede77a407c1475ce (diff)
parent24e30c9417230b359bf6dfeb923e90138df7c112 (diff)
Merge tag 'tegra-for-3.9-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra into next/cleanup
From Stephen Warren: ARM: tegra: cleanup This pull request contains various cleanup and minor changes to core Tegra code: * Tegra clocksource driver is moved to drivers/clocksource. * Various typos, warning cleanup, statics cleanup, section mismatch fixes, etc. * Various small fixes/cleanups for CPU/hotplug/SMP code. This pull request is based on a merge of v3.8-rc3 and at least part of arm-soc's timer/cleanup branch. * tag 'tegra-for-3.9-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra: ARM: tegra: fix compile error when disable CPU_IDLE ARM: tegra30: make the wait time of CPU power up to proportional to HZ ARM: tegra: make device can run on UP ARM: tegra: clean up the CPUINIT section ARM: tegra: moving the clock gating procedure to tegra_cpu_kill ARM: tegra: update the cache maintenance order for CPU shutdown ARM: tegra30: fix power up sequence for boot_secondary ARM: tegra: cpufreq: move clk_get/put out of function tegra_cpu_init/exit ARM: tegra: fix Kconfig warnings when !SMP ARM: tegra: Make variables static clocksource: tegra: cosmetic: Fix error message ARM: tegra: move timer.c to drivers/clocksource/ Signed-off-by: Olof Johansson <olof@lixom.net> Trivial conflicts: arch/arm/mach-tegra/board-dt-tegra20.c arch/arm/mach-tegra/board-dt-tegra30.c drivers/clocksource/Makefile
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/Kconfig4
-rw-r--r--arch/arm/mach-tegra/Makefile6
-rw-r--r--arch/arm/mach-tegra/apbio.c2
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra20.c13
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra30.c5
-rw-r--r--arch/arm/mach-tegra/board.h1
-rw-r--r--arch/arm/mach-tegra/common.c3
-rw-r--r--arch/arm/mach-tegra/common.h1
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c40
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra30.c6
-rw-r--r--arch/arm/mach-tegra/flowctrl.c4
-rw-r--r--arch/arm/mach-tegra/headsmp.S221
-rw-r--r--arch/arm/mach-tegra/hotplug.c21
-rw-r--r--arch/arm/mach-tegra/platsmp.c43
-rw-r--r--arch/arm/mach-tegra/pm.c4
-rw-r--r--arch/arm/mach-tegra/reset-handler.S239
-rw-r--r--arch/arm/mach-tegra/reset.c2
-rw-r--r--arch/arm/mach-tegra/sleep-tegra20.S3
-rw-r--r--arch/arm/mach-tegra/sleep-tegra30.S3
-rw-r--r--arch/arm/mach-tegra/sleep.S4
-rw-r--r--arch/arm/mach-tegra/sleep.h1
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks_data.c6
-rw-r--r--arch/arm/mach-tegra/timer.c284
23 files changed, 347 insertions, 569 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index b442f15fd01a..1ec7f80e2af5 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -6,9 +6,9 @@ config ARCH_TEGRA_2x_SOC
6 bool "Enable support for Tegra20 family" 6 bool "Enable support for Tegra20 family"
7 select ARCH_REQUIRE_GPIOLIB 7 select ARCH_REQUIRE_GPIOLIB
8 select ARM_ERRATA_720789 8 select ARM_ERRATA_720789
9 select ARM_ERRATA_742230 9 select ARM_ERRATA_742230 if SMP
10 select ARM_ERRATA_751472 10 select ARM_ERRATA_751472
11 select ARM_ERRATA_754327 11 select ARM_ERRATA_754327 if SMP
12 select ARM_ERRATA_764369 if SMP 12 select ARM_ERRATA_764369 if SMP
13 select ARM_GIC 13 select ARM_GIC
14 select CPU_FREQ_TABLE if CPU_FREQ 14 select CPU_FREQ_TABLE if CPU_FREQ
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 0979e8bba78a..f0520961bafe 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -2,15 +2,16 @@ obj-y += common.o
2obj-y += io.o 2obj-y += io.o
3obj-y += irq.o 3obj-y += irq.o
4obj-y += clock.o 4obj-y += clock.o
5obj-y += timer.o
6obj-y += fuse.o 5obj-y += fuse.o
7obj-y += pmc.o 6obj-y += pmc.o
8obj-y += flowctrl.o 7obj-y += flowctrl.o
9obj-y += powergate.o 8obj-y += powergate.o
10obj-y += apbio.o 9obj-y += apbio.o
11obj-y += pm.o 10obj-y += pm.o
11obj-y += reset.o
12obj-y += reset-handler.o
13obj-y += sleep.o
12obj-$(CONFIG_CPU_IDLE) += cpuidle.o 14obj-$(CONFIG_CPU_IDLE) += cpuidle.o
13obj-$(CONFIG_CPU_IDLE) += sleep.o
14obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks.o 15obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks.o
15obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks_data.o 16obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks_data.o
16obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o 17obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
@@ -27,7 +28,6 @@ ifeq ($(CONFIG_CPU_IDLE),y)
27obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o 28obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o
28endif 29endif
29obj-$(CONFIG_SMP) += platsmp.o headsmp.o 30obj-$(CONFIG_SMP) += platsmp.o headsmp.o
30obj-$(CONFIG_SMP) += reset.o
31obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 31obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
32obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o 32obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
33obj-$(CONFIG_TEGRA_PCI) += pcie.o 33obj-$(CONFIG_TEGRA_PCI) += pcie.o
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
index d091675ba376..d7aa52ea6cfc 100644
--- a/arch/arm/mach-tegra/apbio.c
+++ b/arch/arm/mach-tegra/apbio.c
@@ -38,7 +38,7 @@ static void tegra_apb_writel_direct(u32 value, unsigned long offset);
38static struct dma_chan *tegra_apb_dma_chan; 38static struct dma_chan *tegra_apb_dma_chan;
39static struct dma_slave_config dma_sconfig; 39static struct dma_slave_config dma_sconfig;
40 40
41bool tegra_apb_dma_init(void) 41static bool tegra_apb_dma_init(void)
42{ 42{
43 dma_cap_mask_t mask; 43 dma_cap_mask_t mask;
44 44
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c
index 5ed81bab2d4b..d320f7ad7350 100644
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ b/arch/arm/mach-tegra/board-dt-tegra20.c
@@ -15,6 +15,7 @@
15 * 15 *
16 */ 16 */
17 17
18#include <linux/clocksource.h>
18#include <linux/kernel.h> 19#include <linux/kernel.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
@@ -43,31 +44,31 @@
43#include "common.h" 44#include "common.h"
44#include "iomap.h" 45#include "iomap.h"
45 46
46struct tegra_ehci_platform_data tegra_ehci1_pdata = { 47static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
47 .operating_mode = TEGRA_USB_OTG, 48 .operating_mode = TEGRA_USB_OTG,
48 .power_down_on_bus_suspend = 1, 49 .power_down_on_bus_suspend = 1,
49 .vbus_gpio = -1, 50 .vbus_gpio = -1,
50}; 51};
51 52
52struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = { 53static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
53 .reset_gpio = -1, 54 .reset_gpio = -1,
54 .clk = "cdev2", 55 .clk = "cdev2",
55}; 56};
56 57
57struct tegra_ehci_platform_data tegra_ehci2_pdata = { 58static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
58 .phy_config = &tegra_ehci2_ulpi_phy_config, 59 .phy_config = &tegra_ehci2_ulpi_phy_config,
59 .operating_mode = TEGRA_USB_HOST, 60 .operating_mode = TEGRA_USB_HOST,
60 .power_down_on_bus_suspend = 1, 61 .power_down_on_bus_suspend = 1,
61 .vbus_gpio = -1, 62 .vbus_gpio = -1,
62}; 63};
63 64
64struct tegra_ehci_platform_data tegra_ehci3_pdata = { 65static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
65 .operating_mode = TEGRA_USB_HOST, 66 .operating_mode = TEGRA_USB_HOST,
66 .power_down_on_bus_suspend = 1, 67 .power_down_on_bus_suspend = 1,
67 .vbus_gpio = -1, 68 .vbus_gpio = -1,
68}; 69};
69 70
70struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = { 71static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
71 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL), 72 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
72 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL), 73 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
73 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL), 74 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL),
@@ -200,7 +201,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
200 .smp = smp_ops(tegra_smp_ops), 201 .smp = smp_ops(tegra_smp_ops),
201 .init_early = tegra20_init_early, 202 .init_early = tegra20_init_early,
202 .init_irq = tegra_dt_init_irq, 203 .init_irq = tegra_dt_init_irq,
203 .init_time = tegra_init_timer, 204 .init_time = clocksource_of_init,
204 .init_machine = tegra_dt_init, 205 .init_machine = tegra_dt_init,
205 .init_late = tegra_dt_init_late, 206 .init_late = tegra_dt_init_late,
206 .restart = tegra_assert_system_reset, 207 .restart = tegra_assert_system_reset,
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
index 12dc2ddeca64..97e1f67fc31d 100644
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ b/arch/arm/mach-tegra/board-dt-tegra30.c
@@ -23,6 +23,7 @@
23 * 23 *
24 */ 24 */
25 25
26#include <linux/clocksource.h>
26#include <linux/kernel.h> 27#include <linux/kernel.h>
27#include <linux/of.h> 28#include <linux/of.h>
28#include <linux/of_address.h> 29#include <linux/of_address.h>
@@ -37,7 +38,7 @@
37#include "common.h" 38#include "common.h"
38#include "iomap.h" 39#include "iomap.h"
39 40
40struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = { 41static struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
41 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL), 42 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL),
42 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000200, "sdhci-tegra.1", NULL), 43 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000200, "sdhci-tegra.1", NULL),
43 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000400, "sdhci-tegra.2", NULL), 44 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000400, "sdhci-tegra.2", NULL),
@@ -111,7 +112,7 @@ DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
111 .map_io = tegra_map_common_io, 112 .map_io = tegra_map_common_io,
112 .init_early = tegra30_init_early, 113 .init_early = tegra30_init_early,
113 .init_irq = tegra_dt_init_irq, 114 .init_irq = tegra_dt_init_irq,
114 .init_time = tegra_init_timer, 115 .init_time = clocksource_of_init,
115 .init_machine = tegra30_dt_init, 116 .init_machine = tegra30_dt_init,
116 .init_late = tegra_init_late, 117 .init_late = tegra_init_late,
117 .restart = tegra_assert_system_reset, 118 .restart = tegra_assert_system_reset,
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 744cdd246f6a..da8f5a3c4240 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -55,5 +55,4 @@ static inline int harmony_pcie_init(void) { return 0; }
55 55
56void __init tegra_paz00_wifikill_init(void); 56void __init tegra_paz00_wifikill_init(void);
57 57
58extern void tegra_init_timer(void);
59#endif 58#endif
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 3599959517b3..8f0ffe97ffee 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -36,6 +36,7 @@
36#include "apbio.h" 36#include "apbio.h"
37#include "sleep.h" 37#include "sleep.h"
38#include "pm.h" 38#include "pm.h"
39#include "reset.h"
39 40
40/* 41/*
41 * Storage for debug-macro.S's state. 42 * Storage for debug-macro.S's state.
@@ -131,6 +132,7 @@ static void __init tegra_init_cache(void)
131#ifdef CONFIG_ARCH_TEGRA_2x_SOC 132#ifdef CONFIG_ARCH_TEGRA_2x_SOC
132void __init tegra20_init_early(void) 133void __init tegra20_init_early(void)
133{ 134{
135 tegra_cpu_reset_handler_init();
134 tegra_apb_io_init(); 136 tegra_apb_io_init();
135 tegra_init_fuse(); 137 tegra_init_fuse();
136 tegra2_init_clocks(); 138 tegra2_init_clocks();
@@ -144,6 +146,7 @@ void __init tegra20_init_early(void)
144#ifdef CONFIG_ARCH_TEGRA_3x_SOC 146#ifdef CONFIG_ARCH_TEGRA_3x_SOC
145void __init tegra30_init_early(void) 147void __init tegra30_init_early(void)
146{ 148{
149 tegra_cpu_reset_handler_init();
147 tegra_apb_io_init(); 150 tegra_apb_io_init();
148 tegra_init_fuse(); 151 tegra_init_fuse();
149 tegra30_init_clocks(); 152 tegra30_init_clocks();
diff --git a/arch/arm/mach-tegra/common.h b/arch/arm/mach-tegra/common.h
index 02f71b4f1e51..32f8eb3fe344 100644
--- a/arch/arm/mach-tegra/common.h
+++ b/arch/arm/mach-tegra/common.h
@@ -1,4 +1,5 @@
1extern struct smp_operations tegra_smp_ops; 1extern struct smp_operations tegra_smp_ops;
2 2
3extern int tegra_cpu_kill(unsigned int cpu);
3extern void tegra_cpu_die(unsigned int cpu); 4extern void tegra_cpu_die(unsigned int cpu);
4extern int tegra_cpu_disable(unsigned int cpu); 5extern int tegra_cpu_disable(unsigned int cpu);
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index a74d3c7d2e26..85d4a23bba03 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -214,24 +214,6 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
214 if (policy->cpu >= NUM_CPUS) 214 if (policy->cpu >= NUM_CPUS)
215 return -EINVAL; 215 return -EINVAL;
216 216
217 cpu_clk = clk_get_sys(NULL, "cpu");
218 if (IS_ERR(cpu_clk))
219 return PTR_ERR(cpu_clk);
220
221 pll_x_clk = clk_get_sys(NULL, "pll_x");
222 if (IS_ERR(pll_x_clk))
223 return PTR_ERR(pll_x_clk);
224
225 pll_p_clk = clk_get_sys(NULL, "pll_p");
226 if (IS_ERR(pll_p_clk))
227 return PTR_ERR(pll_p_clk);
228
229 emc_clk = clk_get_sys("cpu", "emc");
230 if (IS_ERR(emc_clk)) {
231 clk_put(cpu_clk);
232 return PTR_ERR(emc_clk);
233 }
234
235 clk_prepare_enable(emc_clk); 217 clk_prepare_enable(emc_clk);
236 clk_prepare_enable(cpu_clk); 218 clk_prepare_enable(cpu_clk);
237 219
@@ -256,8 +238,6 @@ static int tegra_cpu_exit(struct cpufreq_policy *policy)
256{ 238{
257 cpufreq_frequency_table_cpuinfo(policy, freq_table); 239 cpufreq_frequency_table_cpuinfo(policy, freq_table);
258 clk_disable_unprepare(emc_clk); 240 clk_disable_unprepare(emc_clk);
259 clk_put(emc_clk);
260 clk_put(cpu_clk);
261 return 0; 241 return 0;
262} 242}
263 243
@@ -278,12 +258,32 @@ static struct cpufreq_driver tegra_cpufreq_driver = {
278 258
279static int __init tegra_cpufreq_init(void) 259static int __init tegra_cpufreq_init(void)
280{ 260{
261 cpu_clk = clk_get_sys(NULL, "cpu");
262 if (IS_ERR(cpu_clk))
263 return PTR_ERR(cpu_clk);
264
265 pll_x_clk = clk_get_sys(NULL, "pll_x");
266 if (IS_ERR(pll_x_clk))
267 return PTR_ERR(pll_x_clk);
268
269 pll_p_clk = clk_get_sys(NULL, "pll_p");
270 if (IS_ERR(pll_p_clk))
271 return PTR_ERR(pll_p_clk);
272
273 emc_clk = clk_get_sys("cpu", "emc");
274 if (IS_ERR(emc_clk)) {
275 clk_put(cpu_clk);
276 return PTR_ERR(emc_clk);
277 }
278
281 return cpufreq_register_driver(&tegra_cpufreq_driver); 279 return cpufreq_register_driver(&tegra_cpufreq_driver);
282} 280}
283 281
284static void __exit tegra_cpufreq_exit(void) 282static void __exit tegra_cpufreq_exit(void)
285{ 283{
286 cpufreq_unregister_driver(&tegra_cpufreq_driver); 284 cpufreq_unregister_driver(&tegra_cpufreq_driver);
285 clk_put(emc_clk);
286 clk_put(cpu_clk);
287} 287}
288 288
289 289
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
index 5e8cbf5b799f..82530bd9b8c2 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra30.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -121,9 +121,9 @@ static inline bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
121} 121}
122#endif 122#endif
123 123
124static int __cpuinit tegra30_idle_lp2(struct cpuidle_device *dev, 124static int tegra30_idle_lp2(struct cpuidle_device *dev,
125 struct cpuidle_driver *drv, 125 struct cpuidle_driver *drv,
126 int index) 126 int index)
127{ 127{
128 u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu; 128 u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu;
129 bool entered_lp2 = false; 129 bool entered_lp2 = false;
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
index a2250ddae797..5393eb2cae21 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
@@ -26,14 +26,14 @@
26#include "flowctrl.h" 26#include "flowctrl.h"
27#include "iomap.h" 27#include "iomap.h"
28 28
29u8 flowctrl_offset_halt_cpu[] = { 29static u8 flowctrl_offset_halt_cpu[] = {
30 FLOW_CTRL_HALT_CPU0_EVENTS, 30 FLOW_CTRL_HALT_CPU0_EVENTS,
31 FLOW_CTRL_HALT_CPU1_EVENTS, 31 FLOW_CTRL_HALT_CPU1_EVENTS,
32 FLOW_CTRL_HALT_CPU1_EVENTS + 8, 32 FLOW_CTRL_HALT_CPU1_EVENTS + 8,
33 FLOW_CTRL_HALT_CPU1_EVENTS + 16, 33 FLOW_CTRL_HALT_CPU1_EVENTS + 16,
34}; 34};
35 35
36u8 flowctrl_offset_cpu_csr[] = { 36static u8 flowctrl_offset_cpu_csr[] = {
37 FLOW_CTRL_CPU0_CSR, 37 FLOW_CTRL_CPU0_CSR,
38 FLOW_CTRL_CPU1_CSR, 38 FLOW_CTRL_CPU1_CSR,
39 FLOW_CTRL_CPU1_CSR + 8, 39 FLOW_CTRL_CPU1_CSR + 8,
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index 4a317fae6860..b2834810b02b 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -1,22 +1,9 @@
1#include <linux/linkage.h> 1#include <linux/linkage.h>
2#include <linux/init.h> 2#include <linux/init.h>
3 3
4#include <asm/cache.h>
5#include <asm/asm-offsets.h>
6#include <asm/hardware/cache-l2x0.h>
7
8#include "flowctrl.h"
9#include "iomap.h"
10#include "reset.h"
11#include "sleep.h" 4#include "sleep.h"
12 5
13#define APB_MISC_GP_HIDREV 0x804
14#define PMC_SCRATCH41 0x140
15
16#define RESET_DATA(x) ((TEGRA_RESET_##x)*4)
17
18 .section ".text.head", "ax" 6 .section ".text.head", "ax"
19 __CPUINIT
20 7
21/* 8/*
22 * Tegra specific entry point for secondary CPUs. 9 * Tegra specific entry point for secondary CPUs.
@@ -61,7 +48,6 @@ ENTRY(v7_invalidate_l1)
61 mov pc, lr 48 mov pc, lr
62ENDPROC(v7_invalidate_l1) 49ENDPROC(v7_invalidate_l1)
63 50
64
65ENTRY(tegra_secondary_startup) 51ENTRY(tegra_secondary_startup)
66 bl v7_invalidate_l1 52 bl v7_invalidate_l1
67 /* Enable coresight */ 53 /* Enable coresight */
@@ -69,210 +55,3 @@ ENTRY(tegra_secondary_startup)
69 mcr p14, 0, r0, c7, c12, 6 55 mcr p14, 0, r0, c7, c12, 6
70 b secondary_startup 56 b secondary_startup
71ENDPROC(tegra_secondary_startup) 57ENDPROC(tegra_secondary_startup)
72
73#ifdef CONFIG_PM_SLEEP
74/*
75 * tegra_resume
76 *
77 * CPU boot vector when restarting the a CPU following
78 * an LP2 transition. Also branched to by LP0 and LP1 resume after
79 * re-enabling sdram.
80 */
81ENTRY(tegra_resume)
82 bl v7_invalidate_l1
83 /* Enable coresight */
84 mov32 r0, 0xC5ACCE55
85 mcr p14, 0, r0, c7, c12, 6
86
87 cpu_id r0
88 cmp r0, #0 @ CPU0?
89 bne cpu_resume @ no
90
91#ifdef CONFIG_ARCH_TEGRA_3x_SOC
92 /* Are we on Tegra20? */
93 mov32 r6, TEGRA_APB_MISC_BASE
94 ldr r0, [r6, #APB_MISC_GP_HIDREV]
95 and r0, r0, #0xff00
96 cmp r0, #(0x20 << 8)
97 beq 1f @ Yes
98 /* Clear the flow controller flags for this CPU. */
99 mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR
100 ldr r1, [r2]
101 /* Clear event & intr flag */
102 orr r1, r1, \
103 #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
104 movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps
105 bic r1, r1, r0
106 str r1, [r2]
1071:
108#endif
109
110#ifdef CONFIG_HAVE_ARM_SCU
111 /* enable SCU */
112 mov32 r0, TEGRA_ARM_PERIF_BASE
113 ldr r1, [r0]
114 orr r1, r1, #1
115 str r1, [r0]
116#endif
117
118 /* L2 cache resume & re-enable */
119 l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
120
121 b cpu_resume
122ENDPROC(tegra_resume)
123#endif
124
125#ifdef CONFIG_CACHE_L2X0
126 .globl l2x0_saved_regs_addr
127l2x0_saved_regs_addr:
128 .long 0
129#endif
130
131 .align L1_CACHE_SHIFT
132ENTRY(__tegra_cpu_reset_handler_start)
133
134/*
135 * __tegra_cpu_reset_handler:
136 *
137 * Common handler for all CPU reset events.
138 *
139 * Register usage within the reset handler:
140 *
141 * R7 = CPU present (to the OS) mask
142 * R8 = CPU in LP1 state mask
143 * R9 = CPU in LP2 state mask
144 * R10 = CPU number
145 * R11 = CPU mask
146 * R12 = pointer to reset handler data
147 *
148 * NOTE: This code is copied to IRAM. All code and data accesses
149 * must be position-independent.
150 */
151
152 .align L1_CACHE_SHIFT
153ENTRY(__tegra_cpu_reset_handler)
154
155 cpsid aif, 0x13 @ SVC mode, interrupts disabled
156 mrc p15, 0, r10, c0, c0, 5 @ MPIDR
157 and r10, r10, #0x3 @ R10 = CPU number
158 mov r11, #1
159 mov r11, r11, lsl r10 @ R11 = CPU mask
160 adr r12, __tegra_cpu_reset_handler_data
161
162#ifdef CONFIG_SMP
163 /* Does the OS know about this CPU? */
164 ldr r7, [r12, #RESET_DATA(MASK_PRESENT)]
165 tst r7, r11 @ if !present
166 bleq __die @ CPU not present (to OS)
167#endif
168
169#ifdef CONFIG_ARCH_TEGRA_2x_SOC
170 /* Are we on Tegra20? */
171 mov32 r6, TEGRA_APB_MISC_BASE
172 ldr r0, [r6, #APB_MISC_GP_HIDREV]
173 and r0, r0, #0xff00
174 cmp r0, #(0x20 << 8)
175 bne 1f
176 /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
177 mov32 r6, TEGRA_PMC_BASE
178 mov r0, #0
179 cmp r10, #0
180 strne r0, [r6, #PMC_SCRATCH41]
1811:
182#endif
183
184 /* Waking up from LP2? */
185 ldr r9, [r12, #RESET_DATA(MASK_LP2)]
186 tst r9, r11 @ if in_lp2
187 beq __is_not_lp2
188 ldr lr, [r12, #RESET_DATA(STARTUP_LP2)]
189 cmp lr, #0
190 bleq __die @ no LP2 startup handler
191 bx lr
192
193__is_not_lp2:
194
195#ifdef CONFIG_SMP
196 /*
197 * Can only be secondary boot (initial or hotplug) but CPU 0
198 * cannot be here.
199 */
200 cmp r10, #0
201 bleq __die @ CPU0 cannot be here
202 ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
203 cmp lr, #0
204 bleq __die @ no secondary startup handler
205 bx lr
206#endif
207
208/*
209 * We don't know why the CPU reset. Just kill it.
210 * The LR register will contain the address we died at + 4.
211 */
212
213__die:
214 sub lr, lr, #4
215 mov32 r7, TEGRA_PMC_BASE
216 str lr, [r7, #PMC_SCRATCH41]
217
218 mov32 r7, TEGRA_CLK_RESET_BASE
219
220 /* Are we on Tegra20? */
221 mov32 r6, TEGRA_APB_MISC_BASE
222 ldr r0, [r6, #APB_MISC_GP_HIDREV]
223 and r0, r0, #0xff00
224 cmp r0, #(0x20 << 8)
225 bne 1f
226
227#ifdef CONFIG_ARCH_TEGRA_2x_SOC
228 mov32 r0, 0x1111
229 mov r1, r0, lsl r10
230 str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET
231#endif
2321:
233#ifdef CONFIG_ARCH_TEGRA_3x_SOC
234 mov32 r6, TEGRA_FLOW_CTRL_BASE
235
236 cmp r10, #0
237 moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS
238 moveq r2, #FLOW_CTRL_CPU0_CSR
239 movne r1, r10, lsl #3
240 addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
241 addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
242
243 /* Clear CPU "event" and "interrupt" flags and power gate
244 it when halting but not before it is in the "WFI" state. */
245 ldr r0, [r6, +r2]
246 orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
247 orr r0, r0, #FLOW_CTRL_CSR_ENABLE
248 str r0, [r6, +r2]
249
250 /* Unconditionally halt this CPU */
251 mov r0, #FLOW_CTRL_WAITEVENT
252 str r0, [r6, +r1]
253 ldr r0, [r6, +r1] @ memory barrier
254
255 dsb
256 isb
257 wfi @ CPU should be power gated here
258
259 /* If the CPU didn't power gate above just kill it's clock. */
260
261 mov r0, r11, lsl #8
262 str r0, [r7, #348] @ CLK_CPU_CMPLX_SET
263#endif
264
265 /* If the CPU still isn't dead, just spin here. */
266 b .
267ENDPROC(__tegra_cpu_reset_handler)
268
269 .align L1_CACHE_SHIFT
270 .type __tegra_cpu_reset_handler_data, %object
271 .globl __tegra_cpu_reset_handler_data
272__tegra_cpu_reset_handler_data:
273 .rept TEGRA_RESET_DATA_SIZE
274 .long 0
275 .endr
276 .align L1_CACHE_SHIFT
277
278ENTRY(__tegra_cpu_reset_handler_end)
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index dca5141a2c31..6a27de4001ee 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -19,6 +19,17 @@
19 19
20static void (*tegra_hotplug_shutdown)(void); 20static void (*tegra_hotplug_shutdown)(void);
21 21
22int tegra_cpu_kill(unsigned cpu)
23{
24 cpu = cpu_logical_map(cpu);
25
26 /* Clock gate the CPU */
27 tegra_wait_cpu_in_reset(cpu);
28 tegra_disable_cpu_clock(cpu);
29
30 return 1;
31}
32
22/* 33/*
23 * platform-specific code to shutdown a CPU 34 * platform-specific code to shutdown a CPU
24 * 35 *
@@ -26,18 +37,12 @@ static void (*tegra_hotplug_shutdown)(void);
26 */ 37 */
27void __ref tegra_cpu_die(unsigned int cpu) 38void __ref tegra_cpu_die(unsigned int cpu)
28{ 39{
29 cpu = cpu_logical_map(cpu); 40 /* Clean L1 data cache */
30 41 tegra_disable_clean_inv_dcache();
31 /* Flush the L1 data cache. */
32 flush_cache_all();
33 42
34 /* Shut down the current CPU. */ 43 /* Shut down the current CPU. */
35 tegra_hotplug_shutdown(); 44 tegra_hotplug_shutdown();
36 45
37 /* Clock gate the CPU */
38 tegra_wait_cpu_in_reset(cpu);
39 tegra_disable_cpu_clock(cpu);
40
41 /* Should never return here. */ 46 /* Should never return here. */
42 BUG(); 47 BUG();
43} 48}
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 18d7290cf93b..3c4a43c892a5 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -23,6 +23,7 @@
23#include <asm/cacheflush.h> 23#include <asm/cacheflush.h>
24#include <asm/mach-types.h> 24#include <asm/mach-types.h>
25#include <asm/smp_scu.h> 25#include <asm/smp_scu.h>
26#include <asm/smp_plat.h>
26 27
27#include <mach/powergate.h> 28#include <mach/powergate.h>
28 29
@@ -36,6 +37,7 @@
36 37
37extern void tegra_secondary_startup(void); 38extern void tegra_secondary_startup(void);
38 39
40static cpumask_t tegra_cpu_init_mask;
39static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); 41static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
40 42
41#define EVP_CPU_RESET_VECTOR \ 43#define EVP_CPU_RESET_VECTOR \
@@ -50,6 +52,7 @@ static void __cpuinit tegra_secondary_init(unsigned int cpu)
50 */ 52 */
51 gic_secondary_init(0); 53 gic_secondary_init(0);
52 54
55 cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
53} 56}
54 57
55static int tegra20_power_up_cpu(unsigned int cpu) 58static int tegra20_power_up_cpu(unsigned int cpu)
@@ -72,14 +75,42 @@ static int tegra30_power_up_cpu(unsigned int cpu)
72 if (pwrgateid < 0) 75 if (pwrgateid < 0)
73 return pwrgateid; 76 return pwrgateid;
74 77
75 /* If this is the first boot, toggle powergates directly. */ 78 /*
79 * The power up sequence of cold boot CPU and warm boot CPU
80 * was different.
81 *
82 * For warm boot CPU that was resumed from CPU hotplug, the
83 * power will be resumed automatically after un-halting the
84 * flow controller of the warm boot CPU. We need to wait for
85 * the confirmaiton that the CPU is powered then removing
86 * the IO clamps.
87 * For cold boot CPU, do not wait. After the cold boot CPU be
88 * booted, it will run to tegra_secondary_init() and set
89 * tegra_cpu_init_mask which influences what tegra30_power_up_cpu()
90 * next time around.
91 */
92 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
93 timeout = jiffies + msecs_to_jiffies(50);
94 do {
95 if (!tegra_powergate_is_powered(pwrgateid))
96 goto remove_clamps;
97 udelay(10);
98 } while (time_before(jiffies, timeout));
99 }
100
101 /*
102 * The power status of the cold boot CPU is power gated as
103 * default. To power up the cold boot CPU, the power should
104 * be un-gated by un-toggling the power gate register
105 * manually.
106 */
76 if (!tegra_powergate_is_powered(pwrgateid)) { 107 if (!tegra_powergate_is_powered(pwrgateid)) {
77 ret = tegra_powergate_power_on(pwrgateid); 108 ret = tegra_powergate_power_on(pwrgateid);
78 if (ret) 109 if (ret)
79 return ret; 110 return ret;
80 111
81 /* Wait for the power to come up. */ 112 /* Wait for the power to come up. */
82 timeout = jiffies + 10*HZ; 113 timeout = jiffies + msecs_to_jiffies(100);
83 while (tegra_powergate_is_powered(pwrgateid)) { 114 while (tegra_powergate_is_powered(pwrgateid)) {
84 if (time_after(jiffies, timeout)) 115 if (time_after(jiffies, timeout))
85 return -ETIMEDOUT; 116 return -ETIMEDOUT;
@@ -87,6 +118,7 @@ static int tegra30_power_up_cpu(unsigned int cpu)
87 } 118 }
88 } 119 }
89 120
121remove_clamps:
90 /* CPU partition is powered. Enable the CPU clock. */ 122 /* CPU partition is powered. Enable the CPU clock. */
91 tegra_enable_cpu_clock(cpu); 123 tegra_enable_cpu_clock(cpu);
92 udelay(10); 124 udelay(10);
@@ -105,6 +137,8 @@ static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *
105{ 137{
106 int status; 138 int status;
107 139
140 cpu = cpu_logical_map(cpu);
141
108 /* 142 /*
109 * Force the CPU into reset. The CPU must remain in reset when the 143 * Force the CPU into reset. The CPU must remain in reset when the
110 * flow controller state is cleared (which will cause the flow 144 * flow controller state is cleared (which will cause the flow
@@ -163,7 +197,9 @@ static void __init tegra_smp_init_cpus(void)
163 197
164static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) 198static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
165{ 199{
166 tegra_cpu_reset_handler_init(); 200 /* Always mark the boot CPU (CPU0) as initialized. */
201 cpumask_set_cpu(0, &tegra_cpu_init_mask);
202
167 scu_enable(scu_base); 203 scu_enable(scu_base);
168} 204}
169 205
@@ -173,6 +209,7 @@ struct smp_operations tegra_smp_ops __initdata = {
173 .smp_secondary_init = tegra_secondary_init, 209 .smp_secondary_init = tegra_secondary_init,
174 .smp_boot_secondary = tegra_boot_secondary, 210 .smp_boot_secondary = tegra_boot_secondary,
175#ifdef CONFIG_HOTPLUG_CPU 211#ifdef CONFIG_HOTPLUG_CPU
212 .cpu_kill = tegra_cpu_kill,
176 .cpu_die = tegra_cpu_die, 213 .cpu_die = tegra_cpu_die,
177 .cpu_disable = tegra_cpu_disable, 214 .cpu_disable = tegra_cpu_disable,
178#endif 215#endif
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1b11707eaca0..498d70b33775 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -148,7 +148,7 @@ static void suspend_cpu_complex(void)
148 save_cpu_arch_register(); 148 save_cpu_arch_register();
149} 149}
150 150
151void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id) 151void tegra_clear_cpu_in_lp2(int phy_cpu_id)
152{ 152{
153 u32 *cpu_in_lp2 = tegra_cpu_lp2_mask; 153 u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
154 154
@@ -160,7 +160,7 @@ void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id)
160 spin_unlock(&tegra_lp2_lock); 160 spin_unlock(&tegra_lp2_lock);
161} 161}
162 162
163bool __cpuinit tegra_set_cpu_in_lp2(int phy_cpu_id) 163bool tegra_set_cpu_in_lp2(int phy_cpu_id)
164{ 164{
165 bool last_cpu = false; 165 bool last_cpu = false;
166 cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask; 166 cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask;
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
new file mode 100644
index 000000000000..54382ceade4a
--- /dev/null
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -0,0 +1,239 @@
1/*
2 * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/linkage.h>
18#include <linux/init.h>
19
20#include <asm/cache.h>
21#include <asm/asm-offsets.h>
22#include <asm/hardware/cache-l2x0.h>
23
24#include "flowctrl.h"
25#include "iomap.h"
26#include "reset.h"
27#include "sleep.h"
28
29#define APB_MISC_GP_HIDREV 0x804
30#define PMC_SCRATCH41 0x140
31
32#define RESET_DATA(x) ((TEGRA_RESET_##x)*4)
33
34#ifdef CONFIG_PM_SLEEP
35/*
36 * tegra_resume
37 *
38 * CPU boot vector when restarting the a CPU following
39 * an LP2 transition. Also branched to by LP0 and LP1 resume after
40 * re-enabling sdram.
41 */
42ENTRY(tegra_resume)
43 bl v7_invalidate_l1
44 /* Enable coresight */
45 mov32 r0, 0xC5ACCE55
46 mcr p14, 0, r0, c7, c12, 6
47
48 cpu_id r0
49 cmp r0, #0 @ CPU0?
50 bne cpu_resume @ no
51
52#ifdef CONFIG_ARCH_TEGRA_3x_SOC
53 /* Are we on Tegra20? */
54 mov32 r6, TEGRA_APB_MISC_BASE
55 ldr r0, [r6, #APB_MISC_GP_HIDREV]
56 and r0, r0, #0xff00
57 cmp r0, #(0x20 << 8)
58 beq 1f @ Yes
59 /* Clear the flow controller flags for this CPU. */
60 mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR
61 ldr r1, [r2]
62 /* Clear event & intr flag */
63 orr r1, r1, \
64 #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
65 movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps
66 bic r1, r1, r0
67 str r1, [r2]
681:
69#endif
70
71#ifdef CONFIG_HAVE_ARM_SCU
72 /* enable SCU */
73 mov32 r0, TEGRA_ARM_PERIF_BASE
74 ldr r1, [r0]
75 orr r1, r1, #1
76 str r1, [r0]
77#endif
78
79 /* L2 cache resume & re-enable */
80 l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
81
82 b cpu_resume
83ENDPROC(tegra_resume)
84#endif
85
86#ifdef CONFIG_CACHE_L2X0
87 .globl l2x0_saved_regs_addr
88l2x0_saved_regs_addr:
89 .long 0
90#endif
91
92 .align L1_CACHE_SHIFT
93ENTRY(__tegra_cpu_reset_handler_start)
94
95/*
96 * __tegra_cpu_reset_handler:
97 *
98 * Common handler for all CPU reset events.
99 *
100 * Register usage within the reset handler:
101 *
102 * R7 = CPU present (to the OS) mask
103 * R8 = CPU in LP1 state mask
104 * R9 = CPU in LP2 state mask
105 * R10 = CPU number
106 * R11 = CPU mask
107 * R12 = pointer to reset handler data
108 *
109 * NOTE: This code is copied to IRAM. All code and data accesses
110 * must be position-independent.
111 */
112
113 .align L1_CACHE_SHIFT
114ENTRY(__tegra_cpu_reset_handler)
115
116 cpsid aif, 0x13 @ SVC mode, interrupts disabled
117 mrc p15, 0, r10, c0, c0, 5 @ MPIDR
118 and r10, r10, #0x3 @ R10 = CPU number
119 mov r11, #1
120 mov r11, r11, lsl r10 @ R11 = CPU mask
121 adr r12, __tegra_cpu_reset_handler_data
122
123#ifdef CONFIG_SMP
124 /* Does the OS know about this CPU? */
125 ldr r7, [r12, #RESET_DATA(MASK_PRESENT)]
126 tst r7, r11 @ if !present
127 bleq __die @ CPU not present (to OS)
128#endif
129
130#ifdef CONFIG_ARCH_TEGRA_2x_SOC
131 /* Are we on Tegra20? */
132 mov32 r6, TEGRA_APB_MISC_BASE
133 ldr r0, [r6, #APB_MISC_GP_HIDREV]
134 and r0, r0, #0xff00
135 cmp r0, #(0x20 << 8)
136 bne 1f
137 /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
138 mov32 r6, TEGRA_PMC_BASE
139 mov r0, #0
140 cmp r10, #0
141 strne r0, [r6, #PMC_SCRATCH41]
1421:
143#endif
144
145 /* Waking up from LP2? */
146 ldr r9, [r12, #RESET_DATA(MASK_LP2)]
147 tst r9, r11 @ if in_lp2
148 beq __is_not_lp2
149 ldr lr, [r12, #RESET_DATA(STARTUP_LP2)]
150 cmp lr, #0
151 bleq __die @ no LP2 startup handler
152 bx lr
153
154__is_not_lp2:
155
156#ifdef CONFIG_SMP
157 /*
158 * Can only be secondary boot (initial or hotplug) but CPU 0
159 * cannot be here.
160 */
161 cmp r10, #0
162 bleq __die @ CPU0 cannot be here
163 ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
164 cmp lr, #0
165 bleq __die @ no secondary startup handler
166 bx lr
167#endif
168
169/*
170 * We don't know why the CPU reset. Just kill it.
171 * The LR register will contain the address we died at + 4.
172 */
173
174__die:
175 sub lr, lr, #4
176 mov32 r7, TEGRA_PMC_BASE
177 str lr, [r7, #PMC_SCRATCH41]
178
179 mov32 r7, TEGRA_CLK_RESET_BASE
180
181 /* Are we on Tegra20? */
182 mov32 r6, TEGRA_APB_MISC_BASE
183 ldr r0, [r6, #APB_MISC_GP_HIDREV]
184 and r0, r0, #0xff00
185 cmp r0, #(0x20 << 8)
186 bne 1f
187
188#ifdef CONFIG_ARCH_TEGRA_2x_SOC
189 mov32 r0, 0x1111
190 mov r1, r0, lsl r10
191 str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET
192#endif
1931:
194#ifdef CONFIG_ARCH_TEGRA_3x_SOC
195 mov32 r6, TEGRA_FLOW_CTRL_BASE
196
197 cmp r10, #0
198 moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS
199 moveq r2, #FLOW_CTRL_CPU0_CSR
200 movne r1, r10, lsl #3
201 addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
202 addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
203
204 /* Clear CPU "event" and "interrupt" flags and power gate
205 it when halting but not before it is in the "WFI" state. */
206 ldr r0, [r6, +r2]
207 orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
208 orr r0, r0, #FLOW_CTRL_CSR_ENABLE
209 str r0, [r6, +r2]
210
211 /* Unconditionally halt this CPU */
212 mov r0, #FLOW_CTRL_WAITEVENT
213 str r0, [r6, +r1]
214 ldr r0, [r6, +r1] @ memory barrier
215
216 dsb
217 isb
218 wfi @ CPU should be power gated here
219
220 /* If the CPU didn't power gate above just kill it's clock. */
221
222 mov r0, r11, lsl #8
223 str r0, [r7, #348] @ CLK_CPU_CMPLX_SET
224#endif
225
226 /* If the CPU still isn't dead, just spin here. */
227 b .
228ENDPROC(__tegra_cpu_reset_handler)
229
230 .align L1_CACHE_SHIFT
231 .type __tegra_cpu_reset_handler_data, %object
232 .globl __tegra_cpu_reset_handler_data
233__tegra_cpu_reset_handler_data:
234 .rept TEGRA_RESET_DATA_SIZE
235 .long 0
236 .endr
237 .align L1_CACHE_SHIFT
238
239ENTRY(__tegra_cpu_reset_handler_end)
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index 3fd89ecd158e..1ac434e0068f 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -75,7 +75,7 @@ void __init tegra_cpu_reset_handler_init(void)
75 75
76#ifdef CONFIG_SMP 76#ifdef CONFIG_SMP
77 __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] = 77 __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
78 *((u32 *)cpu_present_mask); 78 *((u32 *)cpu_possible_mask);
79 __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] = 79 __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] =
80 virt_to_phys((void *)tegra_secondary_startup); 80 virt_to_phys((void *)tegra_secondary_startup);
81#endif 81#endif
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index 72ce709799da..ad2ca07d0578 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -33,9 +33,6 @@
33 * should never return 33 * should never return
34 */ 34 */
35ENTRY(tegra20_hotplug_shutdown) 35ENTRY(tegra20_hotplug_shutdown)
36 /* Turn off SMP coherency */
37 exit_smp r4, r5
38
39 /* Put this CPU down */ 36 /* Put this CPU down */
40 cpu_id r0 37 cpu_id r0
41 bl tegra20_cpu_shutdown 38 bl tegra20_cpu_shutdown
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index 562a8e7e413d..63a15bd9b653 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -32,9 +32,6 @@
32 * Should never return. 32 * Should never return.
33 */ 33 */
34ENTRY(tegra30_hotplug_shutdown) 34ENTRY(tegra30_hotplug_shutdown)
35 /* Turn off SMP coherency */
36 exit_smp r4, r5
37
38 /* Powergate this CPU */ 35 /* Powergate this CPU */
39 mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN 36 mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
40 bl tegra30_cpu_shutdown 37 bl tegra30_cpu_shutdown
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 26afa7cbed11..addae357da3f 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -34,7 +34,7 @@
34#include "flowctrl.h" 34#include "flowctrl.h"
35#include "sleep.h" 35#include "sleep.h"
36 36
37#ifdef CONFIG_PM_SLEEP 37#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
38/* 38/*
39 * tegra_disable_clean_inv_dcache 39 * tegra_disable_clean_inv_dcache
40 * 40 *
@@ -60,7 +60,9 @@ ENTRY(tegra_disable_clean_inv_dcache)
60 60
61 ldmfd sp!, {r0, r4-r5, r7, r9-r11, pc} 61 ldmfd sp!, {r0, r4-r5, r7, r9-r11, pc}
62ENDPROC(tegra_disable_clean_inv_dcache) 62ENDPROC(tegra_disable_clean_inv_dcache)
63#endif
63 64
65#ifdef CONFIG_PM_SLEEP
64/* 66/*
65 * tegra_sleep_cpu_finish(unsigned long v2p) 67 * tegra_sleep_cpu_finish(unsigned long v2p)
66 * 68 *
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 9821ee725420..56505c381ea8 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -106,6 +106,7 @@ exit_l2_resume:
106#else 106#else
107void tegra_resume(void); 107void tegra_resume(void);
108int tegra_sleep_cpu_finish(unsigned long); 108int tegra_sleep_cpu_finish(unsigned long);
109void tegra_disable_clean_inv_dcache(void);
109 110
110#ifdef CONFIG_HOTPLUG_CPU 111#ifdef CONFIG_HOTPLUG_CPU
111void tegra20_hotplug_init(void); 112void tegra20_hotplug_init(void);
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
index 6942c7add3bb..741d264d5ecb 100644
--- a/arch/arm/mach-tegra/tegra30_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra30_clocks_data.c
@@ -1183,7 +1183,7 @@ static struct clk tegra_dsib = {
1183 .num_parents = ARRAY_SIZE(mux_plld_out0_plld2_out0), 1183 .num_parents = ARRAY_SIZE(mux_plld_out0_plld2_out0),
1184}; 1184};
1185 1185
1186struct clk *tegra_list_clks[] = { 1186static struct clk *tegra_list_clks[] = {
1187 &tegra_apbdma, 1187 &tegra_apbdma,
1188 &tegra_rtc, 1188 &tegra_rtc,
1189 &tegra_kbc, 1189 &tegra_kbc,
@@ -1289,7 +1289,7 @@ struct clk *tegra_list_clks[] = {
1289 * configuration. List those here to register them twice in the clock lookup 1289 * configuration. List those here to register them twice in the clock lookup
1290 * table under two names. 1290 * table under two names.
1291 */ 1291 */
1292struct clk_duplicate tegra_clk_duplicates[] = { 1292static struct clk_duplicate tegra_clk_duplicates[] = {
1293 CLK_DUPLICATE("uarta", "serial8250.0", NULL), 1293 CLK_DUPLICATE("uarta", "serial8250.0", NULL),
1294 CLK_DUPLICATE("uartb", "serial8250.1", NULL), 1294 CLK_DUPLICATE("uartb", "serial8250.1", NULL),
1295 CLK_DUPLICATE("uartc", "serial8250.2", NULL), 1295 CLK_DUPLICATE("uartc", "serial8250.2", NULL),
@@ -1340,7 +1340,7 @@ struct clk_duplicate tegra_clk_duplicates[] = {
1340 CLK_DUPLICATE("pll_d2_out0", "hdmi", "parent"), 1340 CLK_DUPLICATE("pll_d2_out0", "hdmi", "parent"),
1341}; 1341};
1342 1342
1343struct clk *tegra_ptr_clks[] = { 1343static struct clk *tegra_ptr_clks[] = {
1344 &tegra_clk_32k, 1344 &tegra_clk_32k,
1345 &tegra_clk_m, 1345 &tegra_clk_m,
1346 &tegra_clk_m_div2, 1346 &tegra_clk_m_div2,
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
deleted file mode 100644
index eba0969ded19..000000000000
--- a/arch/arm/mach-tegra/timer.c
+++ /dev/null
@@ -1,284 +0,0 @@
1/*
2 * arch/arch/mach-tegra/timer.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 *
6 * Author:
7 * Colin Cross <ccross@google.com>
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/init.h>
21#include <linux/err.h>
22#include <linux/time.h>
23#include <linux/interrupt.h>
24#include <linux/irq.h>
25#include <linux/clockchips.h>
26#include <linux/clocksource.h>
27#include <linux/clk.h>
28#include <linux/io.h>
29#include <linux/of_address.h>
30#include <linux/of_irq.h>
31
32#include <asm/mach/time.h>
33#include <asm/smp_twd.h>
34#include <asm/sched_clock.h>
35
36#include "board.h"
37
38#define RTC_SECONDS 0x08
39#define RTC_SHADOW_SECONDS 0x0c
40#define RTC_MILLISECONDS 0x10
41
42#define TIMERUS_CNTR_1US 0x10
43#define TIMERUS_USEC_CFG 0x14
44#define TIMERUS_CNTR_FREEZE 0x4c
45
46#define TIMER1_BASE 0x0
47#define TIMER2_BASE 0x8
48#define TIMER3_BASE 0x50
49#define TIMER4_BASE 0x58
50
51#define TIMER_PTV 0x0
52#define TIMER_PCR 0x4
53
54static void __iomem *timer_reg_base;
55static void __iomem *rtc_base;
56
57static struct timespec persistent_ts;
58static u64 persistent_ms, last_persistent_ms;
59
60#define timer_writel(value, reg) \
61 __raw_writel(value, timer_reg_base + (reg))
62#define timer_readl(reg) \
63 __raw_readl(timer_reg_base + (reg))
64
65static int tegra_timer_set_next_event(unsigned long cycles,
66 struct clock_event_device *evt)
67{
68 u32 reg;
69
70 reg = 0x80000000 | ((cycles > 1) ? (cycles-1) : 0);
71 timer_writel(reg, TIMER3_BASE + TIMER_PTV);
72
73 return 0;
74}
75
76static void tegra_timer_set_mode(enum clock_event_mode mode,
77 struct clock_event_device *evt)
78{
79 u32 reg;
80
81 timer_writel(0, TIMER3_BASE + TIMER_PTV);
82
83 switch (mode) {
84 case CLOCK_EVT_MODE_PERIODIC:
85 reg = 0xC0000000 | ((1000000/HZ)-1);
86 timer_writel(reg, TIMER3_BASE + TIMER_PTV);
87 break;
88 case CLOCK_EVT_MODE_ONESHOT:
89 break;
90 case CLOCK_EVT_MODE_UNUSED:
91 case CLOCK_EVT_MODE_SHUTDOWN:
92 case CLOCK_EVT_MODE_RESUME:
93 break;
94 }
95}
96
97static struct clock_event_device tegra_clockevent = {
98 .name = "timer0",
99 .rating = 300,
100 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
101 .set_next_event = tegra_timer_set_next_event,
102 .set_mode = tegra_timer_set_mode,
103};
104
105static u32 notrace tegra_read_sched_clock(void)
106{
107 return timer_readl(TIMERUS_CNTR_1US);
108}
109
110/*
111 * tegra_rtc_read - Reads the Tegra RTC registers
112 * Care must be taken that this funciton is not called while the
113 * tegra_rtc driver could be executing to avoid race conditions
114 * on the RTC shadow register
115 */
116static u64 tegra_rtc_read_ms(void)
117{
118 u32 ms = readl(rtc_base + RTC_MILLISECONDS);
119 u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
120 return (u64)s * MSEC_PER_SEC + ms;
121}
122
123/*
124 * tegra_read_persistent_clock - Return time from a persistent clock.
125 *
126 * Reads the time from a source which isn't disabled during PM, the
127 * 32k sync timer. Convert the cycles elapsed since last read into
128 * nsecs and adds to a monotonically increasing timespec.
129 * Care must be taken that this funciton is not called while the
130 * tegra_rtc driver could be executing to avoid race conditions
131 * on the RTC shadow register
132 */
133static void tegra_read_persistent_clock(struct timespec *ts)
134{
135 u64 delta;
136 struct timespec *tsp = &persistent_ts;
137
138 last_persistent_ms = persistent_ms;
139 persistent_ms = tegra_rtc_read_ms();
140 delta = persistent_ms - last_persistent_ms;
141
142 timespec_add_ns(tsp, delta * NSEC_PER_MSEC);
143 *ts = *tsp;
144}
145
146static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
147{
148 struct clock_event_device *evt = (struct clock_event_device *)dev_id;
149 timer_writel(1<<30, TIMER3_BASE + TIMER_PCR);
150 evt->event_handler(evt);
151 return IRQ_HANDLED;
152}
153
154static struct irqaction tegra_timer_irq = {
155 .name = "timer0",
156 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH,
157 .handler = tegra_timer_interrupt,
158 .dev_id = &tegra_clockevent,
159};
160
161static const struct of_device_id timer_match[] __initconst = {
162 { .compatible = "nvidia,tegra20-timer" },
163 {}
164};
165
166static const struct of_device_id rtc_match[] __initconst = {
167 { .compatible = "nvidia,tegra20-rtc" },
168 {}
169};
170
171void __init tegra_init_timer(void)
172{
173 struct device_node *np;
174 struct clk *clk;
175 unsigned long rate;
176 int ret;
177
178 np = of_find_matching_node(NULL, timer_match);
179 if (!np) {
180 pr_err("Failed to find timer DT node\n");
181 BUG();
182 }
183
184 timer_reg_base = of_iomap(np, 0);
185 if (!timer_reg_base) {
186 pr_err("Can't map timer registers");
187 BUG();
188 }
189
190 tegra_timer_irq.irq = irq_of_parse_and_map(np, 2);
191 if (tegra_timer_irq.irq <= 0) {
192 pr_err("Failed to map timer IRQ\n");
193 BUG();
194 }
195
196 clk = clk_get_sys("timer", NULL);
197 if (IS_ERR(clk)) {
198 pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
199 rate = 12000000;
200 } else {
201 clk_prepare_enable(clk);
202 rate = clk_get_rate(clk);
203 }
204
205 of_node_put(np);
206
207 np = of_find_matching_node(NULL, rtc_match);
208 if (!np) {
209 pr_err("Failed to find RTC DT node\n");
210 BUG();
211 }
212
213 rtc_base = of_iomap(np, 0);
214 if (!rtc_base) {
215 pr_err("Can't map RTC registers");
216 BUG();
217 }
218
219 /*
220 * rtc registers are used by read_persistent_clock, keep the rtc clock
221 * enabled
222 */
223 clk = clk_get_sys("rtc-tegra", NULL);
224 if (IS_ERR(clk))
225 pr_warn("Unable to get rtc-tegra clock\n");
226 else
227 clk_prepare_enable(clk);
228
229 of_node_put(np);
230
231 switch (rate) {
232 case 12000000:
233 timer_writel(0x000b, TIMERUS_USEC_CFG);
234 break;
235 case 13000000:
236 timer_writel(0x000c, TIMERUS_USEC_CFG);
237 break;
238 case 19200000:
239 timer_writel(0x045f, TIMERUS_USEC_CFG);
240 break;
241 case 26000000:
242 timer_writel(0x0019, TIMERUS_USEC_CFG);
243 break;
244 default:
245 WARN(1, "Unknown clock rate");
246 }
247
248 setup_sched_clock(tegra_read_sched_clock, 32, 1000000);
249
250 if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
251 "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) {
252 pr_err("Failed to register clocksource\n");
253 BUG();
254 }
255
256 ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
257 if (ret) {
258 pr_err("Failed to register timer IRQ: %d\n", ret);
259 BUG();
260 }
261
262 tegra_clockevent.cpumask = cpu_all_mask;
263 tegra_clockevent.irq = tegra_timer_irq.irq;
264 clockevents_config_and_register(&tegra_clockevent, 1000000,
265 0x1, 0x1fffffff);
266#ifdef CONFIG_HAVE_ARM_TWD
267 twd_local_timer_of_register();
268#endif
269 register_persistent_clock(NULL, tegra_read_persistent_clock);
270}
271
272#ifdef CONFIG_PM
273static u32 usec_config;
274
275void tegra_timer_suspend(void)
276{
277 usec_config = timer_readl(TIMERUS_USEC_CFG);
278}
279
280void tegra_timer_resume(void)
281{
282 timer_writel(usec_config, TIMERUS_USEC_CFG);
283}
284#endif