xref: /openbmc/linux/arch/arm/mach-tegra/platsmp.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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