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