blob: 249ab043934267b083f95f79cd343be72d803adb [file] [log] [blame]
Gary Jennejohn6bd24472007-01-24 12:16:56 +01001/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17
18#include <config.h>
19#include <common.h>
20#include <net.h>
21#include <asm/arch/hardware.h>
22#include "spi.h"
23
24/*
25 * Control Registers in Bank 0
26 */
27
Wolfgang Denkf8db84f2007-01-30 00:50:40 +010028#define CTL_REG_ERDPTL 0x00
29#define CTL_REG_ERDPTH 0x01
30#define CTL_REG_EWRPTL 0x02
31#define CTL_REG_EWRPTH 0x03
32#define CTL_REG_ETXSTL 0x04
33#define CTL_REG_ETXSTH 0x05
34#define CTL_REG_ETXNDL 0x06
35#define CTL_REG_ETXNDH 0x07
36#define CTL_REG_ERXSTL 0x08
37#define CTL_REG_ERXSTH 0x09
38#define CTL_REG_ERXNDL 0x0A
39#define CTL_REG_ERXNDA 0x0B
Gary Jennejohn6bd24472007-01-24 12:16:56 +010040#define CTL_REG_ERXRDPTL 0x0C
41#define CTL_REG_ERXRDPTH 0x0D
42#define CTL_REG_ERXWRPTL 0x0E
43#define CTL_REG_ERXWRPTH 0x0F
44#define CTL_REG_EDMASTL 0x10
45#define CTL_REG_EDMASTH 0x11
46#define CTL_REG_EDMANDL 0x12
47#define CTL_REG_EDMANDH 0x13
48#define CTL_REG_EDMADSTL 0x14
49#define CTL_REG_EDMADSTH 0x15
50#define CTL_REG_EDMACSL 0x16
51#define CTL_REG_EDMACSH 0x17
52/* these are common in all banks */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +010053#define CTL_REG_EIE 0x1B
54#define CTL_REG_EIR 0x1C
55#define CTL_REG_ESTAT 0x1D
56#define CTL_REG_ECON2 0x1E
57#define CTL_REG_ECON1 0x1F
Gary Jennejohn6bd24472007-01-24 12:16:56 +010058
59/*
60 * Control Registers in Bank 1
61 */
62
Wolfgang Denkf8db84f2007-01-30 00:50:40 +010063#define CTL_REG_EHT0 0x00
64#define CTL_REG_EHT1 0x01
65#define CTL_REG_EHT2 0x02
66#define CTL_REG_EHT3 0x03
67#define CTL_REG_EHT4 0x04
68#define CTL_REG_EHT5 0x05
69#define CTL_REG_EHT6 0x06
70#define CTL_REG_EHT7 0x07
71#define CTL_REG_EPMM0 0x08
72#define CTL_REG_EPMM1 0x09
73#define CTL_REG_EPMM2 0x0A
74#define CTL_REG_EPMM3 0x0B
75#define CTL_REG_EPMM4 0x0C
76#define CTL_REG_EPMM5 0x0D
77#define CTL_REG_EPMM6 0x0E
78#define CTL_REG_EPMM7 0x0F
79#define CTL_REG_EPMCSL 0x10
80#define CTL_REG_EPMCSH 0x11
81#define CTL_REG_EPMOL 0x14
82#define CTL_REG_EPMOH 0x15
83#define CTL_REG_EWOLIE 0x16
84#define CTL_REG_EWOLIR 0x17
Gary Jennejohn6bd24472007-01-24 12:16:56 +010085#define CTL_REG_ERXFCON 0x18
86#define CTL_REG_EPKTCNT 0x19
87
88/*
89 * Control Registers in Bank 2
90 */
91
Wolfgang Denkf8db84f2007-01-30 00:50:40 +010092#define CTL_REG_MACON1 0x00
93#define CTL_REG_MACON2 0x01
94#define CTL_REG_MACON3 0x02
95#define CTL_REG_MACON4 0x03
Gary Jennejohn6bd24472007-01-24 12:16:56 +010096#define CTL_REG_MABBIPG 0x04
Wolfgang Denkf8db84f2007-01-30 00:50:40 +010097#define CTL_REG_MAIPGL 0x06
98#define CTL_REG_MAIPGH 0x07
Gary Jennejohn6bd24472007-01-24 12:16:56 +010099#define CTL_REG_MACLCON1 0x08
100#define CTL_REG_MACLCON2 0x09
101#define CTL_REG_MAMXFLL 0x0A
102#define CTL_REG_MAMXFLH 0x0B
103#define CTL_REG_MAPHSUP 0x0D
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100104#define CTL_REG_MICON 0x11
105#define CTL_REG_MICMD 0x12
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100106#define CTL_REG_MIREGADR 0x14
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100107#define CTL_REG_MIWRL 0x16
108#define CTL_REG_MIWRH 0x17
109#define CTL_REG_MIRDL 0x18
110#define CTL_REG_MIRDH 0x19
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100111
112/*
113 * Control Registers in Bank 3
114 */
115
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100116#define CTL_REG_MAADR1 0x00
117#define CTL_REG_MAADR0 0x01
118#define CTL_REG_MAADR3 0x02
119#define CTL_REG_MAADR2 0x03
120#define CTL_REG_MAADR5 0x04
121#define CTL_REG_MAADR4 0x05
122#define CTL_REG_EBSTSD 0x06
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100123#define CTL_REG_EBSTCON 0x07
124#define CTL_REG_EBSTCSL 0x08
125#define CTL_REG_EBSTCSH 0x09
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100126#define CTL_REG_MISTAT 0x0A
127#define CTL_REG_EREVID 0x12
128#define CTL_REG_ECOCON 0x15
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100129#define CTL_REG_EFLOCON 0x17
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100130#define CTL_REG_EPAUSL 0x18
131#define CTL_REG_EPAUSH 0x19
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100132
133
134/*
135 * PHY Register
136 */
137
138#define PHY_REG_PHID1 0x02
139#define PHY_REG_PHID2 0x03
140
141
142/*
143 * Receive Filter Register (ERXFCON) bits
144 */
145
146#define ENC_RFR_UCEN 0x80
147#define ENC_RFR_ANDOR 0x40
148#define ENC_RFR_CRCEN 0x20
149#define ENC_RFR_PMEN 0x10
150#define ENC_RFR_MPEN 0x08
151#define ENC_RFR_HTEN 0x04
152#define ENC_RFR_MCEN 0x02
153#define ENC_RFR_BCEN 0x01
154
155/*
156 * ECON1 Register Bits
157 */
158
159#define ENC_ECON1_TXRST 0x80
160#define ENC_ECON1_RXRST 0x40
161#define ENC_ECON1_DMAST 0x20
162#define ENC_ECON1_CSUMEN 0x10
163#define ENC_ECON1_TXRTS 0x08
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100164#define ENC_ECON1_RXEN 0x04
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100165#define ENC_ECON1_BSEL1 0x02
166#define ENC_ECON1_BSEL0 0x01
167
168/*
169 * ECON2 Register Bits
170 */
171#define ENC_ECON2_AUTOINC 0x80
172#define ENC_ECON2_PKTDEC 0x40
173#define ENC_ECON2_PWRSV 0x20
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100174#define ENC_ECON2_VRPS 0x08
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100175
176/*
177 * EIR Register Bits
178 */
179#define ENC_EIR_PKTIF 0x40
180#define ENC_EIR_DMAIF 0x20
181#define ENC_EIR_LINKIF 0x10
182#define ENC_EIR_TXIF 0x08
183#define ENC_EIR_WOLIF 0x04
184#define ENC_EIR_TXERIF 0x02
185#define ENC_EIR_RXERIF 0x01
186
187/*
188 * ESTAT Register Bits
189 */
190
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100191#define ENC_ESTAT_INT 0x80
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100192#define ENC_ESTAT_LATECOL 0x10
193#define ENC_ESTAT_RXBUSY 0x04
194#define ENC_ESTAT_TXABRT 0x02
195#define ENC_ESTAT_CLKRDY 0x01
196
197/*
198 * EIE Register Bits
199 */
200
201#define ENC_EIE_INTIE 0x80
202#define ENC_EIE_PKTIE 0x40
203#define ENC_EIE_DMAIE 0x20
204#define ENC_EIE_LINKIE 0x10
205#define ENC_EIE_TXIE 0x08
206#define ENC_EIE_WOLIE 0x04
207#define ENC_EIE_TXERIE 0x02
208#define ENC_EIE_RXERIE 0x01
209
210/*
211 * MACON1 Register Bits
212 */
213#define ENC_MACON1_LOOPBK 0x10
214#define ENC_MACON1_TXPAUS 0x08
215#define ENC_MACON1_RXPAUS 0x04
216#define ENC_MACON1_PASSALL 0x02
217#define ENC_MACON1_MARXEN 0x01
218
219
220/*
221 * MACON2 Register Bits
222 */
223#define ENC_MACON2_MARST 0x80
224#define ENC_MACON2_RNDRST 0x40
225#define ENC_MACON2_MARXRST 0x08
226#define ENC_MACON2_RFUNRST 0x04
227#define ENC_MACON2_MATXRST 0x02
228#define ENC_MACON2_TFUNRST 0x01
229
230/*
231 * MACON3 Register Bits
232 */
233#define ENC_MACON3_PADCFG2 0x80
234#define ENC_MACON3_PADCFG1 0x40
235#define ENC_MACON3_PADCFG0 0x20
236#define ENC_MACON3_TXCRCEN 0x10
237#define ENC_MACON3_PHDRLEN 0x08
238#define ENC_MACON3_HFRMEN 0x04
239#define ENC_MACON3_FRMLNEN 0x02
240#define ENC_MACON3_FULDPX 0x01
241
242/*
243 * MICMD Register Bits
244 */
245#define ENC_MICMD_MIISCAN 0x02
246#define ENC_MICMD_MIIRD 0x01
247
248/*
249 * MISTAT Register Bits
250 */
251#define ENC_MISTAT_NVALID 0x04
252#define ENC_MISTAT_SCAN 0x02
253#define ENC_MISTAT_BUSY 0x01
254
255/*
256 * PHID1 and PHID2 values
257 */
258#define ENC_PHID1_VALUE 0x0083
259#define ENC_PHID2_VALUE 0x1400
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100260#define ENC_PHID2_MASK 0xFC00
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100261
262
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100263#define ENC_SPI_SLAVE_CS 0x00010000 /* pin P1.16 */
264#define ENC_RESET 0x00020000 /* pin P1.17 */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100265
266#define FAILSAFE_VALUE 5000
267
268/*
269 * Controller memory layout:
270 *
271 * 0x0000 - 0x17ff 6k bytes receive buffer
272 * 0x1800 - 0x1fff 2k bytes transmit buffer
273 */
274/* Use the lower memory for receiver buffer. See errata pt. 5 */
275#define ENC_RX_BUF_START 0x0000
276#define ENC_TX_BUF_START 0x1800
277
278/* maximum frame length */
279#define ENC_MAX_FRM_LEN 1518
280
281#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS)
282#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS)
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100283#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100284
285
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100286static unsigned char encReadReg (unsigned char regNo);
287static void encWriteReg (unsigned char regNo, unsigned char data);
288static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c);
289static void encReadBuff (unsigned short length, unsigned char *pBuff);
290static void encWriteBuff (unsigned short length, unsigned char *pBuff);
291static void encBitSet (unsigned char regNo, unsigned char data);
292static void encBitClr (unsigned char regNo, unsigned char data);
293static void encReset (void);
294static void encInit (unsigned char *pEthAddr);
295static unsigned short phyRead (unsigned char addr);
296static void encPoll (void);
297static void encRx (void);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100298
299#define m_nic_read(reg) encReadReg(reg)
300#define m_nic_write(reg, data) encWriteReg(reg, data)
301#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count)
302#define m_nic_read_data(len, buf) encReadBuff((len), (buf))
303#define m_nic_write_data(len, buf) encWriteBuff((len), (buf))
304
305/* bit field set */
306#define m_nic_bfs(reg, data) encBitSet(reg, data)
307
308/* bit field clear */
309#define m_nic_bfc(reg, data) encBitClr(reg, data)
310
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100311static unsigned char bank = 0; /* current bank in enc28j60 */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100312static unsigned char next_pointer_lsb;
313static unsigned char next_pointer_msb;
314
315static unsigned char buffer[ENC_MAX_FRM_LEN];
316static int rxResetCounter = 0;
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100317
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100318#define RX_RESET_COUNTER 1000;
319
320/*-----------------------------------------------------------------------------
321 * Returns 0 when failes otherwize 1
322 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100323int eth_init (bd_t * bis)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100324{
325 /* configure GPIO */
326 (*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS;
327 (*((volatile unsigned long *) IO1DIR)) |= ENC_RESET;
328
329 /* CS and RESET active low */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100330 PUT32 (IO1SET, ENC_SPI_SLAVE_CS);
331 PUT32 (IO1SET, ENC_RESET);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100332
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100333 spi_init ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100334
335 /* initialize controller */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100336 encReset ();
337 encInit (bis->bi_enetaddr);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100338
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100339 m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100340
341 return 0;
342}
343
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100344int eth_send (volatile void *packet, int length)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100345{
346 /* check frame length, etc. */
347 /* TODO: */
348
349 /* switch to bank 0 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100350 m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100351
352 /* set EWRPT */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100353 m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff));
354 m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8));
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100355
356 /* set ETXST */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100357 m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF);
358 m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100359
360 /* write packet */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100361 m_nic_write_data (length, (unsigned char *) packet);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100362
363 /* set ETXND */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100364 m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF);
365 m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100366
367 /* set ECON1.TXRTS */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100368 m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100369
370 return 0;
371}
372
373
374/*****************************************************************************
375 * This function resets the receiver only. This function may be called from
376 * interrupt-context.
377 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100378static void encReceiverReset (void)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100379{
380 unsigned char econ1;
381
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100382 econ1 = m_nic_read (CTL_REG_ECON1);
383 if ((econ1 & ENC_ECON1_RXRST) == 0) {
384 m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100385 rxResetCounter = RX_RESET_COUNTER;
386 }
387}
388
389/*****************************************************************************
390 * receiver reset timer
391 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100392static void encReceiverResetCallback (void)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100393{
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100394 m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST);
395 m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100396}
397
398/*-----------------------------------------------------------------------------
399 * Check for received packets. Call NetReceive for each packet. The return
400 * value is ignored by the caller.
401 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100402int eth_rx (void)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100403{
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100404 if (rxResetCounter > 0 && --rxResetCounter == 0) {
405 encReceiverResetCallback ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100406 }
407
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100408 encPoll ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100409
410 return 0;
411}
412
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100413void eth_halt (void)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100414{
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100415 m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN); /* disable receive */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100416}
417
418/*****************************************************************************/
419
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100420static void encPoll (void)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100421{
422 unsigned char eir_reg;
423 volatile unsigned char estat_reg;
424 unsigned char pkt_cnt;
425
426 /* clear global interrupt enable bit in enc28j60 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100427 m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE);
428 estat_reg = m_nic_read (CTL_REG_ESTAT);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100429
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100430 eir_reg = m_nic_read (CTL_REG_EIR);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100431
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100432 if (eir_reg & ENC_EIR_TXIF) {
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100433 /* clear TXIF bit in EIR */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100434 m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100435 }
436
437 /* We have to use pktcnt and not pktif bit, see errata pt. 6 */
438
439 /* move to bank 1 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100440 m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
441 m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100442
443 /* read pktcnt */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100444 pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100445
446 if (pkt_cnt > 0) {
447 if ((eir_reg & ENC_EIR_PKTIF) == 0) {
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100448 /*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100449 }
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100450 encRx ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100451 /* clear PKTIF bit in EIR, this should not need to be done but it
452 seems like we get problems if we do not */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100453 m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100454 }
455
456 if (eir_reg & ENC_EIR_RXERIF) {
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100457 printf ("encPoll: rx error\n");
458 m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100459 }
460 if (eir_reg & ENC_EIR_TXERIF) {
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100461 printf ("encPoll: tx error\n");
462 m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100463 }
464
465 /* set global interrupt enable bit in enc28j60 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100466 m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100467}
468
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100469static void encRx (void)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100470{
471 unsigned short pkt_len;
472 unsigned short copy_len;
473 unsigned short status;
474 unsigned char eir_reg;
475 unsigned char pkt_cnt = 0;
476
477 /* switch to bank 0 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100478 m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100479
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100480 m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
481 m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100482
483 do {
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100484 m_nic_read_data (6, buffer);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100485 next_pointer_lsb = buffer[0];
486 next_pointer_msb = buffer[1];
487 pkt_len = buffer[2];
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100488 pkt_len |= (unsigned short) buffer[3] << 8;
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100489 status = buffer[4];
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100490 status |= (unsigned short) buffer[5] << 8;
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100491
492 if (pkt_len <= ENC_MAX_FRM_LEN) {
493 copy_len = pkt_len;
494 } else {
495 copy_len = 0;
496 /* p_priv->stats.rx_dropped++; */
497 /* we will drop this packet */
498 }
499
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100500 if ((status & (1L << 7)) == 0) { /* check Received Ok bit */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100501 copy_len = 0;
502 /* p_priv->stats.rx_errors++; */
503 }
504
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100505 if (copy_len > 0) {
506 m_nic_read_data (copy_len, buffer);
507 }
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100508
509 /* advance read pointer to next pointer */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100510 m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
511 m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100512
513 /* decrease packet counter */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100514 m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100515
516 /* move to bank 1 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100517 m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
518 m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100519
520 /* read pktcnt */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100521 pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100522
523 /* switch to bank 0 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100524 m_nic_bfc (CTL_REG_ECON1,
525 (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100526
527 if (copy_len == 0) {
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100528 eir_reg = m_nic_read (CTL_REG_EIR);
529 encReceiverReset ();
530 printf ("eth_rx: copy_len=0\n");
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100531 continue;
532 }
533
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100534 NetReceive ((unsigned char *) buffer, pkt_len);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100535
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100536 eir_reg = m_nic_read (CTL_REG_EIR);
537 } while (pkt_cnt); /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
538 m_nic_write (CTL_REG_ERXRDPTL, next_pointer_lsb);
539 m_nic_write (CTL_REG_ERXRDPTH, next_pointer_msb);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100540}
541
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100542static void encWriteReg (unsigned char regNo, unsigned char data)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100543{
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100544 spi_lock ();
545 enc_cfg_spi ();
546 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100547
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100548 spi_write (0x40 | regNo); /* write in regNo */
549 spi_write (data);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100550
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100551 enc_disable ();
552 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100553
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100554 spi_write (0x1f); /* write reg 0x1f */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100555
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100556 enc_disable ();
557 spi_unlock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100558}
559
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100560static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100561{
562 unsigned char readback;
563 int i;
564
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100565 spi_lock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100566
567 for (i = 0; i < c; i++) {
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100568 enc_cfg_spi ();
569 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100570
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100571 spi_write (0x40 | regNo); /* write in regNo */
572 spi_write (data);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100573
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100574 enc_disable ();
575 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100576
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100577 spi_write (0x1f); /* write reg 0x1f */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100578
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100579 enc_disable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100580
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100581 spi_unlock (); /* we must unlock spi first */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100582
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100583 readback = encReadReg (regNo);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100584
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100585 spi_lock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100586
587 if (readback == data)
588 break;
589 }
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100590 spi_unlock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100591
592 if (i == c) {
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100593 printf ("enc28j60: write reg %d failed\n", regNo);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100594 }
595}
596
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100597static unsigned char encReadReg (unsigned char regNo)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100598{
599 unsigned char rxByte;
600
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100601 spi_lock ();
602 enc_cfg_spi ();
603 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100604
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100605 spi_write (0x1f); /* read reg 0x1f */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100606
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100607 bank = spi_read () & 0x3;
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100608
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100609 enc_disable ();
610 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100611
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100612 spi_write (regNo);
613 rxByte = spi_read ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100614
615 /* check if MAC or MII register */
616 if (((bank == 2) && (regNo <= 0x1a)) ||
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100617 ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) {
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100618 /* ignore first byte and read another byte */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100619 rxByte = spi_read ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100620 }
621
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100622 enc_disable ();
623 spi_unlock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100624
625 return rxByte;
626}
627
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100628static void encReadBuff (unsigned short length, unsigned char *pBuff)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100629{
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100630 spi_lock ();
631 enc_cfg_spi ();
632 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100633
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100634 spi_write (0x20 | 0x1a); /* read buffer memory */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100635
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100636 while (length--) {
637 if (pBuff != NULL)
638 *pBuff++ = spi_read ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100639 else
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100640 spi_write (0);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100641 }
642
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100643 enc_disable ();
644 spi_unlock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100645}
646
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100647static void encWriteBuff (unsigned short length, unsigned char *pBuff)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100648{
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100649 spi_lock ();
650 enc_cfg_spi ();
651 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100652
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100653 spi_write (0x60 | 0x1a); /* write buffer memory */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100654
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100655 spi_write (0x00); /* control byte */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100656
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100657 while (length--)
658 spi_write (*pBuff++);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100659
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100660 enc_disable ();
661 spi_unlock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100662}
663
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100664static void encBitSet (unsigned char regNo, unsigned char data)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100665{
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100666 spi_lock ();
667 enc_cfg_spi ();
668 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100669
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100670 spi_write (0x80 | regNo); /* bit field set */
671 spi_write (data);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100672
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100673 enc_disable ();
674 spi_unlock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100675}
676
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100677static void encBitClr (unsigned char regNo, unsigned char data)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100678{
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100679 spi_lock ();
680 enc_cfg_spi ();
681 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100682
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100683 spi_write (0xA0 | regNo); /* bit field clear */
684 spi_write (data);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100685
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100686 enc_disable ();
687 spi_unlock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100688}
689
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100690static void encReset (void)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100691{
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100692 spi_lock ();
693 enc_cfg_spi ();
694 enc_enable ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100695
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100696 spi_write (0xff); /* soft reset */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100697
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100698 enc_disable ();
699 spi_unlock ();
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100700
701 /* sleep 1 ms. See errata pt. 2 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100702 udelay (1000);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100703
704#if 0
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100705 (*((volatile unsigned long *) IO1CLR)) &= ENC_RESET;
706 mdelay (5);
707 (*((volatile unsigned long *) IO1SET)) &= ENC_RESET;
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100708#endif
709}
710
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100711static void encInit (unsigned char *pEthAddr)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100712{
713 unsigned short phid1 = 0;
714 unsigned short phid2 = 0;
715
716 /* switch to bank 0 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100717 m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100718
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100719 /*
720 * Setup the buffer space. The reset values are valid for the
721 * other pointers.
722 */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100723#if 0
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100724 /* We shall not write to ERXST, see errata pt. 5. Instead we
725 have to make sure that ENC_RX_BUS_START is 0. */
726 m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1);
727 m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100728#endif
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100729 m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1);
730 m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100731
732 next_pointer_lsb = (ENC_RX_BUF_START & 0xFF);
733 next_pointer_msb = (ENC_RX_BUF_START >> 8);
734
735 /*
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100736 * For tracking purposes, the ERXRDPT registers should be programmed with
737 * the same value. This is the read pointer.
738 */
739 m_nic_write (CTL_REG_ERXRDPTL, (ENC_RX_BUF_START & 0xFF));
740 m_nic_write_retry (CTL_REG_ERXRDPTH, (ENC_RX_BUF_START >> 8), 1);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100741
742 /* Setup receive filters. */
743
744 /* move to bank 1 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100745 m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
746 m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100747
748 /* OR-filtering, Unicast, CRC-check and broadcast */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100749 m_nic_write_retry (CTL_REG_ERXFCON,
750 (ENC_RFR_UCEN | ENC_RFR_CRCEN | ENC_RFR_BCEN), 1);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100751
752 /* Wait for Oscillator Start-up Timer (OST). */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100753 while ((m_nic_read (CTL_REG_ESTAT) & ENC_ESTAT_CLKRDY) == 0) {
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100754 static int cnt = 0;
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100755
756 if (cnt++ >= 1000) {
757 cnt = 0;
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100758 }
759 }
760
761 /* verify identification */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100762 phid1 = phyRead (PHY_REG_PHID1);
763 phid2 = phyRead (PHY_REG_PHID2);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100764
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100765 if (phid1 != ENC_PHID1_VALUE
766 || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) {
767 printf ("ERROR: failed to identify controller\n");
768 printf ("phid1 = %x, phid2 = %x\n",
769 phid1, (phid2 & ENC_PHID2_MASK));
770 printf ("should be phid1 = %x, phid2 = %x\n",
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100771 ENC_PHID1_VALUE, ENC_PHID2_VALUE);
772 }
773
774 /*
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100775 * --- MAC Initialization ---
776 */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100777
778 /* Pull MAC out of Reset */
779
780 /* switch to bank 2 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100781 m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
782 m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100783 /* clear MAC reset bits */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100784 m_nic_write_retry (CTL_REG_MACON2, 0, 1);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100785
786 /* enable MAC to receive frames */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100787 m_nic_write_retry (CTL_REG_MACON1, ENC_MACON1_MARXEN, 10);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100788
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100789 /* configure pad, tx-crc and duplex */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100790 /* TODO maybe enable FRMLNEN */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100791 m_nic_write_retry (CTL_REG_MACON3,
792 (ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN), 10);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100793
794 /* set maximum frame length */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100795 m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10);
796 m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100797
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100798 /*
799 * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex
800 * and 0x15 for full duplex.
801 */
802 m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100803
804 /* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100805 m_nic_write_retry (CTL_REG_MAIPGL, 0x12, 10);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100806
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100807 /*
808 * Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended
809 * 0x0c for half-duplex. Nothing for full-duplex
810 */
811 m_nic_write_retry (CTL_REG_MAIPGH, 0x0C, 10);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100812
813 /* set MAC address */
814
815 /* switch to bank 3 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100816 m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1));
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100817
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100818 m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1);
819 m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1);
820 m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1);
821 m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1);
822 m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1);
823 m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100824
825 /*
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100826 * Receive settings
827 */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100828
829 /* auto-increment RX-pointer when reading a received packet */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100830 m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_AUTOINC);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100831
832 /* enable interrupts */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100833 m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE);
834 m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE);
835 m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE);
836 m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE);
837 m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100838}
839
840/*****************************************************************************
841 *
842 * Description:
843 * Read PHY registers.
844 *
845 * NOTE! This function will change to Bank 2.
846 *
847 * Params:
848 * [in] addr address of the register to read
849 *
850 * Returns:
851 * The value in the register
852 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100853static unsigned short phyRead (unsigned char addr)
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100854{
855 unsigned short ret = 0;
856
857 /* move to bank 2 */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100858 m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
859 m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100860
861 /* write address to MIREGADR */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100862 m_nic_write (CTL_REG_MIREGADR, addr);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100863
864 /* set MICMD.MIIRD */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100865 m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100866
867 /* poll MISTAT.BUSY bit until operation is complete */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100868 while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100869 static int cnt = 0;
870
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100871 if (cnt++ >= 1000) {
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100872 /* GJ - this seems extremely dangerous! */
873 /* printf("#"); */
874 cnt = 0;
875 }
876 }
877
878 /* clear MICMD.MIIRD */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100879 m_nic_write (CTL_REG_MICMD, 0);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100880
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100881 ret = (m_nic_read (CTL_REG_MIRDH) << 8);
882 ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100883
884 return ret;
885}