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

phy54680.c (152199B)


      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:        phy54680.c
      8  * Purpose:     PHY driver for BCM54680
      9  */
     10 #include <sal/types.h>
     11 #include <sal/core/spl.h>
     12 #include <shared/bsl.h>
     13 #include <soc/drv.h>
     14 #include <soc/debug.h>
     15 #include <soc/error.h>
     16 #include <soc/phyreg.h>
     17 
     18 #include <soc/phy.h>
     19 #include <soc/phy/phyctrl.h>
     20 #include <soc/phy/drv.h>
     21 
     22 #include "phydefs.h"      /* Must include before other phy related includes */
     23 
     24 #if defined(INCLUDE_PHY_54680) || defined(INCLUDE_PHY_54680E) || defined(INCLUDE_PHY_52681E)
     25 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     26 
     27 #include "phyident.h"
     28 #include "phyreg.h"
     29 #include "phyfege.h"
     30 #include "phynull.h"
     31 #include "phy54680.h"
     32 
     33 #define PHY_IS_BCM54680(_pc)      (PHY_MODEL_CHECK((_pc), \
     34                                                 PHY_BCM54680_OUI, \
     35                                                 PHY_BCM54680_MODEL))
     36 
     37 #define PHY_IS_BCM54680_A0(_pc)   (PHY_MODEL_CHECK((_pc), \
     38                                                 PHY_BCM54680_OUI, \
     39                                                 PHY_BCM54680_MODEL) \
     40                                    && ((_pc)->phy_rev == 0x0 ))
     41 
     42 #define PHY_BCM54680_A0_ID0    PHY_ID0(PHY_BCM54680_OUI,PHY_BCM54680_MODEL,0)
     43 #define PHY_BCM54680_A0_ID1    PHY_ID1(PHY_BCM54680_OUI,PHY_BCM54680_MODEL,0)
     44 
     45 #define PHY_IS_BCM54880E(_pc)   (PHY_MODEL_CHECK((_pc), \
     46                                  PHY_BCM54880E_OUI, \
     47                                  PHY_BCM54880E_MODEL))
     48 
     49 #define PHY_IS_BCM54880E_A0(_pc) (PHY_MODEL_CHECK((_pc), \
     50                                   PHY_BCM54880E_OUI, \
     51                                   PHY_BCM54880E_MODEL) \
     52                                   && ((_pc)->phy_rev == 0x0 ))
     53 
     54 #define PHY_IS_BCM54880E_A1(_pc) (PHY_MODEL_CHECK((_pc), \
     55                                   PHY_BCM54880E_OUI, \
     56                                   PHY_BCM54880E_MODEL) \
     57                                   && ((_pc)->phy_rev == 0x1))
     58 
     59 #define PHY_IS_BCM54880E_A0A1(_pc) (PHY_MODEL_CHECK((_pc), \
     60                                   PHY_BCM54880E_OUI, \
     61                                   PHY_BCM54880E_MODEL) \
     62                                   && (((_pc)->phy_rev & 0xe) == 0x0))
     63 
     64 #define PHY_IS_BCM54680E(_pc)   (PHY_MODEL_CHECK((_pc), \
     65                                  PHY_BCM54680E_OUI, \
     66                                  PHY_BCM54680E_MODEL) \
     67                                  && (((_pc)->phy_rev & 0x8) == 0x8))
     68 
     69 #define PHY_IS_BCM54680E_A0(_pc)   (PHY_MODEL_CHECK((_pc), \
     70                                  PHY_BCM54680E_OUI, \
     71                                  PHY_BCM54680E_MODEL) \
     72                                  && ((_pc)->phy_rev == 0x8))
     73 
     74 #define PHY_IS_BCM54680E_A1(_pc)   (PHY_MODEL_CHECK((_pc), \
     75                                  PHY_BCM54680E_OUI, \
     76                                  PHY_BCM54680E_MODEL) \
     77                                  && ((_pc)->phy_rev == 0x9))
     78 
     79 #define PHY_IS_BCM54680E_A0A1(_pc)   (PHY_MODEL_CHECK((_pc), \
     80                                  PHY_BCM54680E_OUI, \
     81                                  PHY_BCM54680E_MODEL) \
     82                                  && (((_pc)->phy_rev & 0xe) == 0x8))
     83 
     84 #define PHY_IS_BCM52681E(_pc)   (PHY_MODEL_CHECK((_pc), \
     85                                  PHY_BCM52681E_OUI, \
     86                                  PHY_BCM52681E_MODEL) \
     87                                  && (((_pc)->phy_rev & 0x8) == 0x8))
     88 
     89 #define SOC_IF_ERROR_BREAK(op, __rv__) \
     90         if (((__rv__) = (op)) < 0) {   \
     91             break;                     \
     92         }
     93 
     94 #ifndef DISABLE_CLK125
     95 #define DISABLE_CLK125 0
     96 #endif
     97 
     98 #ifndef AUTO_MDIX_WHEN_AN_DIS
     99 #define AUTO_MDIX_WHEN_AN_DIS 0
    100 #endif
    101 
    102 #define ECD_ENABLE 0
    103 
    104 #define DISABLE_TEST_PORT 1
    105 /* #define A0_AUTO_FILL_PORT_INDEX 1 */
    106 
    107 STATIC int
    108 phy_54680_speed_set(int unit, soc_port_t port, int speed);
    109 STATIC int
    110 phy_54680_duplex_set(int unit, soc_port_t port, int duplex);
    111 STATIC int
    112 phy_54680_master_set(int unit, soc_port_t port, int master);
    113 STATIC int
    114 phy_54680_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability);
    115 STATIC int
    116 phy_54680_autoneg_set(int unit, soc_port_t port, int autoneg);
    117 STATIC int
    118 phy_54680_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode);
    119 STATIC int
    120 phy_54680_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability);
    121 
    122 STATIC int
    123 phy_54680_control_set(int unit, soc_port_t port,
    124                      soc_phy_control_t type, uint32 value);
    125 
    126 extern int
    127 phy_ecd_cable_diag_init(int unit, soc_port_t port);
    128 
    129 extern int
    130 phy_ecd_cable_diag(int unit, soc_port_t port,
    131             soc_port_cable_diag_t *status);
    132 
    133 
    134 
    135 
    136 /*
    137  * Function:
    138  *      _phy_54680e_cl45_reg_read
    139  * Purpose:
    140  *      Read Clause 45 Register using Clause 22 register access
    141  * Parameters:
    142  *      unit      - StrataSwitch unit #.
    143  *      pc        - Phy control
    144  *      flags     - Flags
    145  *      dev_addr  - Clause 45 Device
    146  *      reg_addr  - Register Address to read
    147  *      val       - Value Read
    148  * Returns:
    149  *      SOC_E_XXX
    150  */
    151 
    152 STATIC int
    153 _phy_54680e_cl45_reg_read(int unit, phy_ctrl_t *pc, uint32 flags, 
    154                          uint8 dev_addr, uint16 reg_addr, uint16 *val)
    155 {
    156 
    157     /* Write Device Address to register 0x0D (Set Function field to Address)*/
    158     SOC_IF_ERROR_RETURN
    159         (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0D, (dev_addr & 0x001f)));
    160 
    161     /* Select the register by writing to register address to register 0x0E */
    162     SOC_IF_ERROR_RETURN
    163         (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0E, reg_addr));
    164 
    165     /* Write Device Address to register 0x0D (Set Function field to Data)*/
    166     SOC_IF_ERROR_RETURN
    167         (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0D, 
    168                            ((0x4000) | (dev_addr & 0x001f))));
    169 
    170     /* Read register 0x0E to get the value */
    171     SOC_IF_ERROR_RETURN
    172         (PHY54680_REG_READ(unit, pc, flags, 0x00, 0x0E, val));
    173 
    174     return SOC_E_NONE;
    175 }
    176 
    177 /*
    178  * Function:
    179  *      _phy_54680e_cl45_reg_write
    180  * Purpose:
    181  *      Write Clause 45 Register content using Clause 22 register access
    182  * Parameters:
    183  *      unit      - StrataSwitch unit #.
    184  *      pc        - Phy control
    185  *      flags     - Flags
    186  *      dev_addr  - Clause 45 Device
    187  *      reg_addr  - Register Address to read
    188  *      val       - Value to be written
    189  * Returns:
    190  *      SOC_E_XXX
    191  */
    192 
    193 STATIC int
    194 _phy_54680e_cl45_reg_write(int unit, phy_ctrl_t *pc, uint32 flags, 
    195                          uint8 dev_addr, uint16 reg_addr, uint16 val)
    196 {
    197 
    198     /* Write Device Address to register 0x0D (Set Function field to Address)*/
    199     SOC_IF_ERROR_RETURN
    200         (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0D, (dev_addr & 0x001f)));
    201 
    202     /* Select the register by writing to register address to register 0x0E */
    203     SOC_IF_ERROR_RETURN
    204         (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0E, reg_addr));
    205 
    206     /* Write Device Address to register 0x0D (Set Function field to Data)*/
    207     SOC_IF_ERROR_RETURN
    208         (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0D, 
    209                            ((0x4000) | (dev_addr & 0x001f))));
    210 
    211     /* Write register 0x0E to write the value */
    212     SOC_IF_ERROR_RETURN
    213         (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0E, val));
    214 
    215     return SOC_E_NONE;
    216 }
    217 
    218 /*
    219  * Function:
    220  *      _phy_54680e_cl45_reg_modify
    221  * Purpose:
    222  *      Modify Clause 45 Register contents using Clause 22 register access
    223  * Parameters:
    224  *      unit      - StrataSwitch unit #.
    225  *      pc        - Phy control
    226  *      flags     - Flags
    227  *      reg_bank  - Register bank
    228  *      dev_addr  - Clause 45 Device
    229  *      reg_addr  - Register Address to read
    230  *      val       - Value 
    231  *      mask      - Mask for modifying the contents of the register
    232  * Returns:
    233  *      SOC_E_XXX
    234  */
    235 
    236 STATIC int
    237 _phy_54680e_cl45_reg_modify(int unit, phy_ctrl_t *pc, uint32 flags, 
    238                           uint8 dev_addr, uint16 reg_addr, uint16 val, 
    239                           uint16 mask)
    240 {
    241 
    242     uint16 value = 0;
    243 
    244     SOC_IF_ERROR_RETURN
    245         (PHY54680E_CL45_REG_READ(unit, pc, flags, dev_addr, reg_addr, &value));
    246 
    247     value = (val & mask) | (value & ~mask);
    248 
    249     SOC_IF_ERROR_RETURN
    250         (PHY54680E_CL45_REG_WRITE(unit, pc, flags, dev_addr, reg_addr, value));
    251 
    252     return SOC_E_NONE;
    253 }
    254 
    255 /*
    256  * Function:
    257  *      _phy_54680e_blk_top_lvl_reg_read
    258  * Purpose:
    259  *      New mechanism to Read Top Level Registers for EEE and 1588.
    260  * Parameters:
    261  *      unit       - StrataSwitch unit #.
    262  *      pc         - Phy control
    263  *      flags      - Flags
    264  *      reg_offset - Register Address to read
    265  *      val        - Value Read
    266  * Returns:
    267  *      SOC_E_XXX
    268  */
    269 
    270 STATIC int
    271 _phy_54680e_blk_top_lvl_reg_read(int unit, phy_ctrl_t *pc, uint32 flags, 
    272                          uint16 reg_offset, uint16 *val)
    273 {
    274 
    275     /* Write register 0x17 with the top level reg offset to read (handled in PHY54680_REG_READ) */
    276     /* Read register 0x15 to get the value */
    277     SOC_IF_ERROR_RETURN
    278         (PHY54680_REG_READ(unit, pc, flags, (0x0D00|(reg_offset & 0xff)), 0x15, val));
    279 
    280     return SOC_E_NONE;
    281 }
    282 
    283 /*
    284  * Function:
    285  *      _phy_54680e_blk_top_lvl_reg_write
    286  * Purpose:
    287  *      New mechanism to Write Top Level Registers for EEE and 1588
    288  * Parameters:
    289  *      unit      - StrataSwitch unit #.
    290  *      pc        - Phy control
    291  *      flags     - Flags
    292  *      reg_offset  - Register Address to read
    293  *      val       - Value to be written
    294  * Returns:
    295  *      SOC_E_XXX
    296  */
    297 
    298 STATIC int
    299 _phy_54680e_blk_top_lvl_reg_write(int unit, phy_ctrl_t *pc, uint32 flags, 
    300                                   uint16 reg_offset, uint16 val)
    301 {
    302 
    303     /* Write register 0x17 with the top level reg offset to write (handled in PHY54680_REG_WRITE) */
    304     /* Write register 0x15 the value to write to the top level register offset */
    305     SOC_IF_ERROR_RETURN
    306         (PHY54680_REG_WRITE(unit, pc, flags, (0x0D00|(reg_offset & 0xff)), 0x15, val));
    307 
    308     return SOC_E_NONE;
    309 }
    310 
    311 /*
    312  * Function:
    313  *      _phy_54680e_blk_top_lvl_reg_modify
    314  * Purpose:
    315  *      Modify Clause 45 Register contents using Clause 22 register access
    316  * Parameters:
    317  *      unit      - StrataSwitch unit #.
    318  *      pc        - Phy control
    319  *      flags     - Flags
    320  *      reg_bank  - Register bank
    321  *      dev_addr  - Clause 45 Device
    322  *      reg_addr  - Register Address to read
    323  *      val       - Value 
    324  *      mask      - Mask for modifying the contents of the register
    325  * Returns:
    326  *      SOC_E_XXX
    327  */
    328 
    329 STATIC int
    330 _phy_54680e_blk_top_lvl_reg_modify(int unit, phy_ctrl_t *pc, uint32 flags,
    331                           uint16 reg_offset, uint16 val, uint16 mask)
    332 {
    333 
    334     uint16 value = 0;
    335 
    336     /* Write register 0x17 with the top level reg offset to read */
    337     SOC_IF_ERROR_RETURN
    338         (_phy_54680e_blk_top_lvl_reg_read(unit, pc, flags, 
    339                                           reg_offset, &value));
    340     value = (val & mask) | (value & ~mask);
    341 
    342     /* Write register 0x17 with the top level reg offset to read */
    343     SOC_IF_ERROR_RETURN
    344         (_phy_54680e_blk_top_lvl_reg_write(unit, pc, flags, 
    345                                           reg_offset, value));
    346 
    347     return SOC_E_NONE;
    348 }
    349 
    350 /*
    351  * Function:
    352  *      phy_54680_toplvl_reg_read
    353  * Purpose:
    354  *      Read a top level register from a supporting chip
    355  * Parameters:
    356  *      unit - SOC Unit #.
    357  *      port - Port number.
    358  *      flags - 
    359  *      reg_offset  - Offset to the reg
    360  *      data  - Pointer to data returned
    361  * Returns:
    362  *      SOC_E_XXX
    363  */
    364 int
    365 phy_54680_toplvl_reg_read(int unit, soc_port_t port, int flags, uint8 reg_offset, uint16 *data)
    366 {
    367     phy_ctrl_t    *pc;
    368     uint16 reg_data, status;
    369     int         rv = SOC_E_NONE;
    370 
    371     LOG_VERBOSE(BSL_LS_SOC_PHY,
    372                 (BSL_META_U(unit,
    373                             "entered phy_54680_toplvl_reg_read: "
    374                             "unit %d, port %d, flags %x reg_offset %u\n"), 
    375                  unit, port, flags, reg_offset));
    376     
    377     pc = EXT_PHY_SW_STATE(unit, port);
    378 
    379     /* Write Reg address to Port 5's (offset=4) register 0x1C, shadow 0x0B */
    380     /* Status READ from Port 3's (offset=2) register 0x15 */
    381 
    382     /* Write Reg offset to Port 5's register 0x1C, shadow 0x0B */
    383     reg_data = (0xAC00 | reg_offset);
    384     INT_MCU_LOCK(unit);
    385     pc->phy_id =  PHY54680_SLICE_ADDR(pc, 4);
    386     rv = pc->write(unit, pc->phy_id, 0x1c, reg_data);
    387     if (SOC_FAILURE(rv)) {
    388         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    389         INT_MCU_UNLOCK(unit);
    390         return rv;
    391     }
    392 
    393     pc->phy_id =  PHY54680_SLICE_ADDR(pc, 2);
    394     /* Read data from Top level MII Status register(0x15h) */
    395     rv = pc->write(unit, pc->phy_id, 0x17, 0x8F0B);
    396     if (SOC_FAILURE(rv)) {
    397         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    398         INT_MCU_UNLOCK(unit);
    399         return rv;
    400     }
    401     rv = pc->read(unit, pc->phy_id, 0x15, &status);
    402     INT_MCU_UNLOCK(unit);
    403     if (SOC_FAILURE(rv)) {
    404         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    405         return rv;
    406     }
    407 
    408     *data = (status & 0xff);
    409 
    410     pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    411 
    412     return SOC_E_NONE;
    413 }
    414 
    415 /*
    416  * Function:
    417  *      phy_54680_toplvl_reg_write
    418  * Purpose:
    419  *      Write to a top level register from a supporting chip
    420  * Parameters:
    421  *      unit - SOC Unit #.
    422  *      port - Port number.
    423  *      flags - 
    424  *      reg_offset  - Offset to the reg
    425  *      data  - Data to be written
    426  * Returns:
    427  *      SOC_E_XXX
    428  */
    429 int
    430 phy_54680_toplvl_reg_write(int unit, soc_port_t port, int flags, uint8 reg_offset, uint16 data)
    431 {
    432     phy_ctrl_t *pc;
    433     uint16 reg_data;
    434 #ifdef BROADCOM_DEBUG
    435     uint16 status;
    436 #endif
    437     int         rv = SOC_E_NONE;
    438     
    439     LOG_VERBOSE(BSL_LS_SOC_PHY,
    440                 (BSL_META_U(unit,
    441                             "entered phy_54680_toplvl_reg_write: "
    442                             "unit %d, port %d, flags %x reg_offset %u, data %u\n"), 
    443                  unit, port, flags, reg_offset, data));
    444 
    445     pc       = EXT_PHY_SW_STATE(unit, port);
    446 
    447     /* Write Reg address to Port 5's register 0x1C, shadow 0x0B */
    448     /* Write data to Port 6's register 0x1C, shadow 0x0c */
    449     /* Status READ from Port 3's register 0x15 */
    450 
    451     /* Write Data to port6 (offset = 5), register 0x1C, shadow 0x0c */
    452     INT_MCU_LOCK(unit);
    453     pc->phy_id =  PHY54680_SLICE_ADDR(pc, 5);
    454     reg_data = (0xB000 | (data & 0xff));
    455     rv = pc->write(unit, pc->phy_id, 0x1c, reg_data);
    456     if (SOC_FAILURE(rv)) {
    457         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    458         INT_MCU_UNLOCK(unit);
    459         return rv;
    460     }
    461 
    462     pc->phy_id =  PHY54680_SLICE_ADDR(pc, 4);
    463     /* Write Reg address to Port 5's (offset = 4) register 0x1C, shadow 0x0B */
    464     /* Enable Write ( Port 5's register 0x1C, shadow 0x0B) Bit 7 = 1 */
    465     reg_data = (0xAC80 | reg_offset);
    466     rv = pc->write(unit, pc->phy_id, 0x1c, reg_data);
    467     if (SOC_FAILURE(rv)) {
    468         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    469         INT_MCU_UNLOCK(unit);
    470         return rv;
    471     }
    472 
    473     /* Disable Write ( Port 5's register 0x1C, shadow 0x0B) Bit 7 = 0 */
    474     reg_data = (0xAC00 | reg_offset);
    475     rv = pc->write(unit, pc->phy_id, 0x1c, reg_data);
    476     if (SOC_FAILURE(rv)) {
    477         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    478         INT_MCU_UNLOCK(unit);
    479         return rv;
    480     }
    481 
    482 #ifdef BROADCOM_DEBUG
    483     pc->phy_id =  PHY54680_SLICE_ADDR(pc, 2);
    484     /* Read data from Top level MII Status register(0x15h) */
    485     rv = pc->write(unit, pc->phy_id, 0x17, 0x8F0B);
    486     if (SOC_FAILURE(rv)) {
    487         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    488         INT_MCU_UNLOCK(unit);
    489         return rv;
    490     }
    491     rv = pc->read(unit, pc->phy_id, 0x15, &status);
    492 
    493     if (SOC_FAILURE(rv)) {
    494         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    495         return rv;
    496     }
    497 #endif
    498 
    499     pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
    500     INT_MCU_UNLOCK(unit);
    501 
    502     return SOC_E_NONE;
    503 }
    504 
    505 /*
    506  * Function:
    507  *      phy_54680_medium_status
    508  * Purpose:
    509  *      Indicate the current active medium
    510  * Parameters:
    511  *      unit - StrataSwitch unit #.
    512  *      port - StrataSwitch port #.
    513  *      medium - (OUT) One of:
    514  *              SOC_PORT_MEDIUM_COPPER
    515  *              SOC_PORT_MEDIUM_FIBER
    516  * Returns:
    517  *      SOC_E_NONE.
    518  */
    519 STATIC int
    520 phy_54680_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium)
    521 {
    522 
    523     *medium = SOC_PORT_MEDIUM_COPPER;
    524 
    525     return SOC_E_NONE;
    526 
    527 }
    528 
    529 /*
    530  * Function:
    531  *      phy_54680_medium_config_set
    532  * Purpose:
    533  *      Set the operating parameters that are automatically selected
    534  *      when medium switches type.
    535  * Parameters:
    536  *      unit - StrataSwitch unit #
    537  *      port - Port number
    538  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
    539  *      cfg - Operating parameters
    540  * Returns:
    541  *      SOC_E_XXX
    542  */
    543 STATIC int
    544 phy_54680_medium_config_set(int unit, soc_port_t port, 
    545                            soc_port_medium_t  medium,
    546                            soc_phy_config_t  *cfg)
    547 {
    548     COMPILER_REFERENCE(medium);
    549 
    550     SOC_IF_ERROR_RETURN
    551         (phy_54680_speed_set(unit, port, cfg->force_speed));
    552     SOC_IF_ERROR_RETURN
    553         (phy_54680_duplex_set(unit, port, cfg->force_duplex));
    554     SOC_IF_ERROR_RETURN
    555         (phy_54680_master_set(unit, port, cfg->master));
    556     SOC_IF_ERROR_RETURN
    557         (phy_54680_ability_advert_set(unit, port, &cfg->advert_ability));
    558     SOC_IF_ERROR_RETURN
    559         (phy_54680_autoneg_set(unit, port, cfg->autoneg_enable));
    560     SOC_IF_ERROR_RETURN
    561         (phy_54680_mdix_set(unit, port, cfg->mdix));
    562 
    563     return SOC_E_NONE;
    564 }
    565 
    566 /*
    567  * Function:
    568  *      phy_54680_medium_config_get
    569  * Purpose:
    570  *      Get the operating parameters that are automatically selected
    571  *      when medium switches type.
    572  * Parameters:
    573  *      unit - StrataSwitch unit #
    574  *      port - Port number
    575  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
    576  *      cfg - (OUT) Operating parameters
    577  * Returns:
    578  *      SOC_E_XXX
    579  */
    580 
    581 STATIC int
    582 phy_54680_medium_config_get(int unit, soc_port_t port, 
    583                            soc_port_medium_t medium,
    584                            soc_phy_config_t *cfg)
    585 {
    586     phy_ctrl_t    *pc;
    587 
    588     COMPILER_REFERENCE(medium);
    589 
    590     pc = EXT_PHY_SW_STATE(unit, port);
    591 
    592     sal_memcpy(cfg, &pc->copper, sizeof (*cfg));
    593 
    594     return SOC_E_NONE;
    595 }
    596 
    597 
    598 
    599 
    600 
    601 STATIC int
    602 _phy_54680_mdi_pair_set(int unit, soc_port_t port, uint32 mdi_pair_map)
    603 {
    604     phy_ctrl_t *pc;
    605     uint16  reg_val;
    606     pc = EXT_PHY_SW_STATE(unit, port);
    607 
    608     if (mdi_pair_map) {
    609         /*
    610              * lane 0 (bit0~1), lane 1 (bit2~3), lane 2 (bit4~5), lane 3 (bit6~7)
    611              * Enable swap (bit 8)
    612              */
    613         reg_val = ((mdi_pair_map & (0x3<<12)) >> 6) | 
    614                   ((mdi_pair_map & (0x3<<8)) >> 4)  | 
    615                   ((mdi_pair_map & (0x3<<4)) >> 2)  | 
    616                   (mdi_pair_map & 0x3);
    617         reg_val |= 0x100; /* Enable */
    618         SOC_IF_ERROR_RETURN(
    619             WRITE_PHY_REG(unit, pc, 0x17, 0x0f09));
    620         SOC_IF_ERROR_RETURN(
    621             WRITE_PHY_REG(unit, pc, 0x15, reg_val));
    622     }
    623 
    624     LOG_INFO(BSL_LS_SOC_PORT,
    625              (BSL_META_U(unit,
    626                          "_phy_54680_mdi_pair_set port %d\n"), port));
    627 
    628     return SOC_E_NONE;
    629 }
    630 
    631 
    632 /*
    633  * Function:
    634  *      _phy_54680_reset_setup
    635  * Purpose:
    636  *      Function to reset the PHY and set up initial operating registers.
    637  * Parameters:
    638  *      unit - StrataSwitch unit #.
    639  *      port - StrataSwitch port #.
    640  * Returns:
    641  *      SOC_E_XXX
    642  */
    643 
    644 STATIC int
    645 _phy_54680_reset_setup(int unit, soc_port_t port)
    646 {
    647     phy_ctrl_t        *pc;
    648     uint16             tmp;
    649     uint16             phy_addr;
    650     soc_port_t         primary_port;
    651     uint16             id0, id1;
    652     int                index;
    653     uint32             phy_mdi_pair_map;
    654 
    655     pc     = EXT_PHY_SW_STATE(unit, port);
    656 
    657     if (PHY_IS_BCM52681E(pc)) {
    658         SOC_IF_ERROR_RETURN(phy_fe_init(unit, port));
    659 
    660         SOC_IF_ERROR_RETURN
    661             (MODIFY_PHY54680_MII_GB_CTRLr(unit, pc, 0, MII_GB_CTRL_ADV_1000HD | MII_GB_CTRL_ADV_1000FD));
    662     } else {
    663         SOC_IF_ERROR_RETURN(phy_ge_init(unit, port));
    664     }
    665 
    666     if ( soc_phy_primary_and_offset_get(unit, port, &primary_port, &index)
    667                                        == SOC_E_NONE ) {
    668         /* determine the order of logical ports on a PHY chip */
    669         if ( index & 0x80 ) {
    670             PHY54680_FLAGS(pc) |= ( PHY54680_PHYA_REV);    /* reverse order */
    671         } else {
    672             PHY54680_FLAGS(pc) &= (~PHY54680_PHYA_REV);    /* normal  order */
    673         }
    674     } else {
    675         /* config variable 'phy_port_primary_and_offset' not specified  *\
    676         |* Assign default values in a 4-alignment basis :               *|
    677         |*    e.g.         port =  2 3 4 5 6 7 8 9                      *|
    678         |*                index =  0 1 2 3 0 1 2 3                      *|
    679         \*         primary_port =  2 2 2 2 6 6 6 6                      */
    680         index        = pc->phy_id & ( PHY54680_DEV_PHY_SLICE_MASK);
    681         primary_port = ((port - index) <= 0) ?  0 :  (port - index);
    682         PHY54680_FLAGS(pc) &= (~PHY54680_PHYA_REV);        /* normal  order */
    683         LOG_WARN(BSL_LS_SOC_PHY,
    684                  (BSL_META_U(unit,
    685                              "Config property 'phy_port_primary_and_offset' "
    686                              "not set for unit %d, port %d.  "
    687                              "Default to slice=0x%x, base=0x%x\n"),
    688                              unit, port, index, primary_port));
    689     }
    690 
    691     /* keep the original MDIO address.  Set slice ID & base PHY address */
    692     /*   Do not change the order to the following four lines */
    693     index &= ~0x80;    /* clear reverse bit (PHYA_REV) */
    694     PHY54680_DEV_PHY_ID_ORIG(pc) = pc->phy_id;
    695     PHY54680_DEV_PHY_SLICE(pc)   = index;
    696     PHY54680_DEV_SET_BASE_ADDR(pc);   /* phy address of port 0 of this chip */
    697 
    698     SOC_IF_ERROR_RETURN
    699         (phy_54680_control_set( unit, port, SOC_PHY_CONTROL_PORT_PRIMARY,
    700                                             primary_port));
    701     SOC_IF_ERROR_RETURN
    702         (phy_54680_control_set( unit, port, SOC_PHY_CONTROL_PORT_OFFSET,
    703                                             index ));
    704  
    705 #ifdef DISABLE_TEST_PORT
    706     if (PHY_IS_BCM54680_A0(pc))  {
    707         /* Disable test port */
    708 
    709         phy_addr = pc->phy_id + 1;
    710 
    711         SOC_IF_ERROR_RETURN
    712             (pc->read(unit, phy_addr, MII_PHY_ID0_REG, &id0));
    713 
    714         SOC_IF_ERROR_RETURN
    715             (pc->read(unit, phy_addr, MII_PHY_ID1_REG, &id1));
    716 
    717         if ( ( id0 != PHY_BCM54680_A0_ID0 ) || ( id1 != PHY_BCM54680_A0_ID1 ) ) {
    718 
    719 
    720             SOC_IF_ERROR_RETURN
    721                 (pc->write(unit, phy_addr, 0x1f, 0xffd0));
    722 
    723             SOC_IF_ERROR_RETURN
    724                 (pc->write(unit, phy_addr, 0x1e, 0x001f));
    725 
    726             SOC_IF_ERROR_RETURN
    727                 (pc->write(unit, phy_addr, 0x1f, 0x8000));
    728 
    729             SOC_IF_ERROR_RETURN
    730                 (pc->write(unit, phy_addr, 0x1d, 0x4002));
    731 
    732             SOC_IF_ERROR_RETURN
    733                 (pc->write(unit, phy_addr, 0x00, MII_CTRL_RESET));
    734 
    735 #ifdef A0_AUTO_FILL_PORT_INDEX
    736             {
    737                 int i;
    738 
    739                 for (i = 0; i < 8; i++) {
    740                     SOC_IF_ERROR_RETURN
    741                         (phy_54680_control_set( unit, port - i, SOC_PHY_CONTROL_PORT_PRIMARY, port - 7 ));
    742                     SOC_IF_ERROR_RETURN
    743                         (phy_54680_control_set( unit, port - i, SOC_PHY_CONTROL_PORT_OFFSET, 7 - i ));
    744                 }
    745             }
    746 #endif
    747         }
    748     }
    749 #endif
    750     /* Disable super-isolate */
    751     SOC_IF_ERROR_RETURN
    752         (MODIFY_PHY54680_MII_POWER_CTRLr(unit, pc, 0x0, 1U<<5));
    753 
    754     /* remove power down */
    755     if (pc->copper.enable) {
    756         tmp = PHY_DISABLED_MODE(unit, port) ? MII_CTRL_PD : 0;
    757     } else {
    758         tmp = MII_CTRL_PD;
    759     }
    760     SOC_IF_ERROR_RETURN
    761         (MODIFY_PHY54680_MII_CTRLr(unit, pc, tmp, MII_CTRL_PD));
    762 
    763     if (PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc)) {
    764         SOC_IF_ERROR_RETURN
    765             (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x4f, (1U << 12), (1U << 12)));
    766 
    767         SOC_IF_ERROR_RETURN
    768             (MODIFY_PHY54680_MODE_CTRLr(unit, pc, 0x00, 0x06));
    769 
    770         SOC_IF_ERROR_RETURN
    771             (MODIFY_PHY54680_SGMII_SLAVEr(unit, pc, 0x02, 0x02));
    772 
    773         SOC_IF_ERROR_RETURN
    774             (MODIFY_PHY54680_EXT_SERDES_CTRLr(unit, pc, 0x00, 0x01));
    775 
    776         if (!PHY_IS_BCM52681E(pc)) {
    777             SOC_IF_ERROR_RETURN
    778                 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0F7F,0x15, 0x7, 0x7)); /* exp 7f */
    779         }
    780 
    781     }
    782 
    783 #if DISABLE_CLK125
    784     /* Reduce EMI emissions by disabling the CLK125 pin if not used */
    785     SOC_IF_ERROR_RETURN
    786         (MODIFY_PHY54680_SPARE_CTRL_3r(unit, pc, 0, 1));
    787 #endif
    788 
    789     /* Get Requested LED selectors (defaults are hardware defaults) */
    790     pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0);
    791     pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1);
    792     pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3);
    793     pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6);
    794     pc->ledctrl    = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8);
    795     pc->ledselect  = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0);
    796 
    797     /* Configure Extended Control Register */
    798     /* Enable LEDs to indicate traffic status */
    799     SOC_IF_ERROR_RETURN
    800         (MODIFY_PHY54680_MII_ECRr(unit, pc, 0x0020, 0x0020));
    801 
    802 #if AUTO_MDIX_WHEN_AN_DIS
    803     /* Enable Auto-MDIX When autoneg disabled */
    804     SOC_IF_ERROR_RETURN
    805         (MODIFY_PHY54680_MII_MISC_CTRLr(unit, pc, 0x0200, 0x0200));
    806 #endif
    807 
    808     /* Enable extended packet length (4.5k through 25k) */
    809     SOC_IF_ERROR_RETURN
    810         (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x4000, 0x4000));
    811 
    812     SOC_IF_ERROR_RETURN
    813         (MODIFY_PHY54680_MISC_1000X_CTRL2r(unit, pc, 0x0001, 0x0001));
    814 
    815     SOC_IF_ERROR_RETURN
    816         (MODIFY_PHY54680_AUX_CTRLr(unit, pc, 0x0002, 0x0002));
    817 
    818     /* Configure LED selectors */
    819     tmp = ((pc->ledmode[1] & 0xf) << 4) | (pc->ledmode[0] & 0xf);
    820     SOC_IF_ERROR_RETURN
    821         (WRITE_PHY54680_LED_SELECTOR_1r(unit, pc, tmp));
    822 
    823     tmp = ((pc->ledmode[3] & 0xf) << 4) | (pc->ledmode[2] & 0xf);
    824     SOC_IF_ERROR_RETURN
    825         (WRITE_PHY54680_LED_SELECTOR_2r(unit, pc, tmp));
    826 
    827     tmp = (pc->ledctrl & 0x3ff);
    828     SOC_IF_ERROR_RETURN
    829         (WRITE_PHY54680_LED_CTRLr(unit, pc, tmp));
    830 
    831     SOC_IF_ERROR_RETURN
    832         (WRITE_PHY54680_EXP_LED_SELECTORr(unit, pc, pc->ledselect));
    833 
    834     /*
    835      * Configure Auxiliary control register to turn off
    836      * carrier extension.  The Intel 7131 NIC does not accept carrier
    837      * extension and gets CRC errors.
    838      */
    839     /* Disable carrier extension */
    840     SOC_IF_ERROR_RETURN
    841         (MODIFY_PHY54680_AUX_CTRLr(unit, pc, 0x0040, 0x0040));
    842 
    843     /* BCM54880E is EEE capable */
    844     if (PHY_IS_BCM54680E(pc) || PHY_IS_BCM54880E(pc)) {
    845         if (pc->phy_rev == 0x1) { /* rev A1 */
    846             SOC_IF_ERROR_RETURN
    847                 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00));
    848             SOC_IF_ERROR_RETURN(
    849                 WRITE_PHY_REG(unit, pc, 0x17, 0x0ffe));
    850             SOC_IF_ERROR_RETURN(
    851                 WRITE_PHY_REG(unit, pc, 0x15, 0x0100));
    852             SOC_IF_ERROR_RETURN(
    853                 WRITE_PHY_REG(unit, pc, 0x17, 0x2022));
    854             SOC_IF_ERROR_RETURN(
    855                 WRITE_PHY_REG(unit, pc, 0x15, 0x01f0));
    856             SOC_IF_ERROR_RETURN(
    857                 WRITE_PHY_REG(unit, pc, 0x17, 0x4021));
    858             SOC_IF_ERROR_RETURN(
    859                 WRITE_PHY_REG(unit, pc, 0x15, 0x0887));
    860             SOC_IF_ERROR_RETURN(
    861                 WRITE_PHY_REG(unit, pc, 0x17, 0x2021));
    862             SOC_IF_ERROR_RETURN(
    863                 WRITE_PHY_REG(unit, pc, 0x15, 0x8983));
    864             SOC_IF_ERROR_RETURN
    865                 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00));
    866         }
    867         SOC_IF_ERROR_RETURN
    868            (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7,
    869                                                    0x0000, 0x0003));
    870         PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE);
    871     }
    872 
    873     /* BCM52681E is EEE capable */
    874     if (PHY_IS_BCM52681E(pc)) {
    875         SOC_IF_ERROR_RETURN
    876             (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7,
    877                                                    0x0000, 0x0003));
    878         SOC_IF_ERROR_RETURN
    879             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0F7F,0x15, 0x0, 0x7)); /* exp 7f */
    880         PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE);
    881     }
    882 
    883     if (PHY_IS_BCM54680(pc)) {
    884         SOC_IF_ERROR_RETURN
    885             (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00));
    886         SOC_IF_ERROR_RETURN(
    887             WRITE_PHY_REG(unit, pc, 0x17, 0x000e));
    888         SOC_IF_ERROR_RETURN(
    889             WRITE_PHY_REG(unit, pc, 0x15, 0x0752));
    890         SOC_IF_ERROR_RETURN(
    891             WRITE_PHY_REG(unit, pc, 0x17, 0x000f));
    892         SOC_IF_ERROR_RETURN(
    893             WRITE_PHY_REG(unit, pc, 0x15, 0xe04e));
    894         SOC_IF_ERROR_RETURN
    895             (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00));
    896     }
    897 
    898 #if defined(BCM_53314)
    899     if (PHY_IS_BCM53324(pc)) {
    900         /* BCM53324 internal GPHY is EEE capable */
    901         PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE);
    902     }
    903 #endif /* BCM_53314 */    
    904 
    905 
    906 
    907 
    908     /* Check config for MDI PAIR */
    909     phy_mdi_pair_map = soc_property_port_get(unit, port,
    910                                             spn_PHY_MDI_PAIR_MAP, 0);
    911     if (phy_mdi_pair_map) {
    912         SOC_IF_ERROR_RETURN(
    913             _phy_54680_mdi_pair_set(unit, port, phy_mdi_pair_map));
    914     }
    915 
    916     if (ECD_ENABLE && ((((PHY_IS_BCM54880E(pc)) || (PHY_IS_BCM54680E(pc))) && ((pc->phy_rev & 0x7) > 0x2)) ||
    917         ((PHY_IS_BCM54680(pc)) && ((pc->phy_rev & 0xf) > 0x1))))  {
    918         SOC_IF_ERROR_RETURN(
    919             phy_ecd_cable_diag_init(unit, port));
    920     }
    921 
    922     if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
    923         return SOC_E_NONE;
    924     }
    925 
    926     /* 100BASE-TX initialization change for EEE and autogreen mode */
    927     SOC_IF_ERROR_RETURN
    928         (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00));
    929     SOC_IF_ERROR_RETURN(
    930         WRITE_PHY_REG(unit, pc, 0x17, 0x4022));
    931     SOC_IF_ERROR_RETURN(
    932         WRITE_PHY_REG(unit, pc, 0x15, 0x017b));
    933     SOC_IF_ERROR_RETURN
    934         (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00));
    935 
    936     return SOC_E_NONE;
    937 }
    938 
    939 
    940 /*
    941  * Function:
    942  *      phy_54680_init
    943  * Purpose:
    944  *      Init function for 54680 PHY.
    945  * Parameters:
    946  *      unit - StrataSwitch unit #.
    947  *      port - StrataSwitch port #.
    948  * Returns:
    949  *      SOC_E_XXX
    950  */
    951 STATIC int
    952 phy_54680_init(int unit, soc_port_t port)
    953 {
    954     phy_ctrl_t         *pc;
    955 
    956     pc     = EXT_PHY_SW_STATE(unit, port);
    957 
    958     pc->automedium = FALSE;
    959     pc->fiber_detect = FALSE;
    960     pc->fiber.enable = FALSE;
    961 
    962     pc->copper.enable = TRUE;
    963     pc->copper.preferred = TRUE;
    964     pc->copper.autoneg_enable = TRUE;
    965     if (PHY_IS_BCM52681E(pc)) {
    966         pc->copper.force_speed = 100;
    967     } else {
    968         pc->copper.force_speed = 1000;
    969     }
    970     pc->copper.force_duplex = TRUE;
    971     pc->copper.master = SOC_PORT_MS_AUTO;
    972     pc->copper.mdix = SOC_PORT_MDIX_AUTO;
    973 
    974 
    975     /* Initially configure for the preferred medium. */
    976 
    977     PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
    978     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
    979     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU);
    980     PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
    981     PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE);
    982 
    983     SOC_IF_ERROR_RETURN
    984         (_phy_54680_reset_setup(unit, port));
    985 
    986     /* Advertise all possible by default */
    987     SOC_IF_ERROR_RETURN
    988         (phy_54680_ability_local_get(unit, port, &pc->copper.advert_ability));
    989 
    990     SOC_IF_ERROR_RETURN
    991         (phy_54680_medium_config_set(unit, port, 0, &pc->copper)); 
    992 
    993     return SOC_E_NONE;
    994 
    995 }
    996 
    997 /*
    998  * Function:
    999  *      phy_54680_enable_set
   1000  * Purpose:
   1001  *      Enable or disable the physical interface.
   1002  * Parameters:
   1003  *      unit - StrataSwitch unit #.
   1004  *      port - StrataSwitch port #.
   1005  *      enable - Boolean, true = enable PHY, false = disable.
   1006  * Returns:
   1007  *      SOC_E_XXX
   1008  */
   1009 
   1010 STATIC int
   1011 phy_54680_enable_set(int unit, soc_port_t port, int enable)
   1012 {
   1013     phy_ctrl_t    *pc;
   1014     soc_timeout_t  to;
   1015     uint16 power_down, mii_stat;
   1016 
   1017     pc = EXT_PHY_SW_STATE(unit, port);
   1018 
   1019     power_down = (enable) ? 0 : MII_CTRL_PD;
   1020 
   1021     SOC_IF_ERROR_RETURN
   1022         (MODIFY_PHY54680_MII_CTRLr(unit, pc, power_down, MII_CTRL_PD));
   1023 
   1024     if (!enable) {
   1025         if ((PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED)) &&
   1026            (((pc->phy_rev & 0x4) == 0x0) || /* A0,A1,B0,B1 */
   1027             (PHY_IS_BCM53324(pc) && pc->phy_rev == 0x0))) {
   1028             soc_timeout_init(&to, 2000000, 0);
   1029             do {
   1030                 SOC_IF_ERROR_RETURN
   1031                     (READ_PHY54680_MII_STATr(unit, pc, &mii_stat));
   1032 
   1033                 if (soc_timeout_check(&to)) {
   1034                     LOG_WARN(BSL_LS_SOC_PHY,
   1035                              (BSL_META_U(unit,
   1036                                          "phy54680.c: link didn't go down after power down: u=%d p=%d\n"),
   1037                               unit, port));
   1038                     break;
   1039                 }
   1040             } while(mii_stat & MII_STAT_LA);
   1041         }
   1042     }
   1043 
   1044     SOC_IF_ERROR_RETURN
   1045         (phy_fe_ge_enable_set(unit, port, enable));
   1046 
   1047     return SOC_E_NONE;
   1048 
   1049 }
   1050 
   1051 /*
   1052  * Function:
   1053  *      phy_54680_enable_get
   1054  * Purpose:
   1055  *      Enable or disable the physical interface for a 54680 device.
   1056  * Parameters:
   1057  *      unit - StrataSwitch unit #.
   1058  *      port - StrataSwitch port #.
   1059  *      enable - (OUT) Boolean, true = enable PHY, false = disable.
   1060  * Returns:
   1061  *      SOC_E_XXX
   1062  */
   1063 
   1064 STATIC int
   1065 phy_54680_enable_get(int unit, soc_port_t port, int *enable)
   1066 {
   1067     SOC_IF_ERROR_RETURN
   1068         (phy_fe_ge_enable_get(unit, port, enable));
   1069 
   1070     return SOC_E_NONE;
   1071 }
   1072 
   1073 
   1074 /*
   1075  * Function:
   1076  *      phy_54680_link_get
   1077  * Purpose:
   1078  *      Determine the current link up/down status for a 54680 device.
   1079  * Parameters:
   1080  *      unit - StrataSwitch unit #.
   1081  *      port - StrataSwitch port #.
   1082  *      link - (OUT) Boolean, true indicates link established.
   1083  * Returns:
   1084  *      SOC_E_XXX
   1085  * Notes:
   1086  *      If using automedium, also switches the mode.
   1087  */
   1088 
   1089 STATIC int
   1090 phy_54680_link_get(int unit, soc_port_t port, int *link)
   1091 {
   1092 
   1093     SOC_IF_ERROR_RETURN
   1094         (phy_fe_ge_link_get(unit, port, link));
   1095 
   1096     return SOC_E_NONE;
   1097 }
   1098 
   1099 /*
   1100  * Function:
   1101  *      phy_54680_duplex_set
   1102  * Purpose:
   1103  *      Set the current duplex mode (forced).
   1104  * Parameters:
   1105  *      unit - StrataSwitch unit #.
   1106  *      port - StrataSwitch port #.
   1107  *      duplex - Boolean, true indicates full duplex, false indicates half.
   1108  * Returns:
   1109  *      SOC_E_XXX
   1110  *      SOC_E_UNAVAIL - Half duplex requested, and not supported.
   1111  * Notes:
   1112  *      The duplex is set only for the ACTIVE medium.
   1113  *      No synchronization performed at this level.
   1114  *      Autonegotiation is not manipulated.
   1115  */
   1116 
   1117 STATIC int
   1118 phy_54680_duplex_set(int unit, soc_port_t port, int duplex)
   1119 {
   1120     phy_ctrl_t    *pc;
   1121 
   1122     pc = EXT_PHY_SW_STATE(unit, port);
   1123 
   1124     SOC_IF_ERROR_RETURN
   1125         (phy_fe_ge_duplex_set(unit, port, duplex));
   1126 
   1127     pc->copper.force_duplex = duplex;
   1128 
   1129     return SOC_E_NONE;
   1130 }
   1131 
   1132 /*
   1133  * Function:
   1134  *      phy_54680_duplex_get
   1135  * Purpose:
   1136  *      Get the current operating duplex mode. If autoneg is enabled,
   1137  *      then operating mode is returned, otherwise forced mode is returned.
   1138  * Parameters:
   1139  *      unit - StrataSwitch unit #.
   1140  *      port - StrataSwitch port #.
   1141  *      duplex - (OUT) Boolean, true indicates full duplex, false
   1142  *              indicates half.
   1143  * Returns:
   1144  *      SOC_E_XXX
   1145  * Notes:
   1146  *      The duplex is retrieved for the ACTIVE medium.
   1147  *      No synchronization performed at this level. Autonegotiation is
   1148  *      not manipulated.
   1149  */
   1150 
   1151 STATIC int
   1152 phy_54680_duplex_get(int unit, soc_port_t port, int *duplex)
   1153 {
   1154     SOC_IF_ERROR_RETURN
   1155         (phy_fe_ge_duplex_get(unit, port, duplex));
   1156 
   1157     return SOC_E_NONE;
   1158 }
   1159 
   1160 /*
   1161  * Function:
   1162  *      phy_54680_speed_set
   1163  * Purpose:
   1164  *      Set the current operating speed (forced).
   1165  * Parameters:
   1166  *      unit - StrataSwitch unit #.
   1167  *      port - StrataSwitch port #.
   1168  *      speed - Requested speed.
   1169  * Returns:
   1170  *      SOC_E_XXX
   1171  * Notes:
   1172  *      The speed is set only for the ACTIVE medium.
   1173  */
   1174 
   1175 STATIC int
   1176 phy_54680_speed_set(int unit, soc_port_t port, int speed)
   1177 {
   1178     SOC_IF_ERROR_RETURN
   1179         (phy_fe_ge_speed_set(unit, port, speed));
   1180 
   1181     return SOC_E_NONE;
   1182 }
   1183 
   1184 /*
   1185  * Function:
   1186  *      phy_54680_speed_get
   1187  * Purpose:
   1188  *      Get the current operating speed for a 54680 device.
   1189  * Parameters:
   1190  *      unit - StrataSwitch unit #.
   1191  *      port - StrataSwitch port #.
   1192  *      duplex - (OUT) Boolean, true indicates full duplex, false
   1193  *              indicates half.
   1194  * Returns:
   1195  *      SOC_E_XXX
   1196  * Notes:
   1197  *      The speed is retrieved for the ACTIVE medium.
   1198  */
   1199 
   1200 STATIC int
   1201 phy_54680_speed_get(int unit, soc_port_t port, int *speed)
   1202 {
   1203     SOC_IF_ERROR_RETURN
   1204         (phy_fe_ge_speed_get(unit, port, speed));
   1205 
   1206     return SOC_E_NONE;
   1207 }
   1208 
   1209 /*
   1210  * Function:
   1211  *      phy_54680_master_set
   1212  * Purpose:
   1213  *      Set the current master mode
   1214  * Parameters:
   1215  *      unit - StrataSwitch unit #.
   1216  *      port - StrataSwitch port #.
   1217  *      master - SOC_PORT_MS_*
   1218  * Returns:
   1219  *      SOC_E_XXX
   1220  * Notes:
   1221  *      The master mode is set only for the ACTIVE medium.
   1222  */
   1223 
   1224 STATIC int
   1225 phy_54680_master_set(int unit, soc_port_t port, int master)
   1226 {
   1227     phy_ctrl_t    *pc;
   1228 
   1229     pc = EXT_PHY_SW_STATE(unit, port);
   1230 
   1231     SOC_IF_ERROR_RETURN
   1232         (phy_fe_ge_master_set(unit, port, master));
   1233 
   1234     pc->copper.master = master;
   1235 
   1236     return SOC_E_NONE;
   1237 }
   1238 
   1239 /*
   1240  * Function:
   1241  *      phy_54680_master_get
   1242  * Purpose:
   1243  *      Get the current master mode for a 54680 device.
   1244  * Parameters:
   1245  *      unit - StrataSwitch unit #.
   1246  *      port - StrataSwitch port #.
   1247  *      master - (OUT) SOC_PORT_MS_*
   1248  * Returns:
   1249  *      SOC_E_XXX
   1250  * Notes:
   1251  *      The master mode is retrieved for the ACTIVE medium.
   1252  */
   1253 
   1254 STATIC int
   1255 phy_54680_master_get(int unit, soc_port_t port, int *master)
   1256 {
   1257     SOC_IF_ERROR_RETURN
   1258         (phy_fe_ge_master_get(unit, port, master));
   1259 
   1260     return SOC_E_NONE;
   1261 }
   1262 
   1263 /*
   1264  * Function:
   1265  *      phy_54680_autoneg_set
   1266  * Purpose:
   1267  *      Enable or disable auto-negotiation on the specified port.
   1268  * Parameters:
   1269  *      unit - StrataSwitch unit #.
   1270  *      port - StrataSwitch port #.
   1271  *      autoneg - Boolean, if true, auto-negotiation is enabled
   1272  *              (and/or restarted). If false, autonegotiation is disabled.
   1273  * Returns:
   1274  *      SOC_E_XXX
   1275  * Notes:
   1276  *      The autoneg mode is set only for the ACTIVE medium.
   1277  */
   1278 
   1279 STATIC int
   1280 phy_54680_autoneg_set(int unit, soc_port_t port, int autoneg)
   1281 {
   1282     int           rv;
   1283     phy_ctrl_t    *pc;
   1284 
   1285     pc             = EXT_PHY_SW_STATE(unit, port);
   1286     rv             = SOC_E_NONE;
   1287 
   1288     /* Set auto-neg on PHY */
   1289     rv = phy_fe_ge_an_set(unit, port, autoneg);
   1290     if (SOC_SUCCESS(rv)) {
   1291         pc->copper.autoneg_enable = autoneg ? 1 : 0;
   1292     }
   1293 
   1294     return SOC_E_NONE;
   1295 }
   1296 
   1297 /*
   1298  * Function:
   1299  *      phy_54680_autoneg_get
   1300  * Purpose:
   1301  *      Get the current auto-negotiation status (enabled/busy).
   1302  * Parameters:
   1303  *      unit - StrataSwitch unit #.
   1304  *      port - StrataSwitch port #.
   1305  *      autoneg - (OUT) if true, auto-negotiation is enabled.
   1306  *      autoneg_done - (OUT) if true, auto-negotiation is complete. This
   1307  *              value is undefined if autoneg == FALSE.
   1308  * Returns:
   1309  *      SOC_E_XXX
   1310  * Notes:
   1311  *      The autoneg mode is retrieved for the ACTIVE medium.
   1312  */
   1313 
   1314 STATIC int
   1315 phy_54680_autoneg_get(int unit, soc_port_t port,
   1316                      int *autoneg, int *autoneg_done)
   1317 {
   1318 
   1319     SOC_IF_ERROR_RETURN
   1320         (phy_fe_ge_an_get(unit, port, autoneg, autoneg_done));
   1321 
   1322     return SOC_E_NONE;
   1323 }
   1324 
   1325 /*
   1326  * Function:
   1327  *      phy_54680_ability_advert_set
   1328  * Purpose:
   1329  *      Set the current advertisement for auto-negotiation.
   1330  * Parameters:
   1331  *      unit    - StrataSwitch unit #.
   1332  *      port    - StrataSwitch port #.
   1333  *      ability - Port ability indicating supported options/speeds.
   1334  * Returns:
   1335  *      SOC_E_XXX
   1336  */
   1337 
   1338 STATIC int
   1339 phy_54680_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability)
   1340 {
   1341     phy_ctrl_t *pc;
   1342     uint16     eee_ability = 0;
   1343 
   1344     if (NULL == ability) {
   1345         return (SOC_E_PARAM);
   1346     }
   1347 
   1348     pc = EXT_PHY_SW_STATE(unit, port);
   1349 
   1350     SOC_IF_ERROR_RETURN
   1351         (phy_fe_ge_ability_advert_set(unit, port, ability));
   1352 
   1353     /* EEE settings */
   1354     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   1355         eee_ability = 0;
   1356         if (ability->eee & SOC_PA_EEE_1GB_BASET) {
   1357             eee_ability |= 0x4;
   1358         }
   1359         if (ability->eee & SOC_PA_EEE_100MB_BASETX) {
   1360             eee_ability |= 0x2;
   1361         }
   1362         if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED)) {
   1363             SOC_IF_ERROR_RETURN
   1364                 (MODIFY_PHY54680_EEE_ADVr(unit, pc, eee_ability, 0x0006));
   1365         } else {
   1366             SOC_IF_ERROR_RETURN
   1367                 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0000, 0x0006));
   1368         }
   1369     }
   1370 
   1371     return SOC_E_NONE;
   1372 
   1373 }
   1374 
   1375 /*
   1376  * Function:
   1377  *      phy_54680_ability_advert_get
   1378  * Purpose:
   1379  *      Get the current advertisement for auto-negotiation.
   1380  * Parameters:
   1381  *      unit    - StrataSwitch unit #.
   1382  *      port    - StrataSwitch port #.
   1383  *      ability - Port ability indicating supported options/speeds.
   1384  * Returns:
   1385  *      SOC_E_XXX
   1386  * Notes:
   1387  *      The advertisement is retrieved for the ACTIVE medium.
   1388  *      No synchronization performed at this level.
   1389  */
   1390 
   1391 STATIC int
   1392 phy_54680_ability_advert_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1393 {
   1394     phy_ctrl_t *pc;
   1395     uint16      eee_ability = 0;
   1396 
   1397     if (NULL == ability) {
   1398         return (SOC_E_PARAM);
   1399     }
   1400 
   1401     pc = EXT_PHY_SW_STATE(unit, port);
   1402 
   1403     SOC_IF_ERROR_RETURN
   1404         (phy_fe_ge_ability_advert_get(unit, port, ability));
   1405 
   1406     /* EEE settings */
   1407     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   1408         SOC_IF_ERROR_RETURN
   1409             (READ_PHY54680_EEE_ADVr(unit, pc, &eee_ability));
   1410         if (eee_ability & 0x04) {
   1411             ability->eee |= SOC_PA_EEE_1GB_BASET;
   1412         }
   1413         if (eee_ability & 0x02) {
   1414             ability->eee |= SOC_PA_EEE_100MB_BASETX;
   1415         }
   1416     }
   1417 
   1418     return SOC_E_NONE;
   1419 }
   1420 
   1421 /*
   1422  * Function:
   1423  *      phy_54680_ability_remote_get
   1424  * Purpose:
   1425  *      Get partners current advertisement for auto-negotiation.
   1426  * Parameters:
   1427  *      unit    - StrataSwitch unit #.
   1428  *      port    - StrataSwitch port #.
   1429  *      ability - Port ability indicating supported options/speeds.
   1430  * Returns:
   1431  *      SOC_E_XXX
   1432  * Notes:
   1433  *      The remote advertisement is retrieved for the ACTIVE medium.
   1434  *      No synchronization performed at this level. If Autonegotiation is
   1435  *      disabled or in progress, this routine will return an error.
   1436  */
   1437 
   1438 STATIC int
   1439 phy_54680_ability_remote_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1440 {
   1441     phy_ctrl_t       *pc;
   1442     uint16            eee_resolution;
   1443 
   1444     if (NULL == ability) {
   1445         return (SOC_E_PARAM);
   1446     }
   1447 
   1448     pc = EXT_PHY_SW_STATE(unit, port);
   1449 
   1450     SOC_IF_ERROR_RETURN
   1451         (phy_fe_ge_ability_remote_get(unit, port, ability));
   1452 
   1453     /* EEE settings */
   1454     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   1455         SOC_IF_ERROR_RETURN
   1456             (READ_PHY54680_EEE_RESOLUTION_STATr(unit, pc, &eee_resolution));
   1457         if (eee_resolution & 0x04) {
   1458             ability->eee |= SOC_PA_EEE_1GB_BASET;
   1459         }
   1460         if (eee_resolution & 0x02) {
   1461             ability->eee |= SOC_PA_EEE_100MB_BASETX;
   1462         }
   1463     }
   1464 
   1465     return SOC_E_NONE;
   1466 }
   1467 
   1468 /*
   1469  * Function:
   1470  *      phy_54680_ability_local_get
   1471  * Purpose:
   1472  *      Get the device's complete abilities.
   1473  * Parameters:
   1474  *      unit - StrataSwitch unit #.
   1475  *      port - StrataSwitch port #.
   1476  *      ability - return device's abilities.
   1477  * Returns:
   1478  *      SOC_E_XXX
   1479  */
   1480 
   1481 STATIC int
   1482 phy_54680_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1483 {
   1484     phy_ctrl_t *pc;
   1485 
   1486     pc = EXT_PHY_SW_STATE(unit, port);
   1487 
   1488 
   1489     if (NULL == ability) {
   1490         return SOC_E_PARAM;
   1491     }
   1492 
   1493     ability->speed_half_duplex  = SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB;
   1494     ability->speed_full_duplex  = SOC_PA_SPEED_1000MB |SOC_PA_SPEED_100MB | 
   1495                                   SOC_PA_SPEED_10MB;
   1496 
   1497                                   
   1498     if (PHY_IS_BCM54880E_A0(pc)) { /* 880E A0 has a bug, 10Mbs doesn't work */
   1499         ability->speed_half_duplex  = SOC_PA_SPEED_100MB;
   1500         ability->speed_full_duplex  = SOC_PA_SPEED_1000MB |SOC_PA_SPEED_100MB;
   1501     }
   1502 
   1503     if (PHY_IS_BCM52681E(pc)) {
   1504         ability->speed_half_duplex  = SOC_PA_SPEED_100MB |SOC_PA_SPEED_10MB;
   1505         ability->speed_full_duplex  = SOC_PA_SPEED_100MB |SOC_PA_SPEED_10MB;
   1506     }
   1507 
   1508     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   1509     ability->interface = SOC_PA_INTF_SGMII;
   1510     if (PHY_IS_BCM53324(pc)) {
   1511         /* No SGMII interface */
   1512         ability->interface = SOC_PA_INTF_GMII;
   1513     }
   1514     ability->medium    = SOC_PA_MEDIUM_COPPER; 
   1515     ability->loopback  = SOC_PA_LB_PHY;
   1516     ability->flags     = SOC_PA_AUTONEG;
   1517     
   1518     /* EEE settings */
   1519     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   1520         if (PHY_IS_BCM52681E(pc)) {
   1521             ability->eee = SOC_PA_EEE_100MB_BASETX;
   1522         } else {
   1523             ability->eee = SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX;
   1524         }
   1525     }
   1526 
   1527     return SOC_E_NONE;
   1528 }
   1529 
   1530 
   1531 /*
   1532  * Function:
   1533  *      phy_54680_lb_set
   1534  * Purpose:
   1535  *      Set the local PHY loopback mode.
   1536  * Parameters:
   1537  *      unit - StrataSwitch unit #.
   1538  *      port - StrataSwitch port #.
   1539  *      loopback - Boolean: true = enable loopback, false = disable.
   1540  * Returns:
   1541  *      SOC_E_XXX
   1542  * Notes:
   1543  *      The loopback mode is set only for the ACTIVE medium.
   1544  *      No synchronization performed at this level.
   1545  */
   1546 
   1547 STATIC int
   1548 phy_54680_lb_set(int unit, soc_port_t port, int enable)
   1549 {
   1550     phy_ctrl_t *pc;
   1551     int         link = FALSE;
   1552 
   1553     pc = EXT_PHY_SW_STATE(unit, port);
   1554 
   1555     if ( PHY_IS_BCM53324(pc) || PHY_IS_BCM52681E(pc) ) {
   1556         /* No SGMII interface */
   1557 
   1558         /* 
   1559          * Force link state machine into pass state.
   1560          * Thus the PHY is forced to show link up without the link partner.
   1561          * This is WA for no link-up issue about forcing 10/100 Mbps 
   1562          * in PHY loopback. 
   1563          */
   1564         if( PHY_IS_BCM53324(pc) ) {
   1565             if( enable ) {
   1566                 /* Force LSM to pass state */
   1567                 SOC_IF_ERROR_RETURN
   1568                     (MODIFY_PHY54680_TEST1r(unit, pc, (1U << 12), (1U << 12)));
   1569             } else {
   1570                 /* Normal LSM operation */
   1571                 SOC_IF_ERROR_RETURN
   1572                     (MODIFY_PHY54680_TEST1r(unit, pc, 0, (1U << 12)));
   1573             }
   1574         }
   1575         if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   1576             if ( enable ) {
   1577                 SOC_IF_ERROR_RETURN(
   1578                     PHY_LINKUP_EVT(pc->pd, unit, port));
   1579             } else {
   1580                 SOC_IF_ERROR_RETURN(
   1581                     phy_54680_link_get(unit, port, &link));
   1582                 if ( link == TRUE ) {
   1583                     SOC_IF_ERROR_RETURN(
   1584                         PHY_LINKUP_EVT(pc->pd, unit, port));
   1585                 } else {
   1586                     SOC_IF_ERROR_RETURN(
   1587                         PHY_LINKDN_EVT(pc->pd, unit, port));
   1588                 }
   1589             }
   1590         }
   1591     } else {
   1592 
   1593         /* devices with SGMII interface */
   1594         if ( enable ) {
   1595             /* SGMII loopback with RX/TX on MDI suppressed */
   1596             SOC_IF_ERROR_RETURN
   1597                 (WRITE_PHY54680_EXP_SGMII_LINESIDE_LOOPBACK_CTRLr(unit, pc,
   1598                                             (1U << 2) | (1U << 1) | (1U << 0)));
   1599             /* Force LSM to pass state */
   1600             SOC_IF_ERROR_RETURN
   1601                 (MODIFY_PHY54680_TEST1r(unit, pc, (1U << 12), (1U << 12)));
   1602             /* Disable TX */
   1603             SOC_IF_ERROR_RETURN
   1604                 (MODIFY_PHY54680_MII_ECRr(unit, pc, (1U << 13), (1U << 13)));
   1605 
   1606         } else {
   1607             /* no SGMII loopback */
   1608             SOC_IF_ERROR_RETURN
   1609                 (WRITE_PHY54680_EXP_SGMII_LINESIDE_LOOPBACK_CTRLr(unit, pc,
   1610                                                                   0x0));
   1611             /* Normal LSM operation */
   1612             SOC_IF_ERROR_RETURN
   1613                 (MODIFY_PHY54680_TEST1r(unit, pc, 0, (1U << 12)));
   1614             /* Enable TX */
   1615             SOC_IF_ERROR_RETURN
   1616                 (MODIFY_PHY54680_MII_ECRr(unit, pc, 0, (1U << 13)));
   1617         }
   1618     }
   1619 
   1620     /* MII Control Register,  Reg.0x0 bit[14] internal loopback */
   1621     SOC_IF_ERROR_RETURN
   1622             (phy_fe_ge_lb_set(unit, port, enable));
   1623 
   1624     return SOC_E_NONE;
   1625 }
   1626 
   1627 /*
   1628  * Function:
   1629  *      phy_54680_lb_get
   1630  * Purpose:
   1631  *      Get the local PHY loopback mode.
   1632  * Parameters:
   1633  *      unit - StrataSwitch unit #.
   1634  *      port - StrataSwitch port #.
   1635  *      loopback - (OUT) Boolean: true = enable loopback, false = disable.
   1636  * Returns:
   1637  *      SOC_E_XXX
   1638  * Notes:
   1639  *      The loopback mode is retrieved for the ACTIVE medium.
   1640  */
   1641 
   1642 STATIC int
   1643 phy_54680_lb_get(int unit, soc_port_t port, int *enable)
   1644 {
   1645     phy_ctrl_t *pc;
   1646     uint16 temp;
   1647 
   1648     pc = EXT_PHY_SW_STATE(unit, port);
   1649 
   1650     if ( PHY_IS_BCM53324(pc) || PHY_IS_BCM52681E(pc) ) {
   1651         /* No SGMII interface */
   1652         SOC_IF_ERROR_RETURN(phy_fe_ge_lb_get(unit, port, enable));
   1653         return SOC_E_NONE;
   1654     }
   1655 
   1656     SOC_IF_ERROR_RETURN
   1657         (READ_PHY54680_EXP_SGMII_LINESIDE_LOOPBACK_CTRLr(unit, pc, &temp));
   1658     *enable = (temp & (1U << 2)) ? TRUE : FALSE;
   1659 
   1660     return SOC_E_NONE;
   1661 }
   1662 
   1663 /*
   1664  * Function:
   1665  *      phy_54680_interface_set
   1666  * Purpose:
   1667  *      Set the current operating mode of the internal PHY.
   1668  *      (Pertaining to the MAC/PHY interface, not the line interface).
   1669  * Parameters:
   1670  *      unit - StrataSwitch unit #.
   1671  *      port - StrataSwitch port #.
   1672  *      pif - one of SOC_PORT_IF_*
   1673  * Returns:
   1674  *      SOC_E_XXX
   1675  */
   1676 
   1677 STATIC int
   1678 phy_54680_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   1679 {
   1680     COMPILER_REFERENCE(unit);
   1681     COMPILER_REFERENCE(port);
   1682     COMPILER_REFERENCE(pif);
   1683 
   1684     return SOC_E_NONE;
   1685 
   1686 }
   1687 
   1688 /*
   1689  * Function:
   1690  *      phy_54680_interface_get
   1691  * Purpose:
   1692  *      Get the current operating mode of the internal PHY.
   1693  *      (Pertaining to the MAC/PHY interface, not the line interface).
   1694  * Parameters:
   1695  *      unit - StrataSwitch unit #.
   1696  *      port - StrataSwitch port #.
   1697  *      pif - (OUT) one of SOC_PORT_IF_*
   1698  * Returns:
   1699  *      SOC_E_XXX
   1700  */
   1701 
   1702 STATIC int
   1703 phy_54680_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   1704 {
   1705 #if defined(BCM_53314)
   1706     phy_ctrl_t *pc;
   1707 
   1708     pc = EXT_PHY_SW_STATE(unit, port);
   1709 
   1710     if(PHY_IS_BCM53324(pc)) {
   1711         *pif = SOC_PORT_IF_GMII;
   1712     } else
   1713 #endif /* BCM_53314 */
   1714     {
   1715         *pif = SOC_PORT_IF_SGMII;
   1716     }
   1717 
   1718     return(SOC_E_NONE);
   1719 }
   1720 
   1721 /*
   1722  * Function:
   1723  *      phy_54680_mdix_set
   1724  * Description:
   1725  *      Set the Auto-MDIX mode of a port/PHY
   1726  * Parameters:
   1727  *      unit - Device number
   1728  *      port - Port number
   1729  *      mode - One of:
   1730  *              SOC_PORT_MDIX_AUTO
   1731  *                      Enable auto-MDIX when autonegotiation is enabled
   1732  *              SOC_PORT_MDIX_FORCE_AUTO
   1733  *                      Enable auto-MDIX always
   1734  *              SOC_PORT_MDIX_NORMAL
   1735  *                      Disable auto-MDIX
   1736  *              SOC_PORT_MDIX_XOVER
   1737  *                      Disable auto-MDIX, and swap cable pairs
   1738  * Return Value:
   1739  *      SOC_E_XXX
   1740  */
   1741 STATIC int
   1742 phy_54680_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode)
   1743 {
   1744     phy_ctrl_t    *pc;
   1745     int            speed;
   1746 
   1747     pc = EXT_PHY_SW_STATE(unit, port);
   1748 
   1749     switch (mode) {
   1750     case SOC_PORT_MDIX_AUTO:
   1751         /* Clear bit 14 for automatic MDI crossover */
   1752         SOC_IF_ERROR_RETURN
   1753             (MODIFY_PHY54680_MII_ECRr(unit, pc, 0, 0x4000));
   1754 
   1755         /*
   1756          * Write the result in the register 0x18, shadow copy 7
   1757          */
   1758         /* Clear bit 9 to disable forced auto MDI xover */
   1759         SOC_IF_ERROR_RETURN
   1760             (MODIFY_PHY54680_MII_MISC_CTRLr(unit, pc, 0, 0x0200));
   1761         break;
   1762 
   1763     case SOC_PORT_MDIX_FORCE_AUTO:
   1764         /* Clear bit 14 for automatic MDI crossover */
   1765         SOC_IF_ERROR_RETURN
   1766             (MODIFY_PHY54680_MII_ECRr(unit, pc, 0, 0x4000));
   1767 
   1768         /*
   1769          * Write the result in the register 0x18, shadow copy 7
   1770          */
   1771         /* Set bit 9 to force automatic MDI crossover */
   1772         SOC_IF_ERROR_RETURN
   1773             (MODIFY_PHY54680_MII_MISC_CTRLr(unit, pc, 0x0200, 0x0200));
   1774         break;
   1775 
   1776     case SOC_PORT_MDIX_NORMAL:
   1777         SOC_IF_ERROR_RETURN(phy_54680_speed_get(unit, port, &speed));
   1778         if (speed == 0 || speed == 10 || speed == 100) {
   1779             /* Set bit 14 for manual MDI crossover */
   1780             SOC_IF_ERROR_RETURN
   1781                 (MODIFY_PHY54680_MII_ECRr(unit, pc, 0x4000, 0x4000));
   1782 
   1783             SOC_IF_ERROR_RETURN
   1784                 (WRITE_PHY54680_TEST1r(unit, pc, 0));
   1785         } else {
   1786             return SOC_E_UNAVAIL;
   1787         }
   1788         break;
   1789 
   1790     case SOC_PORT_MDIX_XOVER:
   1791         SOC_IF_ERROR_RETURN(phy_54680_speed_get(unit, port, &speed));
   1792         if (speed == 0 || speed == 10 || speed == 100) {
   1793              /* Set bit 14 for manual MDI crossover */
   1794             SOC_IF_ERROR_RETURN
   1795                 (MODIFY_PHY54680_MII_ECRr(unit, pc, 0x4000, 0x4000));
   1796 
   1797             SOC_IF_ERROR_RETURN
   1798                 (WRITE_PHY54680_TEST1r(unit, pc, 0x0080));
   1799         } else {
   1800             return SOC_E_UNAVAIL;
   1801         }
   1802         break;
   1803 
   1804     default:
   1805         return SOC_E_PARAM;
   1806     }
   1807 
   1808     pc->copper.mdix = mode;
   1809     return SOC_E_NONE;
   1810 
   1811 }        
   1812 
   1813 #if defined(BCM_WARM_BOOT_SUPPORT)
   1814 /*
   1815  * Function:
   1816  *      phy_54680_mdix_wb_update
   1817  * Description:
   1818  *      Read the hw, derive the mode and update the mdix mode in sw structure
   1819  *      during wb.
   1820  * Parameters:
   1821  *      unit - (IN) Device number
   1822  *      port - (IN) Port number
   1823  *      mode - (OUT) :One of:
   1824  *              SOC_PORT_MDIX_AUTO
   1825  *                      Enable auto-MDIX when autonegotiation is enabled
   1826  *              SOC_PORT_MDIX_FORCE_AUTO
   1827  *                      Enable auto-MDIX always
   1828  *              SOC_PORT_MDIX_NORMAL
   1829  *                      Disable auto-MDIX
   1830  *              SOC_PORT_MDIX_XOVER
   1831  *                      Disable auto-MDIX, and swap cable pairs
   1832  * Return Value:
   1833  *      SOC_E_XXX
   1834  */
   1835 STATIC int
   1836 phy_54680_mdix_wb_update(int unit, soc_port_t port)
   1837 {
   1838     phy_ctrl_t    *pc;
   1839     int            speed;
   1840     int            mode = 0;
   1841     uint16         val = 0;
   1842 
   1843     pc = EXT_PHY_SW_STATE(unit, port);
   1844 
   1845     /* Check bit 14 for automatic MDI crossover */
   1846     SOC_IF_ERROR_RETURN (READ_PHY54680_MII_ECRr(unit, pc, &val));
   1847     if(val & 0x4000) {
   1848         SOC_IF_ERROR_RETURN(phy_54680_speed_get(unit, port, &speed));
   1849         if (speed == 0 || speed == 10 || speed == 100) {
   1850             SOC_IF_ERROR_RETURN (READ_PHY54680_TEST1r(unit, pc, &val));
   1851             if (0 == val) {
   1852                 mode = SOC_PORT_MDIX_NORMAL;
   1853             } else if (0x80 == val) {
   1854                 mode = SOC_PORT_MDIX_XOVER;
   1855             } else {
   1856                 return SOC_E_UNAVAIL;
   1857             }
   1858         } else {
   1859             return SOC_E_UNAVAIL;
   1860         }
   1861     } else {
   1862         /* Check bit 9 forced auto MDI xover */
   1863         SOC_IF_ERROR_RETURN (READ_PHY54680_MII_MISC_CTRLr(unit, pc,&val));
   1864         if (val & 0x200) {
   1865             /* bit 9 Set, forced auto MDI xover */
   1866             mode = SOC_PORT_MDIX_FORCE_AUTO;
   1867         } else {
   1868             /* bit 9 Clear, forced auto MDI xover */
   1869             mode = SOC_PORT_MDIX_AUTO;
   1870         }
   1871     }
   1872     pc->copper.mdix = mode;
   1873 
   1874     return SOC_E_NONE;
   1875 }
   1876 #endif /* defined(BCM_WARM_BOOT_SUPPORT) */
   1877 
   1878 
   1879 /*
   1880  * Function:
   1881  *      phy_54680_mdix_get
   1882  * Description:
   1883  *      Get the Auto-MDIX mode of a port/PHY
   1884  * Parameters:
   1885  *      unit - Device number
   1886  *      port - Port number
   1887  *      mode - (Out) One of:
   1888  *              SOC_PORT_MDIX_AUTO
   1889  *                      Enable auto-MDIX when autonegotiation is enabled
   1890  *              SOC_PORT_MDIX_FORCE_AUTO
   1891  *                      Enable auto-MDIX always
   1892  *              SOC_PORT_MDIX_NORMAL
   1893  *                      Disable auto-MDIX
   1894  *              SOC_PORT_MDIX_XOVER
   1895  *                      Disable auto-MDIX, and swap cable pairs
   1896  * Return Value:
   1897  *      SOC_E_XXX
   1898  */
   1899 STATIC int
   1900 phy_54680_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode)
   1901 {
   1902     phy_ctrl_t    *pc;
   1903     int            speed;
   1904 
   1905     pc = EXT_PHY_SW_STATE(unit, port);
   1906 
   1907 #if defined(BCM_WARM_BOOT_SUPPORT)
   1908     if (SOC_WARM_BOOT(unit)) {
   1909         return phy_54680_mdix_wb_update(unit, port);
   1910     }
   1911 #endif /* defined(BCM_WARM_BOOT_SUPPORT) */
   1912 
   1913     SOC_IF_ERROR_RETURN(phy_54680_speed_get(unit, port, &speed));
   1914     if (speed == 1000) {
   1915        *mode = SOC_PORT_MDIX_AUTO;
   1916     } else {
   1917         *mode = pc->copper.mdix;
   1918     }
   1919 
   1920     return SOC_E_NONE;
   1921 }    
   1922 
   1923 /*
   1924  * Function:
   1925  *      phy_54680_mdix_status_get
   1926  * Description:
   1927  *      Get the current MDIX status on a port/PHY
   1928  * Parameters:
   1929  *      unit    - Device number
   1930  *      port    - Port number
   1931  *      status  - (OUT) One of:
   1932  *              SOC_PORT_MDIX_STATUS_NORMAL
   1933  *                      Straight connection
   1934  *              SOC_PORT_MDIX_STATUS_XOVER
   1935  *                      Crossover has been performed
   1936  * Return Value:
   1937  *      SOC_E_XXX
   1938  */
   1939 STATIC int
   1940 phy_54680_mdix_status_get(int unit, soc_port_t port, 
   1941                          soc_port_mdix_status_t *status)
   1942 {
   1943     phy_ctrl_t    *pc;
   1944     uint16               tmp;
   1945 
   1946     pc = EXT_PHY_SW_STATE(unit, port);
   1947 
   1948     SOC_IF_ERROR_RETURN
   1949         (READ_PHY54680_MII_ESRr(unit, pc, &tmp));
   1950     if (tmp & 0x2000) {
   1951         *status = SOC_PORT_MDIX_STATUS_XOVER;
   1952     } else {
   1953         *status = SOC_PORT_MDIX_STATUS_NORMAL;
   1954     }
   1955 
   1956     return SOC_E_NONE;
   1957 }    
   1958 
   1959 STATIC int
   1960 _phy_54680_power_mode_set (int unit, soc_port_t port, int mode)
   1961 {
   1962     phy_ctrl_t    *pc;
   1963 
   1964     pc       = EXT_PHY_SW_STATE(unit, port);
   1965 
   1966     if (pc->power_mode == mode) {
   1967         return SOC_E_NONE;
   1968     }
   1969 
   1970     if (mode == SOC_PHY_CONTROL_POWER_LOW) {
   1971         /* enable dsp clock */
   1972         SOC_IF_ERROR_RETURN
   1973             (MODIFY_PHY54680_MII_AUX_CTRLr(unit,pc,0x0c00,0x0c00));
   1974 
   1975         /* enable low power 136 */
   1976         SOC_IF_ERROR_RETURN
   1977             (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc,0x80,0x80));
   1978 
   1979         /* reduce tx bias current to -20% */
   1980         SOC_IF_ERROR_RETURN
   1981             (WRITE_PHY_REG(unit, pc, 0x17, 0x0f75));
   1982         SOC_IF_ERROR_RETURN
   1983             (WRITE_PHY_REG(unit, pc, 0x15, 0x1555));
   1984 
   1985         /* disable dsp clock */
   1986         SOC_IF_ERROR_RETURN
   1987             (MODIFY_PHY54680_MII_AUX_CTRLr(unit,pc,0x0400,0x0c00));
   1988 
   1989     } else if (mode == SOC_PHY_CONTROL_POWER_FULL) {
   1990 
   1991         /* back to normal mode */
   1992         /* enable dsp clock */
   1993         SOC_IF_ERROR_RETURN
   1994             (MODIFY_PHY54680_MII_AUX_CTRLr(unit,pc,0x0c00,0x0c00));
   1995 
   1996         /* disable low power 136 */
   1997         SOC_IF_ERROR_RETURN
   1998             (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc,0x00,0x80));
   1999 
   2000         /* set tx bias current to nominal */
   2001         SOC_IF_ERROR_RETURN
   2002             (WRITE_PHY_REG(unit, pc, 0x17, 0x0f75));
   2003         SOC_IF_ERROR_RETURN
   2004             (WRITE_PHY_REG(unit, pc, 0x15, 0x0));
   2005 
   2006         /* disable dsp clock */
   2007         SOC_IF_ERROR_RETURN
   2008             (MODIFY_PHY54680_MII_AUX_CTRLr(unit,pc,0x0400,0x0c00));
   2009 
   2010         /* disable the auto power mode */
   2011         SOC_IF_ERROR_RETURN
   2012             (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc,
   2013                         0,
   2014                         PHY_54680_AUTO_PWRDWN_EN));
   2015     } else if (mode == SOC_PHY_CONTROL_POWER_AUTO) {
   2016         SOC_IF_ERROR_RETURN
   2017             (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc,
   2018                         PHY_54680_AUTO_PWRDWN_EN,
   2019                         PHY_54680_AUTO_PWRDWN_EN));
   2020     } else if (mode == SOC_PHY_CONTROL_POWER_AUTO_DISABLE) {
   2021         /* 
   2022            Power mode added(SDK-30895). Requirement is to disable Auto Power Down
   2023            without changing Tx bias current 
   2024         */
   2025         SOC_IF_ERROR_RETURN
   2026             (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc,
   2027                         0,
   2028                         PHY_54680_AUTO_PWRDWN_EN));
   2029 
   2030     }
   2031 
   2032     pc->power_mode = mode;
   2033 
   2034     return SOC_E_NONE;
   2035 }
   2036 
   2037 /*
   2038  * Function:
   2039  *      _phy_54680_eee_enable
   2040  * Purpose:
   2041  *      Enable or disable EEE (Native)
   2042  * Parameters:
   2043  *      unit   - StrataSwitch unit #.
   2044  *      port   - StrataSwitch port #.
   2045  *      enable - Enable Native EEE
   2046  * Returns:
   2047  *      SOC_E_NONE
   2048  */
   2049 STATIC int
   2050 _phy_54680_eee_enable(int unit, soc_port_t port, int enable)
   2051 {
   2052     phy_ctrl_t *pc;
   2053 
   2054     if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2055         return SOC_E_FAIL;
   2056     }
   2057     pc = EXT_PHY_SW_STATE(unit, port);
   2058 
   2059     if (enable == 1) {
   2060         if (PHY_IS_BCM54680E_A0A1(pc) || PHY_IS_BCM54880E_A0A1(pc)) {
   2061             SOC_IF_ERROR_RETURN
   2062                 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00));
   2063 
   2064             SOC_IF_ERROR_RETURN(
   2065                 WRITE_PHY_REG(unit, pc, 0x17, 0x0ffe));
   2066             SOC_IF_ERROR_RETURN(
   2067                 WRITE_PHY_REG(unit, pc, 0x15, 0x0100));
   2068 
   2069             SOC_IF_ERROR_RETURN(
   2070                 WRITE_PHY_REG(unit, pc, 0x17, 0x0fff));
   2071             SOC_IF_ERROR_RETURN(
   2072                 WRITE_PHY_REG(unit, pc, 0x15, 0x4000));
   2073 
   2074             SOC_IF_ERROR_RETURN(
   2075                 WRITE_PHY_REG(unit, pc, 0x17, 0x2022));
   2076             SOC_IF_ERROR_RETURN(
   2077                 WRITE_PHY_REG(unit, pc, 0x15, 0x01f1));
   2078 
   2079             SOC_IF_ERROR_RETURN(
   2080                 WRITE_PHY_REG(unit, pc, 0x17, 0x4021));
   2081             SOC_IF_ERROR_RETURN(
   2082                 WRITE_PHY_REG(unit, pc, 0x15, 0x0887));
   2083 
   2084             SOC_IF_ERROR_RETURN(
   2085                 WRITE_PHY_REG(unit, pc, 0x17, 0x2021));
   2086             SOC_IF_ERROR_RETURN(
   2087                 WRITE_PHY_REG(unit, pc, 0x15, 0x8983));
   2088 
   2089             SOC_IF_ERROR_RETURN(
   2090                 WRITE_PHY_REG(unit, pc, 0x17, 0x0021));
   2091             SOC_IF_ERROR_RETURN(
   2092                 WRITE_PHY_REG(unit, pc, 0x15, 0x4600));
   2093 
   2094             SOC_IF_ERROR_RETURN(
   2095                 WRITE_PHY_REG(unit, pc, 0x17, 0x0e40));
   2096             SOC_IF_ERROR_RETURN(
   2097                 WRITE_PHY_REG(unit, pc, 0x15, 0x0000));
   2098 
   2099             SOC_IF_ERROR_RETURN
   2100                 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00));
   2101 
   2102             SOC_IF_ERROR_RETURN
   2103                 (MODIFY_PHY54680_EEE_TEST_CTRL_Br(unit, pc, 0xc000, 0xc000));
   2104             SOC_IF_ERROR_RETURN
   2105                 (MODIFY_PHY54680_EEE_TEST_CTRL_Ar(unit, pc, 0xf300, 0xf300));
   2106         } else {
   2107             SOC_IF_ERROR_RETURN
   2108                 (MODIFY_PHY54680_EEE_803Dr(unit, pc, 0xc000, 0xc000)); /* 7.803d */
   2109         }
   2110         if (PHY_IS_BCM52681E(pc)) {
   2111             SOC_IF_ERROR_RETURN
   2112                 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0002, 0x0006));
   2113             pc->copper.advert_ability.eee |= SOC_PA_EEE_100MB_BASETX;
   2114 
   2115         } else {
   2116             SOC_IF_ERROR_RETURN
   2117                 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0006, 0x0006));
   2118             pc->copper.advert_ability.eee |= (SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX);
   2119         }
   2120 
   2121         /* no support  of AutogrEEEn */
   2122         SOC_IF_ERROR_RETURN
   2123             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x1, 0x1)); /* exp af */
   2124     } else {  /* enable != 1 */
   2125         if (PHY_IS_BCM54680E_A0A1(pc) || PHY_IS_BCM54880E_A0A1(pc)) {
   2126             SOC_IF_ERROR_RETURN
   2127                 (MODIFY_PHY54680_EEE_TEST_CTRL_Br(unit, pc, 0x0000, 0xc000));
   2128             SOC_IF_ERROR_RETURN
   2129                 (MODIFY_PHY54680_EEE_TEST_CTRL_Ar(unit, pc, 0x0000, 0xf300));
   2130         } else {
   2131             SOC_IF_ERROR_RETURN
   2132                 (MODIFY_PHY54680_EEE_803Dr(unit, pc, 0x0000, 0xc000)); /* 7.803d */
   2133         }
   2134         SOC_IF_ERROR_RETURN
   2135             (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0000, 0x0006));
   2136         pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX);
   2137 
   2138         /* no support  of AutogrEEEn */
   2139         SOC_IF_ERROR_RETURN
   2140             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 0x1)); /* exp af */
   2141     }
   2142 
   2143     return SOC_E_NONE;
   2144 }
   2145 
   2146 /*
   2147  * Function:
   2148  *      _phy_54680_eee_auto_enable
   2149  * Purpose:
   2150  *      Enable or disable EEE (Native)
   2151  * Parameters:
   2152  *      unit   - StrataSwitch unit #.
   2153  *      port   - StrataSwitch port #.
   2154  *      enable - Enable Native EEE
   2155  * Returns:
   2156  *      SOC_E_NONE
   2157  */
   2158 STATIC int
   2159 _phy_54680_eee_auto_enable(int unit, soc_port_t port, int enable)
   2160 {
   2161     phy_ctrl_t *pc;
   2162 
   2163     if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2164         return SOC_E_FAIL;
   2165     }
   2166     pc = EXT_PHY_SW_STATE(unit, port);
   2167 
   2168     if (enable == 1) {
   2169         if (PHY_IS_BCM54680E_A0A1(pc) || PHY_IS_BCM54880E_A0A1(pc)) {
   2170             SOC_IF_ERROR_RETURN
   2171                 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00));
   2172 
   2173             SOC_IF_ERROR_RETURN(
   2174                 WRITE_PHY_REG(unit, pc, 0x17, 0x0ffe));
   2175             SOC_IF_ERROR_RETURN(
   2176                 WRITE_PHY_REG(unit, pc, 0x15, 0x0900));
   2177 
   2178             SOC_IF_ERROR_RETURN(
   2179                 WRITE_PHY_REG(unit, pc, 0x17, 0x0fff));
   2180             SOC_IF_ERROR_RETURN(
   2181                 WRITE_PHY_REG(unit, pc, 0x15, 0x4000));
   2182 
   2183             SOC_IF_ERROR_RETURN(
   2184                 WRITE_PHY_REG(unit, pc, 0x17, 0x2022));
   2185             SOC_IF_ERROR_RETURN(
   2186                 WRITE_PHY_REG(unit, pc, 0x15, 0x01f1));
   2187 
   2188             SOC_IF_ERROR_RETURN(
   2189                 WRITE_PHY_REG(unit, pc, 0x17, 0x2021));
   2190             SOC_IF_ERROR_RETURN(
   2191                 WRITE_PHY_REG(unit, pc, 0x15, 0x8983));
   2192 
   2193             SOC_IF_ERROR_RETURN(
   2194                 WRITE_PHY_REG(unit, pc, 0x17, 0x4021));
   2195             SOC_IF_ERROR_RETURN(
   2196                 WRITE_PHY_REG(unit, pc, 0x15, 0x0887));
   2197 
   2198             SOC_IF_ERROR_RETURN(
   2199                 WRITE_PHY_REG(unit, pc, 0x17, 0x0021));
   2200             SOC_IF_ERROR_RETURN(
   2201                 WRITE_PHY_REG(unit, pc, 0x15, 0x4600));
   2202 
   2203             SOC_IF_ERROR_RETURN
   2204                 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00));
   2205 
   2206             SOC_IF_ERROR_RETURN
   2207                 (MODIFY_PHY54680_EEE_TEST_CTRL_Br(unit, pc, 0xc000, 0xc000));
   2208 
   2209             SOC_IF_ERROR_RETURN
   2210                 (MODIFY_PHY54680_EEE_TEST_CTRL_Ar(unit, pc, 0x1300, 0x1300));
   2211 
   2212         } else {
   2213             SOC_IF_ERROR_RETURN
   2214                 (MODIFY_PHY54680_EEE_803Dr(unit, pc, 0xc000, 0xc000)); /* 7.803d */
   2215         }
   2216         if (PHY_IS_BCM52681E(pc)) {
   2217             SOC_IF_ERROR_RETURN
   2218                 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0002, 0x0006));
   2219             pc->copper.advert_ability.eee |= SOC_PA_EEE_100MB_BASETX;
   2220         } else {
   2221             SOC_IF_ERROR_RETURN
   2222                 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0006, 0x0006));
   2223             pc->copper.advert_ability.eee |= (SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX);
   2224         }
   2225 
   2226         SOC_IF_ERROR_RETURN
   2227             (MODIFY_PHY54680_MODE_CTRLr(unit, pc, 0x00, 0x06));
   2228 
   2229         SOC_IF_ERROR_RETURN
   2230             (MODIFY_PHY54680_SGMII_SLAVEr(unit, pc, 0x02, 0x02));
   2231 
   2232         if (!PHY_IS_BCM52681E(pc)) {
   2233             SOC_IF_ERROR_RETURN
   2234                 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0F7F,0x15, 0x7, 0x7)); /* exp 7f */
   2235         }
   2236 
   2237         SOC_IF_ERROR_RETURN
   2238             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x1, 0x1)); /* exp af */
   2239 
   2240         SOC_IF_ERROR_RETURN
   2241            (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7, 0x0001, 0x0003));
   2242 
   2243     } else {  /* enable != 1 */
   2244         SOC_IF_ERROR_RETURN
   2245             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 0x3)); /* exp af */
   2246         SOC_IF_ERROR_RETURN
   2247             (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0000, 0x0006));
   2248         pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX);
   2249 
   2250         if (PHY_IS_BCM54680E_A0A1(pc) || PHY_IS_BCM54880E_A0A1(pc)) {
   2251             SOC_IF_ERROR_RETURN
   2252                 (MODIFY_PHY54680_EEE_TEST_CTRL_Br(unit, pc, 0x0000, 0xc000)); /* 7.8031 */
   2253             SOC_IF_ERROR_RETURN
   2254                 (MODIFY_PHY54680_EEE_TEST_CTRL_Ar(unit, pc, 0x0000, 0xf300)); /* 7.8030 2 ops */
   2255         } else {
   2256             SOC_IF_ERROR_RETURN
   2257                 (MODIFY_PHY54680_EEE_803Dr(unit, pc, 0x0000, 0xc000)); /* 7.803d */
   2258         }
   2259     }
   2260 
   2261     return SOC_E_NONE;
   2262 }
   2263 
   2264 /*
   2265 * Function:
   2266  *      phy_54680_control_set
   2267  * Purpose:
   2268  *      Configure PHY device specific control fucntion.
   2269  * Parameters:
   2270  *      unit  - StrataSwitch unit #.
   2271  *      port  - StrataSwitch port #.
   2272  *      type  - Control to update
   2273  *      value - New setting for the control
   2274  * Returns:
   2275  *      SOC_E_NONE
   2276  */
   2277 STATIC int
   2278 phy_54680_control_set(int unit, soc_port_t port,
   2279                      soc_phy_control_t type, uint32 value)
   2280 {
   2281     int rv;
   2282     phy_ctrl_t *pc;
   2283     uint16 data;
   2284     soc_port_t primary;
   2285     int offset, saved_autoneg;
   2286 
   2287     PHY_CONTROL_TYPE_CHECK(type);
   2288 
   2289     pc = EXT_PHY_SW_STATE(unit, port);
   2290     rv = SOC_E_NONE;
   2291 
   2292     switch(type) {
   2293     case SOC_PHY_CONTROL_POWER:
   2294             rv = _phy_54680_power_mode_set(unit,port,value);
   2295         break;
   2296 
   2297     case SOC_PHY_CONTROL_DLL_POWER_AUTO:
   2298         /*
   2299          Deep Green Mode Control(PHY-401) - to enable/diable DLL Auto Power Down 
   2300         */
   2301         if(1 == value) { /* enable */
   2302             SOC_IF_ERROR_RETURN
   2303             (MODIFY_PHY54680_SPARE_CTRL_3r(unit, pc,
   2304                         0,
   2305                         PHY_54680_SPARE_CTRL3_REG_DLL_AUTO_PWR_DOWN));
   2306 
   2307         } else if(0 == value){ /* disable */
   2308             SOC_IF_ERROR_RETURN
   2309             (MODIFY_PHY54680_SPARE_CTRL_3r(unit, pc,
   2310                         PHY_54680_SPARE_CTRL3_REG_DLL_AUTO_PWR_DOWN,
   2311                         PHY_54680_SPARE_CTRL3_REG_DLL_AUTO_PWR_DOWN));
   2312         } else {
   2313             rv = SOC_E_PARAM; 
   2314         }
   2315         break;
   2316 
   2317     case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME:
   2318         if (value <= PHY_54680_AUTO_PWRDWN_WAKEUP_MAX) {
   2319 
   2320             /* at least one unit */
   2321             if (value < PHY_54680_AUTO_PWRDWN_WAKEUP_UNIT) {
   2322                 value = PHY_54680_AUTO_PWRDWN_WAKEUP_UNIT;
   2323             }
   2324         } else { /* anything more then max, set to the max */
   2325             value = PHY_54680_AUTO_PWRDWN_WAKEUP_MAX;
   2326         }
   2327         SOC_IF_ERROR_RETURN
   2328             (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc,
   2329                       value/PHY_54680_AUTO_PWRDWN_WAKEUP_UNIT,
   2330                       PHY_54680_AUTO_PWRDWN_WAKEUP_MASK));
   2331         break;
   2332 
   2333     case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME:
   2334         /* sleep time configuration is either 2.7s or 5.4 s, default is 2.7s */
   2335         if (value < PHY_54680_AUTO_PWRDWN_SLEEP_MAX) {
   2336             data = 0; /* anything less than 5.4s, default to 2.7s */
   2337         } else {
   2338             data = PHY_54680_AUTO_PWRDWN_SLEEP_MASK;
   2339         }
   2340         SOC_IF_ERROR_RETURN
   2341             (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc,
   2342                       data,
   2343                       PHY_54680_AUTO_PWRDWN_SLEEP_MASK));
   2344         break;
   2345 
   2346         case SOC_PHY_CONTROL_PORT_PRIMARY:
   2347             SOC_IF_ERROR_RETURN
   2348                 (soc_phyctrl_primary_set(unit, port, (soc_port_t)value));
   2349         break;
   2350 
   2351     case SOC_PHY_CONTROL_PORT_OFFSET:
   2352             SOC_IF_ERROR_RETURN
   2353                 (soc_phyctrl_offset_set(unit, port, (int)value));
   2354         break;
   2355 
   2356     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   2357         SOC_IF_ERROR_RETURN
   2358             (soc_phyctrl_primary_get(unit, port, &primary));
   2359         SOC_IF_ERROR_RETURN
   2360             (soc_phyctrl_offset_get(unit, port, &offset));
   2361         SOC_IF_ERROR_RETURN
   2362             (phy_54680_toplvl_reg_read(unit, port, primary, 0x0, &data));
   2363         if ( value ) {
   2364             SOC_IF_ERROR_RETURN
   2365                 (phy_54680_toplvl_reg_write(unit, port, primary, 0x0, 
   2366                      ( data & 0xf0 ) | ( offset & 0x7 )));
   2367         } else {
   2368             SOC_IF_ERROR_RETURN
   2369                 (phy_54680_toplvl_reg_write(unit, port, primary, 0x0, 
   2370                      ( data & 0xf0 ) | 0x8 ));
   2371         }
   2372         break;
   2373 
   2374     case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE:
   2375         SOC_IF_ERROR_RETURN
   2376             (soc_phyctrl_primary_get(unit, port, &primary));
   2377         SOC_IF_ERROR_RETURN
   2378             (soc_phyctrl_offset_get(unit, port, &offset));
   2379         SOC_IF_ERROR_RETURN
   2380             (phy_54680_toplvl_reg_read(unit, port, primary, 0x0, &data));
   2381         if ( value ) {
   2382             SOC_IF_ERROR_RETURN
   2383                 (phy_54680_toplvl_reg_write(unit, port, primary, 0x0, 
   2384                      ( data & 0x0f ) | (( offset & 0x7 )<<4 )));
   2385         } else {
   2386             SOC_IF_ERROR_RETURN
   2387                 (phy_54680_toplvl_reg_write(unit, port, primary, 0x0, 
   2388                      ( data & 0x0f ) | (0x8<<4) ));
   2389         }
   2390         break;
   2391 
   2392     case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT:
   2393         /* Not supported for 10/100/1000BASE-T interfaces */
   2394         rv = SOC_E_UNAVAIL;
   2395         break;
   2396 
   2397     case SOC_PHY_CONTROL_EEE:
   2398         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2399             rv = SOC_E_UNAVAIL;
   2400         }
   2401 
   2402         if (value == 1) {
   2403             /* didn't support Auto EEE */
   2404             if ((!PHY_IS_BCM53324(pc))) { 
   2405                 /* Disable Auto EEE */
   2406                 SOC_IF_ERROR_RETURN
   2407                     (_phy_54680_eee_auto_enable(unit, port, 0));
   2408             }
   2409             /* Enable Native EEE */
   2410             SOC_IF_ERROR_RETURN
   2411                 (_phy_54680_eee_enable(unit, port, 1));
   2412             saved_autoneg = pc->copper.autoneg_enable;
   2413             /* Initiate AN */
   2414             SOC_IF_ERROR_RETURN
   2415                 (phy_54680_autoneg_set(unit, port, 1));
   2416             pc->copper.autoneg_enable = saved_autoneg;
   2417             PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   2418             PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE);
   2419         } else {
   2420             SOC_IF_ERROR_RETURN
   2421                 (_phy_54680_eee_enable(unit, port, 0));
   2422                 /* Initiate AN if administratively enabled */
   2423             SOC_IF_ERROR_RETURN
   2424                 (phy_54680_autoneg_set(unit, port, pc->copper.autoneg_enable ? 1 : 0));
   2425             PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   2426 
   2427         }
   2428 
   2429 
   2430         break;
   2431 
   2432     case SOC_PHY_CONTROL_EEE_AUTO:
   2433         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2434             rv = SOC_E_UNAVAIL;
   2435         }
   2436         if (PHY_IS_BCM53324(pc)) {
   2437             rv = SOC_E_UNAVAIL;
   2438         }
   2439         if (value == 1) {
   2440             /* Disable Native EEE */
   2441             SOC_IF_ERROR_RETURN
   2442                 (_phy_54680_eee_enable(unit, port, 0));
   2443             /* Enable Auto EEE */
   2444             SOC_IF_ERROR_RETURN
   2445                 (_phy_54680_eee_auto_enable(unit, port, 1));
   2446             saved_autoneg = pc->copper.autoneg_enable;
   2447             /* Initiate AN */
   2448             SOC_IF_ERROR_RETURN
   2449                 (phy_54680_autoneg_set(unit, port, 1));
   2450             pc->copper.autoneg_enable = saved_autoneg;
   2451             PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   2452             PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_MODE);
   2453         } else {
   2454             /* Disable Auto EEE */
   2455             SOC_IF_ERROR_RETURN
   2456                 (_phy_54680_eee_auto_enable(unit, port, 0));
   2457                 /* Initiate AN if administratively enabled */
   2458             SOC_IF_ERROR_RETURN
   2459                 (phy_54680_autoneg_set(unit, port, pc->copper.autoneg_enable ? 1 : 0));
   2460             PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   2461         }
   2462 
   2463         break;
   2464 
   2465     case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD:
   2466         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2467             rv = SOC_E_UNAVAIL;
   2468         }
   2469 
   2470         if (value > 7) { /* Values needs to between 0 to 7 (inclusive) */
   2471             rv = SOC_E_CONFIG;
   2472         }
   2473 
   2474         SOC_IF_ERROR_RETURN
   2475            (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7,
   2476                                                    value<<8, 0x0700));
   2477         /* Setting GPHY core, MII buffer register as well */
   2478         SOC_IF_ERROR_RETURN
   2479            (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, 
   2480                                                     value<<8, 0x0700));
   2481         break;
   2482 
   2483 
   2484     case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY:
   2485         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2486             rv = SOC_E_UNAVAIL;
   2487         }
   2488         /* Fixed latency can have only 0 or 1 value  */
   2489         if ((value != FALSE) && (value != TRUE)) {
   2490             return SOC_E_PARAM;
   2491         }
   2492         if (value == FALSE) { 
   2493             /* Sets Variable Latency */
   2494             SOC_IF_ERROR_RETURN
   2495                (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7,
   2496                                                    0x0004, 0x0004));
   2497             /* Setting GPHY core, MII buffer register as well */
   2498             SOC_IF_ERROR_RETURN
   2499                (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc,
   2500                                                         0x0004, 0x0004));
   2501         } else {
   2502             /* Sets Fixed Latency */
   2503             SOC_IF_ERROR_RETURN
   2504                (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7,
   2505                                                    0x0000, 0x0004));
   2506             /* Setting GPHY core, MII buffer register as well */
   2507             SOC_IF_ERROR_RETURN
   2508                (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, 
   2509                                                         0x0000, 0x0004));
   2510         } 
   2511         break;
   2512 
   2513 
   2514     case SOC_PHY_CONTROL_EEE_AUTO_BUFFER_LIMIT:
   2515         /* Buffer limit modification is not allowed */
   2516 
   2517     case SOC_PHY_CONTROL_EEE_TRANSMIT_WAKE_TIME:
   2518     case SOC_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME:
   2519     case SOC_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME:
   2520     case SOC_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME:
   2521     case SOC_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME:
   2522     case SOC_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME:
   2523     case SOC_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME:
   2524         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2525             rv = SOC_E_UNAVAIL;
   2526         }
   2527 
   2528         /* Time modification not allowed, IEEE EEE spec constants */
   2529         rv = SOC_E_UNAVAIL;
   2530         break;
   2531 
   2532     case SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR:
   2533         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2534             rv = SOC_E_UNAVAIL;
   2535         }
   2536         
   2537         if (value == 1) {
   2538             /* Clearing the stats: Enable clear on Read  */
   2539             SOC_IF_ERROR_RETURN
   2540                (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, 
   2541                                                         0x1000, 0x1000));
   2542 
   2543             /* Read all the stats to clear */
   2544             SOC_IF_ERROR_RETURN
   2545                 (READ_PHY54680_EXP_EEE_TX_EVENTSr(unit, pc, &data));
   2546             SOC_IF_ERROR_RETURN
   2547                 (READ_PHY54680_EXP_EEE_TX_EVENTSr(unit, pc, &data));
   2548             SOC_IF_ERROR_RETURN
   2549                 (READ_PHY54680_EXP_EEE_TX_DURATIONr(unit, pc, &data));
   2550             SOC_IF_ERROR_RETURN
   2551                 (READ_PHY54680_EXP_EEE_TX_DURATIONr(unit, pc, &data));
   2552             SOC_IF_ERROR_RETURN
   2553                 (READ_PHY54680_EXP_EEE_RX_EVENTSr(unit, pc, &data));
   2554             SOC_IF_ERROR_RETURN
   2555                 (READ_PHY54680_EXP_EEE_RX_EVENTSr(unit, pc, &data));
   2556             SOC_IF_ERROR_RETURN
   2557                 (READ_PHY54680_EXP_EEE_RX_DURATIONr(unit, pc, &data));
   2558             SOC_IF_ERROR_RETURN
   2559                 (READ_PHY54680_EXP_EEE_RX_DURATIONr(unit, pc, &data));
   2560 
   2561             /* Disable Clear on Read  */
   2562             SOC_IF_ERROR_RETURN
   2563                (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, 
   2564                                                         0x0000, 0x1000));
   2565         }
   2566         break;
   2567 
   2568     case SOC_PHY_CONTROL_LOOPBACK_EXTERNAL:
   2569         if (value) {
   2570             int saved_autoneg, saved_speed;
   2571 
   2572             saved_autoneg = pc->copper.autoneg_enable;
   2573             SOC_IF_ERROR_RETURN
   2574                 (phy_54680_autoneg_set(unit, port, 0));
   2575             pc->copper.autoneg_enable = saved_autoneg;
   2576             
   2577             saved_speed = pc->copper.force_speed;
   2578             SOC_IF_ERROR_RETURN
   2579                 (phy_54680_speed_set(unit, port, 1000));
   2580             pc->copper.force_speed = saved_speed;
   2581 
   2582             SOC_IF_ERROR_RETURN
   2583                 (MODIFY_PHY54680_MII_GB_CTRLr(unit, pc, (1U << 12 | 1U << 11), (1U << 12 | 1U << 11)));
   2584             SOC_IF_ERROR_RETURN
   2585                 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, (1U << 15 | 1U << 10), (1U << 15 | 1U << 10)));
   2586         } else {
   2587             SOC_IF_ERROR_RETURN
   2588                 (MODIFY_PHY54680_MII_GB_CTRLr(unit, pc, 0, (1U << 12 | 1U << 11)));
   2589             SOC_IF_ERROR_RETURN
   2590                 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0, (1U << 15 | 1U << 10)));
   2591             SOC_IF_ERROR_RETURN
   2592                 (phy_54680_speed_set(unit, port, pc->copper.force_speed));
   2593             SOC_IF_ERROR_RETURN
   2594                 (phy_54680_autoneg_set(unit, port, pc->copper.autoneg_enable ? 1 : 0));
   2595         }
   2596         break;
   2597 
   2598     default:
   2599         rv = SOC_E_UNAVAIL;
   2600         break;
   2601     }
   2602     return rv;
   2603 }
   2604 
   2605 /*
   2606  * Function:
   2607  *      phy_54680_control_get
   2608  * Purpose:
   2609  *      Get current control settign of the PHY.
   2610  * Parameters:
   2611  *      unit  - StrataSwitch unit #.
   2612  *      port  - StrataSwitch port #.
   2613  *      type  - Control to update
   2614  *      value - (OUT)Current setting for the control
   2615  * Returns:
   2616  *      SOC_E_NONE
   2617  */
   2618 STATIC int
   2619 phy_54680_control_get(int unit, soc_port_t port,
   2620                      soc_phy_control_t type, uint32 *value)
   2621 {
   2622     int rv;
   2623     phy_ctrl_t *pc;
   2624     uint16 data;
   2625     uint32 temp;
   2626     soc_port_t primary;
   2627     int offset;
   2628 
   2629     PHY_CONTROL_TYPE_CHECK(type);
   2630 
   2631     pc = EXT_PHY_SW_STATE(unit, port);
   2632     rv = SOC_E_NONE;
   2633 
   2634     switch(type) {
   2635     case SOC_PHY_CONTROL_POWER:
   2636             *value = pc->power_mode;
   2637         break;
   2638 
   2639     case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME:
   2640         SOC_IF_ERROR_RETURN
   2641             (READ_PHY54680_AUTO_POWER_DOWNr(unit,pc, &data));
   2642 
   2643         if (data & PHY_54680_AUTO_PWRDWN_SLEEP_MASK) {
   2644             *value = PHY_54680_AUTO_PWRDWN_SLEEP_MAX;
   2645         } else {
   2646             *value = 2700;
   2647         }
   2648         break;
   2649 
   2650     case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME:
   2651         SOC_IF_ERROR_RETURN
   2652             (READ_PHY54680_AUTO_POWER_DOWNr(unit,pc, &data));
   2653 
   2654         data &= PHY_54680_AUTO_PWRDWN_WAKEUP_MASK;
   2655         *value = data * PHY_54680_AUTO_PWRDWN_WAKEUP_UNIT;
   2656         break;
   2657 
   2658     case SOC_PHY_CONTROL_PORT_PRIMARY:
   2659             SOC_IF_ERROR_RETURN
   2660                 (soc_phyctrl_primary_get(unit, port, &primary));
   2661             *value = (uint32) primary;
   2662         break;
   2663 
   2664     case SOC_PHY_CONTROL_PORT_OFFSET:
   2665             SOC_IF_ERROR_RETURN
   2666                 (soc_phyctrl_offset_get(unit, port, &offset));
   2667             *value = (uint32) offset;
   2668         break;
   2669 
   2670     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   2671         SOC_IF_ERROR_RETURN
   2672             (soc_phyctrl_primary_get(unit, port, &primary));
   2673         SOC_IF_ERROR_RETURN
   2674             (soc_phyctrl_offset_get(unit, port, &offset));
   2675         if (phy_54680_toplvl_reg_read(unit, port, primary, 0x0, &data) == SOC_E_NONE) {
   2676             if (( data & 0x8 ) || (( data & 0x7 ) != offset)) {
   2677                 *value = FALSE;
   2678             } else {
   2679                 *value = TRUE;
   2680             }
   2681         }
   2682         break;
   2683 
   2684     case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE:
   2685         SOC_IF_ERROR_RETURN
   2686             (soc_phyctrl_primary_get(unit, port, &primary));
   2687         SOC_IF_ERROR_RETURN
   2688             (soc_phyctrl_offset_get(unit, port, &offset));
   2689         if (phy_54680_toplvl_reg_read(unit, port, primary, 0x0, &data) == SOC_E_NONE) {
   2690             if (( data & (0x8<<4) ) || (( data & (0x7<<4) ) != (offset<<4) )) {
   2691                 *value = FALSE;
   2692             } else {
   2693                 *value = TRUE;
   2694             }
   2695         }
   2696         break;
   2697 
   2698     case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT:
   2699         /* Not supported for 10/100/1000BASE-T interfaces */
   2700         rv = SOC_E_UNAVAIL;
   2701         break;
   2702 
   2703     case SOC_PHY_CONTROL_EEE:
   2704         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2705             rv = SOC_E_UNAVAIL;
   2706         }
   2707         *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) &&
   2708                  !PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0;
   2709         break;
   2710 
   2711     case SOC_PHY_CONTROL_EEE_AUTO:
   2712         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2713             rv = SOC_E_UNAVAIL;
   2714         }
   2715         if (PHY_IS_BCM53324(pc)) {
   2716             rv = SOC_E_UNAVAIL;
   2717         }
   2718         *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) &&
   2719                   PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0;
   2720         break;
   2721 
   2722     case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY:
   2723         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2724             rv = SOC_E_UNAVAIL;
   2725         }
   2726         SOC_IF_ERROR_RETURN
   2727             (READ_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, &data));
   2728         *value = ((data & 0x0004) == 0);
   2729         break;
   2730 
   2731     case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD:
   2732         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2733             rv = SOC_E_UNAVAIL;
   2734         }
   2735         SOC_IF_ERROR_RETURN
   2736             (READ_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, &data));
   2737         *value = ((data & 0x0700) >> 8);
   2738         break;
   2739 
   2740     case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS:
   2741         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2742             rv = SOC_E_UNAVAIL;
   2743         }
   2744         if (PHY_IS_BCM53324(pc)) { 
   2745             /* Internal GPHY didn't support */
   2746             rv = SOC_E_UNAVAIL;
   2747             return rv;
   2748         }
   2749         SOC_IF_ERROR_RETURN
   2750             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 1U<<14)); /* exp af */
   2751         SOC_IF_ERROR_RETURN
   2752             (READ_PHY54680_EXP_EEE_TX_EVENTSr(unit, pc, &data));
   2753         temp = data;
   2754         SOC_IF_ERROR_RETURN
   2755             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 1U<<14, 1U<<14)); /* exp af */
   2756         SOC_IF_ERROR_RETURN
   2757             (READ_PHY54680_EXP_EEE_TX_EVENTSr(unit, pc, &data));
   2758         temp |= (data << 16);
   2759         *value = temp;
   2760         break;
   2761 
   2762     case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION:
   2763         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2764             rv = SOC_E_UNAVAIL;
   2765         }
   2766         if (PHY_IS_BCM53324(pc)) {
   2767             /* Internal GPHY didn't support */
   2768             rv = SOC_E_UNAVAIL;
   2769             return rv;
   2770         }
   2771         SOC_IF_ERROR_RETURN
   2772             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 1U<<14)); /* exp af */
   2773         SOC_IF_ERROR_RETURN
   2774             (READ_PHY54680_EXP_EEE_TX_DURATIONr(unit, pc, &data));
   2775         temp = data;
   2776         SOC_IF_ERROR_RETURN
   2777             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 1U<<14, 1U<<14)); /* exp af */
   2778         SOC_IF_ERROR_RETURN
   2779             (READ_PHY54680_EXP_EEE_TX_DURATIONr(unit, pc, &data));
   2780         temp |= (data << 16);
   2781         *value = temp;
   2782         break;
   2783 
   2784     case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS:
   2785         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2786             rv = SOC_E_UNAVAIL;
   2787         }
   2788         SOC_IF_ERROR_RETURN
   2789             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 1U<<14)); /* exp af */
   2790         SOC_IF_ERROR_RETURN
   2791             (READ_PHY54680_EXP_EEE_RX_EVENTSr(unit, pc, &data));
   2792         temp = data;
   2793         SOC_IF_ERROR_RETURN
   2794             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 1U<<14, 1U<<14)); /* exp af */
   2795         SOC_IF_ERROR_RETURN
   2796             (READ_PHY54680_EXP_EEE_RX_EVENTSr(unit, pc, &data));
   2797         temp |= (data << 16);
   2798         *value = temp;
   2799         break;
   2800 
   2801     case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION:
   2802         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2803             rv = SOC_E_UNAVAIL;
   2804         }
   2805         SOC_IF_ERROR_RETURN
   2806             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 1U<<14)); /* exp af */
   2807         SOC_IF_ERROR_RETURN
   2808             (READ_PHY54680_EXP_EEE_RX_DURATIONr(unit, pc, &data));
   2809         temp = data;
   2810         SOC_IF_ERROR_RETURN
   2811             (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 1U<<14, 1U<<14)); /* exp af */
   2812         SOC_IF_ERROR_RETURN
   2813             (READ_PHY54680_EXP_EEE_RX_DURATIONr(unit, pc, &data));
   2814         temp |= (data << 16);
   2815         *value = temp;
   2816         break;
   2817 
   2818     case SOC_PHY_CONTROL_LOOPBACK_EXTERNAL:
   2819          SOC_IF_ERROR_RETURN
   2820              (READ_PHY54680_MII_AUX_CTRLr(unit, pc, &data));
   2821          *value = data & (1U<<15) ? 1 : 0;
   2822          break;
   2823 
   2824     default:
   2825         rv = SOC_E_UNAVAIL;
   2826         break;
   2827     }
   2828     return rv;
   2829 }
   2830 
   2831 /*
   2832  * Function:
   2833  *      phy_54680_cable_diag
   2834  * Purpose:
   2835  *      Run 546x cable diagnostics
   2836  * Parameters:
   2837  *      unit - device number
   2838  *      port - port number
   2839  *      status - (OUT) cable diagnotic status structure
   2840  * Returns:
   2841  *      SOC_E_XXX
   2842  */
   2843 STATIC int
   2844 phy_54680_cable_diag(int unit, soc_port_t port,
   2845                     soc_port_cable_diag_t *status)
   2846 {
   2847     int rv, rv2, i;
   2848     phy_ctrl_t *pc;
   2849 
   2850     extern int phy_5464_cable_diag_sw(int, soc_port_t ,
   2851                                       soc_port_cable_diag_t *);
   2852 
   2853     pc = EXT_PHY_SW_STATE(unit, port);
   2854 
   2855     if (status == NULL) {
   2856         return SOC_E_PARAM;
   2857     }
   2858 
   2859     status->state = SOC_PORT_CABLE_STATE_OK;
   2860     status->npairs = 4;
   2861     status->fuzz_len = 0;
   2862     for (i = 0; i < 4; i++) {
   2863         status->pair_state[i] = SOC_PORT_CABLE_STATE_OK;
   2864     }
   2865 
   2866     MIIM_LOCK(unit);    /* this locks out linkscan, essentially */
   2867     rv = phy_5464_cable_diag_sw(unit,port, status);
   2868     MIIM_UNLOCK(unit);
   2869     rv2 = 0;
   2870     if (rv <= 0) {      /* don't reset if > 0 -- link was up */
   2871         rv2 = _phy_54680_reset_setup(unit, port);
   2872         if (SOC_SUCCESS(rv2)) {
   2873             rv2 = phy_54680_medium_config_set(unit, port, SOC_PORT_MEDIUM_COPPER, &pc->copper);
   2874         }
   2875     }
   2876     if (rv >= 0 && rv2 < 0) {
   2877         return rv2;
   2878     }
   2879     return rv;
   2880 }
   2881 
   2882 /*
   2883  * Function:
   2884  *      phy_54680_probe
   2885  * Purpose:
   2886  *      Complement the generic phy probe routine to identify this phy when its
   2887  *      phy id0 and id1 is same as some other phy's.
   2888  * Parameters:
   2889  *      unit - StrataSwitch unit #.
   2890  *      pc   - phy ctrl descriptor.
   2891  * Returns:
   2892  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   2893  */
   2894 STATIC int
   2895 phy_54680_probe(int unit, phy_ctrl_t *pc)
   2896 {
   2897     uint16 id0, id1;
   2898     int rv = SOC_E_NOT_FOUND;
   2899 
   2900     if (READ_PHY54680_MII_PHY_ID0r(unit, pc, &id0) < 0) {
   2901         return rv;
   2902     }
   2903     if (READ_PHY54680_MII_PHY_ID1r(unit, pc, &id1) < 0) {
   2904         return rv;
   2905     }
   2906 
   2907     switch (PHY_MODEL(id0, id1)) {
   2908 
   2909     case PHY_BCM54680_MODEL:
   2910     case PHY_BCM54880E_MODEL:
   2911     case PHY_BCM53324_MODEL:
   2912         rv = SOC_E_NONE;
   2913     break;
   2914 
   2915     case PHY_BCM54680E_MODEL:
   2916         if (id1 & 0x8) {
   2917             rv = SOC_E_NONE;
   2918         }
   2919     break;
   2920 
   2921     case PHY_BCM52681E_MODEL:
   2922         if (id1 & 0x8) {
   2923             rv = SOC_E_NONE;
   2924         }
   2925     break;
   2926 
   2927     default:
   2928     break;
   2929 
   2930     }
   2931     pc->size = sizeof(PHY54680_DEV_DESC_t);
   2932 
   2933     return rv;
   2934 }
   2935 
   2936 
   2937 STATIC int
   2938 phy_54680_link_up(int unit, soc_port_t port)
   2939 {
   2940     phy_ctrl_t *pc;
   2941     int speed;
   2942     uint16  phy_auto, value;
   2943     uint32 rev_b_cfg = 0;
   2944     uint32 rev_a_cfg = 0;
   2945     
   2946 
   2947     pc = EXT_PHY_SW_STATE(unit, port);
   2948 
   2949     SOC_IF_ERROR_RETURN
   2950         (phy_54680_speed_get(unit, port, &speed));
   2951 
   2952     if (speed == 100) {
   2953         SOC_IF_ERROR_RETURN(
   2954             READ_PHY_REG(unit, pc, 0x11, &value));
   2955         if(value & (1U << 13)) {
   2956                 SOC_IF_ERROR_RETURN
   2957                     (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FF5,0x15, 0x0<<10, 0x3<<10)); /* exp reg f5 */
   2958         } else {
   2959                 SOC_IF_ERROR_RETURN
   2960                     (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FF5,0x15, 0x1<<10, 0x3<<10)); /* exp reg f5 */
   2961         }
   2962     }
   2963 
   2964     if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED)) { /*non EEE */
   2965         /* do nothing */
   2966         rev_a_cfg = rev_b_cfg = 0;
   2967     } else
   2968     if (PHY_IS_BCM53324(pc)) {
   2969         /* Check if rev Bx configuration is required for integrated PHY */
   2970         if ((PHY_IS_BCM53324(pc) && pc->phy_rev == 0x0)) {
   2971             rev_b_cfg = 1;
   2972         }
   2973     } else {
   2974         if ((pc->phy_rev & 0x6) == 0x2) {
   2975             rev_b_cfg = 1;
   2976         } else if ((pc->phy_rev & 0x6) == 0x0) {
   2977             rev_a_cfg = 1;
   2978         }
   2979     }
   2980     if (rev_b_cfg) {
   2981         /* revs B0 and B1 of supported PHYs */
   2982         sal_usleep(10000);    
   2983         SOC_IF_ERROR_RETURN(
   2984             READ_PHY54680_AUTO_POWER_DOWNr(unit, pc, &phy_auto));
   2985         if ((phy_auto & PHY_54680_AUTO_PWRDWN_EN) != 0) {
   2986             /* Disable PHY Auto Power-Down mode */
   2987             SOC_IF_ERROR_RETURN(
   2988                 MODIFY_PHY54680_AUTO_POWER_DOWNr(unit, pc,
   2989                     0, PHY_54680_AUTO_PWRDWN_EN));
   2990         }
   2991         SOC_IF_ERROR_RETURN(
   2992             MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, (1U << 11), (1U << 11)));
   2993         SOC_IF_ERROR_RETURN(
   2994             WRITE_PHY_REG(unit, pc, 0x17, 0x001a));
   2995         SOC_IF_ERROR_RETURN(
   2996             WRITE_PHY_REG(unit, pc, 0x15, 0x0003));
   2997         SOC_IF_ERROR_RETURN(
   2998             MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0, (1U << 11)));
   2999         if ((phy_auto & PHY_54680_AUTO_PWRDWN_EN) != 0) {
   3000             /* Enable PHY Auto Power-Down mode */
   3001             SOC_IF_ERROR_RETURN(
   3002                 MODIFY_PHY54680_AUTO_POWER_DOWNr(unit, pc,
   3003                     PHY_54680_AUTO_PWRDWN_EN, PHY_54680_AUTO_PWRDWN_EN));
   3004         }
   3005     } 
   3006     if (rev_a_cfg) {
   3007         /* revs A0 and A1 of supported PHYs */
   3008         uint32 eee_auto;
   3009 
   3010         SOC_IF_ERROR_RETURN
   3011             (phy_54680_control_get(unit, port,
   3012                      SOC_PHY_CONTROL_EEE_AUTO, &eee_auto));
   3013         if ((speed == 100) && (eee_auto == 1)) {
   3014             SOC_IF_ERROR_RETURN(
   3015                 WRITE_PHY_REG(unit, pc, 0x17, 0x0d10));
   3016             SOC_IF_ERROR_RETURN(
   3017                 WRITE_PHY_REG(unit, pc, 0x15, 0x00ff));
   3018 
   3019         } else {
   3020             SOC_IF_ERROR_RETURN(
   3021                 WRITE_PHY_REG(unit, pc, 0x17, 0x0d10));
   3022             SOC_IF_ERROR_RETURN(
   3023                 WRITE_PHY_REG(unit, pc, 0x15, 0x0000));
   3024         }
   3025     }
   3026 
   3027     /* Notify interface to internal PHY */
   3028     SOC_IF_ERROR_RETURN
   3029         (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII));
   3030 
   3031     /* Situation observed with Saber devices XGXS16g1l+BCM54640E
   3032        Linkscan is not updating speed for internal phy xgxs16g1l. 
   3033        It was observed that when speed is set to 100M the int phy 
   3034        is still set to 1G and traffic does not flow through untill 
   3035        int phy speed is also update to 100M. This applies to other 
   3036        speeds as well. 
   3037        Explicitly send speed notify to int phy from ext phy.
   3038     */
   3039     SOC_IF_ERROR_RETURN
   3040         (soc_phyctrl_notify(unit, port, phyEventSpeed, speed));
   3041 
   3042 
   3043     return SOC_E_NONE;
   3044 }
   3045 
   3046 STATIC int
   3047 phy_54680_link_down(int unit, soc_port_t port)
   3048 {
   3049     phy_ctrl_t *pc;
   3050     uint16  phy_auto;
   3051     uint32 rev_b_cfg = 0;
   3052 
   3053     if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED)) { /*non EEE */
   3054         return SOC_E_NONE;
   3055     }
   3056 
   3057     pc = EXT_PHY_SW_STATE(unit, port);
   3058 
   3059     if (PHY_IS_BCM53324(pc)) {
   3060         /* Check if rev Bx configuration is required for integrated PHY */
   3061         if ((PHY_IS_BCM53324(pc) && pc->phy_rev == 0x0)) {
   3062             rev_b_cfg = 1;
   3063         }
   3064     } else {
   3065         if ((pc->phy_rev & 0x6) == 0x2) {
   3066             rev_b_cfg = 1;
   3067         }
   3068     }
   3069     
   3070     if (rev_b_cfg) {
   3071         /* revs B0 and B1 of supported PHYs */
   3072         SOC_IF_ERROR_RETURN(
   3073             READ_PHY54680_AUTO_POWER_DOWNr(unit, pc, &phy_auto));
   3074         if ((phy_auto & PHY_54680_AUTO_PWRDWN_EN) != 0) {
   3075             /* Disable PHY Auto Power-Down mode */
   3076             SOC_IF_ERROR_RETURN(
   3077                 MODIFY_PHY54680_AUTO_POWER_DOWNr(unit, pc,
   3078                     0, PHY_54680_AUTO_PWRDWN_EN));
   3079         }         
   3080         SOC_IF_ERROR_RETURN(
   3081             MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, (1U << 11), (1U << 11)));
   3082         SOC_IF_ERROR_RETURN(
   3083             WRITE_PHY_REG(unit, pc, 0x17, 0x001a));
   3084         SOC_IF_ERROR_RETURN(
   3085             WRITE_PHY_REG(unit, pc, 0x15, 0x0007));
   3086         SOC_IF_ERROR_RETURN(
   3087             MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0, (1U << 11)));
   3088         if ((phy_auto & PHY_54680_AUTO_PWRDWN_EN) != 0) {
   3089             /* Enable PHY Auto Power-Down mode */
   3090             SOC_IF_ERROR_RETURN(
   3091                 MODIFY_PHY54680_AUTO_POWER_DOWNr(unit, pc,
   3092                     PHY_54680_AUTO_PWRDWN_EN, PHY_54680_AUTO_PWRDWN_EN));
   3093         }     
   3094     }
   3095 
   3096     return SOC_E_NONE;
   3097 }
   3098 
   3099 STATIC int
   3100 phy54680_cable_diag_dispatch(int unit, soc_port_t port,
   3101             soc_port_cable_diag_t *status)
   3102 {
   3103     phy_ctrl_t *pc;
   3104 
   3105     pc = EXT_PHY_SW_STATE(unit, port);
   3106 
   3107     if (ECD_ENABLE && ((((PHY_IS_BCM54880E(pc)) || (PHY_IS_BCM54680E(pc))) && ((pc->phy_rev & 0x7) > 0x2)) ||
   3108         ((PHY_IS_BCM54680(pc)) && ((pc->phy_rev & 0xf) > 0x1))))  {
   3109         SOC_IF_ERROR_RETURN(
   3110             phy_ecd_cable_diag(unit, port, status));
   3111         SOC_IF_ERROR_RETURN(
   3112             _phy_54680_reset_setup(unit, port));
   3113     } else {
   3114         SOC_IF_ERROR_RETURN(
   3115             phy_54680_cable_diag(unit, port, status));
   3116     }
   3117 
   3118     return SOC_E_NONE;
   3119 }
   3120 
   3121 void _phy_54680e_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode,
   3122                                             int offset, uint16 *value)
   3123 {
   3124 
   3125     switch (mode) {
   3126     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE:
   3127         *value |= (0x0 << offset);
   3128         break;
   3129     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD:
   3130         *value |= (0x1 << offset);
   3131         break;
   3132     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN:
   3133         *value |= (0x2 << offset);
   3134         break;
   3135     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP:
   3136         *value |= (0x3 << offset);
   3137         break;
   3138     default:
   3139         break;
   3140     }
   3141 
   3142 }
   3143 
   3144 void _phy_54680e_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode,
   3145                                             int offset, uint16 *value)
   3146 {
   3147 
   3148     switch (mode) {
   3149     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE:
   3150         *value |= (0x0 << offset);
   3151         break;
   3152     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD:
   3153         *value |= (0x1 << offset);
   3154         break;
   3155     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP:
   3156         *value |= (0x2 << offset);
   3157         break;
   3158     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME:
   3159         *value |= (0x3 << offset);
   3160         break;
   3161     default:
   3162         break;
   3163     }
   3164 
   3165 }
   3166 
   3167 void _phy_54680e_decode_egress_message_mode(uint16 value, int offset,
   3168                                             soc_port_phy_timesync_event_message_egress_mode_t *mode)
   3169 {
   3170 
   3171     switch ((value >> offset) & 0x3) {
   3172     case 0x0:
   3173         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE;
   3174         break;
   3175     case 0x1:
   3176         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD;
   3177         break;
   3178     case 0x2:
   3179         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN;
   3180         break;
   3181     case 0x3:
   3182         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP;
   3183         break;
   3184     }
   3185 
   3186 }
   3187 
   3188 void _phy_54680e_decode_ingress_message_mode(uint16 value, int offset,
   3189                                             soc_port_phy_timesync_event_message_ingress_mode_t *mode)
   3190 {
   3191 
   3192     switch ((value >> offset) & 0x3) {
   3193     case 0x0:
   3194         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE;
   3195         break;
   3196     case 0x1:
   3197         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD;
   3198         break;
   3199     case 0x2:
   3200         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP;
   3201         break;
   3202     case 0x3:
   3203         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME;
   3204         break;
   3205     }
   3206 
   3207 }
   3208 
   3209 void _phy_54680e_encode_gmode(soc_port_phy_timesync_global_mode_t mode,
   3210                                             uint16 *value)
   3211 {
   3212 
   3213     switch (mode) {
   3214     case SOC_PORT_PHY_TIMESYNC_MODE_FREE:
   3215         *value = 0x1;
   3216         break;
   3217     case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN:
   3218         *value = 0x2;
   3219         break;
   3220     case SOC_PORT_PHY_TIMESYNC_MODE_CPU:
   3221         *value = 0x3;
   3222         break;
   3223     default:
   3224         break;
   3225     }
   3226 
   3227 }
   3228 
   3229 void _phy_54680e_decode_gmode(uint16 value,
   3230                                             soc_port_phy_timesync_global_mode_t *mode)
   3231 {
   3232 
   3233     switch (value & 0x3) {
   3234     case 0x1:
   3235         *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   3236         break;
   3237     case 0x2:
   3238         *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN;
   3239         break;
   3240     case 0x3:
   3241         *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU;
   3242         break;
   3243     default:
   3244         break;
   3245     }
   3246 
   3247 }
   3248 
   3249 void _phy_54680e_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode,
   3250                                             uint16 *value)
   3251 {
   3252 
   3253     switch (mode) {
   3254     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0:
   3255         *value = 1U << 0;
   3256         break;
   3257     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1:
   3258         *value = 1U << 1;
   3259         break;
   3260     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT:
   3261         *value = 1U << 2;
   3262         break;
   3263     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU:
   3264         *value = 1U << 3;
   3265         break;
   3266     default:
   3267         break;
   3268     }
   3269 
   3270 }
   3271 
   3272 void _phy_54680e_decode_framesync_mode(uint16 value,
   3273                                             soc_port_phy_timesync_framesync_mode_t *mode)
   3274 {
   3275 
   3276     switch (value & 0xf) {
   3277     case 1U << 0:
   3278         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0;
   3279         break;
   3280     case 1U << 1:
   3281         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1;
   3282         break;
   3283     case 1U << 2:
   3284         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT;
   3285         break;
   3286     case 1U << 3:
   3287         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU;
   3288         break;
   3289     default:
   3290         break;
   3291     }
   3292 
   3293 }
   3294 
   3295 void _phy_54680e_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode,
   3296                                             uint16 *value)
   3297 {
   3298 
   3299     switch (mode) {
   3300     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE:
   3301         *value = 0x0;
   3302         break;
   3303     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME:
   3304         *value = 0x1;
   3305         break;
   3306     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN:
   3307         *value = 0x2;
   3308         break;
   3309     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC:
   3310         *value = 0x3;
   3311         break;
   3312     default:
   3313         break;
   3314     }
   3315 
   3316 }
   3317 
   3318 void _phy_54680e_decode_syncout_mode(uint16 value,
   3319                                             soc_port_phy_timesync_syncout_mode_t *mode)
   3320 {
   3321 
   3322     switch (value & 0x3) {
   3323     case 0x0:
   3324         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   3325         break;
   3326     case 0x1:
   3327         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME;
   3328         break;
   3329     case 0x2:
   3330         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN;
   3331         break;
   3332     case 0x3:
   3333         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC;
   3334         break;
   3335     }
   3336 
   3337 }
   3338 
   3339 
   3340 STATIC int
   3341 phy_54680_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf)
   3342 {
   3343     phy_ctrl_t *pc;
   3344     int offset, rv = SOC_E_NONE;
   3345     uint16 rx_control_reg = 0, tx_control_reg = 0, rx_crc_control_reg = 0,
   3346            en_control_reg = 0, tx_capture_en_reg = 0, rx_capture_en_reg = 0,
   3347            nse_nco_6 = 0, nse_nco_2c = 0, value, mask,
   3348            gmode = 0, framesync_mode = 0, syncout_mode = 0,
   3349            pulse_1_length, pulse_2_length, length_threshold, event_offset;
   3350     uint32 interval;
   3351 
   3352     pc = EXT_PHY_SW_STATE(unit, port);
   3353 
   3354     if ((!(PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc))) || PHY_IS_BCM54880E_A0A1(pc)) {
   3355         return SOC_E_UNAVAIL;
   3356     }
   3357 
   3358     offset = PHY54680_DEV_PHY_SLICE(pc);
   3359 
   3360     do {
   3361         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   3362 
   3363             if (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) {
   3364                 en_control_reg |= ((1U << (offset + 8)) | (1U << offset));
   3365                 nse_nco_6 |= (1U << 12); /* NSE init */
   3366                 SOC_IF_ERROR_BREAK
   3367                     (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FF5,0x15, 1U<<0, 1U<<0), rv); /* exp reg f5 */
   3368             } else {
   3369                 SOC_IF_ERROR_BREAK
   3370                     (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FF5,0x15, 0, 1U<<0), rv); /* exp reg f5 */
   3371             }
   3372 
   3373             /* pc->phy_id =  PHY54680_SLICE_ADDR(pc, 0); */
   3374             pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   3375 
   3376             SOC_IF_ERROR_BREAK
   3377                 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x10, en_control_reg, 
   3378                                            ((1U << (offset + 8)) | (1U << offset))), rv);
   3379 
   3380             SOC_IF_ERROR_BREAK
   3381                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x10, &en_control_reg), rv);
   3382 
   3383             if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) {
   3384                 tx_capture_en_reg |= (1U << offset);
   3385                 rx_capture_en_reg |= (1U << (offset + 8));
   3386             }
   3387 
   3388             SOC_IF_ERROR_BREAK
   3389                 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x12, tx_capture_en_reg, 
   3390                                            (1U << offset)), rv);
   3391 
   3392             SOC_IF_ERROR_BREAK
   3393                 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x13, rx_capture_en_reg, 
   3394                                            (1U << (offset + 8))), rv);
   3395 
   3396             if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) {
   3397                 nse_nco_6 |= (1U << 13);
   3398             }
   3399 
   3400             SOC_IF_ERROR_BREAK
   3401                 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x4f, nse_nco_6, 
   3402                                            (1U << 13)), rv);
   3403 
   3404             if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) {
   3405                 rx_crc_control_reg |= (1U << 3);
   3406             }
   3407 
   3408             SOC_IF_ERROR_BREAK
   3409                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x34, rx_crc_control_reg), rv);
   3410 
   3411             if (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) {
   3412                 rx_control_reg |= (1U << 3);
   3413                 tx_control_reg |= (1U << 3);
   3414             }
   3415 
   3416             if (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) {
   3417                 rx_control_reg |= (1U << 2);
   3418                 tx_control_reg |= (1U << 2);
   3419             }
   3420 
   3421             if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) {
   3422                 rx_control_reg |= (1U << 1);
   3423                 tx_control_reg |= (1U << 1);
   3424             }
   3425 
   3426             if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) {
   3427                 rx_control_reg |= (1U << 0);
   3428                 tx_control_reg |= (1U << 0);
   3429             }
   3430 
   3431             SOC_IF_ERROR_BREAK
   3432                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x32, tx_control_reg), rv);
   3433                                               
   3434             SOC_IF_ERROR_BREAK
   3435                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x33, rx_control_reg), rv);
   3436                                               
   3437             if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) {
   3438                 nse_nco_2c &= (uint16) ~(1U << 14);
   3439             } else {
   3440                 nse_nco_2c |= (1U << 14);
   3441             }
   3442 
   3443             SOC_IF_ERROR_BREAK
   3444                 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x47, nse_nco_2c, 
   3445                                                (1U << 14)), rv);
   3446         }
   3447 
   3448         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   3449             /* VLAN TAG register */
   3450             SOC_IF_ERROR_BREAK
   3451                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x35, conf->itpid), rv);
   3452         }
   3453 
   3454         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   3455             /* OUTER VLAN TAG register */
   3456             SOC_IF_ERROR_BREAK
   3457                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x36, conf->otpid), rv);
   3458         }
   3459 
   3460         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   3461             /* INNER VLAN TAG register */
   3462             SOC_IF_ERROR_BREAK
   3463                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x52, conf->otpid2), rv);
   3464         }
   3465 
   3466         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   3467             SOC_IF_ERROR_BREAK
   3468                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4b, conf->ts_divider & 0xfff), rv);
   3469         }
   3470 
   3471 
   3472         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   3473             pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
   3474             SOC_IF_ERROR_BREAK
   3475                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x6f, conf->rx_link_delay & 0xffff), rv);
   3476             SOC_IF_ERROR_BREAK
   3477                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x70, (conf->rx_link_delay >> 16) & 0xffff), rv);
   3478             pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   3479         }
   3480 
   3481         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   3482             SOC_IF_ERROR_BREAK
   3483                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x25, (uint16)(conf->original_timecode.nanoseconds & 0xffff)), rv);
   3484 
   3485             SOC_IF_ERROR_BREAK
   3486                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x26, (uint16)((conf->original_timecode.nanoseconds >> 16) & 0xffff)), rv);
   3487 
   3488             SOC_IF_ERROR_BREAK
   3489                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x27, (uint16)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff)), rv);
   3490 
   3491             SOC_IF_ERROR_BREAK
   3492                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x28, (uint16)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) & 0xffff)), rv);
   3493 
   3494             SOC_IF_ERROR_BREAK
   3495                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x29, (uint16)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff)), rv);
   3496 
   3497         }
   3498         mask = 0;
   3499 
   3500         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   3501             _phy_54680e_encode_gmode(conf->gmode,&gmode);
   3502             mask |= (0x3 << 14);
   3503         }
   3504 
   3505         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   3506             _phy_54680e_encode_framesync_mode(conf->framesync.mode, &framesync_mode);
   3507             mask |= (0xf << 2) |  (0x1 << 11);
   3508 
   3509             /* Divide by 8 */
   3510             length_threshold = conf->framesync.length_threshold >> 3;
   3511             event_offset = conf->framesync.event_offset >> 3;
   3512 
   3513             SOC_IF_ERROR_BREAK
   3514                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x51, length_threshold), rv);
   3515             SOC_IF_ERROR_BREAK
   3516                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x50, event_offset), rv);
   3517         }
   3518 
   3519         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   3520             _phy_54680e_encode_syncout_mode(conf->syncout.mode, &syncout_mode);
   3521             mask |= (0x3 << 0);
   3522 
   3523             /* Divide by 8 */
   3524             interval = conf->syncout.interval >> 3;
   3525             pulse_1_length = conf->syncout.pulse_1_length >> 3;
   3526             pulse_2_length = conf->syncout.pulse_2_length >> 3;
   3527 
   3528             SOC_IF_ERROR_BREAK
   3529                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x48, interval & 0xffff), rv);
   3530             SOC_IF_ERROR_BREAK
   3531                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x49, 
   3532                     ((pulse_2_length & 0x3) << 14) | ((interval >> 16) & 0x3fff)), rv);
   3533             SOC_IF_ERROR_BREAK
   3534                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4a, 
   3535                     ((pulse_1_length & 0x1ff) << 7) | ((pulse_2_length >> 2) & 0x7f)), rv);
   3536 
   3537             SOC_IF_ERROR_BREAK
   3538                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4e, 
   3539                     (uint16)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xffff)), rv);
   3540             SOC_IF_ERROR_BREAK
   3541                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4d, 
   3542                     (uint16)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff)), rv);
   3543             SOC_IF_ERROR_BREAK
   3544                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4c, 
   3545                     (uint16)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff)), rv);
   3546         }
   3547 
   3548         SOC_IF_ERROR_BREAK
   3549             (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x4f, (gmode << 14) |
   3550                 ((framesync_mode & 0x2) ? (1U << 11) : (1U << 6)) | /* if bits 1 or 2 are set, turn off syncout */
   3551                 (framesync_mode << 2) | (syncout_mode << 0), mask), rv);
   3552 
   3553         /* tx_timestamp_offset */
   3554         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   3555             SOC_IF_ERROR_BREAK
   3556                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x15 + offset, (uint16)(conf->tx_timestamp_offset & 0xffff)), rv);
   3557 
   3558             if (offset < 4 ) {
   3559                 SOC_IF_ERROR_BREAK
   3560                     (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x63, 
   3561                         ((conf->tx_timestamp_offset & 0xf0000) >> ((4 - offset) << 2)), 0xf << (offset << 2)), rv);
   3562             } else {
   3563                 uint16 offset1 = offset - 4;
   3564                 SOC_IF_ERROR_BREAK
   3565                     (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x64, 
   3566                         ((conf->tx_timestamp_offset & 0xf0000) >> ((4 - offset1) << 2)), 0xf << (offset1 << 2)), rv);
   3567             }
   3568         }
   3569 
   3570         /* rx_timestamp_offset */
   3571         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   3572             SOC_IF_ERROR_BREAK
   3573                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x1d + offset, (uint16)(conf->rx_timestamp_offset & 0xffff)), rv);
   3574 
   3575             if (offset < 4 ) {
   3576                 SOC_IF_ERROR_BREAK
   3577                     (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x65, 
   3578                         ((conf->rx_timestamp_offset & 0xf0000) >> ((4 - offset) << 2)), 0xf << (offset << 2)), rv);
   3579             } else {
   3580                 uint16 offset1 = offset - 4;
   3581                 SOC_IF_ERROR_BREAK
   3582                     (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x66, 
   3583                         ((conf->rx_timestamp_offset & 0xf0000) >> ((4 - offset1) << 2)), 0xf << (offset1 << 2)), rv);
   3584             }
   3585         }
   3586 
   3587         value = 0;
   3588         mask = 0;
   3589 
   3590         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   3591             _phy_54680e_encode_egress_message_mode(conf->tx_sync_mode, 0, &value);
   3592             mask |= 0x3 << 0;
   3593         }
   3594 
   3595         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   3596             _phy_54680e_encode_egress_message_mode(conf->tx_delay_request_mode, 2, &value);
   3597             mask |= 0x3 << 2;
   3598         }
   3599 
   3600         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   3601             _phy_54680e_encode_egress_message_mode(conf->tx_pdelay_request_mode, 4, &value);
   3602             mask |= 0x3 << 4;
   3603         }
   3604 
   3605         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   3606             _phy_54680e_encode_egress_message_mode(conf->tx_pdelay_response_mode, 6, &value);
   3607             mask |= 0x3 << 6;
   3608         }
   3609                                                 
   3610         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
   3611 
   3612         SOC_IF_ERROR_BREAK
   3613             (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x11, value, mask), rv); 
   3614 
   3615         value = 0;
   3616         mask = 0;
   3617 
   3618         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   3619             _phy_54680e_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value);
   3620             mask |= 0x3 << 0;
   3621         }
   3622 
   3623         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   3624             _phy_54680e_encode_ingress_message_mode(conf->rx_delay_request_mode, 2, &value);
   3625             mask |= 0x3 << 2;
   3626         }
   3627 
   3628         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   3629             _phy_54680e_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 4, &value);
   3630             mask |= 0x3 << 4;
   3631         }
   3632 
   3633         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   3634             _phy_54680e_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 6, &value);
   3635             mask |= 0x3 << 6;
   3636         }
   3637                                                 
   3638                                                 
   3639         SOC_IF_ERROR_BREAK
   3640             (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x12, value << 8, mask << 8), rv); 
   3641 
   3642         /* pc->phy_id =  PHY54680_SLICE_ADDR(pc, 0); */
   3643         pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   3644 
   3645         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   3646             /* Initial ref phase [15:0] */
   3647             SOC_IF_ERROR_BREAK
   3648                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x38, (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff)), rv);
   3649 
   3650             /* Initial ref phase [31:16]  */
   3651             SOC_IF_ERROR_BREAK
   3652                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x39, (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff)), rv);
   3653 
   3654             /*  Initial ref phase [47:32] */
   3655             SOC_IF_ERROR_BREAK
   3656                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3a, (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff)), rv);
   3657         }
   3658 
   3659         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   3660             /* Ref phase delta [15:0] */
   3661             SOC_IF_ERROR_BREAK
   3662                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3b, (uint16)(conf->phy_1588_dpll_ref_phase_delta & 0xffff)), rv);
   3663 
   3664             /* Ref phase delta [31:16]  */
   3665             SOC_IF_ERROR_BREAK
   3666                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3c, (uint16)((conf->phy_1588_dpll_ref_phase_delta >> 16) & 0xffff)), rv);
   3667         }
   3668 
   3669         /* DPLL K1 & K2 */
   3670         mask = 0;
   3671 
   3672         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   3673             mask |= 0xff << 8;
   3674         }
   3675 
   3676         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   3677             mask |= 0xff;
   3678         }
   3679         SOC_IF_ERROR_BREAK
   3680             (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x3d, (conf->phy_1588_dpll_k1 & 0xff)<<8 | (conf->phy_1588_dpll_k2 & 0xff), mask ), rv);
   3681 
   3682         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   3683             /* DPLL K3 */
   3684             SOC_IF_ERROR_BREAK
   3685                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3e, conf->phy_1588_dpll_k3 & 0xff), rv);
   3686         }
   3687 
   3688 
   3689         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER) {
   3690             /* Initial loop filter[15:0] */
   3691             SOC_IF_ERROR_BREAK
   3692                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3f, (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_loop_filter) & 0xffff)), rv);
   3693 
   3694             /* Initial loop filter[31:16]  */
   3695             SOC_IF_ERROR_BREAK
   3696                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x40, (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_loop_filter) >> 16) & 0xffff)), rv);
   3697 
   3698             /*  Initial loop filter[47:32] */
   3699             SOC_IF_ERROR_BREAK
   3700                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x41, (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_loop_filter) & 0xffff)), rv);
   3701 
   3702             /* Initial loop filter[63:48]  */
   3703             SOC_IF_ERROR_BREAK
   3704                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x42, (uint16)((COMPILER_64_HI(conf->phy_1588_dpll_loop_filter) >> 16) & 0xffff)), rv);
   3705         }
   3706 
   3707     } while(0);
   3708 
   3709     pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
   3710 
   3711     return SOC_E_NONE;
   3712 }
   3713 
   3714 STATIC int
   3715 phy_54680_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf)
   3716 {
   3717     phy_ctrl_t *pc;
   3718     int offset, rv = SOC_E_NONE;
   3719     uint16 tx_control_reg = 0, rx_crc_control_reg = 0,
   3720            en_control_reg = 0, tx_capture_en_reg = 0,
   3721            nse_nco_6 = 0, nse_nco_2c = 0, temp1, temp2, temp3, temp4, value;
   3722     soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   3723     soc_port_phy_timesync_framesync_mode_t framesync_mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE;
   3724     soc_port_phy_timesync_syncout_mode_t syncout_mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   3725 
   3726     pc = EXT_PHY_SW_STATE(unit, port);
   3727 
   3728     if ((!(PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc))) || PHY_IS_BCM54880E_A0A1(pc)) {
   3729         return SOC_E_UNAVAIL;
   3730     }
   3731 
   3732     conf->flags = 0;
   3733 
   3734     offset = PHY54680_DEV_PHY_SLICE(pc);
   3735 
   3736     do {
   3737         /* pc->phy_id =  PHY54680_SLICE_ADDR(pc, 0); */
   3738         pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   3739 
   3740         SOC_IF_ERROR_BREAK
   3741             (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4f, &nse_nco_6), rv);
   3742 
   3743         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   3744             SOC_IF_ERROR_BREAK
   3745                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x10, &en_control_reg), rv); 
   3746 
   3747             if (en_control_reg & (1U << offset)) {
   3748                 conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE;
   3749             }
   3750 
   3751             SOC_IF_ERROR_BREAK
   3752                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x12, &tx_capture_en_reg), rv); 
   3753 
   3754             if (tx_capture_en_reg & (1U << offset)) {
   3755                 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE;
   3756             }
   3757 
   3758             /*
   3759                 SOC_IF_ERROR_BREAK
   3760                     (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4f, &nse_nco_6), rv);
   3761              */
   3762 
   3763             if (nse_nco_6 & (1U << 13)) {
   3764                 conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE;
   3765             }
   3766 
   3767             SOC_IF_ERROR_BREAK
   3768                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x34, &rx_crc_control_reg), rv);
   3769 
   3770             if (rx_crc_control_reg & (1U << 3)) {
   3771                 conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE;
   3772             }
   3773 
   3774             SOC_IF_ERROR_BREAK
   3775                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x32, &tx_control_reg), rv);
   3776                                               
   3777             if (tx_control_reg & (1U << 3)) {
   3778                 conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE;
   3779             }
   3780 
   3781             if (tx_control_reg & (1U << 2)) {
   3782                 conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE;
   3783             }
   3784 
   3785             if (tx_control_reg & (1U << 1)) {
   3786                 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE;
   3787             }
   3788 
   3789             if (tx_control_reg & (1U << 0)) {
   3790                 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE;
   3791             }
   3792 
   3793             SOC_IF_ERROR_BREAK
   3794                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x47, &nse_nco_2c), rv);
   3795 
   3796             if (!(nse_nco_2c & (1U << 14))) {
   3797                 conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT;
   3798             }
   3799         }
   3800 
   3801         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   3802             _phy_54680e_decode_gmode((nse_nco_6  >> 14),&gmode);
   3803             conf->gmode = gmode;
   3804         }
   3805 
   3806         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   3807             _phy_54680e_decode_framesync_mode((nse_nco_6  >> 2), &framesync_mode);
   3808             conf->framesync.mode = framesync_mode;
   3809             SOC_IF_ERROR_BREAK
   3810                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x51, &temp1), rv);
   3811             SOC_IF_ERROR_BREAK
   3812                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x50, &temp2), rv);
   3813 
   3814             /* Multiply by 8 */
   3815             conf->framesync.length_threshold = temp1 << 3;
   3816             conf->framesync.event_offset = temp2 << 3;
   3817         }
   3818 
   3819         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   3820             _phy_54680e_decode_syncout_mode((nse_nco_6  >> 0), &syncout_mode);
   3821             conf->syncout.mode = syncout_mode;
   3822 
   3823             SOC_IF_ERROR_BREAK
   3824                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x48, &temp1), rv);
   3825             SOC_IF_ERROR_BREAK
   3826                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x49, &temp2), rv);
   3827             SOC_IF_ERROR_BREAK
   3828                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4a, &temp3), rv);
   3829 
   3830             /* Multiply by 8 */
   3831             conf->syncout.pulse_1_length = ((temp3 >> 7) & 0x1ff) << 3;
   3832             conf->syncout.pulse_2_length =  (((temp3 & 0x7f) << 2) | ((temp2 >> 14) & 0x3)) << 3;
   3833             conf->syncout.interval =  (((temp2 & 0x3fff) << 16) | temp1) << 3;
   3834 
   3835             SOC_IF_ERROR_BREAK
   3836                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4e, &temp1), rv);
   3837             SOC_IF_ERROR_BREAK
   3838                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4d, &temp2), rv);
   3839             SOC_IF_ERROR_BREAK
   3840                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4c, &temp3), rv);
   3841 
   3842             COMPILER_64_SET(conf->syncout.syncout_ts, ((uint32)temp3),  (((uint32)temp2<<16)|((uint32)temp1)));
   3843         }
   3844 
   3845         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   3846             SOC_IF_ERROR_BREAK
   3847                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x35, &conf->itpid), rv);
   3848         }
   3849 
   3850         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   3851             SOC_IF_ERROR_BREAK
   3852                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x36, &conf->otpid), rv);
   3853         }
   3854 
   3855         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   3856             SOC_IF_ERROR_BREAK
   3857                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x52, &conf->otpid2), rv);
   3858         }
   3859 
   3860         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   3861             SOC_IF_ERROR_BREAK
   3862                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4b, &conf->ts_divider), rv);
   3863         }
   3864 
   3865         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   3866             pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
   3867 
   3868             SOC_IF_ERROR_BREAK
   3869                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x6f, &temp1), rv);
   3870             SOC_IF_ERROR_BREAK
   3871                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x70, &temp2), rv);
   3872 
   3873             conf->rx_link_delay = ((uint32)temp2 << 16) | temp1; 
   3874 
   3875             /* pc->phy_id =  PHY54680_SLICE_ADDR(pc, 0); */
   3876             pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   3877         }
   3878 
   3879 
   3880         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   3881             SOC_IF_ERROR_BREAK
   3882                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x25, &temp1), rv);
   3883 
   3884             SOC_IF_ERROR_BREAK
   3885                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x26, &temp2), rv);
   3886 
   3887             conf->original_timecode.nanoseconds = ((uint32)temp2 << 16) | temp1; 
   3888 
   3889             SOC_IF_ERROR_BREAK
   3890                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x27, &temp1), rv);
   3891 
   3892             SOC_IF_ERROR_BREAK
   3893                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x28, &temp2), rv);
   3894 
   3895             SOC_IF_ERROR_BREAK
   3896                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x29, &temp3), rv);
   3897 
   3898             /* conf->original_timecode.seconds = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */
   3899 
   3900             COMPILER_64_SET(conf->original_timecode.seconds, ((uint32)temp3),  (((uint32)temp2<<16)|((uint32)temp1)));
   3901         }
   3902 
   3903         /* tx_timestamp_offset */
   3904         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   3905             uint32 temp32;
   3906 
   3907             SOC_IF_ERROR_BREAK
   3908                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x15 + offset, &temp1), rv);
   3909             if (offset < 4 ) {
   3910                 SOC_IF_ERROR_BREAK
   3911                     (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x63, &temp2), rv);
   3912                 temp32 = (temp2 & (0xf << (offset << 2))) << ((4 - offset) << 2);
   3913             } else {
   3914                 uint16 offset1 = offset - 4;
   3915                 SOC_IF_ERROR_BREAK
   3916                     (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x64, &temp2), rv);
   3917                 temp32 = (temp2 & (0xf << (offset1 << 2))) << ((4 - offset1) << 2);
   3918             }
   3919             conf->tx_timestamp_offset = temp32 | temp1;
   3920         }
   3921 
   3922         /* rx_timestamp_offset */
   3923         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   3924             uint32 temp32;
   3925 
   3926             SOC_IF_ERROR_BREAK
   3927                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x1d + offset, &temp1), rv);
   3928             if (offset < 4 ) {
   3929                 SOC_IF_ERROR_BREAK
   3930                     (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x65, &temp2), rv);
   3931                 temp32 = (temp2 & (0xf << (offset << 2))) << ((4 - offset) << 2);
   3932             } else {
   3933                 uint16 offset1 = offset - 4;
   3934                 SOC_IF_ERROR_BREAK
   3935                     (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x66, &temp2), rv);
   3936                 temp32 = (temp2 & (0xf << (offset1 << 2))) << ((4 - offset1) << 2);
   3937             }
   3938             conf->rx_timestamp_offset = temp32 | temp1;
   3939         }
   3940 
   3941         pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
   3942 
   3943         SOC_IF_ERROR_BREAK
   3944             (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x11, &value), rv); 
   3945 
   3946         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   3947             _phy_54680e_decode_egress_message_mode(value, 0, &conf->tx_sync_mode);
   3948         }
   3949 
   3950         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   3951             _phy_54680e_decode_egress_message_mode(value, 2, &conf->tx_delay_request_mode);
   3952         }
   3953 
   3954         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   3955             _phy_54680e_decode_egress_message_mode(value, 4, &conf->tx_pdelay_request_mode);
   3956         }
   3957 
   3958         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   3959             _phy_54680e_decode_egress_message_mode(value, 6, &conf->tx_pdelay_response_mode);
   3960         }
   3961 
   3962         SOC_IF_ERROR_BREAK
   3963             (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x12, &value), rv); 
   3964 
   3965         value >>= 8;
   3966 
   3967         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   3968             _phy_54680e_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode);
   3969         }
   3970 
   3971         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   3972             _phy_54680e_decode_ingress_message_mode(value, 2, &conf->rx_delay_request_mode);
   3973         }
   3974 
   3975         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   3976             _phy_54680e_decode_ingress_message_mode(value, 4, &conf->rx_pdelay_request_mode);
   3977         }
   3978 
   3979         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   3980             _phy_54680e_decode_ingress_message_mode(value, 6, &conf->rx_pdelay_response_mode);
   3981         }
   3982 
   3983         /* pc->phy_id =  PHY54680_SLICE_ADDR(pc, 0); */
   3984         pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   3985 
   3986         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   3987             /* Initial ref phase [15:0] */
   3988             SOC_IF_ERROR_BREAK
   3989                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x38, &temp1), rv);
   3990 
   3991             /* Initial ref phase [31:16]  */
   3992             SOC_IF_ERROR_BREAK
   3993                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x39, &temp2), rv);
   3994 
   3995             /*  Initial ref phase [47:32] */
   3996             SOC_IF_ERROR_BREAK
   3997                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3a, &temp3), rv);
   3998 
   3999             COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1)));
   4000         }
   4001 
   4002         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   4003             /* Ref phase delta [15:0] */
   4004             SOC_IF_ERROR_BREAK
   4005                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3b, &temp1), rv);
   4006 
   4007             /* Ref phase delta [31:16]  */
   4008             SOC_IF_ERROR_BREAK
   4009                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3c, &temp2), rv);
   4010 
   4011             conf->phy_1588_dpll_ref_phase_delta = (temp2 << 16) | temp1;
   4012         }
   4013 
   4014         /* DPLL K1 & K2 */
   4015         SOC_IF_ERROR_BREAK
   4016             (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3d, &temp1 ), rv);
   4017 
   4018         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   4019             conf->phy_1588_dpll_k1 = (temp1 >> 8 ) & 0xff;
   4020         }
   4021 
   4022         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   4023             conf->phy_1588_dpll_k2 = temp1 & 0xff;
   4024         }
   4025 
   4026         /* DPLL K3 */
   4027         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   4028             SOC_IF_ERROR_BREAK
   4029                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3e, &temp1), rv);
   4030             conf->phy_1588_dpll_k3 = temp1 & 0xff;
   4031         }
   4032 
   4033         if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER) {
   4034             /* Initial loop filter[15:0] */
   4035             SOC_IF_ERROR_BREAK
   4036                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3f, &temp1), rv);
   4037 
   4038             /* Initial loop filter[31:16]  */
   4039             SOC_IF_ERROR_BREAK
   4040                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x40, &temp2), rv);
   4041 
   4042             /*  Initial loop filter[47:32] */
   4043             SOC_IF_ERROR_BREAK
   4044                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x41, &temp3), rv);
   4045 
   4046             /* Initial loop filter[63:48]  */
   4047             SOC_IF_ERROR_BREAK
   4048                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x42, &temp4), rv);
   4049 
   4050             COMPILER_64_SET(conf->phy_1588_dpll_loop_filter, (((uint32)temp4<<16)|((uint32)temp3)), (((uint32)temp2<<16)|((uint32)temp1)));
   4051         }
   4052     } while(0);
   4053                                             
   4054     pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
   4055   
   4056     return SOC_E_NONE;
   4057 }
   4058 
   4059 STATIC int
   4060 phy_54680_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 value)
   4061 {
   4062     phy_ctrl_t *pc;
   4063     uint16 temp1, temp2;
   4064     uint32 value0;
   4065     int offset, rv = SOC_E_NONE;
   4066 
   4067     pc = EXT_PHY_SW_STATE(unit, port);
   4068 
   4069     if ((!(PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc))) || PHY_IS_BCM54880E_A0A1(pc)) {
   4070         return SOC_E_UNAVAIL;
   4071     }
   4072 
   4073     offset = PHY54680_DEV_PHY_SLICE(pc);
   4074 
   4075     do {
   4076         /* pc->phy_id =  PHY54680_SLICE_ADDR(pc, 0); */
   4077         pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   4078 
   4079         switch (type) {
   4080         case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   4081         case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   4082             return SOC_E_FAIL;
   4083 
   4084         case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   4085             SOC_IF_ERROR_BREAK
   4086                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x44, (uint16)COMPILER_64_LO(value)), rv);
   4087             break;
   4088 
   4089         case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC:
   4090             SOC_IF_ERROR_BREAK
   4091                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4f, &temp1), rv);
   4092             temp2 = ((temp1 | (0x3 << 14) | (0x1 << 12)) & ~(0xf << 2)) | (0x1 << 5);
   4093             SOC_IF_ERROR_BREAK
   4094                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4f, temp2), rv);
   4095             sal_udelay(1);
   4096             temp2 &= ~((0x1 << 5) | (0x1 << 12));
   4097             SOC_IF_ERROR_BREAK
   4098                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4f, temp2), rv);
   4099             sal_udelay(1);
   4100             SOC_IF_ERROR_BREAK
   4101                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4f, temp1), rv);
   4102 
   4103             break;
   4104 
   4105         case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   4106             COMPILER_64_SHR(value, 4);
   4107             SOC_IF_ERROR_BREAK
   4108                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x45, (uint16)(COMPILER_64_LO(value) & 0xffff)), rv);
   4109             SOC_IF_ERROR_BREAK
   4110                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x46, (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff)), rv);
   4111             SOC_IF_ERROR_BREAK
   4112                 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x47, (uint16)(COMPILER_64_HI(value) & 0xfff), 0xfff), rv);
   4113             break;
   4114 
   4115         case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   4116             temp1 = 0;
   4117             temp2 = 0;
   4118 
   4119             value0 = COMPILER_64_LO(value);
   4120 
   4121             if (value0 &  SOC_PORT_PHY_TIMESYNC_TN_LOAD) {
   4122                 temp1 |= 1U << 11;
   4123             }
   4124             if (value0 &  SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) {
   4125                 temp2 |= 1U << 11;
   4126             }
   4127             if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) {
   4128                 temp1 |= 1U << 10;
   4129             }
   4130             if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) {
   4131                 temp2 |= 1U << 10;
   4132             }
   4133             if (value0 &  SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) {
   4134                 temp1 |= 1U << 9;
   4135             }
   4136             if (value0 &  SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) {
   4137                 temp2 |= 1U << 9;
   4138             }
   4139             if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) {
   4140                 temp1 |= 1U << 8;
   4141             }
   4142             if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) {
   4143                 temp2 |= 1U << 8;
   4144             }
   4145             if (value0 &  SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) {
   4146                 temp1 |= 1U << 7;
   4147             }
   4148             if (value0 &  SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) {
   4149                 temp2 |= 1U << 7;
   4150             }
   4151             if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) {
   4152                 temp1 |= 1U << 6;
   4153             }
   4154             if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) {
   4155                 temp2 |= 1U << 6;
   4156             }
   4157             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) {
   4158                 temp1 |= 1U << 5;
   4159             }
   4160             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) {
   4161                 temp2 |= 1U << 5;
   4162             }
   4163             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) {
   4164                 temp1 |= 1U << 4;
   4165             }
   4166             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) {
   4167                 temp2 |= 1U << 4;
   4168             }
   4169             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) {
   4170                 temp1 |= 1U << 3;
   4171             }
   4172             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) {
   4173                 temp2 |= 1U << 3;
   4174             }
   4175             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) {
   4176                 temp1 |= 1U << 2;
   4177             }
   4178             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) {
   4179                 temp2 |= 1U << 2;
   4180             }
   4181             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) {
   4182                 temp1 |= 1U << 1;
   4183             }
   4184             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) {
   4185                 temp2 |= 1U << 1;
   4186             }
   4187             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) {
   4188                 temp1 |= 1U << 0;
   4189             }
   4190             if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) {
   4191                 temp2 |= 1U << 0;
   4192             }
   4193             SOC_IF_ERROR_BREAK
   4194                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x2e, temp1), rv);
   4195             SOC_IF_ERROR_BREAK
   4196                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x2f, temp2), rv);
   4197             break;
   4198 
   4199         case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   4200             temp1 = 0;
   4201 
   4202             value0 = COMPILER_64_LO(value);
   4203 
   4204             if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) {
   4205                 temp1 |= 1U << 1;
   4206             }
   4207             if (value0 &  SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) {
   4208                 temp1 |= 1U << 0;
   4209             }
   4210             SOC_IF_ERROR_BREAK
   4211                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x30, temp1), rv);
   4212             break;
   4213 
   4214         case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   4215             value0 = COMPILER_64_LO(value);
   4216 
   4217             /* tx_timestamp_offset */
   4218             SOC_IF_ERROR_BREAK
   4219                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x15 + offset, (uint16)(value0 & 0xffff)), rv);
   4220 
   4221             if (offset < 4 ) {
   4222                 SOC_IF_ERROR_BREAK
   4223                     (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x63, 
   4224                         ((value0 & 0xf0000) >> ((4 - offset) << 2)), 0xf << (offset << 2)), rv);
   4225             } else {
   4226                 uint16 offset1 = offset - 4;
   4227                 SOC_IF_ERROR_BREAK
   4228                     (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x64, 
   4229                         ((value0 & 0xf0000) >> ((4 - offset1) << 2)), 0xf << (offset1 << 2)), rv);
   4230             }
   4231             break;
   4232 
   4233         case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   4234             value0 = COMPILER_64_LO(value);
   4235 
   4236             /* rx_timestamp_offset */
   4237             SOC_IF_ERROR_BREAK
   4238                 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x1d + offset, (uint16)(value0 & 0xffff)), rv);
   4239 
   4240             if (offset < 4 ) {
   4241                 SOC_IF_ERROR_BREAK
   4242                     (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x65, 
   4243                         ((value0 & 0xf0000) >> ((4 - offset) << 2)), 0xf << (offset << 2)), rv);
   4244             } else {
   4245                 uint16 offset1 = offset - 4;
   4246                 SOC_IF_ERROR_BREAK
   4247                     (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x66, 
   4248                         ((value0 & 0xf0000) >> ((4 - offset1) << 2)), 0xf << (offset1 << 2)), rv);
   4249             }
   4250             break;
   4251 
   4252 
   4253         default:
   4254             pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
   4255             return SOC_E_FAIL;
   4256         }
   4257     } while(0);
   4258 
   4259     pc->phy_id =  PHY54680_DEV_PHY_ID_ORIG(pc);
   4260 
   4261     return SOC_E_NONE;
   4262 }
   4263 
   4264 STATIC int
   4265 phy_54680_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 *value)
   4266 {
   4267     phy_ctrl_t *pc;
   4268     uint16 value0;
   4269     uint16 value1;
   4270     uint16 value2;
   4271     uint32 temp32;
   4272     int offset, rv = SOC_E_NONE;
   4273 
   4274     pc = EXT_PHY_SW_STATE(unit, port);
   4275 
   4276     if ((!(PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc))) || PHY_IS_BCM54880E_A0A1(pc)) {
   4277         return SOC_E_UNAVAIL;
   4278     }
   4279 
   4280     offset = PHY54680_DEV_PHY_SLICE(pc);
   4281 
   4282     do {
   4283         /* pc->phy_id =  PHY54680_SLICE_ADDR(pc, 0); */
   4284         pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   4285 
   4286         switch (type) {
   4287         case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   4288             SOC_IF_ERROR_BREAK
   4289                 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x1), rv);
   4290 
   4291             SOC_IF_ERROR_BREAK
   4292                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x56, &value0), rv);
   4293             SOC_IF_ERROR_BREAK
   4294                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x57, &value1), rv);
   4295             SOC_IF_ERROR_BREAK
   4296                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x58, &value2), rv);
   4297 
   4298             SOC_IF_ERROR_BREAK
   4299                 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x2), rv);
   4300             SOC_IF_ERROR_BREAK
   4301                 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x0), rv);
   4302 
   4303             COMPILER_64_SET((*value), ((uint32)value2),  (((uint32)value1<<16)|((uint32)value0)));
   4304 
   4305         /*    *value =  (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */
   4306             break;
   4307 
   4308         case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   4309             SOC_IF_ERROR_BREAK
   4310                 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x4), rv);
   4311 
   4312             SOC_IF_ERROR_BREAK
   4313                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x53, &value0), rv);
   4314             SOC_IF_ERROR_BREAK
   4315                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x54, &value1), rv);
   4316             SOC_IF_ERROR_BREAK
   4317                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x55, &value2), rv);
   4318 
   4319             SOC_IF_ERROR_BREAK
   4320                 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x8), rv);
   4321             SOC_IF_ERROR_BREAK
   4322                 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x0), rv);
   4323 
   4324             COMPILER_64_SET((*value), ((uint32)value2),  (((uint32)value1<<16)|((uint32)value0)));
   4325 
   4326         /*   *value = (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */
   4327             break;
   4328 
   4329         case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   4330             SOC_IF_ERROR_BREAK
   4331                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x44, &value0), rv);
   4332             /* *value = value0; */
   4333             COMPILER_64_SET((*value), 0,  (uint32)value0);
   4334             break;
   4335 
   4336         case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   4337             SOC_IF_ERROR_BREAK
   4338                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x45, &value0), rv);
   4339             SOC_IF_ERROR_BREAK
   4340                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x46, &value1), rv);
   4341             SOC_IF_ERROR_BREAK
   4342                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x47, &value2), rv);
   4343 
   4344             COMPILER_64_SET((*value), (value2 & 0x0fff), ((uint32)value1 << 16) | value0 );
   4345             COMPILER_64_SHL((*value), 4);
   4346             break;
   4347 
   4348 
   4349         case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   4350             SOC_IF_ERROR_BREAK
   4351                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x2e, &value1), rv);
   4352             SOC_IF_ERROR_BREAK
   4353                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x2f, &value2), rv);
   4354             value0 = 0;
   4355             if (value1 & (1U << 11)) {
   4356                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_TN_LOAD;
   4357             }
   4358             if (value2 & (1U << 11)) {
   4359                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD;
   4360             }
   4361             if (value1 & (1U << 10)) {
   4362                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD;
   4363             }
   4364             if (value2 & (1U << 10)) {
   4365                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD;
   4366             }
   4367             if (value1 & (1U << 9)) {
   4368                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD;
   4369             }
   4370             if (value2 & (1U << 9)) {
   4371                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD;
   4372             }
   4373             if (value1 & (1U << 8)) {
   4374                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD;
   4375             }
   4376             if (value1 & (1U << 8)) {
   4377                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD;
   4378             }
   4379             if (value1 & (1U << 7)) {
   4380                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD;
   4381             }
   4382             if (value1 & (1U << 7)) {
   4383                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD;
   4384             }
   4385             if (value1 & (1U << 6)) {
   4386                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD;
   4387             }
   4388             if (value2 & (1U << 6)) {
   4389                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD;
   4390             }
   4391             if (value1 & (1U << 5)) {
   4392                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD;
   4393             }
   4394             if (value2 & (1U << 5)) {
   4395                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD;
   4396             }
   4397             if (value1 & (1U << 4)) {
   4398                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD;
   4399             }
   4400             if (value2 & (1U << 4)) {
   4401                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD;
   4402             }
   4403             if (value1 & (1U << 3)) {
   4404                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD;
   4405             }
   4406             if (value2 & (1U << 3)) {
   4407                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD;
   4408             }
   4409             if (value1 & (1U << 2)) {
   4410                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD;
   4411             }
   4412             if (value2 & (1U << 2)) {
   4413                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD;
   4414             }
   4415             if (value1 & (1U << 1)) {
   4416                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD;
   4417             }
   4418             if (value2 & (1U << 1)) {
   4419                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD;
   4420             }
   4421             if (value1 & (1U << 0)) {
   4422                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD;
   4423             }
   4424             if (value2 & (1U << 0)) {
   4425                 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD;
   4426             }
   4427             COMPILER_64_SET((*value), 0, (uint32)value0);
   4428             break;
   4429 
   4430         case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT:
   4431             SOC_IF_ERROR_BREAK
   4432                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x31, &value1), rv);
   4433             value0 = 0;
   4434             if (value1 & (1U << 1)) {
   4435                 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT;
   4436             }
   4437             if (value1 & (1U << 0)) {
   4438                 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT;
   4439             }
   4440             COMPILER_64_SET((*value), 0, (uint32)value0);
   4441             break;
   4442 
   4443         case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   4444             SOC_IF_ERROR_BREAK
   4445                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x30, &value1), rv);
   4446             value0 = 0;
   4447             if (value1 & (1U << 1)) {
   4448                 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK;
   4449             }
   4450             if (value1 & (1U << 0)) {
   4451                 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK;
   4452             }
   4453             COMPILER_64_SET((*value), 0, (uint32)value0);
   4454             break;
   4455 
   4456 
   4457         case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   4458         /* tx_timestamp_offset */
   4459             SOC_IF_ERROR_BREAK
   4460                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x15 + offset, &value1), rv);
   4461             if (offset < 4 ) {
   4462                 SOC_IF_ERROR_BREAK
   4463                     (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x63, &value2), rv);
   4464                 temp32 = (value2 & (0xf << (offset << 2))) << ((4 - offset) << 2);
   4465             } else {
   4466                 uint16 offset1 = offset - 4;
   4467                 SOC_IF_ERROR_BREAK
   4468                     (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x64, &value2), rv);
   4469                 temp32 = (value2 & (0xf << (offset1 << 2))) << ((4 - offset1) << 2);
   4470             }
   4471             /* *value = temp32 | value1; */
   4472             COMPILER_64_SET((*value), 0, (uint32)(temp32 | value1));
   4473             break;
   4474 
   4475         case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   4476         /* rx_timestamp_offset */
   4477             SOC_IF_ERROR_BREAK
   4478                 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x1d + offset, &value1), rv);
   4479             if (offset < 4 ) {
   4480                 SOC_IF_ERROR_BREAK
   4481                     (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x65, &value2), rv);
   4482                 temp32 = (value2 & (0xf << (offset << 2))) << ((4 - offset) << 2);
   4483             } else {
   4484                 uint16 offset1 = offset - 4;
   4485                 SOC_IF_ERROR_BREAK
   4486                     (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x66, &value2), rv);
   4487                 temp32 = (value2 & (0xf << (offset1 << 2))) << ((4 - offset1) << 2);
   4488             }
   4489             /* *value = temp32 | value1; */
   4490             COMPILER_64_SET((*value), 0, (uint32)(temp32 | value1));
   4491             break;
   4492 
   4493         default:
   4494             pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   4495             return SOC_E_FAIL;
   4496         }
   4497     } while(0);
   4498 
   4499     pc->phy_id =  PHY54680_DEV_PHY_ID_BASE(pc);
   4500 
   4501     return SOC_E_NONE;
   4502 }
   4503 
   4504 /*
   4505  * Variable:    phy_54680drv_ge
   4506  * Purpose:     PHY driver for 54680
   4507  */
   4508 
   4509 phy_driver_t phy_54680drv_ge = {
   4510     "54680 Gigabit PHY Driver",
   4511     phy_54680_init,
   4512     phy_fe_ge_reset,
   4513     phy_54680_link_get,
   4514     phy_54680_enable_set,
   4515     phy_54680_enable_get,
   4516     phy_54680_duplex_set,
   4517     phy_54680_duplex_get,
   4518     phy_54680_speed_set,
   4519     phy_54680_speed_get,
   4520     phy_54680_master_set,
   4521     phy_54680_master_get,
   4522     phy_54680_autoneg_set,
   4523     phy_54680_autoneg_get,
   4524     NULL,
   4525     NULL,
   4526     NULL,
   4527     phy_54680_lb_set,
   4528     phy_54680_lb_get,
   4529     phy_54680_interface_set,
   4530     phy_54680_interface_get,
   4531     NULL,                       /* Deprecated */
   4532     phy_54680_link_up,          /* Link up event */
   4533     phy_54680_link_down,
   4534     phy_54680_mdix_set,
   4535     phy_54680_mdix_get,
   4536     phy_54680_mdix_status_get,
   4537     phy_54680_medium_config_set,
   4538     phy_54680_medium_config_get,
   4539     phy_54680_medium_status,
   4540     phy54680_cable_diag_dispatch,
   4541     NULL,                        /* phy_link_change */
   4542     phy_54680_control_set,       /* phy_control_set */ 
   4543     phy_54680_control_get,       /* phy_control_get */
   4544     phy_ge_reg_read,
   4545     phy_ge_reg_write,
   4546     phy_ge_reg_modify,
   4547     NULL,                        /* Phy notify event */    
   4548     phy_54680_probe,             /* pd_probe  */
   4549     phy_54680_ability_advert_set,/* pd_ability_advert_set */
   4550     phy_54680_ability_advert_get,/* pd_ability_advert_get */
   4551     phy_54680_ability_remote_get,/* pd_ability_remote_get */
   4552     phy_54680_ability_local_get, /* pd_ability_local_get  */
   4553     NULL,                        /* pd_firmware_set */    
   4554     phy_54680_timesync_config_set,
   4555     phy_54680_timesync_config_get,
   4556     phy_54680_timesync_control_set,
   4557     phy_54680_timesync_control_get
   4558 };
   4559 
   4560 #else /* INCLUDE_PHY_54680_ESW */
   4561 int _phy_54680_not_empty;
   4562 #endif /* INCLUDE_PHY_54680_ESW */
   4563