summaryrefslogtreecommitdiffstats
path: root/local_src/geckoboot-2013.01.0/geckoboot.S
blob: d5a0d6bacb19b248a7f8da93cf2cfd94983407bf (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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#define UARTBASE	0x4000e400
#define UARTLOCATION	2
#define DTB_SRC		0x80000
#define DTB_DST		0x10000000
#define LINUX_ENTRY	0x8c000000

#define BC_REGISTER	0x80000000

	.syntax unified
	.thumb
	.int 0x10001000			@ Initial SP value
	.int reset + 1

reset:
	/* init external RAM, serial port, EBI and stuff */
	adr	r0, reginit
1:
	ldr	r1, [r0]
	ldr	r2, [r0, #4]
	str	r2, [r1]
	add	r0, r0, #8
	cmp	r0, #(reginit_end)
	blo	1b

	/* init some BC registers */
	adr	r0, bcinit
1:
	ldrh	r1, [r0]
	ldrh	r2, [r0, #2]
	add	r1, r1, #BC_REGISTER
	strh	r2, [r1]
	add	r0, r0, 4
	cmp	r0, #(bcinit_end)
	blo	1b

	/* give mux some time to enable the level shifter */
	ldr	r0, =0x4000
1:	subs	r0, r0, #1
	bne	1b

	/* First sign of life */
	ldr	r0, =(UARTBASE + 0x34)
	mov	r1, #'G'
	str	r1, [r0]

	/* if PB1 is pressed setup for SWO */
	ldr	r0, =(BC_REGISTER)
	ldr	r1, [r0, #8]		@ BC_REGISTER->UIF_PB
	tst	r1, #1
	ldrne	r0, =(UARTBASE + 0x34)
	movne	r1, #'e'
	strne	r1, [r0]
	bne	wait_boot_linux

	ldr	r0, =(UARTBASE + 0x34)
	mov	r1, #'E'
	str	r1, [r0]

	/* poll for CMU_STATUS_AUXHFRCORDY */
	ldr	r0, =(0x400c8000)
1:
	ldr	r1, [r0, 0x2c]		@ CMU_STATUS
	tst	r1, #0x20
	beq	1b

	adr	r0, swoinit
1:
	ldmia	r0!, {r1, r2, r3} /* load addr, mask, value */
	teq	r2, #0xffffffff
	ldrne	r4, [r1]
	bicne	r4, r2
	orrne	r3, r4
	str	r3, [r1]
	cmp	r0, #(swoinit_end)
	blo	1b

wait_boot_linux:
#ifdef CONFIG_WAIT_FOR_PB2
	ldr	r0, =(UARTBASE + 0x34)
	mov	r1, #'C'
	str	r1, [r0]
	/* only boot into Linux when PB2 is pressed */
	ldr	r0, =(BC_REGISTER)
1:	ldr	r1, [r0, #8]		@ BC_REGISTER->UIF_PB
	tst	r1, #2
	bne	1b
#else
	ldr	r0, =(UARTBASE)
	mov	r1, #'c'
	str	r1, [r0, 0x34]
	@ wait for STATUS.TXBL being set, otherwise the 'k' might not appear
1:	ldr	r1, [r0, 0x10]
	tst	r1, #0x40
	beq	1b
#endif

boot_linux:
	ldr	r0, =(UARTBASE + 0x34)
	mov	r1, #'k'
	str	r1, [r0]

	/* Copy oftree to RAM */
	ldr	r0, =(DTB_DST)
	ldr	r1, =(DTB_SRC)
	ldr	r2, [r1, #4]
	rev	r2, r2

	bl	memcpy

	ldr	r0, =(UARTBASE + 0x34)
	mov	r1, #'o'
	str	r1, [r0]
	mov	r1, #'\r'
	str	r1, [r0]
	mov	r1, #'\n'
	str	r1, [r0]

	/* boot Linux */
	mov	r0, #0
	ldr	r1, =#0xf11
	ldr	r2, =(DTB_DST)
	mov	r3, #0
	mov	r4, #0
	mov	r5, #0
	mov	r6, #0

	ldr	r7, =(LINUX_ENTRY + 1)
	bx	r7

memcpy:
	@ copies r2 bytes from r1 to r0 with r2 > 0
	ldrb	r3, [r1], #1
	strb	r3, [r0], #1
	subs	r2, r2, #1
	bhi	memcpy
	bx	lr

	.ltorg

	.align 3
	.type reginit, %object
reginit:
	.int	0x400c8020, 0x00000014		@ CMU_OSCENCMD = HFXOEN | AUXHFRCOEN

	.int	0x400c8008, 0x00000100		@ CMU_HFPERCLKDIV, reset default
	.int	0x43900814, 0x00000001		@ CMU_HFCORECLKEN0 |= EBI via bitband
	.int	0x439008b4, 0x00000001		@ CMU_HFPERCLKEN0 |= GPIO via bitband
	.int	0x43900890, 0x00000001		@ CMU_HFPERCLKEN0 |= UART1 via bitband

	/* XXX: these should be enabled in Linux */
	.int	0x43900884, 0x00000001		@ CMU_HFPERCLKEN0 |= USART1 via bitband
	.int	0x439008c0, 0x00000001		@ CMU_HFPERCLKEN0 |= ADC via bitband

	/* pinmuxing */
	.int	0x40006000, 0x00000000		@ GPIO_PA_CTRL, reset default
	.int	0x40006014, 0x0000807f		@ GPIO_PA_DOUTCLR; EBI AD8..15 set dataout to 0
	.int	0x40006004, 0x04444444		@ GPIO_PA_MODEL; EBI AD9..15 set mode=pushpull
	.int	0x40006008, 0x40000000		@ GPIO_PA_MODEH; EBI AD8 set mode=pushpull

	.int	0x40006024, 0x00000000		@ GPIO_PB_CTRL, reset default
/* XXX join following two */
	.int	0x40006038, 0x00008000		@ GPIO_PB_DOUTCLR; EBI mode on PB15 MCU_EBI_CONNECT (0)
	.int	0x40006038, 0x0000007f		@ GPIO_PB_DOUTCLR; EBI A16-22
	.int	0x40006028, 0x04444444		@ GPIO_PB_MODEL; EBI A16-22
	.int	0x40006034, 0x00000200		@ GPIO_PB_DOUTSET; set UART_TX to avoid false start
	.int	0x4000602c, 0x40000140		@ GPIO_PB_MODEH; MCU_EBI_CONNECT -> output, UART_TX, UART_RX

	.int	0x40006048, 0x00000000		@ GPIO_PC_CTRL, reset default
	.int	0x4000605c, 0x00000001		@ GPIO_PC_DOUTCLR; PC11 (EBI_ALE)
	.int	0x40006050, 0x00004000		@ GPIO_PC_MODEH; PC11: Push-pull output

	.int	0x4000606c, 0x00000000		@ GPIO_PD_CTRL, reset default
	.int	0x4000607c, 0x00003e08		@ GPIO_PD_DOUTSET, EBI CS0-3, spiconnect set dataout to 1; ETH_SPI_#CS (D3)
	.int	0x40006080, 0x00000007		@ GPIO_PD_DOUTCLR, ETH_SPI_{TX, RX, CLK}
	.int	0x40006070, 0x00004414		@ GPIO_PD_MODEL; ETH_SPI_
	.int	0x40006074, 0x00444440		@ GPIO_PD_MODEH; EBI CS0-3, spiconnect set mode=pushpull

	.int	0x40006090, 0x00000000		@ GPIO_PE_CTRL, reset default
	.int	0x400060a0, 0x00000011		@ GPIO_PE_DOUTSET; FPGA irq with pullup (E0), SPI_CS (E4)
	.int	0x400060a4, 0x0000ffe0		@ GPIO_PE_DOUTCLR; EBI AD0..7 set dataout to 0, SPI_{TX, RX, CLK}
	.int	0x40006094, 0x41440002		@ GPIO_PE_MODEL; FPGA irq input with pullup, SPI for microsd
	.int	0x40006098, 0x44444444		@ GPIO_PE_MODEH; EBI AD0..7 set mode=pushpull

	.int	0x400060b4, 0x00000000		@ GPIO_PF_CTRL, reset default
	.int	0x400060c8, 0x000003c0		@ GPIO_PF_DOUTCLR; EBI Wen+Ren set dataout to 0
	.int	0x400060b8, 0x44000000		@ GPIO_PF_MODEL; EBI Byte Lane 0 support BL0/BL1
	.int	0x400060bc, 0x00000044		@ GPIO_PF_MODEH; EBI WEN, REN

	.int	0x40006100, 0x00000004		@ GPIO_EXTIPSELL: select port E for irq 0
	.int	0x4000610c, 0x00000001		@ GPIO_EXTIFALL: trigger for falling FPGA irq line
	.int	0x4000611c, 0x0000ffff		@ GPIO_IFC: clear all irqs
	.int	0x40006110, 0x00000001		@ GPIO_IEN: enable irq 0

	/* EBI */
	.int	0x40008000, 0x4f00d051		@ EBI_CTRL, enable ITS, mode0=mode2=mode3=D16A16ALE, bl0-3, noidle[023]
	/* EBI PSRAM */
	.int	0x40008028, 0x10000000		@ EBI_ADDRTIMING2; HALFALE
	.int	0x4000802c, 0x20000400		@ EBI_RDTIMING2; Prefetch, StrobeCycles = 4, HoldCycles = SetupCycles = 0
	.int	0x40008030, 0x00000200		@ EBI_WRTIMING2; StrobeCycles = 2, HoldCycles = SetupCycles = 0
	.int	0x40008034, 0x00000008		@ EBI_POLARITY2, ARDY_, ALE, WE_, RE_, CS_, BL_

	/* Board Control FPGA */
	.int	0x40008004, 0x10000303		@ EBI_ADDRTIMING; HALFALE, HoldCycles = SetupCycles = 3
	.int	0x40008008, 0x00030703		@ EBI_RDTIMING; StrobeCycles = 7, HoldCycles = SetupCycles = 3
	.int	0x4000800c, 0x00030703		@ EBI_WRTIMING; StrobeCycles = 7, HoldCycles = SetupCycles = 3
	.int	0x40008010, 0x00000008		@ EBI_POLARITY, ARDY_, ALE, WE_, RE_, CS_, BL_

	/* external NOR flash */
	.int	0x40008038, 0x10000000		@ EBI_ADDRTIMING3; HALFALE, HoldCycles = SetupCycles = 0
#define PRE
#ifdef PRE
	.int	0x4000803c, 0x00000700		@ EBI_RDTIMING3; StrobeCycles = 7, HoldCycles = SetupCycles = 0
	.int	0x40008040, 0x00000200		@ EBI_WRTIMING3; StrobeCycles = 2, HoldCycles = SetupCycles =0
#else
	/* reference: kits/common/bsp/bsp_dk_3201.c: 5 strobe cycles, hold=setup=0 */
	.int	0x4000803c, 0x00000700		@ EBI_RDTIMING3; StrobeCycles = 7, HoldCycles = SetupCycles = 0
	.int	0x40008040, 0x00000700		@ EBI_WRTIMING3; StrobeCycles = 7, HoldCycles = SetupCycles =0
#endif
	.int	0x40008044, 0x00000008		@ EBI_POLARITY3, ARDY_, ALE, WE_, RE_, CS_, BL_

	.int	0x40008014, 0x105e00bb		@ EBI_ROUTE
	.int	0x40008000, 0x4f00dd51		@ EBI_CTRL, enable ITS, mode0=mode2=mode3=D16A16ALE, bl0-3, noidle[023], bank[023]en

	.int	UARTBASE + 0x00, 0x00000000		@ UART1_CTRL
	.int	UARTBASE + 0x04, 0x00001005		@ UART1_FRAME
	.int	UARTBASE + 0x14, 0x00001900		@ UART1_CLKDIV
	.int	UARTBASE + 0x0c, 0x00000c04		@ UART1_CMD
	.int	UARTBASE + 0x54, 0x00000003 + (UARTLOCATION << 8)		@ UART1_ROUTE
	.int	0x400c8024, 0x00000002		@ CMU_CMD = HFCLKSEL_HFXO

reginit_end:
	.size reginit, . - reginit

	.align	3
	.type	bcinit, %object
bcinit:
	.short	0x0018, 0x1301			@ enable UART mux, ETH and spi
	.short	0x0014, 0x0001			@ /
	.short	0x001a, 0x0001			@ ETH
	.short	0x0042, 0x0010			@ workaround bug in BC's irq detection
	.short	0x0040, 0x0010

bcinit_end:
	.size	bcinit, . - bcinit

	.align 3
	.type	swoinit, %object
swoinit:
	.int	0x40006120, 0x00000304, 0x00000004	@ GPIO_ROUTE: SWOPEN + LOCATION = 0
	.int	0x400060b8, 0x00000f00, 0x00000400	@ configure F2 as pushpull output
	.int	0xe000edf0, 0x00000001, 0x00000001	@ CoreDebug->DHCSR |= 1
	.int	0xe000edfc, 0x01000000, 0x01000000	@ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk
	.int	0xe0001000, 0xffffffff, 0x400113ff	@ Enable PC and IRQ sampling output
	.int 	0xe0040010, 0xffffffff, 0x0000000f	@ Set TPIU prescaler to 16.
	.int	0xe00400f0, 0xffffffff, 0x00000002	@ Set protocol to NRZ
	.int	0xe0000fb0, 0xffffffff, 0xc5acce55	@ Unlock ITM
	.int	0xe0000e80, 0xffffffff, 0x00010009	@ output data
	.int	(UARTBASE + 0x34), 0xffffffff, 0x00000043 @ some output to uart
swoinit_end:
	.size	swoinit, . - swoinit