1/*  *********************************************************************
2    *  SB1250 Board Support Package
3    *
4    *  CPU initialization			File: sb1250_cpu.S
5    *
6    *  This module contains code to initialize the CPU.
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
12    *
13    *********************************************************************
14    *
15    *  Copyright 2000,2001,2002,2003
16    *  Broadcom Corporation. All rights reserved.
17    *
18    *  This software is furnished under license and may be used and
19    *  copied only in accordance with the following terms and
20    *  conditions.  Subject to these conditions, you may download,
21    *  copy, install, use, modify and distribute modified or unmodified
22    *  copies of this software in source and/or binary form.  No title
23    *  or ownership is transferred hereby.
24    *
25    *  1) Any source code used, modified or distributed must reproduce
26    *     and retain this copyright notice and list of conditions
27    *     as they appear in the source file.
28    *
29    *  2) No right is granted to use any trade name, trademark, or
30    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
31    *     name may not be used to endorse or promote products derived
32    *     from this software without the prior written permission of
33    *     Broadcom Corporation.
34    *
35    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
36    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
37    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
39    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
40    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
41    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
43    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
46    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
47    *     THE POSSIBILITY OF SUCH DAMAGE.
48    ********************************************************************* */
49
50#include "sbmips.h"
51#include "bsp_config.h"
52#include "cpu_config.h"
53#include "mipsmacros.h"
54#include "exception.h"
55
56#include "sb1250_regs.h"
57#include "sb1250_scd.h"
58
59
60		.text
61		.set mips64
62
63		.extern _exc_entry
64
65
66/*  *********************************************************************
67    *  Macros
68    ********************************************************************* */
69
70/*
71 * Duplicates from cfe_iocb.h -- warning!
72 */
73
74#define CFE_CACHE_FLUSH_D	1
75#define CFE_CACHE_INVAL_I	2
76#define CFE_CACHE_INVAL_D	4
77#define CFE_CACHE_INVAL_L2	8
78#define CFE_CACHE_FLUSH_L2	16
79#define CFE_CACHE_INVAL_RANGE	32
80#define CFE_CACHE_FLUSH_RANGE	64
81
82#define L1CACHE_NUMWAYS	4
83#define L1CACHE_NUMIDX  256
84#define L1CACHE_LINESIZE 32
85#define L1CACHE_IDXHIGH (L1CACHE_LINESIZE*L1CACHE_NUMWAYS*L1CACHE_NUMIDX)
86
87#define L1CACHEOP(cachename,op) ((cachename) | ((op) << 2))
88
89#define L1C_OP_IDXINVAL     0
90#define L1C_OP_IDXLOADTAG   1
91#define L1C_OP_IDXSTORETAG  2
92#define L1C_OP_IMPLRSVD     3
93#define L1C_OP_HITINVAL     4
94#define L1C_OP_FILL         5
95#define L1C_OP_HITWRITEBACK 6
96#define L1C_OP_FETCHLOCK    7
97
98#define L1C_I		    0
99#define L1C_D		    1
100
101
102/*  *********************************************************************
103    *  LED macros
104    ********************************************************************* */
105
106#define SETLEDS1(a,b,c,d)                     \
107       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
108       JAL_KSEG1(board_setleds)
109#define SETLEDS(a,b,c,d)                     \
110       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
111       JAL_KSEG1(board_setleds)
112
113
114
115/*  *********************************************************************
116    *  SB1250_CPUINIT
117    *
118    *  Initialize the CPU core.
119    *
120    *  Input parameters:
121    *  	   nothing
122    *
123    *  Return value:
124    *  	   nothing
125    ********************************************************************* */
126
127LEAF(sb1250_cpuinit)
128
129		move	k0,ra			/* will be trashing RA */
130
131
132	/*
133	 * Clear the SOFTRES bit in the SYSTEM_CONFIG register.
134	 */
135
136		li	t0,PHYS_TO_K1(A_SCD_SYSTEM_CFG)
137		ld	t1,0(t0)
138		dli	t2,~M_SYS_SB_SOFTRES
139		and	t1,t1,t2
140		sd	t1,0(t0)
141
142
143	/*
144	 * Note that the initialization order here is important.
145	 * In particular, the cache needs to be running before
146	 * DRAM is turned on, since the DRAM init code is
147	 * in cacheable space.  This code assumes that we are
148	 * linked at KSEG0's address but are executed starting
149	 * in KSEG1.  Therefore, we need to be somewhat careful
150	 * until the cache is alive to call routines
151	 * making sure we are calling in KSEG1.
152	 */
153
154		JAL_KSEG1(sb1_cpu_init)
155
156
157#ifdef _SB1250_PASS1_WORKAROUNDS_
158	/*
159	 * Note: We initially set the coherency attribute
160	 * to just "cacheable" since we want to avoid problems
161	 * with coherency when Generic Bus (KSEG1) addresses are involved.
162	 * This is a pass-1 workaround, as in pass-1 the bridge can
163	 * respond again (after the CPU has already responded)
164	 * to a cacheable read, causing the cache to get wrong data.
165	 *
166	 * Once you are not using the generic bus for data anymore,
167	 * it is safe to switch to coherent.
168	 */
169
170		SETCCAMODE(v0,K_CFG_K0COH_CACHEABLE) /* cacheable NONCOHERENT */
171#endif
172
173#------------------------------------------------------------------------------
174
175	/*
176	 * Init the L1 cache.
177	 */
178
179#if CFG_INIT_L1
180		SETLEDS1('L','1','C','I')
181		JAL_KSEG1(sb1250_l1cache_init)
182#endif
183
184	/*
185         * Init the L2 cache.  We don't init L2 on
186	 * secondary CPU(s), since they are shared by all CPUs.  We'll
187         * do it here on CPU0.
188         */
189
190#if CFG_INIT_L2
191	 	SETLEDS1('L','2','C','I')
192		JAL_KSEG1(sb1250_l2cache_init)
193#endif
194
195		move	ra,k0			/* saved return address */
196		j	ra
197
198
199END(sb1250_cpuinit)
200
201/*  *********************************************************************
202    *  SB1250_CPURESTART
203    *
204    *  'Restart' the CPU (reset things back to some sane state after
205    *  a program returns to the firmware)
206    *
207    *  Input parameters:
208    *  	   nothing
209    *
210    *  Return value:
211    *  	   nothing
212    ********************************************************************* */
213
214#ifndef _ZIPSTART_
215LEAF(sb1250_cpurestart)
216
217		move	k0,ra
218
219		JAL(sb1_cp0_init)
220
221		LR	v0,cfe_pagetable		# reestablish
222		dsll	v0,v0,13			# see mips_arena.c for this
223		dmtc0	v0,C0_CTEXT			# boot area TLBs
224
225		move	ra,k0
226		j	ra
227
228END(sb1250_cpurestart)
229#endif
230
231
232/*  *********************************************************************
233    *  SB1250_CACHEOPS
234    *
235    *  This routine handles the various cache-related functions
236    *  needed by CFE.
237    *
238    *  Input parameters:
239    *  	   a0 - cache functions (bit mask)
240    *
241    *  Return value:
242    *  	   nothing
243    *
244    *  Registers used:
245    *  	   trashes t0..t7, a0, v0  (especially for L2)
246    ********************************************************************* */
247
248LEAF(sb1250_cacheops)
249
250		move	s0,ra
251
252		move	v1,a0
253
254	/*
255	 * With no flags, we flush L1D and invalid L1I
256	 */
257
258		bne	v1,zero,1f
259		li	v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I
2601:
261
262	/*
263	 * Flush the D-Cache, since the program we loaded is "data".
264	 */
265
266		and	a0,v1,CFE_CACHE_FLUSH_D
267		beq	a0,zero,1f
268		JAL(sb1250_l1cache_flush_d)
2691:
270
271	/*
272	 * Invalidate the I-Cache, so that addresses in the program
273	 * region will miss and need to be filled from the data we
274	 * just flushed above.
275	 */
276
277		and	a0,v1,CFE_CACHE_INVAL_I
278		beq	a0,zero,1f
279		JAL(sb1250_l1cache_inval_i)
2801:
281
282	/*
283	 * Invalidate the L2, if requested.  Use this cautiously,
284	 * since it invalidates both I and D!
285	 */
286
287		and	a0,v1,CFE_CACHE_INVAL_L2
288		beq	a0,zero,1f
289		JAL(sb1250_l2cache_init)
2901:
291
292
293	/*
294	 * Invalidate cache range
295	 */
296
297		and	a0,v1,CFE_CACHE_INVAL_RANGE
298		beq	a0,zero,2f
299
300		move	t0,a1
3011:		cache	L1CACHEOP(L1C_D,L1C_OP_HITINVAL),0(t0)
302		add	t0,L1CACHE_LINESIZE
303		blt	t0,a2,1b
304
305	/*
306	 * Flush cache range
307	 */
308
309
3102:
311		and	a0,v1,CFE_CACHE_FLUSH_RANGE
312		beq	a0,zero,2f
313
314		move	t0,a1
3151:		cache	L1CACHEOP(L1C_D,L1C_OP_HITWRITEBACK),0(t0)
316		add	t0,L1CACHE_LINESIZE
317		blt	t0,a2,1b
318
3192:
320
321	/*
322	 * Invalidate the L2, if requested.  Use this cautiously,
323	 * since it invalidates both I and D!
324	 */
325
326		and	a0,v1,CFE_CACHE_FLUSH_L2
327		beq	a0,zero,1f
328		JAL(sb1250_l2cache_flush)	/* Trashes T0..T7, V0, A0 */
3291:
330
331		move	ra,s0
332		j	ra
333
334END(sb1250_cacheops)
335
336
337/*  *********************************************************************
338    *  SB1250_TLBHANDLER
339    *
340    *  This is the TLB exception handler for the SB1250.
341    *
342    *  Note: only K0 and K1 are available to us at this time.
343    *
344    *  Input parameters:
345    *  	   nothing
346    *
347    *  Return value:
348    *  	   nothing
349    ********************************************************************* */
350
351
352LEAF(sb1250_tlbhandler)
353                .set    noreorder
354                .set    noat
355
356/*
357 * This requires a bit of explanation:  We only support 256KB
358 * of mapped space for the boot program.  This space will be
359 * mapped from 0x2000_0000 to 0x2004_0000 to some physical
360 * memory allocated by the firmware.  This is 64 pages
361 * of 4KB each.
362 *
363 * We know our BadVPN2 will be in the range
364 * 0x100000 to 0x1001F0, since the memory is mapped from
365 * 0x2000_0000 to 0x2004_0000.  BadVPN2 plus the four bits
366 * of zeroes at the end are bits 31..9
367 *
368 * We also want to place the PTEbase on something other than
369 * a 16MB boundary.  Each entry is 16 bytes, and there
370 * are 64 entries, so we need only 10 bits to address
371 * the entire table (it can therefore be aligned on a
372 * 1KB boundary).
373 *
374 * To make this work, we'll shift PTEbase to the right, leaving
375 * the bottom ten bits for the page number, as:
376 *
377 *    Bits 31..10: PTEbase
378 *    Bits 9..4:   BadVPN
379 *    Bits 3..0:   16 bytes for table entry
380 *
381 * Therefore:
382 *    PTEbase gets shifted right 13 bits.
383 *    BadVPN  gets masked at 6 bits (mask is 0x3F0)
384 *    The bottom 4 bits are zero.
385 *
386 * To range check the address, we can shift the Bad VPN
387 * right by 9 bits, and check for values of 0x1000 and
388 * 0x1001.
389 */
390
391
392	/*
393	 * This part range checks the VPN2 field in the
394	 * context register.  We only handle
395	 * VPN2s in the range 0x100000 to 0x1001F0
396	 */
397		dmfc0	k0,C0_TLBHI
398
399		dmfc0	k0,C0_CTEXT		# Get context
400		dsra	k0,8			# keep hi part
401		and	k0,0x1FFF		# of VPN2
402		li	k1,0x1000		# 0x1000 is ok
403		beq	k0,k1,1f		#
404		nop				# BDSLOT
405		li	k1,0x1001		# 0x1001 is ok
406		beq	k0,k1,1f		#
407		nop				# BDSLOT
408
409		li	k0,XTYPE_TLBFILL	# all other bits are not
410		JMP(_exc_entry)
411		nop				# BDSLOT
412
4131:		dmfc0	k0,C0_CTEXT		# Get context
414		dsra	k0,13			# Shift PTEbase
415		li	k1,0x3FF		# Generate mask to kill
416		not	k1			# BadVPN2 bits
417		and	k0,k1			# keep only PTEBase part.
418
419		dmfc0	k1,C0_CTEXT		# Get Context
420		and	k1,0x3F0		# Keep only BadVPN2 bits
421		or	k1,k0			# Replace PTEBase
422
423		ld	k0,0(k1)		# Load entrylo0
424		ld	k1,8(k1)		# Load entrylo1
425		mtc0	k0,C0_TLBLO0		# and write to CP0
426		mtc0	k1,C0_TLBLO1
427		tlbwr				# put it in the TLB
428		eret
429		nop
430
431		.set	reorder
432		.set	at
433
434END(sb1250_tlbhandler)
435
436/*  *********************************************************************
437    *  sb1250_cerrhandler
438    *
439    *  Cache error handler.  We get called here on a cache error
440    *  exception.   Registers k0, k1, gp, and sp have been saved
441    *  for us.  We are running uncached, with ERL set, so kuseg
442    *  is mapped into uncached memory.
443    *
444    *  Input parameters:
445    *  	   nothing
446    *
447    *  Return value:
448    *  	   nothing
449    ********************************************************************* */
450
451LEAF(sb1250_cerrhandler)
452
453		mfc0	k0, $26
454		bgez	k0, real_cerr
455
456		mtc0	zero, $26
457		mtc0	zero, $27
458		mtc0	zero, $27, 1
459		mtc0	zero, $27, 3
460		eret
461
462real_cerr:	SETLEDS1('C','e','r','r')
463
4641:		b	1b		/* death */
465
466END(sb1250_cerrhandler)
467
468
469/*  *********************************************************************
470    *  End
471    ********************************************************************* */
472
473
474