xref: /linux/arch/mips/kernel/bmips_5xxx_init.S (revision 95298d63c67673c654c08952672d016212b26054)
1
2/*
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License.  See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 * Copyright (C) 2011-2012 by Broadcom Corporation
8 *
9 * Init for bmips 5000.
10 * Used to init second core in dual core 5000's.
11 */
12
13#include <linux/init.h>
14
15#include <asm/asm.h>
16#include <asm/asmmacro.h>
17#include <asm/cacheops.h>
18#include <asm/regdef.h>
19#include <asm/mipsregs.h>
20#include <asm/stackframe.h>
21#include <asm/addrspace.h>
22#include <asm/hazards.h>
23#include <asm/bmips.h>
24
25#ifdef CONFIG_CPU_BMIPS5000
26
27
28#define cacheop(kva, size, linesize, op) 	\
29	.set noreorder			;	\
30	addu		t1, kva, size	;	\
31	subu		t2, linesize, 1	;	\
32	not		t2		;	\
33	and		t0, kva, t2	;	\
34	addiu		t1, t1, -1	;	\
35	and		t1, t2		;	\
369:	cache		op, 0(t0)	;	\
37	bne		t0, t1, 9b	;	\
38	 addu		t0, linesize	;	\
39	.set reorder			;
40
41
42
43#define	IS_SHIFT	22
44#define	IL_SHIFT	19
45#define	IA_SHIFT	16
46#define	DS_SHIFT	13
47#define	DL_SHIFT	10
48#define	DA_SHIFT	 7
49#define	IS_MASK		 7
50#define	IL_MASK		 7
51#define	IA_MASK		 7
52#define	DS_MASK		 7
53#define	DL_MASK		 7
54#define	DA_MASK		 7
55#define	ICE_MASK	0x80000000
56#define	DCE_MASK	0x40000000
57
58#define CP0_BRCM_CONFIG0	$22, 0
59#define CP0_BRCM_MODE		$22, 1
60#define	CP0_CONFIG_K0_MASK	7
61
62#define CP0_ICACHE_TAG_LO	$28
63#define CP0_ICACHE_DATA_LO	$28, 1
64#define CP0_DCACHE_TAG_LO	$28, 2
65#define CP0_D_SEC_CACHE_DATA_LO	$28, 3
66#define CP0_ICACHE_TAG_HI	$29
67#define CP0_ICACHE_DATA_HI	$29, 1
68#define CP0_DCACHE_TAG_HI	$29, 2
69
70#define CP0_BRCM_MODE_Luc_MASK		(1 << 11)
71#define	CP0_BRCM_CONFIG0_CWF_MASK	(1 << 20)
72#define	CP0_BRCM_CONFIG0_TSE_MASK	(1 << 19)
73#define CP0_BRCM_MODE_SET_MASK		(1 << 7)
74#define CP0_BRCM_MODE_ClkRATIO_MASK	(7 << 4)
75#define CP0_BRCM_MODE_BrPRED_MASK 	(3 << 24)
76#define CP0_BRCM_MODE_BrPRED_SHIFT	24
77#define CP0_BRCM_MODE_BrHIST_MASK 	(0x1f << 20)
78#define CP0_BRCM_MODE_BrHIST_SHIFT	20
79
80/* ZSC L2 Cache Register Access Register Definitions */
81#define BRCM_ZSC_ALL_REGS_SELECT		0x7 << 24
82
83#define BRCM_ZSC_CONFIG_REG			0 << 3
84#define BRCM_ZSC_REQ_BUFFER_REG			2 << 3
85#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG0		4 << 3
86#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG1		6 << 3
87#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG2		8 << 3
88
89#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG0		0xa << 3
90#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG1		0xc << 3
91
92#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG0		0xe << 3
93#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG1		0x10 << 3
94
95#define BRCM_ZSC_CONFIG_LMB1En			1 << (15)
96#define BRCM_ZSC_CONFIG_LMB0En			1 << (14)
97
98/* branch predition values */
99
100#define BRCM_BrPRED_ALL_TAKEN		(0x0)
101#define BRCM_BrPRED_ALL_NOT_TAKEN	(0x1)
102#define BRCM_BrPRED_BHT_ENABLE		(0x2)
103#define BRCM_BrPRED_PREDICT_BACKWARD	(0x3)
104
105
106
107.align 2
108/*
109 * Function: 	size_i_cache
110 * Arguments: 	None
111 * Returns:	v0 = i cache size, v1 = I cache line size
112 * Description: compute the I-cache size and I-cache line size
113 * Trashes:	v0, v1, a0, t0
114 *
115 *	pseudo code:
116 *
117 */
118
119LEAF(size_i_cache)
120	.set	noreorder
121
122	mfc0	a0, CP0_CONFIG, 1
123	move	t0, a0
124
125	/*
126	 * Determine sets per way: IS
127	 *
128	 * This field contains the number of sets (i.e., indices) per way of
129	 * the instruction cache:
130	 * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k
131	 * vi) 0x5 - 0x7: Reserved.
132	 */
133
134	srl	a0, a0, IS_SHIFT
135	and	a0, a0, IS_MASK
136
137	/* sets per way = (64<<IS) */
138
139	li	v0, 0x40
140	sllv	v0, v0, a0
141
142	/*
143	 * Determine line size
144	 *
145	 * This field contains the line size of the instruction cache:
146	 * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)
147	 * 0x5: 64 bytes, iv) the rest: Reserved.
148	 */
149
150	move	a0, t0
151
152	srl	a0, a0, IL_SHIFT
153	and	a0, a0, IL_MASK
154
155	beqz	a0, no_i_cache
156	nop
157
158	/* line size = 2 ^ (IL+1) */
159
160	addi	a0, a0, 1
161	li	v1, 1
162	sll	v1, v1, a0
163
164	/* v0 now have sets per way, multiply it by line size now
165	 * that will give the set size
166	 */
167
168	sll	v0, v0, a0
169
170	/*
171	 * Determine set associativity
172	 *
173	 * This field contains the set associativity of the instruction cache.
174	 * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:
175	 * 4-way, v) 0x4 - 0x7: Reserved.
176	 */
177
178	move	a0, t0
179
180	srl	a0, a0, IA_SHIFT
181	and	a0, a0, IA_MASK
182	addi	a0, a0, 0x1
183
184	/* v0 has the set size, multiply it by
185	 * set associativiy, to get the cache size
186	 */
187
188	multu	v0, a0	/*multu is interlocked, so no need to insert nops */
189	mflo	v0
190	b	1f
191	nop
192
193no_i_cache:
194	move	v0, zero
195	move	v1, zero
1961:
197	jr	ra
198	nop
199	.set	reorder
200
201END(size_i_cache)
202
203/*
204 * Function: 	size_d_cache
205 * Arguments: 	None
206 * Returns:	v0 = d cache size, v1 = d cache line size
207 * Description: compute the D-cache size and D-cache line size.
208 * Trashes:	v0, v1, a0, t0
209 *
210 */
211
212LEAF(size_d_cache)
213	.set	noreorder
214
215	mfc0	a0, CP0_CONFIG, 1
216	move	t0, a0
217
218	/*
219	 * Determine sets per way: IS
220	 *
221	 * This field contains the number of sets (i.e., indices) per way of
222	 * the instruction cache:
223	 * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k
224	 * vi) 0x5 - 0x7: Reserved.
225	 */
226
227	srl	a0, a0, DS_SHIFT
228	and	a0, a0, DS_MASK
229
230	/* sets per way = (64<<IS) */
231
232	li	v0, 0x40
233	sllv	v0, v0, a0
234
235	/*
236	 * Determine line size
237	 *
238	 * This field contains the line size of the instruction cache:
239	 * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)
240	 * 0x5: 64 bytes, iv) the rest: Reserved.
241	 */
242	move	a0, t0
243
244	srl	a0, a0, DL_SHIFT
245	and	a0, a0, DL_MASK
246
247	beqz	a0, no_d_cache
248	nop
249
250	/* line size = 2 ^ (IL+1) */
251
252	addi	a0, a0, 1
253	li	v1, 1
254	sll	v1, v1, a0
255
256	/* v0 now have sets per way, multiply it by line size now
257	 * that will give the set size
258	 */
259
260	sll	v0, v0, a0
261
262	/* determine set associativity
263	 *
264	 * This field contains the set associativity of the instruction cache.
265	 * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:
266	 * 4-way, v) 0x4 - 0x7: Reserved.
267	 */
268
269	move	a0, t0
270
271	srl	a0, a0, DA_SHIFT
272	and	a0, a0, DA_MASK
273	addi	a0, a0, 0x1
274
275	/* v0 has the set size, multiply it by
276	 * set associativiy, to get the cache size
277	 */
278
279	multu	v0, a0	/*multu is interlocked, so no need to insert nops */
280	mflo	v0
281
282	b	1f
283	nop
284
285no_d_cache:
286	move	v0, zero
287	move	v1, zero
2881:
289	jr	ra
290	nop
291	.set	reorder
292
293END(size_d_cache)
294
295
296/*
297 * Function: enable_ID
298 * Arguments: 	None
299 * Returns:	None
300 * Description: Enable I and D caches, initialize I and D-caches, also set
301 *		hardware delay for d-cache (TP0).
302 * Trashes:	t0
303 *
304 */
305	.global	enable_ID
306	.ent	enable_ID
307	.set	noreorder
308enable_ID:
309	mfc0	t0, CP0_BRCM_CONFIG0
310	or	t0, t0, (ICE_MASK | DCE_MASK)
311	mtc0	t0, CP0_BRCM_CONFIG0
312	jr	ra
313	nop
314
315	.end	enable_ID
316	.set	reorder
317
318
319/*
320 * Function: l1_init
321 * Arguments: 	None
322 * Returns:	None
323 * Description: Enable I and D caches, and initialize I and D-caches
324 * Trashes:	a0, v0, v1, t0, t1, t2, t8
325 *
326 */
327	.globl	l1_init
328	.ent	l1_init
329	.set	noreorder
330l1_init:
331
332	/* save return address */
333	move	t8, ra
334
335
336	/* initialize I and D cache Data and Tag registers.  */
337	mtc0	zero, CP0_ICACHE_TAG_LO
338	mtc0	zero, CP0_ICACHE_TAG_HI
339	mtc0	zero, CP0_ICACHE_DATA_LO
340	mtc0	zero, CP0_ICACHE_DATA_HI
341	mtc0	zero, CP0_DCACHE_TAG_LO
342	mtc0	zero, CP0_DCACHE_TAG_HI
343
344	/* Enable Caches before Clearing. If the caches are disabled
345	 * then the cache operations to clear the cache will be ignored
346	 */
347
348	jal	enable_ID
349	nop
350
351	jal	size_i_cache	/* v0 = i-cache size, v1 = i-cache line size */
352	nop
353
354	/* run uncached in kseg 1 */
355	la	k0, 1f
356	lui	k1, 0x2000
357	or	k0, k1, k0
358	jr	k0
359	nop
3601:
361
362	/*
363	 * set K0 cache mode
364	 */
365
366	mfc0	t0, CP0_CONFIG
367	and	t0, t0, ~CP0_CONFIG_K0_MASK
368	or	t0, t0, 3	/* Write Back mode */
369	mtc0	t0, CP0_CONFIG
370
371	/*
372	 * Initialize instruction cache.
373	 */
374
375	li	a0, KSEG0
376	cacheop(a0, v0, v1, Index_Store_Tag_I)
377
378	/*
379	 * Now we can run from I-$, kseg 0
380	 */
381	la	k0, 1f
382	lui	k1, 0x2000
383	or	k0, k1, k0
384	xor	k0, k1, k0
385	jr	k0
386	nop
3871:
388	/*
389	 * Initialize data cache.
390	 */
391
392	jal	size_d_cache	/* v0 = d-cache size, v1 = d-cache line size */
393	nop
394
395
396	li	a0, KSEG0
397	cacheop(a0, v0, v1, Index_Store_Tag_D)
398
399	jr	t8
400	nop
401
402	.end 	l1_init
403	.set	reorder
404
405
406/*
407 * Function: 	set_other_config
408 * Arguments:	none
409 * Returns:	None
410 * Description: initialize other remainder configuration to defaults.
411 * Trashes:	t0, t1
412 *
413 *	pseudo code:
414 *
415 */
416LEAF(set_other_config)
417	.set noreorder
418
419	/* enable Bus error for I-fetch */
420	mfc0	t0, CP0_CACHEERR, 0
421	li	t1, 0x4
422	or	t0, t1
423	mtc0	t0, CP0_CACHEERR, 0
424
425	/* enable Bus error for Load */
426	mfc0	t0, CP0_CACHEERR, 1
427	li	t1, 0x4
428	or	t0, t1
429	mtc0	t0, CP0_CACHEERR, 1
430
431	/* enable Bus Error for Store */
432	mfc0	t0, CP0_CACHEERR, 2
433	li	t1, 0x4
434	or	t0, t1
435	mtc0	t0, CP0_CACHEERR, 2
436
437	jr	ra
438	nop
439	.set reorder
440END(set_other_config)
441
442/*
443 * Function: 	set_branch_pred
444 * Arguments:	none
445 * Returns:	None
446 * Description:
447 * Trashes:	t0, t1
448 *
449 *	pseudo code:
450 *
451 */
452
453LEAF(set_branch_pred)
454	.set noreorder
455	mfc0	t0, CP0_BRCM_MODE
456	li	t1, ~(CP0_BRCM_MODE_BrPRED_MASK | CP0_BRCM_MODE_BrHIST_MASK )
457	and	t0, t0, t1
458
459	/* enable Branch prediction */
460	li	t1, BRCM_BrPRED_BHT_ENABLE
461	sll	t1, CP0_BRCM_MODE_BrPRED_SHIFT
462	or	t0, t0, t1
463
464	/* set history count to 8 */
465	li	t1, 8
466	sll	t1, CP0_BRCM_MODE_BrHIST_SHIFT
467	or	t0, t0, t1
468
469	mtc0	t0, CP0_BRCM_MODE
470	jr	ra
471	nop
472	.set	reorder
473END(set_branch_pred)
474
475
476/*
477 * Function: 	set_luc
478 * Arguments:	set link uncached.
479 * Returns:	None
480 * Description:
481 * Trashes:	t0, t1
482 *
483 */
484LEAF(set_luc)
485	.set noreorder
486	mfc0	t0, CP0_BRCM_MODE
487	li	t1, ~(CP0_BRCM_MODE_Luc_MASK)
488	and	t0, t0, t1
489
490	/* set Luc */
491	ori	t0, t0, CP0_BRCM_MODE_Luc_MASK
492
493	mtc0	t0, CP0_BRCM_MODE
494	jr	ra
495	nop
496	.set	reorder
497END(set_luc)
498
499/*
500 * Function: 	set_cwf_tse
501 * Arguments:	set CWF and TSE bits
502 * Returns:	None
503 * Description:
504 * Trashes:	t0, t1
505 *
506 */
507LEAF(set_cwf_tse)
508	.set noreorder
509	mfc0	t0, CP0_BRCM_CONFIG0
510	li	t1, (CP0_BRCM_CONFIG0_CWF_MASK | CP0_BRCM_CONFIG0_TSE_MASK)
511	or	t0, t0, t1
512
513	mtc0	t0, CP0_BRCM_CONFIG0
514	jr	ra
515	nop
516	.set	reorder
517END(set_cwf_tse)
518
519/*
520 * Function: 	set_clock_ratio
521 * Arguments:	set clock ratio specified by a0
522 * Returns:	None
523 * Description:
524 * Trashes:	v0, v1, a0, a1
525 *
526 *	pseudo code:
527 *
528 */
529LEAF(set_clock_ratio)
530	.set noreorder
531
532	mfc0	t0, CP0_BRCM_MODE
533	li	t1, ~(CP0_BRCM_MODE_SET_MASK | CP0_BRCM_MODE_ClkRATIO_MASK)
534	and	t0, t0, t1
535	li	t1, CP0_BRCM_MODE_SET_MASK
536	or	t0, t0, t1
537	or	t0, t0, a0
538	mtc0	t0, CP0_BRCM_MODE
539	jr	ra
540	nop
541	.set	reorder
542END(set_clock_ratio)
543/*
544 * Function: set_zephyr
545 * Arguments:	None
546 * Returns:	None
547 * Description: Set any zephyr bits
548 * Trashes:	t0 & t1
549 *
550 */
551LEAF(set_zephyr)
552	.set	noreorder
553
554	/* enable read/write of CP0 #22 sel. 8 */
555	li	t0, 0x5a455048
556	.word	0x4088b00f	/* mtc0    t0, $22, 15 */
557
558	.word	0x4008b008	/* mfc0    t0, $22, 8 */
559	li	t1, 0x09008000	/* turn off pref, jtb */
560	or	t0, t0, t1
561	.word	0x4088b008	/* mtc0    t0, $22, 8 */
562	sync
563
564	/* disable read/write of CP0 #22 sel 8 */
565	li	t0, 0x0
566	.word	0x4088b00f	/* mtc0    t0, $22, 15 */
567
568
569	jr	ra
570	nop
571	.set reorder
572
573END(set_zephyr)
574
575
576/*
577 * Function:	set_llmb
578 * Arguments:	a0=0 disable llmb, a0=1 enables llmb
579 * Returns:	None
580 * Description:
581 * Trashes:	t0, t1, t2
582 *
583 *      pseudo code:
584 *
585 */
586LEAF(set_llmb)
587	.set noreorder
588
589	li	t2, 0x90000000 | BRCM_ZSC_ALL_REGS_SELECT | BRCM_ZSC_CONFIG_REG
590	sync
591	cache	0x7, 0x0(t2)
592	sync
593	mfc0	t0, CP0_D_SEC_CACHE_DATA_LO
594	li	t1, ~(BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)
595	and	t0, t0, t1
596
597	beqz	a0, svlmb
598	nop
599
600enable_lmb:
601	li	t1, (BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)
602	or	t0, t0, t1
603
604svlmb:
605	mtc0	t0, CP0_D_SEC_CACHE_DATA_LO
606	sync
607	cache	0xb, 0x0(t2)
608	sync
609
610	jr	ra
611	nop
612	.set reorder
613
614END(set_llmb)
615/*
616 * Function: 	core_init
617 * Arguments:	none
618 * Returns:	None
619 * Description: initialize core related configuration
620 * Trashes:	v0,v1,a0,a1,t8
621 *
622 *	pseudo code:
623 *
624 */
625	.globl	core_init
626	.ent	core_init
627	.set	noreorder
628core_init:
629	move	t8, ra
630
631	/* set Zephyr bits. */
632	bal	set_zephyr
633	nop
634
635	/* set low latency memory bus */
636	li	a0, 1
637	bal	set_llmb
638	nop
639
640	/* set branch prediction (TP0 only) */
641	bal	set_branch_pred
642	nop
643
644	/* set link uncached */
645	bal	set_luc
646	nop
647
648	/* set CWF and TSE */
649	bal	set_cwf_tse
650	nop
651
652	/*
653	 *set clock ratio by setting 1 to 'set'
654	 * and 0 to ClkRatio, (TP0 only)
655	 */
656	li	a0, 0
657	bal	set_clock_ratio
658	nop
659
660	/* set other configuration to defaults */
661	bal	set_other_config
662	nop
663
664	move	ra, t8
665	jr	ra
666	nop
667
668	.set reorder
669	.end	core_init
670
671/*
672 * Function: 	clear_jump_target_buffer
673 * Arguments:	None
674 * Returns:	None
675 * Description:
676 * Trashes:	t0, t1, t2
677 *
678 */
679#define RESET_CALL_RETURN_STACK_THIS_THREAD		(0x06<<16)
680#define RESET_JUMP_TARGET_BUFFER_THIS_THREAD		(0x04<<16)
681#define JTB_CS_CNTL_MASK				(0xFF<<16)
682
683	.globl	clear_jump_target_buffer
684	.ent	clear_jump_target_buffer
685	.set	noreorder
686clear_jump_target_buffer:
687
688	mfc0	t0, $22, 2
689	nop
690	nop
691
692	li	t1, ~JTB_CS_CNTL_MASK
693	and	t0, t0, t1
694	li	t2, RESET_CALL_RETURN_STACK_THIS_THREAD
695	or	t0, t0, t2
696	mtc0	t0, $22, 2
697	nop
698	nop
699
700	and	t0, t0, t1
701	li	t2, RESET_JUMP_TARGET_BUFFER_THIS_THREAD
702	or	t0, t0, t2
703	mtc0	t0, $22, 2
704	nop
705	nop
706	jr	ra
707	nop
708
709	.end	clear_jump_target_buffer
710	.set	reorder
711/*
712 * Function: 	bmips_cache_init
713 * Arguments: 	None
714 * Returns:	None
715 * Description: Enable I and D caches, and initialize I and D-caches
716 * Trashes:	v0, v1, t0, t1, t2, t5, t7, t8
717 *
718 */
719	.globl	bmips_5xxx_init
720	.ent	bmips_5xxx_init
721	.set	noreorder
722bmips_5xxx_init:
723
724	/* save return address and A0 */
725	move	t7, ra
726	move	t5, a0
727
728	jal	l1_init
729	nop
730
731	jal	core_init
732	nop
733
734	jal	clear_jump_target_buffer
735	nop
736
737	mtc0	zero, CP0_CAUSE
738
739	move 	a0, t5
740	jr	t7
741	nop
742
743	.end 	bmips_5xxx_init
744	.set	reorder
745
746
747#endif
748