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