blob: b7185b510d08b8cf0ab6142b2d19229e97d0a615 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/* fw-m0sub.S
2 *
3 * Copyright 2015 Brian Swetland <swetland@frotz.net>
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18.syntax unified
19
20m0_vectors:
21 .word 0x18003FF0
22 .word m0_reset + 1
23 .word m0_fault + 1
24 .word m0_fault + 1
25 .word m0_fault + 1
26 .word m0_fault + 1
27 .word m0_fault + 1
28 .word m0_fault + 1
29 .word m0_fault + 1
30 .word m0_fault + 1
31 .word m0_fault + 1
32 .word m0_fault + 1
33 .word m0_fault + 1
34 .word m0_fault + 1
35 .word m0_fault + 1
36 .word m0_fault + 1
37// external IRQs
38 .word m0_fault + 1
39 .word m0_irq + 1
40
41m0_fault:
42 ldr r0, =0x18000000
43 ldr r1, =0xeeee0000
44 mrs r2, xpsr
45 movs r3, #0xFF
46 ands r2, r2, r3
47 orrs r1, r1, r2
48 str r1, [r0]
49 b .
50
51.ltorg
52
53#define REPORT_DELAY 0
54
55#define COMM_BASE 0x18004000
56
57#define COMM_CMD 0
58#define COMM_ARG0 4
59#define COMM_ARG1 8
60#define COMM_RESP 12
61#define COMM_RETRY 16
62
63
64#define M4_TXEV 0x40043130 // write 0 to clear
65
66#define SGPIO_BASE (0x40101210)
67#define OFF_IN 0
68#define OFF_OUT 4
69#define OFF_OEN 8
70#define SGPIO_IN (0x40101210)
71#define SGPIO_OUT (0x40101214)
72#define SGPIO_OEN (0x40101218)
73
74#define CLK_BIT 11
75#define DIO_BIT 14
76#define TEN_BIT 15
77#define CLK_MSK (1 << CLK_BIT)
78#define DIO_MSK (1 << DIO_BIT)
79#define TEN_MSK (1 << TEN_BIT)
80
81#define CLK1_OUT (CLK_MSK | TEN_MSK)
82#define CLK0_OUT (TEN_MSK)
83#define CLK1_IN (CLK_MSK)
84#define CLK0_IN (0)
85
86#define OEN_IN ((1 << CLK_BIT) | (1 << TEN_BIT))
87#define OEN_OUT ((1 << CLK_BIT) | (1 << DIO_BIT) | (1 << TEN_BIT))
88
89#define NOP4 nop ; nop ; nop ; nop
90#define NOP8 NOP4 ; NOP4
91#define NOP16 NOP8 ; NOP8
92
93//#define DELAY nop ; nop
94//#define DELAY NOP8
95
96// r11 CLK1_OUT const
97// r10 CLK0_OUT const
98// r9 delay subroutine
99// r8 comm_base addr
100// r7 SGPIO_BASE addr
101// r6 DIO_MSK const
102// r5 CLK1_IN const
103// r4 CLK0_IN const
104// r3 outbits data
105
106snooze_2m:
107 nop ; nop ; nop ; nop
108 nop ; nop ; nop ; nop
109 nop ; nop ; nop ; nop
110 nop ; nop ; nop ; nop
111snooze_3m:
112 nop ; nop ; nop ; nop
113 nop ; nop ; nop ; nop
114snooze_4m:
115 nop ; nop ; nop ; nop
116 nop ; nop ; nop ; nop
117snooze_6m:
118 nop ; nop ; nop ; nop
119snooze_8m:
120 bx lr
121
122// delay 0 nops 16MHz
123// delay 2 nops 12MHz
124// delay 4 nops 9.6MHz
125#define DELAY blx r9
126
127// 12 cycles + DELAY x 2
128.macro ONE_BIT_OUT
129 lsls r2, r3, #DIO_BIT // shift bit 1 to posn
130 ands r2, r2, r6 // isolate bit 1
131 movs r1, r2 // save bit 1
132 add r2, r2, r10 // combine with CLK1
133 DELAY
134 str r2, [r7, #OFF_OUT] // commit negative egde
135 lsrs r3, r3, #1 // advance to next bit
136 add r1, r1, r11 // combine with CLK1
137 nop
138 nop
139 DELAY
140 str r1, [r7, #OFF_OUT] // commit positive edge
141.endm
142
143.macro ONE_BIT_IN
144 ands r0, r0, r6 // isolate input bit
145 lsls r0, r0, #(31-DIO_BIT) // move to posn 31
146 lsrs r3, r3, #1 // make room
147 orrs r3, r3, r0 // add bit
148 DELAY
149 str r4, [r7, #OFF_OUT] // commit negative edge
150 ldr r0, [r7, #OFF_IN] // sample input
151 nop
152 nop
153 DELAY
154 str r5, [r7, #OFF_OUT] // commit positive edge
155.endm
156
157// used for the final parity and turn bits on input so this
158// actually only reads one bit
159read_2:
160 push {lr}
161 nop
162 nop
163 nop
164 nop
165 DELAY
166 str r4, [r7, #OFF_OUT]
167 ldr r0, [r7, #OFF_IN]
168 nop
169 nop
170 DELAY
171 str r5, [r7, #OFF_OUT]
172 ands r0, r0, r6 // isolate bit
173 lsrs r0, r0, #DIO_BIT // shift to bit0
174 nop
175 nop
176 DELAY
177 str r4, [r7, #OFF_OUT]
178 nop
179 nop
180 nop
181 nop
182 DELAY
183 str r5, [r7, #OFF_OUT]
184 pop {pc}
185
186// w0: <15> <parity:1> <cmd:16>
187// w1: <data:32>
188
189
190write_16:
191 push {lr}
192 b _write_16
193write_32:
194 push {lr}
195 ONE_BIT_OUT
196 ONE_BIT_OUT
197 ONE_BIT_OUT
198 ONE_BIT_OUT
199 ONE_BIT_OUT
200 ONE_BIT_OUT
201 ONE_BIT_OUT
202 ONE_BIT_OUT
203 ONE_BIT_OUT
204 ONE_BIT_OUT
205 ONE_BIT_OUT
206 ONE_BIT_OUT
207 ONE_BIT_OUT
208 ONE_BIT_OUT
209 ONE_BIT_OUT
210 ONE_BIT_OUT
211_write_16:
212 ONE_BIT_OUT
213 ONE_BIT_OUT
214 ONE_BIT_OUT
215 ONE_BIT_OUT
216 ONE_BIT_OUT
217 ONE_BIT_OUT
218 ONE_BIT_OUT
219 ONE_BIT_OUT
220 ONE_BIT_OUT
221 ONE_BIT_OUT
222 ONE_BIT_OUT
223 ONE_BIT_OUT
224 ONE_BIT_OUT
225 ONE_BIT_OUT
226 ONE_BIT_OUT
227 ONE_BIT_OUT
228 pop {pc}
229write_1:
230 push {lr}
231 ONE_BIT_OUT
232 pop {pc}
233
234read_4:
235 push {lr}
236 b _read_4
237read_32:
238 push {lr}
239 ONE_BIT_IN
240 ONE_BIT_IN
241 ONE_BIT_IN
242 ONE_BIT_IN
243 ONE_BIT_IN
244 ONE_BIT_IN
245 ONE_BIT_IN
246 ONE_BIT_IN
247 ONE_BIT_IN
248 ONE_BIT_IN
249 ONE_BIT_IN
250 ONE_BIT_IN
251 ONE_BIT_IN
252 ONE_BIT_IN
253 ONE_BIT_IN
254 ONE_BIT_IN
255 ONE_BIT_IN
256 ONE_BIT_IN
257 ONE_BIT_IN
258 ONE_BIT_IN
259 ONE_BIT_IN
260 ONE_BIT_IN
261 ONE_BIT_IN
262 ONE_BIT_IN
263 ONE_BIT_IN
264 ONE_BIT_IN
265 ONE_BIT_IN
266 ONE_BIT_IN
267_read_4:
268 ONE_BIT_IN
269 ONE_BIT_IN
270 ONE_BIT_IN
271 ONE_BIT_IN
272 ands r0, r0, r6 // isolate input bit
273 lsls r0, r0, #(31-DIO_BIT) // move to posn 31
274 lsrs r3, r3, #1 // make room
275 orrs r3, r3, r0 // add bit
276 pop {pc}
277
278init:
279 ldr r0, =CLK1_OUT
280 mov r11, r0
281 ldr r0, =CLK0_OUT
282 mov r10, r0
283 ldr r0, =(snooze_4m + 1)
284 mov r9, r0
285 ldr r0, =COMM_BASE
286 mov r8, r0
287 ldr r7, =SGPIO_BASE
288 ldr r6, =DIO_MSK
289 ldr r5, =CLK1_IN
290 ldr r4, =CLK0_IN
291 bx lr
292
293#define MAX_RETRY 8192
294
295err_fail:
296 movs r0, #3
297 mov r3, r8
298 str r0, [r3, #COMM_RESP];
299 pop {pc}
300
301err_timeout:
302 movs r0, #2
303 mov r3, r8
304 str r0, [r3, #COMM_RESP];
305 pop {pc}
306
307cmd_read_txn:
308 push {lr}
309
310 ldr r0, =MAX_RETRY
311 //movs r0, #MAX_RETRY
312 mov r12, r0
313
314rd_retry:
315 ldr r3, [r3, #COMM_ARG0]
316 bl write_16
317
318 ldr r3, =OEN_IN
319 str r3, [r7, #OFF_OEN]
320 bl read_4
321
322 lsrs r3, r3, #29
323 cmp r3, #1 // OK
324 beq rd_okay
325
326 ldr r1, =OEN_OUT
327 str r1, [r7, #OFF_OEN]
328
329 cmp r3, #2 // WAIT
330 bne err_fail
331
332 mov r0, r12
333 subs r0, r0, #1
334 mov r12, r0
335 beq err_timeout
336 mov r3, r8
337 b rd_retry
338
339rd_okay:
340 bl read_32
341 bl read_2
342 ldr r1, =OEN_OUT
343 str r1, [r7, #OFF_OEN]
344 mov r1, r11
345 orrs r1, r1, r6
346 str r1, [r7, #OFF_OUT]
347
348 mov r1, r8 // get COMM_BASE
349 str r3, [r1, #COMM_ARG0]
350 str r0, [r1, #COMM_ARG1]
351 movs r0, #0
352 str r0, [r1, #COMM_RESP]
353#if REPORT_DELAY
354 mov r0, r12
355 str r0, [r1, #COMM_RETRY]
356#endif
357 pop {pc}
358
359
360cmd_write_txn:
361 push {lr}
362
363 ldr r0, =MAX_RETRY
364 mov r12, r0
365
366wr_retry:
367 ldr r3, [r3, #COMM_ARG0]
368 bl write_16
369 push {r3} // stash parity bit
370
371 ldr r3, =OEN_IN
372 str r3, [r7, #OFF_OEN]
373 bl read_4
374
375 lsrs r3, r3, #29
376 cmp r3, #1 // OK
377 beq wr_okay
378
379 pop {r0} // discard saved parity bit
380
381 ldr r1, =OEN_OUT
382 str r1, [r7, #OFF_OEN]
383
384 cmp r3, #2 // WAIT
385 bne err_fail
386
387 mov r0, r12
388 subs r0, r0, #1
389 mov r12, r0
390 beq err_timeout
391
392 mov r3, r8
393 b wr_retry
394
395wr_okay:
396 ldr r3, =OEN_OUT
397 str r3, [r7, #OFF_OEN]
398 bl write_1
399
400 mov r3, r8
401 ldr r3, [r3, #COMM_ARG1]
402 bl write_32
403
404 pop {r3} // recover parity bit
405 bl write_1
406
407 mov r3, r8 // get COMM_BASE
408 movs r0, #0
409 str r0, [r3, #COMM_RESP]
410#if REPORT_DELAY
411 mov r0, r12
412 str r0, [r3, #COMM_RETRY]
413#endif
414 pop {pc}
415
416cmd_reset:
417 push {lr}
418 ldr r3, =0xffffffff
419 mov r12, r3
420 bl write_32
421 mov r3, r12
422 bl write_32
423
424 ldr r3, =0b1110011110011110
425 bl write_16
426
427 mov r3, r12
428 bl write_32
429 mov r3, r12
430 bl write_32
431
432 mov r3, r8
433 movs r0, #0
434 str r0, [r3, #COMM_RESP]
435 pop {pc}
436
437
438m0_irq:
439 push {lr}
440
441 // clear event from m4
442 ldr r0, =M4_TXEV
443 movs r1, #0
444 str r1, [r0]
445
446 mov r3, r8 // get COMM_BASE
447 ldr r0, [r3, #COMM_CMD]
448 cmp r0, #5
449 bls good_cmd
450 movs r0, #0
451good_cmd:
452 lsls r0, r0, #2
453 adr r1, cmd_table
454 ldr r2, [r1, r0]
455 blx r2
456
457 pop {pc}
458
459.align 2
460cmd_table:
461 .word cmd_invalid + 1
462 .word cmd_nop + 1
463 .word cmd_read_txn + 1
464 .word cmd_write_txn + 1
465 .word cmd_reset + 1
466 .word cmd_setclock + 1
467
468cmd_invalid:
469 movs r0, #9
470 str r0, [r3, #COMM_RESP]
471 bx lr
472
473cmd_nop:
474 movs r0, #0
475 str r0, [r3, #COMM_RESP]
476 bx lr
477
478cmd_setclock:
479 ldr r0, [r3, #COMM_ARG0]
480 cmp r0, #8
481 bls good_clock
482 movs r0, #0
483good_clock:
484 lsls r0, r0, #2
485 adr r1, snooze_table
486 ldr r1, [r1, r0]
487 mov r9, r1
488
489 movs r0, #0
490 str r0, [r3, #COMM_RESP]
491 bx lr
492
493.align 2
494snooze_table:
495 .word snooze_2m + 1
496 .word snooze_2m + 1
497 .word snooze_2m + 1
498 .word snooze_3m + 1
499 .word snooze_4m + 1
500 .word snooze_4m + 1
501 .word snooze_6m + 1
502 .word snooze_6m + 1
503 .word snooze_8m + 1
504
505m0_reset:
506 ldr r0, =0x18000000
507 ldr r1, =0xaaaa0000
508 str r1, [r0]
509
510 bl init
511
512 // enable IRQ1 (Event From M4)
513 ldr r0, =0xE000E100
514 movs r1, #2
515 str r1, [r0]
516
517m0_idle:
518 wfi
519 b m0_idle