• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/cfe/cfe/arch/mips/cpu/rm7000/src/
1/*  *********************************************************************
2    *  P5064 Board Support Package
3    *
4    *  CPU initialization			File: rm7000_cpuinit.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 (mpl@broadcom.com)
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 "mipsmacros.h"
53#include "exception.h"
54
55
56		.text
57		.set mips64
58
59
60/*  *********************************************************************
61    *  Macros
62    ********************************************************************* */
63
64#define CFG_BE		0x00008000	/* Big Endian */
65#define CFG_EPMASK	0x0f000000	/* Transmit data pattern */
66#define CFG_EPD		0x00000000	/* D */
67#define NTLBENTRIES 64
68#define LINESIZE 32
69
70
71#define CACHEOP(cachename,op) ((cachename) | ((op) << 2))
72
73#define CACHE_OP_IDXINVAL     0
74#define CACHE_OP_IDXLOADTAG   1
75#define CACHE_OP_IDXSTORETAG  2
76#define CACHE_OP_IMPLRSVD     3
77#define CACHE_OP_HITINVAL     4
78#define CACHE_OP_FILL         5
79#define CACHE_OP_HITWRITEBACK_INVAL  5
80#define CACHE_OP_HITWRITEBACK 6
81#define CACHE_OP_FETCHLOCK    7
82
83#define L2C		    3
84#define L1C_I		    0
85#define L1C_D		    1
86
87
88/*
89 * Duplicates from cfe_iocb.h -- warning!
90 */
91
92#define CFE_CACHE_FLUSH_D	1
93#define CFE_CACHE_INVAL_I	2
94#define CFE_CACHE_INVAL_D	4
95#define CFE_CACHE_INVAL_L2	8
96#define CFE_CACHE_FLUSH_L2	16
97#define CFE_CACHE_INVAL_RANGE	32
98#define CFE_CACHE_FLUSH_RANGE	64
99
100/*  *********************************************************************
101    *  Linkage tables
102    ********************************************************************* */
103
104#define R_CPU_CP0INIT	_TBLIDX(0)
105#define R_CPU_L1CINIT	_TBLIDX(1)
106#define R_CPU_L2CINIT	_TBLIDX(2)
107#define R_CPU_SETLEDS	_TBLIDX(3)
108
109cpuinit_table:
110		_LONG_  rm7000_cp0_init		# [  0] R_CPU_CP0INIT
111		_LONG_  rm7000_l1cache_init	# [  1] R_CPU_L1CINIT
112		_LONG_  rm7000_l2cache_init	# [  1] R_CPU_L2CINIT
113		_LONG_  board_setleds		# [  3] R_CPU_SETLEDS
114
115#define SETLEDS1(a,b,c,d)                     \
116       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
117       CALLINIT_KSEG1(cpuinit_table,R_CPU_SETLEDS)
118#define SETLEDS(a,b,c,d)                     \
119       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
120       CALLINIT_KSEG0(cpuinit_table,R_CPU_SETLEDS)
121
122
123
124/*  *********************************************************************
125    *  RM7000_CP0_INIT
126    *
127    *  Initialize CP0 registers for an RM7000 core.
128    *
129    *  Input parameters:
130    *  	   nothing
131    *
132    *  Return value:
133    *  	   nothing
134    ********************************************************************* */
135
136LEAF(rm7000_cp0_init)
137
138	/*
139	 * Set SR and CAUSE to something sensible.
140	 */
141
142		.set noreorder
143		mfc0	t0,C0_PRID
144		mfc0	v0,C0_SR
145		mtc0	zero,C0_WATCHLO
146		mtc0	zero,C0_WATCHHI
147		li	t1,-1
148		mtc0	t1,C0_COMPARE
149		and	v0,M_SR_SR		# preserve Soft Reset
150		or	v0,M_SR_BEV		# set Boot Exceptions
151		mtc0	zero,C0_CAUSE		# Must clear WP before
152		mtc0	v0,C0_SR		# writing STATUS register.
153		.set reorder
154
155
156		mfc0	t1,C0_CONFIG
157
158		mtc0	zero,C0_WATCHLO
159		mtc0	zero,C0_WATCHHI
160
161	/*
162	 * make KSEG0 cacheable
163	 */
164
165	 	and	t1,~M_CFG_K0COH
166		or	t1,V_CFG_K0COH(K_CFG_K0COH_CACHEABLE)
167		or	t1,0x08			/* enable SCache */
168		and	t1,~(1<<12)		/* disable TCache */
169
170	/*
171	 * set DDDD rate for CPUs that aren't hardware configured
172 	 */
173
174	 	and	t1,~CFG_EPMASK
175		or	t1,CFG_EPD
176
177#ifdef __MIPSEB
178		or	t1,CFG_BE
179#else
180		and	t1,~CFG_BE
181#endif
182		mtc0	t1,C0_CONFIG
183
184
185	/*
186	 * initialize tlb
187	 */
188	 	mtc0	zero,C0_TLBLO0		/* tlblo0 = invalid */
189		mtc0	zero,C0_TLBLO1		/* tlblo1 = invalid */
190		mtc0	zero,C0_PGMASK
191		li	t8,K1BASE		/* tlbhi  = impossible vpn */
192		li	t9,(NTLBENTRIES-1)	/* index */
193
194
195		.set noreorder
196		nop
1971:		mtc0	t8,C0_TLBHI
198		mtc0	t9,C0_INX
199		addu	t8,0x2000		/* inc vpn */
200		tlbwi
201		bnez	t9,1b
202		subu	t9,1			# BDSLOT
203		.set reorder
204
205		j	ra
206
207END(rm7000_cp0_init)
208
209
210/*  *********************************************************************
211    *  RM7000_NULL_INIT
212    *
213    *  This stub routine is used by initialization functions that
214    *  we leave unimplemented.
215    *
216    *  Input parameters:
217    *  	   nothing
218    *
219    *  Return value:
220    *  	   nothing
221    ********************************************************************* */
222
223LEAF(rm7000_null_init)
224		j	ra
225END(rm7000_null_init)
226
227
228
229/*  *********************************************************************
230    *  RM7000_CPUINIT
231    *
232    *  Initialize the CPU core.
233    *
234    *  Input parameters:
235    *  	   nothing
236    *
237    *  Return value:
238    *  	   nothing
239    ********************************************************************* */
240
241LEAF(rm7000_cpuinit)
242
243		move	k0,ra			/* will be trashing RA */
244
245	/*
246	 * Basic CPU initialization
247	 */
248
249		CALLINIT_KSEG1(cpuinit_table,R_CPU_CP0INIT)
250
251	/*
252	 * CP0 registers
253	 */
254
255
256#------------------------------------------------------------------------------
257
258	/*
259	 * Init the L1 cache.
260	 */
261
262#if CFG_INIT_L1
263		SETLEDS1('L','1','C','I')
264		CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINIT)
265#endif
266
267	/*
268         * Init the L2 cache
269         */
270#if CFG_INIT_L1
271		SETLEDS1('L','2','C','I')
272		CALLINIT_KSEG1(cpuinit_table,R_CPU_L2CINIT)
273#endif
274
275		move	ra,k0			/* saved return address */
276		j	ra
277
278
279END(rm7000_cpuinit)
280
281/*  *********************************************************************
282    *  RM7000_CPURESTART
283    *
284    *  'Restart' the CPU (reset things back to some sane state after
285    *  a program returns to the firmware)
286    *
287    *  Input parameters:
288    *  	   nothing
289    *
290    *  Return value:
291    *  	   nothing
292    ********************************************************************* */
293
294LEAF(rm7000_cpurestart)
295
296		move	k0,ra
297
298		CALLINIT_KSEG0(cpuinit_table,R_CPU_CP0INIT)
299
300		LR	v0,cfe_pagetable		# reestablish
301		dsll	v0,v0,13			# see mips_arena.c for this
302		dmtc0	v0,C0_CTEXT			# boot area TLBs
303
304		move	ra,k0
305		j	ra
306
307END(rm7000_cpurestart)
308
309
310LEAF(rm7000_cacheops)
311
312		move	s0,ra
313
314		move	v1,a0
315
316	/*
317	 * With no flags, we flush L1D and invalid L1I
318	 */
319
320		bne	v1,zero,1f
321		li	v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I
3221:
323
324	/*
325	 * Flush the D-Cache, since the program we loaded is "data".
326	 */
327
328		and	a0,v1,CFE_CACHE_FLUSH_D
329		beq	a0,zero,1f
330		jal	rm7000_l1cache_flush_d
3311:
332
333	/*
334	 * Invalidate the I-Cache, so that addresses in the program
335	 * region will miss and need to be filled from the data we
336	 * just flushed above.
337	 */
338
339		and	a0,v1,CFE_CACHE_INVAL_I
340		beq	a0,zero,1f
341		jal	rm7000_l1cache_inval_i
3421:
343
344
345	/*
346	 * Invalidate the L2, if requested.  Use this cautiously,
347	 * since it invalidates both I and D!
348	 */
349
350		and	a0,v1,CFE_CACHE_INVAL_L2
351		beq	a0,zero,1f
352		jal	rm7000_l2cache_init
3531:
354
355	/*
356	 * Invalidate the L2, if requested.  Use this cautiously,
357	 * since it invalidates both I and D!
358	 */
359
360		and	a0,v1,CFE_CACHE_FLUSH_L2
361		beq	a0,zero,1f
362		jal	rm7000_l2cache_flush	/* Trashes T0..T7, V0, A0 */
3631:
364
365	/*
366	 * Invalidate cache range
367	 */
368
369		and	a0,v1,CFE_CACHE_INVAL_RANGE
370		beq	a0,zero,2f
371
372		move	t0,a1
3731:		cache	CACHEOP(L2C,CACHE_OP_HITINVAL),0(t0)
374		add	t0,LINESIZE
375		blt	t0,a2,1b
376
377		move	t0,a1
3781:		cache	CACHEOP(L1C_D,CACHE_OP_HITINVAL),0(t0)
379		add	t0,LINESIZE
380		blt	t0,a2,1b
381
382	/*
383	 * Flush cache range
384	 */
385
386
3872:
388		and	a0,v1,CFE_CACHE_FLUSH_RANGE
389		beq	a0,zero,2f
390
391		move	t0,a1
3921:		cache	CACHEOP(L1C_D,CACHE_OP_HITWRITEBACK_INVAL),0(t0)
393		add	t0,LINESIZE
394		blt	t0,a2,1b
395		move	t0,a1
3961:		cache	CACHEOP(L2C,CACHE_OP_HITWRITEBACK_INVAL),0(t0)
397		add	t0,LINESIZE
398		blt	t0,a2,1b
399
400
4012:
402		move	ra,s0
403		j	ra
404
405END(rm7000_cacheops)
406
407/*  *********************************************************************
408    *  RM7000_TLBHANDLER
409    *
410    *  This is the TLB exception handler for the RM7000
411    *
412    *  Note: only K0 and K1 are available to us at this time.
413    *
414    *  Input parameters:
415    *  	   nothing
416    *
417    *  Return value:
418    *  	   nothing
419    ********************************************************************* */
420
421
422LEAF(rm7000_tlbhandler)
423                .set    noreorder
424                .set    noat
425
426/*
427 * This requires a bit of explanation:  We only support 256KB
428 * of mapped space for the boot program.  This space will be
429 * mapped from 0x2000_0000 to 0x2004_0000 to some physical
430 * memory allocated by the firmware.  This is 64 pages
431 * of 4KB each.
432 *
433 * We know our BadVPN2 will be in the range
434 * 0x100000 to 0x1001F0, since the memory is mapped from
435 * 0x2000_0000 to 0x2004_0000.  BadVPN2 plus the four bits
436 * of zeroes at the end are bits 31..9
437 *
438 * We also want to place the PTEbase on something other than
439 * a 16MB boundary.  Each entry is 16 bytes, and there
440 * are 64 entries, so we need only 10 bits to address
441 * the entire table (it can therefore be aligned on a
442 * 1KB boundary).
443 *
444 * To make this work, we'll shift PTEbase to the right, leaving
445 * the bottom ten bits for the page number, as:
446 *
447 *    Bits 31..10: PTEbase
448 *    Bits 9..4:   BadVPN
449 *    Bits 3..0:   16 bytes for table entry
450 *
451 * Therefore:
452 *    PTEbase gets shifted right 13 bits.
453 *    BadVPN  gets masked at 6 bits (mask is 0x3F0)
454 *    The bottom 4 bits are zero.
455 *
456 * To range check the address, we can shift the Bad VPN
457 * right by 9 bits, and check for values of 0x1000 and
458 * 0x1001.
459 */
460
461
462	/*
463	 * This part range checks the VPN2 field in the
464	 * context register.  We only handle
465	 * VPN2s in the range 0x100000 to 0x1001F0
466	 */
467		dmfc0	k0,C0_TLBHI
468
469		dmfc0	k0,C0_CTEXT		# Get context
470		dsra	k0,8			# keep hi part
471		and	k0,0x1FFF		# of VPN2
472		li	k1,0x1000		# 0x1000 is ok
473		beq	k0,k1,1f		#
474		nop				# BDSLOT
475		li	k1,0x1001		# 0x1001 is ok
476		beq	k0,k1,1f		#
477		nop				# BDSLOT
478
479		li	k0,XTYPE_TLBFILL	# all other bits are not
480		j	_exc_entry
481		nop				# BDSLOT
482
4831:		dmfc0	k0,C0_CTEXT		# Get context
484		dsra	k0,13			# Shift PTEbase
485		li	k1,0x3FF		# Generate mask to kill
486		not	k1			# BadVPN2 bits
487		and	k0,k1			# keep only PTEBase part.
488
489		dmfc0	k1,C0_CTEXT		# Get Context
490		and	k1,0x3F0		# Keep only BadVPN2 bits
491		or	k1,k0			# Replace PTEBase
492
493		ld	k0,0(k1)		# Load entrylo0
494		ld	k1,8(k1)		# Load entrylo1
495		mtc0	k0,C0_TLBLO0		# and write to CP0
496		mtc0	k1,C0_TLBLO1
497		tlbwr				# put it in the TLB
498		eret
499		nop
500
501		.set	reorder
502		.set	at
503
504END(rm7000_tlbhandler)
505
506/*  *********************************************************************
507    *  End
508    ********************************************************************* */
509