1*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 2*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi.c: A U-Boot driver for the NatSemi DP8381x series. 3*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Author: Mark A. Rakes (mark_rakes@vivato.net) 4*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 5*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Adapted from an Etherboot driver written by: 6*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 7*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Copyright (C) 2001 Entity Cyber, Inc. 8*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 9*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This development of this Etherboot driver was funded by 10*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 11*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Sicom Systems: http://www.sicompos.com/ 12*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 13*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Author: Marty Connor (mdc@thinguin.org) 14*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Adapted from a Linux driver which was written by Donald Becker 15*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 16*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This software may be used and distributed according to the terms 17*2439e4bfSJean-Christophe PLAGNIOL-VILLARD of the GNU Public License (GPL), incorporated herein by reference. 18*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 19*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Original Copyright Notice: 20*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 21*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Written/copyright 1999-2001 by Donald Becker. 22*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 23*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This software may be used and distributed according to the terms of 24*2439e4bfSJean-Christophe PLAGNIOL-VILLARD the GNU General Public License (GPL), incorporated herein by reference. 25*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Drivers based on or derived from this code fall under the GPL and must 26*2439e4bfSJean-Christophe PLAGNIOL-VILLARD retain the authorship, copyright and license notice. This file is not 27*2439e4bfSJean-Christophe PLAGNIOL-VILLARD a complete program and may only be used when the entire operating 28*2439e4bfSJean-Christophe PLAGNIOL-VILLARD system is licensed under the GPL. License for under other terms may be 29*2439e4bfSJean-Christophe PLAGNIOL-VILLARD available. Contact the original author for details. 30*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 31*2439e4bfSJean-Christophe PLAGNIOL-VILLARD The original author may be reached as becker@scyld.com, or at 32*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Scyld Computing Corporation 33*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 410 Severn Ave., Suite 210 34*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Annapolis MD 21403 35*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 36*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Support information and updates available at 37*2439e4bfSJean-Christophe PLAGNIOL-VILLARD http://www.scyld.com/network/netsemi.html 38*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 39*2439e4bfSJean-Christophe PLAGNIOL-VILLARD References: 40*2439e4bfSJean-Christophe PLAGNIOL-VILLARD http://www.scyld.com/expert/100mbps.html 41*2439e4bfSJean-Christophe PLAGNIOL-VILLARD http://www.scyld.com/expert/NWay.html 42*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Datasheet is available from: 43*2439e4bfSJean-Christophe PLAGNIOL-VILLARD http://www.national.com/pf/DP/DP83815.html 44*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 45*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 46*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Revision History 47*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * October 2002 mar 1.0 48*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Initial U-Boot Release. Tested with Netgear FA311 board 49*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * and dp83815 chipset on custom board 50*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 51*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 52*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Includes */ 53*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 54*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h> 55*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h> 56*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 57*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <pci.h> 58*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 59*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_CMD_NET) \ 60*2439e4bfSJean-Christophe PLAGNIOL-VILLARD && defined(CONFIG_NET_MULTI) && defined(CONFIG_NATSEMI) 61*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 62*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* defines */ 63*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/ 64*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 65*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DSIZE 0x00000FFF 66*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define ETH_ALEN 6 67*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CRC_SIZE 4 68*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TOUT_LOOP 500000 69*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_BUF_SIZE 1536 70*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_BUF_SIZE 1536 71*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */ 72*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 73*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Offsets to the device registers. 74*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Unlike software-only systems, device drivers interact with complex hardware. 75*2439e4bfSJean-Christophe PLAGNIOL-VILLARD It's not useful to define symbolic names for every register bit in the 76*2439e4bfSJean-Christophe PLAGNIOL-VILLARD device. */ 77*2439e4bfSJean-Christophe PLAGNIOL-VILLARD enum register_offsets { 78*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ChipCmd = 0x00, 79*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ChipConfig = 0x04, 80*2439e4bfSJean-Christophe PLAGNIOL-VILLARD EECtrl = 0x08, 81*2439e4bfSJean-Christophe PLAGNIOL-VILLARD IntrMask = 0x14, 82*2439e4bfSJean-Christophe PLAGNIOL-VILLARD IntrEnable = 0x18, 83*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxRingPtr = 0x20, 84*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxConfig = 0x24, 85*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxRingPtr = 0x30, 86*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxConfig = 0x34, 87*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ClkRun = 0x3C, 88*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxFilterAddr = 0x48, 89*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxFilterData = 0x4C, 90*2439e4bfSJean-Christophe PLAGNIOL-VILLARD SiliconRev = 0x58, 91*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PCIPM = 0x44, 92*2439e4bfSJean-Christophe PLAGNIOL-VILLARD BasicControl = 0x80, 93*2439e4bfSJean-Christophe PLAGNIOL-VILLARD BasicStatus = 0x84, 94*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* These are from the spec, around page 78... on a separate table. */ 95*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PGSEL = 0xCC, 96*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PMDCSR = 0xE4, 97*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TSTDAT = 0xFC, 98*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DSPCFG = 0xF4, 99*2439e4bfSJean-Christophe PLAGNIOL-VILLARD SDCFG = 0x8C 100*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 101*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 102*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Bit in ChipCmd. */ 103*2439e4bfSJean-Christophe PLAGNIOL-VILLARD enum ChipCmdBits { 104*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ChipReset = 0x100, 105*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxReset = 0x20, 106*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxReset = 0x10, 107*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxOff = 0x08, 108*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxOn = 0x04, 109*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxOff = 0x02, 110*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxOn = 0x01 111*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 112*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 113*2439e4bfSJean-Christophe PLAGNIOL-VILLARD enum ChipConfigBits { 114*2439e4bfSJean-Christophe PLAGNIOL-VILLARD LinkSts = 0x80000000, 115*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HundSpeed = 0x40000000, 116*2439e4bfSJean-Christophe PLAGNIOL-VILLARD FullDuplex = 0x20000000, 117*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TenPolarity = 0x10000000, 118*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegDone = 0x08000000, 119*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegEnBothBoth = 0x0000E000, 120*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegDis100Full = 0x0000C000, 121*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegEn100Both = 0x0000A000, 122*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegDis100Half = 0x00008000, 123*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegEnBothHalf = 0x00006000, 124*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegDis10Full = 0x00004000, 125*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegEn10Both = 0x00002000, 126*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DuplexMask = 0x00008000, 127*2439e4bfSJean-Christophe PLAGNIOL-VILLARD SpeedMask = 0x00004000, 128*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegMask = 0x00002000, 129*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AnegDis10Half = 0x00000000, 130*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ExtPhy = 0x00001000, 131*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PhyRst = 0x00000400, 132*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PhyDis = 0x00000200, 133*2439e4bfSJean-Christophe PLAGNIOL-VILLARD BootRomDisable = 0x00000004, 134*2439e4bfSJean-Christophe PLAGNIOL-VILLARD BEMode = 0x00000001, 135*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 136*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 137*2439e4bfSJean-Christophe PLAGNIOL-VILLARD enum TxConfig_bits { 138*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxDrthMask = 0x3f, 139*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxFlthMask = 0x3f00, 140*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMxdmaMask = 0x700000, 141*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMxdma_512 = 0x0, 142*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMxdma_4 = 0x100000, 143*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMxdma_8 = 0x200000, 144*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMxdma_16 = 0x300000, 145*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMxdma_32 = 0x400000, 146*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMxdma_64 = 0x500000, 147*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMxdma_128 = 0x600000, 148*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMxdma_256 = 0x700000, 149*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxCollRetry = 0x800000, 150*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxAutoPad = 0x10000000, 151*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxMacLoop = 0x20000000, 152*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxHeartIgn = 0x40000000, 153*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxCarrierIgn = 0x80000000 154*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 155*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 156*2439e4bfSJean-Christophe PLAGNIOL-VILLARD enum RxConfig_bits { 157*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxDrthMask = 0x3e, 158*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxMxdmaMask = 0x700000, 159*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxMxdma_512 = 0x0, 160*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxMxdma_4 = 0x100000, 161*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxMxdma_8 = 0x200000, 162*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxMxdma_16 = 0x300000, 163*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxMxdma_32 = 0x400000, 164*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxMxdma_64 = 0x500000, 165*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxMxdma_128 = 0x600000, 166*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxMxdma_256 = 0x700000, 167*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxAcceptLong = 0x8000000, 168*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxAcceptTx = 0x10000000, 169*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxAcceptRunt = 0x40000000, 170*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxAcceptErr = 0x80000000 171*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 172*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 173*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Bits in the RxMode register. */ 174*2439e4bfSJean-Christophe PLAGNIOL-VILLARD enum rx_mode_bits { 175*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AcceptErr = 0x20, 176*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AcceptRunt = 0x10, 177*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AcceptBroadcast = 0xC0000000, 178*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AcceptMulticast = 0x00200000, 179*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AcceptAllMulticast = 0x20000000, 180*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AcceptAllPhys = 0x10000000, 181*2439e4bfSJean-Christophe PLAGNIOL-VILLARD AcceptMyPhys = 0x08000000 182*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 183*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 184*2439e4bfSJean-Christophe PLAGNIOL-VILLARD typedef struct _BufferDesc { 185*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 link; 186*2439e4bfSJean-Christophe PLAGNIOL-VILLARD vu_long cmdsts; 187*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 bufptr; 188*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 software_use; 189*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } BufferDesc; 190*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 191*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Bits in network_desc.status */ 192*2439e4bfSJean-Christophe PLAGNIOL-VILLARD enum desc_status_bits { 193*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescOwn = 0x80000000, DescMore = 0x40000000, DescIntr = 0x20000000, 194*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescNoCRC = 0x10000000, DescPktOK = 0x08000000, 195*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescSizeMask = 0xfff, 196*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 197*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescTxAbort = 0x04000000, DescTxFIFO = 0x02000000, 198*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescTxCarrier = 0x01000000, DescTxDefer = 0x00800000, 199*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescTxExcDefer = 0x00400000, DescTxOOWCol = 0x00200000, 200*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescTxExcColl = 0x00100000, DescTxCollCount = 0x000f0000, 201*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 202*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescRxAbort = 0x04000000, DescRxOver = 0x02000000, 203*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescRxDest = 0x01800000, DescRxLong = 0x00400000, 204*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescRxRunt = 0x00200000, DescRxInvalid = 0x00100000, 205*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescRxCRC = 0x00080000, DescRxAlign = 0x00040000, 206*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DescRxLoop = 0x00020000, DesRxColl = 0x00010000, 207*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 208*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 209*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Globals */ 210*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 211*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int natsemi_debug = 0; /* 1 verbose debugging, 0 normal */ 212*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 213*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static u32 SavedClkRun; 214*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned int cur_rx; 215*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned int advertising; 216*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned int rx_config; 217*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned int tx_config; 218*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 219*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Note: transmit and receive buffers and descriptors must be 220*2439e4bfSJean-Christophe PLAGNIOL-VILLARD longword aligned */ 221*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static BufferDesc txd __attribute__ ((aligned(4))); 222*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(4))); 223*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 224*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(4))); 225*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE] 226*2439e4bfSJean-Christophe PLAGNIOL-VILLARD __attribute__ ((aligned(4))); 227*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 228*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Function Prototypes */ 229*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 230*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void write_eeprom(struct eth_device *dev, long addr, int location, 231*2439e4bfSJean-Christophe PLAGNIOL-VILLARD short value); 232*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 233*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int read_eeprom(struct eth_device *dev, long addr, int location); 234*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int mdio_read(struct eth_device *dev, int phy_id, int location); 235*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int natsemi_init(struct eth_device *dev, bd_t * bis); 236*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void natsemi_reset(struct eth_device *dev); 237*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void natsemi_init_rxfilter(struct eth_device *dev); 238*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void natsemi_init_txd(struct eth_device *dev); 239*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void natsemi_init_rxd(struct eth_device *dev); 240*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void natsemi_set_rx_mode(struct eth_device *dev); 241*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void natsemi_check_duplex(struct eth_device *dev); 242*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int natsemi_send(struct eth_device *dev, volatile void *packet, 243*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int length); 244*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int natsemi_poll(struct eth_device *dev); 245*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void natsemi_disable(struct eth_device *dev); 246*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 247*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct pci_device_id supported[] = { 248*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83815}, 249*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {} 250*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 251*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 252*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) 253*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) 254*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 255*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline int 256*2439e4bfSJean-Christophe PLAGNIOL-VILLARD INW(struct eth_device *dev, u_long addr) 257*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 258*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return le16_to_cpu(*(vu_short *) (addr + dev->iobase)); 259*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 260*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 261*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 262*2439e4bfSJean-Christophe PLAGNIOL-VILLARD INL(struct eth_device *dev, u_long addr) 263*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 264*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return le32_to_cpu(*(vu_long *) (addr + dev->iobase)); 265*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 266*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 267*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void 268*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(struct eth_device *dev, int command, u_long addr) 269*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 270*2439e4bfSJean-Christophe PLAGNIOL-VILLARD *(vu_short *) ((addr + dev->iobase)) = cpu_to_le16(command); 271*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 272*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 273*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void 274*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(struct eth_device *dev, int command, u_long addr) 275*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 276*2439e4bfSJean-Christophe PLAGNIOL-VILLARD *(vu_long *) ((addr + dev->iobase)) = cpu_to_le32(command); 277*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 278*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 279*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 280*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Function: natsemi_initialize 281*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 282*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: Retrieves the MAC address of the card, and sets up some 283*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * globals required by other routines, and initializes the NIC, making it 284*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * ready to send and receive packets. 285*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 286*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Side effects: 287*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * leaves the natsemi initialized, and ready to recieve packets. 288*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 289*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns: struct eth_device *: pointer to NIC data structure 290*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 291*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 292*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int 293*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_initialize(bd_t * bis) 294*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 295*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_dev_t devno; 296*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int card_number = 0; 297*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev; 298*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 iobase, status, chip_config; 299*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, idx = 0; 300*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int prev_eedata; 301*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 tmp; 302*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 303*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while (1) { 304*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Find PCI device(s) */ 305*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((devno = pci_find_devices(supported, idx++)) < 0) { 306*2439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 307*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 308*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 309*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); 310*2439e4bfSJean-Christophe PLAGNIOL-VILLARD iobase &= ~0x3; /* bit 1: unused and bit 0: I/O Space Indicator */ 311*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 312*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_dword(devno, PCI_COMMAND, 313*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 314*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 315*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check if I/O accesses and Bus Mastering are enabled. */ 316*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_dword(devno, PCI_COMMAND, &status); 317*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(status & PCI_COMMAND_MEMORY)) { 318*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Error: Can not enable MEM access.\n"); 319*2439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 320*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else if (!(status & PCI_COMMAND_MASTER)) { 321*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Error: Can not enable Bus Mastering.\n"); 322*2439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 323*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 324*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 325*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = (struct eth_device *) malloc(sizeof *dev); 326*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 327*2439e4bfSJean-Christophe PLAGNIOL-VILLARD sprintf(dev->name, "dp83815#%d", card_number); 328*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->iobase = bus_to_phys(iobase); 329*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 330*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("natsemi: NatSemi ns8381[56] @ %#x\n", dev->iobase); 331*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 332*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->priv = (void *) devno; 333*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->init = natsemi_init; 334*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->halt = natsemi_disable; 335*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->send = natsemi_send; 336*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->recv = natsemi_poll; 337*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 338*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_register(dev); 339*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 340*2439e4bfSJean-Christophe PLAGNIOL-VILLARD card_number++; 341*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 342*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the latency timer for value. */ 343*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); 344*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 345*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10 * 1000); 346*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 347*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* natsemi has a non-standard PM control register 348*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * in PCI config space. Some boards apparently need 349*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * to be brought to D0 in this manner. */ 350*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_dword(devno, PCIPM, &tmp); 351*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (tmp & (0x03 | 0x100)) { 352*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* D0 state, disable PME assertion */ 353*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 newtmp = tmp & ~(0x03 | 0x100); 354*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_dword(devno, PCIPM, newtmp); 355*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 356*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 357*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("natsemi: EEPROM contents:\n"); 358*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i <= EEPROM_SIZE; i++) { 359*2439e4bfSJean-Christophe PLAGNIOL-VILLARD short eedata = read_eeprom(dev, EECtrl, i); 360*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf(" %04hx", eedata); 361*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 362*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("\n"); 363*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 364*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* get MAC address */ 365*2439e4bfSJean-Christophe PLAGNIOL-VILLARD prev_eedata = read_eeprom(dev, EECtrl, 6); 366*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 3; i++) { 367*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eedata = read_eeprom(dev, EECtrl, i + 7); 368*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->enetaddr[i*2] = (eedata << 1) + (prev_eedata >> 15); 369*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->enetaddr[i*2+1] = eedata >> 7; 370*2439e4bfSJean-Christophe PLAGNIOL-VILLARD prev_eedata = eedata; 371*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 372*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 373*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Reset the chip to erase any previous misconfiguration. */ 374*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, ChipReset, ChipCmd); 375*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 376*2439e4bfSJean-Christophe PLAGNIOL-VILLARD advertising = mdio_read(dev, 1, 4); 377*2439e4bfSJean-Christophe PLAGNIOL-VILLARD chip_config = INL(dev, ChipConfig); 378*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 379*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: Transceiver status %#08X advertising %#08X\n", 380*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name, (int) INL(dev, BasicStatus), advertising); 381*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: Transceiver default autoneg. %s 10%s %s duplex.\n", 382*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name, chip_config & AnegMask ? "enabled, advertise" : 383*2439e4bfSJean-Christophe PLAGNIOL-VILLARD "disabled, force", chip_config & SpeedMask ? "0" : "", 384*2439e4bfSJean-Christophe PLAGNIOL-VILLARD chip_config & DuplexMask ? "full" : "half"); 385*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 386*2439e4bfSJean-Christophe PLAGNIOL-VILLARD chip_config |= AnegEnBothBoth; 387*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 388*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: changed to autoneg. %s 10%s %s duplex.\n", 389*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name, chip_config & AnegMask ? "enabled, advertise" : 390*2439e4bfSJean-Christophe PLAGNIOL-VILLARD "disabled, force", chip_config & SpeedMask ? "0" : "", 391*2439e4bfSJean-Christophe PLAGNIOL-VILLARD chip_config & DuplexMask ? "full" : "half"); 392*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 393*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*write new autoneg bits, reset phy*/ 394*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, (chip_config | PhyRst), ChipConfig); 395*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*un-reset phy*/ 396*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, chip_config, ChipConfig); 397*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 398*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Disable PME: 399*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * The PME bit is initialized from the EEPROM contents. 400*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * PCI cards probably have PME disabled, but motherboard 401*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * implementations may have PME set to enable WakeOnLan. 402*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * With PME set the chip will scan incoming packets but 403*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * nothing will be written to memory. */ 404*2439e4bfSJean-Christophe PLAGNIOL-VILLARD SavedClkRun = INL(dev, ClkRun); 405*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, SavedClkRun & ~0x100, ClkRun); 406*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 407*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return card_number; 408*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 409*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 410*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. 411*2439e4bfSJean-Christophe PLAGNIOL-VILLARD The EEPROM code is for common 93c06/46 EEPROMs w/ 6bit addresses. */ 412*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 413*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Delay between EEPROM clock transitions. 414*2439e4bfSJean-Christophe PLAGNIOL-VILLARD No extra delay is needed with 33Mhz PCI, but future 66Mhz 415*2439e4bfSJean-Christophe PLAGNIOL-VILLARD access may need a delay. */ 416*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define eeprom_delay(ee_addr) INL(dev, ee_addr) 417*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 418*2439e4bfSJean-Christophe PLAGNIOL-VILLARD enum EEPROM_Ctrl_Bits { 419*2439e4bfSJean-Christophe PLAGNIOL-VILLARD EE_ShiftClk = 0x04, 420*2439e4bfSJean-Christophe PLAGNIOL-VILLARD EE_DataIn = 0x01, 421*2439e4bfSJean-Christophe PLAGNIOL-VILLARD EE_ChipSelect = 0x08, 422*2439e4bfSJean-Christophe PLAGNIOL-VILLARD EE_DataOut = 0x02 423*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 424*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 425*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_Write0 (EE_ChipSelect) 426*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_Write1 (EE_ChipSelect | EE_DataIn) 427*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The EEPROM commands include the alway-set leading bit. */ 428*2439e4bfSJean-Christophe PLAGNIOL-VILLARD enum EEPROM_Cmds { 429*2439e4bfSJean-Christophe PLAGNIOL-VILLARD EE_WrEnCmd = (4 << 6), EE_WriteCmd = (5 << 6), 430*2439e4bfSJean-Christophe PLAGNIOL-VILLARD EE_ReadCmd = (6 << 6), EE_EraseCmd = (7 << 6), 431*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 432*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 433*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 434*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 435*2439e4bfSJean-Christophe PLAGNIOL-VILLARD write_eeprom(struct eth_device *dev, long addr, int location, short value) 436*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 437*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 438*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int ee_addr = (typeof(ee_addr))addr; 439*2439e4bfSJean-Christophe PLAGNIOL-VILLARD short wren_cmd = EE_WrEnCmd | 0x30; /*wren is 100 + 11XXXX*/ 440*2439e4bfSJean-Christophe PLAGNIOL-VILLARD short write_cmd = location | EE_WriteCmd; 441*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 442*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 443*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("write_eeprom: %08x, %04hx, %04hx\n", 444*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->iobase + ee_addr, write_cmd, value); 445*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 446*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Shift the write enable command bits out. */ 447*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 9; i >= 0; i--) { 448*2439e4bfSJean-Christophe PLAGNIOL-VILLARD short cmdval = (wren_cmd & (1 << i)) ? EE_Write1 : EE_Write0; 449*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, cmdval, ee_addr); 450*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 451*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, cmdval | EE_ShiftClk, ee_addr); 452*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 453*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 454*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 455*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, 0, ee_addr); /*bring chip select low*/ 456*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, EE_ShiftClk, ee_addr); 457*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 458*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 459*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Shift the write command bits out. */ 460*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 9; i >= 0; i--) { 461*2439e4bfSJean-Christophe PLAGNIOL-VILLARD short cmdval = (write_cmd & (1 << i)) ? EE_Write1 : EE_Write0; 462*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, cmdval, ee_addr); 463*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 464*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, cmdval | EE_ShiftClk, ee_addr); 465*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 466*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 467*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 468*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 16; i++) { 469*2439e4bfSJean-Christophe PLAGNIOL-VILLARD short cmdval = (value & (1 << i)) ? EE_Write1 : EE_Write0; 470*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, cmdval, ee_addr); 471*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 472*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, cmdval | EE_ShiftClk, ee_addr); 473*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 474*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 475*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 476*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, 0, ee_addr); /*bring chip select low*/ 477*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, EE_ShiftClk, ee_addr); 478*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 200000; i++) { 479*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, EE_Write0, ee_addr); /*poll for done*/ 480*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (INL(dev, ee_addr) & EE_DataOut) { 481*2439e4bfSJean-Christophe PLAGNIOL-VILLARD break; /*finished*/ 482*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 483*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 484*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 485*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 486*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Terminate the EEPROM access. */ 487*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, EE_Write0, ee_addr); 488*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, 0, ee_addr); 489*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return; 490*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 491*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 492*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 493*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 494*2439e4bfSJean-Christophe PLAGNIOL-VILLARD read_eeprom(struct eth_device *dev, long addr, int location) 495*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 496*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 497*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int retval = 0; 498*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int ee_addr = (typeof(ee_addr))addr; 499*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int read_cmd = location | EE_ReadCmd; 500*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 501*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, EE_Write0, ee_addr); 502*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 503*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Shift the read command bits out. */ 504*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 10; i >= 0; i--) { 505*2439e4bfSJean-Christophe PLAGNIOL-VILLARD short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0; 506*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, dataval, ee_addr); 507*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 508*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, dataval | EE_ShiftClk, ee_addr); 509*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 510*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 511*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, EE_ChipSelect, ee_addr); 512*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 513*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 514*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 16; i++) { 515*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, EE_ChipSelect | EE_ShiftClk, ee_addr); 516*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 517*2439e4bfSJean-Christophe PLAGNIOL-VILLARD retval |= (INL(dev, ee_addr) & EE_DataOut) ? 1 << i : 0; 518*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, EE_ChipSelect, ee_addr); 519*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_delay(ee_addr); 520*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 521*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 522*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Terminate the EEPROM access. */ 523*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, EE_Write0, ee_addr); 524*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, 0, ee_addr); 525*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 526*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (natsemi_debug) 527*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("read_eeprom: %08x, %08x, retval %08x\n", 528*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->iobase + ee_addr, read_cmd, retval); 529*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 530*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return retval; 531*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 532*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 533*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* MII transceiver control section. 534*2439e4bfSJean-Christophe PLAGNIOL-VILLARD The 83815 series has an internal transceiver, and we present the 535*2439e4bfSJean-Christophe PLAGNIOL-VILLARD management registers as if they were MII connected. */ 536*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 537*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 538*2439e4bfSJean-Christophe PLAGNIOL-VILLARD mdio_read(struct eth_device *dev, int phy_id, int location) 539*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 540*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_id == 1 && location < 32) 541*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return INL(dev, BasicControl+(location<<2))&0xffff; 542*2439e4bfSJean-Christophe PLAGNIOL-VILLARD else 543*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0xffff; 544*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 545*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 546*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Function: natsemi_init 547*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 548*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: resets the ethernet controller chip and configures 549*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * registers and data structures required for sending and receiving packets. 550*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 551*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Arguments: struct eth_device *dev: NIC data structure 552*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 553*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * returns: int. 554*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 555*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 556*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 557*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_init(struct eth_device *dev, bd_t * bis) 558*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 559*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 560*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_reset(dev); 561*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 562*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Disable PME: 563*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * The PME bit is initialized from the EEPROM contents. 564*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * PCI cards probably have PME disabled, but motherboard 565*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * implementations may have PME set to enable WakeOnLan. 566*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * With PME set the chip will scan incoming packets but 567*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * nothing will be written to memory. */ 568*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, SavedClkRun & ~0x100, ClkRun); 569*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 570*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_init_rxfilter(dev); 571*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_init_txd(dev); 572*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_init_rxd(dev); 573*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 574*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Configure the PCI bus bursts and FIFO thresholds. */ 575*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_config = TxAutoPad | TxCollRetry | TxMxdma_256 | (0x1002); 576*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_config = RxMxdma_256 | 0x20; 577*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 578*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 579*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: Setting TxConfig Register %#08X\n", dev->name, tx_config); 580*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: Setting RxConfig Register %#08X\n", dev->name, rx_config); 581*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 582*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, tx_config, TxConfig); 583*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, rx_config, RxConfig); 584*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 585*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_check_duplex(dev); 586*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_set_rx_mode(dev); 587*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 588*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, (RxOn | TxOn), ChipCmd); 589*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 590*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 591*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 592*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 593*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Function: natsemi_reset 594*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 595*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: soft resets the controller chip 596*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 597*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Arguments: struct eth_device *dev: NIC data structure 598*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 599*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns: void. 600*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 601*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 602*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_reset(struct eth_device *dev) 603*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 604*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, ChipReset, ChipCmd); 605*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 606*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* On page 78 of the spec, they recommend some settings for "optimum 607*2439e4bfSJean-Christophe PLAGNIOL-VILLARD performance" to be done in sequence. These settings optimize some 608*2439e4bfSJean-Christophe PLAGNIOL-VILLARD of the 100Mbit autodetection circuitry. Also, we only want to do 609*2439e4bfSJean-Christophe PLAGNIOL-VILLARD this for rev C of the chip. */ 610*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (INL(dev, SiliconRev) == 0x302) { 611*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, 0x0001, PGSEL); 612*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, 0x189C, PMDCSR); 613*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, 0x0000, TSTDAT); 614*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, 0x5040, DSPCFG); 615*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, 0x008C, SDCFG); 616*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 617*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Disable interrupts using the mask. */ 618*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, 0, IntrMask); 619*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, 0, IntrEnable); 620*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 621*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 622*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Function: natsemi_init_rxfilter 623*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 624*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: sets receive filter address to our MAC address 625*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 626*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Arguments: struct eth_device *dev: NIC data structure 627*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 628*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * returns: void. 629*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 630*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 631*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 632*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_init_rxfilter(struct eth_device *dev) 633*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 634*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 635*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 636*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < ETH_ALEN; i += 2) { 637*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, i, RxFilterAddr); 638*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8), 639*2439e4bfSJean-Christophe PLAGNIOL-VILLARD RxFilterData); 640*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 641*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 642*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 643*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 644*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Function: natsemi_init_txd 645*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 646*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: initializes the Tx descriptor 647*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 648*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Arguments: struct eth_device *dev: NIC data structure 649*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 650*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * returns: void. 651*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 652*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 653*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 654*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_init_txd(struct eth_device *dev) 655*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 656*2439e4bfSJean-Christophe PLAGNIOL-VILLARD txd.link = (u32) 0; 657*2439e4bfSJean-Christophe PLAGNIOL-VILLARD txd.cmdsts = (u32) 0; 658*2439e4bfSJean-Christophe PLAGNIOL-VILLARD txd.bufptr = (u32) & txb[0]; 659*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 660*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* load Transmit Descriptor Register */ 661*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, (u32) & txd, TxRingPtr); 662*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 663*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("natsemi_init_txd: TX descriptor reg loaded with: %#08X\n", 664*2439e4bfSJean-Christophe PLAGNIOL-VILLARD INL(dev, TxRingPtr)); 665*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 666*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 667*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 668*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Function: natsemi_init_rxd 669*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 670*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: initializes the Rx descriptor ring 671*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 672*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Arguments: struct eth_device *dev: NIC data structure 673*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 674*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns: void. 675*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 676*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 677*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 678*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_init_rxd(struct eth_device *dev) 679*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 680*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 681*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 682*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cur_rx = 0; 683*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 684*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* init RX descriptor */ 685*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < NUM_RX_DESC; i++) { 686*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rxd[i].link = 687*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32((i + 1 < 688*2439e4bfSJean-Christophe PLAGNIOL-VILLARD NUM_RX_DESC) ? (u32) & rxd[i + 689*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 1] : (u32) & 690*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rxd[0]); 691*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rxd[i].cmdsts = cpu_to_le32((u32) RX_BUF_SIZE); 692*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rxd[i].bufptr = cpu_to_le32((u32) & rxb[i * RX_BUF_SIZE]); 693*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 694*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf 695*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ("natsemi_init_rxd: rxd[%d]=%p link=%X cmdsts=%lX bufptr=%X\n", 696*2439e4bfSJean-Christophe PLAGNIOL-VILLARD i, &rxd[i], le32_to_cpu(rxd[i].link), 697*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rxd[i].cmdsts, rxd[i].bufptr); 698*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 699*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 700*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 701*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* load Receive Descriptor Register */ 702*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, (u32) & rxd[0], RxRingPtr); 703*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 704*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 705*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("natsemi_init_rxd: RX descriptor register loaded with: %X\n", 706*2439e4bfSJean-Christophe PLAGNIOL-VILLARD INL(dev, RxRingPtr)); 707*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 708*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 709*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 710*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Function: natsemi_set_rx_mode 711*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 712*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: 713*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * sets the receive mode to accept all broadcast packets and packets 714*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * with our MAC address, and reject all multicast packets. 715*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 716*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Arguments: struct eth_device *dev: NIC data structure 717*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 718*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns: void. 719*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 720*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 721*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 722*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_set_rx_mode(struct eth_device *dev) 723*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 724*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 rx_mode = AcceptBroadcast | AcceptMyPhys; 725*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 726*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, rx_mode, RxFilterAddr); 727*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 728*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 729*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 730*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_check_duplex(struct eth_device *dev) 731*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 732*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int duplex = INL(dev, ChipConfig) & FullDuplex ? 1 : 0; 733*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 734*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 735*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: Setting %s-duplex based on negotiated link" 736*2439e4bfSJean-Christophe PLAGNIOL-VILLARD " capability.\n", dev->name, duplex ? "full" : "half"); 737*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 738*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (duplex) { 739*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_config |= RxAcceptTx; 740*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_config |= (TxCarrierIgn | TxHeartIgn); 741*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 742*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_config &= ~RxAcceptTx; 743*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_config &= ~(TxCarrierIgn | TxHeartIgn); 744*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 745*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, tx_config, TxConfig); 746*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, rx_config, RxConfig); 747*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 748*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 749*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Function: natsemi_send 750*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 751*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: transmits a packet and waits for completion or timeout. 752*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 753*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns: void. */ 754*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 755*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_send(struct eth_device *dev, volatile void *packet, int length) 756*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 757*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 i, status = 0; 758*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 tx_status = 0; 759*2439e4bfSJean-Christophe PLAGNIOL-VILLARD vu_long *res = (vu_long *)&tx_status; 760*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 761*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Stop the transmitter */ 762*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, TxOff, ChipCmd); 763*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 764*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 765*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (natsemi_debug) 766*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("natsemi_send: sending %d bytes\n", (int) length); 767*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 768*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 769*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* set the transmit buffer descriptor and enable Transmit State Machine */ 770*2439e4bfSJean-Christophe PLAGNIOL-VILLARD txd.link = cpu_to_le32(0); 771*2439e4bfSJean-Christophe PLAGNIOL-VILLARD txd.bufptr = cpu_to_le32(phys_to_bus((u32) packet)); 772*2439e4bfSJean-Christophe PLAGNIOL-VILLARD txd.cmdsts = cpu_to_le32(DescOwn | length); 773*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 774*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* load Transmit Descriptor Register */ 775*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, phys_to_bus((u32) & txd), TxRingPtr); 776*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 777*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (natsemi_debug) 778*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("natsemi_send: TX descriptor register loaded with: %#08X\n", 779*2439e4bfSJean-Christophe PLAGNIOL-VILLARD INL(dev, TxRingPtr)); 780*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 781*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* restart the transmitter */ 782*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, TxOn, ChipCmd); 783*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 784*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; 785*2439e4bfSJean-Christophe PLAGNIOL-VILLARD (*res = le32_to_cpu(txd.cmdsts)) & DescOwn; 786*2439e4bfSJean-Christophe PLAGNIOL-VILLARD i++) { 787*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i >= TOUT_LOOP) { 788*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf 789*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ("%s: tx error buffer not ready: txd.cmdsts == %#X\n", 790*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name, tx_status); 791*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 792*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 793*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 794*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 795*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(tx_status & DescPktOK)) { 796*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("natsemi_send: Transmit error, Tx status %X.\n", 797*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_status); 798*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 799*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 800*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 801*2439e4bfSJean-Christophe PLAGNIOL-VILLARD status = 1; 802*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Done: 803*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return status; 804*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 805*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 806*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Function: natsemi_poll 807*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 808*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: checks for a received packet and returns it if found. 809*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 810*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Arguments: struct eth_device *dev: NIC data structure 811*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 812*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns: 1 if packet was received. 813*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0 if no packet was received. 814*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 815*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Side effects: 816*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns (copies) the packet to the array dev->packet. 817*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns the length of the packet. 818*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 819*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 820*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 821*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_poll(struct eth_device *dev) 822*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 823*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int retstat = 0; 824*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int length = 0; 825*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 rx_status = le32_to_cpu(rxd[cur_rx].cmdsts); 826*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 827*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(rx_status & (u32) DescOwn)) 828*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return retstat; 829*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef NATSEMI_DEBUG 830*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (natsemi_debug) 831*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("natsemi_poll: got a packet: cur_rx:%d, status:%X\n", 832*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cur_rx, rx_status); 833*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 834*2439e4bfSJean-Christophe PLAGNIOL-VILLARD length = (rx_status & DSIZE) - CRC_SIZE; 835*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 836*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((rx_status & (DescMore | DescPktOK | DescRxLong)) != DescPktOK) { 837*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf 838*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ("natsemi_poll: Corrupted packet received, buffer status = %X\n", 839*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_status); 840*2439e4bfSJean-Christophe PLAGNIOL-VILLARD retstat = 0; 841*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { /* give packet to higher level routine */ 842*2439e4bfSJean-Christophe PLAGNIOL-VILLARD NetReceive((rxb + cur_rx * RX_BUF_SIZE), length); 843*2439e4bfSJean-Christophe PLAGNIOL-VILLARD retstat = 1; 844*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 845*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 846*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* return the descriptor and buffer to receive ring */ 847*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rxd[cur_rx].cmdsts = cpu_to_le32(RX_BUF_SIZE); 848*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rxd[cur_rx].bufptr = cpu_to_le32((u32) & rxb[cur_rx * RX_BUF_SIZE]); 849*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 850*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (++cur_rx == NUM_RX_DESC) 851*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cur_rx = 0; 852*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 853*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* re-enable the potentially idle receive state machine */ 854*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, RxOn, ChipCmd); 855*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 856*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return retstat; 857*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 858*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 859*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Function: natsemi_disable 860*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 861*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description: Turns off interrupts and stops Tx and Rx engines 862*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 863*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Arguments: struct eth_device *dev: NIC data structure 864*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 865*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns: void. 866*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 867*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 868*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 869*2439e4bfSJean-Christophe PLAGNIOL-VILLARD natsemi_disable(struct eth_device *dev) 870*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 871*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Disable interrupts using the mask. */ 872*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, 0, IntrMask); 873*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, 0, IntrEnable); 874*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 875*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Stop the chip's Tx and Rx processes. */ 876*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, RxOff | TxOff, ChipCmd); 877*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 878*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Restore PME enable bit */ 879*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL(dev, SavedClkRun, ClkRun); 880*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 881*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 882*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 883