Merge branch 'master' of http://git.denx.de/u-boot-mmc
[oweals/u-boot.git] / arch / arm / mach-uniphier / arm32 / lowlevel_init.S
1 /*
2  * Copyright (C) 2012-2015 Panasonic Corporation
3  * Copyright (C) 2015-2016 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
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         bl      setup_init_ram          @ RAM area for stack and page table
29
30         /*
31          * Now we are using the page table embedded in the Boot ROM.
32          * It is not handy since it is not a straight mapped table for sLD3.
33          * Also, the access to the external bus is prohibited.  What we need
34          * to do next is to create a page table and switch over to it.
35          */
36         bl      create_page_table
37         bl      __v7_flush_dcache_all
38
39         /* Disable MMU and Dcache before switching Page Table */
40         mrc     p15, 0, r0, c1, c0, 0   @ SCTLR (System Control Register)
41         bic     r0, r0, #(CR_C | CR_M)  @ disable MMU and Dcache
42         mcr     p15, 0, r0, c1, c0, 0
43
44         bl      enable_mmu
45
46 #ifdef CONFIG_DEBUG_LL
47         bl      debug_ll_init
48 #endif
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_RAM_WAYS   (0x00000100)    @ way 8
90
91 #define SSCO_BASE               0x506c0000
92 #define SSCOPE                  0x244
93 #define SSCOQM                  0x248
94 #define SSCOQAD                 0x24c
95 #define SSCOQSZ                 0x250
96 #define SSCOQWN                 0x258
97 #define SSCOPPQSEF              0x25c
98 #define SSCOLPQS                0x260
99
100 ENTRY(setup_init_ram)
101         ldr     r1, = SSCO_BASE
102         mrc     p15, 0, r0, c2, c0, 0   @ TTBR0
103         ldr     r0, [r0, #0x400]        @ entry for virtual address 0x100*****
104         bfc     r0, #0, #20
105         cmp     r0, #0x50000000         @ is sLD3 page table?
106         biceq   r1, r1, #0xc0000000     @ sLD3 ROM maps 0x5******* to 0x1*******
107
108         /* Touch to zero for the boot way */
109 0:      ldr     r0, = 0x00408006        @ touch to zero with address range
110         str     r0, [r1, #SSCOQM]
111         ldr     r0, = BOOT_RAM_BASE
112         str     r0, [r1, #SSCOQAD]
113         ldr     r0, = BOOT_RAM_SIZE
114         str     r0, [r1, #SSCOQSZ]
115         ldr     r0, = BOOT_RAM_WAYS
116         str     r0, [r1, #SSCOQWN]
117         ldr     r0, [r1, #SSCOPPQSEF]
118         cmp     r0, #0                  @ check if the command is successfully set
119         bne     0b                      @ try again if an error occurs
120
121 1:      ldr     r0, [r1, #SSCOLPQS]
122         cmp     r0, #0x4
123         bne     1b                      @ wait until the operation is completed
124         str     r0, [r1, #SSCOLPQS]     @ clear the complete notification flag
125
126         mov     pc, lr
127 ENDPROC(setup_init_ram)
128
129 #define DEVICE  0x00002002 /* Non-shareable Device */
130 #define NORMAL  0x0000000e /* Normal Memory Write-Back, No Write-Allocate */
131
132 ENTRY(create_page_table)
133         ldr     r0, = DEVICE
134         ldr     r1, = BOOT_RAM_BASE
135         mov     r12, r1                 @ r12 is preserved during D-cache flush
136 0:      str     r0, [r1], #4            @ specify all the sections as Device
137         adds    r0, r0, #0x00100000
138         bcc     0b
139
140         ldr     r0, = NORMAL
141         str     r0, [r12]               @ mark the first section as Normal
142         add     r0, r0, #0x00100000
143         str     r0, [r12, #4]           @ mark the second section as Normal
144         mov     pc, lr
145 ENDPROC(create_page_table)