ARM: uniphier: add a command to find the first MMC (non-SD) device
[oweals/u-boot.git] / arch / arm / mach-uniphier / lowlevel_init.S
1 /*
2  * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <config.h>
8 #include <linux/linkage.h>
9 #include <linux/sizes.h>
10 #include <asm/system.h>
11
12 #include "ssc-regs.h"
13
14 ENTRY(lowlevel_init)
15         mov     r8, lr                  @ persevere link reg across call
16
17         /*
18          * The UniPhier Boot ROM loads SPL code to the L2 cache.
19          * But CPUs can only do instruction fetch now because start.S has
20          * cleared C and M bits.
21          * First we need to turn on MMU and Dcache again to get back
22          * data access to L2.
23          */
24         mrc     p15, 0, r0, c1, c0, 0   @ SCTLR (System Control Register)
25         orr     r0, r0, #(CR_C | CR_M)  @ enable MMU and Dcache
26         mcr     p15, 0, r0, c1, c0, 0
27
28 #ifdef CONFIG_DEBUG_LL
29         bl      debug_ll_init
30 #endif
31
32         bl      setup_init_ram          @ RAM area for stack and page talbe
33
34         /*
35          * Now we are using the page table embedded in the Boot ROM.
36          * It is not handy since it is not a straight mapped table for sLD3.
37          * Also, the access to the external bus is prohibited.  What we need
38          * to do next is to create a page table and switch over to it.
39          */
40         bl      create_page_table
41         bl      v7_flush_dcache_all
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         mov     lr, r8                  @ restore link
51         mov     pc, lr                  @ back to my caller
52 ENDPROC(lowlevel_init)
53
54 ENTRY(enable_mmu)
55         mrc     p15, 0, r0, c2, c0, 2   @ TTBCR (Translation Table Base Control Register)
56         bic     r0, r0, #0x37
57         orr     r0, r0, #0x20           @ disable TTBR1
58         mcr     p15, 0, r0, c2, c0, 2
59
60         orr     r0, r12, #0x8           @ Outer Cacheability for table walks: WBWA
61         mcr     p15, 0, r0, c2, c0, 0   @ TTBR0
62
63         mov     r0, #0
64         mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLBs
65
66         mov     r0, #-1                 @ manager for all domains (No permission check)
67         mcr     p15, 0, r0, c3, c0, 0   @ DACR (Domain Access Control Register)
68
69         dsb
70         isb
71         /*
72          * MMU on:
73          * TLBs was already invalidated in "../start.S"
74          * So, we don't need to invalidate it here.
75          */
76         mrc     p15, 0, r0, c1, c0, 0   @ SCTLR (System Control Register)
77         orr     r0, r0, #(CR_C | CR_M)  @ MMU and Dcache enable
78         mcr     p15, 0, r0, c1, c0, 0
79
80         mov     pc, lr
81 ENDPROC(enable_mmu)
82
83 /*
84  * For PH1-Pro4 or older SoCs, the size of WAY is 32KB.
85  * It is large enough for tmp RAM.
86  */
87 #define BOOT_RAM_SIZE   (SZ_32K)
88 #define BOOT_RAM_BASE   ((CONFIG_SPL_STACK) - (BOOT_RAM_SIZE))
89 #define BOOT_WAY_BITS   (0x00000100)   /* way 8 */
90
91 ENTRY(setup_init_ram)
92         /*
93          * Touch to zero for the boot way
94          */
95 0:
96         /*
97          * set SSCOQM, SSCOQAD, SSCOQSZ, SSCOQWN in this order
98          */
99         ldr     r0, = 0x00408006        @ touch to zero with address range
100         ldr     r1, = SSCOQM
101         str     r0, [r1]
102         ldr     r0, = BOOT_RAM_BASE
103         ldr     r1, = SSCOQAD
104         str     r0, [r1]
105         ldr     r0, = BOOT_RAM_SIZE
106         ldr     r1, = SSCOQSZ
107         str     r0, [r1]
108         ldr     r0, = BOOT_WAY_BITS
109         ldr     r1, = SSCOQWN
110         str     r0, [r1]
111         ldr     r1, = SSCOPPQSEF
112         ldr     r0, [r1]
113         cmp     r0, #0                  @ check if the command is successfully set
114         bne     0b                      @ try again if an error occurs
115
116         ldr     r1, = SSCOLPQS
117 1:
118         ldr     r0, [r1]
119         cmp     r0, #0x4
120         bne     1b                      @ wait until the operation is completed
121         str     r0, [r1]                @ clear the complete notification flag
122
123         mov     pc, lr
124 ENDPROC(setup_init_ram)
125
126 #define DEVICE  0x00002002 /* Non-shareable Device */
127 #define NORMAL  0x0000000e /* Normal Memory Write-Back, No Write-Allocate */
128
129 ENTRY(create_page_table)
130         ldr     r0, = DEVICE
131         ldr     r1, = BOOT_RAM_BASE
132         mov     r12, r1                 @ r12 is preserved during D-cache flush
133 0:      str     r0, [r1], #4            @ specify all the sections as Device
134         adds    r0, r0, #0x00100000
135         bcc     0b
136
137         ldr     r0, = NORMAL
138         str     r0, [r12]               @ mark the first section as Normal
139         add     r0, r0, #0x00100000
140         str     r0, [r12, #4]           @ mark the second section as Normal
141         mov     pc, lr
142 ENDPROC(create_page_table)
143
144 /* We don't use Thumb instructions for now */
145 #define ARM(x...)       x
146 #define THUMB(x...)
147
148 /*
149  *      v7_flush_dcache_all()
150  *
151  *      Flush the whole D-cache.
152  *
153  *      Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
154  *
155  *      - mm    - mm_struct describing address space
156  *
157  *      Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4
158  */
159 ENTRY(v7_flush_dcache_all)
160         dmb                                     @ ensure ordering with previous memory accesses
161         mrc     p15, 1, r0, c0, c0, 1           @ read clidr
162         mov     r3, r0, lsr #23                 @ move LoC into position
163         ands    r3, r3, #7 << 1                 @ extract LoC*2 from clidr
164         beq     finished                        @ if loc is 0, then no need to clean
165 start_flush_levels:
166         mov     r10, #0                         @ start clean at cache level 0
167 flush_levels:
168         add     r2, r10, r10, lsr #1            @ work out 3x current cache level
169         mov     r1, r0, lsr r2                  @ extract cache type bits from clidr
170         and     r1, r1, #7                      @ mask of the bits for current cache only
171         cmp     r1, #2                          @ see what cache we have at this level
172         blt     skip                            @ skip if no cache, or just i-cache
173         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
174         isb                                     @ isb to sych the new cssr&csidr
175         mrc     p15, 1, r1, c0, c0, 0           @ read the new csidr
176         and     r2, r1, #7                      @ extract the length of the cache lines
177         add     r2, r2, #4                      @ add 4 (line length offset)
178         movw    r4, #0x3ff
179         ands    r4, r4, r1, lsr #3              @ find maximum number on the way size
180         clz     r5, r4                          @ find bit position of way size increment
181         movw    r7, #0x7fff
182         ands    r7, r7, r1, lsr #13             @ extract max number of the index size
183 loop1:
184         mov     r9, r7                          @ create working copy of max index
185 loop2:
186  ARM(   orr     r11, r10, r4, lsl r5    )       @ factor way and cache number into r11
187  THUMB( lsl     r6, r4, r5              )
188  THUMB( orr     r11, r10, r6            )       @ factor way and cache number into r11
189  ARM(   orr     r11, r11, r9, lsl r2    )       @ factor index number into r11
190  THUMB( lsl     r6, r9, r2              )
191  THUMB( orr     r11, r11, r6            )       @ factor index number into r11
192         mcr     p15, 0, r11, c7, c14, 2         @ clean & invalidate by set/way
193         subs    r9, r9, #1                      @ decrement the index
194         bge     loop2
195         subs    r4, r4, #1                      @ decrement the way
196         bge     loop1
197 skip:
198         add     r10, r10, #2                    @ increment cache number
199         cmp     r3, r10
200         bgt     flush_levels
201 finished:
202         mov     r10, #0                         @ swith back to cache level 0
203         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
204         dsb     st
205         isb
206         mov     pc, lr
207 ENDPROC(v7_flush_dcache_all)