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