0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/delay.h>
0009 #include <linux/init.h>
0010 #include <linux/smp.h>
0011 #include <linux/io.h>
0012 #include <linux/of.h>
0013 #include <linux/of_address.h>
0014
0015 #include <asm/cacheflush.h>
0016 #include <asm/smp_scu.h>
0017 #include <asm/smp_plat.h>
0018
0019 #include "core.h"
0020
0021 static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
0022 {
0023 int trampoline_size = secondary_trampoline_end - secondary_trampoline;
0024
0025 if (socfpga_cpu1start_addr) {
0026
0027 writel(RSTMGR_MPUMODRST_CPU1,
0028 rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST);
0029
0030 memcpy(phys_to_virt(0), secondary_trampoline, trampoline_size);
0031
0032 writel(__pa_symbol(secondary_startup),
0033 sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff));
0034
0035 flush_cache_all();
0036 smp_wmb();
0037 outer_clean_range(0, trampoline_size);
0038
0039
0040 writel(0, rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST);
0041 }
0042
0043 return 0;
0044 }
0045
0046 static int socfpga_a10_boot_secondary(unsigned int cpu, struct task_struct *idle)
0047 {
0048 int trampoline_size = secondary_trampoline_end - secondary_trampoline;
0049
0050 if (socfpga_cpu1start_addr) {
0051 writel(RSTMGR_MPUMODRST_CPU1, rst_manager_base_addr +
0052 SOCFPGA_A10_RSTMGR_MODMPURST);
0053 memcpy(phys_to_virt(0), secondary_trampoline, trampoline_size);
0054
0055 writel(__pa_symbol(secondary_startup),
0056 sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff));
0057
0058 flush_cache_all();
0059 smp_wmb();
0060 outer_clean_range(0, trampoline_size);
0061
0062
0063 writel(0, rst_manager_base_addr + SOCFPGA_A10_RSTMGR_MODMPURST);
0064 }
0065
0066 return 0;
0067 }
0068
0069 static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
0070 {
0071 struct device_node *np;
0072 void __iomem *socfpga_scu_base_addr;
0073
0074 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
0075 if (!np) {
0076 pr_err("%s: missing scu\n", __func__);
0077 return;
0078 }
0079
0080 socfpga_scu_base_addr = of_iomap(np, 0);
0081 if (!socfpga_scu_base_addr)
0082 return;
0083 scu_enable(socfpga_scu_base_addr);
0084 }
0085
0086 #ifdef CONFIG_HOTPLUG_CPU
0087
0088
0089
0090
0091
0092 static void socfpga_cpu_die(unsigned int cpu)
0093 {
0094
0095 while (1)
0096 cpu_do_idle();
0097 }
0098
0099
0100
0101
0102
0103
0104
0105 static int socfpga_cpu_kill(unsigned int cpu)
0106 {
0107 return 1;
0108 }
0109 #endif
0110
0111 static const struct smp_operations socfpga_smp_ops __initconst = {
0112 .smp_prepare_cpus = socfpga_smp_prepare_cpus,
0113 .smp_boot_secondary = socfpga_boot_secondary,
0114 #ifdef CONFIG_HOTPLUG_CPU
0115 .cpu_die = socfpga_cpu_die,
0116 .cpu_kill = socfpga_cpu_kill,
0117 #endif
0118 };
0119
0120 static const struct smp_operations socfpga_a10_smp_ops __initconst = {
0121 .smp_prepare_cpus = socfpga_smp_prepare_cpus,
0122 .smp_boot_secondary = socfpga_a10_boot_secondary,
0123 #ifdef CONFIG_HOTPLUG_CPU
0124 .cpu_die = socfpga_cpu_die,
0125 .cpu_kill = socfpga_cpu_kill,
0126 #endif
0127 };
0128
0129 CPU_METHOD_OF_DECLARE(socfpga_smp, "altr,socfpga-smp", &socfpga_smp_ops);
0130 CPU_METHOD_OF_DECLARE(socfpga_a10_smp, "altr,socfpga-a10-smp", &socfpga_a10_smp_ops);