1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun ns8382x.c: A U-Boot driver for the NatSemi DP8382[01].
3*4882a593Smuzhiyun ported by: Mark A. Rakes (mark_rakes@vivato.net)
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun Adapted from:
6*4882a593Smuzhiyun 1. an Etherboot driver for DP8381[56] written by:
7*4882a593Smuzhiyun Copyright (C) 2001 Entity Cyber, Inc.
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun This development of this Etherboot driver was funded by
10*4882a593Smuzhiyun Sicom Systems: http://www.sicompos.com/
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun Author: Marty Connor (mdc@thinguin.org)
13*4882a593Smuzhiyun Adapted from a Linux driver which was written by Donald Becker
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun This software may be used and distributed according to the terms
16*4882a593Smuzhiyun of the GNU Public License (GPL), incorporated herein by reference.
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun 2. A Linux driver by Donald Becker, ns820.c:
19*4882a593Smuzhiyun Written/copyright 1999-2002 by Donald Becker.
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun This software may be used and distributed according to the terms of
22*4882a593Smuzhiyun the GNU General Public License (GPL), incorporated herein by reference.
23*4882a593Smuzhiyun Drivers based on or derived from this code fall under the GPL and must
24*4882a593Smuzhiyun retain the authorship, copyright and license notice. This file is not
25*4882a593Smuzhiyun a complete program and may only be used when the entire operating
26*4882a593Smuzhiyun system is licensed under the GPL. License for under other terms may be
27*4882a593Smuzhiyun available. Contact the original author for details.
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun The original author may be reached as becker@scyld.com, or at
30*4882a593Smuzhiyun Scyld Computing Corporation
31*4882a593Smuzhiyun 410 Severn Ave., Suite 210
32*4882a593Smuzhiyun Annapolis MD 21403
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun Support information and updates available at
35*4882a593Smuzhiyun http://www.scyld.com/network/netsemi.html
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun Datasheets available from:
38*4882a593Smuzhiyun http://www.national.com/pf/DP/DP83820.html
39*4882a593Smuzhiyun http://www.national.com/pf/DP/DP83821.html
40*4882a593Smuzhiyun */
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* Revision History
43*4882a593Smuzhiyun * October 2002 mar 1.0
44*4882a593Smuzhiyun * Initial U-Boot Release.
45*4882a593Smuzhiyun * Tested with Netgear GA622T (83820)
46*4882a593Smuzhiyun * and SMC9452TX (83821)
47*4882a593Smuzhiyun * NOTE: custom boards with these chips may (likely) require
48*4882a593Smuzhiyun * a programmed EEPROM device (if present) in order to work
49*4882a593Smuzhiyun * correctly.
50*4882a593Smuzhiyun */
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* Includes */
53*4882a593Smuzhiyun #include <common.h>
54*4882a593Smuzhiyun #include <malloc.h>
55*4882a593Smuzhiyun #include <net.h>
56*4882a593Smuzhiyun #include <netdev.h>
57*4882a593Smuzhiyun #include <asm/io.h>
58*4882a593Smuzhiyun #include <pci.h>
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /* defines */
61*4882a593Smuzhiyun #define DSIZE 0x00000FFF
62*4882a593Smuzhiyun #define ETH_ALEN 6
63*4882a593Smuzhiyun #define CRC_SIZE 4
64*4882a593Smuzhiyun #define TOUT_LOOP 500000
65*4882a593Smuzhiyun #define TX_BUF_SIZE 1536
66*4882a593Smuzhiyun #define RX_BUF_SIZE 1536
67*4882a593Smuzhiyun #define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun enum register_offsets {
70*4882a593Smuzhiyun ChipCmd = 0x00,
71*4882a593Smuzhiyun ChipConfig = 0x04,
72*4882a593Smuzhiyun EECtrl = 0x08,
73*4882a593Smuzhiyun IntrMask = 0x14,
74*4882a593Smuzhiyun IntrEnable = 0x18,
75*4882a593Smuzhiyun TxRingPtr = 0x20,
76*4882a593Smuzhiyun TxRingPtrHi = 0x24,
77*4882a593Smuzhiyun TxConfig = 0x28,
78*4882a593Smuzhiyun RxRingPtr = 0x30,
79*4882a593Smuzhiyun RxRingPtrHi = 0x34,
80*4882a593Smuzhiyun RxConfig = 0x38,
81*4882a593Smuzhiyun PriQueue = 0x3C,
82*4882a593Smuzhiyun RxFilterAddr = 0x48,
83*4882a593Smuzhiyun RxFilterData = 0x4C,
84*4882a593Smuzhiyun ClkRun = 0xCC,
85*4882a593Smuzhiyun PCIPM = 0x44,
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun enum ChipCmdBits {
89*4882a593Smuzhiyun ChipReset = 0x100,
90*4882a593Smuzhiyun RxReset = 0x20,
91*4882a593Smuzhiyun TxReset = 0x10,
92*4882a593Smuzhiyun RxOff = 0x08,
93*4882a593Smuzhiyun RxOn = 0x04,
94*4882a593Smuzhiyun TxOff = 0x02,
95*4882a593Smuzhiyun TxOn = 0x01
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun enum ChipConfigBits {
99*4882a593Smuzhiyun LinkSts = 0x80000000,
100*4882a593Smuzhiyun GigSpeed = 0x40000000,
101*4882a593Smuzhiyun HundSpeed = 0x20000000,
102*4882a593Smuzhiyun FullDuplex = 0x10000000,
103*4882a593Smuzhiyun TBIEn = 0x01000000,
104*4882a593Smuzhiyun Mode1000 = 0x00400000,
105*4882a593Smuzhiyun T64En = 0x00004000,
106*4882a593Smuzhiyun D64En = 0x00001000,
107*4882a593Smuzhiyun M64En = 0x00000800,
108*4882a593Smuzhiyun PhyRst = 0x00000400,
109*4882a593Smuzhiyun PhyDis = 0x00000200,
110*4882a593Smuzhiyun ExtStEn = 0x00000100,
111*4882a593Smuzhiyun BEMode = 0x00000001,
112*4882a593Smuzhiyun };
113*4882a593Smuzhiyun #define SpeedStatus_Polarity ( GigSpeed | HundSpeed | FullDuplex)
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun enum TxConfig_bits {
116*4882a593Smuzhiyun TxDrthMask = 0x000000ff,
117*4882a593Smuzhiyun TxFlthMask = 0x0000ff00,
118*4882a593Smuzhiyun TxMxdmaMask = 0x00700000,
119*4882a593Smuzhiyun TxMxdma_8 = 0x00100000,
120*4882a593Smuzhiyun TxMxdma_16 = 0x00200000,
121*4882a593Smuzhiyun TxMxdma_32 = 0x00300000,
122*4882a593Smuzhiyun TxMxdma_64 = 0x00400000,
123*4882a593Smuzhiyun TxMxdma_128 = 0x00500000,
124*4882a593Smuzhiyun TxMxdma_256 = 0x00600000,
125*4882a593Smuzhiyun TxMxdma_512 = 0x00700000,
126*4882a593Smuzhiyun TxMxdma_1024 = 0x00000000,
127*4882a593Smuzhiyun TxCollRetry = 0x00800000,
128*4882a593Smuzhiyun TxAutoPad = 0x10000000,
129*4882a593Smuzhiyun TxMacLoop = 0x20000000,
130*4882a593Smuzhiyun TxHeartIgn = 0x40000000,
131*4882a593Smuzhiyun TxCarrierIgn = 0x80000000
132*4882a593Smuzhiyun };
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun enum RxConfig_bits {
135*4882a593Smuzhiyun RxDrthMask = 0x0000003e,
136*4882a593Smuzhiyun RxMxdmaMask = 0x00700000,
137*4882a593Smuzhiyun RxMxdma_8 = 0x00100000,
138*4882a593Smuzhiyun RxMxdma_16 = 0x00200000,
139*4882a593Smuzhiyun RxMxdma_32 = 0x00300000,
140*4882a593Smuzhiyun RxMxdma_64 = 0x00400000,
141*4882a593Smuzhiyun RxMxdma_128 = 0x00500000,
142*4882a593Smuzhiyun RxMxdma_256 = 0x00600000,
143*4882a593Smuzhiyun RxMxdma_512 = 0x00700000,
144*4882a593Smuzhiyun RxMxdma_1024 = 0x00000000,
145*4882a593Smuzhiyun RxAcceptLenErr = 0x04000000,
146*4882a593Smuzhiyun RxAcceptLong = 0x08000000,
147*4882a593Smuzhiyun RxAcceptTx = 0x10000000,
148*4882a593Smuzhiyun RxStripCRC = 0x20000000,
149*4882a593Smuzhiyun RxAcceptRunt = 0x40000000,
150*4882a593Smuzhiyun RxAcceptErr = 0x80000000,
151*4882a593Smuzhiyun };
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* Bits in the RxMode register. */
154*4882a593Smuzhiyun enum rx_mode_bits {
155*4882a593Smuzhiyun RxFilterEnable = 0x80000000,
156*4882a593Smuzhiyun AcceptAllBroadcast = 0x40000000,
157*4882a593Smuzhiyun AcceptAllMulticast = 0x20000000,
158*4882a593Smuzhiyun AcceptAllUnicast = 0x10000000,
159*4882a593Smuzhiyun AcceptPerfectMatch = 0x08000000,
160*4882a593Smuzhiyun };
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun typedef struct _BufferDesc {
163*4882a593Smuzhiyun u32 link;
164*4882a593Smuzhiyun u32 bufptr;
165*4882a593Smuzhiyun vu_long cmdsts;
166*4882a593Smuzhiyun u32 extsts; /*not used here */
167*4882a593Smuzhiyun } BufferDesc;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* Bits in network_desc.status */
170*4882a593Smuzhiyun enum desc_status_bits {
171*4882a593Smuzhiyun DescOwn = 0x80000000, DescMore = 0x40000000, DescIntr = 0x20000000,
172*4882a593Smuzhiyun DescNoCRC = 0x10000000, DescPktOK = 0x08000000,
173*4882a593Smuzhiyun DescSizeMask = 0xfff,
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun DescTxAbort = 0x04000000, DescTxFIFO = 0x02000000,
176*4882a593Smuzhiyun DescTxCarrier = 0x01000000, DescTxDefer = 0x00800000,
177*4882a593Smuzhiyun DescTxExcDefer = 0x00400000, DescTxOOWCol = 0x00200000,
178*4882a593Smuzhiyun DescTxExcColl = 0x00100000, DescTxCollCount = 0x000f0000,
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun DescRxAbort = 0x04000000, DescRxOver = 0x02000000,
181*4882a593Smuzhiyun DescRxDest = 0x01800000, DescRxLong = 0x00400000,
182*4882a593Smuzhiyun DescRxRunt = 0x00200000, DescRxInvalid = 0x00100000,
183*4882a593Smuzhiyun DescRxCRC = 0x00080000, DescRxAlign = 0x00040000,
184*4882a593Smuzhiyun DescRxLoop = 0x00020000, DesRxColl = 0x00010000,
185*4882a593Smuzhiyun };
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /* Bits in MEAR */
188*4882a593Smuzhiyun enum mii_reg_bits {
189*4882a593Smuzhiyun MDIO_ShiftClk = 0x0040,
190*4882a593Smuzhiyun MDIO_EnbOutput = 0x0020,
191*4882a593Smuzhiyun MDIO_Data = 0x0010,
192*4882a593Smuzhiyun };
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /* PHY Register offsets. */
195*4882a593Smuzhiyun enum phy_reg_offsets {
196*4882a593Smuzhiyun BMCR = 0x00,
197*4882a593Smuzhiyun BMSR = 0x01,
198*4882a593Smuzhiyun PHYIDR1 = 0x02,
199*4882a593Smuzhiyun PHYIDR2 = 0x03,
200*4882a593Smuzhiyun ANAR = 0x04,
201*4882a593Smuzhiyun KTCR = 0x09,
202*4882a593Smuzhiyun };
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* basic mode control register bits */
205*4882a593Smuzhiyun enum bmcr_bits {
206*4882a593Smuzhiyun Bmcr_Reset = 0x8000,
207*4882a593Smuzhiyun Bmcr_Loop = 0x4000,
208*4882a593Smuzhiyun Bmcr_Speed0 = 0x2000,
209*4882a593Smuzhiyun Bmcr_AutoNegEn = 0x1000, /*if set ignores Duplex, Speed[01] */
210*4882a593Smuzhiyun Bmcr_RstAutoNeg = 0x0200,
211*4882a593Smuzhiyun Bmcr_Duplex = 0x0100,
212*4882a593Smuzhiyun Bmcr_Speed1 = 0x0040,
213*4882a593Smuzhiyun Bmcr_Force10H = 0x0000,
214*4882a593Smuzhiyun Bmcr_Force10F = 0x0100,
215*4882a593Smuzhiyun Bmcr_Force100H = 0x2000,
216*4882a593Smuzhiyun Bmcr_Force100F = 0x2100,
217*4882a593Smuzhiyun Bmcr_Force1000H = 0x0040,
218*4882a593Smuzhiyun Bmcr_Force1000F = 0x0140,
219*4882a593Smuzhiyun };
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* auto negotiation advertisement register */
222*4882a593Smuzhiyun enum anar_bits {
223*4882a593Smuzhiyun anar_adv_100F = 0x0100,
224*4882a593Smuzhiyun anar_adv_100H = 0x0080,
225*4882a593Smuzhiyun anar_adv_10F = 0x0040,
226*4882a593Smuzhiyun anar_adv_10H = 0x0020,
227*4882a593Smuzhiyun anar_ieee_8023 = 0x0001,
228*4882a593Smuzhiyun };
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /* 1K-base T control register */
231*4882a593Smuzhiyun enum ktcr_bits {
232*4882a593Smuzhiyun ktcr_adv_1000H = 0x0100,
233*4882a593Smuzhiyun ktcr_adv_1000F = 0x0200,
234*4882a593Smuzhiyun };
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun /* Globals */
237*4882a593Smuzhiyun static u32 SavedClkRun;
238*4882a593Smuzhiyun static unsigned int cur_rx;
239*4882a593Smuzhiyun static unsigned int rx_config;
240*4882a593Smuzhiyun static unsigned int tx_config;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /* Note: transmit and receive buffers and descriptors must be
243*4882a593Smuzhiyun long long word aligned */
244*4882a593Smuzhiyun static BufferDesc txd __attribute__ ((aligned(8)));
245*4882a593Smuzhiyun static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(8)));
246*4882a593Smuzhiyun static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(8)));
247*4882a593Smuzhiyun static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE]
248*4882a593Smuzhiyun __attribute__ ((aligned(8)));
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun /* Function Prototypes */
251*4882a593Smuzhiyun static int mdio_read(struct eth_device *dev, int phy_id, int addr);
252*4882a593Smuzhiyun static void mdio_write(struct eth_device *dev, int phy_id, int addr, int value);
253*4882a593Smuzhiyun static void mdio_sync(struct eth_device *dev, u32 offset);
254*4882a593Smuzhiyun static int ns8382x_init(struct eth_device *dev, bd_t * bis);
255*4882a593Smuzhiyun static void ns8382x_reset(struct eth_device *dev);
256*4882a593Smuzhiyun static void ns8382x_init_rxfilter(struct eth_device *dev);
257*4882a593Smuzhiyun static void ns8382x_init_txd(struct eth_device *dev);
258*4882a593Smuzhiyun static void ns8382x_init_rxd(struct eth_device *dev);
259*4882a593Smuzhiyun static void ns8382x_set_rx_mode(struct eth_device *dev);
260*4882a593Smuzhiyun static void ns8382x_check_duplex(struct eth_device *dev);
261*4882a593Smuzhiyun static int ns8382x_send(struct eth_device *dev, void *packet, int length);
262*4882a593Smuzhiyun static int ns8382x_poll(struct eth_device *dev);
263*4882a593Smuzhiyun static void ns8382x_disable(struct eth_device *dev);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun static struct pci_device_id supported[] = {
266*4882a593Smuzhiyun {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83820},
267*4882a593Smuzhiyun {}
268*4882a593Smuzhiyun };
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a)
271*4882a593Smuzhiyun #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a)
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun static inline int
INW(struct eth_device * dev,u_long addr)274*4882a593Smuzhiyun INW(struct eth_device *dev, u_long addr)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun return le16_to_cpu(*(vu_short *) (addr + dev->iobase));
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun static int
INL(struct eth_device * dev,u_long addr)280*4882a593Smuzhiyun INL(struct eth_device *dev, u_long addr)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun return le32_to_cpu(*(vu_long *) (addr + dev->iobase));
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun static inline void
OUTW(struct eth_device * dev,int command,u_long addr)286*4882a593Smuzhiyun OUTW(struct eth_device *dev, int command, u_long addr)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun *(vu_short *) ((addr + dev->iobase)) = cpu_to_le16(command);
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun static inline void
OUTL(struct eth_device * dev,int command,u_long addr)292*4882a593Smuzhiyun OUTL(struct eth_device *dev, int command, u_long addr)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun *(vu_long *) ((addr + dev->iobase)) = cpu_to_le32(command);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun /* Function: ns8382x_initialize
298*4882a593Smuzhiyun * Description: Retrieves the MAC address of the card, and sets up some
299*4882a593Smuzhiyun * globals required by other routines, and initializes the NIC, making it
300*4882a593Smuzhiyun * ready to send and receive packets.
301*4882a593Smuzhiyun * Side effects: initializes ns8382xs, ready to receive packets.
302*4882a593Smuzhiyun * Returns: int: number of cards found
303*4882a593Smuzhiyun */
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun int
ns8382x_initialize(bd_t * bis)306*4882a593Smuzhiyun ns8382x_initialize(bd_t * bis)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun pci_dev_t devno;
309*4882a593Smuzhiyun int card_number = 0;
310*4882a593Smuzhiyun struct eth_device *dev;
311*4882a593Smuzhiyun u32 iobase, status;
312*4882a593Smuzhiyun int i, idx = 0;
313*4882a593Smuzhiyun u32 phyAddress;
314*4882a593Smuzhiyun u32 tmp;
315*4882a593Smuzhiyun u32 chip_config;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun while (1) { /* Find PCI device(s) */
318*4882a593Smuzhiyun if ((devno = pci_find_devices(supported, idx++)) < 0)
319*4882a593Smuzhiyun break;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase);
322*4882a593Smuzhiyun iobase &= ~0x3; /* 1: unused and 0:I/O Space Indicator */
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun debug("ns8382x: NatSemi dp8382x @ 0x%x\n", iobase);
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun pci_write_config_dword(devno, PCI_COMMAND,
327*4882a593Smuzhiyun PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /* Check if I/O accesses and Bus Mastering are enabled. */
330*4882a593Smuzhiyun pci_read_config_dword(devno, PCI_COMMAND, &status);
331*4882a593Smuzhiyun if (!(status & PCI_COMMAND_MEMORY)) {
332*4882a593Smuzhiyun printf("Error: Can not enable MEM access.\n");
333*4882a593Smuzhiyun continue;
334*4882a593Smuzhiyun } else if (!(status & PCI_COMMAND_MASTER)) {
335*4882a593Smuzhiyun printf("Error: Can not enable Bus Mastering.\n");
336*4882a593Smuzhiyun continue;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun dev = (struct eth_device *) malloc(sizeof *dev);
340*4882a593Smuzhiyun if (!dev) {
341*4882a593Smuzhiyun printf("ns8382x: Can not allocate memory\n");
342*4882a593Smuzhiyun break;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun memset(dev, 0, sizeof(*dev));
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun sprintf(dev->name, "dp8382x#%d", card_number);
347*4882a593Smuzhiyun dev->iobase = bus_to_phys(iobase);
348*4882a593Smuzhiyun dev->priv = (void *) devno;
349*4882a593Smuzhiyun dev->init = ns8382x_init;
350*4882a593Smuzhiyun dev->halt = ns8382x_disable;
351*4882a593Smuzhiyun dev->send = ns8382x_send;
352*4882a593Smuzhiyun dev->recv = ns8382x_poll;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun /* ns8382x has a non-standard PM control register
355*4882a593Smuzhiyun * in PCI config space. Some boards apparently need
356*4882a593Smuzhiyun * to be brought to D0 in this manner. */
357*4882a593Smuzhiyun pci_read_config_dword(devno, PCIPM, &tmp);
358*4882a593Smuzhiyun if (tmp & (0x03 | 0x100)) { /* D0 state, disable PME assertion */
359*4882a593Smuzhiyun u32 newtmp = tmp & ~(0x03 | 0x100);
360*4882a593Smuzhiyun pci_write_config_dword(devno, PCIPM, newtmp);
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun /* get MAC address */
364*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
365*4882a593Smuzhiyun u32 data;
366*4882a593Smuzhiyun char *mac = (char *)&dev->enetaddr[i * 2];
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun OUTL(dev, i * 2, RxFilterAddr);
369*4882a593Smuzhiyun data = INL(dev, RxFilterData);
370*4882a593Smuzhiyun *mac++ = data;
371*4882a593Smuzhiyun *mac++ = data >> 8;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun /* get PHY address, can't be zero */
374*4882a593Smuzhiyun for (phyAddress = 1; phyAddress < 32; phyAddress++) {
375*4882a593Smuzhiyun u32 rev, phy1;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun phy1 = mdio_read(dev, phyAddress, PHYIDR1);
378*4882a593Smuzhiyun if (phy1 == 0x2000) { /*check for 83861/91 */
379*4882a593Smuzhiyun rev = mdio_read(dev, phyAddress, PHYIDR2);
380*4882a593Smuzhiyun if ((rev & ~(0x000f)) == 0x00005c50 ||
381*4882a593Smuzhiyun (rev & ~(0x000f)) == 0x00005c60) {
382*4882a593Smuzhiyun debug("phy rev is %x\n", rev);
383*4882a593Smuzhiyun debug("phy address is %x\n",
384*4882a593Smuzhiyun phyAddress);
385*4882a593Smuzhiyun break;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun /* set phy to autonegotiate && advertise everything */
391*4882a593Smuzhiyun mdio_write(dev, phyAddress, KTCR,
392*4882a593Smuzhiyun (ktcr_adv_1000H | ktcr_adv_1000F));
393*4882a593Smuzhiyun mdio_write(dev, phyAddress, ANAR,
394*4882a593Smuzhiyun (anar_adv_100F | anar_adv_100H | anar_adv_10H |
395*4882a593Smuzhiyun anar_adv_10F | anar_ieee_8023));
396*4882a593Smuzhiyun mdio_write(dev, phyAddress, BMCR, 0x0); /*restore */
397*4882a593Smuzhiyun mdio_write(dev, phyAddress, BMCR,
398*4882a593Smuzhiyun (Bmcr_AutoNegEn | Bmcr_RstAutoNeg));
399*4882a593Smuzhiyun /* Reset the chip to erase any previous misconfiguration. */
400*4882a593Smuzhiyun OUTL(dev, (ChipReset), ChipCmd);
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun chip_config = INL(dev, ChipConfig);
403*4882a593Smuzhiyun /* reset the phy */
404*4882a593Smuzhiyun OUTL(dev, (chip_config | PhyRst), ChipConfig);
405*4882a593Smuzhiyun /* power up and initialize transceiver */
406*4882a593Smuzhiyun OUTL(dev, (chip_config & ~(PhyDis)), ChipConfig);
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun mdio_sync(dev, EECtrl);
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun {
411*4882a593Smuzhiyun u32 chpcfg =
412*4882a593Smuzhiyun INL(dev, ChipConfig) ^ SpeedStatus_Polarity;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun debug("%s: Transceiver 10%s %s duplex.\n", dev->name,
415*4882a593Smuzhiyun (chpcfg & GigSpeed) ? "00" : (chpcfg & HundSpeed)
416*4882a593Smuzhiyun ? "0" : "",
417*4882a593Smuzhiyun chpcfg & FullDuplex ? "full" : "half");
418*4882a593Smuzhiyun debug("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
419*4882a593Smuzhiyun dev->enetaddr[0], dev->enetaddr[1],
420*4882a593Smuzhiyun dev->enetaddr[2], dev->enetaddr[3],
421*4882a593Smuzhiyun dev->enetaddr[4], dev->enetaddr[5]);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /* Disable PME:
425*4882a593Smuzhiyun * The PME bit is initialized from the EEPROM contents.
426*4882a593Smuzhiyun * PCI cards probably have PME disabled, but motherboard
427*4882a593Smuzhiyun * implementations may have PME set to enable WakeOnLan.
428*4882a593Smuzhiyun * With PME set the chip will scan incoming packets but
429*4882a593Smuzhiyun * nothing will be written to memory. */
430*4882a593Smuzhiyun SavedClkRun = INL(dev, ClkRun);
431*4882a593Smuzhiyun OUTL(dev, SavedClkRun & ~0x100, ClkRun);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun eth_register(dev);
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun card_number++;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x60);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun udelay(10 * 1000);
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun return card_number;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun /* MII transceiver control section.
445*4882a593Smuzhiyun Read and write MII registers using software-generated serial MDIO
446*4882a593Smuzhiyun protocol. See the MII specifications or DP83840A data sheet for details.
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun The maximum data clock rate is 2.5 MHz. To meet minimum timing we
449*4882a593Smuzhiyun must flush writes to the PCI bus with a PCI read. */
450*4882a593Smuzhiyun #define mdio_delay(mdio_addr) INL(dev, mdio_addr)
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun #define MDIO_EnbIn (0)
453*4882a593Smuzhiyun #define MDIO_WRITE0 (MDIO_EnbOutput)
454*4882a593Smuzhiyun #define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput)
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun /* Generate the preamble required for initial synchronization and
457*4882a593Smuzhiyun a few older transceivers. */
458*4882a593Smuzhiyun static void
mdio_sync(struct eth_device * dev,u32 offset)459*4882a593Smuzhiyun mdio_sync(struct eth_device *dev, u32 offset)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun int bits = 32;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun /* Establish sync by sending at least 32 logic ones. */
464*4882a593Smuzhiyun while (--bits >= 0) {
465*4882a593Smuzhiyun OUTL(dev, MDIO_WRITE1, offset);
466*4882a593Smuzhiyun mdio_delay(offset);
467*4882a593Smuzhiyun OUTL(dev, MDIO_WRITE1 | MDIO_ShiftClk, offset);
468*4882a593Smuzhiyun mdio_delay(offset);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun static int
mdio_read(struct eth_device * dev,int phy_id,int addr)473*4882a593Smuzhiyun mdio_read(struct eth_device *dev, int phy_id, int addr)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun int mii_cmd = (0xf6 << 10) | (phy_id << 5) | addr;
476*4882a593Smuzhiyun int i, retval = 0;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun /* Shift the read command bits out. */
479*4882a593Smuzhiyun for (i = 15; i >= 0; i--) {
480*4882a593Smuzhiyun int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun OUTL(dev, dataval, EECtrl);
483*4882a593Smuzhiyun mdio_delay(EECtrl);
484*4882a593Smuzhiyun OUTL(dev, dataval | MDIO_ShiftClk, EECtrl);
485*4882a593Smuzhiyun mdio_delay(EECtrl);
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun /* Read the two transition, 16 data, and wire-idle bits. */
488*4882a593Smuzhiyun for (i = 19; i > 0; i--) {
489*4882a593Smuzhiyun OUTL(dev, MDIO_EnbIn, EECtrl);
490*4882a593Smuzhiyun mdio_delay(EECtrl);
491*4882a593Smuzhiyun retval =
492*4882a593Smuzhiyun (retval << 1) | ((INL(dev, EECtrl) & MDIO_Data) ? 1 : 0);
493*4882a593Smuzhiyun OUTL(dev, MDIO_EnbIn | MDIO_ShiftClk, EECtrl);
494*4882a593Smuzhiyun mdio_delay(EECtrl);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun return (retval >> 1) & 0xffff;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun static void
mdio_write(struct eth_device * dev,int phy_id,int addr,int value)500*4882a593Smuzhiyun mdio_write(struct eth_device *dev, int phy_id, int addr, int value)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (addr << 18) | value;
503*4882a593Smuzhiyun int i;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun /* Shift the command bits out. */
506*4882a593Smuzhiyun for (i = 31; i >= 0; i--) {
507*4882a593Smuzhiyun int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun OUTL(dev, dataval, EECtrl);
510*4882a593Smuzhiyun mdio_delay(EECtrl);
511*4882a593Smuzhiyun OUTL(dev, dataval | MDIO_ShiftClk, EECtrl);
512*4882a593Smuzhiyun mdio_delay(EECtrl);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun /* Clear out extra bits. */
515*4882a593Smuzhiyun for (i = 2; i > 0; i--) {
516*4882a593Smuzhiyun OUTL(dev, MDIO_EnbIn, EECtrl);
517*4882a593Smuzhiyun mdio_delay(EECtrl);
518*4882a593Smuzhiyun OUTL(dev, MDIO_EnbIn | MDIO_ShiftClk, EECtrl);
519*4882a593Smuzhiyun mdio_delay(EECtrl);
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun return;
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun /* Function: ns8382x_init
525*4882a593Smuzhiyun * Description: resets the ethernet controller chip and configures
526*4882a593Smuzhiyun * registers and data structures required for sending and receiving packets.
527*4882a593Smuzhiyun * Arguments: struct eth_device *dev: NIC data structure
528*4882a593Smuzhiyun * returns: int.
529*4882a593Smuzhiyun */
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun static int
ns8382x_init(struct eth_device * dev,bd_t * bis)532*4882a593Smuzhiyun ns8382x_init(struct eth_device *dev, bd_t * bis)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun u32 config;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun ns8382x_reset(dev);
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun /* Disable PME:
539*4882a593Smuzhiyun * The PME bit is initialized from the EEPROM contents.
540*4882a593Smuzhiyun * PCI cards probably have PME disabled, but motherboard
541*4882a593Smuzhiyun * implementations may have PME set to enable WakeOnLan.
542*4882a593Smuzhiyun * With PME set the chip will scan incoming packets but
543*4882a593Smuzhiyun * nothing will be written to memory. */
544*4882a593Smuzhiyun OUTL(dev, SavedClkRun & ~0x100, ClkRun);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun ns8382x_init_rxfilter(dev);
547*4882a593Smuzhiyun ns8382x_init_txd(dev);
548*4882a593Smuzhiyun ns8382x_init_rxd(dev);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun /*set up ChipConfig */
551*4882a593Smuzhiyun config = INL(dev, ChipConfig);
552*4882a593Smuzhiyun /*turn off 64 bit ops && Ten-bit interface
553*4882a593Smuzhiyun * && big-endian mode && extended status */
554*4882a593Smuzhiyun config &= ~(TBIEn | Mode1000 | T64En | D64En | M64En | BEMode | PhyDis | ExtStEn);
555*4882a593Smuzhiyun OUTL(dev, config, ChipConfig);
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun /* Configure the PCI bus bursts and FIFO thresholds. */
558*4882a593Smuzhiyun tx_config = TxCarrierIgn | TxHeartIgn | TxAutoPad
559*4882a593Smuzhiyun | TxCollRetry | TxMxdma_1024 | (0x1002);
560*4882a593Smuzhiyun rx_config = RxMxdma_1024 | 0x20;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun debug("%s: Setting TxConfig Register %#08X\n", dev->name, tx_config);
563*4882a593Smuzhiyun debug("%s: Setting RxConfig Register %#08X\n", dev->name, rx_config);
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun OUTL(dev, tx_config, TxConfig);
566*4882a593Smuzhiyun OUTL(dev, rx_config, RxConfig);
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun /*turn off priority queueing */
569*4882a593Smuzhiyun OUTL(dev, 0x0, PriQueue);
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun ns8382x_check_duplex(dev);
572*4882a593Smuzhiyun ns8382x_set_rx_mode(dev);
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun OUTL(dev, (RxOn | TxOn), ChipCmd);
575*4882a593Smuzhiyun return 1;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun /* Function: ns8382x_reset
579*4882a593Smuzhiyun * Description: soft resets the controller chip
580*4882a593Smuzhiyun * Arguments: struct eth_device *dev: NIC data structure
581*4882a593Smuzhiyun * Returns: void.
582*4882a593Smuzhiyun */
583*4882a593Smuzhiyun static void
ns8382x_reset(struct eth_device * dev)584*4882a593Smuzhiyun ns8382x_reset(struct eth_device *dev)
585*4882a593Smuzhiyun {
586*4882a593Smuzhiyun OUTL(dev, ChipReset, ChipCmd);
587*4882a593Smuzhiyun while (INL(dev, ChipCmd))
588*4882a593Smuzhiyun /*wait until done */ ;
589*4882a593Smuzhiyun OUTL(dev, 0, IntrMask);
590*4882a593Smuzhiyun OUTL(dev, 0, IntrEnable);
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun /* Function: ns8382x_init_rxfilter
594*4882a593Smuzhiyun * Description: sets receive filter address to our MAC address
595*4882a593Smuzhiyun * Arguments: struct eth_device *dev: NIC data structure
596*4882a593Smuzhiyun * returns: void.
597*4882a593Smuzhiyun */
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun static void
ns8382x_init_rxfilter(struct eth_device * dev)600*4882a593Smuzhiyun ns8382x_init_rxfilter(struct eth_device *dev)
601*4882a593Smuzhiyun {
602*4882a593Smuzhiyun int i;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun for (i = 0; i < ETH_ALEN; i += 2) {
605*4882a593Smuzhiyun OUTL(dev, i, RxFilterAddr);
606*4882a593Smuzhiyun OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8),
607*4882a593Smuzhiyun RxFilterData);
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun /* Function: ns8382x_init_txd
612*4882a593Smuzhiyun * Description: initializes the Tx descriptor
613*4882a593Smuzhiyun * Arguments: struct eth_device *dev: NIC data structure
614*4882a593Smuzhiyun * returns: void.
615*4882a593Smuzhiyun */
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun static void
ns8382x_init_txd(struct eth_device * dev)618*4882a593Smuzhiyun ns8382x_init_txd(struct eth_device *dev)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun txd.link = (u32) 0;
621*4882a593Smuzhiyun txd.bufptr = cpu_to_le32((u32) & txb[0]);
622*4882a593Smuzhiyun txd.cmdsts = (u32) 0;
623*4882a593Smuzhiyun txd.extsts = (u32) 0;
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun OUTL(dev, 0x0, TxRingPtrHi);
626*4882a593Smuzhiyun OUTL(dev, phys_to_bus((u32)&txd), TxRingPtr);
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun debug("ns8382x_init_txd: TX descriptor register loaded with: %#08X (&txd: %p)\n",
629*4882a593Smuzhiyun INL(dev, TxRingPtr), &txd);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun /* Function: ns8382x_init_rxd
633*4882a593Smuzhiyun * Description: initializes the Rx descriptor ring
634*4882a593Smuzhiyun * Arguments: struct eth_device *dev: NIC data structure
635*4882a593Smuzhiyun * Returns: void.
636*4882a593Smuzhiyun */
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun static void
ns8382x_init_rxd(struct eth_device * dev)639*4882a593Smuzhiyun ns8382x_init_rxd(struct eth_device *dev)
640*4882a593Smuzhiyun {
641*4882a593Smuzhiyun int i;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun OUTL(dev, 0x0, RxRingPtrHi);
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun cur_rx = 0;
646*4882a593Smuzhiyun for (i = 0; i < NUM_RX_DESC; i++) {
647*4882a593Smuzhiyun rxd[i].link =
648*4882a593Smuzhiyun cpu_to_le32((i + 1 <
649*4882a593Smuzhiyun NUM_RX_DESC) ? (u32) & rxd[i +
650*4882a593Smuzhiyun 1] : (u32) &
651*4882a593Smuzhiyun rxd[0]);
652*4882a593Smuzhiyun rxd[i].extsts = cpu_to_le32((u32) 0x0);
653*4882a593Smuzhiyun rxd[i].cmdsts = cpu_to_le32((u32) RX_BUF_SIZE);
654*4882a593Smuzhiyun rxd[i].bufptr = cpu_to_le32((u32) & rxb[i * RX_BUF_SIZE]);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun debug
657*4882a593Smuzhiyun ("ns8382x_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n",
658*4882a593Smuzhiyun i, &rxd[i], le32_to_cpu(rxd[i].link),
659*4882a593Smuzhiyun le32_to_cpu(rxd[i].cmdsts), le32_to_cpu(rxd[i].bufptr));
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun OUTL(dev, phys_to_bus((u32) & rxd), RxRingPtr);
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun debug("ns8382x_init_rxd: RX descriptor register loaded with: %X\n",
664*4882a593Smuzhiyun INL(dev, RxRingPtr));
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun /* Function: ns8382x_set_rx_mode
668*4882a593Smuzhiyun * Description:
669*4882a593Smuzhiyun * sets the receive mode to accept all broadcast packets and packets
670*4882a593Smuzhiyun * with our MAC address, and reject all multicast packets.
671*4882a593Smuzhiyun * Arguments: struct eth_device *dev: NIC data structure
672*4882a593Smuzhiyun * Returns: void.
673*4882a593Smuzhiyun */
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun static void
ns8382x_set_rx_mode(struct eth_device * dev)676*4882a593Smuzhiyun ns8382x_set_rx_mode(struct eth_device *dev)
677*4882a593Smuzhiyun {
678*4882a593Smuzhiyun u32 rx_mode = 0x0;
679*4882a593Smuzhiyun /*spec says RxFilterEnable has to be 0 for rest of
680*4882a593Smuzhiyun * this stuff to be properly configured. Linux driver
681*4882a593Smuzhiyun * seems to support this*/
682*4882a593Smuzhiyun /* OUTL(dev, rx_mode, RxFilterAddr);*/
683*4882a593Smuzhiyun rx_mode = (RxFilterEnable | AcceptAllBroadcast | AcceptPerfectMatch);
684*4882a593Smuzhiyun OUTL(dev, rx_mode, RxFilterAddr);
685*4882a593Smuzhiyun printf("ns8382x_set_rx_mode: set to %X\n", rx_mode);
686*4882a593Smuzhiyun /*now we turn RxFilterEnable back on */
687*4882a593Smuzhiyun /*rx_mode |= RxFilterEnable;
688*4882a593Smuzhiyun OUTL(dev, rx_mode, RxFilterAddr);*/
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun static void
ns8382x_check_duplex(struct eth_device * dev)692*4882a593Smuzhiyun ns8382x_check_duplex(struct eth_device *dev)
693*4882a593Smuzhiyun {
694*4882a593Smuzhiyun int gig = 0;
695*4882a593Smuzhiyun int hun = 0;
696*4882a593Smuzhiyun int duplex = 0;
697*4882a593Smuzhiyun int config = (INL(dev, ChipConfig) ^ SpeedStatus_Polarity);
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun duplex = (config & FullDuplex) ? 1 : 0;
700*4882a593Smuzhiyun gig = (config & GigSpeed) ? 1 : 0;
701*4882a593Smuzhiyun hun = (config & HundSpeed) ? 1 : 0;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun debug("%s: Setting 10%s %s-duplex based on negotiated link"
704*4882a593Smuzhiyun " capability.\n", dev->name, (gig) ? "00" : (hun) ? "0" : "",
705*4882a593Smuzhiyun duplex ? "full" : "half");
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun if (duplex) {
708*4882a593Smuzhiyun rx_config |= RxAcceptTx;
709*4882a593Smuzhiyun tx_config |= (TxCarrierIgn | TxHeartIgn);
710*4882a593Smuzhiyun } else {
711*4882a593Smuzhiyun rx_config &= ~RxAcceptTx;
712*4882a593Smuzhiyun tx_config &= ~(TxCarrierIgn | TxHeartIgn);
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun debug("%s: Resetting TxConfig Register %#08X\n", dev->name, tx_config);
716*4882a593Smuzhiyun debug("%s: Resetting RxConfig Register %#08X\n", dev->name, rx_config);
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun OUTL(dev, tx_config, TxConfig);
719*4882a593Smuzhiyun OUTL(dev, rx_config, RxConfig);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun /*if speed is 10 or 100, remove MODE1000,
722*4882a593Smuzhiyun * if it's 1000, then set it */
723*4882a593Smuzhiyun config = INL(dev, ChipConfig);
724*4882a593Smuzhiyun if (gig)
725*4882a593Smuzhiyun config |= Mode1000;
726*4882a593Smuzhiyun else
727*4882a593Smuzhiyun config &= ~Mode1000;
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun debug("%s: %setting Mode1000\n", dev->name, (gig) ? "S" : "Uns");
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun OUTL(dev, config, ChipConfig);
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun /* Function: ns8382x_send
735*4882a593Smuzhiyun * Description: transmits a packet and waits for completion or timeout.
736*4882a593Smuzhiyun * Returns: void. */
ns8382x_send(struct eth_device * dev,void * packet,int length)737*4882a593Smuzhiyun static int ns8382x_send(struct eth_device *dev, void *packet, int length)
738*4882a593Smuzhiyun {
739*4882a593Smuzhiyun u32 i, status = 0;
740*4882a593Smuzhiyun vu_long tx_stat = 0;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun /* Stop the transmitter */
743*4882a593Smuzhiyun OUTL(dev, TxOff, ChipCmd);
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun debug("ns8382x_send: sending %d bytes\n", (int)length);
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun /* set the transmit buffer descriptor and enable Transmit State Machine */
748*4882a593Smuzhiyun txd.link = cpu_to_le32(0x0);
749*4882a593Smuzhiyun txd.bufptr = cpu_to_le32(phys_to_bus((u32)packet));
750*4882a593Smuzhiyun txd.extsts = cpu_to_le32(0x0);
751*4882a593Smuzhiyun txd.cmdsts = cpu_to_le32(DescOwn | length);
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun /* load Transmit Descriptor Register */
754*4882a593Smuzhiyun OUTL(dev, phys_to_bus((u32) & txd), TxRingPtr);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun debug("ns8382x_send: TX descriptor register loaded with: %#08X\n",
757*4882a593Smuzhiyun INL(dev, TxRingPtr));
758*4882a593Smuzhiyun debug("\ttxd.link:%X\tbufp:%X\texsts:%X\tcmdsts:%X\n",
759*4882a593Smuzhiyun le32_to_cpu(txd.link), le32_to_cpu(txd.bufptr),
760*4882a593Smuzhiyun le32_to_cpu(txd.extsts), le32_to_cpu(txd.cmdsts));
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun /* restart the transmitter */
763*4882a593Smuzhiyun OUTL(dev, TxOn, ChipCmd);
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun for (i = 0; (tx_stat = le32_to_cpu(txd.cmdsts)) & DescOwn; i++) {
766*4882a593Smuzhiyun if (i >= TOUT_LOOP) {
767*4882a593Smuzhiyun printf ("%s: tx error buffer not ready: txd.cmdsts %#lX\n",
768*4882a593Smuzhiyun dev->name, tx_stat);
769*4882a593Smuzhiyun goto Done;
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun if (!(tx_stat & DescPktOK)) {
774*4882a593Smuzhiyun printf("ns8382x_send: Transmit error, Tx status %lX.\n", tx_stat);
775*4882a593Smuzhiyun goto Done;
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun debug("ns8382x_send: tx_stat: %#08lX\n", tx_stat);
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun status = 1;
781*4882a593Smuzhiyun Done:
782*4882a593Smuzhiyun return status;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun /* Function: ns8382x_poll
786*4882a593Smuzhiyun * Description: checks for a received packet and returns it if found.
787*4882a593Smuzhiyun * Arguments: struct eth_device *dev: NIC data structure
788*4882a593Smuzhiyun * Returns: 1 if packet was received.
789*4882a593Smuzhiyun * 0 if no packet was received.
790*4882a593Smuzhiyun * Side effects:
791*4882a593Smuzhiyun * Returns (copies) the packet to the array dev->packet.
792*4882a593Smuzhiyun * Returns the length of the packet.
793*4882a593Smuzhiyun */
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun static int
ns8382x_poll(struct eth_device * dev)796*4882a593Smuzhiyun ns8382x_poll(struct eth_device *dev)
797*4882a593Smuzhiyun {
798*4882a593Smuzhiyun int retstat = 0;
799*4882a593Smuzhiyun int length = 0;
800*4882a593Smuzhiyun vu_long rx_status = le32_to_cpu(rxd[cur_rx].cmdsts);
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun if (!(rx_status & (u32) DescOwn))
803*4882a593Smuzhiyun return retstat;
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun debug("ns8382x_poll: got a packet: cur_rx:%u, status:%lx\n",
806*4882a593Smuzhiyun cur_rx, rx_status);
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun length = (rx_status & DSIZE) - CRC_SIZE;
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun if ((rx_status & (DescMore | DescPktOK | DescRxLong)) != DescPktOK) {
811*4882a593Smuzhiyun /* corrupted packet received */
812*4882a593Smuzhiyun printf("ns8382x_poll: Corrupted packet, status:%lx\n",
813*4882a593Smuzhiyun rx_status);
814*4882a593Smuzhiyun retstat = 0;
815*4882a593Smuzhiyun } else {
816*4882a593Smuzhiyun /* give packet to higher level routine */
817*4882a593Smuzhiyun net_process_received_packet((rxb + cur_rx * RX_BUF_SIZE),
818*4882a593Smuzhiyun length);
819*4882a593Smuzhiyun retstat = 1;
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun /* return the descriptor and buffer to receive ring */
823*4882a593Smuzhiyun rxd[cur_rx].cmdsts = cpu_to_le32(RX_BUF_SIZE);
824*4882a593Smuzhiyun rxd[cur_rx].bufptr = cpu_to_le32((u32) & rxb[cur_rx * RX_BUF_SIZE]);
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun if (++cur_rx == NUM_RX_DESC)
827*4882a593Smuzhiyun cur_rx = 0;
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun /* re-enable the potentially idle receive state machine */
830*4882a593Smuzhiyun OUTL(dev, RxOn, ChipCmd);
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun return retstat;
833*4882a593Smuzhiyun }
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun /* Function: ns8382x_disable
836*4882a593Smuzhiyun * Description: Turns off interrupts and stops Tx and Rx engines
837*4882a593Smuzhiyun * Arguments: struct eth_device *dev: NIC data structure
838*4882a593Smuzhiyun * Returns: void.
839*4882a593Smuzhiyun */
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun static void
ns8382x_disable(struct eth_device * dev)842*4882a593Smuzhiyun ns8382x_disable(struct eth_device *dev)
843*4882a593Smuzhiyun {
844*4882a593Smuzhiyun /* Disable interrupts using the mask. */
845*4882a593Smuzhiyun OUTL(dev, 0, IntrMask);
846*4882a593Smuzhiyun OUTL(dev, 0, IntrEnable);
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun /* Stop the chip's Tx and Rx processes. */
849*4882a593Smuzhiyun OUTL(dev, (RxOff | TxOff), ChipCmd);
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun /* Restore PME enable bit */
852*4882a593Smuzhiyun OUTL(dev, SavedClkRun, ClkRun);
853*4882a593Smuzhiyun }
854