2 * linux/arch/arm/mach-tegra/platsmp.c
4 * Copyright (C) 2002 ARM Ltd.
7 * Copyright (C) 2009 Palm
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.
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>
21 #include <linux/irqchip/arm-gic.h>
22 #include <linux/clk/tegra.h>
24 #include <asm/cacheflush.h>
25 #include <asm/mach-types.h>
26 #include <asm/smp_scu.h>
27 #include <asm/smp_plat.h>
29 #include <mach/powergate.h>
38 extern void tegra_secondary_startup(void);
40 static cpumask_t tegra_cpu_init_mask
;
41 static void __iomem
*scu_base
= IO_ADDRESS(TEGRA_ARM_PERIF_BASE
);
43 #define EVP_CPU_RESET_VECTOR \
44 (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
46 static void __cpuinit
tegra_secondary_init(unsigned int cpu
)
49 * if any interrupts are already enabled for the primary
50 * core (e.g. timer irq), then they will not have been enabled
53 gic_secondary_init(0);
55 cpumask_set_cpu(cpu
, &tegra_cpu_init_mask
);
58 static int tegra20_power_up_cpu(unsigned int cpu
)
60 /* Enable the CPU clock. */
61 tegra_enable_cpu_clock(cpu
);
63 /* Clear flow controller CSR. */
64 flowctrl_write_cpu_csr(cpu
, 0);
69 static int tegra30_power_up_cpu(unsigned int cpu
)
72 unsigned long timeout
;
74 pwrgateid
= tegra_cpu_powergate_id(cpu
);
79 * The power up sequence of cold boot CPU and warm boot CPU
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
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()
92 if (cpumask_test_cpu(cpu
, &tegra_cpu_init_mask
)) {
93 timeout
= jiffies
+ msecs_to_jiffies(50);
95 if (!tegra_powergate_is_powered(pwrgateid
))
98 } while (time_before(jiffies
, timeout
));
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
107 if (!tegra_powergate_is_powered(pwrgateid
)) {
108 ret
= tegra_powergate_power_on(pwrgateid
);
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
))
122 /* CPU partition is powered. Enable the CPU clock. */
123 tegra_enable_cpu_clock(cpu
);
126 /* Remove I/O clamps. */
127 ret
= tegra_powergate_remove_clamping(pwrgateid
);
130 /* Clear flow controller CSR. */
131 flowctrl_write_cpu_csr(cpu
, 0);
136 static int __cpuinit
tegra_boot_secondary(unsigned int cpu
, struct task_struct
*idle
)
140 cpu
= cpu_logical_map(cpu
);
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.
149 tegra_put_cpu_in_reset(cpu
);
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.
157 flowctrl_write_cpu_halt(cpu
, 0);
159 switch (tegra_chip_id
) {
161 status
= tegra20_power_up_cpu(cpu
);
164 status
= tegra30_power_up_cpu(cpu
);
174 /* Take the CPU out of reset. */
175 tegra_cpu_out_of_reset(cpu
);
181 * Initialise the CPU possible map early - this describes the CPUs
182 * which may be present or become present in the system.
184 static void __init
tegra_smp_init_cpus(void)
186 unsigned int i
, ncores
= scu_get_core_count(scu_base
);
188 if (ncores
> nr_cpu_ids
) {
189 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
194 for (i
= 0; i
< ncores
; i
++)
195 set_cpu_possible(i
, true);
198 static void __init
tegra_smp_prepare_cpus(unsigned int max_cpus
)
200 /* Always mark the boot CPU (CPU0) as initialized. */
201 cpumask_set_cpu(0, &tegra_cpu_init_mask
);
203 scu_enable(scu_base
);
206 struct smp_operations tegra_smp_ops __initdata
= {
207 .smp_init_cpus
= tegra_smp_init_cpus
,
208 .smp_prepare_cpus
= tegra_smp_prepare_cpus
,
209 .smp_secondary_init
= tegra_secondary_init
,
210 .smp_boot_secondary
= tegra_boot_secondary
,
211 #ifdef CONFIG_HOTPLUG_CPU
212 .cpu_kill
= tegra_cpu_kill
,
213 .cpu_die
= tegra_cpu_die
,
214 .cpu_disable
= tegra_cpu_disable
,