summaryrefslogtreecommitdiff
path: root/arch/arm/mach-uniphier/arm32/lowlevel_init.S
blob: af5ed1c050fe610691521bdddc583169c608c266 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * Copyright (C) 2012-2015 Panasonic Corporation
 * Copyright (C) 2015-2016 Socionext Inc.
 *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <config.h>
#include <linux/linkage.h>
#include <linux/sizes.h>
#include <asm/system.h>

ENTRY(lowlevel_init)
	mov	r8, lr			@ persevere link reg across call

	/*
	 * The UniPhier Boot ROM loads SPL code to the L2 cache.
	 * But CPUs can only do instruction fetch now because start.S has
	 * cleared C and M bits.
	 * First we need to turn on MMU and Dcache again to get back
	 * data access to L2.
	 */
	mrc	p15, 0, r0, c1, c0, 0	@ SCTLR (System Control Register)
	orr	r0, r0, #(CR_C | CR_M)	@ enable MMU and Dcache
	mcr	p15, 0, r0, c1, c0, 0

	bl	setup_init_ram		@ RAM area for stack and page table

	/*
	 * Now we are using the page table embedded in the Boot ROM.
	 * It is not handy since it is not a straight mapped table for sLD3.
	 * Also, the access to the external bus is prohibited.  What we need
	 * to do next is to create a page table and switch over to it.
	 */
	bl	create_page_table
	bl	__v7_flush_dcache_all

	/* Disable MMU and Dcache before switching Page Table */
	mrc	p15, 0, r0, c1, c0, 0	@ SCTLR (System Control Register)
	bic	r0, r0, #(CR_C | CR_M)	@ disable MMU and Dcache
	mcr	p15, 0, r0, c1, c0, 0

	bl	enable_mmu

#ifdef CONFIG_DEBUG_LL
	bl	debug_ll_init
#endif

	mov	lr, r8			@ restore link
	mov	pc, lr			@ back to my caller
ENDPROC(lowlevel_init)

ENTRY(enable_mmu)
	mrc	p15, 0, r0, c2, c0, 2	@ TTBCR (Translation Table Base Control Register)
	bic	r0, r0, #0x37
	orr	r0, r0, #0x20		@ disable TTBR1
	mcr	p15, 0, r0, c2, c0, 2

	orr	r0, r12, #0x8		@ Outer Cacheability for table walks: WBWA
	mcr	p15, 0, r0, c2, c0, 0   @ TTBR0

	mov	r0, #0
	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLBs

	mov	r0, #-1			@ manager for all domains (No permission check)
	mcr	p15, 0, r0, c3, c0, 0   @ DACR (Domain Access Control Register)

	dsb
	isb
	/*
	 * MMU on:
	 * TLBs was already invalidated in "../start.S"
	 * So, we don't need to invalidate it here.
	 */
	mrc	p15, 0, r0, c1, c0, 0	@ SCTLR (System Control Register)
	orr	r0, r0, #(CR_C | CR_M)	@ MMU and Dcache enable
	mcr	p15, 0, r0, c1, c0, 0

	mov	pc, lr
ENDPROC(enable_mmu)

/*
 * For PH1-Pro4 or older SoCs, the size of WAY is 32KB.
 * It is large enough for tmp RAM.
 */
#define BOOT_RAM_SIZE	(SZ_32K)
#define BOOT_RAM_BASE	((CONFIG_SPL_STACK) - (BOOT_RAM_SIZE))
#define BOOT_RAM_WAYS	(0x00000100)	@ way 8

#define SSCO_BASE		0x506c0000
#define SSCOPE			0x244
#define SSCOQM			0x248
#define SSCOQAD			0x24c
#define SSCOQSZ			0x250
#define SSCOQWN			0x258
#define SSCOPPQSEF		0x25c
#define SSCOLPQS		0x260

ENTRY(setup_init_ram)
	ldr	r1, = SSCO_BASE
	mrc	p15, 0, r0, c2, c0, 0	@ TTBR0
	ldr	r0, [r0, #0x400]	@ entry for virtual address 0x100*****
	bfc	r0, #0, #20
	cmp	r0, #0x50000000		@ is sLD3 page table?
	biceq	r1, r1, #0xc0000000	@ sLD3 ROM maps 0x5******* to 0x1*******

	/* Touch to zero for the boot way */
0:	ldr	r0, = 0x00408006	@ touch to zero with address range
	str	r0, [r1, #SSCOQM]
	ldr	r0, = BOOT_RAM_BASE
	str	r0, [r1, #SSCOQAD]
	ldr	r0, = BOOT_RAM_SIZE
	str	r0, [r1, #SSCOQSZ]
	ldr	r0, = BOOT_RAM_WAYS
	str	r0, [r1, #SSCOQWN]
	ldr	r0, [r1, #SSCOPPQSEF]
	cmp	r0, #0			@ check if the command is successfully set
	bne	0b			@ try again if an error occurs

1:	ldr	r0, [r1, #SSCOLPQS]
	cmp	r0, #0x4
	bne	1b			@ wait until the operation is completed
	str	r0, [r1, #SSCOLPQS]	@ clear the complete notification flag

	mov	pc, lr
ENDPROC(setup_init_ram)

#define DEVICE	0x00002002 /* Non-shareable Device */
#define NORMAL	0x0000000e /* Normal Memory Write-Back, No Write-Allocate */

ENTRY(create_page_table)
	ldr	r0, = DEVICE
	ldr	r1, = BOOT_RAM_BASE
	mov	r12, r1			@ r12 is preserved during D-cache flush
0:	str	r0, [r1], #4		@ specify all the sections as Device
	adds	r0, r0, #0x00100000
	bcc	0b

	ldr	r0, = NORMAL
	str	r0, [r12]		@ mark the first section as Normal
	add	r0, r0, #0x00100000
	str	r0, [r12, #4]		@ mark the second section as Normal
	mov	pc, lr
ENDPROC(create_page_table)