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