|
|
1.1 root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.