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 fa25e4e..4faed24 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 a7f1102..1cb3179 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 += clk.o common.o dtmachine.o time.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 */
|