aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-04-09 09:27:52 -0400
committerArnd Bergmann <arnd@arndb.de>2013-04-09 09:27:52 -0400
commit8024206dbf4e0701f0cdf259a122ea23db3a7a16 (patch)
tree11d2f30d0c9209036613ec8f78d682ae31c89315 /arch/arm
parent5be8f6368800d9e3e570373d2aaff8a48be36574 (diff)
parent6affb4826405dc1f53bae0e5c302a18f734a44ca (diff)
Merge tag 'tegra-for-3.10-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra into next/cleanup
From Stephen Warren <swarren@wwwdotorg.org>: ARM: tegra: cleanup This branch includes various cleanup of the core Tegra support. * Unification of the separate board-dt-tegra*.c files into a single tegra.c, now that everything is DT-driven and basically identical. * Use of_clk_get() in the Tegra clocksource driver so that clocks are described in DT rather than hard-coding clock names. * Some cleanup of the PMC-related code, with the aim that the PMC "driver" contains more of the code that touches PMC registers, rather than spreading PMC register accesses through other files. * Conversion of the "PMC" driver to acquire resources describe in device tree rather than hard-coding them. * Use of common code for the CPU sleep TLB invalidation. This branch is based on the previous fixes pull request. * tag 'tegra-for-3.10-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra: ARM: tegra: use setup_mm_for_reboot rather than explicit pgd switch ARM: tegra: replace the CPU power on function with PMC call ARM: tegra: pmc: add power on function for secondary CPUs ARM: tegra: pmc: convert PMC driver to support DT only ARM: tegra: fix the PMC compatible string in DT ARM: tegra: pmc: add specific compatible DT string for Tegra30 and Tegra114 ARM: tegra: refactor tegra{20,30}_boot_secondary clocksource: tegra: move to of_clk_get ARM: tegra: Unify Device tree board files ARM: tegra: Rename board-dt-tegra20.c to tegra.c ARM: tegra: Unify tegra{20,30,114}_init_early() Conflicts: drivers/clocksource/tegra20_timer.c Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/boot/dts/tegra114.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra30.dtsi4
-rw-r--r--arch/arm/mach-tegra/Makefile4
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra114.c46
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra30.c60
-rw-r--r--arch/arm/mach-tegra/board.h4
-rw-r--r--arch/arm/mach-tegra/common.c26
-rw-r--r--arch/arm/mach-tegra/hotplug.c23
-rw-r--r--arch/arm/mach-tegra/platsmp.c110
-rw-r--r--arch/arm/mach-tegra/pm.c7
-rw-r--r--arch/arm/mach-tegra/pmc.c152
-rw-r--r--arch/arm/mach-tegra/pmc.h4
-rw-r--r--arch/arm/mach-tegra/sleep.h10
-rw-r--r--arch/arm/mach-tegra/tegra.c (renamed from arch/arm/mach-tegra/board-dt-tegra20.c)16
15 files changed, 205 insertions, 265 deletions
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 1dfaf2874c57..e4ddeddcd437 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -99,7 +99,7 @@
99 }; 99 };
100 100
101 pmc { 101 pmc {
102 compatible = "nvidia,tegra114-pmc", "nvidia,tegra30-pmc"; 102 compatible = "nvidia,tegra114-pmc";
103 reg = <0x7000e400 0x400>; 103 reg = <0x7000e400 0x400>;
104 }; 104 };
105 105
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 48d00a099ce3..de3f5d7530bc 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -145,6 +145,7 @@
145 0 1 0x04 145 0 1 0x04
146 0 41 0x04 146 0 41 0x04
147 0 42 0x04>; 147 0 42 0x04>;
148 clocks = <&tegra_car 5>;
148 }; 149 };
149 150
150 tegra_car: clock { 151 tegra_car: clock {
@@ -304,6 +305,7 @@
304 compatible = "nvidia,tegra20-rtc"; 305 compatible = "nvidia,tegra20-rtc";
305 reg = <0x7000e000 0x100>; 306 reg = <0x7000e000 0x100>;
306 interrupts = <0 2 0x04>; 307 interrupts = <0 2 0x04>;
308 clocks = <&tegra_car 4>;
307 }; 309 };
308 310
309 i2c@7000c000 { 311 i2c@7000c000 {
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 9d87a3ffe998..eddd0f9f7b5e 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -148,6 +148,7 @@
148 0 42 0x04 148 0 42 0x04
149 0 121 0x04 149 0 121 0x04
150 0 122 0x04>; 150 0 122 0x04>;
151 clocks = <&tegra_car 5>;
151 }; 152 };
152 153
153 tegra_car: clock { 154 tegra_car: clock {
@@ -291,6 +292,7 @@
291 compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc"; 292 compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
292 reg = <0x7000e000 0x100>; 293 reg = <0x7000e000 0x100>;
293 interrupts = <0 2 0x04>; 294 interrupts = <0 2 0x04>;
295 clocks = <&tegra_car 4>;
294 }; 296 };
295 297
296 i2c@7000c000 { 298 i2c@7000c000 {
@@ -423,7 +425,7 @@
423 }; 425 };
424 426
425 pmc { 427 pmc {
426 compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc"; 428 compatible = "nvidia,tegra30-pmc";
427 reg = <0x7000e400 0x400>; 429 reg = <0x7000e400 0x400>;
428 }; 430 };
429 431
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index f6b46ae2b7f8..92703f955a37 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -10,6 +10,7 @@ obj-y += pm.o
10obj-y += reset.o 10obj-y += reset.o
11obj-y += reset-handler.o 11obj-y += reset-handler.o
12obj-y += sleep.o 12obj-y += sleep.o
13obj-y += tegra.o
13obj-$(CONFIG_CPU_IDLE) += cpuidle.o 14obj-$(CONFIG_CPU_IDLE) += cpuidle.o
14obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o 15obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
15obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o 16obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
@@ -27,9 +28,6 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
27obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o 28obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
28obj-$(CONFIG_TEGRA_PCI) += pcie.o 29obj-$(CONFIG_TEGRA_PCI) += pcie.o
29 30
30obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o
31obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o
32obj-$(CONFIG_ARCH_TEGRA_114_SOC) += board-dt-tegra114.o
33ifeq ($(CONFIG_CPU_IDLE),y) 31ifeq ($(CONFIG_CPU_IDLE),y)
34obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o 32obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o
35endif 33endif
diff --git a/arch/arm/mach-tegra/board-dt-tegra114.c b/arch/arm/mach-tegra/board-dt-tegra114.c
deleted file mode 100644
index 085d63637b62..000000000000
--- a/arch/arm/mach-tegra/board-dt-tegra114.c
+++ /dev/null
@@ -1,46 +0,0 @@
1/*
2 * NVIDIA Tegra114 device tree board support
3 *
4 * Copyright (C) 2013 NVIDIA Corporation
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/of.h>
18#include <linux/of_platform.h>
19#include <linux/clocksource.h>
20
21#include <asm/mach/arch.h>
22
23#include "board.h"
24#include "common.h"
25
26static void __init tegra114_dt_init(void)
27{
28 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
29}
30
31static const char * const tegra114_dt_board_compat[] = {
32 "nvidia,tegra114",
33 NULL,
34};
35
36DT_MACHINE_START(TEGRA114_DT, "NVIDIA Tegra114 (Flattened Device Tree)")
37 .smp = smp_ops(tegra_smp_ops),
38 .map_io = tegra_map_common_io,
39 .init_early = tegra114_init_early,
40 .init_irq = tegra_dt_init_irq,
41 .init_time = clocksource_of_init,
42 .init_machine = tegra114_dt_init,
43 .init_late = tegra_init_late,
44 .restart = tegra_assert_system_reset,
45 .dt_compat = tegra114_dt_board_compat,
46MACHINE_END
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
deleted file mode 100644
index bf68567e549d..000000000000
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ /dev/null
@@ -1,60 +0,0 @@
1/*
2 * arch/arm/mach-tegra/board-dt-tegra30.c
3 *
4 * NVIDIA Tegra30 device tree board support
5 *
6 * Copyright (C) 2011 NVIDIA Corporation
7 *
8 * Derived from:
9 *
10 * arch/arm/mach-tegra/board-dt-tegra20.c
11 *
12 * Copyright (C) 2010 Secret Lab Technologies, Ltd.
13 * Copyright (C) 2010 Google, Inc.
14 *
15 * This software is licensed under the terms of the GNU General Public
16 * License version 2, as published by the Free Software Foundation, and
17 * may be copied, distributed, and modified under those terms.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 */
25
26#include <linux/clocksource.h>
27#include <linux/kernel.h>
28#include <linux/of.h>
29#include <linux/of_address.h>
30#include <linux/of_fdt.h>
31#include <linux/of_irq.h>
32#include <linux/of_platform.h>
33
34#include <asm/mach/arch.h>
35
36#include "board.h"
37#include "common.h"
38#include "iomap.h"
39
40static void __init tegra30_dt_init(void)
41{
42 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
43}
44
45static const char *tegra30_dt_board_compat[] = {
46 "nvidia,tegra30",
47 NULL
48};
49
50DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
51 .smp = smp_ops(tegra_smp_ops),
52 .map_io = tegra_map_common_io,
53 .init_early = tegra30_init_early,
54 .init_irq = tegra_dt_init_irq,
55 .init_time = clocksource_of_init,
56 .init_machine = tegra30_dt_init,
57 .init_late = tegra_init_late,
58 .restart = tegra_assert_system_reset,
59 .dt_compat = tegra30_dt_board_compat,
60MACHINE_END
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 86851c81a350..60431de585ca 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -26,9 +26,7 @@
26 26
27void tegra_assert_system_reset(char mode, const char *cmd); 27void tegra_assert_system_reset(char mode, const char *cmd);
28 28
29void __init tegra20_init_early(void); 29void __init tegra_init_early(void);
30void __init tegra30_init_early(void);
31void __init tegra114_init_early(void);
32void __init tegra_map_common_io(void); 30void __init tegra_map_common_io(void);
33void __init tegra_init_irq(void); 31void __init tegra_init_irq(void);
34void __init tegra_dt_init_irq(void); 32void __init tegra_dt_init_irq(void);
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 5449a3f2977b..f0315c95c76d 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -94,7 +94,7 @@ static void __init tegra_init_cache(void)
94 94
95} 95}
96 96
97static void __init tegra_init_early(void) 97void __init tegra_init_early(void)
98{ 98{
99 tegra_cpu_reset_handler_init(); 99 tegra_cpu_reset_handler_init();
100 tegra_apb_io_init(); 100 tegra_apb_io_init();
@@ -102,31 +102,9 @@ static void __init tegra_init_early(void)
102 tegra_init_cache(); 102 tegra_init_cache();
103 tegra_pmc_init(); 103 tegra_pmc_init();
104 tegra_powergate_init(); 104 tegra_powergate_init();
105 tegra_hotplug_init();
105} 106}
106 107
107#ifdef CONFIG_ARCH_TEGRA_2x_SOC
108void __init tegra20_init_early(void)
109{
110 tegra_init_early();
111 tegra20_hotplug_init();
112}
113#endif
114
115#ifdef CONFIG_ARCH_TEGRA_3x_SOC
116void __init tegra30_init_early(void)
117{
118 tegra_init_early();
119 tegra30_hotplug_init();
120}
121#endif
122
123#ifdef CONFIG_ARCH_TEGRA_114_SOC
124void __init tegra114_init_early(void)
125{
126 tegra_init_early();
127}
128#endif
129
130void __init tegra_init_late(void) 108void __init tegra_init_late(void)
131{ 109{
132 tegra_powergate_debugfs_init(); 110 tegra_powergate_debugfs_init();
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index a599f6e36dea..8da9f78475da 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -1,8 +1,7 @@
1/* 1/*
2 *
3 * Copyright (C) 2002 ARM Ltd. 2 * Copyright (C) 2002 ARM Ltd.
4 * All Rights Reserved 3 * All Rights Reserved
5 * Copyright (c) 2010, 2012 NVIDIA Corporation. All rights reserved. 4 * Copyright (c) 2010, 2012-2013, NVIDIA Corporation. All rights reserved.
6 * 5 *
7 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +14,7 @@
15#include <asm/cacheflush.h> 14#include <asm/cacheflush.h>
16#include <asm/smp_plat.h> 15#include <asm/smp_plat.h>
17 16
17#include "fuse.h"
18#include "sleep.h" 18#include "sleep.h"
19 19
20static void (*tegra_hotplug_shutdown)(void); 20static void (*tegra_hotplug_shutdown)(void);
@@ -56,18 +56,13 @@ int tegra_cpu_disable(unsigned int cpu)
56 return cpu == 0 ? -EPERM : 0; 56 return cpu == 0 ? -EPERM : 0;
57} 57}
58 58
59#ifdef CONFIG_ARCH_TEGRA_2x_SOC 59void __init tegra_hotplug_init(void)
60extern void tegra20_hotplug_shutdown(void);
61void __init tegra20_hotplug_init(void)
62{ 60{
63 tegra_hotplug_shutdown = tegra20_hotplug_shutdown; 61 if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
64} 62 return;
65#endif
66 63
67#ifdef CONFIG_ARCH_TEGRA_3x_SOC 64 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
68extern void tegra30_hotplug_shutdown(void); 65 tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
69void __init tegra30_hotplug_init(void) 66 if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
70{ 67 tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
71 tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
72} 68}
73#endif
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index fb86a00ce254..c31db797e199 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -25,46 +25,58 @@
25#include <asm/smp_scu.h> 25#include <asm/smp_scu.h>
26#include <asm/smp_plat.h> 26#include <asm/smp_plat.h>
27 27
28#include <mach/powergate.h>
29
30#include "fuse.h" 28#include "fuse.h"
31#include "flowctrl.h" 29#include "flowctrl.h"
32#include "reset.h" 30#include "reset.h"
31#include "pmc.h"
33 32
34#include "common.h" 33#include "common.h"
35#include "iomap.h" 34#include "iomap.h"
36 35
37extern void tegra_secondary_startup(void);
38
39static cpumask_t tegra_cpu_init_mask; 36static cpumask_t tegra_cpu_init_mask;
40 37
41#define EVP_CPU_RESET_VECTOR \
42 (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
43
44static void __cpuinit tegra_secondary_init(unsigned int cpu) 38static void __cpuinit tegra_secondary_init(unsigned int cpu)
45{ 39{
46 cpumask_set_cpu(cpu, &tegra_cpu_init_mask); 40 cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
47} 41}
48 42
49static int tegra20_power_up_cpu(unsigned int cpu) 43
44static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
50{ 45{
51 /* Enable the CPU clock. */ 46 cpu = cpu_logical_map(cpu);
52 tegra_enable_cpu_clock(cpu);
53 47
54 /* Clear flow controller CSR. */ 48 /*
55 flowctrl_write_cpu_csr(cpu, 0); 49 * Force the CPU into reset. The CPU must remain in reset when
50 * the flow controller state is cleared (which will cause the
51 * flow controller to stop driving reset if the CPU has been
52 * power-gated via the flow controller). This will have no
53 * effect on first boot of the CPU since it should already be
54 * in reset.
55 */
56 tegra_put_cpu_in_reset(cpu);
56 57
58 /*
59 * Unhalt the CPU. If the flow controller was used to
60 * power-gate the CPU this will cause the flow controller to
61 * stop driving reset. The CPU will remain in reset because the
62 * clock and reset block is now driving reset.
63 */
64 flowctrl_write_cpu_halt(cpu, 0);
65
66 tegra_enable_cpu_clock(cpu);
67 flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
68 tegra_cpu_out_of_reset(cpu);
57 return 0; 69 return 0;
58} 70}
59 71
60static int tegra30_power_up_cpu(unsigned int cpu) 72static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
61{ 73{
62 int ret, pwrgateid; 74 int ret;
63 unsigned long timeout; 75 unsigned long timeout;
64 76
65 pwrgateid = tegra_cpu_powergate_id(cpu); 77 cpu = cpu_logical_map(cpu);
66 if (pwrgateid < 0) 78 tegra_put_cpu_in_reset(cpu);
67 return pwrgateid; 79 flowctrl_write_cpu_halt(cpu, 0);
68 80
69 /* 81 /*
70 * The power up sequence of cold boot CPU and warm boot CPU 82 * The power up sequence of cold boot CPU and warm boot CPU
@@ -77,13 +89,13 @@ static int tegra30_power_up_cpu(unsigned int cpu)
77 * the IO clamps. 89 * the IO clamps.
78 * For cold boot CPU, do not wait. After the cold boot CPU be 90 * For cold boot CPU, do not wait. After the cold boot CPU be
79 * booted, it will run to tegra_secondary_init() and set 91 * booted, it will run to tegra_secondary_init() and set
80 * tegra_cpu_init_mask which influences what tegra30_power_up_cpu() 92 * tegra_cpu_init_mask which influences what tegra30_boot_secondary()
81 * next time around. 93 * next time around.
82 */ 94 */
83 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) { 95 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
84 timeout = jiffies + msecs_to_jiffies(50); 96 timeout = jiffies + msecs_to_jiffies(50);
85 do { 97 do {
86 if (tegra_powergate_is_powered(pwrgateid)) 98 if (tegra_pmc_cpu_is_powered(cpu))
87 goto remove_clamps; 99 goto remove_clamps;
88 udelay(10); 100 udelay(10);
89 } while (time_before(jiffies, timeout)); 101 } while (time_before(jiffies, timeout));
@@ -95,14 +107,14 @@ static int tegra30_power_up_cpu(unsigned int cpu)
95 * be un-gated by un-toggling the power gate register 107 * be un-gated by un-toggling the power gate register
96 * manually. 108 * manually.
97 */ 109 */
98 if (!tegra_powergate_is_powered(pwrgateid)) { 110 if (!tegra_pmc_cpu_is_powered(cpu)) {
99 ret = tegra_powergate_power_on(pwrgateid); 111 ret = tegra_pmc_cpu_power_on(cpu);
100 if (ret) 112 if (ret)
101 return ret; 113 return ret;
102 114
103 /* Wait for the power to come up. */ 115 /* Wait for the power to come up. */
104 timeout = jiffies + msecs_to_jiffies(100); 116 timeout = jiffies + msecs_to_jiffies(100);
105 while (tegra_powergate_is_powered(pwrgateid)) { 117 while (tegra_pmc_cpu_is_powered(cpu)) {
106 if (time_after(jiffies, timeout)) 118 if (time_after(jiffies, timeout))
107 return -ETIMEDOUT; 119 return -ETIMEDOUT;
108 udelay(10); 120 udelay(10);
@@ -115,60 +127,26 @@ remove_clamps:
115 udelay(10); 127 udelay(10);
116 128
117 /* Remove I/O clamps. */ 129 /* Remove I/O clamps. */
118 ret = tegra_powergate_remove_clamping(pwrgateid); 130 ret = tegra_pmc_cpu_remove_clamping(cpu);
119 if (ret) 131 if (ret)
120 return ret; 132 return ret;
121 133
122 udelay(10); 134 udelay(10);
123 135
124 /* Clear flow controller CSR. */ 136 flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
125 flowctrl_write_cpu_csr(cpu, 0); 137 tegra_cpu_out_of_reset(cpu);
126
127 return 0; 138 return 0;
128} 139}
129 140
130static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle) 141static int __cpuinit tegra_boot_secondary(unsigned int cpu,
142 struct task_struct *idle)
131{ 143{
132 int status; 144 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
133 145 return tegra20_boot_secondary(cpu, idle);
134 cpu = cpu_logical_map(cpu); 146 if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
135 147 return tegra30_boot_secondary(cpu, idle);
136 /*
137 * Force the CPU into reset. The CPU must remain in reset when the
138 * flow controller state is cleared (which will cause the flow
139 * controller to stop driving reset if the CPU has been power-gated
140 * via the flow controller). This will have no effect on first boot
141 * of the CPU since it should already be in reset.
142 */
143 tegra_put_cpu_in_reset(cpu);
144 148
145 /* 149 return -EINVAL;
146 * Unhalt the CPU. If the flow controller was used to power-gate the
147 * CPU this will cause the flow controller to stop driving reset.
148 * The CPU will remain in reset because the clock and reset block
149 * is now driving reset.
150 */
151 flowctrl_write_cpu_halt(cpu, 0);
152
153 switch (tegra_chip_id) {
154 case TEGRA20:
155 status = tegra20_power_up_cpu(cpu);
156 break;
157 case TEGRA30:
158 status = tegra30_power_up_cpu(cpu);
159 break;
160 default:
161 status = -EINVAL;
162 break;
163 }
164
165 if (status)
166 goto done;
167
168 /* Take the CPU out of reset. */
169 tegra_cpu_out_of_reset(cpu);
170done:
171 return status;
172} 150}
173 151
174static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) 152static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 0494f739c95f..acacbe8d1afc 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -164,12 +164,7 @@ bool tegra_set_cpu_in_lp2(int phy_cpu_id)
164 164
165static int tegra_sleep_cpu(unsigned long v2p) 165static int tegra_sleep_cpu(unsigned long v2p)
166{ 166{
167 /* Switch to the identity mapping. */ 167 setup_mm_for_reboot();
168 cpu_switch_mm(idmap_pgd, &init_mm);
169
170 /* Flush the TLB. */
171 local_flush_tlb_all();
172
173 tegra_sleep_cpu_finish(v2p); 168 tegra_sleep_cpu_finish(v2p);
174 169
175 /* should never here */ 170 /* should never here */
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index d4fdb5fcec20..b30e921cc3a9 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. 2 * Copyright (C) 2012,2013 NVIDIA CORPORATION. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 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, 5 * under the terms and conditions of the GNU General Public License,
@@ -18,57 +18,149 @@
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/of.h> 20#include <linux/of.h>
21#include <linux/of_address.h>
21 22
22#include "iomap.h" 23#define PMC_CTRL 0x0
24#define PMC_CTRL_INTR_LOW (1 << 17)
25#define PMC_PWRGATE_TOGGLE 0x30
26#define PMC_PWRGATE_TOGGLE_START (1 << 8)
27#define PMC_REMOVE_CLAMPING 0x34
28#define PMC_PWRGATE_STATUS 0x38
23 29
24#define PMC_CTRL 0x0 30#define TEGRA_POWERGATE_PCIE 3
25#define PMC_CTRL_INTR_LOW (1 << 17) 31#define TEGRA_POWERGATE_VDEC 4
32#define TEGRA_POWERGATE_CPU1 9
33#define TEGRA_POWERGATE_CPU2 10
34#define TEGRA_POWERGATE_CPU3 11
35
36static u8 tegra_cpu_domains[] = {
37 0xFF, /* not available for CPU0 */
38 TEGRA_POWERGATE_CPU1,
39 TEGRA_POWERGATE_CPU2,
40 TEGRA_POWERGATE_CPU3,
41};
42static DEFINE_SPINLOCK(tegra_powergate_lock);
43
44static void __iomem *tegra_pmc_base;
45static bool tegra_pmc_invert_interrupt;
26 46
27static inline u32 tegra_pmc_readl(u32 reg) 47static inline u32 tegra_pmc_readl(u32 reg)
28{ 48{
29 return readl(IO_ADDRESS(TEGRA_PMC_BASE + reg)); 49 return readl(tegra_pmc_base + reg);
30} 50}
31 51
32static inline void tegra_pmc_writel(u32 val, u32 reg) 52static inline void tegra_pmc_writel(u32 val, u32 reg)
33{ 53{
34 writel(val, IO_ADDRESS(TEGRA_PMC_BASE + reg)); 54 writel(val, tegra_pmc_base + reg);
55}
56
57static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
58{
59 if (cpuid <= 0 || cpuid >= num_possible_cpus())
60 return -EINVAL;
61 return tegra_cpu_domains[cpuid];
62}
63
64static bool tegra_pmc_powergate_is_powered(int id)
65{
66 return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;
67}
68
69static int tegra_pmc_powergate_set(int id, bool new_state)
70{
71 bool old_state;
72 unsigned long flags;
73
74 spin_lock_irqsave(&tegra_powergate_lock, flags);
75
76 old_state = tegra_pmc_powergate_is_powered(id);
77 WARN_ON(old_state == new_state);
78
79 tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);
80
81 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
82
83 return 0;
84}
85
86static int tegra_pmc_powergate_remove_clamping(int id)
87{
88 u32 mask;
89
90 /*
91 * Tegra has a bug where PCIE and VDE clamping masks are
92 * swapped relatively to the partition ids.
93 */
94 if (id == TEGRA_POWERGATE_VDEC)
95 mask = (1 << TEGRA_POWERGATE_PCIE);
96 else if (id == TEGRA_POWERGATE_PCIE)
97 mask = (1 << TEGRA_POWERGATE_VDEC);
98 else
99 mask = (1 << id);
100
101 tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);
102
103 return 0;
104}
105
106bool tegra_pmc_cpu_is_powered(int cpuid)
107{
108 int id;
109
110 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
111 if (id < 0)
112 return false;
113 return tegra_pmc_powergate_is_powered(id);
114}
115
116int tegra_pmc_cpu_power_on(int cpuid)
117{
118 int id;
119
120 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
121 if (id < 0)
122 return id;
123 return tegra_pmc_powergate_set(id, true);
124}
125
126int tegra_pmc_cpu_remove_clamping(int cpuid)
127{
128 int id;
129
130 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
131 if (id < 0)
132 return id;
133 return tegra_pmc_powergate_remove_clamping(id);
35} 134}
36 135
37#ifdef CONFIG_OF
38static const struct of_device_id matches[] __initconst = { 136static const struct of_device_id matches[] __initconst = {
137 { .compatible = "nvidia,tegra114-pmc" },
138 { .compatible = "nvidia,tegra30-pmc" },
39 { .compatible = "nvidia,tegra20-pmc" }, 139 { .compatible = "nvidia,tegra20-pmc" },
40 { } 140 { }
41}; 141};
42#endif
43 142
44void __init tegra_pmc_init(void) 143static void tegra_pmc_parse_dt(void)
45{ 144{
46 /* 145 struct device_node *np;
47 * For now, Harmony is the only board that uses the PMC, and it wants
48 * the signal inverted. Seaboard would too if it used the PMC.
49 * Hopefully by the time other boards want to use the PMC, everything
50 * will be device-tree, or they also want it inverted.
51 */
52 bool invert_interrupt = true;
53 u32 val;
54 146
55#ifdef CONFIG_OF 147 np = of_find_matching_node(NULL, matches);
56 if (of_have_populated_dt()) { 148 BUG_ON(!np);
57 struct device_node *np;
58 149
59 invert_interrupt = false; 150 tegra_pmc_base = of_iomap(np, 0);
151
152 tegra_pmc_invert_interrupt = of_property_read_bool(np,
153 "nvidia,invert-interrupt");
154}
155
156void __init tegra_pmc_init(void)
157{
158 u32 val;
60 159
61 np = of_find_matching_node(NULL, matches); 160 tegra_pmc_parse_dt();
62 if (np) {
63 if (of_find_property(np, "nvidia,invert-interrupt",
64 NULL))
65 invert_interrupt = true;
66 }
67 }
68#endif
69 161
70 val = tegra_pmc_readl(PMC_CTRL); 162 val = tegra_pmc_readl(PMC_CTRL);
71 if (invert_interrupt) 163 if (tegra_pmc_invert_interrupt)
72 val |= PMC_CTRL_INTR_LOW; 164 val |= PMC_CTRL_INTR_LOW;
73 else 165 else
74 val &= ~PMC_CTRL_INTR_LOW; 166 val &= ~PMC_CTRL_INTR_LOW;
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
index 8995ee4a8768..7d44710368be 100644
--- a/arch/arm/mach-tegra/pmc.h
+++ b/arch/arm/mach-tegra/pmc.h
@@ -18,6 +18,10 @@
18#ifndef __MACH_TEGRA_PMC_H 18#ifndef __MACH_TEGRA_PMC_H
19#define __MACH_TEGRA_PMC_H 19#define __MACH_TEGRA_PMC_H
20 20
21bool tegra_pmc_cpu_is_powered(int cpuid);
22int tegra_pmc_cpu_power_on(int cpuid);
23int tegra_pmc_cpu_remove_clamping(int cpuid);
24
21void tegra_pmc_init(void); 25void tegra_pmc_init(void);
22 26
23#endif 27#endif
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 4ffae541726e..970ebd5138b9 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. 2 * Copyright (c) 2010-2013, NVIDIA Corporation. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 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, 5 * under the terms and conditions of the GNU General Public License,
@@ -124,11 +124,11 @@ int tegra_sleep_cpu_finish(unsigned long);
124void tegra_disable_clean_inv_dcache(void); 124void tegra_disable_clean_inv_dcache(void);
125 125
126#ifdef CONFIG_HOTPLUG_CPU 126#ifdef CONFIG_HOTPLUG_CPU
127void tegra20_hotplug_init(void); 127void tegra20_hotplug_shutdown(void);
128void tegra30_hotplug_init(void); 128void tegra30_hotplug_shutdown(void);
129void tegra_hotplug_init(void);
129#else 130#else
130static inline void tegra20_hotplug_init(void) {} 131static inline void tegra_hotplug_init(void) {}
131static inline void tegra30_hotplug_init(void) {}
132#endif 132#endif
133 133
134void tegra20_cpu_shutdown(int cpu); 134void tegra20_cpu_shutdown(int cpu);
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/tegra.c
index a0edf2510280..27232c901a22 100644
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * nVidia Tegra device tree board support 2 * NVIDIA Tegra SoC device tree board support
3 * 3 *
4 * Copyright (C) 2011, 2013, NVIDIA Corporation
4 * Copyright (C) 2010 Secret Lab Technologies, Ltd. 5 * Copyright (C) 2010 Secret Lab Technologies, Ltd.
5 * Copyright (C) 2010 Google, Inc. 6 * Copyright (C) 2010 Google, Inc.
6 * 7 *
@@ -111,7 +112,8 @@ static void __init harmony_init(void)
111 112
112static void __init paz00_init(void) 113static void __init paz00_init(void)
113{ 114{
114 tegra_paz00_wifikill_init(); 115 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
116 tegra_paz00_wifikill_init();
115} 117}
116 118
117static struct { 119static struct {
@@ -137,19 +139,21 @@ static void __init tegra_dt_init_late(void)
137 } 139 }
138} 140}
139 141
140static const char *tegra20_dt_board_compat[] = { 142static const char * const tegra_dt_board_compat[] = {
143 "nvidia,tegra114",
144 "nvidia,tegra30",
141 "nvidia,tegra20", 145 "nvidia,tegra20",
142 NULL 146 NULL
143}; 147};
144 148
145DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)") 149DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)")
146 .map_io = tegra_map_common_io, 150 .map_io = tegra_map_common_io,
147 .smp = smp_ops(tegra_smp_ops), 151 .smp = smp_ops(tegra_smp_ops),
148 .init_early = tegra20_init_early, 152 .init_early = tegra_init_early,
149 .init_irq = tegra_dt_init_irq, 153 .init_irq = tegra_dt_init_irq,
150 .init_time = clocksource_of_init, 154 .init_time = clocksource_of_init,
151 .init_machine = tegra_dt_init, 155 .init_machine = tegra_dt_init,
152 .init_late = tegra_dt_init_late, 156 .init_late = tegra_dt_init_late,
153 .restart = tegra_assert_system_reset, 157 .restart = tegra_assert_system_reset,
154 .dt_compat = tegra20_dt_board_compat, 158 .dt_compat = tegra_dt_board_compat,
155MACHINE_END 159MACHINE_END