xref: /freebsd/sys/dev/cxgb/common/cxgb_vsc7323.c (revision 0bb263df82e129f5f8c82da6deb55dfe10daa677)
1 
2 /**************************************************************************
3 
4 Copyright (c) 2007, Chelsio Inc.
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10  1. Redistributions of source code must retain the above copyright notice,
11     this list of conditions and the following disclaimer.
12 
13  2. Neither the name of the Chelsio Corporation nor the names of its
14     contributors may be used to endorse or promote products derived from
15     this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
28 
29 ***************************************************************************/
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #ifdef CONFIG_DEFINED
35 #include <common/cxgb_common.h>
36 #else
37 #include <dev/cxgb/common/cxgb_common.h>
38 #endif
39 
40 enum {
41 	ELMR_ADDR    = 0,
42 	ELMR_STAT    = 1,
43 	ELMR_DATA_LO = 2,
44 	ELMR_DATA_HI = 3,
45 
46 	ELMR_MDIO_ADDR = 10
47 };
48 
49 #define VSC_REG(block, subblock, reg) \
50 	((reg) | ((subblock) << 8) | ((block) << 12))
51 
52 int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n)
53 {
54 	int ret;
55 	const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
56 
57 	ELMR_LOCK(adap);
58 	ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
59 	for ( ; !ret && n; n--, vals++) {
60 		ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO,
61 				*vals & 0xffff);
62 		if (!ret)
63 			ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
64 					*vals >> 16);
65 	}
66 	ELMR_UNLOCK(adap);
67 	return ret;
68 }
69 
70 static int elmr_write(adapter_t *adap, int addr, u32 val)
71 {
72 	return t3_elmr_blk_write(adap, addr, &val, 1);
73 }
74 
75 int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n)
76 {
77 	int ret;
78 	unsigned int v;
79 	const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
80 
81 	ELMR_LOCK(adap);
82 
83 	ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
84 	if (ret)
85 		goto out;
86 	ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v);
87 	if (ret)
88 		goto out;
89 	if (v != 1) {
90 		ret = -ETIMEDOUT;
91 		goto out;
92 	}
93 
94 	for ( ; !ret && n; n--, vals++) {
95 		ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals);
96 		if (!ret) {
97 			ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
98 				       &v);
99 			*vals |= v << 16;
100 		}
101 	}
102 out:	ELMR_UNLOCK(adap);
103 	return ret;
104 }
105 
106 int t3_vsc7323_init(adapter_t *adap, int nports)
107 {
108 	static struct addr_val_pair sys_avp[] = {
109 		{ VSC_REG(7, 15, 0xf),  2 },
110 		{ VSC_REG(7, 15, 0x19), 0xd6 },
111 		{ VSC_REG(7, 15, 7),    0xc },
112 		{ VSC_REG(7, 1, 0),     0x220 },
113 	};
114 	static struct addr_val_pair fifo_avp[] = {
115 		{ VSC_REG(2, 0, 0x2f), 0 },
116 		{ VSC_REG(2, 0, 0xf),  0xa0010291 },
117 		{ VSC_REG(2, 1, 0x2f), 1 },
118 		{ VSC_REG(2, 1, 0xf),  0xa0026301 }
119 	};
120 	static struct addr_val_pair xg_avp[] = {
121 		{ VSC_REG(1, 10, 0),    0x600b },
122 		{ VSC_REG(1, 10, 2),    0x4000 },
123 		{ VSC_REG(1, 10, 5),    0x65 },
124 		{ VSC_REG(1, 10, 7),    3 },
125 		{ VSC_REG(1, 10, 0x23), 0x800007bf },
126 		{ VSC_REG(1, 10, 0x24), 4 }
127 	};
128 
129 	int i, ret, ing_step, egr_step, ing_bot, egr_bot;
130 
131 	for (i = 0; i < ARRAY_SIZE(sys_avp); i++)
132 		if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr,
133 			    &sys_avp[i].val, 1)))
134 			return ret;
135 
136 
137 	ing_step = 0xc0 / nports;
138 	egr_step = 0x40 / nports;
139 	ing_bot = egr_bot = 0;
140 //	ing_wm = ing_step * 64;
141 //	egr_wm = egr_step * 64;
142 
143 	/* {ING,EGR}_CONTROL.CLR = 1 here */
144 	for (i = 0; i < nports; i++)
145 		if ((ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i),
146 				((ing_bot + ing_step) << 16) | ing_bot)) ||
147 		    (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 0)) ||
148 		    (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i),
149 				((egr_bot + egr_step) << 16) | egr_bot)) ||
150 		    (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i),
151 				0x2000280)) ||
152 		    (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0)))
153 			return ret;
154 
155 
156 	for (i = 0; i < ARRAY_SIZE(fifo_avp); i++)
157 		if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr,
158 			    &fifo_avp[i].val, 1)))
159                         return ret;
160 
161 	for (i = 0; i < ARRAY_SIZE(xg_avp); i++)
162 		if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr,
163 					     &xg_avp[i].val, 1)))
164 			return ret;
165 
166 	for (i = 0; i < nports; i++)
167 		if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) ||
168 		    (ret = elmr_write(adap, VSC_REG(1, i, 5),
169 				 (i << 12) | 0x63)) ||
170 		    (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) ||
171 		    (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)))
172 			return ret;
173 	return ret;
174 }
175 
176 int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
177 {
178 	int mode, clk, r;
179 
180 	if (speed >= 0) {
181 		if (speed == SPEED_10)
182 			mode = clk = 1;
183 		else if (speed == SPEED_100)
184 			mode = 1, clk = 2;
185 		else if (speed == SPEED_1000)
186 			mode = clk = 3;
187 		else
188 			return -EINVAL;
189 
190 		if ((r = elmr_write(adap, VSC_REG(1, port, 0),
191 				    0xa590 | (mode << 2))) ||
192 		    (r = elmr_write(adap, VSC_REG(1, port, 0xb),
193 				    0x91 | (clk << 1))) ||
194 		    (r = elmr_write(adap, VSC_REG(1, port, 0xb),
195 				    0x90 | (clk << 1))) ||
196 		    (r = elmr_write(adap, VSC_REG(1, port, 0),
197 				    0xa593 | (mode << 2))))
198 			return r;
199 	}
200 
201 	r = (fc & PAUSE_RX) ? 0x6ffff : 0x2ffff;
202 	if (fc & PAUSE_TX)
203 		r |= (1 << 19);
204 	return elmr_write(adap, VSC_REG(1, port, 1), r);
205 }
206 
207 int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
208 {
209 	return elmr_write(adap, VSC_REG(1, port, 2), mtu);
210 }
211 
212 int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port)
213 {
214 	int ret;
215 
216 	ret = elmr_write(adap, VSC_REG(1, port, 3),
217 	    (addr[0] << 16) | (addr[1] << 8) | addr[2]);
218 	if (!ret)
219 		ret = elmr_write(adap, VSC_REG(1, port, 4),
220 		    (addr[3] << 16) | (addr[4] << 8) | addr[5]);
221 	return ret;
222 }
223 
224 int t3_vsc7323_enable(adapter_t *adap, int port, int which)
225 {
226 	int ret;
227 	unsigned int v, orig;
228 
229 	ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
230 	if (!ret) {
231 		orig = v;
232 		if (which & MAC_DIRECTION_TX)
233 			v |= 1;
234 		if (which & MAC_DIRECTION_RX)
235 			v |= 2;
236 		if (v != orig)
237 			ret = elmr_write(adap, VSC_REG(1, port, 0), v);
238 	}
239 	return ret;
240 }
241 
242 int t3_vsc7323_disable(adapter_t *adap, int port, int which)
243 {
244 	int ret;
245 	unsigned int v, orig;
246 
247 	ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
248 	if (!ret) {
249 		orig = v;
250 		if (which & MAC_DIRECTION_TX)
251 			v &= ~1;
252 		if (which & MAC_DIRECTION_RX)
253 			v &= ~2;
254 		if (v != orig)
255 			ret = elmr_write(adap, VSC_REG(1, port, 0), v);
256 	}
257 	return ret;
258 }
259 
260 #define STATS0_START 1
261 #define STATS1_START 0x24
262 #define NSTATS0 (0x1d - STATS0_START + 1)
263 #define NSTATS1 (0x2a - STATS1_START + 1)
264 
265 const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac)
266 {
267 	int ret;
268 	u64 rx_ucast, tx_ucast;
269 	u32 stats0[NSTATS0], stats1[NSTATS1];
270 
271 	ret = t3_elmr_blk_read(mac->adapter,
272 			       VSC_REG(4, mac->ext_port, STATS0_START),
273 			       stats0, NSTATS0);
274 	if (!ret)
275 		ret = t3_elmr_blk_read(mac->adapter,
276 				       VSC_REG(4, mac->ext_port, STATS1_START),
277 				       stats1, NSTATS1);
278 	if (ret)
279 		goto out;
280 
281 	/*
282 	 * HW counts Rx/Tx unicast frames but we want all the frames.
283 	 */
284 	rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames -
285 		   mac->stats.rx_bcast_frames;
286 	rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast);
287 	tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames -
288 		   mac->stats.tx_bcast_frames;
289 	tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast);
290 
291 #define RMON_UPDATE(mac, name, hw_stat) \
292 	mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name))
293 
294 	RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]);
295 	RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]);
296 	RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]);
297 	RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]);
298 	RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]);
299 	RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]);
300 	RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]);
301 	RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]);
302 	RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]);
303 	RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]);
304 	RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]);
305 	RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]);
306 
307 	RMON_UPDATE(mac, rx_frames_64,        stats0[17 - STATS0_START]);
308 	RMON_UPDATE(mac, rx_frames_65_127,    stats0[18 - STATS0_START]);
309 	RMON_UPDATE(mac, rx_frames_128_255,   stats0[19 - STATS0_START]);
310 	RMON_UPDATE(mac, rx_frames_256_511,   stats0[20 - STATS0_START]);
311 	RMON_UPDATE(mac, rx_frames_512_1023,  stats0[21 - STATS0_START]);
312 	RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]);
313 	RMON_UPDATE(mac, rx_frames_1519_max,  stats0[23 - STATS0_START]);
314 
315 	RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]);
316 	RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]);
317 	RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]);
318 	RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]);
319 	RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]);
320 	RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]);
321 	RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]);
322 
323 	RMON_UPDATE(mac, tx_underrun, 0);
324 
325 	RMON_UPDATE(mac, tx_frames_64,        stats1[36 - STATS1_START]);
326 	RMON_UPDATE(mac, tx_frames_65_127,    stats1[37 - STATS1_START]);
327 	RMON_UPDATE(mac, tx_frames_128_255,   stats1[38 - STATS1_START]);
328 	RMON_UPDATE(mac, tx_frames_256_511,   stats1[39 - STATS1_START]);
329 	RMON_UPDATE(mac, tx_frames_512_1023,  stats1[40 - STATS1_START]);
330 	RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]);
331 	RMON_UPDATE(mac, tx_frames_1519_max,  stats1[42 - STATS1_START]);
332 
333 #undef RMON_UPDATE
334 
335 	mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames +
336 			       mac->stats.rx_bcast_frames;
337 	mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames +
338 			       mac->stats.tx_bcast_frames;
339 out:    return &mac->stats;
340 }
341