xref: /titanic_52/usr/src/uts/common/io/chxge/com/mc4.c (revision d39a76e7b087a3d0927cbe6898dc0a6770fa6c68)
1*d39a76e7Sxw161283 /*
2*d39a76e7Sxw161283  * CDDL HEADER START
3*d39a76e7Sxw161283  *
4*d39a76e7Sxw161283  * The contents of this file are subject to the terms of the
5*d39a76e7Sxw161283  * Common Development and Distribution License (the "License").
6*d39a76e7Sxw161283  * You may not use this file except in compliance with the License.
7*d39a76e7Sxw161283  *
8*d39a76e7Sxw161283  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*d39a76e7Sxw161283  * or http://www.opensolaris.org/os/licensing.
10*d39a76e7Sxw161283  * See the License for the specific language governing permissions
11*d39a76e7Sxw161283  * and limitations under the License.
12*d39a76e7Sxw161283  *
13*d39a76e7Sxw161283  * When distributing Covered Code, include this CDDL HEADER in each
14*d39a76e7Sxw161283  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*d39a76e7Sxw161283  * If applicable, add the following below this CDDL HEADER, with the
16*d39a76e7Sxw161283  * fields enclosed by brackets "[]" replaced with your own identifying
17*d39a76e7Sxw161283  * information: Portions Copyright [yyyy] [name of copyright owner]
18*d39a76e7Sxw161283  *
19*d39a76e7Sxw161283  * CDDL HEADER END
20*d39a76e7Sxw161283  */
21*d39a76e7Sxw161283 
22*d39a76e7Sxw161283 /*
23*d39a76e7Sxw161283  * This file is part of the Chelsio T1 Ethernet driver.
24*d39a76e7Sxw161283  *
25*d39a76e7Sxw161283  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
26*d39a76e7Sxw161283  */
27*d39a76e7Sxw161283 
28*d39a76e7Sxw161283 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* mc4.c */
29*d39a76e7Sxw161283 
30*d39a76e7Sxw161283 #include "common.h"
31*d39a76e7Sxw161283 #include "regs.h"
32*d39a76e7Sxw161283 #include "mc4.h"
33*d39a76e7Sxw161283 
34*d39a76e7Sxw161283 struct pemc4 {
35*d39a76e7Sxw161283 	adapter_t *adapter;
36*d39a76e7Sxw161283 	unsigned int size;
37*d39a76e7Sxw161283 	unsigned int nwords;           /* MC4 width in terms of 32-bit words */
38*d39a76e7Sxw161283 	struct pemc4_intr_counts intr_cnt;
39*d39a76e7Sxw161283 };
40*d39a76e7Sxw161283 
41*d39a76e7Sxw161283 void t1_mc4_destroy(struct pemc4 *mc4)
42*d39a76e7Sxw161283 {
43*d39a76e7Sxw161283 	t1_os_free((void *)mc4, sizeof(*mc4));
44*d39a76e7Sxw161283 }
45*d39a76e7Sxw161283 
46*d39a76e7Sxw161283 #define is_MC4A(adapter) (!t1_is_T1B(adapter))
47*d39a76e7Sxw161283 
48*d39a76e7Sxw161283 /* Calculate amount of MC4 memory. */
49*d39a76e7Sxw161283 static unsigned int __devinit mc4_calc_size(adapter_t *adapter)
50*d39a76e7Sxw161283 {
51*d39a76e7Sxw161283 	u32 mc4_cfg = t1_read_reg_4(adapter, A_MC4_CFG);
52*d39a76e7Sxw161283 	unsigned int width = is_MC4A(adapter) ? G_MC4A_WIDTH(mc4_cfg) :
53*d39a76e7Sxw161283 		                                !!(mc4_cfg & F_MC4_NARROW);
54*d39a76e7Sxw161283 
55*d39a76e7Sxw161283 	return (256 * 1024 * 1024) >> width;
56*d39a76e7Sxw161283 }
57*d39a76e7Sxw161283 
58*d39a76e7Sxw161283 /*
59*d39a76e7Sxw161283  * Write a value to a register and check that the write completed.  These
60*d39a76e7Sxw161283  * writes normally complete in a cycle or two, so one read should suffice but
61*d39a76e7Sxw161283  * just in case we give them a bit of grace period.  Note that the very first
62*d39a76e7Sxw161283  * read exists to flush the posted write to the device.
63*d39a76e7Sxw161283  */
64*d39a76e7Sxw161283 static int wrreg_wait(adapter_t *adapter, unsigned int addr, u32 val)
65*d39a76e7Sxw161283 {
66*d39a76e7Sxw161283 	int attempts = 2;
67*d39a76e7Sxw161283 
68*d39a76e7Sxw161283 	t1_write_reg_4(adapter,	addr, val);
69*d39a76e7Sxw161283 	val = t1_read_reg_4(adapter, addr);                   /* flush */
70*d39a76e7Sxw161283 	while (attempts--) {
71*d39a76e7Sxw161283 		if (!(t1_read_reg_4(adapter, addr) & F_BUSY))
72*d39a76e7Sxw161283 			return 0;
73*d39a76e7Sxw161283 		if (attempts)
74*d39a76e7Sxw161283 			DELAY_US(1);
75*d39a76e7Sxw161283 	}
76*d39a76e7Sxw161283 	CH_ERR("%s: write to MC4 register 0x%x timed out\n",
77*d39a76e7Sxw161283 	       adapter_name(adapter), addr);
78*d39a76e7Sxw161283 	return -EIO;
79*d39a76e7Sxw161283 }
80*d39a76e7Sxw161283 
81*d39a76e7Sxw161283 #define MC4_DLL_DONE (F_MASTER_DLL_LOCKED | F_MASTER_DLL_MAX_TAP_COUNT)
82*d39a76e7Sxw161283 
83*d39a76e7Sxw161283 int t1_mc4_init(struct pemc4 *mc4, unsigned int mc4_clock)
84*d39a76e7Sxw161283 {
85*d39a76e7Sxw161283 	int attempts;
86*d39a76e7Sxw161283 	u32 val;
87*d39a76e7Sxw161283 	unsigned int width, ext_mode, slow_mode;
88*d39a76e7Sxw161283 	adapter_t *adapter = mc4->adapter;
89*d39a76e7Sxw161283 
90*d39a76e7Sxw161283 	/* Power up the FCRAMs. */
91*d39a76e7Sxw161283 	val = t1_read_reg_4(adapter, A_MC4_CFG);
92*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_MC4_CFG, val | F_POWER_UP);
93*d39a76e7Sxw161283 	val = t1_read_reg_4(adapter, A_MC4_CFG);               /* flush */
94*d39a76e7Sxw161283 
95*d39a76e7Sxw161283 	if (is_MC4A(adapter)) {
96*d39a76e7Sxw161283 		slow_mode = val & F_MC4A_SLOW;
97*d39a76e7Sxw161283 		width = G_MC4A_WIDTH(val);
98*d39a76e7Sxw161283 
99*d39a76e7Sxw161283 		/* If we're not in slow mode, we are using the DLLs */
100*d39a76e7Sxw161283 		if (!slow_mode) {
101*d39a76e7Sxw161283 			/* Clear Reset */
102*d39a76e7Sxw161283 			val = t1_read_reg_4(adapter, A_MC4_STROBE);
103*d39a76e7Sxw161283 			t1_write_reg_4(adapter, A_MC4_STROBE,
104*d39a76e7Sxw161283 				       val & ~F_SLAVE_DLL_RESET);
105*d39a76e7Sxw161283 
106*d39a76e7Sxw161283 			/* Wait for slave DLLs to lock */
107*d39a76e7Sxw161283 			DELAY_US(2 * 512 / (mc4_clock / 1000000) + 1);
108*d39a76e7Sxw161283 		}
109*d39a76e7Sxw161283 	} else {
110*d39a76e7Sxw161283 		slow_mode = val & F_MC4_SLOW;
111*d39a76e7Sxw161283 		width = !!(val & F_MC4_NARROW);
112*d39a76e7Sxw161283 
113*d39a76e7Sxw161283 		/* Initializes the master DLL and slave delay lines. */
114*d39a76e7Sxw161283 		if (t1_is_asic(adapter) && !slow_mode) {
115*d39a76e7Sxw161283 			val = t1_read_reg_4(adapter, A_MC4_STROBE);
116*d39a76e7Sxw161283 			t1_write_reg_4(adapter, A_MC4_STROBE,
117*d39a76e7Sxw161283 				       val & ~F_MASTER_DLL_RESET);
118*d39a76e7Sxw161283 
119*d39a76e7Sxw161283 			/* Wait for the master DLL to lock. */
120*d39a76e7Sxw161283 			attempts = 100;
121*d39a76e7Sxw161283 			do {
122*d39a76e7Sxw161283 				DELAY_US(1);
123*d39a76e7Sxw161283 				val = t1_read_reg_4(adapter, A_MC4_STROBE);
124*d39a76e7Sxw161283 			} while (!(val & MC4_DLL_DONE) && --attempts);
125*d39a76e7Sxw161283 			if (!(val & MC4_DLL_DONE)) {
126*d39a76e7Sxw161283 				CH_ERR("%s: MC4 DLL lock failed\n",
127*d39a76e7Sxw161283 				       adapter_name(adapter));
128*d39a76e7Sxw161283 				goto out_fail;
129*d39a76e7Sxw161283 			}
130*d39a76e7Sxw161283 		}
131*d39a76e7Sxw161283 	}
132*d39a76e7Sxw161283 
133*d39a76e7Sxw161283 	mc4->nwords = 4 >> width;
134*d39a76e7Sxw161283 
135*d39a76e7Sxw161283 	/* Set the FCRAM output drive strength and enable DLLs if needed */
136*d39a76e7Sxw161283 	ext_mode = t1_is_asic(adapter) && !slow_mode ? 0 : 1;
137*d39a76e7Sxw161283 	if (wrreg_wait(adapter, A_MC4_EXT_MODE, ext_mode))
138*d39a76e7Sxw161283 		goto out_fail;
139*d39a76e7Sxw161283 
140*d39a76e7Sxw161283 	/* Specify the FCRAM operating parameters */
141*d39a76e7Sxw161283 	if (wrreg_wait(adapter, A_MC4_MODE, 0x32))
142*d39a76e7Sxw161283 		goto out_fail;
143*d39a76e7Sxw161283 
144*d39a76e7Sxw161283 	/* Initiate an immediate refresh and wait for the write to complete. */
145*d39a76e7Sxw161283 	val = t1_read_reg_4(adapter, A_MC4_REFRESH);
146*d39a76e7Sxw161283 	if (wrreg_wait(adapter, A_MC4_REFRESH, val & ~F_REFRESH_ENABLE))
147*d39a76e7Sxw161283 		goto out_fail;
148*d39a76e7Sxw161283 
149*d39a76e7Sxw161283 	/* 2nd immediate refresh as before */
150*d39a76e7Sxw161283 	if (wrreg_wait(adapter, A_MC4_REFRESH, val & ~F_REFRESH_ENABLE))
151*d39a76e7Sxw161283 		goto out_fail;
152*d39a76e7Sxw161283 
153*d39a76e7Sxw161283 	/* Convert to KHz first to avoid 64-bit division. */
154*d39a76e7Sxw161283 	mc4_clock /= 1000;                            /* Hz->KHz */
155*d39a76e7Sxw161283 	mc4_clock = mc4_clock * 7812 + mc4_clock / 2; /* ns */
156*d39a76e7Sxw161283 	mc4_clock /= 1000000;                         /* KHz->MHz, ns->us */
157*d39a76e7Sxw161283 
158*d39a76e7Sxw161283 	/* Enable periodic refresh. */
159*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_MC4_REFRESH,
160*d39a76e7Sxw161283 		       F_REFRESH_ENABLE | V_REFRESH_DIVISOR(mc4_clock));
161*d39a76e7Sxw161283 	(void) t1_read_reg_4(adapter, A_MC4_REFRESH);    /* flush */
162*d39a76e7Sxw161283 
163*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_MC4_ECC_CNTL,
164*d39a76e7Sxw161283 		       F_ECC_GENERATION_ENABLE | F_ECC_CHECK_ENABLE);
165*d39a76e7Sxw161283 
166*d39a76e7Sxw161283 	/* Use the BIST engine to clear all of the MC4 memory. */
167*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_MC4_BIST_ADDR_BEG, 0);
168*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_MC4_BIST_ADDR_END, (mc4->size << width) - 1);
169*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_MC4_BIST_DATA, 0);
170*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_MC4_BIST_OP, V_OP(1) | 0x1f0);
171*d39a76e7Sxw161283 	(void) t1_read_reg_4(adapter, A_MC4_BIST_OP);              /* flush */
172*d39a76e7Sxw161283 
173*d39a76e7Sxw161283 	attempts = 100;
174*d39a76e7Sxw161283 	do {
175*d39a76e7Sxw161283 		DELAY_MS(100);
176*d39a76e7Sxw161283 		val = t1_read_reg_4(adapter, A_MC4_BIST_OP);
177*d39a76e7Sxw161283 	} while ((val & F_BUSY) && --attempts);
178*d39a76e7Sxw161283 	if (val & F_BUSY) {
179*d39a76e7Sxw161283 		CH_ERR("%s: MC4 BIST timed out\n", adapter_name(adapter));
180*d39a76e7Sxw161283 		goto out_fail;
181*d39a76e7Sxw161283 	}
182*d39a76e7Sxw161283 
183*d39a76e7Sxw161283 	/* Enable normal memory accesses. */
184*d39a76e7Sxw161283 	val = t1_read_reg_4(adapter, A_MC4_CFG);
185*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_MC4_CFG, val | F_READY);
186*d39a76e7Sxw161283 	val = t1_read_reg_4(adapter, A_MC4_CFG);               /* flush */
187*d39a76e7Sxw161283 	return 0;
188*d39a76e7Sxw161283 
189*d39a76e7Sxw161283  out_fail:
190*d39a76e7Sxw161283 	return -1;
191*d39a76e7Sxw161283 }
192*d39a76e7Sxw161283 
193*d39a76e7Sxw161283 struct pemc4 * __devinit t1_mc4_create(adapter_t *adapter)
194*d39a76e7Sxw161283 {
195*d39a76e7Sxw161283 	struct pemc4 *mc4 = t1_os_malloc_wait_zero(sizeof(*mc4));
196*d39a76e7Sxw161283 
197*d39a76e7Sxw161283 	if (mc4) {
198*d39a76e7Sxw161283 		mc4->adapter = adapter;
199*d39a76e7Sxw161283 		mc4->size = mc4_calc_size(adapter);
200*d39a76e7Sxw161283 	}
201*d39a76e7Sxw161283 	return mc4;
202*d39a76e7Sxw161283 }
203*d39a76e7Sxw161283 
204*d39a76e7Sxw161283 unsigned int t1_mc4_get_size(struct pemc4 *mc4)
205*d39a76e7Sxw161283 {
206*d39a76e7Sxw161283 	return mc4->size;
207*d39a76e7Sxw161283 }
208*d39a76e7Sxw161283 
209*d39a76e7Sxw161283 #define MC4_INT_MASK (F_MC4_CORR_ERR | F_MC4_UNCORR_ERR | F_MC4_ADDR_ERR)
210*d39a76e7Sxw161283 #define MC4_INT_FATAL (F_MC4_UNCORR_ERR | F_MC4_ADDR_ERR)
211*d39a76e7Sxw161283 
212*d39a76e7Sxw161283 void t1_mc4_intr_enable(struct pemc4 *mc4)
213*d39a76e7Sxw161283 {
214*d39a76e7Sxw161283 	u32 pl_intr;
215*d39a76e7Sxw161283 
216*d39a76e7Sxw161283 	if (t1_is_asic(mc4->adapter)) {
217*d39a76e7Sxw161283 		t1_write_reg_4(mc4->adapter, A_MC4_INT_ENABLE, MC4_INT_MASK);
218*d39a76e7Sxw161283 
219*d39a76e7Sxw161283 		pl_intr = t1_read_reg_4(mc4->adapter, A_PL_ENABLE);
220*d39a76e7Sxw161283 		t1_write_reg_4(mc4->adapter, A_PL_ENABLE,
221*d39a76e7Sxw161283 			       pl_intr | F_PL_INTR_MC4);
222*d39a76e7Sxw161283 	}
223*d39a76e7Sxw161283 }
224*d39a76e7Sxw161283 
225*d39a76e7Sxw161283 void t1_mc4_intr_disable(struct pemc4 *mc4)
226*d39a76e7Sxw161283 {
227*d39a76e7Sxw161283 	u32 pl_intr;
228*d39a76e7Sxw161283 
229*d39a76e7Sxw161283 	if (t1_is_asic(mc4->adapter)) {
230*d39a76e7Sxw161283 		t1_write_reg_4(mc4->adapter, A_MC4_INT_ENABLE, 0);
231*d39a76e7Sxw161283 
232*d39a76e7Sxw161283 		pl_intr = t1_read_reg_4(mc4->adapter, A_PL_ENABLE);
233*d39a76e7Sxw161283 		t1_write_reg_4(mc4->adapter, A_PL_ENABLE,
234*d39a76e7Sxw161283 			       pl_intr & ~F_PL_INTR_MC4);
235*d39a76e7Sxw161283 	}
236*d39a76e7Sxw161283 }
237*d39a76e7Sxw161283 
238*d39a76e7Sxw161283 void t1_mc4_intr_clear(struct pemc4 *mc4)
239*d39a76e7Sxw161283 {
240*d39a76e7Sxw161283 	if (t1_is_asic(mc4->adapter)) {
241*d39a76e7Sxw161283 		t1_write_reg_4(mc4->adapter, A_MC4_INT_CAUSE, 0xffffffff);
242*d39a76e7Sxw161283 		t1_write_reg_4(mc4->adapter, A_PL_CAUSE, F_PL_INTR_MC4);
243*d39a76e7Sxw161283 	}
244*d39a76e7Sxw161283 }
245*d39a76e7Sxw161283 
246*d39a76e7Sxw161283 int t1_mc4_intr_handler(struct pemc4 *mc4)
247*d39a76e7Sxw161283 {
248*d39a76e7Sxw161283 	adapter_t *adapter = mc4->adapter;
249*d39a76e7Sxw161283 	u32 cause = t1_read_reg_4(adapter, A_MC4_INT_CAUSE);
250*d39a76e7Sxw161283 
251*d39a76e7Sxw161283 	if (cause & F_MC4_CORR_ERR) {
252*d39a76e7Sxw161283 		mc4->intr_cnt.corr_err++;
253*d39a76e7Sxw161283 		CH_WARN("%s: MC4 correctable error at addr 0x%x, "
254*d39a76e7Sxw161283 			"data 0x%x 0x%x 0x%x 0x%x 0x%x\n",
255*d39a76e7Sxw161283 			adapter_name(adapter),
256*d39a76e7Sxw161283 			G_MC4_CE_ADDR(t1_read_reg_4(adapter, A_MC4_CE_ADDR)),
257*d39a76e7Sxw161283 			t1_read_reg_4(adapter, A_MC4_CE_DATA0),
258*d39a76e7Sxw161283 			t1_read_reg_4(adapter, A_MC4_CE_DATA1),
259*d39a76e7Sxw161283 			t1_read_reg_4(adapter, A_MC4_CE_DATA2),
260*d39a76e7Sxw161283 			t1_read_reg_4(adapter, A_MC4_CE_DATA3),
261*d39a76e7Sxw161283 			t1_read_reg_4(adapter, A_MC4_CE_DATA4));
262*d39a76e7Sxw161283 	}
263*d39a76e7Sxw161283 
264*d39a76e7Sxw161283 	if (cause & F_MC4_UNCORR_ERR) {
265*d39a76e7Sxw161283 		mc4->intr_cnt.uncorr_err++;
266*d39a76e7Sxw161283 		CH_ALERT("%s: MC4 uncorrectable error at addr 0x%x, "
267*d39a76e7Sxw161283 			 "data 0x%x 0x%x 0x%x 0x%x 0x%x\n",
268*d39a76e7Sxw161283 			 adapter_name(adapter),
269*d39a76e7Sxw161283 			 G_MC4_UE_ADDR(t1_read_reg_4(adapter, A_MC4_UE_ADDR)),
270*d39a76e7Sxw161283 			 t1_read_reg_4(adapter, A_MC4_UE_DATA0),
271*d39a76e7Sxw161283 			 t1_read_reg_4(adapter, A_MC4_UE_DATA1),
272*d39a76e7Sxw161283 			 t1_read_reg_4(adapter, A_MC4_UE_DATA2),
273*d39a76e7Sxw161283 			 t1_read_reg_4(adapter, A_MC4_UE_DATA3),
274*d39a76e7Sxw161283 			 t1_read_reg_4(adapter, A_MC4_UE_DATA4));
275*d39a76e7Sxw161283 	}
276*d39a76e7Sxw161283 
277*d39a76e7Sxw161283 	if (cause & F_MC4_ADDR_ERR) {
278*d39a76e7Sxw161283 		mc4->intr_cnt.addr_err++;
279*d39a76e7Sxw161283 		CH_ALERT("%s: MC4 address error\n", adapter_name(adapter));
280*d39a76e7Sxw161283 	}
281*d39a76e7Sxw161283 
282*d39a76e7Sxw161283 	if (cause & MC4_INT_FATAL)
283*d39a76e7Sxw161283 		t1_fatal_err(adapter);
284*d39a76e7Sxw161283 
285*d39a76e7Sxw161283 	t1_write_reg_4(mc4->adapter, A_MC4_INT_CAUSE, cause);
286*d39a76e7Sxw161283 	return 0;
287*d39a76e7Sxw161283 }
288*d39a76e7Sxw161283 
289*d39a76e7Sxw161283 const struct pemc4_intr_counts *t1_mc4_get_intr_counts(struct pemc4 *mc4)
290*d39a76e7Sxw161283 {
291*d39a76e7Sxw161283 	return &mc4->intr_cnt;
292*d39a76e7Sxw161283 }
293*d39a76e7Sxw161283 
294*d39a76e7Sxw161283 /*
295*d39a76e7Sxw161283  * Read n 256-bit words from MC4 starting at word start, using backdoor
296*d39a76e7Sxw161283  * accesses.
297*d39a76e7Sxw161283  */
298*d39a76e7Sxw161283 int t1_mc4_bd_read(struct pemc4 *mc4, unsigned int start, unsigned int n,
299*d39a76e7Sxw161283 		   u32 *buf)
300*d39a76e7Sxw161283 {
301*d39a76e7Sxw161283 	adapter_t *adap = mc4->adapter;
302*d39a76e7Sxw161283 	unsigned int size256 = mc4->size / 32, c = 8 / mc4->nwords, i;
303*d39a76e7Sxw161283 
304*d39a76e7Sxw161283 	if (start >= size256 || start + n > size256)
305*d39a76e7Sxw161283 		return -EINVAL;
306*d39a76e7Sxw161283 
307*d39a76e7Sxw161283 	for (i = 8, start *= 16 * c, n *= c; n; --n, start += 16) {
308*d39a76e7Sxw161283 		int attempts = 10;
309*d39a76e7Sxw161283 		u32 val;
310*d39a76e7Sxw161283 
311*d39a76e7Sxw161283 		t1_write_reg_4(adap, A_MC4_BD_ADDR, start);
312*d39a76e7Sxw161283 		t1_write_reg_4(adap, A_MC4_BD_OP, 0);
313*d39a76e7Sxw161283 		val = t1_read_reg_4(adap, A_MC4_BD_OP);
314*d39a76e7Sxw161283 		while ((val & F_BUSY) && attempts--)
315*d39a76e7Sxw161283 			val = t1_read_reg_4(adap, A_MC4_BD_OP);
316*d39a76e7Sxw161283 
317*d39a76e7Sxw161283 		if (val & F_BUSY)
318*d39a76e7Sxw161283 			return -EIO;
319*d39a76e7Sxw161283 
320*d39a76e7Sxw161283 		buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA3);
321*d39a76e7Sxw161283 		if (mc4->nwords >= 2)
322*d39a76e7Sxw161283 			buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA2);
323*d39a76e7Sxw161283 		if (mc4->nwords == 4) {
324*d39a76e7Sxw161283 			buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA1);
325*d39a76e7Sxw161283 			buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA0);
326*d39a76e7Sxw161283 		}
327*d39a76e7Sxw161283 		if (i == 0) {
328*d39a76e7Sxw161283 			i = 8;
329*d39a76e7Sxw161283 			buf += 8;
330*d39a76e7Sxw161283 		}
331*d39a76e7Sxw161283 	}
332*d39a76e7Sxw161283 	return 0;
333*d39a76e7Sxw161283 }
334