0001
0002
0003
0004
0005 #include <linux/smp.h>
0006 #include <linux/io.h>
0007 #include <linux/of.h>
0008 #include <linux/of_address.h>
0009 #include <linux/regmap.h>
0010 #include <linux/mfd/syscon.h>
0011
0012 #include <asm/cacheflush.h>
0013 #include <asm/smp_plat.h>
0014 #include <asm/smp_scu.h>
0015
0016 #include "platsmp.h"
0017
0018 #define REALVIEW_SYS_FLAGSSET_OFFSET 0x30
0019
0020 static const struct of_device_id realview_scu_match[] = {
0021 { .compatible = "arm,arm11mp-scu", },
0022 { .compatible = "arm,cortex-a9-scu", },
0023 { .compatible = "arm,cortex-a5-scu", },
0024 { }
0025 };
0026
0027 static const struct of_device_id realview_syscon_match[] = {
0028 { .compatible = "arm,core-module-integrator", },
0029 { .compatible = "arm,realview-eb-syscon", },
0030 { .compatible = "arm,realview-pb11mp-syscon", },
0031 { .compatible = "arm,realview-pbx-syscon", },
0032 { },
0033 };
0034
0035 static void __init realview_smp_prepare_cpus(unsigned int max_cpus)
0036 {
0037 struct device_node *np;
0038 void __iomem *scu_base;
0039 struct regmap *map;
0040 unsigned int ncores;
0041 int i;
0042
0043 np = of_find_matching_node(NULL, realview_scu_match);
0044 if (!np) {
0045 pr_err("PLATSMP: No SCU base address\n");
0046 return;
0047 }
0048 scu_base = of_iomap(np, 0);
0049 of_node_put(np);
0050 if (!scu_base) {
0051 pr_err("PLATSMP: No SCU remap\n");
0052 return;
0053 }
0054
0055 scu_enable(scu_base);
0056 ncores = scu_get_core_count(scu_base);
0057 pr_info("SCU: %d cores detected\n", ncores);
0058 for (i = 0; i < ncores; i++)
0059 set_cpu_possible(i, true);
0060 iounmap(scu_base);
0061
0062
0063 np = of_find_matching_node(NULL, realview_syscon_match);
0064 if (!np) {
0065 pr_err("PLATSMP: No syscon match\n");
0066 return;
0067 }
0068 map = syscon_node_to_regmap(np);
0069 if (IS_ERR(map)) {
0070 pr_err("PLATSMP: No syscon regmap\n");
0071 return;
0072 }
0073
0074 regmap_write(map, REALVIEW_SYS_FLAGSSET_OFFSET,
0075 __pa_symbol(versatile_secondary_startup));
0076 }
0077
0078 #ifdef CONFIG_HOTPLUG_CPU
0079 static void realview_cpu_die(unsigned int cpu)
0080 {
0081 return versatile_immitation_cpu_die(cpu, 0x20);
0082 }
0083 #endif
0084
0085 static const struct smp_operations realview_dt_smp_ops __initconst = {
0086 .smp_prepare_cpus = realview_smp_prepare_cpus,
0087 .smp_secondary_init = versatile_secondary_init,
0088 .smp_boot_secondary = versatile_boot_secondary,
0089 #ifdef CONFIG_HOTPLUG_CPU
0090 .cpu_die = realview_cpu_die,
0091 #endif
0092 };
0093 CPU_METHOD_OF_DECLARE(realview_smp, "arm,realview-smp", &realview_dt_smp_ops);