Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / board-js2x / llfw / startup.S
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13 # SLOF for JS20/JS21 -- ROM boot code.
14 # Initial entry point, copy code from flash to cache, memory setup.
15 # Also sets up serial console and optimizes some settings.
16
17 #include "termctrl.h"
18 #include <product.h>
19 #include <xvect.h>
20 #include <cpu.h>
21 #include <macros.h>
22 #include <southbridge.h>
23
24         .text
25         .globl __start
26 __start:
27         /* put rombase in sprg1 ***********************/
28
29         bl      postHeader
30         .long 0xDEADBEE0
31         .long 0x0       /* size */ 
32         .long 0x0       /* crc  */
33         .long relTag - __start
34 postHeader:
35         mflr    r3
36         li      r4, 0x7fff
37         not     r4, r4
38         and     r3, r3, r4
39         mtsprg  1, r3      /* romfs base */
40         bl      _start
41
42         .org 0x150 - 0x100
43 __startSlave:
44         bl setup_cpu
45         bl set_ci_bit
46 #       b slaveWithNumber
47         b slave
48
49         .org 0x180 - 0x100
50 __startMaster:
51         li 3,0
52         mtsprg  1, r3      /* romfs base */
53         bl setup_cpu
54         bl set_ci_bit
55         b master
56
57
58         /* FIXME: Also need 0280, 0380, 0f20, etc. */
59
60         .irp i, 0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,0x0400,0x0500,0x0600,0x0700, \
61                 0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00, \
62                 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, \
63                 0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00, \
64                 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, \
65                 0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00
66         . = \i
67
68         /* enable this if you get exceptions before the console works    */
69         /* this will allow using the hardware debugger to see where      */
70         /* it traps, and with what register values etc.                  */
71         // b    $
72
73         mtsprg  0, r0
74         mfctr   r0
75         mtsprg  2,r0
76         mflr    r0
77 // 10
78         mtsprg  3,r0
79         ld      r0, (\i + 0x160)(0)
80         mtctr   r0
81         li      r0, \i + 0x100
82 // 20
83         bctr
84
85         . = \i + 0x60
86
87         .quad intHandler2C
88
89         .endr
90
91
92         . = XVECT_M_HANDLER - 0x100
93         .quad 0x00
94         . = XVECT_S_HANDLER - 0x100
95
96         .quad 0
97
98
99
100         .org 0x4000 - 0x100
101 _start:
102         # optimize HID register settings
103         bl setup_cpu
104         bl set_ci_bit
105
106         # read semaphore, run as slave if not the first to do so
107         li 3,0 ; oris 3,3,0xf800 ; lwz 3,0x60(3) ; andi. 3,3,1 ; beq slave
108 master:
109         # setup flash, serial
110         bl setup_sio
111
112         # early greet
113         li      r3, 10
114         bl      putc
115         li 3,13 ; bl putc ; li 3,10 ; bl putc ; li 3,'S' ; bl putc
116
117
118         #do we run from ram ?
119         mfsprg  r3, 1   /* rombase */
120         cmpdi   r3,0    /* rombase is 0 when running from RAM */
121
122         bne copy_to_cache
123
124         # wait a bit, start scripts are slow...  need to get all cores running!
125         lis 3,0x4000 ; mtctr 3 ; bdnz $
126
127         # copy 4MB from 0 to temp memory
128    lis 4,0x8 ; mtctr 4 ; lis 4,0x200  ; li 3,0 ; addi 4,4,-8 ; addi 3,3,-8
129 0:      ldu 5,8(3) ; stdu 5,8(4) ; bdnz 0b
130
131         lis 4,0x200
132         mtsprg  1, r4
133
134         lis 4,0x1
135         lis 3,0x20 ; addi 3,3,0x200-8 ;
136         FLUSH_CACHE(r3, r4)
137
138         lis 4,0x200
139         addi 4,4,copy_to_cache@l
140         mtctr 4
141         bctr
142
143 # make all data accesses cache-inhibited
144 set_ci_bit:
145         SETCI(r0)
146         blr
147
148 # make all data accesses cacheable
149 clr_ci_bit:
150         CLRCI(r0)
151         blr
152
153 # write a character to the serial port
154 putc:
155 # always write to serial1
156 0:      lbz 0,5(13) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(13) ; eieio
157
158 # read ID register: only if it is a PC87427 (JS21) also use serial2
159         li 4,0 ; oris 4,4,0xf400
160         li 5,0x20 ; stb 5,0x2e(4) ; lbz 5,0x2f(4); cmpdi 5,0xf2 ; bne 1f
161
162         addi 4,4,0x2f8
163 0:      lbz 0,5(4) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(4) ; eieio
164
165 1:      blr
166
167 # transfer from running from flash to running from cache
168 return_cacheable:
169         # find and set address to start running from cache, set msr value 
170         mflr 3 ; rldicl 3,3,0,44 
171 jump_cacheable:
172         mtsrr0 3 ; 
173         mfmsr 3 ; ori 3,3,0x1000 ; mtsrr1 3 # enable MCE, as well
174
175         # set cacheable insn fetches, jump to cache
176         mfspr 3,HID1 ; rldicl 3,3,32,0 ; oris 3,3,0x0020 ; rldicl 3,3,32,0
177         sync ; mtspr HID1,3 ; mtspr HID1,3 ; rfid ; b .
178
179
180
181
182 copy_to_cache:
183         # zero the whole cache
184         # also, invalidate the insn cache, to clear parity errors
185         # 128kB @ 0MB (boot code and vectors from 0x0 up to 0x20000)
186         li 4,0x400 ; mtctr 4 ; li 5,0x0 ; bl clr_ci_bit
187 0:      dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b
188
189         # 0x2000 to 0x100000/0x80000 (smaller on 970/970FX)
190         li 4,0x1C00 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0xC00
191 0:
192         mtctr 4 ; li 5,0x2000
193 0:      dcbz 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b ; bl set_ci_bit
194
195         # find base address
196         bcl 20,31,$+4 ; mflr 31 ; rldicr 31,31,0,43
197
198         # copy 1kB from 0x4000
199         li 4,0x80 ; mtctr 4 ; 
200         li      5,0x3ff8
201         addi 3,31,0x3ff8
202 0:      ldu 4,8(3) ; bl clr_ci_bit ; stdu 4,8(5) ; bl set_ci_bit ; bdnz 0b
203         # now start executing from cache -- insn cache is huge speed boost
204
205         bl return_cacheable
206
207         li 3,'L' ; bl putc
208
209         # copy 128kB of flash to cache
210         li 4,0x800 ; mtctr 4 ; li 5,0x200-64 ; addi 3,31,0x200-64 ; 
211 0:      ldu 16,64(3) ; ld 17,8(3) ; ld 18,16(3) ; ld 19,24(3)
212         ld 20,32(3) ; ld 21,40(3) ; ld 22,48(3) ; ld 23,56(3)
213         bl clr_ci_bit
214         stdu 16,64(5) ; std 17,8(5) ; std 18,16(5) ; std 19,24(5)
215         std 20,32(5) ; std 21,40(5) ; std 22,48(5) ; std 23,56(5)
216         icbi 0,5 ; bl set_ci_bit ; bdnz 0b ; isync
217
218
219         li 3,'O' ; bl putc
220
221         lis 4,0x20
222         mfsprg  r3,1
223         cmpd r3,r4
224         beq 1f
225
226         // at 0xf8000000 we decide if it is u3 or u4
227         li 4,0 ; oris 4,4,0xf800 ; lwz 3,0(4) ; srdi 3,3,4 ; cmpdi 3,3 ; bne 0f
228         bl setup_mem_u3
229         bl setup_mem_size
230         b 1f
231 0:
232
233 1:
234         li 3,'F' ; bl putc
235
236         # setup nvram logging only when not running from RAM
237         mfsprg  r3, 1   /* rombase */
238         cmpdi   r3, 0   /* rombase is 0 when running from RAM */
239         beq     0f
240
241         // at 0xf8000000 we decide if it is u3 or u4
242         li      r4, 0
243         oris    r4, r4, 0xf800
244         lwz     r3, 0(r4)
245         srdi    r3, r3, 4
246         cmpdi   r3, 3   /* 3 means js20; no nvram logging on js20 */
247         beq     0f
248
249         bl      io_log_init
250 0:
251
252         #bl print_mem
253
254         # data is cacheable by default from now on
255         bl clr_ci_bit
256
257
258         /* give live sign *****************************/
259         bl      0f
260         .ascii  TERM_CTRL_RESET
261         .ascii  TERM_CTRL_CRSOFF
262         .ascii  " **********************************************************************"
263         .ascii  "\r\n"
264         .ascii  TERM_CTRL_BRIGHT
265         .ascii  PRODUCT_NAME
266         .ascii  " Starting\r\n"
267         .ascii  TERM_CTRL_RESET
268         .ascii  " Build Date = ", __DATE__, " ", __TIME__
269         .ascii  "\r\n"
270         .ascii  " FW Version = " , RELEASE
271         .ascii  "\r\n\0"
272         .align  2
273 0:      mflr    r3
274         bl      io_print
275
276         # go!
277         li      r3,__startC@l
278         mtctr   r3
279         mfsprg  r10, 1
280         bctrl
281
282 relTag:
283         .ascii  RELEASE
284         .ascii  "\0"
285         .align  2
286
287 slave:
288
289         # get cpu number
290         li 3,0 ; oris 3,3,0xf800 ; lwz 28,0x50(3)
291
292 slaveWithNumber:
293         # create our slave loop address
294         sldi 3,28,24 ; oris 3,3,0x3000
295
296         # invalidate the insn cache, to clear parity errors
297         # clear the L2 cache as well, to get ECC right
298         li 4,0x2000 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0x1000
299 0:      mtctr 4 ; mr 5,3 ; bl clr_ci_bit
300
301 0:      dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b
302
303
304         # write a "b $" insn in there
305         lis 4,0x4800 ; stw 4,0(3)
306 /*
307         mr 5,3
308
309         # jump there
310         bl set_ci_bit
311         li 13,0 ; oris 13,13,0xf400
312         # device address
313         addi 13,13,0x2f8
314         li 3,'O' ; add 3,3,28 ; bl putc
315         bl clr_ci_bit
316         mr 3,5
317 */
318         b jump_cacheable
319
320
321
322
323 # allow the flash chip to be accessed faster
324 # initialize the 16550-compatible uart on serial port 1 of the sio
325 setup_sio:
326
327         # i/o base address
328         li 3,0 ; oris 3,3,0xf400
329
330         # i/o base address
331         li 3,0 ; oris 3,3,0xf400
332
333         # put x-bus in turbo mode
334         li 4,0xf1 ; stb 4,0x400(3) ; eieio
335
336
337         # select sio serial1
338         li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio
339
340         # set base address to 3f8
341         li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio
342
343         # enable device
344         li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio
345
346         # read ID register: only if it is a PC87427, enable serial2
347         li 4,0x20 ; stb 4,0x2e(3) ; eieio ; lbz 4,0x2f(3) ; cmpdi 4,0xf2 ; bne 0f
348
349         # select sio serial2
350         li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio
351
352         # set base address to 2f8
353         li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio
354
355         # enable device
356         li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio
357
358         # uart @0x2f8
359         addi 3,3,0x2f8
360
361         # disable interrupts, fifo off
362         li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio
363
364         # set serial speed
365         li 4,0x80 ; stb 4,3(3) ; eieio
366         li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio
367
368         # set 8-N-1, set RTS and DTR
369         li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio
370
371         eieio
372
373         addi 3,3,-0x2f8
374
375         # uart @0x3f8
376 0:      addi 3,3,0x3f8
377
378         # disable interrupts, fifo off
379         li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio
380
381         # set serial speed
382         li 4,0x80 ; stb 4,3(3) ; eieio
383         li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio
384
385         # set 8-N-1, set RTS and DTR
386         li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio
387
388         eieio
389
390         # save UART base for putc routine
391 0:      mr 13,3
392
393         blr
394
395
396
397
398 # set the HID registers of the 970 for optimally executing from flash
399 setup_cpu:
400
401         /* clear all the HV cruft */
402         li      r0, 0
403         sync
404         mtspr   HID4, r0
405         isync
406
407         /* enable dpm, disable attn insn, enable external mce
408          * first, try external time base; if clock doesn't run, switch to
409          * internal */
410         li      r0, 1                   /* do the setup for external timebase */
411         rldicl  r0, r0, 44, 0           /* bit 19 has to be set */
412         oris    r0, r0, 0x8000          /* Enable external machine check */
413                                         /* interrupts (preferred state */
414                                         /* equals `1'). */
415         sync
416         mtspr   HID0, r0
417         isync
418
419         mftb    r3                      /* read the timebase */
420         li      r1, 0x4000              /* wait long enough for the external */
421         mtctr   r1                      /* timebase (14MHz) to tick a bit */
422         bdnz    $                       /* 0x4000 seems to be enough (for now) */
423         mftb    r4                      /* read the timebase a second time */
424         cmpld   r3, r4                  /* see if it changed */
425         bne     0f
426         /* timebase did not change, do the setup for internal */
427         rldicl  r0, r0, 19, 1
428         rldicl  r0, r0, 45, 0
429         sync
430         mtspr   HID0, r0
431         isync
432
433 0:
434         /* enable insn prefetch, speculative table walks */
435         mfspr   r0, HID1
436         rldicl  r0, r0, 20, 0
437         ori     r0, r0, 0x1002
438         mfsprg  r3, 1                   /* read rombase */
439         cmpdi   r3, 0                   /* check if running from ram */
440         bne     0f
441         /* running from ram */
442         /* Enable instruction fetch cacheability control */
443         ori     r0, r0, 0x200
444 0:
445         rldicl  r0, r0, 44, 0
446         sync
447         mtspr   HID1, r0
448         isync
449
450         /* enable cache parity */
451         mfspr   r0, HID4
452         oris    r0, r0, 0xfff0
453         xoris   r0, r0, 0xfff0
454         sync
455         mtspr   HID4, r0
456         isync
457
458         /* exception offset at 0 */
459         li      r3, 0
460         mtspr   HIOR, r3
461
462         blr
463
464 C_ENTRY(proceedInterrupt)
465
466         ld      r3,exception_stack_frame@got(r2)
467         ld      r1,0(r3)
468
469         .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
470                 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
471                 27, 28, 29, 30, 31
472         ld      r\i, 0x30+\i*8 (r1)
473         .endr
474
475         ld      r14,0x138(r1);
476         mtsrr0  r14
477
478         ld      r14,0x140(r1);
479         mtsrr1  r14
480
481         ld      r14,0x148(r1);
482         mtcr    r14
483
484
485         ld 0,XVECT_M_HANDLER(0)
486         mtctr 0
487
488         ld      r0,0x30(r1); # restore vector number
489         ld      r1,0x38(r1);
490
491         bctr
492
493 intHandler2C:
494         mtctr   r1 # save old stack pointer
495         lis     r1,0x4
496         stdu    r1, -0x160(r1)
497         .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
498                 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
499                 27, 28, 29, 30, 31
500         std     r\i, 0x30+\i*8 (r1)
501         .endr
502
503         std     r0,0x30(r1);  # save vector number
504
505         mfctr   r14
506         std     r14,0x38(r1); # save old r1
507
508         mfsrr0  r14
509         std     r14,0x138(r1);
510
511         mfsrr1  r14
512         std     r14,0x140(r1);
513
514         mfcr    r14
515         std     r14,0x148(r1);
516
517         mfxer   r14
518         std     r14,0x150(r1);
519
520         bl toc_init
521
522         ld      r3,exception_stack_frame@got(r2)
523         std     r1,0(r3)
524
525
526         mr      r3,r0
527         bl .c_interrupt
528
529         ld      r14,0x138(r1);
530         mtsrr0  r14
531
532         ld      r14,0x140(r1);
533         mtsrr1  r14
534
535         ld      r14,0x148(r1);
536         mtcr    r14
537
538         ld      r14,0x150(r1);
539         mtxer   r14
540
541
542         .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
543                 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
544                 27, 28, 29, 30, 31
545         ld      r\i, 0x30+\i*8 (r1)
546         .endr
547
548         ld      r1,0x38(r1);
549
550         mfsprg  r0,2
551         mtctr   r0
552         mfsprg  r0,3
553         mtlr    r0
554         mfsprg  r0,0
555         rfid
556
557 /* Set exception handler for given exception vector.  
558         r3:     exception vector offset
559         r4:     exception handler
560 */
561         .globl .set_exception
562 .set_exception:
563         .globl set_exception
564 set_exception:
565     ld r4,0x0(r4)
566         .globl .set_exception_asm
567 .set_exception_asm:
568         .globl set_exception_asm
569 set_exception_asm:
570         std     r4, 0x60(r3)    # fixme diff 1f - 0b
571         blr
572
573
574 setup_mem_u3:
575         li 4,0x2000 ; oris 4,4,0xf800
576
577         # MemTimingParam -- CAS lat 2.5 / 4 (read-to-read / read-to-write)
578         lis 3,0x49e1 ; ori 3,3,0xa000 ; stw 3,0x50(4)
579
580         # MRSRegCntl -- CAS lat 2.5
581         li 3,0x6a ; stw 3,0xf0(4)
582
583         # MemBusConfig -- 128 bit bus
584         lis 3,0x8500 ; stw 3,0x190(4)
585
586         # CKDelAdj -- clock delay 75
587         lis 3,0x12c3 ; ori 3,3,0x30cc ; stw 3,0x520(4)
588
589         # IOModeCntl -- no termination on differential and 3-state drivers
590         lis 3,0x0350 ; stw 3,0x530(4)
591
592         li 3,18 ; mtctr 3 ; addi 5,4,0x5f0
593 0:      # DQSDelAdj -- read delay offset -10
594         lis 3,0x3d8f ; ori 3,3,0x6000 ; stwu 3,0x10(5)
595
596         # DQSDataDelAdj -- write delay offset -32, write data delay offset +15
597         lis 3,0x380e ; ori 3,3,0x003c ; stwu 3,0x10(5)
598         bdnz 0b
599
600         # MemProgCntl -- set all
601         lis 3,0xc000 ; stw 3,0xe0(4)
602
603         eieio
604
605         blr
606
607
608 # read dimm SPDs, program memory size and type
609 setup_mem_size:
610         mflr 14
611
612         li 15,0 ; oris 15,15,0xf800 ; li 17,0
613         li 3,0xa0 ; li 4,3 ; li 5,3 ; bl i2c_read
614         mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0
615 0:      li 3,0xa2 ; li 4,3 ; li 5,3 ; bl i2c_read
616         cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f
617 0:      li 16,0x1e00
618 1:      #li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte
619         #mr 3,16 ; bl print_hex
620
621         #li 3,0x20 ; bl print_byte
622         sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00
623         stw 3,0x21c0(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x21e0(15)
624 0:      #bl print_hex
625         sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3
626                 # slw, not sld, so that empty/bad banks translate into size 0
627         stw 17,0x21d0(15) ; bl add17173 ; stw 17,0x21f0(15)
628         andi. 0,16,2 ; beq 0f ; bl add17173
629 0:      #bl print_hex
630
631         li 3,0xa4 ; li 4,3 ; li 5,3 ; bl i2c_read
632         mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0
633 0:      li 3,0xa6 ; li 4,3 ; li 5,3 ; bl i2c_read
634         cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f
635 0:      li 16,0x1e00
636 1:      #li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte
637         #mr 3,16 ; bl print_hex
638
639         #li 3,0x20 ; bl print_byte
640         sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00
641         stw 3,0x2200(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x2220(15)
642 0:      #bl print_hex
643         sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3
644         stw 17,0x2210(15) ; bl add17173 ; stw 17,0x2230(15)
645         andi. 0,16,2 ; beq 0f ; bl add17173
646 0:      #bl print_hex
647         #mr 3,17 ; bl print_hex
648         stw 17,0x2250(15) ; stw 17,0x2270(15)
649         stw 17,0x2290(15) ; stw 17,0x22b0(15)
650
651         mtlr 14
652         blr
653
654
655
656
657 # print GPR3 as 8-digit hex.  uses GPR18,19
658 print_hex:
659         mflr 18 ; mr 19,3 ; li 3,8 ; mtctr 3
660 1:      rlwinm 3,19,4,28,31 ; sldi 19,19,4
661         cmpdi 3,0xa ; blt 0f ; addi 3,3,0x27
662 0:      addi 3,3,0x30 ; bl putc
663         bdnz 1b ; mtlr 18 ; blr
664
665
666 # i2c stuff uses GPR20..GPR24
667
668 # terminate any i2c transaction, at any point during that transaction
669 i2c_stop:
670 0:      lwz 3,0x30(20) ; stw 3,0x30(20) ; andi. 3,3,4 ; beq 0b
671         mr 3,21 ; mr 4,22 ; mtlr 24 ; eieio ; blr
672
673 # do a combined-mode read
674 # in: GPR3 = addr, GPR4 = subaddr, GPR5 = len
675 # out: GPR3 = error, GPR4 = result (right-aligned, msb)
676 i2c_read:
677         mflr 24
678         li 20,0x1000 ; oris 20,20,0xf800        # uni-n i2c base
679         mr 21,3 ; mr 22,4 ; mr 23,5             # save params
680         li 4,0xc ; stw 4,0(20)                  # set mode (combined)
681         ori 4,21,1 ; stw 4,0x50(20)             # set addr, read
682         stw 22,0x60(20)                         # set subaddr
683         li 4,2 ; stw 4,0x10(20) ; eieio         # start address phase
684         li 21,1                                 # error
685         li 22,0                                 # result accumulator
686 0:      lwz 3,0x30(20) ; andi. 3,3,2 ; beq 0b   # wait until sent
687         lwz 3,0x20(20) ; andi. 3,3,2 ; beq i2c_stop # check result
688         li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0
689 0:      stw 4,0x10(20)                          # AAK for next byte (or not)
690         li 4,2 ; stw 4,0x30(20) ; eieio         # ack address phase
691 i2c_read_loop:
692         lwz 3,0x30(20) ; andi. 3,3,1 ; beq 1f   # if byte recv'd:
693         subi 23,23,1 ; sldi 22,22,8             # shift byte accum
694         lwz 3,0x70(20) ; rlwimi 22,3,0,24,31    # get byte
695         cmpdi 23,0 ; bne 0f ; li 21,0 ; b i2c_stop # all done
696 0:      li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0
697 0:      stw 4,0x10(20)                          # AAK for next byte (or not)
698         li 4,1 ; stw 4,0x30(20) ; eieio         # ack data phase
699 1:      lwz 3,0x30(20) ; andi. 3,3,4 ; beq i2c_read_loop
700         li 4,0 ; stw 4,0x10(20) ; eieio ; b i2c_stop # stop bit received
701
702 add17173: # add GPR3 into GPR17; if passing 2GB (0x10000000), add another 2GB.
703         lis 0,0x1000 ; cmpld 17,0 ; add 17,17,3 ; bgtlr
704         cmpld 17,0 ; blelr ; add 17,17,0 ; blr
705
706 io_log_init:
707         LOAD64(r3, SB_NVRAM_adr)
708         b checkinitLog