xref: /onnv-gate/usr/src/uts/common/io/chxge/com/espi.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"	/* espi.c */
27*3833Sxw161283 
28*3833Sxw161283 #include "common.h"
29*3833Sxw161283 #include "regs.h"
30*3833Sxw161283 #include "espi.h"
31*3833Sxw161283 
32*3833Sxw161283 struct peespi {
33*3833Sxw161283 	adapter_t *adapter;
34*3833Sxw161283 	struct espi_intr_counts intr_cnt;
35*3833Sxw161283 	u32 misc_ctrl;
36*3833Sxw161283 	SPINLOCK lock;
37*3833Sxw161283 };
38*3833Sxw161283 
39*3833Sxw161283 #define ESPI_INTR_MASK (F_DIP4ERR | F_RXDROP | F_TXDROP | F_RXOVERFLOW | \
40*3833Sxw161283 			F_RAMPARITYERR | F_DIP2PARITYERR)
41*3833Sxw161283 #define MON_MASK  (V_MONITORED_PORT_NUM(3) | F_MONITORED_DIRECTION \
42*3833Sxw161283 			| F_MONITORED_INTERFACE)
43*3833Sxw161283 
44*3833Sxw161283 #define TRICN_CNFG 14
45*3833Sxw161283 #define TRICN_CMD_READ  0x11
46*3833Sxw161283 #define TRICN_CMD_WRITE 0x21
47*3833Sxw161283 #define TRICN_CMD_ATTEMPTS 10
48*3833Sxw161283 
tricn_write(adapter_t * adapter,int bundle_addr,int module_addr,int ch_addr,int reg_offset,u32 wr_data)49*3833Sxw161283 static int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr,
50*3833Sxw161283 		       int ch_addr, int reg_offset, u32 wr_data)
51*3833Sxw161283 {
52*3833Sxw161283 	int busy;
53*3833Sxw161283 
54*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_CMD_ADDR, V_WRITE_DATA(wr_data) |
55*3833Sxw161283 		       V_REGISTER_OFFSET(reg_offset) |
56*3833Sxw161283 		       V_CHANNEL_ADDR(ch_addr) | V_MODULE_ADDR(module_addr) |
57*3833Sxw161283 		       V_BUNDLE_ADDR(bundle_addr) |
58*3833Sxw161283 		       V_SPI4_COMMAND(TRICN_CMD_WRITE));
59*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_GOSTAT, 0);
60*3833Sxw161283 
61*3833Sxw161283 	busy = t1_wait_op_done(adapter, A_ESPI_GOSTAT, F_ESPI_CMD_BUSY, 0,
62*3833Sxw161283 			TRICN_CMD_ATTEMPTS, 0);
63*3833Sxw161283 
64*3833Sxw161283 	if (busy)
65*3833Sxw161283 		CH_ERR("%s: TRICN write timed out\n", adapter_name(adapter));
66*3833Sxw161283 
67*3833Sxw161283 	return busy;
68*3833Sxw161283 }
69*3833Sxw161283 
70*3833Sxw161283 #if 0
71*3833Sxw161283 static int tricn_read(adapter_t *adapter, int bundle_addr, int module_addr,
72*3833Sxw161283 		      int ch_addr, int reg_offset, u8 *rd_data)
73*3833Sxw161283 {
74*3833Sxw161283 	int busy, attempts = TRICN_CMD_ATTEMPTS;
75*3833Sxw161283 	u32 status;
76*3833Sxw161283 
77*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_CMD_ADDR,
78*3833Sxw161283 		       V_REGISTER_OFFSET(reg_offset) |
79*3833Sxw161283 		       V_CHANNEL_ADDR(ch_addr) | V_MODULE_ADDR(module_addr) |
80*3833Sxw161283 		       V_BUNDLE_ADDR(bundle_addr) |
81*3833Sxw161283 		       V_SPI4_COMMAND(TRICN_CMD_READ));
82*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_GOSTAT, 0);
83*3833Sxw161283 
84*3833Sxw161283 	do {
85*3833Sxw161283 		status = t1_read_reg_4(adapter, A_ESPI_GOSTAT);
86*3833Sxw161283 		busy = status & F_ESPI_CMD_BUSY;
87*3833Sxw161283 	} while (busy && --attempts);
88*3833Sxw161283 
89*3833Sxw161283 	if (busy)
90*3833Sxw161283 		CH_ERR("%s: TRICN read timed out\n", adapter_name(adapter));
91*3833Sxw161283 	else
92*3833Sxw161283 		*rd_data = G_READ_DATA(status);
93*3833Sxw161283 	return busy;
94*3833Sxw161283 }
95*3833Sxw161283 #endif
96*3833Sxw161283 
tricn_init(adapter_t * adapter)97*3833Sxw161283 static int tricn_init(adapter_t *adapter)
98*3833Sxw161283 {
99*3833Sxw161283 	int i, sme = 1;
100*3833Sxw161283 
101*3833Sxw161283 	if (!(t1_read_reg_4(adapter, A_ESPI_RX_RESET) & F_RX_CLK_STATUS)) {
102*3833Sxw161283 		CH_ERR("%s: ESPI clock not ready\n", adapter_name(adapter));
103*3833Sxw161283 		return (-1);
104*3833Sxw161283 	 }
105*3833Sxw161283 
106*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_RX_RESET, F_ESPI_RX_CORE_RST);
107*3833Sxw161283 
108*3833Sxw161283 	if (sme) {
109*3833Sxw161283 		(void) tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
110*3833Sxw161283 		(void) tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
111*3833Sxw161283 		(void) tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
112*3833Sxw161283 	}
113*3833Sxw161283 	for (i=1; i<= 8; i++) (void) tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
114*3833Sxw161283 	for (i=1; i<= 2; i++) (void) tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
115*3833Sxw161283 	for (i=1; i<= 3; i++) (void) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
116*3833Sxw161283 	(void) tricn_write(adapter, 0, 2, 4, TRICN_CNFG, 0xf1);
117*3833Sxw161283 	(void) tricn_write(adapter, 0, 2, 5, TRICN_CNFG, 0xe1);
118*3833Sxw161283 	(void) tricn_write(adapter, 0, 2, 6, TRICN_CNFG, 0xf1);
119*3833Sxw161283 	(void) tricn_write(adapter, 0, 2, 7, TRICN_CNFG, 0x80);
120*3833Sxw161283 	(void) tricn_write(adapter, 0, 2, 8, TRICN_CNFG, 0xf1);
121*3833Sxw161283 
122*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_RX_RESET, F_ESPI_RX_CORE_RST | F_ESPI_RX_LNK_RST);
123*3833Sxw161283 
124*3833Sxw161283 	return 0;
125*3833Sxw161283 }
126*3833Sxw161283 
t1_espi_intr_enable(struct peespi * espi)127*3833Sxw161283 void t1_espi_intr_enable(struct peespi *espi)
128*3833Sxw161283 {
129*3833Sxw161283 	u32 enable, pl_intr = t1_read_reg_4(espi->adapter, A_PL_ENABLE);
130*3833Sxw161283 
131*3833Sxw161283 	/*
132*3833Sxw161283 	 * Cannot enable ESPI interrupts on T1B because HW asserts the
133*3833Sxw161283 	 * interrupt incorrectly, namely the driver gets ESPI interrupts
134*3833Sxw161283 	 * but no data is actually dropped (can verify this reading the ESPI
135*3833Sxw161283 	 * drop registers).  Also, once the ESPI interrupt is asserted it
136*3833Sxw161283 	 * cannot be cleared (HW bug).
137*3833Sxw161283 	 */
138*3833Sxw161283 	enable = t1_is_T1B(espi->adapter) ? 0 : ESPI_INTR_MASK;
139*3833Sxw161283 	t1_write_reg_4(espi->adapter, A_ESPI_INTR_ENABLE, enable);
140*3833Sxw161283 	t1_write_reg_4(espi->adapter, A_PL_ENABLE, pl_intr | F_PL_INTR_ESPI);
141*3833Sxw161283 }
142*3833Sxw161283 
t1_espi_intr_clear(struct peespi * espi)143*3833Sxw161283 void t1_espi_intr_clear(struct peespi *espi)
144*3833Sxw161283 {
145*3833Sxw161283 	(void) t1_read_reg_4(espi->adapter, A_ESPI_DIP2_ERR_COUNT);
146*3833Sxw161283 	t1_write_reg_4(espi->adapter, A_ESPI_INTR_STATUS, 0xffffffff);
147*3833Sxw161283 	t1_write_reg_4(espi->adapter, A_PL_CAUSE, F_PL_INTR_ESPI);
148*3833Sxw161283 }
149*3833Sxw161283 
t1_espi_intr_disable(struct peespi * espi)150*3833Sxw161283 void t1_espi_intr_disable(struct peespi *espi)
151*3833Sxw161283 {
152*3833Sxw161283 	u32 pl_intr = t1_read_reg_4(espi->adapter, A_PL_ENABLE);
153*3833Sxw161283 
154*3833Sxw161283 	t1_write_reg_4(espi->adapter, A_ESPI_INTR_ENABLE, 0);
155*3833Sxw161283 	t1_write_reg_4(espi->adapter, A_PL_ENABLE, pl_intr & ~F_PL_INTR_ESPI);
156*3833Sxw161283 }
157*3833Sxw161283 
t1_espi_intr_handler(struct peespi * espi)158*3833Sxw161283 int t1_espi_intr_handler(struct peespi *espi)
159*3833Sxw161283 {
160*3833Sxw161283 	u32 status = t1_read_reg_4(espi->adapter, A_ESPI_INTR_STATUS);
161*3833Sxw161283 
162*3833Sxw161283 	if (status & F_DIP4ERR)
163*3833Sxw161283 		espi->intr_cnt.DIP4_err++;
164*3833Sxw161283 	if (status & F_RXDROP)
165*3833Sxw161283 		espi->intr_cnt.rx_drops++;
166*3833Sxw161283 	if (status & F_TXDROP)
167*3833Sxw161283 		espi->intr_cnt.tx_drops++;
168*3833Sxw161283 	if (status & F_RXOVERFLOW)
169*3833Sxw161283 		espi->intr_cnt.rx_ovflw++;
170*3833Sxw161283 	if (status & F_RAMPARITYERR)
171*3833Sxw161283 		espi->intr_cnt.parity_err++;
172*3833Sxw161283 	if (status & F_DIP2PARITYERR) {
173*3833Sxw161283 		espi->intr_cnt.DIP2_parity_err++;
174*3833Sxw161283 		(void) t1_read_reg_4(espi->adapter, A_ESPI_DIP2_ERR_COUNT);
175*3833Sxw161283 	 }
176*3833Sxw161283 
177*3833Sxw161283 	/*
178*3833Sxw161283 	 * For T1B we need to write 1 to clear ESPI interrupts.  For T2+ we
179*3833Sxw161283 	 * write the status as is.
180*3833Sxw161283 	 */
181*3833Sxw161283 	if (status && t1_is_T1B(espi->adapter))
182*3833Sxw161283 		status = 1;
183*3833Sxw161283 	t1_write_reg_4(espi->adapter, A_ESPI_INTR_STATUS, status);
184*3833Sxw161283 	return 0;
185*3833Sxw161283 }
186*3833Sxw161283 
t1_espi_get_intr_counts(struct peespi * espi)187*3833Sxw161283 const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi)
188*3833Sxw161283 {
189*3833Sxw161283 	return &espi->intr_cnt;
190*3833Sxw161283 }
191*3833Sxw161283 
espi_setup_for_pm3393(adapter_t * adapter)192*3833Sxw161283 static void espi_setup_for_pm3393(adapter_t *adapter)
193*3833Sxw161283 {
194*3833Sxw161283 	u32 wmark = t1_is_T1B(adapter) ? 0x4000 : 0x3200;
195*3833Sxw161283 
196*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN0, 0x1f4);
197*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN1, 0x1f4);
198*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN2, 0x1f4);
199*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN3, 0x1f4);
200*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK, 0x100);
201*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK, wmark);
202*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_CALENDAR_LENGTH, 3);
203*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_TRAIN, 0x08000008);
204*3833Sxw161283 	t1_write_reg_4(adapter, A_PORT_CONFIG,
205*3833Sxw161283 		       V_RX_NPORTS(1) | V_TX_NPORTS(1));
206*3833Sxw161283 }
207*3833Sxw161283 
espi_setup_for_vsc7321(adapter_t * adapter)208*3833Sxw161283 static void espi_setup_for_vsc7321(adapter_t *adapter)
209*3833Sxw161283 {
210*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_COUGAR
211*3833Sxw161283 	u32 wmark = t1_is_T1B(adapter) ? 0x4000 : 0x3200;
212*3833Sxw161283 
213*3833Sxw161283         t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN0, 0x1f4);
214*3833Sxw161283         t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN1, 0x1f4);
215*3833Sxw161283         t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN2, 0x1f4);
216*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN3, 0x1f4);
217*3833Sxw161283         t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK, 0x100);
218*3833Sxw161283         t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK, wmark);
219*3833Sxw161283         t1_write_reg_4(adapter, A_ESPI_CALENDAR_LENGTH, 3);
220*3833Sxw161283  	t1_write_reg_4(adapter, A_PORT_CONFIG,
221*3833Sxw161283 		       V_RX_NPORTS(1) | V_TX_NPORTS(1));
222*3833Sxw161283 #else
223*3833Sxw161283         t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN0, 0x1f4);
224*3833Sxw161283         t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN1, 0x1f401f4);
225*3833Sxw161283         t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN2, 0x1f4);
226*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK, 0xa00);
227*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK, 0x1ff);
228*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_CALENDAR_LENGTH, 1);
229*3833Sxw161283         t1_write_reg_4(adapter, A_PORT_CONFIG,
230*3833Sxw161283                        V_RX_NPORTS(4) | V_TX_NPORTS(4));
231*3833Sxw161283 #endif
232*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_TRAIN, 0x08000008);
233*3833Sxw161283 }
234*3833Sxw161283 
235*3833Sxw161283 /*
236*3833Sxw161283  * Note that T1B requires at least 2 ports for IXF1010 due to a HW bug.
237*3833Sxw161283  */
espi_setup_for_ixf1010(adapter_t * adapter,int nports)238*3833Sxw161283 static void espi_setup_for_ixf1010(adapter_t *adapter, int nports)
239*3833Sxw161283 {
240*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_CALENDAR_LENGTH, 1);
241*3833Sxw161283 	if (nports == 4) {
242*3833Sxw161283 		if (is_T2(adapter)) {
243*3833Sxw161283 			t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK,
244*3833Sxw161283 				0xf00);
245*3833Sxw161283 			t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK,
246*3833Sxw161283 				0x3c0);
247*3833Sxw161283 		} else {
248*3833Sxw161283 			t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK,
249*3833Sxw161283 				0x7ff);
250*3833Sxw161283 			t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK,
251*3833Sxw161283 				0x1ff);
252*3833Sxw161283 		}
253*3833Sxw161283 	} else {
254*3833Sxw161283 		t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK,
255*3833Sxw161283 			       0x1fff);
256*3833Sxw161283 		t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK,
257*3833Sxw161283 			       0x7ff);
258*3833Sxw161283 	}
259*3833Sxw161283 	t1_write_reg_4(adapter, A_PORT_CONFIG,
260*3833Sxw161283 		       V_RX_NPORTS(nports) | V_TX_NPORTS(nports));
261*3833Sxw161283 }
262*3833Sxw161283 
t1_espi_init(struct peespi * espi,int mac_type,int nports)263*3833Sxw161283 int t1_espi_init(struct peespi *espi, int mac_type, int nports)
264*3833Sxw161283 {
265*3833Sxw161283 	u32 status_enable_extra = 0;
266*3833Sxw161283 	adapter_t *adapter = espi->adapter;
267*3833Sxw161283 
268*3833Sxw161283 	/* Disable ESPI training.  MACs that can handle it enable it below. */
269*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_TRAIN, 0);
270*3833Sxw161283 
271*3833Sxw161283 	if (is_T2(adapter)) {
272*3833Sxw161283 		t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL,
273*3833Sxw161283 			       V_OUT_OF_SYNC_COUNT(4) |
274*3833Sxw161283 			       V_DIP2_PARITY_ERR_THRES(3) | V_DIP4_THRES(1));
275*3833Sxw161283         	t1_write_reg_4(adapter, A_ESPI_MAXBURST1_MAXBURST2,
276*3833Sxw161283 			nports == 4 ? 0x200040 : 0x1000080);
277*3833Sxw161283 	} else
278*3833Sxw161283 		t1_write_reg_4(adapter, A_ESPI_MAXBURST1_MAXBURST2, 0x800100);
279*3833Sxw161283 
280*3833Sxw161283 	if (mac_type == CHBT_MAC_PM3393)
281*3833Sxw161283 		espi_setup_for_pm3393(adapter);
282*3833Sxw161283 	else if (mac_type == CHBT_MAC_VSC7321)
283*3833Sxw161283 		espi_setup_for_vsc7321(adapter);
284*3833Sxw161283 	else if (mac_type == CHBT_MAC_IXF1010) {
285*3833Sxw161283 		status_enable_extra = F_INTEL1010MODE;
286*3833Sxw161283 		espi_setup_for_ixf1010(adapter, nports);
287*3833Sxw161283 	} else
288*3833Sxw161283 		return -1;
289*3833Sxw161283 
290*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_FIFO_STATUS_ENABLE,
291*3833Sxw161283 		       status_enable_extra | F_RXSTATUSENABLE);
292*3833Sxw161283 
293*3833Sxw161283 	if (is_T2(adapter)) {
294*3833Sxw161283 		(void) tricn_init(adapter);
295*3833Sxw161283 		/*
296*3833Sxw161283 		 * Always position the control at the 1st port egress IN
297*3833Sxw161283 		 * (sop,eop) counter to reduce PIOs for T/N210 workaround.
298*3833Sxw161283 		 */
299*3833Sxw161283 		espi->misc_ctrl = t1_read_reg_4(adapter, A_ESPI_MISC_CONTROL);
300*3833Sxw161283 		espi->misc_ctrl &= ~MON_MASK;
301*3833Sxw161283 		espi->misc_ctrl |= F_MONITORED_DIRECTION;
302*3833Sxw161283 		if (adapter->params.nports == 1)
303*3833Sxw161283 			espi->misc_ctrl |= F_MONITORED_INTERFACE;
304*3833Sxw161283 		t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL, espi->misc_ctrl);
305*3833Sxw161283 		SPIN_LOCK_INIT(espi->lock);
306*3833Sxw161283 	}
307*3833Sxw161283 
308*3833Sxw161283 	return 0;
309*3833Sxw161283 }
310*3833Sxw161283 
t1_espi_destroy(struct peespi * espi)311*3833Sxw161283 void t1_espi_destroy(struct peespi *espi)
312*3833Sxw161283 {
313*3833Sxw161283 	if (is_T2(espi->adapter)) {
314*3833Sxw161283 		SPIN_LOCK_DESTROY(espi->lock);
315*3833Sxw161283 	}
316*3833Sxw161283 	t1_os_free((void *)espi, sizeof(*espi));
317*3833Sxw161283 }
318*3833Sxw161283 
t1_espi_create(adapter_t * adapter)319*3833Sxw161283 struct peespi *t1_espi_create(adapter_t *adapter)
320*3833Sxw161283 {
321*3833Sxw161283 	struct peespi *espi = t1_os_malloc_wait_zero(sizeof(*espi));
322*3833Sxw161283 
323*3833Sxw161283 	if (espi)
324*3833Sxw161283 		espi->adapter = adapter;
325*3833Sxw161283 	return espi;
326*3833Sxw161283 }
327*3833Sxw161283 
t1_espi_set_misc_ctrl(adapter_t * adapter,u32 val)328*3833Sxw161283 void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
329*3833Sxw161283 {
330*3833Sxw161283 	struct peespi *espi = adapter->espi;
331*3833Sxw161283 
332*3833Sxw161283 	if (!is_T2(adapter))
333*3833Sxw161283 		return;
334*3833Sxw161283 	SPIN_LOCK(espi->lock);
335*3833Sxw161283 	espi->misc_ctrl = (val & ~MON_MASK) |
336*3833Sxw161283 		(espi->misc_ctrl & MON_MASK);
337*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL, espi->misc_ctrl);
338*3833Sxw161283 	SPIN_UNLOCK(espi->lock);
339*3833Sxw161283 }
340*3833Sxw161283 
t1_espi_get_mon(adapter_t * adapter,u32 addr,u8 wait)341*3833Sxw161283 u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait)
342*3833Sxw161283 {
343*3833Sxw161283 	struct peespi *espi = adapter->espi;
344*3833Sxw161283 	u32 sel;
345*3833Sxw161283 
346*3833Sxw161283 	if (!is_T2(adapter)) return 0;
347*3833Sxw161283 	sel = V_MONITORED_PORT_NUM((addr & 0x3c) >> 2);
348*3833Sxw161283 	if (!wait) {
349*3833Sxw161283 		if (!SPIN_TRYLOCK(espi->lock))
350*3833Sxw161283 			return 0;
351*3833Sxw161283         }
352*3833Sxw161283 	else
353*3833Sxw161283 		SPIN_LOCK(espi->lock);
354*3833Sxw161283 	if ((sel != (espi->misc_ctrl & MON_MASK))) {
355*3833Sxw161283 		t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL,
356*3833Sxw161283 			((espi->misc_ctrl & ~MON_MASK) | sel));
357*3833Sxw161283 		sel = t1_read_reg_4(adapter, A_ESPI_SCH_TOKEN3);
358*3833Sxw161283 		t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL,
359*3833Sxw161283 			espi->misc_ctrl);
360*3833Sxw161283         }
361*3833Sxw161283 	else
362*3833Sxw161283 		sel = t1_read_reg_4(adapter, A_ESPI_SCH_TOKEN3);
363*3833Sxw161283 	SPIN_UNLOCK(espi->lock);
364*3833Sxw161283 	return sel;
365*3833Sxw161283 }
366*3833Sxw161283 
367*3833Sxw161283 /*
368*3833Sxw161283  * This function is for T204 only.
369*3833Sxw161283  * compare with t1_espi_get_mon(), it reads espiInTxSop[0 ~ 3] in
370*3833Sxw161283  * one shot, since there is no per port counter on the out side.
371*3833Sxw161283  */
372*3833Sxw161283 int
t1_espi_get_mon_t204(adapter_t * adapter,u32 * valp,u8 wait)373*3833Sxw161283 t1_espi_get_mon_t204(adapter_t *adapter, u32 *valp, u8 wait)
374*3833Sxw161283 {
375*3833Sxw161283 	struct peespi *espi = adapter->espi;
376*3833Sxw161283 	u8 i, nport = (u8)adapter->params.nports;
377*3833Sxw161283 
378*3833Sxw161283 	if (!wait) {
379*3833Sxw161283 		if (!SPIN_TRYLOCK(espi->lock))
380*3833Sxw161283 			return -1;
381*3833Sxw161283 	} else
382*3833Sxw161283 		SPIN_LOCK(espi->lock);
383*3833Sxw161283 	if ((espi->misc_ctrl & MON_MASK) != F_MONITORED_DIRECTION ) {
384*3833Sxw161283 		espi->misc_ctrl = (espi->misc_ctrl & ~MON_MASK) |
385*3833Sxw161283 			F_MONITORED_DIRECTION;
386*3833Sxw161283 		t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL, espi->misc_ctrl);
387*3833Sxw161283 	}
388*3833Sxw161283 	for (i = 0 ; i < nport; i++, valp++) {
389*3833Sxw161283 		if (i) {
390*3833Sxw161283 			t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL,
391*3833Sxw161283 			(espi->misc_ctrl | V_MONITORED_PORT_NUM(i)));
392*3833Sxw161283 		}
393*3833Sxw161283 		*valp = t1_read_reg_4(adapter, A_ESPI_SCH_TOKEN3);
394*3833Sxw161283 	}
395*3833Sxw161283 
396*3833Sxw161283 	t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL, espi->misc_ctrl);
397*3833Sxw161283 
398*3833Sxw161283 	SPIN_UNLOCK(espi->lock);
399*3833Sxw161283 	return 0;
400*3833Sxw161283 }
401