]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/eltec/elppc/asm_init.S
Initial revision
[karo-tx-uboot.git] / board / eltec / elppc / asm_init.S
1 /*
2  * (C) Copyright 2001 ELTEC Elektronik AG
3  * Frank Gottschling <fgottschling@eltec.de>
4  *
5  * ELTEC ELPPC RAM initialization
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26 #include <config.h>
27 #include <version.h>
28 #include <mpc106.h>
29
30 #include <ppc_asm.tmpl>
31 #include <ppc_defs.h>
32
33 .globl board_asm_init
34 board_asm_init:
35
36 /*
37  * setup pointer to message block
38  */
39     mflr    r13                 /* save away link register */
40     bl      get_lnk_reg         /* r3=addr of next instruction */
41     subi    r4, r3, 8           /* r4=board_asm_init addr */
42     addi    r29, r4, (MessageBlock-board_asm_init)
43
44 /*
45  * dcache_disable
46  */
47     mfspr   r3, HID0
48     li      r4, HID0_DCE
49     andc    r3, r3, r4
50     mr      r2, r3
51     ori     r3, r3, HID0_DCI
52     sync
53     mtspr   HID0, r3
54     mtspr   HID0, r2
55     isync
56     sync
57 /*
58  * icache_disable
59  */
60     mfspr   r3, HID0
61     li      r4, 0
62     ori     r4, r4, HID0_ICE
63     andc    r3, r3, r4
64     sync
65     mtspr   HID0, r3
66 /*
67  * invalidate caches
68  */
69     ori     r3, r3, (HID0_ICE | HID0_ICFI | HID0_DCI | HID0_DCE)
70     or      r4, r4, r3
71     isync
72     mtspr   HID0, r4
73     andc    r4, r4, r3
74     isync
75     mtspr   HID0, r4
76     isync
77 /*
78  * icache_enable
79  */
80     mfspr   r3, HID0
81     ori     r3, r3, (HID0_ICE | HID0_ICFI)
82     sync
83     mtspr   HID0, r3
84
85
86 /*
87  * setup memory controller
88  */
89     lis     r1, MPC106_REG_ADDR@h
90     ori     r1, r1, MPC106_REG_ADDR@l
91     lis     r2, MPC106_REG_DATA@h
92     ori     r2, r2, MPC106_REG_DATA@l
93
94     /* Configure PICR1 */
95     lis     r3, MPC106_REG@h
96     ori     r3, r3, PCI_PICR1
97     stwbrx  r3, 0, r1
98     addis   r3, r0, 0xFF14
99     ori     r3, r3, 0x1CC8
100     eieio
101     stwbrx  r3, 0, r2
102
103     /* Configure PICR2 */
104     lis     r3, MPC106_REG@h
105     ori     r3, r3, PCI_PICR2
106     stwbrx  r3, 0, r1
107     addis   r3, r0, 0x0000
108     ori     r3, r3, 0x0000
109     eieio
110     stwbrx  r3, 0, r2
111
112     /* Configure EUMBAR */
113     lis     r3, MPC106_REG@h
114     ori     r3, r3, 0x0078      /* offest of EUMBAR in PCI config space */
115     stwbrx  r3, 0, r1
116     lis     r3, MPC107_EUMB_ADDR@h
117     eieio
118     stwbrx  r3, 0, r2
119
120     /* Configure Address Map B Option Reg */
121     lis     r3, MPC106_REG@h
122     ori     r3, r3, 0x00e0      /* offest of AMBOR in PCI config space */
123     stwbrx  r3, 0, r1
124     lis     r3, 0
125     eieio
126     stwbrx  r3, 0, r2
127
128     /* Configure I2C Controller */
129     lis     r14, MPC107_I2C_ADDR@h  /* base of I2C controller */
130     ori     r14, r14, MPC107_I2C_ADDR@l
131     lis     r3, 0x2b10          /* I2C clock = 100MHz/1024 */
132     stw     r3, 4(r14)
133     li      r3, 0               /* clear arbitration */
134     eieio
135     stw     r3, 12(r14)
136
137     /* Configure MCCR1 */
138     lis     r3, MPC106_REG@h
139     ori     r3, r3, MPC106_MCCR1
140     stwbrx  r3, 0, r1
141     addis   r3, r0, 0x0660      /* don't set MEMGO now ! */
142     ori     r3, r3, 0x0000
143     eieio
144     stwbrx  r3, 0, r2
145
146     /* Configure MCCR2 */
147     lis     r3, MPC106_REG@h
148     ori     r3, r3, MPC106_MCCR2
149     stwbrx  r3, 0, r1
150     addis   r3, r0, 0x0400
151     ori     r3, r3, 0x1800
152     eieio
153     stwbrx  r3, 0, r2
154
155
156     /* Configure MCCR3 */
157     lis     r3, MPC106_REG@h
158     ori     r3, r3, MPC106_MCCR3
159     stwbrx  r3, 0, r1
160     addis   r3, r0, 0x0230
161     ori     r3, r3, 0x0000
162     eieio
163     stwbrx  r3, 0, r2
164
165     /* Configure MCCR4 */
166     lis     r3, MPC106_REG@h
167     ori     r3, r3, MPC106_MCCR4
168     stwbrx  r3, 0, r1
169     addis   r3, r0, 0x2532
170     ori     r3, r3, 0x2220
171     eieio
172     stwbrx  r3, 0, r2
173
174 /*
175  * configure memory interface (MICRs)
176  */
177     addis   r3, r0, 0x8000      /* ADDR_80 */
178     ori     r3, r3, 0x0080      /* SMEMADD1 */
179     stwbrx  r3, 0, r1
180     addis   r3, r0, 0xFFFF
181     ori     r3, r3, 0x4000
182     eieio
183     stwbrx  r3, 0, r2
184
185     addis   r3, r0, 0x8000      /* ADDR_84 */
186     ori     r3, r3, 0x0084      /* SMEMADD2 */
187     stwbrx  r3, 0, r1
188     addis   r3, r0, 0xFFFF
189     ori     r3, r3, 0xFFFF
190     eieio
191     stwbrx  r3, 0, r2
192
193     addis   r3, r0, 0x8000      /* ADDR_88 */
194     ori     r3, r3, 0x0088      /* EXTSMEM1 */
195     stwbrx  r3, 0, r1
196     addis   r3, r0, 0x0303
197     ori     r3, r3, 0x0000
198     eieio
199     stwbrx  r3, 0, r2
200
201     addis   r3, r0, 0x8000      /* ADDR_8C */
202     ori     r3, r3, 0x008c      /* EXTSMEM2 */
203     stwbrx  r3, 0, r1
204     addis   r3, r0, 0x0303
205     ori     r3, r3, 0x0303
206     eieio
207     stwbrx  r3, 0, r2
208
209     addis   r3, r0, 0x8000      /* ADDR_90 */
210     ori     r3, r3, 0x0090      /* EMEMADD1 */
211     stwbrx  r3, 0, r1
212     addis   r3, r0, 0xFFFF
213     ori     r3, r3, 0x7F3F
214     eieio
215     stwbrx  r3, 0, r2
216
217     addis   r3, r0, 0x8000      /* ADDR_94 */
218     ori     r3, r3, 0x0094      /* EMEMADD2 */
219     stwbrx  r3, 0, r1
220     addis   r3, r0, 0xFFFF
221     ori     r3, r3, 0xFFFF
222     eieio
223     stwbrx  r3, 0, r2
224
225     addis   r3, r0, 0x8000      /* ADDR_98 */
226     ori     r3, r3, 0x0098      /* EXTEMEM1 */
227     stwbrx  r3, 0, r1
228     addis   r3, r0, 0x0303
229     ori     r3, r3, 0x0000
230     eieio
231     stwbrx  r3, 0, r2
232
233     addis   r3, r0, 0x8000      /* ADDR_9C */
234     ori     r3, r3, 0x009c      /* EXTEMEM2 */
235     stwbrx  r3, 0, r1
236     addis   r3, r0, 0x0303
237     ori     r3, r3, 0x0303
238     eieio
239     stwbrx  r3, 0, r2
240
241     addis   r3, r0, 0x8000      /* ADDR_A0 */
242     ori     r3, r3, 0x00a0      /* MEMBNKEN */
243     stwbrx  r3, 0, r1
244     addis   r3, r0, 0x0000
245     ori     r3, r3, 0x0003
246     eieio
247     stwbrx  r3, 0, r2
248
249 /*
250  * must wait at least 100us after HRESET to issue a MEMGO
251  */
252     lis     r0, 1
253     mtctr   r0
254 memStartWait:
255     bdnz    memStartWait
256
257 /*
258  * enable RAM Operations through MCCR1 (MEMGO)
259  */
260     lis     r3, 0x8000
261     ori     r3, r3, 0x00f0
262     stwbrx  r3, r0, r1
263     sync
264     lwbrx   r3, 0, r2
265     lis     r0, 0x0008
266     or      r3, r0, r3
267     stwbrx  r3, 0, r2
268     sync
269
270 /*
271  * set LEDs first time
272  */
273     li      r3, 0x1
274     lis     r30, CFG_USR_LED_BASE@h
275     stb     r3, 2(r30)
276     sync
277
278 /*
279  * init COM1 for polled output
280  */
281     lis     r8, CFG_NS16550_COM1@h  /* COM1 base address*/
282     ori     r8, r8, CFG_NS16550_COM1@l
283     li      r9, 0x00
284     stb     r9, 1(r8)           /* int disabled */
285     eieio
286     li      r9, 0x00
287     stb     r9, 4(r8)           /* modem ctrl */
288     eieio
289     li      r9, 0x80
290     stb     r9, 3(r8)           /* link ctrl */
291     eieio
292     li      r9, (CFG_NS16550_CLK / 16 / CONFIG_BAUDRATE)
293     stb     r9, 0(r8)           /* baud rate (LSB)*/
294     eieio
295     li      r9, ((CFG_NS16550_CLK / 16 / CONFIG_BAUDRATE) >> 8)
296     stb     r9, 1(r8)           /* baud rate (MSB) */
297     eieio
298     li      r9, 0x07
299     stb     r9, 3(r8)           /* 8 data bits, 2 stop bit, no parity */
300     eieio
301     li      r9, 0x0b
302     stb     r9, 4(r8)           /* enable the receiver and transmitter (modem ctrl) */
303     eieio
304 waitEmpty:
305     lbz     r9, 5(r8)           /* transmit empty */
306     andi.   r9, r9, 0x40
307     beq     waitEmpty
308     li      r9, 0x47
309     stb     r9, 3(r8)           /* send break, 8 data bits, 2 stop bit, no parity */
310     eieio
311
312     lis     r0, 0x0001
313     mtctr   r0
314 waitCOM1:
315     lwz     r0, 5(r8)           /* load from port for delay */
316     bdnz    waitCOM1
317
318 waitEmpty1:
319     lbz     r9, 5(r8)           /* transmit empty */
320     andi.   r9, r9, 0x40
321     beq     waitEmpty1
322     li      r9, 0x07
323     stb     r9, 3(r8)           /* 8 data bits, 2 stop bit, no parity */
324     eieio
325
326 /*
327  * intro message from message block
328  */
329     addi    r3, r29, (MnewLine-MessageBlock)
330     bl      Printf
331     addi    r3, r29, (MinitLogo-MessageBlock)
332     bl      Printf
333
334 /*
335  * memory cofiguration using SPD information stored on the SODIMMs
336  */
337     addi    r3, r29, (Mspd01-MessageBlock)
338     bl      Printf
339
340     li      r17, 0
341
342     li      r3, 0x0002          /* get RAM type from spd for bank0/1 */
343     bl      spdRead
344
345     cmpi    0, 0, r3, -1        /* error ? */
346     bne     noSpdError
347
348     addi    r3, r29, (Mfail-MessageBlock)
349     bl      Printf
350
351     li      r6, 0xe             /* error codes in r6 and r7  */
352     li      r7, 0x0
353     b       toggleError         /* fail - loop forever */
354
355 noSpdError:
356     mr      r15, r3             /* save r3 */
357
358     addi    r3, r29, (Mok-MessageBlock)
359     bl      Printf
360
361     cmpli   0, 0, r15, 0x0004   /* SDRAM ? */
362     beq     isSDRAM
363
364     addi    r3, r29, (MramTyp-MessageBlock)
365     bl      Printf
366
367     li      r6, 0xd             /* error codes in r6 and r7  */
368     li      r7, 0x0
369     b       toggleError         /* fail - loop forever */
370
371 isSDRAM:
372     li      r3, 0x0012          /* get supported CAS latencies from byte 18 */
373     bl      spdRead
374     mr      r15, r3
375     li      r3, 0x09
376     andi.   r0, r15, 0x04
377     bne     maxCLis3
378     li      r3, 0x17
379 maxCLis3:
380     andi.   r0, r15, 0x02
381     bne     CL2
382
383     addi    r3, r29, (MramTyp-MessageBlock)
384     bl      Printf
385
386     li      r6, 0xc             /* error codes in r6 and r7  */
387     li      r7, 0x0
388     b       toggleError         /* fail - loop forever */
389 CL2:
390     bl      spdRead
391     cmpli   0, 0, r3, 0xa1      /* cycle time must be 10ns max. */
392     blt     speedOk
393
394     addi    r3, r29, (MramTyp-MessageBlock)
395     bl      Printf
396
397     li      r6, 0xb             /* error codes in r6 and r7  */
398     li      r7, 0x0
399     b       toggleError         /* fail - loop forever */
400 speedOk:
401     lis     r20, 0x06e8         /* preset MCR1 value */
402
403     li      r3, 0x0011          /* get number of internal banks from spd for bank0/1 */
404     bl      spdRead
405
406     cmpli   0, 0, r3, 0x02
407     beq     SD_2B
408     cmpli   0, 0, r3, 0x04
409     beq     SD_4B
410 memConfErr:
411     addi    r3, r29, (MramConfErr-MessageBlock)
412     bl      Printf
413
414     li      r6, 0xa             /* error codes in r6 and r7  */
415     li      r7, 0x0
416     b       toggleError         /* fail - loop forever */
417
418 SD_2B:
419     li      r3, 0x0003          /* get number of row bits from spd for bank0/1 */
420     bl      spdRead
421     cmpli   0, 0, r3, 0x0b
422     beq     row11x2
423     cmpli   0, 0, r3, 0x0c
424     beq     row12x2or13x2
425     cmpli   0, 0, r3, 0x0d
426     beq     row12x2or13x2
427     b       memConfErr
428 SD_4B:
429     li      r3, 0x0003          /* get number of row bits from spd for bank0/1 */
430     bl      spdRead
431     cmpli   0, 0, r3, 0x0b
432     beq     row11x4or12x4
433     cmpli   0, 0, r3, 0x0c
434     beq     row11x4or12x4
435     cmpli   0, 0, r3, 0x0d
436     beq     row13x4
437     b       memConfErr
438 row12x2or13x2:
439     ori     r20, r20, 0x05
440     b       row11x4or12x4
441 row13x4:
442     ori     r20, r20, 0x0a
443     b       row11x4or12x4
444 row11x2:
445     ori     r20, r20, 0x0f
446 row11x4or12x4:
447     /* get the size of bank 0-1 */
448
449     li      r3, 0x001f          /* get bank size from spd for bank0/1 */
450     bl      spdRead
451
452     rlwinm  r16, r3, 2, 24, 29  /* calculate size in MByte (128 MB max.) */
453
454     li      r3, 0x0005          /* get number of banks from spd for bank0/1 */
455     bl      spdRead
456
457     cmpi    0, 0, r3, 2         /* 2 banks ? */
458     bne     SDRAMnobank1
459
460     mr      r17, r16
461
462 SDRAMnobank1:
463     li      r3, 0x000c          /* get refresh from spd for bank0/1 */
464     bl      spdRead
465     andi.   r3, r3, 0x007f      /* mask selfrefresh bit */
466     li      r4, 0x1800          /* refesh cycle 1536 clocks left shifted 2 */
467     cmpli   0, 0, r3, 0x0000    /* 15.6 us ? */
468     beq     writeRefresh
469
470     li      r4, 0x0c00          /* refesh cycle 768 clocks left shifted 2 */
471     cmpli   0, 0, r3, 0x0002    /* 7.8 us ? */
472     beq     writeRefresh
473
474     li      r4, 0x3000          /* refesh cycle 3072 clocks left shifted 2 */
475     cmpli   0, 0, r3, 0x0003    /* 31.3 us ? */
476     beq     writeRefresh
477
478     li      r4, 0x6000          /* refesh cycle 6144 clocks left shifted 2 */
479     cmpli   0, 0, r3, 0x0004    /* 62.5 us ? */
480     beq     writeRefresh
481
482     li      r4, 0
483     ori     r4, r4, 0xc000      /* refesh cycle 8224 clocks left shifted 2 */
484     cmpli   0, 0, r3, 0x0005    /* 125 us ? */
485     beq     writeRefresh
486
487     b       memConfErr
488
489 writeRefresh:
490     lis     r21, 0x0400         /* preset MCCR2 value */
491     or      r21, r21, r4
492
493     /* Overwrite MCCR1 */
494     lis     r3, MPC106_REG@h
495     ori     r3, r3, MPC106_MCCR1
496     stwbrx  r3, 0, r1
497     eieio
498     stwbrx  r20, 0, r2
499
500     /* Overwrite MCCR2 */
501     lis     r3, MPC106_REG@h
502     ori     r3, r3, MPC106_MCCR2
503     stwbrx  r3, 0, r1
504     eieio
505     stwbrx  r21, 0, r2
506
507     /* set the memory boundary registers for bank 0-3 */
508     li      r20, 0
509     lis     r23, 0x0303
510     lis     r24, 0x0303
511     subi    r21, r16, 1         /* calculate end address bank0 */
512     li      r22, 1
513
514     cmpi    0, 0, r17, 0        /* bank1 present ? */
515     beq     nobank1
516
517     andi.   r3, r16, 0x00ff     /* calculate start address of bank1 */
518     andi.   r4, r16, 0x0300
519     rlwinm  r3, r3, 8, 16, 23
520     or      r20, r20, r3
521     or      r23, r23, r4
522
523     add     r16, r16, r17       /* add to total memory size */
524
525     subi    r3, r16, 1          /* calculate end address of bank1 */
526     andi.   r4, r3, 0x0300
527     andi.   r3, r3, 0x00ff
528     rlwinm  r3, r3, 8, 16, 23
529     or      r21, r21, r3
530     or      r24, r24, r4
531
532     ori     r22, r22, 2         /* enable bank1 */
533     b       bankOk
534 nobank1:
535     ori     r23, r23, 0x0300    /* set bank1 start to unused area */
536     ori     r24, r24, 0x0300    /* set bank1 end to unused area */
537 bankOk:
538     addi    r3, r29, (Mactivate-MessageBlock)
539     bl      Printf
540     mr      r3, r16
541     bl      OutDec
542     addi    r3, r29, (Mact0123e-MessageBlock)
543     bl      Printf
544
545 /*
546  * overwrite MSAR1, MEAR1, EMSAR1, and EMEAR1
547  */
548     addis   r3, r0, 0x8000      /* ADDR_80 */
549     ori     r3, r3, 0x0080      /* MSAR1 */
550     stwbrx  r3, 0, r1
551     eieio
552     stwbrx  r20, 0, r2
553
554     addis   r3, r0, 0x8000      /* ADDR_88 */
555     ori     r3, r3, 0x0088      /* EMSAR1 */
556     stwbrx  r3, 0, r1
557     eieio
558     stwbrx  r23, 0, r2
559
560     addis   r3, r0, 0x8000      /* ADDR_90 */
561     ori     r3, r3, 0x0090      /* MEAR1 */
562     stwbrx  r3, 0, r1
563     eieio
564     stwbrx  r21, 0, r2
565
566     addis   r3, r0, 0x8000      /* ADDR_98 */
567     ori     r3, r3, 0x0098      /* EMEAR1 */
568     stwbrx  r3, 0, r1
569     eieio
570     stwbrx  r24, 0, r2
571
572     addis   r3, r0, 0x8000      /* ADDR_A0 */
573     ori     r3, r3, 0x00a0      /* MBER */
574     stwbrx  r3, 0, r1
575     eieio
576     stwbrx  r22, 0, r2
577
578 /*
579  * delay to let SDRAM go through several initialization/refresh cycles
580  */
581     lis     r3, 3
582     mtctr   r3
583 memStartWait_1:
584     bdnz    memStartWait_1
585     eieio
586
587 /*
588  * set LEDs end
589  */
590     li      r3, 0xf
591     lis     r30, CFG_USR_LED_BASE@h
592     stb     r3, 2(r30)
593     sync
594
595     mtlr    r13
596     blr                         /* EXIT board_asm_init ... */
597
598 /*----------------------------------------------------------------------------*/
599 /*
600  * print a message to COM1 in polling mode (r10=COM1 port, r3=(char*)string)
601  */
602
603 Printf:
604     lis     r10, CFG_NS16550_COM1@h /* COM1 base address*/
605     ori     r10, r10, CFG_NS16550_COM1@l
606 WaitChr:
607     lbz     r0, 5(r10)          /* read link status */
608     eieio
609     andi.   r0, r0, 0x40        /* mask transmitter empty bit */
610     beq     cr0, WaitChr        /* wait till empty */
611     lbzx    r0, r0, r3          /* get char */
612     stb     r0, 0(r10)          /* write to transmit reg */
613     eieio
614     addi    r3, r3, 1           /* next char */
615     lbzx    r0, r0, r3          /* get char */
616     cmpwi   cr1, r0, 0          /* end of string ? */
617     bne     cr1, WaitChr
618     blr
619
620 /*
621  * print a char to COM1 in polling mode (r10=COM1 port, r3=char)
622  */
623 OutChr:
624     lis     r10, CFG_NS16550_COM1@h /* COM1 base address*/
625     ori     r10, r10, CFG_NS16550_COM1@l
626 OutChr1:
627     lbz     r0, 5(r10)          /* read link status */
628     eieio
629     andi.   r0, r0, 0x40        /* mask transmitter empty bit */
630     beq     cr0, OutChr1        /* wait till empty */
631     stb     r3, 0(r10)          /* write to transmit reg */
632     eieio
633     blr
634
635 /*
636  * print 8/4/2 digits hex value to COM1 in polling mode (r10=COM1 port, r3=val)
637  */
638 OutHex2:
639     li      r9, 4               /* shift reg for 2 digits */
640     b       OHstart
641 OutHex4:
642     li      r9, 12              /* shift reg for 4 digits */
643     b       OHstart
644 OutHex:
645     li      r9, 28              /* shift reg for 8 digits */
646 OHstart:
647     lis     r10, CFG_NS16550_COM1@h /* COM1 base address*/
648     ori     r10, r10, CFG_NS16550_COM1@l
649 OutDig:
650     lbz     r0, 0(r29)          /* slow down dummy read */
651     lbz     r0, 5(r10)          /* read link status */
652     eieio
653     andi.   r0, r0, 0x40        /* mask transmitter empty bit */
654     beq     cr0, OutDig
655     sraw    r0, r3, r9
656     clrlwi  r0, r0, 28
657     cmpwi   cr1, r0, 9
658     ble     cr1, digIsNum
659     addic   r0, r0, 55
660     b       nextDig
661 digIsNum:
662     addic   r0, r0, 48
663 nextDig:
664     stb     r0, 0(r10)          /* write to transmit reg */
665     eieio
666     addic.  r9, r9, -4
667     bge     OutDig
668     blr
669
670 /*
671  * print 3 digits hdec value to COM1 in polling mode
672  * (r10=COM1 port, r3=val, r7=x00, r8=x0, r9=x, r0, r6=scratch)
673  */
674 OutDec:
675     li      r6, 10
676     divwu   r0, r3, r6          /* r0 = r3 / 10, r9 = r3 mod 10 */
677     mullw   r10, r0, r6
678     subf    r9, r10, r3
679     mr      r3, r0
680     divwu   r0, r3, r6          /* r0 = r3 / 10, r8 = r3 mod 10 */
681     mullw   r10, r0, r6
682     subf    r8, r10, r3
683     mr      r3, r0
684     divwu   r0, r3, r6          /* r0 = r3 / 10, r7 = r3 mod 10 */
685     mullw   r10, r0, r6
686     subf    r7, r10, r3
687     lis     r10, CFG_NS16550_COM1@h /* COM1 base address*/
688     ori     r10, r10, CFG_NS16550_COM1@l
689     or.     r7, r7, r7
690     bne     noblank1
691     li      r3, 0x20
692     b       OutDec4
693 noblank1:
694     addi    r3, r7, 48          /* convert to ASCII */
695 OutDec4:
696     lbz     r0, 0(r29)          /* slow down dummy read */
697     lbz     r0, 5(r10)          /* read link status */
698     eieio
699     andi.   r0, r0, 0x40        /* mask transmitter empty bit */
700     beq     cr0, OutDec4
701     stb     r3, 0(r10)          /* x00 to transmit */
702     eieio
703     or.     r7, r7, r8
704     beq     OutDec5
705     addi    r3, r8, 48          /* convert to ASCII */
706 OutDec5:
707     lbz     r0, 0(r29)          /* slow down dummy read */
708     lbz     r0, 5(r10)          /* read link status */
709     eieio
710     andi.   r0, r0, 0x40        /* mask transmitter empty bit */
711     beq     cr0, OutDec5
712     stb     r3, 0(r10)          /* x0  to transmit */
713     eieio
714     addi    r3, r9, 48          /* convert to ASCII */
715 OutDec6:
716     lbz     r0, 0(r29)          /* slow down dummy read */
717     lbz     r0, 5(r10)          /* read link status */
718     eieio
719     andi.   r0, r0, 0x40        /* mask transmitter empty bit */
720     beq     cr0, OutDec6
721     stb     r3, 0(r10)          /* x   to transmit */
722     eieio
723     blr
724
725 /*
726  * hang endless loop
727  */
728 toggleError:                    /* fail type in r6, r7=0xff, toggle LEDs */
729     stb     r7, 2(r30)          /* r7 to LED */
730     li      r0, 0
731     lis     r9, 127
732     ori     r9, r9, 65535
733 toggleError1:
734     addic   r0, r0, 1
735     cmpw    cr1, r0, r9
736     ble     cr1, toggleError1
737     stb     r6, 2(r30)          /* r6 to LED */
738     li      r0, 0
739     lis     r9, 127
740     ori     r9, r9, 65535
741 toggleError2:
742     addic   r0, r0, 1
743     cmpw    cr1, r0, r9
744     ble     cr1, toggleError2
745     b       toggleError
746
747 /*
748  * routines to read from ram spd
749  */
750 spdWaitIdle:
751     lis     r0, 0x1             /* timeout for about 100us */
752     mtctr   r0
753 iSpd:
754     lbz     r10, 12(r14)
755     andi.   r10, r10, 0x20      /* mask and test MBB */
756     beq     idle
757     bdnz    iSpd
758     orc.    r10, r0, r0         /* return -1 to caller */
759 idle:
760     bclr    20, 0               /* return to caller */
761
762 waitSpd:
763     lis     r0, 0x10            /* timeout for about 1.5ms */
764     mtctr   r0
765 wSpd:
766     lbz     r10, 12(r14)
767     andi.   r10, r10, 0x82
768     cmpli   0, 0, r10, 0x82     /* test MCF and MIF set */
769     beq     wend
770     bdnz    wSpd
771     orc.    r10, r0, r0         /* return -1 to caller */
772     bclr    20, 0               /* return to caller */
773
774 wend:
775     li      r10, 0
776     stb     r10, 12(r14)        /* clear status */
777     bclr    20, 0               /* return to caller */
778
779 /*
780  * spdread
781  * in:  r3 adr to read
782  * out: r3 val or -1 for error
783  * uses r10, assumes that r14 points to I2C controller
784  */
785 spdRead:
786     mfspr   r25, 8              /* save link register */
787
788     bl      spdWaitIdle
789     bne     spdErr
790
791     li      r10, 0x80           /* start with MEN */
792     stb     r10, 8(r14)
793     eieio
794
795     li      r10, 0xb0           /* start as master */
796     stb     r10, 8(r14)
797     eieio
798
799     li      r10, 0xa0           /* write device 0xA0 */
800     stb     r10, 16(r14)
801     eieio
802     bl      waitSpd
803     bne     spdErr
804
805     lbz     r10, 12(r14)        /* test ACK */
806     andi.   r10, r10, 0x01
807     bne     gotNoAck
808
809     stb     r3, 16(r14)         /* data address */
810     eieio
811     bl      waitSpd
812     bne     spdErr
813
814
815     li      r10, 0xb4           /* switch to read - restart */
816     stb     r10, 8(r14)
817     eieio
818
819     li      r10, 0xa1           /* read device 0xA0 */
820     stb     r10, 16(r14)
821     eieio
822     bl      waitSpd
823     bne     spdErr
824
825     li      r10, 0xa8           /* no ACK */
826     stb     r10, 8(r14)
827     eieio
828
829     lbz     r10, 16(r14)        /* trigger read next byte */
830     eieio
831     bl      waitSpd
832     bne     spdErr
833
834     li      r10, 0x88           /* generate STOP condition */
835     stb     r10, 8(r14)
836     eieio
837
838     lbz     r3, 16(r14)         /* return read byte */
839
840     mtspr   8, r25              /* restore link register */
841     blr
842
843 gotNoAck:
844     li      r10, 0x80           /* generate STOP condition */
845     stb     r10, 8(r14)
846     eieio
847 spdErr:
848     orc     r3, r0, r0          /* return -1 */
849     mtspr   8, r25              /* restore link register */
850     blr
851
852 get_lnk_reg:
853     mflr    r3                  /* return link reg */
854     blr
855
856 MessageBlock:
857
858 MinitLogo:
859     .ascii  "\015\012*** ELTEC Elektronik, Mainz ***\015\012"
860     .ascii  "\015\012Initialising RAM\015\012\000"
861 Mspd01:
862     .ascii  "       Reading SPD of SODIMM ...... \000"
863 MramTyp:
864     .ascii  "\015\012\SDRAM with CL=2 at 100 MHz required!\015\012\000"
865 MramConfErr:
866     .ascii  "\015\012\Unsupported SODIMM Configuration!\015\012\000"
867 Mactivate:
868     .ascii  "       Activating \000"
869 Mact0123e:
870     .ascii  " MByte.\015\012\000"
871 Mok:
872     .ascii  "OK \015\012\000"
873 Mfail:
874     .ascii  "FAILED \015\012\000"
875 MnewLine:
876     .ascii  "\015\012\000"
877     .align 4