1/*  *********************************************************************
2    *  SB1250 Board Support Package
3    *
4    *  CPU initialization			File: bcmcore_cpuinit.S
5    *
6    *  This module contains code to initialize the CPU cores.
7    *
8    *  Note: all the routines in this module rely on registers only,
9    *        since DRAM may not be active yet.
10    *
11    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
12    *
13    *********************************************************************
14    *
15    *  XX Copyright 2000,2001
16    *  Broadcom Corporation. All rights reserved.
17    *
18    *  BROADCOM PROPRIETARY AND CONFIDENTIAL
19    *
20    *  This software is furnished under license and may be used and
21    *  copied only in accordance with the license.
22    ********************************************************************* */
23
24#include "sbmips.h"
25#include "exception.h"
26#include "bsp_config.h"
27#include "mipsmacros.h"
28#include "cpu_config.h"			/* for ERET and HAZARD */
29#include "cfe_iocb.h"
30
31
32		.text
33
34		.set mips32
35
36/*  *********************************************************************
37    *  Macros
38    ********************************************************************* */
39
40#define R_CPU_CP0INIT _TBLIDX(0)
41#define R_CPU_L1CINIT _TBLIDX(1)
42#define R_CPU_SETLEDS _TBLIDX(2)
43
44#define SETLEDS1(a,b,c,d)                     \
45       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
46       CALLINIT_KSEG1(cpuinit_table,R_CPU_SETLEDS)
47#define SETLEDS(a,b,c,d)                     \
48       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
49       CALLINIT_KSEG0(cpuinit_table,R_CPU_SETLEDS)
50
51cpuinit_table:
52		_LONG_	bcmcore_cp0_init	# [ 0 ] R_CPU_CP0INIT
53		_LONG_	bcmcore_l1cache_init    # [ 1 ] R_CPU_L1CINIT
54		_LONG_  board_setleds		# [ 2 ] R_CPU_SETLEDS
55
56
57/*  *********************************************************************
58    *  BCMCORE_CP0_INIT()
59    *
60    *  Initialize an BCMCORE CPU's CP0 registers
61    *
62    *  Input parameters:
63    *  	   nothing
64    *
65    *  Return value:
66    *  	   nothing
67    *
68    *  Registers used:
69    *  	   all
70    ********************************************************************* */
71
72
73LEAF(bcmcore_cp0_init)
74
75		.set	noreorder
76
77		mtc0	zero,C0_WATCHLO		# Watch registers.
78		mtc0	zero,C0_WATCHHI
79		mtc0	zero,C0_CAUSE		# must clear before writing SR
80
81		mfc0	v0,C0_SR		# Get status register
82		and	v0,M_SR_SR		# preserve soft reset
83#ifdef DEBUG_ENV_ICE
84		and	v0,~M_SR_BEV
85#else
86		or	v0,M_SR_BEV		# exceptions to boot vector
87#endif
88		mtc0	v0,C0_SR		# set up the status register
89
90
91		mfc0	v0,C0_CONFIG		# get current CONFIG register
92		srl	v0,v0,3			# strip out K0 bits
93		sll	v0,v0,3			# k0 bits now zero
94		or	v0,v0,K_CFG_K0COH_CACHEABLE # K0 is cacheable.
95		mtc0	v0,C0_CONFIG
96		nop
97
98		mfc0	v0,C0_PRID
99		and	v0,0x00fffe00
100		bne	v0,0x00029000,1f	# Broadcom BCM330X
101		nop
102		mfc0	v0,C0_DIAGNOSTIC
103		or	v0,0x80000000		# Enable icache
104		or	v0,0x40000000		# Enable dcache
105		mtc0	v0,C0_DIAGNOSTIC
106
1071:		mtc0	zero,C0_WATCHLO		# Watch registers.
108		mtc0	zero,C0_WATCHHI
109
110		mtc0	zero,C0_TLBHI		# TLB entry (high half)
111		nop
112
113
114	#
115	# This is probably not the right init value for C0_COMPARE,
116	# but it seems to be necessary for the sim model right now.
117	#
118
119		li	v0,-1
120		mtc0	v0,C0_COMPARE
121		nop
122
123	#
124	# Initialize all the TLB entries to some invalid value
125	#
126
127		mtc0	zero,C0_TLBLO0		/* tlblo0 = invalid */
128		nop
129		mtc0	zero,C0_TLBLO1		/* tlblo1 = invalid */
130		nop
131		mtc0	zero,C0_PGMASK		/* 4K pages */
132		nop
133
134		li	t0,K1BASE		/* tlbhi  = impossible vpn */
135		mfc0	v0,C0_CONFIG,1
136		li	t1,M_CFG_MMUSIZE
137		and	t1,v0
138		srl	t1,S_CFG_MMUSIZE	/* index */
139
140
141		nop
1421:		mtc0	t0,C0_TLBHI
143		nop
144		mtc0	t1,C0_INX
145		nop
146		addu	t0,0x2000		/* inc vpn */
147		tlbwi
148		bnez	t1,1b
149		subu	t1,1			# BDSLOT
150		.set reorder
151
152
153
154		jr	ra
155
156
157END(bcmcore_cp0_init)
158
159
160/*  *********************************************************************
161    *  BCMCORE_CPUINIT
162    *
163    *  Do initialization of the Broadcom core
164    *
165    *  Input parameters:
166    *  	   nothing
167    *
168    *  Return value:
169    *  	   nothing
170    ********************************************************************* */
171
172
173LEAF(bcmcore_cpuinit)
174
175		move	fp,ra
176
177		SETLEDS1('C','P','U','I')
178		CALLINIT_KSEG1(cpuinit_table,R_CPU_CP0INIT)
179#if  CFG_INIT_L1 > 0
180		SETLEDS1('L','1','C','I')
181		CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINIT)
182#endif
183		move	ra,fp
184		j	ra
185
186END(bcmcore_cpuinit)
187
188
189/*  *********************************************************************
190    *  BCMCORE_NULL
191    *
192    *  Dummy handler for routines we don't need to implement, like
193    *  the multiprocessor stuff
194    *
195    *  Input parameters:
196    *  	   nothing
197    *
198    *  Return value:
199    *  	   nothing
200    *
201    *  Registers used:
202    *  	   none
203    ********************************************************************* */
204
205LEAF(bcmcore_null)
206
207		j	ra
208
209END(bcmcore_null)
210
211
212/*  *********************************************************************
213    *  BCMCORE_CPURESTART
214    *
215    *  This routine is called when someone soft-exits to CFE.  We
216    *  reinitialize any CP0 stuff here.
217    *
218    *  Input parameters:
219    *  	   nothing
220    *
221    *  Return value:
222    *  	   nothing
223    ********************************************************************* */
224
225LEAF(bcmcore_cpurestart)
226
227		j	ra
228
229END(bcmcore_cpurestart)
230
231
232/*  *********************************************************************
233    *  BCMCORE_CACHEOPS
234    *
235    *  Perform various cache operations on a BCM Core
236    *
237    *  Input parameters:
238    *  	   a0 - flag bits (CFE_CACHE_xxx)
239    *
240    *  Return value:
241    *  	   nothing
242    *
243    *  Registers used:
244    *  	   t0,t1,t2,t3,v1,s0
245    ********************************************************************* */
246
247LEAF(bcmcore_cacheops)
248
249		move	s0,ra
250
251		move	v1,a0
252
253	/*
254	 * With no flags, we flush L1D and invalid L1I
255	 */
256
257		bne	v1,zero,1f
258		li	v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I
2591:
260
261	/*
262	 * Flush the D-Cache, since the program we loaded is "data".
263	 */
264
265		and	a0,v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_D | CFE_CACHE_FLUSH_RANGE | CFE_CACHE_INVAL_RANGE
266		beq	a0,zero,1f
267		jal	bcmcore_l1cache_flush_d
2681:
269
270	/*
271	 * Invalidate the I-Cache, so that addresses in the program
272	 * region will miss and need to be filled from the data we
273	 * just flushed above.
274	 */
275
276		and	a0,v1,CFE_CACHE_INVAL_I
277		beq	a0,zero,1f
278		jal	bcmcore_l1cache_inval_i
2791:
280
281		move	ra,s0
282		j	ra
283
284END(bcmcore_cacheops)
285
286
287
288/*  *********************************************************************
289    *  BCMCORE_TLBHANDLER
290    *
291    *  This is the TLB exception handler for the bcmcore
292    *
293    *  Note: only K0 and K1 are available to us at this time.
294    *
295    *  Input parameters:
296    *  	   nothing
297    *
298    *  Return value:
299    *  	   nothing
300    ********************************************************************* */
301
302
303LEAF(bcmcore_tlbhandler)
304                .set    noreorder
305                .set    noat
306
307#ifdef BCM4704
308		nop
309#endif
310
311
312/*
313 * This requires a bit of explanation:  We only support 256KB
314 * of mapped space for the boot program.  This space will be
315 * mapped from 0x2000_0000 to 0x2004_0000 to some physical
316 * memory allocated by the firmware.  This is 64 pages
317 * of 4KB each.
318 *
319 * We know our BadVPN2 will be in the range
320 * 0x100000 to 0x1001F0, since the memory is mapped from
321 * 0x2000_0000 to 0x2004_0000.  BadVPN2 plus the four bits
322 * of zeroes at the end are bits 31..9
323 *
324 * We also want to place the PTEbase on something other than
325 * a 16MB boundary.  Each entry is 16 bytes, and there
326 * are 64 entries, so we need only 10 bits to address
327 * the entire table (it can therefore be aligned on a
328 * 1KB boundary).
329 *
330 * To make this work, we'll shift PTEbase to the right, leaving
331 * the bottom ten bits for the page number, as:
332 *
333 *    Bits 31..10: PTEbase
334 *    Bits 9..4:   BadVPN
335 *    Bits 3..0:   16 bytes for table entry
336 *
337 * Therefore:
338 *    PTEbase gets shifted right 13 bits.
339 *    BadVPN  gets masked at 6 bits (mask is 0x3F0)
340 *    The bottom 4 bits are zero.
341 *
342 * To range check the address, we can shift the Bad VPN
343 * right by 9 bits, and check for values of 0x1000 and
344 * 0x1001.
345 */
346
347
348	/*
349	 * This part range checks the VPN2 field in the
350	 * context register.  We only handle
351	 * VPN2s in the range 0x100000 to 0x1001F0
352	 */
353		mfc0	k0,C0_TLBHI
354
355		mfc0	k0,C0_CTEXT		# Get context
356		sra	k0,8			# keep hi part
357		and	k0,0x1FFF		# of VPN2
358		li	k1,0x1000		# 0x1000 is ok
359		beq	k0,k1,1f		#
360		nop				# BDSLOT
361		li	k1,0x1001		# 0x1001 is ok
362		beq	k0,k1,1f		#
363		nop				# BDSLOT
364
365		li	k0,XTYPE_TLBFILL	# all other bits are not
366		j	_exc_entry
367		nop				# BDSLOT
368
3691:		mfc0	k0,C0_CTEXT		# Get context
370		sra	k0,13			# Shift PTEbase
371		li	k1,0x3FF		# Generate mask to kill
372		not	k1			# BadVPN2 bits
373		and	k0,k1			# keep only PTEBase part.
374
375		mfc0	k1,C0_CTEXT		# Get Context
376		and	k1,0x3F0		# Keep only BadVPN2 bits
377		or	k1,k0			# Replace PTEBase
378
379		ld	k0,0(k1)		# Load entrylo0
380		ld	k1,8(k1)		# Load entrylo1
381		mtc0	k0,C0_TLBLO0		# and write to CP0
382		mtc0	k1,C0_TLBLO1
383		tlbwr				# put it in the TLB
384		ERET
385		nop
386
387		.set	reorder
388		.set	at
389
390END(bcmcore_tlbhandler)
391
392
393/*  *********************************************************************
394    *  End
395    ********************************************************************* */
396
397