diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/mkamsboot/dualboot/dualboot.S | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/mkamsboot/dualboot/dualboot.S')
-rw-r--r-- | utils/mkamsboot/dualboot/dualboot.S | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/utils/mkamsboot/dualboot/dualboot.S b/utils/mkamsboot/dualboot/dualboot.S new file mode 100644 index 0000000000..4e4dbe5505 --- /dev/null +++ b/utils/mkamsboot/dualboot/dualboot.S | |||
@@ -0,0 +1,307 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 Rafaël Carré | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | .text | ||
23 | |||
24 | /* AS3525 hardware registers */ | ||
25 | .set GPIOA, 0xC80B0000 | ||
26 | .set GPIOB, 0xC80C0000 | ||
27 | .set GPIOC, 0xC80D0000 | ||
28 | .set GPIOD, 0xC80E0000 | ||
29 | .set CGU_PROC, 0xC80F0010 | ||
30 | .set CGU_PERI, 0xC80F0014 | ||
31 | .set CGU_DBOP, 0xC80F0038 | ||
32 | .set CCU_IO, 0xC810000C | ||
33 | .set DBOP, 0xC8120000 | ||
34 | .set I2C_BASE, 0xC8070000 | ||
35 | .set I2C_DATA, 0x00 | ||
36 | .set I2C_SLAD0, 0x04 | ||
37 | .set I2C_CNTRL, 0x0c | ||
38 | .set I2C_DACNT, 0x10 | ||
39 | .set I2C_CPSR0, 0x1c | ||
40 | .set I2C_CPSR1, 0x20 | ||
41 | .set I2C_IMR, 0x24 | ||
42 | .set I2C_SR, 0x30 | ||
43 | .set I2C_SADDR, 0x44 | ||
44 | .set AS3514_I2C_ADDR, 0x46 | ||
45 | .set AS3514_IRQ_ENRD0, 0x25 | ||
46 | .set PCLK, 24000000 | ||
47 | .set I2C_CLK, 400000 | ||
48 | .set I2C_PRESCALER, ((PCLK + I2C_CLK -1) / I2C_CLK) | ||
49 | .set I2C_PRESCALER_LOW, (I2C_PRESCALER & 0xff) | ||
50 | .set I2C_PRESCALER_HIGH, (I2C_PRESCALER >> 8) | ||
51 | #if I2C_PRESCALER_HIGH > 3 | ||
52 | #error i2c prescaler too big! | ||
53 | #endif | ||
54 | |||
55 | b start @ skip our data | ||
56 | |||
57 | /* These values are filled in by mkamsboot - don't move them from offset 0x4 */ | ||
58 | |||
59 | uclunpack_end: .word 0 /* End of the ucl_unpack function */ | ||
60 | uclunpack_size: .word 0 /* Size in bytes of the ucl_unpack function */ | ||
61 | |||
62 | ucl_of_end: .word 0 /* End of the ucl-compressed OF image */ | ||
63 | ucl_of_size: .word 0 /* Size in bytes of the compressed OF image */ | ||
64 | |||
65 | ucl_rb_end: .word 0 /* End of the ucl-compressed RB image */ | ||
66 | ucl_rb_size: .word 0 /* Size in bytes of the compressed RB image */ | ||
67 | |||
68 | ucl_dest: .word 0 /* End of our destination buffer (end of memory) */ | ||
69 | |||
70 | start: | ||
71 | /* First copy the UCL unpack function to the end of RAM */ | ||
72 | ldr r0, uclunpack_end /* Source */ | ||
73 | ldr r1, uclunpack_size /* Source length */ | ||
74 | sub r2, r0, r1 /* Source start - 1*/ | ||
75 | |||
76 | ldr r3, ucl_dest /* Destination end */ | ||
77 | |||
78 | uclcopy: | ||
79 | ldrb r4, [r0], #-1 | ||
80 | strb r4, [r3], #-1 | ||
81 | cmp r2, r0 | ||
82 | bne uclcopy | ||
83 | |||
84 | /* store the new destination buffer */ | ||
85 | str r3, ucl_dest | ||
86 | |||
87 | /* enable gpio clock */ | ||
88 | ldr r0, =CGU_PERI | ||
89 | ldr r1, [r0] | ||
90 | orr r1, r1, #(1<<16) | ||
91 | str r1, [r0] | ||
92 | |||
93 | /* Here are model specific tests for dual boot (test left button) */ | ||
94 | |||
95 | #ifdef SANSA_CLIP | ||
96 | .set row, (1<<5) /* enable output on C5 */ | ||
97 | .set col, (1<<0) /* read keyscan column B0 */ | ||
98 | |||
99 | ldr r0, =GPIOC | ||
100 | mov r1, #row | ||
101 | str r1, [r0, #0x400] | ||
102 | str r1, [r0, #(4*row)] | ||
103 | |||
104 | ldr r0, =GPIOB | ||
105 | mov r1, #0 | ||
106 | str r1, [r0, #0x400] | ||
107 | ldr r1, [r0, #(4*col)] | ||
108 | |||
109 | cmp r1, #0 | ||
110 | bne boot_of | ||
111 | #elif defined(SANSA_CLIPV2) | ||
112 | .set row, (1<<4) /* enable output on D4 */ | ||
113 | .set col, (1<<0) /* read keyscan column D0 */ | ||
114 | |||
115 | ldr r0, =CCU_IO | ||
116 | ldr r1, [r0] | ||
117 | bic r1, r1, #(3<<2) @ XPD works as general purpose IO | ||
118 | str r1, [r0] | ||
119 | |||
120 | ldr r0, =GPIOD | ||
121 | mov r1, #((1<<5)|(1<<4)|(1<<3)) /* all rows as output */ | ||
122 | str r1, [r0, #0x400] | ||
123 | |||
124 | /* all rows high */ | ||
125 | mov r1, #(1<<3) | ||
126 | str r1, [r0, #(4*(1<<3))] | ||
127 | mov r1, #(1<<4) | ||
128 | str r1, [r0, #(4*(1<<4))] | ||
129 | mov r1, #(1<<5) | ||
130 | str r1, [r0, #(4*(1<<5))] | ||
131 | |||
132 | mov r1, #0 /* button row low */ | ||
133 | str r1, [r0, #(4*row)] | ||
134 | |||
135 | mov r1, #5 /* small delay */ | ||
136 | 1: subs r1, r1, #1 | ||
137 | bne 1b | ||
138 | |||
139 | ldr r1, [r0, #(4*col)] | ||
140 | |||
141 | cmp r1, #0 | ||
142 | beq boot_of | ||
143 | #elif defined(SANSA_E200V2) || defined(SANSA_FUZE) | ||
144 | ldr r0, =GPIOC | ||
145 | mov r1, #0 | ||
146 | str r1, [r0, #0x400] | ||
147 | ldr r1, [r0, #0x20] /* read pin C3 */ | ||
148 | |||
149 | cmp r1, #0 /* C3 = #0 means button pressed */ | ||
150 | beq boot_of | ||
151 | |||
152 | #elif defined(SANSA_FUZEV2) | ||
153 | ldr r0, =GPIOC | ||
154 | mov r1, #0 | ||
155 | str r1, [r0, #0x400] | ||
156 | ldr r1, [r0, #0x20] /* read pin C3 */ | ||
157 | |||
158 | cmp r1, #0 /* C3 != #0 means button pressed */ | ||
159 | bne boot_of | ||
160 | |||
161 | #elif defined(SANSA_CLIPPLUS) | ||
162 | @ read pins | ||
163 | ldr r0, =GPIOC | ||
164 | ldr r1, [r0, #4*(1<<3)] @ read pin C3 "|<<" | ||
165 | |||
166 | ldr r0, =GPIOA | ||
167 | ldr r2, [r0, #4*(1<<1)] @ read pin A1 "Home" | ||
168 | |||
169 | orr r2, r2, r1 @ c3 || A1 | ||
170 | |||
171 | cmp r2, #0 @ test input from pins | ||
172 | bne boot_of @ branch directly to OF if either pin high | ||
173 | |||
174 | #elif defined(SANSA_CLIPZIP) | ||
175 | @ read pins | ||
176 | ldr r0, =GPIOA | ||
177 | ldr r1, [r0, #4*(1<<6)] @ read GPIO A6 "vol-" | ||
178 | |||
179 | cmp r1, #0 @ test input from pins | ||
180 | bne boot_of @ branch directly to OF if either pin high | ||
181 | |||
182 | ldr r0, =GPIOC | ||
183 | |||
184 | ldr r1, [r0, #0x400] | ||
185 | orr r1, r1, #((1<<1)|(1<<2)) @ output | ||
186 | bic r1, r1, #(1<<5) @ input | ||
187 | str r1, [r0, #0x400] | ||
188 | |||
189 | mov r1, #0 | ||
190 | str r1, [r0, #4*(1<<1)] @ zero C1 | ||
191 | mov r1, #(1<<2) | ||
192 | str r1, [r0, #4*(1<<2)] @ set C2 | ||
193 | |||
194 | mov r1, #50 /* small delay */ | ||
195 | 1: subs r1, r1, #1 | ||
196 | bne 1b | ||
197 | |||
198 | ldr r1, [r0, #4*(1<<5)] @ read C5 = left | ||
199 | |||
200 | cmp r1, #0 | ||
201 | bne boot_of | ||
202 | |||
203 | #elif defined(SANSA_C200V2) | ||
204 | .set BUTTON_LEFT, (1<< 2) | ||
205 | .set BUTTON_DOWN, (1<< 3) | ||
206 | .set BUTTON_SELECT, (1<< 4) | ||
207 | .set BUTTON_UP, (1<< 5) | ||
208 | .set BUTTON_RIGHT, (1<< 6) | ||
209 | .set BUTTON_HOLD, (1<<12) | ||
210 | |||
211 | ldr r0, =CGU_DBOP | ||
212 | mov r1, #(1<<3) @ DBOP freq = PCLK, clock enabled | ||
213 | str r1, [r0] | ||
214 | |||
215 | @ AFSEL needs to be set for this to work | ||
216 | ldr r2, =GPIOB | ||
217 | mov r1, #0xc | ||
218 | str r1, [r2, #0x420] @ GPIOB_AFSEL | ||
219 | ldr r2, =GPIOC | ||
220 | mov r1, #0xff | ||
221 | str r1, [r2, #0x420] @ GPIOC_AFSEL | ||
222 | |||
223 | ldr r0, =DBOP | ||
224 | @ TIMPOL doesn't matter here since we don't need | ||
225 | @ the control signals. | ||
226 | |||
227 | @ 16 bit data width | ||
228 | @ enable write | ||
229 | @ tri-state output | ||
230 | ldr r1, =0x00091000 | ||
231 | str r1, [r0, #8] @ DBOP_CTRL | ||
232 | |||
233 | ldr r1, =0xf0ff @ precharge | ||
234 | str r1, [r0, #0x10] @ DBOP_DOUT | ||
235 | |||
236 | 2: ldr r1, [r0, #0xc] @ DOBP_STAT | ||
237 | ands r1, r1, #(1<<10) | ||
238 | beq 2b @ make sure fifo is empty | ||
239 | |||
240 | @ 16 bit data width | ||
241 | @ start read | ||
242 | @ tri-state output | ||
243 | @ strobe time 31 | ||
244 | ldr r1, =0x0008901f | ||
245 | str r1, [r0, #8] @ DBOP_CTRL | ||
246 | |||
247 | 3: ldr r1, [r0, #0xc] @ DOBP_STAT | ||
248 | ands r1, r1, #(1<<16) | ||
249 | beq 3b @ wait for valid data | ||
250 | |||
251 | ldrh r1, [r0, #0x14] @ DBOP_DIN | ||
252 | |||
253 | tst r1, #BUTTON_LEFT @ boot of? | ||
254 | beq boot_of | ||
255 | #elif defined(SANSA_M200V4) | ||
256 | .set row, (1<<5) /* enable output on A5 */ | ||
257 | .set col, (1<<0) /* read keyscan column A0 */ | ||
258 | |||
259 | ldr r0, =GPIOA | ||
260 | mov r1, #row | ||
261 | str r1, [r0, #0x400] | ||
262 | str r1, [r0, #(4*row)] | ||
263 | |||
264 | ldr r2, [r0, #(4*col)] | ||
265 | |||
266 | /* check value read (1 means button pressed) */ | ||
267 | cmp r2, #0 | ||
268 | bne boot_of | ||
269 | #else | ||
270 | #error No target-specific key check defined! | ||
271 | #endif | ||
272 | |||
273 | /* The dualboot button was not held, so we boot rockbox */ | ||
274 | ldr r0, ucl_rb_end /* Address of compressed image */ | ||
275 | ldr r1, ucl_rb_size /* Compressed size */ | ||
276 | b decompress | ||
277 | |||
278 | boot_of: | ||
279 | ldr r0, ucl_of_end /* Address of compressed image */ | ||
280 | ldr r1, ucl_of_size /* Compressed size */ | ||
281 | |||
282 | |||
283 | decompress: | ||
284 | /* At this point: */ | ||
285 | /* r0 = source_end for UCL image to copy */ | ||
286 | /* r1 = size of UCL image to copy */ | ||
287 | |||
288 | ldr r3, ucl_dest | ||
289 | add r5, r3, #2 /* r5 is entry point of copy of uclunpack */ | ||
290 | /* function, plus one (for thumb mode */ | ||
291 | |||
292 | sub r4, r3, r1 /* r4 := destination_start - 1 */ | ||
293 | |||
294 | fw_copy: | ||
295 | ldrb r2, [r0], #-1 | ||
296 | strb r2, [r3], #-1 | ||
297 | cmp r3, r4 /* Stop when we reached dest_start-1 */ | ||
298 | bne fw_copy | ||
299 | |||
300 | /* Call the ucl decompress function, which will branch to 0x0 */ | ||
301 | /* on completion */ | ||
302 | add r0, r3, #1 /* r0 := Start of compressed image */ | ||
303 | /* r1 already contains compressed size */ | ||
304 | mov r2, #0 /* r2 := Destination for unpacking */ | ||
305 | bx r5 /* Branch to uclunpack, switching to thumb */ | ||
306 | |||
307 | /* never reached : uclunpack will branch to the reset vector (0x0) */ | ||