|
@@ -1,10 +1,10 @@
|
1
|
1
|
/**************************************************************************
|
2
|
|
-Etherboot - BOOTP/TFTP Bootstrap Program
|
3
|
|
-P2001 NIC driver for Etherboot
|
4
|
|
-***************************************************************************/
|
|
2
|
+ * Etherboot - BOOTP/TFTP Bootstrap Program
|
|
3
|
+ * P2001 NIC driver for Etherboot
|
|
4
|
+ **************************************************************************/
|
5
|
5
|
|
6
|
6
|
/*
|
7
|
|
- * Copyright (C) 2004 Tobias Lorenz
|
|
7
|
+ * Copyright (C) 2005 Tobias Lorenz
|
8
|
8
|
*
|
9
|
9
|
* This program is free software; you can redistribute it and/or modify
|
10
|
10
|
* it under the terms of the GNU General Public License version 2 as
|
|
@@ -19,7 +19,7 @@ P2001 NIC driver for Etherboot
|
19
|
19
|
#include "isa.h"
|
20
|
20
|
|
21
|
21
|
#include "hardware.h"
|
22
|
|
-#include "lxt971a.h"
|
|
22
|
+#include "mii.h"
|
23
|
23
|
#include "timer.h"
|
24
|
24
|
|
25
|
25
|
|
|
@@ -31,25 +31,20 @@ static unsigned char MAC_HW_ADDR[6]={MAC_HW_ADDR_DRV};
|
31
|
31
|
#define DMA_BUF_SIZE 2048 /* Buffer size */
|
32
|
32
|
static DMA_DSC txd __attribute__ ((__section__(".dma.desc")));
|
33
|
33
|
static DMA_DSC rxd[NUM_RX_DESC] __attribute__ ((__section__(".dma.desc")));
|
34
|
|
-static unsigned char rxb[NUM_RX_DESC * DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
|
35
|
|
-static unsigned char txb[ DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
|
|
34
|
+static char rxb[NUM_RX_DESC * DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
|
|
35
|
+static char txb[ DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
|
36
|
36
|
static unsigned int cur_rx;
|
37
|
37
|
|
38
|
38
|
/* Device selectors */
|
39
|
39
|
static unsigned int cur_channel; // DMA channel : 0..3
|
40
|
40
|
static unsigned int cur_phy; // PHY Address : 0..31
|
41
|
41
|
static P2001_ETH_regs_ptr EU; // Ethernet Unit : 0x0018_000 with _=0..3
|
42
|
|
-static P2001_ETH_regs_ptr MU; // Management Unit: 0x00180000
|
43
|
42
|
|
44
|
|
-#define MDIO_MAXCOUNT 1000 /* mdio abort */
|
45
|
|
-static unsigned int mdio_error; /* mdio error */
|
46
|
|
-
|
47
|
|
-/* Function prototypes */
|
48
|
|
-static void p2001_eth_mdio_init ();
|
49
|
|
-static void p2001_eth_mdio_write(unsigned int phyadr, unsigned int regadr, unsigned int data);
|
50
|
|
-static unsigned int p2001_eth_mdio_read (unsigned int phyadr, unsigned int regadr);
|
51
|
|
-extern unsigned int p2001_eth_mdio_error;
|
|
43
|
+/* mdio handling */
|
|
44
|
+static int p2001_eth_mdio_read (int phy_id, int location);
|
|
45
|
+static void p2001_eth_mdio_write(int phy_id, int location, int val);
|
52
|
46
|
|
|
47
|
+/* net_device functions */
|
53
|
48
|
static int p2001_eth_poll (struct nic *nic, int retrieve);
|
54
|
49
|
static void p2001_eth_transmit (struct nic *nic, const char *d,
|
55
|
50
|
unsigned int t, unsigned int s, const char *p);
|
|
@@ -60,103 +55,107 @@ static void p2001_eth_init ();
|
60
|
55
|
static void p2001_eth_disable (struct dev *dev);
|
61
|
56
|
|
62
|
57
|
static int p2001_eth_check_link(unsigned int phy);
|
|
58
|
+static int link;
|
|
59
|
+static void p2001_eth_phyreset ();
|
63
|
60
|
static int p2001_eth_probe (struct dev *dev, unsigned short *probe_addrs __unused);
|
64
|
61
|
|
|
62
|
+/* Supported MII list */
|
|
63
|
+static struct mii_chip_info {
|
|
64
|
+ const char * name;
|
|
65
|
+ unsigned int physid; // (MII_PHYSID2 << 16) | MII_PHYSID1
|
|
66
|
+} mii_chip_table[] = {
|
|
67
|
+ { "Intel LXT971A", 0x78e20013 },
|
|
68
|
+ { "Altima AC104-QF", 0x55410022 },
|
|
69
|
+ {NULL,0},
|
|
70
|
+};
|
|
71
|
+
|
|
72
|
+
|
65
|
73
|
|
66
|
74
|
/**************************************************************************
|
67
|
|
-PHY MANAGEMENT UNIT - Read/write
|
68
|
|
-***************************************************************************/
|
69
|
|
-static void p2001_eth_mdio_init()
|
|
75
|
+ * PHY MANAGEMENT UNIT - Read/write
|
|
76
|
+ **************************************************************************/
|
|
77
|
+
|
|
78
|
+/**
|
|
79
|
+ * mdio_read - read MII PHY register
|
|
80
|
+ * @dev: the net device to read
|
|
81
|
+ * @regadr: the phy register id to read
|
|
82
|
+ *
|
|
83
|
+ * Read MII registers through MDIO and MDC
|
|
84
|
+ * using MDIO management frame structure and protocol(defined by ISO/IEC).
|
|
85
|
+ */
|
|
86
|
+static int p2001_eth_mdio_read(int phy_id, int location)
|
70
|
87
|
{
|
71
|
|
- /* reset ethernet PHYs */
|
72
|
|
- printf("Resetting PHYs...\n");
|
|
88
|
+ int result, boguscnt = 1000;
|
73
|
89
|
|
74
|
|
- /* GPIO24/25: TX_ER2/TX_ER0 */
|
75
|
|
- /* GPIO26/27: PHY_RESET/TX_ER1 */
|
76
|
|
- P2001_GPIO->PIN_MUX |= 0x0018;
|
77
|
|
- // 31-16: 0000 1111 0000 0000
|
78
|
|
- P2001_GPIO->GPIO2_En |= 0x0400;
|
|
90
|
+ do {
|
|
91
|
+ /* Warten bis Hardware inaktiv (MIU = "0") */
|
|
92
|
+ while (P2001_MU->MU_CNTL & 0x8000)
|
|
93
|
+ barrier();
|
79
|
94
|
|
80
|
|
- P2001_GPIO->GPIO2_Out |= 0x04000000;
|
81
|
|
- P2001_GPIO->GPIO2_Out &= ~0x0400;
|
82
|
|
- mdelay(500);
|
83
|
|
- P2001_GPIO->GPIO2_Out |= 0x0400;
|
|
95
|
+ /* Schreiben MU_CNTL */
|
|
96
|
+ P2001_MU->MU_CNTL = location + (phy_id<<5) + (2<<10);
|
84
|
97
|
|
85
|
|
- /* set management unit clock divisor */
|
86
|
|
- // max. MDIO CLK = 2.048 MHz (EU.doc)
|
87
|
|
- // max. MDIO CLK = 8.000 MHz (LXT971A)
|
88
|
|
- // sysclk/(2*(n+1)) = MDIO CLK <= 2.048 MHz
|
89
|
|
- // n >= sysclk/4.096 MHz - 1
|
90
|
|
-#if SYSCLK == 73728000
|
91
|
|
- P2001_MU->MU_DIV = 17; // 73.728 MHZ =17=> 2.020 MHz
|
92
|
|
-#else
|
93
|
|
- //MU->MU_DIV = (SYSCLK/4.096)-1;
|
94
|
|
-#error "Please define a proper MDIO CLK divisor for that sysclk."
|
95
|
|
-#endif
|
96
|
|
- asm("nop \n nop");
|
|
98
|
+ /* Warten bis Hardware aktiv (MIU = "1") */
|
|
99
|
+ while ((P2001_MU->MU_CNTL & 0x8000) == 0)
|
|
100
|
+ barrier();
|
|
101
|
+ //asm("nop \r\n nop");
|
|
102
|
+
|
|
103
|
+ /* Warten bis Hardware inaktiv (MIU = "0") */
|
|
104
|
+ while (P2001_MU->MU_CNTL & 0x8000)
|
|
105
|
+ barrier();
|
|
106
|
+
|
|
107
|
+ /* Fehler, wenn MDIO Read Error (MRE = "1") */
|
|
108
|
+ } while ((P2001_MU->MU_CNTL & 0x4000) && (--boguscnt > 0));
|
|
109
|
+
|
|
110
|
+ /* Lesen MU_DATA */
|
|
111
|
+ result = P2001_MU->MU_DATA;
|
|
112
|
+
|
|
113
|
+ if (boguscnt == 0)
|
|
114
|
+ return 0;
|
|
115
|
+ if ((result & 0xffff) == 0xffff)
|
|
116
|
+ return 0;
|
|
117
|
+
|
|
118
|
+ return result & 0xffff;
|
97
|
119
|
}
|
98
|
120
|
|
99
|
|
-static void p2001_eth_mdio_write(unsigned int phyadr, unsigned int regadr, unsigned int data)
|
100
|
|
-{
|
101
|
|
- static unsigned int count;
|
102
|
|
- count = 0;
|
103
|
121
|
|
|
122
|
+/**
|
|
123
|
+ * mdio_write - write MII PHY register
|
|
124
|
+ * @dev: the net device to write
|
|
125
|
+ * @regadr: the phy register id to write
|
|
126
|
+ * @value: the register value to write with
|
|
127
|
+ *
|
|
128
|
+ * Write MII registers with @value through MDIO and MDC
|
|
129
|
+ * using MDIO management frame structure and protocol(defined by ISO/IEC)
|
|
130
|
+ */
|
|
131
|
+static void p2001_eth_mdio_write(int phy_id, int location, int val)
|
|
132
|
+{
|
104
|
133
|
/* Warten bis Hardware inaktiv (MIU = "0") */
|
105
|
|
- while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
|
106
|
|
- count++;
|
|
134
|
+ while (P2001_MU->MU_CNTL & 0x8000)
|
|
135
|
+ barrier();
|
107
|
136
|
|
108
|
137
|
/* Schreiben MU_DATA */
|
109
|
|
- MU->MU_DATA = data;
|
|
138
|
+ P2001_MU->MU_DATA = val;
|
110
|
139
|
|
111
|
140
|
/* Schreiben MU_CNTL */
|
112
|
|
- MU->MU_CNTL = regadr + (phyadr<<5) + (1<<10);
|
|
141
|
+ P2001_MU->MU_CNTL = location + (phy_id<<5) + (1<<10);
|
113
|
142
|
|
114
|
143
|
/* Warten bis Hardware aktiv (MIU = "1") */
|
115
|
|
- while (((MU->MU_CNTL & 0x8000) == 0) && (count < MDIO_MAXCOUNT))
|
116
|
|
- count++;
|
|
144
|
+ while ((P2001_MU->MU_CNTL & 0x8000) == 0)
|
|
145
|
+ barrier();
|
117
|
146
|
//asm("nop \r\n nop");
|
118
|
147
|
|
119
|
148
|
/* Warten bis Hardware inaktiv (MIU = "0") */
|
120
|
|
- while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
|
121
|
|
- count++;
|
122
|
|
-
|
123
|
|
- mdio_error = (count >= MDIO_MAXCOUNT);
|
|
149
|
+ while (P2001_MU->MU_CNTL & 0x8000)
|
|
150
|
+ barrier();
|
124
|
151
|
}
|
125
|
152
|
|
126
|
|
-static unsigned int p2001_eth_mdio_read(unsigned int phyadr, unsigned int regadr)
|
127
|
|
-{
|
128
|
|
- static unsigned int count;
|
129
|
|
- count = 0;
|
130
|
|
-
|
131
|
|
- do {
|
132
|
|
- /* Warten bis Hardware inaktiv (MIU = "0") */
|
133
|
|
- while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
|
134
|
|
- count++;
|
135
|
|
-
|
136
|
|
- /* Schreiben MU_CNTL */
|
137
|
|
- MU->MU_CNTL = regadr + (phyadr<<5) + (2<<10);
|
138
|
|
-
|
139
|
|
- /* Warten bis Hardware aktiv (MIU = "1") */
|
140
|
|
- while (((MU->MU_CNTL & 0x8000) == 0) && (count < MDIO_MAXCOUNT))
|
141
|
|
- count++;
|
142
|
|
- //asm("nop \r\n nop");
|
143
|
|
-
|
144
|
|
- /* Warten bis Hardware inaktiv (MIU = "0") */
|
145
|
|
- while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
|
146
|
|
- count++;
|
147
|
|
-
|
148
|
|
- /* Fehler, wenn MDIO Read Error (MRE = "1") */
|
149
|
|
- } while ((MU->MU_CNTL & 0x4000) && (count < MDIO_MAXCOUNT));
|
150
|
|
-
|
151
|
|
- /* Lesen MU_DATA */
|
152
|
|
- mdio_error = (count >= MDIO_MAXCOUNT);
|
153
|
|
- return MU->MU_DATA;
|
154
|
|
-}
|
155
|
153
|
|
156
|
154
|
|
157
|
155
|
/**************************************************************************
|
158
|
|
-POLL - Wait for a frame
|
159
|
|
-***************************************************************************/
|
|
156
|
+ * POLL - Wait for a frame
|
|
157
|
+ **************************************************************************/
|
|
158
|
+
|
160
|
159
|
/* Function: p2001_eth_poll
|
161
|
160
|
*
|
162
|
161
|
* Description: checks for a received packet and returns it if found.
|
|
@@ -231,9 +230,11 @@ static int p2001_eth_poll(struct nic *nic, int retrieve)
|
231
|
230
|
}
|
232
|
231
|
|
233
|
232
|
|
|
233
|
+
|
234
|
234
|
/**************************************************************************
|
235
|
|
-TRANSMIT - Transmit a frame
|
236
|
|
-***************************************************************************/
|
|
235
|
+ * TRANSMIT - Transmit a frame
|
|
236
|
+ **************************************************************************/
|
|
237
|
+
|
237
|
238
|
/* Function: p2001_eth_transmit
|
238
|
239
|
*
|
239
|
240
|
* Description: transmits a packet and waits for completion or timeout.
|
|
@@ -271,7 +272,7 @@ static void p2001_eth_transmit(
|
271
|
272
|
// TMAC_CNTL.ATP does the same
|
272
|
273
|
|
273
|
274
|
#ifdef DEBUG_NIC
|
274
|
|
- printf("p2001_eth_transmit: packet from %! to %! sent\n", txb+ETH_ALEN, txb);
|
|
275
|
+ printf("p2001_eth_transmit: packet from %! to %! sent (size: %d)\n", txb+ETH_ALEN, txb, s);
|
275
|
276
|
#endif
|
276
|
277
|
|
277
|
278
|
/* configure descriptor */
|
|
@@ -281,12 +282,12 @@ static void p2001_eth_transmit(
|
281
|
282
|
|
282
|
283
|
/* restart the transmitter */
|
283
|
284
|
EU->TMAC_DMA_EN = 0x01; /* set run bit */
|
284
|
|
- while(EU->TMAC_DMA_EN & 0x01) ; /* wait */
|
|
285
|
+ while(EU->TMAC_DMA_EN & 0x01); /* wait */
|
285
|
286
|
|
286
|
287
|
#ifdef DEBUG_NIC
|
287
|
288
|
/* check status */
|
288
|
289
|
status = EU->TMAC_DMA_STAT;
|
289
|
|
- if (status & ~(0x40))
|
|
290
|
+ if (status & ~(0x40)) // not END
|
290
|
291
|
printf("p2001_eth_transmit: dma status=0x%hx\n", status);
|
291
|
292
|
|
292
|
293
|
printf("TMAC_MIB6..7: %d:%d\n", EU->TMAC_MIB6, EU->TMAC_MIB7);
|
|
@@ -294,9 +295,11 @@ static void p2001_eth_transmit(
|
294
|
295
|
}
|
295
|
296
|
|
296
|
297
|
|
|
298
|
+
|
297
|
299
|
/**************************************************************************
|
298
|
|
-IRQ - Enable, Disable or Force Interrupts
|
299
|
|
-***************************************************************************/
|
|
300
|
+ * IRQ - Enable, Disable or Force Interrupts
|
|
301
|
+ **************************************************************************/
|
|
302
|
+
|
300
|
303
|
/* Function: p2001_eth_irq
|
301
|
304
|
*
|
302
|
305
|
* Description: Enable, Disable, or Force, interrupts
|
|
@@ -321,9 +324,11 @@ p2001_eth_irq(struct nic *nic __unused, irq_action_t action __unused)
|
321
|
324
|
}
|
322
|
325
|
|
323
|
326
|
|
|
327
|
+
|
324
|
328
|
/**************************************************************************
|
325
|
|
-INIT - Initialize device
|
326
|
|
-***************************************************************************/
|
|
329
|
+ * INIT - Initialize device
|
|
330
|
+ **************************************************************************/
|
|
331
|
+
|
327
|
332
|
/* Function: p2001_init
|
328
|
333
|
*
|
329
|
334
|
* Description: resets the ethernet controller chip and various
|
|
@@ -335,6 +340,23 @@ static void p2001_eth_init()
|
335
|
340
|
{
|
336
|
341
|
static int i;
|
337
|
342
|
|
|
343
|
+ /* activate MII 3 */
|
|
344
|
+ if (cur_channel == 3)
|
|
345
|
+ P2001_GPIO->PIN_MUX |= (1<<8); // MII_3_en = 1
|
|
346
|
+
|
|
347
|
+#ifdef RMII
|
|
348
|
+ /* RMII init sequence */
|
|
349
|
+ if (link & LPA_100) {
|
|
350
|
+ EU->CONF_RMII = (1<<2) | (1<<1); // softres | 100Mbit
|
|
351
|
+ EU->CONF_RMII = (1<<2) | (1<<1) | (1<<0); // softres | 100Mbit | RMII
|
|
352
|
+ EU->CONF_RMII = (1<<1) | (1<<0); // 100 Mbit | RMII
|
|
353
|
+ } else {
|
|
354
|
+ EU->CONF_RMII = (1<<2); // softres
|
|
355
|
+ EU->CONF_RMII = (1<<2) | (1<<0); // softres | RMII
|
|
356
|
+ EU->CONF_RMII = (1<<0); // RMII
|
|
357
|
+ }
|
|
358
|
+#endif
|
|
359
|
+
|
338
|
360
|
/* disable transceiver */
|
339
|
361
|
// EU->TMAC_DMA_EN = 0; /* clear run bit */
|
340
|
362
|
// EU->RMAC_DMA_EN = 0; /* clear run bit */
|
|
@@ -353,7 +375,7 @@ static void p2001_eth_init()
|
353
|
375
|
// txd.stat = (1<<31) | (1<<30) | (1<<29); // DSC0 OWN|START|END
|
354
|
376
|
// txd.cntl = cur_channel << 16; // DSC1 CHANNEL
|
355
|
377
|
// txd.cntl |= DMA_BUF_SIZE; // DSC1 LEN
|
356
|
|
- txd.buf = &txb; // DSC2 BUFFER
|
|
378
|
+ txd.buf = (char *)&txb; // DSC2 BUFFER
|
357
|
379
|
txd.next = &txd; // DSC3 NEXTDSC @self
|
358
|
380
|
EU->TMAC_DMA_DESC = &txd;
|
359
|
381
|
|
|
@@ -371,9 +393,12 @@ static void p2001_eth_init()
|
371
|
393
|
EU->RMAC_DMA_DESC = &rxd[0];
|
372
|
394
|
|
373
|
395
|
/* set transmitter mode */
|
374
|
|
- EU->TMAC_CNTL = (1<<4) | /* COI: Collision ignore */
|
375
|
|
- //(1<<3) | /* CSI: Carrier Sense ignore */
|
376
|
|
- (1<<2); /* ATP: Automatic Transmit Padding */
|
|
396
|
+ if (link & LPA_DUPLEX)
|
|
397
|
+ EU->TMAC_CNTL = (1<<4) | /* COI: Collision ignore */
|
|
398
|
+ (1<<3) | /* CSI: Carrier Sense ignore */
|
|
399
|
+ (1<<2); /* ATP: Automatic Transmit Padding */
|
|
400
|
+ else
|
|
401
|
+ EU->TMAC_CNTL = (1<<2); /* ATP: Automatic Transmit Padding */
|
377
|
402
|
|
378
|
403
|
/* set receive mode */
|
379
|
404
|
EU->RMAC_CNTL = (1<<3) | /* BROAD: Broadcast packets */
|
|
@@ -384,9 +409,10 @@ static void p2001_eth_init()
|
384
|
409
|
}
|
385
|
410
|
|
386
|
411
|
|
|
412
|
+
|
387
|
413
|
/**************************************************************************
|
388
|
|
-DISABLE - Turn off ethernet interface
|
389
|
|
-***************************************************************************/
|
|
414
|
+ * DISABLE - Turn off ethernet interface
|
|
415
|
+ **************************************************************************/
|
390
|
416
|
static void p2001_eth_disable(struct dev *dev __unused)
|
391
|
417
|
{
|
392
|
418
|
/* put the card in its initial state */
|
|
@@ -408,40 +434,52 @@ static void p2001_eth_disable(struct dev *dev __unused)
|
408
|
434
|
}
|
409
|
435
|
|
410
|
436
|
|
|
437
|
+
|
411
|
438
|
/**************************************************************************
|
412
|
|
-LINK - Check for valid link
|
413
|
|
-***************************************************************************/
|
|
439
|
+ * LINK - Check for valid link
|
|
440
|
+ **************************************************************************/
|
414
|
441
|
static int p2001_eth_check_link(unsigned int phy)
|
415
|
442
|
{
|
416
|
443
|
static int status;
|
417
|
|
- static unsigned int count;
|
418
|
|
- count = 0;
|
|
444
|
+ static unsigned int i, physid;
|
|
445
|
+
|
|
446
|
+ /* print some information about out PHY */
|
|
447
|
+ physid = (p2001_eth_mdio_read(phy, MII_PHYSID2) << 16) |
|
|
448
|
+ p2001_eth_mdio_read(phy, MII_PHYSID1);
|
|
449
|
+ printf("PHY %d, ID 0x%x ", phy, physid);
|
|
450
|
+ for (i = 0; mii_chip_table[i].physid; i++)
|
|
451
|
+ if (mii_chip_table[i].physid == physid) {
|
|
452
|
+ printf("(%s).\n", mii_chip_table[i].name);
|
|
453
|
+ break;
|
|
454
|
+ }
|
|
455
|
+ if (!mii_chip_table[i].physid)
|
|
456
|
+ printf("(unknown).\n");
|
419
|
457
|
|
420
|
458
|
/* Use 0x3300 for restarting NWay */
|
421
|
459
|
printf("Starting auto-negotiation... ");
|
422
|
|
- p2001_eth_mdio_write(phy, Adr_LXT971A_Control, 0x3300);
|
423
|
|
- if (mdio_error)
|
424
|
|
- goto failed;
|
|
460
|
+ p2001_eth_mdio_write(phy, MII_BMCR, 0x3300);
|
425
|
461
|
|
426
|
|
- /* Bits 1.5 and 17.7 are set to 1 once the Auto-Negotiation process to completed. */
|
|
462
|
+ /* Bit 1.5 is set once the Auto-Negotiation process is completed. */
|
|
463
|
+ i = 0;
|
427
|
464
|
do {
|
428
|
465
|
mdelay(500);
|
429
|
|
- status = p2001_eth_mdio_read(phy, Adr_LXT971A_Status1);
|
430
|
|
- if (mdio_error || (count++ > 6)) // 6*500ms = 3s timeout
|
|
466
|
+ status = p2001_eth_mdio_read(phy, MII_BMSR);
|
|
467
|
+ if (!status || (i++ > 6)) // 6*500ms = 3s timeout
|
431
|
468
|
goto failed;
|
432
|
|
- } while (!(status & 0x20));
|
433
|
|
-
|
434
|
|
- /* Bits 1.2 and 17.10 are set to 1 once the link is established. */
|
435
|
|
- if (p2001_eth_mdio_read(phy, Adr_LXT971A_Status1) & 0x04) {
|
436
|
|
- /* Bits 17.14 and 17.9 can be used to determine the link operation conditions (speed and duplex). */
|
437
|
|
- printf("Valid link, operating at: %sMb-%s\n",
|
438
|
|
- (p2001_eth_mdio_read(phy, Adr_LXT971A_Status2) & 0x4000) ? "100" : "10",
|
439
|
|
- (p2001_eth_mdio_read(phy, Adr_LXT971A_Status2) & 0x0200) ? "FD" : "HD");
|
440
|
|
- return 1;
|
|
469
|
+ } while (!(status & BMSR_ANEGCOMPLETE));
|
|
470
|
+
|
|
471
|
+ /* Bits 1.2 is set once the link is established. */
|
|
472
|
+ if ((status = p2001_eth_mdio_read(phy, MII_BMSR)) & BMSR_LSTATUS) {
|
|
473
|
+ link = p2001_eth_mdio_read(phy, MII_ADVERTISE) &
|
|
474
|
+ p2001_eth_mdio_read(phy, MII_LPA);
|
|
475
|
+ printf(" Valid link, operating at: %sMb-%s\n",
|
|
476
|
+ (link & LPA_100) ? "100" : "10",
|
|
477
|
+ (link & LPA_DUPLEX) ? "FD" : "HD");
|
|
478
|
+ return 1;
|
441
|
479
|
}
|
442
|
480
|
|
443
|
481
|
failed:
|
444
|
|
- if (mdio_error)
|
|
482
|
+ if (!status)
|
445
|
483
|
printf("Failed\n");
|
446
|
484
|
else
|
447
|
485
|
printf("No valid link\n");
|
|
@@ -449,49 +487,79 @@ failed:
|
449
|
487
|
}
|
450
|
488
|
|
451
|
489
|
|
|
490
|
+
|
|
491
|
+/**************************************************************************
|
|
492
|
+ * PHYRESET - hardware reset all MII PHYs
|
|
493
|
+ **************************************************************************/
|
|
494
|
+
|
|
495
|
+/**
|
|
496
|
+ * p2001_eth_phyreset - hardware reset all MII PHYs
|
|
497
|
+ */
|
|
498
|
+static void p2001_eth_phyreset()
|
|
499
|
+{
|
|
500
|
+ /* GPIO24/25: TX_ER2/TX_ER0 */
|
|
501
|
+ /* GPIO26/27: PHY_RESET/TX_ER1 */
|
|
502
|
+ P2001_GPIO->PIN_MUX |= 0x0018;
|
|
503
|
+ // 31-16: 0000 1111 0000 0000
|
|
504
|
+ P2001_GPIO->GPIO2_En |= 0x0400;
|
|
505
|
+
|
|
506
|
+ P2001_GPIO->GPIO2_Out |= 0x04000000;
|
|
507
|
+ P2001_GPIO->GPIO2_Out &= ~0x0400;
|
|
508
|
+ mdelay(500);
|
|
509
|
+ P2001_GPIO->GPIO2_Out |= 0x0400;
|
|
510
|
+
|
|
511
|
+#ifdef RMII
|
|
512
|
+ /* RMII_clk_sel = 0xxb no RMII (default) */
|
|
513
|
+ /* RMII_clk_sel = 100b COL_0 */
|
|
514
|
+ /* RMII_clk_sel = 101b COL_1 */
|
|
515
|
+ /* RMII_clk_sel = 110b COL_2 */
|
|
516
|
+ /* RMII_clk_sel = 111b COL_3 */
|
|
517
|
+ P2001_GPIO->PIN_MUX |= (4 << 13);
|
|
518
|
+#endif
|
|
519
|
+}
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
452
|
523
|
/**************************************************************************
|
453
|
|
-PROBE - Look for an adapter, this routine's visible to the outside
|
454
|
|
-***************************************************************************/
|
|
524
|
+ * PROBE - Look for an adapter, this routine's visible to the outside
|
|
525
|
+ **************************************************************************/
|
|
526
|
+
|
455
|
527
|
static int p2001_eth_probe(struct dev *dev, unsigned short *probe_addrs __unused)
|
456
|
528
|
{
|
457
|
529
|
struct nic *nic = (struct nic *)dev;
|
458
|
530
|
/* if probe_addrs is 0, then routine can use a hardwired default */
|
459
|
|
- static int board_found;
|
460
|
|
- static int valid_link;
|
461
|
531
|
|
462
|
532
|
/* reset phys and configure mdio clk */
|
463
|
|
- p2001_eth_mdio_init();
|
|
533
|
+ printf("Resetting PHYs...\n");
|
|
534
|
+ p2001_eth_phyreset();
|
|
535
|
+
|
|
536
|
+ /* set management unit clock divisor */
|
|
537
|
+ // max. MDIO CLK = 2.048 MHz (EU.doc)
|
|
538
|
+ P2001_MU->MU_DIV = (SYSCLK/4096000)-1; // 2.048 MHz
|
|
539
|
+ //asm("nop \n nop");
|
464
|
540
|
|
465
|
541
|
/* find the correct PHY/DMA/MAC combination */
|
466
|
|
- MU = P2001_MU; // MU for all PHYs is only in EU0
|
467
|
542
|
printf("Searching for P2001 NICs...\n");
|
|
543
|
+ cur_phy = -1;
|
468
|
544
|
for (cur_channel=0; cur_channel<4; cur_channel++) {
|
469
|
|
- switch(cur_channel) {
|
470
|
|
- case 0:
|
471
|
|
- EU = P2001_EU0;
|
472
|
|
- cur_phy = 0;
|
473
|
|
- break;
|
474
|
|
- case 1:
|
475
|
|
- EU = P2001_EU1;
|
476
|
|
- cur_phy = 1;
|
477
|
|
- break;
|
478
|
|
- case 2:
|
479
|
|
- EU = P2001_EU2;
|
480
|
|
- cur_phy = 2;
|
481
|
|
- break;
|
482
|
|
- case 3:
|
483
|
|
- EU = P2001_EU3;
|
484
|
|
- cur_phy = 3;
|
|
545
|
+ EU = P2001_EU(cur_channel);
|
|
546
|
+
|
|
547
|
+ /* find next phy */
|
|
548
|
+ while (++cur_phy < 16) {
|
|
549
|
+ //printf("phy detect %d\n", cur_phy);
|
|
550
|
+ if (p2001_eth_mdio_read(cur_phy, MII_BMSR) != 0)
|
485
|
551
|
break;
|
486
|
552
|
}
|
|
553
|
+ if (cur_phy == 16) {
|
|
554
|
+ printf("no more MII PHYs found\n");
|
|
555
|
+ break;
|
|
556
|
+ }
|
487
|
557
|
|
488
|
558
|
/* first a non destructive test for initial value RMAC_TLEN=1518 */
|
489
|
|
- board_found = (EU->RMAC_TLEN == 1518);
|
490
|
|
- if (board_found) {
|
|
559
|
+ if (EU->RMAC_TLEN == 1518) {
|
491
|
560
|
printf("Checking EU%d...\n", cur_channel);
|
492
|
561
|
|
493
|
|
- valid_link = p2001_eth_check_link(cur_phy);
|
494
|
|
- if (valid_link) {
|
|
562
|
+ if (p2001_eth_check_link(cur_phy)) {
|
495
|
563
|
/* initialize device */
|
496
|
564
|
p2001_eth_init(nic);
|
497
|
565
|
|
|
@@ -507,7 +575,6 @@ static int p2001_eth_probe(struct dev *dev, unsigned short *probe_addrs __unused
|
507
|
575
|
|
508
|
576
|
/* Report the ISA pnp id of the board */
|
509
|
577
|
dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
|
510
|
|
- dev->devid.vendor_id = htons(0x1234);
|
511
|
578
|
return 1;
|
512
|
579
|
}
|
513
|
580
|
}
|