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

phy84728.c (201663B)


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * File:        phy84728.c
      9  * Purpose:     SDK PHY driver for BCM84728
     10  *
     11  * Supported BCM84XXX Family of PHY devices:
     12  *
     13  *      Device  Ports   Media                           MAC Interface
     14  *      84707    1       1 10G SFP+                     XAUI
     15  *      84073    2       2 KR                           XAUI
     16  *      84074    4       4 KR                           XAUI
     17  *      84728    2       2 10G SFP+/WAN                 XAUI
     18  *      84748    4       4 10G SFP+/WAN                 XAUI
     19  *   84727/84722 2       2 10G SFP+                     XAUI
     20  *   84747/84742 4       4 10G SFP+                     XAUI
     21  *      84762    2       2 10G SFP+                     RXAUI
     22  *      84764    4       4 10G SFP+                     RXAUI
     23  *      84042    2       2 KR                           RXAUI
     24  *      84044    4       4 KR                           RXAUI
     25  *
     26  * Workarounds:
     27  *
     28  * References:
     29  *     
     30  * Notes:
     31  */ 
     32 
     33 
     34 #include <sal/types.h>
     35 #include <sal/core/spl.h>
     36 #include <shared/bsl.h>
     37 #include <soc/drv.h>
     38 #include <soc/debug.h>
     39 #include <soc/error.h>
     40 #include <soc/phyreg.h>
     41 
     42 #include <soc/phy.h>
     43 #include <soc/phy/phyctrl.h>
     44 #include <soc/phy/drv.h>
     45 
     46 #include "phydefs.h"      /* Must include before other phy related includes */
     47 
     48 
     49 
     50 #if defined(INCLUDE_PHY_84728)
     51 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     52 #include "phyident.h"
     53 #include "phyreg.h"
     54 #include "phynull.h"
     55 #include "phyfege.h"
     56 #include "phyxehg.h"
     57 
     58 #include "phy84728_int.h"
     59 #include "phy84728.h"
     60 
     61 #define LAN_MODE 0 
     62 #define WAN_MODE 1
     63 STATIC int
     64 _phy_84728_mode_set(int unit, soc_port_t port, uint32 mode);
     65 
     66 
     67 #define ADVERT_ALL_COPPER \
     68         (SOC_PA_PAUSE | SOC_PA_SPEED_10MB | \
     69          SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB)
     70 
     71 #define ADVERT_ALL_FIBER \
     72         (SOC_PA_PAUSE | SOC_PA_SPEED_1000MB) 
     73 
     74 #define ADVERT_ALL_10GFIBER \
     75         (SOC_PA_PAUSE | SOC_PA_SPEED_10GB) 
     76 
     77 #define WRITE_PHY84728_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \
     78 WRITE_PHY_REG((_unit), (_phy_ctrl), \
     79 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val))
     80 
     81 #define MODIFY_PHY84728_PMA_PMD_REG(_unit, _phy_ctrl, _reg, _val, _mask) \
     82 MODIFY_PHY_REG((_unit), (_phy_ctrl), \
     83 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val), (_mask))
     84 
     85 
     86 #define PHY84728_REG_READ(_unit, _phy_ctrl, _addr, _val) \
     87             READ_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val))
     88 
     89 #define READ_PHY84728_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \
     90             PHY84728_REG_READ((_unit), (_phy_ctrl), \
     91               SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val))
     92 
     93 #define NXT_PC(pc) ((phy_ctrl_t *)((pc)->driver_data))
     94 #define PHYDRV_CALL_NOARG(pc,name) \
     95      do { \
     96         if (pc->driver_data) { \
     97             int rv; \
     98             phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \
     99             EXT_PHY_SW_STATE(pc->unit,pc->port) = (phy_ctrl_t *)(pc->driver_data); \
    100             rv = name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port); \
    101             EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \
    102             if (SOC_FAILURE(rv)) { \
    103                 return rv; \
    104             } \
    105        } \
    106     } while(0)
    107 
    108 #define PHYDRV_CALL_ARG1(pc,name,arg0) \
    109     do { \
    110        if (pc->driver_data) { \
    111            int rv; \
    112            phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \
    113            EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \
    114            rv = name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit, \
    115                 (pc)->port,arg0); \
    116            EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \
    117            if (SOC_FAILURE(rv)) { \
    118                return rv; \
    119            } \
    120        } \
    121     } while(0)
    122 
    123 #define PHYDRV_CALL_ARG2(pc,name,arg0,arg1) \
    124     do { \
    125        if (pc->driver_data) { \
    126            int rv; \
    127            phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \
    128            EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \
    129            rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \
    130                         arg1); \
    131            EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \
    132            if (SOC_FAILURE(rv)) { \
    133                return rv; \
    134            } \
    135        } \
    136     } while(0)
    137 
    138 #define PHYDRV_CALL_ARG3(pc,name,arg0,arg1,arg2) \
    139     do { \
    140        if (pc->driver_data) { \
    141            int rv; \
    142            phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \
    143            EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \
    144            rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \
    145                         arg1,arg2); \
    146            EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \
    147            if (SOC_FAILURE(rv)) { \
    148                return rv; \
    149            } \
    150        } \
    151     } while(0)
    152 
    153 #define BSDK_PHY84728_LINE_MAC_PORT(p)    (p)
    154 #define BSDK_PHY84728_SWITCH_MAC_PORT(p)  ((p) + 1)
    155 #define PHY84728_PDET_MASK   (1 << 0)
    156 
    157 /*
    158  * PHY Map structure for mapping mac drivers
    159  */
    160 typedef struct phy84728_map_s {
    161     bsdk_phy84728_intf_t line_mode;     /* configured line mode */
    162     uint32 phy_sys_xaui_tx_lane_map;
    163     uint32 phy_sys_xaui_rx_lane_map;
    164     uint32 devid;
    165     uint32 reverse_mode;
    166     uint32 link_down;
    167 
    168 }phy84728_map_t;
    169 
    170 #define PHY84728_MAP(_pc) ((phy84728_map_t *)((_pc) + 1))
    171 #define REVERSE_MODE(_pc) ((PHY84728_MAP(_pc))->reverse_mode)
    172 
    173 #define BSDK_PHY84728_IS_KR_VARIANT(devid) \
    174 (  (devid) == 0x84073  ||\
    175    (devid) == 0x84074  ||\
    176    (devid) == 0x84042  ||\
    177    (devid) == 0x84044  )
    178 
    179 #define BSDK_PHY84728_IS_84728(devid) \
    180 (   (devid) == 0x84728  )
    181 
    182 #define PHY_84727_EDC_MODE_MASK     0xff
    183 
    184 /* OUI from ID0 and ID1 registers contents */
    185 #define BSDK_PHY84728_PHY_OUI(id0, id1)                          \
    186     bsdk_phy84728_bit_rev_by_byte_word32((uint32)(id0) << 6 | \
    187                                            ((id1) >> 10 & 0x3f))
    188 
    189 /* PHY model from ID0 and ID1 register Contents */
    190 #define BSDK_PHY84728_PHY_MODEL(id0, id1) ((id1) >> 4 & 0x3f)
    191 
    192 /* PHY revision from ID0 and ID1 register Contents */
    193 #define BSDK_PHY84728_PHY_REV(id0, id1)   ((id1) & 0xf)
    194 
    195 /*
    196  * Function:     
    197  *    bsdk_bit_rev_by_byte_word32
    198  * Purpose:    
    199  *    Reverse the bits in each byte of a 32 bit long 
    200  * Parameters:
    201  *    n - 32bit input
    202  * Notes: 
    203  */
    204 STATIC uint32
    205 bsdk_phy84728_bit_rev_by_byte_word32(uint32 n)
    206 {
    207     n = (((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1));
    208     n = (((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2));
    209     n = (((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4));
    210     return n;
    211 }
    212 
    213 STATIC int phy_84728_init(int unit, soc_port_t port);
    214 STATIC int phy_84728_link_get(int unit, soc_port_t port, int *link);
    215 STATIC int phy_84728_enable_set(int unit, soc_port_t port, int enable);
    216 STATIC int phy_84728_duplex_set(int unit, soc_port_t port, int duplex);
    217 STATIC int phy_84728_duplex_get(int unit, soc_port_t port, int *duplex);
    218 STATIC int phy_84728_speed_set(int unit, soc_port_t port, int speed);
    219 STATIC int phy_84728_speed_get(int unit, soc_port_t port, int *speed);
    220 STATIC int phy_84728_master_set(int unit, soc_port_t port, int master);
    221 STATIC int phy_84728_master_get(int unit, soc_port_t port, int *master);
    222 STATIC int phy_84728_an_set(int unit, soc_port_t port, int autoneg);
    223 STATIC int phy_84728_an_get(int unit, soc_port_t port,
    224                                 int *autoneg, int *autoneg_done);
    225 STATIC int phy_84728_lb_set(int unit, soc_port_t port, int enable);
    226 STATIC int phy_84728_lb_get(int unit, soc_port_t port, int *enable);
    227 STATIC int phy_84728_medium_config_set(int unit, soc_port_t port, 
    228                                       soc_port_medium_t  medium,
    229                                       soc_phy_config_t  *cfg);
    230 STATIC int phy_84728_medium_config_get(int unit, soc_port_t port, 
    231                                       soc_port_medium_t medium,
    232                                       soc_phy_config_t *cfg);
    233 STATIC int phy_84728_ability_advert_set(int unit, soc_port_t port, 
    234                                        soc_port_ability_t *ability);
    235 STATIC int phy_84728_ability_advert_get(int unit, soc_port_t port,
    236                                        soc_port_ability_t *ability);
    237 STATIC int phy_84728_ability_remote_get(int unit, soc_port_t port,
    238                                        soc_port_ability_t *ability);
    239 STATIC int phy_84728_ability_local_get(int unit, soc_port_t port, 
    240                                 soc_port_ability_t *ability);
    241 STATIC int phy_84728_firmware_set(int unit, int port, int offset, 
    242                                  uint8 *data, int len);
    243 STATIC int phy_84728_control_set(int unit, soc_port_t port,
    244                      soc_phy_control_t type, uint32 value);
    245 STATIC int phy_84728_control_get(int unit, soc_port_t port,
    246                      soc_phy_control_t type, uint32 *value);
    247 STATIC int phy_84728_link_up(int unit, soc_port_t port);
    248 STATIC int bsdk_phy84728_line_mode_set(phy_ctrl_t *pc, int dev_port,
    249                      bsdk_phy84728_intf_t mode);
    250 STATIC int bsdk_phy84728_sys_mode_set(phy_ctrl_t *pc, int dev_port, 
    251                      bsdk_phy84728_intf_t mode);
    252 
    253 STATIC int
    254 _bsdk_phy84728_system_sgmii_duplex_set(phy_ctrl_t *pc, int dev_port, int duplex);
    255 STATIC int
    256 _bsdk_phy84728_system_sgmii_sync(phy_ctrl_t *pc, int dev_port);
    257 
    258 extern uint8 bcm84728_fw[];
    259 extern uint32 bcm84728_fw_length;
    260 extern uint8 bcm84748_fw[];
    261 extern uint32 bcm84748_fw_length;
    262 
    263 #define NEW_NAME_ARRAY_SIZE 25
    264 STATIC int
    265 _phy_84728_nxt_dev_probe(int unit, soc_port_t port)
    266 {
    267     phy_ctrl_t  *pc;
    268     phy_ctrl_t phy_ctrl;
    269     soc_phy_info_t phy_info;
    270     extern int _ext_phy_probe(int unit, soc_port_t port,soc_phy_info_t *pi, 
    271                               phy_ctrl_t *ext_pc);
    272     soc_phy_info_t *pi;
    273     int offset = 0;
    274     char new_name[NEW_NAME_ARRAY_SIZE];
    275 
    276     pc = EXT_PHY_SW_STATE(unit, port);
    277 
    278     /* initialize the phy_ctrl for the next device connected to the XFI port */
    279     sal_memset(&phy_ctrl, 0, sizeof(phy_ctrl_t));
    280     phy_ctrl.unit = unit;
    281     phy_ctrl.port = port;
    282     phy_ctrl.speed_max = pc->speed_max;
    283     phy_ctrl.read = pc->read;    /* use same MDIO read routine as this device's */
    284     phy_ctrl.write = pc->write;  /* use same MDIO write routine as this device's */ 
    285 
    286     /* get the mdio address of the next device */
    287     phy_ctrl.phy_id = soc_property_port_get(unit, port,
    288                                      spn_PORT_PHY_ADDR1, 0xff);
    289 
    290     if (phy_ctrl.phy_id == 0xff) {
    291         return SOC_E_NOT_FOUND;
    292     }
    293 
    294     /* probe the next device at the given address */
    295     SOC_IF_ERROR_RETURN
    296         (_ext_phy_probe(unit, port, &phy_info, &phy_ctrl));
    297 
    298     /* If we have probed 84728/84764 then we won't allow 
    299      * to chain (physically its not possible) another of the same type.
    300      * The Probe depends on spn_PORT_PHY_ADDR1 to probe 2nd level PHYs.
    301      * It could so happen that 84728/84764 could be chained with 8481.
    302      * In such cases probing could end up in a loop.
    303      */
    304     if ((phy_ctrl.pd == NULL) || ((phy_ctrl.phy_model == pc->phy_model) && 
    305                                   (phy_ctrl.phy_oui == pc->phy_oui))) {
    306         pc->driver_data = NULL;
    307         /* device not found */
    308         return SOC_E_NOT_FOUND;
    309     }
    310 
    311     LOG_INFO(BSL_LS_SOC_PHY,
    312              (BSL_META_U(unit,
    313                          "_phy_84728_nxt_dev_probe: found phy device"
    314                          " u=%d p=%d id0=0x%x id1=0x%x\n"), 
    315               unit, port,phy_ctrl.phy_id0,phy_ctrl.phy_id1));
    316 
    317     /* set the chained flag */
    318     PHY_FLAGS_SET(phy_ctrl.unit, phy_ctrl.port, PHY_FLAGS_CHAINED);
    319 
    320     /* Found device, allocate control structure */
    321     pc->driver_data = (void *)sal_alloc (sizeof (phy_ctrl_t) + phy_ctrl.size, phy_ctrl.pd->drv_name);
    322     if (pc->driver_data == NULL) {
    323         return SOC_E_MEMORY;
    324     }
    325     sal_memcpy(pc->driver_data, &phy_ctrl, sizeof(phy_ctrl_t));
    326 
    327     /* We need to append the (chanined) PHY's name to the parent */
    328     pi = &SOC_PHY_INFO(unit, pc->port);
    329     offset = sal_strlen(pi->phy_name);
    330     /* size of new_name is 25 which is large enough */
    331     /* coverity[secure_coding] */
    332     sal_strcpy(new_name, (pi->phy_name));
    333     /* coverity[secure_coding] */
    334     sal_strcpy(new_name+offset, "->");
    335     offset = sal_strlen(new_name);
    336     if ((offset + sal_strlen(phy_info.phy_name)) < NEW_NAME_ARRAY_SIZE) {
    337         /* coverity[secure_coding] */
    338         sal_strcpy(new_name + offset, phy_info.phy_name);
    339     } else {
    340         return SOC_E_MEMORY;
    341     }
    342     pi->phy_name = sal_strdup(new_name);
    343 
    344     return SOC_E_NONE;
    345 }
    346 #if defined(NEW_NAME_ARRAY_SIZE)
    347     #undef NEW_NAME_ARRAY_SIZE
    348 #endif
    349 
    350 
    351 /*
    352  * Function:
    353  *      _phy_84728_medium_config_update
    354  * Purpose:
    355  *      Update the PHY with config parameters
    356  * Parameters:
    357  *      unit - StrataSwitch unit #.
    358  *      port - StrataSwitch port #.
    359  *      cfg - Config structure.
    360  * Returns:
    361  *      SOC_E_XXX
    362  */
    363 
    364 STATIC int
    365 _phy_84728_medium_config_update(int unit, soc_port_t port,
    366                                 soc_phy_config_t *cfg)
    367 {
    368 
    369     SOC_IF_ERROR_RETURN
    370         (phy_84728_speed_set(unit, port, cfg->force_speed));
    371     SOC_IF_ERROR_RETURN
    372         (phy_84728_duplex_set(unit, port, cfg->force_duplex));
    373     SOC_IF_ERROR_RETURN
    374         (phy_84728_ability_advert_set(unit, port, &cfg->advert_ability));
    375     SOC_IF_ERROR_RETURN
    376         (phy_84728_an_set(unit, port, cfg->autoneg_enable));
    377 
    378     return SOC_E_NONE;
    379 }
    380 
    381 /*
    382 * Squelch enable/disable
    383 * 1) 10G XAUI output squelching enable: 1.C842.12=1 AND 1.C842.11=0;
    384 * 2) 1G XAUI output squelching enable: 1.C842.10=1
    385 */
    386 STATIC int
    387 _phy_84728_squelch_enable(int unit, soc_port_t port, int enable)
    388 {
    389     phy_ctrl_t *pc;
    390     uint16 data16, mask16;
    391     int speed;
    392 
    393     pc = EXT_PHY_SW_STATE(unit, port);
    394 
    395     if (REVERSE_MODE(pc)) {
    396         /* not squelch support in reverse mode - do nothing */
    397         return SOC_E_NONE;
    398     }
    399 
    400     SOC_IF_ERROR_RETURN
    401         (phy_84728_speed_get(unit, port, &speed));
    402 
    403     if (speed == 10000) {
    404         mask16 = (1<<12);
    405         data16 = enable ? mask16 : 0;
    406         mask16 = ((1<<12) | (1<<11));
    407         SOC_IF_ERROR_RETURN
    408             (MODIFY_PHY84728_PMA_PMD_REG(unit, pc, 0xC842, data16, mask16));
    409     } else {
    410         mask16 = (1<<10);
    411         data16 = enable ? mask16 : 0;
    412         SOC_IF_ERROR_RETURN
    413             (MODIFY_PHY84728_PMA_PMD_REG(unit, pc, 0xC842, data16, mask16));
    414     }
    415 
    416     return SOC_E_NONE;
    417 }
    418 
    419 /* Function:
    420  *    phy_84728_init
    421  * Purpose:    
    422  *    Initialize 84728 phys
    423  * Parameters:
    424  *    unit - StrataSwitch unit #.
    425  *    port - StrataSwitch port #. 
    426  * Returns:    
    427  *    SOC_E_NONE
    428  */
    429 
    430 STATIC int
    431 phy_84728_init(int unit, soc_port_t port)
    432 {
    433     int         wan_mode;
    434     phy_ctrl_t *pc;
    435     int line_mode;
    436     int fiber_preferred;
    437     int phy_ext_rom_boot;
    438     int rv;
    439     char           *str;
    440     /*
    441     _phy84728_event_callback_data_t *tmp;
    442     */
    443     /*uint16          ctrl, tmp2;*/
    444     uint16 temp;
    445     uint16 devid;
    446     uint16 mask16;
    447     uint16 data16;
    448     phy_ctrl_t *int_pc;
    449 
    450     pc     = EXT_PHY_SW_STATE(unit, port);
    451 
    452     sal_memset(PHY84728_MAP(pc), 0, sizeof(phy84728_map_t));
    453 
    454     PHY84728_MAP(pc)->link_down = 1;
    455 
    456     if (READ_PHY84728_PMA_PMD_REG(unit, pc, 0xc802, &devid) < 0) {
    457         return SOC_E_FAIL;
    458     }
    459 
    460     PHY84728_MAP(pc)->devid = devid;
    461 
    462     if (READ_PHY84728_PMA_PMD_REG(unit, pc, 0xc803, &devid) < 0) {
    463         return SOC_E_FAIL;
    464     }
    465 
    466     PHY84728_MAP(pc)->devid |= ((devid & 0xf) << 16) ;
    467 
    468     if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) {
    469         phy_ext_rom_boot = soc_property_port_get(unit, port,
    470                                                  spn_PHY_EXT_ROM_BOOT, 1);
    471         if (!phy_ext_rom_boot) {
    472             pc->flags |= PHYCTRL_MDIO_BCST;
    473             pc->dev_name = "BCM84728";
    474         }
    475         /* indicate second pass of init is needed */
    476         PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2);
    477         return SOC_E_NONE;
    478     }
    479 
    480     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) ||
    481         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
    482   
    483         LOG_INFO(BSL_LS_SOC_PHY,
    484                  (BSL_META_U(unit,
    485                              "phy_84728_init: u=%d p=%d\n"),unit, port));
    486 
    487         REVERSE_MODE(pc) = soc_property_port_suffix_num_get(unit, port, 84728,
    488                                        spn_PORT_PHY_MODE_REVERSE, "phy", 0);
    489 
    490 
    491         /* Preferred mode:
    492          * phy_fiber_pref = 1 ; Port is in SFI mode in 10G Default
    493          *                      when speed is changed to 1G, its 1000X
    494          * phy_fiber_pref = 0; Port is in SGMII mode, allows only 1G/100M/10M
    495          */
    496         fiber_preferred =
    497             soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 1);
    498         
    499         /* Initially configure for the preferred medium. */
    500         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
    501         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
    502         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU);
    503         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
    504         
    505         if (fiber_preferred) {
    506             line_mode = BSDK_PHY84728_INTF_SFI;
    507             pc->copper.enable = FALSE;
    508             pc->fiber.enable = TRUE;
    509             pc->interface = SOC_PORT_IF_XFI;
    510             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
    511         } else {
    512             pc->interface = SOC_PORT_IF_SGMII;
    513             line_mode = BSDK_PHY84728_INTF_SGMII;
    514             pc->copper.enable = TRUE;
    515             pc->fiber.enable = FALSE;
    516             PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
    517         }
    518         PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45);
    519         
    520         pc->copper.preferred = !fiber_preferred;
    521         pc->copper.autoneg_enable = TRUE;
    522         pc->copper.autoneg_advert = ADVERT_ALL_COPPER;
    523         pc->copper.force_speed = 1000;
    524         pc->copper.force_duplex = TRUE;
    525         pc->copper.master = SOC_PORT_MS_AUTO;
    526         pc->copper.mdix = SOC_PORT_MDIX_AUTO;
    527         
    528         pc->fiber.preferred = TRUE;
    529         pc->fiber.autoneg_enable = FALSE;
    530         pc->fiber.autoneg_advert = ADVERT_ALL_FIBER;
    531         pc->fiber.force_speed = 10000;
    532         pc->fiber.force_duplex = TRUE;
    533         pc->fiber.master = SOC_PORT_MS_NONE;
    534         pc->fiber.mdix = SOC_PORT_MDIX_NORMAL;
    535         
    536         /* config DAC mode and backplane mode for KR/LR4/SR4  */
    537         mask16 = BSDK_PHY84728_LN_DEV1_CHIP_MODE_DAC_MASK |
    538             BSDK_PHY84728_LN_DEV1_CHIP_MODE_BKPLANE_MASK ;
    539         if (BSDK_PHY84728_IS_KR_VARIANT(PHY84728_MAP(pc)->devid)) {
    540             data16 = BSDK_PHY84728_LN_DEV1_CHIP_MODE_BKPLANE_MASK;
    541         } else {
    542             data16 = 0;
    543         }
    544         
    545         SOC_IF_ERROR_RETURN(
    546             BSDK_MOD_PHY84728_LN_DEV1_CHIP_MODEr(pc, data16, mask16));
    547         
    548         
    549         SOC_IF_ERROR_RETURN(
    550             bsdk_phy84728_reset(pc));
    551         
    552         /* Check where to load ucode from again in pass2 */
    553         phy_ext_rom_boot = soc_property_port_get(unit, port,
    554                                                  spn_PHY_EXT_ROM_BOOT, 1);
    555         SOC_IF_ERROR_RETURN(
    556             bsdk_phy84728_no_reset_setup(pc,
    557                                          line_mode,
    558                                          phy_ext_rom_boot));
    559         
    560         /* Get Requested LED selectors (defaults are hardware defaults) */
    561         pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0);
    562         pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1);
    563         pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3);
    564         pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6);
    565         pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8);
    566         pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0);
    567         
    568         /* WAN/LAN mode set */
    569         wan_mode = soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE);
    570         
    571         if (wan_mode) {
    572             SOC_IF_ERROR_RETURN
    573                 (_phy_84728_mode_set(unit, port, WAN_MODE));
    574         } else {
    575             SOC_IF_ERROR_RETURN
    576                 (_phy_84728_mode_set(unit, port, LAN_MODE));
    577         }
    578         
    579         LOG_INFO(BSL_LS_SOC_PHY,
    580                  (BSL_META_U(unit,
    581                              "84728: u=%d port=%d mode=%s : init.\n"), 
    582                              unit, port, wan_mode ? "WAN" : "LAN"));
    583         
    584         
    585         /* XAUI RX Lane Swap (Lane A, B, C, D changes to Lane D, C, B, A) */
    586         str = soc_property_port_get_str(unit, port, spn_PHY_XAUI_RX_LANE_SWAP); 
    587         if (str != NULL) {
    588             temp = soc_property_port_get(unit, port,
    589                                          spn_PHY_XAUI_RX_LANE_SWAP, 0);
    590         } else {
    591             temp = 0;
    592         }
    593         PHY84728_MAP(pc)->phy_sys_xaui_rx_lane_map = (temp) ? 0x3210 : 0;
    594         
    595         
    596         /* XAUI TX Lane Swap (Lane A, B, C, D changes to Lane D, C, B, A) */
    597         str = soc_property_port_get_str(unit, port, spn_PHY_XAUI_TX_LANE_SWAP); 
    598         if (str != NULL) {
    599             temp = soc_property_port_get(unit, port,
    600                                          spn_PHY_XAUI_TX_LANE_SWAP, 0);
    601         } else {
    602             temp = 0;
    603         }
    604         PHY84728_MAP(pc)->phy_sys_xaui_tx_lane_map = (temp) ? 0x3210 : 0;
    605         
    606         
    607 #if 0
    608         /* Use lane mapping */
    609         SOC_IF_ERROR_RETURN(
    610             bsdk_phy84728_lane_map(pc));
    611 #endif
    612         
    613         
    614         if (line_mode != BSDK_PHY84728_INTF_SGMII) {
    615             SOC_IF_ERROR_RETURN
    616                 (_phy_84728_medium_config_update(unit, port, &pc->fiber));
    617         }
    618         
    619         int_pc = INT_PHY_SW_STATE(unit, port);
    620         if (NULL != int_pc) {
    621             PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0);
    622             PHY_SPEED_SET(int_pc->pd, unit, port, 10000);
    623         }
    624         
    625         if (IS_HG_PORT(unit, port)) {
    626             SOC_IF_ERROR_RETURN(
    627                 BSDK_PHY84728_REG_WR(pc, 0x00, 0x0004, 0x8007, 0x0040));
    628             SOC_IF_ERROR_RETURN(
    629                 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xcd08, 0x0100, 0x0100));
    630         }
    631         
    632         /* Enable Squelch */
    633         SOC_IF_ERROR_RETURN(_phy_84728_squelch_enable(unit, port, TRUE));
    634         
    635         rv = _phy_84728_nxt_dev_probe(unit,port);
    636         if (SOC_SUCCESS(rv)) {
    637             PHYDRV_CALL_NOARG(pc,PHY_INIT);
    638         }
    639     }        
    640     return SOC_E_NONE;
    641 }
    642 
    643 STATIC int
    644 _phy_54942_link_get(int unit, soc_port_t port, int *link)
    645 {
    646     phy_ctrl_t *pc; 
    647     uint16      xgxsstatus1, status1000x1;
    648 
    649     pc = EXT_PHY_SW_STATE(unit, port);
    650 
    651     SOC_IF_ERROR_RETURN
    652         (BSDK_RD_PHY84728_SYS_DEV4_XGXSSTATUS1r(pc, &xgxsstatus1));
    653 
    654     SOC_IF_ERROR_RETURN
    655         (BSDK_RD_PHY84728_SYS_DEV4_XGXS_BASE1000X_STAT1r(pc, &status1000x1));
    656 
    657     if (xgxsstatus1 == 0xffff) {
    658       *link = 0 ;
    659     } else {
    660       *link =  ((xgxsstatus1 & (1U << 2)) | (status1000x1 & (1U << 1))) ? 1 : 0;
    661     }
    662 
    663     LOG_VERBOSE(BSL_LS_SOC_PHY,
    664                 (BSL_META_U(unit,
    665                             "_phy_54942_link_get: u=%d port%d: link:%s\n"),
    666                  unit, port, *link ? "Up": "Down"));
    667 
    668     return SOC_E_NONE;
    669 }
    670 
    671 
    672 /*
    673  * Function:
    674  *    phy_84728_link_get
    675  * Purpose:
    676  *    Get layer2 connection status.
    677  * Parameters:
    678  *    unit - StrataSwitch unit #.
    679  *    port - StrataSwitch port #. 
    680  *      link - address of memory to store link up/down state.
    681  * Returns:    
    682  *    SOC_E_NONE
    683  */
    684 
    685 STATIC int
    686 phy_84728_link_get(int unit, soc_port_t port, int *link)
    687 {
    688     phy_ctrl_t *pc;
    689     int rv = SOC_E_NONE;
    690     bsdk_phy84728_intf_t bsdk_mode;
    691     int bsdk_link;
    692     uint16 wis_mii_stat;
    693 
    694     pc    = EXT_PHY_SW_STATE(unit, port);
    695     *link = FALSE;      /* Default return */
    696 
    697 
    698     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
    699         return SOC_E_NONE;
    700     }
    701 
    702     if (NXT_PC(pc)) {
    703         PHYDRV_CALL_ARG1(pc, PHY_LINK_GET, link);
    704         return SOC_E_NONE;
    705     }
    706 
    707     rv = bsdk_phy84728_line_intf_get(pc, 0, &bsdk_mode);
    708     if (!SOC_SUCCESS(rv)) {
    709         return SOC_E_FAIL;
    710     }
    711 
    712     if ((bsdk_mode == BSDK_PHY84728_INTF_SGMII) && !PHY_FLAGS_TST(unit, port, PHY_FLAGS_COPPER)) {
    713         PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
    714         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
    715     } else if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_FIBER)) {
    716         PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
    717         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
    718     }
    719 
    720     if (REVERSE_MODE(pc)) {
    721         SOC_IF_ERROR_RETURN
    722             (_phy_54942_link_get(unit, port, link));
    723     } else {
    724         if (PHY_WAN_MODE(unit, port)) {
    725              /* WIS status */
    726             SOC_IF_ERROR_RETURN
    727                 (BSDK_RD_PHY84728_WIS_STATr(pc, &wis_mii_stat));
    728             bsdk_link = wis_mii_stat == 0xffff ? 0 : (wis_mii_stat & 0x0004) ? 1 : 0 ;
    729         } else {
    730             rv = bsdk_phy84728_link_get(pc, &bsdk_link);
    731             if (!SOC_SUCCESS(rv)) {
    732                 return SOC_E_FAIL;
    733             }
    734         }
    735 
    736         if (bsdk_link) {
    737             *link = TRUE;
    738         } else {
    739             *link = FALSE;
    740         }
    741     }
    742 
    743     LOG_VERBOSE(BSL_LS_SOC_PHY,
    744                 (BSL_META_U(unit,
    745                             "phy_84728_link_get: u=%d p=%d link=%d\n"),
    746                  unit, port,
    747                  *link));
    748 
    749     return SOC_E_NONE;
    750 }
    751 
    752 
    753 STATIC int
    754 _phy_54942_enable_set(int unit, soc_port_t port, int enable)
    755 {
    756     phy_ctrl_t *pc; 
    757 
    758     pc = EXT_PHY_SW_STATE(unit, port);
    759 
    760     /* disable the Tx */
    761     SOC_IF_ERROR_RETURN
    762         (BSDK_MOD_PHY84728_XGXSBLK0_MISCCONTROL1r(pc,
    763                enable? 0:XGXSBLK0_MISCCONTROL1_GLOBAL_PMD_TX_DISABLE_MASK,
    764                XGXSBLK0_MISCCONTROL1_GLOBAL_PMD_TX_DISABLE_MASK));
    765 
    766     /* disable the Rx */
    767     SOC_IF_ERROR_RETURN
    768         (BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, enable?  BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ : 0,
    769                                                             BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ ));
    770 
    771     return SOC_E_NONE;
    772 }
    773 
    774 /*
    775  * Function:
    776  *      phy_84728_enable_set
    777  * Purpose:
    778  *      Enable or disable the physical interface.
    779  * Parameters:
    780  *      unit - StrataSwitch unit #.
    781  *      port - StrataSwitch port #.
    782  *      enable - Boolean, true = enable PHY, false = disable.
    783  * Returns:
    784  *      SOC_E_XXX
    785  */
    786 
    787 STATIC int
    788 phy_84728_enable_set(int unit, soc_port_t port, int enable)
    789 {
    790     phy_ctrl_t *pc;
    791     uint16 power;
    792 
    793     pc     = EXT_PHY_SW_STATE(unit, port);
    794 
    795     if (enable) {
    796         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
    797     } else {
    798         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
    799     }
    800 
    801     if (REVERSE_MODE(pc)) {
    802         SOC_IF_ERROR_RETURN
    803             (_phy_54942_enable_set(unit, port, enable));
    804     } else {
    805 
    806         /* PMA/PMD */
    807         power = (enable) ? 0 : 0x0001 ;
    808         SOC_IF_ERROR_RETURN(
    809         BSDK_MOD_PHY84728_LN_DEV1_PMD_XMIT_DISABLEr(pc, power, 0x0001));
    810 
    811     }
    812 
    813     if (enable) {
    814         sal_usleep(50);
    815         SOC_IF_ERROR_RETURN(_phy_84728_squelch_enable(unit, port, TRUE));
    816     }
    817 
    818     if (NXT_PC(pc)) {
    819         PHYDRV_CALL_ARG1(pc,PHY_ENABLE_SET,enable);
    820     }
    821 
    822     LOG_INFO(BSL_LS_SOC_PHY,
    823              (BSL_META_U(unit,
    824                          "phy_84728_enable_set: "
    825                          "Power %s fiber medium\n"), (enable) ? "up" : "down"));
    826 
    827     return SOC_E_NONE;
    828 }
    829 
    830 /*
    831  * Function:
    832  *      phy_84728_duplex_set
    833  * Purpose:
    834  *      Set the current duplex mode
    835  * Parameters:
    836  *      unit - StrataSwitch unit #.
    837  *      port - StrataSwitch port #.
    838  *      duplex - Boolean, true indicates full duplex, false indicates half.
    839  * Returns:
    840  *      SOC_E_NONE
    841  *      SOC_E_UNAVAIL - Half duplex requested, and not supported.
    842  * Notes:
    843  */
    844 STATIC int
    845 phy_84728_duplex_set(int unit, soc_port_t port, int duplex_in)
    846 {
    847     int                          rv = SOC_E_NONE ;
    848     phy_ctrl_t                   *pc;
    849     bsdk_phy84728_duplex_t    duplex;
    850     uint16 mii_ctrl;
    851     bsdk_phy84728_intf_t line_mode;
    852 
    853     pc = EXT_PHY_SW_STATE(unit, port);
    854 
    855     if (NXT_PC(pc)) {
    856         PHYDRV_CALL_ARG1(pc,PHY_DUPLEX_SET, duplex_in);
    857         return SOC_E_NONE;
    858     }
    859 
    860     if (duplex_in) {
    861         duplex = BSDK_PHY84728_FULL_DUPLEX;
    862     } else {
    863         duplex = BSDK_PHY84728_HALF_DUPLEX;
    864     }
    865 
    866 
    867     SOC_IF_ERROR_RETURN(
    868         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
    869 
    870     if ((line_mode == BSDK_PHY84728_INTF_1000X ) ||
    871         (line_mode == BSDK_PHY84728_INTF_SFI )) {
    872 
    873         if (duplex == BSDK_PHY84728_FULL_DUPLEX) {
    874             rv =  SOC_E_NONE;
    875             goto exit;
    876         } else {
    877             rv =  SOC_E_UNAVAIL;
    878             goto exit;
    879         }
    880     }
    881     SOC_IF_ERROR_RETURN(
    882         BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &mii_ctrl));
    883 
    884     if (duplex == BSDK_PHY84728_FULL_DUPLEX) {
    885         mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_FD;
    886     } else if (duplex == BSDK_PHY84728_HALF_DUPLEX) {
    887         mii_ctrl &= ~BSDK_PHY84728_AN_MII_CTRL_FD;
    888     } 
    889     SOC_IF_ERROR_RETURN(
    890         BSDK_WR_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, mii_ctrl));
    891 
    892 exit:
    893 
    894     if(SOC_SUCCESS(rv)) {
    895         pc->copper.force_duplex = duplex_in;
    896     }
    897 
    898 
    899     LOG_INFO(BSL_LS_SOC_PHY,
    900              (BSL_META_U(unit,
    901                          "phy_84728_duplex_set: u=%d p=%d d=%d rv=%d\n"),
    902               unit, port, duplex, rv));
    903     return rv;
    904 }
    905 
    906 /*
    907  * Function:
    908  *      phy_84728_duplex_get
    909  * Purpose:
    910  *      Get the current operating duplex mode. If autoneg is enabled,
    911  *      then operating mode is returned, otherwise forced mode is returned.
    912  * Parameters:
    913  *      unit - StrataSwitch unit #.
    914  *      port - StrataSwitch port #.
    915  *      duplex - (OUT) Boolean, true indicates full duplex, false
    916  *              indicates half.
    917  * Returns:
    918  *      SOC_E_NONE
    919  * Notes:
    920  *      The duplex is retrieved for the ACTIVE medium.
    921  *      No synchronization performed at this level. Autonegotiation is
    922  *      not manipulated.
    923  */
    924 
    925 STATIC int
    926 phy_84728_duplex_get(int unit, soc_port_t port, int *duplex)
    927 {
    928 
    929     phy_ctrl_t                   *pc;
    930     uint16	status;
    931     bsdk_phy84728_intf_t line_mode;
    932 
    933     pc = EXT_PHY_SW_STATE(unit, port);
    934 
    935     if (NXT_PC(pc)) {
    936         PHYDRV_CALL_ARG1(pc,PHY_DUPLEX_GET, duplex);
    937         return SOC_E_NONE;
    938     }
    939 
    940     SOC_IF_ERROR_RETURN(
    941         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
    942 
    943     if ((line_mode == BSDK_PHY84728_INTF_1000X ) ||
    944         (line_mode == BSDK_PHY84728_INTF_SFI )) {
    945         *duplex = TRUE;
    946     } else {
    947         SOC_IF_ERROR_RETURN(
    948             BSDK_RD_PHY84728_LN_DEV7_AN_BASE1000X_STAT1r(pc, &status));
    949         if (status & (1U << 2)) {
    950             *duplex = TRUE;
    951         } else {
    952             *duplex = FALSE;
    953         }
    954     }
    955 
    956     return SOC_E_NONE;
    957 }
    958 
    959 
    960 /*
    961  * Function:
    962  *      phy_84728_speed_set
    963  * Purpose:
    964  *      Set PHY speed
    965  * Parameters:
    966  *      unit - StrataSwitch unit #.
    967  *      port - StrataSwitch port #.
    968  *      speed - link speed in Mbps
    969  * Returns:
    970  *      SOC_E_NONE
    971  */
    972 STATIC int
    973 phy_84728_speed_set(int unit, soc_port_t port, int speed)
    974 {
    975     phy_ctrl_t *pc;
    976     phy_ctrl_t  *int_pc;
    977     int            rv; 
    978 
    979     pc = EXT_PHY_SW_STATE(unit, port);
    980     int_pc = INT_PHY_SW_STATE(unit, port);
    981     rv = SOC_E_NONE;
    982 
    983     if (speed > 10000) {
    984         return SOC_E_UNAVAIL;
    985     }
    986 
    987     if (NXT_PC(pc)) {
    988         PHYDRV_CALL_ARG1(pc,PHY_SPEED_SET,speed);
    989         return SOC_E_NONE;
    990     }
    991 
    992     rv = bsdk_phy84728_speed_set(pc, speed);
    993     if(SOC_SUCCESS(rv)) {
    994         /* need to set the internal phy's speed accordingly */
    995         if (NULL != int_pc) {
    996             if (REVERSE_MODE(pc)) {
    997                 SOC_IF_ERROR_RETURN
    998                     (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_SFI));
    999             }
   1000             PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0);
   1001             PHY_SPEED_SET(int_pc->pd, unit, port, speed);
   1002         }
   1003         if(PHY_COPPER_MODE(unit, port)) {
   1004             pc->copper.force_speed = speed;
   1005         } else {
   1006             if(PHY_FIBER_MODE(unit, port)) {
   1007                 pc->fiber.force_speed = speed;
   1008             }
   1009         }
   1010     }
   1011     LOG_INFO(BSL_LS_SOC_PHY,
   1012              (BSL_META_U(unit,
   1013                          "phy_84728_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"),
   1014               unit, port, speed, PHY_FIBER_MODE(unit, port), rv));
   1015 
   1016     return rv;
   1017 }
   1018 
   1019 /*
   1020  * Function:
   1021  *      phy_84728_speed_get
   1022  * Purpose:
   1023  *      Get the current operating speed for a 84728 device.
   1024  * Parameters:
   1025  *      unit - StrataSwitch unit #.
   1026  *      port - StrataSwitch port #.
   1027  *      speed - (OUT) Speed of the phy
   1028  * Returns:
   1029  *      SOC_E_NONE
   1030  * Notes:
   1031  *      The speed is retrieved for the ACTIVE medium.
   1032  */
   1033 
   1034 STATIC int
   1035 phy_84728_speed_get(int unit, soc_port_t port, int *speed)
   1036 {
   1037     phy_ctrl_t    *pc;
   1038     uint16 data = 0;
   1039     bsdk_phy84728_intf_t line_mode;
   1040 
   1041     if (speed == NULL) {
   1042         return SOC_E_PARAM;
   1043     }
   1044 
   1045     pc = EXT_PHY_SW_STATE(unit, port);
   1046 
   1047     if (NXT_PC(pc)) {
   1048         PHYDRV_CALL_ARG1(pc,PHY_SPEED_GET,speed);
   1049         return SOC_E_NONE;
   1050     }
   1051 
   1052     {
   1053         SOC_IF_ERROR_RETURN(
   1054             bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   1055 
   1056         if (line_mode == BSDK_PHY84728_INTF_SFI) {
   1057             *speed = 10000;
   1058             return SOC_E_NONE;
   1059         }
   1060         if (line_mode == BSDK_PHY84728_INTF_1000X) {
   1061             *speed = 1000;
   1062             return SOC_E_NONE;
   1063         }
   1064         SOC_IF_ERROR_RETURN(
   1065             BSDK_RD_PHY84728_LN_DEV1_SPEED_LINK_DETECT_STATr(pc, &data));
   1066         switch(data & BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_MASK) {
   1067         case BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_10M:
   1068             *speed = 10;
   1069             break;
   1070         case BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_100M:
   1071             *speed = 100;
   1072             break;
   1073         case BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_1G:
   1074             *speed = 1000;
   1075             break;
   1076         case BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_10G:
   1077             *speed = 10000;
   1078             break;
   1079         default :
   1080             *speed = 0;
   1081             break;
   1082         }
   1083     }
   1084 
   1085         LOG_INFO(BSL_LS_SOC_PHY,
   1086                  (BSL_META_U(unit,
   1087                              "phy_84728_speed_get: u=%d p=%d speed=%d"),
   1088                   unit, port, *speed));
   1089 
   1090     return SOC_E_NONE;
   1091 }
   1092 
   1093 /*
   1094  * Function:
   1095  *      phy_84728_an_set
   1096  * Purpose:
   1097  *      Enable or disable auto-negotiation on the specified port.
   1098  * Parameters:
   1099  *      unit - StrataSwitch unit #.
   1100  *      port - StrataSwitch port #.
   1101  *      autoneg - Boolean, if true, auto-negotiation is enabled
   1102  *              (and/or restarted). If false, autonegotiation is disabled.
   1103  * Returns:
   1104  *      SOC_E_XXX
   1105  * Notes:
   1106  *      The autoneg mode is set only for the ACTIVE medium.
   1107  */
   1108 
   1109 STATIC int
   1110 phy_84728_an_set(int unit, soc_port_t port, int autoneg)
   1111 {
   1112     int                 rv;
   1113     phy_ctrl_t   *pc;
   1114     uint16 data = 0;
   1115     bsdk_phy84728_intf_t line_mode;
   1116 
   1117     pc = EXT_PHY_SW_STATE(unit, port);
   1118     rv = SOC_E_NONE;
   1119 
   1120     if (NXT_PC(pc)) {
   1121         PHYDRV_CALL_ARG1(pc, PHY_AUTO_NEGOTIATE_SET, autoneg);
   1122         return SOC_E_NONE;
   1123     }
   1124 
   1125     SOC_IF_ERROR_RETURN(
   1126         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   1127 
   1128 
   1129     if (line_mode == BSDK_PHY84728_INTF_SGMII) {
   1130         return SOC_E_NONE;
   1131     }
   1132 
   1133     SOC_IF_ERROR_RETURN
   1134         (BSDK_MOD_PHY84728_LN_DEV7_ANr(pc, 0x8308, autoneg ? 0x0 : 0x1c, 0x1f));
   1135 
   1136     SOC_IF_ERROR_RETURN
   1137         (BSDK_MOD_PHY84728_LN_DEV7_AN_MSIC2r(pc,  autoneg ? 0x0 : 0x20, 0x20));
   1138 
   1139 
   1140 #if 0  /* needed for KR */
   1141     SOC_IF_ERROR_RETURN(
   1142         BSDK_RD_PHY84728_XFI_DEV7_AN_CTRLr(pc, &data));
   1143     if (autoneg) {
   1144         data |= (BSDK_PHY84728_AN_AN_CTRL_AE |
   1145                 BSDK_PHY84728_AN_AN_CTRL_RAN);
   1146     } else {
   1147         data &= ~(BSDK_PHY84728_AN_AN_CTRL_AE |
   1148                   BSDK_PHY84728_AN_AN_CTRL_RAN);
   1149     }
   1150     SOC_IF_ERROR_RETURN(
   1151         BSDK_WR_PHY84728_XFI_DEV7_AN_CTRLr(pc, data));
   1152 #endif
   1153 
   1154 
   1155     SOC_IF_ERROR_RETURN(
   1156         BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &data));
   1157     if (autoneg) {
   1158         data |= (BSDK_PHY84728_AN_MII_CTRL_AE | 
   1159                  BSDK_PHY84728_AN_MII_CTRL_RAN);
   1160     } else {
   1161         data &= ~(BSDK_PHY84728_AN_MII_CTRL_AE | 
   1162                   BSDK_PHY84728_AN_MII_CTRL_RAN);
   1163     }
   1164     SOC_IF_ERROR_RETURN(
   1165         BSDK_WR_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, data));
   1166 
   1167     if(SOC_SUCCESS(rv)) {
   1168         if(PHY_COPPER_MODE(unit, port)) {
   1169             pc->copper.autoneg_enable = autoneg ? TRUE : FALSE;
   1170         } else {
   1171             if(PHY_FIBER_MODE(unit, port)) {
   1172                 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE;
   1173             }
   1174         }
   1175     }
   1176 
   1177     LOG_INFO(BSL_LS_SOC_PHY,
   1178              (BSL_META_U(unit,
   1179                          "phy_84728_an_set: u=%d p=%d autoneg=%d rv=%d\n"),
   1180               unit, port, autoneg, rv));
   1181     return rv;
   1182 }
   1183 
   1184 /*
   1185  * Function:
   1186  *      phy_84728_an_get
   1187  * Purpose:
   1188  *      Get the current auto-negotiation status (enabled/busy).
   1189  * Parameters:
   1190  *      unit - StrataSwitch unit #.
   1191  *      port - StrataSwitch port #.
   1192  *      autoneg - (OUT) if true, auto-negotiation is enabled.
   1193  *      autoneg_done - (OUT) if true, auto-negotiation is complete. This
   1194  *              value is undefined if autoneg == FALSE.
   1195  * Returns:
   1196  *      SOC_E_XXX
   1197  * Notes:
   1198  *      The autoneg mode is retrieved for the ACTIVE medium.
   1199  */
   1200 
   1201 STATIC int
   1202 phy_84728_an_get(int unit, soc_port_t port,
   1203                      int *autoneg, int *autoneg_done)
   1204 {
   1205     int           rv;
   1206     phy_ctrl_t   *pc;
   1207 #if 0
   1208     uint16 an_ctrl = 0, an_stat = 0;
   1209 #endif
   1210     uint16 an_mii_ctrl = 0, an_mii_stat = 0;
   1211     bsdk_phy84728_intf_t line_mode;
   1212 
   1213     pc = EXT_PHY_SW_STATE(unit, port);
   1214 
   1215     rv            = SOC_E_NONE;
   1216     *autoneg      = FALSE;
   1217     *autoneg_done = FALSE;
   1218 
   1219     if (NXT_PC(pc)) {
   1220         PHYDRV_CALL_ARG2(pc, PHY_AUTO_NEGOTIATE_GET, autoneg, autoneg_done);
   1221         return SOC_E_NONE;
   1222     }
   1223 
   1224     SOC_IF_ERROR_RETURN(
   1225         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   1226 
   1227     /* revisit for KR */
   1228 #if 0
   1229     if (line_mode == BSDK_PHY84728_INTF_SFI) {
   1230         SOC_IF_ERROR_RETURN(
   1231             BSDK_RD_PHY84728_LN_DEV7_AN_CTRLr(pc, &an_ctrl));
   1232         SOC_IF_ERROR_RETURN(
   1233             BSDK_RD_PHY84728_LN_DEV7_AN_STATr(pc, &an_stat));
   1234         *autoneg = (an_ctrl & BSDK_PHY84728_AN_AN_CTRL_AE) ? 1 : 0;
   1235         *autoneg_done = (an_stat & BSDK_PHY84728_AN_AN_STAT_AN_DONE) ? 1 : 0;
   1236     } else {
   1237 #endif
   1238     {
   1239         SOC_IF_ERROR_RETURN(
   1240             BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &an_mii_ctrl));
   1241         SOC_IF_ERROR_RETURN(
   1242             BSDK_RD_PHY84728_LN_DEV7_AN_MII_STATr(pc, &an_mii_stat));
   1243         *autoneg = (an_mii_ctrl & BSDK_PHY84728_AN_MII_CTRL_AE) ? 1 : 0;
   1244         *autoneg_done = 
   1245             (an_mii_stat & BSDK_PHY84728_AN_MII_STAT_AN_DONE) ? 1 : 0;
   1246     }
   1247 
   1248     return rv;
   1249 }
   1250 
   1251 
   1252 STATIC int
   1253 _phy_54942_lb_set(int unit, soc_port_t port, int enable)
   1254 {
   1255     phy_ctrl_t *pc; 
   1256 
   1257     pc = EXT_PHY_SW_STATE(unit, port);
   1258 
   1259     SOC_IF_ERROR_RETURN
   1260         (BSDK_PHY84728_REG_MOD(pc,
   1261                0x0, 0x4, 0, enable ? (1U << 14) : 0, (1U << 14)));
   1262 
   1263     return SOC_E_NONE;
   1264 }
   1265 /*
   1266  * Function:
   1267  *      phy_84728_lb_set
   1268  * Purpose:
   1269  *      Set the local PHY loopback mode.
   1270  * Parameters:
   1271  *      unit - StrataSwitch unit #.
   1272  *      port - StrataSwitch port #.
   1273  *      loopback - Boolean: true = enable loopback, false = disable.
   1274  * Returns:
   1275  *      SOC_E_XXX
   1276  * Notes:
   1277  *      The loopback mode is set only for the ACTIVE medium.
   1278  *      No synchronization performed at this level.
   1279  */
   1280 
   1281 STATIC int
   1282 phy_84728_lb_set(int unit, soc_port_t port, int enable)
   1283 {
   1284     int           rv;
   1285     phy_ctrl_t    *pc;
   1286     uint16 data = 0;
   1287     bsdk_phy84728_intf_t line_mode;
   1288 
   1289     pc = EXT_PHY_SW_STATE(unit, port);
   1290     rv = SOC_E_NONE;
   1291 
   1292     if (NXT_PC(pc)) {
   1293         PHYDRV_CALL_ARG1(pc,PHY_LOOPBACK_SET,enable);
   1294         if (enable) {
   1295             SOC_IF_ERROR_RETURN
   1296                 (phy_84728_link_up(unit, port));
   1297         }
   1298         return SOC_E_NONE;
   1299     }
   1300 
   1301 #if 1
   1302     /* Disable(Enable) Squelch when we Enable(Disable) loopback */
   1303     SOC_IF_ERROR_RETURN
   1304         (_phy_84728_squelch_enable(unit, port, enable ? FALSE : TRUE));
   1305 #endif
   1306 
   1307     SOC_IF_ERROR_RETURN(
   1308         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   1309 
   1310     if (REVERSE_MODE(pc)) {
   1311         SOC_IF_ERROR_RETURN
   1312             (_phy_54942_lb_set(unit, port, enable));
   1313 
   1314         if (rv == SOC_E_NONE) {
   1315             /* wait for link up when loopback is enabled */
   1316             
   1317             if (enable) {
   1318                 sal_usleep(2000000);
   1319             }
   1320         }
   1321     } else {
   1322 
   1323         /* lock detect bypass */
   1324         SOC_IF_ERROR_RETURN(
   1325             BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 
   1326                 0xCA7B, enable ? (1<<14) : 0, (1<<14)));
   1327 
   1328 
   1329         if (line_mode == BSDK_PHY84728_INTF_SFI) {
   1330             SOC_IF_ERROR_RETURN(
   1331                 BSDK_RD_PHY84728_LN_DEV1_PMD_CTRLr(pc, &data));
   1332             data &= ~(1);
   1333             data |= (enable) ? 1 : 0x0000;
   1334             SOC_IF_ERROR_RETURN(
   1335                 BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, data));
   1336         } else {
   1337             SOC_IF_ERROR_RETURN(
   1338                 BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &data));
   1339             data &= ~BSDK_PHY84728_AN_MII_CTRL_LE;
   1340             data |= (enable) ? BSDK_PHY84728_AN_MII_CTRL_LE : 0;
   1341             SOC_IF_ERROR_RETURN(
   1342                 BSDK_WR_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, data));
   1343             if (!enable) 
   1344             { 
   1345                 SOC_IF_ERROR_RETURN( 
   1346                 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xC8E4, (1 << 12), (1 << 12))); 
   1347                 SOC_IF_ERROR_RETURN( 
   1348                 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xC8E4, (1 << 4), (1 << 4))); 
   1349                 SOC_IF_ERROR_RETURN( 
   1350                 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xC8E4, 0, (1 << 12))); 
   1351                 SOC_IF_ERROR_RETURN( 
   1352                 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xC8E4, 0, (1 << 4))); 
   1353              } 
   1354 	}
   1355 
   1356         if (rv == SOC_E_NONE) {
   1357             /* wait for link up when loopback is enabled */
   1358             
   1359             if (enable) {
   1360                 sal_usleep(2000000);
   1361             }
   1362         }
   1363     }
   1364 
   1365     LOG_INFO(BSL_LS_SOC_PHY,
   1366              (BSL_META_U(unit,
   1367                          "phy_84728_lb_set: u=%d p=%d en=%d rv=%d\n"), 
   1368               unit, port, enable, rv));
   1369 
   1370     return rv; 
   1371 }
   1372 
   1373 STATIC int
   1374 _phy_54942_lb_get(int unit, soc_port_t port, int *enable)
   1375 {
   1376     phy_ctrl_t *pc; 
   1377     uint16 tmp;
   1378 
   1379     pc = EXT_PHY_SW_STATE(unit, port);
   1380 
   1381     SOC_IF_ERROR_RETURN
   1382         (BSDK_PHY84728_REG_RD(pc, 0x0, 0x4, 0, &tmp));
   1383 
   1384     *enable = tmp & (1U << 14) ? TRUE : FALSE;
   1385 
   1386     return SOC_E_NONE;
   1387 }
   1388 
   1389 /*
   1390  * Function:
   1391  *      phy_84728_lb_get
   1392  * Purpose:
   1393  *      Get the local PHY loopback mode.
   1394  * Parameters:
   1395  *      unit - StrataSwitch unit #.
   1396  *      port - StrataSwitch port #.
   1397  *      loopback - (OUT) Boolean: true = enable loopback, false = disable.
   1398  * Returns:
   1399  *      SOC_E_XXX
   1400  * Notes:
   1401  *      The loopback mode is retrieved for the ACTIVE medium.
   1402  */
   1403 
   1404 STATIC int
   1405 phy_84728_lb_get(int unit, soc_port_t port, int *enable)
   1406 {
   1407     int                  rv;
   1408     phy_ctrl_t    *pc;
   1409     uint16 data = 0;
   1410     bsdk_phy84728_intf_t line_mode;
   1411 
   1412     pc = EXT_PHY_SW_STATE(unit, port);
   1413     rv = SOC_E_NONE;
   1414 
   1415     if (NXT_PC(pc)) {
   1416         PHYDRV_CALL_ARG1(pc,PHY_LOOPBACK_GET,enable);
   1417         return SOC_E_NONE;
   1418     }
   1419 
   1420     SOC_IF_ERROR_RETURN(
   1421         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   1422 
   1423     if (REVERSE_MODE(pc)) {
   1424         SOC_IF_ERROR_RETURN
   1425             (_phy_54942_lb_get(unit, port, enable));
   1426     } else {
   1427         if (line_mode == BSDK_PHY84728_INTF_SFI) {
   1428             SOC_IF_ERROR_RETURN(
   1429                 BSDK_RD_PHY84728_LN_DEV1_PMD_CTRLr(pc, &data));
   1430             *enable = (data & 1) ? 1 : 0;
   1431         } else {
   1432             SOC_IF_ERROR_RETURN(
   1433                 BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &data));
   1434             *enable = (data & BSDK_PHY84728_AN_MII_CTRL_LE) ? 1 : 0;
   1435         }
   1436     }
   1437 
   1438     return rv; 
   1439 }
   1440 
   1441 STATIC int
   1442 _phy_84728_control_pdet_set(int unit, soc_port_t port, uint32 enable)
   1443 {
   1444     uint16 mask;
   1445     uint16 data;
   1446     phy_ctrl_t *pc;   /* PHY software state */
   1447 
   1448     mask = PHY84728_PDET_MASK;
   1449     data = enable ? mask : 0;
   1450 
   1451     pc = EXT_PHY_SW_STATE(unit, port);
   1452 
   1453     SOC_IF_ERROR_RETURN(
   1454          BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL2r(pc, data, mask));
   1455     
   1456     return SOC_E_NONE;
   1457 }
   1458 
   1459 STATIC int
   1460 _phy_84728_control_pdet_get(int unit, soc_port_t port, uint32 *value)
   1461 {
   1462     uint16         data16;
   1463     phy_ctrl_t    *pc;       /* PHY software state */
   1464 
   1465     pc = EXT_PHY_SW_STATE(unit, port);
   1466 
   1467     SOC_IF_ERROR_RETURN(
   1468          BSDK_RD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL2r(pc, &data16));
   1469 
   1470     if ((data16 & PHY84728_PDET_MASK) == PHY84728_PDET_MASK) {
   1471         *value = 1; 
   1472     } else {
   1473         *value = 0; 
   1474     }
   1475 
   1476     return SOC_E_NONE;
   1477 }
   1478 
   1479 
   1480 STATIC int
   1481 _phy_84728_control_edc_mode_get(int unit, soc_port_t port, uint32 *value)
   1482 {
   1483     uint16         data16;
   1484     phy_ctrl_t    *pc;       /* PHY software state */
   1485 
   1486     pc = EXT_PHY_SW_STATE(unit, port);
   1487 
   1488     /* program EDC mode */
   1489     SOC_IF_ERROR_RETURN
   1490         (READ_PHY84728_PMA_PMD_REG(unit,pc, 0xCA1A,&data16));
   1491 
   1492     *value = data16 & PHY_84727_EDC_MODE_MASK;
   1493     return SOC_E_NONE;
   1494 }
   1495 
   1496 STATIC int
   1497 _phy_84728_control_edc_mode_set(int unit, soc_port_t port, uint32 value)
   1498 {
   1499     uint16         data16;
   1500     uint16         mask16;
   1501     phy_ctrl_t    *pc;       /* PHY software state */
   1502 
   1503     pc = EXT_PHY_SW_STATE(unit, port);
   1504 
   1505     /* EDC mode programming sequence*/
   1506     mask16 = 1 << 9;
   1507 
   1508     /* induce LOS condition: toggle register bit 0xc800.9 */
   1509     SOC_IF_ERROR_RETURN
   1510         (READ_PHY84728_PMA_PMD_REG(unit,pc, 0xC800,&data16));
   1511     /* only change toggled bit 9 */
   1512     SOC_IF_ERROR_RETURN
   1513         (MODIFY_PHY84728_PMA_PMD_REG(unit,pc, 0xC800,~data16,mask16));
   1514     
   1515     /* program EDC mode */
   1516     SOC_IF_ERROR_RETURN
   1517         (MODIFY_PHY84728_PMA_PMD_REG(unit,pc, 0xCA1A,(uint16)value,
   1518                                     PHY_84727_EDC_MODE_MASK));
   1519     
   1520     /* remove LOS condition: restore back original value of bit 0xc800.9 */
   1521     SOC_IF_ERROR_RETURN
   1522         (MODIFY_PHY84728_PMA_PMD_REG(unit,pc, 0xC800,data16,mask16));
   1523 
   1524     return SOC_E_NONE;
   1525 }
   1526 
   1527 STATIC int
   1528 _phy_84728_mode_set(int unit, soc_port_t port, uint32 mode) {
   1529     uint16      dev_reg, mask;
   1530     phy_ctrl_t *pc;
   1531 
   1532     pc = EXT_PHY_SW_STATE(unit, port);
   1533 
   1534     switch(mode) {
   1535         case WAN_MODE:
   1536             if (PHY_WAN_MODE(unit, port)) {
   1537                 /* Already in WAN mode */ 
   1538                 return SOC_E_NONE;
   1539             }
   1540             SOC_IF_ERROR_RETURN
   1541                 (BSDK_RD_PHY84728_WIS_DEV_IN_PKGr(pc,  &dev_reg));
   1542 #if 0
   1543             /* Check WIS present */ 
   1544             if (!(dev_reg & 0x0004)) {
   1545                 return SOC_E_UNAVAIL;
   1546             }
   1547 #endif
   1548             /* To configure WAN mode clock, */
   1549             mask = PMD_MISC_CTRL_WAN_MODE;
   1550             SOC_IF_ERROR_RETURN
   1551                 (BSDK_MOD_PHY84728_PMD_MISC_CTRLr(pc, PMD_MISC_CTRL_WAN_MODE, mask));
   1552 
   1553             PHY_FLAGS_SET(unit, port, PHY_FLAGS_WAN);
   1554             break;
   1555 
   1556         case LAN_MODE:
   1557 #if 0
   1558             if (!PHY_WAN_MODE(unit, port)) {
   1559                 /* Already in LAN mode */
   1560                 return SOC_E_NONE;
   1561             } 
   1562 #endif
   1563 
   1564             /* To configure LAN mode clock, */ 
   1565             mask = PMD_MISC_CTRL_WAN_MODE;
   1566            
   1567             /* put device in LAN mode */
   1568             SOC_IF_ERROR_RETURN
   1569                 (BSDK_MOD_PHY84728_PMD_MISC_CTRLr(pc, 0, mask));
   1570 
   1571             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_WAN);
   1572             break;
   1573         default:
   1574             return SOC_E_UNAVAIL;
   1575     }
   1576  
   1577     LOG_INFO(BSL_LS_SOC_PHY,
   1578              (BSL_META_U(unit,
   1579                          "phy_84728_mode_set: u=%d port=%d mode=%d\n"),
   1580               unit, port, mode));
   1581 
   1582     return SOC_E_NONE;
   1583 }
   1584 
   1585 
   1586 /*
   1587  * Function:
   1588  *      phy_84728_medium_config_set
   1589  * Purpose:
   1590  *      Set the operating parameters that are automatically selected
   1591  *      when medium switches type.
   1592  * Parameters:
   1593  *      unit - StrataSwitch unit #
   1594  *      port - Port number
   1595  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
   1596  *      cfg - Operating parameters
   1597  * Returns:
   1598  *      SOC_E_XXX
   1599  */
   1600 
   1601 STATIC int
   1602 phy_84728_medium_config_set(int unit, soc_port_t port, 
   1603                            soc_port_medium_t  medium,
   1604                            soc_phy_config_t  *cfg)
   1605 {
   1606     phy_ctrl_t    *pc;
   1607 #if 0
   1608     soc_phy_config_t *active_medium;  /* Currently active medium */
   1609 #endif
   1610     soc_phy_config_t *change_medium;  /* Requested medium */
   1611     soc_phy_config_t *other_medium;   /* The other medium */
   1612 
   1613     soc_port_mode_t   advert_mask;
   1614 
   1615     if (NULL == cfg) {
   1616         return SOC_E_PARAM;
   1617     }
   1618 
   1619     pc            = EXT_PHY_SW_STATE(unit, port);
   1620 
   1621     if (NXT_PC(pc)) {
   1622         PHYDRV_CALL_ARG2(pc, PHY_MEDIUM_CONFIG_SET, medium, cfg);
   1623         return SOC_E_NONE;
   1624     }
   1625 
   1626    switch (medium) {
   1627     case SOC_PORT_MEDIUM_COPPER:
   1628         if (!pc->automedium && !PHY_COPPER_MODE(unit, port)) {
   1629             return SOC_E_UNAVAIL;
   1630         }
   1631         change_medium  = &pc->copper;
   1632         other_medium   = &pc->fiber;
   1633         advert_mask    = ADVERT_ALL_COPPER;
   1634         break;
   1635     case SOC_PORT_MEDIUM_FIBER:
   1636         if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) {
   1637             return SOC_E_UNAVAIL;
   1638         }
   1639         change_medium  = &pc->fiber;
   1640         other_medium   = &pc->copper;
   1641         advert_mask    = ADVERT_ALL_FIBER;
   1642         break;
   1643     default:
   1644         return SOC_E_PARAM;
   1645     }
   1646 
   1647     /*
   1648      * Changes take effect immediately if the target medium is active or
   1649      * the preferred medium changes.
   1650      */
   1651     if (change_medium->preferred != cfg->preferred) {
   1652         /* Make sure that only one medium is preferred */
   1653         other_medium->preferred = !cfg->preferred;
   1654     }
   1655 
   1656     sal_memcpy(change_medium, cfg, sizeof(*change_medium));
   1657     change_medium->autoneg_advert &= advert_mask;
   1658 
   1659     return SOC_E_NONE;
   1660 }
   1661 
   1662 /*
   1663  * Function:
   1664  *      phy_84728_medium_config_get
   1665  * Purpose:
   1666  *      Get the operating parameters that are automatically selected
   1667  *      when medium switches type.
   1668  * Parameters:
   1669  *      unit - StrataSwitch unit #
   1670  *      port - Port number
   1671  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
   1672  *      cfg - (OUT) Operating parameters
   1673  * Returns:
   1674  *      SOC_E_XXX
   1675  */
   1676 
   1677 STATIC int
   1678 phy_84728_medium_config_get(int unit, soc_port_t port, 
   1679                            soc_port_medium_t medium,
   1680                            soc_phy_config_t *cfg)
   1681 {
   1682     int            rv;
   1683     phy_ctrl_t    *pc;
   1684 
   1685     pc = EXT_PHY_SW_STATE(unit, port);
   1686     rv = SOC_E_NONE;
   1687 
   1688     if (NXT_PC(pc)) {
   1689         PHYDRV_CALL_ARG2(pc, PHY_MEDIUM_CONFIG_GET, medium, cfg);
   1690         return SOC_E_NONE;
   1691     }
   1692 
   1693     switch (medium) {
   1694     case SOC_PORT_MEDIUM_COPPER:
   1695         if (pc->automedium || PHY_COPPER_MODE(unit, port)) {
   1696             sal_memcpy(cfg, &pc->copper, sizeof (*cfg));
   1697         } else {
   1698             rv = SOC_E_UNAVAIL;
   1699         }
   1700         break;
   1701     case SOC_PORT_MEDIUM_FIBER:
   1702         if (pc->automedium || PHY_FIBER_MODE(unit, port)) {
   1703             sal_memcpy(cfg, &pc->fiber, sizeof (*cfg));
   1704         } else {
   1705             rv = SOC_E_UNAVAIL;
   1706         }
   1707         break;
   1708     default:
   1709         rv = SOC_E_PARAM;
   1710         break;
   1711     }
   1712 
   1713     return rv;
   1714 }
   1715 
   1716 /*
   1717  * Function:
   1718  *      phy_84728_ability_advert_set
   1719  * Purpose:
   1720  *      Set the current advertisement for auto-negotiation.
   1721  * Parameters:
   1722  *      unit - StrataSwitch unit #.
   1723  *      port - StrataSwitch port #.
   1724  *      mode - Port mode mask indicating supported options/speeds.
   1725  * Returns:
   1726  *      SOC_E_XXX
   1727  * Notes:
   1728  *      The advertisement is set only for the ACTIVE medium.
   1729  *      No synchronization performed at this level.
   1730  */
   1731 STATIC int
   1732 phy_84728_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability)
   1733 {
   1734     int        rv;
   1735     phy_ctrl_t *pc;
   1736     bsdk_phy84728_port_ability_t local_ability;
   1737 
   1738     pc = EXT_PHY_SW_STATE(unit, port);
   1739 
   1740     if (NULL == ability) {
   1741         return (SOC_E_PARAM);
   1742     }
   1743 
   1744     if (NXT_PC(pc)) {
   1745         PHYDRV_CALL_ARG1(pc,PHY_ABILITY_ADVERT_SET,ability);
   1746         return SOC_E_NONE;
   1747     }
   1748 
   1749     if (PHY_COPPER_MODE(unit, port)) {
   1750         pc->copper.advert_ability = *ability;
   1751     } else {
   1752         pc->fiber.advert_ability = *ability;
   1753     }
   1754 
   1755     local_ability = 0;
   1756 
   1757     if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) {
   1758         local_ability |= BSDK_PHY84728_PA_1000MB_FD;
   1759     }
   1760     if(ability->speed_full_duplex & SOC_PA_SPEED_10GB) {
   1761         local_ability |= BSDK_PHY84728_PA_10000MB_FD;
   1762     }
   1763 
   1764     if(ability->pause & SOC_PA_PAUSE_TX) {
   1765         local_ability |= BSDK_PHY84728_PA_PAUSE_TX;
   1766     }
   1767     if(ability->pause & SOC_PA_PAUSE_RX) {
   1768         local_ability |= BSDK_PHY84728_PA_PAUSE_RX;
   1769     }
   1770     if(ability->pause & SOC_PA_PAUSE_ASYMM) {
   1771         local_ability |= BSDK_PHY84728_PA_PAUSE_ASYMM;
   1772     }
   1773 
   1774     if(ability->loopback & SOC_PA_LB_NONE) {
   1775         local_ability |= BSDK_PHY84728_PA_LB_NONE;
   1776     }
   1777     if(ability->loopback & SOC_PA_LB_PHY) {
   1778         local_ability |= BSDK_PHY84728_PA_LB_PHY;
   1779     }
   1780     if(ability->flags & SOC_PA_AUTONEG) {
   1781         local_ability |= BSDK_PHY84728_PA_AN;
   1782     }
   1783 
   1784     rv = bsdk_phy84728_ability_advert_set(pc, local_ability);
   1785 
   1786     return rv;
   1787 }
   1788 
   1789 /*
   1790  * Function:
   1791  *      phy_84728_ability_advert_get
   1792  * Purpose:
   1793  *      Get the current advertisement for auto-negotiation.
   1794  * Parameters:
   1795  *      unit - StrataSwitch unit #.
   1796  *      port - StrataSwitch port #.
   1797  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1798  * Returns:
   1799  *      SOC_E_XXX
   1800  * Notes:
   1801  *      The advertisement is retrieved for the ACTIVE medium.
   1802  *      No synchronization performed at this level.
   1803  */
   1804 STATIC int
   1805 phy_84728_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   1806 {
   1807     phy_ctrl_t      *pc;
   1808     int        rv;
   1809     bsdk_phy84728_port_ability_t local_ability;
   1810 
   1811     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1812         return SOC_E_NONE;
   1813     }
   1814 
   1815     if (NULL == ability) {
   1816         return (SOC_E_PARAM);
   1817     }
   1818 
   1819     pc = EXT_PHY_SW_STATE(unit, port);
   1820 
   1821     if (NXT_PC(pc)) {
   1822         PHYDRV_CALL_ARG1(pc,PHY_ABILITY_ADVERT_GET,ability);
   1823         return SOC_E_NONE;
   1824     }
   1825 
   1826     local_ability = 0;
   1827 
   1828     rv = bsdk_phy84728_ability_advert_get(pc, &local_ability);
   1829     if (rv != SOC_E_NONE) {
   1830         return SOC_E_FAIL;
   1831     }
   1832 
   1833     if(local_ability & BSDK_PHY84728_PA_1000MB_FD) {
   1834         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1835     }
   1836     if(local_ability & BSDK_PHY84728_PA_10000MB_FD) {
   1837         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1838     }
   1839 
   1840     if(local_ability & BSDK_PHY84728_PA_PAUSE_TX) {
   1841         ability->pause |= SOC_PA_PAUSE_TX;
   1842     }
   1843     if(local_ability & BSDK_PHY84728_PA_PAUSE_RX) {
   1844         ability->pause |= SOC_PA_PAUSE_RX;
   1845     }
   1846     if(local_ability & BSDK_PHY84728_PA_PAUSE_ASYMM) {
   1847         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1848     }
   1849 
   1850     if(local_ability & BSDK_PHY84728_PA_LB_NONE) {
   1851         ability->loopback |= SOC_PA_LB_NONE;
   1852     }
   1853     if(local_ability & BSDK_PHY84728_PA_LB_PHY) {
   1854         ability->loopback |= SOC_PA_LB_PHY;
   1855     }
   1856     if(local_ability & BSDK_PHY84728_PA_AN) {
   1857         ability->flags = SOC_PA_AUTONEG;
   1858     }
   1859 
   1860     return SOC_E_NONE;
   1861 }
   1862 
   1863 /*
   1864  * Function:
   1865  *      phy_84728_ability_remote_get
   1866  * Purpose:
   1867  *      Get the current remote advertisement for auto-negotiation.
   1868  * Parameters:
   1869  *      unit - StrataSwitch unit #.
   1870  *      port - StrataSwitch port #.
   1871  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1872  * Returns:
   1873  *      SOC_E_XXX
   1874  * Notes:
   1875  *      The advertisement is retrieved for the ACTIVE medium.
   1876  *      No synchronization performed at this level.
   1877  */
   1878 STATIC int
   1879 phy_84728_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   1880 {
   1881     phy_ctrl_t      *pc;
   1882     int        rv;
   1883     bsdk_phy84728_port_ability_t remote_ability;
   1884 
   1885     if (NULL == ability) {
   1886         return (SOC_E_PARAM);
   1887     }
   1888 
   1889     pc = EXT_PHY_SW_STATE(unit, port);
   1890 
   1891     if (NXT_PC(pc)) {
   1892         PHYDRV_CALL_ARG1(pc,PHY_ABILITY_REMOTE_GET,ability);
   1893         return SOC_E_NONE;
   1894     }
   1895 
   1896     remote_ability = 0;
   1897 
   1898     rv = bsdk_phy84728_remote_ability_advert_get(pc,
   1899                                                    &remote_ability);
   1900     if (rv != SOC_E_NONE) {
   1901         return SOC_E_FAIL;
   1902     }
   1903 
   1904     if(remote_ability & BSDK_PHY84728_PA_1000MB_FD) {
   1905         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1906     }
   1907     if(remote_ability & BSDK_PHY84728_PA_10000MB_FD) {
   1908         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1909     }
   1910 
   1911     if(remote_ability & BSDK_PHY84728_PA_PAUSE_TX) {
   1912         ability->pause |= SOC_PA_PAUSE_TX;
   1913     }
   1914     if(remote_ability & BSDK_PHY84728_PA_PAUSE_RX) {
   1915         ability->pause |= SOC_PA_PAUSE_RX;
   1916     }
   1917     if(remote_ability & BSDK_PHY84728_PA_PAUSE_ASYMM) {
   1918         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1919     }
   1920 
   1921     if(remote_ability & BSDK_PHY84728_PA_LB_NONE) {
   1922         ability->loopback |= SOC_PA_LB_NONE;
   1923     }
   1924     if(remote_ability & BSDK_PHY84728_PA_LB_PHY) {
   1925         ability->loopback |= SOC_PA_LB_PHY;
   1926     }
   1927     if(remote_ability & BSDK_PHY84728_PA_AN) {
   1928         ability->flags = SOC_PA_AUTONEG;
   1929     }
   1930 
   1931     return SOC_E_NONE;
   1932 }
   1933 
   1934 
   1935 
   1936 /*
   1937  * Function:
   1938  *      phy_84728_ability_local_get
   1939  * Purpose:
   1940  *      Get local abilities 
   1941  * Parameters:
   1942  *      unit - StrataSwitch unit #.
   1943  *      port - StrataSwitch port #.
   1944  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1945  * Returns:
   1946  *      SOC_E_NONE
   1947  * Notes:
   1948  *      The ability is retrieved only for the ACTIVE medium.
   1949  */
   1950 
   1951 STATIC int
   1952 phy_84728_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1953 {
   1954     int         rv = SOC_E_NONE;
   1955     phy_ctrl_t *pc;
   1956     bsdk_phy84728_port_ability_t local_ability = 0;
   1957 
   1958     if (NULL == ability) {
   1959         return SOC_E_PARAM;
   1960     }
   1961 
   1962     pc = EXT_PHY_SW_STATE(unit, port);
   1963 
   1964     if (NXT_PC(pc)) {
   1965         PHYDRV_CALL_ARG1(pc,PHY_ABILITY_LOCAL_GET,ability);
   1966         return SOC_E_NONE;
   1967     }
   1968 
   1969     rv = bsdk_phy84728_ability_local_get(pc, &local_ability);
   1970     if (rv != SOC_E_NONE) {
   1971         return SOC_E_FAIL;
   1972     }
   1973 
   1974     if(local_ability & BSDK_PHY84728_PA_1000MB_FD) {
   1975         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1976     }
   1977     if(local_ability & BSDK_PHY84728_PA_10000MB_FD) {
   1978         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1979     }
   1980 
   1981     if(local_ability & BSDK_PHY84728_PA_PAUSE_TX) {
   1982         ability->pause |= SOC_PA_PAUSE_TX;
   1983     }
   1984     if(local_ability & BSDK_PHY84728_PA_PAUSE_RX) {
   1985         ability->pause |= SOC_PA_PAUSE_RX;
   1986     }
   1987     if(local_ability & BSDK_PHY84728_PA_PAUSE_ASYMM) {
   1988         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1989     }
   1990     if(local_ability & BSDK_PHY84728_PA_LB_NONE) {
   1991         ability->loopback |= SOC_PA_LB_NONE;
   1992     }
   1993     if(local_ability & BSDK_PHY84728_PA_LB_PHY) {
   1994         ability->loopback |= SOC_PA_LB_PHY;
   1995     }
   1996     if(local_ability & BSDK_PHY84728_PA_AN) {
   1997         ability->flags = SOC_PA_AUTONEG;
   1998     }
   1999 
   2000     return SOC_E_NONE;
   2001 }
   2002 
   2003 STATIC int
   2004 _phy_84728_init_ucode_bcst(int unit, int port, int cmd)
   2005 {
   2006     uint16 data16;
   2007     int j;
   2008     uint16 num_words;
   2009     uint8 *fw_ptr;
   2010     int fw_length;
   2011     phy_ctrl_t *pc;
   2012 
   2013     pc = EXT_PHY_SW_STATE(unit, port);
   2014 
   2015     if (cmd == PHYCTRL_UCODE_BCST_SETUP) {
   2016 
   2017         LOG_INFO(BSL_LS_SOC_PHY,
   2018                  (BSL_META_U(unit,
   2019                              "PHY84740 BCST start: u=%d p=%d\n"), unit, port));
   2020         SOC_IF_ERROR_RETURN
   2021             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc8fe, 0xffff));
   2022         return SOC_E_NONE;
   2023 
   2024     } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) {
   2025         LOG_INFO(BSL_LS_SOC_PHY,
   2026                  (BSL_META_U(unit,
   2027                              "PHY84740 BCST1: u=%d p=%d\n"), unit, port));
   2028         /* 0xc848[15]=0, MDIO downloading to RAM, 0xc848[14]=1, serial boot */
   2029         /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */
   2030         SOC_IF_ERROR_RETURN(
   2031             BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc848,
   2032                                            (0 << 15)|(1 << 14),
   2033                                            (1 << 15)|(1 << 14)|((1 << 13) | (1 << 2))));
   2034 
   2035         /* apply bcst Reset to start download code from MDIO */
   2036         SOC_IF_ERROR_RETURN
   2037             (BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, 0x8000));
   2038         return SOC_E_NONE;
   2039     } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) {
   2040         LOG_INFO(BSL_LS_SOC_PHY,
   2041                  (BSL_META_U(unit,
   2042                              "PHY84740 BCST2: u=%d p=%d\n"), unit, port));
   2043         /* reset clears bcst register */
   2044         /* restore bcst register after reset */
   2045         SOC_IF_ERROR_RETURN
   2046             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc8fe, 0xffff));
   2047         return SOC_E_NONE;
   2048 
   2049     } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) {
   2050         LOG_INFO(BSL_LS_SOC_PHY,
   2051                  (BSL_META_U(unit,
   2052                              "firmware_bcst,device name %s: u=%d p=%d\n"),
   2053                              pc->dev_name? pc->dev_name: "NULL", unit, port));
   2054         /* find the right firmware */
   2055         /* MDIO based firmware download to RAM */
   2056         if (BSDK_PHY84728_IS_84728(PHY84728_MAP(pc)->devid)) {
   2057             fw_ptr = bcm84728_fw;
   2058             fw_length = bcm84728_fw_length;
   2059         } else { /* non-84728 device */
   2060             fw_ptr = bcm84748_fw;
   2061             fw_length = bcm84748_fw_length;
   2062         }
   2063 
   2064         /* wait for 2ms for M8051 start and 5ms to initialize the RAM */
   2065         sal_usleep(10000); /* Wait for 10ms */
   2066 
   2067         /* Write Starting Address, where the Code will reside in SRAM */
   2068         data16 = 0x8000;
   2069         SOC_IF_ERROR_RETURN
   2070             (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, data16));
   2071 
   2072         /* make sure address word is read by the micro */
   2073         sal_udelay(10); /* Wait for 10us */
   2074 
   2075         /* Write SPI SRAM Count Size */
   2076         data16 = (fw_length)/2;
   2077         SOC_IF_ERROR_RETURN
   2078             (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, data16));
   2079 
   2080         /* make sure read by the micro */
   2081         sal_udelay(10); /* Wait for 10us */
   2082 
   2083         /* Fill in the SRAM */
   2084         num_words = (fw_length - 1);
   2085         for (j = 0; j < num_words; j+=2) {
   2086             /* Make sure the word is read by the Micro */
   2087             sal_udelay(10);
   2088             data16 = (fw_ptr[j] << 8) | fw_ptr[j+1];
   2089             SOC_IF_ERROR_RETURN
   2090                 (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, data16));
   2091         }
   2092         return SOC_E_NONE;
   2093 
   2094     } else if (cmd == PHYCTRL_UCODE_BCST_END) {
   2095         LOG_INFO(BSL_LS_SOC_PHY,
   2096                  (BSL_META_U(unit,
   2097                              "PHY84740 BCST end: u=%d p=%d\n"), unit, port));
   2098 
   2099         /* make sure last code word is read by the micro */
   2100         sal_udelay(20);
   2101 
   2102         /* first disable bcst mode */
   2103         SOC_IF_ERROR_RETURN
   2104             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc8fe, 0));
   2105         
   2106         /* Read Hand-Shake message (Done) from Micro */
   2107         SOC_IF_ERROR_RETURN
   2108             (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &data16));
   2109         if (data16 != 0x4321 ) {
   2110             /* Download done message */
   2111             LOG_CLI((BSL_META_U(unit,
   2112                                 "MDIO firmware download failed. Message: 0x%x\n"),
   2113                      data16));
   2114             return SOC_E_FAIL;
   2115         }
   2116 
   2117         /* Download done message */
   2118         LOG_INFO(BSL_LS_SOC_PHY,
   2119                  (BSL_META_U(unit,
   2120                              "u=%d p=%d MDIO firmware download done message: 0x%x\n"),
   2121                              unit, port,data16));
   2122         
   2123         /* Clear LASI status */
   2124         SOC_IF_ERROR_RETURN
   2125             (BSDK_RD_PHY84728_LN_DEV1_RX_ALARMr(pc, &data16));
   2126 
   2127         /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */
   2128         sal_udelay(100); /* Wait for 100 usecs */
   2129 
   2130         SOC_IF_ERROR_RETURN
   2131             (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &data16));
   2132 
   2133         /* Need to check if checksum is correct */
   2134         SOC_IF_ERROR_RETURN
   2135             (BSDK_RD_PHY84728_LN_DEV1_CHECKSUMr(pc, &data16));
   2136 
   2137         if (data16 != 0x600D) {
   2138             /* Bad CHECKSUM */
   2139             LOG_CLI((BSL_META_U(unit,
   2140                                 "firmware_bcst downlad failure: port %d "
   2141                                 "Incorrect Checksum %x\n"), port, data16));
   2142             return SOC_E_FAIL;
   2143         }
   2144 
   2145         /* read Rev-ID */
   2146         SOC_IF_ERROR_RETURN
   2147             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xCA1A, &data16));
   2148         LOG_ERROR(BSL_LS_SOC_PHY,
   2149                   (BSL_META_U(unit,
   2150                               "u=%d p=%d MDIO Firmware broadcast download revID: 0x%x\n"),
   2151                               unit, port,data16));
   2152 
   2153         return SOC_E_NONE;
   2154 
   2155     } else {
   2156         LOG_WARN(BSL_LS_SOC_PHY,
   2157                  (BSL_META_U(unit,
   2158                              "u=%d p=%d firmware_bcst: invalid cmd 0x%x\n"),
   2159                              unit, port,cmd));
   2160     }
   2161 
   2162     return SOC_E_FAIL;
   2163 }
   2164 
   2165 
   2166 /*
   2167  * Function:
   2168  *      phy_84728_firmware_set
   2169  * Purpose:
   2170  *      program the given firmware into the SPI-ROM
   2171  * Parameters:
   2172  *      unit - StrataSwitch unit #.
   2173  *      port - StrataSwitch port #.
   2174  *      offset - offset to the data stream
   2175  *      array  - the given data
   2176  *      datalen- the data length
   2177  * Returns:
   2178  *      SOC_E_NONE
   2179  */
   2180 
   2181 STATIC int
   2182 phy_84728_firmware_set(int unit, int port, int offset, uint8 *data, int len)
   2183 {
   2184     int            rv;
   2185     phy_ctrl_t *pc;
   2186 
   2187     if (data == NULL) {
   2188         return _phy_84728_init_ucode_bcst(unit, port, offset);
   2189     }
   2190 
   2191     pc = EXT_PHY_SW_STATE(unit, port);
   2192 
   2193     rv = bsdk_phy84728_spi_firmware_update(pc, data, len);
   2194     if (rv != SOC_E_NONE) {
   2195             LOG_WARN(BSL_LS_SOC_PHY,
   2196                      (BSL_META_U(unit,
   2197                                  "PHY84728 firmware upgrade possibly failed:"
   2198                                  "u=%d p=%d\n"), unit, port));
   2199         return (SOC_E_FAIL);
   2200     }
   2201     LOG_INFO(BSL_LS_SOC_PHY,
   2202              (BSL_META_U(unit,
   2203                          "PHY84728 firmware upgrade successful:"
   2204                          "u=%d p=%d\n"), unit, port));
   2205 
   2206     return SOC_E_NONE;
   2207 }
   2208 
   2209 /*
   2210  * Function:
   2211  *      phy_84728_medium_status
   2212  * Purpose:
   2213  *      Indicate the current active medium
   2214  * Parameters:
   2215  *      unit - StrataSwitch unit #.
   2216  *      port - StrataSwitch port #.
   2217  *      medium - (OUT) One of:
   2218  *              SOC_PORT_MEDIUM_COPPER
   2219  *              SOC_PORT_MEDIUM_XAUI
   2220  * Returns:
   2221  *      SOC_E_NONE
   2222  */
   2223 
   2224 STATIC int
   2225 phy_84728_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium)
   2226 {
   2227     phy_ctrl_t *pc;
   2228 
   2229     pc = EXT_PHY_SW_STATE(unit, port);
   2230 
   2231     if (NXT_PC(pc)) {
   2232         PHYDRV_CALL_ARG1(pc,PHY_MEDIUM_GET, medium);
   2233         return SOC_E_NONE;
   2234     }
   2235     if (PHY_COPPER_MODE(unit, port)) {
   2236         *medium = SOC_PORT_MEDIUM_COPPER;
   2237     } else {
   2238         *medium = SOC_PORT_MEDIUM_FIBER;
   2239     }
   2240 
   2241 
   2242     return SOC_E_NONE;
   2243 }
   2244 
   2245 
   2246 /*
   2247  * Function:
   2248  *      phy_84728_control_set
   2249  * Purpose:
   2250  *      Configure PHY device specific control fucntion.
   2251  * Parameters:
   2252  *      unit  - StrataSwitch unit #.
   2253  *      port  - StrataSwitch port #.
   2254  *      type  - Control to update
   2255  *      value - New setting for the control
   2256  * Returns:    
   2257  *      SOC_E_NONE
   2258  */
   2259 STATIC int
   2260 phy_84728_control_set(int unit, soc_port_t port,
   2261                      soc_phy_control_t type, uint32 value)
   2262 {
   2263     int rv;
   2264     phy_ctrl_t *pc;
   2265     uint16 regval = 0;
   2266 
   2267     PHY_CONTROL_TYPE_CHECK(type);
   2268     
   2269     pc = EXT_PHY_SW_STATE(unit, port);
   2270     rv = SOC_E_UNAVAIL;    
   2271 
   2272     if (NXT_PC(pc)) {
   2273         PHYDRV_CALL_ARG2(pc, PHY_CONTROL_SET, type, value);
   2274         return SOC_E_NONE;
   2275     }
   2276 
   2277     switch(type) {
   2278         case SOC_PHY_CONTROL_WAN:
   2279             rv = _phy_84728_mode_set(unit, port, 
   2280                                        value ? WAN_MODE : LAN_MODE);
   2281             break;
   2282 
   2283         case SOC_PHY_CONTROL_EDC_MODE:
   2284             rv = _phy_84728_control_edc_mode_set(unit,port,value);
   2285             break;    
   2286 
   2287         case SOC_PHY_CONTROL_CLOCK_ENABLE:
   2288 
   2289             if(value) {
   2290                 regval = (1 << 10);
   2291             }
   2292             SOC_IF_ERROR_RETURN
   2293                 (BSDK_PHY84728_REG_MOD(pc, 0x01,0x01,0xca23,regval,0x400));
   2294 
   2295             rv = SOC_E_NONE;
   2296             break;
   2297 
   2298         case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   2299 
   2300             switch(value)
   2301             {
   2302                 case 125000: /* for 125 MHz */
   2303                     regval = 1;
   2304                     break;
   2305                 case 19531: /* for 19.53125 MHz */
   2306                     regval = 2;
   2307                     break;
   2308                 case 156250:
   2309                     regval = 3; /* for 156.25 MHz */
   2310                     break;
   2311                 default:
   2312                     return SOC_E_PARAM;
   2313                     break;
   2314             }
   2315             regval = (regval << 14); /* programming the frequency */
   2316             regval |= (1 << 13);
   2317 
   2318             SOC_IF_ERROR_RETURN
   2319                 (BSDK_PHY84728_REG_MOD(pc, 0x01,0x01,0xcace,regval, 0xe000));
   2320             rv = SOC_E_NONE;
   2321             break;
   2322         case SOC_PHY_CONTROL_PARALLEL_DETECTION: 
   2323             rv = _phy_84728_control_pdet_set(unit, port, value);
   2324             break;
   2325 
   2326         default:
   2327             break; 
   2328     }
   2329     return rv;
   2330 }
   2331 
   2332 /*
   2333  * Function:
   2334  *      phy_84728_control_get
   2335  * Purpose:
   2336  *      Get current control settign of the PHY.
   2337  * Parameters:
   2338  *      unit  - StrataSwitch unit #.
   2339  *      port  - StrataSwitch port #.
   2340  *      type  - Control to update
   2341  *      value - (OUT)Current setting for the control
   2342  * Returns:
   2343  *      SOC_E_NONE
   2344  */
   2345 STATIC int 
   2346 phy_84728_control_get(int unit, soc_port_t port,
   2347                      soc_phy_control_t type, uint32 *value)
   2348 {
   2349     int    rv;
   2350     uint16 temp16;
   2351     phy_ctrl_t *pc;
   2352 
   2353     if (NULL == value) {
   2354         return SOC_E_PARAM;
   2355     }
   2356 
   2357     PHY_CONTROL_TYPE_CHECK(type);
   2358 
   2359     pc = EXT_PHY_SW_STATE(unit, port);
   2360     rv = SOC_E_UNAVAIL;
   2361 
   2362     if (NXT_PC(pc)) {
   2363         PHYDRV_CALL_ARG2(pc, PHY_CONTROL_GET, type, value);
   2364         return SOC_E_NONE;
   2365     }
   2366 
   2367     switch(type) {
   2368         case SOC_PHY_CONTROL_WAN:
   2369             *value = PHY_WAN_MODE(unit, port) ? 1 : 0;   
   2370             rv = SOC_E_NONE;
   2371             break;
   2372 
   2373         case SOC_PHY_CONTROL_EDC_MODE:
   2374             rv = _phy_84728_control_edc_mode_get(unit,port,value);
   2375             break;    
   2376 
   2377         case SOC_PHY_CONTROL_CLOCK_ENABLE:
   2378 
   2379             {
   2380                 SOC_IF_ERROR_RETURN
   2381                 (BSDK_PHY84728_REG_RD(pc, 0x01,0x01,0xca23,&temp16));
   2382                 *value = (temp16 & (0x1 << 10))? TRUE : FALSE;
   2383             }
   2384             rv = SOC_E_NONE;
   2385             break;
   2386 
   2387         case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   2388 
   2389 
   2390             SOC_IF_ERROR_RETURN
   2391             (BSDK_PHY84728_REG_RD(pc, 0x01,0x01,0xcace,&temp16));
   2392 
   2393             if(temp16 & (0x1 << 13))
   2394             {
   2395                 switch(temp16 >> 14)
   2396                 {
   2397                     case 1: /* for 125 MHz */
   2398                         *value = 125000;
   2399                         break;
   2400                     case 2: /* for 19.53125 MHz */
   2401                         *value = 19531;
   2402                         break;
   2403                     case 3:
   2404                         *value = 156250; /* for 156.25 MHz */
   2405                         break;
   2406                     default:
   2407                         *value = 0;
   2408                         break;
   2409                 }
   2410                 if(*value) {
   2411                     rv = SOC_E_NONE;
   2412                 } else {
   2413                     rv = SOC_E_UNAVAIL;
   2414                 }
   2415             } else {
   2416                 rv = SOC_E_DISABLED;
   2417             }
   2418             break;
   2419         case SOC_PHY_CONTROL_PARALLEL_DETECTION:
   2420             rv = _phy_84728_control_pdet_get(unit, port, value);
   2421             break; 
   2422 
   2423         default:
   2424             break;
   2425     }
   2426     return rv;
   2427 }
   2428 
   2429 /*
   2430  * Function:
   2431  *      phy_84728_link_up
   2432  * Purpose:
   2433  *      Link up handler
   2434  * Parameters:
   2435  *      unit  - StrataSwitch unit #.
   2436  *      port  - StrataSwitch port #.
   2437  * Returns:
   2438  *      SOC_E_NONE
   2439  */
   2440 STATIC int 
   2441 phy_84728_link_up(int unit, soc_port_t port)
   2442 {
   2443 
   2444     /* After link up configure the system side to operate at 10G */
   2445     phy_ctrl_t *pc;
   2446     bsdk_phy84728_intf_t line_mode;
   2447     int speed;
   2448 
   2449     pc = EXT_PHY_SW_STATE(unit, port);
   2450 
   2451     SOC_IF_ERROR_RETURN
   2452         (phy_84728_speed_get(unit, port, &speed));
   2453 
   2454     if (NXT_PC(pc)) {
   2455         PHYDRV_CALL_NOARG(pc, PHY_LINKUP_EVT);
   2456         /* PHYDRV_CALL_ARG1(pc,PHY_SPEED_GET, &speed); */
   2457         if (speed == 10000) {
   2458             line_mode = BSDK_PHY84728_INTF_SFI;
   2459             SOC_IF_ERROR_RETURN(
   2460                 bsdk_phy84728_sys_mode_set(pc, 0, 
   2461                                  BSDK_PHY84728_INTF_XAUI));
   2462         } else if (speed == 1000) {
   2463             if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_COPPER)) {
   2464                 line_mode = BSDK_PHY84728_INTF_SGMII;
   2465                 SOC_IF_ERROR_RETURN(
   2466                     bsdk_phy84728_sys_mode_set(pc, 0, 
   2467                                      BSDK_PHY84728_INTF_SGMII));
   2468             } else {
   2469                 line_mode = BSDK_PHY84728_INTF_1000X;
   2470                 SOC_IF_ERROR_RETURN(
   2471                     bsdk_phy84728_sys_mode_set(pc, 0, 
   2472                                      BSDK_PHY84728_INTF_1000X));
   2473             }
   2474         } else {
   2475             line_mode = BSDK_PHY84728_INTF_SGMII;
   2476             SOC_IF_ERROR_RETURN(
   2477                 bsdk_phy84728_sys_mode_set(pc, 0, 
   2478                                  BSDK_PHY84728_INTF_SGMII));
   2479         }
   2480         SOC_IF_ERROR_RETURN
   2481             (bsdk_phy84728_line_mode_set(pc, 0, line_mode));
   2482 
   2483         SOC_IF_ERROR_RETURN
   2484             (bsdk_phy84728_speed_set(pc, speed));
   2485     }
   2486 
   2487     SOC_IF_ERROR_RETURN(
   2488         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   2489 
   2490     if (line_mode == BSDK_PHY84728_INTF_SGMII) {
   2491         SOC_IF_ERROR_RETURN(
   2492             _bsdk_phy84728_system_sgmii_sync(pc, 0));
   2493         SOC_IF_ERROR_RETURN
   2494             (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII));
   2495     }
   2496 #if 0   /* don't need to notify if speed is 10G */
   2497     else {
   2498         SOC_IF_ERROR_RETURN
   2499             (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_XAUI));
   2500     }
   2501 #endif
   2502 
   2503     if (PHY84728_MAP(pc)->link_down) {      /* was link down */
   2504         if ( speed < 10000 ) {    /* don't need to notify if speed is 10G */
   2505             SOC_IF_ERROR_RETURN
   2506                 (soc_phyctrl_notify(unit, port, phyEventSpeed, speed));
   2507         }
   2508         PHY84728_MAP(pc)->link_down = 0;    /* link is up now */
   2509     }
   2510 
   2511     if ((line_mode == BSDK_PHY84728_INTF_SGMII) || (line_mode == BSDK_PHY84728_INTF_1000X)) {
   2512         SOC_IF_ERROR_RETURN(
   2513             bsdk_phy84728_lane_map(pc));
   2514     }
   2515 
   2516     return SOC_E_NONE;
   2517 }
   2518 
   2519 /*
   2520  * Function:
   2521  *      phy_84728_link_down
   2522  * Purpose:
   2523  *      Link down handler
   2524  * Parameters:
   2525  *      unit  - StrataSwitch unit #.
   2526  *      port  - StrataSwitch port #.
   2527  * Returns:
   2528  *      SOC_E_NONE
   2529  */
   2530 STATIC int
   2531 phy_84728_link_down(int unit, soc_port_t port)
   2532 {
   2533 
   2534     /* After link up configure the system side to operate at 10G */
   2535     phy_ctrl_t *pc;
   2536 
   2537     pc = EXT_PHY_SW_STATE(unit, port);
   2538 
   2539     PHY84728_MAP(pc)->link_down = 1;
   2540     return SOC_E_NONE;
   2541 }
   2542 
   2543 
   2544 /*
   2545  * Function:
   2546  *      phy_84728_interface_get
   2547  * Purpose:
   2548  *      Get interface on a given port.
   2549  * Parameters:
   2550  *      unit  - StrataSwitch unit #.
   2551  *      port  - StrataSwitch port #.
   2552  *      pif   - Interface.
   2553  * Returns:
   2554  *      SOC_E_NONE
   2555  */
   2556 STATIC int
   2557 phy_84728_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   2558 {
   2559     phy_ctrl_t *pc;
   2560     bsdk_phy84728_intf_t line_mode;
   2561 
   2562     pc = EXT_PHY_SW_STATE(unit, port);
   2563 
   2564     SOC_IF_ERROR_RETURN(
   2565         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   2566 
   2567     if (line_mode == BSDK_PHY84728_INTF_SGMII) {
   2568         *pif =  SOC_PORT_IF_SGMII;
   2569     } else {
   2570         *pif =  SOC_PORT_IF_XGMII;
   2571     }
   2572 
   2573     return SOC_E_NONE;
   2574 }
   2575 
   2576 /*
   2577  * Function:
   2578  *      phy_84728_probe
   2579  * Purpose:
   2580  *      Complement the generic phy probe routine to identify this phy when its
   2581  *      phy id0 and id1 is same as some other phy's.
   2582  * Parameters:
   2583  *      unit - StrataSwitch unit #.
   2584  *      pc   - phy ctrl descriptor.
   2585  * Returns:
   2586  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   2587  */
   2588 STATIC int
   2589 phy_84728_probe(int unit, phy_ctrl_t *pc)
   2590 {
   2591     uint16  data1, data2;
   2592 
   2593     if (READ_PHY84728_PMA_PMD_REG(unit, pc, 0xc802, &data1) < 0) {
   2594         return SOC_E_NOT_FOUND;
   2595     }
   2596 
   2597     if (READ_PHY84728_PMA_PMD_REG(unit, pc, 0xc803, &data2) < 0) {
   2598         return SOC_E_NOT_FOUND;
   2599     }
   2600 
   2601     if ((data2 & 0xf) == 0x8) {
   2602 
   2603         switch (data1) {
   2604 
   2605             case 0x4707:
   2606             case 0x4073:
   2607             case 0x4074:
   2608             case 0x4728:
   2609             case 0x4748:
   2610             case 0x4727:
   2611             case 0x4747:
   2612             case 0x4722:
   2613             case 0x4742:
   2614             case 0x4762:
   2615             case 0x4764:
   2616             case 0x4042:
   2617             case 0x4044:
   2618 
   2619                 pc->size = sizeof(phy84728_map_t);
   2620                 return SOC_E_NONE;
   2621         }
   2622     }
   2623 
   2624     if ((data2 & 0xf) == 0x5) {
   2625 
   2626         switch (data1) {
   2627 
   2628             case 0x4942:
   2629 
   2630                 pc->size = sizeof(phy84728_map_t);
   2631                 return SOC_E_NONE;
   2632         }
   2633     }
   2634 
   2635     return SOC_E_NOT_FOUND;
   2636 }
   2637 
   2638 /*
   2639  * Function:     
   2640  *    _phy84728_get_model_rev
   2641  * Purpose:    
   2642  *    Get OUI, Model and Revision of the PHY
   2643  * Parameters:
   2644  *    phy_dev_addr - PHY Device Address
   2645  *    oui          - (OUT) Organization Unique Identifier
   2646  *    model        - (OUT)Device Model number`
   2647  *    rev          - (OUT)Device Revision number
   2648  * Notes: 
   2649  */
   2650 int 
   2651 _phy84728_get_model_rev(phy_ctrl_t *pc,
   2652                        int *oui, int *model, int *rev)
   2653 {
   2654     uint16  id0, id1;
   2655 
   2656     SOC_IF_ERROR_RETURN
   2657             (BSDK_RD_PHY84728_LN_DEV1_PMD_ID0r(pc, &id0));
   2658 
   2659     SOC_IF_ERROR_RETURN
   2660             (BSDK_RD_PHY84728_LN_DEV1_PMD_ID1r(pc, &id1));
   2661 
   2662     *oui   = BSDK_PHY84728_PHY_OUI(id0, id1);
   2663     *model = BSDK_PHY84728_PHY_MODEL(id0, id1);
   2664     *rev   = BSDK_PHY84728_PHY_REV(id0, id1);
   2665 
   2666     return SOC_E_NONE;
   2667 }
   2668 
   2669 
   2670 
   2671 /*
   2672  * Function:
   2673  *     bsdk_phy84728_firmware_spi_download
   2674  * Purpose:
   2675  *     Download firmware via SPI
   2676  *         - Check if firmware download is complete
   2677  *         - Check if the checksum is good
   2678  * Parameters:
   2679  *    phy_id    - PHY Device Address
   2680  * Returns:
   2681  */
   2682 /* STATIC int */
   2683 int
   2684 bsdk_phy84728_firmware_spi_download(phy_ctrl_t *pc)
   2685 {
   2686     uint16 data = 0;
   2687     int i;
   2688 
   2689     /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */
   2690     /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */
   2691     SOC_IF_ERROR_RETURN(
   2692            BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc848, 
   2693                (1 << 15)|(1 << 14), 
   2694                ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 2))));
   2695 
   2696     /* apply software reset to download code from SPI-ROM */
   2697     /* Reset the PHY **/
   2698     SOC_IF_ERROR_RETURN(
   2699            BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 
   2700                BSDK_PHY84728_PMD_CTRL_RESET, BSDK_PHY84728_PMD_CTRL_RESET));
   2701 
   2702     for (i = 0; i < 5; i++) {
   2703         sal_usleep(100000);
   2704         SOC_IF_ERROR_RETURN(
   2705                BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc848, &data));
   2706         if (data & 0x2000) {  /* Check for download complete */
   2707             /* Need to check if checksum is correct */
   2708             SOC_IF_ERROR_RETURN(
   2709                    BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xca1c, &data));
   2710             if (data == 0x600D) {
   2711                 break;
   2712             }
   2713         }
   2714     }
   2715     if (i >= 5) { /* Bad CHECKSUM */
   2716         LOG_CLI((BSL_META_U(pc->unit,
   2717                             "SPI-Download Firmware download failure:"
   2718                             "Incorrect Checksum %x\n"), data));
   2719         return SOC_E_FAIL;
   2720     }
   2721 
   2722     SOC_IF_ERROR_RETURN(
   2723            BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xca1a, &data));
   2724 
   2725     LOG_CLI((BSL_META_U(pc->unit,
   2726                         "BCM84728: u=%d p=%d: SPI-ROM download complete: "
   2727                         "Version: 0x%x\n"), 
   2728              pc->unit, pc->port, data));
   2729 
   2730     return SOC_E_NONE;
   2731 }
   2732 
   2733 /*
   2734  * Function:     
   2735  *    bsdk_phy84728_line_intf_get
   2736  * Purpose:    
   2737  *    Determine the Line side Interface
   2738  * Parameters:
   2739  *    phy_id    - PHY's device address
   2740  *    dev_port  - Channel number 
   2741  *    mode      - (OUT) Line Port mode status
   2742  * Returns:    
   2743  */
   2744 int 
   2745 bsdk_phy84728_line_intf_get(phy_ctrl_t *pc, int dev_port, 
   2746                               bsdk_phy84728_intf_t *mode)
   2747 {
   2748 
   2749     phy84728_map_t      *phy_info;
   2750 
   2751     if (mode == NULL) {
   2752         return SOC_E_PARAM;
   2753     }
   2754 
   2755     phy_info = PHY84728_MAP(pc);
   2756 
   2757     *mode = phy_info->line_mode;
   2758     return SOC_E_NONE;
   2759 }
   2760 
   2761 
   2762 
   2763 /*
   2764  * Function:     
   2765  *    bsdk_phy84728_line_mode_set
   2766  * Purpose:    
   2767  *    Set the Line side mode
   2768  * Parameters:
   2769  *    phy_id    - PHY's device address
   2770  *    dev_port  - Channel number 
   2771  *    mode      - Desired mode (SGMII/1000x/SFI)
   2772  * Returns:    
   2773  */
   2774 int
   2775 bsdk_phy84728_line_mode_set(phy_ctrl_t *pc, int dev_port, 
   2776                               bsdk_phy84728_intf_t mode)
   2777 {
   2778 
   2779     int rv = SOC_E_NONE;
   2780     phy84728_map_t      *phy_info;
   2781 
   2782     phy_info = PHY84728_MAP(pc);
   2783 
   2784     /* Disable Autodetect */
   2785     SOC_IF_ERROR_RETURN(
   2786         BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 0,
   2787                        BSDK_PHY84728_AN_BASE1000X_CTRL1_AUTODETECT_EN));
   2788     switch (mode) {
   2789 
   2790     case BSDK_PHY84728_INTF_SGMII :
   2791 
   2792         SOC_IF_ERROR_RETURN(
   2793             BSDK_WR_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_COMMA_DET_EN |
   2794                                                              BSDK_PHY84728_AN_BASE1000X_CTRL1_CRC_CHK_DIS |
   2795                                                              BSDK_PHY84728_AN_BASE1000X_CTRL1_SD_ENABLE));
   2796         SOC_IF_ERROR_RETURN(
   2797             BSDK_WR_PHY84728_LN_DEV7_AN_MISC1r(pc, 0x6000));
   2798         SOC_IF_ERROR_RETURN(
   2799             BSDK_MOD_PHY84728_LN_DEV7_AN_MSIC2r(pc, BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL, 
   2800                                                     BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL |
   2801                                                     BSDK_PHY84728_AN_MISC2_PMA_PMD_FORCED_SPEED_ENC_EN));
   2802         SOC_IF_ERROR_RETURN(
   2803             BSDK_WR_PHY84728_LN_DEV7_AN_SGMII_BASEPAGEr(pc, 0x0801));
   2804         SOC_IF_ERROR_RETURN(
   2805             BSDK_WR_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, BSDK_PHY84728_AN_MII_CTRL_AE |
   2806                                                       BSDK_PHY84728_AN_MII_CTRL_FD |
   2807                                                       BSDK_PHY84728_AN_MII_CTRL_SS_1000));
   2808         break;
   2809         
   2810     case BSDK_PHY84728_INTF_1000X :
   2811         SOC_IF_ERROR_RETURN(
   2812             BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE,
   2813                      BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE));
   2814             /* Set PMA speed */
   2815             SOC_IF_ERROR_RETURN(
   2816                 BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, BSDK_PHY84728_PMD_CTRL_SS_1000));
   2817         break;
   2818 
   2819     case BSDK_PHY84728_INTF_SFI :
   2820         SOC_IF_ERROR_RETURN(
   2821             BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE,
   2822                      BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE));
   2823         /* Set PMA speed */
   2824         SOC_IF_ERROR_RETURN(
   2825             BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, BSDK_PHY84728_PMD_CTRL_SS_10000));
   2826         break;
   2827 
   2828     default :
   2829         rv = SOC_E_PARAM;
   2830         break;
   2831         
   2832     }
   2833 
   2834     if (SOC_SUCCESS(rv)) {
   2835         phy_info->line_mode = mode;
   2836     }
   2837     return rv;
   2838 }
   2839 
   2840 
   2841 /*
   2842  * Function:     
   2843  *    bsdk_phy84728_sys_intf_get
   2844  * Purpose:    
   2845  *    Determine the System side Interface
   2846  * Parameters:
   2847  *    phy_id    - PHY's device address
   2848  *    dev_port  - Channel number 
   2849  *    mode      - (OUT) System side mode status
   2850  * Returns:    
   2851  */
   2852 int 
   2853 bsdk_phy84728_sys_intf_get(phy_ctrl_t *pc, int dev_port, 
   2854                              bsdk_phy84728_intf_t *mode)
   2855 {
   2856 
   2857     phy84728_map_t      *phy_info;
   2858 
   2859     if (mode == NULL) {
   2860         return SOC_E_PARAM;
   2861     }
   2862 
   2863     phy_info = PHY84728_MAP(pc);
   2864 
   2865     /* System will always follow line side interface */
   2866     *mode = phy_info->line_mode;
   2867 
   2868     return SOC_E_NONE;
   2869 }
   2870 
   2871 
   2872 
   2873 /*
   2874  * Function:     
   2875  *    bsdk_phy84728_sys_mode_set
   2876  * Purpose:    
   2877  *    Set the system side mode
   2878  * Parameters:
   2879  *    phy_id    - PHY's device address
   2880  *    dev_port  - Channel number 
   2881  *    mode      - Desired mode (SGMII/1000x/XFI)
   2882  * Returns:    
   2883  */
   2884 int
   2885 bsdk_phy84728_sys_mode_set(phy_ctrl_t *pc, int dev_port, 
   2886                               bsdk_phy84728_intf_t mode)
   2887 {
   2888     int rv = SOC_E_NONE;
   2889 
   2890     /* Disable Autodetect */
   2891     SOC_IF_ERROR_RETURN(
   2892         BSDK_MOD_PHY84728_SYS_DEV4_XGXS_BASE1000X_CTRL1r(pc, 0,
   2893                        BSDK_PHY84728_AN_BASE1000X_CTRL1_AUTODETECT_EN));
   2894     switch (mode) {
   2895     case BSDK_PHY84728_INTF_SGMII :
   2896         SOC_IF_ERROR_RETURN(
   2897             BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, 0x0000, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ));
   2898 
   2899         SOC_IF_ERROR_RETURN(
   2900             BSDK_WR_PHY84728_SYS_DEV4_XGXS_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_COMMA_DET_EN|
   2901                                                             BSDK_PHY84728_AN_BASE1000X_CTRL1_CRC_CHK_DIS |
   2902                                                             BSDK_PHY84728_AN_BASE1000X_CTRL1_SGMII_MASTER));
   2903 
   2904         SOC_IF_ERROR_RETURN(
   2905             BSDK_WR_PHY84728_SYS_DEV4_XGXS_MISC1r(pc, 0x6000));
   2906 
   2907         SOC_IF_ERROR_RETURN(
   2908             BSDK_MOD_PHY84728_SYS_DEV4_XGXS_MISC2r(pc, BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL, 
   2909                                                    BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL |
   2910                                                    BSDK_PHY84728_AN_MISC2_PMA_PMD_FORCED_SPEED_ENC_EN));
   2911 
   2912         SOC_IF_ERROR_RETURN(
   2913             BSDK_WR_PHY84728_SYS_DEV4_XGXS_SGMII_BASEPAGEr(pc, 0x0001));
   2914 
   2915         SOC_IF_ERROR_RETURN(
   2916             BSDK_WR_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, BSDK_PHY84728_AN_MII_CTRL_FD |
   2917                                                          BSDK_PHY84728_AN_MII_CTRL_SS_1000));
   2918 
   2919         SOC_IF_ERROR_RETURN(
   2920             BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ,
   2921                                                       BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ));
   2922 
   2923         break;
   2924         
   2925     case BSDK_PHY84728_INTF_1000X :
   2926         SOC_IF_ERROR_RETURN(
   2927             BSDK_WR_PHY84728_SYS_DEV4_XGXS_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_COMMA_DET_EN|
   2928                                                             BSDK_PHY84728_AN_BASE1000X_CTRL1_CRC_CHK_DIS |
   2929                                                             BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE));
   2930         break;
   2931 
   2932     case BSDK_PHY84728_INTF_XAUI :
   2933         SOC_IF_ERROR_RETURN(
   2934             BSDK_WR_PHY84728_SYS_DEV4_XGXS_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_COMMA_DET_EN|
   2935                                                             BSDK_PHY84728_AN_BASE1000X_CTRL1_CRC_CHK_DIS |
   2936                                                             BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE));
   2937         break;
   2938 
   2939     default :
   2940         rv = SOC_E_PARAM;
   2941         break;
   2942     }
   2943 
   2944     return rv;
   2945 }
   2946 
   2947 
   2948 /*
   2949  * Function:     
   2950  *    bsdk_phy84728_no_reset_setup
   2951  * Purpose:    
   2952  *    Initialize the PHY without reset.
   2953  * Parameters:
   2954  *    phy_dev_addr        - PHY Device Address
   2955  *    line_mode           - Line side Mode (SGMII/1000X/SFI).
   2956  *    fcmap_enable        - Fibre Channel enabled or disabled.
   2957  * Notes: 
   2958  */
   2959 int
   2960 bsdk_phy84728_no_reset_setup(phy_ctrl_t *pc, int line_mode,
   2961                                int phy_ext_boot)
   2962 {
   2963     if ((line_mode != BSDK_PHY84728_INTF_SGMII) &&
   2964         (line_mode != BSDK_PHY84728_INTF_1000X) && 
   2965         (line_mode != BSDK_PHY84728_INTF_SFI)) {
   2966         return SOC_E_CONFIG;
   2967     }
   2968 
   2969     /* Enable Power - PMA/PMD, PCS, AN */
   2970     SOC_IF_ERROR_RETURN(
   2971          BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 0,
   2972                                         BSDK_PHY84728_PMD_CTRL_PD));
   2973     SOC_IF_ERROR_RETURN(
   2974         BSDK_MOD_PHY84728_LN_DEV3_PCS_CTRLr(pc, 0,
   2975                                        BSDK_PHY84728_PCS_PCS_CTRL_PD));
   2976     SOC_IF_ERROR_RETURN(
   2977         BSDK_MOD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, 0,
   2978                                        BSDK_PHY84728_AN_MII_CTRL_PD));
   2979     if (phy_ext_boot) {
   2980         /* Download firmware if via SPI */
   2981         SOC_IF_ERROR_RETURN(bsdk_phy84728_firmware_spi_download(pc));
   2982     }  else if (!(pc->flags & PHYCTRL_MDIO_BCST)) {
   2983         /* MDIO based firmware download to RAM */
   2984         if (BSDK_PHY84728_IS_84728(PHY84728_MAP(pc)->devid)) {
   2985             SOC_IF_ERROR_RETURN(
   2986                 bsdk_phy84728_mdio_firmware_download(pc,
   2987                                                     bcm84728_fw, bcm84728_fw_length));
   2988         } else { /* non-84728 device */
   2989             SOC_IF_ERROR_RETURN(
   2990                 bsdk_phy84728_mdio_firmware_download(pc,
   2991                                                     bcm84748_fw, bcm84748_fw_length));
   2992         }
   2993     } 
   2994 
   2995     /* Set Line mode */
   2996     SOC_IF_ERROR_RETURN(
   2997         bsdk_phy84728_line_mode_set(pc, 0, line_mode));
   2998     
   2999     /* System side mode */
   3000     if (line_mode == BSDK_PHY84728_INTF_SFI) {
   3001         SOC_IF_ERROR_RETURN(
   3002             bsdk_phy84728_sys_mode_set(pc, 0, 
   3003                                        BSDK_PHY84728_INTF_XAUI));
   3004         SOC_IF_ERROR_RETURN(
   3005             bsdk_phy84728_speed_set(pc, 10000));
   3006     } else if (line_mode == BSDK_PHY84728_INTF_1000X) {
   3007         SOC_IF_ERROR_RETURN(
   3008             bsdk_phy84728_sys_mode_set(pc, 0, 
   3009                                        BSDK_PHY84728_INTF_1000X));
   3010         /* Force Speed to 1G */
   3011         SOC_IF_ERROR_RETURN(
   3012             bsdk_phy84728_speed_set(pc, 1000));
   3013     } else { /* SGMII MODE */
   3014         SOC_IF_ERROR_RETURN(
   3015             bsdk_phy84728_sys_mode_set(pc, 0, 
   3016                                        BSDK_PHY84728_INTF_SGMII));
   3017     }
   3018 
   3019     return SOC_E_NONE;
   3020 }
   3021 
   3022 /*
   3023  * Function:     
   3024  *    bsdk_phy84728_reset 
   3025  * Purpose:    
   3026  *    Reset the PHY.
   3027  * Parameters:
   3028  *    phy_id - PHY Device Address of the PHY to reset
   3029  */
   3030 int 
   3031 bsdk_phy84728_reset(phy_ctrl_t *pc)
   3032 {
   3033     int         wan_mode;
   3034     uint16          ctrl, tmp;
   3035 
   3036 
   3037     /* Reset the PHY **/
   3038     SOC_IF_ERROR_RETURN(
   3039         BSDK_RD_PHY84728_LN_DEV1_PMD_CTRLr(pc, &ctrl));
   3040 
   3041     SOC_IF_ERROR_RETURN(
   3042         BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, 
   3043                                (ctrl | BSDK_PHY84728_PMD_CTRL_RESET)));
   3044 
   3045     wan_mode = soc_property_port_get(pc->unit, pc->port, spn_PHY_WAN_MODE, FALSE);
   3046 
   3047     if (wan_mode) {
   3048         SOC_IF_ERROR_RETURN(
   3049             BSDK_MOD_PHY84728_WIS_CTRLr(pc, 
   3050                                      BSDK_PHY84728_WIS_CTRL_RESET,
   3051                                      BSDK_PHY84728_WIS_CTRL_RESET));
   3052     }
   3053 
   3054     /* Needs minimum of 5us to complete the reset */
   3055     sal_usleep(30);
   3056 
   3057     SOC_IF_ERROR_RETURN(
   3058         BSDK_RD_PHY84728_LN_DEV1_PMD_CTRLr(pc, &tmp));
   3059 
   3060     if ((tmp & BSDK_PHY84728_PMD_CTRL_RESET) != 0) {
   3061         SOC_IF_ERROR_RETURN
   3062             (BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, ctrl));
   3063         return SOC_E_FAIL;
   3064     }
   3065 
   3066     if (wan_mode) {
   3067         SOC_IF_ERROR_RETURN(
   3068             BSDK_MOD_PHY84728_WIS_CTRLr(pc, 
   3069                                      0,
   3070                                      BSDK_PHY84728_WIS_CTRL_RESET));
   3071     }
   3072 
   3073     return SOC_E_NONE;
   3074 }
   3075 /*
   3076  * Function:     
   3077  *    bsdk_phy84728_lane_map
   3078  * Purpose:    
   3079  *    To set the PHY's lane map  
   3080  * Parameters:
   3081  *    phy_id    - PHY's device address
   3082  * Returns:    
   3083  */
   3084 int
   3085 bsdk_phy84728_lane_map(phy_ctrl_t *pc)
   3086 {
   3087     uint32 phy_sys_xaui_tx_lane_map, phy_sys_xaui_rx_lane_map;
   3088     uint16 temp;
   3089 
   3090     phy_sys_xaui_tx_lane_map = PHY84728_MAP(pc)->phy_sys_xaui_tx_lane_map ;
   3091 
   3092     if (phy_sys_xaui_tx_lane_map) {
   3093         LOG_INFO(BSL_LS_SOC_PHY,
   3094                  (BSL_META_U(pc->unit,
   3095                              "phy_sys_xaui_tx_lane_map: u=%d p=%d val=0x%x\n"),
   3096                   pc->unit, pc->port, phy_sys_xaui_tx_lane_map));
   3097         temp  = ((phy_sys_xaui_tx_lane_map & (0x3<<12)) >> 6) |
   3098                  ((phy_sys_xaui_tx_lane_map & (0x3<<8)) >> 4) |
   3099                  ((phy_sys_xaui_tx_lane_map & (0x3<<4)) >> 2) |
   3100                  (phy_sys_xaui_tx_lane_map & 0x3) | 0x0100;
   3101         SOC_IF_ERROR_RETURN(
   3102             BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0004, 0x8169, temp, 0x01ff));
   3103     }
   3104 
   3105     phy_sys_xaui_rx_lane_map = PHY84728_MAP(pc)->phy_sys_xaui_rx_lane_map ;
   3106 
   3107     if (phy_sys_xaui_rx_lane_map) {
   3108         LOG_INFO(BSL_LS_SOC_PHY,
   3109                  (BSL_META_U(pc->unit,
   3110                              "phy_sys_xaui_rx_lane_map: u=%d p=%d val=0x%x\n"),
   3111                   pc->unit, pc->port, phy_sys_xaui_rx_lane_map));
   3112         temp  = ((phy_sys_xaui_rx_lane_map & (0x3<<12)) >> 6) |
   3113                  ((phy_sys_xaui_rx_lane_map & (0x3<<8)) >> 4) |
   3114                  ((phy_sys_xaui_rx_lane_map & (0x3<<4)) >> 2) |
   3115                  (phy_sys_xaui_rx_lane_map & 0x3) | 0x0100;
   3116         SOC_IF_ERROR_RETURN(
   3117             BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0004, 0x816b, temp, 0x01ff));
   3118     }
   3119 
   3120     return SOC_E_NONE;
   3121 }
   3122 
   3123 
   3124 /*
   3125  * Function:     
   3126  *    bsdk_phy84728_speed_set
   3127  * Purpose:    
   3128  *    To set the PHY's speed  
   3129  * Parameters:
   3130  *    phy_id    - PHY's device address
   3131  *    speed     - Speed to set
   3132  *               10   = 10Mbps
   3133  *               100  = 100Mbps
   3134  *               1000 = 1000Mbps
   3135  * Returns:    
   3136  */
   3137 int
   3138 bsdk_phy84728_speed_set(phy_ctrl_t *pc, int speed)
   3139 {
   3140     int value = 0;
   3141     bsdk_phy84728_intf_t line_mode;
   3142 
   3143     if ((speed != 10) && (speed != 100) && 
   3144          (speed != 1000) && (speed != 10000)) {
   3145         return SOC_E_NONE;
   3146     }
   3147 
   3148     SOC_IF_ERROR_RETURN(
   3149         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   3150 
   3151     switch (line_mode) {
   3152     case BSDK_PHY84728_INTF_SFI:
   3153     case BSDK_PHY84728_INTF_1000X:
   3154         /* Disable Clause 37 Autoneg */
   3155         SOC_IF_ERROR_RETURN(
   3156             BSDK_MOD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, 0x0000,
   3157                                    BSDK_PHY84728_AN_MII_CTRL_AE));
   3158         SOC_IF_ERROR_RETURN(
   3159             BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE,
   3160                                    BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE));
   3161         SOC_IF_ERROR_RETURN(
   3162             BSDK_MOD_PHY84728_LN_DEV7_AN_MSIC2r(pc, BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL |  
   3163                                                     BSDK_PHY84728_AN_MISC2_PMA_PMD_FORCED_SPEED_ENC_EN,
   3164                                                     BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL |
   3165                                                     BSDK_PHY84728_AN_MISC2_PMA_PMD_FORCED_SPEED_ENC_EN));
   3166         if (speed == 10000) {
   3167 
   3168             /* Set Line mode */
   3169             SOC_IF_ERROR_RETURN(
   3170                 bsdk_phy84728_line_mode_set(pc, 0,
   3171                 BSDK_PHY84728_INTF_SFI));
   3172 
   3173             /* Set System side to match Line side */
   3174             SOC_IF_ERROR_RETURN(
   3175                 bsdk_phy84728_sys_mode_set(pc, 0, 
   3176                                          BSDK_PHY84728_INTF_XAUI));
   3177             /* Force Speed in PMD */
   3178             SOC_IF_ERROR_RETURN(
   3179                 BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 
   3180                                      BSDK_PHY84728_PMD_CTRL_SS_10000,
   3181                                      BSDK_PHY84728_PMD_CTRL_10GSS_MASK));
   3182             /* Select 10G-LRM PMA */
   3183             SOC_IF_ERROR_RETURN(
   3184                 BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRL2r(pc,
   3185                              BSDK_PHY84728_PMD_CTRL2_PMA_10GLRMPMD_TYPE,
   3186                              BSDK_PHY84728_PMD_CTRL2_PMA_SELECT_MASK));
   3187 
   3188         } else if (speed == 1000) {
   3189            
   3190                 /* Set Line mode */
   3191                 SOC_IF_ERROR_RETURN(
   3192                     bsdk_phy84728_line_mode_set(pc, 0,
   3193                                                    BSDK_PHY84728_INTF_1000X));
   3194                 /* Set System side to match Line side */
   3195                 SOC_IF_ERROR_RETURN(
   3196                     bsdk_phy84728_sys_mode_set(pc, 0, 
   3197                                              BSDK_PHY84728_INTF_1000X));
   3198                 /* Force Speed in PMD */
   3199                 SOC_IF_ERROR_RETURN(
   3200                     BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 
   3201                                          BSDK_PHY84728_PMD_CTRL_SS_1000,
   3202                                          BSDK_PHY84728_PMD_CTRL_10GSS_MASK));
   3203             } else {
   3204                 return SOC_E_CONFIG;
   3205         }
   3206     break;
   3207 
   3208     case BSDK_PHY84728_INTF_SGMII:
   3209         if (speed > 1000) {
   3210             return SOC_E_CONFIG;
   3211         }
   3212         /* Disable Clause 37 Autoneg */
   3213         SOC_IF_ERROR_RETURN(
   3214             BSDK_MOD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, 0x0000,
   3215                                    0x1000));
   3216         if (speed == 1000) {
   3217             value = BSDK_PHY84728_PMD_CTRL_SS_1000;
   3218         }
   3219         if (speed == 100) {
   3220             value = BSDK_PHY84728_PMD_CTRL_SS_100;
   3221         }
   3222         if (speed == 10) {
   3223             value = BSDK_PHY84728_PMD_CTRL_SS_10;
   3224         }
   3225         SOC_IF_ERROR_RETURN(
   3226             BSDK_MOD_PHY84728_LN_DEV7_XGXS_CTRLr(pc, 0x0000, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ));
   3227 
   3228         SOC_IF_ERROR_RETURN(
   3229             BSDK_MOD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, value,
   3230                      BSDK_PHY84728_AN_MII_CTRL_SS_MASK | BSDK_PHY84728_AN_MII_CTRL_AE));
   3231 
   3232         /* Force Speed in PMD */
   3233         SOC_IF_ERROR_RETURN(
   3234             BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 
   3235                                  value,
   3236                                  BSDK_PHY84728_PMD_CTRL_10GSS_MASK));
   3237         SOC_IF_ERROR_RETURN(
   3238             BSDK_MOD_PHY84728_LN_DEV7_XGXS_CTRLr(pc, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ,
   3239                                                      BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ));
   3240     break;
   3241 
   3242     default:
   3243         return SOC_E_CONFIG;
   3244     }
   3245 
   3246     /* Enable Squelch */
   3247     SOC_IF_ERROR_RETURN(_phy_84728_squelch_enable(pc->unit, pc->port, TRUE));
   3248 
   3249     return SOC_E_NONE;
   3250 }
   3251 
   3252 /*
   3253  * Function:
   3254  *      phy_84728_mdix_set
   3255  * Description:
   3256  *      Set the Auto-MDIX mode of a port/PHY
   3257  * Parameters:
   3258  *      unit - Device number
   3259  *      port - Port number
   3260  *      mode - One of:
   3261  *              SOC_PORT_MDIX_AUTO
   3262  *                      Enable auto-MDIX when autonegotiation is enabled
   3263  *              SOC_PORT_MDIX_FORCE_AUTO
   3264  *                      Enable auto-MDIX always
   3265  *              SOC_PORT_MDIX_NORMAL
   3266  *                      Disable auto-MDIX
   3267  *              SOC_PORT_MDIX_XOVER
   3268  *                      Disable auto-MDIX, and swap cable pairs
   3269  * Return Value:
   3270  *      SOC_E_XXX
   3271  */
   3272 STATIC int
   3273 phy_84728_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode)
   3274 {
   3275     phy_ctrl_t    *pc;
   3276 
   3277     pc = EXT_PHY_SW_STATE(unit, port);
   3278 
   3279     if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) {
   3280             PHYDRV_CALL_ARG1(pc, PHY_MDIX_SET, mode);
   3281             return SOC_E_NONE;
   3282     }
   3283     SOC_IF_ERROR_RETURN(
   3284         phy_null_mdix_set(unit, port, mode));
   3285 
   3286     return SOC_E_NONE;
   3287 
   3288 }        
   3289 
   3290 /*
   3291  * Function:
   3292  *      phy_84728_mdix_get
   3293  * Description:
   3294  *      Get the Auto-MDIX mode of a port/PHY
   3295  * Parameters:
   3296  *      unit - Device number
   3297  *      port - Port number
   3298  *      mode - (Out) One of:
   3299  *              SOC_PORT_MDIX_AUTO
   3300  *                      Enable auto-MDIX when autonegotiation is enabled
   3301  *              SOC_PORT_MDIX_FORCE_AUTO
   3302  *                      Enable auto-MDIX always
   3303  *              SOC_PORT_MDIX_NORMAL
   3304  *                      Disable auto-MDIX
   3305  *              SOC_PORT_MDIX_XOVER
   3306  *                      Disable auto-MDIX, and swap cable pairs
   3307  * Return Value:
   3308  *      SOC_E_XXX
   3309  */
   3310 STATIC int
   3311 phy_84728_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode)
   3312 {
   3313     phy_ctrl_t    *pc;
   3314 
   3315     pc = EXT_PHY_SW_STATE(unit, port);
   3316 
   3317     if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) {
   3318         PHYDRV_CALL_ARG1(pc, PHY_MDIX_GET, mode);
   3319         return SOC_E_NONE;
   3320     }
   3321     SOC_IF_ERROR_RETURN(
   3322         phy_null_mdix_get(unit, port, mode));
   3323 
   3324     return SOC_E_NONE;
   3325 }    
   3326 
   3327 /*
   3328  * Function:
   3329  *      phy_84728_mdix_status_get
   3330  * Description:
   3331  *      Get the current MDIX status on a port/PHY
   3332  * Parameters:
   3333  *      unit    - Device number
   3334  *      port    - Port number
   3335  *      status  - (OUT) One of:
   3336  *              SOC_PORT_MDIX_STATUS_NORMAL
   3337  *                      Straight connection
   3338  *              SOC_PORT_MDIX_STATUS_XOVER
   3339  *                      Crossover has been performed
   3340  * Return Value:
   3341  *      SOC_E_XXX
   3342  */
   3343 STATIC int
   3344 phy_84728_mdix_status_get(int unit, soc_port_t port,
   3345                          soc_port_mdix_status_t *status)
   3346 {
   3347     phy_ctrl_t    *pc;
   3348 
   3349     pc = EXT_PHY_SW_STATE(unit, port);
   3350 
   3351     if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) {
   3352         PHYDRV_CALL_ARG1(pc, PHY_MDIX_STATUS_GET, status);
   3353         return SOC_E_NONE;
   3354     }
   3355     SOC_IF_ERROR_RETURN(
   3356         phy_null_mdix_status_get(unit, port, status));
   3357 
   3358     return SOC_E_NONE;
   3359 }
   3360 
   3361 /*
   3362  * Function:
   3363  *      phy_84728_master_set
   3364  * Purpose:
   3365  *      Set the master mode for the PHY.
   3366  * Parameters:
   3367  *      unit - StrataSwitch unit #.
   3368  *      port - StrataSwitch port #.
   3369  *      master - SOC_PORT_MS_*
   3370  * Returns:
   3371  *      SOC_E_XXX
   3372  * Notes:
   3373  *      No synchronization performed at this level. Autonegotiation is
   3374  *      not manipulated.
   3375  */
   3376 
   3377 STATIC int
   3378 phy_84728_master_set(int unit, soc_port_t port, int master)
   3379 {
   3380     phy_ctrl_t  *pc;
   3381 
   3382     pc = EXT_PHY_SW_STATE(unit, port);
   3383 
   3384     if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) {
   3385         PHYDRV_CALL_ARG1(pc, PHY_MASTER_SET, master);
   3386         return SOC_E_NONE;
   3387     }
   3388     SOC_IF_ERROR_RETURN(
   3389         phy_null_set(unit, port, master));
   3390 
   3391     return SOC_E_NONE;
   3392 }
   3393 
   3394 /*
   3395  * Function:
   3396  *      phy_84728_master_get
   3397  * Purpose:
   3398  *      Get the master mode for the PHY.  If mode is forced, then
   3399  *      forced mode is returned; otherwise operating mode is returned.
   3400  * Parameters:
   3401  *      unit - StrataSwitch unit #.
   3402  *      port - StrataSwitch port #.
   3403  *      master - (OUT) SOC_PORT_MS_*
   3404  * Returns:
   3405  *      SOC_E_XXX
   3406  * Notes:
   3407  *      No synchronization performed at this level. Autonegotiation is
   3408  *      not manipulated.
   3409  */
   3410 
   3411 STATIC int
   3412 phy_84728_master_get(int unit, soc_port_t port, int *master)
   3413 {
   3414     phy_ctrl_t  *pc;
   3415 
   3416     pc = EXT_PHY_SW_STATE(unit, port);
   3417 
   3418     if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) {
   3419         PHYDRV_CALL_ARG1(pc, PHY_MASTER_GET, master);
   3420         return SOC_E_NONE;
   3421     }
   3422     SOC_IF_ERROR_RETURN(
   3423         phy_null_zero_get(unit, port, master));
   3424 
   3425     return SOC_E_NONE;
   3426 }
   3427 
   3428 /*
   3429  * Function:
   3430  *      bsdk_phy84728_link_get
   3431  * Purpose:
   3432  *      Determine the current link up/down status for a 84728 device.
   3433  * Parameters:
   3434  *    phy_id    - PHY Device Address
   3435  *    link      - (OUT) 
   3436  *                1 = Indicates Link is established
   3437  *                0 = No Link.
   3438  * Returns:
   3439  */
   3440 int
   3441 bsdk_phy84728_link_get(phy_ctrl_t *pc, int *link)
   3442 {
   3443 
   3444     uint16 data = 0, pma_mii_stat = 0, pcs_mii_stat = 0;
   3445     int an, an_done;
   3446     bsdk_phy84728_intf_t line_mode;
   3447 
   3448     *link = 0;
   3449     SOC_IF_ERROR_RETURN(
   3450         phy_84728_an_get(pc->unit, pc->port, &an, &an_done)); 
   3451 
   3452     /* Firmware issue: need to comment out as workaround */
   3453 #if 0
   3454     if (an && (an_done == 0)) {
   3455         /* Auto neg in progess, return no link */
   3456         *link = 0;
   3457         return SOC_E_NONE;
   3458     }
   3459 #endif
   3460 
   3461 
   3462      SOC_IF_ERROR_RETURN(
   3463          bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   3464 
   3465      switch (line_mode) {
   3466         case BSDK_PHY84728_INTF_SFI:
   3467 
   3468             SOC_IF_ERROR_RETURN(
   3469                 BSDK_RD_PHY84728_LN_DEV1_PMD_STATr(pc, &pma_mii_stat));
   3470 
   3471             SOC_IF_ERROR_RETURN(
   3472                 BSDK_RD_PHY84728_LN_DEV3_PCS_STATr(pc, &pcs_mii_stat));
   3473 
   3474             if (pma_mii_stat == 0xffff || pcs_mii_stat == 0xffff) {
   3475                 *link = 0;
   3476                 break;
   3477             }
   3478 
   3479             *link = pma_mii_stat & pcs_mii_stat & BSDK_PHY84728_PMD_STAT_RX_LINK_STATUS;
   3480 
   3481             break;
   3482 
   3483         case BSDK_PHY84728_INTF_1000X:
   3484         case BSDK_PHY84728_INTF_SGMII:
   3485             SOC_IF_ERROR_RETURN(
   3486                 BSDK_RD_PHY84728_LN_DEV7_AN_MII_STATr(pc, &data));
   3487 
   3488             if (data == 0xffff) {
   3489                 *link = 0;
   3490                 break;
   3491             }
   3492 
   3493             *link = data & BSDK_PHY84728_AN_MII_STAT_LINK_STATUS;
   3494             break;
   3495 
   3496         default:
   3497             break;
   3498      }
   3499 
   3500      if (*link == 0) {
   3501          if (line_mode != BSDK_PHY84728_INTF_SGMII && an && an_done) {
   3502             SOC_IF_ERROR_RETURN(
   3503                 bsdk_phy84728_line_mode_set(pc, 0, BSDK_PHY84728_INTF_1000X));
   3504          }
   3505      }
   3506 
   3507     return SOC_E_NONE;
   3508 }
   3509 
   3510 
   3511 /*
   3512  * Function:
   3513  *     bsdk_phy84728_ability_advert_set 
   3514  * Purpose:
   3515  *      Set the current advertisement for auto-negotiation.
   3516  * Parameters:
   3517  *    phy_id    - PHY Device Address
   3518  *    ability   - Ability indicating supported options/speeds.
   3519  *                For Speed & Duplex:
   3520  *                BSDK_PM_10MB_HD    = 10Mb, Half Duplex
   3521  *                BSDK_PM_10MB_FD    = 10Mb, Full Duplex
   3522  *                BSDK_PM_100MB_HD   = 100Mb, Half Duplex
   3523  *                BSDK_PM_100MB_FD   = 100Mb, Full Duplex
   3524  *                BSDK_PM_1000MB_HD  = 1000Mb, Half Duplex
   3525  *                BSDK_PM_1000MB_FD  = 1000Mb, Full Duplex
   3526  *                BSDK_PM_PAUSE_TX   = TX Pause
   3527  *                BSDK_PM_PAUSE_RX   = RX Pause
   3528  *                BSDK_PM_PAUSE_ASYMM = Asymmetric Pause
   3529  * Returns:
   3530  */
   3531 
   3532 int
   3533 bsdk_phy84728_ability_advert_set(phy_ctrl_t *pc,
   3534                                bsdk_phy84728_port_ability_t ability)
   3535 {
   3536     uint16 data = 0;
   3537     bsdk_phy84728_intf_t line_mode;
   3538 
   3539     SOC_IF_ERROR_RETURN(
   3540         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   3541 
   3542     if (line_mode == BSDK_PHY84728_INTF_1000X) {
   3543         /* Always advertise 1000X full duplex */
   3544         data = BSDK_PHY84728_DEV7_1000X_ANA_C37_FD;  
   3545         if ((ability & BSDK_PHY84728_PA_PAUSE) == 
   3546                                              BSDK_PHY84728_PA_PAUSE) {
   3547             data |= BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE;
   3548         } else {
   3549             if (ability & BSDK_PHY84728_PA_PAUSE_TX) {
   3550                 data |= BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE;
   3551             } else {
   3552                 if (ability & BSDK_PHY84728_PA_PAUSE_RX) {
   3553                     data |= BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE;
   3554                     data |= BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE;
   3555                 }
   3556             }
   3557         }
   3558         SOC_IF_ERROR_RETURN(
   3559             BSDK_WR_PHY84728_LN_DEV7_AN_ANAr(pc, data));
   3560 
   3561     }
   3562     if (line_mode == BSDK_PHY84728_INTF_SGMII) {
   3563         
   3564         
   3565     } else {
   3566         /* No Autoneg in SFI mode */
   3567         /* return SOC_E_UNAVAIL; */
   3568     }
   3569     return SOC_E_NONE;
   3570 }
   3571 
   3572 
   3573 /*
   3574  * Function:
   3575  *      bsdk_phy84728_ability_advert_get
   3576  * Purpose:
   3577  *      Get the current advertisement for auto-negotiation.
   3578  * Parameters:
   3579  *    phy_id    - PHY Device Address
   3580  *    ability   - (OUT) Port ability mask indicating supported options/speeds.
   3581  *                For Speed & Duplex:
   3582  *                BSDK_PM_10MB_HD    = 10Mb, Half Duplex
   3583  *                BSDK_PM_10MB_FD    = 10Mb, Full Duplex
   3584  *                BSDK_PM_100MB_HD   = 100Mb, Half Duplex
   3585  *                BSDK_PM_100MB_FD   = 100Mb, Full Duplex
   3586  *                BSDK_PM_1000MB_HD  = 1000Mb, Half Duplex
   3587  *                BSDK_PM_1000MB_FD  = 1000Mb, Full Duplex
   3588  *                BSDK_PM_PAUSE_TX   = TX Pause
   3589  *                BSDK_PM_PAUSE_RX   = RX Pause
   3590  *                BSDK_PM_PAUSE_ASYMM = Asymmetric Pause
   3591  * Returns:
   3592  */
   3593 
   3594 int
   3595 bsdk_phy84728_ability_advert_get(phy_ctrl_t *pc,
   3596                                bsdk_phy84728_port_ability_t *ability)
   3597 {
   3598     uint16 data = 0;
   3599     bsdk_phy84728_intf_t line_mode;
   3600 
   3601     if (ability == NULL) {
   3602         return SOC_E_PARAM;
   3603     }
   3604 
   3605     SOC_IF_ERROR_RETURN(
   3606         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   3607 
   3608     if (line_mode == BSDK_PHY84728_INTF_1000X) {
   3609         SOC_IF_ERROR_RETURN(
   3610             BSDK_RD_PHY84728_LN_DEV7_AN_ANAr(pc, &data));
   3611 
   3612         *ability |= (data & BSDK_PHY84728_DEV7_1000X_ANA_C37_FD) ? 
   3613                   BSDK_PHY84728_PA_1000MB_FD : 0;
   3614         *ability |= (data & BSDK_PHY84728_DEV7_1000X_ANA_C37_HD) ?
   3615                   BSDK_PHY84728_PA_1000MB_HD : 0;
   3616         switch (data & (BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE | 
   3617                         BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE)) {
   3618         case BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE:
   3619             *ability |= BSDK_PHY84728_PA_PAUSE;
   3620             break;
   3621         case BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE:
   3622             *ability |= BSDK_PHY84728_PA_PAUSE_TX;
   3623             break;
   3624         case (BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE | 
   3625               BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE):
   3626             *ability |= BSDK_PHY84728_PA_PAUSE_RX;
   3627             break;
   3628         }
   3629     } else {
   3630         if (line_mode == BSDK_PHY84728_INTF_SGMII) {
   3631             *ability = BSDK_PHY84728_PA_SPEED_ALL |
   3632                        BSDK_PHY84728_PA_AN        |
   3633                        BSDK_PHY84728_PA_PAUSE     |
   3634                        BSDK_PHY84728_PA_PAUSE_ASYMM;
   3635         
   3636         } else {
   3637             /* No Autoneg in SFI mode */
   3638             *ability = BSDK_PHY84728_PA_10000MB_FD |
   3639                        BSDK_PHY84728_PA_PAUSE;
   3640         }
   3641     }
   3642     return SOC_E_NONE;
   3643 }
   3644 
   3645 
   3646 /*
   3647  * Function:
   3648  *      bsdk_phy84728_remote_ability_advert_get
   3649  * Purpose:
   3650  *      Get partners current advertisement for auto-negotiation.
   3651  * Parameters:
   3652  *    phy_id         - PHY Device Address
   3653  *    remote_ability - (OUT) Port ability mask indicating supported options/speeds.
   3654  *                For Speed & Duplex:
   3655  *                BSDK_PM_10MB_HD    = 10Mb, Half Duplex
   3656  *                BSDK_PM_10MB_FD    = 10Mb, Full Duplex
   3657  *                BSDK_PM_100MB_HD   = 100Mb, Half Duplex
   3658  *                BSDK_PM_100MB_FD   = 100Mb, Full Duplex
   3659  *                BSDK_PM_1000MB_HD  = 1000Mb, Half Duplex
   3660  *                BSDK_PM_1000MB_FD  = 1000Mb, Full Duplex
   3661  *                BSDK_PM_PAUSE_TX   = TX Pause
   3662  *                BSDK_PM_PAUSE_RX   = RX Pause
   3663  *                BSDK_PM_PAUSE_ASYMM = Asymmetric Pause
   3664  * Returns:
   3665  */
   3666 
   3667 int
   3668 bsdk_phy84728_remote_ability_advert_get(phy_ctrl_t *pc,
   3669                                 bsdk_phy84728_port_ability_t *remote_ability)
   3670 {
   3671     uint16 data = 0;
   3672     bsdk_phy84728_intf_t line_mode;
   3673 
   3674     if (remote_ability == NULL) {
   3675         return SOC_E_PARAM;
   3676     }
   3677 
   3678     SOC_IF_ERROR_RETURN(
   3679         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   3680 
   3681     if (line_mode == BSDK_PHY84728_INTF_1000X) {
   3682         SOC_IF_ERROR_RETURN(
   3683             BSDK_RD_PHY84728_LN_DEV7_AN_ANPr(pc, &data));
   3684 
   3685         *remote_ability |= (data & BSDK_PHY84728_DEV7_1000X_ANA_C37_FD) ?
   3686                   BSDK_PHY84728_PA_1000MB_FD : 0;
   3687         *remote_ability |= (data & BSDK_PHY84728_DEV7_1000X_ANA_C37_HD) ?
   3688                                BSDK_PHY84728_PA_1000MB_HD : 0;
   3689         switch (data & (BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE | 
   3690                         BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE)) {
   3691         case BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE:
   3692             *remote_ability |= BSDK_PHY84728_PA_PAUSE;
   3693             break;
   3694         case BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE:
   3695             *remote_ability |= BSDK_PHY84728_PA_PAUSE_TX;
   3696             break;
   3697         case (BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE | 
   3698               BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE):
   3699             *remote_ability |= BSDK_PHY84728_PA_PAUSE_RX;
   3700             break;
   3701         }
   3702     } else if (line_mode == BSDK_PHY84728_INTF_SGMII) {
   3703         
   3704         
   3705     } else {
   3706         if (!REVERSE_MODE(pc)) {
   3707         /* No Autoneg in SFI mode */
   3708         return SOC_E_UNAVAIL;
   3709         }
   3710     }
   3711     return SOC_E_NONE;
   3712 }
   3713 
   3714 
   3715 /*
   3716  * Function:
   3717  *      bsdk_phy84728_ability_local_get
   3718  * Purpose:
   3719  *      Get the PHY abilities
   3720  * Parameters:
   3721  *    phy_id    - PHY Device Address
   3722  *    mode      - Mask indicating supported options/speeds.
   3723  *                For Speed & Duplex:
   3724  *                BSDK_PM_10MB_HD    = 10Mb, Half Duplex
   3725  *                BSDK_PM_10MB_FD    = 10Mb, Full Duplex
   3726  *                BSDK_PM_100MB_HD   = 100Mb, Half Duplex
   3727  *                BSDK_PM_100MB_FD   = 100Mb, Full Duplex
   3728  *                BSDK_PM_1000MB_HD  = 1000Mb, Half Duplex
   3729  *                BSDK_PM_1000MB_FD  = 1000Mb, Full Duplex
   3730  *                BSDK_PM_PAUSE_TX   = TX Pause
   3731  *                BSDK_PM_PAUSE_RX   = RX Pause
   3732  *                BSDK_PM_PAUSE_ASYMM = Asymmetric Pause
   3733  *                BSDK_PM_SGMII       = SGMIII Supported
   3734  *                BSDK_PM_XSGMII      = XSGMIII Supported
   3735  * Returns:
   3736  */
   3737 int
   3738 bsdk_phy84728_ability_local_get(phy_ctrl_t *pc,
   3739                              bsdk_phy84728_port_ability_t *ability)
   3740 {
   3741     bsdk_phy84728_intf_t line_mode;
   3742 
   3743     if (ability == NULL) {
   3744         return SOC_E_PARAM;
   3745     }
   3746 
   3747     SOC_IF_ERROR_RETURN(
   3748         bsdk_phy84728_line_intf_get(pc, 0, &line_mode));
   3749 
   3750     *ability = BSDK_PHY84728_PA_LB_PHY | BSDK_PHY84728_PA_PAUSE;
   3751     *ability |= BSDK_PHY84728_PA_SGMII;
   3752 
   3753     if (line_mode == BSDK_PHY84728_INTF_SGMII) {
   3754         *ability |= BSDK_PHY84728_PA_AN;
   3755         *ability |= BSDK_PHY84728_PA_SPEED_ALL;
   3756         
   3757     } else {
   3758         *ability |= BSDK_PHY84728_PA_XSGMII;
   3759         *ability |= BSDK_PHY84728_PA_10000MB_FD;
   3760         *ability |= BSDK_PHY84728_PA_1000MB_FD;
   3761     }
   3762 
   3763     return(SOC_E_NONE);
   3764 }
   3765 
   3766 STATIC int
   3767 _bsdk_phy84728_system_sgmii_speed_set(phy_ctrl_t *pc, int dev_port, int speed)
   3768 {
   3769     uint16 mii_ctrl = 0;
   3770 
   3771     if (speed == 0) {
   3772         return SOC_E_NONE;
   3773     }
   3774 
   3775     {
   3776         SOC_IF_ERROR_RETURN(
   3777             BSDK_RD_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, &mii_ctrl));
   3778 
   3779         mii_ctrl &= ~(BSDK_PHY84728_AN_MII_CTRL_SS_MASK);
   3780         switch(speed) {
   3781         case 10:
   3782             mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_SS_10;
   3783             break;
   3784         case 100:
   3785             mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_SS_100;
   3786             break;
   3787         case 1000:
   3788             mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_SS_1000;
   3789             break;
   3790         default:
   3791             return SOC_E_CONFIG;
   3792         }
   3793         SOC_IF_ERROR_RETURN(
   3794             BSDK_WR_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, mii_ctrl));
   3795     }
   3796     return SOC_E_NONE;
   3797 }
   3798 
   3799 STATIC int
   3800 _bsdk_phy84728_system_sgmii_duplex_set(phy_ctrl_t *pc, int dev_port,
   3801                                  int duplex)
   3802 {
   3803     uint16 mii_ctrl;
   3804 
   3805     {
   3806         SOC_IF_ERROR_RETURN(
   3807             BSDK_RD_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, &mii_ctrl));
   3808 
   3809         if ( duplex ) {
   3810             mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_FD;
   3811         } else {
   3812             mii_ctrl &= ~BSDK_PHY84728_AN_MII_CTRL_FD;
   3813         }
   3814         SOC_IF_ERROR_RETURN(
   3815             BSDK_WR_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, mii_ctrl));
   3816     }
   3817 
   3818     return SOC_E_NONE;
   3819 }
   3820 
   3821 STATIC int
   3822 _bsdk_phy84728_system_sgmii_sync(phy_ctrl_t *pc, int dev_port)
   3823 {
   3824     int speed;
   3825     int duplex;
   3826 
   3827         SOC_IF_ERROR_RETURN(
   3828             phy_84728_speed_get(pc->unit, pc->port, &speed));
   3829 
   3830         SOC_IF_ERROR_RETURN(
   3831             phy_84728_duplex_get(pc->unit, pc->port, &duplex));
   3832 
   3833         SOC_IF_ERROR_RETURN(
   3834             BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, 0x0000, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ));
   3835 
   3836         SOC_IF_ERROR_RETURN(
   3837             _bsdk_phy84728_system_sgmii_speed_set(pc, dev_port, speed));
   3838 
   3839         SOC_IF_ERROR_RETURN(
   3840             _bsdk_phy84728_system_sgmii_duplex_set(pc, dev_port, duplex));
   3841 
   3842         SOC_IF_ERROR_RETURN(
   3843             BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ,
   3844                                                       BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ));
   3845 
   3846     return SOC_E_NONE;
   3847 }
   3848 
   3849 /*
   3850  * Function:
   3851  *     bsdk_phy84728_mdio_firmware_download
   3852  * Purpose:
   3853  *     Download new firmware via MDIO.
   3854  * Parameters:
   3855  *    phy_id    - PHY Device Address
   3856  *    new_fw    - Pointer to new firmware
   3857  *    fw_length    - Length of the firmware
   3858  * Returns:
   3859  */
   3860 int
   3861 bsdk_phy84728_mdio_firmware_download(phy_ctrl_t *pc,
   3862                                   uint8 *new_fw, uint32 fw_length)
   3863 {
   3864 
   3865     uint16 data16;
   3866     int j;
   3867     uint16 num_words;
   3868 
   3869     /* 0xc848[15]=0, MDIO downloading to RAM, 0xc848[14]=1, serial boot */
   3870     /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */
   3871     SOC_IF_ERROR_RETURN(
   3872            BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc848, 
   3873                (0 << 15)|(1 << 14),
   3874                (1 << 15)|(1 << 14)|((1 << 13) | (1 << 2))));
   3875 
   3876     /* Reset, to download code from MDIO */
   3877     SOC_IF_ERROR_RETURN(
   3878            BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 
   3879                BSDK_PHY84728_PMD_CTRL_RESET, BSDK_PHY84728_PMD_CTRL_RESET));
   3880 
   3881     sal_usleep(50000);
   3882 
   3883     /* Write Starting Address, where the Code will reside in SRAM */
   3884     data16 = 0x8000;
   3885     SOC_IF_ERROR_RETURN
   3886         (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, BSDK_PHY84728_PMAD_M8051_MSGIN_REG, data16));
   3887 
   3888     /* make sure address word is read by the micro */
   3889     sal_usleep(10); /* Wait for 10us */
   3890 
   3891     /* Write SPI SRAM Count Size */
   3892     data16 = (fw_length)/2;
   3893     SOC_IF_ERROR_RETURN
   3894         (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, BSDK_PHY84728_PMAD_M8051_MSGIN_REG, data16));
   3895 
   3896     /* make sure read by the micro */
   3897     sal_usleep(10); /* Wait for 10us */
   3898 
   3899     /* Fill in the SRAM */
   3900     num_words = (fw_length - 1);
   3901     for (j = 0; j < num_words; j+=2) {
   3902         /* Make sure the word is read by the Micro */
   3903         sal_usleep(10);
   3904 
   3905         data16 = (new_fw[j] << 8) | new_fw[j+1];
   3906         SOC_IF_ERROR_RETURN
   3907             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, BSDK_PHY84728_PMAD_M8051_MSGIN_REG,
   3908                  data16));
   3909     }
   3910 
   3911     /* make sure last code word is read by the micro */
   3912     sal_usleep(20);
   3913 
   3914     /* Read Hand-Shake message (Done) from Micro */
   3915     SOC_IF_ERROR_RETURN
   3916         (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc,BSDK_PHY84728_PMAD_M8051_MSGOUT_REG, &data16)); 
   3917 
   3918     if (data16 != 0x4321 ) {
   3919         /* Download done message */
   3920         LOG_CLI((BSL_META_U(pc->unit,
   3921                             "MDIO firmware download failed. Message: 0x%x\n"), data16));
   3922     }
   3923 
   3924     /* Clear LASI status */
   3925     SOC_IF_ERROR_RETURN
   3926         (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0x9003, &data16));
   3927 
   3928     /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */
   3929     sal_usleep(100); /* Wait for 100 usecs */
   3930 
   3931     SOC_IF_ERROR_RETURN
   3932         (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc,BSDK_PHY84728_PMAD_M8051_MSGOUT_REG, &data16));
   3933     
   3934     /* Need to check if checksum is correct */
   3935     SOC_IF_ERROR_RETURN
   3936         (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xCA1C, &data16));
   3937 
   3938     if (data16 != 0x600D) {
   3939         /* Bad CHECKSUM */
   3940         LOG_CLI((BSL_META_U(pc->unit,
   3941                             "MDIO Firmware downlad failure:"
   3942                  "Incorrect Checksum %x\n"), data16));
   3943         return SOC_E_FAIL;
   3944     }
   3945 
   3946     /* read Rev-ID */
   3947     SOC_IF_ERROR_RETURN
   3948         (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xCA1A, &data16));
   3949     LOG_CLI((BSL_META_U(pc->unit,
   3950                         "MDIO Firmware download completed. Version : 0x%x\n"), data16));
   3951 
   3952     return SOC_E_NONE;
   3953 }
   3954 
   3955 /*
   3956  *  Function:
   3957  *       _phy_84728_phy_84728_write_message
   3958  *
   3959  *  Purpose:
   3960  *      Write into Message In and Read from MSG Out register.
   3961  *  Input:
   3962  *      phy_id
   3963  *      wrdata
   3964  *      rddata
   3965  */
   3966 
   3967 STATIC int
   3968 _phy_84728_write_message(phy_ctrl_t *pc, uint16 wrdata, uint16 *rddata)
   3969 {
   3970     uint16 tmp_data = 0;
   3971     int iter = 0;
   3972 
   3973     SOC_IF_ERROR_RETURN
   3974         (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &tmp_data));
   3975     SOC_IF_ERROR_RETURN         
   3976         (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, wrdata));
   3977 
   3978     do {
   3979         SOC_IF_ERROR_RETURN
   3980             (BSDK_RD_PHY84728_LN_DEV1_LASI_STATr(pc, &tmp_data));
   3981 
   3982         if (tmp_data & 0x4) {
   3983             break;
   3984         }
   3985         sal_usleep(BSDK_WR_TIMEOUT);
   3986         iter++;
   3987     } while (iter < BSDK_WR_ITERATIONS);
   3988 
   3989     if (!(tmp_data & 0x4)) {
   3990         LOG_CLI((BSL_META_U(pc->unit,
   3991                             "write message failed due to timeout\n")));
   3992         return SOC_E_FAIL;
   3993     }
   3994 
   3995     SOC_IF_ERROR_RETURN
   3996         (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &tmp_data));
   3997 
   3998     *rddata = tmp_data;
   3999     SOC_IF_ERROR_RETURN
   4000         (BSDK_RD_PHY84728_LN_DEV1_RX_ALARMr(pc, &tmp_data));
   4001 
   4002     return SOC_E_NONE;
   4003 }
   4004 
   4005 
   4006 /*
   4007  *  Function:
   4008  *       _phy_84728_rom_wait
   4009  *
   4010  *  Purpose:
   4011  *      Wait for data to be written to the SPI-ROM.
   4012  *  Input:
   4013  *      phy_id
   4014  */
   4015 
   4016 STATIC int
   4017 _phy_84728_rom_wait(phy_ctrl_t *pc)
   4018 {
   4019     uint16  rd_data = 0, wr_data;
   4020     int        count;
   4021     int        SPI_READY;
   4022     int        iter = 0;
   4023 
   4024     do {
   4025         count = 1;
   4026         wr_data = ((BSDK_RD_CPU_CTRL_REGS * 0x0100) | count);
   4027         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4028         wr_data = BSDK_SPI_CTRL_1_L;
   4029         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4030         if (rd_data & 0x0100) {
   4031             break;
   4032         }
   4033         sal_usleep(BSDK_WR_TIMEOUT);
   4034         iter++;
   4035     } while (iter < BSDK_WR_ITERATIONS);
   4036 
   4037     if (!(rd_data & 0x0100)) {
   4038         LOG_CLI((BSL_META_U(pc->unit,
   4039                             "_phy_84728_rom_wait: write timeout\n")));
   4040         return SOC_E_TIMEOUT;
   4041     }
   4042 
   4043      SPI_READY = 1;
   4044      while (SPI_READY == 1) {
   4045         /* Set-up SPI Controller To Receive SPI EEPROM Status. */
   4046         count = 1;
   4047         wr_data = ((BSDK_WR_CPU_CTRL_REGS * 0x0100) | count);
   4048         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4049         wr_data = BSDK_SPI_CTRL_2_H;
   4050         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4051         wr_data = 0x0100;
   4052         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4053         /* Fill-up SPI Transmit Fifo To check SPI Status. */
   4054         count = 2;
   4055         wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4056         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4057         /* Write Tx Fifo Register Address. */
   4058         wr_data = BSDK_SPI_TXFIFO;
   4059         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4060 
   4061         /* Write SPI Tx Fifo Control Word-1. */
   4062         wr_data = ((1 * 0x0100) | BSDK_MSGTYPE_HRD);
   4063         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4064         /* Write SPI Tx Fifo Control Word-2. */
   4065         wr_data = BSDK_RDSR_OPCODE;
   4066         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4067         /* Write SPI Control Register Write Command. */
   4068         count = 2;
   4069         wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4070         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4071         /* Write SPI Control -1 Register Address. */
   4072         wr_data = BSDK_SPI_CTRL_1_L;
   4073         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4074         /* Write SPI Control -1 Register Word-1. */
   4075         wr_data = 0x0101;
   4076         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4077         /* Write SPI Control -1 Register Word-2. */
   4078         wr_data = 0x0100;
   4079         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4080         /* Write SPI Control Register Write Command. */
   4081         count = 1;
   4082         wr_data = ((BSDK_WR_CPU_CTRL_REGS * 0x0100) | count);
   4083         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4084         /* Write SPI Control -1 Register Address. */
   4085         wr_data = BSDK_SPI_CTRL_1_H;
   4086         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4087         /* Write SPI Control -1 Register Word-2. */
   4088         wr_data = 0x0103;
   4089         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4090         /* Wait For 64 bytes To be written.   */
   4091         rd_data = 0x0000;
   4092         
   4093         do {
   4094             count = 1;
   4095             wr_data = ((BSDK_RD_CPU_CTRL_REGS * 0x0100) | count);
   4096             SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4097             wr_data = BSDK_SPI_CTRL_1_L;
   4098             SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4099             if (rd_data & 0x0100) {
   4100                 break;
   4101             }
   4102             sal_usleep(BSDK_WR_TIMEOUT);
   4103             iter ++;
   4104         } while (iter < BSDK_WR_ITERATIONS); 
   4105 
   4106         if (!(rd_data & 0x0100)) {
   4107             LOG_CLI((BSL_META_U(pc->unit,
   4108                                 "_phy_84728_rom_program:timeout 2\n")));
   4109             return SOC_E_TIMEOUT;
   4110         }
   4111         /* Write SPI Control Register Read Command. */
   4112         count = 1;
   4113         wr_data = ((BSDK_RD_CPU_CTRL_REGS * 0x0100) | count);
   4114         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4115         /* Write SPI Control -1 Register Address. */
   4116         wr_data = BSDK_SPI_RXFIFO;
   4117 
   4118         SOC_IF_ERROR_RETURN         
   4119             (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, wr_data));
   4120         SOC_IF_ERROR_RETURN
   4121             (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &rd_data));
   4122 
   4123         /* Clear LASI Message Out Status. */
   4124         SOC_IF_ERROR_RETURN
   4125             (BSDK_RD_PHY84728_LN_DEV1_LASI_STATr(pc, &wr_data));
   4126 
   4127         if ((rd_data & 0x1) == 0) {
   4128             SPI_READY = 0;
   4129         }
   4130      } /* SPI_READY */
   4131      return SOC_E_NONE;
   4132 }
   4133 
   4134 
   4135 /*
   4136  * Function:
   4137  *      _phy_84728_rom_write_enable_set
   4138  *
   4139  * Purpose:
   4140  *      Enable disable protection on SPI_EEPROM
   4141  *
   4142  * Input:
   4143  *      phy_id
   4144  * Output:
   4145  *      SOC_E_xxx
   4146  *
   4147  * Notes:
   4148  *          25AA256 256Kbit Serial EEPROM
   4149  *          STATUS Register
   4150  *          +------------------------------------------+
   4151  *          | WPEN | x | x | x | BP1 | BP0 | WEL | WIP |
   4152  *          +------------------------------------------+
   4153  *      BP1 BP0  :   Protected Blocks
   4154  *       0   0   :  Protect None
   4155  *       1   1   :  Protect All
   4156  *
   4157  *      WEL : Write Latch Enable
   4158  *       0  : Do not allow writes
   4159  *       1  : Allow writes
   4160  */
   4161 STATIC int
   4162 _phy_84728_rom_write_enable_set(phy_ctrl_t *pc, int enable)
   4163 {
   4164     uint16  rd_data, wr_data;
   4165     uint8   wrsr_data;
   4166     int        count;
   4167 
   4168     /*
   4169      * Write SPI Control Register Write Command.
   4170      */
   4171     count = 2;
   4172     wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4173     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4174 
   4175     /*
   4176      * Write SPI Control -2 Register Address.
   4177      */
   4178     wr_data = BSDK_SPI_CTRL_2_L;
   4179     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4180 
   4181     /*
   4182      * Write SPI Control -2 Register Word-1.
   4183      */
   4184     wr_data = 0x8200;
   4185     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4186 
   4187     /*
   4188      * Write SPI Control -2 Register Word-2.
   4189      */
   4190     wr_data = 0x0100;
   4191     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4192 
   4193     /*
   4194      * Fill-up SPI Transmit Fifo With SPI EEPROM Messages.
   4195      * Write SPI Control Register Write Command.
   4196      */
   4197     count = 4;
   4198     wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4199     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4200 
   4201     /*
   4202      * Write Tx Fifo Register Address.
   4203      */
   4204     wr_data = BSDK_SPI_TXFIFO;
   4205     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4206 
   4207     /*
   4208      * Write SPI Tx Fifo Control Word-1.
   4209      */
   4210     wr_data = ((1 * 0x0100) | BSDK_MSGTYPE_HWR);
   4211     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4212 
   4213     /*
   4214      * Write SPI Tx Fifo Control Word-2.
   4215      */
   4216     wr_data = ((BSDK_MSGTYPE_HWR * 0x0100) | BSDK_WREN_OPCODE);
   4217     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4218 
   4219     /*
   4220      * Write SPI Tx Fifo Control Word-3.
   4221      */
   4222     wr_data = ((BSDK_WRSR_OPCODE * 0x100) | (0x2));
   4223     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4224 
   4225     /*
   4226      * Write SPI Tx Fifo Control Word-4.
   4227      */
   4228     wrsr_data = enable ? 0x2 : 0xc;
   4229     wr_data = ((wrsr_data * 0x0100) | wrsr_data);
   4230     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4231 
   4232     /*
   4233      * Write SPI Control Register Write Command.
   4234      */
   4235     count = 2;
   4236     wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4237     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4238 
   4239     /*
   4240      * Write SPI Control -1 Register Address.
   4241      */
   4242     wr_data = BSDK_SPI_CTRL_1_L;
   4243     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4244 
   4245     /*
   4246      * Write SPI Control -1 Register Word-1.
   4247      */
   4248     wr_data = 0x0101;
   4249     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4250 
   4251     /*
   4252      * Write SPI Control -1 Register Word-2.
   4253      */
   4254     wr_data = 0x0003;
   4255     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4256 
   4257     /*
   4258      * Wait For WRSR Command To be written.
   4259      */
   4260     SOC_IF_ERROR_RETURN(_phy_84728_rom_wait(pc));
   4261 
   4262     return SOC_E_NONE;
   4263 }
   4264 
   4265 /*
   4266  * Function:
   4267  *     bsdk_phy84728_spi_firmware_update
   4268  * Purpose:
   4269  *     Update the firmware in SPI ROM 
   4270  * Parameters:
   4271  *    phy_id    - PHY Device Address
   4272  *    new_fw    - Pointer to new firmware
   4273  *    fw_length    - Length of the firmware
   4274  * Returns:
   4275  */
   4276 int
   4277 bsdk_phy84728_spi_firmware_update(phy_ctrl_t *pc,
   4278                                   uint8 *array, uint32 datalen)
   4279 {
   4280 
   4281     uint16   data = 0;
   4282     int      j;
   4283     uint16   rd_data, wr_data;
   4284     uint8    spi_values[BSDK_WR_BLOCK_SIZE];
   4285     int count, i = 0;
   4286 
   4287 
   4288     if (array == NULL) {
   4289         return SOC_E_PARAM;
   4290     }
   4291 
   4292     /* Set Bit 2 and Bit 0 in SPI Control */
   4293     SOC_IF_ERROR_RETURN(
   4294         BSDK_MOD_PHY84728_LN_DEV1_SPI_CTRL_STATr(pc, 0x80FD, 0xffff));
   4295 
   4296     /* ser_boot pin high */
   4297     SOC_IF_ERROR_RETURN(
   4298         BSDK_MOD_PHY84728_LN_DEV1_MISC_CNTL2r(pc, 0x1, 0x1));
   4299 
   4300     /* Read LASI Status */
   4301     SOC_IF_ERROR_RETURN(
   4302         BSDK_RD_PHY84728_LN_DEV1_RX_ALARM_STATr(pc, &data));
   4303     SOC_IF_ERROR_RETURN(
   4304         BSDK_RD_PHY84728_LN_DEV1_TX_ALARM_STATr(pc, &data));
   4305     SOC_IF_ERROR_RETURN(
   4306         BSDK_RD_PHY84728_LN_DEV1_LASI_STATr(pc, &data));
   4307 
   4308     /* Enable LASI for Message Out */
   4309     SOC_IF_ERROR_RETURN(
   4310         BSDK_MOD_PHY84728_LN_DEV1_RX_ALARM_CNTLr(pc, 0x4, 0x4));
   4311 
   4312     /* Enable RX Alarm in LASI */
   4313     SOC_IF_ERROR_RETURN(
   4314         BSDK_MOD_PHY84728_LN_DEV1_LASI_CNTLr(pc, 0x4, 0x4));
   4315 
   4316     /* Read any residual Message out register */
   4317     SOC_IF_ERROR_RETURN(
   4318         BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &data));
   4319 
   4320     /* Clear LASI Message OUT status */
   4321     SOC_IF_ERROR_RETURN(
   4322         BSDK_RD_PHY84728_LN_DEV1_RX_ALARM_STATr(pc, &data));
   4323 
   4324     /* Set SPI-ROM write enable */
   4325     SOC_IF_ERROR_RETURN(
   4326         _phy_84728_rom_write_enable_set(pc, 1));
   4327 
   4328 
   4329     for (j = 0; j < datalen; j +=BSDK_WR_BLOCK_SIZE) {
   4330         /* Setup SPI Controller */
   4331         count = 2;
   4332         wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4333         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4334 
   4335         /* Write SPI Control -2 Register Address.*/
   4336         wr_data = BSDK_SPI_CTRL_2_L;
   4337         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4338 
   4339         /* Write SPI Control -2 Register Word-1. */
   4340         wr_data = 0x8200;
   4341         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4342 
   4343         /* Write SPI Control -2 Register Word-2. */
   4344         wr_data = 0x0100;
   4345         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4346         
   4347         /* Fill-up SPI Transmit Fifo.
   4348          * Write SPI Control Register Write Command.
   4349          */
   4350         count = 4 + (BSDK_WR_BLOCK_SIZE / 2);
   4351         wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4352         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4353 
   4354         /* Write Tx Fifo Register Address. */
   4355         wr_data = BSDK_SPI_TXFIFO;
   4356         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4357 
   4358         /* Write SPI Tx Fifo Control Word-1. */
   4359         wr_data = ((1 * 0x0100) | BSDK_MSGTYPE_HWR);
   4360         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4361 
   4362         /* Write SPI Tx Fifo Control Word-2. */
   4363         wr_data = ((BSDK_MSGTYPE_HWR * 0x0100) | BSDK_WREN_OPCODE);
   4364         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4365 
   4366         /* Write SPI Tx Fifo Control Word-3. */
   4367         wr_data = ((BSDK_WR_OPCODE * 0x0100) | (0x3 + BSDK_WR_BLOCK_SIZE));
   4368         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4369 
   4370         /* Write SPI Tx Fifo Control Word-4. */
   4371         wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100));
   4372         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4373 
   4374         if (datalen < (j + BSDK_WR_BLOCK_SIZE)) {   /* last block */ 
   4375             sal_memset(spi_values,0,BSDK_WR_BLOCK_SIZE);
   4376             sal_memcpy(spi_values,&array[j],datalen - j);
   4377 
   4378             for (i = 0; i < BSDK_WR_BLOCK_SIZE; i += 2) {
   4379                 /* Write SPI Tx Fifo Data Word-4. */
   4380                 wr_data = ((spi_values[i+1] * 0x0100) | spi_values[i]);
   4381                 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4382             }           
   4383         } else {        
   4384             for (i = 0; i < BSDK_WR_BLOCK_SIZE; i += 2) {
   4385                 /* Write SPI Tx Fifo Data Word-4. */
   4386                 wr_data = ((array[j+i+1] * 0x0100) | array[j+i]);
   4387                 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4388             }
   4389         }
   4390 
   4391         /* 
   4392          * Set-up SPI Controller To Transmit.
   4393          * Write SPI Control Register Write Command.
   4394          */
   4395         count = 2;
   4396         wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4397         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4398 
   4399         wr_data = BSDK_SPI_CTRL_1_L;
   4400         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4401 
   4402         /* Write SPI Control -1 Register Word-1. */
   4403         wr_data = 0x0501;
   4404         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4405 
   4406         /* Write SPI Control -1 Register Word-2. */
   4407         wr_data = 0x0003;
   4408         SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4409 
   4410         /* Wait For 64 bytes To be written.   */
   4411         SOC_IF_ERROR_RETURN(_phy_84728_rom_wait(pc));
   4412     }
   4413 
   4414     /* Clear SPI-ROM write enable */
   4415     SOC_IF_ERROR_RETURN(
   4416         _phy_84728_rom_write_enable_set(pc, 0));
   4417 
   4418     /* Disable SPI EEPROM. */
   4419     count = 2;
   4420     wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4421     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4422 
   4423     /* Write SPI Control -2 Register Address. */
   4424     wr_data = BSDK_SPI_CTRL_2_L;
   4425     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4426 
   4427     /* Write SPI Control -2 Register Word-1. */
   4428     wr_data = 0x8200;
   4429     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4430 
   4431     /* Write SPI Control -2 Register Word-2. */
   4432     wr_data = 0x0100;
   4433     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4434 
   4435 
   4436     /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */
   4437     count = 2;
   4438     wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4439     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4440 
   4441     /* Write Tx Fifo Register Address. */
   4442     wr_data = BSDK_SPI_TXFIFO;
   4443     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4444 
   4445     /* Write SPI Tx Fifo Control Word-1. */
   4446     wr_data = ((0x1*0x0100) | BSDK_MSGTYPE_HWR);
   4447     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4448 
   4449     /* Write SPI Tx Fifo Control Word-2. */
   4450     wr_data = BSDK_WRDI_OPCODE;
   4451     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4452 
   4453     /* Write SPI Control Register Write Command. */
   4454     count = 2;
   4455     wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count);
   4456     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4457 
   4458     /* Write SPI Control -1 Register Address. */
   4459     wr_data = BSDK_SPI_CTRL_1_L;
   4460     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4461 
   4462     /* Write SPI Control -1 Register Word-1. */
   4463     wr_data = 0x0101;
   4464     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4465 
   4466     /* Write SPI Control -1 Register Word-2. */
   4467     wr_data = 0x0003;
   4468     SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data));
   4469 
   4470     /* ser_boot pin LOW */
   4471     SOC_IF_ERROR_RETURN(
   4472         BSDK_MOD_PHY84728_LN_DEV1_MISC_CNTL2r(pc, 0x0, 0x1));
   4473 
   4474     /* Disable Bit 2 and Bit 0 in SPI Control */
   4475     SOC_IF_ERROR_RETURN(
   4476         BSDK_MOD_PHY84728_LN_DEV1_SPI_CTRL_STATr(pc, 0xc0F9, 0xffff));
   4477 
   4478     return SOC_E_NONE;
   4479 }
   4480 
   4481 STATIC int
   4482 _phy_84728_bsc_rw(phy_ctrl_t *pc, int dev_addr, int opr,
   4483                     int addr, int count, void *data_array,uint32 ram_start)
   4484 {
   4485     int rv = SOC_E_NONE;
   4486     int iter = 0;
   4487     uint16 data16;
   4488     int i;
   4489     int access_type;
   4490     int data_type;
   4491 
   4492     if (!data_array) {
   4493         return SOC_E_PARAM;
   4494     }
   4495 
   4496     if (count > BSDK_PHY84728_BSC_XFER_MAX) {
   4497         return SOC_E_PARAM;
   4498     }
   4499 
   4500     data_type = BSDK_PHY84728_I2C_DATA_TYPE(opr);
   4501     access_type = BSDK_PHY84728_I2C_ACCESS_TYPE(opr);
   4502 
   4503     if (access_type == BSDK_PHY84728_I2CDEV_WRITE) {
   4504         for (i = 0; i < count; i++) {
   4505             if (data_type == BSDK_PHY84728_I2C_8BIT) {
   4506                 SOC_IF_ERROR_RETURN
   4507                     (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, ram_start + i,
   4508                           ((uint8 *)data_array)[i]));
   4509             } else {  /* 16 bit */
   4510                 SOC_IF_ERROR_RETURN
   4511                     (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, ram_start + i,
   4512                           ((uint16 *)data_array)[i]));
   4513             }
   4514         }
   4515     }
   4516 
   4517     data16 = ram_start;
   4518     SOC_IF_ERROR_RETURN
   4519         (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8004, data16));
   4520     SOC_IF_ERROR_RETURN
   4521         (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8003, addr));
   4522     SOC_IF_ERROR_RETURN
   4523         (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8002, count));
   4524 
   4525     data16 = 1;
   4526     data16 |= (dev_addr<<9);
   4527     if (access_type == BSDK_PHY84728_I2CDEV_WRITE) {
   4528         data16 |= BSDK_PHY84728_WR_FREQ_400KHZ;
   4529     }
   4530 
   4531     SOC_IF_ERROR_RETURN
   4532         (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8005,data16));
   4533 
   4534     if (access_type == BSDK_PHY84728_I2CDEV_WRITE) {
   4535         data16 =  0x8000 | BSDK_PHY84728_BSC_WRITE_OP;
   4536     } else {
   4537         data16 =  0x8000 | BSDK_PHY84728_BSC_READ_OP;
   4538     }
   4539 
   4540     if (data_type == BSDK_PHY84728_I2C_16BIT) {
   4541         data16 |= (1 << 12);
   4542     }
   4543 
   4544     /* for single port mode, there should be only one I2C interface active
   4545      * from lane0. The 0x800x register block is bcst type registers. If writing
   4546      * to 0x8000 directly, it will enable all four I2C masters. Use indirect access
   4547      * to enable only the lane 0.
   4548      */
   4549 
   4550     SOC_IF_ERROR_RETURN
   4551         (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8000, data16));
   4552 
   4553     while (iter < 100000) {
   4554         rv = BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0x8000, &data16);
   4555         if (((data16 & BSDK_PHY84728_2W_STAT) == BSDK_PHY84728_2W_STAT_COMPLETE)) {
   4556             break;
   4557         }
   4558         iter++;
   4559     }
   4560 
   4561     /* need some delays */
   4562     sal_usleep(10000);
   4563 
   4564     LOG_CLI((BSL_META_U(pc->unit,
   4565                         "BSC command status %d\n"),(data16 & BSDK_PHY84728_2W_STAT)));
   4566 
   4567     if (access_type == BSDK_PHY84728_I2CDEV_WRITE) {
   4568         return SOC_E_NONE;
   4569     }
   4570 
   4571     if ((data16 & BSDK_PHY84728_2W_STAT) == BSDK_PHY84728_2W_STAT_COMPLETE) {
   4572         for (i = 0; i < count; i++) {
   4573             SOC_IF_ERROR_RETURN
   4574                 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, (ram_start+i), &data16));
   4575             if (data_type == BSDK_PHY84728_I2C_16BIT) {
   4576                 ((uint16 *)data_array)[i] = data16;
   4577                 LOG_CLI((BSL_META_U(pc->unit,
   4578                                     "%04x "), data16));
   4579             } else {
   4580                 ((uint8 *)data_array)[i] = (uint8)data16;
   4581                 LOG_CLI((BSL_META_U(pc->unit,
   4582                                     "%02x "), data16));
   4583             }
   4584         }
   4585     }
   4586     return rv;
   4587 }
   4588 
   4589 /*
   4590  * Read a slave device such as NVRAM/EEPROM connected to the 84728's I2C
   4591  * interface. This function will be mainly used for diagnostic or workaround
   4592  * purpose.
   4593  * Note:
   4594  * The size of read_array buffer must be greater than or equal to the
   4595  * parameter nbytes.
   4596  * usage example:
   4597  *   Retrieve the first 100 byte data of the non-volatile storage device with
   4598  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
   4599  *   port 2.
   4600  *   uint8 data8[100];
   4601  *   phy_84728_i2cdev_read(0,2,0x50,0,100,data8);
   4602  */
   4603 int
   4604 bsdk_phy_84728_i2cdev_read(phy_ctrl_t *pc,
   4605                      int dev_addr,  /* 7 bit I2C bus device address */
   4606                      int offset,    /* starting data address to read */
   4607                      int nbytes,    /* number of bytes to read */
   4608                      uint8 *read_array)   /* buffer to hold retrieved data */
   4609 {
   4610     return _phy_84728_bsc_rw(pc, dev_addr,BSDK_PHY84728_I2CDEV_READ,
   4611              offset, nbytes, (void *)read_array,BSDK_PHY84728_READ_START_ADDR);
   4612 
   4613 }
   4614 
   4615 /*
   4616  * Write to a slave device such as NVRAM/EEPROM connected to the 84728's I2C
   4617  * interface. This function will be mainly used for diagnostic or workaround
   4618  * purpose.
   4619  * Note:
   4620  * The size of write_array buffer should be equal to the parameter nbytes.
   4621  * The EEPROM may limit the maximun write size to 16 bytes
   4622  * usage example:
   4623  *   Write to first 100 byte space of the non-volatile storage device with
   4624  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
   4625  *   port 2, with written data specified in array data8.
   4626  *   uint8 data8[100];
   4627  *   *** initialize the data8 array with written data ***
   4628  *
   4629  *   phy_84728_i2cdev_write(0,2,0x50,0,100,data8);
   4630  */
   4631 
   4632 int
   4633 bsdk_phy_84728_i2cdev_write(phy_ctrl_t *pc,
   4634                      int dev_addr,  /* I2C bus device address */
   4635                      int offset,    /* starting data address to write to */
   4636                      int nbytes,    /* number of bytes to write */
   4637                      uint8 *write_array)   /* buffer to hold written data */
   4638 {
   4639     int j;
   4640     int rv = SOC_E_NONE;
   4641 
   4642     for (j = 0; j < (nbytes/BSDK_PHY84728_BSC_WR_MAX); j++) {
   4643         rv = _phy_84728_bsc_rw(pc, dev_addr,BSDK_PHY84728_I2CDEV_WRITE,
   4644                     offset + j * BSDK_PHY84728_BSC_WR_MAX, BSDK_PHY84728_BSC_WR_MAX,
   4645                     (void *)(write_array + j * BSDK_PHY84728_BSC_WR_MAX),
   4646                     BSDK_PHY84728_WRITE_START_ADDR);
   4647         if (rv != SOC_E_NONE) {
   4648             return rv;
   4649         }
   4650         sal_usleep(20000);
   4651     }
   4652     if (nbytes%BSDK_PHY84728_BSC_WR_MAX) {
   4653         rv = _phy_84728_bsc_rw(pc, dev_addr,BSDK_PHY84728_I2CDEV_WRITE,
   4654                 offset + j * BSDK_PHY84728_BSC_WR_MAX, nbytes%BSDK_PHY84728_BSC_WR_MAX,
   4655                 (void *)(write_array + j * BSDK_PHY84728_BSC_WR_MAX),
   4656                 BSDK_PHY84728_WRITE_START_ADDR);
   4657     }
   4658     return rv;
   4659 }
   4660 
   4661 void _phy_84728_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode,
   4662                                             int offset, uint16 *value)
   4663 {
   4664 
   4665     switch (mode) {
   4666     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE:
   4667         *value |= (0x0 << offset);
   4668         break;
   4669     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD:
   4670         *value |= (0x1 << offset);
   4671         break;
   4672     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN:
   4673         *value |= (0x2 << offset);
   4674         break;
   4675     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP:
   4676         *value |= (0x3 << offset);
   4677         break;
   4678     }
   4679 
   4680 }
   4681 
   4682 void _phy_84728_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode,
   4683                                             int offset, uint16 *value)
   4684 {
   4685 
   4686     switch (mode) {
   4687     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE:
   4688         *value |= (0x0 << offset);
   4689         break;
   4690     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD:
   4691         *value |= (0x1 << offset);
   4692         break;
   4693     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP:
   4694         *value |= (0x2 << offset);
   4695         break;
   4696     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME:
   4697         *value |= (0x3 << offset);
   4698         break;
   4699     }
   4700 
   4701 }
   4702 
   4703 void _phy_84728_decode_egress_message_mode(uint16 value, int offset,
   4704                                             soc_port_phy_timesync_event_message_egress_mode_t *mode)
   4705 {
   4706 
   4707     switch ((value >> offset) & 0x3) {
   4708     case 0x0:
   4709         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE;
   4710         break;
   4711     case 0x1:
   4712         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD;
   4713         break;
   4714     case 0x2:
   4715         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN;
   4716         break;
   4717     case 0x3:
   4718         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP;
   4719         break;
   4720     }
   4721 
   4722 }
   4723 
   4724 void _phy_84728_decode_ingress_message_mode(uint16 value, int offset,
   4725                                             soc_port_phy_timesync_event_message_ingress_mode_t *mode)
   4726 {
   4727 
   4728     switch ((value >> offset) & 0x3) {
   4729     case 0x0:
   4730         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE;
   4731         break;
   4732     case 0x1:
   4733         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD;
   4734         break;
   4735     case 0x2:
   4736         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP;
   4737         break;
   4738     case 0x3:
   4739         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME;
   4740         break;
   4741     }
   4742 
   4743 }
   4744 
   4745 void _phy_84728_encode_gmode(soc_port_phy_timesync_global_mode_t mode,
   4746                                             uint16 *value)
   4747 {
   4748 
   4749     switch (mode) {
   4750     case SOC_PORT_PHY_TIMESYNC_MODE_FREE:
   4751         *value = 0x1;
   4752         break;
   4753     case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN:
   4754         *value = 0x2;
   4755         break;
   4756     case SOC_PORT_PHY_TIMESYNC_MODE_CPU:
   4757         *value = 0x3;
   4758         break;
   4759     default:
   4760         break;
   4761     }
   4762 
   4763 }
   4764 
   4765 void _phy_84728_decode_gmode(uint16 value,
   4766                                             soc_port_phy_timesync_global_mode_t *mode)
   4767 {
   4768 
   4769     switch (value & 0x3) {
   4770     case 0x1:
   4771         *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   4772         break;
   4773     case 0x2:
   4774         *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN;
   4775         break;
   4776     case 0x3:
   4777         *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU;
   4778         break;
   4779     default:
   4780         break;
   4781     }
   4782 
   4783 }
   4784 
   4785 
   4786 void _phy_84728_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode,
   4787                                             uint16 *value)
   4788 {
   4789 
   4790     switch (mode) {
   4791     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0:
   4792         *value = 1U << 0;
   4793         break;
   4794     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1:
   4795         *value = 1U << 1;
   4796         break;
   4797     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT:
   4798         *value = 1U << 2;
   4799         break;
   4800     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU:
   4801         *value = 1U << 3;
   4802         break;
   4803     default:
   4804         break;
   4805     }
   4806 
   4807 }
   4808 
   4809 void _phy_84728_decode_framesync_mode(uint16 value,
   4810                                             soc_port_phy_timesync_framesync_mode_t *mode)
   4811 {
   4812 
   4813     switch (value & 0xf) {
   4814     case 1U << 0:
   4815         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0;
   4816         break;
   4817     case 1U << 1:
   4818         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1;
   4819         break;
   4820     case 1U << 2:
   4821         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT;
   4822         break;
   4823     case 1U << 3:
   4824         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU;
   4825         break;
   4826     default:
   4827         break;
   4828     }
   4829 
   4830 }
   4831 
   4832 void _phy_84728_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode,
   4833                                             uint16 *value)
   4834 {
   4835 
   4836     switch (mode) {
   4837     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE:
   4838         *value = 0x0;
   4839         break;
   4840     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME:
   4841         *value = 0x1;
   4842         break;
   4843     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN:
   4844         *value = 0x2;
   4845         break;
   4846     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC:
   4847         *value = 0x3;
   4848         break;
   4849     }
   4850 
   4851 }
   4852 
   4853 void _phy_84728_decode_syncout_mode(uint16 value,
   4854                                             soc_port_phy_timesync_syncout_mode_t *mode)
   4855 {
   4856 
   4857     switch (value & 0x3) {
   4858     case 0x0:
   4859         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   4860         break;
   4861     case 0x1:
   4862         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME;
   4863         break;
   4864     case 0x2:
   4865         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN;
   4866         break;
   4867     case 0x3:
   4868         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC;
   4869         break;
   4870     }
   4871 
   4872 }
   4873 
   4874 
   4875 int
   4876 phy_84728_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf)
   4877 {
   4878     uint16 rx_control_reg = 0, tx_control_reg = 0, rx_tx_control_reg = 0,
   4879            en_control_reg = 0, capture_en_reg = 0,
   4880            nse_sc_8 = 0, nse_nco_3 = 0, value, mpls_control_reg = 0, temp = 0,
   4881            gmode = 0, framesync_mode = 0, syncout_mode = 0, mask = 0,
   4882            pulse_1_length, pulse_2_length, length_threshold, event_offset;
   4883     uint32 interval;
   4884     int i;
   4885     phy_ctrl_t *pc;
   4886 
   4887     pc = EXT_PHY_SW_STATE(unit, port);
   4888 
   4889     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   4890 
   4891         if (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) {
   4892             SOC_IF_ERROR_RETURN
   4893                 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc600, 0x0003));
   4894 #if 0
   4895             SOC_IF_ERROR_RETURN
   4896                 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc8f0, 0x0000));
   4897 #endif
   4898             en_control_reg |= 3U;
   4899             nse_sc_8 |= (1U << 12);
   4900         }
   4901 
   4902         /* slice enable control reg */
   4903         SOC_IF_ERROR_RETURN
   4904             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc600, en_control_reg, 
   4905                                            3U));
   4906 
   4907         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) {
   4908             capture_en_reg |= 3U;
   4909         }
   4910 
   4911         /* TXRX SOP TS CAPTURE ENABLE reg */
   4912         SOC_IF_ERROR_RETURN
   4913             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc607, capture_en_reg, 3U));
   4914 
   4915         if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) {
   4916             nse_sc_8 |= (1U << 13);
   4917         }
   4918 
   4919         /* NSE SC 8 register */
   4920         SOC_IF_ERROR_RETURN
   4921             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, nse_sc_8, 
   4922                                            (1U << 12)| (1U << 13)));
   4923 
   4924         if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) {
   4925             rx_tx_control_reg |= (1U << 3);
   4926         }
   4927 
   4928         /* RX TX CONTROL register */
   4929         SOC_IF_ERROR_RETURN
   4930             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc61c, rx_tx_control_reg, (1U << 3)));
   4931 
   4932         if (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) {
   4933             rx_control_reg |= (1U << 3);
   4934             tx_control_reg |= (1U << 3);
   4935         }
   4936 
   4937         if (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) {
   4938             rx_control_reg |= (1U << 2);
   4939             tx_control_reg |= (1U << 2);
   4940         }
   4941 
   4942         if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) {
   4943             rx_control_reg |= (1U << 1);
   4944             tx_control_reg |= (1U << 1);
   4945         }
   4946 
   4947         if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) {
   4948             rx_control_reg |= (1U << 0);
   4949             tx_control_reg |= (1U << 0);
   4950         }
   4951 
   4952         /* TX CONTROL register */
   4953         SOC_IF_ERROR_RETURN
   4954             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc618, tx_control_reg));
   4955                                           
   4956         /* RX CONTROL register */
   4957         SOC_IF_ERROR_RETURN
   4958             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc61a, rx_control_reg));
   4959                                           
   4960         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) {
   4961             nse_nco_3 &= (uint16) ~(1U << 14);
   4962         } else {
   4963             nse_nco_3 |= (1U << 14);
   4964         }
   4965 
   4966         /* NSE NCO 3 register */
   4967         SOC_IF_ERROR_RETURN
   4968             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc630, nse_nco_3, 
   4969                                            (1U << 14)));
   4970     }
   4971 
   4972     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   4973         /* VLAN TAG register */
   4974         SOC_IF_ERROR_RETURN
   4975             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc61d, conf->itpid));
   4976     }
   4977 
   4978     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   4979         /* OUTER VLAN TAG register */
   4980         SOC_IF_ERROR_RETURN
   4981             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc61e, conf->otpid));
   4982     }
   4983 
   4984     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   4985         /* INNER VLAN TAG register */
   4986         SOC_IF_ERROR_RETURN
   4987             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc61f, conf->otpid2));
   4988     }
   4989 
   4990     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   4991         SOC_IF_ERROR_RETURN
   4992             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc636, conf->ts_divider & 0xfff));
   4993     }
   4994 
   4995     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   4996         SOC_IF_ERROR_RETURN
   4997             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc605, conf->rx_link_delay & 0xffff));
   4998         SOC_IF_ERROR_RETURN
   4999             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc606, (conf->rx_link_delay >> 16) & 0xffff));
   5000     }
   5001 
   5002 
   5003     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   5004 
   5005         /* TIME CODE 5 register */
   5006         SOC_IF_ERROR_RETURN
   5007             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc610, (uint16)(conf->original_timecode.nanoseconds & 0xffff)));
   5008 
   5009         /* TIME CODE 4 register */
   5010         SOC_IF_ERROR_RETURN
   5011             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc60f, (uint16)((conf->original_timecode.nanoseconds >> 16) & 0xffff)));
   5012 
   5013         /* TIME CODE 3 register */
   5014         SOC_IF_ERROR_RETURN
   5015             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc60e, (uint16)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff)));
   5016 
   5017         /* TIME CODE 2 register */
   5018         SOC_IF_ERROR_RETURN
   5019             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc60d, (uint16)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) & 0xffff)));
   5020 
   5021         /* TIME CODE 1 register */
   5022         SOC_IF_ERROR_RETURN
   5023             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc60c, (uint16)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff)));
   5024     }
   5025 
   5026     mask = 0;
   5027 
   5028     /* NSE SC 8 register */
   5029 
   5030     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   5031         _phy_84728_encode_gmode(conf->gmode,&gmode);
   5032         mask |= (0x3 << 14);
   5033     }
   5034 
   5035     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   5036         _phy_84728_encode_framesync_mode(conf->framesync.mode, &framesync_mode);
   5037         mask |= (0xf << 2) | (0x1 << 11);
   5038 
   5039         /* Divide by 6.4 without floating point */
   5040         length_threshold = (conf->framesync.length_threshold * 10) / 64;
   5041         event_offset = (conf->framesync.event_offset * 10) / 64;
   5042 
   5043         SOC_IF_ERROR_RETURN
   5044             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63c, length_threshold));
   5045         SOC_IF_ERROR_RETURN
   5046             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63b, event_offset));
   5047     }
   5048 
   5049     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   5050         _phy_84728_encode_syncout_mode(conf->syncout.mode, &syncout_mode);
   5051         mask |= (0x3 << 0);
   5052 
   5053         /* Divide by 6.4 without floating point */
   5054         interval = (conf->syncout.interval * 10) / 64;
   5055         pulse_1_length = (conf->syncout.pulse_1_length * 10) / 64;
   5056         pulse_2_length = (conf->syncout.pulse_2_length * 10) / 64;
   5057 
   5058         SOC_IF_ERROR_RETURN
   5059             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc635, interval & 0xffff));
   5060         SOC_IF_ERROR_RETURN
   5061             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc634,
   5062                 ((pulse_2_length & 0x3) << 14) | ((interval >> 16) & 0x3fff)));
   5063         SOC_IF_ERROR_RETURN
   5064             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc633,
   5065                 ((pulse_1_length & 0x1ff) << 7) | ((pulse_2_length >> 2) & 0x7f)));
   5066 
   5067         SOC_IF_ERROR_RETURN
   5068             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc639,
   5069                 (uint16)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xfff0)));
   5070         SOC_IF_ERROR_RETURN
   5071             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc638,
   5072                 (uint16)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff)));
   5073         SOC_IF_ERROR_RETURN
   5074             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc637,
   5075                 (uint16)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff)));
   5076     }
   5077 
   5078     SOC_IF_ERROR_RETURN
   5079         (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, (gmode << 14) | 
   5080             ((framesync_mode & 0x2) ? (1U << 11) : (1U << 6)) | /* if bits 1 or 2 are set, turn off syncout */
   5081             (framesync_mode << 2) | (syncout_mode << 0), mask));
   5082 
   5083     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   5084         /* RX_TS_Offset[19:0] = (1.0xC67B[7:4]) | (1.0xC60B[15:0]) */
   5085         SOC_IF_ERROR_RETURN
   5086             (BSDK_WR_PHY84728_LN_DEV1_PMDr( pc, 0xc60b,
   5087                        (uint16) (  conf->rx_timestamp_offset & 0x0ffff)) );
   5088         SOC_IF_ERROR_RETURN
   5089             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b,
   5090                        (uint16) (((conf->rx_timestamp_offset & 0xf0000)) >> 12),
   5091                        (0xf << 4)) );
   5092     }
   5093 
   5094     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   5095         /* TX_TS_Offset[19:0] = (1.0xC67B[3:0]) | (1.0xC60A[15:0]) */
   5096         SOC_IF_ERROR_RETURN
   5097             (BSDK_WR_PHY84728_LN_DEV1_PMDr( pc, 0xc60a,
   5098                        (uint16) (  conf->tx_timestamp_offset & 0x0ffff)) );
   5099         SOC_IF_ERROR_RETURN
   5100             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b,
   5101                        (uint16) (((conf->tx_timestamp_offset & 0xf0000)) >> 16),
   5102                        (0xf << 0)) );
   5103     }
   5104 
   5105     value = mask =  0;
   5106     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   5107         _phy_84728_encode_egress_message_mode(conf->tx_sync_mode, 0, &value);
   5108         mask |= 0x3 << 0;
   5109     }
   5110 
   5111     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   5112         _phy_84728_encode_egress_message_mode(conf->tx_delay_request_mode, 2, &value);
   5113         mask |= 0x3 << 2;
   5114     }
   5115 
   5116     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   5117         _phy_84728_encode_egress_message_mode(conf->tx_pdelay_request_mode, 4, &value);
   5118         mask |= 0x3 << 4;
   5119     }
   5120 
   5121     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   5122         _phy_84728_encode_egress_message_mode(conf->tx_pdelay_response_mode, 6, &value);
   5123         mask |= 0x3 << 6;
   5124     }
   5125                                             
   5126     /* TX EVENT MESSAGE MODE SEL register */
   5127     SOC_IF_ERROR_RETURN
   5128         (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc601, value, mask)); 
   5129 
   5130     value = mask =  0;
   5131     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   5132         _phy_84728_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value);
   5133         mask |= 0x3 << 0;
   5134     }
   5135 
   5136     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   5137         _phy_84728_encode_ingress_message_mode(conf->rx_delay_request_mode, 2, &value);
   5138         mask |= 0x3 << 2;
   5139     }
   5140 
   5141     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   5142         _phy_84728_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 4, &value);
   5143         mask |= 0x3 << 4;
   5144     }
   5145 
   5146     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   5147         _phy_84728_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 6, &value);
   5148         mask |= 0x3 << 6;
   5149     }
   5150                                             
   5151     /* RX EVENT MESSAGE MODE SEL register */
   5152     SOC_IF_ERROR_RETURN
   5153         (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc603, value, mask)); 
   5154 
   5155     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   5156 
   5157         /* Initial ref phase [15:0] */
   5158         SOC_IF_ERROR_RETURN
   5159             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc623, (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff)));
   5160 
   5161         /* Initial ref phase [31:16]  */
   5162         SOC_IF_ERROR_RETURN
   5163             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc622, (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff)));
   5164 
   5165         /*  Initial ref phase [47:32] */
   5166         SOC_IF_ERROR_RETURN
   5167             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc621, (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff)));
   5168     }
   5169 
   5170 
   5171     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   5172         SOC_IF_ERROR_RETURN
   5173             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc625, conf->phy_1588_dpll_ref_phase_delta & 0xffff));
   5174         SOC_IF_ERROR_RETURN
   5175             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc624, (conf->phy_1588_dpll_ref_phase_delta >> 16) & 0xffff));
   5176     }
   5177 
   5178     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   5179         /* DPLL K1 */
   5180         SOC_IF_ERROR_RETURN
   5181             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc626, conf->phy_1588_dpll_k1 & 0xff)); 
   5182     }
   5183 
   5184     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   5185         /* DPLL K2 */
   5186         SOC_IF_ERROR_RETURN
   5187             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc627, conf->phy_1588_dpll_k2 & 0xff)); 
   5188     }
   5189 
   5190     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   5191         /* DPLL K3 */
   5192         SOC_IF_ERROR_RETURN
   5193             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc628, conf->phy_1588_dpll_k3 & 0xff)); 
   5194     }
   5195 
   5196 
   5197     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) {
   5198 
   5199         /* MPLS controls */
   5200         if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE) {
   5201             mpls_control_reg |= (1U << 7) | (1U << 3);
   5202         }
   5203 
   5204         if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE) {
   5205             mpls_control_reg |= (1U << 6) | (1U << 2);
   5206         }
   5207 
   5208         if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE) {
   5209             mpls_control_reg |= (1U << 4);
   5210         }
   5211 
   5212         if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE) {
   5213             mpls_control_reg |= (1U << 5) | (1U << 1);
   5214         }
   5215 
   5216         SOC_IF_ERROR_RETURN
   5217             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc651, mpls_control_reg, 
   5218                 (1U << 7) | (1U << 3)| (1U << 6) | (1U << 2) | (1U << 4) | (1U << 5) | (1U << 1))); 
   5219 
   5220         /* special label [19:16] */
   5221         SOC_IF_ERROR_RETURN
   5222             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc653, (uint16)((conf->mpls_control.special_label >> 16 ) & 0xf)));
   5223                                           
   5224         /* special label [15:0] */
   5225         SOC_IF_ERROR_RETURN
   5226             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc652, (uint16)(conf->mpls_control.special_label & 0xffff)));
   5227 
   5228         for (i = 0; i < 10; i++ ) {
   5229             SOC_IF_ERROR_RETURN
   5230                 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc654 + i, (uint16)(conf->mpls_control.labels[i].value & 0xffff)));
   5231             SOC_IF_ERROR_RETURN
   5232                 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc661 + i, (uint16)(conf->mpls_control.labels[i].mask & 0xffff)));
   5233         }
   5234  
   5235         SOC_IF_ERROR_RETURN
   5236             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc65e, (uint16)(
   5237                 ((conf->mpls_control.labels[3].value >> 4)  & 0xf000) | 
   5238                 ((conf->mpls_control.labels[2].value >> 8)  & 0x0f00) | 
   5239                 ((conf->mpls_control.labels[1].value >> 12) & 0x00f0) | 
   5240                 ((conf->mpls_control.labels[0].value >> 16) & 0x000f))));
   5241 
   5242         SOC_IF_ERROR_RETURN
   5243             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc65f, (uint16)(
   5244                 ((conf->mpls_control.labels[7].value >> 4)  & 0xf000) | 
   5245                 ((conf->mpls_control.labels[6].value >> 8)  & 0x0f00) | 
   5246                 ((conf->mpls_control.labels[5].value >> 12) & 0x00f0) | 
   5247                 ((conf->mpls_control.labels[4].value >> 16) & 0x000f))));
   5248 
   5249         SOC_IF_ERROR_RETURN
   5250             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc660, (uint16)(
   5251                 ((conf->mpls_control.labels[9].value >> 12) & 0x00f0) | 
   5252                 ((conf->mpls_control.labels[8].value >> 16) & 0x000f))));
   5253 
   5254         SOC_IF_ERROR_RETURN
   5255             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66b, (uint16)(
   5256                 ((conf->mpls_control.labels[3].mask >> 4)  & 0xf000) | 
   5257                 ((conf->mpls_control.labels[2].mask >> 8)  & 0x0f00) | 
   5258                 ((conf->mpls_control.labels[1].mask >> 12) & 0x00f0) | 
   5259                 ((conf->mpls_control.labels[0].mask >> 16) & 0x000f))));
   5260 
   5261         SOC_IF_ERROR_RETURN
   5262             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66c, (uint16)(
   5263                 ((conf->mpls_control.labels[7].mask >> 4)  & 0xf000) | 
   5264                 ((conf->mpls_control.labels[6].mask >> 8)  & 0x0f00) | 
   5265                 ((conf->mpls_control.labels[5].mask >> 12) & 0x00f0) | 
   5266                 ((conf->mpls_control.labels[4].mask >> 16) & 0x000f))));
   5267 
   5268         SOC_IF_ERROR_RETURN
   5269             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66d, (uint16)(
   5270                 ((conf->mpls_control.labels[9].mask >> 12) & 0x00f0) | 
   5271                 ((conf->mpls_control.labels[8].mask >> 16) & 0x000f))));
   5272 
   5273         /* label flags */
   5274         temp = 0;
   5275         for (i = 0; i < 8; i++ ) {
   5276             temp |= conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT ? (0x2 << (i<<1)) : 0;
   5277             temp |= (conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN)  ? (0x1 << (i<<1)) : 0;
   5278         }
   5279 
   5280         SOC_IF_ERROR_RETURN
   5281             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66e, temp)); 
   5282 
   5283         temp = 0;
   5284         for (i = 0; i < 2; i++ ) {
   5285             temp |= (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT) ? (0x2 << (i<<1)) : 0;
   5286             temp |= (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN)  ? (0x1 << (i<<1)) : 0;
   5287         }
   5288 
   5289         SOC_IF_ERROR_RETURN
   5290             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66f, temp)); 
   5291     }
   5292 
   5293 
   5294     return SOC_E_NONE;
   5295 }
   5296 
   5297 int
   5298 phy_84728_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf)
   5299 {
   5300     uint16 rx_tx_control_reg = 0, tx_control_reg = 0,
   5301               en_control_reg = 0, capture_en_reg = 0,
   5302               nse_sc_8 = 0, nse_nco_3 = 0, temp1, temp2, temp3, value, mpls_control_reg;
   5303     soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   5304     soc_port_phy_timesync_framesync_mode_t framesync_mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE;
   5305     soc_port_phy_timesync_syncout_mode_t syncout_mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   5306     int i;
   5307     phy_ctrl_t *pc;
   5308 
   5309     pc = EXT_PHY_SW_STATE(unit, port);
   5310 
   5311     conf->flags = 0;
   5312 
   5313     /* NSE SC 8 register */
   5314     SOC_IF_ERROR_RETURN
   5315         (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, &nse_sc_8));
   5316 
   5317     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   5318         /* SLICE ENABLE CONTROL register */
   5319         SOC_IF_ERROR_RETURN
   5320             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc600, &en_control_reg)); 
   5321 
   5322         if (en_control_reg & 1U) {
   5323             conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE;
   5324         }
   5325 
   5326         /* TXRX SOP TS CAPTURE ENABLE reg */
   5327         SOC_IF_ERROR_RETURN
   5328             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc607, &capture_en_reg)); 
   5329 
   5330         if (capture_en_reg & 1U) {
   5331             conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE;
   5332         }
   5333 
   5334         /* NSE SC 8 register */
   5335         /* SOC_IF_ERROR_RETURN
   5336             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, &nse_sc_8));
   5337          */
   5338 
   5339         if (nse_sc_8 & (1U << 13)) {
   5340             conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE;
   5341         }
   5342 
   5343          /* RX TX CONTROL register */
   5344         SOC_IF_ERROR_RETURN
   5345             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc61c, &rx_tx_control_reg));
   5346 
   5347         if (rx_tx_control_reg & (1U << 3)) {
   5348             conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE;
   5349         }
   5350 
   5351         /* TX CONTROL register */
   5352         SOC_IF_ERROR_RETURN
   5353             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc618, &tx_control_reg));
   5354                                           
   5355         if (tx_control_reg & (1U << 3)) {
   5356             conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE;
   5357         }
   5358 
   5359         if (tx_control_reg & (1U << 2)) {
   5360             conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE;
   5361         }
   5362 
   5363         if (tx_control_reg & (1U << 1)) {
   5364             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE;
   5365         }
   5366 
   5367         if (tx_control_reg & (1U << 0)) {
   5368             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE;
   5369         }
   5370 
   5371         SOC_IF_ERROR_RETURN
   5372             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc630, &nse_nco_3));
   5373 
   5374         if (!(nse_nco_3 & (1U << 14))) {
   5375             conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT;
   5376         }
   5377     }
   5378 
   5379     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   5380         _phy_84728_decode_gmode((nse_sc_8 >> 14),&gmode);
   5381         conf->gmode = gmode;
   5382     }
   5383 
   5384     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   5385         _phy_84728_decode_framesync_mode((nse_sc_8 >> 2), &framesync_mode);
   5386         conf->framesync.mode = framesync_mode;
   5387         SOC_IF_ERROR_RETURN
   5388             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63c, &temp1));
   5389         SOC_IF_ERROR_RETURN
   5390             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63b, &temp2));
   5391 
   5392         /* Multiply by 6.4 without floating point */
   5393         conf->framesync.length_threshold = (temp1 * 64) / 10;
   5394         conf->framesync.event_offset = (temp2 * 64) / 10;
   5395     }
   5396 
   5397     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   5398         _phy_84728_decode_syncout_mode((nse_sc_8 >> 0), &syncout_mode);
   5399         conf->syncout.mode = syncout_mode;
   5400 
   5401         SOC_IF_ERROR_RETURN
   5402             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc635, &temp1));
   5403         SOC_IF_ERROR_RETURN
   5404             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc634, &temp2));
   5405         SOC_IF_ERROR_RETURN
   5406             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc633, &temp3));
   5407 
   5408         /* Multiply by 6.4 without floating point */
   5409         conf->syncout.pulse_1_length = (((temp3 >> 7) & 0x1ff) * 64) / 10;
   5410         conf->syncout.pulse_2_length = ((((temp3 & 0x7f) << 2) | ((temp2 >> 14) & 0x3)) * 64) / 10;
   5411         conf->syncout.interval =  ((((temp2 & 0x3fff) << 16) | temp1) * 64) / 10;
   5412 
   5413         SOC_IF_ERROR_RETURN
   5414             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc639, &temp1));
   5415         SOC_IF_ERROR_RETURN
   5416             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc638, &temp2));
   5417         SOC_IF_ERROR_RETURN
   5418             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc637, &temp3));
   5419 
   5420         COMPILER_64_SET(conf->syncout.syncout_ts, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1)));
   5421     }
   5422 
   5423     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   5424         /* VLAN TAG register */
   5425         SOC_IF_ERROR_RETURN
   5426             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc61d, &conf->itpid));
   5427     }
   5428 
   5429     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   5430         /* OUTER VLAN TAG register */
   5431         SOC_IF_ERROR_RETURN
   5432             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc61e, &conf->otpid));
   5433     }
   5434 
   5435     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   5436         /* INNER VLAN TAG register */
   5437         SOC_IF_ERROR_RETURN
   5438             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc61f, &conf->otpid2));
   5439     }
   5440 
   5441     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   5442         SOC_IF_ERROR_RETURN
   5443             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc636, &conf->ts_divider));
   5444         conf->ts_divider &= 0xfff;
   5445     }
   5446 
   5447     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   5448         SOC_IF_ERROR_RETURN
   5449             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc605, &temp1));
   5450         SOC_IF_ERROR_RETURN
   5451             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc606, &temp2));
   5452 
   5453         conf->rx_link_delay = ((uint32)temp2 << 16) | temp1; 
   5454     }
   5455 
   5456     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   5457         /* TIME CODE 5 register */
   5458         SOC_IF_ERROR_RETURN
   5459             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc610, &temp1));
   5460 
   5461         /* TIME CODE 4 register */
   5462         SOC_IF_ERROR_RETURN
   5463             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60f, &temp2));
   5464 
   5465         conf->original_timecode.nanoseconds = ((uint32)temp2 << 16) | temp1; 
   5466 
   5467         /* TIME CODE 3 register */
   5468         SOC_IF_ERROR_RETURN
   5469             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60e, &temp1));
   5470 
   5471         /* TIME CODE 2 register */
   5472         SOC_IF_ERROR_RETURN
   5473             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60d, &temp2));
   5474 
   5475         /* TIME CODE 1 register */
   5476         SOC_IF_ERROR_RETURN
   5477             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60c, &temp3));
   5478 
   5479         /* conf->original_timecode.seconds = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */
   5480 
   5481         COMPILER_64_SET(conf->original_timecode.seconds, ((uint32)temp3),  (((uint32)temp2<<16)|((uint32)temp1)));
   5482     }
   5483 
   5484     /* Tx/Rx TS Offset */
   5485     if (conf->validity_mask & (SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET |
   5486                                SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET)) {
   5487         /* MSB [19:16] of Tx/Rx TS Offset */
   5488         SOC_IF_ERROR_RETURN
   5489             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, &temp1));
   5490     }
   5491     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   5492         /* RX_TS_Offset[19:0] = (1.0xC67B[7:4]) | (1.0xC60B[15:0]) */
   5493         SOC_IF_ERROR_RETURN
   5494             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60b, &temp2));
   5495         conf->rx_timestamp_offset = (((uint32)(temp1 & 0xf0)) << 12) | temp2;
   5496     }
   5497     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   5498         /* TX_TS_Offset[19:0] = (1.0xC67B[3:0]) | (1.0xC60A[15:0]) */
   5499         SOC_IF_ERROR_RETURN
   5500             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60a, &temp2));
   5501         conf->rx_timestamp_offset = (((uint32)(temp1 & 0x0f)) << 16) | temp2;
   5502     }
   5503 
   5504     /* TX EVENT MESSAGE MODE SEL register */
   5505     SOC_IF_ERROR_RETURN
   5506         (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc601, &value)); 
   5507 
   5508     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   5509         _phy_84728_decode_egress_message_mode(value, 0, &conf->tx_sync_mode);
   5510     }
   5511 
   5512     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   5513         _phy_84728_decode_egress_message_mode(value, 2, &conf->tx_delay_request_mode);
   5514     }
   5515 
   5516     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   5517         _phy_84728_decode_egress_message_mode(value, 4, &conf->tx_pdelay_request_mode);
   5518     }
   5519 
   5520     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   5521         _phy_84728_decode_egress_message_mode(value, 6, &conf->tx_pdelay_response_mode);
   5522     }
   5523                                             
   5524     /* RX EVENT MESSAGE MODE SEL register */
   5525     SOC_IF_ERROR_RETURN
   5526         (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc603, &value)); 
   5527 
   5528     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   5529         _phy_84728_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode);
   5530     }
   5531 
   5532     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   5533         _phy_84728_decode_ingress_message_mode(value, 2, &conf->rx_delay_request_mode);
   5534     }
   5535 
   5536     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   5537         _phy_84728_decode_ingress_message_mode(value, 4, &conf->rx_pdelay_request_mode);
   5538     }
   5539 
   5540     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   5541         _phy_84728_decode_ingress_message_mode(value, 6, &conf->rx_pdelay_response_mode);
   5542     }
   5543                                             
   5544     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   5545         /* Initial ref phase [15:0] */
   5546         SOC_IF_ERROR_RETURN
   5547             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc623, &temp1));
   5548 
   5549         /* Initial ref phase [31:16] */
   5550         SOC_IF_ERROR_RETURN
   5551             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc622, &temp2));
   5552 
   5553         /* Initial ref phase [47:32] */
   5554         SOC_IF_ERROR_RETURN
   5555             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc621, &temp3));
   5556 
   5557         /* conf->phy_1588_dpll_phase_initial = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */
   5558 
   5559         COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1)));
   5560     }
   5561 
   5562     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   5563         SOC_IF_ERROR_RETURN
   5564             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc625, &temp1));
   5565         SOC_IF_ERROR_RETURN
   5566             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc624, &temp2));
   5567 
   5568         conf->phy_1588_dpll_ref_phase_delta = ((uint32)temp2 << 16) | temp1; 
   5569     }
   5570 
   5571     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   5572         /* DPLL K1 */
   5573         SOC_IF_ERROR_RETURN
   5574             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc626, &conf->phy_1588_dpll_k1)); 
   5575         conf->phy_1588_dpll_k1 &= 0xff;
   5576     }
   5577 
   5578     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   5579         /* DPLL K2 */
   5580         SOC_IF_ERROR_RETURN
   5581             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc627, &conf->phy_1588_dpll_k2)); 
   5582         conf->phy_1588_dpll_k2 &= 0xff;
   5583     }
   5584 
   5585     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   5586         /* DPLL K3 */
   5587         SOC_IF_ERROR_RETURN
   5588             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc628, &conf->phy_1588_dpll_k3)); 
   5589         conf->phy_1588_dpll_k3 &= 0xff;
   5590     }
   5591 
   5592     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) {
   5593         SOC_IF_ERROR_RETURN
   5594             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc651, &mpls_control_reg));
   5595                                           
   5596         conf->mpls_control.flags = 0;
   5597 
   5598         if (mpls_control_reg & (1U << 7)) {
   5599             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE;
   5600         }
   5601 
   5602         if (mpls_control_reg & (1U << 6)) {
   5603             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE;
   5604         }
   5605 
   5606         if (mpls_control_reg & (1U << 4)) {
   5607             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE;
   5608         }
   5609 
   5610         if (mpls_control_reg & (1U << 5)) {
   5611             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE;
   5612         }
   5613 
   5614         /* special label [19:16] */
   5615         SOC_IF_ERROR_RETURN
   5616             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc653, &temp2));
   5617                                           
   5618         /* special label [15:0] */
   5619         SOC_IF_ERROR_RETURN
   5620             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc652, &temp1));
   5621 
   5622         conf->mpls_control.special_label = ((uint32)(temp2 & 0x0f) << 16) | temp1; 
   5623 
   5624 
   5625         for (i = 0; i < 10; i++ ) {
   5626 
   5627             SOC_IF_ERROR_RETURN
   5628                 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc654 + i, &temp1));
   5629             conf->mpls_control.labels[i].value = temp1;
   5630 
   5631             SOC_IF_ERROR_RETURN
   5632                 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc661 + i, &temp1));
   5633             conf->mpls_control.labels[i].mask = temp1;
   5634         }
   5635  
   5636         /* now get [19:16] of labels */
   5637         SOC_IF_ERROR_RETURN
   5638             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc65e, &temp1));
   5639 
   5640         conf->mpls_control.labels[0].value |= ((uint32)(temp1 & 0x000f) << 16); 
   5641         conf->mpls_control.labels[1].value |= ((uint32)(temp1 & 0x00f0) << 12); 
   5642         conf->mpls_control.labels[2].value |= ((uint32)(temp1 & 0x0f00) << 8); 
   5643         conf->mpls_control.labels[3].value |= ((uint32)(temp1 & 0xf000) << 4); 
   5644 
   5645 
   5646         SOC_IF_ERROR_RETURN
   5647             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc65f, &temp1));
   5648 
   5649         conf->mpls_control.labels[4].value |= ((uint32)(temp1 & 0x000f) << 16); 
   5650         conf->mpls_control.labels[5].value |= ((uint32)(temp1 & 0x00f0) << 12); 
   5651         conf->mpls_control.labels[6].value |= ((uint32)(temp1 & 0x0f00) << 8); 
   5652         conf->mpls_control.labels[7].value |= ((uint32)(temp1 & 0xf000) << 4); 
   5653 
   5654 
   5655         SOC_IF_ERROR_RETURN
   5656             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc660, &temp1));
   5657 
   5658         conf->mpls_control.labels[8].value |= ((uint32)(temp1 & 0x000f) << 16); 
   5659         conf->mpls_control.labels[9].value |= ((uint32)(temp1 & 0x00f0) << 12); 
   5660 
   5661         /* now get [19:16] of masks */
   5662         SOC_IF_ERROR_RETURN
   5663             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66b, &temp1));
   5664 
   5665         conf->mpls_control.labels[0].mask |= ((uint32)(temp1 & 0x000f) << 16); 
   5666         conf->mpls_control.labels[1].mask |= ((uint32)(temp1 & 0x00f0) << 12); 
   5667         conf->mpls_control.labels[2].mask |= ((uint32)(temp1 & 0x0f00) << 8); 
   5668         conf->mpls_control.labels[3].mask |= ((uint32)(temp1 & 0xf000) << 4); 
   5669 
   5670 
   5671         SOC_IF_ERROR_RETURN
   5672             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66c, &temp1));
   5673 
   5674         conf->mpls_control.labels[4].mask |= ((uint32)(temp1 & 0x000f) << 16); 
   5675         conf->mpls_control.labels[5].mask |= ((uint32)(temp1 & 0x00f0) << 12); 
   5676         conf->mpls_control.labels[6].mask |= ((uint32)(temp1 & 0x0f00) << 8); 
   5677         conf->mpls_control.labels[7].mask |= ((uint32)(temp1 & 0xf000) << 4); 
   5678 
   5679 
   5680         SOC_IF_ERROR_RETURN
   5681             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66d, &temp1));
   5682 
   5683         conf->mpls_control.labels[8].mask |= ((uint32)(temp1 & 0x000f) << 16); 
   5684         conf->mpls_control.labels[9].mask |= ((uint32)(temp1 & 0x00f0) << 12); 
   5685 
   5686 
   5687         /* label flags */
   5688         SOC_IF_ERROR_RETURN
   5689             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66e, &temp1)); 
   5690         for (i = 0; i < 8; i++ ) {
   5691             conf->mpls_control.labels[i].flags |= temp1 & (0x2 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT : 0;
   5692             conf->mpls_control.labels[i].flags |= temp1 & (0x1 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN : 0;
   5693         }
   5694         SOC_IF_ERROR_RETURN
   5695             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66f, &temp2)); 
   5696         for (i = 0; i < 2; i++ ) {
   5697             conf->mpls_control.labels[i + 8].flags |= temp2 & (0x2 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT : 0;
   5698             conf->mpls_control.labels[i + 8].flags |= temp2 & (0x1 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN : 0;
   5699         }
   5700 
   5701     }
   5702     return SOC_E_NONE;
   5703 }
   5704 
   5705 int
   5706 phy_84728_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 value)
   5707 {
   5708     uint16 temp1, temp2; 
   5709     uint32 value0;
   5710     phy_ctrl_t *pc;
   5711 
   5712     pc = EXT_PHY_SW_STATE(unit, port);
   5713 
   5714     switch (type) {
   5715 
   5716     case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   5717     case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   5718         return SOC_E_FAIL;
   5719 
   5720 
   5721     case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   5722         SOC_IF_ERROR_RETURN
   5723             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc62f, (uint16)(COMPILER_64_LO(value) & 0xffff)));
   5724         SOC_IF_ERROR_RETURN
   5725             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc62e, (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff)));
   5726         break;
   5727 
   5728     case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC:
   5729 
   5730         SOC_IF_ERROR_RETURN
   5731             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, &temp1));
   5732         temp2 = ((temp1 | (0x3 << 14) | (0x1 << 12)) & ~(0xf << 2)) | (0x1 << 5);
   5733         SOC_IF_ERROR_RETURN
   5734             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, temp2));
   5735         sal_usleep(1);
   5736         temp2 &= ~((0x1 << 5) | (0x1 << 12));
   5737         SOC_IF_ERROR_RETURN
   5738             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, temp2));
   5739         sal_usleep(1);
   5740         SOC_IF_ERROR_RETURN
   5741             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, temp1));
   5742         break;
   5743 
   5744     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   5745         COMPILER_64_SHR(value, 4);
   5746         SOC_IF_ERROR_RETURN
   5747             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc632, (uint16)(COMPILER_64_LO(value) & 0xffff)));
   5748         SOC_IF_ERROR_RETURN
   5749             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc631, (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff)));
   5750         SOC_IF_ERROR_RETURN
   5751             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc630, (uint16)(COMPILER_64_HI(value) & 0xfff), 0x0fff));
   5752         break;
   5753 
   5754     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   5755         temp1 = 0;
   5756         temp2 = 0;
   5757 
   5758         value0 = COMPILER_64_LO(value);
   5759 
   5760         if (value0 &  SOC_PORT_PHY_TIMESYNC_TN_LOAD) {
   5761             temp1 |= 1U << 11;
   5762         }
   5763         if (value0 &  SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) {
   5764             temp2 |= 1U << 11;
   5765         }
   5766         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) {
   5767             temp1 |= 1U << 10;
   5768         }
   5769         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) {
   5770             temp2 |= 1U << 10;
   5771         }
   5772         if (value0 &  SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) {
   5773             temp1 |= 1U << 9;
   5774         }
   5775         if (value0 &  SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) {
   5776             temp2 |= 1U << 9;
   5777         }
   5778         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) {
   5779             temp1 |= 1U << 8;
   5780         }
   5781         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) {
   5782             temp2 |= 1U << 8;
   5783         }
   5784         if (value0 &  SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) {
   5785             temp1 |= 1U << 7;
   5786         }
   5787         if (value0 &  SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) {
   5788             temp2 |= 1U << 7;
   5789         }
   5790         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) {
   5791             temp1 |= 1U << 6;
   5792         }
   5793         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) {
   5794             temp2 |= 1U << 6;
   5795         }
   5796         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) {
   5797             temp1 |= 1U << 5;
   5798         }
   5799         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) {
   5800             temp2 |= 1U << 5;
   5801         }
   5802         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) {
   5803             temp1 |= 1U << 4;
   5804         }
   5805         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) {
   5806             temp2 |= 1U << 4;
   5807         }
   5808         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) {
   5809             temp1 |= 1U << 3;
   5810         }
   5811         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) {
   5812             temp2 |= 1U << 3;
   5813         }
   5814         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) {
   5815             temp1 |= 1U << 2;
   5816         }
   5817         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) {
   5818             temp2 |= 1U << 2;
   5819         }
   5820         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) {
   5821             temp1 |= 1U << 1;
   5822         }
   5823         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) {
   5824             temp2 |= 1U << 1;
   5825         }
   5826         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) {
   5827             temp1 |= 1U << 0;
   5828         }
   5829         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) {
   5830             temp2 |= 1U << 0;
   5831         }
   5832         SOC_IF_ERROR_RETURN
   5833             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc615, temp1));
   5834 
   5835         /* always load not supported at the moment */
   5836         /*
   5837         SOC_IF_ERROR_RETURN
   5838             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc615, temp2));
   5839          */
   5840 
   5841         break;
   5842 
   5843     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT:
   5844         temp1 = 0;
   5845 
   5846         value0 = COMPILER_64_LO(value);
   5847 
   5848         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT) {
   5849             temp1 |= 1U << 1;
   5850         }
   5851         if (value0 &  SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT) {
   5852             temp1 |= 1U << 0;
   5853         }
   5854         SOC_IF_ERROR_RETURN
   5855             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc617, temp1));
   5856         break;
   5857 
   5858     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   5859         temp1 = 0;
   5860 
   5861         value0 = COMPILER_64_LO(value);
   5862 
   5863         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) {
   5864             temp1 |= 1U << 1;
   5865         }
   5866         if (value0 &  SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) {
   5867             temp1 |= 1U << 0;
   5868         }
   5869         SOC_IF_ERROR_RETURN
   5870             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc616, temp1));
   5871         break;
   5872 
   5873     case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   5874         value0 = COMPILER_64_LO(value);
   5875         /* TX_TS_Offset[19:0] = (1.0xC67B[3:0]) | (1.0xC60A[15:0]) */
   5876         SOC_IF_ERROR_RETURN
   5877             (BSDK_WR_PHY84728_LN_DEV1_PMDr( pc, 0xc60a,
   5878                        (uint16) (  value0 & 0x0ffff)) );
   5879         SOC_IF_ERROR_RETURN
   5880             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b,
   5881                        (uint16) (((value0 & 0xf0000)) >> 16), (0xf << 0)) );
   5882         break;
   5883 
   5884     case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   5885         value0 = COMPILER_64_LO(value);
   5886         /* RX_TS_Offset[19:0] = (1.0xC67B[7:4]) | (1.0xC60B[15:0]) */
   5887         SOC_IF_ERROR_RETURN
   5888             (BSDK_WR_PHY84728_LN_DEV1_PMDr( pc, 0xc60b,
   5889                        (uint16) (  value0 & 0x0ffff)) );
   5890         SOC_IF_ERROR_RETURN
   5891             (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b,
   5892                        (uint16) (((value0 & 0xf0000)) >> 12), (0xf << 4)) );
   5893         break;
   5894 
   5895     default:
   5896         return SOC_E_NONE;
   5897         break;
   5898     }
   5899 
   5900     return SOC_E_NONE;
   5901 }
   5902 
   5903 int
   5904 phy_84728_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 *value)
   5905 {
   5906     uint16 value0 = 0;
   5907     uint16 value1 = 0;
   5908     uint16 value2 = 0;
   5909     uint32 value4 = 0;
   5910     phy_ctrl_t *pc;
   5911 
   5912     pc = EXT_PHY_SW_STATE(unit, port);
   5913 
   5914     switch (type) {
   5915     case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   5916 
   5917         SOC_IF_ERROR_RETURN
   5918             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x4));
   5919 
   5920         SOC_IF_ERROR_RETURN
   5921             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc647, &value0)); 
   5922         SOC_IF_ERROR_RETURN
   5923             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc646, &value1)); 
   5924         SOC_IF_ERROR_RETURN
   5925             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc645, &value2)); 
   5926 
   5927         SOC_IF_ERROR_RETURN
   5928             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x8));
   5929         SOC_IF_ERROR_RETURN
   5930             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x0));
   5931 
   5932     /*    *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */
   5933         COMPILER_64_SET((*value), ((uint32)value2),  (((uint32)value1<<16)|((uint32)value0)));
   5934 
   5935         break;
   5936 
   5937     case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   5938 
   5939         SOC_IF_ERROR_RETURN
   5940             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x1));
   5941 
   5942         SOC_IF_ERROR_RETURN
   5943             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc640, &value0)); 
   5944         SOC_IF_ERROR_RETURN
   5945             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63f, &value1)); 
   5946         SOC_IF_ERROR_RETURN
   5947             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63e, &value2)); 
   5948 
   5949         SOC_IF_ERROR_RETURN
   5950             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x2));
   5951         SOC_IF_ERROR_RETURN
   5952             (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x0));
   5953 
   5954     /*   *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */
   5955          COMPILER_64_SET((*value), ((uint32)value2),  (((uint32)value1<<16)|((uint32)value0)));
   5956         break;
   5957 
   5958     case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   5959         SOC_IF_ERROR_RETURN
   5960             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc62f, &value0));
   5961         SOC_IF_ERROR_RETURN
   5962             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc62e, &value1));
   5963         COMPILER_64_SET((*value), 0, (((uint32)value1<<16)|((uint32)value0)));
   5964         break;
   5965 
   5966     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   5967         SOC_IF_ERROR_RETURN
   5968             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc632, &value0)); 
   5969         SOC_IF_ERROR_RETURN
   5970             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc631, &value1)); 
   5971         SOC_IF_ERROR_RETURN
   5972             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc630, &value2)); 
   5973         COMPILER_64_SET((*value), ((uint32)(value2 & 0x0fff)),  (((uint32)value1<<16)|((uint32)value0)));
   5974         COMPILER_64_SHL((*value), 4);
   5975         break;
   5976 
   5977     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   5978 
   5979         SOC_IF_ERROR_RETURN
   5980             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc615, &value1));
   5981         /* always load not supported at the moment */
   5982         /*
   5983         SOC_IF_ERROR_RETURN
   5984             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc615, &value2));
   5985          */
   5986 
   5987         value4 = 0;
   5988 
   5989         if (value1 & (1U << 11)) {
   5990             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_TN_LOAD;
   5991         }
   5992 #if 0
   5993         if (value2 & (1U << 11)) {
   5994             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD;
   5995         }
   5996 #endif
   5997         if (value1 & (1U << 10)) {
   5998             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD;
   5999         }
   6000 #if 0
   6001         if (value2 & (1U << 10)) {
   6002             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD;
   6003         }
   6004 #endif
   6005         if (value1 & (1U << 9)) {
   6006             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD;
   6007         }
   6008 #if 0
   6009         if (value2 & (1U << 9)) {
   6010             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD;
   6011         }
   6012 #endif
   6013         if (value1 & (1U << 8)) {
   6014             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD;
   6015         }
   6016         if (value1 & (1U << 8)) {
   6017             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD;
   6018         }
   6019         if (value1 & (1U << 7)) {
   6020             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD;
   6021         }
   6022         if (value1 & (1U << 7)) {
   6023             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD;
   6024         }
   6025         if (value1 & (1U << 6)) {
   6026             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD;
   6027         }
   6028 #if 0
   6029         if (value2 & (1U << 6)) {
   6030             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD;
   6031         }
   6032 #endif
   6033         if (value1 & (1U << 5)) {
   6034             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD;
   6035         }
   6036 #if 0
   6037         if (value2 & (1U << 5)) {
   6038             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD;
   6039         }
   6040 #endif
   6041         if (value1 & (1U << 4)) {
   6042             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD;
   6043         }
   6044 #if 0
   6045         if (value2 & (1U << 4)) {
   6046             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD;
   6047         }
   6048 #endif
   6049         if (value1 & (1U << 3)) {
   6050             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD;
   6051         }
   6052 #if 0
   6053         if (value2 & (1U << 3)) {
   6054             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD;
   6055         }
   6056 #endif
   6057         if (value1 & (1U << 2)) {
   6058             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD;
   6059         }
   6060 #if 0
   6061         if (value2 & (1U << 2)) {
   6062             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD;
   6063         }
   6064 #endif
   6065         if (value1 & (1U << 1)) {
   6066             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD;
   6067         }
   6068 #if 0
   6069         if (value2 & (1U << 1)) {
   6070             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD;
   6071         }
   6072 #endif
   6073         if (value1 & (1U << 0)) {
   6074             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD;
   6075         }
   6076 #if 0
   6077         if (value2 & (1U << 0)) {
   6078             value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD;
   6079         }
   6080 #endif
   6081         COMPILER_64_SET((*value), 0, value4);
   6082 
   6083         break;
   6084 
   6085     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT:
   6086         SOC_IF_ERROR_RETURN
   6087             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc617, &value1));
   6088 
   6089         value0 = 0;
   6090 
   6091         if (value1 & (1U << 1)) {
   6092             value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT;
   6093         }
   6094         if (value1 & (1U << 0)) {
   6095             value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT;
   6096         }
   6097         COMPILER_64_SET((*value), 0, (uint32)value0);
   6098 
   6099         break;
   6100 
   6101     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   6102         SOC_IF_ERROR_RETURN
   6103             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc616, &value1));
   6104 
   6105         value0 = 0;
   6106 
   6107         if (value1 & (1U << 1)) {
   6108             value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK;
   6109         }
   6110         if (value1 & (1U << 0)) {
   6111             value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK;
   6112         }
   6113         COMPILER_64_SET((*value), 0, (uint32)value0);
   6114 
   6115         break;
   6116 
   6117     case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   6118         /* MSB [19:16] of Tx TS Offset */
   6119         SOC_IF_ERROR_RETURN
   6120             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, &value1));
   6121         /* TX_TS_Offset[19:0] = (1.0xC67B[3:0]) | (1.0xC60A[15:0]) */
   6122         SOC_IF_ERROR_RETURN
   6123             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60a, &value0));
   6124         COMPILER_64_SET((*value),  0,
   6125                        (((uint32)(value1 & 0x0f)) << 16) | value0);
   6126         break;
   6127 
   6128     case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   6129         /* MSB [19:16] of Rx TS Offset */
   6130         SOC_IF_ERROR_RETURN
   6131             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, &value1));
   6132         /* RX_TS_Offset[19:0] = (1.0xC67B[7:4]) | (1.0xC60B[15:0]) */
   6133         SOC_IF_ERROR_RETURN
   6134             (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60b, &value0));
   6135         COMPILER_64_SET((*value),  0,
   6136                        (((uint32)(value1 & 0xf0)) << 12) | value0);
   6137         break;
   6138 
   6139     default:
   6140         return SOC_E_FAIL;
   6141     }
   6142 
   6143     return SOC_E_NONE;
   6144 }
   6145 
   6146 int
   6147 bsdk_phy84728_reg_read(phy_ctrl_t *  pc, uint32 flags, uint8 reg_bank,
   6148                           uint16 reg_addr, uint16 *data)
   6149 {
   6150     int rv;
   6151 #if 0
   6152     uint16 reg_data, xpmd_reg_sel = 0xffff;
   6153 #endif
   6154     uint32 cl45_reg_addr;
   6155 
   6156     rv = SOC_E_NONE;
   6157 
   6158 #if 0
   6159     if (flags & BSDK_PHY84728_SYS_SIDE) {
   6160         /* Select System side registers */
   6161         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel);
   6162         reg_data = 0x01;
   6163         SOC_IF_ERROR_RETURN(
   6164             BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   6165 
   6166         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr);
   6167         rv = BSDK_PHY84728_IO_MDIO_READ(pc, cl45_reg_addr, data);
   6168 
   6169         /* De-Select System side registers */
   6170         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel);
   6171         reg_data = 0x0;
   6172         SOC_IF_ERROR_RETURN(
   6173             BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   6174 
   6175     } else {
   6176 #endif
   6177     {
   6178         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr);
   6179         rv = BSDK_PHY84728_IO_MDIO_READ(pc, cl45_reg_addr, data);
   6180     }
   6181 
   6182     return rv;
   6183 }
   6184 
   6185 int
   6186 bsdk_phy84728_reg_write(phy_ctrl_t *  pc, uint32 flags, uint8 reg_bank,
   6187                            uint16 reg_addr, uint16 data)
   6188 {
   6189     int rv;
   6190 #if 0
   6191     uint16 reg_data, xpmd_reg_sel = 0xffff;
   6192 #endif
   6193     uint32 cl45_reg_addr;
   6194 
   6195     rv = SOC_E_NONE;
   6196 
   6197 #if 0
   6198     if (flags & BSDK_PHY84728_SYS_SIDE) {
   6199         /* Select System side registers */
   6200         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel);
   6201         reg_data = 0x01;
   6202         SOC_IF_ERROR_RETURN(
   6203             BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   6204 
   6205         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr);
   6206         rv = BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, data);
   6207 
   6208         /* De-Select System side registers */
   6209         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel);
   6210         reg_data = 0x00;
   6211         SOC_IF_ERROR_RETURN(
   6212             BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   6213 
   6214     } else {
   6215 #endif
   6216     {
   6217         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr);
   6218         rv = BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, data);
   6219     }
   6220 
   6221     return rv;
   6222 }
   6223 
   6224 
   6225 int
   6226 bsdk_phy84728_reg_modify(phy_ctrl_t *  pc, uint32 flags, uint8 reg_bank,
   6227                             uint16 reg_addr, uint16 data, uint16 mask)
   6228 {
   6229     uint16  tmp, otmp, reg_data;
   6230     uint32 cl45_reg_addr = 0;
   6231 #if 0
   6232     uint16 xpmd_reg_sel = 0xffff;
   6233 #endif
   6234 
   6235 #if 0
   6236     if (flags & BSDK_PHY84728_SYS_SIDE) {
   6237         /* Select System side registers */
   6238         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel);
   6239         reg_data = 0x01;
   6240         SOC_IF_ERROR_RETURN(
   6241             BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   6242 
   6243         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr);
   6244 
   6245         SOC_IF_ERROR_RETURN
   6246             (BSDK_PHY84728_IO_MDIO_READ(pc, cl45_reg_addr, &tmp));
   6247 
   6248         reg_data = data & mask; /* Mask off other bits */
   6249         otmp = tmp;
   6250         tmp &= ~(mask);
   6251         tmp |= reg_data;
   6252 
   6253         if (otmp != tmp) {
   6254             SOC_IF_ERROR_RETURN
   6255                 (BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, tmp));
   6256         }
   6257 
   6258         /* De-Select System side registers */
   6259         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel);
   6260         data = 0x00;
   6261         SOC_IF_ERROR_RETURN(
   6262             BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, data));
   6263 
   6264     } else {
   6265 #endif
   6266     {
   6267         cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr);
   6268 
   6269         SOC_IF_ERROR_RETURN
   6270             (BSDK_PHY84728_IO_MDIO_READ(pc, cl45_reg_addr, &tmp));
   6271 
   6272         reg_data = data & mask; /* Mask off other bits */
   6273         otmp = tmp;
   6274         tmp &= ~(mask);
   6275         tmp |= reg_data;
   6276 
   6277         if (otmp != tmp) {
   6278             SOC_IF_ERROR_RETURN
   6279                 (BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, tmp));
   6280         }
   6281     }
   6282     return SOC_E_NONE;
   6283 }
   6284 
   6285 /*
   6286  * Variable:
   6287  *    phy_84728_drv
   6288  * Purpose:
   6289  *    Phy Driver for BCM84728 PHY
   6290  */
   6291 
   6292 phy_driver_t phy_84728drv_xe = {
   6293     "84728 1G/10-Gigabit PHY Driver",
   6294     phy_84728_init,        /* Init */
   6295     phy_null_reset,       /* Reset */
   6296     phy_84728_link_get,    /* Link get   */
   6297     phy_84728_enable_set,  /* Enable set */
   6298     phy_null_enable_get,  /* Enable get */
   6299     phy_84728_duplex_set,  /* Duplex set */
   6300     phy_84728_duplex_get,  /* Duplex get */
   6301     phy_84728_speed_set,   /* Speed set  */
   6302     phy_84728_speed_get,   /* Speed get  */
   6303     phy_84728_master_set,  /* Master set */
   6304     phy_84728_master_get,  /* Master get */
   6305     phy_84728_an_set,      /* ANA set */
   6306     phy_84728_an_get,      /* ANA get */
   6307     NULL,                 /* Local Advert set, deprecated */
   6308     NULL,                 /* Local Advert get, deprecated */
   6309     NULL,                 /* Remote Advert get, deprecated */
   6310     phy_84728_lb_set,      /* PHY loopback set */
   6311     phy_84728_lb_get,      /* PHY loopback set */
   6312     phy_null_interface_set,  /* IO Interface set */
   6313     phy_84728_interface_get, /* IO Interface get */
   6314     NULL,                   /* pd_ability, deprecated */
   6315     phy_84728_link_up,
   6316     phy_84728_link_down,
   6317     phy_84728_mdix_set,        /* phy_84728_mdix_set */
   6318     phy_84728_mdix_get,        /* phy_84728_mdix_get */
   6319     phy_84728_mdix_status_get, /* phy_84728_mdix_status_get */
   6320     phy_84728_medium_config_set, /* medium config setting set */
   6321     phy_84728_medium_config_get, /* medium config setting get */
   6322     phy_84728_medium_status,        /* active medium */
   6323     NULL,                    /* phy_cable_diag  */
   6324     NULL,                    /* phy_link_change */
   6325     phy_84728_control_set,    /* phy_control_set */
   6326     phy_84728_control_get,    /* phy_control_get */
   6327     NULL,                    /* phy_reg_read */
   6328     NULL,                    /* phy_reg_write */
   6329     NULL,                    /* phy_reg_modify */
   6330     NULL,                    /* phy_notify */
   6331     phy_84728_probe,         /* pd_probe  */
   6332     phy_84728_ability_advert_set,  /* pd_ability_advert_set */
   6333     phy_84728_ability_advert_get,  /* pd_ability_advert_get */
   6334     phy_84728_ability_remote_get,  /* pd_ability_remote_get */
   6335     phy_84728_ability_local_get,   /* pd_ability_local_get  */
   6336     phy_84728_firmware_set,
   6337     phy_84728_timesync_config_set,
   6338     phy_84728_timesync_config_get,
   6339     phy_84728_timesync_control_set,
   6340     phy_84728_timesync_control_get
   6341 };
   6342 #else /* INCLUDE_PHY_84728 */
   6343 int _phy_84728_not_empty;
   6344 #endif /* INCLUDE_PHY_84728 */