1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * linux/arch/arm/mach-tegra/platsmp.c 4 * 5 * Copyright (C) 2002 ARM Ltd. 6 * All Rights Reserved 7 * 8 * Copyright (C) 2009 Palm 9 * All Rights Reserved 10 */ 11 12 #include <linux/clk/tegra.h> 13 #include <linux/delay.h> 14 #include <linux/device.h> 15 #include <linux/errno.h> 16 #include <linux/init.h> 17 #include <linux/io.h> 18 #include <linux/jiffies.h> 19 #include <linux/smp.h> 20 21 #include <soc/tegra/flowctrl.h> 22 #include <soc/tegra/fuse.h> 23 #include <soc/tegra/pmc.h> 24 25 #include <asm/cacheflush.h> 26 #include <asm/mach-types.h> 27 #include <asm/smp_plat.h> 28 #include <asm/smp_scu.h> 29 30 #include "common.h" 31 #include "iomap.h" 32 #include "reset.h" 33 34 static cpumask_t tegra_cpu_init_mask; 35 36 static void tegra_secondary_init(unsigned int cpu) 37 { 38 cpumask_set_cpu(cpu, &tegra_cpu_init_mask); 39 } 40 41 42 static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle) 43 { 44 cpu = cpu_logical_map(cpu); 45 46 /* 47 * Force the CPU into reset. The CPU must remain in reset when 48 * the flow controller state is cleared (which will cause the 49 * flow controller to stop driving reset if the CPU has been 50 * power-gated via the flow controller). This will have no 51 * effect on first boot of the CPU since it should already be 52 * in reset. 53 */ 54 tegra_put_cpu_in_reset(cpu); 55 56 /* 57 * Unhalt the CPU. If the flow controller was used to 58 * power-gate the CPU this will cause the flow controller to 59 * stop driving reset. The CPU will remain in reset because the 60 * clock and reset block is now driving reset. 61 */ 62 flowctrl_write_cpu_halt(cpu, 0); 63 64 tegra_enable_cpu_clock(cpu); 65 flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */ 66 tegra_cpu_out_of_reset(cpu); 67 return 0; 68 } 69 70 static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle) 71 { 72 int ret; 73 unsigned long timeout; 74 75 cpu = cpu_logical_map(cpu); 76 tegra_put_cpu_in_reset(cpu); 77 flowctrl_write_cpu_halt(cpu, 0); 78 79 /* 80 * The power up sequence of cold boot CPU and warm boot CPU 81 * was different. 82 * 83 * For warm boot CPU that was resumed from CPU hotplug, the 84 * power will be resumed automatically after un-halting the 85 * flow controller of the warm boot CPU. We need to wait for 86 * the confirmation that the CPU is powered then removing 87 * the IO clamps. 88 * For cold boot CPU, do not wait. After the cold boot CPU be 89 * booted, it will run to tegra_secondary_init() and set 90 * tegra_cpu_init_mask which influences what tegra30_boot_secondary() 91 * next time around. 92 */ 93 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) { 94 timeout = jiffies + msecs_to_jiffies(50); 95 do { 96 if (tegra_pmc_cpu_is_powered(cpu)) 97 goto remove_clamps; 98 udelay(10); 99 } while (time_before(jiffies, timeout)); 100 } 101 102 /* 103 * The power status of the cold boot CPU is power gated as 104 * default. To power up the cold boot CPU, the power should 105 * be un-gated by un-toggling the power gate register 106 * manually. 107 */ 108 ret = tegra_pmc_cpu_power_on(cpu); 109 if (ret) 110 return ret; 111 112 remove_clamps: 113 /* CPU partition is powered. Enable the CPU clock. */ 114 tegra_enable_cpu_clock(cpu); 115 udelay(10); 116 117 /* Remove I/O clamps. */ 118 ret = tegra_pmc_cpu_remove_clamping(cpu); 119 if (ret) 120 return ret; 121 122 udelay(10); 123 124 flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */ 125 tegra_cpu_out_of_reset(cpu); 126 return 0; 127 } 128 129 static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle) 130 { 131 int ret = 0; 132 133 cpu = cpu_logical_map(cpu); 134 135 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) { 136 /* 137 * Warm boot flow 138 * The flow controller in charge of the power state and 139 * control for each CPU. 140 */ 141 /* set SCLK as event trigger for flow controller */ 142 flowctrl_write_cpu_csr(cpu, 1); 143 flowctrl_write_cpu_halt(cpu, 144 FLOW_CTRL_WAITEVENT | FLOW_CTRL_SCLK_RESUME); 145 } else { 146 /* 147 * Cold boot flow 148 * The CPU is powered up by toggling PMC directly. It will 149 * also initial power state in flow controller. After that, 150 * the CPU's power state is maintained by flow controller. 151 */ 152 ret = tegra_pmc_cpu_power_on(cpu); 153 } 154 155 return ret; 156 } 157 158 static int tegra_boot_secondary(unsigned int cpu, 159 struct task_struct *idle) 160 { 161 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20) 162 return tegra20_boot_secondary(cpu, idle); 163 if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30) 164 return tegra30_boot_secondary(cpu, idle); 165 if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114) 166 return tegra114_boot_secondary(cpu, idle); 167 if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124) 168 return tegra114_boot_secondary(cpu, idle); 169 170 return -EINVAL; 171 } 172 173 static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) 174 { 175 /* Always mark the boot CPU (CPU0) as initialized. */ 176 cpumask_set_cpu(0, &tegra_cpu_init_mask); 177 178 if (scu_a9_has_base()) 179 scu_enable(IO_ADDRESS(scu_a9_get_base())); 180 } 181 182 const struct smp_operations tegra_smp_ops __initconst = { 183 .smp_prepare_cpus = tegra_smp_prepare_cpus, 184 .smp_secondary_init = tegra_secondary_init, 185 .smp_boot_secondary = tegra_boot_secondary, 186 #ifdef CONFIG_HOTPLUG_CPU 187 .cpu_kill = tegra_cpu_kill, 188 .cpu_die = tegra_cpu_die, 189 #endif 190 }; 191
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.