diff options
Diffstat (limited to 'arch/arm/mach-socfpga/platsmp.c')
-rw-r--r-- | arch/arm/mach-socfpga/platsmp.c | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c index 79c5336c569f..c6f1df89f9af 100644 --- a/arch/arm/mach-socfpga/platsmp.c +++ b/arch/arm/mach-socfpga/platsmp.c | |||
@@ -54,32 +54,43 @@ static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | 56 | ||
57 | /* | 57 | static int socfpga_a10_boot_secondary(unsigned int cpu, struct task_struct *idle) |
58 | * Initialise the CPU possible map early - this describes the CPUs | ||
59 | * which may be present or become present in the system. | ||
60 | */ | ||
61 | static void __init socfpga_smp_init_cpus(void) | ||
62 | { | 58 | { |
63 | unsigned int i, ncores; | 59 | int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; |
64 | 60 | ||
65 | ncores = scu_get_core_count(socfpga_scu_base_addr); | 61 | if (socfpga_cpu1start_addr) { |
62 | writel(RSTMGR_MPUMODRST_CPU1, rst_manager_base_addr + | ||
63 | SOCFPGA_A10_RSTMGR_MODMPURST); | ||
64 | memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); | ||
66 | 65 | ||
67 | for (i = 0; i < ncores; i++) | 66 | writel(virt_to_phys(secondary_startup), |
68 | set_cpu_possible(i, true); | 67 | sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff)); |
69 | 68 | ||
70 | /* sanity check */ | 69 | flush_cache_all(); |
71 | if (ncores > num_possible_cpus()) { | 70 | smp_wmb(); |
72 | pr_warn("socfpga: no. of cores (%d) greater than configured" | 71 | outer_clean_range(0, trampoline_size); |
73 | "maximum of %d - clipping\n", ncores, num_possible_cpus()); | 72 | |
74 | ncores = num_possible_cpus(); | 73 | /* This will release CPU #1 out of reset. */ |
74 | writel(0, rst_manager_base_addr + SOCFPGA_A10_RSTMGR_MODMPURST); | ||
75 | } | 75 | } |
76 | 76 | ||
77 | for (i = 0; i < ncores; i++) | 77 | return 0; |
78 | set_cpu_possible(i, true); | ||
79 | } | 78 | } |
80 | 79 | ||
81 | static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus) | 80 | static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus) |
82 | { | 81 | { |
82 | struct device_node *np; | ||
83 | void __iomem *socfpga_scu_base_addr; | ||
84 | |||
85 | np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); | ||
86 | if (!np) { | ||
87 | pr_err("%s: missing scu\n", __func__); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | socfpga_scu_base_addr = of_iomap(np, 0); | ||
92 | if (!socfpga_scu_base_addr) | ||
93 | return; | ||
83 | scu_enable(socfpga_scu_base_addr); | 94 | scu_enable(socfpga_scu_base_addr); |
84 | } | 95 | } |
85 | 96 | ||
@@ -95,11 +106,21 @@ static void socfpga_cpu_die(unsigned int cpu) | |||
95 | cpu_do_idle(); | 106 | cpu_do_idle(); |
96 | } | 107 | } |
97 | 108 | ||
98 | struct smp_operations socfpga_smp_ops __initdata = { | 109 | static struct smp_operations socfpga_smp_ops __initdata = { |
99 | .smp_init_cpus = socfpga_smp_init_cpus, | ||
100 | .smp_prepare_cpus = socfpga_smp_prepare_cpus, | 110 | .smp_prepare_cpus = socfpga_smp_prepare_cpus, |
101 | .smp_boot_secondary = socfpga_boot_secondary, | 111 | .smp_boot_secondary = socfpga_boot_secondary, |
102 | #ifdef CONFIG_HOTPLUG_CPU | 112 | #ifdef CONFIG_HOTPLUG_CPU |
103 | .cpu_die = socfpga_cpu_die, | 113 | .cpu_die = socfpga_cpu_die, |
104 | #endif | 114 | #endif |
105 | }; | 115 | }; |
116 | |||
117 | static struct smp_operations socfpga_a10_smp_ops __initdata = { | ||
118 | .smp_prepare_cpus = socfpga_smp_prepare_cpus, | ||
119 | .smp_boot_secondary = socfpga_a10_boot_secondary, | ||
120 | #ifdef CONFIG_HOTPLUG_CPU | ||
121 | .cpu_die = socfpga_cpu_die, | ||
122 | #endif | ||
123 | }; | ||
124 | |||
125 | CPU_METHOD_OF_DECLARE(socfpga_smp, "altr,socfpga-smp", &socfpga_smp_ops); | ||
126 | CPU_METHOD_OF_DECLARE(socfpga_a10_smp, "altr,socfpga-a10-smp", &socfpga_a10_smp_ops); | ||