ftmac100.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Faraday FTMAC100 Ethernet
  3. *
  4. * (C) Copyright 2009 Faraday Technology
  5. * Po-Yu Chuang <ratbert@faraday-tech.com>
  6. *
  7. * SPDX-License-Identifier: GPL-2.0+
  8. */
  9. #include <config.h>
  10. #include <common.h>
  11. #include <malloc.h>
  12. #include <net.h>
  13. #include <asm/io.h>
  14. #include "ftmac100.h"
  15. #define ETH_ZLEN 60
  16. struct ftmac100_data {
  17. struct ftmac100_txdes txdes[1];
  18. struct ftmac100_rxdes rxdes[PKTBUFSRX];
  19. int rx_index;
  20. };
  21. /*
  22. * Reset MAC
  23. */
  24. static void ftmac100_reset (struct eth_device *dev)
  25. {
  26. struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
  27. debug ("%s()\n", __func__);
  28. writel (FTMAC100_MACCR_SW_RST, &ftmac100->maccr);
  29. while (readl (&ftmac100->maccr) & FTMAC100_MACCR_SW_RST)
  30. ;
  31. }
  32. /*
  33. * Set MAC address
  34. */
  35. static void ftmac100_set_mac (struct eth_device *dev, const unsigned char *mac)
  36. {
  37. struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
  38. unsigned int maddr = mac[0] << 8 | mac[1];
  39. unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
  40. debug ("%s(%x %x)\n", __func__, maddr, laddr);
  41. writel (maddr, &ftmac100->mac_madr);
  42. writel (laddr, &ftmac100->mac_ladr);
  43. }
  44. static void ftmac100_set_mac_from_env (struct eth_device *dev)
  45. {
  46. eth_getenv_enetaddr ("ethaddr", dev->enetaddr);
  47. ftmac100_set_mac (dev, dev->enetaddr);
  48. }
  49. /*
  50. * disable transmitter, receiver
  51. */
  52. static void ftmac100_halt (struct eth_device *dev)
  53. {
  54. struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
  55. debug ("%s()\n", __func__);
  56. writel (0, &ftmac100->maccr);
  57. }
  58. static int ftmac100_init (struct eth_device *dev, bd_t *bd)
  59. {
  60. struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
  61. struct ftmac100_data *priv = dev->priv;
  62. struct ftmac100_txdes *txdes = priv->txdes;
  63. struct ftmac100_rxdes *rxdes = priv->rxdes;
  64. unsigned int maccr;
  65. int i;
  66. debug ("%s()\n", __func__);
  67. ftmac100_reset (dev);
  68. /* set the ethernet address */
  69. ftmac100_set_mac_from_env (dev);
  70. /* disable all interrupts */
  71. writel (0, &ftmac100->imr);
  72. /* initialize descriptors */
  73. priv->rx_index = 0;
  74. txdes[0].txdes1 = FTMAC100_TXDES1_EDOTR;
  75. rxdes[PKTBUFSRX - 1].rxdes1 = FTMAC100_RXDES1_EDORR;
  76. for (i = 0; i < PKTBUFSRX; i++) {
  77. /* RXBUF_BADR */
  78. rxdes[i].rxdes2 = (unsigned int)net_rx_packets[i];
  79. rxdes[i].rxdes1 |= FTMAC100_RXDES1_RXBUF_SIZE (PKTSIZE_ALIGN);
  80. rxdes[i].rxdes0 = FTMAC100_RXDES0_RXDMA_OWN;
  81. }
  82. /* transmit ring */
  83. writel ((unsigned int)txdes, &ftmac100->txr_badr);
  84. /* receive ring */
  85. writel ((unsigned int)rxdes, &ftmac100->rxr_badr);
  86. /* poll receive descriptor automatically */
  87. writel (FTMAC100_APTC_RXPOLL_CNT (1), &ftmac100->aptc);
  88. /* enable transmitter, receiver */
  89. maccr = FTMAC100_MACCR_XMT_EN |
  90. FTMAC100_MACCR_RCV_EN |
  91. FTMAC100_MACCR_XDMA_EN |
  92. FTMAC100_MACCR_RDMA_EN |
  93. FTMAC100_MACCR_CRC_APD |
  94. FTMAC100_MACCR_ENRX_IN_HALFTX |
  95. FTMAC100_MACCR_RX_RUNT |
  96. FTMAC100_MACCR_RX_BROADPKT;
  97. writel (maccr, &ftmac100->maccr);
  98. return 0;
  99. }
  100. /*
  101. * Get a data block via Ethernet
  102. */
  103. static int ftmac100_recv (struct eth_device *dev)
  104. {
  105. struct ftmac100_data *priv = dev->priv;
  106. struct ftmac100_rxdes *curr_des;
  107. unsigned short rxlen;
  108. curr_des = &priv->rxdes[priv->rx_index];
  109. if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN)
  110. return -1;
  111. if (curr_des->rxdes0 & (FTMAC100_RXDES0_RX_ERR |
  112. FTMAC100_RXDES0_CRC_ERR |
  113. FTMAC100_RXDES0_FTL |
  114. FTMAC100_RXDES0_RUNT |
  115. FTMAC100_RXDES0_RX_ODD_NB)) {
  116. return -1;
  117. }
  118. rxlen = FTMAC100_RXDES0_RFL (curr_des->rxdes0);
  119. debug ("%s(): RX buffer %d, %x received\n",
  120. __func__, priv->rx_index, rxlen);
  121. /* pass the packet up to the protocol layers. */
  122. net_process_received_packet((void *)curr_des->rxdes2, rxlen);
  123. /* release buffer to DMA */
  124. curr_des->rxdes0 |= FTMAC100_RXDES0_RXDMA_OWN;
  125. priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
  126. return 0;
  127. }
  128. /*
  129. * Send a data block via Ethernet
  130. */
  131. static int ftmac100_send(struct eth_device *dev, void *packet, int length)
  132. {
  133. struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
  134. struct ftmac100_data *priv = dev->priv;
  135. struct ftmac100_txdes *curr_des = priv->txdes;
  136. ulong start;
  137. if (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
  138. debug ("%s(): no TX descriptor available\n", __func__);
  139. return -1;
  140. }
  141. debug ("%s(%x, %x)\n", __func__, (int)packet, length);
  142. length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
  143. /* initiate a transmit sequence */
  144. curr_des->txdes2 = (unsigned int)packet; /* TXBUF_BADR */
  145. curr_des->txdes1 &= FTMAC100_TXDES1_EDOTR;
  146. curr_des->txdes1 |= FTMAC100_TXDES1_FTS |
  147. FTMAC100_TXDES1_LTS |
  148. FTMAC100_TXDES1_TXBUF_SIZE (length);
  149. curr_des->txdes0 = FTMAC100_TXDES0_TXDMA_OWN;
  150. /* start transmit */
  151. writel (1, &ftmac100->txpd);
  152. /* wait for transfer to succeed */
  153. start = get_timer(0);
  154. while (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
  155. if (get_timer(start) >= 5) {
  156. debug ("%s(): timed out\n", __func__);
  157. return -1;
  158. }
  159. }
  160. debug ("%s(): packet sent\n", __func__);
  161. return 0;
  162. }
  163. int ftmac100_initialize (bd_t *bd)
  164. {
  165. struct eth_device *dev;
  166. struct ftmac100_data *priv;
  167. dev = malloc (sizeof *dev);
  168. if (!dev) {
  169. printf ("%s(): failed to allocate dev\n", __func__);
  170. goto out;
  171. }
  172. /* Transmit and receive descriptors should align to 16 bytes */
  173. priv = memalign (16, sizeof (struct ftmac100_data));
  174. if (!priv) {
  175. printf ("%s(): failed to allocate priv\n", __func__);
  176. goto free_dev;
  177. }
  178. memset (dev, 0, sizeof (*dev));
  179. memset (priv, 0, sizeof (*priv));
  180. strcpy(dev->name, "FTMAC100");
  181. dev->iobase = CONFIG_FTMAC100_BASE;
  182. dev->init = ftmac100_init;
  183. dev->halt = ftmac100_halt;
  184. dev->send = ftmac100_send;
  185. dev->recv = ftmac100_recv;
  186. dev->priv = priv;
  187. eth_register (dev);
  188. return 1;
  189. free_dev:
  190. free (dev);
  191. out:
  192. return 0;
  193. }