1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  SDRAM init module			File: sbmemc.S
5    *
6    *  BCM5836 Sonics SiliconBackplane MEMC core initialization
7    *
8    *********************************************************************
9    *
10    *  Copyright 2002,2003,2004
11    *  Broadcom Corporation. All rights reserved.
12    *
13    *  This software is furnished under license and may be used and
14    *  copied only in accordance with the following terms and
15    *  conditions.  Subject to these conditions, you may download,
16    *  copy, install, use, modify and distribute modified or unmodified
17    *  copies of this software in source and/or binary form.  No title
18    *  or ownership is transferred hereby.
19    *
20    *  1) Any source code used, modified or distributed must reproduce
21    *     and retain this copyright notice and list of conditions
22    *     as they appear in the source file.
23    *
24    *  2) No right is granted to use any trade name, trademark, or
25    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
26    *     name may not be used to endorse or promote products derived
27    *     from this software without the prior written permission of
28    *     Broadcom Corporation.
29    *
30    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
31    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
32    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
33    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
34    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
35    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
36    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
40    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
41    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
42    *     THE POSSIBILITY OF SUCH DAMAGE.
43    ********************************************************************* */
44
45#include "sbmips32.h"
46#include "bsp_config.h"
47#include "sb_bp.h"
48#include "sbmemc.h"
49
50/*
51 * LEAF - declare leaf routine
52 */
53#undef  LEAF
54#define	LEAF(symbol)			\
55	.globl	symbol;			\
56	.align	2;			\
57	.type	symbol,@function;	\
58	.ent	symbol,0;		\
59symbol:	.frame	sp,0,ra
60
61/*
62 * END - mark end of function
63 */
64#undef  END
65#define	END(function)			\
66	.end	function;		\
67	.size	function,.-function
68
69
70LEAF(board_draminfo)
71	/*
72	 * XXX - in the future, v0 could return the address of the
73	 * PROM SDRAM table.
74	 */
75
76	move	v0,zero		# auto configure
77	j	ra
78END(board_draminfo)
79
80
81/*
82 * Register usage within this file:
83 *
84 *		top	ncdlsearch	test_mem	Xdr_do_init	sb_core_reset
85 *	v0:	retval			retval
86 *	v1:	corerev	-		-		corerev		-
87 *	a0:	coreptr	coreptr		-		coreptr		coreptr
88 *	a1:		x		x		x		sdr/ddr flag
89 *	a2:				x
90 *	a3:				x
91 *	t0:	-	-				config
92 *	t1:	-	-				mode
93 *	t2:	-	wr/strm		off		wr/strm
94 *	t3:	-	rd/strd				rd/strd
95 *	t4:	-	g/clkd				g/clkd
96 *	t5:				x
97 *	t6:	retaddr	-				-		-
98 *	t7:	-	-				retaddr		-
99 *	s0:		pass_count			-		-
100 *	s1:		wrsum/clkdsum			-		-
101 *	s2:		rdsum/pass_countmax		-		-
102 *	s3:		gsum/strmmax			-		-
103 *	s4:		wrlim/stdmmax			-		-
104 *	s5:		rdlim/clkdmax			-		-
105 *	s6:		glim/clkdlim			-		-
106 *	s7:		dll				-		-
107 *	t8:	-	-				x		tmp
108 *	t9:	-	-				x		retaddr
109 *	k0:	trace	trace		trace		-		-
110 *	k1:	trace	trace		trace		-		-
111 *	gp:
112 *	sp:
113 *	s8:	-	step				-		-
114 *	ra:
115 */
116
117LEAF(board_draminit)
118	.set	noreorder
119
120	/* Save return address */
121	move	t6,ra
122
123	/* Scan for a MEMC controller (a0) */
124	li	a0,PHYS_TO_K1(SB_ENUM_BASE)
1251:	lw	v1,R_SBIDHIGH(a0)
126	and	a1,v1,M_SBID_CR
127	srl	a1,a1,S_SBID_CR
128	beq	a1,K_CR_MEMC,read_nvram
129	nop
130	addu	a0,SB_CORE_SIZE
131	bne	a1,(M_SBID_CR >> S_SBID_CR),1b	# XXX No bus error?
132	nop
133
134	/* No MEMC controller */
135	jr	t6
136	li	v0, 0
137
138read_nvram:
139	/* Isolate corerev in v1 */
140	and	v1,v1,M_SBID_RV
141#ifdef BCM5365
142	li	v1,1                            # chip mis-id, per HNBU
143#endif
144
145#if 0   /* XXX Force defaults */
146	/* Find NVRAM (a2) */
147	li	t0,PHYS_TO_K1(SB_ENUM_BASE)	# Is it a chipcommon core?
148	lw	t1,R_SBIDHIGH(t0)
149	and	t1,t1,M_SBID_CR
150	srl	t1,t1,S_SBID_CR
151	bne	t1,K_CR_CHIP_COMMON,notcc
152	nop
153	/* If it is a chipcommon core, use the 32MB window */
154	li	t2,(CC_FLASH_BASE - NVRAM_SPACE)
155	li	t4,CC_FLASH_MAX
156	b	find_nvram
157	nop
158
159notcc:
160	/* else use the 4MB window */
161	li	t2,(FLASH_BASE - NVRAM_SPACE)
162	li	t4,FLASH_MAX
163
164find_nvram:
165	li	t3,FLASH_MIN
166	li	t0, NVRAM_MAGIC
167
1681:
169	add	a2,t2,t3
170	lw	t1, 0(a2)
171	beq	t0,t1,read_parms
172	nop
173
174	sll	t3,t3,1
175	ble	t3,t4,1b
176	nop
177
178	/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
179	li	a2,(FLASH_BASE + 0x1000)
180	lw	t1,0(a2)
181	beq	t0,t1,read_parms
182	nop
183
184	li	a2,(FLASH_BASE + 0x400)
185	lw	t1,0(a2)
186	beq	t0,t1,read_parms
187	nop
188#endif /* XXX */
189
190	b	init			# No NVRAM
191	li	a2, 0
192
193read_parms:
194	/* Get SDRAM parameters (t0, t1, t2) from NVRAM (a2) */
195	lw	t0, 8(a2)		# SDRAM init
196	srl	t0, 16
197	lw	t2, 12(a2)
198	andi	t1, t2, 0xffff		# SDRAM config
199	srl	t2, 16			# SDRAM refresh
200	lw	t3,16(a2)		# SDRAM ncdl
201
202init:
203memc_init:
204	bnez	a2,1f		# Already have the parms in t0, t1, t2, t3
205	nop
206
207	/* No nvram parms: get configured values (sbmemc.h) */
208
209#ifdef MEMSDR
210	li	t0,MEMC_SDR_INIT
211	li	t1,MEMC_SDR_MODE
212	li	t3,MEMC_SDR_NCDL	# If rev0, 2:
213	bne	v1,1,1f
214	nop
215	li	t3,MEMC_SDR1_NCDL	# rev1:
2161:
217#else
218	li	t0,MEMC_DDR_INIT
219	li	t1,MEMC_DDR_MODE
220	li	t3,MEMC_DDR_NCDL	# If rev0, 2:
221	bne	v1,1,1f
222	nop
223	li	t3,MEMC_DDR1_NCDL	# rev1:
2241:
225#endif
226	andi	a3,t0,MEMC_CONFIG_DDR	# Low bit of init selects ddr or sdr
227	beqz	a3,memc_sdr_init
228	nop
229
230
231/*
232 * Routines for initializing DDR SDRAM
233 */
234
235memc_ddr_init:
236	beqz	t3,ddr_find_ncdl	# Do we have ncdl values? (0s)
237	nop
238	li	t4,-1			# or ffs
239	bne	t3,t4,break_ddr_ncdl
240	nop
241
242ddr_find_ncdl:
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	andi	dll,dll,0xfe
273	srl	dll,dll,1
274	beqz	dll,szmem		# If zero, leave the default values
275	nop
276
277	move	wrlim,dll		# dll value is lim for wr, rd and g
278	move	rdlim,dll
279	move	glim,dll
280
281	addi	step,dll,15		# step = (dll + 16 - 1) / 16
282	srl	step,step,4
283
284	sub	wr,zero,dll		# Negate dll as initial value
285	move	rd,wr
286	move	g,wr
287
288	/* Inner loop:	call ddr_do_init to re-initialize and the test mem */
289loop:
290	bal	ddr_do_init
291	nop
292
293	bal	test_mem
294	nop
295
296	beqz	v0,nextg
297	nop
298
299	/* Memory is ok */
300
301	addi	pass_count,1
302	add	wrsum,wrsum,wr
303	add	rdsum,rdsum,rd
304	add	gsum,gsum,g
305
306	bne	wr,dll,1f
307	nop
308	sll	wrlim,dll,1
3091:
310	bne	rd,dll,2f
311	nop
312	sll	rdlim,dll,1
3132:
314	bne	g,dll,nextg
315	nop
316	sll	glim,dll,1
317
318nextg:
319	add	g,g,step
320	ble	g,glim,loop
321	nop
322	sub	g,zero,dll
323	move	glim,dll
324
325	/* nextrd: */
326	add	rd,rd,step
327	ble	rd,rdlim,loop
328	nop
329	sub	rd,zero,dll
330	move	rdlim,dll
331
332	/* nextwr: */
333	add	wr,wr,step
334	ble	wr,wrlim,loop
335	nop
336
337	/* All done, calculate average values and program them */
338
339	beqz	pass_count,1f
340	nop
341
342	div	zero,wrsum,pass_count
343	mflo	wr
344
345	div	zero,rdsum,pass_count
346	mflo	rd
347
348	div	zero,gsum,pass_count
349	mflo	g
350
351	b	ddr_got_ncdl
352	nop
353
354	/* No passing values, panic! (use defaults) */
3551:
356#ifdef MEMSDR
357	li	t3,MEMC_SDR_NCDL		# If rev0, 2:
358	bne	v1,1,2f
359	nop
360	li	t3,MEMC_SDR1_NCDL		# rev1:
361#else
362	li	t3,MEMC_DDR_NCDL		# If rev0, 2:
363	bne	v1,1,2f
364	nop
365	li	t3,MEMC_DDR1_NCDL		# rev1:
366#endif
3672:
368
369break_ddr_ncdl:
370	andi	t4,t3,0xff			# t4:	g
371	srl	t2,t3,16			# t2:	wr
372	andi	t2,t2,0xff
373	srl	t3,t3,8				# t3:	rd
374	andi	t3,t3,0xff
375
376ddr_got_ncdl:
377	bal	ddr_do_init
378	nop
379
380	b	szmem
381	nop
382
383
384	/* Do an init of the memc core for ddr
385	 *	a0:	memc core pointer
386	 *	t0:	memc config value
387	 *	t1:	memc mode value
388	 *	t2:	memc wr ncdl value
389	 *	t3:	memc rd ncdl value
390	 *	t4:	memc g ncdl value
391	 *
392	 * Uses a1, t7, t8, t9 (here and by calling sb_core_reset)
393	 */
394ddr_do_init:
395
396	/* Save return address */
397	move	t7,ra
398
399	bal	sb_core_reset
400	li	a1,0
401
402	li	a1,MEMC_CONFIG_INIT
403	or	a1,a1,t0
404	sw	a1,MEMC_CONFIG(a0)
405
406	li	a1,MEMC_DRAMTIM25_INIT		# Assume CAS latency of 2.5
407	andi	t8,t1,0xf0			# Find out the CAS latency
408	bne	t8,0x20,1f
409	nop
410	li	a1,MEMC_DRAMTIM2_INIT		# CAS latency is 2
4111:
412	sw	a1,MEMC_DRAMTIM(a0)
413
414	andi	t8,t3,0xff
415	sll	a1,t8,8				# Replicate rd ncdl 4 times
416	or	a1,a1,t8
417	sll	t8,a1,16
418	or	t8,t8,a1
419	li	a1,MEMC_RDNCDLCOR_INIT
420	or	a1,a1,t8
421	sw	a1,MEMC_RDNCDLCOR(a0)
422
423	li	a1,MEMC_WRNCDLCOR_INIT		# If rev0, 2:
424	bne	v1,1,1f
425	nop
426	li	a1,MEMC_1_WRNCDLCOR_INIT	# rev1
4271:
428	andi	t8,t2,0xff
429	or	a1,a1,t8
430	sw	a1,MEMC_WRNCDLCOR(a0)
431
432	li	a1,MEMC_DQSGATENCDL_INIT
433	andi	t8,t4,0xff
434	or	a1,a1,t8
435	sw	a1,MEMC_DQSGATENCDL(a0)
436
437	li	a1,MEMC_MISCDLYCTL_INIT		# If rev0, 2:
438	bne	v1,1,2f
439	nop
440	li	a1,MEMC_1_MISCDLYCTL_INIT	# rev1
4412:
442	sw	a1,MEMC_MISCDLYCTL(a0)
443
444	li	a1,MEMC_NCDLCTL_INIT
445	sw	a1,MEMC_NCDLCTL(a0)
446
447	li	a1,MEMC_CONTROL_INIT0
448	sw	a1,MEMC_CONTROL(a0)
449
450	li	a1,MEMC_CONTROL_INIT1
451	sw	a1,MEMC_CONTROL(a0)
452
453	li	a1,MEMC_MODEBUF_INIT0
454	sw	a1,MEMC_MODEBUF(a0)
455
456	li	a1,MEMC_CONTROL_INIT2
457	sw	a1,MEMC_CONTROL(a0)
458
459	li	a1,MEMC_MODEBUF_INIT1
460	or	a1,a1,t1
461	sw	a1,MEMC_MODEBUF(a0)
462
463	li	a1,MEMC_CONTROL_INIT3
464	sw	a1,MEMC_CONTROL(a0)
465
466	li	a1,MEMC_CONTROL_INIT4
467	sw	a1,MEMC_CONTROL(a0)
468
469	li	a1,MEMC_CONTROL_INIT5
470	sw	a1,MEMC_CONTROL(a0)
471	lw	a1,MEMC_CONTROL(a0)
472	lw	a1,MEMC_CONTROL(a0)
473	lw	a1,MEMC_CONTROL(a0)
474
475	li	a1,MEMC_CONTROL_INIT5
476	sw	a1,MEMC_CONTROL(a0)
477	lw	a1,MEMC_CONTROL(a0)
478	lw	a1,MEMC_CONTROL(a0)
479	lw	a1,MEMC_CONTROL(a0)
480
481	li	a1,MEMC_REFRESH_INIT
482	sw	a1,MEMC_REFRESH(a0)
483
484	li	a1,MEMC_MODEBUF_INIT2
485	or	a1,a1,t1
486	sw	a1,MEMC_MODEBUF(a0)
487
488	li	a1,MEMC_CONTROL_INIT6
489	sw	a1,MEMC_CONTROL(a0)
490
491	li	a1,MEMC_CONTROL_INIT7
492	sw	a1,MEMC_CONTROL(a0)
493
494	/* Wait for SDRAM controller to refresh.
495	 * We want 8uS delay. (Assumes >= 160ns per iteration)
496	 */
497	li	t8,50
4981:	lw	a1,R_SBIDLOW(a0)
499	lw	a1,R_SBIDHIGH(a0)
500
501	bnez	t8,1b
502	subu	t8,1
503
504	jr	t7
505	nop
506
507
508/*
509 *  Routines for initializing SDR SDRAM
510 */
511
512memc_sdr_init:
513	beqz	t3,sdr_find_ncdl	# Do we have ncdl values?
514	nop
515
516	li	t4,-1
517	bne	t3,t4,break_sdr_ncdl
518	nop
519
520sdr_find_ncdl:
521
522/* Register usage */
523#define	pass_count	s0
524#define	clkdsum		s1
525#define	pass_countmax	s2
526#define	strmmax		s3
527#define	strdmax		s4
528#define	clkdmax		s5
529#define	clkdlim		s6
530#define	strm		t2
531#define	strd		t3
532#define	clkd		t4
533
534#define	STRMLIM		4
535#define	STRDLIM		16
536#define	CLKDLIM		128
537#define	CLKDLIM_IC	256
538
539	/* Initialize counter & saved values */
540	move	pass_countmax,zero
541	move	strmmax,zero
542	move	strdmax,zero
543	li	clkdlim,CLKDLIM
544
545	and	strm,t0,0x2000		# Test for internal clock (Using strm as a temp)
546	beqz	strm,strmloop
547	nop
548
549	li	clkdlim,CLKDLIM_IC
550
551	move	strm,zero		# strm loop
552strmloop:
553	move	strd,zero
554strdloop:
555	move	pass_count,zero
556	move	clkdsum,zero
557	move	clkd,zero
558
559	/* Inner loop:	call sdr_do_init to re-initialize and the test mem */
560clkdloop:
561	bal	sdr_do_init
562	nop
563
564	bal	test_mem
565	nop
566
567	beqz	v0,failclkd
568	nop
569
570	/* Memory is ok */
571
572	addi	pass_count,1
573	add	clkdsum,clkdsum,clkd
574	b	nextclkd
575	nop
576
577failclkd:
578	bnez	pass_count,clkdout	# End of passing range, leave clkd loop
579	nop
580
581nextclkd:
582	addi	clkd,clkd,1
583	blt	clkd,clkdlim,clkdloop
584	nop
585
586clkdout:
587	/* If no passing values, skip to next strm */
588	beqz	pass_count,nextstrm
589	nop
590
591	/* If this is a new max, Save the values */
592	ble	pass_count,pass_countmax,nextstrd
593	nop
594
595	move	pass_countmax,pass_count
596	div	zero,clkdsum,pass_count
597	mflo	clkdmax
598	move	strdmax,strd
599	move	strmmax,strm
600
601nextstrd:
602	addi	strd,strd,1
603	blt	strd,STRDLIM,strdloop
604	nop
605
606nextstrm:
607	addi	strm,strm,1
608	blt	strm,STRMLIM,strmloop
609	nop
610
611	/* All done, program the new ncdl values */
612
613	beqz	pass_countmax,1f
614	nop
615
616	move	clkd,clkdmax
617	move	strd,strdmax
618	move	strm,strmmax
619	b	sdr_got_ncdl
620	nop
621
622	/* No passing values, panic! (use defaults) */
6231:
624#ifdef MEMSDR
625	li	t3,MEMC_SDR_NCDL	# If rev0, 2:
626	bne	v1,1,2f
627	nop
628	li	t3,MEMC_SDR1_NCDL	# rev1:
629#else
630	li	t3,MEMC_DDR_NCDL		# If rev0, 2:
631	bne	v1,1,2f
632	nop
633	li	t3,MEMC_DDR1_NCDL		# rev1:
634#endif
6352:
636
637break_sdr_ncdl:
638	andi	t4,t3,0xff		# t4:	cd
639	srl	t2,t3,16		# t2:	sm
640	andi	t2,t2,3			#	sm is 2 bits only
641	srl	t3,t3,8			# t3:	sd
642	andi	t3,t3,0xf		#	sd is 4 bits
643
644sdr_got_ncdl:
645	bal	sdr_do_init
646	nop
647
648	b	szmem
649	nop
650
651
652	/* Do an init of the memc core for sdr
653	 *	a0:	memc core pointer
654	 *	t0:	memc config value
655	 *	t1:	memc mode value
656	 *	t2:	memc strobe mode ncdl value
657	 *	t3:	memc strobe delay ncdl value
658	 *	t4:	memc clock delay ncdl value
659	 *
660	 * Uses a1, t7, t8, t9 (here and by calling sb_core_reset)
661	 */
662sdr_do_init:
663
664	/* Save return address */
665	move	t7,ra
666
667	bal	sb_core_reset
668	li	a1,0x40
669
670	/* Initialize SDRAM */
671	li	a1,MEMC_SD_CONFIG_INIT
672	or	a1,a1,t0
673	sw	a1,MEMC_CONFIG(a0)
674
675	li	a1,MEMC_SD_DRAMTIM3_INIT	# Assume CAS latency of 3
676	andi	t8,t1,0xf0			# Find out the CAS latency
677	bne	t8,0x20,1f
678	nop
679	li	a1,MEMC_SD_DRAMTIM2_INIT	# CAS latency is 2
6801:
681	sw	a1,MEMC_DRAMTIM(a0)
682
683	andi	t8,t4,0xff
684	ble	t8,MEMC_CD_THRESHOLD,1f		# if (cd <= 128) rd = cd
685	nop
686
687	li	t8,MEMC_CD_THRESHOLD		# else rd = 128
688
6891:						# t8 is now rd
690	sll	a1,t8,8				#  .. replicate it 4 times
691	or	a1,a1,t8
692	sll	t8,a1,16
693	or	t8,t8,a1
694	li	a1,MEMC_SD_RDNCDLCOR_INIT
695	or	a1,a1,t8
696	sw	a1,MEMC_RDNCDLCOR(a0)
697
698	li	a1,MEMC_SD1_WRNCDLCOR_INIT	# rev1
699	beq	v1,1,1f
700	nop
701	li	a1,MEMC_SD_WRNCDLCOR_INIT	# rev0, 2
7021:
703	li	t8,0
704	ble	t4,MEMC_CD_THRESHOLD,2f		# if (cd <= 128) wr = 0
705	nop
706
707	andi	t8,t4,0xff			# else wr = cd - 128
708	sub	t8,t8,MEMC_CD_THRESHOLD
709	andi	t8,t8,0xff
710
7112:						# t8 is now wr, a0 is extra bits
712	or	a1,a1,t8
713	sw	a1,MEMC_WRNCDLCOR(a0)
714
715	andi	t8,t2,3
716	sll	a1,t8,28
717	andi	t8,t3,0xf
718	sll	t8,t8,24
719	or	t8,t8,a1
720	li	a1,MEMC_SD_MISCDLYCTL_INIT
721	bne	v1,1,3f				# If rev0, 2:
722	nop
723	li	a1,MEMC_SD1_MISCDLYCTL_INIT	# rev1:
7243:
725	or	a1,a1,t8
726	sw	a1,MEMC_MISCDLYCTL(a0)
727
728	li	a1,MEMC_SD_CONTROL_INIT0
729	sw	a1,MEMC_CONTROL(a0)
730
731	li	a1,MEMC_SD_CONTROL_INIT1
732	sw	a1,MEMC_CONTROL(a0)
733
734	li	a1,MEMC_SD_CONTROL_INIT2
735	sw	a1,MEMC_CONTROL(a0)
736	lw	a1,MEMC_CONTROL(a0)
737	lw	a1,MEMC_CONTROL(a0)
738	lw	a1,MEMC_CONTROL(a0)
739
740	li	a1,MEMC_SD_CONTROL_INIT2
741	sw	a1,MEMC_CONTROL(a0)
742	lw	a1,MEMC_CONTROL(a0)
743	lw	a1,MEMC_CONTROL(a0)
744	lw	a1,MEMC_CONTROL(a0)
745
746	li	a1,MEMC_SD_CONTROL_INIT2
747	sw	a1,MEMC_CONTROL(a0)
748	lw	a1,MEMC_CONTROL(a0)
749	lw	a1,MEMC_CONTROL(a0)
750	lw	a1,MEMC_CONTROL(a0)
751
752	li	a1,MEMC_SD_REFRESH_INIT
753	sw	a1,MEMC_REFRESH(a0)
754
755	li	a1,MEMC_SD_MODEBUF_INIT
756	or	a1,a1,t1
757	sw	a1,MEMC_MODEBUF(a0)
758
759	li	a1,MEMC_SD_CONTROL_INIT3
760	sw	a1,MEMC_CONTROL(a0)
761
762	li	a1,MEMC_SD_CONTROL_INIT4
763	sw	a1,MEMC_CONTROL(a0)
764
765	li	t8,50
7661:	lw	a1,R_SBIDLOW(a0)
767	lw	a1,R_SBIDHIGH(a0)
768	bnez	t8,1b
769	subu	t8,1
770
771	jr	t7
772	nop
773
774
775
776/*
777 *  Common exit code and subroutines shared by SDR and DDR initialization.
778 */
779
780	/* Determine memory size and return
781	 *
782	 * Somewhat simplistic, assumes size is a power of 2 and looks
783	 * for aliases of location 0.
784	 */
785szmem:
786	li	t0,PHYS_TO_K1(0)
787	li	t2,0xaa55beef
788	sw	t2,0(t0)
789	li	v0,4		/* Assume minimum of 4MB */
790
7911:
792	sll	t0,v0,20
793	or	t0,PHYS_TO_K1(0)
794	lw	t1,0(t0)
795	beq	t1,t2,done
796	nop
797
798	sll	v0,v0,1
799	bne	v0,128,1b	/* Fully populated at 128MB, no alias */
800	nop
801
802done:
803	jr	t6
804	nop
805
806
807	/*
808	 * Test memory
809	 *
810	 * Uses arg in t2(wr/sd), t3(rd/sm) and t4(g/clkd)
811	 * Returns success (1) or failure (0) in v0
812	 * Uses a1, a2, a3 & t5
813	 */
814test_mem:
815	/* Use t4 to generate a semi-random address in the second KB */
816	li	a1,0xa0000000
817	addi	a2,t4,255
818	sll	a2,a2,2
819	add	a1,a1,a2
820
821	/* First set: 0 & its negation */
822	li	a2,0
823	sw	a2,0(a1)
824	not	a3,a2
825	sw	a3,4(a1)
826	nop
827	lw	t5,0(a1)
828	bne	a2,t5,bad_mem
829	nop
830	lw	t5,4(a1)
831	bne	a3,t5,bad_mem
832	nop
833
834	/* Second set: 0xaaaaaaaa & its negation */
835	li	a2,0xaaaaaaaa
836	sw	a2,0(a1)
837	not	a3,a2
838	sw	a3,4(a1)
839	nop
840	lw	t5,0(a1)
841	bne	a2,t5,bad_mem
842	nop
843	lw	t5,4(a1)
844	bne	a3,t5,bad_mem
845	nop
846
847	/* Third set: 0x12345678 & its negation */
848	li	a2,0x12345678
849	sw	a2,0(a1)
850	not	a3,a2
851	sw	a3,4(a1)
852	nop
853	lw	t5,0(a1)
854	bne	a2,t5,bad_mem
855	nop
856	lw	t5,4(a1)
857	bne	a3,t5,bad_mem
858	nop
859
860	/* Fourth set: the ncdl & its negation */
861	sll	a2,t2,8
862	or	a2,t3
863	sll	a2,a2,8
864	or	a2,t4
865	sw	a2,0(a1)
866	not	a3,a2
867	sw	a3,4(a1)
868	nop
869	lw	t5,0(a1)
870	bne	a2,t5,bad_mem
871	nop
872	lw	t5,4(a1)
873	bne	a3,t5,bad_mem
874	nop
875
876	/* Fifth set: the CPU count register & its negation */
877	mfc0	a2,$9
878	sw	a2,0(a1)
879	not	a3,a2
880	sw	a3,4(a1)
881	nop
882	lw	t5,0(a1)
883	bne	a2,t5,bad_mem
884	nop
885	lw	t5,4(a1)
886	bne	a3,t5,bad_mem
887	nop
888
889	jr	ra
890	li	v0,1
891
892bad_mem:
893	jr	ra
894	li	v0,0
895
896
897	/* Special sb_core_reset that makes sure the first time
898	 * clock is enabled, address line 6 is in the state specified
899	 * by a1.
900	 *
901	 * a0:	Core pointer
902	 * a1:	0x40 if a6 needs to be 1, 0 otherwise
903	 * uses t8, t9
904	 */
905
906	.align 6
907
908sb_core_reset:
909
910	/* Save return address */
911	move	t9,ra
912
913	/* run uncached */
914	bal     kseg1_switch
915	nop
916
917	/* Figure out our address */
918	bal	h0
919	nop
920h0:	add	t8,ra,24		# This is (h1 - h0)
921	andi	t8,t8,0x40
922	bne	t8,a1,alt_core_reset
923	nop
924
925	/* Set reset while enabling the clock */
926	li	t8,(M_SBTS_FC | M_SBTS_CE | M_SBTS_RS)	# 2 instructions
927h1:	sw	t8,R_SBTMSTATELOW(a0)
928	b	cont
929	nop
930
931	/* Now pad to 0x40: We want (h2 - h1) == 0x40 and there
932	 * are 5 instructions in between them.
933	 */
934	.space	(0x40 - 20)
935
936alt_core_reset:
937	/* Set reset while enabling the clock */
938	li	t8,(M_SBTS_FC | M_SBTS_CE | M_SBTS_RS)	# 2 instructions
939h2:	sw	t8,R_SBTMSTATELOW(a0)
940
941cont:
942	/* Read back and delay */
943	lw	t8, R_SBTMSTATELOW(a0)
944	lw	t8, R_SBTMSTATELOW(a0)
945	lw	t8, R_SBTMSTATELOW(a0)
946
947	/* Clear reset */
948	li	t8, (M_SBTS_FC | M_SBTS_CE)
949	sw	t8, R_SBTMSTATELOW(a0)
950
951	/* Read back and delay */
952	lw	t8, R_SBTMSTATELOW(a0)
953	lw	t8, R_SBTMSTATELOW(a0)
954	lw	t8, R_SBTMSTATELOW(a0)
955
956	/* Leave clock enabled */
957	li	t8, M_SBTS_CE
958	sw	t8, R_SBTMSTATELOW(a0)
959
960	/* Read back and delay */
961	lw	t8, R_SBTMSTATELOW(a0)
962	lw	t8, R_SBTMSTATELOW(a0)
963	lw	t8, R_SBTMSTATELOW(a0)
964
965	jr	t9
966	nop
967
968
969kseg1_switch:
970	and     ra, ra, 0x1fffffff
971	or      ra, ra, PHYS_TO_K1(0)
972	jr      ra
973	nop
974
975	.set	reorder
976	END(board_draminit)
977