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 */
19 #include "types.h"
20 #include "iblloc.h"
21 #include "device.h"
22 #include "net.h"
23 #include "cpmac_regs.h"
24 #include <string.h>
27 /**********************************************************************
28 ************************** Local Definitions *************************
29 **********************************************************************/
31 // Packet Flags for TX and RX
32 #define EMAC_DSC_FLAG_SOP 0x80000000u
33 #define EMAC_DSC_FLAG_EOP 0x40000000u
34 #define EMAC_DSC_FLAG_OWNER 0x20000000u
35 #define EMAC_DSC_FLAG_EOQ 0x10000000u
36 #define EMAC_DSC_FLAG_TDOWNCMPLT 0x08000000u
37 #define EMAC_DSC_FLAG_PASSCRC 0x04000000u
39 // The following flags are RX only
40 #define EMAC_DSC_FLAG_JABBER 0x02000000u
41 #define EMAC_DSC_FLAG_OVERSIZE 0x01000000u
42 #define EMAC_DSC_FLAG_FRAGMENT 0x00800000u
43 #define EMAC_DSC_FLAG_UNDERSIZED 0x00400000u
44 #define EMAC_DSC_FLAG_CONTROL 0x00200000u
45 #define EMAC_DSC_FLAG_OVERRUN 0x00100000u
46 #define EMAC_DSC_FLAG_CODEERROR 0x00080000u
47 #define EMAC_DSC_FLAG_ALIGNERROR 0x00040000u
48 #define EMAC_DSC_FLAG_CRCERROR 0x00020000u
49 #define EMAC_DSC_FLAG_NOMATCH 0x00010000u
51 /**********************************************************************
52 ************************** Local Structures **************************
53 **********************************************************************/
55 /**
56 * @brief
57 * The structure describes the EMAC Descriptor.
58 *
59 * @details
60 * Ethernet drivers receives and transmits data through the descriptor
61 * object described here.
62 */
63 typedef struct _EMAC_Desc
64 {
65 /**
66 * @brief Pointer to next descriptor in chain
67 */
68 struct _EMAC_Desc* pNext;
70 /**
71 * @brief Pointer to the data buffer.
72 */
73 Uint8* pBuffer;
75 /**
76 * @brief Buffer Offset(MSW) and Length(LSW)
77 */
78 Uint32 BufOffLen;
80 /**
81 * @brief Packet Flags(MSW) and Length(LSW)
82 */
83 volatile Uint32 PktFlgLen;
84 }EMAC_Desc;
86 /**
87 * @brief
88 * The structure describes the EMAC Master Control Block.
89 *
90 * @details
91 * The structure stores information required by the EMAC Driver;
92 * which includes the Receive and Transmit Buffer Descriptors.
93 */
94 typedef struct EMAC_MCB
95 {
96 /**
97 * @brief Pointer to the Receive Buffer Descriptor
98 */
99 EMAC_Desc* rx_bd;
101 /**
102 * @brief Pointer to the Transmit Buffer Descriptor
103 */
104 EMAC_Desc* tx_bd;
106 /**
107 * @brief Buffer for receiving data linked with the receive
108 * buffer descriptor.
109 */
110 Uint8 rx_buffer[NET_MAX_MTU];
111 }EMAC_MCB;
113 /**********************************************************************
114 ************************** Global Variables **************************
115 **********************************************************************/
117 /**
118 * @brief Global Driver structure which keeps track of all the Ethernet
119 * Driver related information.
120 */
121 EMAC_MCB emacMCB;
123 /**
124 * @brief EMAC Registers.
125 */
126 CPMAC_REGS* ptr_EMACRegs = (CPMAC_REGS *)EMAC_BASE_ADDRESS;
128 /**********************************************************************
129 ************************** ETHDRV Functions **************************
130 **********************************************************************/
132 /**
133 * @b Description
134 * @n
135 * This is the Network Open API which is registered with the
136 * NET Boot module to initialize the Ethernet device.
137 *
138 * @param[in] ptr_device
139 * Pointer to the NET Device structure which is being opened.
140 *
141 * @retval
142 * Success - 0
143 * @retval
144 * Error - <0
145 */
146 Int32 cpmac_drv_start (NET_DRV_DEVICE* ptr_device)
147 {
148 Uint32 tmpval;
149 volatile Uint32* pRegAddr;
150 Int32 index;
151 EMAC_Desc* pDesc;
153 /* Reset EMAC */
154 ptr_EMACRegs->SOFTRESET = 0x1;
155 while (ptr_EMACRegs->SOFTRESET != 0x0);
157 /* Reset MAC Control */
158 ptr_EMACRegs->MACCONTROL = 0;
160 /* Must manually init HDPs to NULL */
161 pRegAddr = &ptr_EMACRegs->TX0HDP;
162 for( index=0; index<8; index++ )
163 *pRegAddr++ = 0;
164 pRegAddr = &ptr_EMACRegs->RX0HDP;
165 for( index=0; index<8; index++ )
166 *pRegAddr++ = 0;
168 /* Initialize the RAM locations */
169 for (index = 0; index < 32; index++)
170 {
171 ptr_EMACRegs->MACINDEX = index;
172 ptr_EMACRegs->MACADDRHI = 0;
173 ptr_EMACRegs->MACADDRLO = 0;
174 }
176 /* Setup device MAC address */
177 ptr_EMACRegs->MACINDEX = 0x0;
179 /* Configure the MAC Address into the EMAC Controller. */
180 tmpval = 0;
181 for( index=3; index>=0; index-- )
182 tmpval = (tmpval<<8) | *(ptr_device->mac_address+index);
183 ptr_EMACRegs->MACADDRHI = tmpval;
184 tmpval = *(ptr_device->mac_address+5);
185 ptr_EMACRegs->MACADDRLO = CPMAC_MACADDRLO_VALID | CPMAC_MACADDRLO_MATCHFILT |
186 (tmpval<<8) | *(ptr_device->mac_address+4);
188 /* For us buffer offset will always be zero */
189 ptr_EMACRegs->RXBUFFEROFFSET = 0;
191 /* Reset RX (M)ulticast (B)roadcast (P)romiscuous Enable register */
192 ptr_EMACRegs->RXMBPENABLE = 0;
193 ptr_EMACRegs->MACHASH1 = 0;
194 ptr_EMACRegs->MACHASH2 = 0;
196 /* Clear Unicast RX on channel 0-7 */
197 ptr_EMACRegs->RXUNICASTCLEAR = 0xFF;
199 /* Make sure there are none of the interrupts are enabled. */
200 ptr_EMACRegs->RXINTMASKCLEAR = 0xFF;
201 ptr_EMACRegs->TXINTMASKCLEAR = 0xFF;
202 ptr_EMACRegs->MACINTMASKCLEAR = 0x0;
204 /* Setup the receive buffer descriptors. */
205 pDesc = (EMAC_Desc *)_EMAC_DSC_BASE_ADDR;
207 /* Initialize the receive buffer descriptor. */
208 pDesc->pNext = 0;
209 pDesc->pBuffer = &emacMCB.rx_buffer[0];
210 pDesc->BufOffLen = NET_MAX_MTU;
211 pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
213 /* Store this buffer descriptor in the global EMAC MCB */
214 emacMCB.rx_bd = pDesc;
216 /* Get the transmit buffer descriptor; it comes right after the receive BD. */
217 pDesc = pDesc + 1;
219 /* Initialize the transmit buffer descriptor. */
220 pDesc->pNext = 0;
221 pDesc->pBuffer = 0;
222 pDesc->BufOffLen = 0;
223 pDesc->PktFlgLen = 0;
225 /* Store this buffer descriptor in the global EMAC MCB */
226 emacMCB.tx_bd = pDesc;
228 #ifdef EMAC_CACHE_SUPPORT
229 /* Writeback the EMAC MCB Information to the PHYSICAL Memory.
230 * This is required because the buffer in the cache will always be
231 * invalidated on the RECEIVE; if the buffer is not aligned on the
232 * CACHE Line then it will result in the RX & TX BD in the structure
233 * to also get invalidated to what resides in the PHYSICAL memory.
234 * But if we have written back the structure here then the PHYSICAL
235 * and CACHE are one and the same as far as the BD's are concerned. */
236 Cache_wbL2((void *)&emacMCB, sizeof(emacMCB));
237 #endif
239 /* Enable the receive and transmit. */
240 ptr_EMACRegs->TXCONTROL = 0x1;
241 ptr_EMACRegs->RXCONTROL = 0x1;
243 /* Initialize the MAC Control: We set the Receive Ownership Bit and the Receive
244 * Offset Length Word and enable the MII. */
245 ptr_EMACRegs->MACCONTROL = CPMAC_MACCONTROL_RXOWNERSHIP |
246 CPMAC_MACCONTROL_RXOFFLENBLOCK |
247 CPMAC_MACCONTROL_MIIEN;
249 /* Startup RX */
250 ptr_EMACRegs->RX0HDP = (Uint32)emacMCB.rx_bd;
252 /* Enable receive filters for channel 1 and all broadcast packets. */
253 ptr_EMACRegs->RXUNICASTSET = 1;
254 ptr_EMACRegs->RXMBPENABLE = CPMAC_RXMBPENABLE_RXBROADEN;
256 /* Initialize the Device MDIO layer: The function returns only when
257 * the LINK is UP and RUNNING. */
258 if (dev_mdio_open () < 0)
259 return -1;
261 /* Debug Message: */
262 mprintf ("DEBUG: Ethernet Link is UP \n");
264 /* Hardware is up and running. */
265 return 0;
266 }
268 /**
269 * @b Description
270 * @n
271 * This is the Network Send API which is registered with the NET boot module
272 * to send out packets.
273 *
274 * @param[in] ptr_device
275 * Pointer to the network interface descriptor object.
276 * @param[in] buffer
277 * Pointer to the packet which is to be transmitted.
278 * @param[in] num_bytes
279 * Length of the packet which is transmitted.
280 *
281 * @retval
282 * Success - Number of bytes transmitted.
283 * @retval
284 * Error - <0
285 */
286 Int32 cpmac_drv_send (NET_DRV_DEVICE* ptr_device, Uint8* buffer, int num_bytes)
287 {
288 volatile EMAC_Desc* pDesc;
290 /* Ensure the minimum ethernet size is sent out. */
291 if (num_bytes < 64)
292 num_bytes = 64;
294 #ifdef EMAC_CACHE_SUPPORT
295 /* Clean the cache for external addesses */
296 Cache_wbL2((void *)buffer, num_bytes);
297 #endif
299 /* Get the pointer to the transmit buffer descriptor. */
300 pDesc = emacMCB.tx_bd;
302 /* Fill out the transmit buffer descriptor */
303 pDesc->pNext = 0;
304 pDesc->pBuffer = buffer;
305 pDesc->BufOffLen = num_bytes;
306 pDesc->PktFlgLen = EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_EOP | num_bytes | EMAC_DSC_FLAG_OWNER;
308 /* Send the packet out. */
309 ptr_EMACRegs->TX0HDP = (Uint32)pDesc;
311 /* Loop around till the transmission is complete. */
312 pDesc = (EMAC_Desc *)ptr_EMACRegs->TX0CP;
313 while (pDesc->PktFlgLen & EMAC_DSC_FLAG_OWNER);
315 /* The packet has been successfully transmitted. */
316 return num_bytes;
317 }
319 /**
320 * @b Description
321 * @n
322 * This is the Network Receive API which is registered with the NET boot module
323 * to receive packets.
324 *
325 * @param[in] ptr_device
326 * Pointer to the network interface descriptor object.
327 * @param[out] buffer
328 * Pointer to the packet which is populated with the received data
329 *
330 * @retval
331 * Success - Number of bytes received.
332 * @retval
333 * Error - <0
334 */
335 Int32 cpmac_drv_receive (NET_DRV_DEVICE* ptr_device, Uint8* buffer)
336 {
337 Int32 bytes_received = 0;
338 EMAC_Desc* pDesc;
340 /* Initialize the number of bytes received. */
341 bytes_received = 0;
343 /* Read the completion register. We know for sure if the SOP flag is set then
344 * a packet has been received and needs to be picked up from the controller. */
345 pDesc = (EMAC_Desc *)ptr_EMACRegs->RX0CP;
346 if (pDesc->PktFlgLen & EMAC_DSC_FLAG_SOP)
347 {
348 /* Acknowledge that the descriptor has been processed. */
349 ptr_EMACRegs->RX0CP = (Uint32)pDesc;
351 #ifdef EMAC_CACHE_SUPPORT
352 /* External Memory Support: Invalidate the cache. */
353 Cache_invL2((void *)(pDesc->pBuffer), NET_MAX_MTU);
354 #endif
355 /* Remember the number of bytes received. */
356 bytes_received = (pDesc->PktFlgLen & 0xFFFF);
358 /* The descriptor is now free to receive more data. Set the status accordingly. */
359 pDesc->BufOffLen = NET_MAX_MTU;
360 pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
362 /* Copy the data from the descriptor buffer to the supplied buffer. */
363 memcpy((void *)buffer, (void *)pDesc->pBuffer, bytes_received);
365 /* Put this descriptor back to the HDP. */
366 ptr_EMACRegs->RX0HDP = (Uint32)pDesc;
367 }
369 /* Return the number of bytes received. */
370 return bytes_received;
371 }
373 /**
374 * @b Description
375 * @n
376 * This is the Network Close API which is registered with the NET boot module
377 * to close and shutdown the Ethernet controller.
378 *
379 * @param[in] ptr_device
380 * Pointer to the network interface descriptor object.
381 *
382 * @retval
383 * Success - 0
384 * @retval
385 * Error - <0
386 */
387 Int32 cpmac_drv_stop (NET_DRV_DEVICE* ptr_device)
388 {
389 return 0;
390 }