Merge linux-block/for-4.3/core into md/for-linux
[deliverable/linux.git] / arch / arm / mach-uniphier / platsmp.c
1 /*
2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15 #include <linux/sizes.h>
16 #include <linux/compiler.h>
17 #include <linux/init.h>
18 #include <linux/io.h>
19 #include <linux/regmap.h>
20 #include <linux/mfd/syscon.h>
21 #include <asm/smp.h>
22 #include <asm/smp_scu.h>
23
24 static struct regmap *sbcm_regmap;
25
26 static void __init uniphier_smp_prepare_cpus(unsigned int max_cpus)
27 {
28 static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
29 unsigned long scu_base_phys = 0;
30 void __iomem *scu_base;
31
32 sbcm_regmap = syscon_regmap_lookup_by_compatible(
33 "socionext,uniphier-system-bus-controller-misc");
34 if (IS_ERR(sbcm_regmap)) {
35 pr_err("failed to regmap system-bus-controller-misc\n");
36 goto err;
37 }
38
39 if (scu_a9_has_base())
40 scu_base_phys = scu_a9_get_base();
41
42 if (!scu_base_phys) {
43 pr_err("failed to get scu base\n");
44 goto err;
45 }
46
47 scu_base = ioremap(scu_base_phys, SZ_128);
48 if (!scu_base) {
49 pr_err("failed to remap scu base (0x%08lx)\n", scu_base_phys);
50 goto err;
51 }
52
53 scu_enable(scu_base);
54 iounmap(scu_base);
55
56 return;
57 err:
58 pr_warn("disabling SMP\n");
59 init_cpu_present(&only_cpu_0);
60 sbcm_regmap = NULL;
61 }
62
63 static int uniphier_boot_secondary(unsigned int cpu,
64 struct task_struct *idle)
65 {
66 int ret;
67
68 if (!sbcm_regmap)
69 return -ENODEV;
70
71 ret = regmap_write(sbcm_regmap, 0x1208,
72 virt_to_phys(secondary_startup));
73 if (!ret)
74 asm("sev"); /* wake up secondary CPU */
75
76 return ret;
77 }
78
79 struct smp_operations uniphier_smp_ops __initdata = {
80 .smp_prepare_cpus = uniphier_smp_prepare_cpus,
81 .smp_boot_secondary = uniphier_boot_secondary,
82 };
83 CPU_METHOD_OF_DECLARE(uniphier_smp, "socionext,uniphier-smp",
84 &uniphier_smp_ops);
This page took 0.048654 seconds and 5 git commands to generate.