platsmp.c revision f7c66dc0bf0f4ecd349c79315c87841c67e27aef
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 udelay(10); 128 129 /* Clear flow controller CSR. */ 130 flowctrl_write_cpu_csr(cpu, 0); 131 132 return 0; 133} 134 135static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle) 136{ 137 int status; 138 139 cpu = cpu_logical_map(cpu); 140 141 /* 142 * Force the CPU into reset. The CPU must remain in reset when the 143 * flow controller state is cleared (which will cause the flow 144 * controller to stop driving reset if the CPU has been power-gated 145 * via the flow controller). This will have no effect on first boot 146 * of the CPU since it should already be in reset. 147 */ 148 tegra_put_cpu_in_reset(cpu); 149 150 /* 151 * Unhalt the CPU. If the flow controller was used to power-gate the 152 * CPU this will cause the flow controller to stop driving reset. 153 * The CPU will remain in reset because the clock and reset block 154 * is now driving reset. 155 */ 156 flowctrl_write_cpu_halt(cpu, 0); 157 158 switch (tegra_chip_id) { 159 case TEGRA20: 160 status = tegra20_power_up_cpu(cpu); 161 break; 162 case TEGRA30: 163 status = tegra30_power_up_cpu(cpu); 164 break; 165 default: 166 status = -EINVAL; 167 break; 168 } 169 170 if (status) 171 goto done; 172 173 /* Take the CPU out of reset. */ 174 tegra_cpu_out_of_reset(cpu); 175done: 176 return status; 177} 178 179static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) 180{ 181 /* Always mark the boot CPU (CPU0) as initialized. */ 182 cpumask_set_cpu(0, &tegra_cpu_init_mask); 183 184 if (scu_a9_has_base()) 185 scu_enable(IO_ADDRESS(scu_a9_get_base())); 186} 187 188struct smp_operations tegra_smp_ops __initdata = { 189 .smp_prepare_cpus = tegra_smp_prepare_cpus, 190 .smp_secondary_init = tegra_secondary_init, 191 .smp_boot_secondary = tegra_boot_secondary, 192#ifdef CONFIG_HOTPLUG_CPU 193 .cpu_kill = tegra_cpu_kill, 194 .cpu_die = tegra_cpu_die, 195 .cpu_disable = tegra_cpu_disable, 196#endif 197}; 198