bcm-sf2-eth.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright 2014 Broadcom Corporation.
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <malloc.h>
  8. #include <net.h>
  9. #include <config.h>
  10. #include <phy.h>
  11. #include <miiphy.h>
  12. #include <asm/io.h>
  13. #include <netdev.h>
  14. #include "bcm-sf2-eth.h"
  15. #if defined(CONFIG_BCM_SF2_ETH_GMAC)
  16. #include "bcm-sf2-eth-gmac.h"
  17. #else
  18. #error "bcm_sf2_eth: NEED to define a MAC!"
  19. #endif
  20. #define BCM_NET_MODULE_DESCRIPTION "Broadcom Starfighter2 Ethernet driver"
  21. #define BCM_NET_MODULE_VERSION "0.1"
  22. #define BCM_SF2_ETH_DEV_NAME "bcm_sf2"
  23. static const char banner[] =
  24. BCM_NET_MODULE_DESCRIPTION " " BCM_NET_MODULE_VERSION "\n";
  25. static int bcm_sf2_eth_init(struct eth_device *dev)
  26. {
  27. struct eth_info *eth = (struct eth_info *)(dev->priv);
  28. struct eth_dma *dma = &(eth->dma);
  29. struct phy_device *phydev;
  30. int rc = 0;
  31. int i;
  32. rc = eth->mac_init(dev);
  33. if (rc) {
  34. error("%s: Couldn't cofigure MAC!\n", __func__);
  35. return rc;
  36. }
  37. /* disable DMA */
  38. dma->disable_dma(dma, MAC_DMA_RX);
  39. dma->disable_dma(dma, MAC_DMA_TX);
  40. eth->port_num = 0;
  41. debug("Connecting PHY 0...\n");
  42. phydev = phy_connect(miiphy_get_dev_by_name(dev->name),
  43. 0, dev, eth->phy_interface);
  44. if (phydev != NULL) {
  45. eth->port[0] = phydev;
  46. eth->port_num += 1;
  47. } else {
  48. debug("No PHY found for port 0\n");
  49. }
  50. for (i = 0; i < eth->port_num; i++)
  51. phy_config(eth->port[i]);
  52. return rc;
  53. }
  54. /*
  55. * u-boot net functions
  56. */
  57. static int bcm_sf2_eth_send(struct eth_device *dev, void *packet, int length)
  58. {
  59. struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma);
  60. uint8_t *buf = (uint8_t *)packet;
  61. int rc = 0;
  62. int i = 0;
  63. debug("%s enter\n", __func__);
  64. /* load buf and start transmit */
  65. rc = dma->tx_packet(dma, buf, length);
  66. if (rc) {
  67. debug("ERROR - Tx failed\n");
  68. return rc;
  69. }
  70. while (!(dma->check_tx_done(dma))) {
  71. udelay(100);
  72. debug(".");
  73. i++;
  74. if (i > 20) {
  75. error("%s: Tx timeout: retried 20 times\n", __func__);
  76. rc = -1;
  77. break;
  78. }
  79. }
  80. debug("%s exit rc(0x%x)\n", __func__, rc);
  81. return rc;
  82. }
  83. static int bcm_sf2_eth_receive(struct eth_device *dev)
  84. {
  85. struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma);
  86. uint8_t *buf = (uint8_t *)net_rx_packets[0];
  87. int rcvlen;
  88. int rc = 0;
  89. int i = 0;
  90. while (1) {
  91. /* Poll Rx queue to get a packet */
  92. rcvlen = dma->check_rx_done(dma, buf);
  93. if (rcvlen < 0) {
  94. /* No packet received */
  95. rc = -1;
  96. debug("\nNO More Rx\n");
  97. break;
  98. } else if ((rcvlen == 0) || (rcvlen > RX_BUF_SIZE)) {
  99. error("%s: Wrong Ethernet packet size (%d B), skip!\n",
  100. __func__, rcvlen);
  101. break;
  102. } else {
  103. debug("recieved\n");
  104. /* Forward received packet to uboot network handler */
  105. net_process_received_packet(buf, rcvlen);
  106. if (++i >= PKTBUFSRX)
  107. i = 0;
  108. buf = net_rx_packets[i];
  109. }
  110. }
  111. return rc;
  112. }
  113. static int bcm_sf2_eth_write_hwaddr(struct eth_device *dev)
  114. {
  115. struct eth_info *eth = (struct eth_info *)(dev->priv);
  116. printf(" ETH MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
  117. dev->enetaddr[0], dev->enetaddr[1], dev->enetaddr[2],
  118. dev->enetaddr[3], dev->enetaddr[4], dev->enetaddr[5]);
  119. return eth->set_mac_addr(dev->enetaddr);
  120. }
  121. static int bcm_sf2_eth_open(struct eth_device *dev, bd_t *bt)
  122. {
  123. struct eth_info *eth = (struct eth_info *)(dev->priv);
  124. struct eth_dma *dma = &(eth->dma);
  125. int i;
  126. debug("Enabling BCM SF2 Ethernet.\n");
  127. eth->enable_mac();
  128. /* enable tx and rx DMA */
  129. dma->enable_dma(dma, MAC_DMA_RX);
  130. dma->enable_dma(dma, MAC_DMA_TX);
  131. /*
  132. * Need to start PHY here because link speed can change
  133. * before each ethernet operation
  134. */
  135. for (i = 0; i < eth->port_num; i++) {
  136. if (phy_startup(eth->port[i])) {
  137. error("%s: PHY %d startup failed!\n", __func__, i);
  138. if (i == CONFIG_BCM_SF2_ETH_DEFAULT_PORT) {
  139. error("%s: No default port %d!\n", __func__, i);
  140. return -1;
  141. }
  142. }
  143. }
  144. /* Set MAC speed using default port */
  145. i = CONFIG_BCM_SF2_ETH_DEFAULT_PORT;
  146. debug("PHY %d: speed:%d, duplex:%d, link:%d\n", i,
  147. eth->port[i]->speed, eth->port[i]->duplex, eth->port[i]->link);
  148. eth->set_mac_speed(eth->port[i]->speed, eth->port[i]->duplex);
  149. debug("Enable Ethernet Done.\n");
  150. return 0;
  151. }
  152. static void bcm_sf2_eth_close(struct eth_device *dev)
  153. {
  154. struct eth_info *eth = (struct eth_info *)(dev->priv);
  155. struct eth_dma *dma = &(eth->dma);
  156. /* disable DMA */
  157. dma->disable_dma(dma, MAC_DMA_RX);
  158. dma->disable_dma(dma, MAC_DMA_TX);
  159. eth->disable_mac();
  160. }
  161. int bcm_sf2_eth_register(bd_t *bis, u8 dev_num)
  162. {
  163. struct eth_device *dev;
  164. struct eth_info *eth;
  165. int rc;
  166. dev = (struct eth_device *)malloc(sizeof(struct eth_device));
  167. if (dev == NULL) {
  168. error("%s: Not enough memory!\n", __func__);
  169. return -1;
  170. }
  171. eth = (struct eth_info *)malloc(sizeof(struct eth_info));
  172. if (eth == NULL) {
  173. error("%s: Not enough memory!\n", __func__);
  174. return -1;
  175. }
  176. printf(banner);
  177. memset(dev, 0, sizeof(*dev));
  178. sprintf(dev->name, "%s_%s-%hu", BCM_SF2_ETH_DEV_NAME,
  179. BCM_SF2_ETH_MAC_NAME, dev_num);
  180. dev->priv = (void *)eth;
  181. dev->iobase = 0;
  182. dev->init = bcm_sf2_eth_open;
  183. dev->halt = bcm_sf2_eth_close;
  184. dev->send = bcm_sf2_eth_send;
  185. dev->recv = bcm_sf2_eth_receive;
  186. dev->write_hwaddr = bcm_sf2_eth_write_hwaddr;
  187. #ifdef CONFIG_BCM_SF2_ETH_GMAC
  188. if (gmac_add(dev)) {
  189. free(eth);
  190. free(dev);
  191. error("%s: Adding GMAC failed!\n", __func__);
  192. return -1;
  193. }
  194. #else
  195. #error "bcm_sf2_eth: NEED to register a MAC!"
  196. #endif
  197. eth_register(dev);
  198. #ifdef CONFIG_CMD_MII
  199. int retval;
  200. struct mii_dev *mdiodev = mdio_alloc();
  201. if (!mdiodev)
  202. return -ENOMEM;
  203. strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
  204. mdiodev->read = eth->miiphy_read;
  205. mdiodev->write = eth->miiphy_write;
  206. retval = mdio_register(mdiodev);
  207. if (retval < 0)
  208. return retval;
  209. #endif
  210. /* Initialization */
  211. debug("Ethernet initialization ...");
  212. rc = bcm_sf2_eth_init(dev);
  213. if (rc != 0) {
  214. error("%s: configuration failed!\n", __func__);
  215. return -1;
  216. }
  217. printf("Basic ethernet functionality initialized\n");
  218. return 0;
  219. }