Add Auto-MDIX support for INCA-IP
[pandora-u-boot.git] / drivers / inca-ip_sw.c
1 /*
2  * INCA-IP internal switch ethernet driver.
3  *
4  * (C) Copyright 2003
5  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26
27 #include <common.h>
28
29 #if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
30         && defined(CONFIG_INCA_IP_SWITCH)
31
32 #include <malloc.h>
33 #include <net.h>
34 #include <asm/inca-ip.h>
35 #include <asm/addrspace.h>
36
37
38 #define NUM_RX_DESC     PKTBUFSRX
39 #define NUM_TX_DESC     3
40 #define TOUT_LOOP       1000000
41
42
43 #define DELAY   udelay(10000)
44
45 #define DMA_WRITE_REG(reg, value) *((volatile u32 *)reg) = (u32)value;
46 #define DMA_READ_REG(reg, value)    value = (u32)*((volatile u32*)reg)
47 #define SW_WRITE_REG(reg, value)   \
48          *((volatile u32*)reg) = (u32)value;\
49          DELAY;\
50          *((volatile u32*)reg) = (u32)value;
51
52 #define SW_READ_REG(reg, value)    \
53          value = (u32)*((volatile u32*)reg);\
54          DELAY;\
55          value = (u32)*((volatile u32*)reg);
56
57 #define INCA_DMA_TX_POLLING_TIME       0x07
58 #define INCA_DMA_RX_POLLING_TIME       0x07
59
60 #define INCA_DMA_TX_HOLD   0x80000000
61 #define INCA_DMA_TX_EOP    0x40000000
62 #define INCA_DMA_TX_SOP    0x20000000
63 #define INCA_DMA_TX_ICPT   0x10000000
64 #define INCA_DMA_TX_IEOP   0x08000000
65
66 #define INCA_DMA_RX_C   0x80000000
67 #define INCA_DMA_RX_SOP 0x40000000
68 #define INCA_DMA_RX_EOP 0x20000000
69
70 /************************ Auto MDIX settings ************************/
71 #define INCA_IP_AUTO_MDIX_LAN_PORTS_DIR      INCA_IP_Ports_P1_DIR
72 #define INCA_IP_AUTO_MDIX_LAN_PORTS_ALTSEL   INCA_IP_Ports_P1_ALTSEL  
73 #define INCA_IP_AUTO_MDIX_LAN_PORTS_OUT      INCA_IP_Ports_P1_OUT
74 #define INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX  16
75
76 #define WAIT_SIGNAL_RETRIES                  100
77 #define WAIT_LINK_RETRIES                    100
78 #define LINK_RETRY_DELAY                     300  /* ms */
79 /********************************************************************/
80
81 typedef struct
82 {
83         union {
84                 struct {
85                         volatile u32 HOLD                :1;
86                         volatile u32 ICpt                :1;
87                         volatile u32 IEop                :1;
88                         volatile u32 offset              :3;
89                         volatile u32 reserved0           :4;
90                         volatile u32 NFB                 :22;
91                 }field;
92
93                 volatile u32 word;
94         }params;
95
96         volatile u32 nextRxDescPtr;
97
98         volatile u32 RxDataPtr;
99
100         union {
101                 struct {
102                         volatile u32 C                   :1;
103                         volatile u32 Sop                 :1;
104                         volatile u32 Eop                 :1;
105                         volatile u32 reserved3           :12;
106                         volatile u32 NBT                 :17;
107                 }field;
108
109                 volatile u32 word;
110         }status;
111
112 } inca_rx_descriptor_t;
113
114
115 typedef struct
116 {
117         union {
118                 struct {
119                         volatile u32 HOLD                :1;
120                         volatile u32 Eop                 :1;
121                         volatile u32 Sop                 :1;
122                         volatile u32 ICpt                :1;
123                         volatile u32 IEop                :1;
124                         volatile u32 reserved0           :5;
125                         volatile u32 NBA                 :22;
126                 }field;
127
128                 volatile u32 word;
129         }params;
130
131         volatile u32 nextTxDescPtr;
132
133         volatile u32 TxDataPtr;
134
135         volatile u32 C                   :1;
136         volatile u32 reserved3           :31;
137
138 } inca_tx_descriptor_t;
139
140
141 static inca_rx_descriptor_t rx_ring[NUM_RX_DESC] __attribute__ ((aligned(16)));
142 static inca_tx_descriptor_t tx_ring[NUM_TX_DESC] __attribute__ ((aligned(16)));
143
144 static int tx_new, rx_new, tx_hold, rx_hold;
145 static int tx_old_hold = -1;
146 static int initialized  = 0;
147
148
149 static int inca_switch_init(struct eth_device *dev, bd_t * bis);
150 static int inca_switch_send(struct eth_device *dev, volatile void *packet,
151                                                   int length);
152 static int inca_switch_recv(struct eth_device *dev);
153 static void inca_switch_halt(struct eth_device *dev);
154 static void inca_init_switch_chip(void);
155 static void inca_dma_init(void);
156 static int inca_amdix(void);
157
158
159 int inca_switch_initialize(bd_t * bis)
160 {
161         struct eth_device *dev;
162
163 #if 0
164         printf("Entered inca_switch_initialize()\n");
165 #endif
166
167         if (!(dev = (struct eth_device *) malloc (sizeof *dev))) {
168                 printf("Failed to allocate memory\n");
169                 return 0;
170         }
171         memset(dev, 0, sizeof(*dev));
172
173         inca_dma_init();
174
175         inca_init_switch_chip();
176         
177         inca_amdix();
178
179         sprintf(dev->name, "INCA-IP Switch");
180         dev->init = inca_switch_init;
181         dev->halt = inca_switch_halt;
182         dev->send = inca_switch_send;
183         dev->recv = inca_switch_recv;
184
185         eth_register(dev);
186
187 #if 0
188         printf("Leaving inca_switch_initialize()\n");
189 #endif
190
191         return 1;
192 }
193
194
195 static int inca_switch_init(struct eth_device *dev, bd_t * bis)
196 {
197         int i;
198         u32 v, regValue;
199         u16 wTmp;
200
201 #if 0
202         printf("Entering inca_switch_init()\n");
203 #endif
204
205         /* Set MAC address.
206          */
207         wTmp = (u16)dev->enetaddr[0];
208         regValue = (wTmp << 8) | dev->enetaddr[1];
209
210         SW_WRITE_REG(INCA_IP_Switch_PMAC_SA1, regValue);
211
212         wTmp = (u16)dev->enetaddr[2];
213         regValue = (wTmp << 8) | dev->enetaddr[3];
214         regValue = regValue << 16;
215         wTmp = (u16)dev->enetaddr[4];
216         regValue |= (wTmp<<8) | dev->enetaddr[5];
217
218         SW_WRITE_REG(INCA_IP_Switch_PMAC_SA2, regValue);
219
220         /* Initialize the descriptor rings.
221          */
222         for (i = 0; i < NUM_RX_DESC; i++)
223         {
224                 inca_rx_descriptor_t * rx_desc = KSEG1ADDR(&rx_ring[i]);
225                 memset(rx_desc, 0, sizeof(rx_ring[i]));
226
227                 /* Set maximum size of receive buffer.
228                  */
229                 rx_desc->params.field.NFB = PKTSIZE_ALIGN;
230
231                 /* Set the offset of the receive buffer. Zero means
232                  * that the offset mechanism is not used.
233                  */
234                 rx_desc->params.field.offset = 0;
235
236                 /* Check if it is the last descriptor.
237                  */
238                 if (i == (NUM_RX_DESC - 1)) {
239                         /* Let the last descriptor point to the first
240                          * one.
241                          */
242                         rx_desc->nextRxDescPtr = KSEG1ADDR((u32)rx_ring);
243                 } else {
244                         /* Set the address of the next descriptor.
245                          */
246                         rx_desc->nextRxDescPtr = (u32)KSEG1ADDR(&rx_ring[i+1]);
247                 }
248
249                 rx_desc->RxDataPtr = (u32)KSEG1ADDR(NetRxPackets[i]);
250         }
251
252 #if 0
253         printf("rx_ring = 0x%08X 0x%08X\n", (u32)rx_ring, (u32)&rx_ring[0]);
254         printf("tx_ring = 0x%08X 0x%08X\n", (u32)tx_ring, (u32)&tx_ring[0]);
255 #endif
256
257         for (i = 0; i < NUM_TX_DESC; i++) {
258                 inca_tx_descriptor_t * tx_desc = KSEG1ADDR(&tx_ring[i]);
259
260                 memset(tx_desc, 0, sizeof(tx_ring[i]));
261
262                 tx_desc->params.word       = 0;
263                 tx_desc->params.field.HOLD = 1;
264                 tx_desc->C                 = 1;
265
266                         /* Check if it is the last descriptor.
267                          */
268                 if (i == (NUM_TX_DESC - 1)) {
269                                 /* Let the last descriptor point to the
270                                  * first one.
271                                  */
272                         tx_desc->nextTxDescPtr = KSEG1ADDR((u32)tx_ring);
273                 } else {
274                                 /* Set the address of the next descriptor.
275                                  */
276                         tx_desc->nextTxDescPtr = (u32)KSEG1ADDR(&tx_ring[i+1]);
277                 }
278         }
279
280         /* Initialize RxDMA.
281          */
282         DMA_READ_REG(INCA_IP_DMA_DMA_RXISR, v);
283 #if 0
284         printf("RX status = 0x%08X\n", v);
285 #endif
286
287         /* Writing to the FRDA of CHANNEL.
288          */
289         DMA_WRITE_REG(INCA_IP_DMA_DMA_RXFRDA0, (u32)rx_ring);
290
291         /* Writing to the COMMAND REG.
292          */
293         DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0,
294                       INCA_IP_DMA_DMA_RXCCR0_INIT);
295
296         /* Initialize TxDMA.
297          */
298         DMA_READ_REG(INCA_IP_DMA_DMA_TXISR, v);
299 #if 0
300         printf("TX status = 0x%08X\n", v);
301 #endif
302
303         /* Writing to the FRDA of CHANNEL.
304          */
305         DMA_WRITE_REG(INCA_IP_DMA_DMA_TXFRDA0, (u32)tx_ring);
306
307         tx_new = rx_new = 0;
308
309         tx_hold = NUM_TX_DESC - 1;
310         rx_hold = NUM_RX_DESC - 1;
311
312 #if 0
313         rx_ring[rx_hold].params.field.HOLD = 1;
314 #endif
315         /* enable spanning tree forwarding, enable the CPU port */
316         /* ST_PT:
317          *      CPS (CPU port status)   0x3 (forwarding)
318          *      LPS (LAN port status)   0x3 (forwarding)
319          *      PPS (PC port status)    0x3 (forwarding)
320          */
321         SW_WRITE_REG(INCA_IP_Switch_ST_PT,0x3f);
322
323 #if 0
324         printf("Leaving inca_switch_init()\n");
325 #endif
326
327         return 0;
328 }
329
330
331 static int inca_switch_send(struct eth_device *dev, volatile void *packet,
332                                                   int length)
333 {
334         int                    i;
335         int                    res         = -1;
336         u32                    command;
337         u32                    regValue;
338         inca_tx_descriptor_t * tx_desc     = KSEG1ADDR(&tx_ring[tx_new]);
339
340 #if 0
341         printf("Entered inca_switch_send()\n");
342 #endif
343
344         if (length <= 0) {
345                 printf ("%s: bad packet size: %d\n", dev->name, length);
346                 goto Done;
347         }
348
349         for(i = 0; tx_desc->C == 0; i++) {
350                 if (i >= TOUT_LOOP) {
351                         printf("%s: tx error buffer not ready\n", dev->name);
352                         goto Done;
353                 }
354         }
355
356         if (tx_old_hold >= 0) {
357                 KSEG1ADDR(&tx_ring[tx_old_hold])->params.field.HOLD = 1;
358         }
359         tx_old_hold = tx_hold;
360
361         tx_desc->params.word =
362                         (INCA_DMA_TX_SOP | INCA_DMA_TX_EOP | INCA_DMA_TX_HOLD);
363
364         tx_desc->C = 0;
365         tx_desc->TxDataPtr = (u32)packet;
366         tx_desc->params.field.NBA = length;
367
368         KSEG1ADDR(&tx_ring[tx_hold])->params.field.HOLD = 0;
369
370         tx_hold = tx_new;
371         tx_new  = (tx_new + 1) % NUM_TX_DESC;
372
373
374         if (! initialized) {
375                 command = INCA_IP_DMA_DMA_TXCCR0_INIT;
376                 initialized = 1;
377         } else {
378                 command = INCA_IP_DMA_DMA_TXCCR0_HR;
379         }
380
381         DMA_READ_REG(INCA_IP_DMA_DMA_TXCCR0, regValue);
382         regValue |= command;
383 #if 0
384         printf("regValue = 0x%x\n", regValue);
385 #endif
386         DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, regValue);
387
388 #if 1
389         for(i = 0; KSEG1ADDR(&tx_ring[tx_hold])->C == 0; i++) {
390                 if (i >= TOUT_LOOP) {
391                         printf("%s: tx buffer not ready\n", dev->name);
392                         goto Done;
393                 }
394         }
395 #endif
396         res = length;
397 Done:
398 #if 0
399         printf("Leaving inca_switch_send()\n");
400 #endif
401         return res;
402 }
403
404
405 static int inca_switch_recv(struct eth_device *dev)
406 {
407         int                    length  = 0;
408         inca_rx_descriptor_t * rx_desc;
409
410 #if 0
411         printf("Entered inca_switch_recv()\n");
412 #endif
413
414         for (;;) {
415                 rx_desc = KSEG1ADDR(&rx_ring[rx_new]);
416
417                 if (rx_desc->status.field.C == 0) {
418                         break;
419                 }
420
421 #if 0
422                 rx_ring[rx_new].params.field.HOLD = 1;
423 #endif
424
425                 if (! rx_desc->status.field.Eop) {
426                         printf("Partly received packet!!!\n");
427                         break;
428                 }
429
430                 length = rx_desc->status.field.NBT;
431                 rx_desc->status.word &=
432                          ~(INCA_DMA_RX_EOP | INCA_DMA_RX_SOP | INCA_DMA_RX_C);
433 #if 0
434 {
435   int i;
436   for (i=0;i<length - 4;i++) {
437     if (i % 16 == 0) printf("\n%04x: ", i);
438     printf("%02X ", NetRxPackets[rx_new][i]);
439   }
440   printf("\n");
441 }
442 #endif
443
444                 if (length) {
445 #if 0
446                         printf("Received %d bytes\n", length);
447 #endif
448                         NetReceive((void*)KSEG1ADDR(NetRxPackets[rx_new]),
449                                     length - 4);
450                 } else {
451 #if 1
452                         printf("Zero length!!!\n");
453 #endif
454                 }
455
456
457                 KSEG1ADDR(&rx_ring[rx_hold])->params.field.HOLD = 0;
458
459                 rx_hold = rx_new;
460
461                 rx_new = (rx_new + 1) % NUM_RX_DESC;
462         }
463
464 #if 0
465         printf("Leaving inca_switch_recv()\n");
466 #endif
467
468         return length;
469 }
470
471
472 static void inca_switch_halt(struct eth_device *dev)
473 {
474 #if 0
475         printf("Entered inca_switch_halt()\n");
476 #endif
477
478 #if 1
479         initialized = 0;
480 #endif
481 #if 1
482         /* Disable forwarding to the CPU port.
483          */
484         SW_WRITE_REG(INCA_IP_Switch_ST_PT,0xf);
485
486         /* Close RxDMA channel.
487          */
488         DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0, INCA_IP_DMA_DMA_RXCCR0_OFF);
489
490         /* Close TxDMA channel.
491          */
492         DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, INCA_IP_DMA_DMA_TXCCR0_OFF);
493
494
495 #endif
496 #if 0
497         printf("Leaving inca_switch_halt()\n");
498 #endif
499 }
500
501
502 static void inca_init_switch_chip(void)
503 {
504         u32 regValue;
505
506         /* To workaround a problem with collision counter
507          * (see Errata sheet).
508          */
509         SW_WRITE_REG(INCA_IP_Switch_PC_TX_CTL, 0x00000001);
510         SW_WRITE_REG(INCA_IP_Switch_LAN_TX_CTL, 0x00000001);
511
512 #if 1
513         /* init MDIO configuration:
514          *      MDS (Poll speed):       0x01 (4ms)
515          *      PHY_LAN_ADDR:           0x06
516          *      PHY_PC_ADDR:            0x05
517          *      UEP (Use External PHY): 0x00 (Internal PHY is used)
518          *      PS (Port Select):       0x00 (PT/UMM for LAN)
519          *      PT (PHY Test):          0x00 (no test mode)
520          *      UMM (Use MDIO Mode):    0x00 (state machine is disabled)
521          */
522         SW_WRITE_REG(INCA_IP_Switch_MDIO_CFG, 0x4c50);
523
524         /* init PHY:
525          *      SL (Auto Neg. Speed for LAN)
526          *      SP (Auto Neg. Speed for PC)
527          *      LL (Link Status for LAN)
528          *      LP (Link Status for PC)
529          *      DL (Duplex Status for LAN)
530          *      DP (Duplex Status for PC)
531          *      PL (Auto Neg. Pause Status for LAN)
532          *      PP (Auto Neg. Pause Status for PC)
533          */
534         SW_WRITE_REG (INCA_IP_Switch_EPHY, 0xff);
535
536         /* MDIO_ACC:
537          *      RA (Request/Ack)  0x01 (Request)
538          *      RW (Read/Write)   0x01 (Write)
539          *      PHY_ADDR          0x05 (PC)
540          *      REG_ADDR          0x00 (PHY_BCR: basic control register)
541          *      PHY_DATA          0x8000
542          *                    Reset                   - software reset
543          *                    LB (loop back)          - normal
544          *                    SS (speed select)       - 10 Mbit/s
545          *                    ANE (auto neg. enable)  - enable
546          *                    PD (power down)         - normal
547          *                    ISO (isolate)           - normal
548          *                    RAN (restart auto neg.) - normal
549          *                    DM (duplex mode)        - half duplex
550          *                    CT (collision test)     - enable
551          */
552         SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, 0xc0a09000);
553
554         /* MDIO_ACC:
555          *      RA (Request/Ack)  0x01 (Request)
556          *      RW (Read/Write)   0x01 (Write)
557          *      PHY_ADDR          0x06 (LAN)
558          *      REG_ADDR          0x00 (PHY_BCR: basic control register)
559          *      PHY_DATA          0x8000
560          *                    Reset                   - software reset
561          *                    LB (loop back)          - normal
562          *                    SS (speed select)       - 10 Mbit/s
563          *                    ANE (auto neg. enable)  - enable
564          *                    PD (power down)         - normal
565          *                    ISO (isolate)           - normal
566          *                    RAN (restart auto neg.) - normal
567          *                    DM (duplex mode)        - half duplex
568          *                    CT (collision test)     - enable
569          */
570         SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, 0xc0c09000);
571
572 #endif
573
574         /* Make sure the CPU port is disabled for now. We
575          * don't want packets to get stacked for us until
576          * we enable DMA and are prepared to receive them.
577          */
578         SW_WRITE_REG(INCA_IP_Switch_ST_PT,0xf);
579
580         SW_READ_REG(INCA_IP_Switch_ARL_CTL, regValue);
581
582         /* CRC GEN is enabled.
583          */
584         regValue |= 0x00000200;
585         SW_WRITE_REG(INCA_IP_Switch_ARL_CTL, regValue);
586
587         /* ADD TAG is disabled.
588          */
589         SW_READ_REG(INCA_IP_Switch_PMAC_HD_CTL, regValue);
590         regValue &= ~0x00000002;
591         SW_WRITE_REG(INCA_IP_Switch_PMAC_HD_CTL, regValue);
592 }
593
594
595 static void inca_dma_init(void)
596 {
597         /* Switch off all DMA channels.
598          */
599         DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0, INCA_IP_DMA_DMA_RXCCR0_OFF);
600         DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR1, INCA_IP_DMA_DMA_RXCCR1_OFF);
601
602         DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, INCA_IP_DMA_DMA_RXCCR0_OFF);
603         DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR1, INCA_IP_DMA_DMA_TXCCR1_OFF);
604         DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR2, INCA_IP_DMA_DMA_TXCCR2_OFF);
605
606         /* Setup TX channel polling time.
607          */
608         DMA_WRITE_REG(INCA_IP_DMA_DMA_TXPOLL, INCA_DMA_TX_POLLING_TIME);
609
610         /* Setup RX channel polling time.
611          */
612         DMA_WRITE_REG(INCA_IP_DMA_DMA_RXPOLL, INCA_DMA_RX_POLLING_TIME);
613
614         /* ERRATA: write reset value into the DMA RX IMR register.
615          */
616         DMA_WRITE_REG(INCA_IP_DMA_DMA_RXIMR, 0xFFFFFFFF);
617
618         /* Just in case: disable all transmit interrupts also.
619          */
620         DMA_WRITE_REG(INCA_IP_DMA_DMA_TXIMR, 0xFFFFFFFF);
621
622         DMA_WRITE_REG(INCA_IP_DMA_DMA_TXISR, 0xFFFFFFFF);
623         DMA_WRITE_REG(INCA_IP_DMA_DMA_RXISR, 0xFFFFFFFF);
624 }
625
626 static int inca_amdix(void)
627 {
628         u32 regValue = 0;
629         int mdi_flag;
630         int retries;
631
632         /* Setup GPIO pins.
633          */
634         *INCA_IP_AUTO_MDIX_LAN_PORTS_DIR    |= (1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX);
635         *INCA_IP_AUTO_MDIX_LAN_PORTS_ALTSEL |= (1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX);
636
637         /* Wait for signal.
638          */
639         retries = WAIT_SIGNAL_RETRIES;
640         while (--retries)
641         {
642                 SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC,
643                                 (0x1 << 31) |   /* RA           */
644                                 (0x0 << 30) |   /* Read         */
645                                 (0x6 << 21) |   /* LAN          */
646                                 (17  << 16));   /* PHY_MCSR     */
647                 do
648                 {
649                         SW_READ_REG(INCA_IP_Switch_MDIO_ACC, regValue);
650                 }
651                 while (regValue & (1 << 31));
652
653                 if (regValue & (1 << 1))
654                 {
655                         /* Signal detected */
656                         break;
657                 }
658         }
659
660         if (!retries)
661                 return -1;
662
663         /* Set MDI mode.
664          */
665         *INCA_IP_AUTO_MDIX_LAN_PORTS_OUT &= ~(1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX);
666         mdi_flag = 1;
667
668         /* Wait for link.
669          */
670         retries = WAIT_LINK_RETRIES;
671         while (--retries)
672         {
673                 udelay(LINK_RETRY_DELAY * 1000);
674                 SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC,
675                                 (0x1 << 31) |   /* RA           */
676                                 (0x0 << 30) |   /* Read         */
677                                 (0x6 << 21) |   /* LAN          */
678                                 (1   << 16));   /* PHY_BSR      */
679                 do
680                 {
681                         SW_READ_REG(INCA_IP_Switch_MDIO_ACC, regValue);
682                 }
683                 while (regValue & (1 << 31));
684
685                 if (regValue & (1 << 2))
686                 {
687                         /* Link is up */
688                         break;
689                 }
690                 else if (mdi_flag)
691                 {
692                         /* Set MDIX mode */
693                         *INCA_IP_AUTO_MDIX_LAN_PORTS_OUT |= (1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX);
694                         mdi_flag = 0;
695                 }
696                 else
697                 {
698                         /* Set MDI mode */
699                         *INCA_IP_AUTO_MDIX_LAN_PORTS_OUT &= ~(1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX);
700                         mdi_flag = 1;
701                 }
702         }
703
704         if (!retries)
705                 return -1;
706
707         return 0;
708 }
709
710 #endif