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

phy522x.c (20850B)


      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:        phy522x.c
      8  * Purpose:    Broadcom 522x phy driver
      9  *        Supports 5218, 5220/5221, 5226, 5228, 5238, 5248
     10  */
     11 
     12 #ifdef INCLUDE_PHY_522X
     13 
     14 #include <sal/types.h>
     15 #include <sal/core/thread.h>
     16 
     17 #include <soc/drv.h>
     18 #include <soc/debug.h>
     19 #include <soc/error.h>
     20 #include <soc/phyreg.h>
     21 
     22 #include <soc/phy.h>
     23 #include <soc/phy/phyctrl.h>
     24 #include <soc/phy/drv.h>
     25 
     26 #include "phyident.h"
     27 #include "phyreg.h"
     28 #include "phyfege.h"
     29 #include "phy522x.h"
     30 
     31 extern int 
     32 phy_522x_cable_diag(int unit, soc_port_t port,
     33             soc_port_cable_diag_t *status);
     34 
     35 #define LINK_WAIT_TIMEOUT 100
     36 
     37 #define EFX_HALF_THRESHOLD_MODE 0
     38 
     39 /*
     40  * Function:
     41  *    phy_522x_init
     42  * Purpose:
     43  *    Initialize phy
     44  * Parameters:
     45  *    unit - device number
     46  *    port - port number
     47  * Returns:
     48  *    SOC_E_XXX
     49  */
     50 STATIC int
     51 phy_522x_init(int unit, soc_port_t port)
     52 {
     53     phy_ctrl_t  *pc;
     54     uint16       led1;
     55     uint16       led2;
     56     uint16       led_mode;
     57     int          phy_index;
     58     soc_pbmp_t pbmp_100fx;
     59     uint16      tmp = 0;
     60 
     61 
     62     pc = EXT_PHY_SW_STATE(unit, port);
     63    
     64     /* BCM5248 after a hardware reset or s/w reset does not 
     65        guarantee internal automatic power down (APD) timer to be 
     66        reset for all ports. It could result in waking up of 
     67        all inactive ports at the same time causing excessive noise 
     68        on the power supplies causing active ports to have performance
     69        issues. To avoid this reset all the MII registers.
     70        Refer - Design Guide for more detials 
     71      */
     72     if(PHY_IS_BCM5248(pc)) {
     73         /* Set all the MII registers to their default values */
     74         SOC_IF_ERROR_RETURN
     75             (PHY522X_REG_WRITE(unit, pc, 0x0000, 0x1f, 0x0200));
     76        /* Delay 100 microseconds */
     77        sal_usleep(100); 
     78     }
     79 
     80     SOC_IF_ERROR_RETURN(phy_fe_init(unit, port));
     81 
     82     SOC_IF_ERROR_RETURN
     83         (WRITE_PHY_REG(unit, pc, 0x16, 0x0002)); 
     84 
     85     switch ((pc->phy_model << 16) | pc->phy_oui) {
     86     case (PHY_BCM5228_MODEL << 16) | PHY_BCM5228_OUI:
     87     case (PHY_BCM5238_MODEL << 16) | PHY_BCM5238_OUI:
     88     case (PHY_BCM5248_MODEL << 16) | PHY_BCM5248_OUI:
     89 
     90         /* enable jumbo packets */
     91         SOC_IF_ERROR_RETURN
     92             (MODIFY_PHY522X_AUX_MODE2r(unit, pc, 0x0400, 0x0400));
     93         break;
     94     }
     95 
     96     if (PHY_IS_BCM5248(pc)) {
     97         /* Find out which port is the first port of the octal PHY */
     98         phy_index = soc_property_port_get(unit, port, 
     99                                           spn_PHY_OCTAL_PORT_FIRST, 0);
    100 
    101         phy_index = (port - phy_index) % 8;
    102         if (0 == phy_index) {
    103             /* Link */
    104             led1 = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0); 
    105 
    106             /* Activity */
    107             led2 = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1);
    108 
    109             /* Enable parallel LED mode and program LED 1 and LED2 */
    110             SOC_IF_ERROR_RETURN
    111                 (READ_PHY522X_AUX_MODE4r(unit, pc, &led_mode));
    112             led_mode = ~(0x023f);
    113             led_mode |= (1 << 9) |             /* Enable parallel LED mode */
    114                         (led2 << 3) | (led1);  /* LED1 and LED2 mode select */ 
    115             SOC_IF_ERROR_RETURN
    116                 (WRITE_PHY522X_AUX_MODE4r(unit, pc, led_mode));
    117         }
    118 
    119         if (2 == phy_index) {
    120             /* Disable Extended Parallel LED Mode */
    121             SOC_IF_ERROR_RETURN
    122                 (READ_PHY522X_AUX_MODE4r(unit, pc, &led_mode));
    123             led_mode = ~(1 << 9);
    124             SOC_IF_ERROR_RETURN
    125                 (WRITE_PHY522X_AUX_MODE4r(unit, pc, led_mode));
    126         }
    127     }
    128 
    129     /*
    130       * Get 100-FX ports from config.bcm.
    131       */
    132     pbmp_100fx = soc_property_get_pbmp(unit, spn_PBMP_FE_100FX, 0);
    133     if (SOC_PBMP_MEMBER(pbmp_100fx, port)) {
    134         /* Speed/Duplex selection and auto-negotiation Disable */
    135         SOC_IF_ERROR_RETURN             
    136             (WRITE_PHY522X_MII_CTRLr(unit, pc, 0x2100));
    137 
    138         /* Scrambler and Descrambler Disable and Far-End-Fault Enable */
    139         SOC_IF_ERROR_RETURN            
    140             (READ_PHY522X_AUX_CTRLr(unit, pc, &tmp));
    141         tmp |= 0x0220;
    142         SOC_IF_ERROR_RETURN            
    143             (WRITE_PHY522X_AUX_CTRLr(unit, pc, tmp));
    144 
    145         /* Configure Transmit and Receive for Binary Signaling */
    146         SOC_IF_ERROR_RETURN
    147             (PHY522X_REG_READ(unit, pc, 0x0000, 0x17, &tmp));
    148         tmp |= 0x20;
    149         SOC_IF_ERROR_RETURN
    150             (PHY522X_REG_WRITE(unit, pc, 0x0000, 0x17, 0x20));
    151 
    152         /* Enable Internal EFX Signal Detect Function */
    153         /* Enable the shadow register */
    154         SOC_IF_ERROR_RETURN
    155             (PHY522X_REG_WRITE(unit, pc, 0x0000, 0x1f, 0x008b));
    156         /* Enable the special Signal Detect function */
    157         SOC_IF_ERROR_RETURN
    158             (PHY522X_REG_WRITE(unit, pc, 0x0000, 0x19, 0x0200));
    159         /* Configure the transmit amplitude for 1V pk-pk differential */
    160         SOC_IF_ERROR_RETURN
    161             (PHY522X_REG_WRITE(unit, pc, 0x0000, 0x1d, 0x0084));
    162         /* Exist the shadow register */
    163         SOC_IF_ERROR_RETURN
    164             (PHY522X_REG_WRITE(unit, pc, 0x0000, 0x1f, 0x000b));
    165 #if EFX_HALF_THRESHOLD_MODE
    166         /* Enable the shadow register */
    167         SOC_IF_ERROR_RETURN
    168             (PHY522X_REG_WRITE(unit, pc, 0x0000, 0x1f, 0x008b));
    169         /* Set the threshold to the Half Threshold mode*/
    170         SOC_IF_ERROR_RETURN
    171             (PHY522X_REG_WRITE(unit, pc, 0x0000, 0x11, 0x0a01));
    172         /* Exist the shadow register */
    173         SOC_IF_ERROR_RETURN
    174             (PHY522X_REG_WRITE(unit, pc, 0x0000, 0x1f, 0x000b));
    175 #endif
    176     }
    177 
    178     return SOC_E_NONE;
    179 }
    180 
    181 /*
    182  * Function:
    183  *     phy_522x_enable_set
    184  * Description:
    185  *     Enable or disable the physical interface
    186  * Parameters:
    187  *     unit   - Device number
    188  *     port   - Port number
    189  *     enable - Boolean, true = enable, false = enable.
    190  * Returns:
    191  *     SOC_E_XXX
    192  */
    193 STATIC int
    194 phy_522x_enable_set(int unit, soc_port_t port, int enable)
    195 {
    196     int           rv;         /* Return value */
    197     uint16        data;       /* New value to write to PHY register */
    198     phy_ctrl_t   *pc;
    199 
    200     pc    = EXT_PHY_SW_STATE(unit, port);
    201     data  = enable ? 0 : MII_ECR_TD; /* Transmitt enable/disable */
    202 
    203     SOC_IF_ERROR_RETURN
    204         (MODIFY_PHY522X_AUX_CTRLr(unit, pc, data, MII_ECR_TD));
    205 
    206     data  = enable ? 0 : PHY522X_SUPER_ISOLATE_MODE; 
    207 
    208     /* Device needs to be put in super-isolate mode in order to disable 
    209      * the link in 10BaseT mode
    210      */
    211     SOC_IF_ERROR_RETURN
    212         (MODIFY_PHY522X_AUX_MULTIPLE_PHYr(unit, pc, data,
    213                                           PHY522X_SUPER_ISOLATE_MODE));
    214 
    215     rv = phy_fe_ge_enable_set(unit, port, enable);
    216 
    217     return rv;
    218 }
    219 
    220 /*
    221  * Function:
    222  *    phy_522x_mdix_set
    223  * Description:
    224  *    Set the Auto-MDIX mode of a port/PHY
    225  * Parameters:
    226  *    unit - Device number
    227  *    port - Port number
    228  *    mode - One of:
    229  *            SOC_PORT_MDIX_AUTO
    230  *            Enable auto-MDIX when autonegotiation is enabled
    231  *            SOC_PORT_MDIX_FORCE_AUTO
    232  *            Enable auto-MDIX always
    233  *        SOC_PORT_MDIX_NORMAL
    234  *            Disable auto-MDIX
    235  *        SOC_PORT_MDIX_XOVER
    236  *            Disable auto-MDIX, and swap cable pairs
    237  * Returns:
    238  *    SOC_E_XXX
    239  */
    240 STATIC int
    241 phy_522x_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode)
    242 {
    243     uint16       tmp;
    244     uint16       miscreg;
    245     int          force_auto;
    246     phy_ctrl_t  *pc;
    247 
    248     pc = EXT_PHY_SW_STATE(unit, port);
    249 
    250     if (PHY_IS_BCM5218(pc)) {
    251         if (mode == SOC_PORT_MDIX_NORMAL) {
    252             return SOC_E_NONE;
    253         } else {
    254             return SOC_E_UNAVAIL;
    255         }
    256     }
    257     force_auto = PHY_IS_BCM5248(pc);
    258 
    259     tmp = miscreg = 0;
    260     switch (mode) {
    261     case SOC_PORT_MDIX_AUTO:
    262                                /* clear manual swap and disable */
    263                                /* clear force auto */
    264         break;
    265     case SOC_PORT_MDIX_FORCE_AUTO:
    266         if (!force_auto) {
    267             return SOC_E_UNAVAIL;
    268         }
    269                               /* clear manual swap and disable */
    270         miscreg = 0x4000;    /* set force auto */
    271         break;
    272 
    273     case SOC_PORT_MDIX_XOVER:
    274         tmp = 0x1800;         /* force MDIX */
    275                               /* disable auto-MDIX */
    276         break;
    277     case SOC_PORT_MDIX_NORMAL:
    278         tmp = 0x0800;         /* force mode to normal */
    279                               /* disable auto-MDIX */
    280         break;
    281     default:
    282         return SOC_E_UNAVAIL;
    283     }
    284 
    285     if (force_auto) {
    286         SOC_IF_ERROR_RETURN
    287             (MODIFY_PHY522X_MISC_CTRLr(unit, pc, miscreg, 0x4000));
    288     }
    289 
    290     SOC_IF_ERROR_RETURN
    291         (MODIFY_PHY522X_AUX_ERR_GENERAL_STATr(unit, pc, tmp, 0x1800));
    292   
    293     return SOC_E_NONE;
    294 }
    295 
    296 /*
    297  * Function:
    298  *    phy_522x_mdix_get
    299  * Description:
    300  *    Get the Auto-MDIX mode of a port/PHY
    301  * Parameters:
    302  *    unit - Device number
    303  *    port - Port number
    304  *    mode - (Out) One of:
    305  *            SOC_PORT_MDIX_AUTO
    306  *            Enable auto-MDIX when autonegotiation is enabled
    307  *            SOC_PORT_MDIX_FORCE_AUTO
    308  *            Enable auto-MDIX always
    309  *        SOC_PORT_MDIX_NORMAL
    310  *            Disable auto-MDIX
    311  *        SOC_PORT_MDIX_XOVER
    312  *            Disable auto-MDIX, and swap cable pairs
    313  * Returns:
    314  *    SOC_E_XXX
    315  */
    316 STATIC int
    317 phy_522x_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode)
    318 {
    319     uint16       tmp;
    320     phy_ctrl_t  *pc;
    321 
    322     pc = EXT_PHY_SW_STATE(unit, port);
    323     if (mode == NULL) {
    324         return SOC_E_PARAM;
    325     }
    326 
    327     if (PHY_IS_BCM5218(pc)) {
    328         *mode = SOC_PORT_MDIX_NORMAL;
    329         return SOC_E_NONE;
    330     }
    331 
    332     SOC_IF_ERROR_RETURN
    333         (READ_PHY522X_AUX_ERR_GENERAL_STATr(unit, pc, &tmp));
    334 
    335     switch (tmp & 0x1800) {
    336     case 0x0000:
    337     case 0x1000:
    338         *mode = SOC_PORT_MDIX_AUTO;
    339         break;
    340     case 0x0800:
    341         *mode = SOC_PORT_MDIX_NORMAL;
    342         break;
    343     case 0x1800:
    344         *mode = SOC_PORT_MDIX_XOVER;
    345         break;
    346     }
    347 
    348     if (PHY_IS_BCM5248(pc) &&
    349         (*mode == SOC_PORT_MDIX_AUTO)) {
    350 
    351         SOC_IF_ERROR_RETURN
    352             (READ_PHY522X_MISC_CTRLr(unit, pc, &tmp));
    353         if (tmp & 0x4000) {
    354             *mode = SOC_PORT_MDIX_FORCE_AUTO;
    355         }
    356     }
    357 
    358     return SOC_E_NONE;
    359 }
    360 
    361 /*
    362  * Function:
    363  *    phy_522x_mdix_status_get
    364  * Description:
    365  *    Get the current MDIX status on a port/PHY
    366  * Parameters:
    367  *    unit    - Device number
    368  *    port    - Port number
    369  *    status  - (OUT) One of:
    370  *            SOC_PORT_MDIX_STATUS_NORMAL
    371  *            Straight connection
    372  *            SOC_PORT_MDIX_STATUS_XOVER
    373  *            Crossover has been performed
    374  * Returns:
    375  *    SOC_E_XXX
    376  */
    377 STATIC int
    378 phy_522x_mdix_status_get(int unit, soc_port_t port,
    379                          soc_port_mdix_status_t *status)
    380 {
    381     phy_ctrl_t  *pc;
    382     uint16       tmp;
    383 
    384     if (status == NULL) {
    385         return SOC_E_PARAM;
    386     }
    387 
    388     pc = EXT_PHY_SW_STATE(unit, port);
    389     if (PHY_IS_BCM5218(pc)) {
    390         *status = SOC_PORT_MDIX_STATUS_NORMAL;
    391         return SOC_E_NONE;
    392     }
    393 
    394     SOC_IF_ERROR_RETURN
    395         (READ_PHY522X_AUX_ERR_GENERAL_STATr(unit, pc, &tmp));
    396     if (tmp & 0x2000) {
    397         *status = SOC_PORT_MDIX_STATUS_XOVER;
    398     } else {
    399         *status = SOC_PORT_MDIX_STATUS_NORMAL;
    400     }
    401     return SOC_E_NONE;
    402 }
    403 
    404 /*
    405  * Function:
    406  *      phy_522x_reg_read
    407  * Purpose:
    408  *      Routine to read PHY register
    409  * Parameters:
    410  *      uint         - BCM unit number
    411  *      pc           - PHY state
    412  *      flags        - Flags which specify the register type
    413  *      phy_reg_addr - Encoded register address
    414  *      phy_data     - (OUT) Value read from PHY register
    415  * Note:
    416  *      This register read function is not thread safe. Higher level
    417  * function that calls this function must obtain a per port lock
    418  * to avoid overriding register page mapping between threads.
    419  */
    420 STATIC int
    421 phy_522x_reg_read(int unit, soc_port_t port, uint32 flags,
    422                   uint32 phy_reg_addr, uint32 *phy_data)
    423 {
    424     uint16               reg_bank;
    425     uint8                reg_addr;
    426     uint16               data;     /* Temporary holder for phy_data */
    427     phy_ctrl_t           *pc;      /* PHY software state */
    428 
    429     EXT_PHY_INIT_CHECK(unit, port);
    430 
    431     pc        = EXT_PHY_SW_STATE(unit, port);
    432     reg_bank  = SOC_PHY_REG_BANK(phy_reg_addr);
    433     reg_addr  = SOC_PHY_REG_ADDR(phy_reg_addr);
    434 
    435     SOC_IF_ERROR_RETURN
    436         (phy_reg_fe_read(unit, pc, reg_bank, reg_addr, &data));
    437 
    438    *phy_data = data;
    439 
    440     return SOC_E_NONE;
    441 }
    442 
    443 /*
    444  * Function:
    445  *      phy_522x_reg_write
    446  * Purpose:
    447  *      Routine to write PHY register
    448  * Parameters:
    449  *      uint         - BCM unit number
    450  *      pc           - PHY state
    451  *      flags        - Flags which specify the register type
    452  *      phy_reg_addr - Encoded register address
    453  *      phy_data     - Value write to PHY register
    454  * Note:
    455  *      This register read function is not thread safe. Higher level
    456  * function that calls this function must obtain a per port lock
    457  * to avoid overriding register page mapping between threads.
    458  */
    459 STATIC int
    460 phy_522x_reg_write(int unit, soc_port_t port, uint32 flags,
    461                    uint32 phy_reg_addr, uint32 phy_data)
    462 {
    463     uint16               reg_bank;
    464     uint8                reg_addr;
    465     uint16               data;     /* Temporary holder for phy_data */
    466     phy_ctrl_t           *pc;      /* PHY software state */
    467 
    468     EXT_PHY_INIT_CHECK(unit, port);
    469 
    470     pc   = EXT_PHY_SW_STATE(unit, port);
    471     data = (uint16) (phy_data & 0x0000FFFF);
    472 
    473     reg_bank  = SOC_PHY_REG_BANK(phy_reg_addr);
    474     reg_addr  = SOC_PHY_REG_ADDR(phy_reg_addr);
    475 
    476     return phy_reg_fe_write(unit, pc, reg_bank, reg_addr, data);
    477 }
    478 /*
    479  * Function:
    480  *      phy_522x_reg_modify
    481  * Purpose:
    482  *      Routine to write PHY register
    483  * Parameters:
    484  *      uint         - BCM unit number
    485  *      pc           - PHY state
    486  *      flags        - Flags which specify the register type
    487  *      phy_reg_addr - Encoded register address
    488  *      phy_mo_data  - New value for the bits specified in phy_mo_mask
    489  *      phy_mo_mask  - Bit mask to modify
    490  * Note:
    491  *      This register read function is not thread safe. Higher level
    492  * function that calls this function must obtain a per port lock
    493  * to avoid overriding register page mapping between threads.
    494  */
    495 STATIC int
    496 phy_522x_reg_modify(int unit, soc_port_t port, uint32 flags,
    497                     uint32 phy_reg_addr, uint32 phy_data, uint32 phy_data_mask)
    498 {
    499     uint16               reg_bank;
    500     uint8                reg_addr;
    501     uint16               data;     /* Temporary holder for phy_data */
    502     uint16               mask;     /* Temporary holder for phy_data_mask */
    503     phy_ctrl_t           *pc;      /* PHY software state */
    504 
    505     EXT_PHY_INIT_CHECK(unit, port);
    506 
    507     pc   = EXT_PHY_SW_STATE(unit, port);
    508     data = (uint16) (phy_data & 0x0000FFFF);
    509     mask = (uint16) (phy_data_mask & 0x0000FFFF);
    510 
    511     reg_bank  = SOC_PHY_REG_BANK(phy_reg_addr);
    512     reg_addr  = SOC_PHY_REG_ADDR(phy_reg_addr);
    513 
    514     return phy_reg_fe_modify(unit, pc, reg_bank, reg_addr, data, mask);
    515 }
    516 
    517 /*
    518  * Function:
    519  *    phy_522x_control_set
    520  * Description:
    521  *     Set PHY specific properties 
    522  * Parameters:
    523  *     unit        device number
    524  *     port        port number
    525  *     type        configuration type
    526  *     value       new value for the configuration ; ms 
    527  * Return:
    528  *     BCM_E_XXX
    529  */
    530 STATIC int
    531 phy_522x_control_set(int unit, soc_port_t port, 
    532                              soc_phy_control_t type, uint32 value)
    533 {
    534     int rv = SOC_E_NONE;
    535     uint16 data16;
    536     phy_ctrl_t *pc;
    537     
    538     pc = EXT_PHY_SW_STATE(unit, port);
    539 
    540     if (!PHY_IS_BCM5248(pc)) {
    541         return SOC_E_UNAVAIL;
    542     }
    543 
    544     PHY_CONTROL_TYPE_CHECK(type);
    545 
    546 
    547     switch(type) {
    548         case SOC_PHY_CONTROL_POWER:
    549             if (pc->power_mode == value) {
    550                 return SOC_E_NONE;
    551             } else if (value == SOC_PHY_CONTROL_POWER_AUTO) {
    552                 SOC_IF_ERROR_RETURN
    553                     (MODIFY_PHY522X_AUX_STAT2r(unit,pc,
    554                         PHY_522X_AUTO_PWRDWN_EN,
    555                         PHY_522X_AUTO_PWRDWN_EN));
    556                 pc->power_mode = value;
    557             } else if ((value == SOC_PHY_CONTROL_POWER_FULL)
    558                    || (value == SOC_PHY_CONTROL_POWER_AUTO_DISABLE)) {
    559                 SOC_IF_ERROR_RETURN
    560                     (MODIFY_PHY522X_AUX_STAT2r(unit,pc,
    561                         0,
    562                         PHY_522X_AUTO_PWRDWN_EN));
    563                 pc->power_mode = value;
    564             } else {
    565                 rv = SOC_E_PARAM;
    566             }
    567             break;
    568         case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME:
    569             if (value <= PHY_522X_AUTO_PWRDWN_WAKEUP_MAX) {
    570                 /* value = 0 mean force stay in low-power mode */
    571                 if (value < PHY_522X_AUTO_PWRDWN_WAKEUP_UNIT) {
    572                     value = PHY_522X_AUTO_PWRDWN_WAKEUP_UNIT;
    573                 }
    574             } else { /* anything more then max, set to the max */
    575                 value = PHY_522X_AUTO_PWRDWN_WAKEUP_MAX;
    576             }
    577             SOC_IF_ERROR_RETURN
    578                 (MODIFY_PHY522X_AUX_STAT2r(unit,pc,
    579                     value/PHY_522X_AUTO_PWRDWN_WAKEUP_UNIT,
    580                     PHY_522X_AUTO_PWRDWN_WAKEUP_MASK));
    581             break;
    582         case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME:
    583             /* 
    584              * sleep time configuration is either 2.5s or 5.0 s, 
    585              * default is 2.5s 
    586              */
    587             if (value < PHY_522X_AUTO_PWRDWN_SLEEP_MAX) {
    588                 data16 = 0; /* anything less than 5.0s, default to 2.5s */
    589             } else {
    590                 data16 = PHY_522X_AUTO_PWRDWN_SLEEP_MASK;
    591             }
    592             SOC_IF_ERROR_RETURN
    593                 (MODIFY_PHY522X_AUX_STAT2r(unit,pc,
    594                     data16, PHY_522X_AUTO_PWRDWN_SLEEP_MASK));
    595             break;
    596         default:
    597             rv = SOC_E_UNAVAIL;
    598             break;
    599     }
    600     return rv;
    601 }    
    602 
    603 /*
    604  * Function:
    605  *    phy_522x_control_get
    606  * Description:
    607  *     Get PHY specific properties 
    608  * Parameters:
    609  *     unit        device number
    610  *     port        port number
    611  *     type        configuration type
    612  *     value       new value for the configuration ; ms 
    613  * Return:
    614  *     BCM_E_XXX
    615  */
    616 STATIC int
    617 phy_522x_control_get(int unit, soc_port_t port, 
    618                              soc_phy_control_t type, uint32 *value)
    619 {
    620     int rv;
    621     phy_ctrl_t *pc;
    622     uint16 data16;
    623 
    624     pc = EXT_PHY_SW_STATE(unit, port);
    625     if (!PHY_IS_BCM5248(pc)) {
    626         return SOC_E_UNAVAIL;
    627     }
    628 
    629     PHY_CONTROL_TYPE_CHECK(type);
    630 
    631     rv = SOC_E_NONE;
    632     switch(type) {
    633         case SOC_PHY_CONTROL_POWER:
    634             *value = pc->power_mode;
    635             break;
    636         case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME:
    637             SOC_IF_ERROR_RETURN
    638                 (READ_PHY522X_AUX_STAT2r(unit,pc, &data16));
    639 
    640             if (data16 & PHY_522X_AUTO_PWRDWN_SLEEP_MASK) {
    641                 *value = PHY_522X_AUTO_PWRDWN_SLEEP_MAX;
    642             } else {
    643                 *value = 2500;
    644             }
    645             break;
    646 
    647         case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME:
    648             SOC_IF_ERROR_RETURN
    649                 (READ_PHY522X_AUX_STAT2r(unit,pc, &data16));
    650 
    651             data16 &= PHY_522X_AUTO_PWRDWN_WAKEUP_MASK;
    652             *value = data16 * PHY_522X_AUTO_PWRDWN_WAKEUP_UNIT;
    653             break;
    654 
    655         default:
    656             rv = SOC_E_UNAVAIL;
    657             break;
    658     }
    659     return rv;
    660 }
    661 
    662 /*
    663  * Variable:    phy_522xdrv_fe
    664  * Purpose:    Phy Driver for 522X
    665  */
    666 phy_driver_t phy_522xdrv_fe = {
    667     "Broadcom 522X 10/100 Fast Ethernet PHY Driver",
    668     phy_522x_init,
    669     phy_fe_ge_reset,
    670     phy_fe_ge_link_get,
    671     phy_522x_enable_set,
    672     phy_fe_ge_enable_get,
    673     phy_fe_ge_duplex_set,
    674     phy_fe_ge_duplex_get,
    675     phy_fe_ge_speed_set,
    676     phy_fe_ge_speed_get,
    677     phy_fe_ge_master_set,
    678     phy_fe_ge_master_get,
    679     phy_fe_ge_an_set,
    680     phy_fe_ge_an_get,
    681     phy_fe_adv_local_set,
    682     phy_fe_adv_local_get,
    683     phy_fe_adv_remote_get,
    684     phy_fe_ge_lb_set,
    685     phy_fe_ge_lb_get,
    686     phy_fe_interface_set,
    687     phy_fe_interface_get,
    688     phy_fe_ability_get,
    689     NULL,                       /* Link up event */
    690     NULL,                       /* Link down event */
    691     phy_522x_mdix_set,
    692     phy_522x_mdix_get,
    693     phy_522x_mdix_status_get,
    694     NULL,                       /* Medium config set */
    695     NULL,                       /* Medium config get */
    696     phy_fe_ge_medium_get,
    697     phy_522x_cable_diag,
    698     NULL,                       /* phy_link_change */
    699     phy_522x_control_set,       /* phy_control_set */
    700     phy_522x_control_get,       /* phy_control_get */
    701     phy_522x_reg_read,
    702     phy_522x_reg_write, 
    703     phy_522x_reg_modify,   
    704     NULL                        /* Phy event notify */
    705 };
    706 
    707 #endif /* INCLUDE_PHY_522X */
    708 
    709 int _soc_phy_522x_not_empty;