TomatoVPN 1.27vpn3.6 release
[tomato.git] / release / src / shared / sbsdram.S
blobc9233a78c37a2566a4a5421c94329eb34718ea00
1 /*
2  * BCM47XX Sonics SiliconBackplane SDRAM/MEMC core initialization
3  *
4  * Copyright 2005, Broadcom Corporation
5  * All Rights Reserved.
6  * 
7  * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8  * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9  * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10  * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11  *
12  * $Id: sbsdram.S,v 1.7 2005/03/07 08:35:32 kanki Exp $
13  */
15 #include <sbconfig.h>
16 #include <sbsdram.h>
17 #include <sbmemc.h>
18 #include <sbsocram.h>
19 #include <sbchipc.h>
20 #include <bcmdevs.h>
21 #include <bcmnvram.h>
23 #include <mipsinc.h>
25 /* #define      DEBUG_SBSDRAM   1 */
26 #ifdef  DEBUG_SBSDRAM
27         /* Trace function
28          * Write to prog space so we can see it in
29          * the Logic Analizer
30          */
31 #define TRACE_INIT              \
32         li      k0,0xb8000120;  \
33         li      k1,0x11;        \
34         sw      k1,0(k0);       \
35         li      k1,0x01020108;  \
36         sw      k1,4(k0);       \
37         li      k0,0xbb000000
39 #define TRACE(num, reg) sw      reg,(num << 4)(k0)
40 #else
41 #define TRACE(num, reg)
42 #define TRACE_INIT
43 #endif
45  * Register usage within this file:
46  *
47  *              top     ncdlsearch      test_mem        Xdr_do_init     sb_reset_core
48  *      v0:     retval                  retval
49  *      v1:     corerev -               -               corerev         -
50  *      a0:     coreptr coreptr         -               coreptr         coreptr
51  *      a1:             x               x               x               sdr/ddr flag
52  *      a2:                             x
53  *      a3:                             x
54  *      t0:     -       -                               config
55  *      t1:     -       -                               mode
56  *      t2:     -       wr/strm         off             wr/strm
57  *      t3:     -       rd/strd                         rd/strd
58  *      t4:     -       g/clkd                          g/clkd
59  *      t5:                             x
60  *      t6:     retaddr -                               -               -
61  *      t7:     -       -                               retaddr         -
62  *      s0:             pass_count                      -               -
63  *      s1:             wrsum/clkdsum                   -               -
64  *      s2:             rdsum/pass_countmax             -               -
65  *      s3:             gsum/strmmax                    -               -
66  *      s4:             wrlim/stdmmax                   -               -
67  *      s5:             rdlim/clkdmax                   -               -
68  *      s6:             glim/clkdlim                    -               -
69  *      s7:             dll                             -               -
70  *      t8:     -       -                               x               tmp
71  *      t9:     -       -                               x               retaddr
72  *      k0:     trace   trace           trace           -               -
73  *      k1:     trace   trace           trace           -               -
74  *      gp:
75  *      sp:
76  *      s8:     -       step                            -               -
77  *      ra:
78  */
81         LEAF(board_draminit)
82         .set    noreorder
84         /* Save return address */
85         move    t6,ra
87         TRACE_INIT
89         /* Scan for an SDRAM controller (a0) */
90         li      a0,KSEG1ADDR(SB_ENUM_BASE)
91 1:      lw      v1,(SBCONFIGOFF + SBIDHIGH)(a0)
92         and     a1,v1,SBIDH_CC_MASK
93         srl     a1,a1,SBIDH_CC_SHIFT
94         beq     a1,SB_MEMC,foundctrl
95         nop
96         beq     a1,SB_SOCRAM,foundctrl
97         nop
98         beq     a1,SB_SDRAM,foundctrl
99         nop
100         addu    a0,SB_CORE_SIZE
101         bne     a1,(SBIDH_CC_MASK >> SBIDH_CC_SHIFT),1b
102         nop
104         /* No SDRAM controller */
105         jr      t6
106         li      v0, 0
108 foundctrl:
109         /* If we are already in RAM, just go and size it */
110         bal     1f
111         nop
112 1:      li      t0,PHYSADDR_MASK
113         and     t0,t0,ra
114         li      t1,SB_FLASH1
115         blt     t0,t1,memprio_szmem
116         nop
118         /* For socram we don't need any nvram parms, just do a core reset */
119         bne     a1,SB_SOCRAM,read_nvram
120         nop
121         bal     sb_core_reset
122         li      a2,0
123         /* and size memory */
124         b       memprio_szmem
125         nop
127 read_nvram:
128         /* Find NVRAM (a2) */
129         li      t0,KSEG1ADDR(SB_ENUM_BASE)      # Is there a chipcommon core?
130         lw      t1,(SBCONFIGOFF + SBIDHIGH)(t0)
131         and     t1,t1,SBIDH_CC_MASK
132         srl     t1,t1,SBIDH_CC_SHIFT
133         bne     t1,SB_CC,notcc
134         nop
136         /* It is a chipcommon core: */
137         /* 1: Isolate corerev in v1 */
138         and     v1,v1,SBIDH_RC_MASK
140         /* 1.5: 5365a0 lies about its revision, it is really 1 */
141         bnez    v1,1f
142         nop
143         lw      t1,0(t0)                # Check chipid
144         andi    t1,CID_ID_MASK
145         bne     t1,BCM5365_DEVICE_ID,1f
146         nop
147         li      v1,1
149         /* 2: use the 32MB window */
150 1:      li      t2,KSEG1ADDR(SB_FLASH2 - NVRAM_SPACE)
151         li      t4,SB_FLASH2_SZ
152         b       find_nvram
153         nop
155 notcc:
156         /* else use the 4MB window */
157         li      t2,KSEG1ADDR(SB_FLASH1 - NVRAM_SPACE)
158         li      t4,SB_FLASH1_SZ
160 find_nvram:
161         li      t3,FLASH_MIN 
162         li      t0, NVRAM_MAGIC
165         add     a2,t2,t3
166         lw      t1, 0(a2)
167         beq     t0,t1,read_parms
168         nop
170         sll     t3,t3,1
171         ble     t3,t4,1b
172         nop
174         /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
175         li      a2,KSEG1ADDR(SB_FLASH1 + 0x1000)
176         lw      t1,0(a2)
177         beq     t0,t1,read_parms
178         nop
180         li      a2,KSEG1ADDR(SB_FLASH1 + 0x400)
181         lw      t1,0(a2)
182         beq     t0,t1,read_parms
183         nop
185         b       init                    # No NVRAM
186         li      a2, 0
188 read_parms:
189         /* Get SDRAM parameters (t0, t1, t2) from NVRAM (a2) */
190         lw      t0,8(a2)                # SDRAM init
191         srl     t0,16
192         lw      t2,12(a2)
193         andi    t1,t2,0xffff            # SDRAM config
194         srl     t2,16                   # SDRAM refresh
195         lw      t3,16(a2)               # SDRAM ncdl
197 init:
198         /* Initialize SDRAM controller:  sdram core */
199         beq     a1,SB_SDRAM,sdram_init
200         nop
201         /* else it is a memc core */
203 memc_init:
204         bnez    a2,1f                   # Already have the parms in
205         nop                             #  t0, t1, t2, t3
207         /* No nvram parms: assume DDRM16MX16X2 */
209         li      t0,MEMC_DDR_INIT
210         li      t1,MEMC_DDR_MODE
211         li      t3,MEMC_DDR1_NCDL       # If rev1 (4712):
212         beq     v1,1,1f
213         nop
214                                         # rev0, 2:
215         li      t3,MEMC_DDR_NCDL
218         andi    a3,t0,MEMC_CONFIG_DDR   # Is it ddr or sdr?
219         beqz    a3,memc_sdr_init
220         nop
222         /* Initialize DDR SDRAM */
223 memc_ddr_init:
224         beqz    t3,ddr_find_ncdl        # Do we have ncdl values? (0s)
225         nop
227         li      t4,-1                   # or ffs
228         bne     t3,t4,break_ddr_ncdl
229         nop
231 ddr_find_ncdl:
233 /* Register usage */
234 #define pass_count      s0
235 #define wrsum           s1
236 #define rdsum           s2
237 #define gsum            s3
238 #define wrlim           s4
239 #define rdlim           s5
240 #define glim            s6
241 #define dll             s7
242 #define step            s8
243 #define wr              t2
244 #define rd              t3
245 #define g               t4
247         /* Initialize counter & accumulators */
248         move    pass_count,zero
249         move    wrsum,zero
250         move    rdsum,zero
251         move    gsum,zero
253         /* Initialize with default values */
254         li      wr,5
255         li      rd,5
256         bal     ddr_do_init
257         li      g,10
259         /* Read dll value */
260         lw      dll,MEMC_NCDLCTL(a0)
261         TRACE(1, dll)
262         andi    dll,dll,0xfe
263         srl     dll,dll,1
264         beqz    dll,memprio_szmem               /* If zero, leave the default values */
265         nop
267         move    wrlim,dll               /* dll value is lim for wr, rd and g */
268         move    rdlim,dll
269         move    glim,dll
270         TRACE(2, wrlim)
271         TRACE(3, rdlim)
272         TRACE(4, glim)
274         addi    step,dll,15             /* step = (dll + 16 - 1) / 16 */
275         srl     step,step,4
276         TRACE(5, step)
278         sub     wr,zero,dll             /* Negate dll as initial value */
279         move    rd,wr
280         move    g,wr
282         /* Inner loop:  call ddr_do_init to re-initialize and the test mem */
283 loop:
284         TRACE(6, wr)
285         TRACE(7, rd)
286         TRACE(8, g)     
287         bal     ddr_do_init
288         nop
290         bal     test_mem
291         nop
293         TRACE(9, v0)
294         beqz    v0,nextg
295         nop
297         /* Memory is ok */
299         addi    pass_count,1
300         add     wrsum,wrsum,wr
301         add     rdsum,rdsum,rd
302         add     gsum,gsum,g
303         TRACE(0xa, pass_count)
304         TRACE(0xb, wrsum)
305         TRACE(0xc, rdsum)
306         TRACE(0xd, gsum)
308         bne     wr,dll,1f
309         nop
310         sll     wrlim,dll,1
311         TRACE(0xe, wrlim)
314         bne     rd,dll,2f
315         nop
316         sll     rdlim,dll,1
317         TRACE(0xf, rdlim)
320         bne     g,dll,nextg
321         nop
322         sll     glim,dll,1
323         TRACE(0x10, glim)
325 nextg:
326         add     g,g,step
327         ble     g,glim,loop
328         nop
329         sub     g,zero,dll
330         move    glim,dll
331         TRACE(0x11, g)
333         /* nextrd: */
334         add     rd,rd,step
335         ble     rd,rdlim,loop
336         nop
337         sub     rd,zero,dll
338         move    rdlim,dll
339         TRACE(0x12, rd)
341         /* nextwr: */
342         add     wr,wr,step
343         ble     wr,wrlim,loop
344         nop
346         /* All done, calculate average values and program them */
347         
348         TRACE(0x13, pass_count)
349         TRACE(0x14, wrsum)
350         TRACE(0x15, rdsum)
351         TRACE(0x16, gsum)
352         beqz    pass_count,1f
353         nop
355         div     zero,wrsum,pass_count
356         mflo    wr
358         div     zero,rdsum,pass_count
359         mflo    rd
361         div     zero,gsum,pass_count
362         mflo    g
364         b       ddr_got_ncdl
365         nop
367         /* No passing values, panic! (use defaults) */
369         li      t3,MEMC_DDR1_NCDL       # If rev1:
370         beq     v1,1,2f
371         nop
372                                         # rev0, 2:
373         li      t3,MEMC_DDR_NCDL
376 break_ddr_ncdl:
377         andi    t4,t3,0xff              # t4:   g
378         srl     t2,t3,16                # t2:   wr
379         andi    t2,t2,0xff
380         srl     t3,t3,8                 # t3:   rd
381         andi    t3,t3,0xff
383 ddr_got_ncdl:
384         TRACE(0x17, wr)
385         TRACE(0x18, rd)
386         TRACE(0x19, g)
387         bal     ddr_do_init
388         nop
390         b       memprio_szmem
391         nop
393 memc_sdr_init:
394         beqz    t3,sdr_find_ncdl        # Do we have ncdl values?
395         nop
397         li      t4,-1
398         bne     t3,t4,break_sdr_ncdl
399         nop
401 sdr_find_ncdl:
403 /* Register usage */
404 #define pass_count      s0
405 #define clkdsum         s1
406 #define pass_countmax   s2
407 #define strmmax         s3
408 #define strdmax         s4
409 #define clkdmax         s5
410 #define clkdlim         s6
411 #define strm            t2
412 #define strd            t3
413 #define clkd            t4
415 #define STRMLIM         4
416 #define STRDLIM         16
417 #define CLKDLIM         128
418 #define CLKDLIM_IC      256
420         /* Initialize counter & saved values */
421         move    pass_countmax,zero
422         move    strmmax,zero
423         move    strdmax,zero
424         li      clkdlim,CLKDLIM
426         and     strm,t0,0x2000          /* Test for internal clock (Using strm as a temp) */
427         beqz    strm,strmloop
428         nop
430         li      clkdlim,CLKDLIM_IC
432         move    strm,zero               /* strm loop */
433 strmloop:
434         move    strd,zero
435 strdloop:
436         move    pass_count,zero
437         move    clkdsum,zero
438         move    clkd,zero
440         /* Inner loop:  call sdr_do_init to re-initialize and the test mem */
441 clkdloop:
442         TRACE(0x1a, strm)
443         TRACE(0x1b, strd)
444         TRACE(0x1c, clkd)       
445         bal     sdr_do_init
446         nop
448         bal     test_mem
449         nop
451         TRACE(0x1d, v0)
452         beqz    v0,failclkd
453         nop
455         /* Memory is ok */
457         addi    pass_count,1
458         add     clkdsum,clkdsum,clkd
459         TRACE(0x1e, pass_count)
460         TRACE(0x1f, clkdsum)
461         b       nextclkd
462         nop
464 failclkd:
465         bnez    pass_count,clkdout      # End of passing range, leave clkd loop
466         nop
468 nextclkd:
469         addi    clkd,clkd,1
470         blt     clkd,clkdlim,clkdloop
471         nop
473 clkdout:
474         /* If no passing values, skip to next strm */
475         beqz    pass_count,nextstrm
476         nop
478         /* If this is a new max, Save the values */
479         ble     pass_count,pass_countmax,nextstrd
480         nop
482         move    pass_countmax,pass_count
483         div     zero,clkdsum,pass_count
484         mflo    clkdmax
485         move    strdmax,strd
486         move    strmmax,strm
487         TRACE(0x20, pass_count)
488         TRACE(0x21, clkdmax)
489         TRACE(0x22, strdmax)
490         TRACE(0x23, strmmax)
492 nextstrd:
493         addi    strd,strd,1
494         blt     strd,STRDLIM,strdloop
495         nop
497 nextstrm:
498         addi    strm,strm,1
499         blt     strm,STRMLIM,strmloop
500         nop
502         /* All done, program the new ncdl values */
503         
504         TRACE(0x24, pass_count)
505         TRACE(0x25, clkdmax)
506         TRACE(0x26, strdmax)
507         TRACE(0x27, strmmax)
509         beqz    pass_countmax,1f
510         nop
512         move    clkd,clkdmax
513         move    strd,strdmax
514         move    strm,strmmax
515         b       sdr_got_ncdl
516         nop
518         /* No passing values, panic! (use defaults) */
520         li      t3,MEMC_SDR1_NCDL       # If rev1:
521         beq     v1,1,2f
522         nop
523                                         # rev0, 2:
524         li      t3,MEMC_SDR_NCDL
527 break_sdr_ncdl:
528         andi    t4,t3,0xff              # t4:   cd
529         srl     t2,t3,16                # t2:   sm
530         andi    t2,t2,3                 #       sm is 2 bits only
531         srl     t3,t3,8                 # t3:   sd
532         andi    t3,t3,0xf               #       sd is 4 bits
534 sdr_got_ncdl:
535         bal     sdr_do_init
536         nop
538         b       memprio_szmem
539         nop
541 sdram_init:
542         bnez    a2,1f                   # Already have the parms in t0, t1, t2
543         nop
545         /* Use default SDRAM parameters */
546         li      t0, SDRAM_INIT
547         li      t1, SDRAM_CONFIG
548         li      t2, SDRAM_REFRESH
550         /* Initialize SDRAM */
552         bal     sb_core_reset
553         li      a2,0
555         sw      t1, 4(a0)               # SDRAM config
556         li      a1, 0x000a
557         sw      a1, 0(a0)
558         li      a1, 0x000c
559         sw      a1, 0(a0)
560         li      a1, 0x0009
561         sw      a1, 0(a0)               # 1st refresh of power up sequence
562         sw      a1, 0(a0)               # 2nd refresh of power up sequence
563         sw      a1, 0(a0)               # 3rd refresh of power up sequence
564         sw      a1, 0(a0)               # 4th refresh of power up sequence
565         sw      a1, 0(a0)               # 5th refresh of power up sequence
566         sw      a1, 0(a0)               # 6th refresh of power up sequence
567         sw      a1, 0(a0)               # 7th refresh of power up sequence
568         sw      a1, 0(a0)               # 8th refresh of power up sequence
569         sw      t0, 0(a0)               # SDRAM init
570         sw      t2, 8(a0)               # SDRAM refresh
573         /* Change the memory priority inversion counter value*/
574         /* Determine memory size and return */
575 memprio_szmem:
577 #ifdef APPLE
578         lw      t0, MEMC_PRIORINV(a0) 
579         li      t1, 0xFFFF0000
580         and     t0, t0, t1
581         ori     t0, t0, 0x1
582         sw      t0, MEMC_PRIORINV(a0)
583 #endif
584         lw      t0,(SBCONFIGOFF + SBIDHIGH)(a0)
585         and     t0,t0,SBIDH_CC_MASK
586         srl     t0,t0,SBIDH_CC_SHIFT
587         bne     t0,SB_SOCRAM,szmem_alias
588         nop
590         /* The socram core tells us how much memory there is */
591         lw      t0,SOCRAM_MEMSIZE(a0)
592         addi    t0,SOCRAM_MEMSIZE_BASESHIFT
593         li      v0,1
594         sll     v0,v0,t0
595         jr      t6
596         nop
597         
598 szmem_alias:
599         li      t0,KSEG1
600         li      t2,0xaa55beef
601         sw      t2,0(t0)
602         li      v0,(1 << 20)
605         or      t0,v0,KSEG1
606         lw      t1,0(t0)
607         beq     t1,t2,done
608         nop
610         sll     v0,v0,1
611         bne     v0,(128 << 20),1b
612         nop
613         /* Didn't find an alias, must be 128MB */
615 done:
616         jr      t6      
617         nop
620         /*
621          * Test memory
622          *
623          * Uses arg in t2(wr/sd), t3(rd/sm) and t4(g/clkd)
624          * Returns success (1) or failure (0) in v0
625          * Uses a1, a2, a3 & t5
626          */
627 test_mem:
628         /* Use t4 to generate a semi-random address in the second KB */
629         li      a1,KSEG1
630         addi    a2,t4,255
631         sll     a2,a2,2
632         add     a1,a1,a2
634         /* First set: 0 & its negation */
635         li      a2,0
636         sw      a2,0(a1)
637         not     a3,a2
638         sw      a3,4(a1)
639         nop
640         lw      t5,0(a1)
641         bne     a2,t5,bad_mem
642         nop
644         lw      t5,4(a1)
645         bne     a3,t5,bad_mem
646         nop
648         /* Second set: 0xaaaaaaaa & its negation */
649         li      a2,0xaaaaaaaa
650         sw      a2,0(a1)
651         not     a3,a2
652         sw      a3,4(a1)
653         nop
654         lw      t5,0(a1)
655         bne     a2,t5,bad_mem
656         nop
658         lw      t5,4(a1)
659         bne     a3,t5,bad_mem
660         nop
662         /* Third set: 0x12345678 & its negation */
663         li      a2,0x12345678
664         sw      a2,0(a1)
665         not     a3,a2
666         sw      a3,4(a1)
667         nop
668         lw      t5,0(a1)
669         bne     a2,t5,bad_mem
670         nop
672         lw      t5,4(a1)
673         bne     a3,t5,bad_mem
674         nop
676         /* Fourth set: the ncdl & its negation */
677         sll     a2,t2,8
678         or      a2,t3
679         sll     a2,a2,8
680         or      a2,t4
681         sw      a2,0(a1)
682         not     a3,a2
683         sw      a3,4(a1)
684         nop
685         lw      t5,0(a1)
686         bne     a2,t5,bad_mem
687         nop
689         lw      t5,4(a1)
690         bne     a3,t5,bad_mem
691         nop
693         /* Fifth set: the CPU count register & its negation */
694         mfc0    a2,$9
695         sw      a2,0(a1)
696         not     a3,a2
697         sw      a3,4(a1)
698         nop
699         lw      t5,0(a1)
700         bne     a2,t5,bad_mem
701         nop
703         lw      t5,4(a1)
704         bne     a3,t5,bad_mem
705         nop
707         jr      ra
708         li      v0,1
710 bad_mem:
711         jr      ra
712         li      v0,0
715         /* Do an init of the memc core for ddr
716          *      a0:     memc core pointer
717          *      t0:     memc config value
718          *      t1:     memc mode value
719          *      t2:     memc wr ncdl value
720          *      t3:     memc rd ncdl value
721          *      t4:     memc g ncdl value
722          *
723          * Uses a1, t7, t8, t9 (here and by calling sb_core_reset)
724          */
725 ddr_do_init:
727         /* Save return address */
728         move    t7,ra
730         bal     sb_core_reset
731         li      a1,0
733         li      a1,MEMC_CONFIG_INIT
734         or      a1,a1,t0
735         sw      a1,MEMC_CONFIG(a0)
737         li      a1,MEMC_DRAMTIM25_INIT  # Assume CAS latency of 2.5
738         andi    t8,t1,0xf0              # Find out the CAS latency
739         bne     t8,0x20,1f
740         nop
741         li      a1,MEMC_DRAMTIM2_INIT   # CAS latency is 2
742 1:      
743         sw      a1,MEMC_DRAMTIM(a0)
745         andi    t8,t3,0xff
746         sll     a1,t8,8                 # Replicate rd ncdl 4 times
747         or      a1,a1,t8
748         sll     t8,a1,16
749         or      t8,t8,a1
750         li      a1,MEMC_RDNCDLCOR_INIT
751         or      a1,a1,t8
752         sw      a1,MEMC_RDNCDLCOR(a0)
754         li      a1,MEMC_1_WRNCDLCOR_INIT # If rev1:
755         beq     v1,1,1f
756         nop
757                                         # rev0, 2
758         li      a1,MEMC_WRNCDLCOR_INIT
760         andi    t8,t2,0xff
761         or      a1,a1,t8
762         sw      a1,MEMC_WRNCDLCOR(a0)
764         li      a1,MEMC_DQSGATENCDL_INIT
765         andi    t8,t4,0xff
766         or      a1,a1,t8
767         sw      a1,MEMC_DQSGATENCDL(a0)
769         li      a1,MEMC_1_MISCDLYCTL_INIT # If rev1:
770         beq     v1,1,2f
771         nop
772                                         # rev0,2
773         li      a1,MEMC_MISCDLYCTL_INIT
775         sw      a1,MEMC_MISCDLYCTL(a0)
777         li      a1,MEMC_NCDLCTL_INIT
778         sw      a1,MEMC_NCDLCTL(a0)
780         li      a1,MEMC_CONTROL_INIT0
781         sw      a1,MEMC_CONTROL(a0)
783         li      a1,MEMC_CONTROL_INIT1
784         sw      a1,MEMC_CONTROL(a0)
786         li      a1,MEMC_MODEBUF_INIT0
787         sw      a1,MEMC_MODEBUF(a0)
789         li      a1,MEMC_CONTROL_INIT2
790         sw      a1,MEMC_CONTROL(a0)
792         li      a1,MEMC_MODEBUF_INIT1
793         or      a1,a1,t1
794         sw      a1,MEMC_MODEBUF(a0)
796         li      a1,MEMC_CONTROL_INIT3
797         sw      a1,MEMC_CONTROL(a0)
799         li      a1,MEMC_CONTROL_INIT4
800         sw      a1,MEMC_CONTROL(a0)
802         li      a1,MEMC_CONTROL_INIT5
803         sw      a1,MEMC_CONTROL(a0)
804         lw      a1,MEMC_CONTROL(a0)
805         lw      a1,MEMC_CONTROL(a0)
806         lw      a1,MEMC_CONTROL(a0)
808         li      a1,MEMC_CONTROL_INIT5
809         sw      a1,MEMC_CONTROL(a0)
810         lw      a1,MEMC_CONTROL(a0)
811         lw      a1,MEMC_CONTROL(a0)
812         lw      a1,MEMC_CONTROL(a0)
814         li      a1,MEMC_REFRESH_INIT
815         sw      a1,MEMC_REFRESH(a0)
816         
817         li      a1,MEMC_MODEBUF_INIT2
818         or      a1,a1,t1
819         sw      a1,MEMC_MODEBUF(a0)
821         li      a1,MEMC_CONTROL_INIT6
822         sw      a1,MEMC_CONTROL(a0)
824         li      a1,MEMC_CONTROL_INIT7
825         sw      a1,MEMC_CONTROL(a0)
827         /* Wait for SDRAM controller to refresh.
828          * We want 8uS delay.
829          */
830         li      t8,50
831 1:      lw      a1,(SBCONFIGOFF + SBIDLOW)(a0)
832         lw      a1,(SBCONFIGOFF + SBIDHIGH)(a0)
834         bnez    t8,1b
835         subu    t8,1
837         jr      t7
838         nop
840         /* Do an init of the memc core for sdr
841          *      a0:     memc core pointer
842          *      t0:     memc config value
843          *      t1:     memc mode value
844          *      t2:     memc strobe mode ncdl value
845          *      t3:     memc strobe delay ncdl value
846          *      t4:     memc clock delay ncdl value
847          *
848          * Uses a1, t7, t8, t9 (here and by calling sb_core_reset)
849          */
850 sdr_do_init:
852         /* Save return address */
853         move    t7,ra
855         bal     sb_core_reset
856         li      a1,0x40
858         /* Initialize SDRAM */
859         li      a1,MEMC_SD_CONFIG_INIT
860         or      a1,a1,t0
861         sw      a1,MEMC_CONFIG(a0)
863         li      a1,MEMC_SD_DRAMTIM3_INIT # Assume CAS latency of 3
864         andi    t8,t1,0xf0              # Find out the CAS latency
865         bne     t8,0x20,1f
866         nop
867         li      a1,MEMC_SD_DRAMTIM2_INIT # CAS latency is 2
868 1:      
869         sw      a1,MEMC_DRAMTIM(a0)
871         andi    t8,t4,0xff
872         ble     t8,MEMC_CD_THRESHOLD,1f # if (cd <= MEMC_CD_THRESHOLD) rd = cd
873         nop
875         li      t8,MEMC_CD_THRESHOLD    # else rd = MEMC_CD_THRESHOLD
877 1:                                      # t8 is now rd
878         sll     a1,t8,8                 #  .. replicate it 4 times
879         or      a1,a1,t8
880         sll     t8,a1,16
881         or      t8,t8,a1
882         li      a1,MEMC_SD_RDNCDLCOR_INIT
883         or      a1,a1,t8
884         sw      a1,MEMC_RDNCDLCOR(a0)
886         li      a1,MEMC_SD1_WRNCDLCOR_INIT # rev1
887         beq     v1,1,1f
888         nop
890         li      a1,MEMC_SD_WRNCDLCOR_INIT # rev0, 2
892         li      t8,0
893         ble     t4,MEMC_CD_THRESHOLD,2f # if (cd <= MEMC_CD_THRESHOLD) wr = 0
894         nop
895         
896         andi    t8,t4,0xff              # else wr = cd - MEMC_CD_THRESHOLD
897         sub     t8,t8,MEMC_CD_THRESHOLD
898         andi    t8,t8,0xff
900 2:                                      # t8 is now wr, a0 is extra bits
901         or      a1,a1,t8
902         sw      a1,MEMC_WRNCDLCOR(a0)
904         andi    t8,t2,3
905         sll     a1,t8,28
906         andi    t8,t3,0xf
907         sll     t8,t8,24
908         or      t8,t8,a1
909         li      a1,MEMC_SD1_MISCDLYCTL_INIT
910         beq     v1,1,3f                 # If rev1:
911         nop
912                                         # rev0, 2:
913         li      a1,MEMC_SD_MISCDLYCTL_INIT
915         or      a1,a1,t8
916         sw      a1,MEMC_MISCDLYCTL(a0)
918         li      a1,MEMC_SD_CONTROL_INIT0
919         sw      a1,MEMC_CONTROL(a0)
921         li      a1,MEMC_SD_CONTROL_INIT1
922         sw      a1,MEMC_CONTROL(a0)
924         li      a1,MEMC_SD_CONTROL_INIT2
925         sw      a1,MEMC_CONTROL(a0)
926         lw      a1,MEMC_CONTROL(a0)
927         lw      a1,MEMC_CONTROL(a0)
928         lw      a1,MEMC_CONTROL(a0)
930         li      a1,MEMC_SD_CONTROL_INIT2
931         sw      a1,MEMC_CONTROL(a0)
932         lw      a1,MEMC_CONTROL(a0)
933         lw      a1,MEMC_CONTROL(a0)
934         lw      a1,MEMC_CONTROL(a0)
936         li      a1,MEMC_SD_CONTROL_INIT2
937         sw      a1,MEMC_CONTROL(a0)
938         lw      a1,MEMC_CONTROL(a0)
939         lw      a1,MEMC_CONTROL(a0)
940         lw      a1,MEMC_CONTROL(a0)
942         li      a1,MEMC_SD_REFRESH_INIT
943         sw      a1,MEMC_REFRESH(a0)
945         li      a1,MEMC_SD_MODEBUF_INIT
946         or      a1,a1,t1
947         sw      a1,MEMC_MODEBUF(a0)
949         li      a1,MEMC_SD_CONTROL_INIT3
950         sw      a1,MEMC_CONTROL(a0)
952         li      a1,MEMC_SD_CONTROL_INIT4
953         sw      a1,MEMC_CONTROL(a0)
955         li      t8,50
956 1:      lw      a1,(SBCONFIGOFF + SBIDLOW)(a0)
957         lw      a1,(SBCONFIGOFF + SBIDHIGH)(a0)
958         bnez    t8,1b
959         subu    t8,1
961         jr      t7
962         nop
965         /* Special sb_core_reset that makes sure the first time
966          * clock is enabled, address line 6 is in the state specified
967          * by a1.
968          *
969          * a0:  Core pointer
970          * a1:  0x40 if a6 needs to be 1, 0 otherwise
971          * uses t8, t9
972          */
974         .align 6
976 sb_core_reset:
978         /* Save return address */
979         move    t9,ra
980         
981         /* run uncached */
982         bal     kseg1_switch
983         nop                                
985         /* Figure out our address */
986         bal     h0
987         nop
988 h0:     add     t8,ra,24                # This is (h1 - h0)
989         andi    t8,t8,0x40
990         bne     t8,a1,alt_core_reset
991         nop
993         /* Set reset while enabling the clock */
994         li      t8,(SBTML_FGC | SBTML_CLK | SBTML_RESET)
995 h1:     sw      t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
996         b       cont
997         nop
999         /* Now pad to 0x40: We want (h2 - h1) == 0x40 and there
1000          * are 5 instructions inbetween them.
1001          */
1002         .space  (0x40 - 20)
1004 alt_core_reset:
1005         /* Set reset while enabling the clock */
1006         li      t8,(SBTML_FGC | SBTML_CLK | SBTML_RESET)
1007 h2:     sw      t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1009 cont:
1010         /* Read back and delay */
1011         lw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1012         lw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1013         lw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1015         /* Clear reset */
1016         li      t8, (SBTML_FGC | SBTML_CLK)
1017         sw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1019         /* Read back and delay */
1020         lw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1021         lw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1022         lw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1024         /* Leave clock enabled */
1025         li      t8, SBTML_CLK
1026         sw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1028         /* Read back and delay */
1029         lw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1030         lw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1031         lw      t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1033         jr      t9
1034         nop
1036         
1037 kseg1_switch:
1038         and     ra,ra,PHYSADDR_MASK
1039         or      ra,ra,KSEG1
1040         jr      ra
1041         nop 
1042         
1043         .set    reorder
1044         END(board_draminit)