1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21cea7326SColin Cross /*
31cea7326SColin Cross * linux/arch/arm/mach-tegra/platsmp.c
41cea7326SColin Cross *
51cea7326SColin Cross * Copyright (C) 2002 ARM Ltd.
61cea7326SColin Cross * All Rights Reserved
71cea7326SColin Cross *
81cea7326SColin Cross * Copyright (C) 2009 Palm
91cea7326SColin Cross * All Rights Reserved
101cea7326SColin Cross */
11a0524accSThierry Reding
12a0524accSThierry Reding #include <linux/clk/tegra.h>
131cea7326SColin Cross #include <linux/delay.h>
141cea7326SColin Cross #include <linux/device.h>
15a0524accSThierry Reding #include <linux/errno.h>
16a0524accSThierry Reding #include <linux/init.h>
17a0524accSThierry Reding #include <linux/io.h>
181cea7326SColin Cross #include <linux/jiffies.h>
191cea7326SColin Cross #include <linux/smp.h>
201cea7326SColin Cross
217e10cf74SJon Hunter #include <soc/tegra/flowctrl.h>
22304664eaSThierry Reding #include <soc/tegra/fuse.h>
237232398aSThierry Reding #include <soc/tegra/pmc.h>
24304664eaSThierry Reding
251cea7326SColin Cross #include <asm/cacheflush.h>
261cea7326SColin Cross #include <asm/mach-types.h>
27130bfed7SJoseph Lo #include <asm/smp_plat.h>
28a0524accSThierry Reding #include <asm/smp_scu.h>
29b36ab975SPeter De Schrijver
30a1725732SMarc Zyngier #include "common.h"
312be39c07SStephen Warren #include "iomap.h"
32a0524accSThierry Reding #include "reset.h"
33a1725732SMarc Zyngier
34130bfed7SJoseph Lo static cpumask_t tegra_cpu_init_mask;
351cea7326SColin Cross
tegra_secondary_init(unsigned int cpu)368bd26e3aSPaul Gortmaker static void tegra_secondary_init(unsigned int cpu)
371cea7326SColin Cross {
38130bfed7SJoseph Lo cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
39b36ab975SPeter De Schrijver }
40b36ab975SPeter De Schrijver
410d1f79b0SHiroshi Doyu
tegra20_boot_secondary(unsigned int cpu,struct task_struct * idle)420d1f79b0SHiroshi Doyu static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
43b36ab975SPeter De Schrijver {
440d1f79b0SHiroshi Doyu cpu = cpu_logical_map(cpu);
450d1f79b0SHiroshi Doyu
460d1f79b0SHiroshi Doyu /*
470d1f79b0SHiroshi Doyu * Force the CPU into reset. The CPU must remain in reset when
480d1f79b0SHiroshi Doyu * the flow controller state is cleared (which will cause the
490d1f79b0SHiroshi Doyu * flow controller to stop driving reset if the CPU has been
500d1f79b0SHiroshi Doyu * power-gated via the flow controller). This will have no
510d1f79b0SHiroshi Doyu * effect on first boot of the CPU since it should already be
520d1f79b0SHiroshi Doyu * in reset.
530d1f79b0SHiroshi Doyu */
540d1f79b0SHiroshi Doyu tegra_put_cpu_in_reset(cpu);
550d1f79b0SHiroshi Doyu
560d1f79b0SHiroshi Doyu /*
570d1f79b0SHiroshi Doyu * Unhalt the CPU. If the flow controller was used to
580d1f79b0SHiroshi Doyu * power-gate the CPU this will cause the flow controller to
590d1f79b0SHiroshi Doyu * stop driving reset. The CPU will remain in reset because the
600d1f79b0SHiroshi Doyu * clock and reset block is now driving reset.
610d1f79b0SHiroshi Doyu */
620d1f79b0SHiroshi Doyu flowctrl_write_cpu_halt(cpu, 0);
630d1f79b0SHiroshi Doyu
64bb603277SJoseph Lo tegra_enable_cpu_clock(cpu);
650d1f79b0SHiroshi Doyu flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
660d1f79b0SHiroshi Doyu tegra_cpu_out_of_reset(cpu);
67b36ab975SPeter De Schrijver return 0;
681cea7326SColin Cross }
691cea7326SColin Cross
tegra30_boot_secondary(unsigned int cpu,struct task_struct * idle)700d1f79b0SHiroshi Doyu static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
7186e51a2eSPeter De Schrijver {
727e564744SJoseph Lo int ret;
7386e51a2eSPeter De Schrijver unsigned long timeout;
7486e51a2eSPeter De Schrijver
750d1f79b0SHiroshi Doyu cpu = cpu_logical_map(cpu);
760d1f79b0SHiroshi Doyu tegra_put_cpu_in_reset(cpu);
770d1f79b0SHiroshi Doyu flowctrl_write_cpu_halt(cpu, 0);
780d1f79b0SHiroshi Doyu
79130bfed7SJoseph Lo /*
80130bfed7SJoseph Lo * The power up sequence of cold boot CPU and warm boot CPU
81130bfed7SJoseph Lo * was different.
82130bfed7SJoseph Lo *
83130bfed7SJoseph Lo * For warm boot CPU that was resumed from CPU hotplug, the
84130bfed7SJoseph Lo * power will be resumed automatically after un-halting the
85130bfed7SJoseph Lo * flow controller of the warm boot CPU. We need to wait for
86*d5becc32SJulia Lawall * the confirmation that the CPU is powered then removing
87130bfed7SJoseph Lo * the IO clamps.
88130bfed7SJoseph Lo * For cold boot CPU, do not wait. After the cold boot CPU be
89130bfed7SJoseph Lo * booted, it will run to tegra_secondary_init() and set
900d1f79b0SHiroshi Doyu * tegra_cpu_init_mask which influences what tegra30_boot_secondary()
91130bfed7SJoseph Lo * next time around.
92130bfed7SJoseph Lo */
93130bfed7SJoseph Lo if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
941395868cSJoseph Lo timeout = jiffies + msecs_to_jiffies(50);
95130bfed7SJoseph Lo do {
967e564744SJoseph Lo if (tegra_pmc_cpu_is_powered(cpu))
97130bfed7SJoseph Lo goto remove_clamps;
98130bfed7SJoseph Lo udelay(10);
99130bfed7SJoseph Lo } while (time_before(jiffies, timeout));
100130bfed7SJoseph Lo }
101130bfed7SJoseph Lo
102130bfed7SJoseph Lo /*
103130bfed7SJoseph Lo * The power status of the cold boot CPU is power gated as
104130bfed7SJoseph Lo * default. To power up the cold boot CPU, the power should
105130bfed7SJoseph Lo * be un-gated by un-toggling the power gate register
106130bfed7SJoseph Lo * manually.
107130bfed7SJoseph Lo */
1087e564744SJoseph Lo ret = tegra_pmc_cpu_power_on(cpu);
10986e51a2eSPeter De Schrijver if (ret)
11086e51a2eSPeter De Schrijver return ret;
11186e51a2eSPeter De Schrijver
112130bfed7SJoseph Lo remove_clamps:
11386e51a2eSPeter De Schrijver /* CPU partition is powered. Enable the CPU clock. */
114bb603277SJoseph Lo tegra_enable_cpu_clock(cpu);
11586e51a2eSPeter De Schrijver udelay(10);
11686e51a2eSPeter De Schrijver
11786e51a2eSPeter De Schrijver /* Remove I/O clamps. */
1187e564744SJoseph Lo ret = tegra_pmc_cpu_remove_clamping(cpu);
119b4c25cc3SHiroshi Doyu if (ret)
120b4c25cc3SHiroshi Doyu return ret;
121b4c25cc3SHiroshi Doyu
12286e51a2eSPeter De Schrijver udelay(10);
12386e51a2eSPeter De Schrijver
1240d1f79b0SHiroshi Doyu flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
1250d1f79b0SHiroshi Doyu tegra_cpu_out_of_reset(cpu);
12686e51a2eSPeter De Schrijver return 0;
12786e51a2eSPeter De Schrijver }
12886e51a2eSPeter De Schrijver
tegra114_boot_secondary(unsigned int cpu,struct task_struct * idle)129e562b865SJoseph Lo static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
130e562b865SJoseph Lo {
13118901e9fSJoseph Lo int ret = 0;
13218901e9fSJoseph Lo
133e562b865SJoseph Lo cpu = cpu_logical_map(cpu);
13418901e9fSJoseph Lo
13518901e9fSJoseph Lo if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
13618901e9fSJoseph Lo /*
13718901e9fSJoseph Lo * Warm boot flow
13818901e9fSJoseph Lo * The flow controller in charge of the power state and
13918901e9fSJoseph Lo * control for each CPU.
14018901e9fSJoseph Lo */
14118901e9fSJoseph Lo /* set SCLK as event trigger for flow controller */
14218901e9fSJoseph Lo flowctrl_write_cpu_csr(cpu, 1);
14318901e9fSJoseph Lo flowctrl_write_cpu_halt(cpu,
14418901e9fSJoseph Lo FLOW_CTRL_WAITEVENT | FLOW_CTRL_SCLK_RESUME);
14518901e9fSJoseph Lo } else {
14618901e9fSJoseph Lo /*
14718901e9fSJoseph Lo * Cold boot flow
14818901e9fSJoseph Lo * The CPU is powered up by toggling PMC directly. It will
14918901e9fSJoseph Lo * also initial power state in flow controller. After that,
15018901e9fSJoseph Lo * the CPU's power state is maintained by flow controller.
15118901e9fSJoseph Lo */
15218901e9fSJoseph Lo ret = tegra_pmc_cpu_power_on(cpu);
15318901e9fSJoseph Lo }
15418901e9fSJoseph Lo
15518901e9fSJoseph Lo return ret;
156e562b865SJoseph Lo }
157e562b865SJoseph Lo
tegra_boot_secondary(unsigned int cpu,struct task_struct * idle)1588bd26e3aSPaul Gortmaker static int tegra_boot_secondary(unsigned int cpu,
1590d1f79b0SHiroshi Doyu struct task_struct *idle)
1601cea7326SColin Cross {
161304664eaSThierry Reding if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
1620d1f79b0SHiroshi Doyu return tegra20_boot_secondary(cpu, idle);
163304664eaSThierry Reding if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
1640d1f79b0SHiroshi Doyu return tegra30_boot_secondary(cpu, idle);
165304664eaSThierry Reding if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
166e562b865SJoseph Lo return tegra114_boot_secondary(cpu, idle);
167304664eaSThierry Reding if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
16873944475SJoseph Lo return tegra114_boot_secondary(cpu, idle);
169b36ab975SPeter De Schrijver
1700d1f79b0SHiroshi Doyu return -EINVAL;
1711cea7326SColin Cross }
1721cea7326SColin Cross
tegra_smp_prepare_cpus(unsigned int max_cpus)173a1725732SMarc Zyngier static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
1741cea7326SColin Cross {
175130bfed7SJoseph Lo /* Always mark the boot CPU (CPU0) as initialized. */
176130bfed7SJoseph Lo cpumask_set_cpu(0, &tegra_cpu_init_mask);
177130bfed7SJoseph Lo
178909444abSHiroshi Doyu if (scu_a9_has_base())
179909444abSHiroshi Doyu scu_enable(IO_ADDRESS(scu_a9_get_base()));
1801cea7326SColin Cross }
181a1725732SMarc Zyngier
18275305275SMasahiro Yamada const struct smp_operations tegra_smp_ops __initconst = {
183a1725732SMarc Zyngier .smp_prepare_cpus = tegra_smp_prepare_cpus,
184a1725732SMarc Zyngier .smp_secondary_init = tegra_secondary_init,
185a1725732SMarc Zyngier .smp_boot_secondary = tegra_boot_secondary,
186a1725732SMarc Zyngier #ifdef CONFIG_HOTPLUG_CPU
187b8119431SJoseph Lo .cpu_kill = tegra_cpu_kill,
188a1725732SMarc Zyngier .cpu_die = tegra_cpu_die,
189a1725732SMarc Zyngier #endif
190a1725732SMarc Zyngier };
191