]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/sys/ti_drv_emac.c
Get rid of "last line of file ends without a newline" warning
[pes-rpp/rpp-lib.git] / rpp / src / sys / ti_drv_emac.c
1 /**
2  *  \file   emac.c
3  *
4  *  \brief  EMAC APIs.
5  *
6  *   This file contains the device abstraction layer APIs for EMAC.
7  */
8
9 /* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
10  * ALL RIGHTS RESERVED
11  */
12
13 #include "base.h"
14 #include "sys/hw_reg_access.h"
15 #include "sys/ti_drv_emac.h"
16 #include "sys/hw_emac.h"
17 #include "sys/hw_emac_ctrl.h"
18
19 /*******************************************************************************
20 *                       INTERNAL MACRO DEFINITIONS
21 *******************************************************************************/
22 #define EMAC_CONTROL_RESET             (0x01u)
23 #define EMAC_SOFT_RESET                (0x01u)
24 #define EMAC_MAX_HEADER_DESC           (8u)
25 #define EMAC_UNICAST_DISABLE           (0xFFu)
26
27 /*******************************************************************************
28 *                        API FUNCTION DEFINITIONS
29 *******************************************************************************/
30 /**
31  * \brief   Enables the TXPULSE Interrupt Generation.
32  *
33  * \param   emacBase      Base address of the EMAC Module registers.
34  * \param   emacCtrlBase  Base address of the EMAC CONTROL module registers
35  * \param   ctrlCore      Control core for which the interrupt to be enabled.
36  * \param   channel       Channel number for which interrupt to be enabled
37  *
38  * \return  None
39  *
40  **/
41 void EMACTxIntPulseEnable(unsigned int emacBase, unsigned int emacCtrlBase,
42                           unsigned int ctrlCore, unsigned int channel)
43 {
44     HWREG(emacBase + EMAC_TXINTMASKSET) |= (1 << channel);
45
46     HWREG(emacCtrlBase + EMAC_CTRL_CnTXEN(ctrlCore)) |= (1 << channel);
47 }
48
49 /**
50  * \brief   Disables the TXPULSE Interrupt Generation.
51  *
52  * \param   emacBase      Base address of the EMAC Module registers.
53  * \param   emacCtrlBase  Base address of the EMAC CONTROL module registers
54  * \param   ctrlCore      Control core for which the interrupt to be disabled.
55  * \param   channel       Channel number for which interrupt to be disabled
56  *
57  * \return  None
58  *
59  **/
60 void EMACTxIntPulseDisable(unsigned int emacBase, unsigned int emacCtrlBase,
61                            unsigned int ctrlCore, unsigned int channel)
62 {
63     HWREG(emacBase + EMAC_TXINTMASKCLEAR) |= (1 << channel);
64
65     HWREG(emacCtrlBase + EMAC_CTRL_CnTXEN(ctrlCore)) &= ~(1 << channel);
66 }
67
68 /**
69  * \brief   Enables the RXPULSE Interrupt Generation.
70  *
71  * \param   emacBase      Base address of the EMAC Module registers.
72  * \param   emacCtrlBase  Base address of the EMAC CONTROL module registers
73  * \param   ctrlCore      Control core for which the interrupt to be enabled.
74  * \param   channel       Channel number for which interrupt to be enabled
75  *
76  * \return  None
77  *
78  **/
79 void EMACRxIntPulseEnable(unsigned int emacBase, unsigned int emacCtrlBase,
80                           unsigned int ctrlCore, unsigned int channel)
81 {
82     HWREG(emacBase + EMAC_RXINTMASKSET) |= (1 << channel);
83
84     HWREG(emacCtrlBase + EMAC_CTRL_CnRXEN(ctrlCore)) |= (1 << channel);
85 }
86
87 /**
88  * \brief   Disables the RXPULSE Interrupt Generation.
89  *
90  * \param   emacBase      Base address of the EMAC Module registers.
91  * \param   emacCtrlBase  Base address of the EMAC CONTROL module registers
92  * \param   ctrlCore      Control core for which the interrupt to be disabled.
93  * \param   channel       Channel number for which interrupt to be disabled
94  *
95  * \return  None
96  *
97  **/
98 void EMACRxIntPulseDisable(unsigned int emacBase, unsigned int emacCtrlBase,
99                            unsigned int ctrlCore, unsigned int channel)
100 {
101     HWREG(emacBase + EMAC_RXINTMASKCLEAR) |= (1 << channel);
102
103     HWREG(emacCtrlBase + EMAC_CTRL_CnRXEN(ctrlCore)) &= ~(1 << channel);
104 }
105 /**
106  * \brief   This API sets the RMII speed. The RMII Speed can be 10 Mbps or
107  *          100 Mbps
108  *
109  * \param   emacBase     Base address of the EMAC Module registers.
110  * \param   speed        speed for setting.
111  *          speed can take the following values. \n
112  *                EMAC_RMIISPEED_10MBPS - 10 Mbps \n
113  *                EMAC_RMIISPEED_100MBPS - 100 Mbps.
114  *
115  * \return  None
116  *
117  **/
118 void EMACRMIISpeedSet(unsigned int emacBase, unsigned int speed)
119 {
120     HWREG(emacBase + EMAC_MACCONTROL) &= ~EMAC_MACCONTROL_RMIISPEED;
121
122     HWREG(emacBase + EMAC_MACCONTROL) |= speed;
123 }
124
125 /**
126  * \brief   This API enables the MII control block
127  *
128  * \param   emacBase     Base address of the EMAC Module registers.
129  *
130  * \return  None
131  *
132  **/
133 void EMACMIIEnable(unsigned int emacBase)
134 {
135     HWREG(emacBase + EMAC_MACCONTROL) |= EMAC_MACCONTROL_GMIIEN;
136 }
137
138 /**
139  * \brief   This API sets the duplex mode of operation(full/half) for MAC.
140  *
141  * \param   emacBase     Base address of the EMAC Module registers.
142  * \param   duplexMode   duplex mode of operation.
143  *          duplexMode can take the following values. \n
144  *                EMAC_DUPLEX_FULL - Full Duplex  \n
145  *                EMAC_DUPLEX_HALF - Half Duplex.
146  *
147  * \return  None
148  *
149  **/
150 void EMACDuplexSet(unsigned int emacBase, unsigned int duplexMode)
151 {
152     HWREG(emacBase + EMAC_MACCONTROL) &= ~EMAC_MACCONTROL_FULLDUPLEX;
153
154     HWREG(emacBase + EMAC_MACCONTROL) |= duplexMode;
155 }
156
157 /**
158  * \brief   API to enable the transmit in the TX Control Register
159  *          After the transmit is enabled, any write to TXHDP of
160  *          a channel will start transmission
161  *
162  * \param   emacBase      Base Address of the EMAC Module Registers.
163  *
164  * \return  None
165  *
166  **/
167 void EMACTxEnable(unsigned int emacBase)
168 {
169     HWREG(emacBase + EMAC_TXCONTROL) = EMAC_TXCONTROL_TXEN;
170 }
171
172 /**
173  * \brief   API to enable the receive in the RX Control Register
174  *          After the transmit is enabled, and write to RXHDP of
175  *          a channel, the data can be received in the destination
176  *          specified by the corresponding RX buffer descriptor.
177  *
178  * \param   emacBase      Base Address of the EMAC Module Registers.
179  *
180  * \return  None
181  *
182  **/
183 void EMACRxEnable(unsigned int emacBase)
184 {
185     HWREG(emacBase + EMAC_RXCONTROL) = EMAC_RXCONTROL_RXEN;
186 }
187
188 /**
189  * \brief   API to write the TX HDP register. If transmit is enabled,
190  *          write to the TX HDP will immediately start transmission.
191  *          The data will be taken from the buffer pointer of the TX buffer
192  *          descriptor written to the TX HDP
193  *
194  * \param   emacBase      Base Address of the EMAC Module Registers.\n
195  * \param   descHdr       Address of the TX buffer descriptor
196  * \param   channel       Channel Number
197  *
198  * \return  None
199  *
200  **/
201 volatile unsigned int lastInputdescHdr = 0;
202 volatile unsigned int valHDPbefWrite = 0;
203 void EMACTxHdrDescPtrWrite(unsigned int emacBase, unsigned int descHdr,
204                            unsigned int channel)
205 {
206     valHDPbefWrite = HWREG(emacBase + EMAC_TXHDP(channel));
207     HWREG(emacBase + EMAC_TXHDP(channel)) = descHdr;
208     lastInputdescHdr = descHdr;
209 }
210
211 /**
212  * \brief   API to write the RX HDP register. If receive is enabled,
213  *          write to the RX HDP will enable data reception to point to
214  *          the corresponding RX buffer descriptor's buffer pointer.
215  *
216  * \param   emacBase      Base Address of the EMAC Module Registers.\n
217  * \param   descHdr       Address of the RX buffer descriptor
218  * \param   channel       Channel Number
219  *
220  * \return  None
221  *
222  **/
223 void EMACRxHdrDescPtrWrite(unsigned int emacBase, unsigned int descHdr,
224                            unsigned int channel)
225 {
226     HWREG(emacBase + EMAC_RXHDP(channel)) = descHdr;
227 }
228
229 /**
230  * \brief   This API Initializes the EMAC and EMAC Control modules. The
231  *          EMAC Control module is reset, the CPPI RAM is cleared. also,
232  *          all the interrupts are disabled. This API doesnot enable any
233  *          interrupt or operation of the EMAC.
234  *
235  * \param   emacCtrlBase      Base Address of the EMAC Control module
236  *                            registers.\n
237  * \param   emacBase          Base address of the EMAC module registers
238  *
239  * \return  None
240  *
241  **/
242 void EMACInit(unsigned int emacCtrlBase, unsigned int emacBase)
243 {
244     unsigned int cnt;
245
246     /* Reset the EMAC Control Module. This clears the CPPI RAM also */
247     HWREG(emacCtrlBase + EMAC_CTRL_SOFTRESET) = EMAC_CONTROL_RESET;
248
249     while(HWREG(emacCtrlBase + EMAC_CTRL_SOFTRESET) & EMAC_CONTROL_RESET);
250
251     /* Reset the EMAC Control Module. This clears the CPPI RAM also */
252     HWREG(emacBase + EMAC_SOFTRESET) = EMAC_SOFT_RESET;
253
254     while(HWREG(emacBase + EMAC_SOFTRESET) & EMAC_SOFT_RESET);
255
256     HWREG(emacBase + EMAC_MACCONTROL)= 0;
257     HWREG(emacBase + EMAC_RXCONTROL)= 0;
258     HWREG(emacBase + EMAC_TXCONTROL)= 0;
259
260     /* Initialize all the header descriptor pointer registers */
261     for(cnt =  0; cnt< EMAC_MAX_HEADER_DESC; cnt++)
262     {
263         HWREG(emacBase + EMAC_RXHDP(cnt)) = 0;
264         HWREG(emacBase + EMAC_TXHDP(cnt)) = 0;
265         HWREG(emacBase + EMAC_RXCP(cnt)) = 0;
266         HWREG(emacBase + EMAC_TXCP(cnt)) = 0;
267         HWREG(emacBase + EMAC_RXFREEBUFFER(cnt)) = 0xFF;
268     }
269     /* Clear the interrupt enable for all the channels */
270     HWREG(emacBase + EMAC_TXINTMASKCLEAR) = 0xFF;
271     HWREG(emacBase + EMAC_RXINTMASKCLEAR) = 0xFF;
272
273     HWREG(emacBase + EMAC_MACHASH1) = 0;
274     HWREG(emacBase + EMAC_MACHASH2) = 0;
275
276     HWREG(emacBase + EMAC_RXBUFFEROFFSET) = 0;
277 }
278
279 /**
280  * \brief   Sets the MAC Address in MACSRCADDR registers.
281  *
282  * \param   emacBase      Base Address of the EMAC module registers.
283  * \param   macAddr       Start address of a MAC address array.
284  *                        The array[0] shall be the LSB of the MAC address
285  *
286  * \return  None
287  *
288  **/
289 void  EMACMACSrcAddrSet(unsigned int emacBase, unsigned char *macAddr)
290 {
291     HWREG(emacBase + EMAC_MACSRCADDRHI) = macAddr[5] |(macAddr[4] << 8)
292                                      |(macAddr[3] << 16) |(macAddr[2] << 24);
293     HWREG(emacBase + EMAC_MACSRCADDRLO) = macAddr[1] | (macAddr[0] << 8);
294 }
295
296 /**
297  * \brief   Sets the MAC Address in MACADDR registers.
298  *
299  * \param   emacBase      Base Address of the EMAC module registers.
300  * \param   channel       Channel Number
301  * \param   matchFilt     Match or Filter
302  * \param   macAddr       Start address of a MAC address array.
303  *                        The array[0] shall be the LSB of the MAC address
304  *          matchFilt can take the following values \n
305  *          EMAC_MACADDR_NO_MATCH_NO_FILTER - Address is not used to match
306  *                                             or filter incoming packet. \n
307  *          EMAC_MACADDR_FILTER - Address is used to filter incoming packets \n
308  *          EMAC_MACADDR_MATCH - Address is used to match incoming packets \n
309  *
310  * \return  None
311  *
312  **/
313 void EMACMACAddrSet(unsigned int emacBase, unsigned int channel,
314                     unsigned char *macAddr, unsigned int matchFilt)
315 {
316     HWREG(emacBase + EMAC_MACINDEX) = channel;
317
318     HWREG(emacBase + EMAC_MACADDRHI) = macAddr[5] |(macAddr[4] << 8)
319                                      |(macAddr[3] << 16) |(macAddr[2] << 24);
320     HWREG(emacBase + EMAC_MACADDRLO) = macAddr[1] | (macAddr[0] << 8)
321                                      | matchFilt | (channel << 16);
322 }
323
324 /**
325  * \brief   Acknowledges an interrupt processed to the EMAC Control Core.
326  *
327  * \param   emacBase      Base Address of the EMAC module registers.
328  * \param   eoiFlag       Type of interrupt to acknowledge to the EMAC Control
329  *                         module.
330  *          eoiFlag can take the following values \n
331  *             EMAC_INT_CORE0_TX - Core 0 TX Interrupt
332  *             EMAC_INT_CORE1_TX - Core 1 TX Interrupt
333  *             EMAC_INT_CORE2_TX - Core 2 TX Interrupt
334  *             EMAC_INT_CORE0_RX - Core 0 RX Interrupt
335  *             EMAC_INT_CORE1_RX - Core 1 RX Interrupt
336  *             EMAC_INT_CORE2_RX - Core 2 RX Interrupt
337  * \return  None
338  *
339  **/
340 void EMACCoreIntAck(unsigned int emacBase, unsigned int eoiFlag)
341 {
342     /* Acknowledge the EMAC Control Core */
343     HWREG(emacBase + EMAC_MACEOIVECTOR) = eoiFlag;
344 }
345
346 /**
347  * \brief   Writes the the TX Completion Pointer for a specific channel
348  *
349  * \param   emacBase      Base Address of the EMAC module registers.
350  * \param   channel       Channel Number.
351  * \param   comPtr        Completion Pointer Value to be written
352  *
353  * \return  None
354  *
355  **/
356 void EMACTxCPWrite(unsigned int emacBase, unsigned int channel, unsigned int comPtr)
357 {
358     HWREG(emacBase + EMAC_TXCP(channel)) = comPtr;
359 }
360
361 uint32_t EMACTxCPRead(unsigned int emacBase, unsigned int channel)
362 {
363     return (HWREG(emacBase + EMAC_TXCP(channel)));
364 }
365
366 /**
367  * \brief   Writes the the RX Completion Pointer for a specific channel
368  *
369  * \param   emacBase      Base Address of the EMAC module registers.
370  * \param   channel       Channel Number.
371  * \param   comPtr        Completion Pointer Value to be written
372  *
373  * \return  None
374  *
375  **/
376 void EMACRxCPWrite(unsigned int emacBase, unsigned int channel, unsigned int comPtr)
377 {
378     HWREG(emacBase + EMAC_RXCP(channel)) = comPtr;
379 }
380
381 /**
382  * \brief   Acknowledges an interrupt processed to the EMAC module. After
383  *          processing an interrupt, the last processed buffer descriptor is
384  *          written to the completion pointer. Also this API acknowledges
385  *          the EMAC Control Module that the RX interrupt is processed for
386  *          a specified core
387  *
388  * \param   emacBase      Base Address of the EMAC module registers.
389  * \param   channel       Channel Number
390  * \param   comPtr        Completion Pointer value. This shall be the buffer
391  *                        descriptor address last processed.
392  * \param   eoiFlag       Type of interrupt to acknowledge to the EMAC Control
393                           module.
394  *          eoiFlag can take the following values \n
395  *             EMAC_INT_CORE0_RX - Core 0 RX Interrupt
396  *             EMAC_INT_CORE1_RX - Core 1 RX Interrupt
397  *             EMAC_INT_CORE2_RX - Core 2 RX Interrupt
398  * \return  None
399  *
400  **/
401 void EMACRxIntAckToClear(unsigned int emacBase, unsigned int channel,
402                          unsigned int comPtr, unsigned eoiFlag)
403 {
404     HWREG(emacBase + EMAC_RXCP(channel)) = comPtr;
405
406     /* Acknowledge the EMAC Control Core */
407     HWREG(emacBase + EMAC_MACEOIVECTOR) = eoiFlag;
408 }
409
410 /**
411  * \brief   Enables a specific channel to receive broadcast frames
412  *
413  * \param   emacBase      Base Address of the EMAC module registers.
414  * \param   channel       Channel Number.
415  *
416  * \return  None
417  *
418  **/
419 void EMACRxBroadCastEnable(unsigned int emacBase, unsigned int channel)
420 {
421     HWREG(emacBase + EMAC_RXMBPENABLE) &= ~EMAC_RXMBPENABLE_RXBROADCH;
422
423     HWREG(emacBase + EMAC_RXMBPENABLE) |=
424                               EMAC_RXMBPENABLE_RXBROADEN |
425                               (channel << EMAC_RXMBPENABLE_RXBROADCH_SHIFT);
426 }
427
428 void EMACRxPromiscEnable(unsigned int emacBase, unsigned int channel)
429 {
430     HWREG(emacBase + EMAC_RXMBPENABLE) |= EMAC_RXMBPENABLE_RXCAFEN | EMAC_RXMBPENABLE_RXCEFEN;
431     HWREG(emacBase + EMAC_RXMBPENABLE) |= (channel << EMAC_RXMBPENABLE_RXPROMCH_SHIFT);
432 }
433 /**
434  * \brief   Enables unicast for a specific channel
435  *
436  * \param   emacBase      Base Address of the EMAC module registers.
437  * \param   channel       Channel Number.
438  *
439  * \return  None
440  *
441  **/
442 void EMACRxUnicastSet(unsigned int emacBase, unsigned int channel)
443 {
444     HWREG(emacBase + EMAC_RXUNICASTSET) |= (1 << channel);
445 }
446
447 /**
448  * \brief   Set the free buffers for a specific channel
449  *
450  * \param   emacBase      Base Address of the EMAC module registers.
451  * \param   channel       Channel Number.
452  * \param   nBuf          Number of free buffers
453  *
454  * \return  None
455  *
456  **/
457 void EMACNumFreeBufSet(unsigned int emacBase, unsigned int channel,
458                        unsigned int nBuf)
459 {
460     HWREG(emacBase + EMAC_RXFREEBUFFER(channel)) = nBuf;
461 }
462
463 /**
464  * \brief   Gets the interrupt vectors of EMAC, which are pending
465  *
466  * \param   emacBase      Base Address of the EMAC module registers.
467  *
468  * \return  Vectors
469  *
470  **/
471 unsigned int EMACIntVectorGet(unsigned int emacBase)
472 {
473     return (HWREG(emacBase + EMAC_MACINVECTOR));
474 }
475
476 unsigned int EMACIntVectorRawGet(unsigned int emacBase)
477 {
478     return (HWREG(emacBase + EMAC_RXINTSTATRAW));
479 }
480
481 /***************************** End Of File ***********************************/