p2001_eth.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /**************************************************************************
  2. * Etherboot - BOOTP/TFTP Bootstrap Program
  3. * P2001 NIC driver for Etherboot
  4. **************************************************************************/
  5. /*
  6. * Copyright (C) 2005 Tobias Lorenz
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. /* to get some global routines like printf */
  13. #include "etherboot.h"
  14. /* to get the interface to the body of the program */
  15. #include "nic.h"
  16. /* to get the ISA support functions, if this is an ISA NIC */
  17. #include "isa.h"
  18. #include "hardware.h"
  19. #include "mii.h"
  20. #include "timer.h"
  21. /* NIC specific static variables go here */
  22. static unsigned char MAC_HW_ADDR[6]={MAC_HW_ADDR_DRV};
  23. /* DMA descriptors and buffers */
  24. #define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */
  25. #define DMA_BUF_SIZE 2048 /* Buffer size */
  26. static DMA_DSC txd __attribute__ ((__section__(".dma.desc")));
  27. static DMA_DSC rxd[NUM_RX_DESC] __attribute__ ((__section__(".dma.desc")));
  28. static char rxb[NUM_RX_DESC * DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
  29. static char txb[ DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
  30. static unsigned int cur_rx;
  31. /* Device selectors */
  32. static unsigned int cur_channel; // DMA channel : 0..3
  33. static unsigned int cur_phy; // PHY Address : 0..31
  34. static P2001_ETH_regs_ptr EU; // Ethernet Unit : 0x0018_000 with _=0..3
  35. /* mdio handling */
  36. static int p2001_eth_mdio_read (int phy_id, int location);
  37. static void p2001_eth_mdio_write(int phy_id, int location, int val);
  38. /* net_device functions */
  39. static int p2001_eth_poll (struct nic *nic, int retrieve);
  40. static void p2001_eth_transmit (struct nic *nic, const char *d,
  41. unsigned int t, unsigned int s, const char *p);
  42. static void p2001_eth_irq (struct nic *nic, irq_action_t action);
  43. static void p2001_eth_init ();
  44. static void p2001_eth_disable (struct dev *dev);
  45. static int p2001_eth_check_link(unsigned int phy);
  46. static int link;
  47. static void p2001_eth_phyreset ();
  48. static int p2001_eth_probe (struct dev *dev, unsigned short *probe_addrs __unused);
  49. /* Supported MII list */
  50. static struct mii_chip_info {
  51. const char * name;
  52. unsigned int physid; // (MII_PHYSID2 << 16) | MII_PHYSID1
  53. } mii_chip_table[] = {
  54. { "Intel LXT971A", 0x78e20013 },
  55. { "Altima AC104-QF", 0x55410022 },
  56. {NULL,0},
  57. };
  58. /**************************************************************************
  59. * PHY MANAGEMENT UNIT - Read/write
  60. **************************************************************************/
  61. /**
  62. * mdio_read - read MII PHY register
  63. * @dev: the net device to read
  64. * @regadr: the phy register id to read
  65. *
  66. * Read MII registers through MDIO and MDC
  67. * using MDIO management frame structure and protocol(defined by ISO/IEC).
  68. */
  69. static int p2001_eth_mdio_read(int phy_id, int location)
  70. {
  71. int result, boguscnt = 1000;
  72. do {
  73. /* Warten bis Hardware inaktiv (MIU = "0") */
  74. while (P2001_MU->MU_CNTL & 0x8000)
  75. barrier();
  76. /* Schreiben MU_CNTL */
  77. P2001_MU->MU_CNTL = location + (phy_id<<5) + (2<<10);
  78. /* Warten bis Hardware aktiv (MIU = "1") */
  79. while ((P2001_MU->MU_CNTL & 0x8000) == 0)
  80. barrier();
  81. //asm("nop \r\n nop");
  82. /* Warten bis Hardware inaktiv (MIU = "0") */
  83. while (P2001_MU->MU_CNTL & 0x8000)
  84. barrier();
  85. /* Fehler, wenn MDIO Read Error (MRE = "1") */
  86. } while ((P2001_MU->MU_CNTL & 0x4000) && (--boguscnt > 0));
  87. /* Lesen MU_DATA */
  88. result = P2001_MU->MU_DATA;
  89. if (boguscnt == 0)
  90. return 0;
  91. if ((result & 0xffff) == 0xffff)
  92. return 0;
  93. return result & 0xffff;
  94. }
  95. /**
  96. * mdio_write - write MII PHY register
  97. * @dev: the net device to write
  98. * @regadr: the phy register id to write
  99. * @value: the register value to write with
  100. *
  101. * Write MII registers with @value through MDIO and MDC
  102. * using MDIO management frame structure and protocol(defined by ISO/IEC)
  103. */
  104. static void p2001_eth_mdio_write(int phy_id, int location, int val)
  105. {
  106. /* Warten bis Hardware inaktiv (MIU = "0") */
  107. while (P2001_MU->MU_CNTL & 0x8000)
  108. barrier();
  109. /* Schreiben MU_DATA */
  110. P2001_MU->MU_DATA = val;
  111. /* Schreiben MU_CNTL */
  112. P2001_MU->MU_CNTL = location + (phy_id<<5) + (1<<10);
  113. /* Warten bis Hardware aktiv (MIU = "1") */
  114. while ((P2001_MU->MU_CNTL & 0x8000) == 0)
  115. barrier();
  116. //asm("nop \r\n nop");
  117. /* Warten bis Hardware inaktiv (MIU = "0") */
  118. while (P2001_MU->MU_CNTL & 0x8000)
  119. barrier();
  120. }
  121. /**************************************************************************
  122. * POLL - Wait for a frame
  123. **************************************************************************/
  124. /* Function: p2001_eth_poll
  125. *
  126. * Description: checks for a received packet and returns it if found.
  127. *
  128. * Arguments: struct nic *nic: NIC data structure
  129. *
  130. * Returns: 1 if a packet was received.
  131. * 0 if no pacet was received.
  132. *
  133. * Side effects:
  134. * Returns (copies) the packet to the array nic->packet.
  135. * Returns the length of the packet in nic->packetlen.
  136. */
  137. static int p2001_eth_poll(struct nic *nic, int retrieve)
  138. {
  139. /* return true if there's an ethernet packet ready to read */
  140. /* nic->packet should contain data on return */
  141. /* nic->packetlen should contain length of data */
  142. int retstat = 0;
  143. if (rxd[cur_rx].stat & (1<<31)) // OWN
  144. return retstat;
  145. if (!retrieve)
  146. return 1;
  147. nic->packetlen = rxd[cur_rx].cntl & 0xffff;
  148. if (rxd[cur_rx].stat & ((1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22))) {
  149. /* corrupted packet received */
  150. printf("p2001_eth_poll: Corrupted packet received, stat = %X\n",
  151. rxd[cur_rx].stat);
  152. retstat = 0;
  153. } else {
  154. /* give packet to higher routine */
  155. memcpy(nic->packet, (rxb + cur_rx*DMA_BUF_SIZE), nic->packetlen);
  156. retstat = 1;
  157. }
  158. #ifdef DEBUG_NIC
  159. printf("p2001_eth_poll: packet from %! to %! received\n",
  160. (rxb+cur_rx*DMA_BUF_SIZE)+ETH_ALEN,
  161. (rxb+cur_rx*DMA_BUF_SIZE));
  162. #endif
  163. /* disable receiver */
  164. // FIXME: is that ok? it can produce grave errors.
  165. EU->RMAC_DMA_EN = 0; /* clear run bit */
  166. /* return the descriptor and buffer to receive ring */
  167. rxd[cur_rx].stat = (1<<31) | (1<<30) | (1<<29); // DSC0 OWN|START|END
  168. rxd[cur_rx].cntl = (1<<23); // DSC1 RECEIVE
  169. rxd[cur_rx].cntl |= cur_channel << 16; // DSC1 CHANNEL
  170. rxd[cur_rx].cntl |= DMA_BUF_SIZE; // DSC1 LEN
  171. if (++cur_rx == NUM_RX_DESC)
  172. cur_rx = 0;
  173. /* enable receiver */
  174. if (!(EU->RMAC_DMA_EN & 0x01))
  175. EU->RMAC_DMA_EN = 0x01; /* set run bit */
  176. #ifdef DEBUG_NIC
  177. printf("RMAC_MIB0..5: %d:%d:%d:%d:%d:%d\n",
  178. EU->RMAC_MIB0, EU->RMAC_MIB1,
  179. EU->RMAC_MIB2, EU->RMAC_MIB3,
  180. EU->RMAC_MIB4, EU->RMAC_MIB5);
  181. #endif
  182. return retstat; /* initially as this is called to flush the input */
  183. }
  184. /**************************************************************************
  185. * TRANSMIT - Transmit a frame
  186. **************************************************************************/
  187. /* Function: p2001_eth_transmit
  188. *
  189. * Description: transmits a packet and waits for completion or timeout.
  190. *
  191. * Arguments: char d[6]: destination ethernet address.
  192. * unsigned short t: ethernet protocol type.
  193. * unsigned short s: size of the data-part of the packet.
  194. * char *p: the data for the packet.
  195. *
  196. * Returns: void.
  197. */
  198. static void p2001_eth_transmit(
  199. struct nic *nic __unused,
  200. const char *d, /* Destination */
  201. unsigned int t, /* Type */
  202. unsigned int s, /* size */
  203. const char *p) /* Packet */
  204. {
  205. unsigned int nstype;
  206. #ifdef DEBUG_NIC
  207. unsigned int status;
  208. #endif
  209. /* assemble packet */
  210. memcpy(txb, d, ETH_ALEN); // destination
  211. memcpy(txb+ETH_ALEN, nic->node_addr, ETH_ALEN); // source
  212. nstype = htons(t);
  213. memcpy(txb+2*ETH_ALEN, (char*)&nstype, 2); // type
  214. memcpy(txb+ETH_HLEN, p, s); // packet
  215. s += ETH_HLEN;
  216. /* pad to minimum packet size */
  217. // while (s<ETH_ZLEN)
  218. // txb[s++] = '\0';
  219. // TMAC_CNTL.ATP does the same
  220. #ifdef DEBUG_NIC
  221. printf("p2001_eth_transmit: packet from %! to %! sent (size: %d)\n", txb+ETH_ALEN, txb, s);
  222. #endif
  223. /* configure descriptor */
  224. txd.stat = (1<<31) | (1<<30) | (1<<29); // DSC0 OWN|START|END
  225. txd.cntl = cur_channel << 16; // DSC1 CHANNEL
  226. txd.cntl |= s; // DSC1 LEN
  227. /* restart the transmitter */
  228. EU->TMAC_DMA_EN = 0x01; /* set run bit */
  229. while(EU->TMAC_DMA_EN & 0x01); /* wait */
  230. #ifdef DEBUG_NIC
  231. /* check status */
  232. status = EU->TMAC_DMA_STAT;
  233. if (status & ~(0x40)) // not END
  234. printf("p2001_eth_transmit: dma status=0x%hx\n", status);
  235. printf("TMAC_MIB6..7: %d:%d\n", EU->TMAC_MIB6, EU->TMAC_MIB7);
  236. #endif
  237. }
  238. /**************************************************************************
  239. * IRQ - Enable, Disable or Force Interrupts
  240. **************************************************************************/
  241. /* Function: p2001_eth_irq
  242. *
  243. * Description: Enable, Disable, or Force, interrupts
  244. *
  245. * Arguments: struct nic *nic: NIC data structure
  246. * irq_action_t action: Requested action
  247. *
  248. * Returns: void.
  249. */
  250. static void
  251. p2001_eth_irq(struct nic *nic __unused, irq_action_t action __unused)
  252. {
  253. switch ( action ) {
  254. case DISABLE :
  255. break;
  256. case ENABLE :
  257. break;
  258. case FORCE :
  259. break;
  260. }
  261. }
  262. /**************************************************************************
  263. * INIT - Initialize device
  264. **************************************************************************/
  265. /* Function: p2001_init
  266. *
  267. * Description: resets the ethernet controller chip and various
  268. * data structures required for sending and receiving packets.
  269. *
  270. * returns: void.
  271. */
  272. static void p2001_eth_init()
  273. {
  274. static int i;
  275. /* activate MII 3 */
  276. if (cur_channel == 3)
  277. P2001_GPIO->PIN_MUX |= (1<<8); // MII_3_en = 1
  278. #ifdef RMII
  279. /* RMII init sequence */
  280. if (link & LPA_100) {
  281. EU->CONF_RMII = (1<<2) | (1<<1); // softres | 100Mbit
  282. EU->CONF_RMII = (1<<2) | (1<<1) | (1<<0); // softres | 100Mbit | RMII
  283. EU->CONF_RMII = (1<<1) | (1<<0); // 100 Mbit | RMII
  284. } else {
  285. EU->CONF_RMII = (1<<2); // softres
  286. EU->CONF_RMII = (1<<2) | (1<<0); // softres | RMII
  287. EU->CONF_RMII = (1<<0); // RMII
  288. }
  289. #endif
  290. /* disable transceiver */
  291. // EU->TMAC_DMA_EN = 0; /* clear run bit */
  292. // EU->RMAC_DMA_EN = 0; /* clear run bit */
  293. /* set rx filter (physical mac addresses) */
  294. EU->RMAC_PHYU =
  295. (MAC_HW_ADDR[0]<< 8) +
  296. (MAC_HW_ADDR[1]<< 0);
  297. EU->RMAC_PHYL =
  298. (MAC_HW_ADDR[2]<<24) +
  299. (MAC_HW_ADDR[3]<<16) +
  300. (MAC_HW_ADDR[4]<<8 ) +
  301. (MAC_HW_ADDR[5]<<0 );
  302. /* initialize the tx descriptor ring */
  303. // txd.stat = (1<<31) | (1<<30) | (1<<29); // DSC0 OWN|START|END
  304. // txd.cntl = cur_channel << 16; // DSC1 CHANNEL
  305. // txd.cntl |= DMA_BUF_SIZE; // DSC1 LEN
  306. txd.buf = (char *)&txb; // DSC2 BUFFER
  307. txd.next = &txd; // DSC3 NEXTDSC @self
  308. EU->TMAC_DMA_DESC = &txd;
  309. /* initialize the rx descriptor ring */
  310. cur_rx = 0;
  311. for (i = 0; i < NUM_RX_DESC; i++) {
  312. rxd[i].stat = (1<<31) | (1<<30) | (1<<29); // DSC0 OWN|START|END
  313. rxd[i].cntl = (1<<23); // DSC1 RECEIVE
  314. rxd[i].cntl |= cur_channel << 16; // DSC1 CHANNEL
  315. rxd[i].cntl |= DMA_BUF_SIZE; // DSC1 LEN
  316. rxd[i].buf = &rxb[i*DMA_BUF_SIZE]; // DSC2 BUFFER (EU-RX data)
  317. rxd[i].next = &rxd[i+1]; // DSC3 NEXTDSC @next
  318. }
  319. rxd[NUM_RX_DESC-1].next = &rxd[0]; // DSC3 NEXTDSC @first
  320. EU->RMAC_DMA_DESC = &rxd[0];
  321. /* set transmitter mode */
  322. if (link & LPA_DUPLEX)
  323. EU->TMAC_CNTL = (1<<4) | /* COI: Collision ignore */
  324. (1<<3) | /* CSI: Carrier Sense ignore */
  325. (1<<2); /* ATP: Automatic Transmit Padding */
  326. else
  327. EU->TMAC_CNTL = (1<<2); /* ATP: Automatic Transmit Padding */
  328. /* set receive mode */
  329. EU->RMAC_CNTL = (1<<3) | /* BROAD: Broadcast packets */
  330. (1<<1); /* PHY : Packets to out MAC address */
  331. /* enable receiver */
  332. EU->RMAC_DMA_EN = 1; /* set run bit */
  333. }
  334. /**************************************************************************
  335. * DISABLE - Turn off ethernet interface
  336. **************************************************************************/
  337. static void p2001_eth_disable(struct dev *dev __unused)
  338. {
  339. /* put the card in its initial state */
  340. /* This function serves 3 purposes.
  341. * This disables DMA and interrupts so we don't receive
  342. * unexpected packets or interrupts from the card after
  343. * etherboot has finished.
  344. * This frees resources so etherboot may use
  345. * this driver on another interface
  346. * This allows etherboot to reinitialize the interface
  347. * if something is something goes wrong.
  348. */
  349. /* disable transmitter */
  350. EU->TMAC_DMA_EN = 0; /* clear run bit */
  351. /* disable receiver */
  352. EU->RMAC_DMA_EN = 0; /* clear run bit */
  353. }
  354. /**************************************************************************
  355. * LINK - Check for valid link
  356. **************************************************************************/
  357. static int p2001_eth_check_link(unsigned int phy)
  358. {
  359. static int status;
  360. static unsigned int i, physid;
  361. /* print some information about out PHY */
  362. physid = (p2001_eth_mdio_read(phy, MII_PHYSID2) << 16) |
  363. p2001_eth_mdio_read(phy, MII_PHYSID1);
  364. printf("PHY %d, ID 0x%x ", phy, physid);
  365. for (i = 0; mii_chip_table[i].physid; i++)
  366. if (mii_chip_table[i].physid == physid) {
  367. printf("(%s).\n", mii_chip_table[i].name);
  368. break;
  369. }
  370. if (!mii_chip_table[i].physid)
  371. printf("(unknown).\n");
  372. /* Use 0x3300 for restarting NWay */
  373. printf("Starting auto-negotiation... ");
  374. p2001_eth_mdio_write(phy, MII_BMCR, 0x3300);
  375. /* Bit 1.5 is set once the Auto-Negotiation process is completed. */
  376. i = 0;
  377. do {
  378. mdelay(500);
  379. status = p2001_eth_mdio_read(phy, MII_BMSR);
  380. if (!status || (i++ > 6)) // 6*500ms = 3s timeout
  381. goto failed;
  382. } while (!(status & BMSR_ANEGCOMPLETE));
  383. /* Bits 1.2 is set once the link is established. */
  384. if ((status = p2001_eth_mdio_read(phy, MII_BMSR)) & BMSR_LSTATUS) {
  385. link = p2001_eth_mdio_read(phy, MII_ADVERTISE) &
  386. p2001_eth_mdio_read(phy, MII_LPA);
  387. printf(" Valid link, operating at: %sMb-%s\n",
  388. (link & LPA_100) ? "100" : "10",
  389. (link & LPA_DUPLEX) ? "FD" : "HD");
  390. return 1;
  391. }
  392. failed:
  393. if (!status)
  394. printf("Failed\n");
  395. else
  396. printf("No valid link\n");
  397. return 0;
  398. }
  399. /**************************************************************************
  400. * PHYRESET - hardware reset all MII PHYs
  401. **************************************************************************/
  402. /**
  403. * p2001_eth_phyreset - hardware reset all MII PHYs
  404. */
  405. static void p2001_eth_phyreset()
  406. {
  407. /* GPIO24/25: TX_ER2/TX_ER0 */
  408. /* GPIO26/27: PHY_RESET/TX_ER1 */
  409. P2001_GPIO->PIN_MUX |= 0x0018;
  410. // 31-16: 0000 1111 0000 0000
  411. P2001_GPIO->GPIO2_En |= 0x0400;
  412. P2001_GPIO->GPIO2_Out |= 0x04000000;
  413. P2001_GPIO->GPIO2_Out &= ~0x0400;
  414. mdelay(500);
  415. P2001_GPIO->GPIO2_Out |= 0x0400;
  416. #ifdef RMII
  417. /* RMII_clk_sel = 0xxb no RMII (default) */
  418. /* RMII_clk_sel = 100b COL_0 */
  419. /* RMII_clk_sel = 101b COL_1 */
  420. /* RMII_clk_sel = 110b COL_2 */
  421. /* RMII_clk_sel = 111b COL_3 */
  422. P2001_GPIO->PIN_MUX |= (4 << 13);
  423. #endif
  424. }
  425. /**************************************************************************
  426. * PROBE - Look for an adapter, this routine's visible to the outside
  427. **************************************************************************/
  428. static int p2001_eth_probe(struct dev *dev, unsigned short *probe_addrs __unused)
  429. {
  430. struct nic *nic = (struct nic *)dev;
  431. /* if probe_addrs is 0, then routine can use a hardwired default */
  432. /* reset phys and configure mdio clk */
  433. printf("Resetting PHYs...\n");
  434. p2001_eth_phyreset();
  435. /* set management unit clock divisor */
  436. // max. MDIO CLK = 2.048 MHz (EU.doc)
  437. P2001_MU->MU_DIV = (SYSCLK/4096000)-1; // 2.048 MHz
  438. //asm("nop \n nop");
  439. /* find the correct PHY/DMA/MAC combination */
  440. printf("Searching for P2001 NICs...\n");
  441. cur_phy = -1;
  442. for (cur_channel=0; cur_channel<4; cur_channel++) {
  443. EU = P2001_EU(cur_channel);
  444. /* find next phy */
  445. while (++cur_phy < 16) {
  446. //printf("phy detect %d\n", cur_phy);
  447. if (p2001_eth_mdio_read(cur_phy, MII_BMSR) != 0)
  448. break;
  449. }
  450. if (cur_phy == 16) {
  451. printf("no more MII PHYs found\n");
  452. break;
  453. }
  454. /* first a non destructive test for initial value RMAC_TLEN=1518 */
  455. if (EU->RMAC_TLEN == 1518) {
  456. printf("Checking EU%d...\n", cur_channel);
  457. if (p2001_eth_check_link(cur_phy)) {
  458. /* initialize device */
  459. p2001_eth_init(nic);
  460. /* set node address */
  461. printf("Setting MAC address to %!\n", MAC_HW_ADDR);
  462. memcpy(nic->node_addr, MAC_HW_ADDR, 6);
  463. /* point to NIC specific routines */
  464. dev->disable = p2001_eth_disable;
  465. nic->poll = p2001_eth_poll;
  466. nic->transmit = p2001_eth_transmit;
  467. nic->irq = p2001_eth_irq;
  468. /* Report the ISA pnp id of the board */
  469. dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
  470. return 1;
  471. }
  472. }
  473. }
  474. /* else */
  475. return 0;
  476. }
  477. ISA_ROM("p2001_eth", "P2001 Ethernet Driver")
  478. static struct isa_driver p2001_eth_driver __isa_driver = {
  479. .type = NIC_DRIVER,
  480. .name = "P2001 Ethernet Driver",
  481. .probe = p2001_eth_probe,
  482. .ioaddrs = 0,
  483. };