Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / cxgb_vsc7323.c
blob65d6222307714d346e9909ce142c786882461d43
2 /**************************************************************************
4 Copyright (c) 2007, Chelsio Inc.
5 All rights reserved.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
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.
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.
29 ***************************************************************************/
31 #include <sys/cdefs.h>
32 #ifdef __NetBSD__
33 __KERNEL_RCSID(0, "$NetBSD: cxgb_vsc7323.c,v 1.2 2007/12/11 11:25:50 lukem Exp $");
34 #endif
35 #ifdef __FreeBSD__
36 __FBSDID("$FreeBSD: src/sys/dev/cxgb/common/cxgb_vsc7323.c,v 1.3 2007/09/09 01:28:03 kmacy Exp $");
37 #endif
39 #ifdef CONFIG_DEFINED
40 #include <common/cxgb_common.h>
41 #else
42 #ifdef __FreeBSD__
43 #include <dev/cxgb/common/cxgb_common.h>
44 #endif
45 #ifdef __NetBSD__
46 #include "cxgb_common.h"
47 #endif
48 #endif
50 enum {
51 ELMR_ADDR = 0,
52 ELMR_STAT = 1,
53 ELMR_DATA_LO = 2,
54 ELMR_DATA_HI = 3,
56 ELMR_THRES0 = 0xe000,
57 ELMR_BW = 0xe00c,
58 ELMR_FIFO_SZ = 0xe00d,
59 ELMR_STATS = 0xf000,
61 ELMR_MDIO_ADDR = 10
64 #define VSC_REG(block, subblock, reg) \
65 ((reg) | ((subblock) << 8) | ((block) << 12))
67 int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n)
69 int ret;
70 const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
72 ELMR_LOCK(adap);
73 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
74 for ( ; !ret && n; n--, vals++) {
75 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO,
76 *vals & 0xffff);
77 if (!ret)
78 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
79 *vals >> 16);
81 ELMR_UNLOCK(adap);
82 return ret;
85 static int elmr_write(adapter_t *adap, int addr, u32 val)
87 return t3_elmr_blk_write(adap, addr, &val, 1);
90 int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n)
92 int i, ret;
93 unsigned int v;
94 const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
96 ELMR_LOCK(adap);
98 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
99 if (ret)
100 goto out;
102 for (i = 0; i < 5; i++) {
103 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v);
104 if (ret)
105 goto out;
106 if (v == 1)
107 break;
108 udelay(5);
110 if (v != 1) {
111 ret = -ETIMEDOUT;
112 goto out;
115 for ( ; !ret && n; n--, vals++) {
116 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals);
117 if (!ret) {
118 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
119 &v);
120 *vals |= v << 16;
123 out: ELMR_UNLOCK(adap);
124 return ret;
127 int t3_vsc7323_init(adapter_t *adap, int nports)
129 static struct addr_val_pair sys_avp[] = {
130 { VSC_REG(7, 15, 0xf), 2 },
131 { VSC_REG(7, 15, 0x19), 0xd6 },
132 { VSC_REG(7, 15, 7), 0xc },
133 { VSC_REG(7, 1, 0), 0x220 },
135 static struct addr_val_pair fifo_avp[] = {
136 { VSC_REG(2, 0, 0x2f), 0 },
137 { VSC_REG(2, 0, 0xf), 0xa0010291 },
138 { VSC_REG(2, 1, 0x2f), 1 },
139 { VSC_REG(2, 1, 0xf), 0xa026301 }
141 static struct addr_val_pair xg_avp[] = {
142 { VSC_REG(1, 10, 0), 0x600b },
143 { VSC_REG(1, 10, 1), 0x70600 }, //QUANTA = 96*1024*8/512
144 { VSC_REG(1, 10, 2), 0x2710 },
145 { VSC_REG(1, 10, 5), 0x65 },
146 { VSC_REG(1, 10, 7), 0x23 },
147 { VSC_REG(1, 10, 0x23), 0x800007bf },
148 { VSC_REG(1, 10, 0x23), 0x000007bf },
149 { VSC_REG(1, 10, 0x23), 0x800007bf },
150 { VSC_REG(1, 10, 0x24), 4 }
153 int i, ret, ing_step, egr_step, ing_bot, egr_bot;
155 for (i = 0; i < ARRAY_SIZE(sys_avp); i++)
156 if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr,
157 &sys_avp[i].val, 1)))
158 return ret;
160 ing_step = 0xc0 / nports;
161 egr_step = 0x40 / nports;
162 ing_bot = egr_bot = 0;
163 // ing_wm = ing_step * 64;
164 // egr_wm = egr_step * 64;
166 /* {ING,EGR}_CONTROL.CLR = 1 here */
167 for (i = 0; i < nports; i++) {
168 if (
169 (ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i),
170 ((ing_bot + ing_step) << 16) | ing_bot)) ||
171 (ret = elmr_write(adap, VSC_REG(2, 0, 0x40 + i),
172 0x6000bc0)) ||
173 (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) ||
174 (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i),
175 ((egr_bot + egr_step) << 16) | egr_bot)) ||
176 (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i),
177 0x2000280)) ||
178 (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0)))
179 return ret;
180 ing_bot += ing_step;
181 egr_bot += egr_step;
184 for (i = 0; i < ARRAY_SIZE(fifo_avp); i++)
185 if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr,
186 &fifo_avp[i].val, 1)))
187 return ret;
189 for (i = 0; i < ARRAY_SIZE(xg_avp); i++)
190 if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr,
191 &xg_avp[i].val, 1)))
192 return ret;
194 for (i = 0; i < nports; i++)
195 if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) ||
196 (ret = elmr_write(adap, VSC_REG(1, i, 5),
197 (i << 12) | 0x63)) ||
198 (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) ||
199 (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)) ||
200 (ret = elmr_write(adap, ELMR_THRES0 + i, 768)))
201 return ret;
203 if ((ret = elmr_write(adap, ELMR_BW, 7)))
204 return ret;
206 return ret;
209 int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
211 int mode, clk, r;
213 if (speed >= 0) {
214 if (speed == SPEED_10)
215 mode = clk = 1;
216 else if (speed == SPEED_100)
217 mode = 1, clk = 2;
218 else if (speed == SPEED_1000)
219 mode = clk = 3;
220 else
221 return -EINVAL;
223 if ((r = elmr_write(adap, VSC_REG(1, port, 0),
224 0xa590 | (mode << 2))) ||
225 (r = elmr_write(adap, VSC_REG(1, port, 0xb),
226 0x91 | (clk << 1))) ||
227 (r = elmr_write(adap, VSC_REG(1, port, 0xb),
228 0x90 | (clk << 1))) ||
229 (r = elmr_write(adap, VSC_REG(1, port, 0),
230 0xa593 | (mode << 2))))
231 return r;
234 r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512
235 if (fc & PAUSE_TX)
236 r |= (1 << 19);
237 return elmr_write(adap, VSC_REG(1, port, 1), r);
240 int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
242 return elmr_write(adap, VSC_REG(1, port, 2), mtu);
245 int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port)
247 int ret;
249 ret = elmr_write(adap, VSC_REG(1, port, 3),
250 (addr[0] << 16) | (addr[1] << 8) | addr[2]);
251 if (!ret)
252 ret = elmr_write(adap, VSC_REG(1, port, 4),
253 (addr[3] << 16) | (addr[4] << 8) | addr[5]);
254 return ret;
257 int t3_vsc7323_enable(adapter_t *adap, int port, int which)
259 int ret;
260 unsigned int v, orig;
262 ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
263 if (!ret) {
264 orig = v;
265 if (which & MAC_DIRECTION_TX)
266 v |= 1;
267 if (which & MAC_DIRECTION_RX)
268 v |= 2;
269 if (v != orig)
270 ret = elmr_write(adap, VSC_REG(1, port, 0), v);
272 return ret;
275 int t3_vsc7323_disable(adapter_t *adap, int port, int which)
277 int ret;
278 unsigned int v, orig;
280 ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
281 if (!ret) {
282 orig = v;
283 if (which & MAC_DIRECTION_TX)
284 v &= ~1;
285 if (which & MAC_DIRECTION_RX)
286 v &= ~2;
287 if (v != orig)
288 ret = elmr_write(adap, VSC_REG(1, port, 0), v);
290 return ret;
293 #define STATS0_START 1
294 #define STATS1_START 0x24
295 #define NSTATS0 (0x1d - STATS0_START + 1)
296 #define NSTATS1 (0x2a - STATS1_START + 1)
298 #define ELMR_STAT(port, reg) (ELMR_STATS + port * 0x40 + reg)
300 const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac)
302 int ret;
303 u64 rx_ucast, tx_ucast;
304 u32 stats0[NSTATS0], stats1[NSTATS1];
306 ret = t3_elmr_blk_read(mac->adapter,
307 ELMR_STAT(mac->ext_port, STATS0_START),
308 stats0, NSTATS0);
309 if (!ret)
310 ret = t3_elmr_blk_read(mac->adapter,
311 ELMR_STAT(mac->ext_port, STATS1_START),
312 stats1, NSTATS1);
313 if (ret)
314 goto out;
317 * HW counts Rx/Tx unicast frames but we want all the frames.
319 rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames -
320 mac->stats.rx_bcast_frames;
321 rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast);
322 tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames -
323 mac->stats.tx_bcast_frames;
324 tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast);
326 #define RMON_UPDATE(mac, name, hw_stat) \
327 mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name))
329 RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]);
330 RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]);
331 RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]);
332 RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]);
333 RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]);
334 RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]);
335 RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]);
336 RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]);
337 RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]);
338 RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]);
339 RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]);
340 RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]);
342 RMON_UPDATE(mac, rx_frames_64, stats0[17 - STATS0_START]);
343 RMON_UPDATE(mac, rx_frames_65_127, stats0[18 - STATS0_START]);
344 RMON_UPDATE(mac, rx_frames_128_255, stats0[19 - STATS0_START]);
345 RMON_UPDATE(mac, rx_frames_256_511, stats0[20 - STATS0_START]);
346 RMON_UPDATE(mac, rx_frames_512_1023, stats0[21 - STATS0_START]);
347 RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]);
348 RMON_UPDATE(mac, rx_frames_1519_max, stats0[23 - STATS0_START]);
350 RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]);
351 RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]);
352 RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]);
353 RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]);
354 RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]);
355 RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]);
356 RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]);
358 RMON_UPDATE(mac, tx_underrun, 0);
360 RMON_UPDATE(mac, tx_frames_64, stats1[36 - STATS1_START]);
361 RMON_UPDATE(mac, tx_frames_65_127, stats1[37 - STATS1_START]);
362 RMON_UPDATE(mac, tx_frames_128_255, stats1[38 - STATS1_START]);
363 RMON_UPDATE(mac, tx_frames_256_511, stats1[39 - STATS1_START]);
364 RMON_UPDATE(mac, tx_frames_512_1023, stats1[40 - STATS1_START]);
365 RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]);
366 RMON_UPDATE(mac, tx_frames_1519_max, stats1[42 - STATS1_START]);
368 #undef RMON_UPDATE
370 mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames +
371 mac->stats.rx_bcast_frames;
372 mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames +
373 mac->stats.tx_bcast_frames;
374 out: return &mac->stats;