inca-ip_sw.c 16 KB

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