xref: /rk3399_rockchip-uboot/arch/mips/mach-ath79/ar933x/ddr.c (revision dc557e9a1fe00ca9d884bd88feef5bebf23fede4)
1ee7bb5beSWills Wang /*
2ee7bb5beSWills Wang  * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
3ee7bb5beSWills Wang  * Based on Atheros LSDK/QSDK
4ee7bb5beSWills Wang  *
5ee7bb5beSWills Wang  * SPDX-License-Identifier: GPL-2.0+
6ee7bb5beSWills Wang  */
7ee7bb5beSWills Wang 
8ee7bb5beSWills Wang #include <common.h>
9ee7bb5beSWills Wang #include <asm/io.h>
10ee7bb5beSWills Wang #include <asm/addrspace.h>
11ee7bb5beSWills Wang #include <asm/types.h>
12ee7bb5beSWills Wang #include <mach/ar71xx_regs.h>
13*37523917SWills Wang #include <mach/ath79.h>
14ee7bb5beSWills Wang 
15ee7bb5beSWills Wang DECLARE_GLOBAL_DATA_PTR;
16ee7bb5beSWills Wang 
17ee7bb5beSWills Wang #define DDR_CTRL_UPD_EMR3S      BIT(5)
18ee7bb5beSWills Wang #define DDR_CTRL_UPD_EMR2S      BIT(4)
19ee7bb5beSWills Wang #define DDR_CTRL_PRECHARGE      BIT(3)
20ee7bb5beSWills Wang #define DDR_CTRL_AUTO_REFRESH   BIT(2)
21ee7bb5beSWills Wang #define DDR_CTRL_UPD_EMRS       BIT(1)
22ee7bb5beSWills Wang #define DDR_CTRL_UPD_MRS        BIT(0)
23ee7bb5beSWills Wang 
245691d10aSWills Wang #define DDR_REFRESH_EN          BIT(14)
25ee7bb5beSWills Wang #define DDR_REFRESH_M           0x3ff
26ee7bb5beSWills Wang #define DDR_REFRESH(x)          ((x) & 0x3ff)
27ee7bb5beSWills Wang #define DDR_REFRESH_VAL_25M     (DDR_REFRESH_EN | DDR_REFRESH(390))
28ee7bb5beSWills Wang #define DDR_REFRESH_VAL_40M     (DDR_REFRESH_EN | DDR_REFRESH(624))
29ee7bb5beSWills Wang 
30ee7bb5beSWills Wang #define DDR_TRAS_S              0
31ee7bb5beSWills Wang #define DDR_TRAS_M              0x1f
32ee7bb5beSWills Wang #define DDR_TRAS(x)             ((x) << DDR_TRAS_S)
33ee7bb5beSWills Wang #define DDR_TRCD_M              0xf
34ee7bb5beSWills Wang #define DDR_TRCD_S              5
35ee7bb5beSWills Wang #define DDR_TRCD(x)             ((x) << DDR_TRCD_S)
36ee7bb5beSWills Wang #define DDR_TRP_M               0xf
37ee7bb5beSWills Wang #define DDR_TRP_S               9
38ee7bb5beSWills Wang #define DDR_TRP(x)              ((x) << DDR_TRP_S)
39ee7bb5beSWills Wang #define DDR_TRRD_M              0xf
40ee7bb5beSWills Wang #define DDR_TRRD_S              13
41ee7bb5beSWills Wang #define DDR_TRRD(x)             ((x) << DDR_TRRD_S)
42ee7bb5beSWills Wang #define DDR_TRFC_M              0x7f
43ee7bb5beSWills Wang #define DDR_TRFC_S              17
44ee7bb5beSWills Wang #define DDR_TRFC(x)             ((x) << DDR_TRFC_S)
45ee7bb5beSWills Wang #define DDR_TMRD_M              0xf
46ee7bb5beSWills Wang #define DDR_TMRD_S              23
47ee7bb5beSWills Wang #define DDR_TMRD(x)             ((x) << DDR_TMRD_S)
48ee7bb5beSWills Wang #define DDR_CAS_L_M             0x17
49ee7bb5beSWills Wang #define DDR_CAS_L_S             27
50ee7bb5beSWills Wang #define DDR_CAS_L(x)            (((x) & DDR_CAS_L_M) << DDR_CAS_L_S)
515691d10aSWills Wang #define DDR_OPEN                BIT(30)
52ee7bb5beSWills Wang #define DDR_CONF_REG_VAL        (DDR_TRAS(16) | DDR_TRCD(6) | \
53ee7bb5beSWills Wang 				 DDR_TRP(6) | DDR_TRRD(4) | \
54ee7bb5beSWills Wang 				 DDR_TRFC(30) | DDR_TMRD(15) | \
55ee7bb5beSWills Wang 				 DDR_CAS_L(7) | DDR_OPEN)
56ee7bb5beSWills Wang 
57ee7bb5beSWills Wang #define DDR_BURST_LEN_S         0
58ee7bb5beSWills Wang #define DDR_BURST_LEN_M         0xf
59ee7bb5beSWills Wang #define DDR_BURST_LEN(x)        ((x) << DDR_BURST_LEN_S)
605691d10aSWills Wang #define DDR_BURST_TYPE          BIT(4)
615691d10aSWills Wang #define DDR_CNTL_OE_EN          BIT(5)
625691d10aSWills Wang #define DDR_PHASE_SEL           BIT(6)
635691d10aSWills Wang #define DDR_CKE                 BIT(7)
64ee7bb5beSWills Wang #define DDR_TWR_S               8
65ee7bb5beSWills Wang #define DDR_TWR_M               0xf
66ee7bb5beSWills Wang #define DDR_TWR(x)              ((x) << DDR_TWR_S)
67ee7bb5beSWills Wang #define DDR_TRTW_S              12
68ee7bb5beSWills Wang #define DDR_TRTW_M              0x1f
69ee7bb5beSWills Wang #define DDR_TRTW(x)             ((x) << DDR_TRTW_S)
70ee7bb5beSWills Wang #define DDR_TRTP_S              17
71ee7bb5beSWills Wang #define DDR_TRTP_M              0xf
72ee7bb5beSWills Wang #define DDR_TRTP(x)             ((x) << DDR_TRTP_S)
73ee7bb5beSWills Wang #define DDR_TWTR_S              21
74ee7bb5beSWills Wang #define DDR_TWTR_M              0x1f
75ee7bb5beSWills Wang #define DDR_TWTR(x)             ((x) << DDR_TWTR_S)
76ee7bb5beSWills Wang #define DDR_G_OPEN_L_S          26
77ee7bb5beSWills Wang #define DDR_G_OPEN_L_M          0xf
78ee7bb5beSWills Wang #define DDR_G_OPEN_L(x)         ((x) << DDR_G_OPEN_L_S)
795691d10aSWills Wang #define DDR_HALF_WIDTH_LOW      BIT(31)
80ee7bb5beSWills Wang #define DDR_CONF2_REG_VAL       (DDR_BURST_LEN(8) | DDR_CNTL_OE_EN | \
81ee7bb5beSWills Wang 				 DDR_CKE | DDR_TWR(6) | DDR_TRTW(14) | \
82ee7bb5beSWills Wang 				 DDR_TRTP(8) | DDR_TWTR(14) | \
83ee7bb5beSWills Wang 				 DDR_G_OPEN_L(7) | DDR_HALF_WIDTH_LOW)
84ee7bb5beSWills Wang 
85ee7bb5beSWills Wang #define DDR2_CONF_TWL_S         10
86ee7bb5beSWills Wang #define DDR2_CONF_TWL_M         0xf
87ee7bb5beSWills Wang #define DDR2_CONF_TWL(x)        (((x) & DDR2_CONF_TWL_M) << DDR2_CONF_TWL_S)
88ee7bb5beSWills Wang #define DDR2_CONF_ODT           BIT(9)
89ee7bb5beSWills Wang #define DDR2_CONF_TFAW_S        2
90ee7bb5beSWills Wang #define DDR2_CONF_TFAW_M        0x3f
91ee7bb5beSWills Wang #define DDR2_CONF_TFAW(x)       (((x) & DDR2_CONF_TFAW_M) << DDR2_CONF_TFAW_S)
92ee7bb5beSWills Wang #define DDR2_CONF_EN            BIT(0)
93ee7bb5beSWills Wang #define DDR2_CONF_VAL           (DDR2_CONF_TWL(2) | DDR2_CONF_ODT | \
94ee7bb5beSWills Wang 				 DDR2_CONF_TFAW(22) | DDR2_CONF_EN)
95ee7bb5beSWills Wang 
96ee7bb5beSWills Wang #define DDR1_EXT_MODE_VAL       0x02
97ee7bb5beSWills Wang #define DDR2_EXT_MODE_VAL       0x402
98ee7bb5beSWills Wang #define DDR2_EXT_MODE_OCD_VAL   0x382
99ee7bb5beSWills Wang #define DDR1_MODE_DLL_VAL       0x133
100ee7bb5beSWills Wang #define DDR2_MODE_DLL_VAL       0x100
101ee7bb5beSWills Wang #define DDR1_MODE_VAL           0x33
102ee7bb5beSWills Wang #define DDR2_MODE_VAL           0xa33
103ee7bb5beSWills Wang #define DDR_TAP_VAL0            0x08
104ee7bb5beSWills Wang #define DDR_TAP_VAL1            0x09
105ee7bb5beSWills Wang 
ddr_init(void)106ee7bb5beSWills Wang void ddr_init(void)
107ee7bb5beSWills Wang {
108ee7bb5beSWills Wang 	void __iomem *regs;
109ee7bb5beSWills Wang 	u32 val;
110ee7bb5beSWills Wang 
111ee7bb5beSWills Wang 	regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
112ee7bb5beSWills Wang 			   MAP_NOCACHE);
113ee7bb5beSWills Wang 
114ee7bb5beSWills Wang 	writel(DDR_CONF_REG_VAL, regs + AR71XX_DDR_REG_CONFIG);
115ee7bb5beSWills Wang 	writel(DDR_CONF2_REG_VAL, regs + AR71XX_DDR_REG_CONFIG2);
116ee7bb5beSWills Wang 
117*37523917SWills Wang 	val = ath79_get_bootstrap();
118ee7bb5beSWills Wang 	if (val & AR933X_BOOTSTRAP_DDR2) {
119ee7bb5beSWills Wang 		/* AHB maximum timeout */
120ee7bb5beSWills Wang 		writel(0xfffff, regs + AR933X_DDR_REG_TIMEOUT_MAX);
121ee7bb5beSWills Wang 
122ee7bb5beSWills Wang 		/* Enable DDR2 */
123ee7bb5beSWills Wang 		writel(DDR2_CONF_VAL, regs + AR933X_DDR_REG_DDR2_CONFIG);
124ee7bb5beSWills Wang 
125ee7bb5beSWills Wang 		/* Precharge All */
126ee7bb5beSWills Wang 		writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
127ee7bb5beSWills Wang 
128ee7bb5beSWills Wang 		/* Disable High Temperature Self-Refresh, Full Array */
129ee7bb5beSWills Wang 		writel(0x00, regs + AR933X_DDR_REG_EMR2);
130ee7bb5beSWills Wang 
131ee7bb5beSWills Wang 		/* Extended Mode Register 2 Set (EMR2S) */
132ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_EMR2S, regs + AR71XX_DDR_REG_CONTROL);
133ee7bb5beSWills Wang 
134ee7bb5beSWills Wang 		writel(0x00, regs + AR933X_DDR_REG_EMR3);
135ee7bb5beSWills Wang 
136ee7bb5beSWills Wang 		/* Extended Mode Register 3 Set (EMR3S) */
137ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_EMR3S, regs + AR71XX_DDR_REG_CONTROL);
138ee7bb5beSWills Wang 
139ee7bb5beSWills Wang 		/* Enable DLL,  Full strength, ODT Disabled */
140ee7bb5beSWills Wang 		writel(0x00, regs + AR71XX_DDR_REG_EMR);
141ee7bb5beSWills Wang 
142ee7bb5beSWills Wang 		/* Extended Mode Register Set (EMRS) */
143ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
144ee7bb5beSWills Wang 
145ee7bb5beSWills Wang 		/* Reset DLL */
146ee7bb5beSWills Wang 		writel(DDR2_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE);
147ee7bb5beSWills Wang 
148ee7bb5beSWills Wang 		/* Mode Register Set (MRS) */
149ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
150ee7bb5beSWills Wang 
151ee7bb5beSWills Wang 		/* Precharge All */
152ee7bb5beSWills Wang 		writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
153ee7bb5beSWills Wang 
154ee7bb5beSWills Wang 		/* Auto Refresh */
155ee7bb5beSWills Wang 		writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL);
156ee7bb5beSWills Wang 		writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL);
157ee7bb5beSWills Wang 
158ee7bb5beSWills Wang 		/* Write recovery (WR) 6 clock, CAS Latency 3, Burst Length 8 */
159ee7bb5beSWills Wang 		writel(DDR2_MODE_VAL, regs + AR71XX_DDR_REG_MODE);
160ee7bb5beSWills Wang 		/* Mode Register Set (MRS) */
161ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
162ee7bb5beSWills Wang 
163ee7bb5beSWills Wang 		/* Enable OCD defaults, Enable DLL, Reduced Drive Strength */
164ee7bb5beSWills Wang 		writel(DDR2_EXT_MODE_OCD_VAL, regs + AR71XX_DDR_REG_EMR);
165ee7bb5beSWills Wang 
166ee7bb5beSWills Wang 		/* Extended Mode Register Set (EMRS) */
167ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
168ee7bb5beSWills Wang 
169ee7bb5beSWills Wang 		/* OCD exit, Enable DLL, Enable /DQS, Reduced Drive Strength */
170ee7bb5beSWills Wang 		writel(DDR2_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR);
171ee7bb5beSWills Wang 		/* Extended Mode Register Set (EMRS) */
172ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
173ee7bb5beSWills Wang 
174ee7bb5beSWills Wang 		/* Refresh time control */
175ee7bb5beSWills Wang 		if (val & AR933X_BOOTSTRAP_REF_CLK_40)
176ee7bb5beSWills Wang 			writel(DDR_REFRESH_VAL_40M, regs +
177ee7bb5beSWills Wang 			       AR71XX_DDR_REG_REFRESH);
178ee7bb5beSWills Wang 		else
179ee7bb5beSWills Wang 			writel(DDR_REFRESH_VAL_25M, regs +
180ee7bb5beSWills Wang 			       AR71XX_DDR_REG_REFRESH);
181ee7bb5beSWills Wang 
182ee7bb5beSWills Wang 		/* DQS 0 Tap Control */
183ee7bb5beSWills Wang 		writel(DDR_TAP_VAL0, regs + AR71XX_DDR_REG_TAP_CTRL0);
184ee7bb5beSWills Wang 
185ee7bb5beSWills Wang 		/* DQS 1 Tap Control */
186ee7bb5beSWills Wang 		writel(DDR_TAP_VAL1, regs + AR71XX_DDR_REG_TAP_CTRL1);
187ee7bb5beSWills Wang 
188ee7bb5beSWills Wang 		/* For 16-bit DDR */
189ee7bb5beSWills Wang 		writel(0xff, regs + AR71XX_DDR_REG_RD_CYCLE);
190ee7bb5beSWills Wang 	} else {
191ee7bb5beSWills Wang 		/* AHB maximum timeout */
192ee7bb5beSWills Wang 		writel(0xfffff, regs + AR933X_DDR_REG_TIMEOUT_MAX);
193ee7bb5beSWills Wang 
194ee7bb5beSWills Wang 		/* Precharge All */
195ee7bb5beSWills Wang 		writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
196ee7bb5beSWills Wang 
197ee7bb5beSWills Wang 		/* Reset DLL, Burst Length 8, CAS Latency 3 */
198ee7bb5beSWills Wang 		writel(DDR1_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE);
199ee7bb5beSWills Wang 
200ee7bb5beSWills Wang 		/* Forces an MRS update cycle in DDR */
201ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
202ee7bb5beSWills Wang 
203ee7bb5beSWills Wang 		/* Enable DLL, Full strength */
204ee7bb5beSWills Wang 		writel(DDR1_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR);
205ee7bb5beSWills Wang 
206ee7bb5beSWills Wang 		/* Extended Mode Register Set (EMRS) */
207ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
208ee7bb5beSWills Wang 
209ee7bb5beSWills Wang 		/* Precharge All */
210ee7bb5beSWills Wang 		writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
211ee7bb5beSWills Wang 
212ee7bb5beSWills Wang 		/* Normal DLL, Burst Length 8, CAS Latency 3 */
213ee7bb5beSWills Wang 		writel(DDR1_MODE_VAL, regs + AR71XX_DDR_REG_MODE);
214ee7bb5beSWills Wang 
215ee7bb5beSWills Wang 		/* Mode Register Set (MRS) */
216ee7bb5beSWills Wang 		writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
217ee7bb5beSWills Wang 
218ee7bb5beSWills Wang 		/* Refresh time control */
219ee7bb5beSWills Wang 		if (val & AR933X_BOOTSTRAP_REF_CLK_40)
220ee7bb5beSWills Wang 			writel(DDR_REFRESH_VAL_40M, regs +
221ee7bb5beSWills Wang 			       AR71XX_DDR_REG_REFRESH);
222ee7bb5beSWills Wang 		else
223ee7bb5beSWills Wang 			writel(DDR_REFRESH_VAL_25M, regs +
224ee7bb5beSWills Wang 			       AR71XX_DDR_REG_REFRESH);
225ee7bb5beSWills Wang 
226ee7bb5beSWills Wang 		/* DQS 0 Tap Control */
227ee7bb5beSWills Wang 		writel(DDR_TAP_VAL0, regs + AR71XX_DDR_REG_TAP_CTRL0);
228ee7bb5beSWills Wang 
229ee7bb5beSWills Wang 		/* DQS 1 Tap Control */
230ee7bb5beSWills Wang 		writel(DDR_TAP_VAL1, regs + AR71XX_DDR_REG_TAP_CTRL1);
231ee7bb5beSWills Wang 
232ee7bb5beSWills Wang 		/* For 16-bit DDR */
233ee7bb5beSWills Wang 		writel(0xff, regs + AR71XX_DDR_REG_RD_CYCLE);
234ee7bb5beSWills Wang 	}
235ee7bb5beSWills Wang }
236ee7bb5beSWills Wang 
ddr_tap_tuning(void)237ee7bb5beSWills Wang void ddr_tap_tuning(void)
238ee7bb5beSWills Wang {
239ee7bb5beSWills Wang 	void __iomem *regs;
240ee7bb5beSWills Wang 	u32 *addr_k0, *addr_k1, *addr;
241ee7bb5beSWills Wang 	u32 val, tap, upper, lower;
242ee7bb5beSWills Wang 	int i, j, dir, err, done;
243ee7bb5beSWills Wang 
244ee7bb5beSWills Wang 	regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
245ee7bb5beSWills Wang 			   MAP_NOCACHE);
246ee7bb5beSWills Wang 
247ee7bb5beSWills Wang 	/* Init memory pattern */
248ee7bb5beSWills Wang 	addr = (void *)CKSEG0ADDR(0x2000);
249ee7bb5beSWills Wang 	for (i = 0; i < 256; i++) {
250ee7bb5beSWills Wang 		val = 0;
251ee7bb5beSWills Wang 		for (j = 0; j < 8; j++) {
252ee7bb5beSWills Wang 			if (i & (1 << j)) {
253ee7bb5beSWills Wang 				if (j % 2)
254ee7bb5beSWills Wang 					val |= 0xffff0000;
255ee7bb5beSWills Wang 				else
256ee7bb5beSWills Wang 					val |= 0x0000ffff;
257ee7bb5beSWills Wang 			}
258ee7bb5beSWills Wang 
259ee7bb5beSWills Wang 			if (j % 2) {
260ee7bb5beSWills Wang 				*addr++ = val;
261ee7bb5beSWills Wang 				val = 0;
262ee7bb5beSWills Wang 			}
263ee7bb5beSWills Wang 		}
264ee7bb5beSWills Wang 	}
265ee7bb5beSWills Wang 
266ee7bb5beSWills Wang 	err = 0;
267ee7bb5beSWills Wang 	done = 0;
268ee7bb5beSWills Wang 	dir = 1;
269ee7bb5beSWills Wang 	tap = readl(regs + AR71XX_DDR_REG_TAP_CTRL0);
270ee7bb5beSWills Wang 	val = tap;
2714349b55bSWills Wang 	upper = tap;
2724349b55bSWills Wang 	lower = tap;
273ee7bb5beSWills Wang 	while (!done) {
274ee7bb5beSWills Wang 		err = 0;
275ee7bb5beSWills Wang 
276ee7bb5beSWills Wang 		/* Update new DDR tap value */
277ee7bb5beSWills Wang 		writel(val, regs + AR71XX_DDR_REG_TAP_CTRL0);
278ee7bb5beSWills Wang 		writel(val, regs + AR71XX_DDR_REG_TAP_CTRL1);
279ee7bb5beSWills Wang 
280ee7bb5beSWills Wang 		/* Compare DDR with cache */
281ee7bb5beSWills Wang 		for (i = 0; i < 2; i++) {
282ee7bb5beSWills Wang 			addr_k1 = (void *)CKSEG1ADDR(0x2000);
283ee7bb5beSWills Wang 			addr_k0 = (void *)CKSEG0ADDR(0x2000);
284ee7bb5beSWills Wang 			addr = (void *)CKSEG0ADDR(0x3000);
285ee7bb5beSWills Wang 
286ee7bb5beSWills Wang 			while (addr_k0 < addr) {
287ee7bb5beSWills Wang 				if (*addr_k1++ != *addr_k0++) {
288ee7bb5beSWills Wang 					err = 1;
289ee7bb5beSWills Wang 					break;
290ee7bb5beSWills Wang 				}
291ee7bb5beSWills Wang 			}
292ee7bb5beSWills Wang 
293ee7bb5beSWills Wang 			if (err)
294ee7bb5beSWills Wang 				break;
295ee7bb5beSWills Wang 		}
296ee7bb5beSWills Wang 
297ee7bb5beSWills Wang 		if (err) {
298ee7bb5beSWills Wang 			/* Save upper/lower threshold if error  */
299ee7bb5beSWills Wang 			if (dir) {
300ee7bb5beSWills Wang 				dir = 0;
301ee7bb5beSWills Wang 				val--;
302ee7bb5beSWills Wang 				upper = val;
303ee7bb5beSWills Wang 				val = tap;
304ee7bb5beSWills Wang 			} else {
305ee7bb5beSWills Wang 				val++;
306ee7bb5beSWills Wang 				lower = val;
307ee7bb5beSWills Wang 				done = 1;
308ee7bb5beSWills Wang 			}
309ee7bb5beSWills Wang 		} else {
310ee7bb5beSWills Wang 			/* Try the next value until limitation */
311ee7bb5beSWills Wang 			if (dir) {
312ee7bb5beSWills Wang 				if (val < 0x20) {
313ee7bb5beSWills Wang 					val++;
314ee7bb5beSWills Wang 				} else {
315ee7bb5beSWills Wang 					dir = 0;
316ee7bb5beSWills Wang 					upper = val;
317ee7bb5beSWills Wang 					val = tap;
318ee7bb5beSWills Wang 				}
319ee7bb5beSWills Wang 			} else {
320ee7bb5beSWills Wang 				if (!val) {
321ee7bb5beSWills Wang 					lower = val;
322ee7bb5beSWills Wang 					done = 1;
323ee7bb5beSWills Wang 				} else {
324ee7bb5beSWills Wang 					val--;
325ee7bb5beSWills Wang 				}
326ee7bb5beSWills Wang 			}
327ee7bb5beSWills Wang 		}
328ee7bb5beSWills Wang 	}
329ee7bb5beSWills Wang 
330ee7bb5beSWills Wang 	/* compute an intermediate value and write back */
331ee7bb5beSWills Wang 	val = (upper + lower) / 2;
332ee7bb5beSWills Wang 	writel(val, regs + AR71XX_DDR_REG_TAP_CTRL0);
333ee7bb5beSWills Wang 	val++;
334ee7bb5beSWills Wang 	writel(val, regs + AR71XX_DDR_REG_TAP_CTRL1);
335ee7bb5beSWills Wang }
336