1/*
2 * DDR23 Denali contoller & DDRPHY init routines.
3 *
4 * Copyright (C) 2015, 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$
19 */
20#include <typedefs.h>
21#include <bcmdefs.h>
22#include <osl.h>
23#include <bcmutils.h>
24#include <bcmdevs.h>
25#include <hndsoc.h>
26#include <siutils.h>
27#include <bcmnvram.h>
28#include <chipcommonb.h>
29#include <ddr_core.h>
30#include <hndcpu.h>
31
32#include <ddr40_phy_init.h>
33#include <shmoo_public.h>
34
35
36#define DDR_DEFAULT_CLOCK	333
37#define DDR3_MIN_CLOCK		400
38
39#define OTPP_TRIES	10000000	/* # of tries for OTPP */
40#define DEFAULT_OTPCPU_CTRL0 0x00a00600
41
42extern void si_mem_setclock(si_t *sih, uint32 ddrclock);
43
44unsigned int ddr2_init_tab_400[] = {
45	0,	0x00000400,
46	1,	0x00000000,
47	3,	0x00000050,
48	4,	0x000000c8,
49	5,	0x0c050c02,
50	6,	0x04020405,
51	7,	0x05031015,
52	8,	0x03101504,
53	9,	0x05020305,
54	10,	0x03006d60,
55	11,	0x05020303,
56	12,	0x03006d60,
57	13,	0x01000003,
58	14,	0x05061001,
59	15,	0x000b0b06,
60	16,	0x030000c8,
61	17,	0x00a01212,
62	18,	0x060600a0,
63	19,	0x00000000,
64	20,	0x00003001,
65	21,	0x00300c2d,
66	22,	0x00050c2d,
67	23,	0x00000200,
68	24,	0x000a0002,
69	25,	0x0002000a,
70	26,	0x00020008,
71	27,	0x00c80008,
72	28,	0x00c80037,
73	29,	0x00000037,
74	30,	0x03000001,
75	31,	0x00030303,
76	32,	0x00000000,
77	35,	0x00000000,
78	36,	0x01000000,
79	37,	0x10000000,
80	38,	0x00100400,
81	39,	0x00000400,
82	40,	0x00000100,
83	41,	0x00000000,
84	42,	0x00000001,
85	43,	0x00000000,
86	44,	0x000a6300,
87	45,	0x00000004,
88	46,	0x00040a63,
89	47,	0x00000000,
90	48,	0x0a630000,
91	49,	0x00000004,
92	50,	0x00040a63,
93	51,	0x00000000,
94	52,	0x0a630000,
95	53,	0x00000004,
96	54,	0x00040a63,
97	55,	0x00000000,
98	56,	0x0a630000,
99	57,	0x00000004,
100	58,	0x00040a63,
101	59,	0x00000000,
102	60,	0x00000000,
103	61,	0x00010100,
104	62,	0x00000000,
105	63,	0x00000000,
106	64,	0x00000000,
107	65,	0x00000000,
108	66,	0x00000000,
109	67,	0x00000000,
110	68,	0x00000000,
111	69,	0x00000000,
112	70,	0x00000000,
113	71,	0x00000000,
114	72,	0x00000000,
115	73,	0x00000000,
116	74,	0x00000000,
117	75,	0x00000000,
118	76,	0x00000000,
119	77,	0x00000000,
120	78,	0x01000200,
121	79,	0x02000040,
122	80,	0x00400100,
123	81,	0x00000200,
124	82,	0x01030001,
125	83,	0x01ffff0a,
126	84,	0x01010101,
127	85,	0x03010101,
128	86,	0x01000003,
129	87,	0x0000010c,
130	88,	0x00010000,
131	89,	0x00000000,
132	90,	0x00000000,
133	91,	0x00000000,
134	92,	0x00000000,
135	93,	0x00000000,
136	94,	0x00000000,
137	95,	0x00000000,
138	96,	0x00000000,
139	97,	0x00000000,
140	98,	0x00000000,
141	99,	0x00000000,
142	100,	0x00000000,
143	101,	0x00000000,
144	102,	0x00000000,
145	103,	0x00000000,
146	104,	0x00000000,
147	105,	0x00000000,
148	106,	0x00000000,
149	107,	0x00000000,
150	108,	0x02020101,
151	109,	0x08080404,
152	110,	0x03020200,
153	111,	0x01000202,
154	112,	0x00000200,
155	113,	0x00000000,
156	114,	0x00000000,
157	115,	0x00000000,
158	116,	0x19000000,
159	117,	0x00000028,
160	118,	0x00000000,
161	119,	0x00010001,
162	120,	0x00010001,
163	121,	0x00010001,
164	122,	0x00010001,
165	123,	0x00010001,
166	124,	0x00000000,
167	125,	0x00000000,
168	126,	0x00000000,
169	127,	0x00000000,
170	128,	0x001c1c00,
171	129,	0x1c1c0001,
172	130,	0x00000001,
173	131,	0x00000000,
174	132,	0x00000000,
175	133,	0x00011c1c,
176	134,	0x00011c1c,
177	135,	0x00000000,
178	136,	0x00000000,
179	137,	0x001c1c00,
180	138,	0x1c1c0001,
181	139,	0x00000001,
182	140,	0x00000000,
183	141,	0x00000000,
184	142,	0x00011c1c,
185	143,	0x00011c1c,
186	144,	0x00000000,
187	145,	0x00000000,
188	146,	0x001c1c00,
189	147,	0x1c1c0001,
190	148,	0xffff0001,
191	149,	0x00ffff00,
192	150,	0x0000ffff,
193	151,	0x00000000,
194	152,	0x03030303,
195	153,	0x03030303,
196	156,	0x02006400,
197	157,	0x02020202,
198	158,	0x02020202,
199	160,	0x01020202,
200	161,	0x01010064,
201	162,	0x01010101,
202	163,	0x01010101,
203	165,	0x00020101,
204	166,	0x00000064,
205	167,	0x00000000,
206	168,	0x000a0a00,
207	169,	0x0c2d0000,
208	170,	0x02000200,
209	171,	0x02000200,
210	172,	0x00000c2d,
211	173,	0x00003ce1,
212	174,	0x0c2d0505,
213	175,	0x02000200,
214	176,	0x02000200,
215	177,	0x00000c2d,
216	178,	0x00003ce1,
217	179,	0x02020505,
218	180,	0x80000100,
219	181,	0x04070303,
220	182,	0x0000000a,
221	183,	0x00000000,
222	184,	0x00000000,
223	185,	0x0010ffff,
224	186,	0x16070303,
225	187,	0x0000000f,
226	188,	0x00000000,
227	189,	0x00000000,
228	190,	0x00000000,
229	191,	0x00000000,
230	192,	0x00000000,
231	193,	0x00000000,
232	194,	0x00000204,
233	195,	0x00000000,
234	196,	0x00000000,
235	197,	0x00000000,
236	198,	0x00000000,
237	199,	0x00000000,
238	200,	0x00000000,
239	201,	0x00000000,
240	202,	0x00000050,
241	203,	0x00000050,
242	204,	0x00000000,
243	205,	0x00000040,
244	206,	0x01030301,
245	207,	0x00000001,
246	0xffffffff
247};
248
249#ifdef _UNUSED_
250unsigned int ddr3_init_tab[] = {
251	14,	0x05051001,
252	15,	0x000a0a05,
253	36,	0x01000000,
254	37,	0x10000000,
255	38,	0x00100400,
256	39,	0x00000400,
257	40,	0x00000100,
258	42,	0x00000001,
259	61,	0x00010100,
260	78,	0x01000200,
261	79,	0x02000040,
262	80,	0x00400100,
263	81,	0x00000200,
264	83,	0x01ffff0a,
265	84,	0x01010101,
266	85,	0x03010101,
267	86,	0x01000003,
268	87,	0x0000010c,
269	88,	0x00010000,
270	112,	0x00000200,
271	116,	0x19000000,
272	117,	0x00000028,
273	119,	0x00010001,
274	120,	0x00010001,
275	121,	0x00010001,
276	122,	0x00010001,
277	123,	0x00010001,
278	130,	0x00000001,
279	139,	0x00000001,
280	148,	0xffff0001,
281	149,	0x00ffff00,
282	150,	0x0000ffff,
283	152,	0x03030303,
284	153,	0x03030303,
285	156,	0x02006400,
286	157,	0x02020202,
287	158,	0x02020202,
288	160,	0x01020202,
289	161,	0x01010064,
290	162,	0x01010101,
291	163,	0x01010101,
292	165,	0x00020101,
293	166,	0x00000064,
294	168,	0x000a0a00,
295	170,	0x02000200,
296	171,	0x02000200,
297	175,	0x02000200,
298	176,	0x02000200,
299	180,	0x80000100,
300	181,	0x04070303,
301	182,	0x0000000a,
302	185,	0x0010ffff,
303	187,	0x0000000f,
304	194,	0x00000204,
305	205,	0x00000040,
306	0xffffffff
307};
308
309unsigned int ddr3_init_tab_666[] = {
310	0,	0x00000600,
311	3,	0x0001046b,
312	4,	0x00028b0b,
313	5,	0x0c050c00,
314	6,	0x04040405,
315	7,	0x05040e14,
316	8,	0x040e1404,
317	9,	0x0c040405,
318	10,	0x03005b68,
319	11,	0x0c040404,
320	12,	0x03005b68,
321	13,	0x01000004,
322	16,	0x03000200,
323	17,	0x00000f0f,
324	18,	0x05050000,
325	20,	0x00007801,
326	21,	0x00780a20,
327	22,	0x00050a20,
328	23,	0x00000300,
329	24,	0x000a0003,
330	25,	0x0000000a,
331	27,	0x02000000,
332	28,	0x0200005a,
333	29,	0x0000005a,
334	30,	0x05000001,
335	31,	0x00050505,
336	44,	0x00022000,
337	45,	0x00000046,
338	46,	0x00460210,
339	48,	0x02100000,
340	49,	0x00000046,
341	50,	0x00460210,
342	52,	0x02100000,
343	53,	0x00000046,
344	54,	0x00460210,
345	56,	0x02100000,
346	57,	0x00000046,
347	58,	0x00460210,
348	82,	0x01010001,
349	108,	0x02040108,
350	109,	0x08010402,
351	110,	0x02020202,
352	111,	0x01000201,
353	128,	0x00212100,
354	129,	0x21210001,
355	133,	0x00012121,
356	134,	0x00012121,
357	137,	0x00212100,
358	138,	0x21210001,
359	142,	0x00012121,
360	143,	0x00012121,
361	146,	0x00212100,
362	147,	0x21210001,
363	169,	0x0a200000,
364	172,	0x00000a20,
365	173,	0x000032a0,
366	174,	0x0a200505,
367	177,	0x00000a20,
368	178,	0x000032a0,
369	179,	0x02020505,
370	186,	0x16070303,
371	202,	0x00000004,
372	203,	0x00000004,
373	206,	0x01040401,
374	207,	0x00000001,
375	0xffffffff
376};
377
378unsigned int ddr3_init_tab_1333[] = {
379	0,	0x00000600,
380	1,	0x00000000,
381	3,	0x00000086,
382	4,	0x0000014e,
383	5,	0x12071200,
384	6,	0x05040407,
385	7,	0x09051821,
386	8,	0x05182105,
387	9,	0x0c040509,
388	10,	0x0400b6d0,
389	11,	0x0c040504,
390	12,	0x0400b6d0,
391	13,	0x01000004,
392	14,	0x090a1001,
393	15,	0x0013130a,
394	16,	0x03000200,
395	17,	0x00001e1e,
396	18,	0x09090000,
397	19,	0x00000000,
398	20,	0x0000ea01,
399	21,	0x00ea1448,
400	22,	0x00051448,
401	23,	0x00000400,
402	24,	0x00100004,
403	25,	0x00000010,
404	26,	0x00000000,
405	27,	0x02000000,
406	28,	0x020000f0,
407	29,	0x000000f0,
408	30,	0x07000001,
409	31,	0x00070707,
410	32,	0x00000000,
411	35,	0x00000000,
412	36,	0x01000000,
413	37,	0x10000000,
414	38,	0x00100400,
415	39,	0x00000400,
416	40,	0x00000100,
417	41,	0x00000000,
418	42,	0x00000001,
419	43,	0x00000000,
420	44,	0x000a5000,
421	45,	0x00100046,
422	46,	0x00460a50,
423	47,	0x00000010,
424	48,	0x0a500000,
425	49,	0x00100046,
426	50,	0x00460a50,
427	51,	0x00000010,
428	52,	0x0a500000,
429	53,	0x00100046,
430	54,	0x00460a50,
431	55,	0x00000010,
432	56,	0x0a500000,
433	57,	0x00100046,
434	58,	0x00460a50,
435	59,	0x00000010,
436	60,	0x00000000,
437	61,	0x00010100,
438	62,	0x00000000,
439	63,	0x00000000,
440	64,	0x00000000,
441	65,	0x00000000,
442	66,	0x00000000,
443	67,	0x00000000,
444	68,	0x00000000,
445	69,	0x00000000,
446	70,	0x00000000,
447	71,	0x00000000,
448	72,	0x00000000,
449	73,	0x00000000,
450	74,	0x00000000,
451	75,	0x00000000,
452	76,	0x00000000,
453	77,	0x00000000,
454	78,	0x01000200,
455	79,	0x02000040,
456	80,	0x00400100,
457	81,	0x00000200,
458	82,	0x01000001,
459	83,	0x01ffff0a,
460	84,	0x01010101,
461	85,	0x03010101,
462	86,	0x01000003,
463	87,	0x0000010c,
464	88,	0x00010000,
465	89,	0x00000000,
466	90,	0x00000000,
467	91,	0x00000000,
468	92,	0x00000000,
469	93,	0x00000000,
470	94,	0x00000000,
471	95,	0x00000000,
472	96,	0x00000000,
473	97,	0x00000000,
474	98,	0x00000000,
475	99,	0x00000000,
476	100,	0x00000000,
477	101,	0x00000000,
478	102,	0x00000000,
479	103,	0x00000000,
480	104,	0x00000000,
481	105,	0x00000000,
482	106,	0x00000000,
483	107,	0x00000000,
484	108,	0x02040108,
485	109,	0x08010402,
486	110,	0x02020202,
487	111,	0x01000201,
488	112,	0x00000200,
489	113,	0x00000000,
490	114,	0x00000000,
491	115,	0x00000000,
492	116,	0x19000000,
493	117,	0x00000028,
494	118,	0x00000000,
495	119,	0x00010001,
496	120,	0x00010001,
497	121,	0x00010001,
498	122,	0x00010001,
499	123,	0x00010001,
500	124,	0x00000000,
501	125,	0x00000000,
502	126,	0x00000000,
503	127,	0x00000000,
504	128,	0x00232300,
505	129,	0x23230001,
506	130,	0x00000001,
507	131,	0x00000000,
508	132,	0x00000000,
509	133,	0x00012323,
510	134,	0x00012323,
511	135,	0x00000000,
512	136,	0x00000000,
513	137,	0x00232300,
514	138,	0x23230001,
515	139,	0x00000001,
516	140,	0x00000000,
517	141,	0x00000000,
518	142,	0x00012323,
519	143,	0x00012323,
520	144,	0x00000000,
521	145,	0x00000000,
522	146,	0x00232300,
523	147,	0x23230001,
524	148,	0xffff0001,
525	149,	0x00ffff00,
526	150,	0x0000ffff,
527	151,	0x00000000,
528	152,	0x03030303,
529	153,	0x03030303,
530	156,	0x02006400,
531	157,	0x02020202,
532	158,	0x02020202,
533	160,	0x01020202,
534	161,	0x01010064,
535	162,	0x01010101,
536	163,	0x01010101,
537	165,	0x00020101,
538	166,	0x00000064,
539	167,	0x00000000,
540	168,	0x000b0b00,
541	169,	0x14480000,
542	170,	0x02000200,
543	171,	0x02000200,
544	172,	0x00001448,
545	173,	0x00006568,
546	174,	0x14480708,
547	175,	0x02000200,
548	176,	0x02000200,
549	177,	0x00001448,
550	178,	0x00006568,
551	179,	0x02020708,
552	180,	0x80000100,
553	181,	0x04070303,
554	182,	0x0000000a,
555	183,	0x00000000,
556	184,	0x00000000,
557	185,	0x0010ffff,
558	186,	0x1a070303,
559	187,	0x0000000f,
560	188,	0x00000000,
561	189,	0x00000000,
562	190,	0x00000000,
563	191,	0x00000000,
564	192,	0x00000000,
565	193,	0x00000000,
566	194,	0x00000204,
567	195,	0x00000000,
568	196,	0x00000000,
569	197,	0x00000000,
570	198,	0x00000000,
571	199,	0x00000000,
572	200,	0x00000000,
573	201,	0x00000000,
574	202,	0x00000007,
575	203,	0x00000007,
576	204,	0x00000000,
577	205,	0x00000040,
578	206,	0x00060601,
579	207,	0x00000000,
580	0xffffffff
581};
582#endif /* _UNUSED_ */
583
584unsigned int ddr3_init_tab_1600[] = {
585	0,	0x00000600,
586	1,	0x00000000,
587	3,	0x000000a0,
588	4,	0x00061a80,
589	5,	0x16081600,
590	6,	0x06040408,
591	7,	0x0b061c27,
592	8,	0x061c2706,
593	9,	0x0c04060b,
594	10,	0x0400db60,
595	11,	0x0c040604,
596	12,	0x0400db60,
597	13,	0x01000004,
598	14,	0x0b0c1001,
599	15,	0x0017170c,
600	16,	0x03000200,
601	17,	0x00002020,
602	18,	0x0b0b0000,
603	19,	0x00000000,
604	20,	0x00011801,
605	21,	0x01181858,
606	22,	0x00051858,
607	23,	0x00000500,
608	24,	0x00140005,
609	25,	0x00000014,
610	26,	0x00000000,
611	27,	0x02000000,
612	28,	0x02000120,
613	29,	0x00000120,
614	30,	0x08000001,
615	31,	0x00080808,
616	32,	0x00000000,
617	35,	0x00000000,
618	36,	0x01000000,
619	37,	0x10000000,
620	38,	0x00100400,
621	39,	0x00000400,
622	40,	0x00000100,
623	41,	0x00000000,
624	42,	0x00000001,
625	43,	0x00000000,
626	44,	0x000c7000,
627	45,	0x00180046,
628	46,	0x00460c70,
629	47,	0x00000018,
630	48,	0x0c700000,
631	49,	0x00180046,
632	50,	0x00460c70,
633	51,	0x00000018,
634	52,	0x0c700000,
635	53,	0x00180046,
636	54,	0x00460c70,
637	55,	0x00000018,
638	56,	0x0c700000,
639	57,	0x00180046,
640	58,	0x00460c70,
641	59,	0x00000018,
642	60,	0x00000000,
643	61,	0x00010100,
644	62,	0x00000000,
645	63,	0x00000000,
646	64,	0x00000000,
647	65,	0x00000000,
648	66,	0x00000000,
649	67,	0x00000000,
650	68,	0x00000000,
651	69,	0x00000000,
652	70,	0x00000000,
653	71,	0x00000000,
654	72,	0x00000000,
655	73,	0x00000000,
656	74,	0x00000000,
657	75,	0x00000000,
658	76,	0x00000000,
659	77,	0x00000000,
660	78,	0x01000200,
661	79,	0x02000040,
662	80,	0x00400100,
663	81,	0x00000200,
664	82,	0x01000001,
665	83,	0x01ffff0a,
666	84,	0x01010101,
667	85,	0x03010101,
668	86,	0x01000003,
669	87,	0x0000010c,
670	88,	0x00010000,
671	89,	0x00000000,
672	90,	0x00000000,
673	91,	0x00000000,
674	92,	0x00000000,
675	93,	0x00000000,
676	94,	0x00000000,
677	95,	0x00000000,
678	96,	0x00000000,
679	97,	0x00000000,
680	98,	0x00000000,
681	99,	0x00000000,
682	100,	0x00000000,
683	101,	0x00000000,
684	102,	0x00000000,
685	103,	0x00000000,
686	104,	0x00000000,
687	105,	0x00000000,
688	106,	0x00000000,
689	107,	0x00000000,
690	108,	0x02040108,
691	109,	0x08010402,
692	110,	0x02020202,
693	111,	0x01000201,
694	112,	0x00000200,
695	113,	0x00000000,
696	114,	0x00000000,
697	115,	0x00000000,
698	116,	0x19000000,
699	117,	0x00000028,
700	118,	0x00000000,
701	119,	0x00010001,
702	120,	0x00010001,
703	121,	0x00010001,
704	122,	0x00010001,
705	123,	0x00010001,
706	124,	0x00000000,
707	125,	0x00000000,
708	126,	0x00000000,
709	127,	0x00000000,
710	128,	0x00232300,
711	129,	0x23230001,
712	130,	0x00000001,
713	131,	0x00000000,
714	132,	0x00000000,
715	133,	0x00012323,
716	134,	0x00012323,
717	135,	0x00000000,
718	136,	0x00000000,
719	137,	0x00232300,
720	138,	0x23230001,
721	139,	0x00000001,
722	140,	0x00000000,
723	141,	0x00000000,
724	142,	0x00012323,
725	143,	0x00012323,
726	144,	0x00000000,
727	145,	0x00000000,
728	146,	0x00232300,
729	147,	0x23230001,
730	148,	0xffff0001,
731	149,	0x00ffff00,
732	150,	0x0000ffff,
733	151,	0x00000000,
734	152,	0x03030303,
735	153,	0x03030303,
736	156,	0x02006400,
737	157,	0x02020202,
738	158,	0x02020202,
739	160,	0x01020202,
740	161,	0x01010064,
741	162,	0x01010101,
742	163,	0x01010101,
743	165,	0x00020101,
744	166,	0x00000064,
745	167,	0x00000000,
746	168,	0x000b0b00,
747	169,	0x18580000,
748	170,	0x02000200,
749	171,	0x02000200,
750	172,	0x00001858,
751	173,	0x000079b8,
752	174,	0x1858080a,
753	175,	0x02000200,
754	176,	0x02000200,
755	177,	0x00001858,
756	178,	0x000079b8,
757	179,	0x0202080a,
758	180,	0x80000100,
759	181,	0x04070303,
760	182,	0x0000000a,
761	183,	0x00000000,
762	184,	0x00000000,
763	185,	0x0010ffff,
764	186,	0x1c070303,
765	187,	0x0000000f,
766	188,	0x00000000,
767	189,	0x00000000,
768	190,	0x00000000,
769	191,	0x00000000,
770	192,	0x00000000,
771	193,	0x00000000,
772	194,	0x00000204,
773	195,	0x00000000,
774	196,	0x00000000,
775	197,	0x00000000,
776	198,	0x00000000,
777	199,	0x00000000,
778	200,	0x00000000,
779	201,	0x00000000,
780	202,	0x00000008,
781	203,	0x00000008,
782	204,	0x00000000,
783	205,	0x00000040,
784	206,	0x00070701,
785	207,	0x00000000,
786	0xffffffff
787};
788
789
790static void
791ddr_regs_init(si_t *sih, ddrcregs_t *ddr, unsigned int ddr_table[])
792{
793	osl_t *osh;
794	uint32 reg_num, reg_val;
795	int idx = 0;
796
797	osh = si_osh(sih);
798	while ((reg_num = ddr_table[idx++]) != DDR_TABLE_END) {
799		reg_val = ddr_table[idx++];
800		W_REG(osh, &ddr->control[reg_num], reg_val);
801	}
802}
803
804int rewrite_mode_registers(void *sih)
805{
806	osl_t *osh;
807	ddrcregs_t *ddr;
808	int nRet = 0;
809	int j = 100;
810	uint32 val;
811
812	osh = si_osh((si_t *)sih);
813	ddr = (ddrcregs_t *)si_setcore((si_t *)sih, NS_DDR23_CORE_ID, 0);
814	if (!ddr) {
815		nRet = 1;
816		goto out;
817	}
818
819	val = R_REG(osh, &ddr->control[89]);
820	val &= ~(1 << 18);
821	W_REG(osh, &ddr->control[89], val);
822
823	/* Set mode register for MR0, MR1, MR2 and MR3 write for all chip selects */
824	val = (1 << 17) | (1 << 24) | (1 << 25);
825	W_REG(osh, &ddr->control[43], val);
826
827	/* Trigger Mode Register Write(MRW) sequence */
828	val |= (1 << 25);
829	W_REG(osh, &ddr->control[43], val);
830
831	do {
832		if (R_REG(osh, &ddr->control[89]) & (1 << 18)) {
833			break;
834		}
835		--j;
836	} while (j);
837
838	if (j == 0 && (R_REG(osh, &ddr->control[89]) & (1 << 18)) == 0) {
839		printf("Error: DRAM mode registers write failed\n");
840		nRet = 1;
841	};
842out:
843	return nRet;
844}
845
846static int
847_check_cmd_done(void)
848{
849	unsigned int k;
850	uint32 st;
851
852	for (k = 0; k < OTPP_TRIES; k++) {
853		st = R_REG(NULL, (uint32 *)DMU_OTP_CPU_STS);
854		if (st & OTPCPU_STS_CMD_DONE_MASK) {
855		    break;
856		}
857	}
858	if (k >= OTPP_TRIES) {
859		printf("%s: %d _check_cmd_done: %08x\n", __FUNCTION__, __LINE__, k);
860		return -1;
861	}
862	return 0;
863}
864
865
866static int
867_issue_read(unsigned int row, uint32 *val)
868{
869	uint32 ctrl1, ctrl0;
870	uint32 start;
871	uint32 cmd;
872	uint32 fuse;
873	uint32 cof;
874	uint32 prog_en;
875	uint32 mode;
876	int rv;
877
878
879	W_REG(NULL, (uint32 *)DMU_OTP_CPU_ADDR, row);
880
881	start = (1 << OTPCPU_CTRL1_START_SHIFT) & OTPCPU_CTRL1_START_MASK;
882	cmd = (OTPCPU_CMD_READ << OTPCPU_CTRL1_CMD_SHIFT) & OTPCPU_CTRL1_CMD_MASK;
883	fuse = (1 << OTPCPU_CTRL1_2XFUSE_SHIFT) & OTPCPU_CTRL1_2XFUSE_MASK;
884	cof = (2 << OTPCPU_CTRL1_COF_SHIFT) & OTPCPU_CTRL1_COF_MASK;
885	prog_en = (0 << OTPCPU_CTRL1_PROG_EN_SHIFT) & OTPCPU_CTRL1_PROG_EN_MASK;
886	mode = (1 << OTPCPU_CTRL1_ACCESS_MODE_SHIFT) & OTPCPU_CTRL1_ACCESS_MODE_MASK;
887
888	ctrl1 = cmd;
889	ctrl1 |= fuse;
890	ctrl1 |= cof;
891	ctrl1 |= prog_en;
892	ctrl1 |= mode;
893
894	ctrl1 |= start;
895	W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL1, ctrl1);
896	ctrl0 = DEFAULT_OTPCPU_CTRL0;
897	W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL0, ctrl0);
898
899	/* Check if cmd_done bit is asserted */
900	rv = _check_cmd_done();
901	if (rv) {
902		printf("%s: %d _check_cmd_done: %08x\n", __FUNCTION__, __LINE__, rv);
903	    return -1;
904	}
905
906	*val = R_REG(NULL, (uint32 *)DMU_OTP_CPU_READ_DATA);
907
908	return 0;
909}
910
911
912static int
913_issue_prog_dis(void)
914{
915	uint32 ctrl1, ctrl0;
916	uint32 start;
917	uint32 cmd;
918	uint32 fuse;
919	uint32 cof;
920	uint32 prog_en;
921	uint32 mode;
922	int rv;
923
924	W_REG(NULL, (uint32 *)DMU_OTP_CPU_ADDR, 0);
925
926	start = (1 << OTPCPU_CTRL1_START_SHIFT) & OTPCPU_CTRL1_START_MASK;
927	cmd = (OTPCPU_CMD_PROG_DIS << OTPCPU_CTRL1_CMD_SHIFT) & OTPCPU_CTRL1_CMD_MASK;
928	fuse = (1 << OTPCPU_CTRL1_2XFUSE_SHIFT) & OTPCPU_CTRL1_2XFUSE_MASK;
929	cof = (1 << OTPCPU_CTRL1_COF_SHIFT) & OTPCPU_CTRL1_COF_MASK;
930	prog_en = (1 << OTPCPU_CTRL1_PROG_EN_SHIFT) & OTPCPU_CTRL1_PROG_EN_MASK;
931	mode = (2 << OTPCPU_CTRL1_ACCESS_MODE_SHIFT) & OTPCPU_CTRL1_ACCESS_MODE_MASK;
932
933	ctrl1 = cmd;
934	ctrl1 |= fuse;
935	ctrl1 |= cof;
936	ctrl1 |= prog_en;
937	ctrl1 |= mode;
938
939	ctrl1 |= start;
940	W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL1, ctrl1);
941	ctrl0 = DEFAULT_OTPCPU_CTRL0;
942	W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL0, ctrl0);
943
944	/* Check if cmd_done bit is asserted */
945	rv = _check_cmd_done();
946	if (rv) {
947		printf("%s: %d _check_cmd_done: %08x\n", __FUNCTION__, __LINE__, rv);
948		return -1;
949	}
950
951	ctrl1 &= ~start;
952	W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL1, ctrl1);
953	W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL0, ctrl0);
954
955	return 0;
956}
957
958int
959bcm5301x_otp_read_dword(unsigned int wn, uint32 *data)
960{
961	uint32 cpu_cfg;
962	int rv;
963
964	/* Check if CPU mode is enabled */
965	cpu_cfg = R_REG(NULL, (uint32 *)DMU_OTP_CPU_CONFIG);
966	if (!(cpu_cfg & OTPCPU_CFG_CPU_MODE_MASK)) {
967		cpu_cfg |= ((1 << OTPCPU_CFG_CPU_MODE_SHIFT) & OTPCPU_CFG_CPU_MODE_MASK);
968		W_REG(NULL, (uint32 *)DMU_OTP_CPU_CONFIG, cpu_cfg);
969	}
970	cpu_cfg = R_REG(NULL, (uint32 *)DMU_OTP_CPU_CONFIG);
971
972	/* Issue ProgDisable command */
973	rv = _issue_prog_dis();
974	if (rv) {
975		printf("%s: %d _issue_prog_dis failed: %d\n", __FUNCTION__, __LINE__, rv);
976		return -1;
977	}
978
979	/* Issue ReadWord command */
980	rv = _issue_read(wn, data);
981	if (rv) {
982		printf("%s: %d _issue_read failed: %d\n", __FUNCTION__, __LINE__, rv);
983		return -1;
984	}
985
986	return 0;
987}
988
989int
990Program_Digital_Core_Power_Voltage(si_t *sih)
991{
992#define ROW_NUMBER 0x8
993#define MDC_DIV 0x8
994#define DIGITAL_POWER_CORE_VOLTAGE_1V		0x520E0020
995#define DIGITAL_POWER_CORE_VOLTAGE_POINT_975V	0x520E0018
996#define DIGITAL_POWER_CORE_VOLTAGE_POINT_9625V	0x520E0014
997#define DIGITAL_POWER_CORE_VOLTAGE_POINT_95V	0x520E0010
998#define DIGITAL_POWER_CORE_VOLTAGE_POINT_9375V	0x520E000C
999#define DIGITAL_POWER_CORE_VOLTAGE_POINT_925V	0x520E0008
1000#define DIGITAL_POWER_CORE_VOLTAGE_POINT_9125V	0x520E0004
1001#define DIGITAL_POWER_CORE_VOLTAGE_POINT_9V	0x520E0000
1002#define AVS_CODE_RS 17
1003#define AVS_CODE_MASK 7
1004
1005	osl_t *osh;
1006	chipcommonbregs_t *chipcb;
1007	uint32 avs_code = 0;
1008	int retval = 0;
1009	char *vol_str = NULL;
1010
1011	osh = si_osh(sih);
1012	chipcb = (chipcommonbregs_t *)si_setcore(sih, NS_CCB_CORE_ID, 0);
1013	if (chipcb == NULL) {
1014		retval = -1;
1015		printf("%s: %d chipcb null %d\n", __FUNCTION__, __LINE__, retval);
1016		return retval;
1017	}
1018
1019	if (CHIPID(sih->chip) == BCM4707_CHIP_ID || CHIPID(sih->chip) == BCM47094_CHIP_ID) {
1020		if (sih->chippkg != BCM4709_PKG_ID) {
1021			/* access internal regulator phy by setting the MDC/MDIO
1022			 * bus frequency to 125/8
1023			 */
1024			W_REG(osh, &chipcb->pcu_mdio_mgt, MDC_DIV);
1025			udelay(500);
1026			/* this is 0.9 V */
1027			W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9375V);
1028			printf("Digital core power voltage set to 0.9375V\n");
1029			return retval;
1030		}
1031	}
1032
1033	retval = bcm5301x_otp_read_dword(ROW_NUMBER, &avs_code);
1034	if (retval != 0) {
1035		printf("%s: %d failed bcm5301x_otp_read_dword: %d\n",
1036			__FUNCTION__, __LINE__, retval);
1037		return retval;
1038	}
1039
1040
1041	/* bits 17 - 19 is the avs code */
1042	avs_code = (avs_code >> AVS_CODE_RS) & AVS_CODE_MASK;
1043
1044	/* access internal regulator phy by setting the MDC/MDIO bus frequency to 125/8 */
1045	W_REG(osh, &chipcb->pcu_mdio_mgt, MDC_DIV);
1046	udelay(500);
1047
1048	switch (avs_code) {
1049	case 0:
1050		/* this is 1 V */
1051		W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_1V);
1052		vol_str = "1.0";
1053		break;
1054	case 1:
1055		/* this is 0.975 V */
1056		W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_975V);
1057		vol_str = "0.975";
1058		break;
1059	case 2:
1060		/* this is 0.9625 V */
1061		W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9625V);
1062		vol_str = "0.9625";
1063		break;
1064	case 3:
1065		/* this is 0.95 V */
1066		W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_95V);
1067		vol_str = "0.95";
1068		break;
1069	case 4:
1070		/* this is 0.9375 V */
1071		W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9375V);
1072		vol_str = "0.9375";
1073		break;
1074	case 5:
1075		/* this is 0.925 V */
1076		W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_925V);
1077		vol_str = "0.925";
1078		break;
1079	case 6:
1080		/* this is 0.9125 V */
1081		W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9125V);
1082		vol_str = "0.9125";
1083		break;
1084	case 7:
1085		/* this is 0.9 V */
1086		W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9V);
1087		vol_str = "0.9";
1088		break;
1089	default:
1090		printf("%s: %d unrecognized avs_code %d\n", __FUNCTION__, __LINE__, avs_code);
1091		break;
1092	}
1093
1094	if (vol_str)
1095		printf("Digital core power voltage set to %sV\n", vol_str);
1096
1097	return retval;
1098}
1099
1100void
1101c_ddr_init(unsigned long ra)
1102{
1103	si_t *sih;
1104	osl_t *osh;
1105	void *regs;
1106	int ddrtype_ddr3 = 0;
1107	int bootdev;
1108	struct nvram_header *nvh = NULL;
1109	uintptr flbase;
1110	uint32 off, sdram_config, sdram_ncdl;
1111	uint32 config_refresh, sdram_refresh;
1112	ddrcregs_t *ddr;
1113	chipcommonbregs_t *chipcb;
1114	uint32 val, val1;
1115	int i;
1116	uint32 ddrclock = DDR_DEFAULT_CLOCK, clkval;
1117	uint32 params, connect, ovride, status;
1118	uint32 wire_dly[4] = {0};
1119
1120
1121	/* Basic initialization */
1122	sih = (si_t *)osl_init();
1123	osh = si_osh(sih);
1124
1125	Program_Digital_Core_Power_Voltage(sih);
1126
1127	regs = (void *)si_setcore(sih, NS_DDR23_CORE_ID, 0);
1128	if (regs) {
1129		ddrtype_ddr3 = ((si_core_sflags(sih, 0, 0) & DDR_TYPE_MASK) == DDR_STAT_DDR3);
1130	}
1131	if (ddrtype_ddr3) {
1132		chipcb = (chipcommonbregs_t *)si_setcore(sih, NS_CCB_CORE_ID, 0);
1133		if (chipcb) {
1134			/* Configure DDR voltage to 1.5V */
1135			val = R_REG(osh, &chipcb->pcu_1v8_1v5_vregcntl);
1136			val = (val & ~PCU_VOLTAGE_SELECT_MASK) | PCU_VOLTAGE_SELECT_1V5;
1137			W_REG(osh, &chipcb->pcu_1v8_1v5_vregcntl, val);
1138
1139			/* Enable LDO voltage output */
1140			val = PCU_AOPC_PWRDIS_SEL;
1141			W_REG(osh, &chipcb->pcu_aopc_control, val);
1142			val |= PCU_AOPC_PWRDIS_LATCHEN;
1143			W_REG(osh, &chipcb->pcu_aopc_control, val);
1144			val1 = R_REG(osh, &chipcb->pcu_status);
1145			val1 &= PCU_PWR_EN_STRAPS_MASK;
1146			val |= (~(val1 << 1) & PCU_AOPC_PWRDIS_MASK);
1147			val &= ~PCU_AOPC_PWRDIS_DDR;
1148			W_REG(osh, &chipcb->pcu_aopc_control, val);
1149		}
1150	}
1151
1152	/* Set DDR clock */
1153	ddr = (ddrcregs_t *)si_setcore(sih, NS_DDR23_CORE_ID, 0);
1154	if (!ddr)
1155		goto out;
1156	val = R_REG(osh, (uint32 *)DDR_S1_IDM_RESET_CONTROL);
1157	if ((val & AIRC_RESET) == 0)
1158		val = R_REG(osh, &ddr->control[0]);
1159	else
1160		val = 0;
1161	if (val & DDRC00_START) {
1162		clkval = *((uint32 *)(0x1000 + BISZ_OFFSET - 4));
1163		if (clkval) {
1164			val = AIRC_RESET;
1165			W_REG(osh, (uint32 *)DDR_S1_IDM_RESET_CONTROL, val);
1166			W_REG(osh, (uint32 *)DDR_S2_IDM_RESET_CONTROL, val);
1167			ddrclock = clkval;
1168			si_mem_setclock(sih, ddrclock);
1169		}
1170	} else {
1171		/* DDR PHY doesn't support 333MHz for DDR3, so set the clock to 400 by default. */
1172		ddrclock = DDR3_MIN_CLOCK;
1173		si_mem_setclock(sih, ddrclock);
1174	}
1175
1176	/* Find NVRAM for the sdram_config variable */
1177	bootdev = soc_boot_dev((void *)sih);
1178#ifdef NFLASH_SUPPORT
1179	if (bootdev == SOC_BOOTDEV_NANDFLASH) {
1180		flbase = SI_NS_NANDFLASH;
1181		goto embedded_nv;
1182	}
1183	else
1184#endif /* NFLASH_SUPPORT */
1185	{
1186		/* bootdev == SOC_BOOTDEV_SFLASH */
1187		flbase = SI_NS_NORFLASH;
1188		off = FLASH_MIN;
1189		while (off <= SI_NS_FLASH_WINDOW) {
1190			nvh = (struct nvram_header *)(flbase + off - MAX_NVRAM_SPACE);
1191			if (R_REG(osh, &nvh->magic) == NVRAM_MAGIC)
1192				break;
1193			off += DEF_NVRAM_SPACE;
1194			nvh = NULL;
1195		};
1196	}
1197#ifdef NFLASH_SUPPORT
1198embedded_nv:
1199#endif
1200	if (nvh == NULL) {
1201		nvh = (struct nvram_header *)(flbase + 1024);
1202		if (R_REG(osh, &nvh->magic) != NVRAM_MAGIC) {
1203			goto out;
1204		}
1205	}
1206	config_refresh = R_REG(osh, &nvh->config_refresh);
1207	sdram_config = config_refresh & 0xffff;
1208	sdram_refresh = (config_refresh >> 16) & 0xffff;
1209	sdram_ncdl = R_REG(osh, &nvh->config_ncdl);
1210
1211	/* Take DDR23 core out of reset */
1212	W_REG(osh, (uint32 *)DDR_S1_IDM_RESET_CONTROL, 0);
1213	W_REG(osh, (uint32 *)DDR_S2_IDM_RESET_CONTROL, 0);
1214	/* Set the ddr_ck to 400 MHz, 2x memc clock */
1215	val = R_REG(osh, (uint32 *)DDR_S1_IDM_IO_CONTROL_DIRECT);
1216	val &= ~(0xfff << 16);
1217	val |= (0x190 << 16);
1218	W_REG(osh, (uint32 *)DDR_S1_IDM_IO_CONTROL_DIRECT, val);
1219
1220	/* Wait for DDR PHY up */
1221	for (i = 0; i < 0x19000; i++) {
1222		val = R_REG(osh, &ddr->phy_control_rev);
1223		if (val != 0)
1224			break; /* DDR PHY is up */
1225	}
1226	if (i == 0x19000) {
1227		si_watchdog(sih, 1);
1228		while (1);
1229	}
1230
1231	/* Change PLL divider values inside PHY */
1232	W_REG(osh, &ddr->phy_control_plldividers, 0x00000c10);	/* high sku ? */
1233	if (ddrclock != DDR_DEFAULT_CLOCK) {
1234		/* SHAMOO related DDR PHY init change */
1235#ifdef CONFIG_DDR_LONG_PREAMBLE
1236		params = DDR40_PHY_PARAM_USE_VTT |
1237			DDR40_PHY_PARAM_ODT_LATE |
1238			DDR40_PHY_PARAM_ADDR_CTL_ADJUST_0 |
1239			DDR40_PHY_PARAM_ADDR_CTL_ADJUST_1 |
1240			DDR40_PHY_PARAM_MAX_ZQ |
1241			DDR40_PHY_PARAM_LONG_PREAMBLE;
1242#else
1243		params = DDR40_PHY_PARAM_USE_VTT |
1244			DDR40_PHY_PARAM_ODT_LATE |
1245			DDR40_PHY_PARAM_ADDR_CTL_ADJUST_0 |
1246			DDR40_PHY_PARAM_ADDR_CTL_ADJUST_1 |
1247			DDR40_PHY_PARAM_MAX_ZQ;
1248#endif /* CONFIG_DDR_LONG_PREAMBLE */
1249		if (ddrtype_ddr3) {
1250			/* DDR3, 1.5v */
1251			params |= DDR40_PHY_PARAM_VDDO_VOLT_0;
1252		}
1253		else {
1254			/* DDR2, 1.8v */
1255			params |= DDR40_PHY_PARAM_VDDO_VOLT_1;
1256		}
1257		connect = 0x01CF7FFF;
1258		ovride = 0x00077FFF;
1259		status = ddr40_phy_init(ddrclock, params, ddrtype_ddr3,
1260			wire_dly, connect, ovride, (uint32_t)DDR_PHY_CONTROL_REGS_REVISION);
1261		if (status != DDR40_PHY_RETURN_OK) {
1262			printf("Error: ddr40_phy_init failed with error 0x%x\n", status);
1263			return;
1264		}
1265	} else {
1266		/* Set LDO output voltage control to 1.00 * VDDC, and enable PLL */
1267		val = (1 << 4);
1268		W_REG(osh, &ddr->phy_control_pllconfig, val);
1269
1270		/* Wait for PLL locked */
1271		for (i = 0; i < 0x1400; i++) {
1272			val = R_REG(osh, &ddr->phy_control_pllstatus);
1273			if (val & 0x1)
1274				break;
1275		}
1276		if (i == 0x1400) {
1277			printf("DDR PHY PLL lock failed\n");
1278			goto out;
1279		}
1280
1281		W_REG(osh, &ddr->phy_ln0_rddata_dly, 3);	/* high sku? */
1282
1283		/* Write 2 if ddr2, 3 if ddr3 */
1284		/* Set preamble mode according to DDR type,
1285		 * and length of write preamble to 1.5 DQs, 0.75 DQ
1286		 */
1287		if (ddrtype_ddr3)
1288			val = 1;
1289		else
1290			val = 0;
1291#ifdef CONFIG_DDR_LONG_PREAMBLE
1292		val |= 2;
1293#endif
1294		W_REG(osh, &ddr->phy_ln0_wr_premb_mode, val);
1295
1296		/* Initiate a PVT calibration cycle */
1297		W_REG(osh, &ddr->phy_control_zq_pvt_compctl, (1 << 20));
1298
1299		/* Initiate auto calibration and apply the results to VDLs */
1300		W_REG(osh, &ddr->phy_control_vdl_calibrate, 0x08000101);	/* high sku? */
1301
1302		/* Wait for Calibration lock done */
1303		for (i = 0; i < 0x1400; i++) {
1304			val = R_REG(osh, &ddr->phy_control_vdl_calibsts);
1305			if (val & 0x1)
1306				break;
1307		}
1308		if (i == 0x1400) {
1309			printf("DDR PHY auto calibration timed out\n");
1310			goto out;
1311		}
1312
1313		if (!(val & 0x2)) {
1314			si_watchdog(sih, 1);
1315			while (1);
1316		}
1317	}
1318
1319	if (ddrtype_ddr3) {
1320		ddr_regs_init(sih, ddr, ddr3_init_tab_1600);
1321	} else {
1322		ddr_regs_init(sih, ddr, ddr2_init_tab_400);
1323	}
1324	if (ddrclock == DDR_DEFAULT_CLOCK) {
1325		/* High SKU, DDR-1600 */
1326		/* Auto initialization fails at DDRCLK 800 MHz, manually override */
1327		W_REG(osh, &ddr->phy_ln0_vdl_ovride_byte1_r_n, 0x00010120);
1328		W_REG(osh, &ddr->phy_ln0_vdl_ovride_byte0_bit_rd_en, 0x0001000d);
1329		W_REG(osh, &ddr->phy_ln0_vdl_ovride_byte1_bit_rd_en, 0x00010020);
1330	}
1331
1332	/* Set Tref */
1333	if (sdram_refresh == 0)
1334		sdram_refresh = (0x1858 * ddrclock) / 800;
1335
1336	val = R_REG(osh, &ddr->control[21]);
1337	val &= ~0x3fff;
1338	val |= sdram_refresh & 0x3fff;
1339	W_REG(osh, &ddr->control[21], val);
1340
1341	val = R_REG(osh, &ddr->control[22]);
1342	val &= ~0x3fff;
1343	val |= sdram_refresh & 0x3fff;
1344	W_REG(osh, &ddr->control[22], val);
1345
1346	if (sdram_config) {
1347		uint32 cas, wrlat;
1348
1349		/* Check reduce mode */
1350		val = R_REG(osh, &ddr->control[87]);
1351		if (sdram_config & 0x80)
1352			val |= (1 << 8);
1353		W_REG(osh, &ddr->control[87], val);
1354
1355		val = R_REG(osh, &ddr->control[82]);
1356		/* Check 8-bank mode */
1357		if (sdram_config & 0x40)
1358			val &= ~(3 << 8);
1359		else {
1360			/* default 4 banks */
1361			val &= ~(3 << 8);
1362			val |= (1 << 8);
1363		}
1364		/* Defaul row_diff=0; Check column diff */
1365		val &= ~(0x707 << 16);
1366		val |= ((sdram_config & 0x700) << 16);
1367		W_REG(osh, &ddr->control[82], val);
1368
1369		/* Now do CAS latency settings */
1370		cas = sdram_config & 0x1f;
1371		if (cas > 5)
1372			wrlat = cas - (cas-4)/2;
1373		else
1374			wrlat = cas - 1;
1375
1376		val = R_REG(osh, &ddr->control[5]);
1377		val &= ~0x3f1f3f00;
1378		val = val | (cas << 9) | (cas << 25) | (wrlat << 16);
1379		W_REG(osh, &ddr->control[5], val);
1380
1381		val = R_REG(osh, &ddr->control[6]);
1382		val &= ~0x1f;
1383		val |= wrlat;
1384		W_REG(osh, &ddr->control[6], val);
1385
1386		val = R_REG(osh, &ddr->control[174]);
1387		val &= ~0x1f3f;
1388		val |= (wrlat << 8) | (cas-1);
1389		W_REG(osh, &ddr->control[174], val);
1390
1391		val = R_REG(osh, &ddr->control[186]);
1392		val &= ~0xff000000;
1393		val |= ((cas+17) << 24);
1394		W_REG(osh, &ddr->control[186], val);
1395
1396		if (ddrtype_ddr3) {
1397			val = R_REG(osh, &ddr->control[44]);
1398			val &= ~0xf000;
1399			val |= ((cas-4) << 12);
1400			W_REG(osh, &ddr->control[44], val);
1401
1402			val = R_REG(osh, &ddr->control[45]);
1403			val &= ~0x00380000;
1404			if (cas > 9)
1405				val |= ((cas-8) << 19);
1406			else if (cas > 7)
1407				val |= ((cas-7) << 19);
1408			else if (cas >= 6)
1409				val |= ((cas-6) << 19);
1410			W_REG(osh, &ddr->control[45], val);
1411
1412			val = R_REG(osh, &ddr->control[206]);
1413			val &= ~0x00001f00;
1414			val |= ((wrlat-1) << 8);
1415			W_REG(osh, &ddr->control[206], val);
1416		} else {
1417			val = R_REG(osh, &ddr->control[44]);
1418			val &= ~0xf000;
1419			val |= (cas << 12);
1420			W_REG(osh, &ddr->control[44], val);
1421		}
1422	}
1423
1424	/* Start the DDR */
1425	val = R_REG(osh, &ddr->control[0]);
1426	val |= DDRC00_START;
1427	W_REG(osh, &ddr->control[0], val);
1428	while (!(R_REG(osh, &ddr->control[89]) & DDR_INT_INIT_DONE));
1429
1430	W_REG(osh, &ddr->phy_ln0_rddata_dly, 3);	/* high sku? */
1431
1432	/* Run the SHMOO */
1433	if (ddrtype_ddr3 && ddrclock > DDR3_MIN_CLOCK) {
1434		status = do_shmoo((void *)sih, DDR_PHY_CONTROL_REGS_REVISION, 0,
1435			((26 << 16) | (16 << 8) | DO_ALL_SHMOO), 0x1000000);
1436		if (status != SHMOO_NO_ERROR) {
1437			printf("Error: do_shmoo failed with error 0x%x\n", status);
1438			hnd_cpu_reset(sih);
1439		}
1440	}
1441
1442out:
1443	asm("mov pc,%0" : : "r"(ra) : "cc");
1444}
1445