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) 2013, 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.35 2010-08-06 00:03:55 $
21 */
22
23#include "mipsinc.h"
24#include "hndsoc.h"
25#include "sbchipc.h"
26#include "bcmdevs.h"
27
28
29/* Debug macro - write a number to a pair of chipc regs - use it with caution,
30 *  the registers being used only exist in chip rev >= 22, meaning NOT in 5354
31 *  and previous chips. Also,  it changes k0 and k1 registers.
32 *  Value can be read from epidiag -j using "pci r 0x180000d0 4"
33 */
34#define TRACEINIT(x)
35#define TRACE(x)
36#define TRACE2(x)
37
38	.text
39	LEAF(startup)
40	.set	noreorder
41
42
43	TRACEINIT(0x424f00)
44	# XXX: the following code snipet sets clk frequency to 200M
45	# correct pll clk freq to real speed in the 5350 case.
46	# unless its vsim which we detect as pkg option 1 (should be 0xe)
47	# It is Ugly...but
48	li	s2,KSEG1ADDR(SI_ENUM_BASE)	# s2 = SI_ENUM_BASE
49	li	a3,BCM5350_CHIP_ID		# 5350 ChipID
50	lw	s1,CC_CHIPID(s2)		# s1 = ChipID register
51	li	t2,CID_ID_MASK			# chip id is bit 0-15
52	and	t2,s1,t2
53	bne	t2,a3,2f			# if not 5350 then skip
54	nop
55
56	TRACE(0x424f01)
57	li	t2,CID_PKG_MASK			# if it is a vsim 5350, also skip
58	and	t2,s1,t2
59	li	a3,(HDLSIM5350_PKG_ID << CID_PKG_SHIFT)
60	beq	t2,a3,initcpu			# if pkg opt 1 then skip
61	nop
62
63	TRACE(0x424f02)
64	li	a3,CLKC_5350_N
65	lw	t3,CC_CLKC_N(s2)
66	beq	a3,t3,initcpu			# move ahead if clk freq set correctly
67	nop
68	sw	a3,CC_CLKC_N(s2)		# set control N1 to select 6
69	li	t3,1
70	sw	t3,CC_WATCHDOG(s2)		# set WatchDog Reset
711:	b	1b
72	nop
73
742:	li	a3,BCM5354_CHIP_ID		# 5354 ChipID
75	bne	t2,a3,initcpu			# if not 5354 then skip
76	nop
77
78	TRACE(0x424f03)
79	li	t2,CID_REV_MASK			# Get chip rev
80	and	t2,s1,t2
81	li	t3,(3 << CID_REV_SHIFT)		# Is it an a3?
82	blt	t2,t3,a0a1a2
83	nop
84
85	/* Fix up for a3 (and up?) */
86	li	a0,0x01330000			# Value for regcontrol 2
87	li	t2,2
88	sw	t2,PMU_REG_CONTROL_ADDR(s2)
89	sw	a0,PMU_REG_CONTROL_DATA(s2)
90
91a0a1a2:
92	li	a0,0x00002000			# Value for regcontrol 0
93	li	a1,0x06800000			# Value for regcontrol 1
94	li	a3,0x02000000			# Value for regcontrol 3
95
96fixregctl:
97	li	t2,0x1				# Need define
98	sw	t2,PMU_REG_CONTROL_ADDR(s2)
99	sw	a1,PMU_REG_CONTROL_DATA(s2)
100
101	/*
102	 * Trim the output voltage of the 1.2V BB switcher and 2.5V
103	 * regulator to the correct value.
104	 */
105	li	t2,0x0
106	sw	t2,PMU_REG_CONTROL_ADDR(s2)
107	sw	a0,PMU_REG_CONTROL_DATA(s2)	# BB switcher to get 1.2V
108	li	t2,0x3
109	sw	t2,PMU_REG_CONTROL_ADDR(s2)
110	sw	a3,PMU_REG_CONTROL_DATA(s2)	# of VDDP LDO to get 2.5V
111
112	lw	t2,PMU_CTL(s2)			# Check if PLL has been programmed
113	andi	t2,t2,PCTL_XTALFREQ_MASK
114	bnez	t2,3f				# Yup, leave it alone
115	nop
116
117	li	t2,0x7ffff			# Should only turn off the PLL bit
118	sw	t2,PMU_MIN_RES_MASK(s2)		# Disable base band PLL
119	sw	t2,PMU_MAX_RES_MASK(s2)
120
121	li	t2,0x1
122	sw	t2,PMU_PLL_CONTROL_ADDR(s2)
123	li	t2,0x66666602			# Set the PLL Mode properly
124	sw	t2,PMU_PLL_CONTROL_DATA(s2)
125	li	t2,0xfffff			# Enable base band PLL
126	sw	t2,PMU_MIN_RES_MASK(s2)
127	sw	t2,PMU_MAX_RES_MASK(s2)
128	nop
129
130	/* Init code for ff4 space without TLB, enabling RAC */
1313:	TRACE(0x424f04)
132	li 	t0,0x1fa0000c			# Set up CBR to 0x1fax_xxxx
133	.set	mips32
134	mtc0 	t0,$22,6
135	li 	t1,0x1fa00000
136	lw 	t2,0x14(t1)
137	or 	t3,t2,0xc0000000		# enable ffxx_xxxx space # without programming TLB
138	sw 	t3,0x14(t1)
139	li 	t0,0xff40000c			# change CBR to ff4x_xxxx
140	mtc0 	t0,$22,6
141	.set	mips0
142
143
144	/* Initialize processor state    */
145initcpu:
146	TRACE(0x424f05)
147	mfc0	t0,C0_STATUS
148	li	t1,~(ST0_CU | ST0_RP | ST0_RE | ST0_TS | ST0_SR | ST0_NMI | ST0_UM | ST0_IE)
149	and	t0,t1
150	li	t1,ST0_IM
151	or	t0,t1
152	mtc0	t0,C0_STATUS
153
154	mtc0	zero,C0_CAUSE
155
156	mtc0	zero,C0_COUNT
157
158	li	t0,-1
159	mtc0	t0,C0_COMPARE
160
161initram:
162	/* Check if we booted from SDRAM */
163	bal	1f
164	nop
165
1661:	li	t0,PHYSADDR_MASK
167	and	t0,t0,ra
168	li	t1,SI_FLASH1
169	blt	t0,t1,chkcacheon
170	move	s5,zero				# In ram, relocate factor is 0
171
172	/* If we are in flash, compute reloc for text addresses */
173	TRACE(0x424f06)
174	li	t0,KSEG0ADDR(SI_FLASH1)
175	la	t1,text_start
176	sub	s5,t0,t1			# s5: Relocate factor
177
178	/* Figure out if we have an SB or AI chip */
179chkchiptype:
180	TRACE(0x424f08)
181	li	t0,CID_TYPE_MASK
182	and	t0,t0,s1
183	srl	s7,t0,CID_TYPE_SHIFT		# s7 = ChipType (0 for SB, = 1 for AI)
184
185	bnez	s7,chkcacheon			# If ai chip no need to check chipc rev
186	nop
187
188	/* Is this chipc rev 11 or 12 and a serial flash? */
189	TRACE(0x424f0a)
190	li	t0,KSEG1ADDR(SI_ENUM_BASE)
191	lw	t1,(SBCONFIGOFF + SBIDHIGH)(t0)
192	and	t2,t1,SBIDH_CC_MASK
193	srl	t2,t2,SBIDH_CC_SHIFT
194	bne	t2,CC_CORE_ID,chkcacheon	# Not chipc
195	nop
196	and	t2,t1,SBIDH_RC_MASK
197	and	t3,t1,SBIDH_RCE_MASK
198	srl	t3,t3,SBIDH_RCE_SHIFT
199	or	t2,t3
200	ble	t2,10,chkcacheon		# ccrev <= 10
201	nop
202	bge	t2,13,chkcacheon		# ccrev >= 13
203	nop
204	lw	t0,CC_CAPABILITIES(t0)
205	and	t0,t0,CC_CAP_FLASH_MASK
206	beq	t0,SFLASH_AT,switchkseg0	# Atmel sflash
207	nop
208	beq	t0,SFLASH_ST,switchkseg0	# ST sflash
209	nop
210
211	b	chkcacheon
212	nop
213
214	/* Black hole for traps with BEV on */
215	.org	0x380
216bevtrap:
217	TRACE2(0x424f0380)
218	nop
219	nop
220	.set	mips32
221	wait
222	.set	mips0
223	nop
224	nop
225	b	bevtrap
226	nop
227
228	/* Record the size of the binary */
229	.org	BISZ_OFFSET
230	.word	BISZ_MAGIC
231	.word	text_start
232	.word	text_end
233	.word	data_start
234	.word	data_end
235	.word	bss_start
236	.word	bss_end
237	.word	_end
238
239	/* Embedded NVRAM */
240	.balign	0x400
241	.globl	embedded_nvram
242embedded_nvram:
243	.fill	0x400,4,~(0x48534c46)
244        .long   0x4c5a4d41              # LZMA NVRAM Supported
245
246chkcacheon:
247	TRACE(0x424f0b)
248	/* Check if the caches are already on */
249	mfc0	t0,C0_CONFIG
250	and	t0,CONF_CM_CMASK
251	bne	t0,CONF_CM_UNCACHED,switchkseg0
252	nop
253
254initcaches:
255	TRACE(0x424f0c)
256	li	t0,(HDLSIM_PKG_ID << CID_PKG_SHIFT)	# vsim package option
257	li	t2,CID_PKG_MASK			# isolate chip package
258	and	t2,s1,t2
259	beq	t0,t2,chcach			# Skip cache init if vsim
260
261	/* Figure if it is a mips32r2 CPU which we take as an indication that
262	 * there is no BRCM CP0 register and the D$ tags are in select 2
263	 */
264	mfc0	s6,C0_CONFIG
265	andi	s6,CONF_AR			# s6 != 0 if mips32r2
266	beqz	s6,1f
267	nop
268	b	2f
269	nop
270
271	/* Turn on the caches in the CP0 register */
2721:	TRACE(0x424f0d)
273	mfc0	t0,C0_DIAGNOSTIC
274	or	t0,(BRCM_IC_ENABLE | BRCM_DC_ENABLE) # Enable both I$ and D$
275	mtc0	t0,C0_DIAGNOSTIC
276	nop
277
2782:	/* Get cache sizes */
279	TRACE(0x424f0e)
280	.set	mips32
281	mfc0	a0,C0_CONFIG,1			# a0 has CP0 CONFIG1
282	.set	mips0
283
284	li	a1,CONF1_DL_MASK
285	and	a1,a0
286	beq	a1,zero,initic
287	nop
288
289	srl	a1,CONF1_DL_SHIFT
290	li	t0,CONF1_DL_BASE
291	sll	a1,t0,a1			# a1 has D$ cache line size
292
293	li	a2,CONF1_DA_MASK
294	and	a2,a0
295	srl	a2,CONF1_DA_SHIFT
296	addiu	a2,CONF1_DA_BASE		# a2 now has D$ associativity
297
298	li	t0,CONF1_DS_MASK
299	and	t0,a0
300	srl	t0,CONF1_DS_SHIFT
301	li	a3,CONF1_DS_BASE
302	sll	a3,a3,t0			# a3 has D$ sets per way
303
304	multu	a2,a3				# sets/way * associativity
305	mflo	t0				# total cache lines
306
307	multu	a1,t0				# D$ linesize * lines
308	mflo	a2				# a2 is now D$ size in bytes
309
310	/* Initilize the D$: */
311	beqz	s6,1f
312	nop
313	.set	mips32
314	mtc0	zero,C0_TAGLO,2			# For mips32r2 the D$ Tags are in select 2
315	mtc0	zero,C0_TAGHI,2
316	.set	mips0
317	b	2f
318	nop
319
3201:	mtc0	zero,C0_TAGLO
321	mtc0	zero,C0_TAGHI
322
3232:	li	t0,KSEG0			# Just an address for the first $ line
324	addu	t1,t0,a2			#  + size of cache == end
325
326	.set	mips32
3273:	cache	Index_Store_Tag_D,0(t0)
328	.set	mips0
329	bne	t0,t1,3b
330	addu	t0,a1
331
332initic:
333	/* Now we get to do it all again for the I$ */
334
335	TRACE(0x424f0f)
336	li	a1,CONF1_IL_MASK
337	and	a1,a0
338	beq	a1,zero,chcach
339	nop
340
341	srl	a1,CONF1_IL_SHIFT
342	li	t0,CONF1_IL_BASE
343	sll	a1,t0,a1			# a1 has I$ cache line size
344
345	li	a2,CONF1_IA_MASK
346	and	a2,a0
347	srl	a2,CONF1_IA_SHIFT
348	addiu	a2,CONF1_IA_BASE		# a2 now has I$ associativity
349
350	li	t0,CONF1_IS_MASK
351	and	t0,a0
352	srl	t0,CONF1_IS_SHIFT
353	li	a3,CONF1_IS_BASE
354	sll	a3,a3,t0			# a3 has I$ sets per way
355
356	multu	a2,a3				# sets/way * associativity
357	mflo	t0				# total cache lines
358
359	multu	a1,t0				# I$ linesize * lines
360	mflo	a2				# a2 is cache size in bytes
361
362	/* Initilize the I$: */
363	mtc0	zero,C0_TAGLO
364	mtc0	zero,C0_TAGHI
365
366	li	t0,KSEG0			# Just an address for the first $ line
367	addu	t1,t0,a2			#  + size of cache == end
368
369	.set	mips32
3701:	cache	Index_Store_Tag_I,0(t0)
371	.set	mips0
372	bne	t0,t1,1b
373	addu	t0,a1
374
375chcach:
376	TRACE(0x424f10)
377	/* Caches initialized, change cacheability */
378	mfc0	t0,C0_CONFIG
379	and	t0,~CONF_CM_CMASK
380	or	t0,CONF_CM_CACHABLE_NONCOHERENT
381	mtc0	t0,C0_CONFIG
382	nop
383
384switchkseg0:
385	la	t2,board_draminit
386	add	t2,t2,s5
387	la	ra,backfbd
388	add	ra,ra,s5
389	jr	t2
390	nop
391
392	/* Should return ram size in v0 */
393backfbd:
394	bnez	v0,1f
395	nop
396
397panic:	TRACE2(0x424f0bad)
398	b	panic
399	nop
400
401	/* Re-check if we booted from SDRAM */
4021:	TRACE(0x424f11)
403	bal	2f
404	nop
405
4062:	li	t0,PHYSADDR_MASK
407	and	t0,t0,ra
408	li	t1,SI_FLASH1
409	blt	t0,t1,inram
410	nop
411
412	/* Copy self to SDRAM */
413copy2ram:
414	TRACE(0x424f12)
415#ifdef	CONFIG_XIP
416	la	a0,text_end
417	la	a1,data_start
418	la	a2,data_end
419#else
420	li	a0,KSEG0ADDR(SI_FLASH1)
421	la	a1,text_start
422	li	t0,PHYSADDR_MASK		# Uncached writes to avoid a flush
423	and	a1,a1,t0
424	li	t1,KSEG1
425	or	a1,a1,t1
426	la	a2,data_end
427	and	a2,a2,t0
428	or	a2,a2,t1
429#endif
4301:	lw	t0,0(a0)
431	sw	t0,0(a1)
432	add	a0,4
433	add	a1,4
434	blt	a1,a2,1b
435	nop
436
437	/* Go execute from ram now */
438	la	t0,inram
439	jr	t0
440	nop
441
442inram:
443clearbss:
444	TRACE(0x424f13)
445	/* Clear BSS */
446	la	a0,bss_start
447	la	a1,bss_end
4481:	sw	zero,0(a0)
449	addi	a0,a0,4
450	blt	a0,a1,1b
451	nop
452
453	/* Setup trap handlers */
454	TRACE(0x424f14)
455	la	t0,trap_init
456	jalr	t0
457	nop
458
459	/* Record the memory size */
4602:	TRACE(0x424f15)
461	la	t0,_memsize
462	sw	v0,0(t0)
463
464	/* Set up stack pointer */
465	or	v0,KSEG0
466	sub	sp,v0,4
467
468/* bootloader supports nvram dl: shift stack pointer beyond nvram */
469#ifdef DL_NVRAM
470	la	t1,_dlvarsz
471	sw	sp,0(t1)
472	li	a0,DL_NVRAM
473	sub	sp,sp,a0
474	la	t1,_dlvars
475	sw	sp,0(t1)
476	sub	sp,sp,4
477#endif /* DL_NVRAM */
478
479	/* Jump to C */
480	la	t0,c_main
481	jal	t0
482	move	a0,ra
483
484	/* In case c_main returns */
485theend:	TRACE2(0x424feedd)
486	nop
487	nop
488	.set	mips32
489	wait
490	.set	mips0
491	nop
492	nop
493	b	theend
494	nop
495
496	.set reorder
497	END(startup)
498
499	.data
500	.globl	_memsize
501_memsize:
502	.word	0
503
504#ifdef DL_NVRAM
505	.globl _dlvars
506_dlvars:
507	.word	0
508
509	.globl _dlvarsz
510_dlvarsz:
511	.word	0
512#endif /* DL_NVRAM */
513