ftmac100.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Faraday FTMAC100 Ethernet
  4. *
  5. * (C) Copyright 2009 Faraday Technology
  6. * Po-Yu Chuang <ratbert@faraday-tech.com>
  7. */
  8. #include <config.h>
  9. #include <common.h>
  10. #include <malloc.h>
  11. #include <net.h>
  12. #include <linux/io.h>
  13. #include "ftmac100.h"
  14. #ifdef CONFIG_DM_ETH
  15. #include <dm.h>
  16. DECLARE_GLOBAL_DATA_PTR;
  17. #endif
  18. #define ETH_ZLEN 60
  19. struct ftmac100_data {
  20. struct ftmac100_txdes txdes[1];
  21. struct ftmac100_rxdes rxdes[PKTBUFSRX];
  22. int rx_index;
  23. const char *name;
  24. phys_addr_t iobase;
  25. };
  26. /*
  27. * Reset MAC
  28. */
  29. static void ftmac100_reset(struct ftmac100_data *priv)
  30. {
  31. struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
  32. debug ("%s()\n", __func__);
  33. writel (FTMAC100_MACCR_SW_RST, &ftmac100->maccr);
  34. while (readl (&ftmac100->maccr) & FTMAC100_MACCR_SW_RST)
  35. mdelay(1);
  36. /*
  37. * When soft reset complete, write mac address immediately maybe fail somehow
  38. * Wait for a while can avoid this problem
  39. */
  40. mdelay(1);
  41. }
  42. /*
  43. * Set MAC address
  44. */
  45. static void ftmac100_set_mac(struct ftmac100_data *priv ,
  46. const unsigned char *mac)
  47. {
  48. struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
  49. unsigned int maddr = mac[0] << 8 | mac[1];
  50. unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
  51. debug ("%s(%x %x)\n", __func__, maddr, laddr);
  52. writel (maddr, &ftmac100->mac_madr);
  53. writel (laddr, &ftmac100->mac_ladr);
  54. }
  55. /*
  56. * Disable MAC
  57. */
  58. static void _ftmac100_halt(struct ftmac100_data *priv)
  59. {
  60. struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
  61. debug ("%s()\n", __func__);
  62. writel (0, &ftmac100->maccr);
  63. }
  64. /*
  65. * Initialize MAC
  66. */
  67. static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6])
  68. {
  69. struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
  70. struct ftmac100_txdes *txdes = priv->txdes;
  71. struct ftmac100_rxdes *rxdes = priv->rxdes;
  72. unsigned int maccr;
  73. int i;
  74. debug ("%s()\n", __func__);
  75. ftmac100_reset(priv);
  76. /* set the ethernet address */
  77. ftmac100_set_mac(priv, enetaddr);
  78. /* disable all interrupts */
  79. writel (0, &ftmac100->imr);
  80. /* initialize descriptors */
  81. priv->rx_index = 0;
  82. txdes[0].txdes1 = FTMAC100_TXDES1_EDOTR;
  83. rxdes[PKTBUFSRX - 1].rxdes1 = FTMAC100_RXDES1_EDORR;
  84. for (i = 0; i < PKTBUFSRX; i++) {
  85. /* RXBUF_BADR */
  86. rxdes[i].rxdes2 = (unsigned int)(unsigned long)net_rx_packets[i];
  87. rxdes[i].rxdes1 |= FTMAC100_RXDES1_RXBUF_SIZE (PKTSIZE_ALIGN);
  88. rxdes[i].rxdes0 = FTMAC100_RXDES0_RXDMA_OWN;
  89. }
  90. /* transmit ring */
  91. writel ((unsigned long)txdes, &ftmac100->txr_badr);
  92. /* receive ring */
  93. writel ((unsigned long)rxdes, &ftmac100->rxr_badr);
  94. /* poll receive descriptor automatically */
  95. writel (FTMAC100_APTC_RXPOLL_CNT (1), &ftmac100->aptc);
  96. /* enable transmitter, receiver */
  97. maccr = FTMAC100_MACCR_XMT_EN |
  98. FTMAC100_MACCR_RCV_EN |
  99. FTMAC100_MACCR_XDMA_EN |
  100. FTMAC100_MACCR_RDMA_EN |
  101. FTMAC100_MACCR_CRC_APD |
  102. FTMAC100_MACCR_ENRX_IN_HALFTX |
  103. FTMAC100_MACCR_RX_RUNT |
  104. FTMAC100_MACCR_RX_BROADPKT;
  105. writel (maccr, &ftmac100->maccr);
  106. return 0;
  107. }
  108. /*
  109. * Free receiving buffer
  110. */
  111. static int _ftmac100_free_pkt(struct ftmac100_data *priv)
  112. {
  113. struct ftmac100_rxdes *curr_des;
  114. curr_des = &priv->rxdes[priv->rx_index];
  115. /* release buffer to DMA */
  116. curr_des->rxdes0 |= FTMAC100_RXDES0_RXDMA_OWN;
  117. priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
  118. return 0;
  119. }
  120. /*
  121. * Receive a data block via Ethernet
  122. */
  123. static int __ftmac100_recv(struct ftmac100_data *priv)
  124. {
  125. struct ftmac100_rxdes *curr_des;
  126. unsigned short rxlen;
  127. curr_des = &priv->rxdes[priv->rx_index];
  128. if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN)
  129. return 0;
  130. if (curr_des->rxdes0 & (FTMAC100_RXDES0_RX_ERR |
  131. FTMAC100_RXDES0_CRC_ERR |
  132. FTMAC100_RXDES0_FTL |
  133. FTMAC100_RXDES0_RUNT |
  134. FTMAC100_RXDES0_RX_ODD_NB)) {
  135. return 0;
  136. }
  137. rxlen = FTMAC100_RXDES0_RFL (curr_des->rxdes0);
  138. invalidate_dcache_range(curr_des->rxdes2,curr_des->rxdes2+rxlen);
  139. debug ("%s(): RX buffer %d, %x received\n",
  140. __func__, priv->rx_index, rxlen);
  141. return rxlen;
  142. }
  143. /*
  144. * Send a data block via Ethernet
  145. */
  146. static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length)
  147. {
  148. struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
  149. struct ftmac100_txdes *curr_des = priv->txdes;
  150. ulong start;
  151. if (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
  152. debug ("%s(): no TX descriptor available\n", __func__);
  153. return -1;
  154. }
  155. debug ("%s(%lx, %x)\n", __func__, (unsigned long)packet, length);
  156. length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
  157. /* initiate a transmit sequence */
  158. flush_dcache_range((unsigned long)packet,(unsigned long)packet+length);
  159. curr_des->txdes2 = (unsigned int)(unsigned long)packet; /* TXBUF_BADR */
  160. curr_des->txdes1 &= FTMAC100_TXDES1_EDOTR;
  161. curr_des->txdes1 |= FTMAC100_TXDES1_FTS |
  162. FTMAC100_TXDES1_LTS |
  163. FTMAC100_TXDES1_TXBUF_SIZE (length);
  164. curr_des->txdes0 = FTMAC100_TXDES0_TXDMA_OWN;
  165. /* start transmit */
  166. writel (1, &ftmac100->txpd);
  167. /* wait for transfer to succeed */
  168. start = get_timer(0);
  169. while (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
  170. if (get_timer(start) >= 5) {
  171. debug ("%s(): timed out\n", __func__);
  172. return -1;
  173. }
  174. }
  175. debug ("%s(): packet sent\n", __func__);
  176. return 0;
  177. }
  178. #ifndef CONFIG_DM_ETH
  179. /*
  180. * disable transmitter, receiver
  181. */
  182. static void ftmac100_halt(struct eth_device *dev)
  183. {
  184. struct ftmac100_data *priv = dev->priv;
  185. return _ftmac100_halt(priv);
  186. }
  187. static int ftmac100_init(struct eth_device *dev, bd_t *bd)
  188. {
  189. struct ftmac100_data *priv = dev->priv;
  190. return _ftmac100_init(priv , dev->enetaddr);
  191. }
  192. static int _ftmac100_recv(struct ftmac100_data *priv)
  193. {
  194. struct ftmac100_rxdes *curr_des;
  195. unsigned short len;
  196. curr_des = &priv->rxdes[priv->rx_index];
  197. len = __ftmac100_recv(priv);
  198. if (len) {
  199. /* pass the packet up to the protocol layers. */
  200. net_process_received_packet((void *)curr_des->rxdes2, len);
  201. _ftmac100_free_pkt(priv);
  202. }
  203. return len ? 1 : 0;
  204. }
  205. /*
  206. * Get a data block via Ethernet
  207. */
  208. static int ftmac100_recv(struct eth_device *dev)
  209. {
  210. struct ftmac100_data *priv = dev->priv;
  211. return _ftmac100_recv(priv);
  212. }
  213. /*
  214. * Send a data block via Ethernet
  215. */
  216. static int ftmac100_send(struct eth_device *dev, void *packet, int length)
  217. {
  218. struct ftmac100_data *priv = dev->priv;
  219. return _ftmac100_send(priv , packet , length);
  220. }
  221. int ftmac100_initialize (bd_t *bd)
  222. {
  223. struct eth_device *dev;
  224. struct ftmac100_data *priv;
  225. dev = malloc (sizeof *dev);
  226. if (!dev) {
  227. printf ("%s(): failed to allocate dev\n", __func__);
  228. goto out;
  229. }
  230. /* Transmit and receive descriptors should align to 16 bytes */
  231. priv = memalign (16, sizeof (struct ftmac100_data));
  232. if (!priv) {
  233. printf ("%s(): failed to allocate priv\n", __func__);
  234. goto free_dev;
  235. }
  236. memset (dev, 0, sizeof (*dev));
  237. memset (priv, 0, sizeof (*priv));
  238. strcpy(dev->name, "FTMAC100");
  239. dev->iobase = CONFIG_FTMAC100_BASE;
  240. dev->init = ftmac100_init;
  241. dev->halt = ftmac100_halt;
  242. dev->send = ftmac100_send;
  243. dev->recv = ftmac100_recv;
  244. dev->priv = priv;
  245. priv->iobase = dev->iobase;
  246. eth_register (dev);
  247. return 1;
  248. free_dev:
  249. free (dev);
  250. out:
  251. return 0;
  252. }
  253. #endif
  254. #ifdef CONFIG_DM_ETH
  255. static int ftmac100_start(struct udevice *dev)
  256. {
  257. struct eth_pdata *plat = dev_get_platdata(dev);
  258. struct ftmac100_data *priv = dev_get_priv(dev);
  259. return _ftmac100_init(priv, plat->enetaddr);
  260. }
  261. static void ftmac100_stop(struct udevice *dev)
  262. {
  263. struct ftmac100_data *priv = dev_get_priv(dev);
  264. _ftmac100_halt(priv);
  265. }
  266. static int ftmac100_send(struct udevice *dev, void *packet, int length)
  267. {
  268. struct ftmac100_data *priv = dev_get_priv(dev);
  269. int ret;
  270. ret = _ftmac100_send(priv , packet , length);
  271. return ret ? 0 : -ETIMEDOUT;
  272. }
  273. static int ftmac100_recv(struct udevice *dev, int flags, uchar **packetp)
  274. {
  275. struct ftmac100_data *priv = dev_get_priv(dev);
  276. struct ftmac100_rxdes *curr_des;
  277. curr_des = &priv->rxdes[priv->rx_index];
  278. int len;
  279. len = __ftmac100_recv(priv);
  280. if (len)
  281. *packetp = (uchar *)(unsigned long)curr_des->rxdes2;
  282. return len ? len : -EAGAIN;
  283. }
  284. static int ftmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
  285. {
  286. struct ftmac100_data *priv = dev_get_priv(dev);
  287. _ftmac100_free_pkt(priv);
  288. return 0;
  289. }
  290. int ftmac100_read_rom_hwaddr(struct udevice *dev)
  291. {
  292. struct eth_pdata *pdata = dev_get_platdata(dev);
  293. eth_env_get_enetaddr("ethaddr", pdata->enetaddr);
  294. return 0;
  295. }
  296. static const char *dtbmacaddr(u32 ifno)
  297. {
  298. int node, len;
  299. char enet[16];
  300. const char *mac;
  301. const char *path;
  302. if (gd->fdt_blob == NULL) {
  303. printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
  304. return NULL;
  305. }
  306. node = fdt_path_offset(gd->fdt_blob, "/aliases");
  307. if (node < 0)
  308. return NULL;
  309. sprintf(enet, "ethernet%d", ifno);
  310. path = fdt_getprop(gd->fdt_blob, node, enet, NULL);
  311. if (!path) {
  312. printf("no alias for %s\n", enet);
  313. return NULL;
  314. }
  315. node = fdt_path_offset(gd->fdt_blob, path);
  316. mac = fdt_getprop(gd->fdt_blob, node, "mac-address", &len);
  317. if (mac && is_valid_ethaddr((u8 *)mac))
  318. return mac;
  319. return NULL;
  320. }
  321. static int ftmac100_ofdata_to_platdata(struct udevice *dev)
  322. {
  323. struct ftmac100_data *priv = dev_get_priv(dev);
  324. struct eth_pdata *pdata = dev_get_platdata(dev);
  325. const char *mac;
  326. pdata->iobase = devfdt_get_addr(dev);
  327. priv->iobase = pdata->iobase;
  328. mac = dtbmacaddr(0);
  329. if (mac)
  330. memcpy(pdata->enetaddr , mac , 6);
  331. return 0;
  332. }
  333. static int ftmac100_probe(struct udevice *dev)
  334. {
  335. struct ftmac100_data *priv = dev_get_priv(dev);
  336. priv->name = dev->name;
  337. return 0;
  338. }
  339. static int ftmac100_bind(struct udevice *dev)
  340. {
  341. return device_set_name(dev, dev->name);
  342. }
  343. static const struct eth_ops ftmac100_ops = {
  344. .start = ftmac100_start,
  345. .send = ftmac100_send,
  346. .recv = ftmac100_recv,
  347. .stop = ftmac100_stop,
  348. .free_pkt = ftmac100_free_pkt,
  349. };
  350. static const struct udevice_id ftmac100_ids[] = {
  351. { .compatible = "andestech,atmac100" },
  352. { }
  353. };
  354. U_BOOT_DRIVER(ftmac100) = {
  355. .name = "nds32_mac",
  356. .id = UCLASS_ETH,
  357. .of_match = ftmac100_ids,
  358. .bind = ftmac100_bind,
  359. .ofdata_to_platdata = ftmac100_ofdata_to_platdata,
  360. .probe = ftmac100_probe,
  361. .ops = &ftmac100_ops,
  362. .priv_auto_alloc_size = sizeof(struct ftmac100_data),
  363. .platdata_auto_alloc_size = sizeof(struct eth_pdata),
  364. .flags = DM_FLAG_ALLOC_PRIV_DMA,
  365. };
  366. #endif