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

phy_egphy28.c (132623B)


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