0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/clk/tegra.h>
0013 #include <linux/delay.h>
0014 #include <linux/device.h>
0015 #include <linux/errno.h>
0016 #include <linux/init.h>
0017 #include <linux/io.h>
0018 #include <linux/jiffies.h>
0019 #include <linux/smp.h>
0020
0021 #include <soc/tegra/flowctrl.h>
0022 #include <soc/tegra/fuse.h>
0023 #include <soc/tegra/pmc.h>
0024
0025 #include <asm/cacheflush.h>
0026 #include <asm/mach-types.h>
0027 #include <asm/smp_plat.h>
0028 #include <asm/smp_scu.h>
0029
0030 #include "common.h"
0031 #include "iomap.h"
0032 #include "reset.h"
0033
0034 static cpumask_t tegra_cpu_init_mask;
0035
0036 static void tegra_secondary_init(unsigned int cpu)
0037 {
0038 cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
0039 }
0040
0041
0042 static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
0043 {
0044 cpu = cpu_logical_map(cpu);
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 tegra_put_cpu_in_reset(cpu);
0055
0056
0057
0058
0059
0060
0061
0062 flowctrl_write_cpu_halt(cpu, 0);
0063
0064 tegra_enable_cpu_clock(cpu);
0065 flowctrl_write_cpu_csr(cpu, 0);
0066 tegra_cpu_out_of_reset(cpu);
0067 return 0;
0068 }
0069
0070 static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
0071 {
0072 int ret;
0073 unsigned long timeout;
0074
0075 cpu = cpu_logical_map(cpu);
0076 tegra_put_cpu_in_reset(cpu);
0077 flowctrl_write_cpu_halt(cpu, 0);
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
0094 timeout = jiffies + msecs_to_jiffies(50);
0095 do {
0096 if (tegra_pmc_cpu_is_powered(cpu))
0097 goto remove_clamps;
0098 udelay(10);
0099 } while (time_before(jiffies, timeout));
0100 }
0101
0102
0103
0104
0105
0106
0107
0108 ret = tegra_pmc_cpu_power_on(cpu);
0109 if (ret)
0110 return ret;
0111
0112 remove_clamps:
0113
0114 tegra_enable_cpu_clock(cpu);
0115 udelay(10);
0116
0117
0118 ret = tegra_pmc_cpu_remove_clamping(cpu);
0119 if (ret)
0120 return ret;
0121
0122 udelay(10);
0123
0124 flowctrl_write_cpu_csr(cpu, 0);
0125 tegra_cpu_out_of_reset(cpu);
0126 return 0;
0127 }
0128
0129 static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
0130 {
0131 int ret = 0;
0132
0133 cpu = cpu_logical_map(cpu);
0134
0135 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
0136
0137
0138
0139
0140
0141
0142 flowctrl_write_cpu_csr(cpu, 1);
0143 flowctrl_write_cpu_halt(cpu,
0144 FLOW_CTRL_WAITEVENT | FLOW_CTRL_SCLK_RESUME);
0145 } else {
0146
0147
0148
0149
0150
0151
0152 ret = tegra_pmc_cpu_power_on(cpu);
0153 }
0154
0155 return ret;
0156 }
0157
0158 static int tegra_boot_secondary(unsigned int cpu,
0159 struct task_struct *idle)
0160 {
0161 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
0162 return tegra20_boot_secondary(cpu, idle);
0163 if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
0164 return tegra30_boot_secondary(cpu, idle);
0165 if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
0166 return tegra114_boot_secondary(cpu, idle);
0167 if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
0168 return tegra114_boot_secondary(cpu, idle);
0169
0170 return -EINVAL;
0171 }
0172
0173 static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
0174 {
0175
0176 cpumask_set_cpu(0, &tegra_cpu_init_mask);
0177
0178 if (scu_a9_has_base())
0179 scu_enable(IO_ADDRESS(scu_a9_get_base()));
0180 }
0181
0182 const struct smp_operations tegra_smp_ops __initconst = {
0183 .smp_prepare_cpus = tegra_smp_prepare_cpus,
0184 .smp_secondary_init = tegra_secondary_init,
0185 .smp_boot_secondary = tegra_boot_secondary,
0186 #ifdef CONFIG_HOTPLUG_CPU
0187 .cpu_kill = tegra_cpu_kill,
0188 .cpu_die = tegra_cpu_die,
0189 #endif
0190 };