1 | /* SPDX-License-Identifier: GPL-2.0 |
2 | * |
3 | * SMP support for R-Mobile / SH-Mobile |
4 | * |
5 | * Copyright (C) 2010 Magnus Damm |
6 | * Copyright (C) 2010 Takashi Yoshii |
7 | * |
8 | * Based on vexpress, Copyright (c) 2003 ARM Limited, All Rights Reserved |
9 | */ |
10 | #include <linux/init.h> |
11 | #include <linux/linkage.h> |
12 | #include <linux/threads.h> |
13 | #include <asm/assembler.h> |
14 | #include <asm/page.h> |
15 | |
16 | #define SCTLR_MMU 0x01 |
17 | #define BOOTROM_ADDRESS 0xE6340000 |
18 | #define RWTCSRA_ADDRESS 0xE6020004 |
19 | #define RWTCSRA_WOVF 0x10 |
20 | |
21 | /* |
22 | * Reset vector for secondary CPUs. |
23 | * This will be mapped at address 0 by SBAR register. |
24 | * We need _long_ jump to the physical address. |
25 | */ |
26 | .arm |
27 | .align 12 |
28 | ENTRY(shmobile_boot_vector) |
29 | ldr r1, 1f |
30 | bx r1 |
31 | |
32 | ENDPROC(shmobile_boot_vector) |
33 | |
34 | .align 2 |
35 | .globl shmobile_boot_fn |
36 | shmobile_boot_fn: |
37 | 1: .space 4 |
38 | .globl shmobile_boot_size |
39 | shmobile_boot_size: |
40 | .long . - shmobile_boot_vector |
41 | |
42 | #ifdef CONFIG_ARCH_RCAR_GEN2 |
43 | /* |
44 | * Reset vector for R-Car Gen2 and RZ/G1 secondary CPUs. |
45 | * This will be mapped at address 0 by SBAR register. |
46 | */ |
47 | ENTRY(shmobile_boot_vector_gen2) |
48 | mrc p15, 0, r0, c0, c0, 5 @ r0 = MPIDR |
49 | ldr r1, shmobile_boot_cpu_gen2 |
50 | cmp r0, r1 |
51 | bne shmobile_smp_continue_gen2 |
52 | |
53 | mrc p15, 0, r1, c1, c0, 0 @ r1 = SCTLR |
54 | and r0, r1, #SCTLR_MMU |
55 | cmp r0, #SCTLR_MMU |
56 | beq shmobile_smp_continue_gen2 |
57 | |
58 | ldr r0, rwtcsra |
59 | mov r1, #0 |
60 | ldrb r1, [r0] |
61 | and r0, r1, #RWTCSRA_WOVF |
62 | cmp r0, #RWTCSRA_WOVF |
63 | bne shmobile_smp_continue_gen2 |
64 | |
65 | ldr r0, bootrom |
66 | bx r0 |
67 | |
68 | shmobile_smp_continue_gen2: |
69 | ldr r1, shmobile_boot_fn_gen2 |
70 | bx r1 |
71 | |
72 | ENDPROC(shmobile_boot_vector_gen2) |
73 | |
74 | .align 4 |
75 | rwtcsra: |
76 | .word RWTCSRA_ADDRESS |
77 | bootrom: |
78 | .word BOOTROM_ADDRESS |
79 | .globl shmobile_boot_cpu_gen2 |
80 | shmobile_boot_cpu_gen2: |
81 | .word 0x00000000 |
82 | |
83 | .align 2 |
84 | .globl shmobile_boot_fn_gen2 |
85 | shmobile_boot_fn_gen2: |
86 | .space 4 |
87 | .globl shmobile_boot_size_gen2 |
88 | shmobile_boot_size_gen2: |
89 | .long . - shmobile_boot_vector_gen2 |
90 | #endif /* CONFIG_ARCH_RCAR_GEN2 */ |
91 | |
92 | /* |
93 | * Per-CPU SMP boot function/argument selection code based on MPIDR |
94 | */ |
95 | |
96 | ENTRY(shmobile_smp_boot) |
97 | mrc p15, 0, r1, c0, c0, 5 @ r1 = MPIDR |
98 | and r0, r1, #0xffffff @ MPIDR_HWID_BITMASK |
99 | @ r0 = cpu_logical_map() value |
100 | mov r1, #0 @ r1 = CPU index |
101 | adr r2, 1f |
102 | ldmia r2, {r5, r6, r7} |
103 | add r5, r5, r2 @ array of per-cpu mpidr values |
104 | add r6, r6, r2 @ array of per-cpu functions |
105 | add r7, r7, r2 @ array of per-cpu arguments |
106 | |
107 | shmobile_smp_boot_find_mpidr: |
108 | ldr r8, [r5, r1, lsl #2] |
109 | cmp r8, r0 |
110 | bne shmobile_smp_boot_next |
111 | |
112 | ldr r9, [r6, r1, lsl #2] |
113 | cmp r9, #0 |
114 | bne shmobile_smp_boot_found |
115 | |
116 | shmobile_smp_boot_next: |
117 | add r1, r1, #1 |
118 | cmp r1, #NR_CPUS |
119 | blo shmobile_smp_boot_find_mpidr |
120 | |
121 | b shmobile_smp_sleep |
122 | |
123 | shmobile_smp_boot_found: |
124 | ldr r0, [r7, r1, lsl #2] |
125 | ret r9 |
126 | ENDPROC(shmobile_smp_boot) |
127 | |
128 | ENTRY(shmobile_smp_sleep) |
129 | wfi |
130 | b shmobile_smp_boot |
131 | ENDPROC(shmobile_smp_sleep) |
132 | |
133 | .align 2 |
134 | 1: .long shmobile_smp_mpidr - . |
135 | .long shmobile_smp_fn - 1b |
136 | .long shmobile_smp_arg - 1b |
137 | |
138 | .bss |
139 | .globl shmobile_smp_mpidr |
140 | shmobile_smp_mpidr: |
141 | .space NR_CPUS * 4 |
142 | .globl shmobile_smp_fn |
143 | shmobile_smp_fn: |
144 | .space NR_CPUS * 4 |
145 | .globl shmobile_smp_arg |
146 | shmobile_smp_arg: |
147 | .space NR_CPUS * 4 |
148 | |