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