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