]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/ethernet_api.c
merging tmk
[qmk_firmware.git] / tmk_core / tool / mbed / mbed-sdk / libraries / mbed / targets / hal / TARGET_NXP / TARGET_LPC43XX / ethernet_api.c
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2015 ARM Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * Contribution by Nitin Bhaskar(nitin.bhaskar.27.09@gmail.com)
17  */
18 #include "ethernet_api.h"
19
20 #include <string.h>
21 #include "cmsis.h"
22 #include "mbed_interface.h"
23 #include "toolchain.h"
24 #include "mbed_error.h"
25 #include "pinmap.h"
26
27 #define NEW_LOGIC       0
28 #define NEW_ETH_BUFFER  0
29
30 #if NEW_ETH_BUFFER
31
32 #define NUM_RX_FRAG         4           // Number of Rx Fragments (== packets)
33 #define NUM_TX_FRAG         3           // Number of Tx Fragments (== packets)
34
35 #define ETH_MAX_FLEN        1536         // Maximum Ethernet Frame Size
36 #define ETH_FRAG_SIZE       ETH_MAX_FLEN // Packet Fragment size (same as packet length)
37
38 #else
39
40 // Memfree calculation:
41 // (16 * 1024) - ((2 * 4 * NUM_RX) + (2 * 4 * NUM_RX) + (0x300 * NUM_RX) +
42 //                (2 * 4 * NUM_TX) + (1 * 4 * NUM_TX) + (0x300 * NUM_TX)) = 8556
43 /* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
44 #define NUM_RX_FRAG         4           /* Num.of RX Fragments 4*1536= 6.0kB */
45 #define NUM_TX_FRAG         3           /* Num.of TX Fragments 3*1536= 4.6kB */
46 //#define ETH_FRAG_SIZE       1536        /* Packet Fragment size 1536 Bytes   */
47
48 //#define ETH_MAX_FLEN        1536        /* Max. Ethernet Frame Size          */
49 #define ETH_FRAG_SIZE       0x300       /* Packet Fragment size 1536/2 Bytes   */
50 #define ETH_MAX_FLEN        0x300       /* Max. Ethernet Frame Size          */
51
52 const int ethernet_MTU_SIZE  = 0x300;
53
54 #endif
55
56 #define ETHERNET_ADDR_SIZE 6
57
58 /*  Descriptors Fields bits       */
59 #define TRDES_OWN_BIT           (1U<<31)        /*  Own bit in RDES0 & TDES0              */
60 #define RX_END_RING             (1<<15)         /*  Receive End of Ring bit in RDES1      */
61 #define RX_NXTDESC_FLAG         (1<<14)         /*  Second Address Chained bit in RDES1   */
62 #define TX_LAST_SEGM            (1<<29)         /*  Last Segment bit in TDES0             */
63 #define TX_FIRST_SEGM           (1<<28)         /*  First Segment bit in TDES0            */
64 #define TX_END_RING             (1<<21)         /*  Transmit End of Ring bit in TDES0     */
65 #define TX_NXTDESC_FLAG         (1<<20)         /*  Second Address Chained bit in TDES0   */
66
67 PACKED struct RX_DESC_TypeDef {                        /* RX Descriptor struct              */
68     unsigned int Status;
69     unsigned int Ctrl;
70     unsigned int BufAddr1;
71     unsigned int NextDescAddr;
72 };
73 typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;
74
75 PACKED struct TX_DESC_TypeDef {                        /* TX Descriptor struct              */
76     unsigned int Status;
77     unsigned int Ctrl;
78     unsigned int BufAddr1;
79     unsigned int NextDescAddr;
80 };
81 typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;
82
83 /* ETHMODE RMII SELECT */
84 #define RMII_SELECT                     0x04
85 /* define to tell PHY about write operation */
86 #define MII_WRITE               (1 << 1)
87 /* define to tell PHY about read operation */
88 #define MII_READ                (0 << 1)
89 /* define to enable duplex mode */
90 #define MAC_DUPLEX_MODE (1 << 11)
91
92 /* MAC_FRAME_FILTER register bit defines */
93 #define MAC_FRAME_FILTER_PR      (1 << 0)               /* Promiscuous Mode */
94 #define MAC_FRAME_FILTER_RA      (1UL << 31)    /* Receive all */
95
96 /* MAC_CONFIG register bit defines */
97 #define MAC_CONFIG_RE     (1 << 2)              /* Receiver enable */
98 #define MAC_CONFIG_TE     (1 << 3)              /* Transmitter Enable */
99
100 /* DMA_OP_MODE register bit defines */
101 #define DMA_OP_MODE_SSR      (1 << 1)           /* Start/stop receive */
102 #define DMA_OP_MODE_SST      (1 << 13)  /* Start/Stop Transmission Command */
103
104 /* DMA_INT_EN register bit defines */
105 #define DMA_INT_EN_TIE     (1 << 0)             /* Transmit interrupt enable */
106 #define DMA_INT_EN_TSE     (1 << 1)             /* Transmit stopped enable */
107 #define DMA_INT_EN_TUE     (1 << 2)             /* Transmit buffer unavailable enable */
108 #define DMA_INT_EN_TJE     (1 << 3)             /* Transmit jabber timeout enable */
109 #define DMA_INT_EN_OVE     (1 << 4)             /* Overflow interrupt enable */
110 #define DMA_INT_EN_UNE     (1 << 5)             /* Underflow interrupt enable */
111 #define DMA_INT_EN_RIE     (1 << 6)             /* Receive interrupt enable */
112 #define DMA_INT_EN_RUE     (1 << 7)             /* Receive buffer unavailable enable */
113 #define DMA_INT_EN_RSE     (1 << 8)             /* Received stopped enable */
114 #define DMA_INT_EN_RWE     (1 << 9)             /* Receive watchdog timeout enable */
115 #define DMA_INT_EN_ETE     (1 << 10)    /* Early transmit interrupt enable */
116 #define DMA_INT_EN_FBE     (1 << 13)    /* Fatal bus error enable */
117 #define DMA_INT_EN_ERE     (1 << 14)    /* Early receive interrupt enable */
118 #define DMA_INT_EN_AIE     (1 << 15)    /* Abnormal interrupt summary enable */
119 #define DMA_INT_EN_NIE     (1 << 16)    /* Normal interrupt summary enable */
120
121
122
123 /* PHY Support Register */
124 #define SUPP_SPEED          0x00004000  /* Reduced MII Logic Current Speed   */
125 //#define SUPP_RES_RMII       0x00000800  /* Reset Reduced MII Logic           */
126 #define SUPP_RES_RMII       0x00000000  /* Reset Reduced MII Logic           */
127
128 /* MII Management Command Register */
129 #define MCMD_READ           0x00000001  /* MII Read                          */
130 #define MCMD_SCAN           0x00000002  /* MII Scan continuously             */
131
132 #define MII_WR_TOUT         0x00050000  /* MII Write timeout count           */
133 #define MII_RD_TOUT         0x00050000  /* MII Read timeout count            */
134
135 /* MII Management Address Register */
136 #define MADR_REG_ADR        0x0000001F  /* MII Register Address Mask         */
137 #define MADR_PHY_ADR        0x00001F00  /* PHY Address Mask                  */
138
139 /* MII Management Indicators Register */
140 #define MIND_BUSY           0x00000001  /* MII is Busy                       */
141 #define MIND_SCAN           0x00000002  /* MII Scanning in Progress          */
142 #define MIND_NOT_VAL        0x00000004  /* MII Read Data not valid           */
143 #define MIND_MII_LINK_FAIL  0x00000008  /* MII Link Failed                   */
144
145 /* DP83848C PHY Registers */
146 #define PHY_REG_BMCR        0x00        /* Basic Mode Control Register       */
147 #define PHY_REG_BMSR        0x01        /* Basic Mode Status Register        */
148 #define PHY_REG_IDR1        0x02        /* PHY Identifier 1                  */
149 #define PHY_REG_IDR2        0x03        /* PHY Identifier 2                  */
150 #define PHY_REG_ANAR        0x04        /* Auto-Negotiation Advertisement    */
151 #define PHY_REG_ANLPAR      0x05        /* Auto-Neg. Link Partner Abitily    */
152 #define PHY_REG_ANER        0x06        /* Auto-Neg. Expansion Register      */
153 #define PHY_REG_ANNPTR      0x07        /* Auto-Neg. Next Page TX            */
154
155 /* PHY Extended Registers */
156 #define PHY_REG_STS         0x10        /* Status Register                   */
157 #define PHY_REG_MICR        0x11        /* MII Interrupt Control Register    */
158 #define PHY_REG_MISR        0x12        /* MII Interrupt Status Register     */
159 #define PHY_REG_FCSCR       0x14        /* False Carrier Sense Counter       */
160 #define PHY_REG_RECR        0x15        /* Receive Error Counter             */
161 #define PHY_REG_PCSR        0x16        /* PCS Sublayer Config. and Status   */
162 #define PHY_REG_RBR         0x17        /* RMII and Bypass Register          */
163 #define PHY_REG_LEDCR       0x18        /* LED Direct Control Register       */
164 #define PHY_REG_PHYCR       0x19        /* PHY Control Register              */
165 #define PHY_REG_10BTSCR     0x1A        /* 10Base-T Status/Control Register  */
166 #define PHY_REG_CDCTRL1     0x1B        /* CD Test Control and BIST Extens.  */
167 #define PHY_REG_EDCR        0x1D        /* Energy Detect Control Register    */
168
169 #define PHY_REG_SCSR        0x1F        /* PHY Special Control/Status Register */
170
171 #define PHY_FULLD_100M      0x2100      /* Full Duplex 100Mbit               */
172 #define PHY_HALFD_100M      0x2000      /* Half Duplex 100Mbit               */
173 #define PHY_FULLD_10M       0x0100      /* Full Duplex 10Mbit                */
174 #define PHY_HALFD_10M       0x0000      /* Half Duplex 10MBit                */
175 #define PHY_AUTO_NEG        0x1000      /* Select Auto Negotiation           */
176
177 #define DP83848C_DEF_ADR    0x01      /* Default PHY device address        */
178 #define DP83848C_ID         0x20005C90  /* PHY Identifier - DP83848C         */
179
180 #define LAN8720_ID          0x0007C0F0  /* PHY Identifier - LAN8720          */
181
182 #define PHY_STS_LINK        0x0001      /* PHY Status Link Mask              */
183 #define PHY_STS_SPEED       0x0002      /* PHY Status Speed Mask             */
184 #define PHY_STS_DUPLEX      0x0004      /* PHY Status Duplex Mask            */
185
186 #define PHY_BMCR_RESET      0x8000      /* PHY Reset                         */
187
188 #define PHY_BMSR_LINK       0x0004      /* PHY BMSR Link valid               */
189
190 #define PHY_SCSR_100MBIT    0x0008      /* Speed: 1=100 MBit, 0=10Mbit       */
191 #define PHY_SCSR_DUPLEX     0x0010      /* PHY Duplex Mask                   */
192
193 static int phy_read(unsigned int PhyReg);
194 static int phy_write(unsigned int PhyReg, unsigned short Data);
195
196 static void txdscr_init(void);
197 static void rxdscr_init(void);
198
199 #if defined (__ICCARM__)
200 #   define AHBSRAM1
201 #elif defined(TOOLCHAIN_GCC_CR)
202 #   define AHBSRAM1 __attribute__((section(".data.$RamPeriph32")))
203 #else
204 #   define AHBSRAM1     __attribute__((section("AHBSRAM1"),aligned))
205 #endif
206
207 AHBSRAM1 volatile uint8_t rxbuf[NUM_RX_FRAG][ETH_FRAG_SIZE];
208 AHBSRAM1 volatile uint8_t txbuf[NUM_TX_FRAG][ETH_FRAG_SIZE];
209 AHBSRAM1 volatile RX_DESC_TypeDef rxdesc[NUM_RX_FRAG];
210 AHBSRAM1 volatile TX_DESC_TypeDef txdesc[NUM_TX_FRAG];
211
212 #ifndef min
213 #define min(x, y) (((x)<(y))?(x):(y))
214 #endif
215
216 static uint32_t phy_id = 0;
217 static uint32_t TxDescIndex = 0;
218 static uint32_t RxDescIndex = 0;
219 static uint32_t RxOffset = 0;
220
221 /*----------------------------------------------------------------------------
222   Ethernet Device initialize
223  *----------------------------------------------------------------------------*/
224 int ethernet_init()
225 {
226     int regv, tout;
227     char mac[ETHERNET_ADDR_SIZE];
228
229     pin_function(PC_0, (SCU_MODE_INACT | FUNC3));       /* Enable ENET RX CLK */
230     pin_function(P1_19, (SCU_MODE_INACT | FUNC0));      /* Enable ENET TX CLK */
231
232     /* Ethernet pinmuxing       */
233     pin_function(P2_0, SCU_PINIO_FAST | FUNC7);         /* ENET_MDC */
234     pin_function(P1_17, SCU_PINIO_FAST | FUNC3);        /* ENET_MDIO */
235     pin_function(P1_18, SCU_PINIO_FAST | FUNC3);        /* ENET_TXD0 */
236     pin_function(P1_20, SCU_PINIO_FAST | FUNC3);        /* ENET_TXD1 */
237     pin_function(P1_19, SCU_PINIO_FAST | FUNC0);        /* ENET_REF */
238     pin_function(P0_1, SCU_PINIO_FAST | FUNC6);         /* ENET_TX_EN */
239     pin_function(P1_15, SCU_PINIO_FAST | FUNC3);        /* ENET_RXD0 */
240     pin_function(P0_0, SCU_PINIO_FAST | FUNC2);         /* ENET_RXD1 */
241     pin_function(P1_16, SCU_PINIO_FAST | FUNC3);        /* ENET_CRS */
242     pin_function(PC_9, SCU_PINIO_FAST | FUNC3);         /* ENET_RX_ER */
243     pin_function(P1_16, SCU_PINIO_FAST | FUNC7);        /* ENET_RXDV */
244
245     LPC_CREG->CREG6 |= RMII_SELECT;
246
247     /* perform RGU soft reset */
248     LPC_RGU->RESET_CTRL0 = 1 << 22;
249     LPC_RGU->RESET_CTRL0 = 0;
250
251     /* Wait until reset is performed */
252     while(1) {
253         if (LPC_RGU->RESET_ACTIVE_STATUS0 & (1 << 22))
254             break;
255     }
256
257     /* Reset MAC DMA Controller */
258     LPC_ETHERNET->DMA_BUS_MODE |= 0x01;
259     while(LPC_ETHERNET->DMA_BUS_MODE & 0x01);
260
261     phy_write(PHY_REG_BMCR, PHY_BMCR_RESET);           /* perform PHY reset */
262
263     for(tout = 0x20000; ; tout--) {                    /* Wait for hardware reset to end. */
264         regv = phy_read(PHY_REG_BMCR);
265         if(regv < 0 || tout == 0) {
266             return -1;                                    /* Error */
267         }
268         if(!(regv & PHY_BMCR_RESET)) {
269             break;                                        /* Reset complete. */
270         }
271     }
272
273     phy_id =  (phy_read(PHY_REG_IDR1) << 16);
274     phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
275
276     if (phy_id != DP83848C_ID && phy_id != LAN8720_ID) {
277         error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id);
278     }
279
280     ethernet_set_link(-1, 0);
281
282     /* Set the Ethernet MAC Address registers */
283     ethernet_address(mac);
284     LPC_ETHERNET->MAC_ADDR0_HIGH = (mac[5] << 8) | mac[4];
285     LPC_ETHERNET->MAC_ADDR0_LOW =       (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0];
286
287     txdscr_init();                                      /* initialize DMA TX Descriptor */
288     rxdscr_init();                                      /* initialize DMA RX Descriptor */
289
290     /* Configure Filter */
291     LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FRAME_FILTER_PR | MAC_FRAME_FILTER_RA;
292
293     /* Enable Receiver and Transmitter */
294     LPC_ETHERNET->MAC_CONFIG |= (MAC_CONFIG_RE | MAC_CONFIG_TE);
295
296     //LPC_ETHERNET->DMA_INT_EN =  DMA_INT_EN_NIE | DMA_INT_EN_RIE | DMA_INT_EN_TJE;     /* Enable EMAC interrupts. */
297
298     /* Start Transmission & Receive processes   */
299     LPC_ETHERNET->DMA_OP_MODE |= (DMA_OP_MODE_SST | DMA_OP_MODE_SSR);
300
301     return 0;
302 }
303
304 /*----------------------------------------------------------------------------
305   Ethernet Device Uninitialize
306  *----------------------------------------------------------------------------*/
307 void ethernet_free()
308 {
309 }
310
311 /*----------------------------------------------------------------------------
312   Ethernet write
313  *----------------------------------------------------------------------------*/
314 int ethernet_write(const char *data, int slen)
315 {
316     if (slen > ETH_FRAG_SIZE)
317         return -1;
318
319     txdesc[TxDescIndex].Ctrl = slen;
320     memcpy((void *)txdesc[TxDescIndex].BufAddr1, data, slen);
321     return slen;
322 }
323
324 /*----------------------------------------------------------------------------
325   Ethernet Send
326  *----------------------------------------------------------------------------*/
327 int ethernet_send()
328 {
329     int s = txdesc[TxDescIndex].Ctrl;
330     txdesc[TxDescIndex].Status |= TRDES_OWN_BIT;
331     LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;   //  Wake Up the DMA if it's in Suspended Mode
332     TxDescIndex++;
333     if (TxDescIndex == NUM_TX_FRAG)
334         TxDescIndex = 0;
335
336     return s;
337 }
338
339 /*----------------------------------------------------------------------------
340   Ethernet receive
341  *----------------------------------------------------------------------------*/
342 int ethernet_receive()
343 {
344     int i, slen = 0;
345     for (i = RxDescIndex;; i++) {
346         if (rxdesc[i].Status & TRDES_OWN_BIT)
347             return (slen - RxOffset);
348         else
349             slen += (rxdesc[i].Status >> 16) & 0x03FFF;
350     }
351     return 0;
352 }
353
354
355 /*----------------------------------------------------------------------------
356   Ethernet read
357  *----------------------------------------------------------------------------*/
358 int ethernet_read(char *data, int dlen)
359 {
360     int copylen;
361     uint32_t *pSrc = (uint32_t *)rxdesc[RxDescIndex].BufAddr1;
362     copylen = (rxdesc[RxDescIndex].Status >> 16) & 0x03FFF;
363     if (rxdesc[RxDescIndex].Status & TRDES_OWN_BIT || (dlen + RxOffset) > copylen)
364         return -1;
365
366     if ((dlen + RxOffset) == copylen) {
367         memcpy(&pSrc[RxOffset], data, copylen);
368         rxdesc[RxDescIndex].Status = TRDES_OWN_BIT;
369         RxDescIndex++;
370         RxOffset = 0;
371         if (RxDescIndex == NUM_RX_FRAG)
372             RxDescIndex = 0;
373     } else if ((dlen + RxOffset) < copylen) {
374         copylen = dlen;
375         memcpy(&pSrc[RxOffset], data, copylen);
376         RxOffset += dlen;
377     }
378     return copylen;
379 }
380
381 int ethernet_link(void)
382 {
383
384     if (phy_id == DP83848C_ID) {
385         return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
386     } else { // LAN8720_ID
387         return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);
388     }
389 }
390
391 static int phy_write(unsigned int PhyReg, unsigned short Data)
392 {
393     unsigned int timeOut;
394
395     while(LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY);
396     LPC_ETHERNET->MAC_MII_ADDR = (DP83848C_DEF_ADR<<11) | (PhyReg<<6) | MII_WRITE;
397     LPC_ETHERNET->MAC_MII_DATA = Data;
398     LPC_ETHERNET->MAC_MII_ADDR |= MIND_BUSY;                            // Start PHY Write Cycle
399
400     /* Wait utill operation completed */
401     for (timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) {
402         if ((LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY) == 0) {
403             break;
404         }
405     }
406
407     return -1;
408 }
409
410 static int phy_read(unsigned int PhyReg)
411 {
412     unsigned int timeOut;
413
414     while(LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY);
415     LPC_ETHERNET->MAC_MII_ADDR = (DP83848C_DEF_ADR<<11) | (PhyReg<<6) | MII_READ;
416     LPC_ETHERNET->MAC_MII_ADDR |= MIND_BUSY;
417
418     for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) {     /* Wait until operation completed */
419         if((LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY) == 0) {
420             return LPC_ETHERNET->MAC_MII_DATA;               /* Return a 16-bit value. */
421         }
422     }
423
424     return -1;
425 }
426
427 static void txdscr_init()
428 {
429     int i;
430
431     for(i = 0; i < NUM_TX_FRAG; i++) {
432         txdesc[i].Status = TX_LAST_SEGM | TX_FIRST_SEGM;;
433         txdesc[i].Ctrl   = 0;
434         txdesc[i].BufAddr1   = (uint32_t)&txbuf[i];
435         if (i == (NUM_RX_FRAG - 1)) {
436             txdesc[i].Status |= TX_END_RING;
437         }
438     }
439
440     LPC_ETHERNET->DMA_TRANS_DES_ADDR = (uint32_t)txdesc;         /* Set EMAC Transmit Descriptor Registers. */
441 }
442
443
444 static void rxdscr_init()
445 {
446     int i;
447
448     for(i = 0; i < NUM_RX_FRAG; i++) {
449         rxdesc[i].Status  = TRDES_OWN_BIT;
450         rxdesc[i].Ctrl    = ETH_FRAG_SIZE;
451         rxdesc[i].BufAddr1  = (uint32_t)&rxbuf[i];
452         if (i == (NUM_RX_FRAG - 1)) {
453             rxdesc[i].Ctrl |= RX_END_RING;
454         }
455     }
456
457     LPC_ETHERNET->DMA_REC_DES_ADDR = (uint32_t)rxdesc;        /* Set EMAC Receive Descriptor Registers. */
458 }
459
460 void ethernet_address(char *mac)
461 {
462     mbed_mac_address(mac);
463 }
464
465 void ethernet_set_link(int speed, int duplex)
466 {
467     volatile unsigned short phy_data;
468     int tout;
469
470     if((speed < 0) || (speed > 1)) {
471
472         phy_data = PHY_AUTO_NEG;
473
474     } else {
475
476         phy_data = (((unsigned short) speed << 13) |
477                     ((unsigned short) duplex << 8));
478     }
479
480     phy_write(PHY_REG_BMCR, phy_data);
481
482     for(tout = 100; tout; tout--) {
483         __NOP();    /* A short delay */
484     }
485
486     switch(phy_id) {
487         case DP83848C_ID:
488
489             phy_data = phy_read(PHY_REG_STS);
490
491             if(phy_data & PHY_STS_DUPLEX) {
492                 /* Full duplex is enabled. */
493                 LPC_ETHERNET->MAC_CONFIG |= MAC_DUPLEX_MODE;
494             } else {
495                 LPC_ETHERNET->MAC_CONFIG &= ~MAC_DUPLEX_MODE;
496             }
497
498             if(phy_data & PHY_STS_SPEED) {
499                 LPC_ETHERNET->MAC_CONFIG &= ~SUPP_SPEED;
500             } else {
501                 LPC_ETHERNET->MAC_CONFIG |= SUPP_SPEED;
502             }
503             break;
504
505         case LAN8720_ID:
506
507             for(tout = 100; tout; tout--) {
508                 phy_data = phy_read(PHY_REG_BMSR);
509                 if (phy_data & PHY_STS_DUPLEX)
510                     break;
511             }
512
513             if (phy_data & PHY_STS_DUPLEX) {
514                 /* Full duplex is enabled. */
515                 LPC_ETHERNET->MAC_CONFIG |= MAC_DUPLEX_MODE;
516             } else {
517                 LPC_ETHERNET->MAC_CONFIG &= ~MAC_DUPLEX_MODE;
518             }
519
520             if(phy_data & PHY_STS_SPEED) {
521                 LPC_ETHERNET->MAC_CONFIG &= ~SUPP_SPEED;
522             } else {
523                 LPC_ETHERNET->MAC_CONFIG |= SUPP_SPEED;
524             }
525             break;
526     }
527 }
528