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