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