1 /******************************************************************************
2 * Copyright (C) 2009 - 2020 Xilinx, Inc. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 ******************************************************************************/
5
6 /*****************************************************************************/
7 /**
8 *
9 * @file xemacps_control.c
10 * @addtogroup emacps_v3_11
11 * @{
12 *
13 * Functions in this file implement general purpose command and control related
14 * functionality. See xemacps.h for a detailed description of the driver.
15 *
16 * <pre>
17 * MODIFICATION HISTORY:
18 *
19 * Ver Who Date Changes
20 * ----- ---- -------- -------------------------------------------------------
21 * 1.00a wsy 01/10/10 First release
22 * 1.02a asa 11/05/12 Added a new API for deleting an entry from the HASH
23 * register. Added a new API for setting the BURST length
24 * in DMACR register.
25 * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp architecture.
26 * 3.0 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
27 * 3.0 hk 02/20/15 Added support for jumbo frames.
28 * 3.2 hk 02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
29 * </pre>
30 *****************************************************************************/
31
32 /***************************** Include Files *********************************/
33
34 #include "xemacps.h"
35
36 /************************** Constant Definitions *****************************/
37
38
39 /**************************** Type Definitions *******************************/
40
41
42 /***************** Macros (Inline Functions) Definitions *********************/
43
44
45 /************************** Function Prototypes ******************************/
46
47
48 /************************** Variable Definitions *****************************/
49
50
51 /*****************************************************************************/
52 /**
53 * Set the MAC address for this driver/device. The address is a 48-bit value.
54 * The device must be stopped before calling this function.
55 *
56 * @param InstancePtr is a pointer to the instance to be worked on.
57 * @param AddressPtr is a pointer to a 6-byte MAC address.
58 * @param Index is a index to which MAC (1-4) address.
59 *
60 * @return
61 * - XST_SUCCESS if the MAC address was set successfully
62 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
63 *
64 *****************************************************************************/
XEmacPs_SetMacAddress(XEmacPs * InstancePtr,void * AddressPtr,u8 Index)65 LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
66 {
67 u32 MacAddr;
68 u8 *Aptr = (u8 *)(void *)AddressPtr;
69 u8 IndexLoc = Index;
70 LONG Status;
71 Xil_AssertNonvoid(InstancePtr != NULL);
72 Xil_AssertNonvoid(Aptr != NULL);
73 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
74 Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
75
76 /* Be sure device has been stopped */
77 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
78 Status = (LONG)(XST_DEVICE_IS_STARTED);
79 }
80 else{
81 /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
82 IndexLoc--;
83
84 /* Set the MAC bits [31:0] in BOT */
85 MacAddr = *(Aptr);
86 MacAddr |= ((u32)(*(Aptr+1)) << 8U);
87 MacAddr |= ((u32)(*(Aptr+2)) << 16U);
88 MacAddr |= ((u32)(*(Aptr+3)) << 24U);
89 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
90 ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
91
92 /* There are reserved bits in TOP so don't affect them */
93 MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
94 ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
95
96 MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK);
97
98 /* Set MAC bits [47:32] in TOP */
99 MacAddr |= (u32)(*(Aptr+4));
100 MacAddr |= (u32)(*(Aptr+5)) << 8U;
101
102 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
103 ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
104
105 Status = (LONG)(XST_SUCCESS);
106 }
107 return Status;
108 }
109
110
111 /*****************************************************************************/
112 /**
113 * Get the MAC address for this driver/device.
114 *
115 * @param InstancePtr is a pointer to the instance to be worked on.
116 * @param AddressPtr is an output parameter, and is a pointer to a buffer into
117 * which the current MAC address will be copied.
118 * @param Index is a index to which MAC (1-4) address.
119 *
120 *****************************************************************************/
XEmacPs_GetMacAddress(XEmacPs * InstancePtr,void * AddressPtr,u8 Index)121 void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
122 {
123 u32 MacAddr;
124 u8 *Aptr = (u8 *)(void *)AddressPtr;
125 u8 IndexLoc = Index;
126 Xil_AssertVoid(InstancePtr != NULL);
127 Xil_AssertVoid(Aptr != NULL);
128 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
129 Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
130
131 /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
132 IndexLoc--;
133
134 MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
135 ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)));
136 *Aptr = (u8) MacAddr;
137 *(Aptr+1) = (u8) (MacAddr >> 8U);
138 *(Aptr+2) = (u8) (MacAddr >> 16U);
139 *(Aptr+3) = (u8) (MacAddr >> 24U);
140
141 /* Read MAC bits [47:32] in TOP */
142 MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
143 ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
144 *(Aptr+4) = (u8) MacAddr;
145 *(Aptr+5) = (u8) (MacAddr >> 8U);
146 }
147
148
149 /*****************************************************************************/
150 /**
151 * Set 48-bit MAC addresses in hash table.
152 * The device must be stopped before calling this function.
153 *
154 * The hash address register is 64 bits long and takes up two locations in
155 * the memory map. The least significant bits are stored in hash register
156 * bottom and the most significant bits in hash register top.
157 *
158 * The unicast hash enable and the multicast hash enable bits in the network
159 * configuration register enable the reception of hash matched frames. The
160 * destination address is reduced to a 6 bit index into the 64 bit hash
161 * register using the following hash function. The hash function is an XOR
162 * of every sixth bit of the destination address.
163 *
164 * <pre>
165 * hash_index[05] = da[05]^da[11]^da[17]^da[23]^da[29]^da[35]^da[41]^da[47]
166 * hash_index[04] = da[04]^da[10]^da[16]^da[22]^da[28]^da[34]^da[40]^da[46]
167 * hash_index[03] = da[03]^da[09]^da[15]^da[21]^da[27]^da[33]^da[39]^da[45]
168 * hash_index[02] = da[02]^da[08]^da[14]^da[20]^da[26]^da[32]^da[38]^da[44]
169 * hash_index[01] = da[01]^da[07]^da[13]^da[19]^da[25]^da[31]^da[37]^da[43]
170 * hash_index[00] = da[00]^da[06]^da[12]^da[18]^da[24]^da[30]^da[36]^da[42]
171 * </pre>
172 *
173 * da[0] represents the least significant bit of the first byte received,
174 * that is, the multicast/unicast indicator, and da[47] represents the most
175 * significant bit of the last byte received.
176 *
177 * If the hash index points to a bit that is set in the hash register then
178 * the frame will be matched according to whether the frame is multicast
179 * or unicast.
180 *
181 * A multicast match will be signaled if the multicast hash enable bit is
182 * set, da[0] is logic 1 and the hash index points to a bit set in the hash
183 * register.
184 *
185 * A unicast match will be signaled if the unicast hash enable bit is set,
186 * da[0] is logic 0 and the hash index points to a bit set in the hash
187 * register.
188 *
189 * To receive all multicast frames, the hash register should be set with
190 * all ones and the multicast hash enable bit should be set in the network
191 * configuration register.
192 *
193 *
194 * @param InstancePtr is a pointer to the instance to be worked on.
195 * @param AddressPtr is a pointer to a 6-byte MAC address.
196 *
197 * @return
198 * - XST_SUCCESS if the HASH MAC address was set successfully
199 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
200 * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
201 * requirement after calculation
202 *
203 * @note
204 * Having Aptr be unsigned type prevents the following operations from sign
205 * extending.
206 *****************************************************************************/
XEmacPs_SetHash(XEmacPs * InstancePtr,void * AddressPtr)207 LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr)
208 {
209 u32 HashAddr;
210 u8 *Aptr = (u8 *)(void *)AddressPtr;
211 u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
212 u32 Result;
213 LONG Status;
214
215 Xil_AssertNonvoid(InstancePtr != NULL);
216 Xil_AssertNonvoid(AddressPtr != NULL);
217 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
218
219 /* Be sure device has been stopped */
220 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
221 Status = (LONG)(XST_DEVICE_IS_STARTED);
222 } else {
223 Temp1 = (*(Aptr+0)) & 0x3FU;
224 Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
225
226 Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U);
227 Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
228 Temp5 = (*(Aptr+3)) & 0x3FU;
229 Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
230 Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
231 Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
232
233 Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
234 (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
235
236 if (Result >= (u32)XEMACPS_MAX_HASH_BITS) {
237 Status = (LONG)(XST_INVALID_PARAM);
238 } else {
239
240 if (Result < (u32)32) {
241 HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
242 XEMACPS_HASHL_OFFSET);
243 HashAddr |= (u32)(0x00000001U << Result);
244 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
245 XEMACPS_HASHL_OFFSET, HashAddr);
246 } else {
247 HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
248 XEMACPS_HASHH_OFFSET);
249 HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32));
250 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
251 XEMACPS_HASHH_OFFSET, HashAddr);
252 }
253 Status = (LONG)(XST_SUCCESS);
254 }
255 }
256 return Status;
257 }
258
259 /*****************************************************************************/
260 /**
261 * Delete 48-bit MAC addresses in hash table.
262 * The device must be stopped before calling this function.
263 *
264 * @param InstancePtr is a pointer to the instance to be worked on.
265 * @param AddressPtr is a pointer to a 6-byte MAC address.
266 *
267 * @return
268 * - XST_SUCCESS if the HASH MAC address was deleted successfully
269 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
270 * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
271 * requirement after calculation
272 *
273 * @note
274 * Having Aptr be unsigned type prevents the following operations from sign
275 * extending.
276 *****************************************************************************/
XEmacPs_DeleteHash(XEmacPs * InstancePtr,void * AddressPtr)277 LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr)
278 {
279 u32 HashAddr;
280 u8 *Aptr = (u8 *)(void *)AddressPtr;
281 u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
282 u32 Result;
283 LONG Status;
284
285 Xil_AssertNonvoid(InstancePtr != NULL);
286 Xil_AssertNonvoid(Aptr != NULL);
287 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
288
289 /* Be sure device has been stopped */
290 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
291 Status = (LONG)(XST_DEVICE_IS_STARTED);
292 } else {
293 Temp1 = (*(Aptr+0)) & 0x3FU;
294 Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
295 Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U);
296 Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
297 Temp5 = (*(Aptr+3)) & 0x3FU;
298 Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
299 Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
300 Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
301
302 Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
303 (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
304
305 if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) {
306 Status = (LONG)(XST_INVALID_PARAM);
307 } else {
308 if (Result < (u32)32) {
309 HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
310 XEMACPS_HASHL_OFFSET);
311 HashAddr &= (u32)(~(0x00000001U << Result));
312 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
313 XEMACPS_HASHL_OFFSET, HashAddr);
314 } else {
315 HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
316 XEMACPS_HASHH_OFFSET);
317 HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32)));
318 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
319 XEMACPS_HASHH_OFFSET, HashAddr);
320 }
321 Status = (LONG)(XST_SUCCESS);
322 }
323 }
324 return Status;
325 }
326 /*****************************************************************************/
327 /**
328 * Clear the Hash registers for the mac address pointed by AddressPtr.
329 *
330 * @param InstancePtr is a pointer to the instance to be worked on.
331 *
332 *****************************************************************************/
XEmacPs_ClearHash(XEmacPs * InstancePtr)333 void XEmacPs_ClearHash(XEmacPs *InstancePtr)
334 {
335 Xil_AssertVoid(InstancePtr != NULL);
336 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
337
338 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
339 XEMACPS_HASHL_OFFSET, 0x0U);
340
341 /* write bits [63:32] in TOP */
342 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
343 XEMACPS_HASHH_OFFSET, 0x0U);
344 }
345
346
347 /*****************************************************************************/
348 /**
349 * Get the Hash address for this driver/device.
350 *
351 * @param InstancePtr is a pointer to the instance to be worked on.
352 * @param AddressPtr is an output parameter, and is a pointer to a buffer into
353 * which the current HASH MAC address will be copied.
354 *
355 *****************************************************************************/
XEmacPs_GetHash(XEmacPs * InstancePtr,void * AddressPtr)356 void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr)
357 {
358 u32 *Aptr = (u32 *)(void *)AddressPtr;
359
360 Xil_AssertVoid(InstancePtr != NULL);
361 Xil_AssertVoid(AddressPtr != NULL);
362 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
363
364 *(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
365 XEMACPS_HASHL_OFFSET);
366
367 /* Read Hash bits [63:32] in TOP */
368 *(Aptr+1) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
369 XEMACPS_HASHH_OFFSET);
370 }
371
372
373 /*****************************************************************************/
374 /**
375 * Set the Type ID match for this driver/device. The register is a 32-bit
376 * value. The device must be stopped before calling this function.
377 *
378 * @param InstancePtr is a pointer to the instance to be worked on.
379 * @param Id_Check is type ID to be configured.
380 * @param Index is a index to which Type ID (1-4).
381 *
382 * @return
383 * - XST_SUCCESS if the MAC address was set successfully
384 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
385 *
386 *****************************************************************************/
XEmacPs_SetTypeIdCheck(XEmacPs * InstancePtr,u32 Id_Check,u8 Index)387 LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index)
388 {
389 u8 IndexLoc = Index;
390 LONG Status;
391 Xil_AssertNonvoid(InstancePtr != NULL);
392 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
393 Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U));
394
395 /* Be sure device has been stopped */
396 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
397 Status = (LONG)(XST_DEVICE_IS_STARTED);
398 } else {
399
400 /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
401 IndexLoc--;
402
403 /* Set the ID bits in MATCHx register */
404 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
405 ((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check);
406
407 Status = (LONG)(XST_SUCCESS);
408 }
409 return Status;
410 }
411
412 /*****************************************************************************/
413 /**
414 * Set options for the driver/device. The driver should be stopped with
415 * XEmacPs_Stop() before changing options.
416 *
417 * @param InstancePtr is a pointer to the instance to be worked on.
418 * @param Options are the options to set. Multiple options can be set by OR'ing
419 * XTE_*_OPTIONS constants together. Options not specified are not
420 * affected.
421 *
422 * @return
423 * - XST_SUCCESS if the options were set successfully
424 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
425 *
426 * @note
427 * See xemacps.h for a description of the available options.
428 *
429 *****************************************************************************/
XEmacPs_SetOptions(XEmacPs * InstancePtr,u32 Options)430 LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options)
431 {
432 u32 Reg; /* Generic register contents */
433 u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */
434 u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */
435 LONG Status;
436 Xil_AssertNonvoid(InstancePtr != NULL);
437 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
438
439 /* Be sure device has been stopped */
440 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
441 Status = (LONG)(XST_DEVICE_IS_STARTED);
442 } else {
443
444 /* Many of these options will change the NET_CONFIG registers.
445 * To reduce the amount of IO to the device, group these options here
446 * and change them all at once.
447 */
448
449 /* Grab current register contents */
450 RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
451 XEMACPS_NWCFG_OFFSET);
452 RegNewNetCfg = RegNetCfg;
453
454 /*
455 * It is configured to max 1536.
456 */
457 if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
458 RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK);
459 }
460
461 /* Turn on VLAN packet only, only VLAN tagged will be accepted */
462 if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
463 RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK;
464 }
465
466 /* Turn on FCS stripping on receive packets */
467 if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
468 RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK;
469 }
470
471 /* Turn on length/type field checking on receive packets */
472 if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
473 RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK;
474 }
475
476 /* Turn on flow control */
477 if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
478 RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK;
479 }
480
481 /* Turn on promiscuous frame filtering (all frames are received) */
482 if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
483 RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK;
484 }
485
486 /* Allow broadcast address reception */
487 if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
488 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK);
489 }
490
491 /* Allow multicast address filtering */
492 if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
493 RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK;
494 }
495
496 /* enable RX checksum offload */
497 if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
498 RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
499 }
500
501 /* Enable jumbo frames */
502 if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) &&
503 (InstancePtr->Version > 2)) {
504 RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK;
505 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
506 XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO);
507 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
508 XEMACPS_DMACR_OFFSET);
509 Reg &= ~XEMACPS_DMACR_RXBUF_MASK;
510 Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) +
511 (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO %
512 (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
513 (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
514 (u32)(XEMACPS_DMACR_RXBUF_MASK));
515 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
516 XEMACPS_DMACR_OFFSET, Reg);
517 InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO;
518 InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO +
519 XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE;
520 InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
521 XEMACPS_HDR_VLAN_SIZE;
522 InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK;
523 }
524
525 if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) &&
526 (InstancePtr->Version > 2)) {
527 RegNewNetCfg |= (XEMACPS_NWCFG_SGMIIEN_MASK |
528 XEMACPS_NWCFG_PCSSEL_MASK);
529 }
530
531 /* Officially change the NET_CONFIG registers if it needs to be
532 * modified.
533 */
534 if (RegNetCfg != RegNewNetCfg) {
535 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
536 XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
537 }
538
539 /* Enable TX checksum offload */
540 if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
541 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
542 XEMACPS_DMACR_OFFSET);
543 Reg |= XEMACPS_DMACR_TCPCKSUM_MASK;
544 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
545 XEMACPS_DMACR_OFFSET, Reg);
546 }
547
548 /* Enable transmitter */
549 if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
550 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
551 XEMACPS_NWCTRL_OFFSET);
552 Reg |= XEMACPS_NWCTRL_TXEN_MASK;
553 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
554 XEMACPS_NWCTRL_OFFSET, Reg);
555 }
556
557 /* Enable receiver */
558 if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
559 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
560 XEMACPS_NWCTRL_OFFSET);
561 Reg |= XEMACPS_NWCTRL_RXEN_MASK;
562 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
563 XEMACPS_NWCTRL_OFFSET, Reg);
564 }
565
566 /* The remaining options not handled here are managed elsewhere in the
567 * driver. No register modifications are needed at this time. Reflecting
568 * the option in InstancePtr->Options is good enough for now.
569 */
570
571 /* Set options word to its new value */
572 InstancePtr->Options |= Options;
573
574 Status = (LONG)(XST_SUCCESS);
575 }
576 return Status;
577 }
578
579
580 /*****************************************************************************/
581 /**
582 * Clear options for the driver/device
583 *
584 * @param InstancePtr is a pointer to the instance to be worked on.
585 * @param Options are the options to clear. Multiple options can be cleared by
586 * OR'ing XEMACPS_*_OPTIONS constants together. Options not specified
587 * are not affected.
588 *
589 * @return
590 * - XST_SUCCESS if the options were set successfully
591 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
592 *
593 * @note
594 * See xemacps.h for a description of the available options.
595 *
596 *****************************************************************************/
XEmacPs_ClearOptions(XEmacPs * InstancePtr,u32 Options)597 LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options)
598 {
599 u32 Reg; /* Generic */
600 u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */
601 u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */
602 LONG Status;
603 Xil_AssertNonvoid(InstancePtr != NULL);
604 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
605
606 /* Be sure device has been stopped */
607 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
608 Status = (LONG)(XST_DEVICE_IS_STARTED);
609 } else {
610
611 /* Many of these options will change the NET_CONFIG registers.
612 * To reduce the amount of IO to the device, group these options here
613 * and change them all at once.
614 */
615
616 /* Grab current register contents */
617 RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
618 XEMACPS_NWCFG_OFFSET);
619 RegNewNetCfg = RegNetCfg;
620
621 /* There is only RX configuration!?
622 * It is configured in two different length, up to 1536 and 10240 bytes
623 */
624 if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
625 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK);
626 }
627
628 /* Turn off VLAN packet only */
629 if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
630 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK);
631 }
632
633 /* Turn off FCS stripping on receive packets */
634 if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
635 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK);
636 }
637
638 /* Turn off length/type field checking on receive packets */
639 if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
640 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK);
641 }
642
643 /* Turn off flow control */
644 if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
645 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK);
646 }
647
648 /* Turn off promiscuous frame filtering (all frames are received) */
649 if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
650 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK);
651 }
652
653 /* Disallow broadcast address filtering => broadcast reception */
654 if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
655 RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK;
656 }
657
658 /* Disallow multicast address filtering */
659 if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
660 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK);
661 }
662
663 /* Disable RX checksum offload */
664 if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
665 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK);
666 }
667
668 /* Disable jumbo frames */
669 if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) &&
670 (InstancePtr->Version > 2)) {
671 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK);
672 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
673 XEMACPS_DMACR_OFFSET);
674 Reg &= ~XEMACPS_DMACR_RXBUF_MASK;
675 Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) +
676 (((((u32)XEMACPS_RX_BUF_SIZE %
677 (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
678 (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
679 (u32)(XEMACPS_DMACR_RXBUF_MASK));
680 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
681 XEMACPS_DMACR_OFFSET, Reg);
682 InstancePtr->MaxMtuSize = XEMACPS_MTU;
683 InstancePtr->MaxFrameSize = XEMACPS_MTU +
684 XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE;
685 InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
686 XEMACPS_HDR_VLAN_SIZE;
687 InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
688 }
689
690 if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) &&
691 (InstancePtr->Version > 2)) {
692 RegNewNetCfg &= (u32)(~(XEMACPS_NWCFG_SGMIIEN_MASK |
693 XEMACPS_NWCFG_PCSSEL_MASK));
694 }
695
696 /* Officially change the NET_CONFIG registers if it needs to be
697 * modified.
698 */
699 if (RegNetCfg != RegNewNetCfg) {
700 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
701 XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
702 }
703
704 /* Disable TX checksum offload */
705 if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
706 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
707 XEMACPS_DMACR_OFFSET);
708 Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK);
709 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
710 XEMACPS_DMACR_OFFSET, Reg);
711 }
712
713 /* Disable transmitter */
714 if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
715 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
716 XEMACPS_NWCTRL_OFFSET);
717 Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
718 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
719 XEMACPS_NWCTRL_OFFSET, Reg);
720 }
721
722 /* Disable receiver */
723 if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
724 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
725 XEMACPS_NWCTRL_OFFSET);
726 Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
727 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
728 XEMACPS_NWCTRL_OFFSET, Reg);
729 }
730
731 /* The remaining options not handled here are managed elsewhere in the
732 * driver. No register modifications are needed at this time. Reflecting
733 * option in InstancePtr->Options is good enough for now.
734 */
735
736 /* Set options word to its new value */
737 InstancePtr->Options &= ~Options;
738
739 Status = (LONG)(XST_SUCCESS);
740 }
741 return Status;
742 }
743
744
745 /*****************************************************************************/
746 /**
747 * Get current option settings
748 *
749 * @param InstancePtr is a pointer to the instance to be worked on.
750 *
751 * @return
752 * A bitmask of XTE_*_OPTION constants. Any bit set to 1 is to be interpreted
753 * as a set option.
754 *
755 * @note
756 * See xemacps.h for a description of the available options.
757 *
758 *****************************************************************************/
XEmacPs_GetOptions(XEmacPs * InstancePtr)759 u32 XEmacPs_GetOptions(XEmacPs *InstancePtr)
760 {
761 Xil_AssertNonvoid(InstancePtr != NULL);
762 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
763
764 return (InstancePtr->Options);
765 }
766
767
768 /*****************************************************************************/
769 /**
770 * Send a pause packet
771 *
772 * @param InstancePtr is a pointer to the instance to be worked on.
773 *
774 * @return
775 * - XST_SUCCESS if pause frame transmission was initiated
776 * - XST_DEVICE_IS_STOPPED if the device has not been started.
777 *
778 *****************************************************************************/
XEmacPs_SendPausePacket(XEmacPs * InstancePtr)779 LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr)
780 {
781 u32 Reg;
782 LONG Status;
783
784 Xil_AssertNonvoid(InstancePtr != NULL);
785 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
786
787 /* Make sure device is ready for this operation */
788 if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) {
789 Status = (LONG)(XST_DEVICE_IS_STOPPED);
790 } else {
791 /* Send flow control frame */
792 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
793 XEMACPS_NWCTRL_OFFSET);
794 Reg |= XEMACPS_NWCTRL_PAUSETX_MASK;
795 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
796 XEMACPS_NWCTRL_OFFSET, Reg);
797 Status = (LONG)(XST_SUCCESS);
798 }
799 return Status;
800 }
801
802 /*****************************************************************************/
803 /**
804 * XEmacPs_GetOperatingSpeed gets the current operating link speed. This may
805 * be the value set by XEmacPs_SetOperatingSpeed() or a hardware default.
806 *
807 * @param InstancePtr references the TEMAC channel on which to operate.
808 *
809 * @return XEmacPs_GetOperatingSpeed returns the link speed in units of
810 * megabits per second.
811 *
812 * @note
813 *
814 *****************************************************************************/
XEmacPs_GetOperatingSpeed(XEmacPs * InstancePtr)815 u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr)
816 {
817 u32 Reg;
818 u16 Status;
819
820 Xil_AssertNonvoid(InstancePtr != NULL);
821 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
822
823 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
824 XEMACPS_NWCFG_OFFSET);
825
826 if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) {
827 Status = (u16)(1000);
828 } else {
829 if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) {
830 Status = (u16)(100);
831 } else {
832 Status = (u16)(10);
833 }
834 }
835 return Status;
836 }
837
838
839 /*****************************************************************************/
840 /**
841 * XEmacPs_SetOperatingSpeed sets the current operating link speed. For any
842 * traffic to be passed, this speed must match the current MII/GMII/SGMII/RGMII
843 * link speed.
844 *
845 * @param InstancePtr references the TEMAC channel on which to operate.
846 * @param Speed is the speed to set in units of Mbps. Valid values are 10, 100,
847 * or 1000. XEmacPs_SetOperatingSpeed ignores invalid values.
848 *
849 * @note
850 *
851 *****************************************************************************/
XEmacPs_SetOperatingSpeed(XEmacPs * InstancePtr,u16 Speed)852 void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed)
853 {
854 u32 Reg;
855 Xil_AssertVoid(InstancePtr != NULL);
856 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
857 Xil_AssertVoid((Speed == (u16)10) || (Speed == (u16)100) || (Speed == (u16)1000));
858
859 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
860 XEMACPS_NWCFG_OFFSET);
861 Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK));
862
863 switch (Speed) {
864 case (u16)10:
865 break;
866
867 case (u16)100:
868 Reg |= XEMACPS_NWCFG_100_MASK;
869 break;
870
871 case (u16)1000:
872 Reg |= XEMACPS_NWCFG_1000_MASK;
873 break;
874 }
875
876 /* Set register and return */
877 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
878 XEMACPS_NWCFG_OFFSET, Reg);
879 }
880
881
882 /*****************************************************************************/
883 /**
884 * Set the MDIO clock divisor.
885 *
886 * Calculating the divisor:
887 *
888 * <pre>
889 * f[HOSTCLK]
890 * f[MDC] = -----------------
891 * (1 + Divisor) * 2
892 * </pre>
893 *
894 * where f[HOSTCLK] is the bus clock frequency in MHz, and f[MDC] is the
895 * MDIO clock frequency in MHz to the PHY. Typically, f[MDC] should not
896 * exceed 2.5 MHz. Some PHYs can tolerate faster speeds which means faster
897 * access. Here is the table to show values to generate MDC,
898 *
899 * <pre>
900 * 000 : divide pclk by 8 (pclk up to 20 MHz)
901 * 001 : divide pclk by 16 (pclk up to 40 MHz)
902 * 010 : divide pclk by 32 (pclk up to 80 MHz)
903 * 011 : divide pclk by 48 (pclk up to 120 MHz)
904 * 100 : divide pclk by 64 (pclk up to 160 MHz)
905 * 101 : divide pclk by 96 (pclk up to 240 MHz)
906 * 110 : divide pclk by 128 (pclk up to 320 MHz)
907 * 111 : divide pclk by 224 (pclk up to 540 MHz)
908 * </pre>
909 *
910 * @param InstancePtr is a pointer to the instance to be worked on.
911 * @param Divisor is the divisor to set. Range is 0b000 to 0b111.
912 *
913 *****************************************************************************/
XEmacPs_SetMdioDivisor(XEmacPs * InstancePtr,XEmacPs_MdcDiv Divisor)914 void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor)
915 {
916 u32 Reg;
917 Xil_AssertVoid(InstancePtr != NULL);
918 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
919 Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */
920
921 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
922 XEMACPS_NWCFG_OFFSET);
923 /* clear these three bits, could be done with mask */
924 Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK);
925
926 Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK);
927
928 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
929 XEMACPS_NWCFG_OFFSET, Reg);
930 }
931
932
933 /*****************************************************************************/
934 /**
935 * Read the current value of the PHY register indicated by the PhyAddress and
936 * the RegisterNum parameters. The MAC provides the driver with the ability to
937 * talk to a PHY that adheres to the Media Independent Interface (MII) as
938 * defined in the IEEE 802.3 standard.
939 *
940 * Prior to PHY access with this function, the user should have setup the MDIO
941 * clock with XEmacPs_SetMdioDivisor().
942 *
943 * @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
944 * @param PhyAddress is the address of the PHY to be read (supports multiple
945 * PHYs)
946 * @param RegisterNum is the register number, 0-31, of the specific PHY register
947 * to read
948 * @param PhyDataPtr is an output parameter, and points to a 16-bit buffer into
949 * which the current value of the register will be copied.
950 *
951 * @return
952 *
953 * - XST_SUCCESS if the PHY was read from successfully
954 * - XST_EMAC_MII_BUSY if there is another PHY operation in progress
955 *
956 * @note
957 *
958 * This function is not thread-safe. The user must provide mutually exclusive
959 * access to this function if there are to be multiple threads that can call it.
960 *
961 * There is the possibility that this function will not return if the hardware
962 * is broken (i.e., it never sets the status bit indicating that the read is
963 * done). If this is of concern to the user, the user should provide a mechanism
964 * suitable to their needs for recovery.
965 *
966 * For the duration of this function, all host interface reads and writes are
967 * blocked to the current XEmacPs instance.
968 *
969 ******************************************************************************/
XEmacPs_PhyRead(XEmacPs * InstancePtr,u32 PhyAddress,u32 RegisterNum,u16 * PhyDataPtr)970 LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress,
971 u32 RegisterNum, u16 *PhyDataPtr)
972 {
973 u32 Mgtcr;
974 volatile u32 Ipisr;
975 u32 IpReadTemp;
976 LONG Status;
977
978 Xil_AssertNonvoid(InstancePtr != NULL);
979
980 /* Make sure no other PHY operation is currently in progress */
981 if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
982 XEMACPS_NWSR_OFFSET) &
983 XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
984 Status = (LONG)(XST_EMAC_MII_BUSY);
985 } else {
986
987 /* Construct Mgtcr mask for the operation */
988 Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK |
989 (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
990 (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK);
991
992 /* Write Mgtcr and wait for completion */
993 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
994 XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
995
996 do {
997 Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
998 XEMACPS_NWSR_OFFSET);
999 IpReadTemp = Ipisr;
1000 } while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
1001
1002 /* Read data */
1003 *PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1004 XEMACPS_PHYMNTNC_OFFSET);
1005 Status = (LONG)(XST_SUCCESS);
1006 }
1007 return Status;
1008 }
1009
1010
1011 /*****************************************************************************/
1012 /**
1013 * Write data to the specified PHY register. The Ethernet driver does not
1014 * require the device to be stopped before writing to the PHY. Although it is
1015 * probably a good idea to stop the device, it is the responsibility of the
1016 * application to deem this necessary. The MAC provides the driver with the
1017 * ability to talk to a PHY that adheres to the Media Independent Interface
1018 * (MII) as defined in the IEEE 802.3 standard.
1019 *
1020 * Prior to PHY access with this function, the user should have setup the MDIO
1021 * clock with XEmacPs_SetMdioDivisor().
1022 *
1023 * @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
1024 * @param PhyAddress is the address of the PHY to be written (supports multiple
1025 * PHYs)
1026 * @param RegisterNum is the register number, 0-31, of the specific PHY register
1027 * to write
1028 * @param PhyData is the 16-bit value that will be written to the register
1029 *
1030 * @return
1031 *
1032 * - XST_SUCCESS if the PHY was written to successfully. Since there is no error
1033 * status from the MAC on a write, the user should read the PHY to verify the
1034 * write was successful.
1035 * - XST_EMAC_MII_BUSY if there is another PHY operation in progress
1036 *
1037 * @note
1038 *
1039 * This function is not thread-safe. The user must provide mutually exclusive
1040 * access to this function if there are to be multiple threads that can call it.
1041 *
1042 * There is the possibility that this function will not return if the hardware
1043 * is broken (i.e., it never sets the status bit indicating that the write is
1044 * done). If this is of concern to the user, the user should provide a mechanism
1045 * suitable to their needs for recovery.
1046 *
1047 * For the duration of this function, all host interface reads and writes are
1048 * blocked to the current XEmacPs instance.
1049 *
1050 ******************************************************************************/
XEmacPs_PhyWrite(XEmacPs * InstancePtr,u32 PhyAddress,u32 RegisterNum,u16 PhyData)1051 LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress,
1052 u32 RegisterNum, u16 PhyData)
1053 {
1054 u32 Mgtcr;
1055 volatile u32 Ipisr;
1056 u32 IpWriteTemp;
1057 LONG Status;
1058
1059 Xil_AssertNonvoid(InstancePtr != NULL);
1060
1061 /* Make sure no other PHY operation is currently in progress */
1062 if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1063 XEMACPS_NWSR_OFFSET) &
1064 XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
1065 Status = (LONG)(XST_EMAC_MII_BUSY);
1066 } else {
1067 /* Construct Mgtcr mask for the operation */
1068 Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK |
1069 (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
1070 (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData;
1071
1072 /* Write Mgtcr and wait for completion */
1073 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
1074 XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
1075
1076 do {
1077 Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1078 XEMACPS_NWSR_OFFSET);
1079 IpWriteTemp = Ipisr;
1080 } while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
1081
1082 Status = (LONG)(XST_SUCCESS);
1083 }
1084 return Status;
1085 }
1086
1087 /*****************************************************************************/
1088 /**
1089 * API to update the Burst length in the DMACR register.
1090 *
1091 * @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
1092 * @param BLength is the length in bytes for the dma burst.
1093 *
1094 * @return None
1095 *
1096 ******************************************************************************/
XEmacPs_DMABLengthUpdate(XEmacPs * InstancePtr,s32 BLength)1097 void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength)
1098 {
1099 u32 Reg;
1100 u32 RegUpdateVal = 0;
1101
1102 Xil_AssertVoid(InstancePtr != NULL);
1103 Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) ||
1104 (BLength == XEMACPS_4BYTE_BURST) ||
1105 (BLength == XEMACPS_8BYTE_BURST) ||
1106 (BLength == XEMACPS_16BYTE_BURST));
1107
1108 switch (BLength) {
1109 case XEMACPS_SINGLE_BURST:
1110 RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST;
1111 break;
1112
1113 case XEMACPS_4BYTE_BURST:
1114 RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST;
1115 break;
1116
1117 case XEMACPS_8BYTE_BURST:
1118 RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST;
1119 break;
1120
1121 case XEMACPS_16BYTE_BURST:
1122 RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST;
1123 break;
1124 }
1125 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1126 XEMACPS_DMACR_OFFSET);
1127
1128 Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK);
1129 Reg |= RegUpdateVal;
1130 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
1131 Reg);
1132 }
1133 /** @} */
1134