openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

phy5690.c (31011B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:
      8  *	phy5690.c
      9  * Purpose:
     10  *	Fiber driver for 5690 using internal QuadSerdes PHY.
     11  *
     12  * For BCM5690, the internal GMACC core of the GPIC should always be
     13  * configured to run in SGMII mode.  TBI mode is not supported between
     14  * the GMACC and the internal SERDES module.
     15  * 
     16  * When operating with an external PHY, this driver is not used.
     17  * However the speed/duplex of the internal PHY must be programmed to
     18  * match the MAC and external PHY settings so the data can pass through.
     19  * This file supplies some routines to allow mac.c to accomplish this
     20  * (think of the internal PHY as part of the MAC in this case):
     21  *
     22  *	_phy_5690_notify_duplex
     23  *	_phy_5690_notify_speed
     24  *	_phy_5690_notify_stop
     25  *	_phy_5690_notify_resume
     26  *
     27  * CMIC MIIM operations can be performed to the internal register set
     28  * using internal MDIO address (PORT_TO_PHY_ADDR_INT), and an external
     29  * PHY register set (such as BCM5424/34/64) can be programmed using the
     30  * external MDIO address (PORT_TO_PHY_ADDR).
     31  *
     32  * MDIO accesses to the internal PHY are not modeled on Quickturn.
     33  */
     34 
     35 #include <sal/types.h>
     36 #include <sal/core/spl.h>
     37 #include <shared/bsl.h>
     38 #include <soc/drv.h>
     39 #include <soc/debug.h>
     40 #include <soc/error.h>
     41 #include <soc/phyreg.h>
     42 
     43 #include <soc/phy.h>
     44 #include <soc/phy/phyctrl.h>
     45 #include <soc/phy/drv.h>
     46 
     47 #include "phyident.h"
     48 #include "phyreg.h"
     49 #include "phynull.h"
     50 #include "phy5690.h"
     51 
     52 #if	defined(BCM_5690) && defined(BCM_ESW_SUPPORT)
     53 
     54 #define PHY_5690_AN_STATE_ACCESS_INTERVAL 60000 /* 60000 Usec */
     55 
     56 #define PHY_5690_AN_TIME(_pc) \
     57 	((_pc)->an_state_time)
     58 #define PHY_5690_AN_VALID(_pc) \
     59 	((_pc)->an_state_valid)
     60 #define PHY_5690_SGMII_STATE(_pc) \
     61 	((_pc)->sgmii_an_state)
     62 
     63 #define PHY_5690_AN_RECORD_TIME(_pc)  \
     64 	((_pc)->an_state_time) = sal_time_usecs()
     65 #define PHY_5690_AN_RECORD_STATE(_pc, _state) \
     66 	((_pc)->sgmii_an_state) = (_state)
     67 #define PHY_5690_AN_VALID_SET(_pc) \
     68 	((_pc)->an_state_valid) = TRUE
     69 #define PHY_5690_AN_VALID_RESET(_pc) \
     70 	((_pc)->an_state_valid) = FALSE
     71 
     72 #define	PHY_5690_AN_ACCESS_TIMEOUT(_pc) \
     73 	((uint32)SAL_USECS_SUB(sal_time_usecs(), PHY_5690_AN_TIME((_pc))) \
     74 		>= PHY_5690_AN_STATE_ACCESS_INTERVAL)
     75 
     76 STATIC int
     77 _phy_5690_notify_resume(int unit, soc_port_t port, uint32 data);
     78 STATIC int
     79 _phy_5690_notify_stop(int unit, soc_port_t port, uint32 data);
     80 STATIC int
     81 _phy_5690_notify_interface(int unit, soc_port_t port, uint32 data);
     82 STATIC int
     83 _phy_5690_notify_duplex(int unit, soc_port_t port, uint32 data);
     84 STATIC int
     85 _phy_5690_notify_speed(int unit, soc_port_t port, uint32 data); 
     86 
     87 /***********************************************************************
     88  *
     89  * FIBER DRIVER ROUTINES
     90  */
     91 
     92 /*
     93  * Function:
     94  *	phy_5690_init
     95  * Purpose:	
     96  *	Initialize 5690 internal PHY driver
     97  * Parameters:
     98  *	unit - StrataSwitch unit #.
     99  *	port - StrataSwitch port #. 
    100  * Returns:	
    101  *	SOC_E_NONE
    102  */
    103 
    104 STATIC int
    105 phy_5690_init(int unit, soc_port_t port)
    106 {
    107     uint16		ctrl;
    108     phy_ctrl_t         *pc;
    109 
    110     pc       = INT_PHY_SW_STATE(unit, port);
    111     LOG_INFO(BSL_LS_SOC_PHY,
    112              (BSL_META_U(unit,
    113                          "phy_5690_init: u=%d p=%d\n"),
    114               unit, port));
    115 
    116     if (soc_feature(unit, soc_feature_phy_5690_link_war)) {
    117 	PHY_5690_AN_VALID_RESET(pc);
    118     }
    119 
    120     /*
    121      * The internal SERDES PHY's reset bit must be held high for at
    122      * least 1 usec and is not self-clearing.
    123      */
    124 
    125     SOC_IF_ERROR_RETURN
    126 	(READ_PHY_REG(unit, pc,
    127 		       QS_MII_CTRL_REG, &ctrl));
    128 
    129     ctrl |= QS_MII_CTRL_RESET;
    130 
    131     SOC_IF_ERROR_RETURN
    132 	(WRITE_PHY_REG(unit, pc, QS_MII_CTRL_REG, ctrl));
    133 
    134     sal_usleep(1);
    135 
    136     ctrl = QS_MII_CTRL_SS_1000 | QS_MII_CTRL_FD;
    137 
    138     SOC_IF_ERROR_RETURN
    139 	(WRITE_PHY_REG(unit, pc, QS_MII_CTRL_REG, ctrl));
    140 
    141     sal_usleep(10000);
    142 
    143     SOC_IF_ERROR_RETURN
    144 	(READ_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, &ctrl));
    145     ctrl &= ~QS_SGMII_TBI_LOOP;
    146     SOC_IF_ERROR_RETURN
    147         (WRITE_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, ctrl));
    148     
    149     SOC_IF_ERROR_RETURN
    150 	(WRITE_PHY_REG(unit, pc, QS_SGMII_CTRL2_REG, 
    151                       (PHY_COPPER_MODE(unit, port) ? 0 : QS_SGMII_FIBER_MODE)));
    152 
    153     return SOC_E_NONE;
    154 }
    155 
    156 
    157 /*
    158  * Function:
    159  *	_phy_5690_war_link_get
    160  * Purpose:
    161  *	Perform Link get work-around
    162  * Parameters:
    163  *	unit - StrataSwitch unit #.
    164  *	port - StrataSwitch port #. 
    165  *	link - (OUT) Boolean, true indicates link established.
    166  * Returns:
    167  *	SOC_E_XXX
    168  * Notes:
    169  *	This is the workaround for GNATS 3711, QS_SGMII_STAT_REG does
    170  *	not properly reflect the link up/down state.  However, it is
    171  *	possible to divine the true link state using the autonegotiation
    172  *	state debug register, in combination with its latching behavior
    173  *	and certain timing requirements.
    174  */
    175 
    176 STATIC int
    177 _phy_5690_war_link_get(int unit, soc_port_t port, int *link)
    178 {
    179     uint16		sgmii_an_state;
    180     uint16		sgmii_misc_ctrl;
    181     uint16		sgmii_stat;
    182     phy_ctrl_t         *pc;
    183 
    184     pc       = INT_PHY_SW_STATE(unit, port);
    185 
    186     if ((PHY_5690_AN_ACCESS_TIMEOUT(pc)) || 
    187 	(!PHY_5690_AN_VALID(pc))) {
    188         SOC_IF_ERROR_RETURN
    189 	    (READ_PHY_REG(unit, pc, QS_SGMII_STAT_REG, &sgmii_stat));
    190 
    191         sgmii_an_state = sgmii_stat & 0x0ff0;
    192 
    193         *link = ((sgmii_an_state == 0x0770 || sgmii_an_state == 0x0880) &&
    194 		 PHY_5690_AN_VALID(pc));
    195 
    196         /* Get a snapshot of AN state into QS_SGMII_STAT_REG */
    197 
    198         if (!(*link)) {
    199             SOC_IF_ERROR_RETURN
    200 		(READ_PHY_REG(unit, pc,
    201 			       QS_SGMII_MISC_CTRL_REG, &sgmii_misc_ctrl));
    202             sgmii_misc_ctrl &= ~0x0010;
    203             SOC_IF_ERROR_RETURN
    204 		(WRITE_PHY_REG(unit, pc,
    205 				QS_SGMII_MISC_CTRL_REG, sgmii_misc_ctrl));
    206             sgmii_misc_ctrl |= 0x0010;
    207             SOC_IF_ERROR_RETURN
    208 		(WRITE_PHY_REG(unit, pc,
    209 				QS_SGMII_MISC_CTRL_REG, sgmii_misc_ctrl));
    210             sgmii_an_state = 0;
    211         }
    212 
    213         PHY_5690_AN_RECORD_TIME(pc);
    214         PHY_5690_AN_RECORD_STATE(pc, sgmii_an_state);
    215         PHY_5690_AN_VALID_SET(pc);
    216     } else {
    217         sgmii_an_state = PHY_5690_SGMII_STATE(pc);
    218 
    219         *link = (sgmii_an_state == 0x0770 || sgmii_an_state == 0x0880);
    220 
    221         /* Check if link went down */
    222 
    223         if (*link) {
    224             SOC_IF_ERROR_RETURN
    225 		(READ_PHY_REG(unit, pc,
    226 			       QS_SGMII_STAT_REG, &sgmii_stat));
    227 
    228             sgmii_an_state = sgmii_stat & 0x0ff0;
    229 
    230             *link = (sgmii_an_state == 0x0770 || sgmii_an_state == 0x0880);
    231 
    232             PHY_5690_AN_RECORD_STATE(pc, sgmii_an_state);
    233         }
    234     }
    235 
    236     return SOC_E_NONE;
    237 }
    238 
    239 
    240 /*
    241  * Function: 	
    242  *	phy_5690_link_get
    243  * Purpose:	
    244  *	Determine the current link up/down status
    245  * Parameters:
    246  *	unit - StrataSwitch unit #.
    247  *	port - StrataSwitch port #. 
    248  *	link - (OUT) Boolean, true indicates link established.
    249  * Returns:
    250  *	SOC_E_XXX
    251  * Notes:
    252  *	MII_STATUS bit 2 reflects link state.
    253  *	This bit gets set immediately when the link is plugged in,
    254  *	before autoneg completes.
    255  *	Energy control (MISC_CONTROL bit 3) is not used.
    256  */
    257 
    258 STATIC int
    259 phy_5690_link_get(int unit, soc_port_t port, int *link)
    260 {
    261     phy_ctrl_t         *pc;
    262     uint16		mii_stat;
    263 
    264     pc       = INT_PHY_SW_STATE(unit, port);
    265  
    266     if (soc_feature(unit, soc_feature_phy_5690_link_war)) {
    267        return (_phy_5690_war_link_get(unit, port, link));
    268     }
    269 
    270     SOC_IF_ERROR_RETURN
    271 	(READ_PHY_REG(unit, pc, QS_MII_STAT_REG, &mii_stat));
    272 
    273     *link = ((mii_stat & QS_MII_STAT_LA) != 0);
    274 
    275 
    276     return SOC_E_NONE;
    277 }
    278 
    279 /*
    280  * Function: 	
    281  *	phy_5690_enable_set
    282  * Purpose:	
    283  *	Enable or disable the physical interface.
    284  * Parameters:
    285  *	unit - StrataSwitch unit #.
    286  *	port - StrataSwitch port #. 
    287  *	enable - Boolean, true = enable PHY, false = disable.
    288  * Returns:	
    289  *	SOC_E_XXX
    290  * Notes:
    291  *	The PHY is held in reset when disabled.  Also, the
    292  *	MISC_CONTROL.IDDQ bit must be set to 1 so the remote partner
    293  *	sees link down.
    294  */
    295 
    296 STATIC int
    297 phy_5690_enable_set(int unit, soc_port_t port, int enable)
    298 {
    299     phy_ctrl_t *pc;
    300     uint16	misc_ctrl;
    301 
    302     pc       = INT_PHY_SW_STATE(unit, port);
    303     LOG_INFO(BSL_LS_SOC_PHY,
    304              (BSL_META_U(unit,
    305                          "phy_5690_enable_set: u=%d p=%d en=%d\n"),
    306               unit, port, enable));
    307 
    308     if (enable) {
    309 	PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
    310 	SOC_IF_ERROR_RETURN
    311 	    (READ_PHY_REG(unit, pc,
    312 			   QS_SGMII_MISC_CTRL_REG, &misc_ctrl));
    313 	misc_ctrl &= ~QS_SGMII_IDDQ_MODE;
    314 	SOC_IF_ERROR_RETURN
    315 	    (WRITE_PHY_REG(unit, pc,
    316 			    QS_SGMII_MISC_CTRL_REG, misc_ctrl));
    317 	SOC_IF_ERROR_RETURN
    318 	    (_phy_5690_notify_resume(unit, port, PHY_STOP_PHY_DIS));
    319     } else {
    320 	PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
    321 	SOC_IF_ERROR_RETURN
    322 	    (_phy_5690_notify_stop(unit, port, PHY_STOP_PHY_DIS));
    323 	SOC_IF_ERROR_RETURN
    324 	    (READ_PHY_REG(unit, pc,
    325 			   QS_SGMII_MISC_CTRL_REG, &misc_ctrl));
    326 	misc_ctrl |= QS_SGMII_IDDQ_MODE;
    327 	SOC_IF_ERROR_RETURN
    328 	    (WRITE_PHY_REG(unit, pc,
    329 			    QS_SGMII_MISC_CTRL_REG, misc_ctrl));
    330     }
    331 
    332     return SOC_E_NONE;
    333 }
    334 
    335 /*
    336  * Function: 	
    337  *	phy_5690_enable_get
    338  * Purpose:	
    339  *	Return physical interface enable/disable state.
    340  * Parameters:
    341  *	unit - StrataSwitch unit #.
    342  *	port - StrataSwitch port #. 
    343  *	enable - (OUT) Boolean, true = enable PHY, false = disable.
    344  * Returns:
    345  *	SOC_E_XXX
    346  */
    347 
    348 STATIC int
    349 phy_5690_enable_get(int unit, soc_port_t port, int *enable)
    350 {
    351     *enable = !PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE);
    352 
    353     return(SOC_E_NONE);
    354 }
    355 
    356 /*
    357  * Function: 	
    358  *	phy_5690_duplex_set
    359  * Purpose:	
    360  *	Set the current duplex mode (forced).
    361  * Parameters:
    362  *	unit - StrataSwitch unit #.
    363  *	port - StrataSwitch port #. 
    364  *	duplex - Boolean, TRUE indicates full duplex, FALSE indicates half.
    365  * Returns:	
    366  *	SOC_E_XXX
    367  */
    368 
    369 STATIC int
    370 phy_5690_duplex_set(int unit, soc_port_t port, int duplex)
    371 {
    372     COMPILER_REFERENCE(unit);
    373     COMPILER_REFERENCE(port);
    374 
    375     return (duplex ? SOC_E_NONE : SOC_E_UNAVAIL);
    376 }
    377 
    378 /*
    379  * Function: 	
    380  *	phy_5690_duplex_get
    381  * Purpose:	
    382  *	Get the current operating duplex mode. If autoneg is enabled, 
    383  *	then operating mode is returned, otherwise forced mode is returned.
    384  * Parameters:
    385  *	unit - StrataSwitch unit #.
    386  *	port - StrataSwitch port #. 
    387  *	duplex - (OUT) Boolean, true indicates full duplex, false 
    388  *		indicates half.
    389  * Returns:	
    390  *	SOC_E_XXX
    391  */
    392 
    393 STATIC int
    394 phy_5690_duplex_get(int unit, soc_port_t port, int *duplex)
    395 {
    396     COMPILER_REFERENCE(unit);
    397     COMPILER_REFERENCE(port);
    398 
    399     *duplex = TRUE;
    400 
    401     return SOC_E_NONE;
    402 }
    403 
    404 /*
    405  * Function: 	
    406  *	phy_5690_speed_set
    407  * Purpose:	
    408  *	Set the current operating speed (forced).
    409  * Parameters:
    410  *	unit - StrataSwitch unit #.
    411  *	port - StrataSwitch port #. 
    412  *	duplex - (OUT) Boolean, true indicates full duplex, false 
    413  *		indicates half.
    414  * Returns:	
    415  *	SOC_E_XXX
    416  */
    417 
    418 STATIC int
    419 phy_5690_speed_set(int unit, soc_port_t port, int speed)
    420 {
    421     COMPILER_REFERENCE(unit);
    422     COMPILER_REFERENCE(port);
    423 
    424     if (speed == 0 || speed == 1000) {
    425 	return SOC_E_NONE;
    426     }
    427 
    428     return SOC_E_CONFIG;
    429 }
    430 
    431 /*
    432  * Function: 	
    433  *	phy_5690_speed_get
    434  * Purpose:	
    435  *	Get the current operating speed. If autoneg is enabled, 
    436  *	then operating mode is returned, otherwise forced mode is returned.
    437  * Parameters:
    438  *	unit - StrataSwitch unit #.
    439  *	port - StrataSwitch port #. 
    440  *	duplex - (OUT) Boolean, true indicates full duplex, false 
    441  *		indicates half.
    442  * Returns:	
    443  *	SOC_E_XXX
    444  */
    445 
    446 STATIC int
    447 phy_5690_speed_get(int unit, soc_port_t port, int *speed)
    448 {
    449     *speed = 1000;
    450 
    451     return SOC_E_NONE;
    452 }
    453 
    454 /*
    455  * Function: 	
    456  *	phy_5690_an_set
    457  * Purpose:	
    458  *	Enable or disabled auto-negotiation on the specified port.
    459  * Parameters:
    460  *	unit - StrataSwitch unit #.
    461  *	port - StrataSwitch port #. 
    462  *	an - Boolean, if true, auto-negotiation is enabled 
    463  *		(and/or restarted). If false, autonegotiation is disabled.
    464  * Returns:	
    465  *	SOC_E_XXX
    466  */
    467 
    468 STATIC int
    469 phy_5690_an_set(int unit, soc_port_t port, int an)
    470 {
    471     phy_ctrl_t *pc; 
    472     uint16	sgmii_ctrl, misc_ctrl;
    473 
    474     pc       = INT_PHY_SW_STATE(unit, port);
    475     SOC_IF_ERROR_RETURN
    476 	(READ_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, &sgmii_ctrl));
    477     SOC_IF_ERROR_RETURN
    478 	(READ_PHY_REG(unit, pc, QS_SGMII_MISC_CTRL_REG, &misc_ctrl));
    479 
    480     /*
    481      * Special case for BCM5421S being used in SGMII copper mode with
    482      * BCM5690.  Always have autoneg on.
    483      */
    484 
    485     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_5421S)) {
    486 	an = 1;
    487     }
    488 
    489     if (an) {
    490 	sgmii_ctrl |= QS_SGMII_AN_SEL;		/* IEEE clause 37 compliant */
    491 	sgmii_ctrl &= ~QS_SGMII_AN_DISABLE;
    492 	misc_ctrl |= QS_SGMII_MAC_MODE;
    493     } else {
    494 	sgmii_ctrl &= ~QS_SGMII_AN_SEL;
    495 	sgmii_ctrl |= QS_SGMII_AN_DISABLE;
    496 	misc_ctrl &= ~QS_SGMII_MAC_MODE;
    497     }
    498 
    499     SOC_IF_ERROR_RETURN
    500 	(WRITE_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, sgmii_ctrl));
    501     SOC_IF_ERROR_RETURN
    502 	(WRITE_PHY_REG(unit, pc, QS_SGMII_MISC_CTRL_REG, misc_ctrl));
    503 
    504     if (an) {
    505 	/* Restart autonegotiation (not a self-clearing bit) */
    506 
    507 	SOC_IF_ERROR_RETURN
    508 	    (WRITE_PHY_REG(unit, pc,
    509 			    QS_SGMII_MISC_REG, QS_SGMII_ANA_RESTART));
    510 	SOC_IF_ERROR_RETURN
    511 	    (WRITE_PHY_REG(unit, pc,
    512 			    QS_SGMII_MISC_REG, 0));
    513     }
    514 
    515     return SOC_E_NONE;
    516 }
    517 
    518 /*
    519  * Function: 	
    520  *	phy_5690_an_get
    521  * Purpose:	
    522  *	Get the current auto-negotiation status (enabled/busy)
    523  * Parameters:
    524  *	unit - StrataSwitch unit #.
    525  *	port - StrataSwitch port #. 
    526  *	an - (OUT) if true, auto-negotiation is enabled.
    527  *	an_done - (OUT) if true, auto-negotiation is complete.
    528  *	        This value is undefined if an == false.
    529  * Returns:	
    530  *	SOC_E_XXX
    531  */
    532 
    533 STATIC int
    534 phy_5690_an_get(int unit, soc_port_t port, int *an, int *an_done)
    535 {
    536     phy_ctrl_t *pc;
    537     uint16	sgmii_ctrl, sgmii_stat;
    538 
    539     pc       = INT_PHY_SW_STATE(unit, port);
    540 
    541     SOC_IF_ERROR_RETURN
    542 	(READ_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, &sgmii_ctrl));
    543 
    544     *an = (sgmii_ctrl & QS_SGMII_AN_DISABLE) == 0;
    545 
    546     SOC_IF_ERROR_RETURN
    547 	(READ_PHY_REG(unit, pc, QS_SGMII_STAT_REG, &sgmii_stat));
    548 
    549     *an_done = (sgmii_stat & QS_SGMII_ANA_COMPLETE) != 0;
    550 
    551     return SOC_E_NONE;
    552 }
    553 
    554 /*
    555  * Function: 	
    556  *	phy_5690_adv_local_set
    557  * Purpose:	
    558  *	Set the current advertisement for auto-negotiation.
    559  * Parameters:
    560  *	unit - StrataSwitch unit #.
    561  *	port - StrataSwitch port #. 
    562  *	mode - Port mode mask indicating supported options/speeds.
    563  * Returns:	
    564  *	SOC_E_XXX
    565  */
    566 
    567 STATIC int 
    568 phy_5690_adv_local_set(int unit, soc_port_t port, soc_port_mode_t mode)
    569 {
    570     uint16	an_adv, sgmii_ctrl;
    571     phy_ctrl_t *pc;
    572 
    573     pc       = INT_PHY_SW_STATE(unit, port);
    574 
    575     mode &= SOC_PM_1000MB_FD | SOC_PM_PAUSE;
    576 
    577     /*
    578      * Set advertised duplex (only FD supported).
    579      */
    580 
    581     SOC_IF_ERROR_RETURN
    582 	(READ_PHY_REG(unit, pc, QS_ANA_REG, &an_adv));
    583 
    584     an_adv &= ~(QS_MII_ANA_FD | QS_MII_ANA_HD);
    585 
    586     if (mode & SOC_PM_1000MB_FD) {
    587 	an_adv |= QS_MII_ANA_FD;
    588     }
    589 
    590     SOC_IF_ERROR_RETURN
    591 	(WRITE_PHY_REG(unit, pc, QS_ANA_REG, an_adv));
    592 
    593     /*
    594      * Set advertised pause bits in link code word.
    595      */
    596 
    597     SOC_IF_ERROR_RETURN
    598 	(READ_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, &sgmii_ctrl));
    599 
    600     sgmii_ctrl &= ~(QS_SGMII_PAUSE_SYM | QS_SGMII_PAUSE_ASYM);
    601 
    602     switch (mode & SOC_PM_PAUSE) {
    603     case SOC_PM_PAUSE_TX:
    604 	sgmii_ctrl |= QS_SGMII_PAUSE_ASYM;
    605 	break;
    606     case SOC_PM_PAUSE_RX:
    607 	sgmii_ctrl |= QS_SGMII_PAUSE_SYM | QS_SGMII_PAUSE_ASYM;
    608 	break;
    609     case SOC_PM_PAUSE_TX | SOC_PM_PAUSE_RX:
    610 	sgmii_ctrl |= QS_SGMII_PAUSE_SYM;
    611 	break;
    612     }
    613 
    614     SOC_IF_ERROR_RETURN
    615 	(WRITE_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, sgmii_ctrl));
    616 
    617     return SOC_E_NONE;
    618 }
    619 
    620 /*
    621  * Function: 	
    622  *	phy_5690_adv_local_get
    623  * Purpose:	
    624  *	Get the current advertisement for auto-negotiation.
    625  * Parameters:
    626  *	unit - StrataSwitch unit #.
    627  *	port - StrataSwitch port #. 
    628  *	mode - (OUT) Port mode mask indicating supported options/speeds.
    629  * Returns:	
    630  *	SOC_E_XXX
    631  */
    632 
    633 STATIC int
    634 phy_5690_adv_local_get(int unit, soc_port_t port, soc_port_mode_t *mode)
    635 {
    636     uint16	an_adv, sgmii_ctrl;
    637     phy_ctrl_t *pc;
    638 
    639     pc       = INT_PHY_SW_STATE(unit, port);
    640 
    641     *mode = 0;
    642 
    643     SOC_IF_ERROR_RETURN
    644 	(READ_PHY_REG(unit, pc, QS_ANA_REG, &an_adv));
    645 
    646     if (an_adv & QS_MII_ANA_FD) {
    647 	*mode |= SOC_PM_1000MB_FD;
    648     }
    649 
    650     SOC_IF_ERROR_RETURN
    651 	(READ_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, &sgmii_ctrl));
    652 
    653     switch (sgmii_ctrl & (QS_SGMII_PAUSE_SYM | QS_SGMII_PAUSE_ASYM)) {
    654     case QS_SGMII_PAUSE_SYM:
    655 	*mode |= SOC_PM_PAUSE_TX | SOC_PM_PAUSE_RX;
    656 	break;
    657     case QS_SGMII_PAUSE_ASYM:
    658 	*mode |= SOC_PM_PAUSE_TX;
    659 	break;
    660     case QS_SGMII_PAUSE_SYM | QS_SGMII_PAUSE_ASYM:
    661 	*mode |= SOC_PM_PAUSE_RX;
    662 	break;
    663     }
    664 
    665     return SOC_E_NONE;
    666 }
    667 
    668 /*
    669  * Function: 	
    670  *	phy_5690_adv_remote_get
    671  * Purpose:	
    672  *	Get partner's current advertisement for auto-negotiation.
    673  * Parameters:
    674  *	unit - StrataSwitch unit #.
    675  *	port - StrataSwitch port #. 
    676  *	mode - (OUT) Port mode mask indicating supported options/speeds.
    677  * Returns:
    678  *	SOC_E_XXX
    679  */
    680 
    681 STATIC int
    682 phy_5690_adv_remote_get(int unit, soc_port_t port, soc_port_mode_t *mode)
    683 {
    684     phy_ctrl_t *pc;
    685     uint16	anlpa;
    686 
    687     pc       = INT_PHY_SW_STATE(unit, port);
    688 
    689     *mode = 0;
    690 
    691     SOC_IF_ERROR_RETURN
    692 	(READ_PHY_REG(unit, pc, QS_ANP_REG, &anlpa));
    693 
    694     if (anlpa & QS_MII_ANP_FIBER_FD) {
    695 	*mode |= SOC_PM_1000MB_FD;
    696     }
    697 
    698     if (anlpa & QS_MII_ANP_FIBER_HD) {
    699 	*mode |= SOC_PM_1000MB_HD;
    700     }
    701 
    702     switch (anlpa &
    703 	    (QS_MII_ANP_FIBER_PAUSE_SYM | QS_MII_ANP_FIBER_PAUSE_ASYM)) {
    704     case QS_MII_ANP_FIBER_PAUSE_SYM:
    705 	*mode |= SOC_PM_PAUSE_TX | SOC_PM_PAUSE_RX;
    706 	break;
    707     case QS_MII_ANP_FIBER_PAUSE_ASYM:
    708 	*mode |= SOC_PM_PAUSE_TX;
    709 	break;
    710     case QS_MII_ANP_FIBER_PAUSE_SYM | QS_MII_ANP_FIBER_PAUSE_ASYM:
    711 	*mode |= SOC_PM_PAUSE_RX;
    712 	break;
    713     }
    714 
    715     return SOC_E_NONE;
    716 }
    717 
    718 /*
    719  * Function:
    720  *      phy_5690_master_set
    721  * Purpose:
    722  *      Configure PHY master mode
    723  * Parameters:
    724  *      unit - StrataSwitch unit #.
    725  *      port - StrataSwitch port #.
    726  *      master - PHY master mode.
    727  * Returns:
    728  *      SOC_E_UNAVAIL
    729  */
    730 STATIC int
    731 phy_5690_master_set(int unit, soc_port_t port, int master)
    732 {
    733     COMPILER_REFERENCE(unit);
    734     COMPILER_REFERENCE(port);
    735 
    736     if (master == SOC_PORT_MS_NONE) {
    737         return SOC_E_NONE;
    738     }
    739     return SOC_E_PARAM;
    740 }
    741 
    742 /*
    743  * Function:
    744  *      phy_5690_master_get
    745  * Purpose:
    746  *      Get current master mode setting
    747  * Parameters:
    748  *      unit - StrataSwitch unit #.
    749  *      port - StrataSwitch port #.
    750  *      master - (OUT) BCM_PORT_MS_NONE
    751  * Returns:
    752  *      SOC_E_NONE
    753  */
    754 STATIC int
    755 phy_5690_master_get(int unit, soc_port_t port, int *master)
    756 {
    757     *master = SOC_PORT_MS_NONE;
    758     return SOC_E_NONE;
    759 }
    760 
    761 /*
    762  * Function: 	
    763  *	phy_5690_lb_set
    764  * Purpose:	
    765  *	Set the internal PHY loopback mode.
    766  * Parameters:
    767  *	unit - StrataSwitch unit #.
    768  *	port - StrataSwitch port #. 
    769  *	loopback - Boolean: true = enable loopback, false = disable.
    770  * Returns:	
    771  *	SOC_E_XXX
    772  */
    773 
    774 STATIC int
    775 phy_5690_lb_set(int unit, soc_port_t port, int enable)
    776 {
    777     uint16	sgmii_ctrl;
    778     phy_ctrl_t *pc;
    779 
    780     pc       = INT_PHY_SW_STATE(unit, port);
    781 
    782     SOC_IF_ERROR_RETURN
    783 	(READ_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, &sgmii_ctrl));
    784 
    785     if (enable) {
    786 	sgmii_ctrl |= QS_SGMII_TBI_LOOP | QS_SGMII_REV_PHASE;
    787     } else {
    788 	sgmii_ctrl &= ~(QS_SGMII_TBI_LOOP | QS_SGMII_REV_PHASE);
    789     }
    790 
    791     SOC_IF_ERROR_RETURN
    792 	(WRITE_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, sgmii_ctrl));
    793 
    794     return SOC_E_NONE;
    795 }
    796 
    797 /*
    798  * Function: 	
    799  *	phy_5690_lb_get
    800  * Purpose:	
    801  *	Get the local PHY loopback mode.
    802  * Parameters:
    803  *	unit - StrataSwitch unit #.
    804  *	port - StrataSwitch port #. 
    805  *	loopback - (OUT) Boolean: true = enable loopback, false = disable.
    806  * Returns:	
    807  *	SOC_E_XXX
    808  */
    809 
    810 STATIC int
    811 phy_5690_lb_get(int unit, soc_port_t port, int *enable)
    812 {
    813     uint16	sgmii_ctrl;
    814     phy_ctrl_t *pc;
    815 
    816     pc       = INT_PHY_SW_STATE(unit, port);
    817 
    818     SOC_IF_ERROR_RETURN
    819 	(READ_PHY_REG(unit, pc, QS_SGMII_CTRL_REG, &sgmii_ctrl));
    820 
    821     *enable = (sgmii_ctrl & QS_SGMII_TBI_LOOP) != 0;
    822 
    823     return SOC_E_NONE;
    824 }
    825 
    826 /*
    827  * Function:
    828  *	phy_5690_interface_set
    829  * Purpose:
    830  *	Set the current operating mode of the internal PHY.
    831  *	(Pertaining to the MAC/PHY interface, not the line interface).
    832  * Parameters:
    833  *	unit - StrataSwitch unit #.
    834  *	port - StrataSwitch port #. 
    835  *	pif - one of SOC_PORT_IF_*
    836  * Returns:
    837  *	SOC_E_XXX
    838  */
    839 
    840 STATIC int
    841 phy_5690_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
    842 {
    843     int			rv;
    844 
    845     switch (pif) {
    846     case SOC_PORT_IF_MII:
    847     case SOC_PORT_IF_GMII:
    848     case SOC_PORT_IF_SGMII:
    849     case SOC_PORT_IF_NOCXN:
    850 	rv = SOC_E_NONE;
    851 	break;
    852     default:
    853         rv = SOC_E_UNAVAIL;
    854 	break;
    855     }
    856 
    857     LOG_INFO(BSL_LS_SOC_PHY,
    858              (BSL_META_U(unit,
    859                          "phy_5690_interface_set: u=%d p=%d pif=%d rv=%d\n"),
    860               unit, port, pif, rv));
    861 
    862     return rv;
    863 }
    864 
    865 /*
    866  * Function:
    867  *	phy_5690_interface_get
    868  * Purpose:
    869  *	Get the current operating mode of the internal PHY.
    870  *	(Pertaining to the MAC/PHY interface, not the line interface).
    871  * Parameters:
    872  *	unit - StrataSwitch unit #.
    873  *	port - StrataSwitch port #. 
    874  *	pif - (OUT) one of SOC_PORT_IF_*
    875  * Returns:
    876  *	SOC_E_XXX
    877  */
    878 
    879 STATIC int
    880 phy_5690_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
    881 {
    882     *pif = SOC_PORT_IF_GMII;
    883 
    884     return(SOC_E_NONE);
    885 }
    886 
    887 /*
    888  * Function: 	
    889  *	phy_5690_ability_get
    890  * Purpose:	
    891  *	Get the abilities of the internal PHY.
    892  * Parameters:
    893  *	unit - StrataSwitch unit #.
    894  *	port - StrataSwitch port #. 
    895  *	mode - (OUT) Port mode mask indicating supported options/speeds.
    896  * Returns:	
    897  *	SOC_E_XXX
    898  */
    899 
    900 STATIC int
    901 phy_5690_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode)
    902 {
    903     uint16      serdes_mode;
    904     phy_ctrl_t *pc;
    905 
    906     pc = INT_PHY_SW_STATE(unit, port);
    907 
    908     SOC_IF_ERROR_RETURN
    909 	(READ_PHY_REG(unit, pc, QS_SGMII_CTRL2_REG, &serdes_mode));
    910 
    911     if (serdes_mode & QS_SGMII_FIBER_MODE) {
    912         *mode = (SOC_PM_1000MB_FD | SOC_PM_PAUSE | SOC_PM_PAUSE_ASYMM |
    913                  SOC_PM_AN | SOC_PM_LB_PHY | SOC_PM_GMII);
    914     } else {
    915         *mode = (SOC_PM_10MB | SOC_PM_100MB | SOC_PM_1000MB_FD | 
    916                  SOC_PM_LB_PHY | SOC_PM_GMII);
    917     }
    918 
    919     return SOC_E_NONE;
    920 }
    921 
    922 STATIC int
    923 phy_5690_notify(int unit, soc_port_t port, 
    924                  soc_phy_event_t event, uint32 value)
    925 {
    926     int             rv;
    927 
    928     if (event >= phyEventCount) {
    929         return SOC_E_PARAM;
    930     }
    931 
    932     rv = SOC_E_NONE;
    933     switch(event) {
    934     case phyEventInterface:
    935         rv = (_phy_5690_notify_interface(unit, port, value));
    936         break;
    937     case phyEventDuplex:
    938         rv = (_phy_5690_notify_duplex(unit, port, value));
    939         break;
    940     case phyEventSpeed:
    941         rv = (_phy_5690_notify_speed(unit, port, value));
    942         break;
    943     case phyEventStop:
    944         rv = (_phy_5690_notify_stop(unit, port, value));
    945         break;
    946     case phyEventResume:
    947         rv = (_phy_5690_notify_resume(unit, port, value));
    948         break;
    949     default:
    950         rv = SOC_E_PARAM;
    951     }
    952 
    953     return rv;
    954 }
    955 
    956 /*
    957  * Variable:	phy_5690drv_ge
    958  * Purpose:	PHY Driver for Quad Serdes PHY internal to Draco, 
    959  */
    960 
    961 phy_driver_t phy_5690drv_ge = {
    962     "BCM5690 Internal SERDES PHY Driver",
    963     phy_5690_init,
    964     phy_null_reset,
    965     phy_5690_link_get, 
    966     phy_5690_enable_set, 
    967     phy_5690_enable_get, 
    968     phy_5690_duplex_set, 
    969     phy_5690_duplex_get, 
    970     phy_5690_speed_set, 
    971     phy_5690_speed_get, 
    972     phy_5690_master_set,
    973     phy_5690_master_get,
    974     phy_5690_an_set,
    975     phy_5690_an_get,
    976     phy_5690_adv_local_set,
    977     phy_5690_adv_local_get,
    978     phy_5690_adv_remote_get,
    979     phy_5690_lb_set,
    980     phy_5690_lb_get,
    981     phy_5690_interface_set, 
    982     phy_5690_interface_get, 
    983     phy_5690_ability_get,
    984     NULL,
    985     NULL,
    986     phy_null_mdix_set,
    987     phy_null_mdix_get,
    988     phy_null_mdix_status_get,
    989     NULL,
    990     NULL,
    991     phy_null_medium_get,
    992     NULL,                       /* phy_cable_diag */
    993     NULL,                       /* phy_link_change */
    994     NULL,                       /* phy_control_set */ 
    995     NULL,                       /* phy_control_get */
    996     NULL,                       /* phy_reg_read */
    997     NULL,                       /* phy_reg_write */
    998     NULL,                       /* phy_reg_modify */
    999     phy_5690_notify
   1000 };
   1001 
   1002 /***********************************************************************
   1003  *
   1004  * PASS-THROUGH NOTIFY ROUTINES
   1005  */
   1006 
   1007 /*
   1008  * Function:
   1009  *	_phy_5690_notify_duplex
   1010  * Purpose:	
   1011  *	Program duplex if (and only if) 5690 is an intermediate PHY.
   1012  * Parameters:
   1013  *	unit - StrataSwitch unit #.
   1014  *	port - StrataSwitch port #. 
   1015  *	duplex - Boolean, TRUE indicates full duplex, FALSE
   1016  *		indicates half.
   1017  * Returns:	
   1018  *	SOC_E_XXX
   1019  * Notes:
   1020  *	If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to
   1021  *	talk directly to an external fiber module.
   1022  *
   1023  *	If PHY_FLAGS_FIBER is clear, the PHY is being used in
   1024  *	pass-through mode to talk to an external SGMII PHY.
   1025  *
   1026  *	When used in pass-through mode, autoneg must be turned off and
   1027  *	the speed/duplex forced to match that of the external PHY.
   1028  */
   1029 
   1030 STATIC int
   1031 _phy_5690_notify_duplex(int unit, soc_port_t port, uint32 duplex)
   1032 {
   1033     int		fiber = PHY_FLAGS_TST(unit, port, PHY_FLAGS_FIBER);
   1034     uint16	mii_ctrl;
   1035     phy_ctrl_t *pc;
   1036 
   1037     pc       = INT_PHY_SW_STATE(unit, port);
   1038 
   1039     LOG_INFO(BSL_LS_SOC_PHY,
   1040              (BSL_META_U(unit,
   1041                          "_phy_5690_notify_duplex: u=%d p=%d duplex=%d fiber=%d\n"),
   1042               unit, port, duplex, fiber));
   1043 
   1044     if (SAL_BOOT_SIMULATION) {
   1045         return SOC_E_NONE;
   1046     }
   1047 
   1048     if (fiber) {
   1049         SOC_IF_ERROR_RETURN
   1050 	    (READ_PHY_REG(unit, pc, QS_MII_CTRL_REG, &mii_ctrl));
   1051 
   1052         if (!(mii_ctrl & QS_MII_CTRL_FD)) {
   1053             mii_ctrl |= QS_MII_CTRL_FD;
   1054             SOC_IF_ERROR_RETURN
   1055 		(WRITE_PHY_REG(unit, pc, QS_MII_CTRL_REG, mii_ctrl));
   1056         }
   1057 
   1058         return SOC_E_NONE;
   1059     }
   1060 
   1061     /* Put SERDES PHY in reset */
   1062 
   1063     SOC_IF_ERROR_RETURN
   1064 	(_phy_5690_notify_stop(unit, port, PHY_STOP_DUPLEX_CHG));
   1065 
   1066     /* Update duplexity */
   1067 
   1068     SOC_IF_ERROR_RETURN
   1069 	(READ_PHY_REG(unit, pc, QS_MII_CTRL_REG, &mii_ctrl));
   1070 
   1071     if (duplex) {
   1072 	mii_ctrl |= QS_MII_CTRL_FD;
   1073     } else {
   1074 	mii_ctrl &= ~QS_MII_CTRL_FD;
   1075     }
   1076 
   1077     SOC_IF_ERROR_RETURN
   1078 	(WRITE_PHY_REG(unit, pc, QS_MII_CTRL_REG, mii_ctrl));
   1079 
   1080     /* Take SERDES PHY out of reset */
   1081 
   1082     SOC_IF_ERROR_RETURN
   1083 	(_phy_5690_notify_resume(unit, port, PHY_STOP_DUPLEX_CHG));
   1084 
   1085     /* Autonegotiation must be turned off to talk to external PHY */
   1086 
   1087     SOC_IF_ERROR_RETURN
   1088 	(phy_5690_an_set(unit, port, FALSE));
   1089 
   1090     return SOC_E_NONE;
   1091 }
   1092 
   1093 /*
   1094  * Function:
   1095  *	_phy_5690_notify_speed
   1096  * Purpose:	
   1097  *	Program duplex if (and only if) 5690 is an intermediate PHY.
   1098  * Parameters:
   1099  *	unit - StrataSwitch unit #.
   1100  *	port - StrataSwitch port #. 
   1101  *	speed - Speed to program.
   1102  * Returns:	
   1103  *	SOC_E_XXX
   1104  * Notes:
   1105  *	If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to
   1106  *	talk directly to an external fiber module.
   1107  *
   1108  *	If PHY_FLAGS_FIBER is clear, the PHY is being used in
   1109  *	pass-through mode to talk to an external SGMII PHY.
   1110  *
   1111  *	When used in pass-through mode, autoneg must be turned off and
   1112  *	the speed/duplex forced to match that of the external PHY.
   1113  */
   1114 
   1115 STATIC int
   1116 _phy_5690_notify_speed(int unit, soc_port_t port, uint32 speed)
   1117 {
   1118     int		fiber = PHY_FLAGS_TST(unit, port, PHY_FLAGS_FIBER);
   1119     uint16	mii_ctrl;
   1120     int		rv = SOC_E_NONE;
   1121     phy_ctrl_t *pc;
   1122 
   1123     pc       = INT_PHY_SW_STATE(unit, port);
   1124 
   1125     LOG_INFO(BSL_LS_SOC_PHY,
   1126              (BSL_META_U(unit,
   1127                          "_phy_5690_notify_speed: u=%d p=%d speed=%d fiber=%d\n"),
   1128               unit, port, speed, fiber));
   1129 
   1130     if (SAL_BOOT_SIMULATION) {
   1131         return SOC_E_NONE;
   1132     }
   1133 
   1134     if (fiber) {
   1135         SOC_IF_ERROR_RETURN
   1136 	    (READ_PHY_REG(unit, pc, QS_MII_CTRL_REG, &mii_ctrl));
   1137 
   1138         if ((mii_ctrl & (QS_MII_CTRL_SS_LSB | QS_MII_CTRL_SS_MSB))
   1139                 != QS_MII_CTRL_SS_1000) {
   1140             mii_ctrl &= ~(QS_MII_CTRL_SS_LSB | QS_MII_CTRL_SS_MSB);
   1141             mii_ctrl |= QS_MII_CTRL_SS_1000;
   1142             SOC_IF_ERROR_RETURN
   1143 		(WRITE_PHY_REG(unit, pc, MII_CTRL_REG, mii_ctrl));
   1144         }
   1145         return rv;
   1146     }
   1147 
   1148     /* Put SERDES PHY in reset */
   1149 
   1150     SOC_IF_ERROR_RETURN
   1151 	(_phy_5690_notify_stop(unit, port, PHY_STOP_SPEED_CHG));
   1152 
   1153     /* Update speed */
   1154 
   1155     SOC_IF_ERROR_RETURN
   1156 	(READ_PHY_REG(unit, pc, QS_MII_CTRL_REG, &mii_ctrl));
   1157 
   1158     mii_ctrl &= ~(QS_MII_CTRL_SS_LSB | QS_MII_CTRL_SS_MSB);
   1159 
   1160     switch (speed) {
   1161     case 10:
   1162 	mii_ctrl |= QS_MII_CTRL_SS_10;
   1163 	break;
   1164     case 100:
   1165 	mii_ctrl |= QS_MII_CTRL_SS_100;
   1166 	break;
   1167     case 0:
   1168     case 1000:	
   1169 	mii_ctrl |= QS_MII_CTRL_SS_1000;
   1170 	break;
   1171     default:
   1172 	rv = SOC_E_CONFIG;
   1173 	break;
   1174     }
   1175 
   1176     SOC_IF_ERROR_RETURN
   1177 	(WRITE_PHY_REG(unit, pc, QS_MII_CTRL_REG, mii_ctrl));
   1178 
   1179     /* Take SERDES PHY out of reset */
   1180 
   1181     SOC_IF_ERROR_RETURN
   1182 	(_phy_5690_notify_resume(unit, port, PHY_STOP_SPEED_CHG));
   1183 
   1184     /* Autonegotiation must be turned off to talk to external PHY */
   1185 
   1186     SOC_IF_ERROR_RETURN
   1187 	(phy_5690_an_set(unit, port, FALSE));
   1188 
   1189     return rv;
   1190 }
   1191 
   1192 /*
   1193  * Function:
   1194  *	_phy_5690_stop
   1195  * Purpose:
   1196  *	Put 5690 SERDES in or out of reset depending on conditions
   1197  */
   1198 
   1199 STATIC int
   1200 _phy_5690_stop(int unit, soc_port_t port)
   1201 {
   1202     uint16		mii_ctrl;
   1203     int			stop, copper;
   1204     phy_ctrl_t         *pc;
   1205 
   1206     pc       = INT_PHY_SW_STATE(unit, port);
   1207 
   1208     copper = (pc->stop &
   1209 	      PHY_STOP_COPPER) != 0;
   1210 
   1211     stop = ((pc->stop &
   1212 	     (PHY_STOP_PHY_DIS |
   1213 	      PHY_STOP_DRAIN)) != 0 ||
   1214 	    (copper &&
   1215 	     (pc->stop &
   1216 	      (PHY_STOP_MAC_DIS |
   1217 	       PHY_STOP_DUPLEX_CHG |
   1218 	       PHY_STOP_SPEED_CHG)) != 0));
   1219 
   1220     LOG_INFO(BSL_LS_SOC_PHY,
   1221              (BSL_META_U(unit,
   1222                          "phy_5690_stop: u=%d p=%d copper=%d stop=%d flg=0x%x\n"),
   1223               unit, port, copper, stop,
   1224               pc->stop));
   1225 
   1226     SOC_IF_ERROR_RETURN
   1227 	(READ_PHY_REG(unit, pc, QS_MII_CTRL_REG, &mii_ctrl));
   1228 
   1229     if (stop) {
   1230 	mii_ctrl |= MII_CTRL_RESET;
   1231     } else {
   1232 	mii_ctrl &= ~MII_CTRL_RESET;
   1233     }
   1234 
   1235     SOC_IF_ERROR_RETURN
   1236 	(WRITE_PHY_REG(unit, pc, QS_MII_CTRL_REG, mii_ctrl));
   1237 
   1238     return SOC_E_NONE;
   1239 }
   1240 
   1241 /*
   1242  * Function:
   1243  *	_phy_5690_notify_stop
   1244  * Purpose:	
   1245  *	Add a reason to put 5690 PHY in reset.
   1246  * Parameters:
   1247  *	unit - StrataSwitch unit #.
   1248  *	port - StrataSwitch port #. 
   1249  *	flags - Reason to stop
   1250  * Returns:	
   1251  *	SOC_E_XXX
   1252  */
   1253 
   1254 STATIC int
   1255 _phy_5690_notify_stop(int unit, soc_port_t port, uint32 flags)
   1256 {
   1257     phy_ctrl_t  *pc;
   1258 
   1259     pc = INT_PHY_SW_STATE(unit, port);
   1260     pc->stop |= flags;
   1261 
   1262     return _phy_5690_stop(unit, port);
   1263 }
   1264 
   1265 /*
   1266  * Function:
   1267  *	_phy_5690_notify_resume
   1268  * Purpose:	
   1269  *	Remove a reason to put 5690 PHY in reset.
   1270  * Parameters:
   1271  *	unit - StrataSwitch unit #.
   1272  *	port - StrataSwitch port #. 
   1273  *	flags - Reason to stop
   1274  * Returns:	
   1275  *	SOC_E_XXX
   1276  */
   1277 
   1278 STATIC int
   1279 _phy_5690_notify_resume(int unit, soc_port_t port, uint32 flags)
   1280 {
   1281     phy_ctrl_t  *pc;
   1282 
   1283     pc = INT_PHY_SW_STATE(unit, port);
   1284     pc->stop &= ~flags;
   1285 
   1286     return _phy_5690_stop(unit, port);
   1287 }
   1288 
   1289 STATIC int
   1290 _phy_5690_notify_interface(int unit, soc_port_t port, uint32 flags)
   1291 {
   1292     uint16      mode;
   1293     phy_ctrl_t *pc;
   1294 
   1295     pc       = INT_PHY_SW_STATE(unit, port);
   1296 
   1297     mode = (flags == SOC_PORT_IF_SGMII) ? 0 : QS_SGMII_FIBER_MODE;
   1298     
   1299     SOC_IF_ERROR_RETURN
   1300 	(WRITE_PHY_REG(unit, pc, QS_SGMII_CTRL2_REG, mode));
   1301     
   1302     return SOC_E_NONE;
   1303 }
   1304 
   1305 #endif /* BCM_5690 */
   1306 
   1307 int _soc_phy_5690_not_empty;