xemacps.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /******************************************************************************
  2. * Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved.
  3. * SPDX-License-Identifier: MIT
  4. ******************************************************************************/
  5. /*****************************************************************************/
  6. /**
  7. *
  8. * @file xemacps.c
  9. * @addtogroup emacps_v3_11
  10. * @{
  11. *
  12. * The XEmacPs driver. Functions in this file are the minimum required functions
  13. * for this driver. See xemacps.h for a detailed description of the driver.
  14. *
  15. * <pre>
  16. * MODIFICATION HISTORY:
  17. *
  18. * Ver Who Date Changes
  19. * ----- ---- -------- -------------------------------------------------------
  20. * 1.00a wsy 01/10/10 First release
  21. * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp GEM specification and
  22. * 64-bit changes.
  23. * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
  24. * 3.0 hk 02/20/15 Added support for jumbo frames. Increase AHB burst.
  25. * Disable extended mode. Perform all 64 bit changes under
  26. * check for arch64.
  27. * 3.1 hk 08/10/15 Update upper 32 bit tx and rx queue ptr registers
  28. * 3.5 hk 08/14/17 Update cache coherency information of the interface in
  29. * its config structure.
  30. * 3.8 hk 09/17/18 Cleanup stale comments.
  31. * 3.8 mus 11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
  32. * 3.10 hk 05/16/19 Clear status registers properly in reset
  33. * 3.11 sd 02/14/20 Add clock support
  34. *
  35. * </pre>
  36. ******************************************************************************/
  37. /***************************** Include Files *********************************/
  38. #include "xemacps.h"
  39. /************************** Constant Definitions *****************************/
  40. /**************************** Type Definitions *******************************/
  41. /***************** Macros (Inline Functions) Definitions *********************/
  42. /************************** Function Prototypes ******************************/
  43. void XEmacPs_StubHandler(void); /* Default handler routine */
  44. /************************** Variable Definitions *****************************/
  45. /*****************************************************************************/
  46. /**
  47. * Initialize a specific XEmacPs instance/driver. The initialization entails:
  48. * - Initialize fields of the XEmacPs instance structure
  49. * - Reset hardware and apply default options
  50. * - Configure the DMA channels
  51. *
  52. * The PHY is setup independently from the device. Use the MII or whatever other
  53. * interface may be present for setup.
  54. *
  55. * @param InstancePtr is a pointer to the instance to be worked on.
  56. * @param CfgPtr is the device configuration structure containing required
  57. * hardware build data.
  58. * @param EffectiveAddress is the base address of the device. If address
  59. * translation is not utilized, this parameter can be passed in using
  60. * CfgPtr->Config.BaseAddress to specify the physical base address.
  61. *
  62. * @return
  63. * - XST_SUCCESS if initialization was successful
  64. *
  65. ******************************************************************************/
  66. LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr,
  67. UINTPTR EffectiveAddress)
  68. {
  69. /* Verify arguments */
  70. Xil_AssertNonvoid(InstancePtr != NULL);
  71. Xil_AssertNonvoid(CfgPtr != NULL);
  72. /* Set device base address and ID */
  73. InstancePtr->Config.DeviceId = CfgPtr->DeviceId;
  74. InstancePtr->Config.BaseAddress = EffectiveAddress;
  75. InstancePtr->Config.IsCacheCoherent = CfgPtr->IsCacheCoherent;
  76. #if defined (XCLOCKING)
  77. InstancePtr->Config.RefClk = CfgPtr->RefClk;
  78. #endif
  79. /* Set callbacks to an initial stub routine */
  80. InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler));
  81. InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler);
  82. InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler);
  83. /* Reset the hardware and set default options */
  84. InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
  85. XEmacPs_Reset(InstancePtr);
  86. return (LONG)(XST_SUCCESS);
  87. }
  88. /*****************************************************************************/
  89. /**
  90. * Start the Ethernet controller as follows:
  91. * - Enable transmitter if XTE_TRANSMIT_ENABLE_OPTION is set
  92. * - Enable receiver if XTE_RECEIVER_ENABLE_OPTION is set
  93. * - Start the SG DMA send and receive channels and enable the device
  94. * interrupt
  95. *
  96. * @param InstancePtr is a pointer to the instance to be worked on.
  97. *
  98. * @return N/A
  99. *
  100. * @note
  101. * Hardware is configured with scatter-gather DMA, the driver expects to start
  102. * the scatter-gather channels and expects that the user has previously set up
  103. * the buffer descriptor lists.
  104. *
  105. * This function makes use of internal resources that are shared between the
  106. * Start, Stop, and Set/ClearOptions functions. So if one task might be setting
  107. * device options while another is trying to start the device, the user is
  108. * required to provide protection of this shared data (typically using a
  109. * semaphore).
  110. *
  111. * This function must not be preempted by an interrupt that may service the
  112. * device.
  113. *
  114. ******************************************************************************/
  115. void XEmacPs_Start(XEmacPs *InstancePtr)
  116. {
  117. u32 Reg;
  118. /* Assert bad arguments and conditions */
  119. Xil_AssertVoid(InstancePtr != NULL);
  120. Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
  121. #if defined (XCLOCKING)
  122. if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) {
  123. Xil_ClockEnable(InstancePtr->Config.RefClk);
  124. }
  125. #endif
  126. /* Start DMA */
  127. /* When starting the DMA channels, both transmit and receive sides
  128. * need an initialized BD list.
  129. */
  130. if (InstancePtr->Version == 2) {
  131. Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0);
  132. Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0);
  133. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  134. XEMACPS_RXQBASE_OFFSET,
  135. InstancePtr->RxBdRing.BaseBdAddr);
  136. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  137. XEMACPS_TXQBASE_OFFSET,
  138. InstancePtr->TxBdRing.BaseBdAddr);
  139. }
  140. /* clear any existed int status */
  141. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
  142. XEMACPS_IXR_ALL_MASK);
  143. /* Enable transmitter if not already enabled */
  144. if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) {
  145. Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
  146. XEMACPS_NWCTRL_OFFSET);
  147. if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) {
  148. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  149. XEMACPS_NWCTRL_OFFSET,
  150. Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK);
  151. }
  152. }
  153. /* Enable receiver if not already enabled */
  154. if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
  155. Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
  156. XEMACPS_NWCTRL_OFFSET);
  157. if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) {
  158. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  159. XEMACPS_NWCTRL_OFFSET,
  160. Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK);
  161. }
  162. }
  163. /* Enable TX and RX interrupts */
  164. XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK |
  165. XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK |
  166. (u32)XEMACPS_IXR_TXCOMPL_MASK));
  167. /* Enable TX Q1 Interrupts */
  168. if (InstancePtr->Version > 2)
  169. XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK);
  170. /* Mark as started */
  171. InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
  172. return;
  173. }
  174. /*****************************************************************************/
  175. /**
  176. * Gracefully stop the Ethernet MAC as follows:
  177. * - Disable all interrupts from this device
  178. * - Stop DMA channels
  179. * - Disable the tansmitter and receiver
  180. *
  181. * Device options currently in effect are not changed.
  182. *
  183. * This function will disable all interrupts. Default interrupts settings that
  184. * had been enabled will be restored when XEmacPs_Start() is called.
  185. *
  186. * @param InstancePtr is a pointer to the instance to be worked on.
  187. *
  188. * @note
  189. * This function makes use of internal resources that are shared between the
  190. * Start, Stop, SetOptions, and ClearOptions functions. So if one task might be
  191. * setting device options while another is trying to start the device, the user
  192. * is required to provide protection of this shared data (typically using a
  193. * semaphore).
  194. *
  195. * Stopping the DMA channels causes this function to block until the DMA
  196. * operation is complete.
  197. *
  198. ******************************************************************************/
  199. void XEmacPs_Stop(XEmacPs *InstancePtr)
  200. {
  201. u32 Reg;
  202. Xil_AssertVoid(InstancePtr != NULL);
  203. Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
  204. /* Disable all interrupts */
  205. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
  206. XEMACPS_IXR_ALL_MASK);
  207. /* Disable the receiver & transmitter */
  208. Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
  209. XEMACPS_NWCTRL_OFFSET);
  210. Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
  211. Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
  212. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  213. XEMACPS_NWCTRL_OFFSET, Reg);
  214. /* Mark as stopped */
  215. InstancePtr->IsStarted = 0U;
  216. #if defined (XCLOCKING)
  217. Xil_ClockDisable(InstancePtr->Config.RefClk);
  218. #endif
  219. }
  220. /*****************************************************************************/
  221. /**
  222. * Perform a graceful reset of the Ethernet MAC. Resets the DMA channels, the
  223. * transmitter, and the receiver.
  224. *
  225. * Steps to reset
  226. * - Stops transmit and receive channels
  227. * - Stops DMA
  228. * - Configure transmit and receive buffer size to default
  229. * - Clear transmit and receive status register and counters
  230. * - Clear all interrupt sources
  231. * - Clear phy (if there is any previously detected) address
  232. * - Clear MAC addresses (1-4) as well as Type IDs and hash value
  233. *
  234. * All options are placed in their default state. Any frames in the
  235. * descriptor lists will remain in the lists. The side effect of doing
  236. * this is that after a reset and following a restart of the device, frames
  237. * were in the list before the reset may be transmitted or received.
  238. *
  239. * The upper layer software is responsible for re-configuring (if necessary)
  240. * and restarting the MAC after the reset. Note also that driver statistics
  241. * are not cleared on reset. It is up to the upper layer software to clear the
  242. * statistics if needed.
  243. *
  244. * When a reset is required, the driver notifies the upper layer software of
  245. * this need through the ErrorHandler callback and specific status codes.
  246. * The upper layer software is responsible for calling this Reset function
  247. * and then re-configuring the device.
  248. *
  249. * @param InstancePtr is a pointer to the instance to be worked on.
  250. *
  251. ******************************************************************************/
  252. void XEmacPs_Reset(XEmacPs *InstancePtr)
  253. {
  254. u32 Reg;
  255. u8 i;
  256. s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
  257. Xil_AssertVoid(InstancePtr != NULL);
  258. Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
  259. /* Stop the device and reset hardware */
  260. XEmacPs_Stop(InstancePtr);
  261. InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS;
  262. InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC);
  263. InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF;
  264. InstancePtr->MaxMtuSize = XEMACPS_MTU;
  265. InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE +
  266. XEMACPS_TRL_SIZE;
  267. InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
  268. XEMACPS_HDR_VLAN_SIZE;
  269. InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
  270. /* Setup hardware with default values */
  271. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  272. XEMACPS_NWCTRL_OFFSET,
  273. (XEMACPS_NWCTRL_STATCLR_MASK |
  274. XEMACPS_NWCTRL_MDEN_MASK) &
  275. (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK));
  276. Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
  277. XEMACPS_NWCFG_OFFSET);
  278. Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK;
  279. Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK |
  280. (u32)XEMACPS_NWCFG_FDEN_MASK |
  281. (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK;
  282. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  283. XEMACPS_NWCFG_OFFSET, Reg);
  284. if (InstancePtr->Version > 2) {
  285. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET,
  286. (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) |
  287. XEMACPS_NWCFG_DWIDTH_64_MASK));
  288. }
  289. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  290. XEMACPS_DMACR_OFFSET,
  291. (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) +
  292. (((((u32)XEMACPS_RX_BUF_SIZE %
  293. (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
  294. (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
  295. (u32)(XEMACPS_DMACR_RXBUF_MASK)) |
  296. (u32)XEMACPS_DMACR_RXSIZE_MASK |
  297. (u32)XEMACPS_DMACR_TXSIZE_MASK);
  298. if (InstancePtr->Version > 2) {
  299. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
  300. (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) |
  301. #if defined(__aarch64__) || defined(__arch64__)
  302. (u32)XEMACPS_DMACR_ADDR_WIDTH_64 |
  303. #endif
  304. (u32)XEMACPS_DMACR_INCR16_AHB_BURST));
  305. }
  306. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  307. XEMACPS_TXSR_OFFSET, XEMACPS_SR_ALL_MASK);
  308. XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND);
  309. if (InstancePtr->Version > 2)
  310. XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND);
  311. XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV);
  312. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  313. XEMACPS_RXSR_OFFSET, XEMACPS_SR_ALL_MASK);
  314. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
  315. XEMACPS_IXR_ALL_MASK);
  316. Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
  317. XEMACPS_ISR_OFFSET);
  318. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
  319. Reg);
  320. XEmacPs_ClearHash(InstancePtr);
  321. for (i = 1U; i < 5U; i++) {
  322. (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i);
  323. (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i);
  324. }
  325. /* clear all counters */
  326. for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U);
  327. i++) {
  328. (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
  329. XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4)));
  330. }
  331. /* Disable the receiver */
  332. Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
  333. XEMACPS_NWCTRL_OFFSET);
  334. Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
  335. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  336. XEMACPS_NWCTRL_OFFSET, Reg);
  337. /* Sync default options with hardware but leave receiver and
  338. * transmitter disabled. They get enabled with XEmacPs_Start() if
  339. * XEMACPS_TRANSMITTER_ENABLE_OPTION and
  340. * XEMACPS_RECEIVER_ENABLE_OPTION are set.
  341. */
  342. (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options &
  343. ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION |
  344. (u32)XEMACPS_RECEIVER_ENABLE_OPTION));
  345. (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options);
  346. }
  347. /******************************************************************************/
  348. /**
  349. * This is a stub for the asynchronous callbacks. The stub is here in case the
  350. * upper layer forgot to set the handler(s). On initialization, all handlers are
  351. * set to this callback. It is considered an error for this handler to be
  352. * invoked.
  353. *
  354. ******************************************************************************/
  355. void XEmacPs_StubHandler(void)
  356. {
  357. Xil_AssertVoidAlways();
  358. }
  359. /*****************************************************************************/
  360. /**
  361. * This function sets the start address of the transmit/receive buffer queue.
  362. *
  363. * @param InstancePtr is a pointer to the instance to be worked on.
  364. * @param QPtr is the address of the Queue to be written
  365. * @param QueueNum is the Buffer Queue Index
  366. * @param Direction indicates Transmit/Receive
  367. *
  368. * @note
  369. * The buffer queue addresses has to be set before starting the transfer, so
  370. * this function has to be called in prior to XEmacPs_Start()
  371. *
  372. ******************************************************************************/
  373. void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum,
  374. u16 Direction)
  375. {
  376. /* Assert bad arguments and conditions */
  377. Xil_AssertVoid(InstancePtr != NULL);
  378. Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
  379. /* If already started, then there is nothing to do */
  380. if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
  381. return;
  382. }
  383. if (QueueNum == 0x00U) {
  384. if (Direction == XEMACPS_SEND) {
  385. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  386. XEMACPS_TXQBASE_OFFSET,
  387. (QPtr & ULONG64_LO_MASK));
  388. } else {
  389. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  390. XEMACPS_RXQBASE_OFFSET,
  391. (QPtr & ULONG64_LO_MASK));
  392. }
  393. }
  394. else {
  395. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  396. XEMACPS_TXQ1BASE_OFFSET,
  397. (QPtr & ULONG64_LO_MASK));
  398. }
  399. #ifdef __aarch64__
  400. if (Direction == XEMACPS_SEND) {
  401. /* Set the MSB of TX Queue start address */
  402. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  403. XEMACPS_MSBBUF_TXQBASE_OFFSET,
  404. (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
  405. } else {
  406. /* Set the MSB of RX Queue start address */
  407. XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
  408. XEMACPS_MSBBUF_RXQBASE_OFFSET,
  409. (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
  410. }
  411. #endif
  412. }
  413. /** @} */