2 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * o Redistributions of source code must retain the above copyright notice, this list
9 * of conditions and the following disclaimer.
11 * o Redistributions in binary form must reproduce the above copyright notice, this
12 * list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
15 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 /* Modified by mbed for the lwIP port */
33 #include "fsl_enet_driver.h"
34 #include "fsl_enet_hal.h"
35 #include "fsl_clock_manager.h"
36 #include "fsl_interrupt_manager.h"
41 /*******************************************************************************
43 ******************************************************************************/
44 /*! @brief Define ENET's IRQ list */
48 /*! @brief Define MAC driver API structure and for application of stack adaptor layer*/
49 const enet_mac_api_t g_enetMacApi
=
52 NULL
, // enet_mac_deinit,
53 NULL
, // enet_mac_send,
54 #if !ENET_RECEIVE_ALL_INTERRUPT
55 NULL
, // enet_mac_receive,
59 NULL
, // enet_mac_add_multicast_group,
60 NULL
, //enet_mac_leave_multicast_group,
62 /*******************************************************************************
64 ******************************************************************************/
66 // NOTE: we need these functions to be non-blocking fpr the PHY task, hence the
69 /*FUNCTION****************************************************************
71 * Function Name: enet_mii_read
72 * Return Value: The execution status.
73 * Description: Read function.
74 * This interface read data over the (R)MII bus from the specified PHY register,
75 * This function is called by all PHY interfaces.
76 *END*********************************************************************/
77 uint32_t enet_mii_read(uint32_t instance
, uint32_t phyAddr
, uint32_t phyReg
, uint32_t *dataPtr
)
81 /* Check the input parameters*/
84 return kStatus_ENET_InvalidInput
;
87 /* Check if the mii is enabled*/
88 if (!enet_hal_is_mii_enabled(instance
))
90 return kStatus_ENET_Miiuninitialized
;
93 /* Clear the MII interrupt event*/
94 enet_hal_clear_interrupt(instance
, kEnetMiiInterrupt
);
96 /* Read command operation*/
97 enet_hal_set_mii_command(instance
, phyAddr
, phyReg
, kEnetReadValidFrame
, 0);
99 /* Poll for MII complete*/
100 for (counter
= 0; counter
< kEnetMaxTimeout
; counter
++)
102 if (enet_hal_get_interrupt_status(instance
, kEnetMiiInterrupt
))
109 /* Check for timeout*/
110 if (counter
== kEnetMaxTimeout
)
112 return kStatus_ENET_TimeOut
;
115 /* Get data from mii register*/
116 *dataPtr
= enet_hal_get_mii_data(instance
);
118 /* Clear MII interrupt event*/
119 enet_hal_clear_interrupt(instance
, kEnetMiiInterrupt
);
121 return kStatus_ENET_Success
;
124 /*FUNCTION****************************************************************
126 * Function Name: enet_mii_write
127 * Return Value: The execution status.
128 * Description: Write function.
129 * This interface write data over the (R)MII bus to the specified PHY register.
130 * This function is called by all PHY interfaces.
131 *END*********************************************************************/
132 uint32_t enet_mii_write(uint32_t instance
, uint32_t phyAddr
, uint32_t phyReg
, uint32_t data
)
136 /* Check if the mii is enabled*/
137 if (!enet_hal_is_mii_enabled(instance
))
139 return kStatus_ENET_Miiuninitialized
;
142 /* Clear the MII interrupt event*/
143 enet_hal_clear_interrupt(instance
, kEnetMiiInterrupt
);
145 /* Read command operation*/
146 enet_hal_set_mii_command(instance
, phyAddr
, phyReg
, kEnetWriteValidFrame
, data
);
148 /* Poll for MII complete*/
149 for (counter
= 0; counter
< kEnetMaxTimeout
; counter
++)
151 if (enet_hal_get_interrupt_status(instance
, kEnetMiiInterrupt
))
158 /* Check for timeout*/
159 if (counter
== kEnetMaxTimeout
)
161 return kStatus_ENET_TimeOut
;
164 /* Clear MII intrrupt event*/
165 enet_hal_clear_interrupt(instance
, kEnetMiiInterrupt
);
167 return kStatus_ENET_Success
;
169 /*FUNCTION****************************************************************
171 * Function Name: enet_mac_mii_init
172 * Return Value: The execution status.
173 * Description:Initialize the ENET Mac mii(mdc/mdio)interface.
174 *END*********************************************************************/
175 uint32_t enet_mac_mii_init(enet_dev_if_t
* enetIfPtr
)
179 /* Check the input parameters*/
180 if (enetIfPtr
== NULL
)
182 return kStatus_ENET_InvalidInput
;
185 /* Configure mii speed*/
186 CLOCK_SYS_GetFreq(kSystemClock
, &frequency
);
187 enet_hal_config_mii(enetIfPtr
->deviceNumber
, (frequency
/(2 * enetIfPtr
->macCfgPtr
->miiClock
) + 1),
188 kEnetMdioHoldOneClkCycle
, false);
190 return kStatus_ENET_Success
;
193 /*FUNCTION****************************************************************
195 * Function Name: enet_mac_rxbd_init
196 * Return Value: The execution status.
197 * Description:Initialize the ENET receive buffer descriptors.
198 * Note: If you do receive on receive interrupt handler the receive
199 * data buffer number can be the same as the receive descriptor numbers.
200 * But if you are polling receive frames please make sure the receive data
201 * buffers are more than buffer descriptors to guarantee a good performance.
202 *END*********************************************************************/
203 uint32_t enet_mac_rxbd_init(enet_dev_if_t
* enetIfPtr
, enet_rxbd_config_t
*rxbdCfg
)
205 /* Check the input parameters*/
206 if ((!enetIfPtr
) || (!rxbdCfg
))
208 return kStatus_ENET_InvalidInput
;
211 enetIfPtr
->macContextPtr
->bufferdescSize
= enet_hal_get_bd_size();
213 /* Initialize the bd status*/
214 enetIfPtr
->macContextPtr
->isRxFull
= false;
216 /* Initialize receive bd base address and current address*/
217 enetIfPtr
->macContextPtr
->rxBdBasePtr
= rxbdCfg
->rxBdPtrAlign
;
218 enetIfPtr
->macContextPtr
->rxBdCurPtr
= enetIfPtr
->macContextPtr
->rxBdBasePtr
;
219 enetIfPtr
->macContextPtr
->rxBdDirtyPtr
= enetIfPtr
->macContextPtr
->rxBdBasePtr
;
220 enet_hal_set_rxbd_address(enetIfPtr
->deviceNumber
, (uint32_t)(enetIfPtr
->macContextPtr
->rxBdBasePtr
));
222 return kStatus_ENET_Success
;
225 /*FUNCTION****************************************************************
227 * Function Name: enet_mac_txbd_init
228 * Return Value: The execution status.
229 * Description:Initialize the ENET transmit buffer descriptors.
230 * This function prepare all of the transmit buffer descriptors.
231 *END*********************************************************************/
232 uint32_t enet_mac_txbd_init(enet_dev_if_t
* enetIfPtr
, enet_txbd_config_t
*txbdCfg
)
234 /* Check the input parameters*/
235 if ((!enetIfPtr
) || (!txbdCfg
))
237 return kStatus_ENET_InvalidInput
;
240 /* Initialize the bd status*/
241 enetIfPtr
->macContextPtr
->isTxFull
= false;
243 /* Initialize transmit bd base address and current address*/
244 enetIfPtr
->macContextPtr
->txBdBasePtr
= txbdCfg
->txBdPtrAlign
;
245 enetIfPtr
->macContextPtr
->txBdCurPtr
= enetIfPtr
->macContextPtr
->txBdBasePtr
;
246 enetIfPtr
->macContextPtr
->txBdDirtyPtr
= enetIfPtr
->macContextPtr
->txBdBasePtr
;
247 enet_hal_set_txbd_address(enetIfPtr
->deviceNumber
, (uint32_t)(enetIfPtr
->macContextPtr
->txBdBasePtr
));
248 return kStatus_ENET_Success
;
251 /*FUNCTION****************************************************************
253 * Function Name: enet_mac_configure_fifo_accel
254 * Return Value: The execution status.
255 * Description: Configure the ENET FIFO and Accelerator.
256 *END*********************************************************************/
257 uint32_t enet_mac_configure_fifo_accel(enet_dev_if_t
* enetIfPtr
)
259 enet_config_rx_fifo_t rxFifo
;
260 enet_config_tx_fifo_t txFifo
;
262 /* Check the input parameters*/
265 return kStatus_ENET_InvalidInput
;
268 /* Initialize values that will not be initialized later on */
271 txFifo
.isStoreForwardEnabled
= 0;
272 txFifo
.txFifoWrite
= 0;
275 /* Configure tx/rx accelerator*/
276 if (enetIfPtr
->macCfgPtr
->isRxAccelEnabled
)
278 enet_hal_config_rx_accelerator(enetIfPtr
->deviceNumber
,
279 (enet_config_rx_accelerator_t
*)&(enetIfPtr
->macCfgPtr
->rxAcceler
));
280 if ((enetIfPtr
->macCfgPtr
->rxAcceler
.isIpcheckEnabled
) || (enetIfPtr
->macCfgPtr
->rxAcceler
.isProtocolCheckEnabled
))
285 if (enetIfPtr
->macCfgPtr
->isTxAccelEnabled
)
287 enet_hal_config_tx_accelerator(enetIfPtr
->deviceNumber
,
288 (enet_config_tx_accelerator_t
*)&(enetIfPtr
->macCfgPtr
->txAcceler
));
289 if ((enetIfPtr
->macCfgPtr
->txAcceler
.isIpCheckEnabled
) || (enetIfPtr
->macCfgPtr
->txAcceler
.isProtocolCheckEnabled
))
291 txFifo
.isStoreForwardEnabled
= 1;
294 if (enetIfPtr
->macCfgPtr
->isStoreAndFwEnabled
)
297 txFifo
.isStoreForwardEnabled
= 1;
301 /* Set TFWR value if STRFWD is not being used */
302 if (txFifo
.isStoreForwardEnabled
== 1)
303 txFifo
.txFifoWrite
= 0;
305 /* TFWR value is a trade-off between transmit latency and risk of transmit FIFO underrun due to contention for the system bus
306 TFWR = 15 means transmission will begin once 960 bytes has been written to the Tx FIFO (for frames larger than 960 bytes)
307 See Section 45.4.18 - Transmit FIFO Watermark Register of the K64F Reference Manual for details */
308 txFifo
.txFifoWrite
= 15;
310 /* Configure tx/rx FIFO with default value*/
311 rxFifo
.rxAlmostEmpty
= 4;
312 rxFifo
.rxAlmostFull
= 4;
313 txFifo
.txAlmostEmpty
= 4;
314 txFifo
.txAlmostFull
= 8;
315 enet_hal_config_rx_fifo(enetIfPtr
->deviceNumber
, &rxFifo
);
316 enet_hal_config_tx_fifo(enetIfPtr
->deviceNumber
, &txFifo
);
318 return kStatus_ENET_Success
;
321 /*FUNCTION****************************************************************
323 * Function Name: enet_mac_configure_controller
324 * Return Value: The execution status.
325 * Description: Configure the ENET controller with the basic configuration.
326 *END*********************************************************************/
327 uint32_t enet_mac_configure_controller(enet_dev_if_t
* enetIfPtr
)
331 /* Check the input parameters*/
332 if (enetIfPtr
== NULL
)
334 return kStatus_ENET_InvalidInput
;
337 macCtlCfg
= enetIfPtr
->macCfgPtr
->macCtlConfigure
;
338 /* Configure rmii/mii interface*/
339 enet_hal_config_rmii(enetIfPtr
->deviceNumber
, enetIfPtr
->macCfgPtr
->rmiiCfgMode
,
340 enetIfPtr
->macCfgPtr
->speed
, enetIfPtr
->macCfgPtr
->duplex
, false,
341 (macCtlCfg
& kEnetRxMiiLoopback
));
342 /* Configure receive buffer size*/
343 if (enetIfPtr
->macCfgPtr
->isVlanEnabled
)
345 enetIfPtr
->maxFrameSize
= kEnetMaxFrameVlanSize
;
346 enet_hal_set_rx_max_size(enetIfPtr
->deviceNumber
,
347 enetIfPtr
->macContextPtr
->rxBufferSizeAligned
, kEnetMaxFrameVlanSize
);
351 enetIfPtr
->maxFrameSize
= kEnetMaxFrameSize
;
352 enet_hal_set_rx_max_size(enetIfPtr
->deviceNumber
,
353 enetIfPtr
->macContextPtr
->rxBufferSizeAligned
, kEnetMaxFrameSize
);
356 /* Set receive controller promiscuous */
357 enet_hal_config_promiscuous(enetIfPtr
->deviceNumber
, macCtlCfg
& kEnetRxPromiscuousEnable
);
358 /* Set receive flow control*/
359 enet_hal_enable_flowcontrol(enetIfPtr
->deviceNumber
, (macCtlCfg
& kEnetRxFlowControlEnable
));
360 /* Set received PAUSE frames are forwarded/terminated*/
361 enet_hal_enable_pauseforward(enetIfPtr
->deviceNumber
, (macCtlCfg
& kEnetRxPauseFwdEnable
));
362 /* Set receive broadcast frame reject*/
363 enet_hal_enable_broadcastreject(enetIfPtr
->deviceNumber
, (macCtlCfg
& kEnetRxBcRejectEnable
));
364 /* Set padding is removed from the received frame*/
365 enet_hal_enable_padremove(enetIfPtr
->deviceNumber
, (macCtlCfg
& kEnetRxPadRemoveEnable
));
366 /* Set the crc of the received frame is stripped from the frame*/
367 enet_hal_enable_rxcrcforward(enetIfPtr
->deviceNumber
, (macCtlCfg
& kEnetRxCrcFwdEnable
));
368 /* Set receive payload length check*/
369 enet_hal_enable_payloadcheck(enetIfPtr
->deviceNumber
, (macCtlCfg
& kEnetPayloadlenCheckEnable
));
370 /* Set control sleep mode*/
371 enet_hal_enable_sleep(enetIfPtr
->deviceNumber
, (macCtlCfg
& kEnetSleepModeEnable
));
372 return kStatus_ENET_Success
;
375 /*FUNCTION****************************************************************
377 * Function Name: enet_mac_init
378 * Return Value: The execution status.
379 * Description:Initialize the ENET device with the basic configuration
380 * When ENET is used, this function need to be called by the NET initialize
382 *END*********************************************************************/
383 uint32_t enet_mac_init(enet_dev_if_t
* enetIfPtr
, enet_rxbd_config_t
*rxbdCfg
,
384 enet_txbd_config_t
*txbdCfg
)
386 uint32_t timeOut
= 0;
387 uint32_t devNumber
, result
= 0;
389 /* Check the input parameters*/
390 if (enetIfPtr
== NULL
)
392 return kStatus_ENET_InvalidInput
;
395 /* Get device number and check the parameter*/
396 devNumber
= enetIfPtr
->deviceNumber
;
398 /* Store the global ENET structure for ISR input parameters */
399 enetIfHandle
= enetIfPtr
;
401 /* Turn on ENET module clock gate */
402 CLOCK_SYS_EnableEnetClock(0U);
405 enet_hal_reset_ethernet(devNumber
);
406 while ((!enet_hal_is_reset_completed(devNumber
)) && (timeOut
< kEnetMaxTimeout
))
412 /* Check out if timeout*/
413 if (timeOut
== kEnetMaxTimeout
)
415 return kStatus_ENET_TimeOut
;
418 /* Disable all ENET mac interrupt and Clear all interrupt events*/
419 enet_hal_config_interrupt(devNumber
, kEnetAllInterrupt
, false);
420 enet_hal_clear_interrupt(devNumber
, kEnetAllInterrupt
);
422 /* Program this station's physical address*/
423 enet_hal_set_mac_address(devNumber
, enetIfPtr
->macCfgPtr
->macAddr
);
425 /* Clear group and individual hash register*/
426 enet_hal_set_group_hashtable(devNumber
, 0, kEnetSpecialAddressInit
);
427 enet_hal_set_individual_hashtable(devNumber
, 0, kEnetSpecialAddressInit
);
429 /* Configure mac controller*/
430 result
= enet_mac_configure_controller(enetIfPtr
);
431 if(result
!= kStatus_ENET_Success
)
435 /* Clear mib zero counters*/
436 enet_hal_clear_mib(devNumber
, true);
438 /* Initialize FIFO and accelerator*/
439 result
= enet_mac_configure_fifo_accel(enetIfPtr
);
440 if(result
!= kStatus_ENET_Success
)
444 /* Initialize receive buffer descriptors*/
445 result
= enet_mac_rxbd_init(enetIfPtr
, rxbdCfg
);
446 if(result
!= kStatus_ENET_Success
)
450 /* Initialize transmit buffer descriptors*/
451 result
= enet_mac_txbd_init(enetIfPtr
, txbdCfg
);
452 if(result
!= kStatus_ENET_Success
)
456 /* Initialize rmii/mii interface*/
457 result
= enet_mac_mii_init(enetIfPtr
);
458 if (result
!= kStatus_ENET_Success
)
463 return kStatus_ENET_Success
;
466 /*******************************************************************************
468 ******************************************************************************/