platsmp.c revision 1395868c06bd41390e50e7c7fe9a4783dd620867
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#include <linux/init.h>
15#include <linux/errno.h>
16#include <linux/delay.h>
17#include <linux/device.h>
18#include <linux/jiffies.h>
19#include <linux/smp.h>
20#include <linux/io.h>
21
22#include <asm/cacheflush.h>
23#include <asm/hardware/gic.h>
24#include <asm/mach-types.h>
25#include <asm/smp_scu.h>
26#include <asm/smp_plat.h>
27
28#include <mach/powergate.h>
29
30#include "fuse.h"
31#include "flowctrl.h"
32#include "reset.h"
33#include "tegra_cpu_car.h"
34
35#include "common.h"
36#include "iomap.h"
37
38extern void tegra_secondary_startup(void);
39
40static cpumask_t tegra_cpu_init_mask;
41static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
42
43#define EVP_CPU_RESET_VECTOR \
44	(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
45
46static void __cpuinit tegra_secondary_init(unsigned int cpu)
47{
48	/*
49	 * if any interrupts are already enabled for the primary
50	 * core (e.g. timer irq), then they will not have been enabled
51	 * for us: do so
52	 */
53	gic_secondary_init(0);
54
55	cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
56}
57
58static int tegra20_power_up_cpu(unsigned int cpu)
59{
60	/* Enable the CPU clock. */
61	tegra_enable_cpu_clock(cpu);
62
63	/* Clear flow controller CSR. */
64	flowctrl_write_cpu_csr(cpu, 0);
65
66	return 0;
67}
68
69static int tegra30_power_up_cpu(unsigned int cpu)
70{
71	int ret, pwrgateid;
72	unsigned long timeout;
73
74	pwrgateid = tegra_cpu_powergate_id(cpu);
75	if (pwrgateid < 0)
76		return pwrgateid;
77
78	/*
79	 * The power up sequence of cold boot CPU and warm boot CPU
80	 * was different.
81	 *
82	 * For warm boot CPU that was resumed from CPU hotplug, the
83	 * power will be resumed automatically after un-halting the
84	 * flow controller of the warm boot CPU. We need to wait for
85	 * the confirmaiton that the CPU is powered then removing
86	 * the IO clamps.
87	 * For cold boot CPU, do not wait. After the cold boot CPU be
88	 * booted, it will run to tegra_secondary_init() and set
89	 * tegra_cpu_init_mask which influences what tegra30_power_up_cpu()
90	 * next time around.
91	 */
92	if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
93		timeout = jiffies + msecs_to_jiffies(50);
94		do {
95			if (!tegra_powergate_is_powered(pwrgateid))
96				goto remove_clamps;
97			udelay(10);
98		} while (time_before(jiffies, timeout));
99	}
100
101	/*
102	 * The power status of the cold boot CPU is power gated as
103	 * default. To power up the cold boot CPU, the power should
104	 * be un-gated by un-toggling the power gate register
105	 * manually.
106	 */
107	if (!tegra_powergate_is_powered(pwrgateid)) {
108		ret = tegra_powergate_power_on(pwrgateid);
109		if (ret)
110			return ret;
111
112		/* Wait for the power to come up. */
113		timeout = jiffies + msecs_to_jiffies(100);
114		while (tegra_powergate_is_powered(pwrgateid)) {
115			if (time_after(jiffies, timeout))
116				return -ETIMEDOUT;
117			udelay(10);
118		}
119	}
120
121remove_clamps:
122	/* CPU partition is powered. Enable the CPU clock. */
123	tegra_enable_cpu_clock(cpu);
124	udelay(10);
125
126	/* Remove I/O clamps. */
127	ret = tegra_powergate_remove_clamping(pwrgateid);
128	udelay(10);
129
130	/* Clear flow controller CSR. */
131	flowctrl_write_cpu_csr(cpu, 0);
132
133	return 0;
134}
135
136static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle)
137{
138	int status;
139
140	cpu = cpu_logical_map(cpu);
141
142	/*
143	 * Force the CPU into reset. The CPU must remain in reset when the
144	 * flow controller state is cleared (which will cause the flow
145	 * controller to stop driving reset if the CPU has been power-gated
146	 * via the flow controller). This will have no effect on first boot
147	 * of the CPU since it should already be in reset.
148	 */
149	tegra_put_cpu_in_reset(cpu);
150
151	/*
152	 * Unhalt the CPU. If the flow controller was used to power-gate the
153	 * CPU this will cause the flow controller to stop driving reset.
154	 * The CPU will remain in reset because the clock and reset block
155	 * is now driving reset.
156	 */
157	flowctrl_write_cpu_halt(cpu, 0);
158
159	switch (tegra_chip_id) {
160	case TEGRA20:
161		status = tegra20_power_up_cpu(cpu);
162		break;
163	case TEGRA30:
164		status = tegra30_power_up_cpu(cpu);
165		break;
166	default:
167		status = -EINVAL;
168		break;
169	}
170
171	if (status)
172		goto done;
173
174	/* Take the CPU out of reset. */
175	tegra_cpu_out_of_reset(cpu);
176done:
177	return status;
178}
179
180/*
181 * Initialise the CPU possible map early - this describes the CPUs
182 * which may be present or become present in the system.
183 */
184static void __init tegra_smp_init_cpus(void)
185{
186	unsigned int i, ncores = scu_get_core_count(scu_base);
187
188	if (ncores > nr_cpu_ids) {
189		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
190			ncores, nr_cpu_ids);
191		ncores = nr_cpu_ids;
192	}
193
194	for (i = 0; i < ncores; i++)
195		set_cpu_possible(i, true);
196
197	set_smp_cross_call(gic_raise_softirq);
198}
199
200static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
201{
202	/* Always mark the boot CPU (CPU0) as initialized. */
203	cpumask_set_cpu(0, &tegra_cpu_init_mask);
204
205	scu_enable(scu_base);
206}
207
208struct smp_operations tegra_smp_ops __initdata = {
209	.smp_init_cpus		= tegra_smp_init_cpus,
210	.smp_prepare_cpus	= tegra_smp_prepare_cpus,
211	.smp_secondary_init	= tegra_secondary_init,
212	.smp_boot_secondary	= tegra_boot_secondary,
213#ifdef CONFIG_HOTPLUG_CPU
214	.cpu_kill		= tegra_cpu_kill,
215	.cpu_die		= tegra_cpu_die,
216	.cpu_disable		= tegra_cpu_disable,
217#endif
218};
219