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 27 #include <mach/clk.h> 28 #include <mach/iomap.h> 29 #include <mach/powergate.h> 30 31 #include "fuse.h" 32 #include "flowctrl.h" 33 #include "reset.h" 34 35 extern void tegra_secondary_startup(void); 36 37 static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); 38 39 #define EVP_CPU_RESET_VECTOR \ 40 (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100) 41 #define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \ 42 (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c) 43 #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET \ 44 (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x340) 45 #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \ 46 (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344) 47 #define CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR \ 48 (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x34c) 49 50 #define CPU_CLOCK(cpu) (0x1<<(8+cpu)) 51 #define CPU_RESET(cpu) (0x1111ul<<(cpu)) 52 53 void __cpuinit platform_secondary_init(unsigned int cpu) 54 { 55 /* 56 * if any interrupts are already enabled for the primary 57 * core (e.g. timer irq), then they will not have been enabled 58 * for us: do so 59 */ 60 gic_secondary_init(0); 61 62 } 63 64 static int tegra20_power_up_cpu(unsigned int cpu) 65 { 66 u32 reg; 67 68 /* Enable the CPU clock. */ 69 reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX); 70 writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX); 71 barrier(); 72 reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX); 73 74 /* Clear flow controller CSR. */ 75 flowctrl_write_cpu_csr(cpu, 0); 76 77 return 0; 78 } 79 80 static int tegra30_power_up_cpu(unsigned int cpu) 81 { 82 u32 reg; 83 int ret, pwrgateid; 84 unsigned long timeout; 85 86 pwrgateid = tegra_cpu_powergate_id(cpu); 87 if (pwrgateid < 0) 88 return pwrgateid; 89 90 /* If this is the first boot, toggle powergates directly. */ 91 if (!tegra_powergate_is_powered(pwrgateid)) { 92 ret = tegra_powergate_power_on(pwrgateid); 93 if (ret) 94 return ret; 95 96 /* Wait for the power to come up. */ 97 timeout = jiffies + 10*HZ; 98 while (tegra_powergate_is_powered(pwrgateid)) { 99 if (time_after(jiffies, timeout)) 100 return -ETIMEDOUT; 101 udelay(10); 102 } 103 } 104 105 /* CPU partition is powered. Enable the CPU clock. */ 106 writel(CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); 107 reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); 108 udelay(10); 109 110 /* Remove I/O clamps. */ 111 ret = tegra_powergate_remove_clamping(pwrgateid); 112 udelay(10); 113 114 /* Clear flow controller CSR. */ 115 flowctrl_write_cpu_csr(cpu, 0); 116 117 return 0; 118 } 119 120 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) 121 { 122 int status; 123 124 /* 125 * Force the CPU into reset. The CPU must remain in reset when the 126 * flow controller state is cleared (which will cause the flow 127 * controller to stop driving reset if the CPU has been power-gated 128 * via the flow controller). This will have no effect on first boot 129 * of the CPU since it should already be in reset. 130 */ 131 writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); 132 dmb(); 133 134 /* 135 * Unhalt the CPU. If the flow controller was used to power-gate the 136 * CPU this will cause the flow controller to stop driving reset. 137 * The CPU will remain in reset because the clock and reset block 138 * is now driving reset. 139 */ 140 flowctrl_write_cpu_halt(cpu, 0); 141 142 switch (tegra_chip_id) { 143 case TEGRA20: 144 status = tegra20_power_up_cpu(cpu); 145 break; 146 case TEGRA30: 147 status = tegra30_power_up_cpu(cpu); 148 break; 149 default: 150 status = -EINVAL; 151 break; 152 } 153 154 if (status) 155 goto done; 156 157 /* Take the CPU out of reset. */ 158 writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR); 159 wmb(); 160 done: 161 return status; 162 } 163 164 /* 165 * Initialise the CPU possible map early - this describes the CPUs 166 * which may be present or become present in the system. 167 */ 168 void __init smp_init_cpus(void) 169 { 170 unsigned int i, ncores = scu_get_core_count(scu_base); 171 172 if (ncores > nr_cpu_ids) { 173 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", 174 ncores, nr_cpu_ids); 175 ncores = nr_cpu_ids; 176 } 177 178 for (i = 0; i < ncores; i++) 179 set_cpu_possible(i, true); 180 181 set_smp_cross_call(gic_raise_softirq); 182 } 183 184 void __init platform_smp_prepare_cpus(unsigned int max_cpus) 185 { 186 tegra_cpu_reset_handler_init(); 187 scu_enable(scu_base); 188 } 189