usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src-rt / shared / boot.S
blob87cc2f1e11a803b4f827d5242ece7c531386d0e0
1 /*
2  * BCM947XX Boot code for standalone apps.
3  *
4  * Code should be position-independent until it copies itself to SDRAM.
5  *
6  * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
7  * 
8  * Permission to use, copy, modify, and/or distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  * 
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
17  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  *
20  * $Id: boot.S,v 1.34 2009-04-21 23:38:36 Exp $
21  */
23 #include "mipsinc.h"
24 #include "hndsoc.h"
25 #include "sbchipc.h"
26 #include "bcmdevs.h"
28 #if     defined(NFLASH_SUPPORT)
29 #include <nflash.h>
30 #endif
33 /* Debug macro - write a number to a chipc reg - use it with caution,
34  *  it changes k0 and k1 registers.
35  *  Value can be read from epidiag -j using "pci r 0x18000044 4"
36  */
37 #ifdef  BCMDBG
38 #if     defined(IL_BIGENDIAN) && defined(BCMHND74K)
39 #define FLADDR_OFF      0
40 #define FLDATA_OFF      12
41 #else
42 #define FLADDR_OFF      4
43 #define FLDATA_OFF      8
44 #endif
46 #define TRACEINIT(x) \
47         li      k0,KSEG1ADDR(0x18000040); \
48         li      k1,x; \
49         sw      k1,FLADDR_OFF(k0)
50         
51 #define TRACE(x) \
52         li      k1,x; \
53         sw      k1,FLADDR_OFF(k0)
55 #define TRACE2(x) \
56         li      k1,x; \
57         sw      k1,FLDATA_OFF(k0)
59 #else
60 #define TRACEINIT(x)
61 #define TRACE(x)
62 #define TRACE2(x)
63 #endif  /* BCMDBG */
65         .text
66         LEAF(startup)
67         .set    noreorder
69         TRACEINIT(0x424f00)
70         # XXX: the following code snipet sets clk frequency to 200M
71         # correct pll clk freq to real speed in the 5350 case.
72         # unless its vsim which we detect as pkg option 1 (should be 0xe)
73         # It is Ugly...but
74         li      s2,KSEG1ADDR(SI_ENUM_BASE)      # s2 = SI_ENUM_BASE
75         li      a3,BCM5350_CHIP_ID              # 5350 ChipID
76         lw      s1,CC_CHIPID(s2)                # s1 = ChipID register
77         li      t2,CID_ID_MASK                  # chip id is bit 0-15
78         and     t2,s1,t2
79         bne     t2,a3,2f                        # if not 5350 then skip
80         nop
81         
82         TRACE(0x424f01)
83         li      t2,CID_PKG_MASK                 # if it is a vsim 5350, also skip
84         and     t2,s1,t2
85         li      a3,(HDLSIM5350_PKG_ID << CID_PKG_SHIFT)
86         beq     t2,a3,initcpu                   # if pkg opt 1 then skip
87         nop
89         TRACE(0x424f02)
90         li      a3,CLKC_5350_N
91         lw      t3,CC_CLKC_N(s2)
92         beq     a3,t3,initcpu                   # move ahead if clk freq set correctly
93         nop
94         sw      a3,CC_CLKC_N(s2)                # set control N1 to select 6
95         li      t3,1
96         sw      t3,CC_WATCHDOG(s2)              # set WatchDog Reset
97 1:      b       1b
98         nop
100 2:      li      a3,BCM5354_CHIP_ID              # 5354 ChipID
101         bne     t2,a3,initcpu                   # if not 5354 then skip
102         nop
104         TRACE(0x424f03)
105         li      t2,CID_REV_MASK                 # Get chip rev
106         and     t2,s1,t2
107         li      t3,(3 << CID_REV_SHIFT)         # Is it an a3?
108         blt     t2,t3,a0a1a2
109         nop 
111         /* Fix up for a3 (and up?) */
112         li      a0,0x01330000                   # Value for regcontrol 2
113         li      t2,2
114         sw      t2,PMU_REG_CONTROL_ADDR(s2)
115         sw      a0,PMU_REG_CONTROL_DATA(s2)
116         
117 a0a1a2:
118         li      a0,0x00002000                   # Value for regcontrol 0
119         li      a1,0x06800000                   # Value for regcontrol 1
120         li      a3,0x02000000                   # Value for regcontrol 3
121         
122 fixregctl:
123         li      t2,0x1                          # Need define
124         sw      t2,PMU_REG_CONTROL_ADDR(s2)
125         sw      a1,PMU_REG_CONTROL_DATA(s2)
126         
127         /* 
128          * Trim the output voltage of the 1.2V BB switcher and 2.5V
129          * regulator to the correct value.
130          */
131         li      t2,0x0
132         sw      t2,PMU_REG_CONTROL_ADDR(s2)
133         sw      a0,PMU_REG_CONTROL_DATA(s2)     # BB switcher to get 1.2V
134         li      t2,0x3
135         sw      t2,PMU_REG_CONTROL_ADDR(s2)
136         sw      a3,PMU_REG_CONTROL_DATA(s2)     # of VDDP LDO to get 2.5V
138         lw      t2,PMU_CTL(s2)                  # Check if PLL has been programmed
139         andi    t2,t2,PCTL_XTALFREQ_MASK
140         bnez    t2,3f                           # Yup, leave it alone
141         nop
143         li      t2,0x7ffff                      # Should only turn off the PLL bit
144         sw      t2,PMU_MIN_RES_MASK(s2)         # Disable base band PLL
145         sw      t2,PMU_MAX_RES_MASK(s2)
147         li      t2,0x1
148         sw      t2,PMU_PLL_CONTROL_ADDR(s2)
149         li      t2,0x66666602                   # Set the PLL Mode properly
150         sw      t2,PMU_PLL_CONTROL_DATA(s2)
151         li      t2,0xfffff                      # Enable base band PLL 
152         sw      t2,PMU_MIN_RES_MASK(s2)
153         sw      t2,PMU_MAX_RES_MASK(s2)
154         nop
156         /* Init code for ff4 space without TLB, enabling RAC */
157 3:      TRACE(0x424f04)
158         li      t0,0x1fa0000c                   # Set up CBR to 0x1fax_xxxx
159         .set    mips32
160         mtc0    t0,$22,6
161         li      t1,0x1fa00000
162         lw      t2,0x14(t1)
163         or      t3,t2,0xc0000000                # enable ffxx_xxxx space # without programming TLB
164         sw      t3,0x14(t1) 
165         li      t0,0xff40000c                   # change CBR to ff4x_xxxx
166         mtc0    t0,$22,6
167         .set    mips0
170         /* Initialize processor state    */
171 initcpu:        
172         TRACE(0x424f05)
173         mfc0    t0,C0_STATUS
174         li      t1,~(ST0_CU | ST0_RP | ST0_RE | ST0_TS | ST0_SR | ST0_NMI | ST0_UM | ST0_IE)
175         and     t0,t1
176         li      t1,ST0_IM
177         or      t0,t1
178         mtc0    t0,C0_STATUS
180         mtc0    zero,C0_CAUSE
182         mtc0    zero,C0_COUNT
184         li      t0,-1
185         mtc0    t0,C0_COMPARE
187 initram:
188         /* Check if we booted from SDRAM */
189         bal     1f
190         nop
192 1:      li      t0,PHYSADDR_MASK
193         and     t0,t0,ra
194         li      t1,SI_FLASH1
195         blt     t0,t1,chkcacheon
196         move    s5,zero                         # In ram, relocate factor is 0
198         /* If we are in flash, compute reloc for text addresses */
199         TRACE(0x424f06)
200         li      t0,KSEG0ADDR(SI_FLASH1)
201         la      t1,text_start
202         sub     s5,t0,t1                        # s5: Relocate factor
203         
204         /* Figure out if we have an SB or AI chip */
205 chkchiptype:
206         TRACE(0x424f08)
207         li      t0,CID_TYPE_MASK
208         and     t0,t0,s1
209         srl     s7,t0,CID_TYPE_SHIFT            # s7 = ChipType (0 for SB, = 1 for AI)
211         bnez    s7,chkcacheon                   # If ai chip no need to check chipc rev
212         nop
214         /* Is this chipc rev 11 or 12 and a serial flash? */
215         TRACE(0x424f0a)
216         li      t0,KSEG1ADDR(SI_ENUM_BASE)
217         lw      t1,(SBCONFIGOFF + SBIDHIGH)(t0)
218         and     t2,t1,SBIDH_CC_MASK
219         srl     t2,t2,SBIDH_CC_SHIFT
220         bne     t2,CC_CORE_ID,chkcacheon        # Not chipc
221         nop
222         and     t2,t1,SBIDH_RC_MASK
223         and     t3,t1,SBIDH_RCE_MASK
224         srl     t3,t3,SBIDH_RCE_SHIFT
225         or      t2,t3
226         ble     t2,10,chkcacheon                # ccrev <= 10
227         nop
228         bge     t2,13,chkcacheon                # ccrev >= 13
229         nop
230         lw      t0,CC_CAPABILITIES(t0)
231         and     t0,t0,CC_CAP_FLASH_MASK
232         beq     t0,SFLASH_AT,switchkseg0        # Atmel sflash
233         nop
234         beq     t0,SFLASH_ST,switchkseg0        # ST sflash
235         nop
237 chkcacheon:
238         TRACE(0x424f0b)
239         /* Check if the caches are already on */
240         mfc0    t0,C0_CONFIG
241         and     t0,CONF_CM_CMASK
242         beq     t0,CONF_CM_UNCACHED,initcaches
243         nop
245         b       switchkseg0
246         nop
248         /* Black hole for traps with BEV on */
249         .org    0x380
250 bevtrap:
251         TRACE2(0x424f0380)
252         nop
253         nop
254         .set    mips32
255         wait
256         .set    mips0
257         nop
258         nop
259         b       bevtrap
260         nop
262         /* Record the size of the binary */
263         .org    BISZ_OFFSET
264         .word   BISZ_MAGIC
265         .word   text_start
266         .word   text_end
267         .word   data_start
268         .word   data_end
269         .word   bss_start
270         .word   bss_end
271         .word   _end
273         /* Embedded NVRAM */
274         .balign 0x400   
275         .globl  embedded_nvram
276 embedded_nvram:
277         .fill   0x400,4,~(0x48534c46)
278         
280 initcaches:
281         TRACE(0x424f0c)
282         li      t0,(HDLSIM_PKG_ID << CID_PKG_SHIFT)     # vsim package option
283         li      t2,CID_PKG_MASK                 # isolate chip package
284         and     t2,s1,t2
285         beq     t0,t2,chcach                    # Skip cache init if vsim
287         /* Figure if it is a mips32r2 CPU which we take as an indication that
288          * there is no BRCM CP0 register and the D$ tags are in select 2
289          */
290         mfc0    s6,C0_CONFIG
291         andi    s6,CONF_AR                      # s6 != 0 if mips32r2
292         beqz    s6,1f
293         nop
294         b       2f
295         nop
297         /* Turn on the caches in the CP0 register */
298 1:      TRACE(0x424f0d)
299         mfc0    t0,C0_DIAGNOSTIC
300         or      t0,(BRCM_IC_ENABLE | BRCM_DC_ENABLE) # Enable both I$ and D$
301         mtc0    t0,C0_DIAGNOSTIC
302         nop
304 2:      /* Get cache sizes */
305         TRACE(0x424f0e)
306         .set    mips32
307         mfc0    a0,C0_CONFIG,1                  # a0 has CP0 CONFIG1
308         .set    mips0
310         li      a1,CONF1_DL_MASK
311         and     a1,a0
312         beq     a1,zero,initic
313         nop
315         srl     a1,CONF1_DL_SHIFT
316         li      t0,CONF1_DL_BASE
317         sll     a1,t0,a1                        # a1 has D$ cache line size
319         li      a2,CONF1_DA_MASK
320         and     a2,a0
321         srl     a2,CONF1_DA_SHIFT
322         addiu   a2,CONF1_DA_BASE                # a2 now has D$ associativity
324         li      t0,CONF1_DS_MASK
325         and     t0,a0
326         srl     t0,CONF1_DS_SHIFT
327         li      a3,CONF1_DS_BASE
328         sll     a3,a3,t0                        # a3 has D$ sets per way
330         multu   a2,a3                           # sets/way * associativity
331         mflo    t0                              # total cache lines
333         multu   a1,t0                           # D$ linesize * lines
334         mflo    a2                              # a2 is now D$ size in bytes
336         /* Initilize the D$: */
337         beqz    s6,1f
338         nop
339         .set    mips32
340         mtc0    zero,C0_TAGLO,2                 # For mips32r2 the D$ Tags are in select 2
341         mtc0    zero,C0_TAGHI,2
342         .set    mips0
343         b       2f
344         nop
346 1:      mtc0    zero,C0_TAGLO
347         mtc0    zero,C0_TAGHI
349 2:      li      t0,KSEG0                        # Just an address for the first $ line
350         addu    t1,t0,a2                        #  + size of cache == end
352         .set    mips32
353 3:      cache   Index_Store_Tag_D,0(t0)
354         .set    mips0
355         bne     t0,t1,3b
356         addu    t0,a1
358 initic:
359         /* Now we get to do it all again for the I$ */
361         TRACE(0x424f0f)
362         li      a1,CONF1_IL_MASK
363         and     a1,a0
364         beq     a1,zero,chcach
365         nop
367         srl     a1,CONF1_IL_SHIFT
368         li      t0,CONF1_IL_BASE
369         sll     a1,t0,a1                        # a1 has I$ cache line size
371         li      a2,CONF1_IA_MASK
372         and     a2,a0
373         srl     a2,CONF1_IA_SHIFT
374         addiu   a2,CONF1_IA_BASE                # a2 now has I$ associativity
376         li      t0,CONF1_IS_MASK
377         and     t0,a0
378         srl     t0,CONF1_IS_SHIFT
379         li      a3,CONF1_IS_BASE
380         sll     a3,a3,t0                        # a3 has I$ sets per way
382         multu   a2,a3                           # sets/way * associativity
383         mflo    t0                              # total cache lines
385         multu   a1,t0                           # I$ linesize * lines
386         mflo    a2                              # a2 is cache size in bytes
388         /* Initilize the I$: */
389         mtc0    zero,C0_TAGLO
390         mtc0    zero,C0_TAGHI
392         li      t0,KSEG0                        # Just an address for the first $ line
393         addu    t1,t0,a2                        #  + size of cache == end
395         .set    mips32
396 1:      cache   Index_Store_Tag_I,0(t0)
397         .set    mips0
398         bne     t0,t1,1b
399         addu    t0,a1
401 chcach: 
402         TRACE(0x424f10)
403         /* Caches initialized, change cacheability */
404         mfc0    t0,C0_CONFIG
405         and     t0,~CONF_CM_CMASK
406         or      t0,CONF_CM_CACHABLE_NONCOHERENT
407         mtc0    t0,C0_CONFIG
408         nop
410 switchkseg0:
411         la      t2,board_draminit
412         add     t2,t2,s5
413         la      ra,backfbd
414         add     ra,ra,s5
415         jr      t2
416         nop
418         /* Should return ram size in v0 */
419 backfbd:
420         bnez    v0,1f
421         nop
423 panic:  TRACE2(0x424f0bad)
424         b       panic
425         nop
427         /* Re-check if we booted from SDRAM */
428 1:      TRACE(0x424f11)
429         bal     2f
430         nop
432 2:      li      t0,PHYSADDR_MASK
433         and     t0,t0,ra
434         li      t1,SI_FLASH1
435         blt     t0,t1,inram
436         nop
438         /* Copy self to SDRAM */
439 copy2ram:       
440         TRACE(0x424f12)
441 #ifdef  CONFIG_XIP
442         la      a0,text_end
443         la      a1,data_start
444         la      a2,data_end
445 #else
446         li      a0,KSEG0ADDR(SI_FLASH1)
447         la      a1,text_start
448         li      t0,PHYSADDR_MASK                # Uncached writes to avoid a flush
449         and     a1,a1,t0
450         li      t1,KSEG1
451         or      a1,a1,t1
452         la      a2,data_end
453         and     a2,a2,t0
454         or      a2,a2,t1
455 #endif
457 #if     defined(NFLASH_SUPPORT)
458         /* Take care of BCM5357 NAND boot (CFE in nand flash) */
459         li      t4,CID_ID_MASK
460         and     t4,t4,s6                        # s6 = ChipId reg
461         bne     t4,BCM5357_CHIP_ID,copydata2
462         nop
464         lw      t5,CC_CHIPST(s2)
465         li      t4,0x10
466         and     t4,t4,t5
467         beqz    t4,copydata2                    # not BCM5357 NAND boot
468         nop
470         move    t1,a0                           # save a0
471         move    t2,v0                           # save v0
472         move    t3,v1                           # save v1
474         la      t0,nfl_size_block               # a0, t8, t9 are corrupted
475         add     t0,t0,s5                        # relocate address
476         jalr    t0                              # v0: block size, v1: page size
477         nop
479         move    a0,t1                           # restore a0
480         move    t0,v0                           # get block size from v0
481         move    t1,v1                           # get page size from v1
482         
483         move    v0,t2                           # restore v0
484         move    v1,t3                           # restore v1
486         move    t2,t0                           # save block size
488         li      t0,1
489         subu    t2,t2,t0                        # block address mask
491         li      t3,KSEG0ADDR(SI_FLASH1)
492         subu    t3,a0,t3                        # block bus address
494         /* t1: page size
495          * t2: block size - 1
496          * t3: block bus address
497          * v0: must be saved and restored when using it
498          */
499 checkalign:
500         and     t5,t3,t2                        # check block bus address alignment
501         bnez    t5,copydata
502         nop
504         move    t4,a0                           # save a0
505         move    t6,a1                           # save a1
506         move    a3,v0                           # save v0
508         move    a0,t3                           # set block bus address, and
509         move    a1,t1                           # set page size for nfl_check_badb
511         /* Wait until nflash controller interface ready */
512         li      t9,NIST_CTRL_READY
513         li      t8,NIST_FLASH_READY
514         or      t9,t9,t8
515 1:      lw      t8,CC_NAND_INTFC_STATUS(s2)
516         and     t7,t8,t9
517         bne     t7,t9,1b
518         nop
520         la      t0,nfl_check_badb               # a0: block bus address, a1: page size
521         add     t0,t0,s5                        # relocate address
522         jalr    t0
523         nop
525         move    t7,v0                           # get v0 after calling nfl_check_badb
526                                                 # v0 = 1: bad block, v0 = 0: good block
527         move    a0,t4                           # restore a0
528         move    a1,t6                           # restore a1
529         move    v0,a3                           # restore v0
531         beqz    t7,copydata                     # go on data copy for good block
532         nop
534 bypassbadb:
535         add     t3,t3,t2                        # increased by one block size
536         addiu   t3,t3,1                         # t2 = block size - 1
538         add     a0,a0,t2                        # increased by one block size
539         addiu   a0,a0,1                         # t2 = block size - 1
541         blt     a1,a2,checkalign
542         nop
544 copydata:
545         lw      t0,0(a0)
546         sw      t0,0(a1)
547         add     a0,4
548         add     a1,4
549         add     t3,4
550         blt     a1,a2,checkalign
551         nop
553         b       copydone                        # bypass copydata2 since data
554         nop                                     # copy is done
555 #endif /* NFLASH_SUPPORT */
557 copydata2:
558 1:      lw      t0,0(a0)
559         sw      t0,0(a1)
560         add     a0,4
561         add     a1,4
562         blt     a1,a2,1b
563         nop
565 copydone:
566         /* Go execute from ram now */
567         la      t0,inram
568         jr      t0
569         nop
571 inram:  
572 clearbss:
573         TRACE(0x424f13)
574         /* Clear BSS */ 
575         la      a0,bss_start
576         la      a1,bss_end
577 1:      sw      zero,0(a0)
578         addi    a0,a0,4
579         blt     a0,a1,1b
580         nop
582         /* Setup trap handlers */
583         TRACE(0x424f14)
584         la      t0,trap_init
585         jalr    t0
586         nop
588         /* Record the memory size */
589 2:      TRACE(0x424f15)
590         la      t0,_memsize
591         sw      v0,0(t0)
593         /* Set up stack pointer */
594         or      v0,KSEG0
595         sub     sp,v0,4
597 /* bootloader supports nvram dl: shift stack pointer beyond nvram */
598 #ifdef DL_NVRAM
599         la      t1,_dlvarsz
600         sw      sp,0(t1)
601         li      a0,DL_NVRAM
602         sub     sp,sp,a0
603         la      t1,_dlvars
604         sw      sp,0(t1)
605         sub     sp,sp,4
606 #endif /* DL_NVRAM */
608         /* Jump to C */
609         la      t0,c_main
610         jal     t0
611         move    a0,ra
613         /* In case c_main returns */
614 theend: TRACE2(0x424feedd)
615         nop
616         nop
617         .set    mips32
618         wait
619         .set    mips0
620         nop
621         nop
622         b       theend
623         nop
625         .set reorder
626         END(startup)
628         .data
629         .globl  _memsize
630 _memsize:
631         .word   0
633 #ifdef DL_NVRAM
634         .globl _dlvars
635 _dlvars:
636         .word   0
638         .globl _dlvarsz
639 _dlvarsz:
640         .word   0
641 #endif /* DL_NVRAM */