1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * SMP support for R-Mobile / SH-Mobile - r8a7779 portion |
4 | * |
5 | * Copyright (C) 2011 Renesas Solutions Corp. |
6 | * Copyright (C) 2011 Magnus Damm |
7 | */ |
8 | #include <linux/kernel.h> |
9 | #include <linux/init.h> |
10 | #include <linux/smp.h> |
11 | #include <linux/spinlock.h> |
12 | #include <linux/io.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/soc/renesas/rcar-sysc.h> |
15 | |
16 | #include <asm/cacheflush.h> |
17 | #include <asm/smp_plat.h> |
18 | #include <asm/smp_scu.h> |
19 | |
20 | #include "common.h" |
21 | #include "r8a7779.h" |
22 | |
23 | #define HPBREG_BASE 0xfe700000 |
24 | #define AVECR 0x0040 /* ARM Reset Vector Address Register */ |
25 | |
26 | #define R8A7779_SCU_BASE 0xf0000000 |
27 | |
28 | static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle) |
29 | { |
30 | int ret = -EIO; |
31 | |
32 | cpu = cpu_logical_map(cpu); |
33 | if (cpu) |
34 | ret = rcar_sysc_power_up_cpu(cpu); |
35 | |
36 | return ret; |
37 | } |
38 | |
39 | static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus) |
40 | { |
41 | void __iomem *base; |
42 | |
43 | if (!request_mem_region(0, SZ_4K, "Boot Area" )) { |
44 | pr_err("Failed to request boot area\n" ); |
45 | return; |
46 | } |
47 | |
48 | base = ioremap(HPBREG_BASE, size: 0x1000); |
49 | |
50 | /* Map the reset vector (in headsmp-scu.S, headsmp.S) */ |
51 | writel(__pa(shmobile_boot_vector), addr: base + AVECR); |
52 | |
53 | /* setup r8a7779 specific SCU bits */ |
54 | shmobile_smp_scu_prepare_cpus(R8A7779_SCU_BASE, max_cpus); |
55 | |
56 | iounmap(addr: base); |
57 | } |
58 | |
59 | #ifdef CONFIG_HOTPLUG_CPU |
60 | static int r8a7779_platform_cpu_kill(unsigned int cpu) |
61 | { |
62 | int ret = -EIO; |
63 | |
64 | cpu = cpu_logical_map(cpu); |
65 | if (cpu) |
66 | ret = rcar_sysc_power_down_cpu(cpu); |
67 | |
68 | return ret ? ret : 1; |
69 | } |
70 | |
71 | static int r8a7779_cpu_kill(unsigned int cpu) |
72 | { |
73 | if (shmobile_smp_scu_cpu_kill(cpu)) |
74 | return r8a7779_platform_cpu_kill(cpu); |
75 | |
76 | return 0; |
77 | } |
78 | #endif /* CONFIG_HOTPLUG_CPU */ |
79 | |
80 | const struct smp_operations r8a7779_smp_ops __initconst = { |
81 | .smp_prepare_cpus = r8a7779_smp_prepare_cpus, |
82 | .smp_boot_secondary = r8a7779_boot_secondary, |
83 | #ifdef CONFIG_HOTPLUG_CPU |
84 | .cpu_die = shmobile_smp_scu_cpu_die, |
85 | .cpu_kill = r8a7779_cpu_kill, |
86 | #endif |
87 | }; |
88 | |