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