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), 0xa026301 } 119 }; 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 } 130 }; 131 132 int i, ret, ing_step, egr_step, ing_bot, egr_bot; 133 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))) 137 return ret; 138 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; 144 145 /* {ING,EGR}_CONTROL.CLR = 1 here */ 146 for (i = 0; i < nports; i++) { 147 if ( 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), 151 0x6000a00)) || 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), 156 0x2000280)) || 157 (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0))) 158 return ret; 159 ing_bot += ing_step; 160 egr_bot += egr_step; 161 } 162 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))) 166 return ret; 167 168 for (i = 0; i < ARRAY_SIZE(xg_avp); i++) 169 if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr, 170 &xg_avp[i].val, 1))) 171 return ret; 172 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))) 179 return ret; 180 return ret; 181 } 182 183 int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port) 184 { 185 int mode, clk, r; 186 187 if (speed >= 0) { 188 if (speed == SPEED_10) 189 mode = clk = 1; 190 else if (speed == SPEED_100) 191 mode = 1, clk = 2; 192 else if (speed == SPEED_1000) 193 mode = clk = 3; 194 else 195 return -EINVAL; 196 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)))) 205 return r; 206 } 207 208 r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512 209 if (fc & PAUSE_TX) 210 r |= (1 << 19); 211 return elmr_write(adap, VSC_REG(1, port, 1), r); 212 } 213 214 int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port) 215 { 216 return elmr_write(adap, VSC_REG(1, port, 2), mtu); 217 } 218 219 int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port) 220 { 221 int ret; 222 223 ret = elmr_write(adap, VSC_REG(1, port, 3), 224 (addr[0] << 16) | (addr[1] << 8) | addr[2]); 225 if (!ret) 226 ret = elmr_write(adap, VSC_REG(1, port, 4), 227 (addr[3] << 16) | (addr[4] << 8) | addr[5]); 228 return ret; 229 } 230 231 int t3_vsc7323_enable(adapter_t *adap, int port, int which) 232 { 233 int ret; 234 unsigned int v, orig; 235 236 ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1); 237 if (!ret) { 238 orig = v; 239 if (which & MAC_DIRECTION_TX) 240 v |= 1; 241 if (which & MAC_DIRECTION_RX) 242 v |= 2; 243 if (v != orig) 244 ret = elmr_write(adap, VSC_REG(1, port, 0), v); 245 } 246 return ret; 247 } 248 249 int t3_vsc7323_disable(adapter_t *adap, int port, int which) 250 { 251 int ret; 252 unsigned int v, orig; 253 254 ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1); 255 if (!ret) { 256 orig = v; 257 if (which & MAC_DIRECTION_TX) 258 v &= ~1; 259 if (which & MAC_DIRECTION_RX) 260 v &= ~2; 261 if (v != orig) 262 ret = elmr_write(adap, VSC_REG(1, port, 0), v); 263 } 264 return ret; 265 } 266 267 #define STATS0_START 1 268 #define STATS1_START 0x24 269 #define NSTATS0 (0x1d - STATS0_START + 1) 270 #define NSTATS1 (0x2a - STATS1_START + 1) 271 272 const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac) 273 { 274 int ret; 275 u64 rx_ucast, tx_ucast; 276 u32 stats0[NSTATS0], stats1[NSTATS1]; 277 278 ret = t3_elmr_blk_read(mac->adapter, 279 VSC_REG(4, mac->ext_port, STATS0_START), 280 stats0, NSTATS0); 281 if (!ret) 282 ret = t3_elmr_blk_read(mac->adapter, 283 VSC_REG(4, mac->ext_port, STATS1_START), 284 stats1, NSTATS1); 285 if (ret) 286 goto out; 287 288 /* 289 * HW counts Rx/Tx unicast frames but we want all the frames. 290 */ 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); 297 298 #define RMON_UPDATE(mac, name, hw_stat) \ 299 mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name)) 300 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]); 313 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]); 321 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]); 329 330 RMON_UPDATE(mac, tx_underrun, 0); 331 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]); 339 340 #undef RMON_UPDATE 341 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; 347 } 348