linux/drivers/net/ethernet/chelsio/cxgb/vsc7326.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* $Date: 2006/04/28 19:20:06 $ $RCSfile: vsc7326.c,v $ $Revision: 1.19 $ */
   3
   4/* Driver for Vitesse VSC7326 (Schaumburg) MAC */
   5
   6#include "gmac.h"
   7#include "elmer0.h"
   8#include "vsc7326_reg.h"
   9
  10/* Update fast changing statistics every 15 seconds */
  11#define STATS_TICK_SECS 15
  12/* 30 minutes for full statistics update */
  13#define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
  14
  15/* The egress WM value 0x01a01fff should be used only when the
  16 * interface is down (MAC port disabled). This is a workaround
  17 * for disabling the T2/MAC flow-control. When the interface is
  18 * enabled, the WM value should be set to 0x014a03F0.
  19 */
  20#define WM_DISABLE      0x01a01fff
  21#define WM_ENABLE       0x014a03F0
  22
  23struct init_table {
  24        u32 addr;
  25        u32 data;
  26};
  27
  28struct _cmac_instance {
  29        u32 index;
  30        u32 ticks;
  31};
  32
  33#define INITBLOCK_SLEEP 0xffffffff
  34
  35static void vsc_read(adapter_t *adapter, u32 addr, u32 *val)
  36{
  37        u32 status, vlo, vhi;
  38        int i;
  39
  40        spin_lock_bh(&adapter->mac_lock);
  41        t1_tpi_read(adapter, (addr << 2) + 4, &vlo);
  42        i = 0;
  43        do {
  44                t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
  45                t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
  46                status = (vhi << 16) | vlo;
  47                i++;
  48        } while (((status & 1) == 0) && (i < 50));
  49        if (i == 50)
  50                pr_err("Invalid tpi read from MAC, breaking loop.\n");
  51
  52        t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo);
  53        t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi);
  54
  55        *val = (vhi << 16) | vlo;
  56
  57        /* pr_err("rd: block: 0x%x  sublock: 0x%x  reg: 0x%x  data: 0x%x\n",
  58                ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
  59                ((addr&0x01fe)>>1), *val); */
  60        spin_unlock_bh(&adapter->mac_lock);
  61}
  62
  63static void vsc_write(adapter_t *adapter, u32 addr, u32 data)
  64{
  65        spin_lock_bh(&adapter->mac_lock);
  66        t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF);
  67        t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF);
  68        /* pr_err("wr: block: 0x%x  sublock: 0x%x  reg: 0x%x  data: 0x%x\n",
  69                ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
  70                ((addr&0x01fe)>>1), data); */
  71        spin_unlock_bh(&adapter->mac_lock);
  72}
  73
  74/* Hard reset the MAC.  This wipes out *all* configuration. */
  75static void vsc7326_full_reset(adapter_t* adapter)
  76{
  77        u32 val;
  78        u32 result = 0xffff;
  79
  80        t1_tpi_read(adapter, A_ELMER0_GPO, &val);
  81        val &= ~1;
  82        t1_tpi_write(adapter, A_ELMER0_GPO, val);
  83        udelay(2);
  84        val |= 0x1;     /* Enable mac MAC itself */
  85        val |= 0x800;   /* Turn off the red LED */
  86        t1_tpi_write(adapter, A_ELMER0_GPO, val);
  87        mdelay(1);
  88        vsc_write(adapter, REG_SW_RESET, 0x80000001);
  89        do {
  90                mdelay(1);
  91                vsc_read(adapter, REG_SW_RESET, &result);
  92        } while (result != 0x0);
  93}
  94
  95static struct init_table vsc7326_reset[] = {
  96        {      REG_IFACE_MODE, 0x00000000 },
  97        {         REG_CRC_CFG, 0x00000020 },
  98        {   REG_PLL_CLK_SPEED, 0x00050c00 },
  99        {   REG_PLL_CLK_SPEED, 0x00050c00 },
 100        {            REG_MSCH, 0x00002f14 },
 101        {       REG_SPI4_MISC, 0x00040409 },
 102        {     REG_SPI4_DESKEW, 0x00080000 },
 103        { REG_SPI4_ING_SETUP2, 0x08080004 },
 104        { REG_SPI4_ING_SETUP0, 0x04111004 },
 105        { REG_SPI4_EGR_SETUP0, 0x80001a04 },
 106        { REG_SPI4_ING_SETUP1, 0x02010000 },
 107        {      REG_AGE_INC(0), 0x00000000 },
 108        {      REG_AGE_INC(1), 0x00000000 },
 109        {     REG_ING_CONTROL, 0x0a200011 },
 110        {     REG_EGR_CONTROL, 0xa0010091 },
 111};
 112
 113static struct init_table vsc7326_portinit[4][22] = {
 114        {       /* Port 0 */
 115                        /* FIFO setup */
 116                {           REG_DBG(0), 0x000004f0 },
 117                {           REG_HDX(0), 0x00073101 },
 118                {        REG_TEST(0,0), 0x00000022 },
 119                {        REG_TEST(1,0), 0x00000022 },
 120                {  REG_TOP_BOTTOM(0,0), 0x003f0000 },
 121                {  REG_TOP_BOTTOM(1,0), 0x00120000 },
 122                { REG_HIGH_LOW_WM(0,0), 0x07460757 },
 123                { REG_HIGH_LOW_WM(1,0), WM_DISABLE },
 124                {   REG_CT_THRHLD(0,0), 0x00000000 },
 125                {   REG_CT_THRHLD(1,0), 0x00000000 },
 126                {         REG_BUCKE(0), 0x0002ffff },
 127                {         REG_BUCKI(0), 0x0002ffff },
 128                {        REG_TEST(0,0), 0x00000020 },
 129                {        REG_TEST(1,0), 0x00000020 },
 130                        /* Port config */
 131                {       REG_MAX_LEN(0), 0x00002710 },
 132                {     REG_PORT_FAIL(0), 0x00000002 },
 133                {    REG_NORMALIZER(0), 0x00000a64 },
 134                {        REG_DENORM(0), 0x00000010 },
 135                {     REG_STICK_BIT(0), 0x03baa370 },
 136                {     REG_DEV_SETUP(0), 0x00000083 },
 137                {     REG_DEV_SETUP(0), 0x00000082 },
 138                {      REG_MODE_CFG(0), 0x0200259f },
 139        },
 140        {       /* Port 1 */
 141                        /* FIFO setup */
 142                {           REG_DBG(1), 0x000004f0 },
 143                {           REG_HDX(1), 0x00073101 },
 144                {        REG_TEST(0,1), 0x00000022 },
 145                {        REG_TEST(1,1), 0x00000022 },
 146                {  REG_TOP_BOTTOM(0,1), 0x007e003f },
 147                {  REG_TOP_BOTTOM(1,1), 0x00240012 },
 148                { REG_HIGH_LOW_WM(0,1), 0x07460757 },
 149                { REG_HIGH_LOW_WM(1,1), WM_DISABLE },
 150                {   REG_CT_THRHLD(0,1), 0x00000000 },
 151                {   REG_CT_THRHLD(1,1), 0x00000000 },
 152                {         REG_BUCKE(1), 0x0002ffff },
 153                {         REG_BUCKI(1), 0x0002ffff },
 154                {        REG_TEST(0,1), 0x00000020 },
 155                {        REG_TEST(1,1), 0x00000020 },
 156                        /* Port config */
 157                {       REG_MAX_LEN(1), 0x00002710 },
 158                {     REG_PORT_FAIL(1), 0x00000002 },
 159                {    REG_NORMALIZER(1), 0x00000a64 },
 160                {        REG_DENORM(1), 0x00000010 },
 161                {     REG_STICK_BIT(1), 0x03baa370 },
 162                {     REG_DEV_SETUP(1), 0x00000083 },
 163                {     REG_DEV_SETUP(1), 0x00000082 },
 164                {      REG_MODE_CFG(1), 0x0200259f },
 165        },
 166        {       /* Port 2 */
 167                        /* FIFO setup */
 168                {           REG_DBG(2), 0x000004f0 },
 169                {           REG_HDX(2), 0x00073101 },
 170                {        REG_TEST(0,2), 0x00000022 },
 171                {        REG_TEST(1,2), 0x00000022 },
 172                {  REG_TOP_BOTTOM(0,2), 0x00bd007e },
 173                {  REG_TOP_BOTTOM(1,2), 0x00360024 },
 174                { REG_HIGH_LOW_WM(0,2), 0x07460757 },
 175                { REG_HIGH_LOW_WM(1,2), WM_DISABLE },
 176                {   REG_CT_THRHLD(0,2), 0x00000000 },
 177                {   REG_CT_THRHLD(1,2), 0x00000000 },
 178                {         REG_BUCKE(2), 0x0002ffff },
 179                {         REG_BUCKI(2), 0x0002ffff },
 180                {        REG_TEST(0,2), 0x00000020 },
 181                {        REG_TEST(1,2), 0x00000020 },
 182                        /* Port config */
 183                {       REG_MAX_LEN(2), 0x00002710 },
 184                {     REG_PORT_FAIL(2), 0x00000002 },
 185                {    REG_NORMALIZER(2), 0x00000a64 },
 186                {        REG_DENORM(2), 0x00000010 },
 187                {     REG_STICK_BIT(2), 0x03baa370 },
 188                {     REG_DEV_SETUP(2), 0x00000083 },
 189                {     REG_DEV_SETUP(2), 0x00000082 },
 190                {      REG_MODE_CFG(2), 0x0200259f },
 191        },
 192        {       /* Port 3 */
 193                        /* FIFO setup */
 194                {           REG_DBG(3), 0x000004f0 },
 195                {           REG_HDX(3), 0x00073101 },
 196                {        REG_TEST(0,3), 0x00000022 },
 197                {        REG_TEST(1,3), 0x00000022 },
 198                {  REG_TOP_BOTTOM(0,3), 0x00fc00bd },
 199                {  REG_TOP_BOTTOM(1,3), 0x00480036 },
 200                { REG_HIGH_LOW_WM(0,3), 0x07460757 },
 201                { REG_HIGH_LOW_WM(1,3), WM_DISABLE },
 202                {   REG_CT_THRHLD(0,3), 0x00000000 },
 203                {   REG_CT_THRHLD(1,3), 0x00000000 },
 204                {         REG_BUCKE(3), 0x0002ffff },
 205                {         REG_BUCKI(3), 0x0002ffff },
 206                {        REG_TEST(0,3), 0x00000020 },
 207                {        REG_TEST(1,3), 0x00000020 },
 208                        /* Port config */
 209                {       REG_MAX_LEN(3), 0x00002710 },
 210                {     REG_PORT_FAIL(3), 0x00000002 },
 211                {    REG_NORMALIZER(3), 0x00000a64 },
 212                {        REG_DENORM(3), 0x00000010 },
 213                {     REG_STICK_BIT(3), 0x03baa370 },
 214                {     REG_DEV_SETUP(3), 0x00000083 },
 215                {     REG_DEV_SETUP(3), 0x00000082 },
 216                {      REG_MODE_CFG(3), 0x0200259f },
 217        },
 218};
 219
 220static void run_table(adapter_t *adapter, struct init_table *ib, int len)
 221{
 222        int i;
 223
 224        for (i = 0; i < len; i++) {
 225                if (ib[i].addr == INITBLOCK_SLEEP) {
 226                        udelay( ib[i].data );
 227                        pr_err("sleep %d us\n",ib[i].data);
 228                } else
 229                        vsc_write( adapter, ib[i].addr, ib[i].data );
 230        }
 231}
 232
 233static int bist_rd(adapter_t *adapter, int moduleid, int address)
 234{
 235        int data = 0;
 236        u32 result = 0;
 237
 238        if ((address != 0x0) &&
 239            (address != 0x1) &&
 240            (address != 0x2) &&
 241            (address != 0xd) &&
 242            (address != 0xe))
 243                        pr_err("No bist address: 0x%x\n", address);
 244
 245        data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) |
 246                ((moduleid & 0xff) << 0));
 247        vsc_write(adapter, REG_RAM_BIST_CMD, data);
 248
 249        udelay(10);
 250
 251        vsc_read(adapter, REG_RAM_BIST_RESULT, &result);
 252        if ((result & (1 << 9)) != 0x0)
 253                pr_err("Still in bist read: 0x%x\n", result);
 254        else if ((result & (1 << 8)) != 0x0)
 255                pr_err("bist read error: 0x%x\n", result);
 256
 257        return result & 0xff;
 258}
 259
 260static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
 261{
 262        int data = 0;
 263        u32 result = 0;
 264
 265        if ((address != 0x0) &&
 266            (address != 0x1) &&
 267            (address != 0x2) &&
 268            (address != 0xd) &&
 269            (address != 0xe))
 270                        pr_err("No bist address: 0x%x\n", address);
 271
 272        if (value > 255)
 273                pr_err("Suspicious write out of range value: 0x%x\n", value);
 274
 275        data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) |
 276                ((moduleid & 0xff) << 0));
 277        vsc_write(adapter, REG_RAM_BIST_CMD, data);
 278
 279        udelay(5);
 280
 281        vsc_read(adapter, REG_RAM_BIST_CMD, &result);
 282        if ((result & (1 << 27)) != 0x0)
 283                pr_err("Still in bist write: 0x%x\n", result);
 284        else if ((result & (1 << 26)) != 0x0)
 285                pr_err("bist write error: 0x%x\n", result);
 286
 287        return 0;
 288}
 289
 290static int run_bist(adapter_t *adapter, int moduleid)
 291{
 292        /*run bist*/
 293        (void) bist_wr(adapter,moduleid, 0x00, 0x02);
 294        (void) bist_wr(adapter,moduleid, 0x01, 0x01);
 295
 296        return 0;
 297}
 298
 299static int check_bist(adapter_t *adapter, int moduleid)
 300{
 301        int result=0;
 302        int column=0;
 303        /*check bist*/
 304        result = bist_rd(adapter,moduleid, 0x02);
 305        column = ((bist_rd(adapter,moduleid, 0x0e)<<8) +
 306                        (bist_rd(adapter,moduleid, 0x0d)));
 307        if ((result & 3) != 0x3)
 308                pr_err("Result: 0x%x  BIST error in ram %d, column: 0x%04x\n",
 309                        result, moduleid, column);
 310        return 0;
 311}
 312
 313static int enable_mem(adapter_t *adapter, int moduleid)
 314{
 315        /*enable mem*/
 316        (void) bist_wr(adapter,moduleid, 0x00, 0x00);
 317        return 0;
 318}
 319
 320static int run_bist_all(adapter_t *adapter)
 321{
 322        int port = 0;
 323        u32 val = 0;
 324
 325        vsc_write(adapter, REG_MEM_BIST, 0x5);
 326        vsc_read(adapter, REG_MEM_BIST, &val);
 327
 328        for (port = 0; port < 12; port++)
 329                vsc_write(adapter, REG_DEV_SETUP(port), 0x0);
 330
 331        udelay(300);
 332        vsc_write(adapter, REG_SPI4_MISC, 0x00040409);
 333        udelay(300);
 334
 335        (void) run_bist(adapter,13);
 336        (void) run_bist(adapter,14);
 337        (void) run_bist(adapter,20);
 338        (void) run_bist(adapter,21);
 339        mdelay(200);
 340        (void) check_bist(adapter,13);
 341        (void) check_bist(adapter,14);
 342        (void) check_bist(adapter,20);
 343        (void) check_bist(adapter,21);
 344        udelay(100);
 345        (void) enable_mem(adapter,13);
 346        (void) enable_mem(adapter,14);
 347        (void) enable_mem(adapter,20);
 348        (void) enable_mem(adapter,21);
 349        udelay(300);
 350        vsc_write(adapter, REG_SPI4_MISC, 0x60040400);
 351        udelay(300);
 352        for (port = 0; port < 12; port++)
 353                vsc_write(adapter, REG_DEV_SETUP(port), 0x1);
 354
 355        udelay(300);
 356        vsc_write(adapter, REG_MEM_BIST, 0x0);
 357        mdelay(10);
 358        return 0;
 359}
 360
 361static int mac_intr_handler(struct cmac *mac)
 362{
 363        return 0;
 364}
 365
 366static int mac_intr_enable(struct cmac *mac)
 367{
 368        return 0;
 369}
 370
 371static int mac_intr_disable(struct cmac *mac)
 372{
 373        return 0;
 374}
 375
 376static int mac_intr_clear(struct cmac *mac)
 377{
 378        return 0;
 379}
 380
 381/* Expect MAC address to be in network byte order. */
 382static int mac_set_address(struct cmac* mac, u8 addr[6])
 383{
 384        u32 val;
 385        int port = mac->instance->index;
 386
 387        vsc_write(mac->adapter, REG_MAC_LOW_ADDR(port),
 388                  (addr[3] << 16) | (addr[4] << 8) | addr[5]);
 389        vsc_write(mac->adapter, REG_MAC_HIGH_ADDR(port),
 390                  (addr[0] << 16) | (addr[1] << 8) | addr[2]);
 391
 392        vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val);
 393        val &= ~0xf0000000;
 394        vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28));
 395
 396        vsc_write(mac->adapter, REG_ING_FFILT_MASK0,
 397                  0xffff0000 | (addr[4] << 8) | addr[5]);
 398        vsc_write(mac->adapter, REG_ING_FFILT_MASK1,
 399                  0xffff0000 | (addr[2] << 8) | addr[3]);
 400        vsc_write(mac->adapter, REG_ING_FFILT_MASK2,
 401                  0xffff0000 | (addr[0] << 8) | addr[1]);
 402        return 0;
 403}
 404
 405static int mac_get_address(struct cmac *mac, u8 addr[6])
 406{
 407        u32 addr_lo, addr_hi;
 408        int port = mac->instance->index;
 409
 410        vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo);
 411        vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi);
 412
 413        addr[0] = (u8) (addr_hi >> 16);
 414        addr[1] = (u8) (addr_hi >> 8);
 415        addr[2] = (u8) addr_hi;
 416        addr[3] = (u8) (addr_lo >> 16);
 417        addr[4] = (u8) (addr_lo >> 8);
 418        addr[5] = (u8) addr_lo;
 419        return 0;
 420}
 421
 422/* This is intended to reset a port, not the whole MAC */
 423static int mac_reset(struct cmac *mac)
 424{
 425        int index = mac->instance->index;
 426
 427        run_table(mac->adapter, vsc7326_portinit[index],
 428                  ARRAY_SIZE(vsc7326_portinit[index]));
 429
 430        return 0;
 431}
 432
 433static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
 434{
 435        u32 v;
 436        int port = mac->instance->index;
 437
 438        vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v);
 439        v |= 1 << 12;
 440
 441        if (t1_rx_mode_promisc(rm))
 442                v &= ~(1 << (port + 16));
 443        else
 444                v |= 1 << (port + 16);
 445
 446        vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v);
 447        return 0;
 448}
 449
 450static int mac_set_mtu(struct cmac *mac, int mtu)
 451{
 452        int port = mac->instance->index;
 453
 454        /* max_len includes header and FCS */
 455        vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4);
 456        return 0;
 457}
 458
 459static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
 460                                   int fc)
 461{
 462        u32 v;
 463        int enable, port = mac->instance->index;
 464
 465        if (speed >= 0 && speed != SPEED_10 && speed != SPEED_100 &&
 466            speed != SPEED_1000)
 467                return -1;
 468        if (duplex > 0 && duplex != DUPLEX_FULL)
 469                return -1;
 470
 471        if (speed >= 0) {
 472                vsc_read(mac->adapter, REG_MODE_CFG(port), &v);
 473                enable = v & 3;             /* save tx/rx enables */
 474                v &= ~0xf;
 475                v |= 4;                     /* full duplex */
 476                if (speed == SPEED_1000)
 477                        v |= 8;             /* GigE */
 478                enable |= v;
 479                vsc_write(mac->adapter, REG_MODE_CFG(port), v);
 480
 481                if (speed == SPEED_1000)
 482                        v = 0x82;
 483                else if (speed == SPEED_100)
 484                        v = 0x84;
 485                else    /* SPEED_10 */
 486                        v = 0x86;
 487                vsc_write(mac->adapter, REG_DEV_SETUP(port), v | 1); /* reset */
 488                vsc_write(mac->adapter, REG_DEV_SETUP(port), v);
 489                vsc_read(mac->adapter, REG_DBG(port), &v);
 490                v &= ~0xff00;
 491                if (speed == SPEED_1000)
 492                        v |= 0x400;
 493                else if (speed == SPEED_100)
 494                        v |= 0x2000;
 495                else    /* SPEED_10 */
 496                        v |= 0xff00;
 497                vsc_write(mac->adapter, REG_DBG(port), v);
 498
 499                vsc_write(mac->adapter, REG_TX_IFG(port),
 500                          speed == SPEED_1000 ? 5 : 0x11);
 501                if (duplex == DUPLEX_HALF)
 502                        enable = 0x0;   /* 100 or 10 */
 503                else if (speed == SPEED_1000)
 504                        enable = 0xc;
 505                else    /* SPEED_100 or 10 */
 506                        enable = 0x4;
 507                enable |= 0x9 << 10;    /* IFG1 */
 508                enable |= 0x6 << 6;     /* IFG2 */
 509                enable |= 0x1 << 4;     /* VLAN */
 510                enable |= 0x3;          /* RX/TX EN */
 511                vsc_write(mac->adapter, REG_MODE_CFG(port), enable);
 512
 513        }
 514
 515        vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v);
 516        v &= 0xfff0ffff;
 517        v |= 0x20000;      /* xon/xoff */
 518        if (fc & PAUSE_RX)
 519                v |= 0x40000;
 520        if (fc & PAUSE_TX)
 521                v |= 0x80000;
 522        if (fc == (PAUSE_RX | PAUSE_TX))
 523                v |= 0x10000;
 524        vsc_write(mac->adapter, REG_PAUSE_CFG(port), v);
 525        return 0;
 526}
 527
 528static int mac_enable(struct cmac *mac, int which)
 529{
 530        u32 val;
 531        int port = mac->instance->index;
 532
 533        /* Write the correct WM value when the port is enabled. */
 534        vsc_write(mac->adapter, REG_HIGH_LOW_WM(1,port), WM_ENABLE);
 535
 536        vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
 537        if (which & MAC_DIRECTION_RX)
 538                val |= 0x2;
 539        if (which & MAC_DIRECTION_TX)
 540                val |= 1;
 541        vsc_write(mac->adapter, REG_MODE_CFG(port), val);
 542        return 0;
 543}
 544
 545static int mac_disable(struct cmac *mac, int which)
 546{
 547        u32 val;
 548        int i, port = mac->instance->index;
 549
 550        /* Reset the port, this also writes the correct WM value */
 551        mac_reset(mac);
 552
 553        vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
 554        if (which & MAC_DIRECTION_RX)
 555                val &= ~0x2;
 556        if (which & MAC_DIRECTION_TX)
 557                val &= ~0x1;
 558        vsc_write(mac->adapter, REG_MODE_CFG(port), val);
 559        vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
 560
 561        /* Clear stats */
 562        for (i = 0; i <= 0x3a; ++i)
 563                vsc_write(mac->adapter, CRA(4, port, i), 0);
 564
 565        /* Clear software counters */
 566        memset(&mac->stats, 0, sizeof(struct cmac_statistics));
 567
 568        return 0;
 569}
 570
 571static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat)
 572{
 573        u32 v, lo;
 574
 575        vsc_read(mac->adapter, addr, &v);
 576        lo = *stat;
 577        *stat = *stat - lo + v;
 578
 579        if (v == 0)
 580                return;
 581
 582        if (v < lo)
 583                *stat += (1ULL << 32);
 584}
 585
 586static void port_stats_update(struct cmac *mac)
 587{
 588        struct {
 589                unsigned int reg;
 590                unsigned int offset;
 591        } hw_stats[] = {
 592
 593#define HW_STAT(reg, stat_name) \
 594        { reg, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL }
 595
 596                /* Rx stats */
 597                HW_STAT(RxUnicast, RxUnicastFramesOK),
 598                HW_STAT(RxMulticast, RxMulticastFramesOK),
 599                HW_STAT(RxBroadcast, RxBroadcastFramesOK),
 600                HW_STAT(Crc, RxFCSErrors),
 601                HW_STAT(RxAlignment, RxAlignErrors),
 602                HW_STAT(RxOversize, RxFrameTooLongErrors),
 603                HW_STAT(RxPause, RxPauseFrames),
 604                HW_STAT(RxJabbers, RxJabberErrors),
 605                HW_STAT(RxFragments, RxRuntErrors),
 606                HW_STAT(RxUndersize, RxRuntErrors),
 607                HW_STAT(RxSymbolCarrier, RxSymbolErrors),
 608                HW_STAT(RxSize1519ToMax, RxJumboFramesOK),
 609
 610                /* Tx stats (skip collision stats as we are full-duplex only) */
 611                HW_STAT(TxUnicast, TxUnicastFramesOK),
 612                HW_STAT(TxMulticast, TxMulticastFramesOK),
 613                HW_STAT(TxBroadcast, TxBroadcastFramesOK),
 614                HW_STAT(TxPause, TxPauseFrames),
 615                HW_STAT(TxUnderrun, TxUnderrun),
 616                HW_STAT(TxSize1519ToMax, TxJumboFramesOK),
 617        }, *p = hw_stats;
 618        unsigned int port = mac->instance->index;
 619        u64 *stats = (u64 *)&mac->stats;
 620        unsigned int i;
 621
 622        for (i = 0; i < ARRAY_SIZE(hw_stats); i++)
 623                rmon_update(mac, CRA(0x4, port, p->reg), stats + p->offset);
 624
 625        rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK);
 626        rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK);
 627        rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad);
 628}
 629
 630/*
 631 * This function is called periodically to accumulate the current values of the
 632 * RMON counters into the port statistics.  Since the counters are only 32 bits
 633 * some of them can overflow in less than a minute at GigE speeds, so this
 634 * function should be called every 30 seconds or so.
 635 *
 636 * To cut down on reading costs we update only the octet counters at each tick
 637 * and do a full update at major ticks, which can be every 30 minutes or more.
 638 */
 639static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
 640                                                           int flag)
 641{
 642        if (flag == MAC_STATS_UPDATE_FULL ||
 643            mac->instance->ticks >= MAJOR_UPDATE_TICKS) {
 644                port_stats_update(mac);
 645                mac->instance->ticks = 0;
 646        } else {
 647                int port = mac->instance->index;
 648
 649                rmon_update(mac, REG_RX_OK_BYTES(port),
 650                            &mac->stats.RxOctetsOK);
 651                rmon_update(mac, REG_RX_BAD_BYTES(port),
 652                            &mac->stats.RxOctetsBad);
 653                rmon_update(mac, REG_TX_OK_BYTES(port),
 654                            &mac->stats.TxOctetsOK);
 655                mac->instance->ticks++;
 656        }
 657        return &mac->stats;
 658}
 659
 660static void mac_destroy(struct cmac *mac)
 661{
 662        kfree(mac);
 663}
 664
 665static const struct cmac_ops vsc7326_ops = {
 666        .destroy                  = mac_destroy,
 667        .reset                    = mac_reset,
 668        .interrupt_handler        = mac_intr_handler,
 669        .interrupt_enable         = mac_intr_enable,
 670        .interrupt_disable        = mac_intr_disable,
 671        .interrupt_clear          = mac_intr_clear,
 672        .enable                   = mac_enable,
 673        .disable                  = mac_disable,
 674        .set_mtu                  = mac_set_mtu,
 675        .set_rx_mode              = mac_set_rx_mode,
 676        .set_speed_duplex_fc      = mac_set_speed_duplex_fc,
 677        .statistics_update        = mac_update_statistics,
 678        .macaddress_get           = mac_get_address,
 679        .macaddress_set           = mac_set_address,
 680};
 681
 682static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index)
 683{
 684        struct cmac *mac;
 685        u32 val;
 686        int i;
 687
 688        mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
 689        if (!mac)
 690                return NULL;
 691
 692        mac->ops = &vsc7326_ops;
 693        mac->instance = (cmac_instance *)(mac + 1);
 694        mac->adapter  = adapter;
 695
 696        mac->instance->index = index;
 697        mac->instance->ticks = 0;
 698
 699        i = 0;
 700        do {
 701                u32 vhi, vlo;
 702
 703                vhi = vlo = 0;
 704                t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
 705                udelay(1);
 706                t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
 707                udelay(5);
 708                val = (vhi << 16) | vlo;
 709        } while ((++i < 10000) && (val == 0xffffffff));
 710
 711        return mac;
 712}
 713
 714static int vsc7326_mac_reset(adapter_t *adapter)
 715{
 716        vsc7326_full_reset(adapter);
 717        (void) run_bist_all(adapter);
 718        run_table(adapter, vsc7326_reset, ARRAY_SIZE(vsc7326_reset));
 719        return 0;
 720}
 721
 722const struct gmac t1_vsc7326_ops = {
 723        .stats_update_period = STATS_TICK_SECS,
 724        .create              = vsc7326_mac_create,
 725        .reset               = vsc7326_mac_reset,
 726};
 727