?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
2 *
3 * PHY external API implementation for Microchip TCP/IP Stack
4 *
5 *********************************************************************
6 * FileName: ETHPIC32ExtPhy.c
7 * Dependencies:
8 * Processor: PIC32
9 *
10 * Complier: MPLAB C32
11 * MPLAB IDE
12 * Company: Microchip Technology, Inc.
13 *
14 * Software License Agreement
15 *
16 * Copyright © 2009 Microchip Technology Inc. All rights reserved.
17 *
18 * Microchip licenses the Software for your use with Microchip microcontrollers
19 * and Microchip digital signal controllers pursuant to the terms of the
20 * Non-Exclusive Software License Agreement accompanying this Software.
21 *
22 * SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT WARRANTY
23 * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION,
24 * ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS
25 * FOR A PARTICULAR PURPOSE.
26 * MICROCHIP AND ITS LICENSORS ASSUME NO RESPONSIBILITY FOR THE ACCURACY,
27 * RELIABILITY OR APPLICATION OF THE SOFTWARE AND DOCUMENTATION.
28 * IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED
29 * UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH
30 * OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT
31 * DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL,
32 * SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS
33 * OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY,
34 * SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED
35 * TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
36 *
37 * $Id: $
38 ********************************************************************/
39  
40  
41 #include <plib.h>
42  
43 // Compile only for PIC32MX with Ethernet MAC interface (must not have external ENCX24J600, ENC28J60, or ZG2100M hardware defined)
44 #if defined(__PIC32MX__) && defined(_ETH) && !defined(ENC100_INTERFACE_MODE) && !defined(ENC_CS_TRIS) && !defined(ZG_CS_TRIS)
45  
46 #include "TCPIP Stack/ETHPIC32ExtPhy.h"
47  
48 #include "TCPIP Stack/ETHPIC32ExtPhyRegs.h"
49  
50 #include "HardwareProfile.h"
51  
52  
53 // local definitions
54 //
55 #define PROT_802_3 0x01 // IEEE 802.3 capability
56 #define MAC_COMM_CPBL_MASK (_BMSTAT_BASE10T_HDX_MASK|_BMSTAT_BASE10T_FDX_MASK|_BMSTAT_BASE100TX_HDX_MASK|_BMSTAT_BASE100TX_FDX_MASK)
57 // all comm capabilities our MAC supports
58  
59  
60  
61 // local prototypes
62 //
63  
64 static void _PhyInitIo(void);
65 static int _PhyDetectReset(void);
66  
67  
68  
69 // local data
70 //
71 unsigned int _PhyAdd; // address of the PHY we're talking to
72  
73  
74  
75 // local inlined functions
76 //
77  
78 static __inline__ eEthLinkStat __attribute__((always_inline)) _Phy2LinkStat(__BMSTATbits_t phyStat)
79 {
80 eEthLinkStat linkStat;
81 linkStat=(phyStat.LINK_STAT)?ETH_LINK_ST_UP:ETH_LINK_ST_DOWN;
82 if(phyStat.REM_FAULT)
83 {
84 linkStat|=ETH_LINK_ST_REMOTE_FAULT;
85 }
86  
87 return linkStat;
88 }
89  
90  
91  
92 /****************************************************************************
93 * interface functions
94 ****************************************************************************/
95  
96  
97  
98 /****************************************************************************
99 * Function: EthPhyInit
100 *
101 * PreCondition: - EthInit should have been called.
102 *
103 * Input: oFlags - the requested open flags
104 * cFlags - PHY MII/RMII configuration flags
105 * pResFlags - address to store the initialization result
106 *
107 * Output: ETH_RES_OK for success,
108 * an error code otherwise
109 *
110 *
111 * Side Effects: None
112 *
113 * Overview: This function initializes the PHY communication.
114 * It tries to detect the external PHY, to read the capabilties and find a match
115 * with the requested features.
116 * Then it programs the PHY accordingly.
117 *
118 * Note: None
119 *****************************************************************************/
120 eEthRes __attribute__((weak)) EthPhyInit(eEthOpenFlags oFlags, eEthPhyCfgFlags cFlags, eEthOpenFlags* pResFlags)
121 {
122 unsigned short ctrlReg;
123 eEthPhyCfgFlags hwFlags, swFlags;
124 unsigned short phyCpbl, openReqs, matchCpbl;
125 eEthRes res;
126  
127 // the way the hw is configured
128 hwFlags=(DEVCFG3bits.FMIIEN!=0)?ETH_PHY_CFG_MII:ETH_PHY_CFG_RMII;
129 hwFlags|=(DEVCFG3bits.FETHIO!=0)?ETH_PHY_CFG_DEFAULT:ETH_PHY_CFG_ALTERNATE;
130  
131 if(cFlags&ETH_PHY_CFG_AUTO)
132 {
133 cFlags=hwFlags;
134 }
135 else
136 { // some minimal check against the way the hw is configured
137 swFlags=cFlags&(ETH_PHY_CFG_RMII|ETH_PHY_CFG_ALTERNATE);
138  
139 if((swFlags ^ hwFlags)!=0)
140 { // hw-sw configuration mismatch MII/RMII, ALT/DEF config
141 return ETH_RES_CFG_ERR;
142 }
143 }
144  
145  
146 _PhyAdd=EthPhyMIIMAddress(); // get the PHY address
147  
148  
149 if(oFlags&(ETH_OPEN_PHY_LOOPBACK|ETH_OPEN_MAC_LOOPBACK))
150 {
151 oFlags&=~ETH_OPEN_AUTO; // no negotiation in loopback mode!
152 }
153  
154 if(!(oFlags&ETH_OPEN_AUTO))
155 {
156 oFlags&=~ETH_OPEN_MDIX_AUTO; // Auto-MDIX has to be in auto negotiation only
157 }
158  
159 _PhyInitIo(); // init IO pins
160  
161 EthMIIMInit(GetSystemClock(), EthPhyMIIMClock(), oFlags, (cFlags&ETH_PHY_CFG_RMII)!=0);
162  
163  
164 // try to detect the PHY and reset it
165 if(!_PhyDetectReset())
166 { // failed to detect the PHY
167 return ETH_RES_DTCT_ERR;
168 }
169  
170 // provide some defaults
171 if(!(oFlags&(ETH_OPEN_FDUPLEX|ETH_OPEN_HDUPLEX)))
172 {
173 oFlags|=ETH_OPEN_HDUPLEX;
174 }
175 if(!(oFlags&(ETH_OPEN_100|ETH_OPEN_10)))
176 {
177 oFlags|=ETH_OPEN_10;
178 }
179  
180 if(oFlags&ETH_OPEN_AUTO)
181 { // advertise auto negotiation
182 openReqs=_BMSTAT_AN_ABLE_MASK;
183  
184 if(oFlags&ETH_OPEN_100)
185 {
186 if(oFlags&ETH_OPEN_FDUPLEX)
187 {
188 openReqs|=_BMSTAT_BASE100TX_FDX_MASK;
189 }
190 if(oFlags&ETH_OPEN_HDUPLEX)
191 {
192 openReqs|=_BMSTAT_BASE100TX_HDX_MASK;
193 }
194 }
195  
196 if(oFlags&ETH_OPEN_10)
197 {
198 if(oFlags&ETH_OPEN_FDUPLEX)
199 {
200 openReqs|=_BMSTAT_BASE10T_FDX_MASK;
201 }
202 if(oFlags&ETH_OPEN_HDUPLEX)
203 {
204 openReqs|=_BMSTAT_BASE10T_HDX_MASK;
205 }
206 }
207 }
208 else
209 { // no auto negotiation
210 if(oFlags&ETH_OPEN_100)
211 {
212 openReqs=(oFlags&ETH_OPEN_FDUPLEX)?_BMSTAT_BASE100TX_FDX_MASK:_BMSTAT_BASE100TX_HDX_MASK;
213 }
214 else
215 {
216 openReqs=(oFlags&ETH_OPEN_FDUPLEX)?_BMSTAT_BASE10T_FDX_MASK:_BMSTAT_BASE10T_HDX_MASK;
217 }
218 }
219  
220 // try to match the oFlags with the PHY capabilities
221 phyCpbl=EthMIIMReadReg(PHY_REG_BMSTAT, _PhyAdd);
222 matchCpbl=(openReqs&(MAC_COMM_CPBL_MASK|_BMSTAT_AN_ABLE_MASK))&phyCpbl; // common features
223 if(!(matchCpbl&MAC_COMM_CPBL_MASK))
224 { // no match?
225 return ETH_RES_CPBL_ERR;
226 }
227  
228 // we're ok, we can configure the PHY
229 res=EthPhyConfigureMII(cFlags);
230 if(res!=ETH_RES_OK)
231 {
232 return res;
233 }
234  
235 res=EthPhyConfigureMdix(oFlags);
236 if(res!=ETH_RES_OK)
237 {
238 return res;
239 }
240  
241 if(matchCpbl&_BMSTAT_AN_ABLE_MASK)
242 { // ok, we can perform auto negotiation
243 unsigned short anadReg;
244  
245 anadReg=(((matchCpbl>>_BMSTAT_NEGOTIATION_POS)<<_ANAD_NEGOTIATION_POS)&_ANAD_NEGOTIATION_MASK)|PROT_802_3;
246 if(MAC_PAUSE_CPBL_MASK&MAC_PAUSE_TYPE_PAUSE)
247 {
248 anadReg|=_ANAD_PAUSE_MASK;
249 }
250 if(MAC_PAUSE_CPBL_MASK&MAC_PAUSE_TYPE_ASM_DIR)
251 {
252 anadReg|=_ANAD_ASM_DIR_MASK;
253 }
254  
255 EthMIIMWriteReg(PHY_REG_ANAD, _PhyAdd, anadReg); // advertise our capabilities
256  
257 EthPhyRestartNegotiation(); // restart negotiation and we'll have to wait
258 }
259 else
260 { // ok, just don't use negotiation
261  
262 ctrlReg=0;
263 if(matchCpbl&(_BMSTAT_BASE100TX_HDX_MASK|_BMSTAT_BASE100TX_FDX_MASK)) // set 100Mbps request/capability
264 {
265 ctrlReg|=_BMCON_SPEED_MASK;
266 }
267  
268 if(matchCpbl&(_BMSTAT_BASE10T_FDX_MASK|_BMSTAT_BASE100TX_FDX_MASK))
269 {
270 ctrlReg|=_BMCON_DUPLEX_MASK;
271 }
272  
273 if(oFlags&ETH_OPEN_PHY_LOOPBACK)
274 {
275 ctrlReg|=_BMCON_LOOPBACK_MASK;
276 }
277  
278 EthMIIMWriteReg(PHY_REG_BMCON, _PhyAdd, ctrlReg); // update the configuration
279 }
280  
281  
282 // now update the open flags
283 // the upper layer needs to know the PHY set-up to further set-up the MAC.
284  
285 // clear the capabilities
286 oFlags&=~(ETH_OPEN_AUTO|ETH_OPEN_FDUPLEX|ETH_OPEN_HDUPLEX|ETH_OPEN_100|ETH_OPEN_10);
287  
288 if(matchCpbl&_BMSTAT_AN_ABLE_MASK)
289 {
290 oFlags|=ETH_OPEN_AUTO;
291 }
292 if(matchCpbl&(_BMSTAT_BASE100TX_HDX_MASK|_BMSTAT_BASE100TX_FDX_MASK)) // set 100Mbps request/capability
293 {
294 oFlags|=ETH_OPEN_100;
295 }
296 if(matchCpbl&(_BMSTAT_BASE10T_HDX_MASK|_BMSTAT_BASE10T_FDX_MASK)) // set 10Mbps request/capability
297 {
298 oFlags|=ETH_OPEN_10;
299 }
300 if(matchCpbl&(_BMSTAT_BASE10T_FDX_MASK|_BMSTAT_BASE100TX_FDX_MASK))
301 {
302 oFlags|=ETH_OPEN_FDUPLEX;
303 }
304 if(matchCpbl&(_BMSTAT_BASE10T_HDX_MASK|_BMSTAT_BASE100TX_HDX_MASK))
305 {
306 oFlags|=ETH_OPEN_HDUPLEX;
307 }
308  
309 *pResFlags=oFlags; // upper layer needs to know the PHY set-up to further set-up the MAC.
310  
311 return ETH_RES_OK;
312  
313 }
314  
315  
316 /****************************************************************************
317 * Function: EthPhyRestartNegotiation
318 *
319 * PreCondition: - EthPhyInit should have been called.
320 * - The PHY should have been initialized with proper duplex/speed mode!
321 *
322 * Input: None
323 *
324 * Output: ETH_RES_OK for success,
325 * ETH_RES_NEGOTIATION_UNABLE if the auto-negotiation is not supported.
326 *
327 * Side Effects: None
328 *
329 * Overview: This function restarts the PHY negotiation.
330 * After this restart the link can be reconfigured.
331 * The EthPhyGetNegotiationResults() can be used to see the outcoming result.
332 *
333 * Note: None
334 *****************************************************************************/
335 eEthRes __attribute__((weak)) EthPhyRestartNegotiation(void)
336 {
337 eEthRes res;
338 __BMSTATbits_t phyCpbl;
339  
340 phyCpbl.w=EthMIIMReadReg(PHY_REG_BMSTAT, _PhyAdd);
341  
342 if(phyCpbl.AN_ABLE)
343 { // ok, we can perform auto negotiation
344 EthMIIMWriteReg(PHY_REG_BMCON, _PhyAdd, _BMCON_AN_ENABLE_MASK|_BMCON_AN_RESTART_MASK); // restart negotiation and we'll have to wait
345 res=ETH_RES_OK;
346 }
347 else
348 {
349 res=ETH_RES_NEGOTIATION_UNABLE; // no negotiation ability!
350 }
351  
352 return res;
353 }
354  
355  
356  
357 /****************************************************************************
358 * Function: EthPhyNegotiationComplete
359 *
360 * PreCondition: EthPhyInit (and EthPhyRestartNegotiation) should have been called.
361 *
362 * Input: waitComplete - if wait for completion needed
363 *
364 * Output: ETH_RES_OK if negotiation done,
365 * ETH_RES_NEGOTIATION_INACTIVE if no negotiation in progress
366 * ETH_RES_NEGOTIATION_NOT_STARTED if negotiation not started yet (means tmo if waitComplete was requested)
367 * ETH_RES_NEGOTIATION_ACTIVE if negotiation ongoing (means tmo if waitComplete was requested)
368 *
369 * Side Effects: None
370 *
371 * Overview: This function waits for a previously initiated PHY negotiation to complete.
372 * Subsequently, EthPhyGetNegotiationResult() can be called.
373 *
374 * Note: None
375 *****************************************************************************/
376 eEthRes __attribute__((weak)) EthPhyNegotiationComplete(int waitComplete)
377 {
378 __BMCONbits_t phyBMCon;
379 __BMSTATbits_t phyStat;
380 eEthRes res;
381  
382 phyBMCon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd);
383 if(phyBMCon.AN_ENABLE)
384 { // just protect from an accidental call
385 phyBMCon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd);
386 phyStat.w=EthMIIMReadReg(PHY_REG_BMSTAT, _PhyAdd);
387  
388 if(waitComplete)
389 {
390 unsigned int tStart, tWait;
391  
392 if(phyBMCon.AN_RESTART)
393 { // not started yet
394 tWait=(GetSystemClock()/2000)*PHY_NEG_INIT_TMO;
395 tStart=ReadCoreTimer();
396 do
397 {
398 phyBMCon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd);
399 }while(phyBMCon.AN_RESTART && (ReadCoreTimer()-tStart)<tWait); // wait auto negotiation start
400 }
401  
402 if(!phyBMCon.AN_RESTART)
403 { // ok, started
404 tWait=(GetSystemClock()/2000)*PHY_NEG_DONE_TMO;
405 tStart=ReadCoreTimer();
406 do
407 {
408 phyStat.w=EthMIIMReadReg(PHY_REG_BMSTAT, _PhyAdd);
409 }while(phyStat.AN_COMPLETE==0 && (ReadCoreTimer()-tStart)<tWait); // wait auto negotiation done
410  
411 phyStat.w=EthMIIMReadReg(PHY_REG_BMSTAT, _PhyAdd);
412 }
413 }
414 }
415  
416 if(!phyBMCon.AN_ENABLE)
417 {
418 res=ETH_RES_NEGOTIATION_INACTIVE; // no negotiation is taking place!
419 }
420 else if(phyBMCon.AN_RESTART)
421 {
422 res=ETH_RES_NEGOTIATION_NOT_STARTED; // not started yet/tmo
423 }
424 else
425 {
426 res= (phyStat.AN_COMPLETE==0)?ETH_RES_NEGOTIATION_ACTIVE:ETH_RES_OK; // active/tmo/ok
427 }
428  
429 return res;
430 }
431  
432  
433  
434 /****************************************************************************
435 * Function: EthPhyGetNegotiationResult
436 *
437 * PreCondition: EthPhyInit, EthPhyRestartNegotiation and EthPhyNegotiationComplete should have been called.
438 *
439 * Input: pFlags - address to store the negotiation result
440 * pPauseType - address to store the pause type supported by the LP
441 *
442 * Output: the link status after the (completed) negotiation
443 *
444 * Side Effects: None
445 *
446 * Overview: This function returns the result of a previously initiated negotiation.
447 * The result is based on the PHY status!.
448 *
449 * Note: If no negotiation possible/active/failed, most likely the flags are invalid!
450 *****************************************************************************/
451 eEthLinkStat __attribute__((weak)) EthPhyGetNegotiationResult(eEthOpenFlags* pFlags, eMacPauseType* pPauseType)
452 {
453 eEthLinkStat linkStat;
454 eEthOpenFlags oFlags;
455 __BMSTATbits_t phyStat;
456 __ANEXPbits_t phyExp;
457 __ANLPADbits_t lpAD;
458 __ANADbits_t anadReg;
459 eMacPauseType pauseType;
460  
461  
462 // should have BMCON.AN_ENABLE==1
463 // wait for it to finish!
464  
465  
466 oFlags=0; // don't know the result yet
467 pauseType=MAC_PAUSE_TYPE_NONE;
468  
469 phyStat.w=EthMIIMReadReg(PHY_REG_BMSTAT, _PhyAdd);
470 if(phyStat.AN_COMPLETE==0)
471 {
472 linkStat=(ETH_LINK_ST_DOWN|ETH_LINK_ST_NEG_TMO);
473 }
474 else if(!phyStat.LINK_STAT)
475 {
476 linkStat=ETH_LINK_ST_DOWN;
477 }
478 else
479 { // we're up and running
480 int lcl_Pause, lcl_AsmDir, lp_Pause, lp_AsmDir; // pause capabilities, local and LP
481  
482 linkStat=ETH_LINK_ST_UP;
483  
484 lcl_Pause=(MAC_PAUSE_CPBL_MASK&MAC_PAUSE_TYPE_PAUSE)?1:0;
485 lcl_AsmDir=(MAC_PAUSE_CPBL_MASK&MAC_PAUSE_TYPE_ASM_DIR)?1:0;
486 lp_Pause=lp_AsmDir=0; // in case negotiation fails
487 lpAD.w=_ANAD_BASE10T_MASK; // lowest priority resolution
488  
489 phyExp.w=EthMIIMReadReg(PHY_REG_ANEXP, _PhyAdd);
490 if(phyExp.LP_AN_ABLE)
491 { // ok,valid auto negotiation info
492  
493 lpAD.w=EthMIIMReadReg(PHY_REG_ANLPAD, _PhyAdd);
494 if(lpAD.REM_FAULT)
495 {
496 linkStat|=ETH_LINK_ST_REMOTE_FAULT;
497 }
498  
499 if(lpAD.PAUSE)
500 {
501 linkStat|=ETH_LINK_ST_LP_PAUSE;
502 lp_Pause=1;
503 }
504 if(lpAD.ASM_DIR)
505 {
506 linkStat|=ETH_LINK_ST_LP_ASM_DIR;
507 lp_AsmDir=1;
508 }
509  
510 }
511 else
512 {
513 linkStat|=ETH_LINK_ST_LP_NEG_UNABLE;
514 if(phyExp.PDF)
515 {
516 linkStat|=ETH_LINK_ST_PDF;
517 }
518 }
519  
520 // set the PHY connection params
521  
522 anadReg.w=EthMIIMReadReg(PHY_REG_ANAD, _PhyAdd); // get our advertised capabilities
523 anadReg.w&=lpAD.w; // get the matching ones
524 // get the settings, according to IEEE 802.3 Annex 28B.3 Priority Resolution
525 // Note: we don't support 100BaseT4 !
526  
527 if(anadReg.w&_ANAD_BASE100TX_FDX_MASK)
528 {
529 oFlags=(ETH_OPEN_100|ETH_OPEN_FDUPLEX);
530 }
531 else if(anadReg.w&_ANAD_BASE100TX_MASK)
532 {
533 oFlags=(ETH_OPEN_100|ETH_OPEN_HDUPLEX);
534 }
535 else if(anadReg.w&_ANAD_BASE10T_FDX_MASK)
536 {
537 oFlags=(ETH_OPEN_10|ETH_OPEN_FDUPLEX);
538 }
539 else if(anadReg.w&_ANAD_BASE10T_MASK)
540 {
541 oFlags=(ETH_OPEN_10|ETH_OPEN_HDUPLEX);
542 }
543 else
544 { // this should NOT happen!
545 linkStat|=ETH_LINK_ST_NEG_FATAL_ERR;
546 linkStat&=~ETH_LINK_ST_UP; // make sure we stop...!
547 }
548  
549  
550 // set the pause type for the MAC
551 // according to IEEE Std 802.3-2002 Tables 28B-2, 28B-3
552 if(oFlags&ETH_OPEN_FDUPLEX)
553 { // pause type relevant for full duplex only
554 if(lp_Pause & (lcl_Pause|(lcl_AsmDir&lp_AsmDir)))
555 {
556 pauseType=MAC_PAUSE_TYPE_EN_TX;
557 }
558 if(lcl_Pause & (lp_Pause | (lcl_AsmDir&lp_AsmDir)))
559 {
560 pauseType|=MAC_PAUSE_TYPE_EN_RX;
561 }
562 }
563 }
564  
565 if(pFlags)
566 {
567 *pFlags=oFlags;
568 }
569  
570 if(pPauseType)
571 {
572 *pPauseType=pauseType;
573 }
574 return linkStat;
575 }
576  
577 /****************************************************************************
578 * Function: EthPhyGetLinkStatus
579 *
580 * PreCondition: EthPhyInit should have been called.
581 *
582 * Input: refresh - boolean to specify if double read is needed.
583 *
584 * Output: the current link status
585 *
586 * Side Effects: None
587 *
588 * Overview: This function reads the PHY to get current link status
589 * If refresh is specified then, if the link is down a second read
590 * will be performed to return the current link status.
591 *
592 * Note: None
593 *****************************************************************************/
594 eEthLinkStat __attribute__((weak)) EthPhyGetLinkStatus(int refresh)
595 {
596 __BMSTATbits_t phyStat;
597  
598 // read the link status
599 phyStat.w=EthMIIMReadReg(PHY_REG_BMSTAT, _PhyAdd);
600 if(phyStat.LINK_STAT==0 && refresh)
601 { // link down could be an old condition. re-read
602 phyStat.w=EthMIIMReadReg(PHY_REG_BMSTAT, _PhyAdd);
603 }
604  
605 return _Phy2LinkStat(phyStat);
606 }
607  
608  
609 /****************************************************************************
610 * Function: EthPhyReset
611 *
612 * PreCondition: EthPhyInit() should have been called
613 * Communication with the PHY already established
614 *
615 * Input: waitComplete - if TRUE the procedure will wait for reset to complete
616 *
617 * Output: TRUE if the reset procedure completed (or completion not required)
618 * FALSE otherwise
619 *
620 * Side Effects: None
621 *
622 * Overview: This function immediately resets the PHY.
623 * It does not wait for the reset procedure to complete
624 *
625 * Note: None
626 *****************************************************************************/
627 int __attribute__((weak)) EthPhyReset(int waitComplete)
628 {
629  
630 EthMIIMWriteReg(PHY_REG_BMCON, _BMCON_RESET_MASK, _PhyAdd); // Soft Reset the PHY
631  
632 if(waitComplete)
633 { // wait reset self clear
634 __BMCONbits_t bmcon;
635 unsigned int tStart, tWaitReset;
636  
637 tWaitReset=(GetSystemClock()/2000)*PHY_RESET_CLR_TMO;
638 tStart=ReadCoreTimer();
639 do
640 {
641 bmcon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd);
642 }while(bmcon.RESET && (ReadCoreTimer()-tStart)<tWaitReset);
643  
644 bmcon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd);
645 if(bmcon.RESET)
646 { // tmo clearing the reset
647 return 0;
648 }
649 }
650  
651 return 1;
652  
653 }
654  
655  
656  
657 /****************************************************************************
658 * Function: EthPhyScanLinkStart
659 *
660 * PreCondition: EthPhyInit() should have been called
661 * Communication with the PHY already established
662 *
663 * Input: None
664 *
665 * Output: None
666 *
667 * Side Effects: None
668 *
669 * Overview: This function starts a scan of the PHY link status register.
670 * It is meant as a more efficient way of having access to the current link status
671 * since the normal MIIM frame read operation is pretty lengthy.
672 *
673 * Note: Any PHY register can be subject of a scan.
674 * The application should use the MIIM access functions of the Ethernet plib abd the specific PHY knowledge.
675 *****************************************************************************/
676 void __attribute__((weak)) EthPhyScanLinkStart(void)
677 {
678 EthMIIMScanStart(PHY_REG_BMSTAT, _PhyAdd);
679 }
680  
681 /****************************************************************************
682 * Function: EthPhyScanLinkRead
683 *
684 * PreCondition: EthPhyInit() should have been called
685 * Communication with the PHY already established
686 * A PHY scan operation should have been started.
687 *
688 * Input: None
689 *
690 * Output: the current link status as being updated by the current scan in progress
691 *
692 * Side Effects: None
693 *
694 * Overview: This function returns the current result of a scan operation.
695 * The last updated value is returned.
696 * There's no way of knowing when effectively this last update occurred.
697 *
698 * Note: None
699 *****************************************************************************/
700 eEthLinkStat __attribute__((weak)) EthPhyScanLinkRead(void)
701 {
702 __BMSTATbits_t phyStat;
703  
704 phyStat.w=EthMIIMScanRead();
705  
706 return _Phy2LinkStat(phyStat);
707 }
708  
709  
710 /****************************************************************************
711 * Function: EthPhyScanLinkStop
712 *
713 * PreCondition: EthPhyInit() should have been called
714 * Communication with the PHY already established
715 * A PHY scan operation should have been started.
716 *
717 * Input: None
718 *
719 * Output: None
720 *
721 * Side Effects: None
722 *
723 * Overview: This function stops a previously started PHY scan.
724 *
725 * Note: The scan operation shouldn't interfere with normal read operations.
726 * Therefore the scan operation should be stopped before initiating another
727 * normal MIIM transaction
728 *****************************************************************************/
729 void __attribute__((weak)) EthPhyScanLinkStop(void)
730 {
731 EthMIIMScanStop();
732 }
733  
734  
735  
736  
737 /****************************************************************************
738 * local functions
739 ****************************************************************************/
740  
741  
742 /****************************************************************************
743 * Function: _PhyInitIo
744 *
745 * PreCondition: None
746 *
747 * Input: None
748 *
749 * Output: None
750 *
751 * Side Effects: None
752 *
753 * Overview: Helper to properly set the Eth i/o pins to digital pins.
754 *
755 * Note: Even when the Eth device is turned on the analog shared pins have to be configured.
756 *****************************************************************************/
757 static void _PhyInitIo(void)
758 {
759 __DEVCFG3bits_t bcfg3;
760  
761 bcfg3=DEVCFG3bits;
762 if(bcfg3.FETHIO)
763 { // default setting, both RMII and MII
764 PORTSetPinsDigitalOut(_ETH_MDC_PORT, _ETH_MDC_BIT);
765 PORTSetPinsDigitalIn(_ETH_MDIO_PORT, _ETH_MDIO_BIT);
766  
767 PORTSetPinsDigitalOut(_ETH_TXEN_PORT, _ETH_TXEN_BIT);
768 PORTSetPinsDigitalOut(_ETH_TXD0_PORT, _ETH_TXD0_BIT);
769 PORTSetPinsDigitalOut(_ETH_TXD1_PORT, _ETH_TXD1_BIT);
770  
771  
772 PORTSetPinsDigitalIn(_ETH_RXCLK_PORT, _ETH_RXCLK_BIT);
773 PORTSetPinsDigitalIn(_ETH_RXDV_PORT, _ETH_RXDV_BIT);
774 PORTSetPinsDigitalIn(_ETH_RXD0_PORT, _ETH_RXD0_BIT);
775 PORTSetPinsDigitalIn(_ETH_RXD1_PORT, _ETH_RXD1_BIT);
776 PORTSetPinsDigitalIn(_ETH_RXERR_PORT, _ETH_RXERR_BIT);
777  
778  
779 if(bcfg3.FMIIEN)
780 { // just MII
781 PORTSetPinsDigitalIn(_ETH_TXCLK_PORT, _ETH_TXCLK_BIT);
782 PORTSetPinsDigitalOut(_ETH_TXD2_PORT, _ETH_TXD2_BIT);
783 PORTSetPinsDigitalOut(_ETH_TXD3_PORT, _ETH_TXD3_BIT);
784 PORTSetPinsDigitalOut(_ETH_TXERR_PORT, _ETH_TXERR_BIT);
785  
786 PORTSetPinsDigitalIn(_ETH_RXD2_PORT, _ETH_RXD2_BIT);
787 PORTSetPinsDigitalIn(_ETH_RXD3_PORT, _ETH_RXD3_BIT);
788 PORTSetPinsDigitalIn(_ETH_CRS_PORT, _ETH_CRS_BIT);
789 PORTSetPinsDigitalIn(_ETH_COL_PORT, _ETH_COL_BIT);
790 }
791 }
792 else
793 { // alternate setting, both RMII and MII
794 PORTSetPinsDigitalOut(_ETH_ALT_MDC_PORT, _ETH_ALT_MDC_BIT);
795 PORTSetPinsDigitalIn(_ETH_ALT_MDIO_PORT, _ETH_ALT_MDIO_BIT);
796  
797 PORTSetPinsDigitalOut(_ETH_ALT_TXEN_PORT, _ETH_ALT_TXEN_BIT);
798 PORTSetPinsDigitalOut(_ETH_ALT_TXD0_PORT, _ETH_ALT_TXD0_BIT);
799 PORTSetPinsDigitalOut(_ETH_ALT_TXD1_PORT, _ETH_ALT_TXD1_BIT);
800  
801  
802 PORTSetPinsDigitalIn(_ETH_ALT_RXCLK_PORT, _ETH_ALT_RXCLK_BIT);
803 PORTSetPinsDigitalIn(_ETH_ALT_RXDV_PORT, _ETH_ALT_RXDV_BIT);
804 PORTSetPinsDigitalIn(_ETH_ALT_RXD0_PORT, _ETH_ALT_RXD0_BIT);
805 PORTSetPinsDigitalIn(_ETH_ALT_RXD1_PORT, _ETH_ALT_RXD1_BIT);
806 PORTSetPinsDigitalIn(_ETH_ALT_RXERR_PORT, _ETH_ALT_RXERR_BIT);
807  
808  
809 if(bcfg3.FMIIEN)
810 { // just MII
811 PORTSetPinsDigitalIn(_ETH_ALT_TXCLK_PORT, _ETH_ALT_TXCLK_BIT);
812 PORTSetPinsDigitalOut(_ETH_ALT_TXD2_PORT, _ETH_ALT_TXD2_BIT);
813 PORTSetPinsDigitalOut(_ETH_ALT_TXD3_PORT, _ETH_ALT_TXD3_BIT);
814 PORTSetPinsDigitalOut(_ETH_ALT_TXERR_PORT, _ETH_ALT_TXERR_BIT);
815  
816 PORTSetPinsDigitalIn(_ETH_ALT_RXD2_PORT, _ETH_ALT_RXD2_BIT);
817 PORTSetPinsDigitalIn(_ETH_ALT_RXD3_PORT, _ETH_ALT_RXD3_BIT);
818 PORTSetPinsDigitalIn(_ETH_ALT_CRS_PORT, _ETH_ALT_CRS_BIT);
819 PORTSetPinsDigitalIn(_ETH_ALT_COL_PORT, _ETH_ALT_COL_BIT);
820 }
821  
822 }
823 }
824  
825  
826 /****************************************************************************
827 * Function: _PhyDetectReset
828 *
829 * PreCondition: EthMIIMInit() should have been called
830 *
831 * Input: None
832 *
833 * Output: TRUE if the detection and the reset of the PHY succeeded,
834 * FALSE if no PHY detected
835 *
836 * Side Effects: None
837 *
838 * Overview: This function detects and resets the PHY.
839 *
840 * Note: Needs the system running frequency to for the PHY detection
841 *****************************************************************************/
842 static int _PhyDetectReset(void)
843 {
844 __BMCONbits_t bmcon;
845 unsigned int tStart, tWaitReset;
846  
847 bmcon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd); // read the BMCON register
848  
849 if(bmcon.RESET)
850 { // that is already suspicios...but give it a chance to clear itself
851 tWaitReset=(GetSystemClock()/2000)*PHY_RESET_CLR_TMO;
852 tStart=ReadCoreTimer();
853 do
854 {
855 bmcon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd);
856 }while(bmcon.RESET && (ReadCoreTimer()-tStart)<tWaitReset); // wait reset self clear
857  
858 bmcon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd);
859 if(bmcon.RESET)
860 { // tmo clearing the reset
861 return 0;
862 }
863 }
864  
865 // ok, reset bit is low
866 // try to see if we can write smth to the PHY
867 // we use Loopback and Isolate bits
868 EthMIIMWriteReg(PHY_REG_BMCON, _PhyAdd, _BMCON_LOOPBACK_MASK|_BMCON_ISOLATE_MASK); // write control bits
869 bmcon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd); // read back
870 if(bmcon.LOOPBACK==0 || bmcon.ISOLATE==0)
871 { // failed to set
872 return 0;
873 }
874 bmcon.w^=_BMCON_LOOPBACK_MASK|_BMCON_ISOLATE_MASK;
875 EthMIIMWriteReg(PHY_REG_BMCON, _PhyAdd, bmcon.w); // clear bits and write
876 bmcon.w=EthMIIMReadReg(PHY_REG_BMCON, _PhyAdd); // read back
877 if(bmcon.LOOPBACK || bmcon.ISOLATE)
878 { // failed to clear
879 return 0;
880 }
881  
882 // everything seems to be fine
883 //
884 return EthPhyReset(1);
885 }
886  
887  
888 #endif // defined(__PIC32MX__) && defined(_ETH) // ETHC present
889  
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3