xemacpsif_hw.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * Copyright (C) 2010 - 2019 Xilinx, Inc.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  17. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  19. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  20. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  21. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  24. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  25. * OF SUCH DAMAGE.
  26. *
  27. * This file is part of the lwIP TCP/IP stack.
  28. *
  29. */
  30. #include "netif/xemacpsif.h"
  31. #include "lwipopts.h"
  32. #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
  33. XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
  34. #define PCM_PMA_CORE_PRESENT
  35. #else
  36. #undef PCM_PMA_CORE_PRESENT
  37. #endif
  38. u32_t link_speed = 100;
  39. extern XEmacPs_Config XEmacPs_ConfigTable[];
  40. extern u32_t phymapemac0[32];
  41. extern u32_t phymapemac1[32];
  42. extern u32_t phyaddrforemac;
  43. extern enum ethernet_link_status eth_link_status;
  44. #ifdef OS_IS_FREERTOS
  45. extern long xInsideISR;
  46. #endif
  47. XEmacPs_Config *xemacps_lookup_config(unsigned mac_base)
  48. {
  49. XEmacPs_Config *cfgptr = NULL;
  50. s32_t i;
  51. for (i = 0; i < XPAR_XEMACPS_NUM_INSTANCES; i++) {
  52. if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) {
  53. cfgptr = &XEmacPs_ConfigTable[i];
  54. break;
  55. }
  56. }
  57. return (cfgptr);
  58. }
  59. void init_emacps(xemacpsif_s *xemacps, struct netif *netif)
  60. {
  61. XEmacPs *xemacpsp;
  62. s32_t status = XST_SUCCESS;
  63. u32_t i;
  64. u32_t phyfoundforemac0 = FALSE;
  65. u32_t phyfoundforemac1 = FALSE;
  66. xemacpsp = &xemacps->emacps;
  67. #ifdef ZYNQMP_USE_JUMBO
  68. XEmacPs_SetOptions(xemacpsp, XEMACPS_JUMBO_ENABLE_OPTION);
  69. #endif
  70. #ifdef LWIP_IGMP
  71. XEmacPs_SetOptions(xemacpsp, XEMACPS_MULTICAST_OPTION);
  72. #endif
  73. /* set mac address */
  74. status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
  75. if (status != XST_SUCCESS) {
  76. xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
  77. }
  78. XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224);
  79. /* Please refer to file header comments for the file xemacpsif_physpeed.c
  80. * to know more about the PHY programming sequence.
  81. * For PCS PMA core, phy_setup_emacps is called with the predefined PHY address
  82. * exposed through xaparemeters.h
  83. * For RGMII case, assuming multiple PHYs can be present on the MDIO bus,
  84. * detect_phy is called to get the addresses of the PHY present on
  85. * a particular MDIO bus (emac0 or emac1). This address map is populated
  86. * in phymapemac0 or phymapemac1.
  87. * phy_setup_emacps is then called for each PHY present on the MDIO bus.
  88. */
  89. #ifdef PCM_PMA_CORE_PRESENT
  90. #ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT
  91. link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR);
  92. #elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT
  93. link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_SGMII_PHYADDR);
  94. #endif
  95. #else
  96. detect_phy(xemacpsp);
  97. for (i = 31; i > 0; i--) {
  98. if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
  99. if (phymapemac0[i] == TRUE) {
  100. link_speed = phy_setup_emacps(xemacpsp, i);
  101. phyfoundforemac0 = TRUE;
  102. phyaddrforemac = i;
  103. }
  104. } else {
  105. if (phymapemac1[i] == TRUE) {
  106. link_speed = phy_setup_emacps(xemacpsp, i);
  107. phyfoundforemac1 = TRUE;
  108. phyaddrforemac = i;
  109. }
  110. }
  111. }
  112. /* If no PHY was detected, use broadcast PHY address of 0 */
  113. if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
  114. if (phyfoundforemac0 == FALSE)
  115. link_speed = phy_setup_emacps(xemacpsp, 0);
  116. } else {
  117. if (phyfoundforemac1 == FALSE)
  118. link_speed = phy_setup_emacps(xemacpsp, 0);
  119. }
  120. #endif
  121. if (link_speed == XST_FAILURE) {
  122. eth_link_status = ETH_LINK_DOWN;
  123. xil_printf("Phy setup failure %s \n\r",__func__);
  124. return;
  125. } else {
  126. eth_link_status = ETH_LINK_UP;
  127. }
  128. XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
  129. /* Setting the operating speed of the MAC needs a delay. */
  130. {
  131. volatile s32_t wait;
  132. for (wait=0; wait < 20000; wait++);
  133. }
  134. }
  135. void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif)
  136. {
  137. XEmacPs *xemacpsp;
  138. s32_t status = XST_SUCCESS;
  139. xemacpsp = &xemacps->emacps;
  140. /* set mac address */
  141. status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
  142. if (status != XST_SUCCESS) {
  143. xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
  144. }
  145. XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
  146. /* Setting the operating speed of the MAC needs a delay. */
  147. {
  148. volatile s32_t wait;
  149. for (wait=0; wait < 20000; wait++);
  150. }
  151. }
  152. void setup_isr (struct xemac_s *xemac)
  153. {
  154. xemacpsif_s *xemacpsif;
  155. xemacpsif = (xemacpsif_s *)(xemac->state);
  156. /*
  157. * Setup callbacks
  158. */
  159. XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
  160. (void *) emacps_send_handler,
  161. (void *) xemac);
  162. XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
  163. (void *) emacps_recv_handler,
  164. (void *) xemac);
  165. XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
  166. (void *) emacps_error_handler,
  167. (void *) xemac);
  168. }
  169. void start_emacps (xemacpsif_s *xemacps)
  170. {
  171. /* start the temac */
  172. XEmacPs_Start(&xemacps->emacps);
  173. }
  174. void restart_emacps_transmitter (xemacpsif_s *xemacps) {
  175. u32_t Reg;
  176. Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
  177. XEMACPS_NWCTRL_OFFSET);
  178. Reg = Reg & (~XEMACPS_NWCTRL_TXEN_MASK);
  179. XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
  180. XEMACPS_NWCTRL_OFFSET, Reg);
  181. Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
  182. XEMACPS_NWCTRL_OFFSET);
  183. Reg = Reg | (XEMACPS_NWCTRL_TXEN_MASK);
  184. XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
  185. XEMACPS_NWCTRL_OFFSET, Reg);
  186. }
  187. void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord)
  188. {
  189. struct xemac_s *xemac;
  190. xemacpsif_s *xemacpsif;
  191. XEmacPs_BdRing *rxring;
  192. XEmacPs_BdRing *txring;
  193. #ifdef OS_IS_FREERTOS
  194. xInsideISR++;
  195. #endif
  196. xemac = (struct xemac_s *)(arg);
  197. xemacpsif = (xemacpsif_s *)(xemac->state);
  198. rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
  199. txring = &XEmacPs_GetTxRing(&xemacpsif->emacps);
  200. if (ErrorWord != 0) {
  201. switch (Direction) {
  202. case XEMACPS_RECV:
  203. if (ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK) {
  204. LWIP_DEBUGF(NETIF_DEBUG, ("Receive DMA error\r\n"));
  205. HandleEmacPsError(xemac);
  206. }
  207. if (ErrorWord & XEMACPS_RXSR_RXOVR_MASK) {
  208. LWIP_DEBUGF(NETIF_DEBUG, ("Receive over run\r\n"));
  209. emacps_recv_handler(arg);
  210. setup_rx_bds(xemacpsif, rxring);
  211. }
  212. if (ErrorWord & XEMACPS_RXSR_BUFFNA_MASK) {
  213. LWIP_DEBUGF(NETIF_DEBUG, ("Receive buffer not available\r\n"));
  214. emacps_recv_handler(arg);
  215. setup_rx_bds(xemacpsif, rxring);
  216. }
  217. break;
  218. case XEMACPS_SEND:
  219. if (ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK) {
  220. LWIP_DEBUGF(NETIF_DEBUG, ("Transmit DMA error\r\n"));
  221. HandleEmacPsError(xemac);
  222. }
  223. if (ErrorWord & XEMACPS_TXSR_URUN_MASK) {
  224. LWIP_DEBUGF(NETIF_DEBUG, ("Transmit under run\r\n"));
  225. HandleTxErrors(xemac);
  226. }
  227. if (ErrorWord & XEMACPS_TXSR_BUFEXH_MASK) {
  228. LWIP_DEBUGF(NETIF_DEBUG, ("Transmit buffer exhausted\r\n"));
  229. HandleTxErrors(xemac);
  230. }
  231. if (ErrorWord & XEMACPS_TXSR_RXOVR_MASK) {
  232. LWIP_DEBUGF(NETIF_DEBUG, ("Transmit retry excessed limits\r\n"));
  233. HandleTxErrors(xemac);
  234. }
  235. if (ErrorWord & XEMACPS_TXSR_FRAMERX_MASK) {
  236. LWIP_DEBUGF(NETIF_DEBUG, ("Transmit collision\r\n"));
  237. // process_sent_bds(xemacpsif, txring);
  238. }
  239. break;
  240. }
  241. }
  242. #ifdef OS_IS_FREERTOS
  243. xInsideISR--;
  244. #endif
  245. }