1 1.1 jklos 2 1.1 jklos /************************************************************************** 3 1.1 jklos 4 1.1 jklos Copyright (c) 2007, Chelsio Inc. 5 1.1 jklos All rights reserved. 6 1.1 jklos 7 1.1 jklos Redistribution and use in source and binary forms, with or without 8 1.1 jklos modification, are permitted provided that the following conditions are met: 9 1.1 jklos 10 1.1 jklos 1. Redistributions of source code must retain the above copyright notice, 11 1.1 jklos this list of conditions and the following disclaimer. 12 1.1 jklos 13 1.1 jklos 2. Neither the name of the Chelsio Corporation nor the names of its 14 1.1 jklos contributors may be used to endorse or promote products derived from 15 1.1 jklos this software without specific prior written permission. 16 1.1 jklos 17 1.1 jklos THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 1.1 jklos AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 1.1 jklos IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 1.1 jklos ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 1.1 jklos LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 1.1 jklos CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 1.1 jklos SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 jklos INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 1.1 jklos CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 1.1 jklos ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 jklos POSSIBILITY OF SUCH DAMAGE. 28 1.1 jklos 29 1.1 jklos ***************************************************************************/ 30 1.1 jklos 31 1.1 jklos #include <sys/cdefs.h> 32 1.1 jklos __KERNEL_RCSID(0, "$NetBSD: cxgb_vsc7323.c,v 1.1 2010/03/21 21:11:13 jklos Exp $"); 33 1.1 jklos 34 1.1 jklos #ifdef CONFIG_DEFINED 35 1.1 jklos #include <common/cxgb_common.h> 36 1.1 jklos #else 37 1.1 jklos #include "cxgb_common.h" 38 1.1 jklos #endif 39 1.1 jklos 40 1.1 jklos enum { 41 1.1 jklos ELMR_ADDR = 0, 42 1.1 jklos ELMR_STAT = 1, 43 1.1 jklos ELMR_DATA_LO = 2, 44 1.1 jklos ELMR_DATA_HI = 3, 45 1.1 jklos 46 1.1 jklos ELMR_THRES0 = 0xe000, 47 1.1 jklos ELMR_BW = 0xe00c, 48 1.1 jklos ELMR_FIFO_SZ = 0xe00d, 49 1.1 jklos ELMR_STATS = 0xf000, 50 1.1 jklos 51 1.1 jklos ELMR_MDIO_ADDR = 10 52 1.1 jklos }; 53 1.1 jklos 54 1.1 jklos #define VSC_REG(block, subblock, reg) \ 55 1.1 jklos ((reg) | ((subblock) << 8) | ((block) << 12)) 56 1.1 jklos 57 1.1 jklos int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n) 58 1.1 jklos { 59 1.1 jklos int ret; 60 1.1 jklos const struct mdio_ops *mo = adapter_info(adap)->mdio_ops; 61 1.1 jklos 62 1.1 jklos ELMR_LOCK(adap); 63 1.1 jklos ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start); 64 1.1 jklos for ( ; !ret && n; n--, vals++) { 65 1.1 jklos ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, 66 1.1 jklos *vals & 0xffff); 67 1.1 jklos if (!ret) 68 1.1 jklos ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI, 69 1.1 jklos *vals >> 16); 70 1.1 jklos } 71 1.1 jklos ELMR_UNLOCK(adap); 72 1.1 jklos return ret; 73 1.1 jklos } 74 1.1 jklos 75 1.1 jklos static int elmr_write(adapter_t *adap, int addr, u32 val) 76 1.1 jklos { 77 1.1 jklos return t3_elmr_blk_write(adap, addr, &val, 1); 78 1.1 jklos } 79 1.1 jklos 80 1.1 jklos int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n) 81 1.1 jklos { 82 1.1 jklos int i, ret; 83 1.1 jklos unsigned int v; 84 1.1 jklos const struct mdio_ops *mo = adapter_info(adap)->mdio_ops; 85 1.1 jklos 86 1.1 jklos ELMR_LOCK(adap); 87 1.1 jklos 88 1.1 jklos ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start); 89 1.1 jklos if (ret) 90 1.1 jklos goto out; 91 1.1 jklos 92 1.1 jklos for (i = 0; i < 5; i++) { 93 1.1 jklos ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v); 94 1.1 jklos if (ret) 95 1.1 jklos goto out; 96 1.1 jklos if (v == 1) 97 1.1 jklos break; 98 1.1 jklos udelay(5); 99 1.1 jklos } 100 1.1 jklos if (v != 1) { 101 1.1 jklos ret = -ETIMEDOUT; 102 1.1 jklos goto out; 103 1.1 jklos } 104 1.1 jklos 105 1.1 jklos for ( ; !ret && n; n--, vals++) { 106 1.1 jklos ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals); 107 1.1 jklos if (!ret) { 108 1.1 jklos ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI, 109 1.1 jklos &v); 110 1.1 jklos *vals |= v << 16; 111 1.1 jklos } 112 1.1 jklos } 113 1.1 jklos out: ELMR_UNLOCK(adap); 114 1.1 jklos return ret; 115 1.1 jklos } 116 1.1 jklos 117 1.1 jklos int t3_vsc7323_init(adapter_t *adap, int nports) 118 1.1 jklos { 119 1.1 jklos static struct addr_val_pair sys_avp[] = { 120 1.1 jklos { VSC_REG(7, 15, 0xf), 2 }, 121 1.1 jklos { VSC_REG(7, 15, 0x19), 0xd6 }, 122 1.1 jklos { VSC_REG(7, 15, 7), 0xc }, 123 1.1 jklos { VSC_REG(7, 1, 0), 0x220 }, 124 1.1 jklos }; 125 1.1 jklos static struct addr_val_pair fifo_avp[] = { 126 1.1 jklos { VSC_REG(2, 0, 0x2f), 0 }, 127 1.1 jklos { VSC_REG(2, 0, 0xf), 0xa0010291 }, 128 1.1 jklos { VSC_REG(2, 1, 0x2f), 1 }, 129 1.1 jklos { VSC_REG(2, 1, 0xf), 0xa026301 } 130 1.1 jklos }; 131 1.1 jklos static struct addr_val_pair xg_avp[] = { 132 1.1 jklos { VSC_REG(1, 10, 0), 0x600b }, 133 1.1 jklos { VSC_REG(1, 10, 1), 0x70600 }, //QUANTA = 96*1024*8/512 134 1.1 jklos { VSC_REG(1, 10, 2), 0x2710 }, 135 1.1 jklos { VSC_REG(1, 10, 5), 0x65 }, 136 1.1 jklos { VSC_REG(1, 10, 7), 0x23 }, 137 1.1 jklos { VSC_REG(1, 10, 0x23), 0x800007bf }, 138 1.1 jklos { VSC_REG(1, 10, 0x23), 0x000007bf }, 139 1.1 jklos { VSC_REG(1, 10, 0x23), 0x800007bf }, 140 1.1 jklos { VSC_REG(1, 10, 0x24), 4 } 141 1.1 jklos }; 142 1.1 jklos 143 1.1 jklos int i, ret, ing_step, egr_step, ing_bot, egr_bot; 144 1.1 jklos 145 1.1 jklos for (i = 0; i < ARRAY_SIZE(sys_avp); i++) 146 1.1 jklos if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr, 147 1.1 jklos &sys_avp[i].val, 1))) 148 1.1 jklos return ret; 149 1.1 jklos 150 1.1 jklos ing_step = 0xc0 / nports; 151 1.1 jklos egr_step = 0x40 / nports; 152 1.1 jklos ing_bot = egr_bot = 0; 153 1.1 jklos // ing_wm = ing_step * 64; 154 1.1 jklos // egr_wm = egr_step * 64; 155 1.1 jklos 156 1.1 jklos /* {ING,EGR}_CONTROL.CLR = 1 here */ 157 1.1 jklos for (i = 0; i < nports; i++) { 158 1.1 jklos if ( 159 1.1 jklos (ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i), 160 1.1 jklos ((ing_bot + ing_step) << 16) | ing_bot)) || 161 1.1 jklos (ret = elmr_write(adap, VSC_REG(2, 0, 0x40 + i), 162 1.1 jklos 0x6000bc0)) || 163 1.1 jklos (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) || 164 1.1 jklos (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i), 165 1.1 jklos ((egr_bot + egr_step) << 16) | egr_bot)) || 166 1.1 jklos (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i), 167 1.1 jklos 0x2000280)) || 168 1.1 jklos (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0))) 169 1.1 jklos return ret; 170 1.1 jklos ing_bot += ing_step; 171 1.1 jklos egr_bot += egr_step; 172 1.1 jklos } 173 1.1 jklos 174 1.1 jklos for (i = 0; i < ARRAY_SIZE(fifo_avp); i++) 175 1.1 jklos if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr, 176 1.1 jklos &fifo_avp[i].val, 1))) 177 1.1 jklos return ret; 178 1.1 jklos 179 1.1 jklos for (i = 0; i < ARRAY_SIZE(xg_avp); i++) 180 1.1 jklos if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr, 181 1.1 jklos &xg_avp[i].val, 1))) 182 1.1 jklos return ret; 183 1.1 jklos 184 1.1 jklos for (i = 0; i < nports; i++) 185 1.1 jklos if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) || 186 1.1 jklos (ret = elmr_write(adap, VSC_REG(1, i, 5), 187 1.1 jklos (i << 12) | 0x63)) || 188 1.1 jklos (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) || 189 1.1 jklos (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)) || 190 1.1 jklos (ret = elmr_write(adap, ELMR_THRES0 + i, 768))) 191 1.1 jklos return ret; 192 1.1 jklos 193 1.1 jklos if ((ret = elmr_write(adap, ELMR_BW, 7))) 194 1.1 jklos return ret; 195 1.1 jklos 196 1.1 jklos return ret; 197 1.1 jklos } 198 1.1 jklos 199 1.1 jklos int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port) 200 1.1 jklos { 201 1.1 jklos int mode, clk, r; 202 1.1 jklos 203 1.1 jklos if (speed >= 0) { 204 1.1 jklos if (speed == SPEED_10) 205 1.1 jklos mode = clk = 1; 206 1.1 jklos else if (speed == SPEED_100) 207 1.1 jklos mode = 1, clk = 2; 208 1.1 jklos else if (speed == SPEED_1000) 209 1.1 jklos mode = clk = 3; 210 1.1 jklos else 211 1.1 jklos return -EINVAL; 212 1.1 jklos 213 1.1 jklos if ((r = elmr_write(adap, VSC_REG(1, port, 0), 214 1.1 jklos 0xa590 | (mode << 2))) || 215 1.1 jklos (r = elmr_write(adap, VSC_REG(1, port, 0xb), 216 1.1 jklos 0x91 | (clk << 1))) || 217 1.1 jklos (r = elmr_write(adap, VSC_REG(1, port, 0xb), 218 1.1 jklos 0x90 | (clk << 1))) || 219 1.1 jklos (r = elmr_write(adap, VSC_REG(1, port, 0), 220 1.1 jklos 0xa593 | (mode << 2)))) 221 1.1 jklos return r; 222 1.1 jklos } 223 1.1 jklos 224 1.1 jklos r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512 225 1.1 jklos if (fc & PAUSE_TX) 226 1.1 jklos r |= (1 << 19); 227 1.1 jklos return elmr_write(adap, VSC_REG(1, port, 1), r); 228 1.1 jklos } 229 1.1 jklos 230 1.1 jklos int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port) 231 1.1 jklos { 232 1.1 jklos return elmr_write(adap, VSC_REG(1, port, 2), mtu); 233 1.1 jklos } 234 1.1 jklos 235 1.1 jklos int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port) 236 1.1 jklos { 237 1.1 jklos int ret; 238 1.1 jklos 239 1.1 jklos ret = elmr_write(adap, VSC_REG(1, port, 3), 240 1.1 jklos (addr[0] << 16) | (addr[1] << 8) | addr[2]); 241 1.1 jklos if (!ret) 242 1.1 jklos ret = elmr_write(adap, VSC_REG(1, port, 4), 243 1.1 jklos (addr[3] << 16) | (addr[4] << 8) | addr[5]); 244 1.1 jklos return ret; 245 1.1 jklos } 246 1.1 jklos 247 1.1 jklos int t3_vsc7323_enable(adapter_t *adap, int port, int which) 248 1.1 jklos { 249 1.1 jklos int ret; 250 1.1 jklos unsigned int v, orig; 251 1.1 jklos 252 1.1 jklos ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1); 253 1.1 jklos if (!ret) { 254 1.1 jklos orig = v; 255 1.1 jklos if (which & MAC_DIRECTION_TX) 256 1.1 jklos v |= 1; 257 1.1 jklos if (which & MAC_DIRECTION_RX) 258 1.1 jklos v |= 2; 259 1.1 jklos if (v != orig) 260 1.1 jklos ret = elmr_write(adap, VSC_REG(1, port, 0), v); 261 1.1 jklos } 262 1.1 jklos return ret; 263 1.1 jklos } 264 1.1 jklos 265 1.1 jklos int t3_vsc7323_disable(adapter_t *adap, int port, int which) 266 1.1 jklos { 267 1.1 jklos int ret; 268 1.1 jklos unsigned int v, orig; 269 1.1 jklos 270 1.1 jklos ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1); 271 1.1 jklos if (!ret) { 272 1.1 jklos orig = v; 273 1.1 jklos if (which & MAC_DIRECTION_TX) 274 1.1 jklos v &= ~1; 275 1.1 jklos if (which & MAC_DIRECTION_RX) 276 1.1 jklos v &= ~2; 277 1.1 jklos if (v != orig) 278 1.1 jklos ret = elmr_write(adap, VSC_REG(1, port, 0), v); 279 1.1 jklos } 280 1.1 jklos return ret; 281 1.1 jklos } 282 1.1 jklos 283 1.1 jklos #define STATS0_START 1 284 1.1 jklos #define STATS1_START 0x24 285 1.1 jklos #define NSTATS0 (0x1d - STATS0_START + 1) 286 1.1 jklos #define NSTATS1 (0x2a - STATS1_START + 1) 287 1.1 jklos 288 1.1 jklos #define ELMR_STAT(port, reg) (ELMR_STATS + port * 0x40 + reg) 289 1.1 jklos 290 1.1 jklos const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac) 291 1.1 jklos { 292 1.1 jklos int ret; 293 1.1 jklos u64 rx_ucast, tx_ucast; 294 1.1 jklos u32 stats0[NSTATS0], stats1[NSTATS1]; 295 1.1 jklos 296 1.1 jklos ret = t3_elmr_blk_read(mac->adapter, 297 1.1 jklos ELMR_STAT(mac->ext_port, STATS0_START), 298 1.1 jklos stats0, NSTATS0); 299 1.1 jklos if (!ret) 300 1.1 jklos ret = t3_elmr_blk_read(mac->adapter, 301 1.1 jklos ELMR_STAT(mac->ext_port, STATS1_START), 302 1.1 jklos stats1, NSTATS1); 303 1.1 jklos if (ret) 304 1.1 jklos goto out; 305 1.1 jklos 306 1.1 jklos /* 307 1.1 jklos * HW counts Rx/Tx unicast frames but we want all the frames. 308 1.1 jklos */ 309 1.1 jklos rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames - 310 1.1 jklos mac->stats.rx_bcast_frames; 311 1.1 jklos rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast); 312 1.1 jklos tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames - 313 1.1 jklos mac->stats.tx_bcast_frames; 314 1.1 jklos tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast); 315 1.1 jklos 316 1.1 jklos #define RMON_UPDATE(mac, name, hw_stat) \ 317 1.1 jklos mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name)) 318 1.1 jklos 319 1.1 jklos RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]); 320 1.1 jklos RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]); 321 1.1 jklos RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]); 322 1.1 jklos RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]); 323 1.1 jklos RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]); 324 1.1 jklos RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]); 325 1.1 jklos RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]); 326 1.1 jklos RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]); 327 1.1 jklos RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]); 328 1.1 jklos RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]); 329 1.1 jklos RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]); 330 1.1 jklos RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]); 331 1.1 jklos 332 1.1 jklos RMON_UPDATE(mac, rx_frames_64, stats0[17 - STATS0_START]); 333 1.1 jklos RMON_UPDATE(mac, rx_frames_65_127, stats0[18 - STATS0_START]); 334 1.1 jklos RMON_UPDATE(mac, rx_frames_128_255, stats0[19 - STATS0_START]); 335 1.1 jklos RMON_UPDATE(mac, rx_frames_256_511, stats0[20 - STATS0_START]); 336 1.1 jklos RMON_UPDATE(mac, rx_frames_512_1023, stats0[21 - STATS0_START]); 337 1.1 jklos RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]); 338 1.1 jklos RMON_UPDATE(mac, rx_frames_1519_max, stats0[23 - STATS0_START]); 339 1.1 jklos 340 1.1 jklos RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]); 341 1.1 jklos RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]); 342 1.1 jklos RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]); 343 1.1 jklos RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]); 344 1.1 jklos RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]); 345 1.1 jklos RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]); 346 1.1 jklos RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]); 347 1.1 jklos 348 1.1 jklos RMON_UPDATE(mac, tx_underrun, 0); 349 1.1 jklos 350 1.1 jklos RMON_UPDATE(mac, tx_frames_64, stats1[36 - STATS1_START]); 351 1.1 jklos RMON_UPDATE(mac, tx_frames_65_127, stats1[37 - STATS1_START]); 352 1.1 jklos RMON_UPDATE(mac, tx_frames_128_255, stats1[38 - STATS1_START]); 353 1.1 jklos RMON_UPDATE(mac, tx_frames_256_511, stats1[39 - STATS1_START]); 354 1.1 jklos RMON_UPDATE(mac, tx_frames_512_1023, stats1[40 - STATS1_START]); 355 1.1 jklos RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]); 356 1.1 jklos RMON_UPDATE(mac, tx_frames_1519_max, stats1[42 - STATS1_START]); 357 1.1 jklos 358 1.1 jklos #undef RMON_UPDATE 359 1.1 jklos 360 1.1 jklos mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames + 361 1.1 jklos mac->stats.rx_bcast_frames; 362 1.1 jklos mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames + 363 1.1 jklos mac->stats.tx_bcast_frames; 364 1.1 jklos out: return &mac->stats; 365 1.1 jklos } 366