platsmp.c (5154B)
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 34static cpumask_t tegra_cpu_init_mask; 35 36static void tegra_secondary_init(unsigned int cpu) 37{ 38 cpumask_set_cpu(cpu, &tegra_cpu_init_mask); 39} 40 41 42static 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 70static 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 112remove_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 129static 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 158static 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 173static 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 182const 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};