summaryrefslogtreecommitdiffstats
path: root/patches/linux-3.12-rc4/0021-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch
blob: a7366a3356636cd5f4b6fc97b8eeaea4458c6780 (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
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
Date: Sun, 30 Oct 2011 21:11:05 +0100
Subject: [PATCH] HACK! ARM: allow a bootloader to be embedded and do it on
 efm32
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 arch/arm/kernel/vmlinux.lds.S    |   5 +
 arch/arm/mach-efm32/Makefile     |   8 ++
 arch/arm/mach-efm32/bootloader.S | 252 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 265 insertions(+)
 create mode 100644 arch/arm/mach-efm32/bootloader.S

diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 7bcee5c..1f34cf8 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -86,6 +86,11 @@ SECTIONS
 #else
 	. = PAGE_OFFSET + TEXT_OFFSET;
 #endif
+
+	.bootloader : {
+		*(.bootloader)
+	}
+
 	.head.text : {
 		_text = .;
 		HEAD_TEXT
diff --git a/arch/arm/mach-efm32/Makefile b/arch/arm/mach-efm32/Makefile
index b295a74..b28d37c 100644
--- a/arch/arm/mach-efm32/Makefile
+++ b/arch/arm/mach-efm32/Makefile
@@ -1,3 +1,11 @@
+ifeq ($(CONFIG_FLASH_MEM_BASE),0x00000000)
+obj-y += bootloader.o
+endif
+
+ifeq ($(CONFIG_USE_OF),y)
+$(obj)/bootloader.o: $(obj)/../boot/dts/efm32gg-dk3750.dtb
+endif
+
 obj-y += common.o dtmachine.o
 
 obj-$(CONFIG_PM) += pm.o
diff --git a/arch/arm/mach-efm32/bootloader.S b/arch/arm/mach-efm32/bootloader.S
new file mode 100644
index 0000000..d4dbf0b
--- /dev/null
+++ b/arch/arm/mach-efm32/bootloader.S
@@ -0,0 +1,252 @@
+#if defined(CONFIG_OF)
+#define EFM32_USE_OF
+#endif
+#define EFM32_DT_IN_SRAM
+
+/* UART1 */
+#define UARTBASE 0x4000e400
+#define UARTLOCATION 2
+
+	.thumb
+
+	.section ".bootloader","ax"
+
+	/* M3 Vector table */
+	.int 0x10001000		@ Initial SP value
+	.int reset + 1		@ Reset
+
+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, #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, #0x80000000
+	strh	r2, [r1]
+	add	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
+
+	ldr	r0, =(UARTBASE + 0x34)
+	mov	r1, 0x55
+	str	r1, [r0]
+
+	/* Zero PSRAM */
+	ldr	r0, =(0x88000000)
+	ldr	r1, =(0x88400000)
+	mov	r2, #0
+	mov	r3, #0
+	mov	r4, #0
+	mov	r5, #0
+1:	stmia	r0!, {r2-r5}
+	cmp	r0, r1
+	bcc	1b
+
+	/* assert zeroing succeeded */
+	ldr	r6, =(UARTBASE + 0x34)
+	mov	r7, #'<'
+	str	r7, [r6]
+	mov	r7, #'*'
+	ldr     r0, =(0x88000000)
+1:	ldmia	r0!, {r2-r5}
+	orr	r2, r3
+	orr	r4, r5
+	orr	r2, r4
+	cmp	r2, #0
+	it	ne
+	strne	r7, [r6]
+	cmp	r0, r1
+	bcc	1b
+	mov	r7, #'>'
+	str	r7, [r6]
+
+#if defined(EFM32_USE_OF) && defined(EFM32_DT_IN_SRAM)
+#define dtbaddr 0x10000000
+	ldr	r0, =(dtbaddr)
+	ldr	r1, =(dtb)
+	adr	r2, dtbend
+	subs	r2, r2, r1
+	bl	_memcpy
+#endif
+	/* detect machine type; easy we know this is an efm32gg_dk3750 */
+	movw	r0, #0
+	movw	r1, #0xf11	@ machid for efm32gg_dk3750
+#ifdef EFM32_USE_OF
+#ifdef EFM32_DT_IN_SRAM
+	ldr	r2, =(dtbaddr)
+#else
+	adr	r2, dtb
+#endif
+#else
+	adr	r2, ataglist
+#endif
+	movw	r3, #0
+	movw	r4, #0
+	movw	r5, #0
+	movw	r6, #0
+	movw	r7, #0
+
+	b	stext
+
+#ifdef EFM32_DT_IN_SRAM
+_memcpy:
+	@ copies r2 bytes from r1 to r0 with r2 > 0
+1:
+	ldrb	r3, [r1], #1
+	strb	r3, [r0], #1
+	subs	r2, #1
+	bhi	1b
+	bx	lr
+#endif
+
+	.ltorg
+
+	.align	3
+	/* register value pairs to initialize the machine */
+	.type reginit, %object
+reginit:
+	/* clocks */
+	.int	0x400C8020, 0x00000004		@ CMU_OSCENCMD |= HFXOEN
+
+	.int	0x400c8008, 0x00000100		@ CMU_HFPERCLKDIV, reset default
+	.int	0x43900814, 0x00000001		@ CMU_HFCORECLKEN0 |= EBI via bitband
+	.int	0x439008b4, 0x00000001		@ CMU_HFPERCLKEN0 |= GPIO via bitband
+	.int	0x43900884, 0x00000001		@ CMU_HFPERCLKEN0 |= USART1 via bitband
+	.int	0x43900890, 0x00000001		@ CMU_HFPERCLKEN0 |= UART1 via bitband
+
+	/* XXX */
+	.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
+	.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, 0x00000001		@ GPIO_PE_DOUTSET; FPGA irq line
+	.int	0x400060a4, 0x0000ff00		@ GPIO_PE_DOUTCLR; EBI AD0..7 set dataout to 0
+	.int	0x40006094, 0x00000002		@ GPIO_PE_MODEL; FPGA irq line set mode=inputpull
+	.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
+	.int	0x4000803c, 0x00000700		@ EBI_RDTIMING3; StrobeCycles = 7, HoldCycles = SetupCycles = 0
+	.int	0x40008040, 0x00000200		@ EBI_WRTIMING3; StrobeCycles = 2, HoldCycles = SetupCycles =0
+	.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
+	/* register value pairs to initialize the board controller */
+	.type bcinit, %object
+bcinit:
+	.short	0x0018, 0x1300			@ enable UART mux and ETH
+	.short	0x0014, 0x0001			@ /
+	.short	0x001a, 0x0001			@ ETH
+
+bcinit_end:
+	.size bcinit, . - bcinit
+
+	.align 3
+#ifdef EFM32_USE_OF
+	.type dtb, %object
+dtb:
+	.incbin "arch/arm/boot/dts/efm32gg-dk3750.dtb"
+dtbend:
+	.size dtb, . - dtb
+	.align 3
+
+#else /* ifdef CONFIG_OF */
+
+	.type ataglist, %object
+ataglist:
+	/* ATAG_CORE */
+	.int	0x00000005		/* .size */
+	.int	0x54410001		/* .tag = ATAG_CORE */
+	.int	0x00000001		/* .flags */
+	.int	0x00001000		/* .pagesize */
+	.int	0x000000ff		/* .rootdev */
+	/* ATAG_MEM */
+	.int	0x00000004		/* .size */
+	.int	0x54410002		/* .tag = ATAG_MEM */
+	.int	0x00400000		/* .size = 4 MiB */
+	.int	0x88000000		/* .start = SRAM_BASE */
+	/* ATAG_CMDLINE */
+cmdline:
+	.int	(cmdline_end - cmdline) >> 2	/* .size */
+	.int	0x54410009		/* .tag = ATAG_CMDLINE */
+	.asciz	"console=ttyefm4,115200 ignore_loglevel ihash_entries=64 dhash_entries=64 rootfstype=romfs init=/linuxrc uclinux.physaddr=0x8c000000 root=/dev/mtdblock0 earlyprintk"
+	.align	2, 0
+cmdline_end:
+	/* ATAG_NONE */
+	.int	0x00000000	/* .size */
+	.int	0x00000000	/* .tag = ATAG_NONE */
+ataglist_end:
+	.size ataglist, . - ataglist
+#endif /* ifdef CONFIG_OF / else */