2 /**************************************************************************
4 Copyright (c) 2007, Chelsio Inc.
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 __FBSDID("$FreeBSD$");
35 #include <common/cxgb_common.h>
37 #include <dev/cxgb/common/cxgb_common.h>
49 #define VSC_REG(block, subblock, reg) \
50 ((reg) | ((subblock) << 8) | ((block) << 12))
52 int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n)
55 const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
58 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
59 for ( ; !ret && n; n--, vals++) {
60 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO,
63 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
70 static int elmr_write(adapter_t *adap, int addr, u32 val)
72 return t3_elmr_blk_write(adap, addr, &val, 1);
75 int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n)
79 const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
83 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
86 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v);
94 for ( ; !ret && n; n--, vals++) {
95 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals);
97 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
102 out: ELMR_UNLOCK(adap);
106 int t3_vsc7323_init(adapter_t *adap, int nports)
108 static struct addr_val_pair sys_avp[] = {
109 { VSC_REG(7, 15, 0xf), 2 },
110 { VSC_REG(7, 15, 0x19), 0xd6 },
111 { VSC_REG(7, 15, 7), 0xc },
112 { VSC_REG(7, 1, 0), 0x220 },
114 static struct addr_val_pair fifo_avp[] = {
115 { VSC_REG(2, 0, 0x2f), 0 },
116 { VSC_REG(2, 0, 0xf), 0xa0010291 },
117 { VSC_REG(2, 1, 0x2f), 1 },
118 { VSC_REG(2, 1, 0xf), 0xa026301 }
120 static struct addr_val_pair xg_avp[] = {
121 { VSC_REG(1, 10, 0), 0x600b },
122 { VSC_REG(1, 10, 1), 0x70600 }, //QUANTA = 96*1024*8/512
123 { VSC_REG(1, 10, 2), 0x2710 },
124 { VSC_REG(1, 10, 5), 0x65 },
125 { VSC_REG(1, 10, 7), 0x23 },
126 { VSC_REG(1, 10, 0x23), 0x800007bf },
127 { VSC_REG(1, 10, 0x23), 0x000007bf },
128 { VSC_REG(1, 10, 0x23), 0x800007bf },
129 { VSC_REG(1, 10, 0x24), 4 }
132 int i, ret, ing_step, egr_step, ing_bot, egr_bot;
134 for (i = 0; i < ARRAY_SIZE(sys_avp); i++)
135 if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr,
136 &sys_avp[i].val, 1)))
139 ing_step = 0xc0 / nports;
140 egr_step = 0x40 / nports;
141 ing_bot = egr_bot = 0;
142 // ing_wm = ing_step * 64;
143 // egr_wm = egr_step * 64;
145 /* {ING,EGR}_CONTROL.CLR = 1 here */
146 for (i = 0; i < nports; i++) {
148 (ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i),
149 ((ing_bot + ing_step) << 16) | ing_bot)) ||
150 (ret = elmr_write(adap, VSC_REG(2, 0, 0x40 + i),
152 (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) ||
153 (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i),
154 ((egr_bot + egr_step) << 16) | egr_bot)) ||
155 (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i),
157 (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0)))
163 for (i = 0; i < ARRAY_SIZE(fifo_avp); i++)
164 if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr,
165 &fifo_avp[i].val, 1)))
168 for (i = 0; i < ARRAY_SIZE(xg_avp); i++)
169 if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr,
173 for (i = 0; i < nports; i++)
174 if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) ||
175 (ret = elmr_write(adap, VSC_REG(1, i, 5),
176 (i << 12) | 0x63)) ||
177 (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) ||
178 (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)))
183 int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
188 if (speed == SPEED_10)
190 else if (speed == SPEED_100)
192 else if (speed == SPEED_1000)
197 if ((r = elmr_write(adap, VSC_REG(1, port, 0),
198 0xa590 | (mode << 2))) ||
199 (r = elmr_write(adap, VSC_REG(1, port, 0xb),
200 0x91 | (clk << 1))) ||
201 (r = elmr_write(adap, VSC_REG(1, port, 0xb),
202 0x90 | (clk << 1))) ||
203 (r = elmr_write(adap, VSC_REG(1, port, 0),
204 0xa593 | (mode << 2))))
208 r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512
211 return elmr_write(adap, VSC_REG(1, port, 1), r);
214 int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
216 return elmr_write(adap, VSC_REG(1, port, 2), mtu);
219 int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port)
223 ret = elmr_write(adap, VSC_REG(1, port, 3),
224 (addr[0] << 16) | (addr[1] << 8) | addr[2]);
226 ret = elmr_write(adap, VSC_REG(1, port, 4),
227 (addr[3] << 16) | (addr[4] << 8) | addr[5]);
231 int t3_vsc7323_enable(adapter_t *adap, int port, int which)
234 unsigned int v, orig;
236 ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
239 if (which & MAC_DIRECTION_TX)
241 if (which & MAC_DIRECTION_RX)
244 ret = elmr_write(adap, VSC_REG(1, port, 0), v);
249 int t3_vsc7323_disable(adapter_t *adap, int port, int which)
252 unsigned int v, orig;
254 ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
257 if (which & MAC_DIRECTION_TX)
259 if (which & MAC_DIRECTION_RX)
262 ret = elmr_write(adap, VSC_REG(1, port, 0), v);
267 #define STATS0_START 1
268 #define STATS1_START 0x24
269 #define NSTATS0 (0x1d - STATS0_START + 1)
270 #define NSTATS1 (0x2a - STATS1_START + 1)
272 const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac)
275 u64 rx_ucast, tx_ucast;
276 u32 stats0[NSTATS0], stats1[NSTATS1];
278 ret = t3_elmr_blk_read(mac->adapter,
279 VSC_REG(4, mac->ext_port, STATS0_START),
282 ret = t3_elmr_blk_read(mac->adapter,
283 VSC_REG(4, mac->ext_port, STATS1_START),
289 * HW counts Rx/Tx unicast frames but we want all the frames.
291 rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames -
292 mac->stats.rx_bcast_frames;
293 rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast);
294 tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames -
295 mac->stats.tx_bcast_frames;
296 tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast);
298 #define RMON_UPDATE(mac, name, hw_stat) \
299 mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name))
301 RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]);
302 RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]);
303 RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]);
304 RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]);
305 RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]);
306 RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]);
307 RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]);
308 RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]);
309 RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]);
310 RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]);
311 RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]);
312 RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]);
314 RMON_UPDATE(mac, rx_frames_64, stats0[17 - STATS0_START]);
315 RMON_UPDATE(mac, rx_frames_65_127, stats0[18 - STATS0_START]);
316 RMON_UPDATE(mac, rx_frames_128_255, stats0[19 - STATS0_START]);
317 RMON_UPDATE(mac, rx_frames_256_511, stats0[20 - STATS0_START]);
318 RMON_UPDATE(mac, rx_frames_512_1023, stats0[21 - STATS0_START]);
319 RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]);
320 RMON_UPDATE(mac, rx_frames_1519_max, stats0[23 - STATS0_START]);
322 RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]);
323 RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]);
324 RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]);
325 RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]);
326 RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]);
327 RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]);
328 RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]);
330 RMON_UPDATE(mac, tx_underrun, 0);
332 RMON_UPDATE(mac, tx_frames_64, stats1[36 - STATS1_START]);
333 RMON_UPDATE(mac, tx_frames_65_127, stats1[37 - STATS1_START]);
334 RMON_UPDATE(mac, tx_frames_128_255, stats1[38 - STATS1_START]);
335 RMON_UPDATE(mac, tx_frames_256_511, stats1[39 - STATS1_START]);
336 RMON_UPDATE(mac, tx_frames_512_1023, stats1[40 - STATS1_START]);
337 RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]);
338 RMON_UPDATE(mac, tx_frames_1519_max, stats1[42 - STATS1_START]);
342 mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames +
343 mac->stats.rx_bcast_frames;
344 mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames +
345 mac->stats.tx_bcast_frames;
346 out: return &mac->stats;