1 /**
2 * enet_phy.c
3 *
4 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 #include <stdio.h>
37 #include <ti/csl/cslr_mdio.h>
38 #include <ti/csl/src/ip/mdio/V2/cslr_mdio.h>
39 #include <ti/csl/csl_mdio.h>
40 #include <ti/csl/src/ip/mdio/V2/csl_mdio.h>
41 #include <ti/csl/csl_mdioAux.h>
42 #include <ti/csl/src/ip/mdio/V2/csl_mdioAux.h>
43 #include <ti/board/src/skAM437x/device/enet_phy.h>
45 /* UART Header files */
46 #include <ti/drv/uart/UART.h>
47 #include <ti/drv/uart/src/UART_osal.h>
48 #include <ti/drv/uart/UART_stdio.h>
50 /* R A N D O M N U M B E R S U P P O R T */
51 #define COMMON_RANDOM_MAX 0xFFFFu
53 /* Enable the below macro to have prints on the IO Console */
54 //#define IO_CONSOLE
56 #ifndef IO_CONSOLE
57 #define ENET_PHY_log UART_printf
58 #else
59 #define ENET_PHY_log printf
60 #endif
62 static uint32_t RandomSeed = 1u;
64 static uint32_t cpswRandom(void)
65 {
66 RandomSeed = (RandomSeed * (1103515245u)) + (12345u);
67 return ((uint32_t) (RandomSeed/(65536u)) % (COMMON_RANDOM_MAX + 1u));
68 }
71 static uint32_t cpswRandomRange(uint32_t min, uint32_t max)
72 {
73 uint32_t iTmp;
75 iTmp = cpswRandom();
76 iTmp %= ((max - min) + 1u);
77 iTmp += min;
78 return(iTmp);
79 }
81 static void ENETPHY_DisablePhy(ENETPHY_Handle hPhyDev,uint32_t PhyNum);
82 static void ENETPHY_PhyTimeOut(ENETPHY_Handle hPhyDev);
83 static void ENETPHY_ResetPhy(ENETPHY_Handle hPhyDev,uint32_t PhyNum);
86 static void ENETPHY_DefaultState (ENETPHY_Handle hPhyDev);
87 static void ENETPHY_FindingState (ENETPHY_Handle hPhyDev);
88 static void ENETPHY_FoundState (ENETPHY_Handle hPhyDev);
89 static void ENETPHY_InitState (ENETPHY_Handle hPhyDev);
90 static void ENETPHY_LinkedState (ENETPHY_Handle hPhyDev);
91 static void ENETPHY_LinkWaitState (ENETPHY_Handle hPhyDev);
92 static void ENETPHY_LoopbackState (ENETPHY_Handle hPhyDev);
93 static void ENETPHY_NwayStartState(ENETPHY_Handle hPhyDev);
94 static void ENETPHY_NwayWaitState (ENETPHY_Handle hPhyDev);
96 #define _cpswIsGigPhy(hPhyDev) (TRUE)
98 #define ENETPHY_NOT_FOUND 0xFFFFu /* Used in Phy Detection */
100 /*CHECK:: PhyState field breakup */
101 #define ENETPHY_DEV_OFFSET (0u)
102 #define ENETPHY_DEV_SIZE (5u)
103 #define ENETPHY_DEV_MASK (0x1f<<ENETPHY_DEV_OFFSET)
105 #define ENETPHY_STATE_OFFSET (ENETPHY_DEV_SIZE+ENETPHY_DEV_OFFSET)
106 #define ENETPHY_STATE_SIZE (5u)
107 #define ENETPHY_STATE_MASK (0x1fu<<ENETPHY_STATE_OFFSET)
108 #define INIT (1u<<ENETPHY_STATE_OFFSET)
109 #define FINDING (2u<<ENETPHY_STATE_OFFSET)
110 #define FOUND (3u<<ENETPHY_STATE_OFFSET)
111 #define NWAY_START (4u<<ENETPHY_STATE_OFFSET)
112 #define NWAY_WAIT (5u<<ENETPHY_STATE_OFFSET)
113 #define LINK_WAIT (6u<<ENETPHY_STATE_OFFSET)
114 #define LINKED (7u<<ENETPHY_STATE_OFFSET)
115 #define LOOPBACK (8u<<ENETPHY_STATE_OFFSET)
117 #define ENETPHY_SPEED_OFFSET (ENETPHY_STATE_OFFSET+ENETPHY_STATE_SIZE)
118 #define ENETPHY_SPEED_SIZE (1u)
119 #define ENETPHY_SPEED_MASK_NDK (1u<<ENETPHY_SPEED_OFFSET)
121 #define ENETPHY_DUPLEX_OFFSET (ENETPHY_SPEED_OFFSET+ENETPHY_SPEED_SIZE)
122 #define ENETPHY_DUPLEX_SIZE (1u)
123 #define ENETPHY_DUPLEX_MASK (1u<<ENETPHY_DUPLEX_OFFSET)
125 #define ENETPHY_TIM_OFFSET (ENETPHY_DUPLEX_OFFSET+ENETPHY_DUPLEX_SIZE)
126 #define ENETPHY_TIM_SIZE (10u)
127 #define ENETPHY_TIM_MASK (0x3ffu<<ENETPHY_TIM_OFFSET)
129 /* we are working with 100ms ticks here */
130 #define ENETPHY_FIND_TO ( 1u<<ENETPHY_TIM_OFFSET)
131 #define ENETPHY_RECK_TO (20u<<ENETPHY_TIM_OFFSET)
132 #define ENETPHY_LINK_TO (50u<<ENETPHY_TIM_OFFSET)
133 #define ENETPHY_NWST_TO (50u<<ENETPHY_TIM_OFFSET)
134 #define ENETPHY_NWDN_TO (80u<<ENETPHY_TIM_OFFSET)
135 #define ENETPHY_MDIX_TO (27u<<ENETPHY_TIM_OFFSET) /* 2.74 Seconds <--Spec and empirical */
137 #define ENETPHY_SMODE_OFFSET (ENETPHY_TIM_OFFSET+ENETPHY_TIM_SIZE)
138 #define ENETPHY_SMODE_SIZE (7u)
139 #define ENETPHY_SMODE_MASK (0x7fu<<ENETPHY_SMODE_OFFSET)
140 #define SMODE_LPBK (0x40u<<ENETPHY_SMODE_OFFSET)
141 #define SMODE_AUTO (0x20u<<ENETPHY_SMODE_OFFSET)
142 #define SMODE_FD1000 (0x10u<<ENETPHY_SMODE_OFFSET)
143 #define SMODE_FD100 (0x08u<<ENETPHY_SMODE_OFFSET)
144 #define SMODE_HD100 (0x04u<<ENETPHY_SMODE_OFFSET)
145 #define SMODE_FD10 (0x02u<<ENETPHY_SMODE_OFFSET)
146 #define SMODE_HD10 (0x01u<<ENETPHY_SMODE_OFFSET)
147 #define SMODE_ALL (0x1fu<<ENETPHY_SMODE_OFFSET)
149 #define ENETPHY_CHNG_OFFSET (ENETPHY_SMODE_OFFSET+ENETPHY_SMODE_SIZE)
150 #define ENETPHY_CHNG_SIZE (1u)
151 #define ENETPHY_CHNG_MASK (1u<<ENETPHY_CHNG_OFFSET)
152 #define ENETPHY_CHANGE (1u<<ENETPHY_CHNG_OFFSET)
154 #define ENETPHY_TIMEDOUT_OFFSET (ENETPHY_CHNG_OFFSET+ENETPHY_CHNG_SIZE)
155 #define ENETPHY_TIMEDOUT_SIZE (1u) /* 30 Bits used */
156 #define ENETPHY_TIMEDOUT_MASK ((uint32_t)(1u<<ENETPHY_TIMEDOUT_OFFSET))
157 #define ENETPHY_MDIX_SWITCH ((uint32_t)(1u<<ENETPHY_TIMEDOUT_OFFSET))
159 #define ENETPHY_MDIX_OFFSET (ENETPHY_TIMEDOUT_OFFSET+ENETPHY_TIMEDOUT_SIZE)
160 #define ENETPHY_MDIX_SIZE (1u) /* 31 Bits used */
161 #define ENETPHY_MDIX_MASK ((uint32_t)(1u<<ENETPHY_MDIX_OFFSET))
162 #define ENETPHY_MDIX ((uint32_t)(1u<<ENETPHY_MDIX_OFFSET))
165 #ifndef VOLATILE32
166 #define VOLATILE32(addr) (*((volatile uint32_t *)(addr)))
167 #endif
169 int32_t cpsw_g_speed_set = 0;
170 int32_t cpsw_g_soft_reset_status = 0;
172 /*User Calls********************************************************* */
174 /* Updates book-keeping with info provided, programs ControlReg
175 * with clkdiv,enable bits*/
176 int32_t ENETPHY_Init(ENETPHY_Handle hPhyDev, uint32_t miibase, uint32_t inst, uint32_t PhyMask, uint32_t MLinkMask, uint32_t MdixMask, uint32_t PhyAddr, uint32_t ResetBit, uint32_t MdioBusFreq, uint32_t MdioClockFreq,int32_t verbose)
177 {
178 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
180 int32_t ret =0 ;
181 uint32_t phy;
183 ((ENETPHY_DEVICE *) hPhyDev)->miibase = miibase;
184 ((ENETPHY_DEVICE *) hPhyDev)->inst = inst;
185 ((ENETPHY_DEVICE *) hPhyDev)->PhyMask = PhyMask;
186 ((ENETPHY_DEVICE *) hPhyDev)->MLinkMask = MLinkMask;
187 ((ENETPHY_DEVICE *) hPhyDev)->MdixMask = MdixMask;
189 (void)verbose;/* remove if not required */
191 *PhyState &= ~ENETPHY_MDIX_MASK; /* Set initial State to MDI */
193 CSL_MDIO_setClkDivVal((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, (MdioBusFreq/MdioClockFreq - 1));
194 CSL_MDIO_enableFaultDetect((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase);
195 CSL_MDIO_disablePreamble((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase);
196 CSL_MDIO_enableStateMachine((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase);
198 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_CNTRL_REG, PhyAddr, &phy);
199 phy |= NWAY_AUTOMDIX_ENABLE;
200 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_CNTRL_REG,PhyAddr,phy);
202 (void)ResetBit; /* suppress warning */
204 *PhyState=INIT;
206 ret = 0;
208 return ret;
209 }/* end of function ENETPHY_Init*/
211 void ENETPHY_SetPhyMode(ENETPHY_Handle hPhyDev,uint32_t PhyMode)
212 {
213 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
214 uint32_t CurrentState;
216 ((ENETPHY_DEVICE *) hPhyDev)->PhyMode = PhyMode; /* used for AUTOMIDX, planned to replace PhyState fields */
217 *PhyState &= (~ENETPHY_SMODE_MASK);
219 if (0u != (PhyMode & NWAY_LPBK))
220 {
221 *PhyState |= SMODE_LPBK;
222 }
223 if (0u != (PhyMode & NWAY_AUTO))
224 {
225 *PhyState |= SMODE_AUTO;
226 }
227 if (0u != (PhyMode & NWAY_FD1000) )
228 {
229 *PhyState |= SMODE_FD1000;
230 }
231 if (0u!= (PhyMode & NWAY_FD100))
232 {
233 *PhyState |= SMODE_FD100;
234 }
235 if (0u != (PhyMode & NWAY_HD100))
236 {
237 *PhyState |= SMODE_HD100;
238 }
239 if (0u != (PhyMode & NWAY_FD10))
240 {
241 *PhyState |= SMODE_FD10;
242 }
243 if (0u != (PhyMode & NWAY_HD10))
244 {
245 *PhyState |= SMODE_HD10;
246 }
248 CurrentState = (*PhyState) & ENETPHY_STATE_MASK;
249 if ( ((CurrentState == NWAY_START)|| (CurrentState == NWAY_WAIT)) ||
250 ( ((CurrentState == LINK_WAIT) || (CurrentState == LINKED) ) || (CurrentState == LOOPBACK)) )
251 {
252 *PhyState = ( (*PhyState)&(~ENETPHY_STATE_MASK)) | (FOUND | ENETPHY_CHANGE);
253 }
255 ENET_PHY_log("SetPhyMode:%08x Auto:%d, FD10:%d, HD10:%d, FD100:%d, HD100:%d, FD1000:%d LPBK:%d\n", (unsigned int)PhyMode,
256 (unsigned int)(PhyMode & NWAY_AUTO), (unsigned int)(PhyMode & MII_NWAY_FD10),(unsigned int)(PhyMode & MII_NWAY_HD10),(unsigned int)(PhyMode & MII_NWAY_FD100),
257 (unsigned int)(PhyMode & MII_NWAY_HD100), (unsigned int)(PhyMode & NWAY_FD1000),
258 (unsigned int)(PhyMode & NWAY_LPBK) );
260 }
262 uint32_t ENETPHY_GetPhyMode(ENETPHY_Handle hPhyDev)
263 {
264 uint32_t PhyMode =0;
265 uint32_t status_reg = 0,control_reg = 0,advertize_reg;
266 uint32_t PhyNum,j;
267 uint32_t PhyMask = ((ENETPHY_DEVICE *) hPhyDev)->PhyMask;
269 PhyNum = 0;
270 for(j = 1;PhyNum < 32;PhyNum++)
271 {
272 if( 0u != ( j & PhyMask))
273 {
274 break;
275 }
276 j = j<<1;
277 }
279 if(0u != _cpswIsGigPhy(hPhyDev))
280 {
281 /* read gig status */
282 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_1000BT_CONTROL, PhyNum, &control_reg);
283 /* read gig status */
284 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_1000BT_STATUS, PhyNum, &status_reg);
285 }
286 /* figure out if gig connected at FD 1000 or not first */
287 if ((0u != (control_reg & MII_NWAY_MY_FD1000)) && (0u != (status_reg & MII_NWAY_REM_FD1000)) )
288 {
289 PhyMode |= NWAY_FD1000;
290 }
292 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BCR, PhyNum, &control_reg);
293 if(0u != (control_reg & MII_AUTO_NEGOTIATE_EN) )
294 {
295 PhyMode |= NWAY_AUTO;
296 }
297 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BSR, PhyNum, &status_reg);
298 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_AUTONEG_ADV, PhyNum, &advertize_reg);
300 /* Check for 10/100 capabilities of PHYs */
301 if((0u != (control_reg & MII_ENETPHY_100))|| (0u != (PhyMode & NWAY_AUTO)) )
302 {
303 if(0u != (advertize_reg & MII_NWAY_FD100))
304 {
305 PhyMode |= NWAY_FD100;
306 }
307 if(0u != (advertize_reg & MII_NWAY_HD100))
308 {
309 PhyMode |= NWAY_HD100;
310 }
312 }
314 if(((control_reg & MII_ENETPHY_100) == 0) || (0u != (PhyMode & NWAY_AUTO)) )
315 {
316 if(0u != (advertize_reg & MII_NWAY_FD10))
317 {
318 PhyMode |= NWAY_FD10;
319 }
320 if(0u != (advertize_reg & MII_NWAY_HD10))
321 {
322 PhyMode |= NWAY_HD10;
323 }
325 }
326 return PhyMode;
327 }
328 /* ENETPHY_Tic is called every 10 mili seconds to process Phy states */
330 int32_t ENETPHY_Tic(ENETPHY_Handle hPhyDev,uint32_t* mdioStatus)
331 {
332 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
333 uint32_t CurrentState;
334 int32_t ret = 0;
336 *mdioStatus = MDIO_EVENT_NOCHANGE;
338 /*Act on current state of the Phy */
339 CurrentState=*PhyState;
340 switch(CurrentState&ENETPHY_STATE_MASK)
341 {
342 case INIT: ENETPHY_InitState(hPhyDev); break;
343 case FINDING: ENETPHY_FindingState(hPhyDev); break;
344 case FOUND: ENETPHY_FoundState(hPhyDev); break;
345 case NWAY_START: ENETPHY_NwayStartState(hPhyDev); break;
346 case NWAY_WAIT: ENETPHY_NwayWaitState(hPhyDev); break;
347 case LINK_WAIT: ENETPHY_LinkWaitState(hPhyDev); break;
348 case LINKED: ENETPHY_LinkedState(hPhyDev); break;
349 case LOOPBACK: ENETPHY_LoopbackState(hPhyDev); break;
350 default: ENETPHY_DefaultState(hPhyDev); break;
351 }
353 /* Check is MDI/MDIX mode switch is needed */
355 if(0u != ((*PhyState) & ENETPHY_MDIX_SWITCH) )
356 {
358 uint32_t Mdix;
360 *PhyState &= (~ENETPHY_MDIX_SWITCH); /* Clear Mdix Flip indicator */
362 if(0u != ((*PhyState) & ENETPHY_MDIX))
363 {
364 Mdix = 1;
365 }
366 else
367 {
368 Mdix = 0;
369 }
370 ret = (int32_t)(_MIIMDIO_MDIXFLIP | Mdix);
372 }
373 else
374 {
376 /*Return state change to user */
377 /** CHECK : report MDIO_LINKEVENTS as MDIO_EVENT_NOCHANGE, MDIO_EVENT_LINKDOWN,
378 * MDIO_EVENT_PHYERROR,MDIO_EVENT_LINKUP
379 * Currently ENETPHY_CHNG_MASK set for any state transition*/
381 if (0u != ((*PhyState) & ENETPHY_CHNG_MASK))
382 {
383 if( ( ((*PhyState) & ENETPHY_STATE_MASK) == LINKED) && ((CurrentState & ENETPHY_STATE_MASK) != LINKED) )
384 {
385 /* we have just entered LInked state */
386 *mdioStatus = MDIO_EVENT_LINKUP;
387 }
388 if( ((CurrentState & ENETPHY_STATE_MASK) == LINKED) && ( ( (*PhyState) & ENETPHY_STATE_MASK) != LINKED))
389 {
390 /* we started in Linked state and we have a state change */
391 *mdioStatus = MDIO_EVENT_LINKDOWN;
392 }
393 *PhyState &= (~ENETPHY_CHNG_MASK);
394 ret = (int32_t)(TRUE);
395 }
396 else
397 {
398 ret = (int32_t)(FALSE);
399 }
400 }
402 return ret;
404 }
407 void ENETPHY_LinkChange(ENETPHY_Handle hPhyDev)
408 {
409 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
410 uint32_t PhyNum,PhyStatus;
412 PhyNum = ( (*PhyState) & ENETPHY_DEV_MASK) >> ENETPHY_DEV_OFFSET;
414 ENET_PHY_log("ENETPHY_LinkChange: PhyNum = %d\n", (unsigned int)PhyNum);
416 if (0u != (ENETPHY_GetLinked(hPhyDev)) )
417 {
418 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BSR, PhyNum, &PhyStatus);
420 if ((PhyStatus & MII_ENETPHY_LINKED) == 0u)
421 {
422 *PhyState &= (~(ENETPHY_TIM_MASK | ENETPHY_STATE_MASK));
423 if (0u!=((*PhyState) & SMODE_AUTO))
424 {
425 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_BCR, PhyNum, MII_AUTO_NEGOTIATE_EN|MII_RENEGOTIATE);
426 *PhyState |= ((ENETPHY_CHANGE | ENETPHY_NWST_TO) | NWAY_START);
427 }
428 else
429 {
430 *PhyState|= ((ENETPHY_CHANGE | ENETPHY_LINK_TO) | LINK_WAIT);
431 }
432 }
433 }
434 }
436 /* returns 0 if current Phy has AutoMdix support, otherwise 0 */
437 static int32_t ENETPHY_MdixSupported(ENETPHY_Handle hPhyDev)
438 {
439 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
440 uint32_t PhyNum;
441 int32_t ret;
443 if((((ENETPHY_DEVICE *) hPhyDev)->PhyMode & NWAY_AUTOMDIX) == 0)
444 {
445 ret = (0); /* AutoMdix not turned on */
446 }
447 else
448 {
449 PhyNum = ((*PhyState) & ENETPHY_DEV_MASK) >> ENETPHY_DEV_OFFSET;
450 if( ((1<<PhyNum) & ((ENETPHY_DEVICE *) hPhyDev)->MdixMask) == 0)
451 {
452 ret = 0; /* Phy does not support AutoMdix*/
453 }
455 ret = 1;
456 }
457 return ret;
458 }
460 /* If current Phy has AutoMdix support add Mdix Delay to the Timer State Value */
461 static void ENETPHY_MdixDelay(ENETPHY_Handle hPhyDev)
462 {
463 uint32_t Delay;
464 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
467 if(ENETPHY_MdixSupported(hPhyDev) != 0)
468 {
469 /* Get the Delay value in milli-seconds and convert to ten-milli second value */
470 Delay = cpswRandomRange(_AUTOMDIX_DELAY_MIN, _AUTOMDIX_DELAY_MAX);
471 Delay /= 10;
473 /* Add AutoMidx Random Switch Delay to AutoMdix Link Delay */
475 Delay += (ENETPHY_MDIX_TO>>ENETPHY_TIM_OFFSET);
477 /* Change Timeout value to AutoMdix standard */
478 *PhyState &= (~(ENETPHY_TIM_MASK)); /* Clear current Time out value */
479 *PhyState |= (Delay<<ENETPHY_TIM_OFFSET); /* Set new value */
480 }
481 return;
483 }
485 void ENETPHY_DisablePhy(ENETPHY_Handle hPhyDev,uint32_t PhyNum)
486 {
487 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_BCR, PhyNum, (MII_ENETPHY_ISOLATE | MII_ENETPHY_PDOWN) );
489 ENET_PHY_log("ENETPHY_DisablePhy(%d)\n",(unsigned int)PhyNum);
491 }
493 void ENETPHY_InitState(ENETPHY_Handle hPhyDev)
494 {
495 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
496 uint32_t CurrentState;
498 CurrentState=*PhyState;
499 CurrentState = (CurrentState & (~ENETPHY_TIM_MASK)) | (ENETPHY_FIND_TO);
500 CurrentState=(CurrentState & (~ENETPHY_STATE_MASK)) | (FINDING);
501 CurrentState=(CurrentState & (~ENETPHY_SPEED_MASK_NDK));
502 CurrentState=(CurrentState & (~ENETPHY_DUPLEX_MASK));
503 CurrentState|=ENETPHY_CHANGE;
505 *PhyState=CurrentState;
507 }
509 void ENETPHY_FindingState(ENETPHY_Handle hPhyDev)
510 {
511 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
512 uint32_t PhyMask = ((ENETPHY_DEVICE *) hPhyDev)->PhyMask;
513 uint32_t PhyNum,i,j;
515 PhyNum=ENETPHY_NOT_FOUND;
517 if (0u!= ((*PhyState) & ENETPHY_TIM_MASK))
518 {
519 *PhyState=( (*PhyState) & (~ENETPHY_TIM_MASK) ) | (( (*PhyState) & ENETPHY_TIM_MASK) - (1 << ENETPHY_TIM_OFFSET));
520 }
521 else
522 {
523 j =1;
524 for(i=0; i<32; i++)
525 {
526 if( PhyMask & j)
527 {
528 if( CSL_MDIO_isPhyAlive((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, i))
529 {
530 PhyNum=i;
531 break;
532 }
533 }
534 j = j << 1;
535 }
536 if (PhyNum!=ENETPHY_NOT_FOUND)
537 {
538 /* Phy Found! */
539 *PhyState = ((*PhyState) & (~ENETPHY_DEV_MASK) ) | ((PhyNum & ENETPHY_DEV_MASK) << ENETPHY_DEV_OFFSET);
540 *PhyState = ( (*PhyState) & (~ENETPHY_STATE_MASK) ) | (FOUND);
541 *PhyState|=ENETPHY_CHANGE;
543 ENET_PHY_log("ENETPHY_FindingState: PhyNum: %d\n",(unsigned int)PhyNum);
545 }
546 else
547 {
549 ENET_PHY_log("ENETPHY_FindingState: Timed Out looking for a Phy!\n");
550 *PhyState|=ENETPHY_RECK_TO; /* Set Timer */
551 }
552 }
553 }
555 void ENETPHY_FoundState(ENETPHY_Handle hPhyDev)
556 {
557 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
558 uint32_t PhyMask = ((ENETPHY_DEVICE *) hPhyDev)->PhyMask;
559 uint32_t MLinkMask = ((ENETPHY_DEVICE *) hPhyDev)->MLinkMask;
560 uint32_t PhyNum,PhyStatus,NWAYadvertise,NWAY1000advertise=0,m,phynum,i,j;
561 uint32_t PhyDummy;
563 static uint32_t auto_neg1 = 0xFFFFFFFF,auto_neg2= 0xFFFFFFFF;
566 if (( (*PhyState) & ENETPHY_SMODE_MASK) == 0)
567 {
568 return;
569 }
571 PhyNum = ((*PhyState) & ENETPHY_DEV_MASK) >> ENETPHY_DEV_OFFSET;
572 j =1;
573 for(phynum=0; phynum<32; phynum++)
574 {
575 if(0u!= (PhyMask & j))
576 {
577 if( CSL_MDIO_isPhyAlive((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, phynum))
578 {
579 ENETPHY_DisablePhy(hPhyDev,phynum);
580 }
581 }
582 j = j << 1;
583 }
584 /* If Aries SWR2 reset then don't reset phy*/
585 /* Reset the Phy and proceed with auto-negotiation */
586 if(( 0u != cpsw_g_speed_set) || ((0u ==cpsw_g_soft_reset_status) || ((auto_neg1 & (1 << PhyNum)) == 0) ) )
587 {
588 ENETPHY_ResetPhy(hPhyDev,PhyNum);
589 }
591 /* Set the way Link will be Monitored */
592 /* Check the Link Selection Method */
593 if (0u != ((1 << PhyNum) & MLinkMask) )
594 {
595 CSL_MDIO_enableLinkStatusChangeInterrupt((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, ((ENETPHY_DEVICE *) hPhyDev)->inst, PhyNum);
596 }
597 else
598 {
599 CSL_MDIO_disableLinkStatusChangeInterrupt((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, ((ENETPHY_DEVICE *) hPhyDev)->inst, PhyNum);
600 }
601 /* Get the Phy Status */
602 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BSR, PhyNum, &PhyStatus);
605 /* For Phy Internal loopback test, need to wait until Phy
606 found, then set Loopback */
607 if (0u != ((*PhyState) & SMODE_LPBK))
608 {
609 /* Set Phy in Loopback */
611 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_BCR, PhyNum, MII_ENETPHY_LOOP|MII_ENETPHY_FD);
612 /* Do a read to ensure ENETPHY_LOOP has completed */
613 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BSR, PhyNum, &PhyDummy);
614 *PhyState = ( (*PhyState) & (~ENETPHY_STATE_MASK) ) | (LOOPBACK);
615 *PhyState|=ENETPHY_CHANGE;
616 return;
617 }
619 ENET_PHY_log("Enable Phy to negotiate external connection\n");
622 NWAYadvertise=MII_NWAY_SEL;
623 if (0u != ((*PhyState) & SMODE_FD100))
624 {
625 NWAYadvertise |= MII_NWAY_FD100;
626 }
627 if (0u != ((*PhyState) & SMODE_HD100))
628 {
629 NWAYadvertise |= MII_NWAY_HD100;
630 }
631 if (0u != ((*PhyState) & SMODE_FD10))
632 {
633 NWAYadvertise |= MII_NWAY_FD10;
634 }
635 if (0u != ((*PhyState) & SMODE_HD10))
636 {
637 NWAYadvertise |= MII_NWAY_HD10;
638 }
639 if (0u != ((*PhyState) & SMODE_FD1000))
640 {
641 NWAY1000advertise= ENETPHY_1000BT_FD;
642 }
644 *PhyState &= ( ~(ENETPHY_TIM_MASK | ENETPHY_STATE_MASK));
645 if ((0u != (PhyStatus & MII_NWAY_CAPABLE)) && (0u != ( (*PhyState) & SMODE_AUTO)) ) /*NWAY Phy Detected*/
646 {
647 if(( 0u != cpsw_g_speed_set) || ((0u ==cpsw_g_soft_reset_status) || ((auto_neg1 & (1 << PhyNum)) == 0) ) )
648 {
649 /*For NWAY compliant Phys */
650 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_AUTONEG_ADV, PhyNum, NWAYadvertise);
651 /* for gig negotiation */
652 if(0u != _cpswIsGigPhy(hPhyDev))
653 {
654 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_1000BT_CONTROL, PhyNum, NWAY1000advertise);
655 }
657 ENET_PHY_log("NWAY Advertising: ");
658 if (0u != ((*PhyState) & SMODE_FD1000))
659 {
660 ENET_PHY_log("FullDuplex-1000 ");
661 }
662 if (0u != (NWAYadvertise & MII_NWAY_FD100))
663 {
664 ENET_PHY_log("FullDuplex-100 ");
665 }
666 if (0u != (NWAYadvertise & MII_NWAY_HD100))
667 {
668 ENET_PHY_log("HalfDuplex-100 ");
669 }
670 if (0u != (NWAYadvertise & MII_NWAY_FD10))
671 {
672 ENET_PHY_log("FullDuplex-10 ");
673 }
674 if (0u != (NWAYadvertise & MII_NWAY_HD10))
675 {
676 ENET_PHY_log("HalfDuplex-10 ");
677 }
679 ENET_PHY_log("\n");
681 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_BCR, PhyNum, MII_AUTO_NEGOTIATE_EN );
682 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_BCR, PhyNum, MII_AUTO_NEGOTIATE_EN|MII_RENEGOTIATE|MII_ENETPHY_FD);
683 *PhyState|= ( (ENETPHY_CHANGE | ENETPHY_NWST_TO) | NWAY_START);
684 }
685 else
686 {
687 *PhyState |= ( (ENETPHY_CHANGE | ENETPHY_NWST_TO) | NWAY_START);
688 auto_neg1 = auto_neg1 & (~(1 << PhyNum));
689 }
690 }
691 else
692 {
693 *PhyState &= (~SMODE_AUTO); /*The Phy is not capable of auto negotiation! */
694 m=NWAYadvertise;
695 j = 0x8000u;
697 for(i=0;(i<16);i++)
698 {
699 if(0u != (j & m))
700 {
701 break;
702 }
703 j = j >> 1 ;
705 }
706 m=j;
707 j=0;
709 /* figure out if gig connected at FD 1000 or not first */
710 if ((NWAY1000advertise & MII_NWAY_MY_FD1000)== MII_NWAY_MY_FD1000)
711 {
712 j = MII_ENETPHY_1000;
713 j |= MII_ENETPHY_FD;
714 }
715 else
716 {
717 if (0u != (m & (MII_NWAY_FD100 | MII_NWAY_HD100)) )
718 {
719 j=MII_ENETPHY_100;
720 m&=(MII_NWAY_FD100|MII_NWAY_HD100);
721 }
722 if (0u != (m & (MII_NWAY_FD100 | MII_NWAY_FD10)) )
723 {
724 j |= MII_ENETPHY_FD;
725 }
726 }
728 ENET_PHY_log("Requested PHY mode %s Duplex %s Mbps\n",(j & MII_ENETPHY_FD) ? "Full":"Half",
729 (j & MII_ENETPHY_1000) ? "1000":((j & MII_ENETPHY_100) ? "100":"10"));
731 if((0u != cpsw_g_speed_set) || ( (0u == cpsw_g_soft_reset_status) || ((auto_neg2 & (1 << PhyNum)) == 0) ))
732 {
733 if(0u != (j & MII_ENETPHY_1000))
734 {
735 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_1000BT_CONTROL, PhyNum, j);
736 }
737 else
738 {
739 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_BCR, PhyNum, j);
740 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_AUTONEG_ADV, PhyNum, NWAYadvertise);
741 }
742 cpsw_g_speed_set = 0;
743 }
744 else
745 {
746 auto_neg2 = auto_neg2 & (~(1 << PhyNum));
747 }
748 *PhyState &= (~ENETPHY_SPEED_MASK_NDK);
749 if(0u != (j & MII_ENETPHY_1000) )
750 {
751 *PhyState|=(1<<ENETPHY_DUPLEX_OFFSET);
752 ((ENETPHY_DEVICE *) hPhyDev)->SPEED_1000 = 1;
753 }
754 else
755 {
756 ((ENETPHY_DEVICE *) hPhyDev)->SPEED_1000 = 0;
757 }
758 if (0u != (j & MII_ENETPHY_100) )
759 {
760 *PhyState|=(1<<ENETPHY_SPEED_OFFSET);
761 }
762 *PhyState &= (~ENETPHY_DUPLEX_MASK);
763 if (0u != (j & MII_ENETPHY_FD) )
764 {
765 *PhyState|=(1<<ENETPHY_DUPLEX_OFFSET);
766 }
767 *PhyState |= ((ENETPHY_CHANGE | ENETPHY_LINK_TO) | LINK_WAIT);
768 }
769 ENETPHY_MdixDelay(hPhyDev); /* If AutoMdix add delay */
771 }
773 void ENETPHY_ResetPhy(ENETPHY_Handle hPhyDev,uint32_t PhyNum)
774 {
775 uint32_t data;
777 data = MII_ENETPHY_RESET;
779 /* Reset the phy */
780 ENETPHY_UserAccessWrite(hPhyDev, ENETPHY_BCR, PhyNum, data);
782 /* wait till the reset bit is auto cleared */
783 while(data & MII_ENETPHY_RESET)
784 {
785 /* Read the reset */
786 if(ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BCR, PhyNum, &data) != TRUE)
787 {
788 break;
789 }
790 }
792 }
794 void ENETPHY_NwayStartState(ENETPHY_Handle hPhyDev)
795 {
796 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
797 uint32_t PhyNum,PhyMode,PhyDummy;
799 PhyNum = ( (*PhyState) & ENETPHY_DEV_MASK) >> ENETPHY_DEV_OFFSET;
801 /*Wait for Negotiation to start */
803 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BCR, PhyNum, &PhyMode);
805 if((PhyMode&MII_RENEGOTIATE)==0)
806 {
807 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BSR, PhyNum,&PhyDummy); /*Flush pending latch bits*/
808 *PhyState &= (~(ENETPHY_STATE_MASK|ENETPHY_TIM_MASK));
809 *PhyState |= ((ENETPHY_CHANGE | NWAY_WAIT) |ENETPHY_NWDN_TO);
810 ENETPHY_MdixDelay(hPhyDev); /* If AutoMdix add delay */
811 }
812 else
813 {
814 if (0u != ((*PhyState) & ENETPHY_TIM_MASK) )
815 {
816 *PhyState=( (*PhyState) & (~ENETPHY_TIM_MASK)) | ( ( (*PhyState) & ENETPHY_TIM_MASK)-(1 << ENETPHY_TIM_OFFSET));
817 }
818 else
819 {
820 ENETPHY_PhyTimeOut(hPhyDev);
821 }
822 }
823 }
825 void ENETPHY_NwayWaitState(ENETPHY_Handle hPhyDev)
826 {
827 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
828 uint32_t PhyNum,PhyStatus,NWAYadvertise = 0,NWAYREadvertise = 0,NegMode,i,j;
829 uint32_t NWAY1000advertise = 0, NWAY1000REMadvertise = 0;
831 PhyNum=( (*PhyState) & ENETPHY_DEV_MASK) >> ENETPHY_DEV_OFFSET;
833 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BSR, PhyNum, &PhyStatus);
835 if (0u != (PhyStatus & MII_NWAY_COMPLETE))
836 {
837 *PhyState|=ENETPHY_CHANGE;
838 *PhyState &= (~ENETPHY_SPEED_MASK_NDK);
839 *PhyState &= (~ENETPHY_DUPLEX_MASK);
841 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_AUTONEG_ADV, PhyNum, &NWAYadvertise);
842 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_LINK_PARTNER_ABLTY, PhyNum, &NWAYREadvertise);
843 /* read gig status */
844 if(0u != _cpswIsGigPhy(hPhyDev))
845 {
846 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_1000BT_CONTROL, PhyNum, &NWAY1000advertise);
847 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_1000BT_STATUS, PhyNum, &NWAY1000REMadvertise);
848 }
850 /* figure out if gig connected at FD 1000 or not first */
851 if ((0u !=(NWAY1000advertise & MII_NWAY_MY_FD1000)) && (0u!=(NWAY1000REMadvertise & MII_NWAY_REM_FD1000)) )
852 {
853 NegMode = MII_NWAY_MY_FD1000;
854 }
855 else
856 {
857 NegMode = 0u;
858 }
860 if (NegMode == 0u)
861 {
862 /* continue checking for 100 and 10 connection */
864 /* Negotiated mode is we and the remote have in common */
865 NegMode = NWAYadvertise & NWAYREadvertise;
867 ENET_PHY_log("Phy: %d, ",(unsigned int)( (*PhyState) & ENETPHY_DEV_MASK) >> ENETPHY_DEV_OFFSET);
868 ENET_PHY_log("NegMode %04X, NWAYadvertise %04X, NWAYREadvertise %04X\n",
869 (unsigned int)NegMode, (unsigned int)NWAYadvertise, (unsigned int)NWAYREadvertise);
871 /* Limit negotiation to fields below */
872 NegMode &= ( (MII_NWAY_FD100|MII_NWAY_HD100) | (MII_NWAY_FD10|MII_NWAY_HD10));
874 if (NegMode == 0u)
875 {
876 NegMode=(MII_NWAY_HD100|MII_NWAY_HD10)&NWAYadvertise; /*or 10 ?? who knows, Phy is not MII compliant*/
877 }
879 j = 0x8000u;
880 for(i = 0; i <16 ; i++)
881 {
882 if (0u != (j & NegMode))
883 {
884 break;
885 }
886 j = j >> 1;
887 }
889 NegMode=j;
892 ENET_PHY_log("Negotiated connection: ");
895 if (0u != (NegMode & MII_NWAY_FD100))
896 {
897 ENET_PHY_log("FullDuplex 100 Mbs\n");
898 }
899 if (0u != (NegMode & MII_NWAY_HD100))
900 {
901 ENET_PHY_log("HalfDuplex 100 Mbs\n");
902 }
903 if (0u != (NegMode & MII_NWAY_FD10))
904 {
905 ENET_PHY_log("FullDuplex 10 Mbs\n");
906 }
907 if (0u != (NegMode & MII_NWAY_HD10))
908 {
909 ENET_PHY_log("HalfDuplex 10 Mbs\n");
910 }
912 ((ENETPHY_DEVICE *) hPhyDev)->SPEED_1000 = 0u;
913 }
914 else
915 {
917 /* found 1000 negotiated connection! */
918 ENET_PHY_log("Negotiated connection: ");
919 ENET_PHY_log("FullDuplex 1000 Mbs\n");
921 ((ENETPHY_DEVICE *) hPhyDev)->SPEED_1000 = 1u;
922 }
924 if (NegMode != 0u)
925 {
926 if (0u != (PhyStatus & MII_ENETPHY_LINKED))
927 {
928 *PhyState=( (*PhyState) & (~ENETPHY_STATE_MASK)) | LINKED;
929 }
930 else
931 {
932 *PhyState=( (*PhyState) & (~ENETPHY_STATE_MASK)) | LINK_WAIT;
933 }
934 if (0u != (NegMode & (MII_NWAY_FD100 | MII_NWAY_HD100)) )
935 {
936 *PhyState=( (*PhyState) & (~ENETPHY_SPEED_MASK_NDK)) | (1 << ENETPHY_SPEED_OFFSET);
937 }
938 if (0u != (NegMode & (MII_NWAY_FD100 | MII_NWAY_FD10 | MII_NWAY_MY_FD1000)))
939 {
940 *PhyState=( (*PhyState) & (~ENETPHY_DUPLEX_MASK)) | (1 << ENETPHY_DUPLEX_OFFSET);
941 }
942 }
943 }
944 else
945 {
946 if ( 0u != ( (*PhyState) & ENETPHY_TIM_MASK) )
947 {
948 *PhyState=( (*PhyState) & (~ENETPHY_TIM_MASK)) | (( (*PhyState) & ENETPHY_TIM_MASK)-(1 << ENETPHY_TIM_OFFSET));
949 }
950 else
951 {
952 ENETPHY_PhyTimeOut(hPhyDev);
953 }
954 }
956 }
958 void ENETPHY_LinkWaitState(ENETPHY_Handle hPhyDev)
959 {
960 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
961 uint32_t PhyStatus;
962 uint32_t PhyNum;
964 PhyNum=( (*PhyState) & ENETPHY_DEV_MASK) >> ENETPHY_DEV_OFFSET;
966 ENETPHY_UserAccessRead(hPhyDev, ENETPHY_BSR, PhyNum, &PhyStatus);
968 if (0u != (PhyStatus & MII_ENETPHY_LINKED) )
969 {
970 *PhyState=( (*PhyState) & (~ENETPHY_STATE_MASK) ) | LINKED;
971 *PhyState|=ENETPHY_CHANGE;
972 }
973 else
974 {
975 if (0u != ( (*PhyState) & ENETPHY_TIM_MASK) )
976 {
977 *PhyState=(*PhyState&~ENETPHY_TIM_MASK)|((*PhyState&ENETPHY_TIM_MASK)-(1<<ENETPHY_TIM_OFFSET));
978 }
979 else
980 {
981 ENETPHY_PhyTimeOut(hPhyDev);
982 }
983 }
984 }
986 void ENETPHY_PhyTimeOut(ENETPHY_Handle hPhyDev)
987 {
988 uint32_t *PhyState;
989 if(ENETPHY_MdixSupported(hPhyDev) == 0)
990 {
991 return; /* AutoMdix not supported */
992 }
993 PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
995 /* Indicate MDI/MDIX mode switch is needed */
996 *PhyState|=ENETPHY_MDIX_SWITCH;
998 /* Toggle the MDIX mode indicatir */
999 if(0u != ( (*PhyState) & ENETPHY_MDIX) )
1000 {
1001 *PhyState &= (~ENETPHY_MDIX_MASK); /* Current State is MDIX, set to MDI */
1002 }
1003 else
1004 {
1005 *PhyState |= ENETPHY_MDIX_MASK; /* Current State is MDI, set to MDIX */
1006 }
1007 /* Reset state machine to FOUND */
1008 *PhyState = ( (*PhyState) & (~ENETPHY_STATE_MASK)) | (FOUND);
1009 }
1011 void ENETPHY_LoopbackState(ENETPHY_Handle hPhyDev)
1012 {
1013 (void)((ENETPHY_DEVICE *) hPhyDev); /* remove if not needed, to avoid warning */
1014 return;
1015 }
1017 void ENETPHY_LinkedState(ENETPHY_Handle hPhyDev)
1018 {
1019 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
1020 uint32_t PhyNum = ( (*PhyState) & ENETPHY_DEV_MASK) >> ENETPHY_DEV_OFFSET;
1022 if (CSL_MDIO_isPhyLinked((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, PhyNum))
1023 {
1024 return; /* if still Linked, exit*/
1025 }
1027 /* Not Linked */
1028 *PhyState &= (~(ENETPHY_STATE_MASK | ENETPHY_TIM_MASK));
1029 if (0u != ( (*PhyState) & SMODE_AUTO) )
1030 {
1031 *PhyState |= ( (ENETPHY_CHANGE | NWAY_WAIT) | ENETPHY_NWDN_TO);
1032 }
1033 else
1034 {
1035 *PhyState |= ( (ENETPHY_CHANGE | ENETPHY_LINK_TO) | LINK_WAIT);
1036 }
1037 ENETPHY_MdixDelay(hPhyDev); /* If AutoMdix add delay */
1039 }
1041 void ENETPHY_DefaultState(ENETPHY_Handle hPhyDev)
1042 {
1043 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
1044 /*Awaiting a ENETPHY_Init call */
1045 *PhyState|=ENETPHY_CHANGE;
1046 }
1048 /* Simple Query Functions for reporting speed,duplex */
1049 /* ENETPHY_GetDuplex is called to retrieve the Duplex info */
1050 int32_t ENETPHY_GetDuplex(ENETPHY_Handle hPhyDev)
1051 {
1052 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
1053 return(( (*PhyState) & ENETPHY_DUPLEX_MASK) ? 1:0); /* return 0 or a 1 */
1054 }
1056 /* ENETPHY_GetSpeed is called to retreive the Speed info */
1057 int32_t ENETPHY_GetSpeed(ENETPHY_Handle hPhyDev)
1058 {
1059 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
1060 int32_t ret = 0 ;
1062 if (((ENETPHY_DEVICE *) hPhyDev)->SPEED_1000 == 1)
1063 {
1064 ret = 2; /* if we are linked at 1000, we return a value of 2 */
1065 }
1066 else
1067 {
1068 ret = ( (*PhyState) & ENETPHY_SPEED_MASK_NDK);
1069 }
1071 return ret;
1072 }
1074 /* ENETPHY_GetPhyNum is called to retreive the Phy Device Adr info*/
1075 int32_t ENETPHY_GetPhyNum(ENETPHY_Handle hPhyDev)
1076 {
1077 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
1078 return((int32_t)(( (*PhyState) & ENETPHY_DEV_MASK) >> ENETPHY_DEV_OFFSET));
1079 }
1081 /* ENETPHY_GetLoopback is called to Determine if the LOOPBACK state has been reached*/
1082 int32_t ENETPHY_GetLoopback(ENETPHY_Handle hPhyDev)
1083 {
1084 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
1085 return(( (*PhyState) & ENETPHY_STATE_MASK) == LOOPBACK);
1086 }
1088 /* ENETPHY_GetLinked is called to Determine if the LINKED state has been reached*/
1089 int32_t ENETPHY_GetLinked(ENETPHY_Handle hPhyDev)
1090 {
1091 uint32_t *PhyState = &((ENETPHY_DEVICE *) hPhyDev)->PhyState;
1092 return (( (*PhyState) & ENETPHY_STATE_MASK) == LINKED);
1093 }
1095 /************************************
1096 ***
1097 *** Waits for MDIO_USERACCESS to be ready and reads data
1098 *** If 'WaitForData' set, waits for read to complete and returns Data,
1099 *** otherwise returns 0
1100 *** Note: 'data' is 16 bits but we use 32 bits
1101 *** to be consistent with rest of the code.
1102 ***
1103 **************************************/
1104 uint32_t ENETPHY_UserAccessRead(ENETPHY_Handle hPhyDev, uint32_t regadr, uint32_t phyadr, uint32_t *data)
1105 {
1106 CSL_MDIO_USERACCESS user_access_reg;
1108 /* Wait till transaction completion if any */
1109 do
1110 {
1111 CSL_MDIO_getUserAccessRegister((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, 0, &user_access_reg);
1112 }
1113 while(user_access_reg.go);
1115 user_access_reg.phyAddr = phyadr;
1116 user_access_reg.regAddr = regadr;
1117 user_access_reg.write = 0U;
1118 user_access_reg.go = 1U;
1120 CSL_MDIO_setUserAccessRegister((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, 0U, &user_access_reg);
1122 /* wait for command completion */
1123 do
1124 {
1125 CSL_MDIO_getUserAccessRegister((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, 0, &user_access_reg);
1126 }
1127 while(user_access_reg.go);
1129 CSL_MDIO_getUserAccessRegister((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, 0, &user_access_reg);
1130 /* Store the data if the read is acknowledged */
1131 if(user_access_reg.ack)
1132 {
1133 *data = user_access_reg.data & MDIO_USERACCESS_DATA;
1134 return 1u;
1135 }
1137 return 0u;
1138 }
1141 /************************************
1142 ***
1143 *** Waits for MDIO_USERACCESS to be ready and writes data
1144 ***
1145 **************************************/
1146 void ENETPHY_UserAccessWrite(ENETPHY_Handle hPhyDev, uint32_t regadr, uint32_t phyadr, uint32_t data)
1147 {
1148 CSL_MDIO_USERACCESS user_access_reg;
1150 /* Wait till transaction completion if any */
1151 do
1152 {
1153 CSL_MDIO_getUserAccessRegister((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, 0, &user_access_reg);
1154 }
1155 while(user_access_reg.go);
1157 user_access_reg.phyAddr = phyadr;
1158 user_access_reg.regAddr = regadr;
1159 user_access_reg.write = 1U;
1160 user_access_reg.go = 1U;
1161 user_access_reg.data = data;
1163 CSL_MDIO_setUserAccessRegister((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, 0U, &user_access_reg);
1165 /* wait for command completion */
1166 do
1167 {
1168 CSL_MDIO_getUserAccessRegister((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, 0, &user_access_reg);
1169 }
1170 while(user_access_reg.go);
1171 }