]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/net/eth/lwip-eth/arch/TARGET_Freescale/fsl_enet_driver.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / net / eth / lwip-eth / arch / TARGET_Freescale / fsl_enet_driver.c
1 /*
2 * Copyright (c) 2013 - 2014, Freescale Semiconductor, 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 * o Redistributions of source code must retain the above copyright notice, this list
9 *   of conditions and the following disclaimer.
10 *
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.
14 *
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.
18 *
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.
29 */
30
31 /* Modified by mbed for the lwIP port */
32
33 #include "fsl_enet_driver.h"
34 #include "fsl_enet_hal.h"
35 #include "fsl_clock_manager.h"
36 #include "fsl_interrupt_manager.h"
37 #include <string.h>
38
39 #include "sys_arch.h"
40
41 /*******************************************************************************
42  * Variables
43  ******************************************************************************/
44 /*! @brief Define ENET's IRQ list */
45
46 void *enetIfHandle;
47
48 /*! @brief Define MAC driver API structure and for application of stack adaptor layer*/
49 const enet_mac_api_t g_enetMacApi =
50 {
51     enet_mac_init,
52     NULL, // enet_mac_deinit,
53     NULL, // enet_mac_send,
54 #if !ENET_RECEIVE_ALL_INTERRUPT
55     NULL, // enet_mac_receive,
56 #endif
57     enet_mii_read,
58     enet_mii_write,
59     NULL, // enet_mac_add_multicast_group,
60     NULL, //enet_mac_leave_multicast_group,
61 };
62 /*******************************************************************************
63  * Code
64  ******************************************************************************/
65
66 // NOTE: we need these functions to be non-blocking fpr the PHY task, hence the
67 // osDelay() below
68
69 /*FUNCTION****************************************************************
70  *
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)
78 {
79     uint32_t  counter;
80         
81     /* Check the input parameters*/
82     if (!dataPtr)
83     {
84         return kStatus_ENET_InvalidInput;
85     }
86
87     /* Check if the mii is enabled*/
88     if (!enet_hal_is_mii_enabled(instance))
89     {
90         return kStatus_ENET_Miiuninitialized;
91     }
92
93     /* Clear the MII interrupt event*/
94     enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
95
96     /* Read command operation*/
97     enet_hal_set_mii_command(instance, phyAddr, phyReg, kEnetReadValidFrame, 0);
98
99     /* Poll for MII complete*/
100     for (counter = 0; counter < kEnetMaxTimeout; counter++)
101     {
102         if (enet_hal_get_interrupt_status(instance, kEnetMiiInterrupt))
103         {
104             break;
105         }
106         osDelay(1);
107     }
108
109     /* Check for timeout*/
110     if (counter == kEnetMaxTimeout)
111     {
112         return kStatus_ENET_TimeOut;
113     }
114
115     /* Get data from mii register*/
116     *dataPtr = enet_hal_get_mii_data(instance);
117
118     /* Clear MII interrupt event*/
119     enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
120         
121     return kStatus_ENET_Success;
122 }
123
124 /*FUNCTION****************************************************************
125  *
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)
133 {
134     uint32_t counter;
135
136     /* Check if the mii is enabled*/
137     if (!enet_hal_is_mii_enabled(instance))
138     {
139         return kStatus_ENET_Miiuninitialized;
140     }
141
142     /* Clear the MII interrupt event*/
143     enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
144
145     /* Read command operation*/
146     enet_hal_set_mii_command(instance, phyAddr, phyReg, kEnetWriteValidFrame, data);
147
148     /* Poll for MII complete*/
149     for (counter = 0; counter < kEnetMaxTimeout; counter++)
150     {
151         if (enet_hal_get_interrupt_status(instance, kEnetMiiInterrupt))
152         {
153             break;
154         }
155         osDelay(1);
156     }
157
158     /* Check for timeout*/
159     if (counter == kEnetMaxTimeout)
160     {
161         return kStatus_ENET_TimeOut;
162     }
163
164     /* Clear MII intrrupt event*/
165     enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
166         
167     return kStatus_ENET_Success;
168 }
169 /*FUNCTION****************************************************************
170  *
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)
176 {
177     uint32_t frequency;
178         
179     /* Check the input parameters*/
180     if (enetIfPtr == NULL)
181     {
182         return kStatus_ENET_InvalidInput;
183     }
184
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);
189
190     return kStatus_ENET_Success;
191 }
192
193 /*FUNCTION****************************************************************
194  *
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)
204 {
205     /* Check the input parameters*/
206     if ((!enetIfPtr) || (!rxbdCfg))
207     {
208         return kStatus_ENET_InvalidInput;
209     }
210
211     enetIfPtr->macContextPtr->bufferdescSize = enet_hal_get_bd_size();
212
213     /* Initialize the bd status*/
214     enetIfPtr->macContextPtr->isRxFull = false;
215                 
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));
221         
222     return kStatus_ENET_Success;
223 }
224
225 /*FUNCTION****************************************************************
226  *
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)
233 {
234     /* Check the input parameters*/
235     if ((!enetIfPtr) || (!txbdCfg))
236     {
237         return kStatus_ENET_InvalidInput;
238     }
239
240     /* Initialize the bd status*/
241     enetIfPtr->macContextPtr->isTxFull = false;
242
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;
249 }
250
251 /*FUNCTION****************************************************************
252  *
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)
258 {
259     enet_config_rx_fifo_t rxFifo;
260     enet_config_tx_fifo_t txFifo;
261         
262     /* Check the input parameters*/
263     if (!enetIfPtr)
264     {
265         return kStatus_ENET_InvalidInput;
266     }
267                 
268                 /* Initialize values that will not be initialized later on */
269     rxFifo.rxEmpty = 0;
270     rxFifo.rxFull = 0;
271     txFifo.isStoreForwardEnabled = 0;
272     txFifo.txFifoWrite = 0;
273     txFifo.txEmpty = 0;
274
275     /* Configure tx/rx accelerator*/
276     if (enetIfPtr->macCfgPtr->isRxAccelEnabled)
277     {
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))
281         {
282             rxFifo.rxFull = 0;
283         }
284     }
285     if (enetIfPtr->macCfgPtr->isTxAccelEnabled)
286     {
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))
290         {
291             txFifo.isStoreForwardEnabled = 1;
292         }
293     }
294     if (enetIfPtr->macCfgPtr->isStoreAndFwEnabled)
295     {
296           rxFifo.rxFull = 0;
297           txFifo.isStoreForwardEnabled = 1;
298     }
299
300
301     /* Set TFWR value if STRFWD is not being used  */
302     if (txFifo.isStoreForwardEnabled == 1)
303           txFifo.txFifoWrite = 0;
304     else
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;
309                 
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);
317
318     return kStatus_ENET_Success;
319 }
320
321 /*FUNCTION****************************************************************
322  *
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)
328 {
329     uint32_t macCtlCfg;
330
331     /* Check the input parameters*/
332     if (enetIfPtr == NULL)
333     {
334         return kStatus_ENET_InvalidInput;
335     }
336
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)
344     {
345         enetIfPtr->maxFrameSize = kEnetMaxFrameVlanSize;
346         enet_hal_set_rx_max_size(enetIfPtr->deviceNumber,
347               enetIfPtr->macContextPtr->rxBufferSizeAligned, kEnetMaxFrameVlanSize);
348     }
349     else
350     {
351         enetIfPtr->maxFrameSize = kEnetMaxFrameSize;
352         enet_hal_set_rx_max_size(enetIfPtr->deviceNumber,
353               enetIfPtr->macContextPtr->rxBufferSizeAligned, kEnetMaxFrameSize);
354     }
355
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;
373 }
374
375 /*FUNCTION****************************************************************
376  *
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
381  * interface.
382  *END*********************************************************************/
383 uint32_t enet_mac_init(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg,
384                             enet_txbd_config_t *txbdCfg)
385 {
386     uint32_t timeOut = 0;
387     uint32_t devNumber, result = 0;
388         
389     /* Check the input parameters*/
390     if (enetIfPtr == NULL)
391     {
392         return kStatus_ENET_InvalidInput;
393     }
394
395     /* Get device number and check the parameter*/
396     devNumber = enetIfPtr->deviceNumber;
397
398     /* Store the global ENET structure for ISR input parameters */
399     enetIfHandle = enetIfPtr;
400
401     /* Turn on ENET module clock gate */
402     CLOCK_SYS_EnableEnetClock(0U);
403
404     /* Reset ENET mac*/
405     enet_hal_reset_ethernet(devNumber);
406     while ((!enet_hal_is_reset_completed(devNumber)) && (timeOut < kEnetMaxTimeout))
407     {
408         time_delay(1);
409         timeOut++;
410     }
411
412     /* Check out if timeout*/
413     if (timeOut == kEnetMaxTimeout)
414     {
415         return kStatus_ENET_TimeOut;
416     }
417         
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);
421         
422     /* Program this station's physical address*/
423     enet_hal_set_mac_address(devNumber, enetIfPtr->macCfgPtr->macAddr);
424
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);
428
429           /* Configure mac controller*/
430     result = enet_mac_configure_controller(enetIfPtr);
431     if(result != kStatus_ENET_Success)
432     {
433         return result;
434     }
435     /* Clear mib zero counters*/
436     enet_hal_clear_mib(devNumber, true);
437
438     /* Initialize FIFO and accelerator*/
439     result = enet_mac_configure_fifo_accel(enetIfPtr);
440     if(result != kStatus_ENET_Success)
441     {
442         return result;
443     }
444     /* Initialize receive buffer descriptors*/
445     result = enet_mac_rxbd_init(enetIfPtr, rxbdCfg);
446     if(result != kStatus_ENET_Success)
447     {
448         return result;
449     }
450     /* Initialize transmit buffer descriptors*/
451           result = enet_mac_txbd_init(enetIfPtr, txbdCfg);
452     if(result != kStatus_ENET_Success)
453     {
454         return result;
455     }
456     /* Initialize rmii/mii interface*/
457     result = enet_mac_mii_init(enetIfPtr);
458     if (result != kStatus_ENET_Success)
459     {
460         return result;
461     }
462     
463     return kStatus_ENET_Success;
464 }
465
466 /*******************************************************************************
467  * EOF
468  ******************************************************************************/
469