xref: /onnv-gate/usr/src/uts/common/io/chxge/com/mc3.c (revision 3833:45d8d0ee8613)
1*3833Sxw161283 /*
2*3833Sxw161283  * CDDL HEADER START
3*3833Sxw161283  *
4*3833Sxw161283  * The contents of this file are subject to the terms of the
5*3833Sxw161283  * Common Development and Distribution License (the "License").
6*3833Sxw161283  * You may not use this file except in compliance with the License.
7*3833Sxw161283  *
8*3833Sxw161283  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3833Sxw161283  * or http://www.opensolaris.org/os/licensing.
10*3833Sxw161283  * See the License for the specific language governing permissions
11*3833Sxw161283  * and limitations under the License.
12*3833Sxw161283  *
13*3833Sxw161283  * When distributing Covered Code, include this CDDL HEADER in each
14*3833Sxw161283  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3833Sxw161283  * If applicable, add the following below this CDDL HEADER, with the
16*3833Sxw161283  * fields enclosed by brackets "[]" replaced with your own identifying
17*3833Sxw161283  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3833Sxw161283  *
19*3833Sxw161283  * CDDL HEADER END
20*3833Sxw161283  */
21*3833Sxw161283 
22*3833Sxw161283 /*
23*3833Sxw161283  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
24*3833Sxw161283  */
25*3833Sxw161283 
26*3833Sxw161283 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* mc3.c */
27*3833Sxw161283 
28*3833Sxw161283 #include "common.h"
29*3833Sxw161283 #include "regs.h"
30*3833Sxw161283 #include "mc3.h"
31*3833Sxw161283 
32*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
33*3833Sxw161283 # include "fpga_defs.h"
34*3833Sxw161283 #endif
35*3833Sxw161283 
36*3833Sxw161283 struct pemc3 {
37*3833Sxw161283 	adapter_t *adapter;
38*3833Sxw161283 	unsigned int size;
39*3833Sxw161283 	struct pemc3_intr_counts intr_cnt;
40*3833Sxw161283 };
41*3833Sxw161283 
42*3833Sxw161283 #define MC3_INTR_MASK (F_MC3_CORR_ERR | F_MC3_UNCORR_ERR | \
43*3833Sxw161283 		       V_MC3_PARITY_ERR(M_MC3_PARITY_ERR) | F_MC3_ADDR_ERR)
44*3833Sxw161283 #define MC3_INTR_FATAL (F_MC3_UNCORR_ERR | V_MC3_PARITY_ERR(M_MC3_PARITY_ERR) | F_MC3_ADDR_ERR)
45*3833Sxw161283 
t1_mc3_intr_enable(struct pemc3 * mc3)46*3833Sxw161283 void t1_mc3_intr_enable(struct pemc3 *mc3)
47*3833Sxw161283 {
48*3833Sxw161283 	u32 en = t1_read_reg_4(mc3->adapter, A_PL_ENABLE);
49*3833Sxw161283 
50*3833Sxw161283 	if (t1_is_asic(mc3->adapter)) {
51*3833Sxw161283 		t1_write_reg_4(mc3->adapter, A_MC3_INT_ENABLE, MC3_INTR_MASK);
52*3833Sxw161283 		t1_write_reg_4(mc3->adapter, A_PL_ENABLE, en | F_PL_INTR_MC3);
53*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
54*3833Sxw161283 	} else {
55*3833Sxw161283 		t1_write_reg_4(mc3->adapter, FPGA_MC3_REG_INTRENABLE,
56*3833Sxw161283 			       MC3_INTR_MASK);
57*3833Sxw161283 		t1_write_reg_4(mc3->adapter, A_PL_ENABLE,
58*3833Sxw161283 			       en | FPGA_PCIX_INTERRUPT_MC3);
59*3833Sxw161283 #endif
60*3833Sxw161283 	}
61*3833Sxw161283 }
62*3833Sxw161283 
t1_mc3_intr_disable(struct pemc3 * mc3)63*3833Sxw161283 void t1_mc3_intr_disable(struct pemc3 *mc3)
64*3833Sxw161283 {
65*3833Sxw161283 	u32 pl_intr = t1_read_reg_4(mc3->adapter, A_PL_ENABLE);
66*3833Sxw161283 
67*3833Sxw161283 	if (t1_is_asic(mc3->adapter)) {
68*3833Sxw161283 		t1_write_reg_4(mc3->adapter, A_MC3_INT_ENABLE, 0);
69*3833Sxw161283 		t1_write_reg_4(mc3->adapter, A_PL_ENABLE,
70*3833Sxw161283 			       pl_intr & ~F_PL_INTR_MC3);
71*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
72*3833Sxw161283 	} else {
73*3833Sxw161283 		t1_write_reg_4(mc3->adapter, FPGA_MC3_REG_INTRENABLE, 0);
74*3833Sxw161283 		t1_write_reg_4(mc3->adapter, A_PL_ENABLE,
75*3833Sxw161283 			       pl_intr & ~FPGA_PCIX_INTERRUPT_MC3);
76*3833Sxw161283 #endif
77*3833Sxw161283 	}
78*3833Sxw161283 }
79*3833Sxw161283 
t1_mc3_intr_clear(struct pemc3 * mc3)80*3833Sxw161283 void t1_mc3_intr_clear(struct pemc3 *mc3)
81*3833Sxw161283 {
82*3833Sxw161283 	if (t1_is_asic(mc3->adapter)) {
83*3833Sxw161283 		if (t1_is_T1B(mc3->adapter)) {
84*3833Sxw161283 			/*
85*3833Sxw161283 			 * Workaround for T1B bug: we must write to enable
86*3833Sxw161283 			 * register to clear interrupts.
87*3833Sxw161283 			 */
88*3833Sxw161283 			u32 old_en;
89*3833Sxw161283 
90*3833Sxw161283 			old_en = t1_read_reg_4(mc3->adapter, A_MC3_INT_ENABLE);
91*3833Sxw161283 			t1_write_reg_4(mc3->adapter, A_MC3_INT_ENABLE,
92*3833Sxw161283 				       0xffffffff);
93*3833Sxw161283 			t1_write_reg_4(mc3->adapter, A_MC3_INT_ENABLE, old_en);
94*3833Sxw161283 		} else
95*3833Sxw161283 			t1_write_reg_4(mc3->adapter, A_MC3_INT_CAUSE,
96*3833Sxw161283 				       0xffffffff);
97*3833Sxw161283 
98*3833Sxw161283 		t1_write_reg_4(mc3->adapter, A_PL_CAUSE, F_PL_INTR_MC3);
99*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
100*3833Sxw161283 	} else {
101*3833Sxw161283 		t1_write_reg_4(mc3->adapter, FPGA_MC3_REG_INTRCAUSE,
102*3833Sxw161283 			       0xffffffff);
103*3833Sxw161283 		t1_write_reg_4(mc3->adapter, A_PL_CAUSE,
104*3833Sxw161283 			       FPGA_PCIX_INTERRUPT_MC3);
105*3833Sxw161283 #endif
106*3833Sxw161283 	}
107*3833Sxw161283 }
108*3833Sxw161283 
t1_mc3_intr_handler(struct pemc3 * mc3)109*3833Sxw161283 int t1_mc3_intr_handler(struct pemc3 *mc3)
110*3833Sxw161283 {
111*3833Sxw161283 	adapter_t *adapter = mc3->adapter;
112*3833Sxw161283 	int cause_reg = A_MC3_INT_CAUSE;
113*3833Sxw161283 	u32 cause;
114*3833Sxw161283 
115*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
116*3833Sxw161283 	if (!t1_is_asic(adapter))
117*3833Sxw161283 		cause_reg = FPGA_MC3_REG_INTRCAUSE;
118*3833Sxw161283 #endif
119*3833Sxw161283 	cause = t1_read_reg_4(adapter, cause_reg);
120*3833Sxw161283 
121*3833Sxw161283 	if (cause & F_MC3_CORR_ERR) {
122*3833Sxw161283 		mc3->intr_cnt.corr_err++;
123*3833Sxw161283 		CH_WARN("%s: MC3 correctable error at addr 0x%x, "
124*3833Sxw161283 			"data 0x%x 0x%x 0x%x 0x%x 0x%x\n",
125*3833Sxw161283 			adapter_name(adapter),
126*3833Sxw161283 			G_MC3_CE_ADDR(t1_read_reg_4(adapter, A_MC3_CE_ADDR)),
127*3833Sxw161283 			t1_read_reg_4(adapter, A_MC3_CE_DATA0),
128*3833Sxw161283 			t1_read_reg_4(adapter, A_MC3_CE_DATA1),
129*3833Sxw161283 			t1_read_reg_4(adapter, A_MC3_CE_DATA2),
130*3833Sxw161283 			t1_read_reg_4(adapter, A_MC3_CE_DATA3),
131*3833Sxw161283 			t1_read_reg_4(adapter, A_MC3_CE_DATA4));
132*3833Sxw161283 	}
133*3833Sxw161283 
134*3833Sxw161283 	if (cause & F_MC3_UNCORR_ERR) {
135*3833Sxw161283 		mc3->intr_cnt.uncorr_err++;
136*3833Sxw161283 		CH_ALERT("%s: MC3 uncorrectable error at addr 0x%x, "
137*3833Sxw161283 			 "data 0x%x 0x%x 0x%x 0x%x 0x%x\n",
138*3833Sxw161283 			 adapter_name(adapter),
139*3833Sxw161283 			 G_MC3_UE_ADDR(t1_read_reg_4(adapter, A_MC3_UE_ADDR)),
140*3833Sxw161283 			 t1_read_reg_4(adapter, A_MC3_UE_DATA0),
141*3833Sxw161283 			 t1_read_reg_4(adapter, A_MC3_UE_DATA1),
142*3833Sxw161283 			 t1_read_reg_4(adapter, A_MC3_UE_DATA2),
143*3833Sxw161283 			 t1_read_reg_4(adapter, A_MC3_UE_DATA3),
144*3833Sxw161283 			 t1_read_reg_4(adapter, A_MC3_UE_DATA4));
145*3833Sxw161283 	}
146*3833Sxw161283 
147*3833Sxw161283 	if (G_MC3_PARITY_ERR(cause)) {
148*3833Sxw161283 		mc3->intr_cnt.parity_err++;
149*3833Sxw161283 		CH_ALERT("%s: MC3 parity error 0x%x\n", adapter_name(adapter),
150*3833Sxw161283 			 G_MC3_PARITY_ERR(cause));
151*3833Sxw161283 	}
152*3833Sxw161283 
153*3833Sxw161283 	if (cause & F_MC3_ADDR_ERR) {
154*3833Sxw161283 		mc3->intr_cnt.addr_err++;
155*3833Sxw161283 		CH_ALERT("%s: MC3 address error\n", adapter_name(adapter));
156*3833Sxw161283 	}
157*3833Sxw161283 
158*3833Sxw161283 	if (cause & MC3_INTR_FATAL)
159*3833Sxw161283 		t1_fatal_err(adapter);
160*3833Sxw161283 
161*3833Sxw161283 	if (t1_is_T1B(adapter)) {
162*3833Sxw161283 		/*
163*3833Sxw161283 		 * Workaround for T1B bug: we must write to enable register to
164*3833Sxw161283 		 * clear interrupts.
165*3833Sxw161283 		 */
166*3833Sxw161283 		t1_write_reg_4(adapter, A_MC3_INT_ENABLE, cause);
167*3833Sxw161283 		/* restore enable */
168*3833Sxw161283 		t1_write_reg_4(adapter, A_MC3_INT_ENABLE, MC3_INTR_MASK);
169*3833Sxw161283 	} else
170*3833Sxw161283 		t1_write_reg_4(adapter, cause_reg, cause);
171*3833Sxw161283 
172*3833Sxw161283 	return 0;
173*3833Sxw161283 }
174*3833Sxw161283 
175*3833Sxw161283 #define is_MC3A(adapter) (!t1_is_T1B(adapter))
176*3833Sxw161283 
177*3833Sxw161283 /*
178*3833Sxw161283  * Write a value to a register and check that the write completed.  These
179*3833Sxw161283  * writes normally complete in a cycle or two, so one read should suffice.
180*3833Sxw161283  * The very first read exists to flush the posted write to the device.
181*3833Sxw161283  */
wrreg_wait(adapter_t * adapter,unsigned int addr,u32 val)182*3833Sxw161283 static int wrreg_wait(adapter_t *adapter, unsigned int addr, u32 val)
183*3833Sxw161283 {
184*3833Sxw161283 	t1_write_reg_4(adapter,	addr, val);
185*3833Sxw161283 	val = t1_read_reg_4(adapter, addr);                   /* flush */
186*3833Sxw161283 	if (!(t1_read_reg_4(adapter, addr) & F_BUSY))
187*3833Sxw161283 		return 0;
188*3833Sxw161283 	CH_ERR("%s: write to MC3 register 0x%x timed out\n",
189*3833Sxw161283 	       adapter_name(adapter), addr);
190*3833Sxw161283 	return -EIO;
191*3833Sxw161283 }
192*3833Sxw161283 
193*3833Sxw161283 #define MC3_DLL_DONE (F_MASTER_DLL_LOCKED | F_MASTER_DLL_MAX_TAP_COUNT)
194*3833Sxw161283 
t1_mc3_init(struct pemc3 * mc3,unsigned int mc3_clock)195*3833Sxw161283 int t1_mc3_init(struct pemc3 *mc3, unsigned int mc3_clock)
196*3833Sxw161283 {
197*3833Sxw161283 	u32 val;
198*3833Sxw161283 	unsigned int width, fast_asic, attempts;
199*3833Sxw161283 	adapter_t *adapter = mc3->adapter;
200*3833Sxw161283 
201*3833Sxw161283 	/* Check to see if ASIC is running in slow mode. */
202*3833Sxw161283 	val = t1_read_reg_4(adapter, A_MC3_CFG);
203*3833Sxw161283 	width = is_MC3A(adapter) ? G_MC3_WIDTH(val) : 0;
204*3833Sxw161283 	fast_asic = t1_is_asic(adapter) && !(val & F_MC3_SLOW);
205*3833Sxw161283 
206*3833Sxw161283 	val &= ~(V_MC3_BANK_CYCLE(M_MC3_BANK_CYCLE) |
207*3833Sxw161283 		 V_REFRESH_CYCLE(M_REFRESH_CYCLE) |
208*3833Sxw161283 		 V_PRECHARGE_CYCLE(M_PRECHARGE_CYCLE) |
209*3833Sxw161283 		 F_ACTIVE_TO_READ_WRITE_DELAY |
210*3833Sxw161283 		 V_ACTIVE_TO_PRECHARGE_DELAY(M_ACTIVE_TO_PRECHARGE_DELAY) |
211*3833Sxw161283 		 V_WRITE_RECOVERY_DELAY(M_WRITE_RECOVERY_DELAY));
212*3833Sxw161283 
213*3833Sxw161283 	if (mc3_clock <= 100000000)
214*3833Sxw161283 		val |= V_MC3_BANK_CYCLE(7) | V_REFRESH_CYCLE(4) |
215*3833Sxw161283 			V_PRECHARGE_CYCLE(2) | V_ACTIVE_TO_PRECHARGE_DELAY(5) |
216*3833Sxw161283 			V_WRITE_RECOVERY_DELAY(2);
217*3833Sxw161283 	else if (mc3_clock <= 133000000)
218*3833Sxw161283 		val |= V_MC3_BANK_CYCLE(9) | V_REFRESH_CYCLE(5) |
219*3833Sxw161283 			V_PRECHARGE_CYCLE(3) | F_ACTIVE_TO_READ_WRITE_DELAY |
220*3833Sxw161283 			V_ACTIVE_TO_PRECHARGE_DELAY(6) |
221*3833Sxw161283 			V_WRITE_RECOVERY_DELAY(2);
222*3833Sxw161283 	else
223*3833Sxw161283 		val |= V_MC3_BANK_CYCLE(0xA) | V_REFRESH_CYCLE(6) |
224*3833Sxw161283 			V_PRECHARGE_CYCLE(3) | F_ACTIVE_TO_READ_WRITE_DELAY |
225*3833Sxw161283 			V_ACTIVE_TO_PRECHARGE_DELAY(7) |
226*3833Sxw161283 			V_WRITE_RECOVERY_DELAY(3);
227*3833Sxw161283 	t1_write_reg_4(adapter, A_MC3_CFG, val);
228*3833Sxw161283 
229*3833Sxw161283 	val = t1_read_reg_4(adapter, A_MC3_CFG);
230*3833Sxw161283 	t1_write_reg_4(adapter, A_MC3_CFG, val | F_CLK_ENABLE);
231*3833Sxw161283 	val = t1_read_reg_4(adapter, A_MC3_CFG);                 /* flush */
232*3833Sxw161283 
233*3833Sxw161283 	if (fast_asic) {                                     /* setup DLLs */
234*3833Sxw161283 		val = t1_read_reg_4(adapter, A_MC3_STROBE);
235*3833Sxw161283 		if (is_MC3A(adapter)) {
236*3833Sxw161283 			t1_write_reg_4(adapter, A_MC3_STROBE,
237*3833Sxw161283 				       val & ~F_SLAVE_DLL_RESET);
238*3833Sxw161283 
239*3833Sxw161283 			/* Wait for slave DLLs to lock */
240*3833Sxw161283 			DELAY_US(2 * 512 / (mc3_clock / 1000000) + 1);
241*3833Sxw161283 		} else {
242*3833Sxw161283 			/* Initialize the master DLL and slave delay lines. */
243*3833Sxw161283 			t1_write_reg_4(adapter, A_MC3_STROBE,
244*3833Sxw161283 				       val & ~F_MASTER_DLL_RESET);
245*3833Sxw161283 
246*3833Sxw161283 			/* Wait for the master DLL to lock. */
247*3833Sxw161283 			attempts = 100;
248*3833Sxw161283 			do {
249*3833Sxw161283 				DELAY_US(1);
250*3833Sxw161283 				val = t1_read_reg_4(adapter, A_MC3_STROBE);
251*3833Sxw161283 			} while (!(val & MC3_DLL_DONE) && --attempts);
252*3833Sxw161283 			if (!(val & MC3_DLL_DONE)) {
253*3833Sxw161283 				CH_ERR("%s: MC3 DLL lock failed\n",
254*3833Sxw161283 				       adapter_name(adapter));
255*3833Sxw161283 				goto out_fail;
256*3833Sxw161283 			}
257*3833Sxw161283 		}
258*3833Sxw161283 	}
259*3833Sxw161283 
260*3833Sxw161283 	/* Initiate a precharge and wait for the precharge to complete. */
261*3833Sxw161283 	if (wrreg_wait(adapter, A_MC3_PRECHARG, 0))
262*3833Sxw161283 		goto out_fail;
263*3833Sxw161283 
264*3833Sxw161283 	/* Set the SDRAM output drive strength and enable DLLs if needed */
265*3833Sxw161283 	if (wrreg_wait(adapter, A_MC3_EXT_MODE, fast_asic ? 0 : 1))
266*3833Sxw161283 		goto out_fail;
267*3833Sxw161283 
268*3833Sxw161283 	/* Specify the SDRAM operating parameters. */
269*3833Sxw161283 	if (wrreg_wait(adapter, A_MC3_MODE, fast_asic ? 0x161 : 0x21))
270*3833Sxw161283 		goto out_fail;
271*3833Sxw161283 
272*3833Sxw161283 	/* Initiate a precharge and wait for the precharge to complete. */
273*3833Sxw161283 	if (wrreg_wait(adapter, A_MC3_PRECHARG, 0))
274*3833Sxw161283 		goto out_fail;
275*3833Sxw161283 
276*3833Sxw161283 	/* Initiate an immediate refresh and wait for the write to complete. */
277*3833Sxw161283 	val = t1_read_reg_4(adapter, A_MC3_REFRESH);
278*3833Sxw161283 	if (wrreg_wait(adapter, A_MC3_REFRESH, val & ~F_REFRESH_ENABLE))
279*3833Sxw161283 		goto out_fail;
280*3833Sxw161283 
281*3833Sxw161283 	/* 2nd immediate refresh as before */
282*3833Sxw161283 	if (wrreg_wait(adapter, A_MC3_REFRESH, val & ~F_REFRESH_ENABLE))
283*3833Sxw161283 		goto out_fail;
284*3833Sxw161283 
285*3833Sxw161283 	/* Specify the SDRAM operating parameters. */
286*3833Sxw161283 	if (wrreg_wait(adapter, A_MC3_MODE, fast_asic ? 0x61 : 0x21))
287*3833Sxw161283 		goto out_fail;
288*3833Sxw161283 
289*3833Sxw161283 	/* Convert to KHz first to avoid 64-bit division. */
290*3833Sxw161283 	mc3_clock /=  1000;                            /* Hz->KHz */
291*3833Sxw161283 	mc3_clock = mc3_clock * 7812 + mc3_clock / 2;  /* ns */
292*3833Sxw161283 	mc3_clock /= 1000000;                          /* KHz->MHz, ns->us */
293*3833Sxw161283 
294*3833Sxw161283 	/* Enable periodic refresh. */
295*3833Sxw161283 	t1_write_reg_4(adapter, A_MC3_REFRESH,
296*3833Sxw161283 		       F_REFRESH_ENABLE | V_REFRESH_DIVISOR(mc3_clock));
297*3833Sxw161283 	(void) t1_read_reg_4(adapter, A_MC3_REFRESH);    /* flush */
298*3833Sxw161283 
299*3833Sxw161283 	t1_write_reg_4(adapter, A_MC3_ECC_CNTL,
300*3833Sxw161283 		       F_ECC_GENERATION_ENABLE | F_ECC_CHECK_ENABLE);
301*3833Sxw161283 
302*3833Sxw161283 	/* Use the BIST engine to clear MC3 memory and initialize ECC. */
303*3833Sxw161283 	t1_write_reg_4(adapter, A_MC3_BIST_ADDR_BEG, 0);
304*3833Sxw161283 	t1_write_reg_4(adapter, A_MC3_BIST_ADDR_END, (mc3->size << width) - 1);
305*3833Sxw161283 	t1_write_reg_4(adapter, A_MC3_BIST_DATA, 0);
306*3833Sxw161283 	t1_write_reg_4(adapter, A_MC3_BIST_OP, V_OP(1) | 0x1f0);
307*3833Sxw161283 	(void) t1_read_reg_4(adapter, A_MC3_BIST_OP);              /* flush */
308*3833Sxw161283 
309*3833Sxw161283 	attempts = 100;
310*3833Sxw161283 	do {
311*3833Sxw161283 		DELAY_MS(100);
312*3833Sxw161283 		val = t1_read_reg_4(adapter, A_MC3_BIST_OP);
313*3833Sxw161283 	} while ((val & F_BUSY) && --attempts);
314*3833Sxw161283 	if (val & F_BUSY) {
315*3833Sxw161283 		CH_ERR("%s: MC3 BIST timed out\n", adapter_name(adapter));
316*3833Sxw161283 		goto out_fail;
317*3833Sxw161283 	}
318*3833Sxw161283 
319*3833Sxw161283 	/* Enable normal memory accesses. */
320*3833Sxw161283 	val = t1_read_reg_4(adapter, A_MC3_CFG);
321*3833Sxw161283 	t1_write_reg_4(adapter, A_MC3_CFG, val | F_READY);
322*3833Sxw161283 	return 0;
323*3833Sxw161283 
324*3833Sxw161283  out_fail:
325*3833Sxw161283 	return -1;
326*3833Sxw161283 }
327*3833Sxw161283 
mc3_calc_size(const adapter_t * adapter,u32 cfg)328*3833Sxw161283 static unsigned int __devinit mc3_calc_size(const adapter_t *adapter, u32 cfg)
329*3833Sxw161283 {
330*3833Sxw161283 	unsigned int banks = !!(cfg & F_BANKS) + 1;
331*3833Sxw161283 	unsigned int org = !!(cfg & F_ORGANIZATION) + 1;
332*3833Sxw161283 	unsigned int density = G_DENSITY(cfg);
333*3833Sxw161283 
334*3833Sxw161283 	unsigned int capacity_in_MB = is_MC3A(adapter) ?
335*3833Sxw161283 		((256 << density) * banks) / (org << G_MC3_WIDTH(cfg)) :
336*3833Sxw161283 		((128 << density) * (16 / org) * banks) / 8;
337*3833Sxw161283 
338*3833Sxw161283 	return capacity_in_MB * 1024 * 1024;
339*3833Sxw161283 }
340*3833Sxw161283 
t1_mc3_create(adapter_t * adapter)341*3833Sxw161283 struct pemc3 * __devinit t1_mc3_create(adapter_t *adapter)
342*3833Sxw161283 {
343*3833Sxw161283 	struct pemc3 *mc3 = t1_os_malloc_wait_zero(sizeof(*mc3));
344*3833Sxw161283 
345*3833Sxw161283 	if (mc3) {
346*3833Sxw161283 		mc3->adapter = adapter;
347*3833Sxw161283 		mc3->size = mc3_calc_size(adapter,
348*3833Sxw161283 					  t1_read_reg_4(adapter, A_MC3_CFG));
349*3833Sxw161283 	}
350*3833Sxw161283 	return mc3;
351*3833Sxw161283 }
352*3833Sxw161283 
t1_mc3_destroy(struct pemc3 * mc3)353*3833Sxw161283 void t1_mc3_destroy(struct pemc3 *mc3)
354*3833Sxw161283 {
355*3833Sxw161283 	t1_os_free((void *)mc3, sizeof(*mc3));
356*3833Sxw161283 }
357*3833Sxw161283 
t1_mc3_get_size(struct pemc3 * mc3)358*3833Sxw161283 unsigned int t1_mc3_get_size(struct pemc3 *mc3)
359*3833Sxw161283 {
360*3833Sxw161283 	return mc3->size;
361*3833Sxw161283 }
362*3833Sxw161283 
t1_mc3_get_intr_counts(struct pemc3 * mc3)363*3833Sxw161283 const struct pemc3_intr_counts *t1_mc3_get_intr_counts(struct pemc3 *mc3)
364*3833Sxw161283 {
365*3833Sxw161283 	return &mc3->intr_cnt;
366*3833Sxw161283 }
367