diff options
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-dt-tegra114.c | 46 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-dt-tegra30.c | 60 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/common.c | 26 | ||||
-rw-r--r-- | arch/arm/mach-tegra/hotplug.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-tegra/platsmp.c | 118 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pm.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pmc.c | 152 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pmc.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/sleep.h | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra.c (renamed from arch/arm/mach-tegra/board-dt-tegra20.c) | 16 |
12 files changed, 199 insertions, 271 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 09b578f9eb84..c1970005f805 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile | |||
@@ -10,6 +10,7 @@ obj-y += pm.o | |||
10 | obj-y += reset.o | 10 | obj-y += reset.o |
11 | obj-y += reset-handler.o | 11 | obj-y += reset-handler.o |
12 | obj-y += sleep.o | 12 | obj-y += sleep.o |
13 | obj-y += tegra.o | ||
13 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o | 14 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o |
14 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o | 15 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o |
15 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o | 16 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o |
@@ -26,9 +27,6 @@ obj-$(CONFIG_SMP) += platsmp.o headsmp.o | |||
26 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 27 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
27 | obj-$(CONFIG_TEGRA_PCI) += pcie.o | 28 | obj-$(CONFIG_TEGRA_PCI) += pcie.o |
28 | 29 | ||
29 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o | ||
30 | obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o | ||
31 | obj-$(CONFIG_ARCH_TEGRA_114_SOC) += board-dt-tegra114.o | ||
32 | ifeq ($(CONFIG_CPU_IDLE),y) | 30 | ifeq ($(CONFIG_CPU_IDLE),y) |
33 | obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o | 31 | obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o |
34 | endif | 32 | endif |
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 | |||
26 | static void __init tegra114_dt_init(void) | ||
27 | { | ||
28 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | ||
29 | } | ||
30 | |||
31 | static const char * const tegra114_dt_board_compat[] = { | ||
32 | "nvidia,tegra114", | ||
33 | NULL, | ||
34 | }; | ||
35 | |||
36 | DT_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, | ||
46 | MACHINE_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 | |||
40 | static void __init tegra30_dt_init(void) | ||
41 | { | ||
42 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | ||
43 | } | ||
44 | |||
45 | static const char *tegra30_dt_board_compat[] = { | ||
46 | "nvidia,tegra30", | ||
47 | NULL | ||
48 | }; | ||
49 | |||
50 | DT_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, | ||
60 | MACHINE_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 | ||
27 | void tegra_assert_system_reset(char mode, const char *cmd); | 27 | void tegra_assert_system_reset(char mode, const char *cmd); |
28 | 28 | ||
29 | void __init tegra20_init_early(void); | 29 | void __init tegra_init_early(void); |
30 | void __init tegra30_init_early(void); | ||
31 | void __init tegra114_init_early(void); | ||
32 | void __init tegra_map_common_io(void); | 30 | void __init tegra_map_common_io(void); |
33 | void __init tegra_init_irq(void); | 31 | void __init tegra_init_irq(void); |
34 | void __init tegra_dt_init_irq(void); | 32 | void __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 | ||
97 | static void __init tegra_init_early(void) | 97 | void __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 | ||
108 | void __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 | ||
116 | void __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 | ||
124 | void __init tegra114_init_early(void) | ||
125 | { | ||
126 | tegra_init_early(); | ||
127 | } | ||
128 | #endif | ||
129 | |||
130 | void __init tegra_init_late(void) | 108 | void __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 | ||
20 | static void (*tegra_hotplug_shutdown)(void); | 20 | static 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 | 59 | void __init tegra_hotplug_init(void) |
60 | extern void tegra20_hotplug_shutdown(void); | ||
61 | void __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) |
68 | extern void tegra30_hotplug_shutdown(void); | 65 | tegra_hotplug_shutdown = tegra20_hotplug_shutdown; |
69 | void __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 e78d52d83acd..c31db797e199 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/irqchip/arm-gic.h> | ||
22 | #include <linux/clk/tegra.h> | 21 | #include <linux/clk/tegra.h> |
23 | 22 | ||
24 | #include <asm/cacheflush.h> | 23 | #include <asm/cacheflush.h> |
@@ -26,53 +25,58 @@ | |||
26 | #include <asm/smp_scu.h> | 25 | #include <asm/smp_scu.h> |
27 | #include <asm/smp_plat.h> | 26 | #include <asm/smp_plat.h> |
28 | 27 | ||
29 | #include <mach/powergate.h> | ||
30 | |||
31 | #include "fuse.h" | 28 | #include "fuse.h" |
32 | #include "flowctrl.h" | 29 | #include "flowctrl.h" |
33 | #include "reset.h" | 30 | #include "reset.h" |
31 | #include "pmc.h" | ||
34 | 32 | ||
35 | #include "common.h" | 33 | #include "common.h" |
36 | #include "iomap.h" | 34 | #include "iomap.h" |
37 | 35 | ||
38 | extern void tegra_secondary_startup(void); | ||
39 | |||
40 | static cpumask_t tegra_cpu_init_mask; | 36 | static cpumask_t tegra_cpu_init_mask; |
41 | 37 | ||
42 | #define EVP_CPU_RESET_VECTOR \ | ||
43 | (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100) | ||
44 | |||
45 | static void __cpuinit tegra_secondary_init(unsigned int cpu) | 38 | static void __cpuinit tegra_secondary_init(unsigned int cpu) |
46 | { | 39 | { |
47 | /* | ||
48 | * if any interrupts are already enabled for the primary | ||
49 | * core (e.g. timer irq), then they will not have been enabled | ||
50 | * for us: do so | ||
51 | */ | ||
52 | gic_secondary_init(0); | ||
53 | |||
54 | cpumask_set_cpu(cpu, &tegra_cpu_init_mask); | 40 | cpumask_set_cpu(cpu, &tegra_cpu_init_mask); |
55 | } | 41 | } |
56 | 42 | ||
57 | static int tegra20_power_up_cpu(unsigned int cpu) | 43 | |
44 | static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
58 | { | 45 | { |
59 | /* Enable the CPU clock. */ | 46 | cpu = cpu_logical_map(cpu); |
60 | tegra_enable_cpu_clock(cpu); | ||
61 | 47 | ||
62 | /* Clear flow controller CSR. */ | 48 | /* |
63 | 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); | ||
64 | 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); | ||
65 | return 0; | 69 | return 0; |
66 | } | 70 | } |
67 | 71 | ||
68 | static int tegra30_power_up_cpu(unsigned int cpu) | 72 | static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle) |
69 | { | 73 | { |
70 | int ret, pwrgateid; | 74 | int ret; |
71 | unsigned long timeout; | 75 | unsigned long timeout; |
72 | 76 | ||
73 | pwrgateid = tegra_cpu_powergate_id(cpu); | 77 | cpu = cpu_logical_map(cpu); |
74 | if (pwrgateid < 0) | 78 | tegra_put_cpu_in_reset(cpu); |
75 | return pwrgateid; | 79 | flowctrl_write_cpu_halt(cpu, 0); |
76 | 80 | ||
77 | /* | 81 | /* |
78 | * 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 |
@@ -85,13 +89,13 @@ static int tegra30_power_up_cpu(unsigned int cpu) | |||
85 | * the IO clamps. | 89 | * the IO clamps. |
86 | * 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 |
87 | * booted, it will run to tegra_secondary_init() and set | 91 | * booted, it will run to tegra_secondary_init() and set |
88 | * tegra_cpu_init_mask which influences what tegra30_power_up_cpu() | 92 | * tegra_cpu_init_mask which influences what tegra30_boot_secondary() |
89 | * next time around. | 93 | * next time around. |
90 | */ | 94 | */ |
91 | if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) { | 95 | if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) { |
92 | timeout = jiffies + msecs_to_jiffies(50); | 96 | timeout = jiffies + msecs_to_jiffies(50); |
93 | do { | 97 | do { |
94 | if (tegra_powergate_is_powered(pwrgateid)) | 98 | if (tegra_pmc_cpu_is_powered(cpu)) |
95 | goto remove_clamps; | 99 | goto remove_clamps; |
96 | udelay(10); | 100 | udelay(10); |
97 | } while (time_before(jiffies, timeout)); | 101 | } while (time_before(jiffies, timeout)); |
@@ -103,14 +107,14 @@ static int tegra30_power_up_cpu(unsigned int cpu) | |||
103 | * be un-gated by un-toggling the power gate register | 107 | * be un-gated by un-toggling the power gate register |
104 | * manually. | 108 | * manually. |
105 | */ | 109 | */ |
106 | if (!tegra_powergate_is_powered(pwrgateid)) { | 110 | if (!tegra_pmc_cpu_is_powered(cpu)) { |
107 | ret = tegra_powergate_power_on(pwrgateid); | 111 | ret = tegra_pmc_cpu_power_on(cpu); |
108 | if (ret) | 112 | if (ret) |
109 | return ret; | 113 | return ret; |
110 | 114 | ||
111 | /* Wait for the power to come up. */ | 115 | /* Wait for the power to come up. */ |
112 | timeout = jiffies + msecs_to_jiffies(100); | 116 | timeout = jiffies + msecs_to_jiffies(100); |
113 | while (tegra_powergate_is_powered(pwrgateid)) { | 117 | while (tegra_pmc_cpu_is_powered(cpu)) { |
114 | if (time_after(jiffies, timeout)) | 118 | if (time_after(jiffies, timeout)) |
115 | return -ETIMEDOUT; | 119 | return -ETIMEDOUT; |
116 | udelay(10); | 120 | udelay(10); |
@@ -123,60 +127,26 @@ remove_clamps: | |||
123 | udelay(10); | 127 | udelay(10); |
124 | 128 | ||
125 | /* Remove I/O clamps. */ | 129 | /* Remove I/O clamps. */ |
126 | ret = tegra_powergate_remove_clamping(pwrgateid); | 130 | ret = tegra_pmc_cpu_remove_clamping(cpu); |
127 | if (ret) | 131 | if (ret) |
128 | return ret; | 132 | return ret; |
129 | 133 | ||
130 | udelay(10); | 134 | udelay(10); |
131 | 135 | ||
132 | /* Clear flow controller CSR. */ | 136 | flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */ |
133 | flowctrl_write_cpu_csr(cpu, 0); | 137 | tegra_cpu_out_of_reset(cpu); |
134 | |||
135 | return 0; | 138 | return 0; |
136 | } | 139 | } |
137 | 140 | ||
138 | static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle) | 141 | static int __cpuinit tegra_boot_secondary(unsigned int cpu, |
142 | struct task_struct *idle) | ||
139 | { | 143 | { |
140 | int status; | 144 | if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20) |
141 | 145 | return tegra20_boot_secondary(cpu, idle); | |
142 | cpu = cpu_logical_map(cpu); | 146 | if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30) |
143 | 147 | return tegra30_boot_secondary(cpu, idle); | |
144 | /* | ||
145 | * Force the CPU into reset. The CPU must remain in reset when the | ||
146 | * flow controller state is cleared (which will cause the flow | ||
147 | * controller to stop driving reset if the CPU has been power-gated | ||
148 | * via the flow controller). This will have no effect on first boot | ||
149 | * of the CPU since it should already be in reset. | ||
150 | */ | ||
151 | tegra_put_cpu_in_reset(cpu); | ||
152 | |||
153 | /* | ||
154 | * Unhalt the CPU. If the flow controller was used to power-gate the | ||
155 | * CPU this will cause the flow controller to stop driving reset. | ||
156 | * The CPU will remain in reset because the clock and reset block | ||
157 | * is now driving reset. | ||
158 | */ | ||
159 | flowctrl_write_cpu_halt(cpu, 0); | ||
160 | 148 | ||
161 | switch (tegra_chip_id) { | 149 | return -EINVAL; |
162 | case TEGRA20: | ||
163 | status = tegra20_power_up_cpu(cpu); | ||
164 | break; | ||
165 | case TEGRA30: | ||
166 | status = tegra30_power_up_cpu(cpu); | ||
167 | break; | ||
168 | default: | ||
169 | status = -EINVAL; | ||
170 | break; | ||
171 | } | ||
172 | |||
173 | if (status) | ||
174 | goto done; | ||
175 | |||
176 | /* Take the CPU out of reset. */ | ||
177 | tegra_cpu_out_of_reset(cpu); | ||
178 | done: | ||
179 | return status; | ||
180 | } | 150 | } |
181 | 151 | ||
182 | static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) | 152 | static 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 04a8e06f59a9..891fb70d0aa7 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c | |||
@@ -169,12 +169,7 @@ int tegra_cpu_do_idle(void) | |||
169 | 169 | ||
170 | static int tegra_sleep_cpu(unsigned long v2p) | 170 | static int tegra_sleep_cpu(unsigned long v2p) |
171 | { | 171 | { |
172 | /* Switch to the identity mapping. */ | 172 | setup_mm_for_reboot(); |
173 | cpu_switch_mm(idmap_pgd, &init_mm); | ||
174 | |||
175 | /* Flush the TLB. */ | ||
176 | local_flush_tlb_all(); | ||
177 | |||
178 | tegra_sleep_cpu_finish(v2p); | 173 | tegra_sleep_cpu_finish(v2p); |
179 | 174 | ||
180 | /* should never here */ | 175 | /* 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 | |||
36 | static u8 tegra_cpu_domains[] = { | ||
37 | 0xFF, /* not available for CPU0 */ | ||
38 | TEGRA_POWERGATE_CPU1, | ||
39 | TEGRA_POWERGATE_CPU2, | ||
40 | TEGRA_POWERGATE_CPU3, | ||
41 | }; | ||
42 | static DEFINE_SPINLOCK(tegra_powergate_lock); | ||
43 | |||
44 | static void __iomem *tegra_pmc_base; | ||
45 | static bool tegra_pmc_invert_interrupt; | ||
26 | 46 | ||
27 | static inline u32 tegra_pmc_readl(u32 reg) | 47 | static 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 | ||
32 | static inline void tegra_pmc_writel(u32 val, u32 reg) | 52 | static 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 | |||
57 | static 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 | |||
64 | static bool tegra_pmc_powergate_is_powered(int id) | ||
65 | { | ||
66 | return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1; | ||
67 | } | ||
68 | |||
69 | static 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 | |||
86 | static 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 | |||
106 | bool 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 | |||
116 | int 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 | |||
126 | int 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 | ||
38 | static const struct of_device_id matches[] __initconst = { | 136 | static 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 | ||
44 | void __init tegra_pmc_init(void) | 143 | static 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 | |||
156 | void __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 | ||
21 | bool tegra_pmc_cpu_is_powered(int cpuid); | ||
22 | int tegra_pmc_cpu_power_on(int cpuid); | ||
23 | int tegra_pmc_cpu_remove_clamping(int cpuid); | ||
24 | |||
21 | void tegra_pmc_init(void); | 25 | void 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 bb308eab9079..2080fb12ce26 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); | |||
124 | void tegra_disable_clean_inv_dcache(void); | 124 | void tegra_disable_clean_inv_dcache(void); |
125 | 125 | ||
126 | #ifdef CONFIG_HOTPLUG_CPU | 126 | #ifdef CONFIG_HOTPLUG_CPU |
127 | void tegra20_hotplug_init(void); | 127 | void tegra20_hotplug_shutdown(void); |
128 | void tegra30_hotplug_init(void); | 128 | void tegra30_hotplug_shutdown(void); |
129 | void tegra_hotplug_init(void); | ||
129 | #else | 130 | #else |
130 | static inline void tegra20_hotplug_init(void) {} | 131 | static inline void tegra_hotplug_init(void) {} |
131 | static inline void tegra30_hotplug_init(void) {} | ||
132 | #endif | 132 | #endif |
133 | 133 | ||
134 | void tegra20_cpu_shutdown(int cpu); | 134 | void 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 | ||
112 | static void __init paz00_init(void) | 113 | static 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 | ||
117 | static struct { | 119 | static struct { |
@@ -137,19 +139,21 @@ static void __init tegra_dt_init_late(void) | |||
137 | } | 139 | } |
138 | } | 140 | } |
139 | 141 | ||
140 | static const char *tegra20_dt_board_compat[] = { | 142 | static 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 | ||
145 | DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)") | 149 | DT_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, |
155 | MACHINE_END | 159 | MACHINE_END |