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