ARM: UniPhier: optimize kicking secondary CPUs code
[platform/kernel/u-boot.git] / arch / arm / mach-uniphier / lowlevel_init.S
1 /*
2  * Copyright (C) 2012-2015 Panasonic Corporation
3  * Copyright (C) 2015      Socionext Inc.
4  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <config.h>
10 #include <linux/linkage.h>
11 #include <linux/sizes.h>
12 #include <asm/system.h>
13 #include <mach/led.h>
14 #include <mach/arm-mpcore.h>
15 #include <mach/sbc-regs.h>
16 #include <mach/ssc-regs.h>
17
18 ENTRY(lowlevel_init)
19         mov     r8, lr                  @ persevere link reg across call
20
21         /*
22          * The UniPhier Boot ROM loads SPL code to the L2 cache.
23          * But CPUs can only do instruction fetch now because start.S has
24          * cleared C and M bits.
25          * First we need to turn on MMU and Dcache again to get back
26          * data access to L2.
27          */
28         mrc     p15, 0, r0, c1, c0, 0   @ SCTLR (System Control Register)
29         orr     r0, r0, #(CR_C | CR_M)  @ enable MMU and Dcache
30         mcr     p15, 0, r0, c1, c0, 0
31
32 #ifdef CONFIG_DEBUG_LL
33         bl      setup_lowlevel_debug
34 #endif
35
36         /*
37          * Now we are using the page table embedded in the Boot ROM.
38          * It is not handy since it is not a straight mapped table for sLD3.
39          * What we need to do next is to switch over to the page table in SPL.
40          */
41         ldr     r3, =init_page_table    @ page table must be 16KB aligned
42
43         /* Disable MMU and Dcache before switching Page Table */
44         mrc     p15, 0, r0, c1, c0, 0   @ SCTLR (System Control Register)
45         bic     r0, r0, #(CR_C | CR_M)  @ disable MMU and Dcache
46         mcr     p15, 0, r0, c1, c0, 0
47
48         bl      enable_mmu
49
50 #ifdef CONFIG_UNIPHIER_SMP
51 secondary_startup:
52         /*
53          * Entry point for secondary CPUs
54          *
55          * The Boot ROM has already enabled MMU for the secondary CPUs as well
56          * as for the primary one.  The MMU table embedded in the Boot ROM
57          * prohibits the DRAM access, so it is impossible to bring the
58          * secondary CPUs into DRAM directly.  They must jump here into SPL,
59          * which is run on L2 cache.
60          *
61          * Boot Sequence
62          *  [primary CPU]                    [secondary CPUs]
63          *  start from Boot ROM             start from Boot ROM
64          *     jump to SPL                    sleep in Boot ROM
65          *  kick secondaries   ---(sev)--->    jump to SPL
66          *  jump to U-Boot main               sleep in SPL
67          *  jump to Linux
68          *  kick secondaries   ---(sev)--->    jump to Linux
69          */
70         /*
71          * ACTLR (Auxiliary Control Register) for Cortex-A9
72          * bit[9]  Parity on
73          * bit[8]  Alloc in one way
74          * bit[7]  EXCL (Exclusive cache bit)
75          * bit[6]  SMP
76          * bit[3]  Write full line of zeros mode
77          * bit[2]  L1 prefetch enable
78          * bit[1]  L2 prefetch enable
79          * bit[0]  FW (Cache and TLB maintenance broadcast)
80          */
81         mrc     p15, 0, r0, c1, c0, 1   @ ACTLR (Auxiliary Control Register)
82         orr     r0, r0, #0x41           @ enable SMP, FW bit
83         mcr     p15, 0, r0, c1, c0, 1
84
85         /* branch by CPU ID */
86         mrc     p15, 0, r0, c0, c0, 5   @ MPIDR (Multiprocessor Affinity Register)
87         and     r0, r0, #0x3
88         cmp     r0, #0x0
89         beq     primary_cpu
90         /* only for secondary CPUs */
91         ldr     r1, =ROM_BOOT_ROMRSV2   @ The last data access to L2 cache
92         mrc     p15, 0, r0, c1, c0, 0   @ SCTLR (System Control Register)
93         orr     r0, r0, #CR_I           @ Enable ICache
94         bic     r0, r0, #(CR_C | CR_M)  @ MMU and Dcache must be disabled
95         mcr     p15, 0, r0, c1, c0, 0   @ before jumping to Linux
96         mov     r0, #0
97         str     r0, [r1]
98         b       1f
99         /*
100          * L2 cache is shared among all the CPUs and it might be disabled by
101          * the primary one.  Before that, the following 5 lines must be cached
102          * on the Icaches of the secondary CPUs.
103          */
104 0:      wfe                             @ kicked by Linux
105 1:      ldr     r0, [r1]
106         cmp     r0, #0
107         bxne    r0                      @ r0: Linux entry for secondary CPUs
108         b       0b
109 primary_cpu:
110         ldr     r1, =ROM_BOOT_ROMRSV2
111         ldr     r0, =secondary_startup
112         str     r0, [r1]
113         ldr     r0, [r1]                @ make sure str is complete before sev
114         sev                             @ kick the secondary CPU
115         mrc     p15, 4, r1, c15, c0, 0  @ Configuration Base Address Register
116         bfc     r1, #0, #13             @ clear bit 12-0
117         mov     r0, #-1
118         str     r0, [r1, #SCU_INV_ALL]  @ SCU Invalidate All Register
119         mov     r0, #1                  @ SCU enable
120         str     r0, [r1, #SCU_CTRL]     @ SCU Control Register
121 #endif
122
123         bl      setup_init_ram          @ RAM area for temporary stack pointer
124
125         mov     lr, r8                  @ restore link
126         mov     pc, lr                  @ back to my caller
127 ENDPROC(lowlevel_init)
128
129 ENTRY(enable_mmu)
130         mrc     p15, 0, r0, c2, c0, 2   @ TTBCR (Translation Table Base Control Register)
131         bic     r0, r0, #0x37
132         orr     r0, r0, #0x20           @ disable TTBR1
133         mcr     p15, 0, r0, c2, c0, 2
134
135         orr     r0, r3, #0x8            @ Outer Cacheability for table walks: WBWA
136         mcr     p15, 0, r0, c2, c0, 0   @ TTBR0
137
138         mov     r0, #0
139         mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLBs
140
141         mov     r0, #-1                 @ manager for all domains (No permission check)
142         mcr     p15, 0, r0, c3, c0, 0   @ DACR (Domain Access Control Register)
143
144         dsb
145         isb
146         /*
147          * MMU on:
148          * TLBs was already invalidated in "../start.S"
149          * So, we don't need to invalidate it here.
150          */
151         mrc     p15, 0, r0, c1, c0, 0   @ SCTLR (System Control Register)
152         orr     r0, r0, #(CR_C | CR_M)  @ MMU and Dcache enable
153         mcr     p15, 0, r0, c1, c0, 0
154
155         mov     pc, lr
156 ENDPROC(enable_mmu)
157
158 /*
159  * For PH1-Pro4 or older SoCs, the size of WAY is 32KB.
160  * It is large enough for tmp RAM.
161  */
162 #define BOOT_RAM_SIZE    (SZ_32K)
163 #define BOOT_WAY_BITS    (0x00000100)   /* way 8 */
164
165 ENTRY(setup_init_ram)
166         /*
167          * Touch to zero for the boot way
168          */
169 0:
170         /*
171          * set SSCOQM, SSCOQAD, SSCOQSZ, SSCOQWN in this order
172          */
173         ldr     r0, = 0x00408006        @ touch to zero with address range
174         ldr     r1, = SSCOQM
175         str     r0, [r1]
176         ldr     r0, = (CONFIG_SPL_STACK - BOOT_RAM_SIZE)        @ base address
177         ldr     r1, = SSCOQAD
178         str     r0, [r1]
179         ldr     r0, = BOOT_RAM_SIZE
180         ldr     r1, = SSCOQSZ
181         str     r0, [r1]
182         ldr     r0, = BOOT_WAY_BITS
183         ldr     r1, = SSCOQWN
184         str     r0, [r1]
185         ldr     r1, = SSCOPPQSEF
186         ldr     r0, [r1]
187         cmp     r0, #0                  @ check if the command is successfully set
188         bne     0b                      @ try again if an error occurs
189
190         ldr     r1, = SSCOLPQS
191 1:
192         ldr     r0, [r1]
193         cmp     r0, #0x4
194         bne     1b                      @ wait until the operation is completed
195         str     r0, [r1]                @ clear the complete notification flag
196
197         mov     pc, lr
198 ENDPROC(setup_init_ram)