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