xref: /freebsd/sys/dev/cxgb/common/cxgb_vsc7323.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
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_THRES0  = 0xe000,
47 	ELMR_BW      = 0xe00c,
48 	ELMR_FIFO_SZ = 0xe00d,
49 	ELMR_STATS   = 0xf000,
50 
51 	ELMR_MDIO_ADDR = 10
52 };
53 
54 #define VSC_REG(block, subblock, reg) \
55 	((reg) | ((subblock) << 8) | ((block) << 12))
56 
57 int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n)
58 {
59 	int ret;
60 	const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
61 
62 	ELMR_LOCK(adap);
63 	ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
64 	for ( ; !ret && n; n--, vals++) {
65 		ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO,
66 				*vals & 0xffff);
67 		if (!ret)
68 			ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
69 					*vals >> 16);
70 	}
71 	ELMR_UNLOCK(adap);
72 	return ret;
73 }
74 
75 static int elmr_write(adapter_t *adap, int addr, u32 val)
76 {
77 	return t3_elmr_blk_write(adap, addr, &val, 1);
78 }
79 
80 int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n)
81 {
82 	int i, ret;
83 	unsigned int v;
84 	const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
85 
86 	ELMR_LOCK(adap);
87 
88 	ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
89 	if (ret)
90 		goto out;
91 
92 	for (i = 0; i < 5; i++) {
93 		ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v);
94 		if (ret)
95 			goto out;
96 		if (v == 1)
97 			break;
98 		udelay(5);
99 	}
100 	if (v != 1) {
101 		ret = -ETIMEDOUT;
102 		goto out;
103 	}
104 
105 	for ( ; !ret && n; n--, vals++) {
106 		ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals);
107 		if (!ret) {
108 			ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
109 				       &v);
110 			*vals |= v << 16;
111 		}
112 	}
113 out:	ELMR_UNLOCK(adap);
114 	return ret;
115 }
116 
117 int t3_vsc7323_init(adapter_t *adap, int nports)
118 {
119 	static struct addr_val_pair sys_avp[] = {
120 		{ VSC_REG(7, 15, 0xf),  2 },
121 		{ VSC_REG(7, 15, 0x19), 0xd6 },
122 		{ VSC_REG(7, 15, 7),    0xc },
123 		{ VSC_REG(7, 1, 0),     0x220 },
124 	};
125 	static struct addr_val_pair fifo_avp[] = {
126 		{ VSC_REG(2, 0, 0x2f), 0 },
127 		{ VSC_REG(2, 0, 0xf),  0xa0010291 },
128 		{ VSC_REG(2, 1, 0x2f), 1 },
129 		{ VSC_REG(2, 1, 0xf),  0xa026301 }
130 	};
131 	static struct addr_val_pair xg_avp[] = {
132 		{ VSC_REG(1, 10, 0),    0x600b },
133 		{ VSC_REG(1, 10, 1),    0x70600 }, //QUANTA = 96*1024*8/512
134 		{ VSC_REG(1, 10, 2),    0x2710 },
135 		{ VSC_REG(1, 10, 5),    0x65 },
136 		{ VSC_REG(1, 10, 7),    0x23 },
137 		{ VSC_REG(1, 10, 0x23), 0x800007bf },
138 		{ VSC_REG(1, 10, 0x23), 0x000007bf },
139 		{ VSC_REG(1, 10, 0x23), 0x800007bf },
140 		{ VSC_REG(1, 10, 0x24), 4 }
141 	};
142 
143 	int i, ret, ing_step, egr_step, ing_bot, egr_bot;
144 
145 	for (i = 0; i < ARRAY_SIZE(sys_avp); i++)
146 		if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr,
147 					     &sys_avp[i].val, 1)))
148 			return ret;
149 
150 	ing_step = 0xc0 / nports;
151 	egr_step = 0x40 / nports;
152 	ing_bot = egr_bot = 0;
153 //	ing_wm = ing_step * 64;
154 //	egr_wm = egr_step * 64;
155 
156 	/* {ING,EGR}_CONTROL.CLR = 1 here */
157 	for (i = 0; i < nports; i++) {
158 		if (
159 		    (ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i),
160 				((ing_bot + ing_step) << 16) | ing_bot)) ||
161 		    (ret = elmr_write(adap, VSC_REG(2, 0, 0x40 + i),
162 				0x6000bc0)) ||
163 		    (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) ||
164 		    (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i),
165 				((egr_bot + egr_step) << 16) | egr_bot)) ||
166 		    (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i),
167 				0x2000280)) ||
168 		    (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0)))
169 			return ret;
170 		ing_bot += ing_step;
171 		egr_bot += egr_step;
172 	}
173 
174 	for (i = 0; i < ARRAY_SIZE(fifo_avp); i++)
175 		if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr,
176 					     &fifo_avp[i].val, 1)))
177 			return ret;
178 
179 	for (i = 0; i < ARRAY_SIZE(xg_avp); i++)
180 		if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr,
181 					     &xg_avp[i].val, 1)))
182 			return ret;
183 
184 	for (i = 0; i < nports; i++)
185 		if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) ||
186 		    (ret = elmr_write(adap, VSC_REG(1, i, 5),
187 				 (i << 12) | 0x63)) ||
188 		    (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) ||
189 		    (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)) ||
190 		    (ret = elmr_write(adap, ELMR_THRES0 + i, 768)))
191 			return ret;
192 
193 	if ((ret = elmr_write(adap, ELMR_BW, 7)))
194 		return ret;
195 
196 	return ret;
197 }
198 
199 int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
200 {
201 	int mode, clk, r;
202 
203 	if (speed >= 0) {
204 		if (speed == SPEED_10)
205 			mode = clk = 1;
206 		else if (speed == SPEED_100)
207 			mode = 1, clk = 2;
208 		else if (speed == SPEED_1000)
209 			mode = clk = 3;
210 		else
211 			return -EINVAL;
212 
213 		if ((r = elmr_write(adap, VSC_REG(1, port, 0),
214 				    0xa590 | (mode << 2))) ||
215 		    (r = elmr_write(adap, VSC_REG(1, port, 0xb),
216 				    0x91 | (clk << 1))) ||
217 		    (r = elmr_write(adap, VSC_REG(1, port, 0xb),
218 				    0x90 | (clk << 1))) ||
219 		    (r = elmr_write(adap, VSC_REG(1, port, 0),
220 				    0xa593 | (mode << 2))))
221 			return r;
222 	}
223 
224 	r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512
225 	if (fc & PAUSE_TX)
226 		r |= (1 << 19);
227 	return elmr_write(adap, VSC_REG(1, port, 1), r);
228 }
229 
230 int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
231 {
232 	return elmr_write(adap, VSC_REG(1, port, 2), mtu);
233 }
234 
235 int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port)
236 {
237 	int ret;
238 
239 	ret = elmr_write(adap, VSC_REG(1, port, 3),
240 			 (addr[0] << 16) | (addr[1] << 8) | addr[2]);
241 	if (!ret)
242 		ret = elmr_write(adap, VSC_REG(1, port, 4),
243 				 (addr[3] << 16) | (addr[4] << 8) | addr[5]);
244 	return ret;
245 }
246 
247 int t3_vsc7323_enable(adapter_t *adap, int port, int which)
248 {
249 	int ret;
250 	unsigned int v, orig;
251 
252 	ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
253 	if (!ret) {
254 		orig = v;
255 		if (which & MAC_DIRECTION_TX)
256 			v |= 1;
257 		if (which & MAC_DIRECTION_RX)
258 			v |= 2;
259 		if (v != orig)
260 			ret = elmr_write(adap, VSC_REG(1, port, 0), v);
261 	}
262 	return ret;
263 }
264 
265 int t3_vsc7323_disable(adapter_t *adap, int port, int which)
266 {
267 	int ret;
268 	unsigned int v, orig;
269 
270 	ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
271 	if (!ret) {
272 		orig = v;
273 		if (which & MAC_DIRECTION_TX)
274 			v &= ~1;
275 		if (which & MAC_DIRECTION_RX)
276 			v &= ~2;
277 		if (v != orig)
278 			ret = elmr_write(adap, VSC_REG(1, port, 0), v);
279 	}
280 	return ret;
281 }
282 
283 #define STATS0_START 1
284 #define STATS1_START 0x24
285 #define NSTATS0 (0x1d - STATS0_START + 1)
286 #define NSTATS1 (0x2a - STATS1_START + 1)
287 
288 #define ELMR_STAT(port, reg) (ELMR_STATS + port * 0x40 + reg)
289 
290 const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac)
291 {
292 	int ret;
293 	u64 rx_ucast, tx_ucast;
294 	u32 stats0[NSTATS0], stats1[NSTATS1];
295 
296 	ret = t3_elmr_blk_read(mac->adapter,
297 			       ELMR_STAT(mac->ext_port, STATS0_START),
298 			       stats0, NSTATS0);
299 	if (!ret)
300 		ret = t3_elmr_blk_read(mac->adapter,
301 				       ELMR_STAT(mac->ext_port, STATS1_START),
302 				       stats1, NSTATS1);
303 	if (ret)
304 		goto out;
305 
306 	/*
307 	 * HW counts Rx/Tx unicast frames but we want all the frames.
308 	 */
309 	rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames -
310 		   mac->stats.rx_bcast_frames;
311 	rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast);
312 	tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames -
313 		   mac->stats.tx_bcast_frames;
314 	tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast);
315 
316 #define RMON_UPDATE(mac, name, hw_stat) \
317 	mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name))
318 
319 	RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]);
320 	RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]);
321 	RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]);
322 	RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]);
323 	RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]);
324 	RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]);
325 	RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]);
326 	RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]);
327 	RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]);
328 	RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]);
329 	RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]);
330 	RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]);
331 
332 	RMON_UPDATE(mac, rx_frames_64,        stats0[17 - STATS0_START]);
333 	RMON_UPDATE(mac, rx_frames_65_127,    stats0[18 - STATS0_START]);
334 	RMON_UPDATE(mac, rx_frames_128_255,   stats0[19 - STATS0_START]);
335 	RMON_UPDATE(mac, rx_frames_256_511,   stats0[20 - STATS0_START]);
336 	RMON_UPDATE(mac, rx_frames_512_1023,  stats0[21 - STATS0_START]);
337 	RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]);
338 	RMON_UPDATE(mac, rx_frames_1519_max,  stats0[23 - STATS0_START]);
339 
340 	RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]);
341 	RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]);
342 	RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]);
343 	RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]);
344 	RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]);
345 	RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]);
346 	RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]);
347 
348 	RMON_UPDATE(mac, tx_underrun, 0);
349 
350 	RMON_UPDATE(mac, tx_frames_64,        stats1[36 - STATS1_START]);
351 	RMON_UPDATE(mac, tx_frames_65_127,    stats1[37 - STATS1_START]);
352 	RMON_UPDATE(mac, tx_frames_128_255,   stats1[38 - STATS1_START]);
353 	RMON_UPDATE(mac, tx_frames_256_511,   stats1[39 - STATS1_START]);
354 	RMON_UPDATE(mac, tx_frames_512_1023,  stats1[40 - STATS1_START]);
355 	RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]);
356 	RMON_UPDATE(mac, tx_frames_1519_max,  stats1[42 - STATS1_START]);
357 
358 #undef RMON_UPDATE
359 
360 	mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames +
361 			       mac->stats.rx_bcast_frames;
362 	mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames +
363 			       mac->stats.tx_bcast_frames;
364 out:    return &mac->stats;
365 }
366