platsmp.c revision 304664eab93f9e95a8d28fbd9702ede88bb10cc5
1/*
2 *  linux/arch/arm/mach-tegra/platsmp.c
3 *
4 *  Copyright (C) 2002 ARM Ltd.
5 *  All Rights Reserved
6 *
7 *  Copyright (C) 2009 Palm
8 *  All Rights Reserved
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/clk/tegra.h>
16#include <linux/delay.h>
17#include <linux/device.h>
18#include <linux/errno.h>
19#include <linux/init.h>
20#include <linux/io.h>
21#include <linux/jiffies.h>
22#include <linux/smp.h>
23
24#include <soc/tegra/fuse.h>
25
26#include <asm/cacheflush.h>
27#include <asm/mach-types.h>
28#include <asm/smp_plat.h>
29#include <asm/smp_scu.h>
30
31#include "common.h"
32#include "flowctrl.h"
33#include "iomap.h"
34#include "pmc.h"
35#include "reset.h"
36
37static cpumask_t tegra_cpu_init_mask;
38
39static void tegra_secondary_init(unsigned int cpu)
40{
41	cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
42}
43
44
45static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
46{
47	cpu = cpu_logical_map(cpu);
48
49	/*
50	 * Force the CPU into reset. The CPU must remain in reset when
51	 * the flow controller state is cleared (which will cause the
52	 * flow controller to stop driving reset if the CPU has been
53	 * power-gated via the flow controller). This will have no
54	 * effect on first boot of the CPU since it should already be
55	 * in reset.
56	 */
57	tegra_put_cpu_in_reset(cpu);
58
59	/*
60	 * Unhalt the CPU. If the flow controller was used to
61	 * power-gate the CPU this will cause the flow controller to
62	 * stop driving reset. The CPU will remain in reset because the
63	 * clock and reset block is now driving reset.
64	 */
65	flowctrl_write_cpu_halt(cpu, 0);
66
67	tegra_enable_cpu_clock(cpu);
68	flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
69	tegra_cpu_out_of_reset(cpu);
70	return 0;
71}
72
73static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
74{
75	int ret;
76	unsigned long timeout;
77
78	cpu = cpu_logical_map(cpu);
79	tegra_put_cpu_in_reset(cpu);
80	flowctrl_write_cpu_halt(cpu, 0);
81
82	/*
83	 * The power up sequence of cold boot CPU and warm boot CPU
84	 * was different.
85	 *
86	 * For warm boot CPU that was resumed from CPU hotplug, the
87	 * power will be resumed automatically after un-halting the
88	 * flow controller of the warm boot CPU. We need to wait for
89	 * the confirmaiton that the CPU is powered then removing
90	 * the IO clamps.
91	 * For cold boot CPU, do not wait. After the cold boot CPU be
92	 * booted, it will run to tegra_secondary_init() and set
93	 * tegra_cpu_init_mask which influences what tegra30_boot_secondary()
94	 * next time around.
95	 */
96	if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
97		timeout = jiffies + msecs_to_jiffies(50);
98		do {
99			if (tegra_pmc_cpu_is_powered(cpu))
100				goto remove_clamps;
101			udelay(10);
102		} while (time_before(jiffies, timeout));
103	}
104
105	/*
106	 * The power status of the cold boot CPU is power gated as
107	 * default. To power up the cold boot CPU, the power should
108	 * be un-gated by un-toggling the power gate register
109	 * manually.
110	 */
111	if (!tegra_pmc_cpu_is_powered(cpu)) {
112		ret = tegra_pmc_cpu_power_on(cpu);
113		if (ret)
114			return ret;
115
116		/* Wait for the power to come up. */
117		timeout = jiffies + msecs_to_jiffies(100);
118		while (!tegra_pmc_cpu_is_powered(cpu)) {
119			if (time_after(jiffies, timeout))
120				return -ETIMEDOUT;
121			udelay(10);
122		}
123	}
124
125remove_clamps:
126	/* CPU partition is powered. Enable the CPU clock. */
127	tegra_enable_cpu_clock(cpu);
128	udelay(10);
129
130	/* Remove I/O clamps. */
131	ret = tegra_pmc_cpu_remove_clamping(cpu);
132	if (ret)
133		return ret;
134
135	udelay(10);
136
137	flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
138	tegra_cpu_out_of_reset(cpu);
139	return 0;
140}
141
142static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
143{
144	int ret = 0;
145
146	cpu = cpu_logical_map(cpu);
147
148	if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
149		/*
150		 * Warm boot flow
151		 * The flow controller in charge of the power state and
152		 * control for each CPU.
153		 */
154		/* set SCLK as event trigger for flow controller */
155		flowctrl_write_cpu_csr(cpu, 1);
156		flowctrl_write_cpu_halt(cpu,
157				FLOW_CTRL_WAITEVENT | FLOW_CTRL_SCLK_RESUME);
158	} else {
159		/*
160		 * Cold boot flow
161		 * The CPU is powered up by toggling PMC directly. It will
162		 * also initial power state in flow controller. After that,
163		 * the CPU's power state is maintained by flow controller.
164		 */
165		ret = tegra_pmc_cpu_power_on(cpu);
166	}
167
168	return ret;
169}
170
171static int tegra_boot_secondary(unsigned int cpu,
172					  struct task_struct *idle)
173{
174	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
175		return tegra20_boot_secondary(cpu, idle);
176	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
177		return tegra30_boot_secondary(cpu, idle);
178	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
179		return tegra114_boot_secondary(cpu, idle);
180	if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
181		return tegra114_boot_secondary(cpu, idle);
182
183	return -EINVAL;
184}
185
186static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
187{
188	/* Always mark the boot CPU (CPU0) as initialized. */
189	cpumask_set_cpu(0, &tegra_cpu_init_mask);
190
191	if (scu_a9_has_base())
192		scu_enable(IO_ADDRESS(scu_a9_get_base()));
193}
194
195struct smp_operations tegra_smp_ops __initdata = {
196	.smp_prepare_cpus	= tegra_smp_prepare_cpus,
197	.smp_secondary_init	= tegra_secondary_init,
198	.smp_boot_secondary	= tegra_boot_secondary,
199#ifdef CONFIG_HOTPLUG_CPU
200	.cpu_kill		= tegra_cpu_kill,
201	.cpu_die		= tegra_cpu_die,
202#endif
203};
204