1/*
2 * BCM47XX Sonics SiliconBackplane SDRAM/MEMC core initialization
3 *
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $Id: sbsdram.S,v 1.45 2008/11/14 17:51:32 Exp $
19 */
20
21#include <hndsoc.h>
22#include <sbmemc.h>
23#include <sbsocram.h>
24#include <sbchipc.h>
25#include <bcmdevs.h>
26#include <bcmnvram.h>
27
28#include <mipsinc.h>
29
30/* #define	DEBUG_SBSDRAM	1 */
31#ifdef	DEBUG_SBSDRAM
32	/* Trace function
33	 * Write to prog space so we can see it in
34	 * the Logic Analizer
35	 */
36#define	LATRACEINIT		\
37	li	k0,0xb8000120;	\
38	li	k1,0x11;	\
39	sw	k1,0(k0);	\
40	li	k1,0x01020108;	\
41	sw	k1,4(k0);	\
42	li	k0,0xbb000000
43
44#define	LATRACE(num, reg)	\
45	sw	reg,((num & 0xff) << 4)(k0)
46
47#else
48#define	LATRACEINIT
49#define	LATRACE(num, reg)
50#endif	/* DEBUG_SBSDRAM */
51/* Debug macro - write a number to a chipc reg - use it with caution,
52 *  it changes k0 and k1 registers.
53 */
54#define TRACEINIT(x)
55#define TRACE(x)
56#define TRACE2(x)
57
58/*
59 * Register usage within this file:
60 *
61 *		top	ncdlsearch	test_mem	Xdr_do_init	sb_reset_core
62 *	v0:	retval			retval
63 *	v1:	corerev	-		-		corerev		-
64 *	a0:	coreptr	coreptr		-		coreptr		coreptr
65 *	a1:		x		x		x		sdr/ddr flag
66 *	a2:	NVRAM			x		x
67 *	a3:				x
68 *	t0:	-	-				config
69 *	t1:	-	-				mode
70 *	t2:	-	wr/strm		off		wr/strm
71 *	t3:	-	rd/strd				rd/strd
72 *	t4:	-	g/clkd				g/clkd
73 *	t5:				x
74 *	t6:	retaddr	-				-		-
75 *	t7:	-	-				retaddr		-
76 *	s0:		pass_count			-		-
77 *	s1:		wrsum/clkdsum			-		-
78 *	s2:		rdsum/pass_countmax		-		-
79 *	s3:		gsum/strmmax			-		-
80 *	s4:		wrlim/stdmmax			-		-
81 *	s5:		rdlim/clkdmax			-		-
82 *	s6:		glim/clkdlim			-		-
83 *	s7:		dll				-		-
84 *	t8:	-	-				x		tmp
85 *	t9:	-	-				x		retaddr
86 *	k0:	trace	trace		trace		-		-
87 *	k1:	trace	trace		trace		-		-
88 *	gp:	PRESERVED
89 *	sp:
90 *	s8:	-	step				-		-
91 *	ra:
92 */
93
94
95	.text
96	.set	mips32
97
98	LEAF(sb_draminit)
99	.set	noreorder
100
101	LATRACEINIT
102	TRACEINIT(0x425300)
103
104	/* Save return address */
105	move	t6,ra
106
107	/* Scan for a memory controller */
108	move	a0,s2
1091:	lw	v1,(SBCONFIGOFF + SBIDHIGH)(a0)
110	and	a1,v1,SBIDH_CC_MASK
111	srl	a1,a1,SBIDH_CC_SHIFT
112	beq	a1,MEMC_CORE_ID,foundctrl
113	nop
114	beq	a1,SOCRAM_CORE_ID,foundctrl
115	nop
116	addu	a0,SI_CORE_SIZE
117	bne	a1,(SBIDH_CC_MASK >> SBIDH_CC_SHIFT),1b
118	nop
119
120	/* No memory controller */
121	li	v0,-1
122	jr	t6
123	nop
124
125foundctrl:
126	TRACE(0x425301)
127	/* If we are already in RAM, just go and size it */
128	bal	1f
129	nop
1301:	li	t0,PHYSADDR_MASK
131	and	t0,t0,ra
132	li	t1,SI_FLASH1
133	blt	t0,t1,memprio_szmem
134	nop
135
136	/* For socram we don't need any nvram parms, just do a core reset */
137socram_init:
138	bne	a1,SOCRAM_CORE_ID,read_nvram
139	nop
140	TRACE(0x425302)
141	bal	sb_core_reset
142	li	a2,0
143	/* and size memory */
144	b	memprio_szmem
145	nop
146
147read_nvram:
148	TRACE(0x425303)
149	/* Find NVRAM (a2) */
150	/* 1: Isolate memc's corerev in v1 */
151	and	t2,v1,SBIDH_RCE_MASK
152	srl	t2,t2,SBIDH_RCE_SHIFT
153	and	v1,v1,SBIDH_RC_MASK
154	or	v1,t2
155
156	/* 1.5: 5365a0 lies about its revision, it is really 1 */
157	bnez	v1,1f
158	nop
159
160	TRACE(0x425304)
161	li	t0,KSEG1ADDR(SI_ENUM_BASE)	# Is there a chipcommon core?
162	lw	t1,CC_CHIPID(t0)		# Get chipid
163	andi	t1,CID_ID_MASK			# Check chipid
164	bne	t1,BCM5365_CHIP_ID,1f
165	nop
166	li	v1,1
167
168	/* 2: find_nvram, use the 32MB window */
1691:	li	t2,KSEG1ADDR(SI_FLASH2 - NVRAM_SPACE)
170	li	t4,SI_FLASH2_SZ
171	li	t3,FLASH_MIN
172	li	t0,NVRAM_MAGIC
173
1742:	add	a2,t2,t3
175	lw	t1,0(a2)
176	beq	t0,t1,read_parms
177	nop
178
179	TRACE(0x425306)
180	sll	t3,t3,1
181	ble	t3,t4,2b
182	nop
183
184	/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
185	li	a2,KSEG1ADDR(SI_FLASH1 + 0x1000)
186	lw	t1,0(a2)
187	beq	t0,t1,read_parms
188	nop
189
190	TRACE(0x425307)
191	li	a2,KSEG1ADDR(SI_FLASH1 + 0x400)
192	lw	t1,0(a2)
193	beq	t0,t1,read_parms
194	nop
195
196	TRACE(0x425308)
197	b	memc_init			# No NVRAM
198	li	a2, 0
199
200read_parms:
201	/* Get SDRAM parameters (t0, t1, t2) from NVRAM (a2) */
202	TRACE(0x425309)
203	lw	t0,8(a2)		# SDRAM init
204	srl	t0,16
205	lw	t2,12(a2)
206	andi	t1,t2,0xffff		# SDRAM config
207	srl	t2,16			# SDRAM refresh
208	lw	t3,16(a2)		# SDRAM ncdl
209
210memc_init:
211	/* Initialize memc core */
212	TRACE(0x425309)
213	bnez	a2,1f			# Already have the parms in
214	nop				#  t0, t1, t2, t3
215
216	/* No nvram parms: assume DDRM16MX16X2 */
217
218	li	t0,MEMC_DDR_INIT
219	li	t1,MEMC_DDR_MODE
220	li	t3,MEMC_DDR1_NCDL	# If rev1 (4712):
221	beq	v1,1,1f
222	nop
223					# rev0, 2:
224	li	t3,MEMC_DDR_NCDL
225
2261:
227	andi	a3,t0,MEMC_CONFIG_DDR	# Is it ddr or sdr?
228	TRACE(0x42530a)
229	beqz	a3,memc_sdr_init
230	nop
231
232	/* Initialize DDR SDRAM */
233memc_ddr_init:
234	beqz	t3,ddr_find_ncdl	# Do we have ncdl values? (0s)
235	nop
236
237	li	t4,-1			# or ffs
238	bne	t3,t4,break_ddr_ncdl
239	nop
240
241ddr_find_ncdl:
242	TRACE(0x42530b)
243
244/* Register usage */
245#define	pass_count	s0
246#define	wrsum		s1
247#define	rdsum		s2
248#define	gsum		s3
249#define	wrlim		s4
250#define	rdlim		s5
251#define	glim		s6
252#define	dll		s7
253#define	step		s8
254#define	wr		t2
255#define	rd		t3
256#define	g		t4
257
258	/* Initialize counter & accumulators */
259	move	pass_count,zero
260	move	wrsum,zero
261	move	rdsum,zero
262	move	gsum,zero
263
264	/* Initialize with default values */
265	li	wr,5
266	li	rd,5
267	bal	ddr_do_init
268	li	g,10
269
270	/* Read dll value */
271	lw	dll,MEMC_NCDLCTL(a0)
272	LATRACE(0xc, dll)
273	andi	dll,dll,0xfe
274	srl	dll,dll,1
275	beqz	dll,memprio_szmem		/* If zero, leave the default values */
276	nop
277
278	move	wrlim,dll		/* dll value is lim for wr, rd and g */
279	move	rdlim,dll
280	move	glim,dll
281	LATRACE(0xd, wrlim)
282	LATRACE(0xe, rdlim)
283	LATRACE(0xf, glim)
284
285	addi	step,dll,15		/* step = (dll + 16 - 1) / 16 */
286	srl	step,step,4
287	LATRACE(0x10, step)
288
289	sub	wr,zero,dll		/* Negate dll as initial value */
290	move	rd,wr
291	move	g,wr
292
293	/* Inner loop:	call ddr_do_init to re-initialize and the test mem */
294loop:
295	LATRACE(0x11, wr)
296	LATRACE(0x12, rd)
297	LATRACE(0x13, g)
298	bal	ddr_do_init
299	nop
300
301	bal	test_mem
302	nop
303
304	LATRACE(0x14, v0)
305	beqz	v0,nextg
306	nop
307
308	/* Memory is ok */
309
310	addi	pass_count,1
311	add	wrsum,wrsum,wr
312	add	rdsum,rdsum,rd
313	add	gsum,gsum,g
314	LATRACE(0x15, pass_count)
315	LATRACE(0x16, wrsum)
316	LATRACE(0x17, rdsum)
317	LATRACE(0x18, gsum)
318
319	bne	wr,dll,1f
320	nop
321	sll	wrlim,dll,1
322	LATRACE(0x19, wrlim)
3231:
324
325	bne	rd,dll,2f
326	nop
327	sll	rdlim,dll,1
328	LATRACE(0x1a, rdlim)
3292:
330
331	bne	g,dll,nextg
332	nop
333	sll	glim,dll,1
334	LATRACE(0x1b, glim)
335
336nextg:
337	add	g,g,step
338	ble	g,glim,loop
339	nop
340	sub	g,zero,dll
341	move	glim,dll
342	LATRACE(0x1c, g)
343
344	/* nextrd: */
345	add	rd,rd,step
346	ble	rd,rdlim,loop
347	nop
348	sub	rd,zero,dll
349	move	rdlim,dll
350	LATRACE(0x1d, rd)
351
352	/* nextwr: */
353	add	wr,wr,step
354	ble	wr,wrlim,loop
355	nop
356
357	/* All done, calculate average values and program them */
358
359	LATRACE(0x1e, pass_count)
360	LATRACE(0x1f, wrsum)
361	LATRACE(0x20, rdsum)
362	LATRACE(0x21, gsum)
363	beqz	pass_count,1f
364	nop
365
366	div	zero,wrsum,pass_count
367	mflo	wr
368
369	div	zero,rdsum,pass_count
370	mflo	rd
371
372	div	zero,gsum,pass_count
373	mflo	g
374
375	b	ddr_got_ncdl
376	nop
377
378	/* No passing values, panic! (use defaults) */
3791:
380	li	t3,MEMC_DDR1_NCDL	# If rev1:
381	beq	v1,1,2f
382	nop
383					# rev0, 2:
384	li	t3,MEMC_DDR_NCDL
3852:
386
387break_ddr_ncdl:
388	TRACE(0x425322)
389	andi	t4,t3,0xff		# t4:	g
390	srl	t2,t3,16		# t2:	wr
391	andi	t2,t2,0xff
392	srl	t3,t3,8			# t3:	rd
393	andi	t3,t3,0xff
394
395ddr_got_ncdl:
396	LATRACE(0x23, wr)
397	LATRACE(0x24, rd)
398	LATRACE(0x25, g)
399	bal	ddr_do_init
400	nop
401
402	b	memprio_szmem
403	nop
404
405memc_sdr_init:
406	beqz	t3,sdr_find_ncdl	# Do we have ncdl values?
407	nop
408
409	li	t4,-1
410	bne	t3,t4,break_sdr_ncdl
411	nop
412
413sdr_find_ncdl:
414	TRACE(0x425326)
415
416/* Register usage */
417#define	pass_count	s0
418#define	clkdsum		s1
419#define	pass_countmax	s2
420#define	strmmax		s3
421#define	strdmax		s4
422#define	clkdmax		s5
423#define	clkdlim		s6
424#define	strm		t2
425#define	strd		t3
426#define	clkd		t4
427
428#define	STRMLIM		4
429#define	STRDLIM		16
430#define	CLKDLIM		128
431#define	CLKDLIM_IC	256
432
433	/* Initialize counter & saved values */
434	move	pass_countmax,zero
435	move	strmmax,zero
436	move	strdmax,zero
437	li	clkdlim,CLKDLIM
438
439	and	strm,t0,0x2000		/* Test for internal clock (Using strm as a temp) */
440	beqz	strm,strmloop
441	nop
442
443	li	clkdlim,CLKDLIM_IC
444
445	move	strm,zero		/* strm loop */
446strmloop:
447	move	strd,zero
448strdloop:
449	move	pass_count,zero
450	move	clkdsum,zero
451	move	clkd,zero
452
453	/* Inner loop:	call sdr_do_init to re-initialize and the test mem */
454clkdloop:
455	LATRACE(0x27, strm)
456	LATRACE(0x28, strd)
457	LATRACE(0x29, clkd)
458	bal	sdr_do_init
459	nop
460
461	bal	test_mem
462	nop
463
464	LATRACE(0x2a, v0)
465	beqz	v0,failclkd
466	nop
467
468	/* Memory is ok */
469
470	addi	pass_count,1
471	add	clkdsum,clkdsum,clkd
472	LATRACE(0x2b, pass_count)
473	LATRACE(0x2c, clkdsum)
474	b	nextclkd
475	nop
476
477failclkd:
478	bnez	pass_count,clkdout	# End of passing range, leave clkd loop
479	nop
480
481nextclkd:
482	addi	clkd,clkd,1
483	blt	clkd,clkdlim,clkdloop
484	nop
485
486clkdout:
487	/* If no passing values, skip to next strm */
488	beqz	pass_count,nextstrm
489	nop
490
491	/* If this is a new max, Save the values */
492	ble	pass_count,pass_countmax,nextstrd
493	nop
494
495	move	pass_countmax,pass_count
496	div	zero,clkdsum,pass_count
497	mflo	clkdmax
498	move	strdmax,strd
499	move	strmmax,strm
500	LATRACE(0x2d, pass_count)
501	LATRACE(0x2e, clkdmax)
502	LATRACE(0x2f, strdmax)
503	LATRACE(0x30, strmmax)
504
505nextstrd:
506	addi	strd,strd,1
507	blt	strd,STRDLIM,strdloop
508	nop
509
510nextstrm:
511	addi	strm,strm,1
512	blt	strm,STRMLIM,strmloop
513	nop
514
515	/* All done, program the new ncdl values */
516
517	LATRACE(0x31, pass_count)
518	LATRACE(0x32, clkdmax)
519	LATRACE(0x33, strdmax)
520	LATRACE(0x34, strmmax)
521
522	beqz	pass_countmax,1f
523	nop
524
525	move	clkd,clkdmax
526	move	strd,strdmax
527	move	strm,strmmax
528	b	sdr_got_ncdl
529	nop
530
531	/* No passing values, panic! (use defaults) */
5321:
533	li	t3,MEMC_SDR1_NCDL	# If rev1:
534	beq	v1,1,2f
535	nop
536					# rev0, 2:
537	li	t3,MEMC_SDR_NCDL
5382:
539
540break_sdr_ncdl:
541	TRACE(0x425335)
542	andi	t4,t3,0xff		# t4:	cd
543	srl	t2,t3,16		# t2:	sm
544	andi	t2,t2,3			#	sm is 2 bits only
545	srl	t3,t3,8			# t3:	sd
546	andi	t3,t3,0xf		#	sd is 4 bits
547
548sdr_got_ncdl:
549	bal	sdr_do_init
550	nop
551
552	/* Change the memory priority inversion counter value */
553	/* If an SOCRAM, determine memory size and return */
554memprio_szmem:
555	TRACE(0x425337)
556
557#ifdef APPLE
558	lw	t0, MEMC_PRIORINV(a0)
559	li 	t1, 0xFFFF0000
560	and     t0, t0, t1
561	ori	t0, t0, 0x1
562	sw      t0, MEMC_PRIORINV(a0)
563#else
564	li	t0,KSEG1ADDR(SI_ENUM_BASE)	# is there a chipcommon core?
565	lw	t1,(SBCONFIGOFF + SBIDHIGH)(t0)
566	and	t1,t1,SBIDH_CC_MASK
567	srl	t1,t1,SBIDH_CC_SHIFT
568	bne	t1,CC_CORE_ID,0f
569	nop
570	lw	t1,CC_CHIPID(t0)		# is this BCM4785 chip?
571	and	t1,t1,CID_ID_MASK
572	bne	t1,BCM4785_CHIP_ID,0f
573	nop
574	lw	t0,MEMC_PRIORINV(a0)		# change PriorInvTim to 2
575	and     t0,t0,0xFFFF0000
576	ori	t0,t0,0x02
577	sw      t0,MEMC_PRIORINV(a0)
578#endif
5790:	TRACE(0x425338)
580	lw	t0,(SBCONFIGOFF + SBIDHIGH)(a0)
581	and	t1,t0,SBIDH_CC_MASK
582	srl	t1,t1,SBIDH_CC_SHIFT
583	beq	t1,SOCRAM_CORE_ID,1f
584	nop
585	jr	t6
586	li	v0,0
587
588	/* The socram core tells us how much memory there is */
5891:	TRACE(0x425339)
590	lw	t1,SR_COREINFO(a0)
591	and	t0,t0,SBIDH_RC_MASK		/* Find corerev */
592	beq	t0,zero,crev0
593
594	/* Its corerev >= 1 */
595	and	t2,t1,SRCI_SRNB_MASK		/* Find number of blocks */
596	srl	t2,t2,SRCI_SRNB_SHIFT
597	and	t1,t1,SRCI_SRBSZ_MASK		/* Find block size */
598	addi	t1,t1,SR_BSZ_BASE
599	li	t0,1
600	sll	t0,t0,t1
601	mul	v0,t0,t2
602	jr	t6
603	nop
604
605crev0:
606	and	t1,t1,SRCI_MS0_MASK
607	add	t1,t1,SR_MS0_BASE
608	li	v0,1
609	sll	v0,v0,t1
610	jr	t6
611	nop
612
613	/*
614	 * Test memory
615	 *
616	 * Uses arg in t2(wr/sd), t3(rd/sm) and t4(g/clkd)
617	 * Returns success (1) or failure (0) in v0
618	 * Uses a1, a2, a3 & t5
619	 */
620test_mem:
621	/* Use t4 to generate a semi-random address in the second KB */
622	li	a1,KSEG1
623	addi	a2,t4,255
624	sll	a2,a2,2
625	add	a1,a1,a2
626
627	/* First set: 0 & its negation */
628	li	a2,0
629	sw	a2,0(a1)
630	not	a3,a2
631	sw	a3,4(a1)
632	nop
633	lw	t5,0(a1)
634	bne	a2,t5,bad_mem
635	nop
636
637	lw	t5,4(a1)
638	bne	a3,t5,bad_mem
639	nop
640
641	/* Second set: 0xaaaaaaaa & its negation */
642	li	a2,0xaaaaaaaa
643	sw	a2,0(a1)
644	not	a3,a2
645	sw	a3,4(a1)
646	nop
647	lw	t5,0(a1)
648	bne	a2,t5,bad_mem
649	nop
650
651	lw	t5,4(a1)
652	bne	a3,t5,bad_mem
653	nop
654
655	/* Third set: 0x12345678 & its negation */
656	li	a2,0x12345678
657	sw	a2,0(a1)
658	not	a3,a2
659	sw	a3,4(a1)
660	nop
661	lw	t5,0(a1)
662	bne	a2,t5,bad_mem
663	nop
664
665	lw	t5,4(a1)
666	bne	a3,t5,bad_mem
667	nop
668
669	/* Fourth set: the ncdl & its negation */
670	sll	a2,t2,8
671	or	a2,t3
672	sll	a2,a2,8
673	or	a2,t4
674	sw	a2,0(a1)
675	not	a3,a2
676	sw	a3,4(a1)
677	nop
678	lw	t5,0(a1)
679	bne	a2,t5,bad_mem
680	nop
681
682	lw	t5,4(a1)
683	bne	a3,t5,bad_mem
684	nop
685
686	/* Fifth set: the CPU count register & its negation */
687	mfc0	a2,$9
688	sw	a2,0(a1)
689	not	a3,a2
690	sw	a3,4(a1)
691	nop
692	lw	t5,0(a1)
693	bne	a2,t5,bad_mem
694	nop
695
696	lw	t5,4(a1)
697	bne	a3,t5,bad_mem
698	nop
699
700	jr	ra
701	li	v0,1
702
703bad_mem:
704	jr	ra
705	li	v0,0
706
707
708	/* Do an init of the memc core for ddr
709	 *	a0:	memc core pointer
710	 *	t0:	memc config value
711	 *	t1:	memc mode value
712	 *	t2:	memc wr ncdl value
713	 *	t3:	memc rd ncdl value
714	 *	t4:	memc g ncdl value
715	 *
716	 * Uses a1, a2, t7, t8, t9 (here and by calling sb_core_reset)
717	 */
718ddr_do_init:
719	TRACE(0x42533a)
720
721	/* Save return address */
722	move	t7,ra
723
724	bal	sb_core_reset
725	li	a1,0
726
727	li	a1,MEMC_CONFIG_INIT
728	or	a1,a1,t0
729	lui	a2, 0x8			# set DQMGate for memc rev 4 or more
730	or	a1, a1, a2
731	sw	a1,MEMC_CONFIG(a0)
732
733	li	a1,MEMC_DRAMTIM25_INIT		# Assume CAS latency of 2.5
734	andi	t8,t1,0xf0			# Find out the CAS latency
735	bne	t8,0x20,1f
736	nop
737	li	a1,MEMC_DRAMTIM2_INIT		# CAS latency is 2
7381:
739	sw	a1,MEMC_DRAMTIM(a0)
740
741#ifndef	BCM_ATE
742	li	t8,KSEG1ADDR(SI_ENUM_BASE)	# Get package options
743	lw	a1,CC_CHIPID(t8)		# Get chipid
744	li	t9,CID_PKG_MASK			# Check package options
745	and	a1,a1,t9
746	srl	a1,a1,CID_PKG_SHIFT
747	addi	t8,SBCONFIGOFF			# Get corerev for chipcommon
748	lw	a2,SBIDHIGH(t8)
749	li	t8,SBIDH_RCE_MASK
750	and	t8,t8,a2
751	srl	t8,SBIDH_RCE_SHIFT
752	li	t9,SBIDH_RC_MASK
753	and	t9,t9,a2
754	or	t8,t8,t9
755	bge	t8,10,1f			# If ccrev is >= 10 use 4bit pkg opt
756	nop
757	ori	a1,8				#  else add a bit to the 3bit field
7581:
759	beq	a1,HDLSIM_PKG_ID,hdlsim		# Special case for hdl sim:
760	nop
761
762	li	t8,KSEG1ADDR(SI_ENUM_BASE)	# Get chipid again
763	lw	a2,CC_CHIPID(t8)
764	li	t9,BCM5350_CHIP_ID		# 5350 ChipID
765	li	t8,CID_ID_MASK
766	and	t8,t8,a2
767	bne	t8,t9,notsim			# if not 5350keep going
768	nop
769
770	bne	a1,(8 | HDLSIM5350_PKG_ID),notsim	# If 5350, is it (3/4-bit) vsim?
771	nop
772#endif	/* !BCM_ATE */
773
774hdlsim:
775	li	a1,MEMC_RDNCDLCOR_SIMINIT	#  Fixed 0xf6 rdncdl and no inits
776	sw	a1,MEMC_RDNCDLCOR(a0)		#  of wrncdl, dqsgate and miscdly.
777
778#ifndef	BCM_ATE
779	b	simskip
780	nop
781
782notsim:	andi	t8,t3,0xff
783	sll	a1,t8,8				# Replicate rd ncdl 4 times
784	or	a1,a1,t8
785	sll	t8,a1,16
786	or	t8,t8,a1
787	li	a1,MEMC_RDNCDLCOR_INIT
788	or	a1,a1,t8
789	sw	a1,MEMC_RDNCDLCOR(a0)
790
791	li	a1,MEMC_1_WRNCDLCOR_INIT # If rev1:
792	beq	v1,1,1f
793	nop
794					# rev0, 2
795	li	a1,MEMC_WRNCDLCOR_INIT
7961:
797	andi	t8,t2,0xff
798	or	a1,a1,t8
799	sw	a1,MEMC_WRNCDLCOR(a0)
800
801	li	a1,MEMC_DQSGATENCDL_INIT
802	andi	t8,t4,0xff
803	or	a1,a1,t8
804	sw	a1,MEMC_DQSGATENCDL(a0)
805
806	li	a1,MEMC_1_MISCDLYCTL_INIT # If rev1:
807	beq	v1,1,2f
808	nop
809					# rev0,2
810	li	a1,MEMC_MISCDLYCTL_INIT
8112:
812	sw	a1,MEMC_MISCDLYCTL(a0)
813#endif	/* !BCM_ATE */
814
815simskip:
816	li	a1,MEMC_NCDLCTL_INIT
817	sw	a1,MEMC_NCDLCTL(a0)
818
819	li	a1,MEMC_CONTROL_INIT0
820	sw	a1,MEMC_CONTROL(a0)
821
822	li	a1,MEMC_CONTROL_INIT1
823	sw	a1,MEMC_CONTROL(a0)
824
825	li	a1,MEMC_MODEBUF_INIT0
826	sw	a1,MEMC_MODEBUF(a0)
827
828	li	a1,MEMC_CONTROL_INIT2
829	sw	a1,MEMC_CONTROL(a0)
830
831	li	a1,MEMC_MODEBUF_INIT1
832	or	a1,a1,t1
833	sw	a1,MEMC_MODEBUF(a0)
834
835	li	a1,MEMC_CONTROL_INIT3
836	sw	a1,MEMC_CONTROL(a0)
837
838	li	a1,MEMC_CONTROL_INIT4
839	sw	a1,MEMC_CONTROL(a0)
840
841	li	a1,MEMC_CONTROL_INIT5
842	sw	a1,MEMC_CONTROL(a0)
843	lw	a1,MEMC_CONTROL(a0)
844	lw	a1,MEMC_CONTROL(a0)
845	lw	a1,MEMC_CONTROL(a0)
846
847	li	a1,MEMC_CONTROL_INIT5
848	sw	a1,MEMC_CONTROL(a0)
849	lw	a1,MEMC_CONTROL(a0)
850	lw	a1,MEMC_CONTROL(a0)
851	lw	a1,MEMC_CONTROL(a0)
852
853	li	a1,MEMC_REFRESH_INIT
854	sw	a1,MEMC_REFRESH(a0)
855
856	li	a1,MEMC_MODEBUF_INIT2
857	or	a1,a1,t1
858	sw	a1,MEMC_MODEBUF(a0)
859
860	li	a1,MEMC_CONTROL_INIT6
861	sw	a1,MEMC_CONTROL(a0)
862
863	li	a1,MEMC_CONTROL_INIT7
864	sw	a1,MEMC_CONTROL(a0)
865
866	/* Wait for SDRAM controller to refresh.
867	 * We want 8uS delay.
868	 */
869	li	t8,50
8701:	lw	a1,(SBCONFIGOFF + SBIDLOW)(a0)
871	lw	a1,(SBCONFIGOFF + SBIDHIGH)(a0)
872
873	bnez	t8,1b
874	subu	t8,1
875
876	jr	t7
877	nop
878
879	/* Do an init of the memc core for sdr
880	 *	a0:	memc core pointer
881	 *	t0:	memc config value
882	 *	t1:	memc mode value
883	 *	t2:	memc strobe mode ncdl value
884	 *	t3:	memc strobe delay ncdl value
885	 *	t4:	memc clock delay ncdl value
886	 *
887	 * Uses a1, t7, t8, t9 (here and by calling sb_core_reset)
888	 */
889sdr_do_init:
890	TRACE(0x42533b)
891
892	/* Save return address */
893	move	t7,ra
894
895	bal	sb_core_reset
896	li	a1,0x40
897
898	/* Initialize for SDR SDRAM */
899	li	a1,MEMC_SD_CONFIG_INIT
900	or	a1,a1,t0
901	sw	a1,MEMC_CONFIG(a0)
902
903	li	a1,MEMC_SD_DRAMTIM3_INIT # Assume CAS latency of 3
904	andi	t8,t1,0xf0		# Find out the CAS latency
905	bne	t8,0x20,1f
906	nop
907	li	a1,MEMC_SD_DRAMTIM2_INIT # CAS latency is 2
9081:
909	sw	a1,MEMC_DRAMTIM(a0)
910
911	andi	t8,t4,0xff
912	ble	t8,MEMC_CD_THRESHOLD,1f	# if (cd <= MEMC_CD_THRESHOLD) rd = cd
913	nop
914
915	li	t8,MEMC_CD_THRESHOLD	# else rd = MEMC_CD_THRESHOLD
916
9171:					# t8 is now rd
918	sll	a1,t8,8			#  .. replicate it 4 times
919	or	a1,a1,t8
920	sll	t8,a1,16
921	or	t8,t8,a1
922	li	a1,MEMC_SD_RDNCDLCOR_INIT
923	or	a1,a1,t8
924	sw	a1,MEMC_RDNCDLCOR(a0)
925
926	li	a1,MEMC_SD1_WRNCDLCOR_INIT # rev1
927	beq	v1,1,1f
928	nop
929
930	li	a1,MEMC_SD_WRNCDLCOR_INIT # rev0, 2
9311:
932	li	t8,0
933	ble	t4,MEMC_CD_THRESHOLD,2f	# if (cd <= MEMC_CD_THRESHOLD) wr = 0
934	nop
935
936	andi	t8,t4,0xff		# else wr = cd - MEMC_CD_THRESHOLD
937	sub	t8,t8,MEMC_CD_THRESHOLD
938	andi	t8,t8,0xff
939
9402:					# t8 is now wr, a0 is extra bits
941	or	a1,a1,t8
942	sw	a1,MEMC_WRNCDLCOR(a0)
943
944	andi	t8,t2,3
945	sll	a1,t8,28
946	andi	t8,t3,0xf
947	sll	t8,t8,24
948	or	t8,t8,a1
949	li	a1,MEMC_SD1_MISCDLYCTL_INIT
950	beq	v1,1,3f			# If rev1:
951	nop
952					# rev0, 2:
953	li	a1,MEMC_SD_MISCDLYCTL_INIT
9543:
955	or	a1,a1,t8
956	sw	a1,MEMC_MISCDLYCTL(a0)
957
958	li	a1,MEMC_SD_CONTROL_INIT0
959	sw	a1,MEMC_CONTROL(a0)
960
961	li	a1,MEMC_SD_CONTROL_INIT1
962	sw	a1,MEMC_CONTROL(a0)
963
964	li	a1,MEMC_SD_CONTROL_INIT2
965	sw	a1,MEMC_CONTROL(a0)
966	lw	a1,MEMC_CONTROL(a0)
967	lw	a1,MEMC_CONTROL(a0)
968	lw	a1,MEMC_CONTROL(a0)
969
970	li	a1,MEMC_SD_CONTROL_INIT2
971	sw	a1,MEMC_CONTROL(a0)
972	lw	a1,MEMC_CONTROL(a0)
973	lw	a1,MEMC_CONTROL(a0)
974	lw	a1,MEMC_CONTROL(a0)
975
976	li	a1,MEMC_SD_CONTROL_INIT2
977	sw	a1,MEMC_CONTROL(a0)
978	lw	a1,MEMC_CONTROL(a0)
979	lw	a1,MEMC_CONTROL(a0)
980	lw	a1,MEMC_CONTROL(a0)
981
982	li	a1,MEMC_SD_REFRESH_INIT
983	sw	a1,MEMC_REFRESH(a0)
984
985	li	a1,MEMC_SD_MODEBUF_INIT
986	or	a1,a1,t1
987	sw	a1,MEMC_MODEBUF(a0)
988
989	li	a1,MEMC_SD_CONTROL_INIT3
990	sw	a1,MEMC_CONTROL(a0)
991
992	li	a1,MEMC_SD_CONTROL_INIT4
993	sw	a1,MEMC_CONTROL(a0)
994
995	li	t8,50
9961:	lw	a1,(SBCONFIGOFF + SBIDLOW)(a0)
997	lw	a1,(SBCONFIGOFF + SBIDHIGH)(a0)
998	bnez	t8,1b
999	subu	t8,1
1000
1001	jr	t7
1002	nop
1003
1004
1005	/* Special sb_core_reset that makes sure the first time
1006	 * clock is enabled, address line 6 is in the state specified
1007	 * by a1.
1008	 *
1009	 * a0:	Core pointer
1010	 * a1:	0x40 if a6 needs to be 1, 0 otherwise
1011	 * uses t8, t9
1012	 */
1013
1014	.align 6
1015
1016sb_core_reset:
1017
1018	/* Save return address */
1019	move	t9,ra
1020
1021	/* run uncached */
1022	bal     kseg1_switch
1023	nop
1024
1025	/* Figure out our address */
1026	bal	h0
1027	nop
1028h0:	add	t8,ra,24		# This is (h1 - h0)
1029	andi	t8,t8,0x40
1030	bne	t8,a1,alt_core_reset
1031	nop
1032
1033	/* Set reset while enabling the clock */
1034	li	t8,(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | SBTML_RESET)
1035h1:	sw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1036	b	cont
1037	nop
1038
1039	/* Now pad to 0x40: We want (h2 - h1) == 0x40 and there
1040	 * are 5 instructions inbetween them.
1041	 */
1042	.space	(0x40 - 20)
1043
1044alt_core_reset:
1045	/* Set reset while enabling the clock */
1046	li	t8,(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | SBTML_RESET)
1047h2:	sw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1048
1049cont:
1050	/* Read back and delay */
1051	lw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1052	lw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1053	lw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1054
1055	/* Clear reset */
1056	li	t8,((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT)
1057	sw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1058
1059	/* Read back and delay */
1060	lw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1061	lw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1062	lw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1063
1064	/* Leave clock enabled */
1065	li	t8,(SICF_CLOCK_EN << SBTML_SICF_SHIFT)
1066	sw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1067
1068	/* Read back and delay */
1069	lw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1070	lw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1071	lw	t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1072
1073	jr	t9
1074	nop
1075
1076
1077kseg1_switch:
1078	and     ra,ra,PHYSADDR_MASK
1079	or      ra,ra,KSEG1
1080	jr      ra
1081	nop
1082
1083	.set	reorder
1084	END(sb_draminit)
1085