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 __KERNEL_RCSID(0, "$NetBSD: cxgb_vsc7323.c,v 1.1 2010/03/21 21:11:13 jklos Exp $");
33
34 #ifdef CONFIG_DEFINED
35 #include <common/cxgb_common.h>
36 #else
37 #include "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
t3_elmr_blk_write(adapter_t * adap,int start,const u32 * vals,int n)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
elmr_write(adapter_t * adap,int addr,u32 val)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
t3_elmr_blk_read(adapter_t * adap,int start,u32 * vals,int n)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
t3_vsc7323_init(adapter_t * adap,int nports)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
t3_vsc7323_set_speed_fc(adapter_t * adap,int speed,int fc,int port)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
t3_vsc7323_set_mtu(adapter_t * adap,unsigned int mtu,int port)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
t3_vsc7323_set_addr(adapter_t * adap,u8 addr[6],int port)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
t3_vsc7323_enable(adapter_t * adap,int port,int which)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
t3_vsc7323_disable(adapter_t * adap,int port,int which)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
t3_vsc7323_update_stats(struct cmac * mac)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