]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blob - src/hw/macs/cpmac/cpmacdrv.c
11adee8b953bb9ab1bb0f3d99ce018f4b07a4d74
[keystone-rtos/ibl.git] / src / hw / macs / cpmac / cpmacdrv.c
1 /**
2  *   @file  cpmacdrv.c
3  *
4  *   @brief   
5  *      The driver is written for the CPMAC Ethernet controller. It follows
6  *      the Network Boot Module Ethernet Driver Specifications.
7  *
8  *      If there are modifications to this driver required for it to work
9  *      on the specific device then device authors are recommended to 
10  *      create a copy of this file in the RBL directory and do the 
11  *      necessary modifications. Please pass on the appropriate information
12  *      to the ROM Boot Loader Framework Development Team.
13  *
14  *  \par
15  *  NOTE:
16  *      (C) Copyright 2008, Texas Instruments, Inc.
17  *  \par
18  */
20 #include "types.h"
21 #include "iblloc.h"
22 #include "device.h"
23 #include "net.h"
24 #include "cpmac_regs.h"
25 #include <string.h>
27 #ifdef TARGET_DEVICE_CPMAC
29 /**********************************************************************
30  ************************** Local Definitions *************************
31  **********************************************************************/
33 // Packet Flags for TX and RX
34 #define EMAC_DSC_FLAG_SOP                       0x80000000u
35 #define EMAC_DSC_FLAG_EOP                       0x40000000u
36 #define EMAC_DSC_FLAG_OWNER                     0x20000000u
37 #define EMAC_DSC_FLAG_EOQ                       0x10000000u
38 #define EMAC_DSC_FLAG_TDOWNCMPLT                0x08000000u
39 #define EMAC_DSC_FLAG_PASSCRC                   0x04000000u
41 // The following flags are RX only
42 #define EMAC_DSC_FLAG_JABBER                    0x02000000u
43 #define EMAC_DSC_FLAG_OVERSIZE                  0x01000000u
44 #define EMAC_DSC_FLAG_FRAGMENT                  0x00800000u
45 #define EMAC_DSC_FLAG_UNDERSIZED                0x00400000u
46 #define EMAC_DSC_FLAG_CONTROL                   0x00200000u
47 #define EMAC_DSC_FLAG_OVERRUN                   0x00100000u
48 #define EMAC_DSC_FLAG_CODEERROR                 0x00080000u
49 #define EMAC_DSC_FLAG_ALIGNERROR                0x00040000u
50 #define EMAC_DSC_FLAG_CRCERROR                  0x00020000u
51 #define EMAC_DSC_FLAG_NOMATCH                   0x00010000u
53 /**********************************************************************
54  ************************** Local Structures **************************
55  **********************************************************************/
57 /**
58  * @brief 
59  *  The structure describes the EMAC Descriptor.
60  *
61  * @details
62  *  Ethernet drivers receives and transmits data through the descriptor
63  *  object described here.
64  */
65 typedef struct _EMAC_Desc 
66 {
67     /**
68      * @brief   Pointer to next descriptor in chain
69      */
70     struct _EMAC_Desc* pNext;
72     /**
73      * @brief   Pointer to the data buffer.
74      */
75     Uint8*             pBuffer;
77     /**
78      * @brief   Buffer Offset(MSW) and Length(LSW)
79      */
80     Uint32             BufOffLen;
82     /**
83      * @brief   Packet Flags(MSW) and Length(LSW)
84      */
85     volatile Uint32    PktFlgLen;
87 }EMAC_Desc;
89 /**
90  * @brief 
91  *  The structure describes the EMAC Master Control Block.
92  *
93  * @details
94  *  The structure stores information required by the EMAC Driver;
95  *  which includes the Receive and Transmit Buffer Descriptors.
96  */
97 typedef struct EMAC_MCB
98 {
99     /**
100      * @brief   Pointer to the Receive Buffer Descriptor
101      */
102     EMAC_Desc*      rx_bd;
104     /**
105      * @brief   Pointer to the Transmit Buffer Descriptor
106      */
107     EMAC_Desc*      tx_bd;
109     /**
110      * @brief   Buffer for receiving data linked with the receive
111      * buffer descriptor.
112      */
113     Uint8           rx_buffer[NET_MAX_MTU];
115     /**
116      * @brief   Tracks the last value placed into the rx hdp
117      */
118     Uint32          lastRxHdp;
120 }EMAC_MCB;
122 /**********************************************************************
123  ************************** Global Variables **************************
124  **********************************************************************/
126 /**
127  * @brief   Global Driver structure which keeps track of all the Ethernet
128  * Driver related information.
129  */
130 EMAC_MCB   emacMCB;
132 /**
133  * @brief   EMAC Registers.
134  */
135 Uint32 aptr_EMACRegs[] = TARGET_EMAC_BASE_ADDRESSES;
136 Uint32 aptr_EmacDesc[] = TARGET_EMAC_DSC_BASE_ADDR;
139 /**********************************************************************
140  ************************** ETHDRV Functions **************************
141  **********************************************************************/
143 /**
144  *  @b Description
145  *  @n  
146  *      This is the Network Open API which is registered with the 
147  *      NET Boot module to initialize the Ethernet device.
148  *
149  *  @param[in]  ptr_device
150  *      Pointer to the NET Device structure which is being opened.
151  *
152  *  @retval
153  *      Success -   0
154  *  @retval
155  *      Error   -   <0
156  */
157 Int32 cpmac_drv_start (NET_DRV_DEVICE* ptr_device)
159     Uint32           tmpval;
160     volatile Uint32* pRegAddr;
161     Int32            index;
162     CPMAC_REGS*      ptr_EMACRegs;
163     EMAC_Desc*       pDesc;
165     if (ptr_device->port_num >= TARGET_EMAC_N_PORTS)
166         return (-1);
169     ptr_EMACRegs = (CPMAC_REGS *)(aptr_EMACRegs[ptr_device->port_num]);
170     pDesc        = (EMAC_Desc *)(aptr_EmacDesc[ptr_device->port_num]);
171         
172     /* Some devices require chip level application of reset before device configuration.
173      * Devices that dont require this will define this function call to be a void statement */
174     deviceSetEthResetState (ptr_device->port_num, TRUE);
175     
176     /* Reset EMAC */
177     ptr_EMACRegs->SOFTRESET = 0x1;
178     while (ptr_EMACRegs->SOFTRESET != 0x0);
180     /* Reset MAC Control */
181     ptr_EMACRegs->MACCONTROL = 0;
183     /* Must manually init HDPs to NULL */
184     pRegAddr = &ptr_EMACRegs->TX0HDP;
185     for( index=0; index<8; index++ )
186         *pRegAddr++ = 0;
188     pRegAddr = &ptr_EMACRegs->RX0HDP;
189     for( index=0; index<8; index++ )
190         *pRegAddr++ = 0;
192     pRegAddr = &ptr_EMACRegs->TX0CP;
193     for( index=0; index<8; index++ )  {
194         tmpval = *pRegAddr;
195         *pRegAddr++ = tmpval;
196     }
198     pRegAddr = &ptr_EMACRegs->RX0CP;
199     for( index=0; index<8; index++ )  {
200         tmpval = *pRegAddr;
201         *pRegAddr++ = tmpval;
202     }
205     /* Initialize the RAM locations */
206     for (index = 0; index < 32; index++)
207     {
208         ptr_EMACRegs->MACINDEX  = index;
209         ptr_EMACRegs->MACADDRHI = 0;
210         ptr_EMACRegs->MACADDRLO = 0;
211     }
213     /* Setup device MAC address */
214     ptr_EMACRegs->MACINDEX = 0x0;
216     /* Configure the MAC Address into the EMAC Controller. */
217     tmpval = 0;
218     for( index=3; index>=0; index-- )
219         tmpval = (tmpval<<8) | *(ptr_device->mac_address+index);
220     ptr_EMACRegs->MACADDRHI = tmpval;
221     tmpval = *(ptr_device->mac_address+5);
222     ptr_EMACRegs->MACADDRLO = CPMAC_MACADDRLO_VALID | CPMAC_MACADDRLO_MATCHFILT | 
223                               (tmpval<<8) | *(ptr_device->mac_address+4);
225     /* For us buffer offset will always be zero */
226     ptr_EMACRegs->RXBUFFEROFFSET = 0;
228     /* Reset RX (M)ulticast (B)roadcast (P)romiscuous Enable register */
229     ptr_EMACRegs->RXMBPENABLE = 0;
230     ptr_EMACRegs->MACHASH1    = 0;
231     ptr_EMACRegs->MACHASH2    = 0;
233     /* Clear Unicast RX on channel 0-7 */
234     ptr_EMACRegs->RXUNICASTCLEAR = 0xFF;
236     /* Make sure there are none of the interrupts are enabled. */
237     ptr_EMACRegs->RXINTMASKCLEAR = 0xFF;
238     ptr_EMACRegs->TXINTMASKCLEAR = 0xFF;
239     ptr_EMACRegs->MACINTMASKCLEAR = 0x0;
241     /* Initialize the receive buffer descriptor. */
242     pDesc->pNext     = 0;
243     pDesc->pBuffer   = (Uint8 *)deviceLocalAddrToGlobal((Uint32)&emacMCB.rx_buffer[0]);
244     pDesc->BufOffLen = NET_MAX_MTU;
245     pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
247     /* Store this buffer descriptor in the global EMAC MCB */
248     emacMCB.rx_bd = pDesc;
250     /* Get the transmit buffer descriptor; it comes right after the receive BD. */
251     pDesc = pDesc + 1;
253     /* Initialize the transmit buffer descriptor. */
254     pDesc->pNext     = 0;
255     pDesc->pBuffer   = 0;
256     pDesc->BufOffLen = 0;
257     pDesc->PktFlgLen = 0;
259     /* Store this buffer descriptor in the global EMAC MCB */
260     emacMCB.tx_bd = pDesc;
262 #ifdef EMAC_CACHE_SUPPORT
263     /* Writeback the EMAC MCB Information to the PHYSICAL Memory. 
264      * This is required because the buffer in the cache will always be
265      * invalidated on the RECEIVE; if the buffer is not aligned on the
266      * CACHE Line then it will result in the RX & TX BD in the structure
267      * to also get invalidated to what resides in the PHYSICAL memory.
268      * But if we have written back the structure here then the PHYSICAL
269      * and CACHE are one and the same as far as the BD's are concerned. */
270     Cache_wbL2((void *)&emacMCB, sizeof(emacMCB));
271 #endif
273     /* Enable the receive and transmit. */
274     ptr_EMACRegs->TXCONTROL = 0x1;
275     ptr_EMACRegs->RXCONTROL = 0x1;
276     
277     /* Initialize the MAC Control: We set the Receive Ownership Bit and the Receive
278      * Offset Length Word and enable the MII. */
279     ptr_EMACRegs->MACCONTROL = TARGET_MAC_CONTROL;
281     /* Startup RX */
282     ptr_EMACRegs->RX0HDP = (Uint32)emacMCB.rx_bd;
283     emacMCB.lastRxHdp    = (Uint32)emacMCB.rx_bd;
285     /* Enable receive filters for channel 1 and all broadcast packets. */
286     ptr_EMACRegs->RXUNICASTSET = 1;
287     ptr_EMACRegs->RXMBPENABLE = CPMAC_RXMBPENABLE_RXBROADEN;
290     /* Some devices require chip level application of reset before device configuration.
291      * Devices that dont require this will define this function call to be a void statement */
292     deviceSetEthResetState (ptr_device->port_num, FALSE);
294     /* Initialize the Device MDIO layer: The function returns only when 
295      * the LINK is UP and RUNNING. */
296     if (dev_mdio_open () < 0)
297         return -1;        
299     /* Debug Message: */
300     mprintf ("DEBUG: Ethernet Link is UP \n");
302     /* Hardware is up and running. */
303     return 0;
306 /**
307  *  @b Description
308  *  @n
309  *      This is the Network Send API which is registered with the NET boot module
310  *      to send out packets. 
311  *
312  *  @param[in]   ptr_device
313  *      Pointer to the network interface descriptor object.
314  *  @param[in]   buffer
315  *      Pointer to the packet which is to be transmitted.
316  *  @param[in]   num_bytes
317  *      Length of the packet which is transmitted.
318  *
319  *  @retval
320  *      Success -   Number of bytes transmitted.
321  *  @retval
322  *      Error   -   <0
323  */
324 Int32 cpmac_drv_send (NET_DRV_DEVICE* ptr_device, Uint8* buffer, int num_bytes)
326     volatile EMAC_Desc* pDesc;
327     CPMAC_REGS*         ptr_EMACRegs;
329     if (ptr_device->port_num >= TARGET_EMAC_N_PORTS)
330         return (-1);
332     ptr_EMACRegs = (CPMAC_REGS *)(aptr_EMACRegs[ptr_device->port_num]);
334     /* Ensure the minimum ethernet size is sent out. */
335     if (num_bytes < 64)
336         num_bytes = 64;
338 #ifdef EMAC_CACHE_SUPPORT
339     /* Clean the cache for external addesses */
340     Cache_wbL2((void *)buffer, num_bytes);
341 #endif
343     /* Get the pointer to the transmit buffer descriptor. */
344     pDesc = emacMCB.tx_bd;
346     /* Fill out the transmit buffer descriptor */
347     pDesc->pNext     = 0;
348     pDesc->pBuffer   = (Uint8 *)deviceLocalAddrToGlobal((Uint32)buffer);
349     pDesc->BufOffLen = num_bytes;
350     pDesc->PktFlgLen = EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_EOP | num_bytes | EMAC_DSC_FLAG_OWNER;
352     /* Send the packet out. */
353     ptr_EMACRegs->TX0HDP = (Uint32)pDesc;
355     /* Loop around till the transmission is complete. */
356     do  {
357         pDesc = (EMAC_Desc *)ptr_EMACRegs->TX0CP;
358     } while (pDesc->PktFlgLen & EMAC_DSC_FLAG_OWNER);
360     /* The packet has been successfully transmitted. */
361     return num_bytes;
364 /**
365  *  @b Description
366  *  @n
367  *      This is the Network Receive API which is registered with the NET boot module
368  *      to receive packets. 
369  *
370  *  @param[in]   ptr_device
371  *      Pointer to the network interface descriptor object.
372  *  @param[out]   buffer
373  *      Pointer to the packet which is populated with the received data
374  *
375  *  @retval
376  *      Success -   Number of bytes received.
377  *  @retval
378  *      Error   -   <0
379  */
380 Int32 cpmac_drv_receive (NET_DRV_DEVICE* ptr_device, Uint8* buffer)
382     Int32        bytes_received = 0;
383     Uint32       rxhdp;
384     EMAC_Desc*   pDesc;
385     CPMAC_REGS*  ptr_EMACRegs;
387     if (ptr_device->port_num >= TARGET_EMAC_N_PORTS)
388         return (-1);
390     ptr_EMACRegs = (CPMAC_REGS *)(aptr_EMACRegs[ptr_device->port_num]);
392     /* Initialize the number of bytes received. */
393     bytes_received = 0;
395     
396     /* Make sure the header pointer has advanced. */
397     rxhdp = (Uint32)ptr_EMACRegs->RX0HDP;
398     if (rxhdp == emacMCB.lastRxHdp)
399         return (0);
401     /* Read the completion register. We know for sure if the SOP flag is set then
402      * a packet has been received and needs to be picked up from the controller. */
403     pDesc = (EMAC_Desc *)ptr_EMACRegs->RX0CP;
404     if (pDesc->PktFlgLen & EMAC_DSC_FLAG_SOP)
405     {
406         /* Acknowledge that the descriptor has been processed. */
407         ptr_EMACRegs->RX0CP = (Uint32)pDesc;
409 #ifdef EMAC_CACHE_SUPPORT
410                 /* External Memory Support: Invalidate the cache. */
411         Cache_invL2((void *)(pDesc->pBuffer), NET_MAX_MTU);
412 #endif
413         /* Remember the number of bytes received. */
414         bytes_received = (pDesc->PktFlgLen & 0xFFFF);
416         /* The descriptor is now free to receive more data. Set the status accordingly. */
417         pDesc->BufOffLen = NET_MAX_MTU;
418         pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
420         /* Copy the data from the descriptor buffer to the supplied buffer. */
421         memcpy((void *)buffer, (void *)pDesc->pBuffer, bytes_received);
423         /* Put this descriptor back to the HDP. */
424         ptr_EMACRegs->RX0HDP = (Uint32)pDesc;
425     }
427     /* Return the number of bytes received. */
428     return bytes_received;
431 /**
432  *  @b Description
433  *  @n
434  *      This is the Network Close API which is registered with the NET boot module
435  *      to close and shutdown the Ethernet controller.
436  *
437  *  @param[in]   ptr_device
438  *      Pointer to the network interface descriptor object.
439  *
440  *  @retval
441  *      Success -   0
442  *  @retval
443  *      Error   -   <0
444  */
445 Int32 cpmac_drv_stop (NET_DRV_DEVICE* ptr_device)
447     return 0;
451 #endif /* TARGET_DEVICE_CPMAC */