blob: e6911a14c096b575ccce20343641ec55104c9b50 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Colin Cross1cea7322010-02-21 17:46:23 -08002/*
3 * linux/arch/arm/mach-tegra/platsmp.c
4 *
5 * Copyright (C) 2002 ARM Ltd.
6 * All Rights Reserved
7 *
8 * Copyright (C) 2009 Palm
9 * All Rights Reserved
Colin Cross1cea7322010-02-21 17:46:23 -080010 */
Thierry Redinga0524ac2014-07-11 09:44:49 +020011
12#include <linux/clk/tegra.h>
Colin Cross1cea7322010-02-21 17:46:23 -080013#include <linux/delay.h>
14#include <linux/device.h>
Thierry Redinga0524ac2014-07-11 09:44:49 +020015#include <linux/errno.h>
16#include <linux/init.h>
17#include <linux/io.h>
Colin Cross1cea7322010-02-21 17:46:23 -080018#include <linux/jiffies.h>
19#include <linux/smp.h>
Colin Cross1cea7322010-02-21 17:46:23 -080020
Jon Hunter7e10cf72017-03-28 13:42:54 +010021#include <soc/tegra/flowctrl.h>
Thierry Reding304664e2014-07-11 09:52:41 +020022#include <soc/tegra/fuse.h>
Thierry Reding72323982014-07-11 13:19:06 +020023#include <soc/tegra/pmc.h>
Thierry Reding304664e2014-07-11 09:52:41 +020024
Colin Cross1cea7322010-02-21 17:46:23 -080025#include <asm/cacheflush.h>
Colin Cross1cea7322010-02-21 17:46:23 -080026#include <asm/mach-types.h>
Joseph Lo130bfed2013-01-03 15:31:31 +080027#include <asm/smp_plat.h>
Thierry Redinga0524ac2014-07-11 09:44:49 +020028#include <asm/smp_scu.h>
Peter De Schrijverb36ab972012-02-10 01:47:45 +020029
Marc Zyngiera1725732011-09-08 13:15:22 +010030#include "common.h"
Stephen Warren2be39c02012-10-04 14:24:09 -060031#include "iomap.h"
Thierry Redinga0524ac2014-07-11 09:44:49 +020032#include "reset.h"
Marc Zyngiera1725732011-09-08 13:15:22 +010033
Joseph Lo130bfed2013-01-03 15:31:31 +080034static cpumask_t tegra_cpu_init_mask;
Colin Cross1cea7322010-02-21 17:46:23 -080035
Paul Gortmaker8bd26e32013-06-17 15:43:14 -040036static void tegra_secondary_init(unsigned int cpu)
Colin Cross1cea7322010-02-21 17:46:23 -080037{
Joseph Lo130bfed2013-01-03 15:31:31 +080038 cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
Peter De Schrijverb36ab972012-02-10 01:47:45 +020039}
40
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +080041
42static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
Peter De Schrijverb36ab972012-02-10 01:47:45 +020043{
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +080044 cpu = cpu_logical_map(cpu);
45
46 /*
47 * Force the CPU into reset. The CPU must remain in reset when
48 * the flow controller state is cleared (which will cause the
49 * flow controller to stop driving reset if the CPU has been
50 * power-gated via the flow controller). This will have no
51 * effect on first boot of the CPU since it should already be
52 * in reset.
53 */
54 tegra_put_cpu_in_reset(cpu);
55
56 /*
57 * Unhalt the CPU. If the flow controller was used to
58 * power-gate the CPU this will cause the flow controller to
59 * stop driving reset. The CPU will remain in reset because the
60 * clock and reset block is now driving reset.
61 */
62 flowctrl_write_cpu_halt(cpu, 0);
63
Joseph Lobb603272012-08-16 17:31:49 +080064 tegra_enable_cpu_clock(cpu);
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +080065 flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
66 tegra_cpu_out_of_reset(cpu);
Peter De Schrijverb36ab972012-02-10 01:47:45 +020067 return 0;
Colin Cross1cea7322010-02-21 17:46:23 -080068}
69
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +080070static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
Peter De Schrijver86e51a22012-02-10 01:47:50 +020071{
Joseph Lo7e564742013-02-26 16:28:06 +000072 int ret;
Peter De Schrijver86e51a22012-02-10 01:47:50 +020073 unsigned long timeout;
74
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +080075 cpu = cpu_logical_map(cpu);
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +080076 tegra_put_cpu_in_reset(cpu);
77 flowctrl_write_cpu_halt(cpu, 0);
78
Joseph Lo130bfed2013-01-03 15:31:31 +080079 /*
80 * The power up sequence of cold boot CPU and warm boot CPU
81 * was different.
82 *
83 * For warm boot CPU that was resumed from CPU hotplug, the
84 * power will be resumed automatically after un-halting the
85 * flow controller of the warm boot CPU. We need to wait for
86 * the confirmaiton that the CPU is powered then removing
87 * the IO clamps.
88 * For cold boot CPU, do not wait. After the cold boot CPU be
89 * booted, it will run to tegra_secondary_init() and set
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +080090 * tegra_cpu_init_mask which influences what tegra30_boot_secondary()
Joseph Lo130bfed2013-01-03 15:31:31 +080091 * next time around.
92 */
93 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
Joseph Lo13958682013-01-07 10:56:14 +080094 timeout = jiffies + msecs_to_jiffies(50);
Joseph Lo130bfed2013-01-03 15:31:31 +080095 do {
Joseph Lo7e564742013-02-26 16:28:06 +000096 if (tegra_pmc_cpu_is_powered(cpu))
Joseph Lo130bfed2013-01-03 15:31:31 +080097 goto remove_clamps;
98 udelay(10);
99 } while (time_before(jiffies, timeout));
100 }
101
102 /*
103 * The power status of the cold boot CPU is power gated as
104 * default. To power up the cold boot CPU, the power should
105 * be un-gated by un-toggling the power gate register
106 * manually.
107 */
Jon Hunter0a2d87e2016-02-26 15:48:40 +0000108 ret = tegra_pmc_cpu_power_on(cpu);
109 if (ret)
110 return ret;
Peter De Schrijver86e51a22012-02-10 01:47:50 +0200111
Joseph Lo130bfed2013-01-03 15:31:31 +0800112remove_clamps:
Peter De Schrijver86e51a22012-02-10 01:47:50 +0200113 /* CPU partition is powered. Enable the CPU clock. */
Joseph Lobb603272012-08-16 17:31:49 +0800114 tegra_enable_cpu_clock(cpu);
Peter De Schrijver86e51a22012-02-10 01:47:50 +0200115 udelay(10);
116
117 /* Remove I/O clamps. */
Joseph Lo7e564742013-02-26 16:28:06 +0000118 ret = tegra_pmc_cpu_remove_clamping(cpu);
Hiroshi Doyub4c25cc2013-02-22 14:24:25 +0800119 if (ret)
120 return ret;
121
Peter De Schrijver86e51a22012-02-10 01:47:50 +0200122 udelay(10);
123
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +0800124 flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
125 tegra_cpu_out_of_reset(cpu);
Peter De Schrijver86e51a22012-02-10 01:47:50 +0200126 return 0;
127}
128
Joseph Loe562b862013-02-26 16:28:07 +0000129static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
130{
Joseph Lo18901e92013-05-20 18:39:27 +0800131 int ret = 0;
132
Joseph Loe562b862013-02-26 16:28:07 +0000133 cpu = cpu_logical_map(cpu);
Joseph Lo18901e92013-05-20 18:39:27 +0800134
135 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
136 /*
137 * Warm boot flow
138 * The flow controller in charge of the power state and
139 * control for each CPU.
140 */
141 /* set SCLK as event trigger for flow controller */
142 flowctrl_write_cpu_csr(cpu, 1);
143 flowctrl_write_cpu_halt(cpu,
144 FLOW_CTRL_WAITEVENT | FLOW_CTRL_SCLK_RESUME);
145 } else {
146 /*
147 * Cold boot flow
148 * The CPU is powered up by toggling PMC directly. It will
149 * also initial power state in flow controller. After that,
150 * the CPU's power state is maintained by flow controller.
151 */
152 ret = tegra_pmc_cpu_power_on(cpu);
153 }
154
155 return ret;
Joseph Loe562b862013-02-26 16:28:07 +0000156}
157
Paul Gortmaker8bd26e32013-06-17 15:43:14 -0400158static int tegra_boot_secondary(unsigned int cpu,
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +0800159 struct task_struct *idle)
Colin Cross1cea7322010-02-21 17:46:23 -0800160{
Thierry Reding304664e2014-07-11 09:52:41 +0200161 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +0800162 return tegra20_boot_secondary(cpu, idle);
Thierry Reding304664e2014-07-11 09:52:41 +0200163 if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +0800164 return tegra30_boot_secondary(cpu, idle);
Thierry Reding304664e2014-07-11 09:52:41 +0200165 if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
Joseph Loe562b862013-02-26 16:28:07 +0000166 return tegra114_boot_secondary(cpu, idle);
Thierry Reding304664e2014-07-11 09:52:41 +0200167 if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
Joseph Lo73944472013-10-08 12:50:03 +0800168 return tegra114_boot_secondary(cpu, idle);
Peter De Schrijverb36ab972012-02-10 01:47:45 +0200169
Hiroshi Doyu0d1f79b2013-02-22 14:24:27 +0800170 return -EINVAL;
Colin Cross1cea7322010-02-21 17:46:23 -0800171}
172
Marc Zyngiera1725732011-09-08 13:15:22 +0100173static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
Colin Cross1cea7322010-02-21 17:46:23 -0800174{
Joseph Lo130bfed2013-01-03 15:31:31 +0800175 /* Always mark the boot CPU (CPU0) as initialized. */
176 cpumask_set_cpu(0, &tegra_cpu_init_mask);
177
Hiroshi Doyu909444a2013-01-22 07:52:02 +0200178 if (scu_a9_has_base())
179 scu_enable(IO_ADDRESS(scu_a9_get_base()));
Colin Cross1cea7322010-02-21 17:46:23 -0800180}
Marc Zyngiera1725732011-09-08 13:15:22 +0100181
Masahiro Yamada75305272015-11-15 10:39:53 +0900182const struct smp_operations tegra_smp_ops __initconst = {
Marc Zyngiera1725732011-09-08 13:15:22 +0100183 .smp_prepare_cpus = tegra_smp_prepare_cpus,
184 .smp_secondary_init = tegra_secondary_init,
185 .smp_boot_secondary = tegra_boot_secondary,
186#ifdef CONFIG_HOTPLUG_CPU
Joseph Lob8119432013-01-03 14:43:00 +0800187 .cpu_kill = tegra_cpu_kill,
Marc Zyngiera1725732011-09-08 13:15:22 +0100188 .cpu_die = tegra_cpu_die,
189#endif
190};