2 * BCM947XX Boot code for standalone apps.
4 * Code should be position-independent until it copies itself to SDRAM.
6 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
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.
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.
20 * $Id: boot.S,v 1.34 2009-04-21 23:38:36 Exp $
28 #if defined(NFLASH_SUPPORT)
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"
38 #if defined(IL_BIGENDIAN) && defined(BCMHND74K)
46 #define TRACEINIT(x) \
47 li k0,KSEG1ADDR(0x18000040); \
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)
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
79 bne t2,a3,2f # if not 5350 then skip
83 li t2,CID_PKG_MASK # if it is a vsim 5350, also skip
85 li a3,(HDLSIM5350_PKG_ID << CID_PKG_SHIFT)
86 beq t2,a3,initcpu # if pkg opt 1 then skip
92 beq a3,t3,initcpu # move ahead if clk freq set correctly
94 sw a3,CC_CLKC_N(s2) # set control N1 to select 6
96 sw t3,CC_WATCHDOG(s2) # set WatchDog Reset
100 2: li a3,BCM5354_CHIP_ID # 5354 ChipID
101 bne t2,a3,initcpu # if not 5354 then skip
105 li t2,CID_REV_MASK # Get chip rev
107 li t3,(3 << CID_REV_SHIFT) # Is it an a3?
111 /* Fix up for a3 (and up?) */
112 li a0,0x01330000 # Value for regcontrol 2
114 sw t2,PMU_REG_CONTROL_ADDR(s2)
115 sw a0,PMU_REG_CONTROL_DATA(s2)
118 li a0,0x00002000 # Value for regcontrol 0
119 li a1,0x06800000 # Value for regcontrol 1
120 li a3,0x02000000 # Value for regcontrol 3
123 li t2,0x1 # Need define
124 sw t2,PMU_REG_CONTROL_ADDR(s2)
125 sw a1,PMU_REG_CONTROL_DATA(s2)
128 * Trim the output voltage of the 1.2V BB switcher and 2.5V
129 * regulator to the correct value.
132 sw t2,PMU_REG_CONTROL_ADDR(s2)
133 sw a0,PMU_REG_CONTROL_DATA(s2) # BB switcher to get 1.2V
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
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)
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)
156 /* Init code for ff4 space without TLB, enabling RAC */
158 li t0,0x1fa0000c # Set up CBR to 0x1fax_xxxx
163 or t3,t2,0xc0000000 # enable ffxx_xxxx space # without programming TLB
165 li t0,0xff40000c # change CBR to ff4x_xxxx
170 /* Initialize processor state */
174 li t1,~(ST0_CU | ST0_RP | ST0_RE | ST0_TS | ST0_SR | ST0_NMI | ST0_UM | ST0_IE)
188 /* Check if we booted from SDRAM */
192 1: li t0,PHYSADDR_MASK
196 move s5,zero # In ram, relocate factor is 0
198 /* If we are in flash, compute reloc for text addresses */
200 li t0,KSEG0ADDR(SI_FLASH1)
202 sub s5,t0,t1 # s5: Relocate factor
204 /* Figure out if we have an SB or AI chip */
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
214 /* Is this chipc rev 11 or 12 and a serial flash? */
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
222 and t2,t1,SBIDH_RC_MASK
223 and t3,t1,SBIDH_RCE_MASK
224 srl t3,t3,SBIDH_RCE_SHIFT
226 ble t2,10,chkcacheon # ccrev <= 10
228 bge t2,13,chkcacheon # ccrev >= 13
230 lw t0,CC_CAPABILITIES(t0)
231 and t0,t0,CC_CAP_FLASH_MASK
232 beq t0,SFLASH_AT,switchkseg0 # Atmel sflash
234 beq t0,SFLASH_ST,switchkseg0 # ST sflash
239 /* Check if the caches are already on */
242 beq t0,CONF_CM_UNCACHED,initcaches
248 /* Black hole for traps with BEV on */
262 /* Record the size of the binary */
275 .globl embedded_nvram
277 .fill 0x400,4,~(0x48534c46)
282 li t0,(HDLSIM_PKG_ID << CID_PKG_SHIFT) # vsim package option
283 li t2,CID_PKG_MASK # isolate chip package
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
291 andi s6,CONF_AR # s6 != 0 if mips32r2
297 /* Turn on the caches in the CP0 register */
299 mfc0 t0,C0_DIAGNOSTIC
300 or t0,(BRCM_IC_ENABLE | BRCM_DC_ENABLE) # Enable both I$ and D$
301 mtc0 t0,C0_DIAGNOSTIC
304 2: /* Get cache sizes */
307 mfc0 a0,C0_CONFIG,1 # a0 has CP0 CONFIG1
315 srl a1,CONF1_DL_SHIFT
317 sll a1,t0,a1 # a1 has D$ cache line size
321 srl a2,CONF1_DA_SHIFT
322 addiu a2,CONF1_DA_BASE # a2 now has D$ associativity
326 srl t0,CONF1_DS_SHIFT
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$: */
340 mtc0 zero,C0_TAGLO,2 # For mips32r2 the D$ Tags are in select 2
346 1: mtc0 zero,C0_TAGLO
349 2: li t0,KSEG0 # Just an address for the first $ line
350 addu t1,t0,a2 # + size of cache == end
353 3: cache Index_Store_Tag_D,0(t0)
359 /* Now we get to do it all again for the I$ */
367 srl a1,CONF1_IL_SHIFT
369 sll a1,t0,a1 # a1 has I$ cache line size
373 srl a2,CONF1_IA_SHIFT
374 addiu a2,CONF1_IA_BASE # a2 now has I$ associativity
378 srl t0,CONF1_IS_SHIFT
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$: */
392 li t0,KSEG0 # Just an address for the first $ line
393 addu t1,t0,a2 # + size of cache == end
396 1: cache Index_Store_Tag_I,0(t0)
403 /* Caches initialized, change cacheability */
405 and t0,~CONF_CM_CMASK
406 or t0,CONF_CM_CACHABLE_NONCOHERENT
418 /* Should return ram size in v0 */
423 panic: TRACE2(0x424f0bad)
427 /* Re-check if we booted from SDRAM */
432 2: li t0,PHYSADDR_MASK
438 /* Copy self to SDRAM */
446 li a0,KSEG0ADDR(SI_FLASH1)
448 li t0,PHYSADDR_MASK # Uncached writes to avoid a flush
457 #if defined(NFLASH_SUPPORT)
458 /* Take care of BCM5357 NAND boot (CFE in nand flash) */
460 and t4,t4,s6 # s6 = ChipId reg
461 bne t4,BCM5357_CHIP_ID,copydata2
467 beqz t4,copydata2 # not BCM5357 NAND boot
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
479 move a0,t1 # restore a0
480 move t0,v0 # get block size from v0
481 move t1,v1 # get page size from v1
483 move v0,t2 # restore v0
484 move v1,t3 # restore v1
486 move t2,t0 # save block size
489 subu t2,t2,t0 # block address mask
491 li t3,KSEG0ADDR(SI_FLASH1)
492 subu t3,a0,t3 # block bus address
496 * t3: block bus address
497 * v0: must be saved and restored when using it
500 and t5,t3,t2 # check block bus address alignment
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
515 1: lw t8,CC_NAND_INTFC_STATUS(s2)
520 la t0,nfl_check_badb # a0: block bus address, a1: page size
521 add t0,t0,s5 # relocate address
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
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
553 b copydone # bypass copydata2 since data
555 #endif /* NFLASH_SUPPORT */
566 /* Go execute from ram now */
582 /* Setup trap handlers */
588 /* Record the memory size */
593 /* Set up stack pointer */
597 /* bootloader supports nvram dl: shift stack pointer beyond nvram */
606 #endif /* DL_NVRAM */
613 /* In case c_main returns */
614 theend: TRACE2(0x424feedd)
641 #endif /* DL_NVRAM */