]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-uniphier/platsmp.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[karo-tx-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);