xref: /rk3399_rockchip-uboot/arch/arm/mach-uniphier/dram/umc-pxs2.c (revision 524b42bc2c6ae0a3d1d73a83de59346e4b3becd7)
1ea65c980SMasahiro Yamada /*
20f4ec05bSMasahiro Yamada  * Copyright (C) 2015-2017 Socionext Inc.
30f4ec05bSMasahiro Yamada  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
4ea65c980SMasahiro Yamada  *
5ea65c980SMasahiro Yamada  * based on commit 21b6e480f92ccc38fe0502e3116411d6509d3bf2 of Diag by:
6ea65c980SMasahiro Yamada  * Copyright (C) 2015 Socionext Inc.
7ea65c980SMasahiro Yamada  *
8ea65c980SMasahiro Yamada  * SPDX-License-Identifier:	GPL-2.0+
9ea65c980SMasahiro Yamada  */
10ea65c980SMasahiro Yamada 
11ea65c980SMasahiro Yamada #include <common.h>
120f4ec05bSMasahiro Yamada #include <linux/errno.h>
13ea65c980SMasahiro Yamada #include <linux/io.h>
14ea65c980SMasahiro Yamada #include <linux/sizes.h>
15ea65c980SMasahiro Yamada #include <asm/processor.h>
16ea65c980SMasahiro Yamada 
17ea65c980SMasahiro Yamada #include "../init.h"
18ea65c980SMasahiro Yamada #include "../soc-info.h"
19ea65c980SMasahiro Yamada #include "ddrmphy-regs.h"
20ea65c980SMasahiro Yamada #include "umc-regs.h"
21ea65c980SMasahiro Yamada 
22ea65c980SMasahiro Yamada #define DRAM_CH_NR	3
23ea65c980SMasahiro Yamada 
24ea65c980SMasahiro Yamada enum dram_freq {
25ea65c980SMasahiro Yamada 	DRAM_FREQ_1866M,
26ea65c980SMasahiro Yamada 	DRAM_FREQ_2133M,
27ea65c980SMasahiro Yamada 	DRAM_FREQ_NR,
28ea65c980SMasahiro Yamada };
29ea65c980SMasahiro Yamada 
30ea65c980SMasahiro Yamada enum dram_size {
31ea65c980SMasahiro Yamada 	DRAM_SZ_256M,
32ea65c980SMasahiro Yamada 	DRAM_SZ_512M,
33ea65c980SMasahiro Yamada 	DRAM_SZ_NR,
34ea65c980SMasahiro Yamada };
35ea65c980SMasahiro Yamada 
36fada9eafSMasahiro Yamada /* PHY */
37ea65c980SMasahiro Yamada static u32 ddrphy_pgcr2[DRAM_FREQ_NR] = {0x00FC7E5D, 0x00FC90AB};
38ea65c980SMasahiro Yamada static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0EA09205, 0x10C0A6C6};
39ea65c980SMasahiro Yamada static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x0DAC041B, 0x0FA104B1};
40ea65c980SMasahiro Yamada static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x15171e45, 0x18182357};
41ea65c980SMasahiro Yamada static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x0e9ad8e9, 0x10b34157};
42ea65c980SMasahiro Yamada static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x35a00d88, 0x39e40e88};
43ea65c980SMasahiro Yamada static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x2288cc2c, 0x228a04d0};
44ea65c980SMasahiro Yamada static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x50005e00, 0x50006a00};
45ea65c980SMasahiro Yamada static u32 ddrphy_dtpr3[DRAM_FREQ_NR] = {0x0010cb49, 0x0010ec89};
46ea65c980SMasahiro Yamada static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000115, 0x00000125};
47ea65c980SMasahiro Yamada static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x000002a0, 0x000002a8};
48ea65c980SMasahiro Yamada 
49ea65c980SMasahiro Yamada /* dependent on package and board design */
50ea65c980SMasahiro Yamada static u32 ddrphy_acbdlr0[DRAM_CH_NR] = {0x0000000c, 0x0000000c, 0x00000009};
51ea65c980SMasahiro Yamada 
52ea65c980SMasahiro Yamada /* DDR multiPHY */
ddrphy_get_rank(int dx)53ea65c980SMasahiro Yamada static inline int ddrphy_get_rank(int dx)
54ea65c980SMasahiro Yamada {
55ea65c980SMasahiro Yamada 	return dx / 2;
56ea65c980SMasahiro Yamada }
57ea65c980SMasahiro Yamada 
ddrphy_fifo_reset(void __iomem * phy_base)58ea65c980SMasahiro Yamada static void ddrphy_fifo_reset(void __iomem *phy_base)
59ea65c980SMasahiro Yamada {
60ea65c980SMasahiro Yamada 	u32 tmp;
61ea65c980SMasahiro Yamada 
62fada9eafSMasahiro Yamada 	tmp = readl(phy_base + MPHY_PGCR0);
63fada9eafSMasahiro Yamada 	tmp &= ~MPHY_PGCR0_PHYFRST;
64fada9eafSMasahiro Yamada 	writel(tmp, phy_base + MPHY_PGCR0);
65ea65c980SMasahiro Yamada 
66ea65c980SMasahiro Yamada 	udelay(1);
67ea65c980SMasahiro Yamada 
68fada9eafSMasahiro Yamada 	tmp |= MPHY_PGCR0_PHYFRST;
69fada9eafSMasahiro Yamada 	writel(tmp, phy_base + MPHY_PGCR0);
70ea65c980SMasahiro Yamada 
71ea65c980SMasahiro Yamada 	udelay(1);
72ea65c980SMasahiro Yamada }
73ea65c980SMasahiro Yamada 
ddrphy_vt_ctrl(void __iomem * phy_base,int enable)74ea65c980SMasahiro Yamada static void ddrphy_vt_ctrl(void __iomem *phy_base, int enable)
75ea65c980SMasahiro Yamada {
76ea65c980SMasahiro Yamada 	u32 tmp;
77ea65c980SMasahiro Yamada 
78fada9eafSMasahiro Yamada 	tmp = readl(phy_base + MPHY_PGCR1);
79ea65c980SMasahiro Yamada 
80ea65c980SMasahiro Yamada 	if (enable)
81fada9eafSMasahiro Yamada 		tmp &= ~MPHY_PGCR1_INHVT;
82ea65c980SMasahiro Yamada 	else
83fada9eafSMasahiro Yamada 		tmp |= MPHY_PGCR1_INHVT;
84ea65c980SMasahiro Yamada 
85fada9eafSMasahiro Yamada 	writel(tmp, phy_base + MPHY_PGCR1);
86ea65c980SMasahiro Yamada 
87ea65c980SMasahiro Yamada 	if (!enable) {
88fada9eafSMasahiro Yamada 		while (!(readl(phy_base + MPHY_PGSR1) & MPHY_PGSR1_VTSTOP))
89ea65c980SMasahiro Yamada 			cpu_relax();
90ea65c980SMasahiro Yamada 	}
91ea65c980SMasahiro Yamada }
92ea65c980SMasahiro Yamada 
ddrphy_dqs_delay_fixup(void __iomem * phy_base,int nr_dx,int step)93ea65c980SMasahiro Yamada static void ddrphy_dqs_delay_fixup(void __iomem *phy_base, int nr_dx, int step)
94ea65c980SMasahiro Yamada {
95ea65c980SMasahiro Yamada 	int dx;
96ea65c980SMasahiro Yamada 	u32 lcdlr1, rdqsd;
97fada9eafSMasahiro Yamada 	void __iomem *dx_base = phy_base + MPHY_DX_BASE;
98ea65c980SMasahiro Yamada 
99ea65c980SMasahiro Yamada 	ddrphy_vt_ctrl(phy_base, 0);
100ea65c980SMasahiro Yamada 
101ea65c980SMasahiro Yamada 	for (dx = 0; dx < nr_dx; dx++) {
102fada9eafSMasahiro Yamada 		lcdlr1 = readl(dx_base + MPHY_DX_LCDLR1);
103ea65c980SMasahiro Yamada 		rdqsd = (lcdlr1 >> 8) & 0xff;
104ea65c980SMasahiro Yamada 		rdqsd = clamp(rdqsd + step, 0U, 0xffU);
105ea65c980SMasahiro Yamada 		lcdlr1 = (lcdlr1 & ~(0xff << 8)) | (rdqsd << 8);
106fada9eafSMasahiro Yamada 		writel(lcdlr1, dx_base + MPHY_DX_LCDLR1);
107fada9eafSMasahiro Yamada 		readl(dx_base + MPHY_DX_LCDLR1); /* relax */
108fada9eafSMasahiro Yamada 		dx_base += MPHY_DX_STRIDE;
109ea65c980SMasahiro Yamada 	}
110ea65c980SMasahiro Yamada 
111ea65c980SMasahiro Yamada 	ddrphy_vt_ctrl(phy_base, 1);
112ea65c980SMasahiro Yamada }
113ea65c980SMasahiro Yamada 
ddrphy_get_system_latency(void __iomem * phy_base,int width)114ea65c980SMasahiro Yamada static int ddrphy_get_system_latency(void __iomem *phy_base, int width)
115ea65c980SMasahiro Yamada {
116fada9eafSMasahiro Yamada 	void __iomem *dx_base = phy_base + MPHY_DX_BASE;
117ea65c980SMasahiro Yamada 	const int nr_dx = width / 8;
118ea65c980SMasahiro Yamada 	int dx, rank;
119ea65c980SMasahiro Yamada 	u32 gtr;
120ea65c980SMasahiro Yamada 	int dgsl, dgsl_min = INT_MAX, dgsl_max = 0;
121ea65c980SMasahiro Yamada 
122ea65c980SMasahiro Yamada 	for (dx = 0; dx < nr_dx; dx++) {
123fada9eafSMasahiro Yamada 		gtr = readl(dx_base + MPHY_DX_GTR);
124ea65c980SMasahiro Yamada 		for (rank = 0; rank < 4; rank++) {
125ea65c980SMasahiro Yamada 			dgsl = gtr & 0x7;
126ea65c980SMasahiro Yamada 			/* if dgsl is zero, this rank was not trained. skip. */
127ea65c980SMasahiro Yamada 			if (dgsl) {
128ea65c980SMasahiro Yamada 				dgsl_min = min(dgsl_min, dgsl);
129ea65c980SMasahiro Yamada 				dgsl_max = max(dgsl_max, dgsl);
130ea65c980SMasahiro Yamada 			}
131ea65c980SMasahiro Yamada 			gtr >>= 3;
132ea65c980SMasahiro Yamada 		}
133fada9eafSMasahiro Yamada 		dx_base += MPHY_DX_STRIDE;
134ea65c980SMasahiro Yamada 	}
135ea65c980SMasahiro Yamada 
136ea65c980SMasahiro Yamada 	if (dgsl_min != dgsl_max)
137ea65c980SMasahiro Yamada 		printf("DQS Gateing System Latencies are not all leveled.\n");
138ea65c980SMasahiro Yamada 
139ea65c980SMasahiro Yamada 	return dgsl_max;
140ea65c980SMasahiro Yamada }
141ea65c980SMasahiro Yamada 
ddrphy_init(void __iomem * phy_base,enum dram_freq freq,int width,int ch)142ea65c980SMasahiro Yamada static void ddrphy_init(void __iomem *phy_base, enum dram_freq freq, int width,
143ea65c980SMasahiro Yamada 			int ch)
144ea65c980SMasahiro Yamada {
145ea65c980SMasahiro Yamada 	u32 tmp;
146ea65c980SMasahiro Yamada 	void __iomem *zq_base, *dx_base;
147ea65c980SMasahiro Yamada 	int zq, dx;
148ea65c980SMasahiro Yamada 	int nr_dx;
149ea65c980SMasahiro Yamada 
150ea65c980SMasahiro Yamada 	nr_dx = width / 8;
151ea65c980SMasahiro Yamada 
152fada9eafSMasahiro Yamada 	writel(MPHY_PIR_ZCALBYP,        phy_base + MPHY_PIR);
153ea65c980SMasahiro Yamada 	/*
154ea65c980SMasahiro Yamada 	 * Disable RGLVT bit (Read DQS Gating LCDL Delay VT Compensation)
155ea65c980SMasahiro Yamada 	 * to avoid read error issue.
156ea65c980SMasahiro Yamada 	 */
157fada9eafSMasahiro Yamada 	writel(0x07d81e37, phy_base + MPHY_PGCR0);
158fada9eafSMasahiro Yamada 	writel(0x0200c4e0, phy_base + MPHY_PGCR1);
159ea65c980SMasahiro Yamada 
160ea65c980SMasahiro Yamada 	tmp = ddrphy_pgcr2[freq];
161ea65c980SMasahiro Yamada 	if (width >= 32)
162fada9eafSMasahiro Yamada 		tmp |= MPHY_PGCR2_DUALCHN | MPHY_PGCR2_ACPDDC;
163fada9eafSMasahiro Yamada 	writel(tmp, phy_base + MPHY_PGCR2);
164ea65c980SMasahiro Yamada 
165fada9eafSMasahiro Yamada 	writel(ddrphy_ptr0[freq], phy_base + MPHY_PTR0);
166fada9eafSMasahiro Yamada 	writel(ddrphy_ptr1[freq], phy_base + MPHY_PTR1);
167fada9eafSMasahiro Yamada 	writel(0x00083def, phy_base + MPHY_PTR2);
168fada9eafSMasahiro Yamada 	writel(ddrphy_ptr3[freq], phy_base + MPHY_PTR3);
169fada9eafSMasahiro Yamada 	writel(ddrphy_ptr4[freq], phy_base + MPHY_PTR4);
170ea65c980SMasahiro Yamada 
171fada9eafSMasahiro Yamada 	writel(ddrphy_acbdlr0[ch], phy_base + MPHY_ACBDLR0);
172ea65c980SMasahiro Yamada 
173fada9eafSMasahiro Yamada 	writel(0x55555555, phy_base + MPHY_ACIOCR1);
174fada9eafSMasahiro Yamada 	writel(0x00000000, phy_base + MPHY_ACIOCR2);
175fada9eafSMasahiro Yamada 	writel(0x55555555, phy_base + MPHY_ACIOCR3);
176fada9eafSMasahiro Yamada 	writel(0x00000000, phy_base + MPHY_ACIOCR4);
177fada9eafSMasahiro Yamada 	writel(0x00000055, phy_base + MPHY_ACIOCR5);
178fada9eafSMasahiro Yamada 	writel(0x00181aa4, phy_base + MPHY_DXCCR);
179ea65c980SMasahiro Yamada 
180fada9eafSMasahiro Yamada 	writel(0x0024641e, phy_base + MPHY_DSGCR);
181fada9eafSMasahiro Yamada 	writel(0x0000040b, phy_base + MPHY_DCR);
182fada9eafSMasahiro Yamada 	writel(ddrphy_dtpr0[freq], phy_base + MPHY_DTPR0);
183fada9eafSMasahiro Yamada 	writel(ddrphy_dtpr1[freq], phy_base + MPHY_DTPR1);
184fada9eafSMasahiro Yamada 	writel(ddrphy_dtpr2[freq], phy_base + MPHY_DTPR2);
185fada9eafSMasahiro Yamada 	writel(ddrphy_dtpr3[freq], phy_base + MPHY_DTPR3);
186fada9eafSMasahiro Yamada 	writel(ddrphy_mr0[freq], phy_base + MPHY_MR0);
187fada9eafSMasahiro Yamada 	writel(0x00000006, phy_base + MPHY_MR1);
188fada9eafSMasahiro Yamada 	writel(ddrphy_mr2[freq], phy_base + MPHY_MR2);
189fada9eafSMasahiro Yamada 	writel(0x00000000, phy_base + MPHY_MR3);
190ea65c980SMasahiro Yamada 
191ea65c980SMasahiro Yamada 	tmp = 0;
192ea65c980SMasahiro Yamada 	for (dx = 0; dx < nr_dx; dx++)
193fada9eafSMasahiro Yamada 		tmp |= BIT(MPHY_DTCR_RANKEN_SHIFT + ddrphy_get_rank(dx));
194fada9eafSMasahiro Yamada 	writel(0x90003087 | tmp, phy_base + MPHY_DTCR);
195ea65c980SMasahiro Yamada 
196fada9eafSMasahiro Yamada 	writel(0x00000000, phy_base + MPHY_DTAR0);
197fada9eafSMasahiro Yamada 	writel(0x00000008, phy_base + MPHY_DTAR1);
198fada9eafSMasahiro Yamada 	writel(0x00000010, phy_base + MPHY_DTAR2);
199fada9eafSMasahiro Yamada 	writel(0x00000018, phy_base + MPHY_DTAR3);
200fada9eafSMasahiro Yamada 	writel(0xdd22ee11, phy_base + MPHY_DTDR0);
201fada9eafSMasahiro Yamada 	writel(0x7788bb44, phy_base + MPHY_DTDR1);
202ea65c980SMasahiro Yamada 
203ea65c980SMasahiro Yamada 	/* impedance control settings */
204fada9eafSMasahiro Yamada 	writel(0x04048900, phy_base + MPHY_ZQCR);
205ea65c980SMasahiro Yamada 
206fada9eafSMasahiro Yamada 	zq_base = phy_base + MPHY_ZQ_BASE;
207ea65c980SMasahiro Yamada 	for (zq = 0; zq < 4; zq++) {
208ea65c980SMasahiro Yamada 		/*
209ea65c980SMasahiro Yamada 		 * board-dependent
210ea65c980SMasahiro Yamada 		 * PXS2: CH0ZQ0=0x5B, CH1ZQ0=0x5B, CH2ZQ0=0x59, others=0x5D
211ea65c980SMasahiro Yamada 		 */
212fada9eafSMasahiro Yamada 		writel(0x0007BB5D, zq_base + MPHY_ZQ_PR);
213fada9eafSMasahiro Yamada 		zq_base += MPHY_ZQ_STRIDE;
214ea65c980SMasahiro Yamada 	}
215ea65c980SMasahiro Yamada 
216ea65c980SMasahiro Yamada 	/* DATX8 settings */
217fada9eafSMasahiro Yamada 	dx_base = phy_base + MPHY_DX_BASE;
218ea65c980SMasahiro Yamada 	for (dx = 0; dx < 4; dx++) {
219fada9eafSMasahiro Yamada 		tmp = readl(dx_base + MPHY_DX_GCR0);
220fada9eafSMasahiro Yamada 		tmp &= ~MPHY_DX_GCR0_WLRKEN_MASK;
221fada9eafSMasahiro Yamada 		tmp |= BIT(MPHY_DX_GCR0_WLRKEN_SHIFT + ddrphy_get_rank(dx)) &
222fada9eafSMasahiro Yamada 						MPHY_DX_GCR0_WLRKEN_MASK;
223fada9eafSMasahiro Yamada 		writel(tmp, dx_base + MPHY_DX_GCR0);
224ea65c980SMasahiro Yamada 
225fada9eafSMasahiro Yamada 		writel(0x00000000, dx_base + MPHY_DX_GCR1);
226fada9eafSMasahiro Yamada 		writel(0x00000000, dx_base + MPHY_DX_GCR2);
227fada9eafSMasahiro Yamada 		writel(0x00000000, dx_base + MPHY_DX_GCR3);
228fada9eafSMasahiro Yamada 		dx_base += MPHY_DX_STRIDE;
229ea65c980SMasahiro Yamada 	}
230ea65c980SMasahiro Yamada 
231fada9eafSMasahiro Yamada 	while (!(readl(phy_base + MPHY_PGSR0) & MPHY_PGSR0_IDONE))
232ea65c980SMasahiro Yamada 		cpu_relax();
233ea65c980SMasahiro Yamada 
234ea65c980SMasahiro Yamada 	ddrphy_dqs_delay_fixup(phy_base, nr_dx, -4);
235ea65c980SMasahiro Yamada }
236ea65c980SMasahiro Yamada 
237ea65c980SMasahiro Yamada struct ddrphy_init_sequence {
238ea65c980SMasahiro Yamada 	char *description;
239ea65c980SMasahiro Yamada 	u32 init_flag;
240ea65c980SMasahiro Yamada 	u32 done_flag;
241ea65c980SMasahiro Yamada 	u32 err_flag;
242ea65c980SMasahiro Yamada };
243ea65c980SMasahiro Yamada 
244ea65c980SMasahiro Yamada static const struct ddrphy_init_sequence impedance_calibration_sequence[] = {
245ea65c980SMasahiro Yamada 	{
246ea65c980SMasahiro Yamada 		"Impedance Calibration",
247fada9eafSMasahiro Yamada 		MPHY_PIR_ZCAL,
248fada9eafSMasahiro Yamada 		MPHY_PGSR0_ZCDONE,
249fada9eafSMasahiro Yamada 		MPHY_PGSR0_ZCERR,
250ea65c980SMasahiro Yamada 	},
251ea65c980SMasahiro Yamada 	{ /* sentinel */ }
252ea65c980SMasahiro Yamada };
253ea65c980SMasahiro Yamada 
254ea65c980SMasahiro Yamada static const struct ddrphy_init_sequence dram_init_sequence[] = {
255ea65c980SMasahiro Yamada 	{
256ea65c980SMasahiro Yamada 		"DRAM Initialization",
257fada9eafSMasahiro Yamada 		MPHY_PIR_DRAMRST | MPHY_PIR_DRAMINIT,
258fada9eafSMasahiro Yamada 		MPHY_PGSR0_DIDONE,
259ea65c980SMasahiro Yamada 		0,
260ea65c980SMasahiro Yamada 	},
261ea65c980SMasahiro Yamada 	{ /* sentinel */ }
262ea65c980SMasahiro Yamada };
263ea65c980SMasahiro Yamada 
264ea65c980SMasahiro Yamada static const struct ddrphy_init_sequence training_sequence[] = {
265ea65c980SMasahiro Yamada 	{
266ea65c980SMasahiro Yamada 		"Write Leveling",
267fada9eafSMasahiro Yamada 		MPHY_PIR_WL,
268fada9eafSMasahiro Yamada 		MPHY_PGSR0_WLDONE,
269fada9eafSMasahiro Yamada 		MPHY_PGSR0_WLERR,
270ea65c980SMasahiro Yamada 	},
271ea65c980SMasahiro Yamada 	{
272ea65c980SMasahiro Yamada 		"Read DQS Gate Training",
273fada9eafSMasahiro Yamada 		MPHY_PIR_QSGATE,
274fada9eafSMasahiro Yamada 		MPHY_PGSR0_QSGDONE,
275fada9eafSMasahiro Yamada 		MPHY_PGSR0_QSGERR,
276ea65c980SMasahiro Yamada 	},
277ea65c980SMasahiro Yamada 	{
278ea65c980SMasahiro Yamada 		"Write Leveling Adjustment",
279fada9eafSMasahiro Yamada 		MPHY_PIR_WLADJ,
280fada9eafSMasahiro Yamada 		MPHY_PGSR0_WLADONE,
281fada9eafSMasahiro Yamada 		MPHY_PGSR0_WLAERR,
282ea65c980SMasahiro Yamada 	},
283ea65c980SMasahiro Yamada 	{
284ea65c980SMasahiro Yamada 		"Read Bit Deskew",
285fada9eafSMasahiro Yamada 		MPHY_PIR_RDDSKW,
286fada9eafSMasahiro Yamada 		MPHY_PGSR0_RDDONE,
287fada9eafSMasahiro Yamada 		MPHY_PGSR0_RDERR,
288ea65c980SMasahiro Yamada 	},
289ea65c980SMasahiro Yamada 	{
290ea65c980SMasahiro Yamada 		"Write Bit Deskew",
291fada9eafSMasahiro Yamada 		MPHY_PIR_WRDSKW,
292fada9eafSMasahiro Yamada 		MPHY_PGSR0_WDDONE,
293fada9eafSMasahiro Yamada 		MPHY_PGSR0_WDERR,
294ea65c980SMasahiro Yamada 	},
295ea65c980SMasahiro Yamada 	{
296ea65c980SMasahiro Yamada 		"Read Eye Training",
297fada9eafSMasahiro Yamada 		MPHY_PIR_RDEYE,
298fada9eafSMasahiro Yamada 		MPHY_PGSR0_REDONE,
299fada9eafSMasahiro Yamada 		MPHY_PGSR0_REERR,
300ea65c980SMasahiro Yamada 	},
301ea65c980SMasahiro Yamada 	{
302ea65c980SMasahiro Yamada 		"Write Eye Training",
303fada9eafSMasahiro Yamada 		MPHY_PIR_WREYE,
304fada9eafSMasahiro Yamada 		MPHY_PGSR0_WEDONE,
305fada9eafSMasahiro Yamada 		MPHY_PGSR0_WEERR,
306ea65c980SMasahiro Yamada 	},
307ea65c980SMasahiro Yamada 	{ /* sentinel */ }
308ea65c980SMasahiro Yamada };
309ea65c980SMasahiro Yamada 
__ddrphy_training(void __iomem * phy_base,const struct ddrphy_init_sequence * seq)310ea65c980SMasahiro Yamada static int __ddrphy_training(void __iomem *phy_base,
311ea65c980SMasahiro Yamada 			     const struct ddrphy_init_sequence *seq)
312ea65c980SMasahiro Yamada {
313ea65c980SMasahiro Yamada 	const struct ddrphy_init_sequence *s;
314ea65c980SMasahiro Yamada 	u32 pgsr0;
315fada9eafSMasahiro Yamada 	u32 init_flag = MPHY_PIR_INIT;
316fada9eafSMasahiro Yamada 	u32 done_flag = MPHY_PGSR0_IDONE;
317ea65c980SMasahiro Yamada 	int timeout = 50000; /* 50 msec is long enough */
318ea65c980SMasahiro Yamada #ifdef DISPLAY_ELAPSED_TIME
319ea65c980SMasahiro Yamada 	ulong start = get_timer(0);
320ea65c980SMasahiro Yamada #endif
321ea65c980SMasahiro Yamada 
322ea65c980SMasahiro Yamada 	for (s = seq; s->description; s++) {
323ea65c980SMasahiro Yamada 		init_flag |= s->init_flag;
324ea65c980SMasahiro Yamada 		done_flag |= s->done_flag;
325ea65c980SMasahiro Yamada 	}
326ea65c980SMasahiro Yamada 
327fada9eafSMasahiro Yamada 	writel(init_flag, phy_base + MPHY_PIR);
328ea65c980SMasahiro Yamada 
329ea65c980SMasahiro Yamada 	do {
330ea65c980SMasahiro Yamada 		if (--timeout < 0) {
331ea65c980SMasahiro Yamada 			pr_err("%s: error: timeout during DDR training\n",
332ea65c980SMasahiro Yamada 			       __func__);
333ea65c980SMasahiro Yamada 			return -ETIMEDOUT;
334ea65c980SMasahiro Yamada 		}
335ea65c980SMasahiro Yamada 		udelay(1);
336fada9eafSMasahiro Yamada 		pgsr0 = readl(phy_base + MPHY_PGSR0);
337ea65c980SMasahiro Yamada 	} while ((pgsr0 & done_flag) != done_flag);
338ea65c980SMasahiro Yamada 
339ea65c980SMasahiro Yamada 	for (s = seq; s->description; s++) {
340ea65c980SMasahiro Yamada 		if (pgsr0 & s->err_flag) {
341ea65c980SMasahiro Yamada 			pr_err("%s: error: %s failed\n", __func__,
342ea65c980SMasahiro Yamada 			       s->description);
343ea65c980SMasahiro Yamada 			return -EIO;
344ea65c980SMasahiro Yamada 		}
345ea65c980SMasahiro Yamada 	}
346ea65c980SMasahiro Yamada 
347ea65c980SMasahiro Yamada #ifdef DISPLAY_ELAPSED_TIME
348ea65c980SMasahiro Yamada 	printf("%s: info: elapsed time %ld msec\n", get_timer(start));
349ea65c980SMasahiro Yamada #endif
350ea65c980SMasahiro Yamada 
351ea65c980SMasahiro Yamada 	return 0;
352ea65c980SMasahiro Yamada }
353ea65c980SMasahiro Yamada 
ddrphy_impedance_calibration(void __iomem * phy_base)354ea65c980SMasahiro Yamada static int ddrphy_impedance_calibration(void __iomem *phy_base)
355ea65c980SMasahiro Yamada {
356ea65c980SMasahiro Yamada 	int ret;
357ea65c980SMasahiro Yamada 	u32 tmp;
358ea65c980SMasahiro Yamada 
359ea65c980SMasahiro Yamada 	ret = __ddrphy_training(phy_base, impedance_calibration_sequence);
360ea65c980SMasahiro Yamada 	if (ret)
361ea65c980SMasahiro Yamada 		return ret;
362ea65c980SMasahiro Yamada 
363ea65c980SMasahiro Yamada 	/*
364ea65c980SMasahiro Yamada 	 * Because of a hardware bug, IDONE flag is set when the first ZQ block
365ea65c980SMasahiro Yamada 	 * is calibrated.  The flag does not guarantee the completion for all
366ea65c980SMasahiro Yamada 	 * the ZQ blocks.  Wait a little more just in case.
367ea65c980SMasahiro Yamada 	 */
368ea65c980SMasahiro Yamada 	udelay(1);
369ea65c980SMasahiro Yamada 
370ea65c980SMasahiro Yamada 	/* reflect ZQ settings and enable average algorithm*/
371fada9eafSMasahiro Yamada 	tmp = readl(phy_base + MPHY_ZQCR);
372fada9eafSMasahiro Yamada 	tmp |= MPHY_ZQCR_FORCE_ZCAL_VT_UPDATE;
373fada9eafSMasahiro Yamada 	writel(tmp, phy_base + MPHY_ZQCR);
374fada9eafSMasahiro Yamada 	tmp &= ~MPHY_ZQCR_FORCE_ZCAL_VT_UPDATE;
375fada9eafSMasahiro Yamada 	tmp |= MPHY_ZQCR_AVGEN;
376fada9eafSMasahiro Yamada 	writel(tmp, phy_base + MPHY_ZQCR);
377ea65c980SMasahiro Yamada 
378ea65c980SMasahiro Yamada 	return 0;
379ea65c980SMasahiro Yamada }
380ea65c980SMasahiro Yamada 
ddrphy_dram_init(void __iomem * phy_base)381ea65c980SMasahiro Yamada static int ddrphy_dram_init(void __iomem *phy_base)
382ea65c980SMasahiro Yamada {
383ea65c980SMasahiro Yamada 	return __ddrphy_training(phy_base, dram_init_sequence);
384ea65c980SMasahiro Yamada }
385ea65c980SMasahiro Yamada 
ddrphy_training(void __iomem * phy_base)386ea65c980SMasahiro Yamada static int ddrphy_training(void __iomem *phy_base)
387ea65c980SMasahiro Yamada {
388ea65c980SMasahiro Yamada 	return __ddrphy_training(phy_base, training_sequence);
389ea65c980SMasahiro Yamada }
390ea65c980SMasahiro Yamada 
391ea65c980SMasahiro Yamada /* UMC */
392fada9eafSMasahiro Yamada static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x66DD131D, 0x77EE1722};
393fada9eafSMasahiro Yamada /*
394fada9eafSMasahiro Yamada  * The ch2 is a different generation UMC core.
395fada9eafSMasahiro Yamada  * The register spec is different, unfortunately.
396fada9eafSMasahiro Yamada  */
397fada9eafSMasahiro Yamada static u32 umc_cmdctlb_ch01[DRAM_FREQ_NR] = {0x13E87C44, 0x18F88C44};
398fada9eafSMasahiro Yamada static u32 umc_cmdctlb_ch2[DRAM_FREQ_NR] = {0x19E8DC44, 0x1EF8EC44};
399fada9eafSMasahiro Yamada static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = {
400fada9eafSMasahiro Yamada 	{0x004A071D, 0x0078071D},
401fada9eafSMasahiro Yamada 	{0x0055081E, 0x0089081E},
402fada9eafSMasahiro Yamada };
403fada9eafSMasahiro Yamada 
404fada9eafSMasahiro Yamada static u32 umc_spcctlb[] = {0x00FF000A, 0x00FF000B};
405fada9eafSMasahiro Yamada /* The ch2 is different for some reason only hardware guys know... */
406fada9eafSMasahiro Yamada static u32 umc_flowctla_ch01[] = {0x0800001E, 0x08000022};
407fada9eafSMasahiro Yamada static u32 umc_flowctla_ch2[] = {0x0800001E, 0x0800001E};
408fada9eafSMasahiro Yamada 
umc_set_system_latency(void __iomem * dc_base,int phy_latency)409ea65c980SMasahiro Yamada static void umc_set_system_latency(void __iomem *dc_base, int phy_latency)
410ea65c980SMasahiro Yamada {
411ea65c980SMasahiro Yamada 	u32 val;
412ea65c980SMasahiro Yamada 	int latency;
413ea65c980SMasahiro Yamada 
414ea65c980SMasahiro Yamada 	val = readl(dc_base + UMC_RDATACTL_D0);
415ea65c980SMasahiro Yamada 	latency = (val & UMC_RDATACTL_RADLTY_MASK) >> UMC_RDATACTL_RADLTY_SHIFT;
416ea65c980SMasahiro Yamada 	latency += (val & UMC_RDATACTL_RAD2LTY_MASK) >>
417ea65c980SMasahiro Yamada 						UMC_RDATACTL_RAD2LTY_SHIFT;
418ea65c980SMasahiro Yamada 	/*
419ea65c980SMasahiro Yamada 	 * UMC works at the half clock rate of the PHY.
420ea65c980SMasahiro Yamada 	 * The LSB of latency is ignored
421ea65c980SMasahiro Yamada 	 */
422ea65c980SMasahiro Yamada 	latency += phy_latency & ~1;
423ea65c980SMasahiro Yamada 
424ea65c980SMasahiro Yamada 	val &= ~(UMC_RDATACTL_RADLTY_MASK | UMC_RDATACTL_RAD2LTY_MASK);
425ea65c980SMasahiro Yamada 	if (latency > 0xf) {
426ea65c980SMasahiro Yamada 		val |= 0xf << UMC_RDATACTL_RADLTY_SHIFT;
427ea65c980SMasahiro Yamada 		val |= (latency - 0xf) << UMC_RDATACTL_RAD2LTY_SHIFT;
428ea65c980SMasahiro Yamada 	} else {
429ea65c980SMasahiro Yamada 		val |= latency << UMC_RDATACTL_RADLTY_SHIFT;
430ea65c980SMasahiro Yamada 	}
431ea65c980SMasahiro Yamada 
432ea65c980SMasahiro Yamada 	writel(val, dc_base + UMC_RDATACTL_D0);
433ea65c980SMasahiro Yamada 	writel(val, dc_base + UMC_RDATACTL_D1);
434ea65c980SMasahiro Yamada 
435ea65c980SMasahiro Yamada 	readl(dc_base + UMC_RDATACTL_D1); /* relax */
436ea65c980SMasahiro Yamada }
437ea65c980SMasahiro Yamada 
438ea65c980SMasahiro Yamada /* enable/disable auto refresh */
umc_refresh_ctrl(void __iomem * dc_base,int enable)439*1d21e1b9SMasahiro Yamada static void umc_refresh_ctrl(void __iomem *dc_base, int enable)
440ea65c980SMasahiro Yamada {
441ea65c980SMasahiro Yamada 	u32 tmp;
442ea65c980SMasahiro Yamada 
443ea65c980SMasahiro Yamada 	tmp = readl(dc_base + UMC_SPCSETB);
444ea65c980SMasahiro Yamada 	tmp &= ~UMC_SPCSETB_AREFMD_MASK;
445ea65c980SMasahiro Yamada 
446ea65c980SMasahiro Yamada 	if (enable)
447ea65c980SMasahiro Yamada 		tmp |= UMC_SPCSETB_AREFMD_ARB;
448ea65c980SMasahiro Yamada 	else
449ea65c980SMasahiro Yamada 		tmp |= UMC_SPCSETB_AREFMD_REG;
450ea65c980SMasahiro Yamada 
451ea65c980SMasahiro Yamada 	writel(tmp, dc_base + UMC_SPCSETB);
452ea65c980SMasahiro Yamada 	udelay(1);
453ea65c980SMasahiro Yamada }
454ea65c980SMasahiro Yamada 
umc_ud_init(void __iomem * umc_base,int ch)455ea65c980SMasahiro Yamada static void umc_ud_init(void __iomem *umc_base, int ch)
456ea65c980SMasahiro Yamada {
457ea65c980SMasahiro Yamada 	writel(0x00000003, umc_base + UMC_BITPERPIXELMODE_D0);
458ea65c980SMasahiro Yamada 
459ea65c980SMasahiro Yamada 	if (ch == 2)
460ea65c980SMasahiro Yamada 		writel(0x00000033, umc_base + UMC_PAIR1DOFF_D0);
461ea65c980SMasahiro Yamada }
462ea65c980SMasahiro Yamada 
umc_dc_init(void __iomem * dc_base,enum dram_freq freq,unsigned long size,int width,int ch)463ea65c980SMasahiro Yamada static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq,
464ea65c980SMasahiro Yamada 		       unsigned long size, int width, int ch)
465ea65c980SMasahiro Yamada {
466ea65c980SMasahiro Yamada 	enum dram_size size_e;
467ea65c980SMasahiro Yamada 	int latency;
468ea65c980SMasahiro Yamada 	u32 val;
469ea65c980SMasahiro Yamada 
470ea65c980SMasahiro Yamada 	switch (size) {
471ea65c980SMasahiro Yamada 	case 0:
472ea65c980SMasahiro Yamada 		return 0;
473ea65c980SMasahiro Yamada 	case SZ_256M:
474ea65c980SMasahiro Yamada 		size_e = DRAM_SZ_256M;
475ea65c980SMasahiro Yamada 		break;
476ea65c980SMasahiro Yamada 	case SZ_512M:
477ea65c980SMasahiro Yamada 		size_e = DRAM_SZ_512M;
478ea65c980SMasahiro Yamada 		break;
479ea65c980SMasahiro Yamada 	default:
480ea65c980SMasahiro Yamada 		pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
481ea65c980SMasahiro Yamada 		       size, ch);
482ea65c980SMasahiro Yamada 		return -EINVAL;
483ea65c980SMasahiro Yamada 	}
484ea65c980SMasahiro Yamada 
485ea65c980SMasahiro Yamada 	writel(umc_cmdctla[freq], dc_base + UMC_CMDCTLA);
486ea65c980SMasahiro Yamada 
487ea65c980SMasahiro Yamada 	writel(ch == 2 ? umc_cmdctlb_ch2[freq] : umc_cmdctlb_ch01[freq],
488ea65c980SMasahiro Yamada 	       dc_base + UMC_CMDCTLB);
489ea65c980SMasahiro Yamada 
490ea65c980SMasahiro Yamada 	writel(umc_spcctla[freq][size_e], dc_base + UMC_SPCCTLA);
491ea65c980SMasahiro Yamada 	writel(umc_spcctlb[freq], dc_base + UMC_SPCCTLB);
492ea65c980SMasahiro Yamada 
493ea65c980SMasahiro Yamada 	val = 0x000e000e;
494ea65c980SMasahiro Yamada 	latency = 12;
495ea65c980SMasahiro Yamada 	/* ES2 inserted one more FF to the logic. */
496ea65c980SMasahiro Yamada 	if (uniphier_get_soc_model() >= 2)
497ea65c980SMasahiro Yamada 		latency += 2;
498ea65c980SMasahiro Yamada 
499ea65c980SMasahiro Yamada 	if (latency > 0xf) {
500ea65c980SMasahiro Yamada 		val |= 0xf << UMC_RDATACTL_RADLTY_SHIFT;
501ea65c980SMasahiro Yamada 		val |= (latency - 0xf) << UMC_RDATACTL_RAD2LTY_SHIFT;
502ea65c980SMasahiro Yamada 	} else {
503ea65c980SMasahiro Yamada 		val |= latency << UMC_RDATACTL_RADLTY_SHIFT;
504ea65c980SMasahiro Yamada 	}
505ea65c980SMasahiro Yamada 
506ea65c980SMasahiro Yamada 	writel(val, dc_base + UMC_RDATACTL_D0);
507ea65c980SMasahiro Yamada 	if (width >= 32)
508ea65c980SMasahiro Yamada 		writel(val, dc_base + UMC_RDATACTL_D1);
509ea65c980SMasahiro Yamada 
510ea65c980SMasahiro Yamada 	writel(0x04060A02, dc_base + UMC_WDATACTL_D0);
511ea65c980SMasahiro Yamada 	if (width >= 32)
512ea65c980SMasahiro Yamada 		writel(0x04060A02, dc_base + UMC_WDATACTL_D1);
513ea65c980SMasahiro Yamada 	writel(0x04000000, dc_base + UMC_DATASET);
514ea65c980SMasahiro Yamada 	writel(0x00400020, dc_base + UMC_DCCGCTL);
515ea65c980SMasahiro Yamada 	writel(0x00000084, dc_base + UMC_FLOWCTLG);
516ea65c980SMasahiro Yamada 	writel(0x00000000, dc_base + UMC_ACSSETA);
517ea65c980SMasahiro Yamada 
518ea65c980SMasahiro Yamada 	writel(ch == 2 ? umc_flowctla_ch2[freq] : umc_flowctla_ch01[freq],
519ea65c980SMasahiro Yamada 	       dc_base + UMC_FLOWCTLA);
520ea65c980SMasahiro Yamada 
521ea65c980SMasahiro Yamada 	writel(0x00004400, dc_base + UMC_FLOWCTLC);
522ea65c980SMasahiro Yamada 	writel(0x200A0A00, dc_base + UMC_SPCSETB);
523ea65c980SMasahiro Yamada 	writel(0x00000520, dc_base + UMC_DFICUPDCTLA);
524ea65c980SMasahiro Yamada 	writel(0x0000000D, dc_base + UMC_RESPCTL);
525ea65c980SMasahiro Yamada 
526ea65c980SMasahiro Yamada 	if (ch != 2) {
527ea65c980SMasahiro Yamada 		writel(0x00202000, dc_base + UMC_FLOWCTLB);
528ea65c980SMasahiro Yamada 		writel(0xFDBFFFFF, dc_base + UMC_FLOWCTLOB0);
529ea65c980SMasahiro Yamada 		writel(0xFFFFFFFF, dc_base + UMC_FLOWCTLOB1);
530ea65c980SMasahiro Yamada 		writel(0x00080700, dc_base + UMC_BSICMAPSET);
531ea65c980SMasahiro Yamada 	} else {
532ea65c980SMasahiro Yamada 		writel(0x00200000, dc_base + UMC_FLOWCTLB);
533ea65c980SMasahiro Yamada 		writel(0x00000000, dc_base + UMC_BSICMAPSET);
534ea65c980SMasahiro Yamada 	}
535ea65c980SMasahiro Yamada 
536ea65c980SMasahiro Yamada 	writel(0x00000000, dc_base + UMC_ERRMASKA);
537ea65c980SMasahiro Yamada 	writel(0x00000000, dc_base + UMC_ERRMASKB);
538ea65c980SMasahiro Yamada 
539ea65c980SMasahiro Yamada 	return 0;
540ea65c980SMasahiro Yamada }
541ea65c980SMasahiro Yamada 
umc_ch_init(void __iomem * umc_ch_base,enum dram_freq freq,unsigned long size,unsigned int width,int ch)542ea65c980SMasahiro Yamada static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq,
543ea65c980SMasahiro Yamada 		       unsigned long size, unsigned int width, int ch)
544ea65c980SMasahiro Yamada {
545ea65c980SMasahiro Yamada 	void __iomem *dc_base = umc_ch_base + 0x00011000;
546ea65c980SMasahiro Yamada 	void __iomem *phy_base = umc_ch_base + 0x00030000;
547ea65c980SMasahiro Yamada 	int ret;
548ea65c980SMasahiro Yamada 
549ea65c980SMasahiro Yamada 	writel(0x00000002, dc_base + UMC_INITSET);
550ea65c980SMasahiro Yamada 	while (readl(dc_base + UMC_INITSTAT) & BIT(2))
551ea65c980SMasahiro Yamada 		cpu_relax();
552ea65c980SMasahiro Yamada 
553ea65c980SMasahiro Yamada 	/* deassert PHY reset signals */
554ea65c980SMasahiro Yamada 	writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST,
555ea65c980SMasahiro Yamada 	       dc_base + UMC_DIOCTLA);
556ea65c980SMasahiro Yamada 
557ea65c980SMasahiro Yamada 	ddrphy_init(phy_base, freq, width, ch);
558ea65c980SMasahiro Yamada 
559ea65c980SMasahiro Yamada 	ret = ddrphy_impedance_calibration(phy_base);
560ea65c980SMasahiro Yamada 	if (ret)
561ea65c980SMasahiro Yamada 		return ret;
562ea65c980SMasahiro Yamada 
563ea65c980SMasahiro Yamada 	ddrphy_dram_init(phy_base);
564ea65c980SMasahiro Yamada 	if (ret)
565ea65c980SMasahiro Yamada 		return ret;
566ea65c980SMasahiro Yamada 
567ea65c980SMasahiro Yamada 	ret = umc_dc_init(dc_base, freq, size, width, ch);
568ea65c980SMasahiro Yamada 	if (ret)
569ea65c980SMasahiro Yamada 		return ret;
570ea65c980SMasahiro Yamada 
571ea65c980SMasahiro Yamada 	umc_ud_init(umc_ch_base, ch);
572ea65c980SMasahiro Yamada 
573ea65c980SMasahiro Yamada 	ret = ddrphy_training(phy_base);
574ea65c980SMasahiro Yamada 	if (ret)
575ea65c980SMasahiro Yamada 		return ret;
576ea65c980SMasahiro Yamada 
577ea65c980SMasahiro Yamada 	udelay(1);
578ea65c980SMasahiro Yamada 
579ea65c980SMasahiro Yamada 	/* match the system latency between UMC and PHY */
580ea65c980SMasahiro Yamada 	umc_set_system_latency(dc_base,
581ea65c980SMasahiro Yamada 			       ddrphy_get_system_latency(phy_base, width));
582ea65c980SMasahiro Yamada 
583ea65c980SMasahiro Yamada 	udelay(1);
584ea65c980SMasahiro Yamada 
585ea65c980SMasahiro Yamada 	/* stop auto refresh before clearing FIFO in PHY */
586ea65c980SMasahiro Yamada 	umc_refresh_ctrl(dc_base, 0);
587ea65c980SMasahiro Yamada 	ddrphy_fifo_reset(phy_base);
588ea65c980SMasahiro Yamada 	umc_refresh_ctrl(dc_base, 1);
589ea65c980SMasahiro Yamada 
590ea65c980SMasahiro Yamada 	udelay(10);
591ea65c980SMasahiro Yamada 
592ea65c980SMasahiro Yamada 	return 0;
593ea65c980SMasahiro Yamada }
594ea65c980SMasahiro Yamada 
um_init(void __iomem * um_base)595ea65c980SMasahiro Yamada static void um_init(void __iomem *um_base)
596ea65c980SMasahiro Yamada {
597ea65c980SMasahiro Yamada 	writel(0x000000ff, um_base + UMC_MBUS0);
598ea65c980SMasahiro Yamada 	writel(0x000000ff, um_base + UMC_MBUS1);
599ea65c980SMasahiro Yamada 	writel(0x000000ff, um_base + UMC_MBUS2);
600ea65c980SMasahiro Yamada 	writel(0x000000ff, um_base + UMC_MBUS3);
601ea65c980SMasahiro Yamada }
602ea65c980SMasahiro Yamada 
uniphier_pxs2_umc_init(const struct uniphier_board_data * bd)6035b660066SMasahiro Yamada int uniphier_pxs2_umc_init(const struct uniphier_board_data *bd)
604ea65c980SMasahiro Yamada {
605ea65c980SMasahiro Yamada 	void __iomem *um_base = (void __iomem *)0x5b600000;
606ea65c980SMasahiro Yamada 	void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
607ea65c980SMasahiro Yamada 	enum dram_freq freq;
608ea65c980SMasahiro Yamada 	int ch, ret;
609ea65c980SMasahiro Yamada 
610ea65c980SMasahiro Yamada 	switch (bd->dram_freq) {
611ea65c980SMasahiro Yamada 	case 1866:
612ea65c980SMasahiro Yamada 		freq = DRAM_FREQ_1866M;
613ea65c980SMasahiro Yamada 		break;
614ea65c980SMasahiro Yamada 	case 2133:
615ea65c980SMasahiro Yamada 		freq = DRAM_FREQ_2133M;
616ea65c980SMasahiro Yamada 		break;
617ea65c980SMasahiro Yamada 	default:
618ea65c980SMasahiro Yamada 		pr_err("unsupported DRAM frequency %d MHz\n", bd->dram_freq);
619ea65c980SMasahiro Yamada 		return -EINVAL;
620ea65c980SMasahiro Yamada 	}
621ea65c980SMasahiro Yamada 
622dd38374dSMasahiro Yamada 	for (ch = 0; ch < DRAM_CH_NR; ch++) {
623ea65c980SMasahiro Yamada 		unsigned long size = bd->dram_ch[ch].size;
624ea65c980SMasahiro Yamada 		unsigned int width = bd->dram_ch[ch].width;
625ea65c980SMasahiro Yamada 
626dd38374dSMasahiro Yamada 		if (size) {
627dd38374dSMasahiro Yamada 			ret = umc_ch_init(umc_ch_base, freq,
628dd38374dSMasahiro Yamada 					  size / (width / 16), width, ch);
629ea65c980SMasahiro Yamada 			if (ret) {
630ea65c980SMasahiro Yamada 				pr_err("failed to initialize UMC ch%d\n", ch);
631ea65c980SMasahiro Yamada 				return ret;
632ea65c980SMasahiro Yamada 			}
633dd38374dSMasahiro Yamada 		}
634ea65c980SMasahiro Yamada 
635ea65c980SMasahiro Yamada 		umc_ch_base += 0x00200000;
636ea65c980SMasahiro Yamada 	}
637ea65c980SMasahiro Yamada 
638ea65c980SMasahiro Yamada 	um_init(um_base);
639ea65c980SMasahiro Yamada 
640ea65c980SMasahiro Yamada 	return 0;
641ea65c980SMasahiro Yamada }
642