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 #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 } 362