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