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

phy84756_fcmap.c (463541B)


      1 
      2 
      3 /*
      4  * 
      5  *
      6  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      7  * 
      8  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      9  *
     10  * File:        phy84756.c
     11  * Purpose:     SDK PHY driver for BCM84756 (FCMAP)
     12  *
     13  * Supported BCM546X Family of PHY devices:
     14  *
     15  *      Device  Ports    Media                           MAC Interface
     16  *      84756    4       4 10G SFP+                      XFI
     17  *      84757    4       4 10G SFP+/8(4/2) FC            XFI
     18  *      84759    4       4 10G SFP+                      XFI
     19  *
     20  *               OUI        Model   Revision
     21  *  BCM84756    18-C0-86    100111  00xx
     22  *  BCM84757    18-C0-86    100111  10xx
     23  *  BCM84759    18-C0-86    100111  01xx
     24  *
     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_FCMAP) || defined(INCLUDE_MACSEC)
     51 #if defined(INCLUDE_PHY_84756)
     52 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     53 #include "phyident.h"
     54 #include "phyreg.h"
     55 #include "phynull.h"
     56 #include "phyfege.h"
     57 #include "phyxehg.h"
     58 
     59 #if defined(INCLUDE_FCMAP)
     60 #include <soc/fcmapphy.h>
     61 #endif
     62 #if defined(INCLUDE_MACSEC)
     63 #include <soc/macsecphy.h>
     64 #endif
     65 #include "phy_mac_ctrl.h"
     66 #include "phy_xmac.h"
     67 #include "phy84756_fcmap_int.h"
     68 #include "phy84756_fcmap.h"
     69 #include "phy84756_i2c.h"
     70 #if defined(INCLUDE_FCMAP)
     71 #include <bfcmap_int.h>
     72 #include <bfcmap_io.h>
     73 #endif
     74 
     75 #define ADVERT_ALL_COPPER \
     76         (SOC_PA_PAUSE | SOC_PA_SPEED_10MB | \
     77          SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB)
     78 
     79 #define ADVERT_ALL_FIBER \
     80         (SOC_PA_PAUSE | SOC_PA_SPEED_1000MB) 
     81 
     82 #define ADVERT_ALL_10GFIBER \
     83         (SOC_PA_PAUSE | SOC_PA_SPEED_10GB) 
     84 
     85 #define PHY84756_REG_READ(_unit, _phy_ctrl, _addr, _val) \
     86             READ_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val))
     87             
     88 #define PHY84756_REG_WRITE(_unit, _phy_ctrl, _addr, _val) \
     89                 WRITE_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val))
     90 
     91 #define READ_PHY84756_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \
     92             PHY84756_REG_READ((_unit), (_phy_ctrl), \
     93               SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val))
     94               
     95 #define WRITE_PHY84756_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \
     96                 PHY84756_REG_WRITE((_unit), (_phy_ctrl), \
     97                   SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val))
     98 
     99 
    100 #define BFCMAP_PHY84756_LINE_MAC_PORT(p)    (p)
    101 #define BFCMAP_PHY84756_SWITCH_MAC_PORT(p)  ((p) + 1)
    102 
    103 #define PHY84756_XFI(unit,_pc)\
    104 BFCMAP_PHY84756_IO_MDIO_WRITE((_pc), BLMI_IO_CL45_ADDRESS(1, 0xffff), 0x1)
    105 
    106 #define PHY84756_MMF(unit,_pc)\
    107 BFCMAP_PHY84756_IO_MDIO_WRITE((_pc), BLMI_IO_CL45_ADDRESS(1, 0xffff), 0x0)
    108 
    109 
    110 /* 40G support macros */
    111 #undef  _PHY_CALL
    112 #define _PHY_CALL(_pd, _pf, _pa) \
    113          ((_pd)->_pf == 0 ? SOC_E_UNAVAIL : (_pd)->_pf _pa)
    114 
    115 extern phy_driver_t phy_84741drv_xe;
    116 #define PHY84756_40G  (&phy_84741drv_xe) 
    117 #define PHY84756_SINGLE_PORT_MODE(_pc)  \
    118 (SOC_INFO((_pc)->unit).port_num_lanes[(_pc)->port] >= 4)
    119 #define PHY84756_IS_8474X(_pc) ((_pc)->size > sizeof(phy84756_map_t))
    120 #define PHY84756_CALL_IF_SINGLE_PORT(_u, _p, _func) \
    121         do { \
    122             int _rv; \
    123             phy_ctrl_t *_pc = EXT_PHY_SW_STATE((_u), (_p)); \
    124             if (PHY84756_IS_8474X(_pc)  && \
    125                 PHY84756_SINGLE_PORT_MODE(_pc)) { \
    126                 _rv = (_func); \
    127                 return _rv; \
    128             } \
    129          } while (0)
    130 
    131 #define PHY84756_CALL_IF_8474X(_u, _p, _func) \
    132         do { \
    133             phy_ctrl_t *_pc = EXT_PHY_SW_STATE((_u), (_p)); \
    134             int _sav; \
    135             if (PHY84756_IS_8474X(_pc)) {\
    136                 _sav = PHYCTRL_INIT_STATE(_pc);\
    137                 SOC_IF_ERROR_RETURN(_func); \
    138                 if (PHY84756_SINGLE_PORT_MODE(_pc)) { \
    139                     return SOC_E_NONE; \
    140                 }\
    141                 PHYCTRL_INIT_STATE_SET(_pc, _sav);\
    142             } \
    143          } while (0)
    144 
    145 #define    PHY84756_PMAD_CHIP_MODE_MASK      0x3
    146 #define    PHY84756_PMAD_DAC_MODE_MASK       (1 << 3)
    147 #define    PHY84756_PMAD_BKPLANE_MODE_MASK   (1 << 2)
    148 #define    PHY84756_PMAD_DAC_MODE            0x8
    149 #define    PHY84756_PMAD_MODE_40G            0x1
    150 #define NUM_LANES  4
    151 STATIC int
    152 _phy_84741_squelch_enable(int unit, soc_port_t port, int intf, int enable, int force);
    153 STATIC int
    154 _phy_84741_single_to_quad_mode(int unit,soc_port_t port, phy_ctrl_t *pc);
    155 
    156 STATIC int
    157 phy_84756_macsec_enable(int unit, int lport, int enable);
    158 
    159 /*
    160  * PHY Map structure for mapping mac drivers
    161  */
    162 typedef struct phy84756_map_s {
    163     bfcmap_phy84756_intf_t line_mode;     /* configured line mode */
    164     phy_mac_ctrl_t      *unimac;
    165     phy_mac_ctrl_t      *xmac;
    166     int phy_ext_rom_boot;
    167     int fcmap_enable;
    168     int macsec_enable;
    169     int macsec_support;
    170     int fiber_force_speed;
    171     int skip_fw_download;
    172     int chip_rev_id;
    173     uint8 *firmware;
    174     int firmware_len;
    175 }phy84756_map_t;
    176 
    177 /* 
    178  * PHY MDIO Address, Device Address and Device Port Mapping table
    179  */
    180 #define PHY84756_PHY_INFO(_pc) \
    181 ((phy84756_map_t *)(((char *)((_pc) + 1))+(_pc)->size-sizeof(phy84756_map_t)))
    182 
    183 #define PHY_EXT_ROM_BOOT(_pc)  ((PHY84756_PHY_INFO(_pc))->phy_ext_rom_boot)
    184 #define FCMAP_ENABLE(_pc)      ((PHY84756_PHY_INFO(_pc))->fcmap_enable)
    185 #define MACSEC_ENABLE(_pc)     ((PHY84756_PHY_INFO(_pc))->macsec_enable)
    186 #define MACSEC_SUPPORT(_pc)    ((PHY84756_PHY_INFO(_pc))->macsec_support)
    187 
    188 #define FIBER_FORCE_SPEED(_pc) ((PHY84756_PHY_INFO(_pc))->fiber_force_speed)
    189 #define SKIP_EDC_FW_DOWNLOAD(_pc)  ((PHY84756_PHY_INFO(_pc))->skip_fw_download)
    190 #define FIRMWARE(_pc)          ((PHY84756_PHY_INFO(_pc))->firmware)
    191 #define FIRMWARE_LEN(_pc)      ((PHY84756_PHY_INFO(_pc))->firmware_len)
    192 #define CHIP_REV_ID(_pc)       ((PHY84756_PHY_INFO(_pc))->chip_rev_id)
    193 
    194 #define CHIP_IS_A0(_pc)  (CHIP_REV_ID(_pc) == 0xa0a0)
    195 #define CHIP_IS_B0(_pc)  (CHIP_REV_ID(_pc) == 0xb0b0)
    196 #define CHIP_IS_C0(_pc)  (CHIP_REV_ID(_pc) == 0xc0c0 || CHIP_REV_ID(_pc) == 0xc1c1 || CHIP_REV_ID(_pc) == 0xc2c2)
    197 /*#define CHIP_IS_C0(_pc) \
    198     ((PHY_REV((_pc)->phy_id0, (_pc)->phy_id1) & 0xe) == 0xa ) 
    199 */
    200 
    201 /* OUI from ID0 and ID1 registers contents */
    202 #define BFCMAP_PHY84756_PHY_OUI(id0, id1)                          \
    203     bfcmap_phy84756_bit_rev_by_byte_word32((buint32_t)(id0) << 6 | \
    204                                            ((id1) >> 10 & 0x3f))
    205 
    206 /* PHY model from ID0 and ID1 register Contents */
    207 #define BFCMAP_PHY84756_PHY_MODEL(id0, id1) ((id1) >> 4 & 0x3f)
    208 
    209 /* PHY revision from ID0 and ID1 register Contents */
    210 #define BFCMAP_PHY84756_PHY_REV(id0, id1)   ((id1) & 0xf)
    211 
    212 #define PHY84756_EDC_MODE_MASK          0xff
    213 /* PRBS */
    214 #define PHY84756_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS         0x0135
    215 #define PHY84756_40G_PRBS31             (1 << 7)               
    216 #define PHY84756_40G_PRBS9              (1 << 6) 
    217 #define PHY84756_40G_PRBS_TX_ENABLE     (1 << 3) 
    218 #define PHY84756_40G_PRBS_RX_ENABLE     (1 << 0) 
    219 #define PHY84756_40G_PRBS_ENABLE     (PHY84756_40G_PRBS_RX_ENABLE | \
    220     PHY84756_40G_PRBS_TX_ENABLE)
    221 
    222 #define PHY84756_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0            0x0140 
    223 #define PHY84756_USER_PRBS_CONTROL_0_REGISTER                       0xCD14 
    224 #define PHY84756_USER_PRBS_TX_INVERT   (1 << 4)
    225 #define PHY84756_USER_PRBS_RX_INVERT   (1 << 15)
    226 #define PHY84756_USER_PRBS_INVERT      (1 << 4 | 1 << 15)
    227 #define PHY84756_USER_PRBS_ENABLE      (1 << 7)
    228 #define PHY84756_USER_PRBS_TYPE_MASK   (0x7)
    229 #define PHY84756_USER_PRBS_TYPE_MASK_1G   (0x3)
    230 
    231 #define PHY84756_USER_PRBS_STATUS_0_REGISTER                        0xCD15 
    232 #define PHY84756_GENSIG_8071_REGISTER                               0xCD16 
    233 #define PHY84756_RESET_CONTROL_REGISTER                             0xCD17 
    234 
    235 /* Speed/Val Map */
    236 #define  SP_MAP(_s,_v)\
    237     ((_s) == 1000  ?  ((_v) -  (((_v) >= 3) ? 3 : 1)) : (_v))
    238 
    239 /* Disable Comma Detect and CL36 */
    240 #define PHY84756_1G_PRBS_XGXS_CTRL                                  0x2c2e
    241 #define PHY84756_1G_PRBS_LANE_CTRL2                                 0xff00
    242 #define PHY84756_1G_PRBS_LANE_CTRL0                                 0x0011
    243 #define PHY84756_1G_USER_PRBS_TX_INVERT   (1 << 2)
    244 
    245 /* preemphasis control */
    246 #define PHY84756_PREEMPH_CTRL_FORCE_SHFT       15
    247 #define PHY84756_PREEMPH_GET_FORCE(_val)  \
    248     (((_val) >> PHY84756_PREEMPH_CTRL_FORCE_SHFT) & 1)
    249 #define PHY84756_PREEMPH_CTRL_POST_TAP_SHFT    10
    250 #define PHY84756_PREEMPH_GET_POST_TAP(_val) \
    251     (((_val) >> PHY84756_PREEMPH_CTRL_POST_TAP_SHFT) & 0x1f)
    252 #define PHY84756_PREEMPH_CTRL_MAIN_TAP_SHFT    4
    253 #define PHY84756_PREEMPH_GET_MAIN_TAP(_val) \
    254     (((_val) >> PHY84756_PREEMPH_CTRL_MAIN_TAP_SHFT) & 0x3f) 
    255 #define PHY84756_PREEMPH_REG_FORCE_MASK     (1 << 15)
    256 #define PHY84756_PREEMPH_REG_POST_TAP_SHFT  4
    257 #define PHY84756_PREEMPH_REG_POST_TAP_MASK  (0xf << PHY84756_PREEMPH_REG_POST_TAP_SHFT)
    258 #define PHY84756_PREEMPH_REG_MAIN_TAP_SHFT  11   
    259 #define PHY84756_PREEMPH_REG_MAIN_TAP_MASK  (0x1f << PHY84756_PREEMPH_REG_MAIN_TAP_SHFT)
    260 #define PHY84756_PREEMPH_REG_TX_PWRDN_MASK  (0x1 << 10)
    261 #define PHY84756_PDET_MASK   (1 << 0)
    262 /*
    263  * Function:     
    264  *    bfcmap_bit_rev_by_byte_word32
    265  * Purpose:    
    266  *    Reverse the bits in each byte of a 32 bit long 
    267  * Parameters:
    268  *    n - 32bit input
    269  * Notes: 
    270  */
    271 STATIC buint32_t
    272 bfcmap_phy84756_bit_rev_by_byte_word32(buint32_t n)
    273 {
    274     n = (((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1));
    275     n = (((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2));
    276     n = (((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4));
    277     return n;
    278 }
    279 
    280 /* Structure used to communicate with the event handler */
    281 typedef struct _phy84756_fcmap_event_callback_data_s{
    282     int unit;
    283     soc_port_t port;
    284     int link;
    285 }_phy84756_fcmap_event_callback_data_t;
    286 
    287 STATIC int phy_84756_fcmap_init(int unit, soc_port_t port);
    288 STATIC int phy_84756_fcmap_link_get(int unit, soc_port_t port, int *link);
    289 STATIC int phy_84756_fcmap_linkfault_get(int unit, soc_port_t port, int *fault);
    290 STATIC int phy_84756_fcmap_enable_set(int unit, soc_port_t port, int enable);
    291 STATIC int phy_84756_fcmap_duplex_set(int unit, soc_port_t port, int duplex);
    292 STATIC int phy_84756_fcmap_duplex_get(int unit, soc_port_t port, int *duplex);
    293 STATIC int phy_84756_fcmap_speed_set(int unit, soc_port_t port, int speed);
    294 STATIC int phy_84756_fcmap_speed_get(int unit, soc_port_t port, int *speed);
    295 STATIC int phy_84756_fcmap_an_set(int unit, soc_port_t port, int autoneg);
    296 STATIC int phy_84756_fcmap_an_get(int unit, soc_port_t port,
    297                                 int *autoneg, int *autoneg_done);
    298 STATIC int phy_84756_fcmap_lb_set(int unit, soc_port_t port, int enable);
    299 STATIC int phy_84756_fcmap_lb_get(int unit, soc_port_t port, int *enable);
    300 STATIC int phy_84756_fcmap_ability_advert_set(int unit, soc_port_t port, 
    301                                        soc_port_ability_t *ability);
    302 STATIC int phy_84756_fcmap_ability_advert_get(int unit, soc_port_t port,
    303                                        soc_port_ability_t *ability);
    304 STATIC int phy_84756_fcmap_ability_remote_get(int unit, soc_port_t port,
    305                                        soc_port_ability_t *ability);
    306 STATIC int phy_84756_fcmap_ability_local_get(int unit, soc_port_t port, 
    307                                 soc_port_ability_t *ability);
    308 STATIC int phy_84756_fcmap_firmware_set(int unit, int port, int offset, 
    309                                  uint8 *data, int len);
    310 STATIC int phy_84756_fcmap_control_set(int unit, soc_port_t port,
    311                      soc_phy_control_t type, uint32 value);
    312 STATIC int phy_84756_fcmap_control_get(int unit, soc_port_t port,
    313                      soc_phy_control_t type, uint32 *value);
    314 STATIC int phy_84756_fcmap_linkup(int unit, soc_port_t port);
    315 
    316 STATIC int phy_84756_fcmap_reg_read(int unit, soc_port_t port, uint32 flags,
    317                   uint32 phy_reg_addr, uint32 *phy_data);
    318 
    319 STATIC int phy_84756_fcmap_reg_write(int unit, soc_port_t port, uint32 flags,
    320                    uint32 phy_reg_addr, uint32 phy_data);
    321 STATIC int
    322 phy_84756_fcmap_squelch_enable(int unit, soc_port_t port, int intf, int enable, int force);
    323 STATIC int
    324 _bfcmap_phy84756_system_sgmii_init(phy_ctrl_t *pc, int dev_port);
    325 STATIC int
    326 _bfcmap_phy84756_system_sgmii_duplex_set(phy_ctrl_t *pc, int dev_port, int duplex);
    327 STATIC int
    328 _bfcmap_phy84756_system_sgmii_sync(phy_ctrl_t *pc, int dev_port);
    329 
    330 extern buint8_t bcm84756_fw[];
    331 extern buint32_t bcm84756_fw_length;
    332 extern buint8_t bcm84756_b0_fw[];
    333 extern buint32_t bcm84756_b0_fw_length;
    334 
    335 /*
    336  * Function:     
    337  *    _phy84756_system_xfi_speed_set
    338  * Purpose:    
    339  *    To set system side SGMII speed
    340  * Parameters:
    341  *    phy_id    - PHY's device address
    342  *    speed     - Speed to set
    343  *               100000 = 10Gbps
    344  * Returns:    
    345  */
    346 static int
    347 _phy84756_system_xfi_speed_set(phy_ctrl_t *pc, int dev_port, int speed)
    348 {
    349     if (speed != 10000) {
    350         return SOC_E_CONFIG;
    351     }
    352     /* Disable Clause 37 Autoneg */
    353     SOC_IF_ERROR_RETURN(
    354         BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, 0,
    355                                   BFCMAP_PHY84756_AN_MII_CTRL_AE));
    356     /* Force Speed in PDM */
    357     SOC_IF_ERROR_RETURN(
    358         BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRLr(pc, 
    359                           BFCMAP_PHY84756_PMD_CTRL_SS_10000,
    360                           BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK));
    361     return SOC_E_NONE;
    362 }
    363 
    364 /*
    365  * Function:
    366  *      _phy_84756_fcmap_medium_config_update
    367  * Purpose:
    368  *      Update the PHY with config parameters
    369  * Parameters:
    370  *      unit - StrataSwitch unit #.
    371  *      port - StrataSwitch port #.
    372  *      cfg - Config structure.
    373  * Returns:
    374  *      SOC_E_XXX
    375  */
    376 
    377 STATIC int
    378 _phy_84756_fcmap_medium_config_update(int unit, soc_port_t port,
    379                                 soc_phy_config_t *cfg)
    380 {
    381 
    382     SOC_IF_ERROR_RETURN
    383         (phy_84756_fcmap_speed_set(unit, port, cfg->force_speed));
    384     SOC_IF_ERROR_RETURN
    385         (phy_84756_fcmap_duplex_set(unit, port, cfg->force_duplex));
    386     SOC_IF_ERROR_RETURN
    387         (phy_84756_fcmap_ability_advert_set(unit, port, &cfg->advert_ability));
    388     SOC_IF_ERROR_RETURN
    389         (phy_84756_fcmap_an_set(unit, port, cfg->autoneg_enable));
    390 
    391     return SOC_E_NONE;
    392 }
    393 
    394 STATIC int
    395 _phy_84756_fcmap_firmware_is_downloaded(int unit, soc_port_t port)
    396 {
    397     int rv = 0;
    398     uint16 data16;
    399     phy_ctrl_t *pc;
    400 
    401     pc = EXT_PHY_SW_STATE(unit, port);
    402 
    403     if (soc_property_port_get(unit, port,spn_PHY_FORCE_FIRMWARE_LOAD, TRUE)) {
    404         return 0;
    405     }
    406 
    407     /*
    408      * To determine whether the firmware has been downloaded, it must
    409      * pass the following:
    410      * 1. firmware is in RAM: 1.c848.13==1
    411      * 2. expected checksum:  1.ca1c==600d
    412      * 3. version is non-zero:  1.ca1a!=0
    413      */
    414 
    415     /* 1. Firmware download status */
    416     rv = BFCMAP_RD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, &data16);
    417     if (rv != SOC_E_NONE) {
    418         return 0;
    419     }
    420     if (PHY_EXT_ROM_BOOT(pc)) {
    421         if ((data16 & 0xa000) != 0xa000) {
    422             return 0;
    423         }
    424     } else if ((data16 & 0x6000) != 0x6000) {
    425             return 0;
    426     }
    427     LOG_INFO(BSL_LS_SOC_PHY,
    428              (BSL_META_U(unit,
    429                          "84756 FW download status=%x: u=%d p=%d\n"), data16, unit, port));
    430 
    431     /* 2. Expected checksum */
    432     rv = BFCMAP_RD_PHY84756_LN_DEV1_CHECKSUMr(pc, &data16);
    433     if ((rv != SOC_E_NONE) || (data16 != BFCMAP_PHY84756_FW_CHECKSUM)) {
    434         return 0;
    435     }
    436     LOG_INFO(BSL_LS_SOC_PHY,
    437              (BSL_META_U(unit,
    438                          "84756 FW checksum=%x: u=%d p=%d\n"), data16, unit, port));
    439 
    440     /* 3. non-zero version */
    441     rv = BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A, &data16);
    442     if ((rv != SOC_E_NONE) || (data16 == 0)) {
    443         return 0;
    444     }
    445     LOG_INFO(BSL_LS_SOC_PHY,
    446              (BSL_META_U(unit,
    447                          "84756 FW version=%x: u=%d p=%d\n"), data16, unit, port));
    448 
    449     return 1;
    450 }
    451 
    452 /* Function:
    453  *    phy_84756_fcmap_init
    454  * Purpose:    
    455  *    Initialize 84756 phys
    456  * Parameters:
    457  *    unit - StrataSwitch unit #.
    458  *    port - StrataSwitch port #. 
    459  * Returns:    
    460  *    SOC_E_NONE
    461  */
    462 
    463 /*
    464   *  ALWAYS_DOWNLOAD_FC_UCODE_AT_POWERUP = 1: always download FC uCode at power-up
    465   *  ALWAYS_DOWNLOAD_FC_UCODE_AT_POWERUP = 0: Download FC uCode at power-up only if at least one of the ports in the same mdio bus is FC enabled
    466   */
    467 #define ALWAYS_DOWNLOAD_FC_UCODE_AT_POWERUP 0
    468 
    469 STATIC int
    470 phy_84756_fcmap_init(int unit, soc_port_t port)
    471 {
    472     phy_ctrl_t *pc;
    473     int rv = SOC_E_NONE;
    474     buint16_t data;
    475 
    476     pc     = EXT_PHY_SW_STATE(unit, port);
    477 
    478     if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT ||
    479         PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1   ) {
    480         int mmi_mdio_addr;
    481 
    482         LOG_INFO(BSL_LS_SOC_PHY,
    483                  (BSL_META_U(unit,
    484                              "phy_84756_fcmap_init PASS1: u=%d p=%d\n"),unit, port));
    485 
    486         sal_memset(PHY84756_PHY_INFO(pc), 0, sizeof(phy84756_map_t));
    487 
    488 
    489 
    490         FCMAP_ENABLE(pc) = soc_property_port_get(unit, port, spn_FCMAP_ENABLE, 0);
    491 
    492         MACSEC_ENABLE(pc) = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0);
    493 
    494         /* Save chip rev */
    495         SOC_IF_ERROR_RETURN(
    496             BFCMAP_RD_PHY84756_LN_DEV1_CHIP_REVr(pc, &data));
    497         CHIP_REV_ID(pc) = data;
    498 
    499         if (CHIP_IS_A0(pc)) {
    500             /* this firmware is used by A0 */
    501             FIRMWARE(pc) = bcm84756_fw;
    502             FIRMWARE_LEN(pc) = bcm84756_fw_length;
    503         } else {
    504             /* this firmware is used by B0 and C0 */
    505             FIRMWARE(pc) = bcm84756_b0_fw;
    506             FIRMWARE_LEN(pc) = bcm84756_b0_fw_length;
    507         }
    508 
    509         MACSEC_SUPPORT(pc) = 0;
    510 
    511 #if defined(INCLUDE_FCMAP)
    512         if (!FCMAP_ENABLE(pc)) {
    513             /* Call 40G Init */
    514             PHY84756_CALL_IF_8474X(unit,port,
    515                                    PHY_INIT(PHY84756_40G, unit, port));
    516         }
    517 #else
    518         /* Call 40G Init */
    519         PHY84756_CALL_IF_8474X(unit,port,
    520                                PHY_INIT(PHY84756_40G, unit, port));
    521 #endif
    522 
    523 #if defined(INCLUDE_FCMAP)
    524         if (FCMAP_ENABLE(pc)) {
    525             pc->fcmap_enable = FCMAP_ENABLE(pc);
    526             pc->fcmap_dev_port = 0;
    527             mmi_mdio_addr = pc->phy_id;
    528 
    529             pc->fcmap_uc_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    530             pc->fcmap_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1);
    531 
    532             rv = bfcmap_phy84756_phy_mac_driver_attach(pc, 
    533                                                   pc->fcmap_dev_addr, 
    534                                                   pc->fcmap_dev_port,
    535                                                   blmi_io_mmi1_cl45);
    536             if(rv != SOC_E_NONE) {
    537                 LOG_WARN(BSL_LS_SOC_PHY,
    538                          (BSL_META_U(unit,
    539                                      "phy_84756_fcmap_init: bfcmap_phy_mac_driver_attach "
    540                                      "returned error for u=%d p=%d\n"), unit, port));
    541                 return SOC_E_FAIL;
    542             }
    543         }
    544 #endif /* INCLUDE_FCMAP */
    545 
    546 #if defined(INCLUDE_MACSEC)
    547         MACSEC_SUPPORT(pc) = 1;
    548         if  (MACSEC_ENABLE(pc)) {
    549             pc->macsec_enable = MACSEC_ENABLE(pc);
    550             pc->macsec_dev_port = soc_property_port_get(unit, port, 
    551                                                spn_MACSEC_PORT_INDEX, -1);
    552 
    553             /* Base PHY ID is used to access MACSEC core */
    554             mmi_mdio_addr = soc_property_port_get(unit, port, 
    555                                                 spn_MACSEC_DEV_ADDR, -1);
    556             if (mmi_mdio_addr < 0) {
    557                 LOG_WARN(BSL_LS_SOC_PHY,
    558                          (BSL_META_U(unit,
    559                                      "phy_84756_macsec_init: "
    560                                      "MACSEC_DEV_ADDR property "
    561                                      "not configured for u=%d p=%d\n"), unit, port));
    562                 return SOC_E_CONFIG;
    563             }
    564 
    565             pc->macsec_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1);
    566 
    567             rv = bfcmap_phy84756_phy_mac_driver_attach(pc, 
    568                                                   pc->macsec_dev_addr, 
    569                                                   pc->macsec_dev_port,
    570                                                   blmi_io_mmi1_cl45);
    571 
    572             if(rv != SOC_E_NONE) {
    573                 LOG_WARN(BSL_LS_SOC_PHY,
    574                          (BSL_META_U(unit,
    575                                      "phy_84756_macsec_init: bfcmap_phy_mac_driver_attach "
    576                                      "returned error for u=%d p=%d\n"), unit, port));
    577                 return SOC_E_FAIL;
    578             }
    579         }
    580 #endif /* INCLUDE_MACSEC */
    581 
    582         /* If 1G link detected set speed */
    583         SOC_IF_ERROR_RETURN
    584             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xC820, &data));
    585         if (data & 0x1) {
    586             FIBER_FORCE_SPEED(pc) = 1000;
    587         } else {
    588             FIBER_FORCE_SPEED(pc) = 10000;
    589         }
    590 
    591         /* By default select ethernet chip mode */
    592         SOC_IF_ERROR_RETURN(
    593             BFCMAP_RD_PHY84756_LN_DEV1_CHIP_MODEr(pc, &data));
    594         data &= ~0x3;
    595         SOC_IF_ERROR_RETURN(
    596             BFCMAP_WR_PHY84756_LN_DEV1_CHIP_MODEr(pc, data));
    597 
    598         PHY_EXT_ROM_BOOT(pc) = soc_property_port_get(unit, port,
    599                                                 spn_PHY_EXT_ROM_BOOT, 1);
    600 
    601         SKIP_EDC_FW_DOWNLOAD(pc) = _phy_84756_fcmap_firmware_is_downloaded(unit, port);
    602         
    603         pc->flags &= ~(PHYCTRL_MDIO_BCST | PHYCTRL_MDIO_BCST2);
    604 
    605         if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) {
    606              if (!PHY_EXT_ROM_BOOT(pc) && !SKIP_EDC_FW_DOWNLOAD(pc)) {
    607                 pc->flags |= PHYCTRL_MDIO_BCST;
    608              }
    609 #if defined(INCLUDE_FCMAP)
    610 #if ALWAYS_DOWNLOAD_FC_UCODE_AT_POWERUP 
    611             /* Always download FC uCode in advance */
    612              pc->flags |= PHYCTRL_MDIO_BCST2;
    613 #else
    614             if (FCMAP_ENABLE(pc)) {
    615                 pc->flags |= PHYCTRL_MDIO_BCST2;
    616             }
    617 #endif
    618 #endif             
    619              if (PHY84756_IS_8474X(pc)) {
    620                  /* pc->dev_name already set */
    621              } else
    622              if (CHIP_IS_A0(pc)) {
    623                  pc->dev_name = "BCM84756_A0";
    624              } else {
    625                  if (CHIP_IS_B0(pc)) {
    626                      pc->dev_name = "BCM84756_B0";
    627                  } else {
    628                      pc->dev_name = "BCM84756_C0";
    629                  }
    630              }
    631         }
    632 
    633         /* reset */
    634         SOC_IF_ERROR_RETURN(
    635                 bfcmap_phy84756_reset(pc));
    636 
    637         if ( PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT ) {
    638             /* indicate second pass of init is needed */
    639             PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_PASS2);
    640 
    641             return SOC_E_NONE;
    642         }
    643 
    644     }
    645 
    646     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) ||
    647         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
    648         int line_mode;
    649         int fiber_preferred;
    650 #if defined(INCLUDE_FCMAP)
    651         phy_ctrl_t *int_pc;
    652 #endif /* INCLUDE_FCMAP */
    653 
    654         LOG_INFO(BSL_LS_SOC_PHY,
    655                  (BSL_META_U(unit,
    656                              "phy_84756_fcmap_init PASS2: u=%d p=%d\n"),unit, port));
    657 
    658 #if defined(INCLUDE_FCMAP)
    659         if (!FCMAP_ENABLE(pc)) {
    660             /* Call 40G Init */
    661             PHY84756_CALL_IF_8474X(unit,port,
    662                                    PHY_INIT(PHY84756_40G, unit, port));
    663         }
    664 #else
    665         /* Call 40G Init */
    666         PHY84756_CALL_IF_8474X(unit,port,
    667                                PHY_INIT(PHY84756_40G, unit, port));
    668 #endif
    669 
    670         /* Preferred mode:
    671          * phy_fiber_pref = 1 ; Port is in SFI mode in 10G Default
    672          *                      when speed is changed to 1G, its 1000X
    673          * phy_fiber_pref = 0; Port is in SGMII mode, allows only 1G/100M/10M
    674          */
    675         fiber_preferred =
    676             soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 1);
    677 
    678         /* Initially configure for the preferred medium. */
    679         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
    680         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
    681         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU);
    682         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
    683 
    684         if (fiber_preferred) {
    685             if (FIBER_FORCE_SPEED(pc) == 10000) {
    686                 line_mode = BFCMAP_PHY84756_INTF_SFI;
    687             } else {
    688                 line_mode = BFCMAP_PHY84756_INTF_1000X;
    689             }
    690             pc->copper.enable = FALSE;
    691             pc->fiber.enable = TRUE;
    692             pc->interface = SOC_PORT_IF_XFI;
    693             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
    694         } else {
    695             pc->interface = SOC_PORT_IF_SGMII;
    696             line_mode = BFCMAP_PHY84756_INTF_SGMII;
    697             pc->copper.enable = TRUE;
    698             pc->fiber.enable = FALSE;
    699             PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
    700         }
    701         PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45);
    702 
    703         pc->copper.preferred = !fiber_preferred;
    704         pc->copper.autoneg_enable = TRUE;
    705         pc->copper.autoneg_advert = ADVERT_ALL_COPPER;
    706         pc->copper.force_speed = 1000;
    707         pc->copper.force_duplex = TRUE;
    708         pc->copper.master = SOC_PORT_MS_AUTO;
    709         pc->copper.mdix = SOC_PORT_MDIX_AUTO;
    710 
    711         pc->fiber.preferred = TRUE;
    712         pc->fiber.autoneg_enable = FALSE;
    713         pc->fiber.autoneg_advert = ADVERT_ALL_FIBER;
    714         pc->fiber.force_speed = FIBER_FORCE_SPEED(pc);
    715         pc->fiber.force_duplex = TRUE;
    716         pc->fiber.master = SOC_PORT_MS_NONE;
    717         pc->fiber.mdix = SOC_PORT_MDIX_NORMAL;
    718 
    719 
    720         SOC_IF_ERROR_RETURN(
    721                 bfcmap_phy84756_no_reset_setup(pc,
    722                                                line_mode,
    723                                                PHY_EXT_ROM_BOOT(pc)));
    724 
    725         /* Get Requested LED selectors (defaults are hardware defaults) */
    726         pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0);
    727         pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1);
    728         pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3);
    729         pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6);
    730         pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8);
    731         pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0);
    732 
    733 
    734         if (line_mode != BFCMAP_PHY84756_INTF_SGMII)
    735         {
    736             SOC_IF_ERROR_RETURN
    737                 (_phy_84756_fcmap_medium_config_update(unit, port,
    738                                         PHY_COPPER_MODE(unit, port) ?
    739                                         &pc->copper :
    740                                         &pc->fiber));
    741         }
    742 
    743 #if defined(INCLUDE_FCMAP)
    744         if (FCMAP_ENABLE(pc)) {
    745             if (CHIP_IS_C0(pc)) {
    746                 rv = soc_fcmapphy_init(unit, port, pc, 
    747                             BFCMAP_CORE_BCM84756_C0, bfcmap_io_mmi1_cl45);
    748             }
    749             else {
    750                 rv = soc_fcmapphy_init(unit, port, pc, 
    751                             BFCMAP_CORE_BCM84756, bfcmap_io_mmi1_cl45);
    752             }
    753             if (!SOC_SUCCESS(rv)) {
    754                 LOG_ERROR(BSL_LS_SOC_PHY,
    755                           (BSL_META_U(unit,
    756                                       "soc_fcmapphy_init: FCMAP init for"
    757                                       " u=%d p=%d FAILED "), unit, port));
    758             } else {
    759                 LOG_INFO(BSL_LS_SOC_PHY,
    760                          (BSL_META_U(unit,
    761                                      "soc_fcmapphy_init: FCMAP init for"
    762                                      " u=%d p=%d SUCCESS "), unit, port));
    763             }
    764 
    765             /* Internal serdes speed should be set to 10G in FC Mode */
    766             int_pc = INT_PHY_SW_STATE(unit, port);
    767             if (NULL != int_pc) {
    768                 PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0);
    769                 PHY_SPEED_SET(int_pc->pd, unit, port, 10000);
    770             }
    771         }
    772 #endif
    773 #if defined(INCLUDE_MACSEC)
    774         if (MACSEC_ENABLE(pc)) {
    775             if (CHIP_IS_C0(pc)) {
    776                 rv = soc_macsecphy_init(unit, port, pc, 
    777                         BMACSEC_CORE_BCM84756_C0, bmacsec_io_mmi1_cl45);
    778             } else {
    779                 rv = soc_macsecphy_init(unit, port, pc, 
    780                         BMACSEC_CORE_BCM84756, bmacsec_io_mmi1_cl45);
    781             }
    782             if (!SOC_SUCCESS(rv)) {
    783             LOG_ERROR(BSL_LS_SOC_PHY,
    784                       (BSL_META_U(unit,
    785                                   "soc_macsec_init: MACSEC init for"
    786                                   " u=%d p=%d FAILED "), unit, port));
    787             } else {
    788             LOG_INFO(BSL_LS_SOC_PHY,
    789                      (BSL_META_U(unit,
    790                                  "soc_macsec_init: MACSEC init for"
    791                                  " u=%d p=%d SUCCESS "), unit, port));
    792             }
    793         }
    794 #endif
    795             PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_DEFAULT);
    796     }
    797 
    798     if (soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, 0)) {
    799         if(!PHY84756_SINGLE_PORT_MODE(pc)) {
    800             /* put device in repeat mode. Single port is already in repeat mode */
    801             SOC_IF_ERROR_RETURN
    802                 (WRITE_PHY84756_PMA_PMD_REG(unit, pc, 0xc806, 0x6));
    803             PHY_FLAGS_SET(unit, port, PHY_FLAGS_REPEATER);
    804         }
    805     }    
    806     return SOC_E_NONE;
    807 }
    808 
    809 /*
    810  * Function:
    811  *    phy_84756_fcmap_link_get
    812  * Purpose:
    813  *    Get layer2 connection status.
    814  * Parameters:
    815  *    unit - StrataSwitch unit #.
    816  *    port - StrataSwitch port #. 
    817  *      link - address of memory to store link up/down state.
    818  * Returns:    
    819  *    SOC_E_NONE
    820  */
    821 
    822 STATIC int
    823 phy_84756_fcmap_link_get(int unit, soc_port_t port, int *link)
    824 {
    825     phy_ctrl_t *pc;
    826     int rv = SOC_E_NONE;
    827     bfcmap_phy84756_intf_t bfcmap_mode;
    828     int bfcmap_link;
    829     phy_ctrl_t *int_pc;
    830     buint16_t repeater_mode;
    831 
    832     int_pc = INT_PHY_SW_STATE(unit, port);
    833     pc    = EXT_PHY_SW_STATE(unit, port);
    834     *link = FALSE;      /* Default return */
    835 
    836     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
    837         return SOC_E_NONE;
    838     }
    839 
    840     /* 40G link get */
    841     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
    842         PHY_LINK_GET(PHY84756_40G, unit, port, link));
    843 
    844 #if defined(INCLUDE_FCMAP)
    845     if (pc->fcmap_enable) {
    846         rv = bfcmap_phy84756_link_get(pc, &bfcmap_link);
    847         if (!SOC_SUCCESS(rv)) {
    848             return SOC_E_FAIL;
    849         }
    850         *link = bfcmap_link ? TRUE : FALSE;
    851         return SOC_E_NONE;
    852     }
    853 #endif
    854 
    855     rv = bfcmap_phy84756_line_intf_get(pc, 0, &bfcmap_mode);
    856     if (!SOC_SUCCESS(rv)) {
    857         return SOC_E_FAIL;
    858     }
    859 
    860     if (bfcmap_mode == BFCMAP_PHY84756_INTF_SGMII) {
    861         PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
    862         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
    863     } else {
    864         PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
    865         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
    866     }
    867 
    868     rv = bfcmap_phy84756_link_get(pc, &bfcmap_link);
    869     if (!SOC_SUCCESS(rv)) {
    870         return SOC_E_FAIL;
    871     }
    872 
    873     if (bfcmap_link) {
    874         *link = TRUE;
    875     } else {
    876         *link = FALSE;
    877     }
    878     LOG_VERBOSE(BSL_LS_SOC_PHY,
    879                 (BSL_META_U(unit,
    880                             "phy_84756_fcmap_link_get: u=%d p=%d link=%d\n"),
    881                  unit, port,
    882                  *link));
    883 
    884     SOC_IF_ERROR_RETURN
    885         (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode));
    886 
    887     if ((repeater_mode & 0x6) == 0x6) {
    888         if (NULL != int_pc) {
    889             SOC_IF_ERROR_RETURN(
    890                 PHY_LINK_GET(int_pc->pd, unit, port, link));
    891         }
    892     }
    893     return SOC_E_NONE;
    894 }
    895 
    896 
    897 /*
    898  * Function:
    899  *    phy_84756_fcmap_linkfault_get
    900  * Purpose:
    901  *    Get layer2 connection status.
    902  * Parameters:
    903  *    unit - StrataSwitch unit #.
    904  *    port - StrataSwitch port #. 
    905  *    fault - address of memory to store link fault state.
    906  * Returns:    
    907  *    SOC_E_NONE
    908  */
    909 
    910 STATIC int
    911 phy_84756_fcmap_linkfault_get(int unit, soc_port_t port, int *fault)
    912 {
    913 #if defined(INCLUDE_FCMAP)
    914     phy_ctrl_t *pc;
    915     
    916     pc    = EXT_PHY_SW_STATE(unit, port);
    917 #endif
    918 
    919     *fault = FALSE;      /* Default return */
    920 
    921 #if defined(INCLUDE_FCMAP)
    922     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
    923         return SOC_E_NONE;
    924     }
    925 
    926     if (pc->fcmap_enable) {
    927         int rv = SOC_E_NONE;
    928 
    929         rv = bfcmap_phy84756_linkfault_get(pc, fault);
    930         if (!SOC_SUCCESS(rv)) {
    931             return SOC_E_FAIL;
    932         }
    933     }
    934 #endif
    935 
    936     LOG_VERBOSE(BSL_LS_SOC_PHY,
    937                 (BSL_META_U(unit,
    938                             "phy_84756_fcmap_linkfault_get: u=%d p=%d linkfault=%d\n"),
    939                  unit, port,
    940                  *fault));
    941     return SOC_E_NONE;
    942 }
    943 
    944 
    945 /*
    946  * Function:
    947  *      phy_84756_fcmap_enable_set
    948  * Purpose:
    949  *      Enable or disable the physical interface.
    950  * Parameters:
    951  *      unit - StrataSwitch unit #.
    952  *      port - StrataSwitch port #.
    953  *      enable - Boolean, true = enable PHY, false = disable.
    954  * Returns:
    955  *      SOC_E_XXX
    956  */
    957 
    958 STATIC int
    959 phy_84756_fcmap_enable_set(int unit, soc_port_t port, int enable)
    960 {
    961     phy_ctrl_t *pc;
    962     buint16_t power;
    963     buint16_t data, tx_ctrl;
    964 
    965     pc     = EXT_PHY_SW_STATE(unit, port);
    966 
    967     if (enable) {
    968         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
    969     } else {
    970         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
    971     }
    972 
    973     /* 40G en set  */
    974     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
    975         PHY_ENABLE_SET(PHY84756_40G, unit, port, enable));
    976 
    977     if (enable) {
    978         /* c8e4[4] indicates the TX active state, 0 means TX active, 1 means inactive. 
    979          * This state = TxOnOff pin XOR c800[7] when c8e4[12]=0. 
    980          * The default value of c800[7] is 1.
    981          * If user straps the TxOnOff to 0,
    982          * then the Tx won't be enabled until this function is called.
    983          * Toggle 0xc800[7] to enable the Tx when c8e4[4]=1.
    984          */
    985          SOC_IF_ERROR_RETURN
    986              (BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc8e4, &data));
    987 
    988          SOC_IF_ERROR_RETURN
    989              (BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc800, &tx_ctrl));
    990 
    991          tx_ctrl &= (1 << 7);
    992          if (data & (1 << 4)) {
    993              SOC_IF_ERROR_RETURN
    994                 (BFCMAP_PHY84756_REG_MOD(pc, 00, 0x1, 0xc800,
    995                                          tx_ctrl? 0:(1 << 7), (1 << 7)));
    996          }
    997     }
    998     else {
    999 #if defined(INCLUDE_FCMAP) || defined(INCLUDE_MACSEC)
   1000          /* If macsec or fcmap is enabled, remain TX active to make sure xmac is accessible */
   1001          if (FCMAP_ENABLE(pc) || MACSEC_ENABLE(pc))
   1002              goto xxx;
   1003 #endif
   1004          /* Toggle 0xc800[7] to set TX inactive if it is currently active */
   1005          SOC_IF_ERROR_RETURN
   1006              (BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc8e4, &data));
   1007 
   1008          SOC_IF_ERROR_RETURN
   1009              (BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc800, &tx_ctrl));
   1010 
   1011          tx_ctrl &= (1 << 7);
   1012          if ((data & (1 << 4)) == 0) {
   1013              SOC_IF_ERROR_RETURN
   1014                 (BFCMAP_PHY84756_REG_MOD(pc, 00, 0x1, 0xc800,
   1015                                          tx_ctrl? 0:(1 << 7), (1 << 7)));
   1016          }
   1017     }
   1018 
   1019 xxx:
   1020 #if defined(INCLUDE_FCMAP)
   1021     if (FCMAP_ENABLE(pc)) {
   1022         int p;
   1023         int rv = SOC_E_NONE;
   1024 
   1025         /* Issue a enable request to the FC firmware */
   1026         p = SOC_FCMAP_PORTID(unit, port);
   1027         if (enable) {
   1028             rv = bfcmap_port_link_enable(p);
   1029         } else {
   1030             rv = bfcmap_port_shutdown(p);
   1031         }
   1032         if (rv != BFCMAP_E_NONE) {
   1033             LOG_INFO(BSL_LS_SOC_PHY,
   1034                      (BSL_META_U(unit,
   1035                                  "phy_84756_fcmap_enable_set: Failed u=%d p=%d enable=%d rv=%d\n"),
   1036                       unit, port, enable, rv));
   1037             return SOC_E_FAIL;
   1038         }
   1039         LOG_INFO(BSL_LS_SOC_PHY,
   1040                  (BSL_META_U(unit,
   1041                              "phy_84756_fcmap_enable_set:  Success u=%d p=%d enable=%d rv=%d\n"),
   1042                   unit, port, enable, rv));
   1043         return SOC_E_NONE;
   1044     }
   1045 #endif
   1046     
   1047 
   1048     /* set 1.9.0 to control OPTXENB pin connected to module */
   1049     power = (enable) ? 0 : 0x0001 ;
   1050     SOC_IF_ERROR_RETURN(
   1051     BFCMAP_MOD_PHY84756_LN_DEV1_PMD_XMIT_DISABLEr(pc, power, 0x0001));
   1052 
   1053 
   1054     LOG_INFO(BSL_LS_SOC_PHY,
   1055              (BSL_META_U(unit,
   1056                          "phy_84756_fcmap_enable_set: "
   1057                          "Power %s fiber medium\n"), (enable) ? "up" : "down"));
   1058 
   1059     return SOC_E_NONE;
   1060 }
   1061 
   1062 /*
   1063  * Function:
   1064  *      phy_84756_fcmap_duplex_set
   1065  * Purpose:
   1066  *      Set the current duplex mode
   1067  * Parameters:
   1068  *      unit - StrataSwitch unit #.
   1069  *      port - StrataSwitch port #.
   1070  *      duplex - Boolean, true indicates full duplex, false indicates half.
   1071  * Returns:
   1072  *      SOC_E_NONE
   1073  *      SOC_E_UNAVAIL - Half duplex requested, and not supported.
   1074  * Notes:
   1075  */
   1076 STATIC int
   1077 phy_84756_fcmap_duplex_set(int unit, soc_port_t port, int duplex_in)
   1078 {
   1079     int                          rv = SOC_E_NONE ;
   1080     phy_ctrl_t                   *pc;
   1081     bfcmap_phy84756_duplex_t    duplex;
   1082     buint16_t mii_ctrl;
   1083     bfcmap_phy84756_intf_t line_mode;
   1084 
   1085     pc = EXT_PHY_SW_STATE(unit, port);
   1086 
   1087     /* 40G duplex set  */
   1088     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1089         PHY_DUPLEX_SET(PHY84756_40G, unit, port, duplex_in));
   1090 
   1091 #if defined(INCLUDE_FCMAP)
   1092     if (pc->fcmap_enable) {
   1093         return SOC_E_NONE;
   1094     }
   1095 #endif
   1096 
   1097     if (duplex_in) {
   1098         duplex = BFCMAP_PHY84756_FULL_DUPLEX;
   1099     } else {
   1100         duplex = BFCMAP_PHY84756_HALF_DUPLEX;
   1101     }
   1102 
   1103     SOC_IF_ERROR_RETURN(
   1104         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   1105 
   1106     if ((line_mode == BFCMAP_PHY84756_INTF_1000X ) ||
   1107         (line_mode == BFCMAP_PHY84756_INTF_SFI )) {
   1108 
   1109         if (duplex == BFCMAP_PHY84756_FULL_DUPLEX) {
   1110             rv =  SOC_E_NONE;
   1111             goto exit;
   1112         } else {
   1113             rv =  SOC_E_UNAVAIL;
   1114             goto exit;
   1115         }
   1116     }
   1117     SOC_IF_ERROR_RETURN(
   1118         BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &mii_ctrl));
   1119 
   1120     if (duplex == BFCMAP_PHY84756_FULL_DUPLEX) {
   1121         mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_FD;
   1122     } else {
   1123         mii_ctrl &= ~BFCMAP_PHY84756_AN_MII_CTRL_FD;
   1124     }
   1125     SOC_IF_ERROR_RETURN(
   1126         BFCMAP_WR_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, mii_ctrl));
   1127 
   1128 exit:
   1129     if(SOC_SUCCESS(rv)) {
   1130         pc->copper.force_duplex = duplex_in;
   1131     }
   1132 
   1133 
   1134     LOG_INFO(BSL_LS_SOC_PHY,
   1135              (BSL_META_U(unit,
   1136                          "phy_84756_fcmap_duplex_set: u=%d p=%d d=%d rv=%d\n"),
   1137               unit, port, duplex, rv));
   1138     return rv;
   1139 }
   1140 
   1141 /*
   1142  * Function:
   1143  *      phy_84756_fcmap_duplex_get
   1144  * Purpose:
   1145  *      Get the current operating duplex mode. If autoneg is enabled,
   1146  *      then operating mode is returned, otherwise forced mode is returned.
   1147  * Parameters:
   1148  *      unit - StrataSwitch unit #.
   1149  *      port - StrataSwitch port #.
   1150  *      duplex - (OUT) Boolean, true indicates full duplex, false
   1151  *              indicates half.
   1152  * Returns:
   1153  *      SOC_E_NONE
   1154  * Notes:
   1155  *      The duplex is retrieved for the ACTIVE medium.
   1156  *      No synchronization performed at this level. Autonegotiation is
   1157  *      not manipulated.
   1158  */
   1159 
   1160 STATIC int
   1161 phy_84756_fcmap_duplex_get(int unit, soc_port_t port, int *duplex)
   1162 {
   1163 
   1164     phy_ctrl_t                   *pc;
   1165     buint16_t   status;
   1166     bfcmap_phy84756_intf_t line_mode;
   1167 
   1168     pc = EXT_PHY_SW_STATE(unit, port);
   1169 
   1170     /* 40G duplex get  */
   1171     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1172         PHY_DUPLEX_GET(PHY84756_40G, unit, port, duplex));
   1173 
   1174 #if defined(INCLUDE_FCMAP)
   1175     if (pc->fcmap_enable) {
   1176         *duplex = TRUE;
   1177         return SOC_E_NONE;
   1178     }
   1179 #endif
   1180 
   1181     SOC_IF_ERROR_RETURN(
   1182         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   1183 
   1184     if ((line_mode == BFCMAP_PHY84756_INTF_1000X ) ||
   1185         (line_mode == BFCMAP_PHY84756_INTF_SFI )) {
   1186         *duplex = TRUE;
   1187     } else {
   1188         SOC_IF_ERROR_RETURN(
   1189             BFCMAP_RD_PHY84756_LN_DEV7_AN_BASE1000X_STAT1r(pc, &status));
   1190         if (status & (1U << 2)) {
   1191             *duplex = TRUE;
   1192         } else {
   1193             *duplex = FALSE;
   1194         }
   1195     }
   1196 
   1197     LOG_INFO(BSL_LS_SOC_PHY,
   1198              (BSL_META_U(unit,
   1199                          "phy_84756_fcmap_duplex_get: u=%d p=%d d=%d \n"),
   1200               unit, port, *duplex));
   1201     return SOC_E_NONE;
   1202 }
   1203 
   1204 
   1205 /*
   1206  * Function:
   1207  *      phy_84756_fcmap_speed_set
   1208  * Purpose:
   1209  *      Set PHY speed
   1210  * Parameters:
   1211  *      unit - StrataSwitch unit #.
   1212  *      port - StrataSwitch port #.
   1213  *      speed - link speed in Mbps
   1214  * Returns:
   1215  *      SOC_E_NONE
   1216  */
   1217 STATIC int
   1218 phy_84756_fcmap_speed_set(int unit, soc_port_t port, int speed)
   1219 {
   1220     phy_ctrl_t *pc;
   1221     phy_ctrl_t  *int_pc;
   1222     int            rv; 
   1223 
   1224     pc = EXT_PHY_SW_STATE(unit, port);
   1225     int_pc = INT_PHY_SW_STATE(unit, port);
   1226     rv = SOC_E_NONE;
   1227 
   1228     /* 40G speed set  */
   1229     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1230         PHY_SPEED_SET(PHY84756_40G, unit, port, speed));
   1231 
   1232 #if defined(INCLUDE_FCMAP)
   1233     if (pc->fcmap_enable) {
   1234         if (NULL != int_pc) {
   1235             PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0);
   1236             PHY_SPEED_SET(int_pc->pd, unit, port, 10000);
   1237         }
   1238         return SOC_E_NONE;
   1239     }
   1240 #endif
   1241 
   1242     if (speed > 10000) {
   1243         return SOC_E_UNAVAIL;
   1244     }
   1245 
   1246     if(PHY_FIBER_MODE(unit, port)) {
   1247         if (speed < 1000) {
   1248             return SOC_E_UNAVAIL;
   1249         }
   1250     }
   1251 
   1252     rv = bfcmap_phy84756_speed_set(pc, speed);
   1253     if(SOC_SUCCESS(rv)) {
   1254         if (NULL != int_pc) {
   1255             PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0);
   1256             PHY_SPEED_SET(int_pc->pd, unit, port, speed);
   1257         }
   1258         if(PHY_COPPER_MODE(unit, port)) {
   1259             pc->copper.force_speed = speed;
   1260         } else {
   1261             if(PHY_FIBER_MODE(unit, port)) {
   1262                 pc->fiber.force_speed = speed;
   1263             }
   1264         }
   1265     }
   1266     LOG_INFO(BSL_LS_SOC_PHY,
   1267              (BSL_META_U(unit,
   1268                          "phy_84756_fcmap_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"),
   1269               unit, port, speed, PHY_FIBER_MODE(unit, port), rv));
   1270 
   1271     return rv;
   1272 }
   1273 
   1274 /*
   1275  * Function:
   1276  *      phy_84756_fcmap_speed_get
   1277  * Purpose:
   1278  *      Get the current operating speed for a 84756 device.
   1279  * Parameters:
   1280  *      unit - StrataSwitch unit #.
   1281  *      port - StrataSwitch port #.
   1282  *      speed - (OUT) Speed of the phy
   1283  * Returns:
   1284  *      SOC_E_NONE
   1285  * Notes:
   1286  *      The speed is retrieved for the ACTIVE medium.
   1287  */
   1288 
   1289 STATIC int
   1290 phy_84756_fcmap_speed_get(int unit, soc_port_t port, int *speed)
   1291 {
   1292     int rv = SOC_E_NONE;
   1293     phy_ctrl_t    *pc;
   1294     buint16_t data = 0;
   1295 #if defined(INCLUDE_FCMAP)
   1296     buint16_t fval = 0;
   1297 #endif
   1298     bfcmap_phy84756_intf_t line_mode;
   1299     phy_ctrl_t *int_pc;
   1300     buint16_t repeater_mode;
   1301 
   1302     int_pc = INT_PHY_SW_STATE(unit, port);
   1303 
   1304     if (speed == NULL) {
   1305         return SOC_E_PARAM;
   1306     }
   1307 
   1308     pc = EXT_PHY_SW_STATE(unit, port);
   1309 
   1310     /* 40G speed set  */
   1311     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1312         PHY_SPEED_GET(PHY84756_40G, unit, port, speed));
   1313 
   1314 
   1315 #if defined(INCLUDE_FCMAP)
   1316     if (pc->fcmap_enable) {
   1317         BFCMAP_PHY84756_REG_RD(pc, 0, 0x1e, 0x50, &fval);
   1318         *speed = 0;
   1319         if (fval == 0x1a) { /* Link up event */
   1320             BFCMAP_PHY84756_REG_RD(pc, 0, 0x1e, 0x52, &fval);
   1321             switch (fval) {
   1322             case 8: 
   1323                 *speed = 8000;
   1324                 break;
   1325             case 4: 
   1326                 *speed = 4000;
   1327                 break;
   1328             case 2: 
   1329                 *speed = 2000;
   1330                 break;
   1331             default:
   1332                 *speed = 0;
   1333                 break;
   1334             }
   1335         }
   1336     } else
   1337 #endif
   1338     {
   1339         SOC_IF_ERROR_RETURN(
   1340             bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   1341 
   1342         if (line_mode == BFCMAP_PHY84756_INTF_SFI) {
   1343             *speed = 10000;
   1344             return SOC_E_NONE;
   1345         }
   1346         if (line_mode == BFCMAP_PHY84756_INTF_1000X) {
   1347             *speed = 1000;
   1348             return SOC_E_NONE;
   1349         }
   1350         SOC_IF_ERROR_RETURN(
   1351             BFCMAP_RD_PHY84756_LN_DEV1_SPEED_LINK_DETECT_STATr(pc, &data));
   1352         switch(data & BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_MASK) {
   1353         case BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_10M:
   1354             *speed = 10;
   1355             break;
   1356         case BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_100M:
   1357             *speed = 100;
   1358             break;
   1359         case BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_1G:
   1360             *speed = 1000;
   1361             break;
   1362         case BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_10G:
   1363             *speed = 10000;
   1364             break;
   1365         default :
   1366             *speed = 0;
   1367             break;
   1368         }
   1369     }
   1370 
   1371     if(!SOC_SUCCESS(rv)) {
   1372         LOG_WARN(BSL_LS_SOC_PHY,
   1373                  (BSL_META_U(unit,
   1374                              "phy_84756_fcmap_speed_get: u=%d p=%d invalid speed\n"),
   1375                   unit, port));
   1376     } else {
   1377         LOG_INFO(BSL_LS_SOC_PHY,
   1378                  (BSL_META_U(unit,
   1379                              "phy_84756_fcmap_speed_get: u=%d p=%d speed=%d"),
   1380                   unit, port, *speed));
   1381     }
   1382 
   1383     SOC_IF_ERROR_RETURN
   1384         (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode));
   1385 
   1386     if ((repeater_mode & 0x6) == 0x6) {
   1387         if (NULL != int_pc) {
   1388             SOC_IF_ERROR_RETURN
   1389                 (PHY_SPEED_GET(int_pc->pd, unit, port, speed));
   1390         }	
   1391     }
   1392     return rv;
   1393 }
   1394 
   1395 /*
   1396  * Function:
   1397  *      phy_84756_fcmap_an_set
   1398  * Purpose:
   1399  *      Enable or disable auto-negotiation on the specified port.
   1400  * Parameters:
   1401  *      unit - StrataSwitch unit #.
   1402  *      port - StrataSwitch port #.
   1403  *      autoneg - Boolean, if true, auto-negotiation is enabled
   1404  *              (and/or restarted). If false, autonegotiation is disabled.
   1405  * Returns:
   1406  *      SOC_E_XXX
   1407  * Notes:
   1408  *      The autoneg mode is set only for the ACTIVE medium.
   1409  */
   1410 
   1411 STATIC int
   1412 phy_84756_fcmap_an_set(int unit, soc_port_t port, int autoneg)
   1413 {
   1414     int                 rv;
   1415     phy_ctrl_t   *pc;
   1416     buint16_t data = 0;
   1417     bfcmap_phy84756_intf_t line_mode;
   1418     phy_ctrl_t *int_pc; 
   1419     buint16_t repeater_mode; 
   1420 
   1421     int_pc = INT_PHY_SW_STATE(unit, port);
   1422     pc = EXT_PHY_SW_STATE(unit, port);
   1423     rv = SOC_E_NONE;
   1424 
   1425     /* 40G an set */
   1426     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1427         PHY_AUTO_NEGOTIATE_SET(PHY84756_40G, unit, port, autoneg));
   1428 
   1429 #if defined(INCLUDE_FCMAP)
   1430     if (pc->fcmap_enable) {
   1431         return SOC_E_NONE;
   1432     }
   1433 #endif
   1434 
   1435     SOC_IF_ERROR_RETURN(
   1436         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   1437 
   1438     if (line_mode == BFCMAP_PHY84756_INTF_SFI ) {
   1439         /* force speed  ie an=f */
   1440         autoneg = 0 ;
   1441     }
   1442 
   1443     /* 
   1444      *  Autoneg
   1445      *        enabled       disabled    
   1446      *      1.0000=2040    1.0000=0040
   1447      *      7.8309=0010    7.8309=0030
   1448      *      7.FFE0=1100    7.FFE0=0100
   1449      */   
   1450 
   1451     if (line_mode != BFCMAP_PHY84756_INTF_SFI ) {
   1452         SOC_IF_ERROR_RETURN(
   1453             BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, autoneg ? 0x2040 : 0x0040, 0x2040));
   1454     }
   1455 
   1456     SOC_IF_ERROR_RETURN(
   1457         BFCMAP_MOD_PHY84756_LN_DEV7_AN_MSIC2r(pc, autoneg ? 0x10 : 0x30, 0x30));
   1458 
   1459     SOC_IF_ERROR_RETURN(
   1460         BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &data));
   1461     if (autoneg) {
   1462         data |= (BFCMAP_PHY84756_AN_MII_CTRL_AE | 
   1463                  BFCMAP_PHY84756_AN_MII_CTRL_FD | 
   1464                  BFCMAP_PHY84756_AN_MII_CTRL_RAN);
   1465     } else {
   1466         data &= ~(BFCMAP_PHY84756_AN_MII_CTRL_AE |
   1467                   BFCMAP_PHY84756_AN_MII_CTRL_RAN);
   1468         data |=  BFCMAP_PHY84756_AN_MII_CTRL_FD;
   1469     }
   1470     SOC_IF_ERROR_RETURN(
   1471         BFCMAP_WR_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, data));
   1472 
   1473     if(SOC_SUCCESS(rv)) {
   1474         if(PHY_COPPER_MODE(unit, port)) {
   1475             pc->copper.autoneg_enable = autoneg ? TRUE : FALSE;
   1476         } else {
   1477             if(PHY_FIBER_MODE(unit, port)) {
   1478                 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE;
   1479             }
   1480         }
   1481     }
   1482 
   1483     LOG_INFO(BSL_LS_SOC_PHY,
   1484              (BSL_META_U(unit,
   1485                          "phy_84756_fcmap_an_set: u=%d p=%d autoneg=%d rv=%d\n"),
   1486               unit, port, autoneg, rv));
   1487 
   1488     SOC_IF_ERROR_RETURN(BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode));
   1489 
   1490     if(NULL != int_pc) {
   1491         /* if in passthru mode, enable autoneg on internal serdes */ 
   1492         if((repeater_mode & 0x6) == 0x6) { 
   1493             SOC_IF_ERROR_RETURN( 
   1494                 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, autoneg)); 
   1495         } else { 
   1496             SOC_IF_ERROR_RETURN( 
   1497                 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, FALSE)); 
   1498         } 
   1499     }
   1500 
   1501     if((autoneg == 0) && !PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1502         SOC_IF_ERROR_RETURN(
   1503             BFCMAP_MOD_PHY84756_LN_DEV1_PMD_XMIT_DISABLEr(pc, 1, 0x0001));
   1504         sal_usleep(50000);
   1505         SOC_IF_ERROR_RETURN(
   1506             BFCMAP_MOD_PHY84756_LN_DEV1_PMD_XMIT_DISABLEr(pc, 0, 0x0001));
   1507     }
   1508 
   1509     return rv;
   1510 }
   1511 
   1512 /*
   1513  * Function:
   1514  *      phy_84756_fcmap_an_get
   1515  * Purpose:
   1516  *      Get the current auto-negotiation status (enabled/busy).
   1517  * Parameters:
   1518  *      unit - StrataSwitch unit #.
   1519  *      port - StrataSwitch port #.
   1520  *      autoneg - (OUT) if true, auto-negotiation is enabled.
   1521  *      autoneg_done - (OUT) if true, auto-negotiation is complete. This
   1522  *              value is undefined if autoneg == FALSE.
   1523  * Returns:
   1524  *      SOC_E_XXX
   1525  * Notes:
   1526  *      The autoneg mode is retrieved for the ACTIVE medium.
   1527  */
   1528 
   1529 STATIC int
   1530 phy_84756_fcmap_an_get(int unit, soc_port_t port,
   1531                      int *autoneg, int *autoneg_done)
   1532 {
   1533     int           rv;
   1534     phy_ctrl_t   *pc;
   1535     buint16_t an_mii_ctrl = 0;
   1536     bfcmap_phy84756_intf_t line_mode;
   1537 
   1538     pc = EXT_PHY_SW_STATE(unit, port);
   1539 
   1540     rv            = SOC_E_NONE;
   1541     *autoneg      = FALSE;
   1542     *autoneg_done = FALSE;
   1543 
   1544     /* 40G an get */
   1545     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1546         PHY_AUTO_NEGOTIATE_GET(PHY84756_40G, unit, port,autoneg,autoneg_done));
   1547 
   1548 #if defined(INCLUDE_FCMAP)
   1549     if (pc->fcmap_enable) {
   1550         int bfcmap_link;
   1551         *autoneg = TRUE;  /* Always in Autoneg */
   1552         rv = bfcmap_phy84756_link_get(pc, &bfcmap_link);
   1553         if (!SOC_SUCCESS(rv)) {
   1554             return SOC_E_FAIL;
   1555         }
   1556         *autoneg_done = bfcmap_link ? TRUE : FALSE;
   1557         return SOC_E_NONE;
   1558     }
   1559 #endif
   1560     SOC_IF_ERROR_RETURN(
   1561         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   1562 
   1563     if (line_mode == BFCMAP_PHY84756_INTF_SFI ) {
   1564         *autoneg      = FALSE;
   1565         *autoneg_done = FALSE;
   1566     } else {
   1567         SOC_IF_ERROR_RETURN(
   1568             BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &an_mii_ctrl));
   1569         *autoneg = (an_mii_ctrl & BFCMAP_PHY84756_AN_MII_CTRL_AE) ? 1 : 0;
   1570         *autoneg_done = 
   1571             (pc->mii_stat & BFCMAP_PHY84756_AN_MII_STAT_AN_DONE) ? 1 : 0;
   1572     }
   1573 
   1574     return rv;
   1575 }
   1576 
   1577 /*
   1578  * Function:
   1579  *      phy_84756_fcmap_lb_set
   1580  * Purpose:
   1581  *      Set the local PHY loopback mode.
   1582  * Parameters:
   1583  *      unit - StrataSwitch unit #.
   1584  *      port - StrataSwitch port #.
   1585  *      loopback - Boolean: true = enable loopback, false = disable.
   1586  * Returns:
   1587  *      SOC_E_XXX
   1588  * Notes:
   1589  *      The loopback mode is set only for the ACTIVE medium.
   1590  *      No synchronization performed at this level.
   1591  */
   1592 
   1593 STATIC int
   1594 phy_84756_fcmap_lb_set(int unit, soc_port_t port, int enable)
   1595 {
   1596     int           rv;
   1597     phy_ctrl_t    *pc;
   1598     buint16_t data = 0;
   1599     bfcmap_phy84756_intf_t line_mode;
   1600     int intf_tx;
   1601     int intf_rx;
   1602 
   1603 
   1604     pc = EXT_PHY_SW_STATE(unit, port);
   1605     rv = SOC_E_NONE;
   1606 
   1607     /* 40G lb set */
   1608     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1609         PHY_LOOPBACK_SET(PHY84756_40G, unit, port, enable));
   1610 
   1611 
   1612     intf_tx = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   1613         PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
   1614 
   1615     intf_rx = ( intf_tx ==  PHY_DIAG_INTF_LINE ) ?
   1616         PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
   1617 
   1618     /* TX Enable(Disable) Squelch(FORCE) when we  Enable(Disable) loopback */
   1619     SOC_IF_ERROR_RETURN
   1620         (phy_84756_fcmap_squelch_enable(unit, port,
   1621         intf_tx, enable ? TRUE : FALSE,  enable ? TRUE : FALSE ));
   1622 
   1623     /* RX Disable(Enable) Squelch when we  Enable(Disable) loopback */
   1624     SOC_IF_ERROR_RETURN
   1625         (phy_84756_fcmap_squelch_enable(unit, port,
   1626         intf_rx, enable ? FALSE : TRUE, FALSE));
   1627 
   1628     SOC_IF_ERROR_RETURN(
   1629         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   1630 
   1631     if (line_mode == BFCMAP_PHY84756_INTF_SFI) {
   1632         SOC_IF_ERROR_RETURN(
   1633             BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRLr(pc, &data));
   1634         data &= ~(1);
   1635         data |= (enable) ? 1 : 0x0000;
   1636         SOC_IF_ERROR_RETURN(
   1637             BFCMAP_WR_PHY84756_LN_DEV1_PMD_CTRLr(pc, data));
   1638     } else {
   1639         SOC_IF_ERROR_RETURN(
   1640             BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &data));
   1641         data &= ~BFCMAP_PHY84756_AN_MII_CTRL_LE;
   1642         data |= (enable) ? BFCMAP_PHY84756_AN_MII_CTRL_LE : 0;
   1643         SOC_IF_ERROR_RETURN(
   1644             BFCMAP_WR_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, data));
   1645     }
   1646     if (rv == SOC_E_NONE) {
   1647         /* wait for link up when loopback is enabled */
   1648         
   1649         if (enable) {
   1650             sal_usleep(2000000);
   1651         }
   1652     }
   1653     LOG_INFO(BSL_LS_SOC_PHY,
   1654              (BSL_META_U(unit,
   1655                          "phy_84756_fcmap_lb_set: u=%d p=%d en=%d rv=%d\n"), 
   1656               unit, port, enable, rv));
   1657 
   1658     return rv; 
   1659 }
   1660 
   1661 /*
   1662  * Function:
   1663  *      phy_84756_fcmap_lb_get
   1664  * Purpose:
   1665  *      Get the local PHY loopback mode.
   1666  * Parameters:
   1667  *      unit - StrataSwitch unit #.
   1668  *      port - StrataSwitch port #.
   1669  *      loopback - (OUT) Boolean: true = enable loopback, false = disable.
   1670  * Returns:
   1671  *      SOC_E_XXX
   1672  * Notes:
   1673  *      The loopback mode is retrieved for the ACTIVE medium.
   1674  */
   1675 
   1676 STATIC int
   1677 phy_84756_fcmap_lb_get(int unit, soc_port_t port, int *enable)
   1678 {
   1679     int                  rv;
   1680     phy_ctrl_t    *pc;
   1681     buint16_t data = 0;
   1682     bfcmap_phy84756_intf_t line_mode;
   1683 
   1684     pc = EXT_PHY_SW_STATE(unit, port);
   1685     rv = SOC_E_NONE;
   1686 
   1687     /* 40G lb get */
   1688     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1689         PHY_LOOPBACK_GET(PHY84756_40G, unit, port, enable));
   1690 
   1691 
   1692     SOC_IF_ERROR_RETURN(
   1693         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   1694 
   1695     if (line_mode == BFCMAP_PHY84756_INTF_SFI) {
   1696         SOC_IF_ERROR_RETURN(
   1697             BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRLr(pc, &data));
   1698     /* ctrl != 0xffff check is to handle removable PHY daughter cards */
   1699         *enable = ((data != 0xffff) && (data & 1)) ? 1 : 0;
   1700     } else {
   1701         SOC_IF_ERROR_RETURN(
   1702             BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &data));
   1703     /* ctrl != 0xffff check is to handle removable PHY daughter cards */
   1704         *enable = ((data != 0xffff) && 
   1705                    (data & BFCMAP_PHY84756_AN_MII_CTRL_LE)) ? 1 : 0;
   1706     }
   1707 
   1708     return rv; 
   1709 }
   1710 
   1711 
   1712 /*
   1713  * Function:
   1714  *      phy_84756_fcmap_ability_advert_set
   1715  * Purpose:
   1716  *      Set the current advertisement for auto-negotiation.
   1717  * Parameters:
   1718  *      unit - StrataSwitch unit #.
   1719  *      port - StrataSwitch port #.
   1720  *      mode - Port mode mask indicating supported options/speeds.
   1721  * Returns:
   1722  *      SOC_E_XXX
   1723  * Notes:
   1724  *      The advertisement is set only for the ACTIVE medium.
   1725  *      No synchronization performed at this level.
   1726  */
   1727 STATIC int
   1728 phy_84756_fcmap_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability)
   1729 {
   1730     int        rv;
   1731     phy_ctrl_t *pc;
   1732     bfcmap_phy84756_port_ability_t local_ability;
   1733     phy_ctrl_t *int_pc;
   1734     buint16_t repeater_mode;
   1735 
   1736     int_pc = INT_PHY_SW_STATE(unit, port);
   1737     pc = EXT_PHY_SW_STATE(unit, port);
   1738 
   1739 
   1740     if (NULL == ability) {
   1741         return (SOC_E_PARAM);
   1742     }
   1743 
   1744     /* 40G advert Set */
   1745     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1746         PHY_ABILITY_ADVERT_SET(PHY84756_40G, unit, port, ability));
   1747 
   1748 #if defined(INCLUDE_FCMAP)
   1749     if (pc->fcmap_enable) {
   1750         return SOC_E_NONE;
   1751     }
   1752 #endif
   1753 
   1754     if (PHY_COPPER_MODE(unit, port)) {
   1755         pc->copper.advert_ability = *ability;
   1756     } else {
   1757         pc->fiber.advert_ability = *ability;
   1758     }
   1759 
   1760     local_ability = 0;
   1761 
   1762     if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) {
   1763         local_ability |= BFCMAP_PHY84756_PA_1000MB_FD;
   1764     }
   1765     if(ability->speed_full_duplex & SOC_PA_SPEED_10GB) {
   1766         local_ability |= BFCMAP_PHY84756_PA_10000MB_FD;
   1767     }
   1768 
   1769     if(ability->pause & SOC_PA_PAUSE_TX) {
   1770         local_ability |= BFCMAP_PHY84756_PA_PAUSE_TX;
   1771     }
   1772     if(ability->pause & SOC_PA_PAUSE_RX) {
   1773         local_ability |= BFCMAP_PHY84756_PA_PAUSE_RX;
   1774     }
   1775     if(ability->pause & SOC_PA_PAUSE_ASYMM) {
   1776         local_ability |= BFCMAP_PHY84756_PA_PAUSE_ASYMM;
   1777     }
   1778 
   1779     if(ability->loopback & SOC_PA_LB_NONE) {
   1780         local_ability |= BFCMAP_PHY84756_PA_LB_NONE;
   1781     }
   1782     if(ability->loopback & SOC_PA_LB_PHY) {
   1783         local_ability |= BFCMAP_PHY84756_PA_LB_PHY;
   1784     }
   1785     if(ability->flags & SOC_PA_AUTONEG) {
   1786         local_ability |= BFCMAP_PHY84756_PA_AN;
   1787     }
   1788 
   1789     rv = bfcmap_phy84756_ability_advert_set(pc, local_ability);
   1790 
   1791     SOC_IF_ERROR_RETURN
   1792         (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode));
   1793 
   1794     if ((repeater_mode & 0x6) == 0x6) {
   1795         if (NULL != int_pc) {
   1796             SOC_IF_ERROR_RETURN(
   1797                 PHY_ABILITY_ADVERT_SET(int_pc->pd, unit, port, ability));
   1798         }
   1799     }
   1800 
   1801     return rv;
   1802 }
   1803 
   1804 /*
   1805  * Function:
   1806  *      phy_84756_fcmap_ability_advert_get
   1807  * Purpose:
   1808  *      Get the current advertisement for auto-negotiation.
   1809  * Parameters:
   1810  *      unit - StrataSwitch unit #.
   1811  *      port - StrataSwitch port #.
   1812  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1813  * Returns:
   1814  *      SOC_E_XXX
   1815  * Notes:
   1816  *      The advertisement is retrieved for the ACTIVE medium.
   1817  *      No synchronization performed at this level.
   1818  */
   1819 STATIC int
   1820 phy_84756_fcmap_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   1821 {
   1822     phy_ctrl_t      *pc;
   1823     int        rv;
   1824     bfcmap_phy84756_port_ability_t local_ability;
   1825     phy_ctrl_t *int_pc; 
   1826     buint16_t repeater_mode;
   1827  
   1828     int_pc = INT_PHY_SW_STATE(unit, port);
   1829 
   1830 
   1831     if (NULL == ability) {
   1832         return (SOC_E_PARAM);
   1833     }
   1834 
   1835     /* 40G advert Get */
   1836     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1837         PHY_ABILITY_ADVERT_GET(PHY84756_40G, unit, port, ability));
   1838 
   1839 
   1840     pc = EXT_PHY_SW_STATE(unit, port);
   1841 #if defined(INCLUDE_FCMAP)
   1842     if (pc->fcmap_enable) {
   1843         ability->pause |= SOC_PA_PAUSE_TX;
   1844         ability->pause |= SOC_PA_PAUSE_RX;
   1845         return SOC_E_NONE;
   1846     }
   1847 #endif
   1848 
   1849     local_ability = 0;
   1850 
   1851     rv = bfcmap_phy84756_ability_advert_get(pc, &local_ability);
   1852     if (rv != SOC_E_NONE) {
   1853         return SOC_E_FAIL;
   1854     }
   1855 
   1856     if(local_ability & BFCMAP_PHY84756_PA_1000MB_FD) {
   1857         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1858     }
   1859     if(local_ability & BFCMAP_PHY84756_PA_10000MB_FD) {
   1860         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1861     }
   1862 
   1863     if(local_ability & BFCMAP_PHY84756_PA_PAUSE_TX) {
   1864         ability->pause |= SOC_PA_PAUSE_TX;
   1865     }
   1866     if(local_ability & BFCMAP_PHY84756_PA_PAUSE_RX) {
   1867         ability->pause |= SOC_PA_PAUSE_RX;
   1868     }
   1869     if(local_ability & BFCMAP_PHY84756_PA_PAUSE_ASYMM) {
   1870         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1871     }
   1872 
   1873     if(local_ability & BFCMAP_PHY84756_PA_LB_NONE) {
   1874         ability->loopback |= SOC_PA_LB_NONE;
   1875     }
   1876     if(local_ability & BFCMAP_PHY84756_PA_LB_PHY) {
   1877         ability->loopback |= SOC_PA_LB_PHY;
   1878     }
   1879     if(local_ability & BFCMAP_PHY84756_PA_AN) {
   1880         ability->flags = SOC_PA_AUTONEG;
   1881     }
   1882 
   1883     SOC_IF_ERROR_RETURN
   1884         (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode));
   1885 
   1886     if ((repeater_mode & 0x6) == 0x6) { 
   1887         if (NULL != int_pc) { 
   1888             SOC_IF_ERROR_RETURN( 
   1889                 PHY_ABILITY_ADVERT_GET(int_pc->pd, unit, port, ability)); 
   1890         } 
   1891     } 
   1892 
   1893     return SOC_E_NONE;
   1894 }
   1895 
   1896 /*
   1897  * Function:
   1898  *      phy_84756_fcmap_ability_remote_get
   1899  * Purpose:
   1900  *      Get the current remote advertisement for auto-negotiation.
   1901  * Parameters:
   1902  *      unit - StrataSwitch unit #.
   1903  *      port - StrataSwitch port #.
   1904  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1905  * Returns:
   1906  *      SOC_E_XXX
   1907  * Notes:
   1908  *      The advertisement is retrieved for the ACTIVE medium.
   1909  *      No synchronization performed at this level.
   1910  */
   1911 STATIC int
   1912 phy_84756_fcmap_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   1913 {
   1914     phy_ctrl_t      *pc;
   1915     int        rv;
   1916     bfcmap_phy84756_port_ability_t remote_ability;
   1917     phy_ctrl_t *int_pc; 
   1918     buint16_t repeater_mode;
   1919  
   1920     int_pc = INT_PHY_SW_STATE(unit, port); 
   1921 
   1922     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1923         return SOC_E_NONE;
   1924     }
   1925 
   1926     if (NULL == ability) {
   1927         return (SOC_E_PARAM);
   1928     }
   1929 
   1930     /* 40G ability Get */
   1931     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   1932         PHY_ABILITY_REMOTE_GET(PHY84756_40G, unit, port, ability));
   1933 
   1934     pc = EXT_PHY_SW_STATE(unit, port);
   1935 #if defined(INCLUDE_FCMAP)
   1936     if (pc->fcmap_enable) {
   1937         ability->pause |= SOC_PA_PAUSE_TX;
   1938         ability->pause |= SOC_PA_PAUSE_RX;
   1939         return SOC_E_NONE;
   1940     }
   1941 #endif
   1942 
   1943     remote_ability = 0;
   1944 
   1945     rv = bfcmap_phy84756_remote_ability_advert_get(pc,
   1946                                                    &remote_ability);
   1947     if (rv != SOC_E_NONE) {
   1948         return SOC_E_FAIL;
   1949     }
   1950 
   1951     if(remote_ability & BFCMAP_PHY84756_PA_1000MB_FD) {
   1952         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1953     }
   1954     if(remote_ability & BFCMAP_PHY84756_PA_10000MB_FD) {
   1955         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1956     }
   1957 
   1958     if(remote_ability & BFCMAP_PHY84756_PA_PAUSE_TX) {
   1959         ability->pause |= SOC_PA_PAUSE_TX;
   1960     }
   1961     if(remote_ability & BFCMAP_PHY84756_PA_PAUSE_RX) {
   1962         ability->pause |= SOC_PA_PAUSE_RX;
   1963     }
   1964     if(remote_ability & BFCMAP_PHY84756_PA_PAUSE_ASYMM) {
   1965         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1966     }
   1967 
   1968     if(remote_ability & BFCMAP_PHY84756_PA_LB_NONE) {
   1969         ability->loopback |= SOC_PA_LB_NONE;
   1970     }
   1971     if(remote_ability & BFCMAP_PHY84756_PA_LB_PHY) {
   1972         ability->loopback |= SOC_PA_LB_PHY;
   1973     }
   1974     if(remote_ability & BFCMAP_PHY84756_PA_AN) {
   1975         ability->flags = SOC_PA_AUTONEG;
   1976     }
   1977 
   1978     SOC_IF_ERROR_RETURN
   1979         (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode));
   1980 
   1981     if ((repeater_mode & 0x6) == 0x6) {
   1982         if (NULL != int_pc) {
   1983             SOC_IF_ERROR_RETURN(
   1984 	        PHY_ABILITY_REMOTE_GET(int_pc->pd, unit, port, ability));
   1985 	}	
   1986     }
   1987 
   1988     return SOC_E_NONE;
   1989 }
   1990 
   1991 
   1992 
   1993 /*
   1994  * Function:
   1995  *      phy_84756_fcmap_ability_local_get
   1996  * Purpose:
   1997  *      Get local abilities 
   1998  * Parameters:
   1999  *      unit - StrataSwitch unit #.
   2000  *      port - StrataSwitch port #.
   2001  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   2002  * Returns:
   2003  *      SOC_E_NONE
   2004  * Notes:
   2005  *      The ability is retrieved only for the ACTIVE medium.
   2006  */
   2007 
   2008 STATIC int
   2009 phy_84756_fcmap_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   2010 {
   2011     int         rv = SOC_E_NONE;
   2012     phy_ctrl_t *pc;
   2013     bfcmap_phy84756_port_ability_t local_ability = 0;
   2014     phy_ctrl_t *int_pc;
   2015     buint16_t repeater_mode;
   2016 
   2017     int_pc = INT_PHY_SW_STATE(unit, port);
   2018 
   2019     if (NULL == ability) {
   2020         return SOC_E_PARAM;
   2021     }
   2022 
   2023     /* 40G ability Get */
   2024     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   2025         PHY_ABILITY_LOCAL_GET(PHY84756_40G, unit, port, ability));
   2026 
   2027     pc = EXT_PHY_SW_STATE(unit, port);
   2028 #if defined(INCLUDE_FCMAP)
   2029     if (pc->fcmap_enable) {
   2030         ability->pause |= SOC_PA_PAUSE_TX;
   2031         ability->pause |= SOC_PA_PAUSE_RX;
   2032         return SOC_E_NONE;
   2033     }
   2034 #endif
   2035 
   2036     rv = bfcmap_phy84756_ability_local_get(pc, &local_ability);
   2037     if (rv != SOC_E_NONE) {
   2038         return SOC_E_FAIL;
   2039     }
   2040 
   2041     if(local_ability & BFCMAP_PHY84756_PA_1000MB_FD) {
   2042         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   2043     }
   2044     if(local_ability & BFCMAP_PHY84756_PA_10000MB_FD) {
   2045         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   2046     }
   2047 
   2048     if(local_ability & BFCMAP_PHY84756_PA_PAUSE_TX) {
   2049         ability->pause |= SOC_PA_PAUSE_TX;
   2050     }
   2051     if(local_ability & BFCMAP_PHY84756_PA_PAUSE_RX) {
   2052         ability->pause |= SOC_PA_PAUSE_RX;
   2053     }
   2054     if(local_ability & BFCMAP_PHY84756_PA_PAUSE_ASYMM) {
   2055         ability->pause |= SOC_PA_PAUSE_ASYMM;
   2056     }
   2057     if(local_ability & BFCMAP_PHY84756_PA_LB_NONE) {
   2058         ability->loopback |= SOC_PA_LB_NONE;
   2059     }
   2060     if(local_ability & BFCMAP_PHY84756_PA_LB_PHY) {
   2061         ability->loopback |= SOC_PA_LB_PHY;
   2062     }
   2063     if(local_ability & BFCMAP_PHY84756_PA_AN) {
   2064         ability->flags = SOC_PA_AUTONEG;
   2065     }
   2066 
   2067     SOC_IF_ERROR_RETURN
   2068         (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode));
   2069 
   2070     if ((repeater_mode & 0x6) == 0x6) {
   2071         if (NULL != int_pc) {
   2072             SOC_IF_ERROR_RETURN(
   2073                 PHY_ABILITY_LOCAL_GET(int_pc->pd, unit, port, ability));
   2074         }
   2075     }
   2076 
   2077     return SOC_E_NONE;
   2078 }
   2079 
   2080 #if defined(INCLUDE_FCMAP)
   2081 extern int 
   2082 bfcmap84756_a0_firmware_download(bfcmap_dev_addr_t dev_addr, int broadcast, int enable);
   2083 #endif
   2084 
   2085 STATIC int
   2086 _phy84756_init_ucode_bcst(int unit, int port, uint32 cmd)
   2087 {
   2088     uint16 data16;
   2089     uint16 mask16;
   2090     int j, bcst_edc_fw;
   2091     uint16 phy_id;
   2092     int i;
   2093     uint16 chip_mode;
   2094     int num_lanes;
   2095     uint16 num_words;
   2096     uint8 *fw_ptr;
   2097     int fw_length;
   2098     phy_ctrl_t *pc;
   2099 #if defined(INCLUDE_FCMAP)
   2100     static int     fc_extra_delay = 0;
   2101     int   bcst_fc_fw;
   2102 #endif    
   2103     pc = EXT_PHY_SW_STATE(unit, port);
   2104     num_lanes = PHY84756_SINGLE_PORT_MODE(pc) ? 4 : 1;
   2105 
   2106     bcst_edc_fw = pc->flags & PHYCTRL_MDIO_BCST;
   2107 #if defined(INCLUDE_FCMAP)
   2108     bcst_fc_fw = pc->flags & PHYCTRL_MDIO_BCST2;
   2109 #endif
   2110 
   2111 #ifdef BCM_WARM_BOOT_SUPPORT
   2112     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
   2113         return SOC_E_NONE;
   2114     }
   2115 #endif
   2116 
   2117     if (cmd == PHYCTRL_UCODE_BCST_SETUP) {
   2118         SOC_IF_ERROR_RETURN(
   2119             BFCMAP_RD_PHY84756_LN_DEV1_CHIP_MODEr(pc, &chip_mode));
   2120 
   2121         LOG_INFO(BSL_LS_SOC_PHY,
   2122                  (BSL_META_U(unit,
   2123                              "PHY84756 BCST start: u=%d p=%d\n"), unit, port));
   2124 
   2125         /* check the current chip mode, switch to quad if in single port mode */
   2126         if ((chip_mode & PHY84756_PMAD_CHIP_MODE_MASK) == PHY84756_PMAD_MODE_40G) {
   2127             LOG_INFO(BSL_LS_SOC_PHY,
   2128                      (BSL_META_U(unit,
   2129                                  "PHY84741 BCST mode switch: u=%d p=%d\n"), unit, port));
   2130             SOC_IF_ERROR_RETURN(
   2131                 _phy_84741_single_to_quad_mode(unit,port,NULL));
   2132         }       
   2133 
   2134         /* program the bcst register. do 4 lanes for single port configuration */
   2135         phy_id = pc->phy_id;
   2136         /* configure all four ports  */
   2137         for (i = 0; i < num_lanes; i++) {
   2138             if (num_lanes > 1) {
   2139                 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */
   2140             }
   2141             SOC_IF_ERROR_RETURN
   2142                 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc8fe, 0xffff));
   2143         }
   2144         /* restore the original phy_id */
   2145         pc->phy_id = phy_id;
   2146         return SOC_E_NONE;
   2147     } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) {
   2148         if (bcst_edc_fw) {
   2149             LOG_INFO(BSL_LS_SOC_PHY,
   2150                      (BSL_META_U(unit,
   2151                                  "PHY84756 BCST1: u=%d p=%d\n"), unit, port));
   2152             /* clear SPA ctrl reg bit 15 and bit 13.
   2153                      * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM
   2154                      * bit 13, 0 clear download done status, 1 skip download
   2155                      */
   2156             mask16 = (1 << 13) | (1 << 15);
   2157             data16 = 0;
   2158 
   2159             SOC_IF_ERROR_RETURN
   2160                 (BFCMAP_MOD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, data16, mask16));
   2161 
   2162             /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */
   2163             mask16 = 1 << 14;
   2164             data16 = mask16;
   2165 
   2166             SOC_IF_ERROR_RETURN
   2167                 (BFCMAP_MOD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, data16, mask16));
   2168 
   2169             /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */
   2170             mask16 = 1 << 3;
   2171             data16 = mask16;
   2172 
   2173             SOC_IF_ERROR_RETURN
   2174                 (BFCMAP_MOD_PHY84756_LN_DEV1_MISC_CNTL2r(pc, data16, mask16));
   2175 
   2176             /* apply bcst Reset to start download code from MDIO */
   2177             SOC_IF_ERROR_RETURN
   2178                 (BFCMAP_WR_PHY84756_LN_DEV1_PMD_CTRLr(pc, 0x8000));
   2179         }
   2180         return SOC_E_NONE;
   2181     } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) {
   2182         LOG_INFO(BSL_LS_SOC_PHY,
   2183                  (BSL_META_U(unit,
   2184                              "PHY84756 BCST2: u=%d p=%d\n"), unit, port));
   2185 
   2186         /* reset clears bcst register */
   2187         /* restore bcst register after reset */
   2188 
   2189         phy_id = pc->phy_id;
   2190         /* configure all four ports  */
   2191         for (i = 0; i < num_lanes; i++) {
   2192             if (num_lanes > 1) {
   2193                 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */
   2194             }
   2195             SOC_IF_ERROR_RETURN
   2196                 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc8fe, 0xffff));
   2197         }
   2198         /* restore the original phy_id */
   2199         pc->phy_id = phy_id;
   2200         return SOC_E_NONE;
   2201     } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) {
   2202         if (bcst_edc_fw) {
   2203             
   2204             LOG_INFO(BSL_LS_SOC_PHY,
   2205                      (BSL_META_U(unit,
   2206                                  "firmware_bcst,device name %s: u=%d p=%d\n"),
   2207                                  pc->dev_name? pc->dev_name: "NULL", unit, port));
   2208             
   2209             
   2210             fw_ptr =  FIRMWARE(pc);
   2211             fw_length =  FIRMWARE_LEN(pc);
   2212 
   2213             /* wait for 2ms for M8051 start and 5ms to initialize the RAM */
   2214             sal_usleep(10000); /* Wait for 10ms */
   2215 
   2216             /* Write Starting Address, where the Code will reside in SRAM */
   2217             data16 = 0x8000;
   2218             SOC_IF_ERROR_RETURN
   2219                 (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, data16));
   2220 
   2221             /* make sure address word is read by the micro */
   2222             sal_udelay(10); /* Wait for 10us */
   2223 
   2224             /* Write SPI SRAM Count Size */
   2225             data16 = (fw_length)/2;
   2226             SOC_IF_ERROR_RETURN
   2227                 (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, data16));
   2228 
   2229             /* make sure read by the micro */
   2230             sal_udelay(10); /* Wait for 10us */
   2231 
   2232             /* Fill in the SRAM */
   2233             num_words = (fw_length - 1);
   2234             for (j = 0; j < num_words; j+=2) {
   2235                 /* Make sure the word is read by the Micro */
   2236                 sal_udelay(10);
   2237 
   2238                 data16 = (fw_ptr[j] << 8) | fw_ptr[j+1];
   2239 
   2240                 SOC_IF_ERROR_RETURN
   2241                     (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, data16));
   2242             }
   2243             
   2244         }
   2245         return SOC_E_NONE;
   2246     } else if (cmd == PHYCTRL_UCODE_BCST_LOAD2) {
   2247 #if defined(INCLUDE_FCMAP)
   2248         if (bcst_fc_fw) 
   2249         {
   2250             LOG_INFO(BSL_LS_SOC_PHY,
   2251                      (BSL_META_U(unit,
   2252                                  "uc_firmware_bcst,device name %s: u=%d p=%d\n"),
   2253                       pc->dev_name? pc->dev_name: "NULL", unit, port));
   2254             /* reset clears macsec enable */
   2255             /* restore macsec enable after reset */
   2256             SOC_IF_ERROR_RETURN
   2257                 (BFCMAP_WR_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, 0));
   2258             sal_udelay(100); /* Wait for 100us */
   2259 
   2260             /* Send to UC Firmware Download data */
   2261             bfcmap84756_a0_firmware_download(SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1), 1, 0);
   2262             sal_udelay(100000);
   2263             fc_extra_delay = 1;
   2264             
   2265             /* Power down MACSEC to reduce power consumption */
   2266             SOC_IF_ERROR_RETURN(
   2267                 BFCMAP_WR_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, 
   2268                 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_BYPASS_MODE | 
   2269                 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_ENABLE_PWRDN_MACSEC |
   2270                 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_PWRDW_MACSEC));
   2271         }
   2272 #endif        
   2273         return SOC_E_NONE;
   2274     } else if (cmd == PHYCTRL_UCODE_BCST_END) {
   2275         LOG_INFO(BSL_LS_SOC_PHY,
   2276                  (BSL_META_U(unit,
   2277                              "PHY84756 BCST end: u=%d p=%d\n"), unit, port));
   2278 
   2279         /* make sure last code word is read by the micro */
   2280         sal_udelay(20);
   2281 
   2282         phy_id = pc->phy_id;
   2283         for (i = 0; i < num_lanes; i++) {
   2284             if (num_lanes > 1) {
   2285                 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */
   2286             }
   2287 
   2288             /* first disable bcst mode */
   2289             SOC_IF_ERROR_RETURN
   2290                 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc8fe, 0x0));
   2291 
   2292             if (bcst_edc_fw) {
   2293                 /* Read Hand-Shake message (Done) from Micro */
   2294                 SOC_IF_ERROR_RETURN
   2295                     (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &data16));
   2296 
   2297                 /* Download done message */
   2298                 LOG_INFO(BSL_LS_SOC_PHY,
   2299                          (BSL_META_U(unit,
   2300                                      "u=%d p=%d MDIO firmware download done message: 0x%x\n"),
   2301                                      unit, port,data16));
   2302 
   2303                 /* Clear LASI status */
   2304                 SOC_IF_ERROR_RETURN
   2305                     (BFCMAP_RD_PHY84756_LN_DEV1_RX_ALARM_STATr(pc, &data16));
   2306 
   2307             }
   2308 
   2309         }
   2310         /* restore the original phy_id */
   2311         pc->phy_id = phy_id;
   2312 
   2313         /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */
   2314         sal_udelay(100); /* Wait for 100 usecs */
   2315 
   2316         phy_id = pc->phy_id;
   2317         for (i = 0; i < num_lanes; i++) {
   2318             if (num_lanes > 1) {
   2319                 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */
   2320             }
   2321             if (bcst_edc_fw) {
   2322                 SOC_IF_ERROR_RETURN
   2323                     (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &data16));
   2324 
   2325 
   2326         /* read Rev-ID */
   2327                 /* Need to check if checksum is correct */
   2328                 SOC_IF_ERROR_RETURN
   2329                     (BFCMAP_RD_PHY84756_LN_DEV1_CHECKSUMr(pc, &data16));
   2330 
   2331                 if (data16 != 0x600D) {
   2332                     /* Bad CHECKSUM */
   2333                     LOG_CLI((BSL_META_U(unit,
   2334                                         "firmware_bcst downlad failure: port %d "
   2335                                         "Incorrect Checksum %x\n"), port,data16));
   2336                     return SOC_E_FAIL;
   2337                 }
   2338 
   2339                 /* read Rev-ID */
   2340                 SOC_IF_ERROR_RETURN
   2341                     (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A, &data16));
   2342                 LOG_INFO(BSL_LS_SOC_PHY,
   2343                          (BSL_META_U(unit,
   2344                                      "BCM84756 u=%d p=%d: MDIO broadcast download, EDC firmware version=%x\n"),
   2345                           unit, port, data16));
   2346             } 
   2347         }
   2348         /* restore the original phy_id */
   2349         pc->phy_id = phy_id;
   2350 
   2351 #if defined(INCLUDE_FCMAP)
   2352         if (bcst_fc_fw) 
   2353         {
   2354             LOG_INFO(BSL_LS_SOC_PHY,
   2355                      (BSL_META_U(unit,
   2356                                  "BCM84756 u=%d p=%d: FC firmware MDIO broadcast download\n"), 
   2357                                  unit, port));
   2358             if (fc_extra_delay) 
   2359             {
   2360                 sal_udelay(100000);  /* per mdio bus: wait 100 msec for bcast disable to become effective */
   2361                 fc_extra_delay = 0;
   2362             }
   2363         }
   2364 #endif        
   2365         return SOC_E_NONE;
   2366     } else {
   2367         LOG_WARN(BSL_LS_SOC_PHY,
   2368                  (BSL_META_U(unit,
   2369                              "u=%d p=%d firmware_bcst: invalid cmd 0x%x\n"),
   2370                              unit, port,cmd));
   2371     }
   2372 
   2373     return SOC_E_FAIL;
   2374 }
   2375 
   2376 /*
   2377  * Function:
   2378  *      phy_84756_firmware_set
   2379  * Purpose:
   2380  *      program the given firmware into the SPI-ROM
   2381  * Parameters:
   2382  *      unit - StrataSwitch unit #.
   2383  *      port - StrataSwitch port #.
   2384  *      offset - offset to the data stream
   2385  *      array  - the given data
   2386  *      datalen- the data length
   2387  * Returns:
   2388  *      SOC_E_NONE
   2389  */
   2390 
   2391 STATIC int
   2392 phy_84756_fcmap_firmware_set(int unit, int port, int offset, uint8 *data,int len)
   2393 {
   2394     int            rv;
   2395     phy_ctrl_t *pc;
   2396 
   2397     pc = EXT_PHY_SW_STATE(unit, port);
   2398 
   2399     if (PHY84756_IS_8474X(pc) &&  (data != NULL)) {
   2400         if (PHY84756_SINGLE_PORT_MODE(pc)) {
   2401             LOG_WARN(BSL_LS_SOC_PHY,
   2402                      (BSL_META_U(unit,
   2403                                  "u=%d p=%d Firmware set not supported in 40G mode\n"),
   2404                       unit, port));
   2405             return SOC_E_FAIL;
   2406         }
   2407     }
   2408 
   2409     /* overload this function a littl bit if data == NULL
   2410      * special handling for init. uCode broadcast. Internal use only
   2411      */
   2412     if (data == NULL) {
   2413         return _phy84756_init_ucode_bcst(unit,port,(uint32)offset);
   2414     }
   2415 
   2416     rv = bfcmap_phy84756_spi_firmware_update(pc, data, len);
   2417     if (rv != SOC_E_NONE) {
   2418             LOG_WARN(BSL_LS_SOC_PHY,
   2419                      (BSL_META_U(unit,
   2420                                  "PHY84756 firmware upgrade possibly failed:"
   2421                                  "u=%d p=%d\n"), unit, port));
   2422         return (SOC_E_FAIL);
   2423     }
   2424     LOG_INFO(BSL_LS_SOC_PHY,
   2425              (BSL_META_U(unit,
   2426                          "PHY84756 firmware upgrade successful:"
   2427                          "u=%d p=%d\n"), unit, port));
   2428 
   2429     return SOC_E_NONE;
   2430 }
   2431 
   2432 /*
   2433  * Function:
   2434  *      phy_84756_fcmap_medium_status
   2435  * Purpose:
   2436  *      Indicate the current active medium
   2437  * Parameters:
   2438  *      unit - StrataSwitch unit #.
   2439  *      port - StrataSwitch port #.
   2440  *      medium - (OUT) One of:
   2441  *              SOC_PORT_MEDIUM_COPPER
   2442  *              SOC_PORT_MEDIUM_XAUI
   2443  * Returns:
   2444  *      SOC_E_NONE
   2445  */
   2446 
   2447 STATIC int
   2448 phy_84756_fcmap_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium)
   2449 {
   2450     COMPILER_REFERENCE(unit);
   2451     COMPILER_REFERENCE(port);
   2452 
   2453     *medium = SOC_PORT_MEDIUM_FIBER;
   2454 
   2455     return SOC_E_NONE;
   2456 }
   2457 
   2458 STATIC int
   2459 _phy_84756_control_tx_driver_set(int unit, soc_port_t port,
   2460                                 soc_phy_control_t type, uint32 value)
   2461 {
   2462     uint16       data;  /* Temporary holder of reg value to be written */
   2463     uint16       mask;  /* Bit mask of reg value to be updated */
   2464     uint16 post_tap;
   2465     uint16 main_tap;
   2466     phy_ctrl_t  *pc;    /* PHY software state */
   2467     uint16 reg;
   2468     int interface;
   2469      
   2470     pc = EXT_PHY_SW_STATE(unit, port);
   2471     interface = (pc->flags & PHYCTRL_SYS_SIDE_CTRL)?
   2472            PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE;
   2473 
   2474     switch(type) {
   2475         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   2476         /* fall through */
   2477             data = (uint16)(value & 0xf);
   2478             data = data << 12;
   2479             mask = 0xf000;
   2480             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
   2481             SOC_IF_ERROR_RETURN
   2482                 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, reg, data, mask));
   2483         break;
   2484 
   2485         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   2486         /* fall through */
   2487             data = (uint16)(value & 0xf);
   2488             data = data << 8;
   2489             mask = 0x0f00;
   2490             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
   2491             SOC_IF_ERROR_RETURN
   2492                 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, reg, data, mask));
   2493             break;
   2494         case SOC_PHY_CONTROL_PREEMPHASIS:
   2495         /* The value format:
   2496          * bit 15:  1 enable forced preemphasis ctrl, 0 auto config
   2497          * bit 14:10:  post_tap value
   2498          * bit 09:04:  main tap value 
   2499          * 
   2500          * set 1.CA05[15] = 0, 1.CA02[15:11] for main_tap and 1.CA05[7:4] for post tap.
   2501          * main tap control is in the register field 0xCA02[15:11]. 
   2502          * If a wrong value is written to the same register, field 0xCA02[9:7],
   2503          *  it may DAMAGE the device. User must avoid writing to 0xCA02[9:7] 
   2504          */ 
   2505         /* Register bit15, 0 force preemphasis, 1 auto config, 1.CA05 */ 
   2506         post_tap = PHY84756_PREEMPH_GET_FORCE(value)? 0:
   2507                    PHY84756_PREEMPH_REG_FORCE_MASK;
   2508 
   2509         /* add post tap value */
   2510         post_tap |= PHY84756_PREEMPH_GET_POST_TAP(value) << 
   2511                     PHY84756_PREEMPH_REG_POST_TAP_SHFT;
   2512 
   2513         /* main tap in 1.CA02 */
   2514         main_tap = PHY84756_PREEMPH_GET_MAIN_TAP(value) <<
   2515                    PHY84756_PREEMPH_REG_MAIN_TAP_SHFT;
   2516 
   2517 
   2518         reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca05;
   2519         SOC_IF_ERROR_RETURN
   2520             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, reg, 
   2521                       post_tap, PHY84756_PREEMPH_REG_POST_TAP_MASK |
   2522                                 PHY84756_PREEMPH_REG_FORCE_MASK));
   2523 
   2524         /* always clear tx_pwrdn bit. The read/modify/write may accidently
   2525          * set the bit 0xCA02[10]. Because the CA02[10] read value is: 
   2526          * CA02[10]_read_value = CA02[10] OR Digital_State_Machine 
   2527          * The problem will occur when the Digital_State_Machine output is 1
   2528          * at the time of reading this register.
   2529          */ 
   2530 
   2531         reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90b : 0xca02;
   2532         SOC_IF_ERROR_RETURN
   2533             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, reg, 
   2534                       main_tap, 
   2535                 PHY84756_PREEMPH_REG_MAIN_TAP_MASK |
   2536                 PHY84756_PREEMPH_REG_TX_PWRDN_MASK));
   2537         break;
   2538         
   2539         default:
   2540          /* should never get here */
   2541          return SOC_E_PARAM;
   2542     }
   2543     return SOC_E_NONE;
   2544 }
   2545 
   2546 STATIC int
   2547 _phy_84756_control_tx_driver_get(int unit, soc_port_t port,
   2548                                 soc_phy_control_t type, uint32 *value)
   2549 {
   2550     uint16         data16;   /* Temporary holder of a reg value */
   2551     uint16         main_tap;
   2552     uint16         post_tap;
   2553     phy_ctrl_t    *pc;       /* PHY software state */
   2554     uint16 reg;
   2555     int interface;
   2556 
   2557     pc = EXT_PHY_SW_STATE(unit, port);
   2558     interface = (pc->flags & PHYCTRL_SYS_SIDE_CTRL)?
   2559            PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE;
   2560 
   2561     data16 = 0;
   2562     switch(type) {
   2563         case SOC_PHY_CONTROL_PREEMPHASIS:
   2564             /* 1.CA05[15] = 0, set 1.CA02[15:11] for main_tap and 
   2565              * 1.CA05[7:4] for postcursor 
   2566              */
   2567 
   2568             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90b : 0xca02;
   2569             SOC_IF_ERROR_RETURN
   2570                 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, reg, &main_tap));
   2571             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca05;
   2572             SOC_IF_ERROR_RETURN
   2573                 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, reg, &post_tap));
   2574 
   2575             /* bit15 force flag, 14:10 post_tap, 09:04 main tap */
   2576             *value = (post_tap & PHY84756_PREEMPH_REG_FORCE_MASK)? 0:
   2577                      (1 << PHY84756_PREEMPH_CTRL_FORCE_SHFT); 
   2578             *value |= ((post_tap & PHY84756_PREEMPH_REG_POST_TAP_MASK) >>
   2579                       PHY84756_PREEMPH_REG_POST_TAP_SHFT) << 
   2580                       PHY84756_PREEMPH_CTRL_POST_TAP_SHFT; 
   2581             *value |= ((main_tap & PHY84756_PREEMPH_REG_MAIN_TAP_MASK) >>
   2582                       PHY84756_PREEMPH_REG_MAIN_TAP_SHFT) <<
   2583                       PHY84756_PREEMPH_CTRL_MAIN_TAP_SHFT; 
   2584 
   2585         break;
   2586 
   2587         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   2588             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
   2589             SOC_IF_ERROR_RETURN
   2590                 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, reg, &data16));
   2591             *value = (data16 & 0xf000) >> 12;
   2592         break;
   2593 
   2594         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   2595             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
   2596             SOC_IF_ERROR_RETURN
   2597                 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, reg, &data16));
   2598             *value = (data16 & 0x0f00) >> 8;
   2599             break;
   2600 
   2601        default:
   2602          /* should never get here */
   2603          return SOC_E_PARAM;
   2604     }
   2605 
   2606     return SOC_E_NONE;
   2607 }
   2608 
   2609 STATIC int
   2610 _phy_84756_control_edc_mode_set(int unit, soc_port_t port, uint32 value)
   2611 {
   2612     uint16         data16;
   2613     uint16         mask16;
   2614     phy_ctrl_t    *pc;       /* PHY software state */
   2615 
   2616     pc = EXT_PHY_SW_STATE(unit, port);
   2617 
   2618 
   2619     /* EDC mode programming sequence*/     
   2620     mask16 = 1 << 9;
   2621 
   2622     /* induce LOS condition: toggle register bit 0xc800.9 */
   2623     SOC_IF_ERROR_RETURN         
   2624         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 
   2625                                    0xc800,&data16));
   2626 
   2627     /* only change toggled bit 9 */
   2628     SOC_IF_ERROR_RETURN
   2629         (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 
   2630              0xc800,~data16,mask16));
   2631 
   2632     /* program EDC mode */
   2633     SOC_IF_ERROR_RETURN
   2634       (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A,(uint16)value,
   2635                               PHY84756_EDC_MODE_MASK));
   2636 
   2637     /* remove LOS condition: restore back original value of bit 0xc800.9 */
   2638     SOC_IF_ERROR_RETURN
   2639         (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 
   2640                0xc800,data16,mask16));
   2641 
   2642     return SOC_E_NONE;
   2643 }
   2644 
   2645 
   2646 STATIC int
   2647 _phy_84756_control_prbs_tx_invert_data_set(int unit, soc_port_t port, int invert)
   2648 {
   2649     phy_ctrl_t    *pc;       /* PHY software state */
   2650     uint16 data16;
   2651     int speed=0;
   2652 
   2653     pc = EXT_PHY_SW_STATE(unit, port);
   2654 
   2655     SOC_IF_ERROR_RETURN(
   2656                phy_84756_fcmap_speed_get(unit, port, &speed));
   2657 
   2658     if (speed == 1000) {
   2659         /* tx inversion */
   2660         data16 = invert? PHY84756_1G_USER_PRBS_TX_INVERT: 0;
   2661         
   2662 
   2663         SOC_IF_ERROR_RETURN
   2664             (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_GEN( pc,
   2665                 data16,
   2666                 PHY84756_1G_USER_PRBS_TX_INVERT));
   2667     } else {
   2668         /* tx inversion */
   2669         data16 = invert? PHY84756_USER_PRBS_TX_INVERT: 0;
   2670         
   2671         SOC_IF_ERROR_RETURN
   2672             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 
   2673                   PHY84756_USER_PRBS_CONTROL_0_REGISTER, data16,
   2674                            PHY84756_USER_PRBS_TX_INVERT));
   2675     }
   2676     return SOC_E_NONE;
   2677 }
   2678 
   2679 STATIC int
   2680 _phy_84756_control_prbs_rx_invert_data_set(int unit, soc_port_t port, int invert)
   2681 {
   2682     phy_ctrl_t    *pc;       /* PHY software state */
   2683     uint16 data16;
   2684     uint16 mask16;
   2685 
   2686     pc = EXT_PHY_SW_STATE(unit, port);
   2687 
   2688     /* rx inversion */
   2689     data16 = invert? PHY84756_USER_PRBS_RX_INVERT: 0;
   2690     mask16 = PHY84756_USER_PRBS_RX_INVERT;
   2691     SOC_IF_ERROR_RETURN
   2692         (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc,
   2693               PHY84756_USER_PRBS_CONTROL_0_REGISTER, data16,
   2694                        mask16));
   2695     return SOC_E_NONE;
   2696 }
   2697 
   2698 STATIC int
   2699 _phy_84756_control_prbs_polynomial_set(int unit, soc_port_t port,int poly_ctrl,
   2700          int tx)   /* tx or rx */
   2701 {
   2702     phy_ctrl_t    *pc;       /* PHY software state */
   2703     uint16 data16;
   2704     uint16 mask16;
   2705     int speed=0;
   2706         
   2707         /*
   2708          * poly_ctrl:
   2709          *  0x0 = prbs7
   2710          *  0x1 = prbs15
   2711          *  0x2 = prbs23
   2712          *  0x3 = prbs31
   2713          */
   2714     pc = EXT_PHY_SW_STATE(unit, port);
   2715 
   2716     /* 001 : prbs7 
   2717        010 : prbs9
   2718        011 : prbs11
   2719        100 : prbs15
   2720        101 : prbs23
   2721        110 : prbs31
   2722      */
   2723     
   2724      SOC_IF_ERROR_RETURN(
   2725                phy_84756_fcmap_speed_get(unit, port, &speed));
   2726 
   2727     if (poly_ctrl == 0) {
   2728         data16 = SP_MAP(speed,1);
   2729     } else if (poly_ctrl == 1) {
   2730         data16 = SP_MAP(speed,4);
   2731     } else if (poly_ctrl == 2) {
   2732         data16 = SP_MAP(speed,5);
   2733     } else if (poly_ctrl == 3) {
   2734         data16 = SP_MAP(speed,6);
   2735     } else {
   2736         return SOC_E_PARAM;
   2737     } 
   2738 
   2739     if(speed == 1000) {
   2740         mask16 = PHY84756_USER_PRBS_TYPE_MASK_1G;
   2741     } else { 
   2742         mask16 = PHY84756_USER_PRBS_TYPE_MASK;
   2743         /* default is tx */
   2744         if (!tx) {  /* rx */
   2745             data16 = data16 << 12;
   2746             mask16 = mask16 << 12;
   2747         }
   2748     }
   2749     
   2750     if(speed == 1000) {
   2751         SOC_IF_ERROR_RETURN
   2752             (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_GEN( pc,
   2753                                                   data16, mask16));
   2754         /* Enable PRBS Checker 7.80B1.[2:0]=111 */ 
   2755         SOC_IF_ERROR_RETURN
   2756             (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_LOCK_ERR(pc, 0x7, 0x7));
   2757 
   2758     } else {    
   2759     /* both tx/rx types */  
   2760     SOC_IF_ERROR_RETURN
   2761         (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 
   2762                 PHY84756_USER_PRBS_CONTROL_0_REGISTER, 
   2763            data16, mask16));
   2764     }
   2765     
   2766     return SOC_E_NONE;
   2767 }
   2768 STATIC int
   2769 _phy_84756_control_prbs_enable_set(int unit, soc_port_t port, int enable)
   2770 {
   2771     phy_ctrl_t    *pc;       /* PHY software state */
   2772     int repeater_mode;
   2773     uint16 data16;
   2774     int speed = 0;
   2775 
   2776     pc = EXT_PHY_SW_STATE(unit, port);
   2777 
   2778     SOC_IF_ERROR_RETURN(
   2779         phy_84756_fcmap_speed_get(unit, port, &speed));
   2780 
   2781     if(speed == 1000) {     
   2782         /* disable Comma Detect and CL36 for 1G PRBS */
   2783         SOC_IF_ERROR_RETURN(
   2784             BFCMAP_WR_PHY84756_XFI_DEV7_XGXS_CTRL(pc, 0x2c22));
   2785         SOC_IF_ERROR_RETURN(
   2786             BFCMAP_WR_PHY84756_XFI_DEV7_LANE_CTRL2(pc, 0));
   2787         SOC_IF_ERROR_RETURN(
   2788             BFCMAP_WR_PHY84756_XFI_DEV7_LANE_CTRL0(pc, 0));
   2789     }
   2790 
   2791     SOC_IF_ERROR_RETURN
   2792         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc81d, &data16));
   2793 
   2794     repeater_mode = ((data16 & 0x6) == 0x6)? TRUE: FALSE;
   2795     if (repeater_mode) {
   2796         /* Enable retimer prbs clocks inside SFI */
   2797         SOC_IF_ERROR_RETURN
   2798             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 
   2799                       PHY84756_GENSIG_8071_REGISTER, 
   2800                             enable?0x3:0,0x3));
   2801 
   2802         /* Enable the retimer datapath */
   2803         SOC_IF_ERROR_RETURN
   2804             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 0xcd58, 
   2805                         enable?0x2:0,0x3));
   2806     }
   2807     /* clear PRBS control if disabled */
   2808     if (!enable) {
   2809         if (speed == 1000) {
   2810 
   2811             SOC_IF_ERROR_RETURN
   2812             (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_GEN( pc,
   2813                                                   0, PHY84756_40G_PRBS_TX_ENABLE));
   2814             /* Set 7.8015, 7.8017, 7.8000 to original values */
   2815             SOC_IF_ERROR_RETURN(
   2816                 BFCMAP_WR_PHY84756_XFI_DEV7_XGXS_CTRL(pc, PHY84756_1G_PRBS_XGXS_CTRL));
   2817             SOC_IF_ERROR_RETURN(
   2818                 BFCMAP_WR_PHY84756_XFI_DEV7_LANE_CTRL2(pc, PHY84756_1G_PRBS_LANE_CTRL2));
   2819             SOC_IF_ERROR_RETURN(
   2820                 BFCMAP_WR_PHY84756_XFI_DEV7_LANE_CTRL0(pc, PHY84756_1G_PRBS_LANE_CTRL0));
   2821 
   2822         } else {
   2823             SOC_IF_ERROR_RETURN
   2824                 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 
   2825                            PHY84756_USER_PRBS_CONTROL_0_REGISTER, 0,
   2826                              PHY84756_USER_PRBS_TYPE_MASK |
   2827                              PHY84756_USER_PRBS_TYPE_MASK << 12)); /* rx type*/
   2828         }
   2829     }         
   2830 
   2831     /*  program the PRBS enable */
   2832     
   2833     if (speed == 1000) {
   2834         SOC_IF_ERROR_RETURN
   2835             (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_GEN( pc,
   2836             enable? PHY84756_40G_PRBS_TX_ENABLE: 0 , PHY84756_40G_PRBS_TX_ENABLE));
   2837     } else {
   2838         SOC_IF_ERROR_RETURN
   2839             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 
   2840                      PHY84756_USER_PRBS_CONTROL_0_REGISTER, 
   2841                      enable? PHY84756_USER_PRBS_ENABLE: 0,PHY84756_USER_PRBS_ENABLE));
   2842     }
   2843     
   2844     return SOC_E_NONE;
   2845 }
   2846 
   2847 STATIC int
   2848 _phy_84756_control_pdet_set(int unit, soc_port_t port, uint32 enable)
   2849 {
   2850     uint16 mask;
   2851     uint16 data;
   2852     phy_ctrl_t *pc;   /* PHY software state */
   2853 
   2854     mask = PHY84756_PDET_MASK;
   2855     data = enable ? mask : 0;
   2856 
   2857     pc = EXT_PHY_SW_STATE(unit, port);
   2858 
   2859     SOC_IF_ERROR_RETURN(
   2860         BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL2r(pc, data, mask));
   2861     
   2862     return SOC_E_NONE;
   2863 }
   2864 
   2865 STATIC int
   2866 _phy_84756_control_prbs_enable_get(int unit, soc_port_t port, uint32 *value)
   2867 {
   2868     uint16 data16;
   2869     phy_ctrl_t    *pc;       /* PHY software state */
   2870     int speed =0;
   2871 
   2872     pc = EXT_PHY_SW_STATE(unit, port);
   2873 
   2874     SOC_IF_ERROR_RETURN(
   2875                phy_84756_fcmap_speed_get(unit, port, &speed));
   2876 
   2877     if(speed == 1000) {
   2878         SOC_IF_ERROR_RETURN
   2879             (BFCMAP_RD_PHY84756_XFI_DEV7_PRBS_GEN( pc,
   2880                                                   &data16));
   2881     } else {
   2882 
   2883     SOC_IF_ERROR_RETURN
   2884         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, 
   2885                PHY84756_USER_PRBS_CONTROL_0_REGISTER, &data16));
   2886     }
   2887 
   2888     if ( ((speed == 1000) &&  (data16 & PHY84756_40G_PRBS_TX_ENABLE)) ) {
   2889         *value = TRUE;
   2890     } else if ( (speed != 1000) && (data16 & PHY84756_USER_PRBS_ENABLE) ) {
   2891         *value = TRUE;
   2892     } else {
   2893         *value = FALSE;
   2894     }
   2895     
   2896     return SOC_E_NONE;
   2897 }
   2898 STATIC int
   2899 _phy_84756_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value)
   2900 {
   2901     phy_ctrl_t    *pc;       /* PHY software state */
   2902     uint16 poly_ctrl;
   2903     int speed =0;
   2904 
   2905     pc = EXT_PHY_SW_STATE(unit, port);
   2906     SOC_IF_ERROR_RETURN(
   2907                phy_84756_fcmap_speed_get(unit, port, &speed));
   2908 
   2909     if(speed == 1000) {
   2910         SOC_IF_ERROR_RETURN
   2911             (BFCMAP_RD_PHY84756_XFI_DEV7_PRBS_GEN( pc,
   2912                                                   &poly_ctrl));
   2913         poly_ctrl &= PHY84756_USER_PRBS_TYPE_MASK_1G;
   2914     } else {
   2915 
   2916         SOC_IF_ERROR_RETURN
   2917             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, 
   2918                        PHY84756_USER_PRBS_CONTROL_0_REGISTER, &poly_ctrl));
   2919         poly_ctrl &= PHY84756_USER_PRBS_TYPE_MASK;
   2920     }
   2921 
   2922     if (poly_ctrl == SP_MAP(speed,1)) {
   2923         * value = 0;
   2924     } else if (poly_ctrl == SP_MAP(speed,4)) {
   2925         *value = 1;
   2926     } else if (poly_ctrl == SP_MAP(speed,5)) {
   2927         *value = 2;
   2928     } else if (poly_ctrl == SP_MAP(speed,6)) {
   2929         *value = 3;
   2930     } else {
   2931         *value = poly_ctrl;
   2932     }
   2933     
   2934     return SOC_E_NONE;
   2935 }
   2936 
   2937 STATIC int
   2938 _phy_84756_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value)
   2939 {
   2940     phy_ctrl_t    *pc;       /* PHY software state */
   2941     uint16 data16;
   2942     int speed=0;
   2943 
   2944     pc = EXT_PHY_SW_STATE(unit, port);
   2945 
   2946     SOC_IF_ERROR_RETURN(
   2947                phy_84756_fcmap_speed_get(unit, port, &speed));
   2948 
   2949     if (speed == 1000) {
   2950 
   2951         SOC_IF_ERROR_RETURN
   2952             (BFCMAP_RD_PHY84756_XFI_DEV7_PRBS_GEN( pc, &data16));
   2953 
   2954         if (data16 & PHY84756_1G_USER_PRBS_TX_INVERT) {
   2955             *value = TRUE;
   2956         } else {
   2957             *value = FALSE;
   2958         }
   2959 
   2960     } else {
   2961 
   2962         SOC_IF_ERROR_RETURN
   2963             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, 
   2964                       PHY84756_USER_PRBS_CONTROL_0_REGISTER, &data16));
   2965         if (data16 & PHY84756_USER_PRBS_TX_INVERT) {
   2966             *value = TRUE;
   2967         } else {
   2968             *value = FALSE;
   2969         }
   2970     }
   2971     return SOC_E_NONE;
   2972 }
   2973 
   2974 STATIC int
   2975 _phy_84756_control_prbs_rx_status_get(int unit, soc_port_t port, uint32 *value)
   2976 {
   2977     phy_ctrl_t    *pc;       /* PHY software state */
   2978     uint16 data16;
   2979     int speed = 0;
   2980 
   2981     pc = EXT_PHY_SW_STATE(unit, port);
   2982 
   2983     *value = 0;
   2984    
   2985     SOC_IF_ERROR_RETURN(
   2986                phy_84756_fcmap_speed_get(unit, port, &speed));
   2987 
   2988     if(speed == 1000) {
   2989         SOC_IF_ERROR_RETURN
   2990             (BFCMAP_RD_PHY84756_XFI_DEV7_PRBS_CHK(pc, &data16));
   2991     } else {
   2992         SOC_IF_ERROR_RETURN
   2993             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, 
   2994                           PHY84756_USER_PRBS_STATUS_0_REGISTER, &data16));
   2995     }
   2996 
   2997     if (data16 == 0x8000) { /* PRBS lock and error free */
   2998         *value = 0;
   2999     } else if (!(data16 & 0x8000)) {
   3000         *value = -1;
   3001     } else {
   3002         *value = data16 & 0x7fff;
   3003     }
   3004 
   3005     return SOC_E_NONE;
   3006 }
   3007 
   3008 STATIC int
   3009 _phy_84756_control_edc_mode_get(int unit, soc_port_t port, uint32 *value)
   3010 {
   3011     uint16         data16;
   3012     phy_ctrl_t    *pc;       /* PHY software state */
   3013 
   3014     pc = EXT_PHY_SW_STATE(unit, port);
   3015 
   3016     /* get EDC mode */     
   3017     SOC_IF_ERROR_RETURN
   3018       (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A,&data16));
   3019 
   3020     *value = data16 & PHY84756_EDC_MODE_MASK;
   3021 
   3022     return SOC_E_NONE;
   3023 }
   3024 
   3025 STATIC char *
   3026 _phy_84756_mode_name_get(int unit, soc_port_t port)
   3027 {
   3028     phy_ctrl_t *pc;
   3029 
   3030     pc = EXT_PHY_SW_STATE(unit, port);
   3031     if (FCMAP_ENABLE(pc)) {
   3032         return "FC";
   3033     } else if (MACSEC_ENABLE(pc)) {
   3034         return "MACSEC";
   3035     }
   3036     return "ETHERNET";
   3037 }
   3038 
   3039 STATIC int
   3040 _phy_84756_firmware_info_dump(int unit, soc_port_t port)
   3041 {   
   3042     uint16 sts;
   3043     uint16 version;
   3044     uint16 cksum;
   3045     phy_ctrl_t *pc;
   3046 
   3047     pc = EXT_PHY_SW_STATE(unit, port);
   3048 
   3049     SOC_IF_ERROR_RETURN
   3050         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A, &version));
   3051     SOC_IF_ERROR_RETURN
   3052         (BFCMAP_RD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, &sts));
   3053     SOC_IF_ERROR_RETURN
   3054         (BFCMAP_RD_PHY84756_LN_DEV1_CHECKSUMr(pc, &cksum));
   3055 
   3056     LOG_CLI((BSL_META_U(unit,
   3057                         "    Firmware: version=%04x, download status=%04x, "
   3058                         "checksum=%04x\n"), 
   3059              version, sts, cksum));
   3060 
   3061     return SOC_E_NONE;
   3062 }
   3063 
   3064 STATIC int
   3065 _phy_84756_control_dump(int unit, soc_port_t port)
   3066 {
   3067     phy_ctrl_t *pc;
   3068     uint16 chip_rev_id;
   3069 
   3070     pc = EXT_PHY_SW_STATE(unit, port);
   3071 
   3072     SOC_IF_ERROR_RETURN
   3073         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xC801, &chip_rev_id));
   3074 
   3075     LOG_CLI((BSL_META_U(unit,
   3076                         "Port %d: chiprev=%04x, mode=%s, MACSEC support=%s\n"), 
   3077              port, chip_rev_id, _phy_84756_mode_name_get(unit, port),
   3078              MACSEC_SUPPORT(pc) ? "yes" : "no"));
   3079     LOG_CLI((BSL_META_U(unit,
   3080                         "size=%d  sof=%d \n"),
   3081              pc->size, (int) sizeof(phy84756_map_t) ));
   3082 
   3083     SOC_IF_ERROR_RETURN(_phy_84756_firmware_info_dump(unit, port));
   3084     return SOC_E_NONE;
   3085 }
   3086 
   3087 STATIC int
   3088 _phy_84756_control_pdet_get(int unit, soc_port_t port, uint32 *value)
   3089 {
   3090     uint16         data16;
   3091     phy_ctrl_t    *pc;       /* PHY software state */
   3092 
   3093     pc = EXT_PHY_SW_STATE(unit, port);
   3094 
   3095     SOC_IF_ERROR_RETURN(
   3096         BFCMAP_RD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL2r(pc, &data16));
   3097 
   3098     if ((data16 & PHY84756_PDET_MASK) == PHY84756_PDET_MASK) {
   3099         *value = 1; 
   3100     } else {
   3101         *value = 0; 
   3102     }
   3103 
   3104     return SOC_E_NONE;
   3105 }
   3106 
   3107 
   3108 /*
   3109  * Function:
   3110  *      phy_84756_control_set
   3111  * Purpose:
   3112  *      Configure PHY device specific control fucntion.
   3113  * Parameters:
   3114  *      unit  - StrataSwitch unit #.
   3115  *      port  - StrataSwitch port #.
   3116  *      type  - Control to update
   3117  *      value - New setting for the control
   3118  * Returns:
   3119  *      SOC_E_NONE
   3120  */
   3121 STATIC int
   3122 _phy_84756_control_set(int unit, soc_port_t port, int intf,int lane,
   3123                      soc_phy_control_t type, uint32 value)
   3124 {
   3125     phy_ctrl_t    *pc;       /* PHY software state */
   3126     int rv;
   3127 
   3128     pc = EXT_PHY_SW_STATE(unit, port);
   3129 
   3130     PHY_CONTROL_TYPE_CHECK(type);
   3131 
   3132     rv = SOC_E_UNAVAIL;
   3133     if (intf == PHY_DIAG_INTF_SYS) {
   3134         /* if is targeted to the system side */
   3135         SOC_IF_ERROR_RETURN
   3136             (PHY84756_XFI(unit,pc));
   3137     }
   3138     switch(type) {
   3139     case SOC_PHY_CONTROL_PREEMPHASIS:
   3140         /* fall through */
   3141     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   3142         /* fall through */
   3143     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   3144         /* fall through */
   3145         rv = _phy_84756_control_tx_driver_set(unit, port, type, value);
   3146         break;
   3147 
   3148     case SOC_PHY_CONTROL_EDC_MODE:
   3149         rv = _phy_84756_control_edc_mode_set(unit,port,value);
   3150         break;
   3151     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   3152         /* on line side, rx poly type is auto-detected. On system side,
   3153          * need to enable the rx type as well.
   3154          */
   3155         rv = _phy_84756_control_prbs_polynomial_set(unit, port, value, TRUE);
   3156         if (intf == PHY_DIAG_INTF_SYS) {
   3157             rv = _phy_84756_control_prbs_polynomial_set(unit, port,value,FALSE);
   3158         }
   3159         break;
   3160     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   3161         /* on line side, rx invertion is auto-detected. On system side,
   3162          * need to enable the rx as well.
   3163          */
   3164         rv = _phy_84756_control_prbs_tx_invert_data_set(unit, port, value);
   3165         if (intf == PHY_DIAG_INTF_SYS) {
   3166             rv = _phy_84756_control_prbs_rx_invert_data_set(unit, port, value);
   3167         }
   3168         break;
   3169     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   3170         /* fall through */
   3171     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   3172         /* tx/rx is enabled at the same time. no seperate control */
   3173         rv = _phy_84756_control_prbs_enable_set(unit, port, value);
   3174         break;
   3175     case SOC_PHY_CONTROL_DUMP:
   3176         _phy_84756_control_dump(unit, port);
   3177         break;
   3178     case SOC_PHY_CONTROL_PARALLEL_DETECTION: 
   3179         rv = _phy_84756_control_pdet_set(unit, port, value);
   3180         break;
   3181     case SOC_PHY_CONTROL_TX_LANE_SQUELCH:
   3182         rv = phy_84756_fcmap_squelch_enable(unit, port, intf, value, FALSE);
   3183         break;
   3184     case SOC_PHY_CONTROL_MACSEC_ENABLE:
   3185         phy_84756_macsec_enable(unit, port, value);
   3186         break;
   3187     default:
   3188         rv = SOC_E_UNAVAIL;
   3189         break;
   3190     }
   3191     if (intf == PHY_DIAG_INTF_SYS) {
   3192         /* if it is targeted to the system side, switch back */
   3193         SOC_IF_ERROR_RETURN
   3194             (PHY84756_MMF(unit,pc));
   3195     }
   3196     return rv;
   3197 }
   3198 
   3199 /*
   3200  * Function:
   3201  *      phy_84756_fcmap_control_set
   3202  * Purpose:
   3203  *      Configure PHY device specific control fucntion.
   3204  * Parameters:
   3205  *      unit  - StrataSwitch unit #.
   3206  *      port  - StrataSwitch port #.
   3207  *      type  - Control to update
   3208  *      value - New setting for the control
   3209  * Returns:    
   3210  *      SOC_E_NONE
   3211  */
   3212 STATIC int
   3213 phy_84756_fcmap_control_set(int unit, soc_port_t port,
   3214                      soc_phy_control_t type, uint32 value)
   3215 {
   3216     int intf;
   3217     phy_ctrl_t    *pc;       /* PHY software state */
   3218 
   3219     pc = EXT_PHY_SW_STATE(unit, port);
   3220 
   3221     intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL)? 
   3222            PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE;
   3223 
   3224     /* 40G control Set */
   3225     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   3226         PHY_CONTROL_SET(PHY84756_40G, unit, port, type, value));
   3227 
   3228     if (PHY84756_IS_8474X(pc)) {
   3229         switch(type) {
   3230             case SOC_PHY_CONTROL_EDC_MODE:
   3231             case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
   3232             case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   3233                 SOC_IF_ERROR_RETURN(
   3234                     PHY_CONTROL_SET(PHY84756_40G, unit, port, type, value));
   3235             return SOC_E_NONE;
   3236             default:
   3237             break;
   3238         }
   3239     }
   3240 
   3241     SOC_IF_ERROR_RETURN
   3242         (_phy_84756_control_set(unit, port, intf,
   3243             PHY_DIAG_LN_DFLT, type, value));
   3244     return SOC_E_NONE;
   3245 }
   3246 
   3247 /*
   3248  * Function:
   3249  *      phy_84756_control_get
   3250  * Purpose:
   3251  *      Get current control settign of the PHY.
   3252  * Parameters:
   3253  *      unit  - StrataSwitch unit #.
   3254  *      port  - StrataSwitch port #.
   3255  *      type  - Control to update
   3256  *      value - (OUT)Current setting for the control
   3257  * Returns:
   3258  *      SOC_E_NONE
   3259  */
   3260 STATIC int
   3261 _phy_84756_control_get(int unit, soc_port_t port, int intf,int lane,
   3262                      soc_phy_control_t type, uint32 *value)
   3263 {
   3264     phy_ctrl_t    *pc;       /* PHY software state */
   3265     int rv;
   3266 
   3267     pc = EXT_PHY_SW_STATE(unit, port);
   3268 
   3269     PHY_CONTROL_TYPE_CHECK(type);
   3270 
   3271     if (intf == PHY_DIAG_INTF_SYS) {
   3272         /* targeted to the system side */
   3273         SOC_IF_ERROR_RETURN
   3274             (PHY84756_XFI(unit,pc));
   3275     }
   3276     rv = SOC_E_UNAVAIL;
   3277     switch(type) {
   3278     case SOC_PHY_CONTROL_PREEMPHASIS:
   3279         /* fall through */
   3280     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   3281         /* fall through */
   3282     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   3283         /* fall through */
   3284         rv = _phy_84756_control_tx_driver_get(unit, port, type, value);
   3285         break;
   3286 
   3287     case SOC_PHY_CONTROL_EDC_MODE:
   3288         rv = _phy_84756_control_edc_mode_get(unit,port,value);
   3289         break;
   3290     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   3291         rv = _phy_84756_control_prbs_polynomial_get(unit, port, value);
   3292         break;
   3293     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   3294         rv = _phy_84756_control_prbs_tx_invert_data_get(unit, port, value);
   3295         break;
   3296     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   3297         /* fall through */
   3298     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   3299         rv = _phy_84756_control_prbs_enable_get(unit, port, value);
   3300         break;
   3301     case SOC_PHY_CONTROL_PRBS_RX_STATUS:
   3302         rv = _phy_84756_control_prbs_rx_status_get(unit, port, value);
   3303         break;
   3304     case SOC_PHY_CONTROL_PARALLEL_DETECTION:
   3305         rv = _phy_84756_control_pdet_get(unit, port, value);
   3306         break; 
   3307     default:
   3308         rv = SOC_E_UNAVAIL;
   3309         break;
   3310     }
   3311 
   3312     if (intf == PHY_DIAG_INTF_SYS) {
   3313         /* if it is targeted to the system side, switch back */
   3314         SOC_IF_ERROR_RETURN
   3315             (PHY84756_MMF(unit,pc));
   3316     }
   3317     return rv;
   3318 }
   3319 /*
   3320  * Function:
   3321  *      phy_84756_fcmap_control_get
   3322  * Purpose:
   3323  *      Get current control settign of the PHY.
   3324  * Parameters:
   3325  *      unit  - StrataSwitch unit #.
   3326  *      port  - StrataSwitch port #.
   3327  *      type  - Control to update
   3328  *      value - (OUT)Current setting for the control
   3329  * Returns:
   3330  *      SOC_E_NONE
   3331  */
   3332 STATIC int 
   3333 phy_84756_fcmap_control_get(int unit, soc_port_t port,
   3334                      soc_phy_control_t type, uint32 *value)
   3335 {
   3336     int intf;
   3337     phy_ctrl_t    *pc;       /* PHY software state */
   3338 
   3339     pc = EXT_PHY_SW_STATE(unit, port);
   3340 
   3341     intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL)? 
   3342            PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE;
   3343 
   3344     /* 40G control get */
   3345     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   3346         PHY_CONTROL_GET(PHY84756_40G, unit, port, type, value));
   3347 
   3348 
   3349     if (PHY84756_IS_8474X(pc)) {
   3350         switch(type) {
   3351             case SOC_PHY_CONTROL_EDC_MODE:
   3352             case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
   3353                 SOC_IF_ERROR_RETURN(
   3354                     PHY_CONTROL_GET(PHY84756_40G, unit, port, type, value));
   3355             return SOC_E_NONE;
   3356             default:
   3357             break;
   3358         }
   3359     }
   3360 
   3361     SOC_IF_ERROR_RETURN
   3362         (_phy_84756_control_get(unit, port, intf,
   3363             PHY_DIAG_LN_DFLT, type, value));
   3364     return SOC_E_NONE;
   3365 }
   3366 
   3367 STATIC int
   3368 phy_84756_diag_ctrl(
   3369    int unit, /* unit */
   3370    soc_port_t port, /* port */
   3371    uint32 inst, /* the specific device block the control action directs to */
   3372    int op_type,  /* operation types: read,write or command sequence */
   3373    int op_cmd,   /* command code */
   3374    void *arg)     /* command argument  */
   3375 {
   3376     int lane;
   3377     int intf;
   3378 
   3379     LOG_INFO(BSL_LS_SOC_PHY,
   3380              (BSL_META_U(unit,
   3381                          "phy_84756_diag_ctrl: u=%d p=%d ctrl=0x%x\n"), 
   3382                          unit, port,op_cmd));
   3383    
   3384     /* 40G reg read */
   3385     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   3386         PHY_DIAG_CTRL(PHY84756_40G, unit, port, inst, op_type, op_cmd, arg));
   3387 
   3388     lane = PHY_DIAG_INST_LN(inst);
   3389     intf = PHY_DIAG_INST_INTF(inst);
   3390     if (intf == PHY_DIAG_INTF_DFLT) {
   3391         intf = PHY_DIAG_INTF_LINE;
   3392     }
   3393 
   3394     if (op_type == PHY_DIAG_CTRL_GET) { 
   3395         SOC_IF_ERROR_RETURN
   3396             (_phy_84756_control_get(unit, port, intf, lane,
   3397                   op_cmd,(uint32 *)arg));
   3398     } else if (op_type == PHY_DIAG_CTRL_SET) {
   3399         SOC_IF_ERROR_RETURN
   3400             (_phy_84756_control_set(unit, port, intf, lane,
   3401                   op_cmd, PTR_TO_INT(arg)));
   3402     }
   3403     return SOC_E_NONE;
   3404 }
   3405 
   3406 /*
   3407  * Function:
   3408  *      phy_84756_fcmap_linkup
   3409  * Purpose:
   3410  *      Link up handler
   3411  * Parameters:
   3412  *      unit  - StrataSwitch unit #.
   3413  *      port  - StrataSwitch port #.
   3414  * Returns:
   3415  *      SOC_E_NONE
   3416  */
   3417 STATIC int 
   3418 phy_84756_fcmap_linkup(int unit, soc_port_t port)
   3419 {
   3420 
   3421     /* After link up configure the system side to operate at 10G */
   3422     phy_ctrl_t *pc;
   3423 #if defined(INCLUDE_FCMAP)
   3424     phy_ctrl_t  *int_pc = INT_PHY_SW_STATE(unit, port);
   3425 #endif
   3426     bfcmap_phy84756_intf_t line_mode;
   3427 
   3428     pc = EXT_PHY_SW_STATE(unit, port);
   3429 
   3430     /* 40G linkup evt */
   3431     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   3432         PHY_LINKUP_EVT(PHY84756_40G, unit, port));
   3433 
   3434 #if defined(INCLUDE_FCMAP)
   3435     if (pc->fcmap_enable) {
   3436         if (NULL != int_pc) {
   3437             PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0);
   3438             PHY_SPEED_SET(int_pc->pd, unit, port, 10000);
   3439         }
   3440         /* XFI System Side Speed to 10G */
   3441         SOC_IF_ERROR_RETURN(
   3442             _phy84756_system_xfi_speed_set(pc, 0, 10000));
   3443 
   3444         /* Notify 10G speed */ 
   3445         SOC_IF_ERROR_RETURN
   3446             (soc_phyctrl_notify(unit, port, phyEventSpeed, 10000)); 
   3447 
   3448     } else 
   3449 #endif
   3450     {
   3451         SOC_IF_ERROR_RETURN(
   3452             bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   3453 
   3454         if (line_mode == BFCMAP_PHY84756_INTF_SGMII) {
   3455             SOC_IF_ERROR_RETURN(
   3456                 _bfcmap_phy84756_system_sgmii_sync(pc, 0));
   3457         } 
   3458     }
   3459 
   3460     return SOC_E_NONE;
   3461 }
   3462 
   3463 /*
   3464  * Function:
   3465  *      phy_84756_fcmap_interface_set
   3466  * Purpose:
   3467  *      Get interface on a given port.
   3468  * Parameters:
   3469  *      unit  - StrataSwitch unit #.
   3470  *      port  - StrataSwitch port #.
   3471  *      pif   - Interface.
   3472  * Returns:
   3473  *      SOC_E_NONE
   3474  */
   3475 STATIC int
   3476 phy_84756_fcmap_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   3477 {
   3478 
   3479     /* 40G INTF set */
   3480     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   3481         PHY_INTERFACE_SET(PHY84756_40G, unit, port, pif));
   3482 
   3483     SOC_IF_ERROR_RETURN(
   3484         phy_null_interface_set(unit, port, pif));
   3485 
   3486     return SOC_E_NONE;
   3487 } 
   3488 
   3489 /*
   3490  * Function:
   3491  *      phy_84756_fcmap_interface_get
   3492  * Purpose:
   3493  *      Get interface on a given port.
   3494  * Parameters:
   3495  *      unit  - StrataSwitch unit #.
   3496  *      port  - StrataSwitch port #.
   3497  *      pif   - Interface.
   3498  * Returns:
   3499  *      SOC_E_NONE
   3500  */
   3501 STATIC int
   3502 phy_84756_fcmap_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   3503 {
   3504     int speed = 0;
   3505 
   3506     /* 40G INTF get */
   3507     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   3508         PHY_INTERFACE_GET(PHY84756_40G, unit, port, pif));
   3509 
   3510     SOC_IF_ERROR_RETURN(
   3511        phy_84756_fcmap_speed_get(unit, port, &speed));
   3512 
   3513     *pif = (speed > 0 && speed <= 1000) ? SOC_PORT_IF_SGMII : SOC_PORT_IF_XFI;
   3514     return SOC_E_NONE;
   3515 } 
   3516 
   3517 /*
   3518  * Function:
   3519  *      phy_84756_precondition_before_probe
   3520  * Purpose:
   3521  *      When the device is in 40G, ie. after a power reset, and the 10G 
   3522  *      port being probed does not have the 40G address in PRTAD, the 
   3523  *      device will not respond until the port that has the 40G address
   3524  *      is probed. To avoid not programming ports correctly, make
   3525  *      sure the device is in quad (4x10G) PMD mode when the SDK port is 10G.
   3526  * Parameters:
   3527  *      unit - StrataSwitch unit #.
   3528  *      pc   - phy ctrl descriptor.
   3529  * Returns:
   3530  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   3531  */
   3532 
   3533 STATIC int
   3534 phy_84756_precondition_before_probe(int unit, phy_ctrl_t *pc)
   3535 {
   3536     int ids;
   3537     int rv = SOC_E_NOT_FOUND;
   3538     uint16 id0, id1;
   3539     uint16 saved_phy_id;
   3540 
   3541     /* Not required when the port is single PMD */
   3542     if (PHY84756_SINGLE_PORT_MODE(pc)) {
   3543         LOG_INFO(BSL_LS_SOC_PHY,
   3544                  (BSL_META_U(unit,
   3545                              "PMD must not be called when in single PMD\n")));
   3546         return rv;
   3547     }
   3548 
   3549     saved_phy_id = pc->phy_id;
   3550 
   3551     /* Look for first address that responds */
   3552     for (ids = 0; ids < 4; ids++) {
   3553 
   3554         pc->phy_id = (saved_phy_id & ~0x3) + ids;
   3555         LOG_INFO(BSL_LS_SOC_PHY,
   3556                  (BSL_META_U(unit,
   3557                              "Try device with address %x\n"), pc->phy_id));
   3558 
   3559         /* 
   3560          * Make sure the device has the correct dev IDs 
   3561          * Note that this is being called either because the soc probe found
   3562          * the ids or there was an id override. In the later case, the device
   3563          * might not have the 84756 ids so this PMD setup will not be supported
   3564          */
   3565         id0 = 0;
   3566         BFCMAP_RD_PHY84756_SYS_DEV1_PMD_ID0r(pc,  &id0);
   3567         if (id0 != 0x600d) {
   3568             continue;
   3569         }
   3570         id1 = 0;
   3571         BFCMAP_RD_PHY84756_SYS_DEV1_PMD_ID1r(pc,  &id1);
   3572         if ((id1 & 0xffff) != 0x8675) {
   3573             continue;
   3574         }
   3575         SOC_IF_ERROR_RETURN(
   3576             _phy_84741_single_to_quad_mode(unit, pc->port, pc));
   3577         /* Found the address that responds and the device now is in 4x10G */
   3578         rv = SOC_E_NONE;
   3579         break;
   3580     }
   3581 
   3582     pc->phy_id = saved_phy_id;
   3583 
   3584     return rv;
   3585 }
   3586 
   3587 /*
   3588  * Function:
   3589  *      phy_84756_fcmap_probe
   3590  * Purpose:
   3591  *      Complement the generic phy probe routine to identify this phy when its
   3592  *      phy id0 and id1 is same as some other phy's.
   3593  * Parameters:
   3594  *      unit - StrataSwitch unit #.
   3595  *      pc   - phy ctrl descriptor.
   3596  * Returns:
   3597  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   3598  */
   3599 STATIC int
   3600 phy_84756_fcmap_probe(int unit, phy_ctrl_t *pc)
   3601 {
   3602 
   3603 
   3604     pc->size = -1 ;
   3605     PHY_PROBE(PHY84756_40G, unit, pc);
   3606 
   3607     /* Support 40G only for 84741/84744 */
   3608     if (PHY84756_SINGLE_PORT_MODE(pc) && pc->size == 0) {
   3609         return SOC_E_NOT_FOUND;
   3610     }
   3611 
   3612 
   3613 #ifdef INCLUDE_MACSEC
   3614     /* Use of Standalone MACSEC driver is selected by fcmap_enable=0xff */
   3615     if (0xff != soc_property_port_get(unit, pc->port, spn_FCMAP_ENABLE, 0)) {
   3616         LOG_CLI((BSL_META_U(unit,
   3617                             "u=%d p=%d Using SDK PHY driver for BCM84756/7/9\n"),
   3618                  unit, pc->port));
   3619         pc->size += sizeof(phy84756_map_t);
   3620         return SOC_E_NONE;
   3621     }
   3622     return SOC_E_NOT_FOUND;
   3623 #else
   3624     pc->size += sizeof(phy84756_map_t);
   3625     LOG_INFO(BSL_LS_SOC_PHY,
   3626              (BSL_META_U(unit,
   3627                          "u=%d p=%d Using SDK PHY driver for BCM84756/7/9 (no MACSEC support)\n"),
   3628               unit, pc->port));
   3629     return SOC_E_NONE;
   3630 #endif
   3631 }
   3632 
   3633 /*
   3634  * Function:     
   3635  *    _phy84756_phy_get_dev_addr
   3636  * Purpose:    
   3637  *    For a given PHY Device address retrive Device port
   3638  * Parameters:
   3639  *    phy_dev_addr    - PHY Device Address
   3640  *    fcmap_dev_addr - MACSEC core Device Address
   3641  *    dev_port        - (OUT)Port number
   3642  * Notes: 
   3643  */
   3644 STATIC int
   3645 _phy84756_phy_get_dev_addr(phy_ctrl_t *pc, 
   3646                           blmi_dev_addr_t *fcmap_dev_addr, int *dev_port)
   3647 {
   3648     if (dev_port) {
   3649 #if defined(INCLUDE_MACSEC)
   3650         if (pc->macsec_enable) {
   3651             *dev_port = pc->macsec_dev_port;
   3652         } else
   3653 #endif
   3654 #if defined(INCLUDE_FCMAP)
   3655         if (pc->fcmap_enable) {
   3656             *dev_port = pc->fcmap_dev_port;
   3657         } else
   3658 #endif
   3659         {
   3660 #if defined(INCLUDE_FCMAP)
   3661             *dev_port = pc->fcmap_dev_port;
   3662 #endif
   3663 #if defined(INCLUDE_MACSEC)
   3664             *dev_port = pc->macsec_dev_port;
   3665 #endif
   3666         }
   3667     }
   3668     if (fcmap_dev_addr) {
   3669 #if defined(INCLUDE_MACSEC)
   3670         if (pc->macsec_enable) {
   3671             *fcmap_dev_addr = pc->macsec_dev_addr;
   3672         } else
   3673 #endif
   3674 #if defined(INCLUDE_FCMAP)
   3675         if (pc->fcmap_enable) {
   3676             *fcmap_dev_addr = pc->fcmap_dev_addr;
   3677         } else
   3678 #endif
   3679         {
   3680 #if defined(INCLUDE_FCMAP)
   3681             *fcmap_dev_addr = pc->fcmap_dev_addr;
   3682 #endif
   3683 #if defined(INCLUDE_MACSEC)
   3684             *fcmap_dev_addr = pc->macsec_dev_addr;
   3685 #endif
   3686         }
   3687     }
   3688     return SOC_E_NONE;
   3689 }
   3690 
   3691 /*
   3692  * Function:     
   3693  *    _phy84756_get_model_rev
   3694  * Purpose:    
   3695  *    Get OUI, Model and Revision of the PHY
   3696  * Parameters:
   3697  *    phy_dev_addr - PHY Device Address
   3698  *    oui          - (OUT) Organization Unique Identifier
   3699  *    model        - (OUT)Device Model number`
   3700  *    rev          - (OUT)Device Revision number
   3701  * Notes: 
   3702  */
   3703 int 
   3704 _phy84756_get_model_rev(phy_ctrl_t *pc,
   3705                        int *oui, int *model, int *rev)
   3706 {
   3707     buint16_t  id0, id1;
   3708 
   3709     SOC_IF_ERROR_RETURN
   3710             (BFCMAP_RD_PHY84756_LN_DEV1_PMD_ID0r(pc, &id0));
   3711 
   3712     SOC_IF_ERROR_RETURN
   3713             (BFCMAP_RD_PHY84756_LN_DEV1_PMD_ID1r(pc, &id1));
   3714 
   3715     *oui   = BFCMAP_PHY84756_PHY_OUI(id0, id1);
   3716     *model = BFCMAP_PHY84756_PHY_MODEL(id0, id1);
   3717     *rev   = BFCMAP_PHY84756_PHY_REV(id0, id1);
   3718 
   3719     return SOC_E_NONE;
   3720 }
   3721 
   3722 
   3723 
   3724 /*
   3725  * Function:
   3726  *     bfcmap_phy84756_firmware_spi_download
   3727  * Purpose:
   3728  *     Download firmware via SPI
   3729  *         - Check if firmware download is complete
   3730  *         - Check if the checksum is good
   3731  * Parameters:
   3732  *    phy_id    - PHY Device Address
   3733  * Returns:
   3734  */
   3735 /* STATIC int */
   3736 int
   3737 bfcmap_phy84756_firmware_spi_download(phy_ctrl_t *pc)
   3738 {
   3739     buint16_t data = 0;
   3740     int i;
   3741 
   3742     LOG_INFO(BSL_LS_SOC_PHY,
   3743              (BSL_META_U(pc->unit,
   3744                          "PHY84756: SPI-ROM firmware download start: u=%d p=%d\n"),
   3745               pc->unit, pc->port));
   3746 
   3747     /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */
   3748     /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */
   3749     SOC_IF_ERROR_RETURN(
   3750            BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc848, 
   3751                (1 << 15)|(1 << 14), 
   3752                ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 2))));
   3753 
   3754     /* apply software reset to download code from SPI-ROM */
   3755     /* Reset the PHY **/
   3756     SOC_IF_ERROR_RETURN(
   3757            BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 
   3758                BFCMAP_PHY84756_PMD_CTRL_RESET, BFCMAP_PHY84756_PMD_CTRL_RESET));
   3759 
   3760     for (i = 0; i < 5; i++) {
   3761         sal_usleep(100000);
   3762         SOC_IF_ERROR_RETURN(
   3763                BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc848, &data));
   3764         if (data & 0x2000) {  /* Check for download complete */
   3765             /* Need to check if checksum is correct */
   3766             SOC_IF_ERROR_RETURN(
   3767                    BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xca1c, &data));
   3768             if (data == 0x600D) {
   3769                 break;
   3770             }
   3771         }
   3772     }
   3773     if (i >= 5) { /* Bad CHECKSUM */
   3774         LOG_CLI((BSL_META_U(pc->unit,
   3775                             "SPI-Download Firmware download failure:"
   3776                             "Incorrect Checksum %x\n"), data));
   3777         return SOC_E_FAIL;
   3778     }
   3779 
   3780     SOC_IF_ERROR_RETURN(
   3781            BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xca1a, &data));
   3782 
   3783     LOG_CLI((BSL_META_U(pc->unit,
   3784                         "BCM84756: SPI-ROM download complete: version: 0x%x\n"), data));
   3785 
   3786     return SOC_E_NONE;
   3787 }
   3788 
   3789 
   3790 /*
   3791  * Function:     
   3792  *    bfcmap_phy84756_phy_mac_driver_attach
   3793  * Purpose:    
   3794  *    Add Mapping of PHY device address, Device port
   3795  * Parameters:
   3796  *    phy_dev_addr    - PHY Device Address
   3797  *    dev_port        - Port number
   3798  * Notes: 
   3799  */
   3800 int 
   3801 bfcmap_phy84756_phy_mac_driver_attach(phy_ctrl_t *pc,
   3802                                  blmi_dev_addr_t fcmap_dev_addr,
   3803                                  int dev_port, blmi_dev_io_f mmi_cbf)
   3804 {
   3805     phy84756_map_t *phy84756_map;
   3806     uint32      mac_config_flag = 0;
   3807 
   3808     /* Delete the mapping if already present */
   3809     (void)bfcmap_phy84756_phy_mac_driver_detach(pc);
   3810 
   3811     phy84756_map = PHY84756_PHY_INFO(pc);
   3812 
   3813     if (phy84756_map == NULL) {
   3814         return SOC_E_RESOURCE;
   3815     }
   3816 
   3817     /* Alloc unimac driver and attach */
   3818     phy84756_map->unimac = 
   3819             phy_mac_driver_attach(fcmap_dev_addr, 
   3820                                      PHY_MAC_CORE_UNIMAC, mmi_cbf);
   3821     if (!phy84756_map->unimac) {
   3822         bfcmap_phy84756_phy_mac_driver_detach(pc);
   3823         return SOC_E_INTERNAL;
   3824     }
   3825 
   3826     phy84756_map->xmac = 
   3827             phy_mac_driver_attach(fcmap_dev_addr, 
   3828                                      PHY_MAC_CORE_XMAC, mmi_cbf);
   3829     if (!phy84756_map->xmac) {
   3830         bfcmap_phy84756_phy_mac_driver_detach(pc);
   3831         return SOC_E_INTERNAL;
   3832     }
   3833 
   3834 
   3835     if (CHIP_IS_C0(pc)) {
   3836         mac_config_flag |= PHY_MAC_CTRL_FLAG_XMAC_V2;
   3837     }
   3838 
   3839     if(mac_config_flag) { 
   3840         phy_mac_driver_config(phy84756_map->xmac,
   3841                              PHY_MAC_CORE_XMAC,
   3842                              mac_config_flag);
   3843     }
   3844 
   3845     return SOC_E_NONE;
   3846 }
   3847 
   3848 
   3849 
   3850 /*
   3851  * Function:     
   3852  *    bfcmap_phy84756_phy_mac_driver_detach
   3853  * Purpose:    
   3854  *    Delete Mapping of PHY device address and Device port
   3855  * Parameters:
   3856  *    phy_dev_addr    - PHY Device Address
   3857  * Notes: 
   3858  */
   3859 int 
   3860 bfcmap_phy84756_phy_mac_driver_detach(phy_ctrl_t     *pc)
   3861 {
   3862     phy84756_map_t *this;
   3863     int rv = SOC_E_NONE;
   3864 
   3865     this = PHY84756_PHY_INFO(pc);
   3866     if (this->unimac) {
   3867         phy_mac_driver_detach(this->unimac);
   3868         this->unimac = NULL;
   3869     }
   3870     if (this->xmac) {
   3871         phy_mac_driver_detach(this->xmac);
   3872         this->xmac = NULL;
   3873     }
   3874     return rv;
   3875 }
   3876 
   3877 
   3878 /*
   3879  * Function:     
   3880  *    bfcmap_phy84756_line_intf_get
   3881  * Purpose:    
   3882  *    Determine the Line side Interface
   3883  * Parameters:
   3884  *    phy_id    - PHY's device address
   3885  *    dev_port  - Channel number 
   3886  *    mode      - (OUT) Line Port mode status
   3887  * Returns:    
   3888  */
   3889 int 
   3890 bfcmap_phy84756_line_intf_get(phy_ctrl_t *pc, int dev_port, 
   3891                               bfcmap_phy84756_intf_t *mode)
   3892 {
   3893 
   3894     phy84756_map_t      *phy_info;
   3895 
   3896     if (mode == NULL) {
   3897         return SOC_E_PARAM;
   3898     }
   3899 
   3900     phy_info = PHY84756_PHY_INFO(pc);
   3901 
   3902     *mode = phy_info->line_mode;
   3903     return SOC_E_NONE;
   3904 }
   3905 
   3906 
   3907 
   3908 /*
   3909  * Function:     
   3910  *    bfcmap_phy84756_line_mode_set
   3911  * Purpose:    
   3912  *    Set the Line side mode
   3913  * Parameters:
   3914  *    phy_id    - PHY's device address
   3915  *    dev_port  - Channel number 
   3916  *    mode      - Desired mode (SGMII/1000x/SFI)
   3917  * Returns:    
   3918  */
   3919 int
   3920 bfcmap_phy84756_line_mode_set(phy_ctrl_t *pc, int dev_port, 
   3921                               bfcmap_phy84756_intf_t mode)
   3922 {
   3923 
   3924     int rv = SOC_E_NONE;
   3925     phy84756_map_t      *phy_info;
   3926 
   3927     phy_info = PHY84756_PHY_INFO(pc);
   3928 
   3929     /* Disable Autodetect */
   3930     SOC_IF_ERROR_RETURN(
   3931         BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 0,
   3932                        BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_AUTODETECT_EN));
   3933     switch (mode) {
   3934 
   3935     case BFCMAP_PHY84756_INTF_SGMII :
   3936 
   3937         SOC_IF_ERROR_RETURN(
   3938             BFCMAP_PHY84756_REG_WR(pc, 0x00, 0x0007, 0x8300, 0x0184));
   3939         SOC_IF_ERROR_RETURN(
   3940             BFCMAP_PHY84756_REG_WR(pc, 0x00, 0x0007, 0x8308, 0x0000));
   3941         SOC_IF_ERROR_RETURN(
   3942             BFCMAP_PHY84756_REG_MOD(pc, 0x00, 0x0007, 0x8309, 0x6000, 0x6020));
   3943         SOC_IF_ERROR_RETURN(
   3944             BFCMAP_PHY84756_REG_WR(pc, 0x00, 0x0007, 0x835c, 0x0801));
   3945         SOC_IF_ERROR_RETURN(
   3946             BFCMAP_PHY84756_REG_WR(pc, 0x00, 0x0007, 0xffe0, 0x1140));
   3947 
   3948         break;
   3949         
   3950     case BFCMAP_PHY84756_INTF_1000X :
   3951         SOC_IF_ERROR_RETURN(
   3952             BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 1,
   3953                      BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_FIBER_MODE));
   3954         break;
   3955 
   3956     case BFCMAP_PHY84756_INTF_SFI :
   3957         SOC_IF_ERROR_RETURN(
   3958             BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 1,
   3959                      BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_FIBER_MODE));
   3960         /* Set PMA type */
   3961         SOC_IF_ERROR_RETURN(
   3962             BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRL2r(pc, 0x8, 0x003f));
   3963         break;
   3964 
   3965     case BFCMAP_PHY84756_INTF_XFI :
   3966     default :
   3967         rv = SOC_E_PARAM;
   3968         break;
   3969         
   3970     }
   3971 
   3972     if (SOC_SUCCESS(rv)) {
   3973         phy_info->line_mode = mode;
   3974     }
   3975     return rv;
   3976 }
   3977 
   3978 
   3979 /*
   3980  * Function:     
   3981  *    bfcmap_phy84756_sys_intf_get
   3982  * Purpose:    
   3983  *    Determine the System side Interface
   3984  * Parameters:
   3985  *    phy_id    - PHY's device address
   3986  *    dev_port  - Channel number 
   3987  *    mode      - (OUT) System side mode status
   3988  * Returns:    
   3989  */
   3990 int 
   3991 bfcmap_phy84756_sys_intf_get(phy_ctrl_t *pc, int dev_port, 
   3992                              bfcmap_phy84756_intf_t *mode)
   3993 {
   3994 
   3995     phy84756_map_t      *phy_info;
   3996 
   3997     if (mode == NULL) {
   3998         return SOC_E_PARAM;
   3999     }
   4000 
   4001     phy_info = PHY84756_PHY_INFO(pc);
   4002 
   4003     /* System will always follow line side interface */
   4004     *mode = phy_info->line_mode;
   4005 
   4006     return SOC_E_NONE;
   4007 }
   4008 
   4009 
   4010 
   4011 /*
   4012  * Function:     
   4013  *    bfcmap_phy84756_sys_mode_set
   4014  * Purpose:    
   4015  *    Set the system side mode
   4016  * Parameters:
   4017  *    phy_id    - PHY's device address
   4018  *    dev_port  - Channel number 
   4019  *    mode      - Desired mode (SGMII/1000x/XFI)
   4020  * Returns:    
   4021  */
   4022 int
   4023 bfcmap_phy84756_sys_mode_set(phy_ctrl_t *pc, int dev_port, 
   4024                               bfcmap_phy84756_intf_t mode)
   4025 {
   4026     int rv = SOC_E_NONE;
   4027 
   4028     /* Disable Autodetect */
   4029     SOC_IF_ERROR_RETURN(
   4030         BFCMAP_MOD_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 0,
   4031                        BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_AUTODETECT_EN));
   4032     switch (mode) {
   4033     case BFCMAP_PHY84756_INTF_SGMII :
   4034         SOC_IF_ERROR_RETURN(
   4035             _bfcmap_phy84756_system_sgmii_init(pc, dev_port));
   4036         break;
   4037         
   4038     case BFCMAP_PHY84756_INTF_1000X :
   4039         SOC_IF_ERROR_RETURN(
   4040             BFCMAP_MOD_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 1,
   4041                      BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_FIBER_MODE));
   4042         break;
   4043     case BFCMAP_PHY84756_INTF_XFI :
   4044         break;
   4045 
   4046     case BFCMAP_PHY84756_INTF_XAUI :
   4047         SOC_IF_ERROR_RETURN(
   4048             BFCMAP_MOD_PHY84756_XGXS_DEV7_AN_BASE1000X_CTRL1r(pc, 1,
   4049                      BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_FIBER_MODE));
   4050         /* Set PMA type */
   4051         SOC_IF_ERROR_RETURN(
   4052             BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRL2r(pc, 0x8,
   4053                      0x000f));
   4054         break;
   4055     case BFCMAP_PHY84756_INTF_SFI :
   4056     default :
   4057         rv = SOC_E_PARAM;
   4058         break;
   4059     }
   4060 
   4061     return rv;
   4062 }
   4063 
   4064 
   4065 #if defined(INCLUDE_FCMAP) || defined(INCLUDE_MACSEC)
   4066 #define  BIT_MASK_07            (1U << 7)
   4067 
   4068 STATIC int
   4069 bfcmap_phy84756_macsec_enable(phy_ctrl_t *pc)
   4070 {
   4071     buint16_t data;
   4072 
   4073     SOC_IF_ERROR_RETURN( BFCMAP_WR_PHY84756_SGMII_DEV1_MACSEC_BYPASS_CTRLr(pc, 0x0000) );
   4074 
   4075     /* Set to TX active to make macsec registers (xmac) accessible */
   4076     SOC_IF_ERROR_RETURN( BFCMAP_PHY84756_REG_RD(pc, 0x00, 0x01, 0xc8e4, &data) );
   4077     /* check if TX inactive */
   4078     if ( data & 0x0010 ) {
   4079         /* disable OPTXENB until the port is explicitly enabled */
   4080         SOC_IF_ERROR_RETURN(
   4081 	        BFCMAP_MOD_PHY84756_LN_DEV1_PMD_XMIT_DISABLEr(pc, 1, 0x0001) );
   4082 		    
   4083         /* Toggle 1.0xc800.7 to become TX active */
   4084         SOC_IF_ERROR_RETURN( BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc800, &data) );
   4085         data ^= BIT_MASK_07;      /* toggle bit[7] */
   4086         SOC_IF_ERROR_RETURN( BFCMAP_PHY84756_REG_WR(pc, 00, 0x1, 0xc800,  data) );
   4087     }
   4088 
   4089     return SOC_E_PARAM;
   4090 }
   4091 #endif
   4092 
   4093 /*
   4094  * Function:     
   4095  *    bfcmap_phy84756_no_reset_setup
   4096  * Purpose:    
   4097  *    Initialize the PHY without reset.
   4098  * Parameters:
   4099  *    phy_dev_addr        - PHY Device Address
   4100  *    line_mode           - Line side Mode (SGMII/1000X/SFI).
   4101  *    fcmap_enable        - Fibre Channel enabled or disabled.
   4102  * Notes: 
   4103  */
   4104 int
   4105 bfcmap_phy84756_no_reset_setup(phy_ctrl_t *pc, int line_mode,
   4106                                int phy_ext_boot)
   4107 {
   4108     int dev_port;
   4109     int port;
   4110     phy84756_map_t      *phy_info;
   4111 #ifdef INCLUDE_FCMAP
   4112     buint16_t val = 0xDEAD;
   4113 #endif
   4114     buint16_t data;
   4115 
   4116     if (_phy84756_phy_get_dev_addr(pc, NULL,
   4117                                   &dev_port) != SOC_E_NONE) {
   4118         return SOC_E_CONFIG;
   4119     }
   4120 
   4121     phy_info = PHY84756_PHY_INFO(pc);
   4122 
   4123     if ((line_mode != BFCMAP_PHY84756_INTF_SGMII) &&
   4124         (line_mode != BFCMAP_PHY84756_INTF_1000X) && 
   4125         (line_mode != BFCMAP_PHY84756_INTF_SFI)) {
   4126         return SOC_E_CONFIG;
   4127     }
   4128 
   4129     /* Enable Power - PMA/PMD, PCS, AN */
   4130     SOC_IF_ERROR_RETURN(
   4131          BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 0,
   4132                                         BFCMAP_PHY84756_PMD_CTRL_PD));
   4133     SOC_IF_ERROR_RETURN(
   4134         BFCMAP_MOD_PHY84756_LN_DEV3_PCS_CTRLr(pc, 0,
   4135                                        BFCMAP_PHY84756_PCS_PCS_CTRL_PD));
   4136     SOC_IF_ERROR_RETURN(
   4137         BFCMAP_MOD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, 0,
   4138                                        BFCMAP_PHY84756_AN_MII_CTRL_PD));
   4139     if (phy_ext_boot) {
   4140         if (!PHY84756_IS_8474X(pc) && (!SKIP_EDC_FW_DOWNLOAD(pc))) {
   4141             /* Download firmware via SPI */
   4142             SOC_IF_ERROR_RETURN(bfcmap_phy84756_firmware_spi_download(pc));
   4143         }
   4144     }  else if (!(pc->flags & PHYCTRL_MDIO_BCST) && (!SKIP_EDC_FW_DOWNLOAD(pc))) {
   4145         /* MDIO based firmware download to RAM */
   4146         SOC_IF_ERROR_RETURN(
   4147             bfcmap_phy84756_mdio_firmware_download(pc,
   4148                                 FIRMWARE(pc),  FIRMWARE_LEN(pc)));
   4149     } 
   4150 
   4151     if ((!soc_property_port_get(pc->unit, pc->port, spn_FCMAP_ENABLE, 0)) &&
   4152         (!soc_property_port_get(pc->unit, pc->port, spn_MACSEC_ENABLE, 0))) {
   4153         /* Set Line mode */
   4154         SOC_IF_ERROR_RETURN(
   4155             bfcmap_phy84756_line_mode_set(pc, 0, line_mode));
   4156 
   4157         /* Disable MACSEC */
   4158         SOC_IF_ERROR_RETURN(
   4159             BFCMAP_RD_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, &data));
   4160 
   4161         data &= ~(BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_BYPASS_MODE |
   4162                   BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_ENABLE_PWRDN_MACSEC |
   4163                   BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_PWRDW_MACSEC |
   4164                   BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_RESET_MACSEC);
   4165 
   4166         data |= BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_BYPASS_MODE;
   4167         /* Power down MACSEC to reduce power consumption */
   4168         data |= BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_ENABLE_PWRDN_MACSEC;
   4169         data |= BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_PWRDW_MACSEC;
   4170 
   4171         SOC_IF_ERROR_RETURN(
   4172             BFCMAP_WR_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, data));
   4173 
   4174         /* System side mode */
   4175         if (line_mode == BFCMAP_PHY84756_INTF_SFI) {
   4176             phy_info->line_mode = BFCMAP_PHY84756_INTF_SFI;
   4177             SOC_IF_ERROR_RETURN(
   4178                 bfcmap_phy84756_sys_mode_set(pc, 0, 
   4179                                      BFCMAP_PHY84756_INTF_XFI));
   4180             /* Force Speed to 10G */
   4181             SOC_IF_ERROR_RETURN(
   4182                 _phy84756_system_xfi_speed_set(pc, 0, 10000));
   4183             SOC_IF_ERROR_RETURN(
   4184                 bfcmap_phy84756_speed_set(pc, 10000));
   4185         } else {
   4186             if (line_mode == BFCMAP_PHY84756_INTF_1000X) {
   4187                 phy_info->line_mode = BFCMAP_PHY84756_INTF_1000X;
   4188                 SOC_IF_ERROR_RETURN(
   4189                     bfcmap_phy84756_sys_mode_set(pc, 0, 
   4190                                          BFCMAP_PHY84756_INTF_1000X));
   4191                 /* Force Speed to 1G */
   4192                 SOC_IF_ERROR_RETURN(
   4193                     bfcmap_phy84756_speed_set(pc, 1000));
   4194             } else { /* SGMII MODE */
   4195                 phy_info->line_mode = BFCMAP_PHY84756_INTF_SGMII;
   4196                 SOC_IF_ERROR_RETURN(
   4197                     bfcmap_phy84756_sys_mode_set(pc, 0, 
   4198                                          BFCMAP_PHY84756_INTF_SGMII));
   4199             }
   4200         }
   4201     } else {
   4202         if (soc_property_port_get(pc->unit, pc->port, spn_FCMAP_ENABLE, 0)) { 
   4203 #ifdef INCLUDE_FCMAP
   4204             /* FCMAP enable */
   4205             sal_usleep(10000);
   4206             /* Enable FC */
   4207             SOC_IF_ERROR_RETURN(
   4208                 BFCMAP_RD_PHY84756_LN_DEV1_CHIP_MODEr(pc, &data));
   4209             data &= ~0x3;
   4210             data |= 0x2;
   4211             SOC_IF_ERROR_RETURN(
   4212                 BFCMAP_WR_PHY84756_LN_DEV1_CHIP_MODEr(pc, data));
   4213 
   4214             sal_usleep(100000); /* need 100ms delay */
   4215 
   4216             /* Enable MACSEC */
   4217             SOC_IF_ERROR_RETURN( bfcmap_phy84756_macsec_enable(pc) );
   4218 
   4219             SOC_IF_ERROR_RETURN(
   4220                 BFCMAP_PHY84756_REG_WR(pc, 0, 1, 0xcd58, 0x300));
   4221             sal_usleep(30);
   4222             SOC_IF_ERROR_RETURN(
   4223                 BFCMAP_PHY84756_REG_WR(pc, 0, 1, 0xcd53, 0));
   4224 
   4225             SOC_IF_ERROR_RETURN(
   4226                 BFCMAP_PHY84756_REG_RD(pc, 0, 1, 0xcd53, &val));
   4227 
   4228             /* Set Line mode */
   4229             SOC_IF_ERROR_RETURN(
   4230                 bfcmap_phy84756_line_mode_set(pc, 0,
   4231                                             BFCMAP_PHY84756_INTF_SFI));
   4232 
   4233             /* System side mode */
   4234             SOC_IF_ERROR_RETURN(
   4235                bfcmap_phy84756_sys_mode_set(pc, 0, 
   4236                                             BFCMAP_PHY84756_INTF_XFI));
   4237             /* Force Speed to 10G */
   4238             SOC_IF_ERROR_RETURN(
   4239                 _phy84756_system_xfi_speed_set(pc, 0, 10000));
   4240 
   4241 
   4242             /* Initialize the switch side XMAC */
   4243             port = BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port);
   4244             SOC_IF_ERROR_RETURN(
   4245                 phy_xmac_mac_fcmap_init(phy_info->xmac, port));
   4246 #endif
   4247 
   4248         } else {
   4249             if (soc_property_port_get(pc->unit, pc->port, spn_MACSEC_ENABLE, 0)) { 
   4250 #ifdef INCLUDE_MACSEC
   4251                 /* Set Line mode */
   4252                 SOC_IF_ERROR_RETURN(
   4253                     bfcmap_phy84756_line_mode_set(pc, 0, line_mode));
   4254 
   4255                 /* System side mode */
   4256                 if (line_mode == BFCMAP_PHY84756_INTF_SFI) {
   4257                     phy_info->line_mode = BFCMAP_PHY84756_INTF_SFI;
   4258                     SOC_IF_ERROR_RETURN(
   4259                         bfcmap_phy84756_sys_mode_set(pc, 0, 
   4260                                              BFCMAP_PHY84756_INTF_XFI));
   4261                     /* Force Speed to 10G */
   4262                     SOC_IF_ERROR_RETURN(
   4263                         _phy84756_system_xfi_speed_set(pc, 0, 10000));
   4264                     SOC_IF_ERROR_RETURN(
   4265                         bfcmap_phy84756_speed_set(pc, 10000));
   4266                 } else {
   4267                     if (line_mode == BFCMAP_PHY84756_INTF_1000X) {
   4268                         phy_info->line_mode = BFCMAP_PHY84756_INTF_1000X;
   4269                         SOC_IF_ERROR_RETURN(
   4270                             bfcmap_phy84756_sys_mode_set(pc, 0, 
   4271                                                  BFCMAP_PHY84756_INTF_1000X));
   4272                         /* Force Speed to 1G */
   4273                         SOC_IF_ERROR_RETURN(
   4274                             bfcmap_phy84756_speed_set(pc, 1000));
   4275                     } else { /* SGMII MODE */
   4276                         phy_info->line_mode = BFCMAP_PHY84756_INTF_SGMII;
   4277                         SOC_IF_ERROR_RETURN(
   4278                             bfcmap_phy84756_sys_mode_set(pc, 0, 
   4279                                                  BFCMAP_PHY84756_INTF_SGMII));
   4280                     }
   4281                 }
   4282 
   4283                 /* Enable MACSEC */
   4284                 SOC_IF_ERROR_RETURN( bfcmap_phy84756_macsec_enable(pc) );
   4285 
   4286                 /* 
   4287                  * Set defaults to Line and Swithc side MAC
   4288                  * MTU = 0x3fff
   4289                  * IPG = 12Bytes
   4290                  * Auto Config Mode Enabled
   4291                  */
   4292                 /* Initialize the Line side MAC */
   4293                 port = BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port);
   4294                 SOC_IF_ERROR_RETURN(
   4295                     BMACSEC_MAC_INIT(phy_info->xmac, port));
   4296 
   4297                 /* Initialize the Line side MAC */
   4298                 port = BFCMAP_PHY84756_LINE_MAC_PORT(dev_port);
   4299                 SOC_IF_ERROR_RETURN(
   4300                     BMACSEC_MAC_INIT(phy_info->xmac, port));
   4301 
   4302                 /* Initialize the Line side MAC */
   4303                 port = BFCMAP_PHY84756_LINE_MAC_PORT(dev_port);
   4304                 SOC_IF_ERROR_RETURN(
   4305                     BMACSEC_MAC_INIT(phy_info->unimac, port));
   4306 
   4307                 /* Initialize the Line side MAC */
   4308                 port = BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port);
   4309                 SOC_IF_ERROR_RETURN(
   4310                     BMACSEC_MAC_INIT(phy_info->unimac, port));
   4311 #endif
   4312             }
   4313         }
   4314     }
   4315     return SOC_E_NONE;
   4316 }
   4317 
   4318 STATIC int
   4319 phy_84756_fcmap_xmac_rx_enable_set(int unit, int port, int side, int enable)
   4320 {
   4321     phy_ctrl_t     *pc;
   4322     phy84756_map_t *phy_info;
   4323 
   4324     pc = EXT_PHY_SW_STATE(unit, port);
   4325     phy_info = PHY84756_PHY_INFO(pc);
   4326     return  BMACSEC_MAC_RX_ENABLE_SET(phy_info->xmac, side, enable);
   4327 }
   4328 
   4329 STATIC int
   4330 phy_84756_fcmap_rx_enable_set(int unit, soc_port_t port, int side, int enable)
   4331 {
   4332 	return  phy_84756_fcmap_xmac_rx_enable_set(unit, port, side, enable);
   4333 }
   4334 
   4335 STATIC int
   4336 phy_84756_macsec_enable(int unit, int lport, int enable)
   4337 {
   4338 	phy_ctrl_t     *pc;
   4339 	phy84756_map_t *phy_info;
   4340 	buint16_t       data = 0;
   4341 	int             dev_port = 0;
   4342 
   4343     EXT_PHY_INIT_CHECK(unit, lport);
   4344 	pc = EXT_PHY_SW_STATE(unit, lport);
   4345 	if ( _phy84756_phy_get_dev_addr(pc, NULL, &dev_port) != SOC_E_NONE ) {
   4346 		return SOC_E_CONFIG;
   4347 	}
   4348 	phy_info = PHY84756_PHY_INFO(pc);
   4349 
   4350 	if ( enable ) {      /* Enable MACSEC */
   4351         SOC_IF_ERROR_RETURN(
   4352                 BFCMAP_WR_PHY84756_SGMII_DEV1_MACSEC_BYPASS_CTRLr(pc, 0x8000) );
   4353         sal_udelay(5); /* Wait for 5 us */
   4354         SOC_IF_ERROR_RETURN(
   4355                 BFCMAP_WR_PHY84756_SGMII_DEV1_MACSEC_BYPASS_CTRLr(pc, 0x0000) );
   4356 
   4357         /* Set defaults to Line and Swithc side MAC                 *\
   4358         \* MTU = 0x3fff , IPG = 12Bytes , Auto Config Mode Enabled  */
   4359 
   4360         /* Initialize the System side  XMAC   */
   4361         SOC_IF_ERROR_RETURN( BMACSEC_MAC_INIT(phy_info->xmac  ,
   4362                                    BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port)) );
   4363         /* Initialize the  Line  side  XMAC   */
   4364         SOC_IF_ERROR_RETURN( BMACSEC_MAC_INIT(phy_info->xmac  ,
   4365                                    BFCMAP_PHY84756_LINE_MAC_PORT(  dev_port)) );
   4366 
   4367         /* Initialize the  Line  side  UNIMAC */
   4368         SOC_IF_ERROR_RETURN( BMACSEC_MAC_INIT(phy_info->unimac,
   4369                                    BFCMAP_PHY84756_LINE_MAC_PORT(  dev_port)) );
   4370         /* Initialize the System side  UNIMAC */
   4371         SOC_IF_ERROR_RETURN( BMACSEC_MAC_INIT(phy_info->unimac,
   4372                                    BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port)) );
   4373 #if defined(INCLUDE_MACSEC)
   4374         SOC_IF_ERROR_RETURN(
   4375                 soc_macsecphy_init(unit, lport, pc,
   4376                                    (CHIP_IS_C0(pc)) ? BMACSEC_CORE_BCM84756_C0
   4377                                                     : BMACSEC_CORE_BCM84756,
   4378                                    bmacsec_io_mmi1_cl45) );
   4379 #endif
   4380     } else {      /* disable MACSEC */
   4381         SOC_IF_ERROR_RETURN(
   4382                 BFCMAP_RD_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, &data) );
   4383         data &= ~BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_RESET_MACSEC;
   4384         /* Power down MACSEC to reduce power consumption */
   4385         data |= (BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_BYPASS_MODE         |
   4386                  BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_ENABLE_PWRDN_MACSEC |
   4387                  BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_PWRDW_MACSEC);
   4388         SOC_IF_ERROR_RETURN(
   4389                 BFCMAP_WR_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc,  data) );
   4390 	}
   4391 
   4392     return SOC_E_NONE;
   4393 }
   4394 
   4395 
   4396 
   4397 /*
   4398  * Function:     
   4399  *    bfcmap_phy84756_reset 
   4400  * Purpose:    
   4401  *    Reset the PHY.
   4402  * Parameters:
   4403  *    phy_id - PHY Device Address of the PHY to reset
   4404  */
   4405 int 
   4406 bfcmap_phy84756_reset(phy_ctrl_t *pc)
   4407 {
   4408     buint16_t ctrl = 0;
   4409     buint16_t tmp  = 0;
   4410 
   4411 
   4412     /* Reset the PHY **/
   4413     SOC_IF_ERROR_RETURN(
   4414         BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRLr(pc, &ctrl));
   4415 
   4416     SOC_IF_ERROR_RETURN(
   4417         BFCMAP_WR_PHY84756_LN_DEV1_PMD_CTRLr(pc, 
   4418                                (ctrl | BFCMAP_PHY84756_PMD_CTRL_RESET)));
   4419     /* Needs minimum of 5us to complete the reset */
   4420     sal_usleep(30);
   4421 
   4422     SOC_IF_ERROR_RETURN(
   4423         BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRLr(pc, &tmp));
   4424 
   4425     if ((tmp & BFCMAP_PHY84756_PMD_CTRL_RESET) != 0) {
   4426         SOC_IF_ERROR_RETURN
   4427             (BFCMAP_WR_PHY84756_LN_DEV1_PMD_CTRLr(pc, ctrl));
   4428         return SOC_E_FAIL;
   4429     }
   4430 
   4431     return SOC_E_NONE;
   4432 }
   4433 
   4434 
   4435 /*
   4436  * Function:     
   4437  *    bfcmap_phy84756_speed_set
   4438  * Purpose:    
   4439  *    To set the PHY's speed  
   4440  * Parameters:
   4441  *    phy_id    - PHY's device address
   4442  *    speed     - Speed to set
   4443  *               10   = 10Mbps
   4444  *               100  = 100Mbps
   4445  *               1000 = 1000Mbps
   4446  * Returns:    
   4447  */
   4448 int
   4449 bfcmap_phy84756_speed_set(phy_ctrl_t *pc, int speed)
   4450 {
   4451     int value = 0;
   4452     bfcmap_phy84756_intf_t line_mode;
   4453 
   4454     if ((speed != 10) && (speed != 100) && 
   4455          (speed != 1000) && (speed != 10000)) {
   4456         return SOC_E_NONE;
   4457     }
   4458 
   4459     SOC_IF_ERROR_RETURN(
   4460         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   4461 
   4462     switch (line_mode) {
   4463     case BFCMAP_PHY84756_INTF_SFI:
   4464     case BFCMAP_PHY84756_INTF_1000X:
   4465         /* Disable Clause 37 Autoneg */
   4466         SOC_IF_ERROR_RETURN(
   4467             BFCMAP_MOD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, 0x0000,
   4468                                    0x3040));
   4469         SOC_IF_ERROR_RETURN(
   4470             BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 1,
   4471                                    1));
   4472         SOC_IF_ERROR_RETURN(
   4473             BFCMAP_MOD_PHY84756_LN_DEV7_AN_MSIC2r(pc, 0x2020,
   4474                                    0x2020));
   4475         /* Disable Clause 37 Autoneg */
   4476         SOC_IF_ERROR_RETURN(
   4477             BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, 0x0000,
   4478                                    0x3040));
   4479         SOC_IF_ERROR_RETURN(
   4480             BFCMAP_MOD_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 1,
   4481                                    1));
   4482         if (speed == 10000) {
   4483 
   4484             /* Set Line mode */
   4485             SOC_IF_ERROR_RETURN(
   4486                 bfcmap_phy84756_line_mode_set(pc, 0,
   4487                 BFCMAP_PHY84756_INTF_SFI));
   4488 
   4489             /* Set System side to match Line side */
   4490             SOC_IF_ERROR_RETURN(
   4491                 bfcmap_phy84756_sys_mode_set(pc, 0, 
   4492                                          BFCMAP_PHY84756_INTF_XFI));
   4493             /* Force Speed in PMD */
   4494             SOC_IF_ERROR_RETURN(
   4495                 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 
   4496                                      BFCMAP_PHY84756_PMD_CTRL_SS_10000,
   4497                                      BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK));
   4498             /* Select 10G-LRM PMA */
   4499             SOC_IF_ERROR_RETURN(
   4500                 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRL2r(pc,
   4501                              BFCMAP_PHY84756_PMD_CTRL2_PMA_10GLRMPMD_TYPE,
   4502                              BFCMAP_PHY84756_PMD_CTRL2_PMA_SELECT_MASK));
   4503             /* Select 10G-LRM PMA */
   4504             SOC_IF_ERROR_RETURN(
   4505                 BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRL2r(pc,
   4506                              BFCMAP_PHY84756_PMD_CTRL2_PMA_10GLRMPMD_TYPE,
   4507                              BFCMAP_PHY84756_PMD_CTRL2_PMA_SELECT_MASK));
   4508 
   4509             /* Force Speed in PMD */
   4510             SOC_IF_ERROR_RETURN(
   4511                 BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRLr(pc, 
   4512                                          BFCMAP_PHY84756_PMD_CTRL_SS_10000,
   4513                                          BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK));
   4514         } else {
   4515             if (speed == 1000) {
   4516                 /* Set Line mode */
   4517                 SOC_IF_ERROR_RETURN(
   4518                     bfcmap_phy84756_line_mode_set(pc, 0,
   4519                                                    BFCMAP_PHY84756_INTF_1000X));
   4520                 /* Set System side to match Line side */
   4521                 SOC_IF_ERROR_RETURN(
   4522                     bfcmap_phy84756_sys_mode_set(pc, 0, 
   4523                                              BFCMAP_PHY84756_INTF_1000X));
   4524                 /* Force Speed in PMD */
   4525                 SOC_IF_ERROR_RETURN(
   4526                     BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 
   4527                                          BFCMAP_PHY84756_PMD_CTRL_SS_1000,
   4528                                          BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK));
   4529 
   4530                 /* Force Speed in PMD */
   4531                 SOC_IF_ERROR_RETURN(
   4532                     BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRLr(pc, 
   4533                                              BFCMAP_PHY84756_PMD_CTRL_SS_1000,
   4534                                              BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK));
   4535             } else {
   4536                 return SOC_E_CONFIG;
   4537             }
   4538         }
   4539     break;
   4540 
   4541     case BFCMAP_PHY84756_INTF_SGMII:
   4542         if (speed > 1000) {
   4543             return SOC_E_CONFIG;
   4544         }
   4545         /* Disable Clause 37 Autoneg */
   4546         SOC_IF_ERROR_RETURN(
   4547             BFCMAP_MOD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, 0x0000,
   4548                                    0x3040));
   4549         SOC_IF_ERROR_RETURN(
   4550             BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 0,
   4551                                    1));
   4552         SOC_IF_ERROR_RETURN(
   4553             BFCMAP_MOD_PHY84756_LN_DEV7_AN_MSIC2r(pc, 0x2020,
   4554                                    0x2020));
   4555         if (speed == 1000) {
   4556             value = BFCMAP_PHY84756_PMD_CTRL_SS_1000;
   4557         }
   4558         if (speed == 100) {
   4559             value = BFCMAP_PHY84756_PMD_CTRL_SS_100;
   4560         }
   4561         if (speed == 100) {
   4562             value = BFCMAP_PHY84756_PMD_CTRL_SS_10;
   4563         }
   4564         /* Force Speed in PMD */
   4565         SOC_IF_ERROR_RETURN(
   4566             BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 
   4567                                  value,
   4568                                  BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK));
   4569 
   4570         /* Set System side to match Line side */
   4571         SOC_IF_ERROR_RETURN(
   4572             bfcmap_phy84756_sys_mode_set(pc, 0, 
   4573                                      BFCMAP_PHY84756_INTF_SGMII));
   4574         /* Disable Clause 37 Autoneg */
   4575         SOC_IF_ERROR_RETURN(
   4576             BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, 0x0000,
   4577                                    0x3040));
   4578         SOC_IF_ERROR_RETURN(
   4579             BFCMAP_MOD_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 0,
   4580                                    1));
   4581         SOC_IF_ERROR_RETURN(
   4582             BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MISC2r(pc, 0x2020,
   4583                                    0x2020));
   4584         /* Force Speed in PMD */
   4585         SOC_IF_ERROR_RETURN(
   4586             BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRLr(pc, 
   4587                                      value,
   4588                                      BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK));
   4589     break;
   4590     default:
   4591         return SOC_E_CONFIG;
   4592     }
   4593 
   4594     return SOC_E_NONE;
   4595 }
   4596 
   4597 
   4598 /*
   4599  * Function:
   4600  *      bfcmap_phy84756_link_get
   4601  * Purpose:
   4602  *      Determine the current link up/down status for a 84756 device.
   4603  * Parameters:
   4604  *    phy_id    - PHY Device Address
   4605  *    link      - (OUT) 
   4606  *                1 = Indicates Link is established
   4607  *                0 = No Link.
   4608  * Returns:
   4609  */
   4610 int
   4611 bfcmap_phy84756_link_get(phy_ctrl_t *pc, int *link)
   4612 {
   4613 
   4614     buint16_t data = 0, pma_mii_stat = 0, pcs_mii_stat = 0,status=0;
   4615     int speed=0;
   4616     uint32 pdet_ena=0;
   4617 #if defined(INCLUDE_FCMAP)
   4618     buint16_t fval = 0;
   4619 #endif
   4620     int an, an_done;
   4621     bfcmap_phy84756_intf_t line_mode;
   4622 
   4623     /* Read AN MII STAT once per link get period */
   4624     SOC_IF_ERROR_RETURN(
   4625         BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_STATr(pc, &pc->mii_stat));
   4626 
   4627 #if defined(INCLUDE_FCMAP)
   4628     if (pc->fcmap_enable) {
   4629         BFCMAP_PHY84756_REG_RD(pc, 0, 0x1e, 0x50, &fval);
   4630         if (fval == 0x1a) {
   4631             *link = 1;
   4632         } else {
   4633             *link = 0;
   4634         }
   4635         return SOC_E_NONE;
   4636     }
   4637 #endif
   4638 
   4639     *link = 0;
   4640     if (pc->mii_stat == 0xffff) {
   4641         /* status == 0xffff check is to handle removable PHY daughter cards */
   4642         return SOC_E_NONE;
   4643     }
   4644 
   4645     SOC_IF_ERROR_RETURN(
   4646         phy_84756_fcmap_an_get(pc->unit, pc->port, &an, &an_done)); 
   4647 
   4648     if (an && (an_done == 0)) {
   4649         /* Auto neg in progess, return no link */
   4650         *link = 0;
   4651         SOC_IF_ERROR_RETURN(
   4652            phy_84756_fcmap_speed_get(pc->unit, pc->port, &speed));
   4653         if(speed == 1000) {
   4654            SOC_IF_ERROR_RETURN(
   4655               _phy_84756_control_pdet_get(pc->unit, pc->port, &pdet_ena));
   4656            SOC_IF_ERROR_RETURN(
   4657               BFCMAP_RD_PHY84756_LN_DEV7_AN_BASE1000X_STAT1r(pc, &status));
   4658            status = (status & (0x1 << 1)) >> 1;
   4659            if (pdet_ena == 1 && status == 1) {
   4660                *link = 1;
   4661            }
   4662         }
   4663         return SOC_E_NONE;
   4664     }
   4665 
   4666 
   4667      SOC_IF_ERROR_RETURN(
   4668          bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   4669 
   4670      switch (line_mode) {
   4671         case BFCMAP_PHY84756_INTF_SFI:
   4672             SOC_IF_ERROR_RETURN(
   4673                 BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRL2r(pc, &data));
   4674  
   4675             SOC_IF_ERROR_RETURN(
   4676                 BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRL2r(pc, &data));
   4677  
   4678             SOC_IF_ERROR_RETURN(
   4679                 BFCMAP_RD_PHY84756_LN_DEV1_PMD_STATr(pc, &pma_mii_stat));
   4680  
   4681             SOC_IF_ERROR_RETURN(
   4682                 BFCMAP_RD_PHY84756_LN_DEV3_PCS_STATr(pc, &pcs_mii_stat));
   4683  
   4684             *link = pma_mii_stat & pcs_mii_stat & BFCMAP_PHY84756_PMD_STAT_RX_LINK_STATUS;
   4685  
   4686             break;
   4687  
   4688         case BFCMAP_PHY84756_INTF_1000X:
   4689         case BFCMAP_PHY84756_INTF_SGMII:
   4690             /* sgmii should have AN enabled to declare link up */
   4691             if ((line_mode == BFCMAP_PHY84756_INTF_SGMII) && (an == 0)) {
   4692                  *link = 0;
   4693                  break;
   4694             } 
   4695             if (!(pc->mii_stat & BFCMAP_PHY84756_AN_MII_STAT_LINK_STATUS)) {
   4696                 /* In transition, no link */
   4697                 *link = 0;
   4698                 break;
   4699             }
   4700             SOC_IF_ERROR_RETURN(
   4701                 BFCMAP_RD_PHY84756_LN_DEV1_SPEED_LINK_DETECT_STATr(pc, &data));
   4702             if ((data & 0x8080) == 0x8080) {
   4703                 /* System side and line side rx signal detect OK */
   4704                 if (data & 0x1700) { /* system side link up */
   4705                     if (data & 0x0017) { /* line side line up */
   4706                         *link = 1;
   4707                     }
   4708                 }
   4709             }
   4710             break;
   4711 
   4712         default:
   4713             break;
   4714     }
   4715     return SOC_E_NONE;
   4716 }
   4717 
   4718 
   4719 /*
   4720  * Function:
   4721  *      bfcmap_phy84756_linkfault_get
   4722  * Purpose:
   4723  *      Determine the current link fault status for a 84757 device.
   4724  * Parameters:
   4725  *    phy_id    - PHY Device Address
   4726  *    fault     - (OUT) 
   4727  *                1 = Indicates fault has triggered
   4728  *                0 = No link fault.
   4729  * Returns:
   4730  */
   4731 int
   4732 bfcmap_phy84756_linkfault_get(phy_ctrl_t *pc, int *fault)
   4733 {
   4734 
   4735 #if defined(INCLUDE_FCMAP)
   4736     buint16_t fval = 0;
   4737 
   4738     if (pc->fcmap_enable) {
   4739         BFCMAP_PHY84756_REG_RD(pc, 0, 0x1e, 0x54, &fval);
   4740         if (fval == 0x1) {
   4741             /* clear the sticky fault */
   4742             BFCMAP_PHY84756_REG_WR(pc, 0, 0x1e, 0x54, 0);
   4743             *fault = 1;
   4744         } else {
   4745             *fault = 0;
   4746         }
   4747         return SOC_E_NONE;
   4748     }
   4749 #endif
   4750     *fault = 0;
   4751     return SOC_E_NONE;
   4752 }
   4753 
   4754 
   4755 
   4756 
   4757 /*
   4758  * Function:
   4759  *     bfcmap_phy84756_ability_advert_set 
   4760  * Purpose:
   4761  *      Set the current advertisement for auto-negotiation.
   4762  * Parameters:
   4763  *    phy_id    - PHY Device Address
   4764  *    ability   - Ability indicating supported options/speeds.
   4765  *                For Speed & Duplex:
   4766  *                BFCMAP_PM_10MB_HD    = 10Mb, Half Duplex
   4767  *                BFCMAP_PM_10MB_FD    = 10Mb, Full Duplex
   4768  *                BFCMAP_PM_100MB_HD   = 100Mb, Half Duplex
   4769  *                BFCMAP_PM_100MB_FD   = 100Mb, Full Duplex
   4770  *                BFCMAP_PM_1000MB_HD  = 1000Mb, Half Duplex
   4771  *                BFCMAP_PM_1000MB_FD  = 1000Mb, Full Duplex
   4772  *                BFCMAP_PM_PAUSE_TX   = TX Pause
   4773  *                BFCMAP_PM_PAUSE_RX   = RX Pause
   4774  *                BFCMAP_PM_PAUSE_ASYMM = Asymmetric Pause
   4775  * Returns:
   4776  */
   4777 
   4778 int
   4779 bfcmap_phy84756_ability_advert_set(phy_ctrl_t *pc,
   4780                                bfcmap_phy84756_port_ability_t ability)
   4781 {
   4782     buint16_t data = 0;
   4783     bfcmap_phy84756_intf_t line_mode;
   4784 
   4785     SOC_IF_ERROR_RETURN(
   4786         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   4787 
   4788     if (line_mode == BFCMAP_PHY84756_INTF_1000X) {
   4789         /* Always advertise 1000X full duplex */
   4790         data = BFCMAP_PHY84756_DEV7_1000X_ANA_C37_FD;  
   4791         if ((ability & BFCMAP_PHY84756_PA_PAUSE) == 
   4792                                              BFCMAP_PHY84756_PA_PAUSE) {
   4793             data |= BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE;
   4794         } else {
   4795             if (ability & BFCMAP_PHY84756_PA_PAUSE_TX) {
   4796                 data |= BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE;
   4797             } else {
   4798                 if (ability & BFCMAP_PHY84756_PA_PAUSE_RX) {
   4799                     data |= BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE;
   4800                     data |= BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE;
   4801                 }
   4802             }
   4803         }
   4804         SOC_IF_ERROR_RETURN(
   4805             BFCMAP_WR_PHY84756_LN_DEV7_AN_ANAr(pc, data));
   4806 
   4807     }
   4808     if (line_mode == BFCMAP_PHY84756_INTF_SGMII) {
   4809         
   4810         
   4811     } else {
   4812         /* No Autoneg in SFI mode */
   4813         /* return SOC_E_UNAVAIL; */
   4814     }
   4815     return SOC_E_NONE;
   4816 }
   4817 
   4818 
   4819 /*
   4820  * Function:
   4821  *      bfcmap_phy84756_ability_advert_get
   4822  * Purpose:
   4823  *      Get the current advertisement for auto-negotiation.
   4824  * Parameters:
   4825  *    phy_id    - PHY Device Address
   4826  *    ability   - (OUT) Port ability mask indicating supported options/speeds.
   4827  *                For Speed & Duplex:
   4828  *                BFCMAP_PM_10MB_HD    = 10Mb, Half Duplex
   4829  *                BFCMAP_PM_10MB_FD    = 10Mb, Full Duplex
   4830  *                BFCMAP_PM_100MB_HD   = 100Mb, Half Duplex
   4831  *                BFCMAP_PM_100MB_FD   = 100Mb, Full Duplex
   4832  *                BFCMAP_PM_1000MB_HD  = 1000Mb, Half Duplex
   4833  *                BFCMAP_PM_1000MB_FD  = 1000Mb, Full Duplex
   4834  *                BFCMAP_PM_PAUSE_TX   = TX Pause
   4835  *                BFCMAP_PM_PAUSE_RX   = RX Pause
   4836  *                BFCMAP_PM_PAUSE_ASYMM = Asymmetric Pause
   4837  * Returns:
   4838  */
   4839 
   4840 int
   4841 bfcmap_phy84756_ability_advert_get(phy_ctrl_t *pc,
   4842                                bfcmap_phy84756_port_ability_t *ability)
   4843 {
   4844     buint16_t data = 0;
   4845     bfcmap_phy84756_intf_t line_mode;
   4846 
   4847     if (ability == NULL) {
   4848         return SOC_E_PARAM;
   4849     }
   4850 
   4851     SOC_IF_ERROR_RETURN(
   4852         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   4853 
   4854     if (line_mode == BFCMAP_PHY84756_INTF_1000X) {
   4855         SOC_IF_ERROR_RETURN(
   4856             BFCMAP_RD_PHY84756_LN_DEV7_AN_ANAr(pc, &data));
   4857 
   4858         *ability |= (data & BFCMAP_PHY84756_DEV7_1000X_ANA_C37_FD) ? 
   4859                   BFCMAP_PHY84756_PA_1000MB_FD : 0;
   4860         *ability |= (data & BFCMAP_PHY84756_DEV7_1000X_ANA_C37_HD) ?
   4861                   BFCMAP_PHY84756_PA_1000MB_HD : 0;
   4862         switch (data & (BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE | 
   4863                         BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE)) {
   4864         case BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE:
   4865             *ability |= BFCMAP_PHY84756_PA_PAUSE;
   4866             break;
   4867         case BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE:
   4868             *ability |= BFCMAP_PHY84756_PA_PAUSE_TX;
   4869             break;
   4870         case (BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE | 
   4871               BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE):
   4872             *ability |= BFCMAP_PHY84756_PA_PAUSE_RX;
   4873             break;
   4874         }
   4875     } else {
   4876         if (line_mode == BFCMAP_PHY84756_INTF_SGMII) {
   4877             *ability = BFCMAP_PHY84756_PA_SPEED_ALL |
   4878                        BFCMAP_PHY84756_PA_AN        |
   4879                        BFCMAP_PHY84756_PA_PAUSE     |
   4880                        BFCMAP_PHY84756_PA_PAUSE_ASYMM;
   4881         
   4882         } else {
   4883             /* No Autoneg in SFI mode */
   4884             *ability = BFCMAP_PHY84756_PA_10000MB_FD |
   4885                        BFCMAP_PHY84756_PA_PAUSE;
   4886         }
   4887     }
   4888     return SOC_E_NONE;
   4889 }
   4890 
   4891 
   4892 /*
   4893  * Function:
   4894  *      bfcmap_phy84756_remote_ability_advert_get
   4895  * Purpose:
   4896  *      Get partners current advertisement for auto-negotiation.
   4897  * Parameters:
   4898  *    phy_id         - PHY Device Address
   4899  *    remote_ability - (OUT) Port ability mask indicating supported options/speeds.
   4900  *                For Speed & Duplex:
   4901  *                BFCMAP_PM_10MB_HD    = 10Mb, Half Duplex
   4902  *                BFCMAP_PM_10MB_FD    = 10Mb, Full Duplex
   4903  *                BFCMAP_PM_100MB_HD   = 100Mb, Half Duplex
   4904  *                BFCMAP_PM_100MB_FD   = 100Mb, Full Duplex
   4905  *                BFCMAP_PM_1000MB_HD  = 1000Mb, Half Duplex
   4906  *                BFCMAP_PM_1000MB_FD  = 1000Mb, Full Duplex
   4907  *                BFCMAP_PM_PAUSE_TX   = TX Pause
   4908  *                BFCMAP_PM_PAUSE_RX   = RX Pause
   4909  *                BFCMAP_PM_PAUSE_ASYMM = Asymmetric Pause
   4910  * Returns:
   4911  */
   4912 
   4913 int
   4914 bfcmap_phy84756_remote_ability_advert_get(phy_ctrl_t *pc,
   4915                                 bfcmap_phy84756_port_ability_t *remote_ability)
   4916 {
   4917     buint16_t data = 0;
   4918     bfcmap_phy84756_intf_t line_mode;
   4919 
   4920     if (remote_ability == NULL) {
   4921         return SOC_E_PARAM;
   4922     }
   4923 
   4924     SOC_IF_ERROR_RETURN(
   4925         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   4926 
   4927     if (line_mode == BFCMAP_PHY84756_INTF_1000X) {
   4928         SOC_IF_ERROR_RETURN(
   4929             BFCMAP_RD_PHY84756_LN_DEV7_AN_ANPr(pc, &data));
   4930 
   4931         *remote_ability |= (data & BFCMAP_PHY84756_DEV7_1000X_ANA_C37_FD) ?
   4932                   BFCMAP_PHY84756_PA_1000MB_FD : 0;
   4933         *remote_ability |= (data & BFCMAP_PHY84756_DEV7_1000X_ANA_C37_HD) ?
   4934                                BFCMAP_PHY84756_PA_1000MB_HD : 0;
   4935         switch (data & (BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE | 
   4936                         BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE)) {
   4937         case BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE:
   4938             *remote_ability |= BFCMAP_PHY84756_PA_PAUSE;
   4939             break;
   4940         case BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE:
   4941             *remote_ability |= BFCMAP_PHY84756_PA_PAUSE_TX;
   4942             break;
   4943         case (BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE | 
   4944               BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE):
   4945             *remote_ability |= BFCMAP_PHY84756_PA_PAUSE_RX;
   4946             break;
   4947         }
   4948     } else  if (line_mode == BFCMAP_PHY84756_INTF_SGMII) {
   4949         
   4950         
   4951     } else {
   4952         /* No Autoneg in SFI mode */
   4953         return SOC_E_UNAVAIL;
   4954     }
   4955     return SOC_E_NONE;
   4956 }
   4957 
   4958 
   4959 /*
   4960  * Function:
   4961  *      bfcmap_phy84756_ability_local_get
   4962  * Purpose:
   4963  *      Get the PHY abilities
   4964  * Parameters:
   4965  *    phy_id    - PHY Device Address
   4966  *    mode      - Mask indicating supported options/speeds.
   4967  *                For Speed & Duplex:
   4968  *                BFCMAP_PM_10MB_HD    = 10Mb, Half Duplex
   4969  *                BFCMAP_PM_10MB_FD    = 10Mb, Full Duplex
   4970  *                BFCMAP_PM_100MB_HD   = 100Mb, Half Duplex
   4971  *                BFCMAP_PM_100MB_FD   = 100Mb, Full Duplex
   4972  *                BFCMAP_PM_1000MB_HD  = 1000Mb, Half Duplex
   4973  *                BFCMAP_PM_1000MB_FD  = 1000Mb, Full Duplex
   4974  *                BFCMAP_PM_PAUSE_TX   = TX Pause
   4975  *                BFCMAP_PM_PAUSE_RX   = RX Pause
   4976  *                BFCMAP_PM_PAUSE_ASYMM = Asymmetric Pause
   4977  *                BFCMAP_PM_SGMII       = SGMIII Supported
   4978  *                BFCMAP_PM_XSGMII      = XSGMIII Supported
   4979  * Returns:
   4980  */
   4981 int
   4982 bfcmap_phy84756_ability_local_get(phy_ctrl_t *pc,
   4983                              bfcmap_phy84756_port_ability_t *ability)
   4984 {
   4985     bfcmap_phy84756_intf_t line_mode;
   4986 
   4987     if (ability == NULL) {
   4988         return SOC_E_PARAM;
   4989     }
   4990 
   4991     SOC_IF_ERROR_RETURN(
   4992         bfcmap_phy84756_line_intf_get(pc, 0, &line_mode));
   4993 
   4994     *ability = BFCMAP_PHY84756_PA_LB_PHY | BFCMAP_PHY84756_PA_PAUSE;
   4995     *ability |= BFCMAP_PHY84756_PA_SGMII;
   4996 
   4997     if (line_mode == BFCMAP_PHY84756_INTF_SGMII) {
   4998         *ability |= BFCMAP_PHY84756_PA_AN;
   4999         *ability |= BFCMAP_PHY84756_PA_SPEED_ALL;
   5000         
   5001     } else {
   5002         *ability |= BFCMAP_PHY84756_PA_XSGMII;
   5003         *ability |= BFCMAP_PHY84756_PA_10000MB_FD;
   5004         *ability |= BFCMAP_PHY84756_PA_1000MB_FD;
   5005     }
   5006 
   5007     return(SOC_E_NONE);
   5008 }
   5009 
   5010 STATIC int
   5011 _bfcmap_phy84756_system_sgmii_speed_set(phy_ctrl_t *pc, int dev_port, int speed)
   5012 {
   5013     buint16_t mii_ctrl = 0;
   5014 
   5015     if (speed == 0) {
   5016         return SOC_E_NONE;
   5017     }
   5018 
   5019     {
   5020         SOC_IF_ERROR_RETURN(
   5021             BFCMAP_RD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, &mii_ctrl));
   5022 
   5023         mii_ctrl &= ~(BFCMAP_PHY84756_SGMII_MII_CTRL_SS_MASK);
   5024         switch(speed) {
   5025         case 10:
   5026             mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_SS_10;
   5027             break;
   5028         case 100:
   5029             mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_SS_100;
   5030             break;
   5031         case 1000:
   5032             mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_SS_1000;
   5033             break;
   5034         default:
   5035             return SOC_E_CONFIG;
   5036         }
   5037         SOC_IF_ERROR_RETURN(
   5038             BFCMAP_WR_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, mii_ctrl));
   5039     }
   5040     return SOC_E_NONE;
   5041 }
   5042 
   5043 STATIC int
   5044 _bfcmap_phy84756_system_sgmii_duplex_set(phy_ctrl_t *pc, int dev_port,
   5045                                  int duplex)
   5046 {
   5047     buint16_t mii_ctrl;
   5048 
   5049     {
   5050         SOC_IF_ERROR_RETURN(
   5051             BFCMAP_RD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, &mii_ctrl));
   5052 
   5053         if ( duplex ) {
   5054             mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_FD;
   5055         } else {
   5056             mii_ctrl &= ~BFCMAP_PHY84756_AN_MII_CTRL_FD;
   5057         }
   5058         SOC_IF_ERROR_RETURN(
   5059             BFCMAP_WR_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, mii_ctrl));
   5060     }
   5061 
   5062     return SOC_E_NONE;
   5063 }
   5064 
   5065 STATIC int
   5066 _bfcmap_phy84756_system_sgmii_init(phy_ctrl_t *pc, int dev_port)
   5067 {
   5068         SOC_IF_ERROR_RETURN(
   5069             BFCMAP_PHY84756_REG_MOD(pc, 0x01, 0x0007, 0x8000, 0x0000, 0x2000));
   5070 
   5071         SOC_IF_ERROR_RETURN(
   5072             BFCMAP_WR_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 0x01a0));
   5073 
   5074         SOC_IF_ERROR_RETURN(
   5075             BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MISC2r(pc, 0x6000, 0x6020));
   5076 
   5077         SOC_IF_ERROR_RETURN(
   5078             BFCMAP_PHY84756_REG_WR(pc, 0x01, 0x0007, 0x835c, 0x0001));
   5079 
   5080         SOC_IF_ERROR_RETURN(
   5081             BFCMAP_WR_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, 0x0140));
   5082 
   5083         SOC_IF_ERROR_RETURN(
   5084             BFCMAP_PHY84756_REG_MOD(pc, 0x01, 0x0007, 0x8000, 0x2000, 0x2000));
   5085 
   5086     return SOC_E_NONE;
   5087 }
   5088 
   5089 STATIC int
   5090 _bfcmap_phy84756_system_sgmii_sync(phy_ctrl_t *pc, int dev_port)
   5091 {
   5092     int speed;
   5093     int duplex;
   5094 
   5095         SOC_IF_ERROR_RETURN(
   5096             phy_84756_fcmap_speed_get(pc->unit, pc->port, &speed));
   5097 
   5098         SOC_IF_ERROR_RETURN(
   5099             phy_84756_fcmap_duplex_get(pc->unit, pc->port, &duplex));
   5100 
   5101         SOC_IF_ERROR_RETURN(
   5102             BFCMAP_PHY84756_REG_MOD(pc, 0x01, 0x0007, 0x8000, 0x0000, 0x2000));
   5103 
   5104         SOC_IF_ERROR_RETURN(
   5105             _bfcmap_phy84756_system_sgmii_speed_set(pc, dev_port, speed));
   5106 
   5107         SOC_IF_ERROR_RETURN(
   5108             _bfcmap_phy84756_system_sgmii_duplex_set(pc, dev_port, duplex));
   5109 
   5110         SOC_IF_ERROR_RETURN(
   5111             BFCMAP_PHY84756_REG_MOD(pc, 0x01, 0x0007, 0x8000, 0x2000, 0x2000));
   5112 
   5113 	SOC_IF_ERROR_RETURN(        /* Notify Switch of Speed */
   5114 	    soc_phyctrl_notify(pc->unit, pc->port, phyEventSpeed, speed));
   5115 
   5116     return SOC_E_NONE;
   5117 }
   5118 
   5119 /*
   5120  * Function:
   5121  *     bfcmap_phy84756_mdio_firmware_download
   5122  * Purpose:
   5123  *     Download new firmware via MDIO.
   5124  * Parameters:
   5125  *    phy_id    - PHY Device Address
   5126  *    new_fw    - Pointer to new firmware
   5127  *    fw_length    - Length of the firmware
   5128  * Returns:
   5129  */
   5130 int
   5131 bfcmap_phy84756_mdio_firmware_download(phy_ctrl_t *pc,
   5132                                   buint8_t *new_fw, buint32_t fw_length)
   5133 {
   5134 
   5135     buint16_t data16;
   5136     int j;
   5137     buint16_t num_words;
   5138 
   5139     /* 0xc848[15]=0, MDIO downloading to RAM, 0xc848[14]=1, serial boot */
   5140     /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */
   5141     SOC_IF_ERROR_RETURN(
   5142            BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc848, 
   5143                (0 << 15)|(1 << 14),
   5144                (1 << 15)|(1 << 14)|((1 << 13) | (1 << 2))));
   5145 
   5146     /* Reset, to download code from MDIO */
   5147     SOC_IF_ERROR_RETURN(
   5148            BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 
   5149                BFCMAP_PHY84756_PMD_CTRL_RESET, BFCMAP_PHY84756_PMD_CTRL_RESET));
   5150 
   5151     sal_usleep(50000);
   5152 
   5153     /* Write Starting Address, where the Code will reside in SRAM */
   5154     data16 = 0x8000;
   5155     SOC_IF_ERROR_RETURN
   5156         (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, BFCMAP_PHY84756_PMAD_M8051_MSGIN_REG, data16));
   5157 
   5158     /* make sure address word is read by the micro */
   5159     sal_usleep(10); /* Wait for 10us */
   5160 
   5161     /* Write SPI SRAM Count Size */
   5162     data16 = (fw_length)/2;
   5163     SOC_IF_ERROR_RETURN
   5164         (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, BFCMAP_PHY84756_PMAD_M8051_MSGIN_REG, data16));
   5165 
   5166     /* make sure read by the micro */
   5167     sal_usleep(10); /* Wait for 10us */
   5168 
   5169     /* Fill in the SRAM */
   5170     num_words = (fw_length - 1);
   5171     for (j = 0; j < num_words; j+=2) {
   5172         /* Make sure the word is read by the Micro */
   5173         sal_usleep(10);
   5174 
   5175         data16 = (new_fw[j] << 8) | new_fw[j+1];
   5176         SOC_IF_ERROR_RETURN
   5177             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, BFCMAP_PHY84756_PMAD_M8051_MSGIN_REG,
   5178                  data16));
   5179     }
   5180 
   5181     /* make sure last code word is read by the micro */
   5182     sal_usleep(20);
   5183 
   5184     /* Read Hand-Shake message (Done) from Micro */
   5185     SOC_IF_ERROR_RETURN
   5186         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc,BFCMAP_PHY84756_PMAD_M8051_MSGOUT_REG, &data16)); 
   5187 
   5188     if (data16 != 0x4321 ) {
   5189         /* Download done message */
   5190         LOG_CLI((BSL_META_U(pc->unit,
   5191                             "MDIO firmware download failed. Message: 0x%x\n"), data16));
   5192     }
   5193 
   5194     /* Clear LASI status */
   5195     SOC_IF_ERROR_RETURN
   5196         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0x9003, &data16));
   5197 
   5198     /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */
   5199     sal_usleep(100); /* Wait for 100 usecs */
   5200 
   5201     SOC_IF_ERROR_RETURN
   5202         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc,BFCMAP_PHY84756_PMAD_M8051_MSGOUT_REG, &data16));
   5203     
   5204     /* Need to check if checksum is correct */
   5205     SOC_IF_ERROR_RETURN
   5206         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1C, &data16));
   5207 
   5208     if (data16 != 0x600D) {
   5209         /* Bad CHECKSUM */
   5210         LOG_CLI((BSL_META_U(pc->unit,
   5211                             "MDIO Firmware downlad failure:"
   5212                             "Incorrect Checksum %x\n"), data16));
   5213         return SOC_E_FAIL;
   5214     }
   5215 
   5216     /* read Rev-ID */
   5217     SOC_IF_ERROR_RETURN
   5218         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A, &data16));
   5219     LOG_INFO(BSL_LS_SOC_PHY,
   5220              (BSL_META_U(pc->unit,
   5221                          "MDIO Firmware download completed. Version : 0x%x\n"), data16));
   5222 
   5223     return SOC_E_NONE;
   5224 }
   5225 
   5226 /*
   5227  *  Function:
   5228  *       _phy_84756_phy_84756_write_message
   5229  *
   5230  *  Purpose:
   5231  *      Write into Message In and Read from MSG Out register.
   5232  *  Input:
   5233  *      phy_id
   5234  *      wrdata
   5235  *      rddata
   5236  */
   5237 
   5238 STATIC int
   5239 _phy_84756_write_message(phy_ctrl_t *pc, buint16_t wrdata, buint16_t *rddata)
   5240 {
   5241     buint16_t tmp_data = 0;
   5242     int iter = 0;
   5243 
   5244     SOC_IF_ERROR_RETURN
   5245         (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &tmp_data));
   5246     SOC_IF_ERROR_RETURN         
   5247         (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, wrdata));
   5248 
   5249     do {
   5250         SOC_IF_ERROR_RETURN
   5251             (BFCMAP_RD_PHY84756_LN_DEV1_LASI_STATr(pc, &tmp_data));
   5252 
   5253         if (tmp_data & 0x4) {
   5254             break;
   5255         }
   5256         sal_usleep(BFCMAP_WR_TIMEOUT);
   5257         iter++;
   5258     } while (iter < BFCMAP_WR_ITERATIONS);
   5259 
   5260     if (!(tmp_data & 0x4)) {
   5261         LOG_CLI((BSL_META_U(pc->unit,
   5262                             "write message failed due to timeout\n")));
   5263         return SOC_E_FAIL;
   5264     }
   5265 
   5266     SOC_IF_ERROR_RETURN
   5267         (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &tmp_data));
   5268 
   5269     *rddata = tmp_data;
   5270     SOC_IF_ERROR_RETURN
   5271         (BFCMAP_RD_PHY84756_LN_DEV1_RX_ALARMr(pc, &tmp_data));
   5272 
   5273     return SOC_E_NONE;
   5274 }
   5275 
   5276 
   5277 /*
   5278  *  Function:
   5279  *       _phy_84756_rom_wait
   5280  *
   5281  *  Purpose:
   5282  *      Wait for data to be written to the SPI-ROM.
   5283  *  Input:
   5284  *      phy_id
   5285  */
   5286 
   5287 STATIC int
   5288 _phy_84756_rom_wait(phy_ctrl_t *pc)
   5289 {
   5290     buint16_t  rd_data = 0, wr_data;
   5291     int        count;
   5292     int        SPI_READY;
   5293     int        iter = 0;
   5294 
   5295     do {
   5296         count = 1;
   5297         wr_data = ((BFCMAP_RD_CPU_CTRL_REGS * 0x0100) | count);
   5298         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5299         wr_data = BFCMAP_SPI_CTRL_1_L;
   5300         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5301         if (rd_data & 0x0100) {
   5302             break;
   5303         }
   5304         sal_usleep(BFCMAP_WR_TIMEOUT);
   5305         iter++;
   5306     } while (iter < BFCMAP_WR_ITERATIONS);
   5307 
   5308     if (!(rd_data & 0x0100)) {
   5309         LOG_CLI((BSL_META_U(pc->unit,
   5310                             "_phy_84756_rom_wait: write timeout\n")));
   5311         return SOC_E_TIMEOUT;
   5312     }
   5313 
   5314      SPI_READY = 1;
   5315      while (SPI_READY == 1) {
   5316         /* Set-up SPI Controller To Receive SPI EEPROM Status. */
   5317         count = 1;
   5318         wr_data = ((BFCMAP_WR_CPU_CTRL_REGS * 0x0100) | count);
   5319         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5320         wr_data = BFCMAP_SPI_CTRL_2_H;
   5321         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5322         wr_data = 0x0100;
   5323         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5324         /* Fill-up SPI Transmit Fifo To check SPI Status. */
   5325         count = 2;
   5326         wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5327         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5328         /* Write Tx Fifo Register Address. */
   5329         wr_data = BFCMAP_SPI_TXFIFO;
   5330         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5331 
   5332         /* Write SPI Tx Fifo Control Word-1. */
   5333         wr_data = ((1 * 0x0100) | BFCMAP_MSGTYPE_HRD);
   5334         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5335         /* Write SPI Tx Fifo Control Word-2. */
   5336         wr_data = BFCMAP_RDSR_OPCODE;
   5337         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5338         /* Write SPI Control Register Write Command. */
   5339         count = 2;
   5340         wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5341         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5342         /* Write SPI Control -1 Register Address. */
   5343         wr_data = BFCMAP_SPI_CTRL_1_L;
   5344         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5345         /* Write SPI Control -1 Register Word-1. */
   5346         wr_data = 0x0101;
   5347         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5348         /* Write SPI Control -1 Register Word-2. */
   5349         wr_data = 0x0100;
   5350         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5351         /* Write SPI Control Register Write Command. */
   5352         count = 1;
   5353         wr_data = ((BFCMAP_WR_CPU_CTRL_REGS * 0x0100) | count);
   5354         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5355         /* Write SPI Control -1 Register Address. */
   5356         wr_data = BFCMAP_SPI_CTRL_1_H;
   5357         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5358         /* Write SPI Control -1 Register Word-2. */
   5359         wr_data = 0x0103;
   5360         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5361         /* Wait For 64 bytes To be written.   */
   5362         rd_data = 0x0000;
   5363         
   5364         do {
   5365             count = 1;
   5366             wr_data = ((BFCMAP_RD_CPU_CTRL_REGS * 0x0100) | count);
   5367             SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5368             wr_data = BFCMAP_SPI_CTRL_1_L;
   5369             SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5370             if (rd_data & 0x0100) {
   5371                 break;
   5372             }
   5373             sal_usleep(BFCMAP_WR_TIMEOUT);
   5374             iter ++;
   5375         } while (iter < BFCMAP_WR_ITERATIONS); 
   5376 
   5377         if (!(rd_data & 0x0100)) {
   5378             LOG_CLI((BSL_META_U(pc->unit,
   5379                                 "_phy_84756_rom_program:timeout 2\n")));
   5380             return SOC_E_TIMEOUT;
   5381         }
   5382         /* Write SPI Control Register Read Command. */
   5383         count = 1;
   5384         wr_data = ((BFCMAP_RD_CPU_CTRL_REGS * 0x0100) | count);
   5385         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5386         /* Write SPI Control -1 Register Address. */
   5387         wr_data = BFCMAP_SPI_RXFIFO;
   5388 
   5389         SOC_IF_ERROR_RETURN         
   5390             (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, wr_data));
   5391         SOC_IF_ERROR_RETURN
   5392             (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &rd_data));
   5393 
   5394         /* Clear LASI Message Out Status. */
   5395         SOC_IF_ERROR_RETURN
   5396             (BFCMAP_RD_PHY84756_LN_DEV1_LASI_STATr(pc, &wr_data));
   5397 
   5398         if ((rd_data & 0x1) == 0) {
   5399             SPI_READY = 0;
   5400         }
   5401      } /* SPI_READY */
   5402      return SOC_E_NONE;
   5403 }
   5404 
   5405 
   5406 /*
   5407  * Function:
   5408  *      _phy_84756_rom_write_enable_set
   5409  *
   5410  * Purpose:
   5411  *      Enable disable protection on SPI_EEPROM
   5412  *
   5413  * Input:
   5414  *      phy_id
   5415  * Output:
   5416  *      SOC_E_xxx
   5417  *
   5418  * Notes:
   5419  *          25AA256 256Kbit Serial EEPROM
   5420  *          STATUS Register
   5421  *          +------------------------------------------+
   5422  *          | WPEN | x | x | x | BP1 | BP0 | WEL | WIP |
   5423  *          +------------------------------------------+
   5424  *      BP1 BP0  :   Protected Blocks
   5425  *       0   0   :  Protect None
   5426  *       1   1   :  Protect All
   5427  *
   5428  *      WEL : Write Latch Enable
   5429  *       0  : Do not allow writes
   5430  *       1  : Allow writes
   5431  */
   5432 STATIC int
   5433 _phy_84756_rom_write_enable_set(phy_ctrl_t *pc, int enable)
   5434 {
   5435     buint16_t  rd_data, wr_data;
   5436     buint8_t   wrsr_data;
   5437     int        count;
   5438 
   5439     /*
   5440      * Write SPI Control Register Write Command.
   5441      */
   5442     count = 2;
   5443     wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5444     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5445 
   5446     /*
   5447      * Write SPI Control -2 Register Address.
   5448      */
   5449     wr_data = BFCMAP_SPI_CTRL_2_L;
   5450     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5451 
   5452     /*
   5453      * Write SPI Control -2 Register Word-1.
   5454      */
   5455     wr_data = 0x8200;
   5456     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5457 
   5458     /*
   5459      * Write SPI Control -2 Register Word-2.
   5460      */
   5461     wr_data = 0x0100;
   5462     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5463 
   5464     /*
   5465      * Fill-up SPI Transmit Fifo With SPI EEPROM Messages.
   5466      * Write SPI Control Register Write Command.
   5467      */
   5468     count = 4;
   5469     wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5470     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5471 
   5472     /*
   5473      * Write Tx Fifo Register Address.
   5474      */
   5475     wr_data = BFCMAP_SPI_TXFIFO;
   5476     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5477 
   5478     /*
   5479      * Write SPI Tx Fifo Control Word-1.
   5480      */
   5481     wr_data = ((1 * 0x0100) | BFCMAP_MSGTYPE_HWR);
   5482     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5483 
   5484     /*
   5485      * Write SPI Tx Fifo Control Word-2.
   5486      */
   5487     wr_data = ((BFCMAP_MSGTYPE_HWR * 0x0100) | BFCMAP_WREN_OPCODE);
   5488     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5489 
   5490     /*
   5491      * Write SPI Tx Fifo Control Word-3.
   5492      */
   5493     wr_data = ((BFCMAP_WRSR_OPCODE * 0x100) | (0x2));
   5494     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5495 
   5496     /*
   5497      * Write SPI Tx Fifo Control Word-4.
   5498      */
   5499     wrsr_data = enable ? 0x2 : 0xc;
   5500     wr_data = ((wrsr_data * 0x0100) | wrsr_data);
   5501     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5502 
   5503     /*
   5504      * Write SPI Control Register Write Command.
   5505      */
   5506     count = 2;
   5507     wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5508     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5509 
   5510     /*
   5511      * Write SPI Control -1 Register Address.
   5512      */
   5513     wr_data = BFCMAP_SPI_CTRL_1_L;
   5514     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5515 
   5516     /*
   5517      * Write SPI Control -1 Register Word-1.
   5518      */
   5519     wr_data = 0x0101;
   5520     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5521 
   5522     /*
   5523      * Write SPI Control -1 Register Word-2.
   5524      */
   5525     wr_data = 0x0003;
   5526     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5527 
   5528     /*
   5529      * Wait For WRSR Command To be written.
   5530      */
   5531     SOC_IF_ERROR_RETURN(_phy_84756_rom_wait(pc));
   5532 
   5533     return SOC_E_NONE;
   5534 }
   5535 
   5536 /*
   5537  * Function:
   5538  *     bfcmap_phy84756_spi_firmware_update
   5539  * Purpose:
   5540  *     Update the firmware in SPI ROM 
   5541  * Parameters:
   5542  *    phy_id    - PHY Device Address
   5543  *    new_fw    - Pointer to new firmware
   5544  *    fw_length    - Length of the firmware
   5545  * Returns:
   5546  */
   5547 int
   5548 bfcmap_phy84756_spi_firmware_update(phy_ctrl_t *pc,
   5549                                   buint8_t *array, buint32_t datalen)
   5550 {
   5551 
   5552     buint16_t   data = 0;
   5553     int         dev_port, j;
   5554     buint16_t   rd_data, wr_data;
   5555     buint8_t    spi_values[BFCMAP_WR_BLOCK_SIZE];
   5556     int count, i = 0;
   5557 
   5558 
   5559     if (array == NULL) {
   5560         return SOC_E_PARAM;
   5561     }
   5562 
   5563     if (_phy84756_phy_get_dev_addr(pc, NULL, &dev_port) != SOC_E_NONE) {
   5564         return SOC_E_CONFIG;
   5565     }
   5566 
   5567     /* Set Bit 2 and Bit 0 in SPI Control */
   5568     SOC_IF_ERROR_RETURN(
   5569         BFCMAP_MOD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, 0x80FD, 0xffff));
   5570 
   5571     /* ser_boot pin high */
   5572     SOC_IF_ERROR_RETURN(
   5573         BFCMAP_MOD_PHY84756_LN_DEV1_MISC_CNTL2r(pc, 0x1, 0x1));
   5574 
   5575     /* Read LASI Status */
   5576     SOC_IF_ERROR_RETURN(
   5577         BFCMAP_RD_PHY84756_LN_DEV1_RX_ALARM_STATr(pc, &data));
   5578     SOC_IF_ERROR_RETURN(
   5579         BFCMAP_RD_PHY84756_LN_DEV1_TX_ALARM_STATr(pc, &data));
   5580     SOC_IF_ERROR_RETURN(
   5581         BFCMAP_RD_PHY84756_LN_DEV1_LASI_STATr(pc, &data));
   5582 
   5583     /* Enable LASI for Message Out */
   5584     SOC_IF_ERROR_RETURN(
   5585         BFCMAP_MOD_PHY84756_LN_DEV1_RX_ALARM_CNTLr(pc, 0x4, 0x4));
   5586 
   5587     /* Enable RX Alarm in LASI */
   5588     SOC_IF_ERROR_RETURN(
   5589         BFCMAP_MOD_PHY84756_LN_DEV1_LASI_CNTLr(pc, 0x4, 0x4));
   5590 
   5591     /* Read any residual Message out register */
   5592     SOC_IF_ERROR_RETURN(
   5593         BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &data));
   5594 
   5595     /* Clear LASI Message OUT status */
   5596     SOC_IF_ERROR_RETURN(
   5597         BFCMAP_RD_PHY84756_LN_DEV1_RX_ALARM_STATr(pc, &data));
   5598 
   5599     /* Set SPI-ROM write enable */
   5600     SOC_IF_ERROR_RETURN(
   5601         _phy_84756_rom_write_enable_set(pc, 1));
   5602 
   5603 
   5604     for (j = 0; j < datalen; j +=BFCMAP_WR_BLOCK_SIZE) {
   5605         /* Setup SPI Controller */
   5606         count = 2;
   5607         wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5608         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5609 
   5610         /* Write SPI Control -2 Register Address.*/
   5611         wr_data = BFCMAP_SPI_CTRL_2_L;
   5612         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5613 
   5614         /* Write SPI Control -2 Register Word-1. */
   5615         wr_data = 0x8200;
   5616         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5617 
   5618         /* Write SPI Control -2 Register Word-2. */
   5619         wr_data = 0x0100;
   5620         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5621         
   5622         /* Fill-up SPI Transmit Fifo.
   5623          * Write SPI Control Register Write Command.
   5624          */
   5625         count = 4 + (BFCMAP_WR_BLOCK_SIZE / 2);
   5626         wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5627         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5628 
   5629         /* Write Tx Fifo Register Address. */
   5630         wr_data = BFCMAP_SPI_TXFIFO;
   5631         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5632 
   5633         /* Write SPI Tx Fifo Control Word-1. */
   5634         wr_data = ((1 * 0x0100) | BFCMAP_MSGTYPE_HWR);
   5635         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5636 
   5637         /* Write SPI Tx Fifo Control Word-2. */
   5638         wr_data = ((BFCMAP_MSGTYPE_HWR * 0x0100) | BFCMAP_WREN_OPCODE);
   5639         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5640 
   5641         /* Write SPI Tx Fifo Control Word-3. */
   5642         wr_data = ((BFCMAP_WR_OPCODE * 0x0100) | (0x3 + BFCMAP_WR_BLOCK_SIZE));
   5643         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5644 
   5645         /* Write SPI Tx Fifo Control Word-4. */
   5646         wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100));
   5647         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5648 
   5649         if (datalen < (j + BFCMAP_WR_BLOCK_SIZE)) {   /* last block */ 
   5650             sal_memset(spi_values,0,BFCMAP_WR_BLOCK_SIZE);
   5651             sal_memcpy(spi_values,&array[j],datalen - j);
   5652 
   5653             for (i = 0; i < BFCMAP_WR_BLOCK_SIZE; i += 2) {
   5654                 /* Write SPI Tx Fifo Data Word-4. */
   5655                 wr_data = ((spi_values[i+1] * 0x0100) | spi_values[i]);
   5656                 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5657             }           
   5658         } else {        
   5659             for (i = 0; i < BFCMAP_WR_BLOCK_SIZE; i += 2) {
   5660                 /* Write SPI Tx Fifo Data Word-4. */
   5661                 wr_data = ((array[j+i+1] * 0x0100) | array[j+i]);
   5662                 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5663             }
   5664         }
   5665 
   5666         /* 
   5667          * Set-up SPI Controller To Transmit.
   5668          * Write SPI Control Register Write Command.
   5669          */
   5670         count = 2;
   5671         wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5672         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5673 
   5674         wr_data = BFCMAP_SPI_CTRL_1_L;
   5675         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5676 
   5677         /* Write SPI Control -1 Register Word-1. */
   5678         wr_data = 0x0501;
   5679         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5680 
   5681         /* Write SPI Control -1 Register Word-2. */
   5682         wr_data = 0x0003;
   5683         SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5684 
   5685         /* Wait For 64 bytes To be written.   */
   5686         SOC_IF_ERROR_RETURN(_phy_84756_rom_wait(pc));
   5687     }
   5688 
   5689     /* Clear SPI-ROM write enable */
   5690     SOC_IF_ERROR_RETURN(
   5691         _phy_84756_rom_write_enable_set(pc, 0));
   5692 
   5693     /* Disable SPI EEPROM. */
   5694     count = 2;
   5695     wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5696     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5697 
   5698     /* Write SPI Control -2 Register Address. */
   5699     wr_data = BFCMAP_SPI_CTRL_2_L;
   5700     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5701 
   5702     /* Write SPI Control -2 Register Word-1. */
   5703     wr_data = 0x8200;
   5704     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5705 
   5706     /* Write SPI Control -2 Register Word-2. */
   5707     wr_data = 0x0100;
   5708     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5709 
   5710 
   5711     /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */
   5712     count = 2;
   5713     wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5714     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5715 
   5716     /* Write Tx Fifo Register Address. */
   5717     wr_data = BFCMAP_SPI_TXFIFO;
   5718     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5719 
   5720     /* Write SPI Tx Fifo Control Word-1. */
   5721     wr_data = ((0x1*0x0100) | BFCMAP_MSGTYPE_HWR);
   5722     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5723 
   5724     /* Write SPI Tx Fifo Control Word-2. */
   5725     wr_data = BFCMAP_WRDI_OPCODE;
   5726     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5727 
   5728     /* Write SPI Control Register Write Command. */
   5729     count = 2;
   5730     wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count);
   5731     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5732 
   5733     /* Write SPI Control -1 Register Address. */
   5734     wr_data = BFCMAP_SPI_CTRL_1_L;
   5735     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5736 
   5737     /* Write SPI Control -1 Register Word-1. */
   5738     wr_data = 0x0101;
   5739     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5740 
   5741     /* Write SPI Control -1 Register Word-2. */
   5742     wr_data = 0x0003;
   5743     SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data));
   5744 
   5745     /* ser_boot pin LOW */
   5746     SOC_IF_ERROR_RETURN(
   5747         BFCMAP_MOD_PHY84756_LN_DEV1_MISC_CNTL2r(pc, 0x0, 0x1));
   5748 
   5749     /* Disable Bit 2 and Bit 0 in SPI Control */
   5750     SOC_IF_ERROR_RETURN(
   5751         BFCMAP_MOD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, 0xc0F9, 0xffff));
   5752 
   5753     return SOC_E_NONE;
   5754 }
   5755 
   5756 
   5757 
   5758 void _phy_84756_fcmap_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode,
   5759                                             int offset, buint16_t *value)
   5760 {
   5761 
   5762     switch (mode) {
   5763     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE:
   5764         *value |= (0x0 << offset);
   5765         break;
   5766     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD:
   5767         *value |= (0x1 << offset);
   5768         break;
   5769     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN:
   5770         *value |= (0x2 << offset);
   5771         break;
   5772     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP:
   5773         *value |= (0x3 << offset);
   5774         break;
   5775     default:
   5776         break;
   5777     }
   5778 
   5779 }
   5780 
   5781 void _phy_84756_fcmap_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode,
   5782                                             int offset, buint16_t *value)
   5783 {
   5784 
   5785     switch (mode) {
   5786     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE:
   5787         *value |= (0x0 << offset);
   5788         break;
   5789     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD:
   5790         *value |= (0x1 << offset);
   5791         break;
   5792     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP:
   5793         *value |= (0x2 << offset);
   5794         break;
   5795     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME:
   5796         *value |= (0x3 << offset);
   5797         break;
   5798     default:
   5799         break;
   5800     }
   5801 
   5802 }
   5803 
   5804 void _phy_84756_fcmap_decode_egress_message_mode(buint16_t value, int offset,
   5805                                             soc_port_phy_timesync_event_message_egress_mode_t *mode)
   5806 {
   5807 
   5808     switch ((value >> offset) & 0x3) {
   5809     case 0x0:
   5810         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE;
   5811         break;
   5812     case 0x1:
   5813         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD;
   5814         break;
   5815     case 0x2:
   5816         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN;
   5817         break;
   5818     case 0x3:
   5819         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP;
   5820         break;
   5821     default:
   5822         break;
   5823     }
   5824 
   5825 }
   5826 
   5827 void _phy_84756_fcmap_decode_ingress_message_mode(buint16_t value, int offset,
   5828                                             soc_port_phy_timesync_event_message_ingress_mode_t *mode)
   5829 {
   5830 
   5831     switch ((value >> offset) & 0x3) {
   5832     case 0x0:
   5833         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE;
   5834         break;
   5835     case 0x1:
   5836         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD;
   5837         break;
   5838     case 0x2:
   5839         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP;
   5840         break;
   5841     case 0x3:
   5842         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME;
   5843         break;
   5844     default:
   5845         break;
   5846     }
   5847 
   5848 }
   5849 
   5850 void _phy_84756_fcmap_encode_gmode(soc_port_phy_timesync_global_mode_t mode,
   5851                                             buint16_t *value)
   5852 {
   5853 
   5854     switch (mode) {
   5855     case SOC_PORT_PHY_TIMESYNC_MODE_FREE:
   5856         *value = 0x1;
   5857         break;
   5858     case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN:
   5859         *value = 0x2;
   5860         break;
   5861     case SOC_PORT_PHY_TIMESYNC_MODE_CPU:
   5862         *value = 0x3;
   5863         break;
   5864     default:
   5865         break;
   5866     }
   5867 
   5868 }
   5869 
   5870 void _phy_84756_fcmap_decode_gmode(buint16_t value,
   5871                                             soc_port_phy_timesync_global_mode_t *mode)
   5872 {
   5873 
   5874     switch (value & 0x3) {
   5875     case 0x1:
   5876         *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   5877         break;
   5878     case 0x2:
   5879         *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN;
   5880         break;
   5881     case 0x3:
   5882         *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU;
   5883         break;
   5884     default:
   5885         break;
   5886     }
   5887 
   5888 }
   5889 
   5890 
   5891 void _phy_84756_fcmap_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode,
   5892                                             buint16_t *value)
   5893 {
   5894 
   5895     switch (mode) {
   5896     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0:
   5897         *value = 1U << 0;
   5898         break;
   5899     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1:
   5900         *value = 1U << 1;
   5901         break;
   5902     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT:
   5903         *value = 1U << 2;
   5904         break;
   5905     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU:
   5906         *value = 1U << 3;
   5907         break;
   5908     default:
   5909         break;
   5910     }
   5911 
   5912 }
   5913 
   5914 void _phy_84756_fcmap_decode_framesync_mode(buint16_t value,
   5915                                             soc_port_phy_timesync_framesync_mode_t *mode)
   5916 {
   5917 
   5918     switch (value & 0xf) {
   5919     case 1U << 0:
   5920         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0;
   5921         break;
   5922     case 1U << 1:
   5923         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1;
   5924         break;
   5925     case 1U << 2:
   5926         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT;
   5927         break;
   5928     case 1U << 3:
   5929         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU;
   5930         break;
   5931     default:
   5932         break;
   5933     }
   5934 
   5935 }
   5936 
   5937 void _phy_84756_fcmap_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode,
   5938                                             buint16_t *value)
   5939 {
   5940 
   5941     switch (mode) {
   5942     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE:
   5943         *value = 0x0;
   5944         break;
   5945     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME:
   5946         *value = 0x1;
   5947         break;
   5948     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN:
   5949         *value = 0x2;
   5950         break;
   5951     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC:
   5952         *value = 0x3;
   5953         break;
   5954     default:
   5955         break;
   5956     }
   5957 
   5958 }
   5959 
   5960 void _phy_84756_fcmap_decode_syncout_mode(buint16_t value,
   5961                                             soc_port_phy_timesync_syncout_mode_t *mode)
   5962 {
   5963 
   5964     switch (value & 0x3) {
   5965     case 0x0:
   5966         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   5967         break;
   5968     case 0x1:
   5969         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME;
   5970         break;
   5971     case 0x2:
   5972         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN;
   5973         break;
   5974     case 0x3:
   5975         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC;
   5976         break;
   5977     default:
   5978         break;
   5979     }
   5980 
   5981 }
   5982 
   5983 
   5984 int
   5985 phy_84756_fcmap_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf)
   5986 {
   5987     buint16_t rx_control_reg = 0, tx_control_reg = 0, rx_tx_control_reg = 0,
   5988            en_control_reg = 0, capture_en_reg = 0,
   5989            nse_sc_8 = 0, nse_nco_3 = 0, value, mpls_control_reg = 0, temp = 0,
   5990            gmode = 0, framesync_mode = 0, syncout_mode = 0, mask = 0;
   5991     int i;
   5992     phy_ctrl_t *pc;
   5993 
   5994     pc = EXT_PHY_SW_STATE(unit, port);
   5995 
   5996     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   5997 
   5998         if (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) {
   5999             SOC_IF_ERROR_RETURN
   6000                 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc600, 0x8000));
   6001             SOC_IF_ERROR_RETURN
   6002                 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc8f0, 0x0000));
   6003             SOC_IF_ERROR_RETURN
   6004                 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xcd58, 0x0300));
   6005             SOC_IF_ERROR_RETURN
   6006                 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xcd53, 0x0000));
   6007             en_control_reg |= 3U;
   6008             nse_sc_8 |= (1U << 12);
   6009         }
   6010 
   6011         /* slice enable control reg */
   6012         SOC_IF_ERROR_RETURN
   6013             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc600, en_control_reg, 
   6014                                            3U));
   6015 
   6016         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) {
   6017             capture_en_reg |= 3U;
   6018         }
   6019 
   6020         /* TXRX SOP TS CAPTURE ENABLE reg */
   6021         SOC_IF_ERROR_RETURN
   6022             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc607, capture_en_reg, 3U));
   6023 
   6024         if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) {
   6025             nse_sc_8 |= (1U << 13);
   6026         }
   6027 
   6028         /* NSE SC 8 register */
   6029         SOC_IF_ERROR_RETURN
   6030             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, nse_sc_8, 
   6031                                            (1U << 12)| (1U << 13)));
   6032 
   6033         if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) {
   6034             rx_tx_control_reg |= (1U << 3);
   6035         }
   6036 
   6037         /* RX TX CONTROL register */
   6038         SOC_IF_ERROR_RETURN
   6039             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc61c, rx_tx_control_reg, (1U << 3)));
   6040 
   6041         if (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) {
   6042             rx_control_reg |= (1U << 3);
   6043             tx_control_reg |= (1U << 3);
   6044         }
   6045 
   6046         if (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) {
   6047             rx_control_reg |= (1U << 2);
   6048             tx_control_reg |= (1U << 2);
   6049         }
   6050 
   6051         if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) {
   6052             rx_control_reg |= (1U << 1);
   6053             tx_control_reg |= (1U << 1);
   6054         }
   6055 
   6056         if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) {
   6057             rx_control_reg |= (1U << 0);
   6058             tx_control_reg |= (1U << 0);
   6059         }
   6060 
   6061         /* TX CONTROL register */
   6062         SOC_IF_ERROR_RETURN
   6063             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc618, tx_control_reg));
   6064                                           
   6065         /* RX CONTROL register */
   6066         SOC_IF_ERROR_RETURN
   6067             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc61a, rx_control_reg));
   6068                                           
   6069         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) {
   6070             nse_nco_3 &= ~(1U << 14);
   6071         } else {
   6072             nse_nco_3 |= (1U << 14);
   6073         }
   6074 
   6075         /* NSE NCO 3 register */
   6076         SOC_IF_ERROR_RETURN
   6077             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc630, nse_nco_3, 
   6078                                            (1U << 14)));
   6079     }
   6080 
   6081     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   6082         /* VLAN TAG register */
   6083         SOC_IF_ERROR_RETURN
   6084             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc61d, conf->itpid));
   6085     }
   6086 
   6087     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   6088         /* OUTER VLAN TAG register */
   6089         SOC_IF_ERROR_RETURN
   6090             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc61e, conf->otpid));
   6091     }
   6092 
   6093     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   6094         /* INNER VLAN TAG register */
   6095         SOC_IF_ERROR_RETURN
   6096             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc61f, conf->otpid2));
   6097     }
   6098 
   6099     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   6100         SOC_IF_ERROR_RETURN
   6101             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc636, conf->ts_divider & 0xfff));
   6102     }
   6103 
   6104     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   6105         SOC_IF_ERROR_RETURN
   6106             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc605, conf->rx_link_delay & 0xffff));
   6107         SOC_IF_ERROR_RETURN
   6108             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc606, (conf->rx_link_delay >> 16) & 0xffff));
   6109     }
   6110 
   6111 
   6112     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   6113 
   6114         /* TIME CODE 5 register */
   6115         SOC_IF_ERROR_RETURN
   6116             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc610, (buint16_t)(conf->original_timecode.nanoseconds & 0xffff)));
   6117 
   6118         /* TIME CODE 4 register */
   6119         SOC_IF_ERROR_RETURN
   6120             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60f, (buint16_t)((conf->original_timecode.nanoseconds >> 16) & 0xffff)));
   6121 
   6122         /* TIME CODE 3 register */
   6123         SOC_IF_ERROR_RETURN
   6124             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60e, (buint16_t)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff)));
   6125 
   6126         /* TIME CODE 2 register */
   6127         SOC_IF_ERROR_RETURN
   6128             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60d, (buint16_t)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) & 0xffff)));
   6129 
   6130         /* TIME CODE 1 register */
   6131         SOC_IF_ERROR_RETURN
   6132             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60c, (buint16_t)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff)));
   6133     }
   6134 
   6135     mask = 0;
   6136 
   6137     /* NSE SC 8 register */
   6138 
   6139     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   6140         _phy_84756_fcmap_encode_gmode(conf->gmode,&gmode);
   6141         mask |= (0x3 << 14);
   6142     }
   6143 
   6144     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   6145         _phy_84756_fcmap_encode_framesync_mode(conf->framesync.mode, &framesync_mode);
   6146         mask |= (0xf << 2);
   6147         SOC_IF_ERROR_RETURN
   6148             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63c, conf->framesync.length_threshold));
   6149         SOC_IF_ERROR_RETURN
   6150             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63b, conf->framesync.event_offset));
   6151     }
   6152 
   6153     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   6154         _phy_84756_fcmap_encode_syncout_mode(conf->syncout.mode, &syncout_mode);
   6155         mask |= (0x3 << 0);
   6156 
   6157         SOC_IF_ERROR_RETURN
   6158             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc635, conf->syncout.interval & 0xffff));
   6159         SOC_IF_ERROR_RETURN
   6160             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc634,
   6161                 ((conf->syncout.pulse_1_length & 0x3) << 14) | ((conf->syncout.interval >> 16) & 0x3fff)));
   6162         SOC_IF_ERROR_RETURN
   6163             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc633,
   6164                 ((conf->syncout.pulse_2_length & 0x1ff) << 7) | ((conf->syncout.pulse_1_length >> 2) & 0x7f)));
   6165 
   6166         SOC_IF_ERROR_RETURN
   6167             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc639,
   6168                 (buint16_t)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xfff0)));
   6169         SOC_IF_ERROR_RETURN
   6170             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc638,
   6171                 (buint16_t)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff)));
   6172         SOC_IF_ERROR_RETURN
   6173             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc637,
   6174                 (buint16_t)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff)));
   6175     }
   6176 
   6177     SOC_IF_ERROR_RETURN
   6178         (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, (gmode << 14) | (framesync_mode << 2) | (syncout_mode << 0), 
   6179                                        mask));
   6180 
   6181     mask = 0;
   6182 
   6183     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   6184         /* RX TS OFFSET register */
   6185         SOC_IF_ERROR_RETURN
   6186             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60b, (buint16_t)(conf->rx_timestamp_offset & 0xffff)));
   6187         mask |= 0xf000;
   6188     }
   6189 
   6190     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   6191         mask |= 0x0fff;
   6192     }
   6193 
   6194     /* TXRX TS OFFSET register */
   6195     SOC_IF_ERROR_RETURN
   6196         (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, (buint16_t)(((conf->rx_timestamp_offset & 0xf0000) >> 4) |
   6197                                           (conf->tx_timestamp_offset & 0xfff)), mask));
   6198     value = 0;
   6199     mask = 0;
   6200 
   6201     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   6202         _phy_84756_fcmap_encode_egress_message_mode(conf->tx_sync_mode, 0, &value);
   6203         mask = 0x3 << 0;
   6204     }
   6205 
   6206     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   6207         _phy_84756_fcmap_encode_egress_message_mode(conf->tx_delay_request_mode, 2, &value);
   6208         mask = 0x3 << 2;
   6209     }
   6210 
   6211     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   6212         _phy_84756_fcmap_encode_egress_message_mode(conf->tx_pdelay_request_mode, 4, &value);
   6213         mask = 0x3 << 4;
   6214     }
   6215 
   6216     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   6217         _phy_84756_fcmap_encode_egress_message_mode(conf->tx_pdelay_response_mode, 6, &value);
   6218         mask = 0x3 << 6;
   6219     }
   6220                                             
   6221     /* TX EVENT MESSAGE MODE SEL register */
   6222     SOC_IF_ERROR_RETURN
   6223         (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc601, value, 0x00ff)); 
   6224 
   6225     value = 0;
   6226     mask = 0;
   6227 
   6228     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   6229         _phy_84756_fcmap_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value);
   6230         mask = 0x3 << 0;
   6231     }
   6232 
   6233     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   6234         _phy_84756_fcmap_encode_ingress_message_mode(conf->rx_delay_request_mode, 2, &value);
   6235         mask = 0x3 << 2;
   6236     }
   6237 
   6238     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   6239         _phy_84756_fcmap_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 4, &value);
   6240         mask = 0x3 << 4;
   6241     }
   6242 
   6243     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   6244         _phy_84756_fcmap_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 6, &value);
   6245         mask = 0x3 << 6;
   6246     }
   6247                                             
   6248     /* RX EVENT MESSAGE MODE SEL register */
   6249     SOC_IF_ERROR_RETURN
   6250         (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc603, value, 0x00ff)); 
   6251 
   6252     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   6253 
   6254         /* Initial ref phase [15:0] */
   6255         SOC_IF_ERROR_RETURN
   6256             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc623, (buint16_t)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff)));
   6257 
   6258         /* Initial ref phase [31:16]  */
   6259         SOC_IF_ERROR_RETURN
   6260             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc622, (buint16_t)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff)));
   6261 
   6262         /*  Initial ref phase [47:32] */
   6263         SOC_IF_ERROR_RETURN
   6264             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc621, (buint16_t)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff)));
   6265     }
   6266 
   6267 
   6268     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   6269         SOC_IF_ERROR_RETURN
   6270             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc625, conf->phy_1588_dpll_ref_phase_delta & 0xffff));
   6271         SOC_IF_ERROR_RETURN
   6272             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc624, (conf->phy_1588_dpll_ref_phase_delta >> 16) & 0xffff));
   6273     }
   6274 
   6275     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   6276         /* DPLL K1 */
   6277         SOC_IF_ERROR_RETURN
   6278             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc626, conf->phy_1588_dpll_k1 & 0xff)); 
   6279     }
   6280 
   6281     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   6282         /* DPLL K2 */
   6283         SOC_IF_ERROR_RETURN
   6284             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc627, conf->phy_1588_dpll_k2 & 0xff)); 
   6285     }
   6286 
   6287     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   6288         /* DPLL K3 */
   6289         SOC_IF_ERROR_RETURN
   6290             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc628, conf->phy_1588_dpll_k3 & 0xff)); 
   6291     }
   6292 
   6293 
   6294     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) {
   6295 
   6296         /* MPLS controls */
   6297         if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE) {
   6298             mpls_control_reg |= (1U << 7) | (1U << 3);
   6299         }
   6300 
   6301         if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE) {
   6302             mpls_control_reg |= (1U << 6) | (1U << 2);
   6303         }
   6304 
   6305         if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE) {
   6306             mpls_control_reg |= (1U << 4);
   6307         }
   6308 
   6309         if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE) {
   6310             mpls_control_reg |= (1U << 5) | (1U << 1);
   6311         }
   6312 
   6313         SOC_IF_ERROR_RETURN
   6314             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc651, mpls_control_reg, 
   6315                 (1U << 7) | (1U << 3)| (1U << 6) | (1U << 2) | (1U << 4) | (1U << 5) | (1U << 1))); 
   6316 
   6317         /* special label [19:16] */
   6318         SOC_IF_ERROR_RETURN
   6319             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc653, (buint16_t)((conf->mpls_control.special_label >> 16 ) & 0xf)));
   6320                                           
   6321         /* special label [15:0] */
   6322         SOC_IF_ERROR_RETURN
   6323             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc652, (buint16_t)(conf->mpls_control.special_label & 0xffff)));
   6324 
   6325         for (i = 0; i < 10; i++ ) {
   6326             SOC_IF_ERROR_RETURN
   6327                 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc654 + i, (buint16_t)(conf->mpls_control.labels[i].value & 0xffff)));
   6328             SOC_IF_ERROR_RETURN
   6329                 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc661 + i, (buint16_t)(conf->mpls_control.labels[i].mask & 0xffff)));
   6330         }
   6331  
   6332         SOC_IF_ERROR_RETURN
   6333             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc65e, (buint16_t)(
   6334                 ((conf->mpls_control.labels[3].value >> 4)  & 0xf000) | 
   6335                 ((conf->mpls_control.labels[2].value >> 8)  & 0x0f00) | 
   6336                 ((conf->mpls_control.labels[1].value >> 12) & 0x00f0) | 
   6337                 ((conf->mpls_control.labels[0].value >> 16) & 0x000f))));
   6338 
   6339         SOC_IF_ERROR_RETURN
   6340             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc65f, (buint16_t)(
   6341                 ((conf->mpls_control.labels[7].value >> 4)  & 0xf000) | 
   6342                 ((conf->mpls_control.labels[6].value >> 8)  & 0x0f00) | 
   6343                 ((conf->mpls_control.labels[5].value >> 12) & 0x00f0) | 
   6344                 ((conf->mpls_control.labels[4].value >> 16) & 0x000f))));
   6345 
   6346         SOC_IF_ERROR_RETURN
   6347             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc660, (buint16_t)(
   6348                 ((conf->mpls_control.labels[9].value >> 12) & 0x00f0) | 
   6349                 ((conf->mpls_control.labels[8].value >> 16) & 0x000f))));
   6350 
   6351         SOC_IF_ERROR_RETURN
   6352             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66b, (buint16_t)(
   6353                 ((conf->mpls_control.labels[3].mask >> 4)  & 0xf000) | 
   6354                 ((conf->mpls_control.labels[2].mask >> 8)  & 0x0f00) | 
   6355                 ((conf->mpls_control.labels[1].mask >> 12) & 0x00f0) | 
   6356                 ((conf->mpls_control.labels[0].mask >> 16) & 0x000f))));
   6357 
   6358         SOC_IF_ERROR_RETURN
   6359             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66c, (buint16_t)(
   6360                 ((conf->mpls_control.labels[7].mask >> 4)  & 0xf000) | 
   6361                 ((conf->mpls_control.labels[6].mask >> 8)  & 0x0f00) | 
   6362                 ((conf->mpls_control.labels[5].mask >> 12) & 0x00f0) | 
   6363                 ((conf->mpls_control.labels[4].mask >> 16) & 0x000f))));
   6364 
   6365         SOC_IF_ERROR_RETURN
   6366             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66d, (buint16_t)(
   6367                 ((conf->mpls_control.labels[9].mask >> 12) & 0x00f0) | 
   6368                 ((conf->mpls_control.labels[8].mask >> 16) & 0x000f))));
   6369 
   6370         /* label flags */
   6371         temp = 0;
   6372         for (i = 0; i < 8; i++ ) {
   6373             temp |= conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT ? (0x2 << (i<<1)) : 0;
   6374             temp |= (conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN)  ? (0x1 << (i<<1)) : 0;
   6375         }
   6376 
   6377         SOC_IF_ERROR_RETURN
   6378             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66e, temp)); 
   6379 
   6380         temp = 0;
   6381         for (i = 0; i < 2; i++ ) {
   6382             temp |= (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT) ? (0x2 << (i<<1)) : 0;
   6383             temp |= (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN)  ? (0x1 << (i<<1)) : 0;
   6384         }
   6385 
   6386         SOC_IF_ERROR_RETURN
   6387             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66f, temp)); 
   6388     }
   6389 
   6390 
   6391     return SOC_E_NONE;
   6392 }
   6393 
   6394 int
   6395 phy_84756_fcmap_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf)
   6396 {
   6397     buint16_t rx_tx_control_reg = 0, tx_control_reg = 0,
   6398               en_control_reg = 0, capture_en_reg = 0,
   6399               nse_sc_8 = 0, nse_nco_3 = 0, temp1, temp2, temp3, value, mpls_control_reg;
   6400     soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   6401     soc_port_phy_timesync_framesync_mode_t framesync_mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE;
   6402     soc_port_phy_timesync_syncout_mode_t syncout_mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   6403     int i;
   6404     phy_ctrl_t *pc;
   6405 
   6406     pc = EXT_PHY_SW_STATE(unit, port);
   6407 
   6408     conf->flags = 0;
   6409 
   6410     /* NSE SC 8 register */
   6411     SOC_IF_ERROR_RETURN
   6412         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, &nse_sc_8));
   6413 
   6414     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   6415         /* SLICE ENABLE CONTROL register */
   6416         SOC_IF_ERROR_RETURN
   6417             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc600, &en_control_reg)); 
   6418 
   6419         if (en_control_reg & 1U) {
   6420             conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE;
   6421         }
   6422 
   6423         /* TXRX SOP TS CAPTURE ENABLE reg */
   6424         SOC_IF_ERROR_RETURN
   6425             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc607, &capture_en_reg)); 
   6426 
   6427         if (capture_en_reg & 1U) {
   6428             conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE;
   6429         }
   6430 
   6431         /* NSE SC 8 register */
   6432         /* SOC_IF_ERROR_RETURN
   6433             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, &nse_sc_8));
   6434          */
   6435 
   6436         if (nse_sc_8 & (1U << 13)) {
   6437             conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE;
   6438         }
   6439 
   6440          /* RX TX CONTROL register */
   6441         SOC_IF_ERROR_RETURN
   6442             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc61c, &rx_tx_control_reg));
   6443 
   6444         if (rx_tx_control_reg & (1U << 3)) {
   6445             conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE;
   6446         }
   6447 
   6448         /* TX CONTROL register */
   6449         SOC_IF_ERROR_RETURN
   6450             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc618, &tx_control_reg));
   6451                                           
   6452         if (tx_control_reg & (1U << 3)) {
   6453             conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE;
   6454         }
   6455 
   6456         if (tx_control_reg & (1U << 2)) {
   6457             conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE;
   6458         }
   6459 
   6460         if (tx_control_reg & (1U << 1)) {
   6461             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE;
   6462         }
   6463 
   6464         if (tx_control_reg & (1U << 0)) {
   6465             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE;
   6466         }
   6467 
   6468         SOC_IF_ERROR_RETURN
   6469             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc630, &nse_nco_3));
   6470 
   6471         if (!(nse_nco_3 & (1U << 14))) {
   6472             conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT;
   6473         }
   6474     }
   6475 
   6476     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   6477         _phy_84756_fcmap_decode_gmode((nse_sc_8 >> 14),&gmode);
   6478         conf->gmode = gmode;
   6479     }
   6480 
   6481     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   6482         _phy_84756_fcmap_decode_framesync_mode((nse_sc_8 >> 2), &framesync_mode);
   6483         conf->framesync.mode = framesync_mode;
   6484         SOC_IF_ERROR_RETURN
   6485             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63c, &temp1));
   6486         SOC_IF_ERROR_RETURN
   6487             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63b, &temp2));
   6488         conf->framesync.length_threshold = temp1;
   6489         conf->framesync.event_offset = temp2;
   6490     }
   6491 
   6492     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   6493         _phy_84756_fcmap_decode_syncout_mode((nse_sc_8 >> 2), &syncout_mode);
   6494         conf->syncout.mode = syncout_mode;
   6495 
   6496         SOC_IF_ERROR_RETURN
   6497             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc635, &temp1));
   6498         SOC_IF_ERROR_RETURN
   6499             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc634, &temp2));
   6500         SOC_IF_ERROR_RETURN
   6501             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc633, &temp3));
   6502 
   6503         conf->syncout.pulse_1_length =  ((temp3 & 0x7f) << 2) | ((temp2 >> 14) & 0x3);
   6504         conf->syncout.pulse_2_length = (temp3 >> 7) & 0x1ff;
   6505         conf->syncout.interval =  ((temp2 & 0x3fff) << 16) | temp1;
   6506 
   6507         SOC_IF_ERROR_RETURN
   6508             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc639, &temp1));
   6509         SOC_IF_ERROR_RETURN
   6510             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc638, &temp2));
   6511         SOC_IF_ERROR_RETURN
   6512             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc637, &temp3));
   6513 
   6514         COMPILER_64_SET(conf->syncout.syncout_ts, ((buint32_t)temp3), (((buint32_t)temp2<<16)|((buint32_t)temp1)));
   6515     }
   6516 
   6517     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   6518         /* VLAN TAG register */
   6519         SOC_IF_ERROR_RETURN
   6520             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc61d, &conf->itpid));
   6521     }
   6522 
   6523     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   6524         /* OUTER VLAN TAG register */
   6525         SOC_IF_ERROR_RETURN
   6526             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc61e, &conf->otpid));
   6527     }
   6528 
   6529     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   6530         /* INNER VLAN TAG register */
   6531         SOC_IF_ERROR_RETURN
   6532             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc61f, &conf->otpid2));
   6533     }
   6534 
   6535     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   6536         SOC_IF_ERROR_RETURN
   6537             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc636, &conf->ts_divider));
   6538         conf->ts_divider &= 0xfff;
   6539     }
   6540 
   6541     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   6542         SOC_IF_ERROR_RETURN
   6543             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc605, &temp1));
   6544         SOC_IF_ERROR_RETURN
   6545             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc606, &temp2));
   6546 
   6547         conf->rx_link_delay = ((buint32_t)temp2 << 16) | temp1; 
   6548     }
   6549 
   6550     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   6551         /* TIME CODE 5 register */
   6552         SOC_IF_ERROR_RETURN
   6553             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc610, &temp1));
   6554 
   6555         /* TIME CODE 4 register */
   6556         SOC_IF_ERROR_RETURN
   6557             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60f, &temp2));
   6558 
   6559         conf->original_timecode.nanoseconds = ((buint32_t)temp2 << 16) | temp1; 
   6560 
   6561         /* TIME CODE 3 register */
   6562         SOC_IF_ERROR_RETURN
   6563             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60e, &temp1));
   6564 
   6565         /* TIME CODE 2 register */
   6566         SOC_IF_ERROR_RETURN
   6567             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60d, &temp2));
   6568 
   6569         /* TIME CODE 1 register */
   6570         SOC_IF_ERROR_RETURN
   6571             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60c, &temp3));
   6572 
   6573         /* conf->original_timecode.seconds = ((uint64)temp3 << 32) | ((buint32_t)temp2 << 16) | temp1; */
   6574 
   6575         COMPILER_64_SET(conf->original_timecode.seconds, ((buint32_t)temp3),  (((buint32_t)temp2<<16)|((buint32_t)temp1)));
   6576     }
   6577 
   6578     /* TXRX TS OFFSET register */
   6579     SOC_IF_ERROR_RETURN
   6580         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, &temp1));
   6581 
   6582     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   6583     /* RX TS OFFSET register */
   6584         SOC_IF_ERROR_RETURN
   6585             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60b, &temp2));
   6586         conf->rx_timestamp_offset = (((buint32_t)(temp1 & 0xf000)) << 4) | temp2;
   6587     }
   6588 
   6589     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   6590         conf->tx_timestamp_offset = temp1 & 0xfff;
   6591     }
   6592 
   6593     /* TX EVENT MESSAGE MODE SEL register */
   6594     SOC_IF_ERROR_RETURN
   6595         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc601, &value)); 
   6596 
   6597     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   6598         _phy_84756_fcmap_decode_egress_message_mode(value, 0, &conf->tx_sync_mode);
   6599     }
   6600 
   6601     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   6602         _phy_84756_fcmap_decode_egress_message_mode(value, 2, &conf->tx_delay_request_mode);
   6603     }
   6604 
   6605     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   6606         _phy_84756_fcmap_decode_egress_message_mode(value, 4, &conf->tx_pdelay_request_mode);
   6607     }
   6608 
   6609     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   6610         _phy_84756_fcmap_decode_egress_message_mode(value, 6, &conf->tx_pdelay_response_mode);
   6611     }
   6612                                             
   6613     /* RX EVENT MESSAGE MODE SEL register */
   6614     SOC_IF_ERROR_RETURN
   6615         (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc603, &value)); 
   6616 
   6617     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   6618         _phy_84756_fcmap_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode);
   6619     }
   6620 
   6621     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   6622         _phy_84756_fcmap_decode_ingress_message_mode(value, 2, &conf->rx_delay_request_mode);
   6623     }
   6624 
   6625     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   6626         _phy_84756_fcmap_decode_ingress_message_mode(value, 4, &conf->rx_pdelay_request_mode);
   6627     }
   6628 
   6629     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   6630         _phy_84756_fcmap_decode_ingress_message_mode(value, 6, &conf->rx_pdelay_response_mode);
   6631     }
   6632                                             
   6633     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   6634         /* Initial ref phase [15:0] */
   6635         SOC_IF_ERROR_RETURN
   6636             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc623, &temp1));
   6637 
   6638         /* Initial ref phase [31:16] */
   6639         SOC_IF_ERROR_RETURN
   6640             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc622, &temp2));
   6641 
   6642         /* Initial ref phase [47:32] */
   6643         SOC_IF_ERROR_RETURN
   6644             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc621, &temp3));
   6645 
   6646         /* conf->phy_1588_dpll_phase_initial = ((uint64)temp3 << 32) | ((buint32_t)temp2 << 16) | temp1; */
   6647 
   6648         COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((buint32_t)temp3), (((buint32_t)temp2<<16)|((buint32_t)temp1)));
   6649     }
   6650 
   6651     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   6652         SOC_IF_ERROR_RETURN
   6653             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc625, &temp1));
   6654         SOC_IF_ERROR_RETURN
   6655             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc624, &temp2));
   6656 
   6657         conf->phy_1588_dpll_ref_phase_delta = ((buint32_t)temp2 << 16) | temp1; 
   6658     }
   6659 
   6660     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   6661         /* DPLL K1 */
   6662         SOC_IF_ERROR_RETURN
   6663             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc626, &conf->phy_1588_dpll_k1)); 
   6664         conf->phy_1588_dpll_k1 &= 0xff;
   6665     }
   6666 
   6667     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   6668         /* DPLL K2 */
   6669         SOC_IF_ERROR_RETURN
   6670             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc627, &conf->phy_1588_dpll_k2)); 
   6671         conf->phy_1588_dpll_k2 &= 0xff;
   6672     }
   6673 
   6674     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   6675         /* DPLL K3 */
   6676         SOC_IF_ERROR_RETURN
   6677             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc628, &conf->phy_1588_dpll_k3)); 
   6678         conf->phy_1588_dpll_k3 &= 0xff;
   6679     }
   6680 
   6681     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) {
   6682         SOC_IF_ERROR_RETURN
   6683             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc651, &mpls_control_reg));
   6684                                           
   6685         conf->mpls_control.flags = 0;
   6686 
   6687         if (mpls_control_reg & (1U << 7)) {
   6688             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE;
   6689         }
   6690 
   6691         if (mpls_control_reg & (1U << 6)) {
   6692             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE;
   6693         }
   6694 
   6695         if (mpls_control_reg & (1U << 4)) {
   6696             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE;
   6697         }
   6698 
   6699         if (mpls_control_reg & (1U << 5)) {
   6700             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE;
   6701         }
   6702 
   6703         /* special label [19:16] */
   6704         SOC_IF_ERROR_RETURN
   6705             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc653, &temp2));
   6706                                           
   6707         /* special label [15:0] */
   6708         SOC_IF_ERROR_RETURN
   6709             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc652, &temp1));
   6710 
   6711         conf->mpls_control.special_label = ((buint32_t)(temp2 & 0x0f) << 16) | temp1; 
   6712 
   6713 
   6714         for (i = 0; i < 10; i++ ) {
   6715 
   6716             SOC_IF_ERROR_RETURN
   6717                 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc654 + i, &temp1));
   6718             conf->mpls_control.labels[i].value = temp1;
   6719 
   6720             SOC_IF_ERROR_RETURN
   6721                 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc661 + i, &temp1));
   6722             conf->mpls_control.labels[i].mask = temp1;
   6723         }
   6724  
   6725         /* now get [19:16] of labels */
   6726         SOC_IF_ERROR_RETURN
   6727             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc65e, &temp1));
   6728 
   6729         conf->mpls_control.labels[0].value |= ((buint32_t)(temp1 & 0x000f) << 16); 
   6730         conf->mpls_control.labels[1].value |= ((buint32_t)(temp1 & 0x00f0) << 12); 
   6731         conf->mpls_control.labels[2].value |= ((buint32_t)(temp1 & 0x0f00) << 8); 
   6732         conf->mpls_control.labels[3].value |= ((buint32_t)(temp1 & 0xf000) << 4); 
   6733 
   6734 
   6735         SOC_IF_ERROR_RETURN
   6736             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc65f, &temp1));
   6737 
   6738         conf->mpls_control.labels[4].value |= ((buint32_t)(temp1 & 0x000f) << 16); 
   6739         conf->mpls_control.labels[5].value |= ((buint32_t)(temp1 & 0x00f0) << 12); 
   6740         conf->mpls_control.labels[6].value |= ((buint32_t)(temp1 & 0x0f00) << 8); 
   6741         conf->mpls_control.labels[7].value |= ((buint32_t)(temp1 & 0xf000) << 4); 
   6742 
   6743 
   6744         SOC_IF_ERROR_RETURN
   6745             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc660, &temp1));
   6746 
   6747         conf->mpls_control.labels[8].value |= ((buint32_t)(temp1 & 0x000f) << 16); 
   6748         conf->mpls_control.labels[9].value |= ((buint32_t)(temp1 & 0x00f0) << 12); 
   6749 
   6750         /* now get [19:16] of masks */
   6751         SOC_IF_ERROR_RETURN
   6752             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66b, &temp1));
   6753 
   6754         conf->mpls_control.labels[0].mask |= ((buint32_t)(temp1 & 0x000f) << 16); 
   6755         conf->mpls_control.labels[1].mask |= ((buint32_t)(temp1 & 0x00f0) << 12); 
   6756         conf->mpls_control.labels[2].mask |= ((buint32_t)(temp1 & 0x0f00) << 8); 
   6757         conf->mpls_control.labels[3].mask |= ((buint32_t)(temp1 & 0xf000) << 4); 
   6758 
   6759 
   6760         SOC_IF_ERROR_RETURN
   6761             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66c, &temp1));
   6762 
   6763         conf->mpls_control.labels[4].mask |= ((buint32_t)(temp1 & 0x000f) << 16); 
   6764         conf->mpls_control.labels[5].mask |= ((buint32_t)(temp1 & 0x00f0) << 12); 
   6765         conf->mpls_control.labels[6].mask |= ((buint32_t)(temp1 & 0x0f00) << 8); 
   6766         conf->mpls_control.labels[7].mask |= ((buint32_t)(temp1 & 0xf000) << 4); 
   6767 
   6768 
   6769         SOC_IF_ERROR_RETURN
   6770             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66d, &temp1));
   6771 
   6772         conf->mpls_control.labels[8].mask |= ((buint32_t)(temp1 & 0x000f) << 16); 
   6773         conf->mpls_control.labels[9].mask |= ((buint32_t)(temp1 & 0x00f0) << 12); 
   6774 
   6775 
   6776         /* label flags */
   6777         SOC_IF_ERROR_RETURN
   6778             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66e, &temp1)); 
   6779         for (i = 0; i < 8; i++ ) {
   6780             conf->mpls_control.labels[i].flags |= temp1 & (0x2 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT : 0;
   6781             conf->mpls_control.labels[i].flags |= temp1 & (0x1 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN : 0;
   6782         }
   6783         SOC_IF_ERROR_RETURN
   6784             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66f, &temp2)); 
   6785         for (i = 0; i < 2; i++ ) {
   6786             conf->mpls_control.labels[i + 8].flags |= temp2 & (0x2 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT : 0;
   6787             conf->mpls_control.labels[i + 8].flags |= temp2 & (0x1 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN : 0;
   6788         }
   6789 
   6790     }
   6791     return SOC_E_NONE;
   6792 }
   6793 
   6794 int
   6795 phy_84756_fcmap_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 value)
   6796 {
   6797     buint16_t temp1, temp2; 
   6798     buint32_t value0;
   6799     phy_ctrl_t *pc;
   6800 
   6801     pc = EXT_PHY_SW_STATE(unit, port);
   6802 
   6803     switch (type) {
   6804 
   6805     case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   6806     case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   6807         return SOC_E_FAIL;
   6808 
   6809 
   6810     case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   6811         SOC_IF_ERROR_RETURN
   6812             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc62f, (buint16_t)(COMPILER_64_LO(value) & 0xffff)));
   6813         SOC_IF_ERROR_RETURN
   6814             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc62e, (buint16_t)((COMPILER_64_LO(value) >> 16) & 0xffff)));
   6815         break;
   6816 
   6817     case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC:
   6818 
   6819         SOC_IF_ERROR_RETURN
   6820             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, &temp1));
   6821         temp2 = ((temp1 | (0x3 << 14) | (0x1 << 12)) & ~(0xf << 2)) | (0x1 << 5);
   6822         SOC_IF_ERROR_RETURN
   6823             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, temp2));
   6824         sal_usleep(1);
   6825         temp2 &= ~((0x1 << 5) | (0x1 << 12));
   6826         SOC_IF_ERROR_RETURN
   6827             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, temp2));
   6828         sal_usleep(1);
   6829         SOC_IF_ERROR_RETURN
   6830             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, temp1));
   6831         break;
   6832 
   6833     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   6834         SOC_IF_ERROR_RETURN
   6835             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc632, (buint16_t)(COMPILER_64_LO(value) & 0xffff)));
   6836         SOC_IF_ERROR_RETURN
   6837             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc631, (buint16_t)((COMPILER_64_LO(value) >> 16) & 0xffff)));
   6838         SOC_IF_ERROR_RETURN
   6839             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc630, (buint16_t)COMPILER_64_HI(value), 0x0fff));
   6840         break;
   6841 
   6842     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   6843         temp1 = 0;
   6844         temp2 = 0;
   6845 
   6846         value0 = COMPILER_64_LO(value);
   6847 
   6848         if (value0 &  SOC_PORT_PHY_TIMESYNC_TN_LOAD) {
   6849             temp1 |= 1U << 11;
   6850         }
   6851         if (value0 &  SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) {
   6852             temp2 |= 1U << 11;
   6853         }
   6854         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) {
   6855             temp1 |= 1U << 10;
   6856         }
   6857         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) {
   6858             temp2 |= 1U << 10;
   6859         }
   6860         if (value0 &  SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) {
   6861             temp1 |= 1U << 9;
   6862         }
   6863         if (value0 &  SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) {
   6864             temp2 |= 1U << 9;
   6865         }
   6866         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) {
   6867             temp1 |= 1U << 8;
   6868         }
   6869         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) {
   6870             temp2 |= 1U << 8;
   6871         }
   6872         if (value0 &  SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) {
   6873             temp1 |= 1U << 7;
   6874         }
   6875         if (value0 &  SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) {
   6876             temp2 |= 1U << 7;
   6877         }
   6878         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) {
   6879             temp1 |= 1U << 6;
   6880         }
   6881         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) {
   6882             temp2 |= 1U << 6;
   6883         }
   6884         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) {
   6885             temp1 |= 1U << 5;
   6886         }
   6887         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) {
   6888             temp2 |= 1U << 5;
   6889         }
   6890         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) {
   6891             temp1 |= 1U << 4;
   6892         }
   6893         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) {
   6894             temp2 |= 1U << 4;
   6895         }
   6896         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) {
   6897             temp1 |= 1U << 3;
   6898         }
   6899         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) {
   6900             temp2 |= 1U << 3;
   6901         }
   6902         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) {
   6903             temp1 |= 1U << 2;
   6904         }
   6905         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) {
   6906             temp2 |= 1U << 2;
   6907         }
   6908         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) {
   6909             temp1 |= 1U << 1;
   6910         }
   6911         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) {
   6912             temp2 |= 1U << 1;
   6913         }
   6914         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) {
   6915             temp1 |= 1U << 0;
   6916         }
   6917         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) {
   6918             temp2 |= 1U << 0;
   6919         }
   6920         SOC_IF_ERROR_RETURN
   6921             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc614, temp1));
   6922         SOC_IF_ERROR_RETURN
   6923             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc615, temp2));
   6924 
   6925         break;
   6926 
   6927     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT:
   6928         temp1 = 0;
   6929 
   6930         value0 = COMPILER_64_LO(value);
   6931 
   6932         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT) {
   6933             temp1 |= 1U << 1;
   6934         }
   6935         if (value0 &  SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT) {
   6936             temp1 |= 1U << 0;
   6937         }
   6938         SOC_IF_ERROR_RETURN
   6939             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc617, temp1));
   6940         break;
   6941 
   6942     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   6943         temp1 = 0;
   6944 
   6945         value0 = COMPILER_64_LO(value);
   6946 
   6947         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) {
   6948             temp1 |= 1U << 1;
   6949         }
   6950         if (value0 &  SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) {
   6951             temp1 |= 1U << 0;
   6952         }
   6953         SOC_IF_ERROR_RETURN
   6954             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc616, temp1));
   6955         break;
   6956 
   6957     case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   6958         value0 = COMPILER_64_LO(value);
   6959 
   6960         SOC_IF_ERROR_RETURN
   6961             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, (buint16_t)(value0 & 0x0fff), 0x0fff));
   6962         break;
   6963 
   6964     case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   6965         value0 = COMPILER_64_LO(value);
   6966 
   6967         SOC_IF_ERROR_RETURN
   6968             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60b, (buint16_t)(value0 & 0xffff)));
   6969         SOC_IF_ERROR_RETURN
   6970             (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, (buint16_t)((value0 >> 4) & 0xf000), 0xf000));
   6971         break;
   6972 
   6973     default:
   6974         return SOC_E_NONE;
   6975         break;
   6976     }
   6977 
   6978     return SOC_E_NONE;
   6979 }
   6980 
   6981 int
   6982 phy_84756_fcmap_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 *value)
   6983 {
   6984     buint16_t value0 = 0;
   6985     buint16_t value1 = 0;
   6986     buint16_t value2 = 0;
   6987     buint16_t value3 = 0;
   6988     phy_ctrl_t *pc;
   6989 
   6990     pc = EXT_PHY_SW_STATE(unit, port);
   6991 
   6992     switch (type) {
   6993     case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   6994 
   6995         SOC_IF_ERROR_RETURN
   6996             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x4));
   6997 
   6998         SOC_IF_ERROR_RETURN
   6999             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc647, &value0)); 
   7000         SOC_IF_ERROR_RETURN
   7001             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc646, &value1)); 
   7002         SOC_IF_ERROR_RETURN
   7003             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc645, &value2)); 
   7004 
   7005         SOC_IF_ERROR_RETURN
   7006             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x8));
   7007         SOC_IF_ERROR_RETURN
   7008             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x0));
   7009 
   7010     /*    *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */
   7011         COMPILER_64_SET((*value), (((buint32_t)value3<<16)|((buint32_t)value2)),  (((buint32_t)value1<<16)|((buint32_t)value0)));
   7012         break;
   7013 
   7014     case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   7015 
   7016         SOC_IF_ERROR_RETURN
   7017             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x1));
   7018 
   7019         SOC_IF_ERROR_RETURN
   7020             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc640, &value0)); 
   7021         SOC_IF_ERROR_RETURN
   7022             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63f, &value1)); 
   7023         SOC_IF_ERROR_RETURN
   7024             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63e, &value2)); 
   7025 
   7026         SOC_IF_ERROR_RETURN
   7027             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x2));
   7028         SOC_IF_ERROR_RETURN
   7029             (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x0));
   7030 
   7031     /*   *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */
   7032         COMPILER_64_SET((*value), (((buint32_t)value3<<16)|((buint32_t)value2)),  (((buint32_t)value1<<16)|((buint32_t)value0)));
   7033         break;
   7034 
   7035     case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   7036         SOC_IF_ERROR_RETURN
   7037             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc62f, &value0));
   7038         SOC_IF_ERROR_RETURN
   7039             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc62e, &value1));
   7040         COMPILER_64_SET((*value), (buint32_t)value1, (buint32_t)value0);
   7041         break;
   7042 
   7043     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   7044         SOC_IF_ERROR_RETURN
   7045             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc632, &value0)); 
   7046         SOC_IF_ERROR_RETURN
   7047             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc631, &value1)); 
   7048         SOC_IF_ERROR_RETURN
   7049             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc630, &value2)); 
   7050 
   7051         COMPILER_64_SET((*value), ((buint32_t)(value2 & 0x0fff)),  (((buint32_t)value1<<16)|((buint32_t)value0)));
   7052         break;
   7053 
   7054     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   7055 
   7056         SOC_IF_ERROR_RETURN
   7057             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0x2e, &value1));
   7058         SOC_IF_ERROR_RETURN
   7059             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0x2f, &value2));
   7060 
   7061         value0 = 0;
   7062 
   7063         if (value1 & (1U << 11)) {
   7064             value0 |= SOC_PORT_PHY_TIMESYNC_TN_LOAD;
   7065         }
   7066         if (value2 & (1U << 11)) {
   7067             value0 |= SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD;
   7068         }
   7069         if (value1 & (1U << 10)) {
   7070             value0 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD;
   7071         }
   7072         if (value2 & (1U << 10)) {
   7073             value0 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD;
   7074         }
   7075         if (value1 & (1U << 9)) {
   7076             value0 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD;
   7077         }
   7078         if (value2 & (1U << 9)) {
   7079             value0 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD;
   7080         }
   7081         if (value1 & (1U << 8)) {
   7082             value0 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD;
   7083         }
   7084         if (value1 & (1U << 8)) {
   7085             value0 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD;
   7086         }
   7087         if (value1 & (1U << 7)) {
   7088             value0 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD;
   7089         }
   7090         if (value1 & (1U << 7)) {
   7091             value0 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD;
   7092         }
   7093         if (value1 & (1U << 6)) {
   7094             value0 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD;
   7095         }
   7096         if (value2 & (1U << 6)) {
   7097             value0 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD;
   7098         }
   7099         if (value1 & (1U << 5)) {
   7100             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD;
   7101         }
   7102         if (value2 & (1U << 5)) {
   7103             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD;
   7104         }
   7105         if (value1 & (1U << 4)) {
   7106             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD;
   7107         }
   7108         if (value2 & (1U << 4)) {
   7109             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD;
   7110         }
   7111         if (value1 & (1U << 3)) {
   7112             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD;
   7113         }
   7114         if (value2 & (1U << 3)) {
   7115             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD;
   7116         }
   7117         if (value1 & (1U << 2)) {
   7118             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD;
   7119         }
   7120         if (value2 & (1U << 2)) {
   7121             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD;
   7122         }
   7123         if (value1 & (1U << 1)) {
   7124             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD;
   7125         }
   7126         if (value2 & (1U << 1)) {
   7127             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD;
   7128         }
   7129         if (value1 & (1U << 0)) {
   7130             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD;
   7131         }
   7132         if (value2 & (1U << 0)) {
   7133             value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD;
   7134         }
   7135         COMPILER_64_SET((*value), 0, (buint32_t)value0);
   7136 
   7137         break;
   7138 
   7139     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT:
   7140         SOC_IF_ERROR_RETURN
   7141             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc617, &value1));
   7142 
   7143         value0 = 0;
   7144 
   7145         if (value1 & (1U << 1)) {
   7146             value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT;
   7147         }
   7148         if (value1 & (1U << 0)) {
   7149             value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT;
   7150         }
   7151         COMPILER_64_SET((*value), 0, (buint32_t)value0);
   7152 
   7153         break;
   7154 
   7155     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   7156         SOC_IF_ERROR_RETURN
   7157             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc616, &value1));
   7158 
   7159         value0 = 0;
   7160 
   7161         if (value1 & (1U << 1)) {
   7162             value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK;
   7163         }
   7164         if (value1 & (1U << 0)) {
   7165             value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK;
   7166         }
   7167         COMPILER_64_SET((*value), 0, (buint32_t)value0);
   7168 
   7169         break;
   7170 
   7171     case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   7172         SOC_IF_ERROR_RETURN
   7173             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, &value0));
   7174 
   7175         COMPILER_64_SET((*value), 0, (buint32_t)(value0 & 0x0fff));
   7176         break;
   7177 
   7178     case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   7179         SOC_IF_ERROR_RETURN
   7180             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60b, &value0));
   7181 
   7182         SOC_IF_ERROR_RETURN
   7183             (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, &value1));
   7184 
   7185         COMPILER_64_SET((*value), 0, (buint32_t)(((((buint32_t)value1) << 4) & 0xf0000) | value0));
   7186         break;
   7187 
   7188     default:
   7189         return SOC_E_FAIL;
   7190     }
   7191 
   7192     return SOC_E_NONE;
   7193 }
   7194 
   7195 int
   7196 bfcmap_phy84756_reg_read(phy_ctrl_t *  pc, buint32_t flags, buint8_t reg_bank,
   7197                           buint16_t reg_addr, buint16_t *data)
   7198 {
   7199     int rv;
   7200     buint16_t reg_data, xpmd_reg_sel = 0xffff;
   7201     buint32_t cl45_reg_addr;
   7202 
   7203 
   7204     rv = SOC_E_NONE;
   7205 
   7206     if (flags & BFCMAP_PHY84756_SYS_SIDE) {
   7207         /* Select System side registers */
   7208         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel);
   7209         reg_data = 0x01;
   7210         SOC_IF_ERROR_RETURN(
   7211             BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   7212 
   7213         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr);
   7214         rv = BFCMAP_PHY84756_IO_MDIO_READ(pc, cl45_reg_addr, data);
   7215 
   7216         /* De-Select System side registers */
   7217         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel);
   7218         reg_data = 0x0;
   7219         SOC_IF_ERROR_RETURN(
   7220             BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   7221 
   7222     } else {
   7223         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr);
   7224         rv = BFCMAP_PHY84756_IO_MDIO_READ(pc, cl45_reg_addr, data);
   7225     }
   7226 
   7227     return rv;
   7228 }
   7229 
   7230 int
   7231 bfcmap_phy84756_reg_write(phy_ctrl_t *  pc, buint32_t flags, buint8_t reg_bank,
   7232                            buint16_t reg_addr, buint16_t data)
   7233 {
   7234     int rv;
   7235     buint16_t reg_data, xpmd_reg_sel = 0xffff;
   7236     buint32_t cl45_reg_addr;
   7237 
   7238     rv = SOC_E_NONE;
   7239 
   7240     if (flags & BFCMAP_PHY84756_SYS_SIDE) {
   7241         /* Select System side registers */
   7242         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel);
   7243         reg_data = 0x01;
   7244         SOC_IF_ERROR_RETURN(
   7245             BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   7246 
   7247         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr);
   7248         rv = BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, data);
   7249 
   7250         /* De-Select System side registers */
   7251         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel);
   7252         reg_data = 0x00;
   7253         SOC_IF_ERROR_RETURN(
   7254             BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   7255     } else {
   7256         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr);
   7257         rv = BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, data);
   7258     }
   7259 
   7260     return rv;
   7261 }
   7262 
   7263 
   7264 int
   7265 bfcmap_phy84756_reg_modify(phy_ctrl_t *  pc, buint32_t flags, buint8_t reg_bank,
   7266                             buint16_t reg_addr, buint16_t data, buint16_t mask)
   7267 {
   7268     buint16_t  tmp, otmp, reg_data;
   7269     buint32_t cl45_reg_addr = 0;
   7270     buint16_t xpmd_reg_sel = 0xffff;
   7271 
   7272 #if defined (BCM_WARM_BOOT_SUPPORT)  /*  */
   7273     if ( SOC_WARM_BOOT(pc->unit) || SOC_IS_RELOADING(pc->unit) ) {
   7274         return SOC_E_NONE;
   7275     }
   7276 #endif /* BCM_WARM_BOOT_SUPPORT */
   7277 
   7278 
   7279     if (flags & BFCMAP_PHY84756_SYS_SIDE) {
   7280         /* Select System side registers */
   7281         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel);
   7282         reg_data = 0x01;
   7283         SOC_IF_ERROR_RETURN(
   7284             BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data));
   7285 
   7286         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr);
   7287 
   7288         SOC_IF_ERROR_RETURN
   7289             (BFCMAP_PHY84756_IO_MDIO_READ(pc, cl45_reg_addr, &tmp));
   7290 
   7291         reg_data = data & mask; /* Mask off other bits */
   7292         otmp = tmp;
   7293         tmp &= ~(mask);
   7294         tmp |= reg_data;
   7295 
   7296         if (otmp != tmp) {
   7297             SOC_IF_ERROR_RETURN
   7298                 (BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, tmp));
   7299         }
   7300 
   7301         /* De-Select System side registers */
   7302         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel);
   7303         data = 0x00;
   7304         SOC_IF_ERROR_RETURN(
   7305             BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, data));
   7306 
   7307     } else {
   7308         cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr);
   7309 
   7310         SOC_IF_ERROR_RETURN
   7311             (BFCMAP_PHY84756_IO_MDIO_READ(pc, cl45_reg_addr, &tmp));
   7312 
   7313         reg_data = data & mask; /* Mask off other bits */
   7314         otmp = tmp;
   7315         tmp &= ~(mask);
   7316         tmp |= reg_data;
   7317 
   7318         if (otmp != tmp) {
   7319             SOC_IF_ERROR_RETURN
   7320                 (BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, tmp));
   7321         }
   7322     }
   7323     return SOC_E_NONE;
   7324 }
   7325 
   7326 
   7327 
   7328 STATIC int 
   7329 phy_84756_fcmap_reg_read(int unit, soc_port_t port, uint32 flags,
   7330                                 uint32 phy_reg_addr, uint32 *phy_data)
   7331 {
   7332     uint16               data16;
   7333     uint16               regdata;
   7334     phy_ctrl_t          *pc;      /* PHY software state */
   7335     int rv = SOC_E_NONE;
   7336     int rd_cnt;
   7337 
   7338     pc = EXT_PHY_SW_STATE(unit, port);
   7339 
   7340     /* 40G reg read */
   7341     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   7342         PHY_REG_READ(PHY84756_40G, unit, port, flags, phy_reg_addr, phy_data));
   7343 
   7344     rd_cnt = 1;
   7345 
   7346     if (flags & SOC_PHY_I2C_DATA8) {
   7347 
   7348         SOC_IF_ERROR_RETURN
   7349             (phy_84756_i2cdev_read(pc,
   7350                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
   7351                         SOC_PHY_I2C_REGAD(phy_reg_addr),
   7352                         rd_cnt,
   7353                         (uint8 *)&data16));
   7354         *phy_data = *((uint8 *)&data16);
   7355 
   7356     } else if (flags & SOC_PHY_I2C_DATA16) {
   7357         /* This operation is generally targeted to access 16-bit device,
   7358          * such as PHY IC inside the SFP.  However there is no 16-bit
   7359          * scratch register space on the device.  Use 1.800e
   7360          * for this operation.
   7361          */
   7362         SOC_IF_ERROR_RETURN
   7363             (READ_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM,
   7364                    &regdata));
   7365 
   7366         rv = _phy_84756_bsc_rw(pc,
   7367                SOC_PHY_I2C_DEVAD(phy_reg_addr),
   7368                PHY84756_I2C_OP_TYPE(PHY84756_I2CDEV_READ,PHY84756_I2C_16BIT),
   7369                SOC_PHY_I2C_REGAD(phy_reg_addr),1,
   7370                (void *)&data16,PHY84756_I2C_TEMP_RAM);
   7371 
   7372         *phy_data = data16;
   7373 
   7374         /* restore the ram register value */
   7375         SOC_IF_ERROR_RETURN
   7376             (WRITE_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM,
   7377                  regdata));
   7378     } else {
   7379         SOC_IF_ERROR_RETURN
   7380             (READ_PHY_REG(unit, pc, phy_reg_addr, &data16));
   7381         *phy_data = data16;
   7382     }
   7383 
   7384     return rv;
   7385 
   7386 }
   7387 
   7388 
   7389 
   7390 STATIC int
   7391 phy_84756_fcmap_reg_write(int unit, soc_port_t port, uint32 flags,
   7392                           uint32 phy_reg_addr, uint32 phy_data)
   7393 {
   7394     uint8  data8[4];
   7395     uint16 data16[2];
   7396     uint16 regdata[2];
   7397     phy_ctrl_t          *pc;      /* PHY software state */
   7398     int rv = SOC_E_NONE;
   7399     int wr_cnt;
   7400 
   7401 #if defined (BCM_WARM_BOOT_SUPPORT)  /*  */
   7402     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   7403         return SOC_E_NONE;
   7404     }
   7405 #endif /* BCM_WARM_BOOT_SUPPORT */
   7406 
   7407     pc = EXT_PHY_SW_STATE(unit, port);
   7408 
   7409     /* 40G reg write */
   7410     PHY84756_CALL_IF_SINGLE_PORT(unit, port,
   7411         PHY_REG_WRITE(PHY84756_40G, unit, port, flags, phy_reg_addr, phy_data));
   7412 
   7413 
   7414     wr_cnt = 1;
   7415 
   7416     if (flags & SOC_PHY_I2C_DATA8) {
   7417         data8[0] = (uint8)phy_data;
   7418         SOC_IF_ERROR_RETURN
   7419             (phy_84756_i2cdev_write(pc,
   7420                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
   7421                         SOC_PHY_I2C_REGAD(phy_reg_addr),
   7422                         wr_cnt,
   7423                         data8));
   7424     } else if (flags & SOC_PHY_I2C_DATA16) {
   7425 
   7426      /* This operation is generally targeted to access 16-bit device,
   7427          * such as PHY IC inside the SFP.  However there is no 16-bit
   7428          * scratch register space on the device.  Use 1.800e
   7429          * for this operation.
   7430          */
   7431         /* save the temp ram register */
   7432         SOC_IF_ERROR_RETURN
   7433             (READ_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM,
   7434                  &regdata[0]));
   7435         data16[0] = phy_data;
   7436         rv = _phy_84756_bsc_rw(pc,
   7437               SOC_PHY_I2C_DEVAD(phy_reg_addr),
   7438               PHY84756_I2C_OP_TYPE(PHY84756_I2CDEV_WRITE,PHY84756_I2C_16BIT),
   7439               SOC_PHY_I2C_REGAD(phy_reg_addr),wr_cnt,
   7440               (void *)data16,PHY84756_I2C_TEMP_RAM);
   7441 
   7442         /* restore the ram register value */
   7443         SOC_IF_ERROR_RETURN
   7444             (WRITE_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM,
   7445                   regdata[0]));
   7446     } else {
   7447         SOC_IF_ERROR_RETURN
   7448             (WRITE_PHY_REG(unit, pc, phy_reg_addr, (uint16)phy_data));
   7449     }
   7450     return rv;
   7451 }
   7452 
   7453 STATIC int
   7454 phy_84756_fcmap_squelch_enable(int unit, soc_port_t port, int intf, int enable, int force)
   7455 {
   7456     phy_ctrl_t     *pc;
   7457     int ix = 0;
   7458     uint16 data16 = 0, mask16 = 0;
   7459     uint16 speed_val = 0;
   7460 
   7461     pc = EXT_PHY_SW_STATE(unit, port);
   7462 
   7463     if (PHY84756_SINGLE_PORT_MODE(pc)) {
   7464         mask16 = (1 << 4) | (1 << 6) | (1 << 11);
   7465         data16 = enable ? mask16 : 0;
   7466 
   7467         for (ix = 0; ix < NUM_LANES; ix++) {
   7468             if (intf == PHY_DIAG_INTF_SYS) {
   7469                 SOC_IF_ERROR_RETURN(PHY84756_MMF(unit, pc));
   7470                 SOC_IF_ERROR_RETURN
   7471                     (BFCMAP_PHY84756_REG_WR(pc, 0x0, 0x1, 0xc702, ix));
   7472                 SOC_IF_ERROR_RETURN(PHY84756_XFI(unit, pc));
   7473                 SOC_IF_ERROR_RETURN
   7474                     (BFCMAP_PHY84756_REG_MOD(pc, 0x1, 0x1, 0xcd18, data16, mask16)); 
   7475             } else {
   7476                 SOC_IF_ERROR_RETURN
   7477                     (BFCMAP_PHY84756_REG_WR(pc, 0x0, 0x1, 0xc702, ix));
   7478                 SOC_IF_ERROR_RETURN
   7479                     (BFCMAP_PHY84756_REG_MOD(pc, 0x0, 0x1, 0xcd18, data16, mask16)); 
   7480             } 
   7481         }
   7482 
   7483         if (intf == PHY_DIAG_INTF_SYS) {
   7484             SOC_IF_ERROR_RETURN(PHY84756_MMF(unit, pc));
   7485             SOC_IF_ERROR_RETURN
   7486                 (BFCMAP_PHY84756_REG_WR(pc, 0x0, 0x1, 0xc702, 0));
   7487             SOC_IF_ERROR_RETURN(PHY84756_XFI(unit, pc));
   7488         } else { 
   7489             SOC_IF_ERROR_RETURN
   7490                 (BFCMAP_PHY84756_REG_WR(pc, 0x0, 0x1, 0xc702, 0));
   7491         } 
   7492     } else {
   7493         SOC_IF_ERROR_RETURN
   7494             (BFCMAP_RD_PHY84756_LN_DEV1_SPEED_LINK_DETECT_STATr(pc, &speed_val));
   7495 
   7496         if ((speed_val & BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_MASK) == 
   7497             BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_1G) {
   7498             mask16 = (1 << 3) | (1 << 5);
   7499             data16 = enable ? mask16 : 0;
   7500         }
   7501 
   7502         if ((speed_val & BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_MASK) ==
   7503             BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_10G) {
   7504             mask16 = (1 << 4) | (1 << 5);
   7505             data16 = enable ? mask16 : 0;
   7506         }
   7507         if (intf == PHY_DIAG_INTF_SYS) {  
   7508             SOC_IF_ERROR_RETURN
   7509                 (BFCMAP_PHY84756_REG_MOD(pc, 0x1, 0x1, 0xcd18, data16, mask16));
   7510             SOC_IF_ERROR_RETURN
   7511                 (BFCMAP_PHY84756_REG_MOD(pc, 0x1, 0x1, 0xcd16,
   7512                                                  force ? (1 << 3) : 0,
   7513                                                  (1 << 3)));
   7514         } else {
   7515             SOC_IF_ERROR_RETURN
   7516                 (BFCMAP_PHY84756_REG_MOD(pc, 0x0, 0x1, 0xcd18, data16, mask16));
   7517             SOC_IF_ERROR_RETURN
   7518                 (BFCMAP_PHY84756_REG_MOD(pc, 0x0, 0x1, 0xcd16,
   7519                                                  force ? (1 << 3) : 0,
   7520                                                  (1 << 3)));
   7521         } 
   7522     }
   7523     return SOC_E_NONE;
   7524 }
   7525 
   7526 /*
   7527  *   Callout interface to phy_84741_i2cdev_read(); 
   7528  *   TBD: Extend to handle max_size > PHY84740_BSC_XFER_MAX. 
   7529  */
   7530 
   7531 STATIC int
   7532 phy_84756_multi_get(int unit, soc_port_t port, uint32 flags,
   7533                  uint32 dev_addr, uint32 offset, int max_size, uint8 *data, int *actual_size)
   7534 {
   7535 
   7536     SOC_IF_ERROR_RETURN
   7537         (PHY_MULTI_GET(PHY84756_40G, unit, port, flags,
   7538                   dev_addr, offset, max_size, data, actual_size));
   7539 
   7540     return SOC_E_NONE;
   7541 }
   7542 
   7543 /*
   7544  * Variable:
   7545  *    phy_84756_fcmap_drv
   7546  * Purpose:
   7547  *    Phy Driver for BCM84756 FCMAP PHY
   7548  */
   7549 phy_driver_t phy_84756drv_fcmap_xe = {
   7550     "84756 1G/10-Gigabit PHY-FCMAP Driver",
   7551     phy_84756_fcmap_init,        /* Init */
   7552     phy_null_reset,       /* Reset */
   7553     phy_84756_fcmap_link_get,    /* Link get   */
   7554     phy_84756_fcmap_enable_set,  /* Enable set */
   7555     phy_null_enable_get,  /* Enable get */
   7556     phy_84756_fcmap_duplex_set,  /* Duplex set */
   7557     phy_84756_fcmap_duplex_get,  /* Duplex get */
   7558     phy_84756_fcmap_speed_set,   /* Speed set  */
   7559     phy_84756_fcmap_speed_get,   /* Speed get  */
   7560     phy_null_set,          /* Master set */
   7561     phy_null_zero_get,     /* Master get */
   7562     phy_84756_fcmap_an_set,      /* ANA set */
   7563     phy_84756_fcmap_an_get,      /* ANA get */
   7564     NULL,                 /* Local Advert set, deprecated */
   7565     NULL,                 /* Local Advert get, deprecated */
   7566     NULL,                 /* Remote Advert get, deprecated */
   7567     phy_84756_fcmap_lb_set,      /* PHY loopback set */
   7568     phy_84756_fcmap_lb_get,      /* PHY loopback set */
   7569     phy_84756_fcmap_interface_set, /* IO Interface set */
   7570     phy_84756_fcmap_interface_get, /* IO Interface get */
   7571     NULL,                   /* pd_ability, deprecated */
   7572     phy_84756_fcmap_linkup,
   7573     NULL,
   7574     phy_null_mdix_set,        /* phy_84756_fcmap_mdix_set */
   7575     phy_null_mdix_get,        /* phy_84756_fcmap_mdix_get */
   7576     phy_null_mdix_status_get, /* phy_84756_fcmap_mdix_status_get */
   7577     NULL, /* medium config setting set */
   7578     NULL, /* medium config setting get */
   7579     phy_84756_fcmap_medium_status,        /* active medium */
   7580     NULL,                    /* phy_cable_diag  */
   7581     NULL,                    /* phy_link_change */
   7582     phy_84756_fcmap_control_set,    /* phy_control_set */
   7583     phy_84756_fcmap_control_get,    /* phy_control_get */
   7584     phy_84756_fcmap_reg_read,       /* phy_reg_read */
   7585     phy_84756_fcmap_reg_write,      /* phy_reg_write */
   7586     NULL,                    /* phy_reg_modify */
   7587     NULL,                    /* phy_notify */
   7588     phy_84756_fcmap_probe,         /* pd_probe  */
   7589     phy_84756_fcmap_ability_advert_set,  /* pd_ability_advert_set */
   7590     phy_84756_fcmap_ability_advert_get,  /* pd_ability_advert_get */
   7591     phy_84756_fcmap_ability_remote_get,  /* pd_ability_remote_get */
   7592     phy_84756_fcmap_ability_local_get,   /* pd_ability_local_get  */
   7593     phy_84756_fcmap_firmware_set,
   7594     phy_84756_fcmap_timesync_config_set,
   7595     phy_84756_fcmap_timesync_config_get,
   7596     phy_84756_fcmap_timesync_control_set,
   7597     phy_84756_fcmap_timesync_control_get,
   7598     phy_84756_diag_ctrl,           /* .pd_diag_ctrl */
   7599     NULL,                          /* pd_lane_control_set */
   7600     NULL,                          /* pd_lane_control_get */
   7601     NULL,                          /* pd_lane_reg_read */
   7602     NULL,                          /* pd_lane_reg_write */
   7603     NULL,                          /* pd_oam_config_set */
   7604     NULL,                          /* pd_oam_config_get */
   7605     NULL,                          /* pd_oam_control_set */
   7606     NULL,                          /* pd_oam_control_get */
   7607     NULL,                          /* pd_timesync_enhanced_capture_get */
   7608     phy_84756_multi_get,           /* pd_multi_get */
   7609     phy_84756_precondition_before_probe, /* pd_precondition_before_probe */
   7610     phy_84756_fcmap_linkfault_get  /* LinkFault get   */
   7611 };
   7612 
   7613 
   7614 /*
   7615  * 
   7616  * $Copyright: (c) 2005 Broadcom Corp.
   7617  * All Rights Reserved.$
   7618  *
   7619  * File:        phy84740.c
   7620  * Purpose:    Phys Driver support for Broadcom 84740 40Gig
   7621  *             transceiver :XLAUI system side and PPI Line interface.
   7622  * Note:       
   7623  */
   7624 
   7625 #include <sal/types.h>
   7626 
   7627 #include <soc/drv.h>
   7628 #include <soc/debug.h>
   7629 #include <soc/error.h>
   7630 #include <soc/phyreg.h>
   7631 
   7632 #include <soc/phy.h>
   7633 #include <soc/phy/phyctrl.h>
   7634 #include <soc/phy/drv.h>
   7635 
   7636 #include "phydefs.h"      /* Must include before other phy related includes */
   7637 
   7638 #if defined(INCLUDE_PHY_84756)
   7639 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
   7640 #include "phyident.h"
   7641 #include "phyreg.h"
   7642 #include "phynull.h"
   7643 #include "phyxehg.h"
   7644 #include "phy84740.h"
   7645 /*
   7646  * SPI-ROM Program related defs
   7647  */
   7648 #define SPI_CTRL_1_L        0xC000
   7649 #define SPI_CTRL_1_H        0xC002
   7650 #define SPI_CTRL_2_L        0xC400
   7651 #define SPI_CTRL_2_H        0xC402
   7652 #define SPI_TXFIFO          0xD000
   7653 #define SPI_RXFIFO          0xD400
   7654 #define WR_CPU_CTRL_REGS    0x11
   7655 #define RD_CPU_CTRL_REGS    0xEE
   7656 #define WR_CPU_CTRL_FIFO    0x66
   7657 
   7658 /*
   7659  * SPI Controller Commands(Messages).
   7660  */
   7661 #define MSGTYPE_HWR          0x40
   7662 #define MSGTYPE_HRD          0x80
   7663 #define WRSR_OPCODE          0x01
   7664 #define WR_OPCODE            0x02
   7665 #define WRDI_OPCODE          0x04
   7666 #define RDSR_OPCODE          0x05
   7667 #define WREN_OPCODE          0x06
   7668 #define WR_BLOCK_SIZE        0x40
   7669 #define TOTAL_WR_BYTE        0x4000
   7670                                                                                 
   7671 #define WR_TIMEOUT   1000000
   7672 
   7673 /* CL73 autoneg */
   7674 #define AN_ADVERT_40GCR4 (1 << 9)
   7675 #define AN_ADVERT_40GKR4 (1 << 8)
   7676 #define AN_ADVERT_10GKR  (1 << 7)
   7677 #define AN_ADVERT_1GKX   (1 << 5)
   7678 
   7679 /* PRBS */
   7680 #define PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS         0x0135
   7681 #define PHY84740_40G_PRBS31             (1 << 7)               
   7682 #define PHY84740_40G_PRBS9              (1 << 6) 
   7683 #define PHY84740_40G_PRBS_TX_ENABLE     (1 << 3) 
   7684 #define PHY84740_40G_PRBS_RX_ENABLE     (1 << 0) 
   7685 #define PHY84740_40G_PRBS_ENABLE     (PHY84740_40G_PRBS_RX_ENABLE | \
   7686     PHY84740_40G_PRBS_TX_ENABLE)
   7687 
   7688 #define PHY84740_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0            0x0140 
   7689 #define PHY84740_USER_PRBS_CONTROL_0_REGISTER                       0xCD14 
   7690 #define PHY84740_USER_PRBS_TX_INVERT   (1 << 4)
   7691 #define PHY84740_USER_PRBS_RX_INVERT   (1 << 15)
   7692 #define PHY84740_USER_PRBS_INVERT      (1 << 4 | 1 << 15)
   7693 #define PHY84740_USER_PRBS_ENABLE      (1 << 7)
   7694 #define PHY84740_USER_PRBS_TYPE_MASK   (0x7)
   7695 
   7696 #define PHY84740_USER_PRBS_STATUS_0_REGISTER                        0xCD15 
   7697 #define PHY84740_GENSIG_8071_REGISTER                               0xCD16 
   7698 #define PHY84740_RESET_CONTROL_REGISTER                             0xCD17 
   7699 
   7700 /* Module auto detect status */
   7701 #define PHY84740_MOD_AUTO_DETECT_STS_REG                0xc82b
   7702 #define PHY84740_MOD_AUTO_DETECT_STS_NOT_DONE           (1 << 15)
   7703 #define PHY84740_MOD_AUTO_DETECT_STS_SFP_EN             (1 << 10)
   7704 #define PHY84740_MOD_AUTO_DETECT_STS_I2C_FAIL           (1 << 9)
   7705 #define PHY84740_MOD_AUTO_DETECT_STS_NOT_RES            (1 << 0)
   7706 
   7707 /* Optical config */
   7708 #define PHY84740_PMAD_OPTICAL_CFG_MOD_PRESENCE          (1 << 3)
   7709 
   7710 /* General purpose register */
   7711 #define PHY84740_PMAD_GEN_PURPOSE_REG                   0xc710
   7712 #define PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN    (1 << 2)
   7713 
   7714 /* Polarity config */
   7715 #define POL_CONFIG_LANE_WIDTH     0x4
   7716 #define POL_CONFIG_LANE_MASK(_ln)   (0xf << ((_ln) * POL_CONFIG_LANE_WIDTH))
   7717 #define POL_CONFIG_ALL_LANES    1 
   7718 /*
   7719  * When a port is being flexed between 40G->10G, 
   7720  * the polarity config syntax can be in
   7721  * 40G syntax for first lane, so there is a need to parse 
   7722  * both 10G and 40G polarity config syntax in 10G.
   7723  */
   7724 #define PHY84740_LN(_pc)         ((_pc)->phy_id & 0x3)
   7725 #define PHY84740_POL_MASK(_pc)   POL_CONFIG_LANE_MASK(PHY84740_LN(_pc))
   7726 #define PHY84740_10G_POL_CFG_GET(_pc, _pol) \
   7727 (((_pol) == POL_CONFIG_ALL_LANES) ||  \
   7728 (((_pol) & PHY84740_POL_MASK(_pc)) ==  PHY84740_POL_MASK(_pc)))
   7729 
   7730 
   7731 /* I2C related defines */
   7732 #define PHY84740_BSC_XFER_MAX     0x1F9
   7733 #define PHY84740_BSC_WR_MAX       16
   7734 #define PHY84740_WRITE_START_ADDR 0x8007
   7735 #define PHY84740_READ_START_ADDR  0x8007
   7736 #define PHY84740_WR_FREQ_400KHZ   0x0100
   7737 #define PHY84740_2W_STAT          0x000C
   7738 #define PHY84740_2W_STAT_IDLE     0x0000
   7739 #define PHY84740_2W_STAT_COMPLETE 0x0004
   7740 #define PHY84740_2W_STAT_IN_PRG   0x0008
   7741 #define PHY84740_2W_STAT_FAIL     0x000C
   7742 #define PHY84740_BSC_WRITE_OP     0x22
   7743 #define PHY84740_BSC_READ_OP      0x2
   7744 #define PHY84740_I2CDEV_WRITE     0x1
   7745 #define PHY84740_I2CDEV_READ      0x0
   7746 #define PHY84740_I2C_8BIT         0
   7747 #define PHY84740_I2C_16BIT        1
   7748 #define PHY84740_I2C_TEMP_RAM     0xE
   7749 #define PHY84740_I2C_OP_TYPE(access_type,data_type) \
   7750         ((access_type) | ((data_type) << 8))
   7751 #define PHY84740_I2C_ACCESS_TYPE(op_type) ((op_type) & 0xff)
   7752 #define PHY84740_I2C_DATA_TYPE(op_type)   (((op_type) >> 8) & 0xff)
   7753 
   7754 /* preemphasis control */
   7755 #define PHY84740_PREEMPH_CTRL_FORCE_SHFT       15
   7756 #define PHY84740_PREEMPH_GET_FORCE(_val)  \
   7757     (((_val) >> PHY84740_PREEMPH_CTRL_FORCE_SHFT) & 1)
   7758 #define PHY84740_PREEMPH_CTRL_POST_TAP_SHFT    10
   7759 #define PHY84740_PREEMPH_GET_POST_TAP(_val) \
   7760     (((_val) >> PHY84740_PREEMPH_CTRL_POST_TAP_SHFT) & 0x1f)
   7761 #define PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT    0
   7762 #define PHY84740_PREEMPH_GET_PRE_TAP(_val) \
   7763     (((_val) >> PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT) & 0xf)
   7764 #define PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT    4
   7765 #define PHY84740_PREEMPH_GET_MAIN_TAP(_val) \
   7766     (((_val) >> PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT) & 0x3f) 
   7767 #define PHY84740_PREEMPH_REG_FORCE_MASK     (1 << 8)
   7768 #define PHY84740_PREEMPH_REG_POST_TAP_SHFT  4
   7769 #define PHY84740_PREEMPH_REG_POST_TAP_MASK  (0xf << PHY84740_PREEMPH_REG_POST_TAP_SHFT)
   7770 #define PHY84740_PREEMPH_REG_PRE_TAP_SHFT  0
   7771 #define PHY84740_PREEMPH_REG_PRE_TAP_MASK  (0x7 << PHY84740_PREEMPH_REG_PRE_TAP_SHFT)
   7772 #define PHY84740_PREEMPH_REG_MAIN_TAP_SHFT  11   
   7773 #define PHY84740_PREEMPH_REG_MAIN_TAP_MASK  (0x1f << PHY84740_PREEMPH_REG_MAIN_TAP_SHFT)
   7774 #define PHY84740_PREEMPH_REG_TX_PWRDN_MASK  (0x1 << 10)
   7775 
   7776 /* Misc. */
   7777 #define PHY84740_UCODE_DEVID_ADDR              0x7FF9
   7778 
   7779 #define PHY84740_SINGLE_PORT_MODE(_pc)  \
   7780 (SOC_INFO((_pc)->unit).port_num_lanes[(_pc)->port] >= 4)
   7781 #define PHY84740_EDC_MODE_MASK          0xff
   7782 #define PHY84740_ID_84740 0x84740
   7783 #define PHY84740_ID_84064 0x84064
   7784 #define PHY84740_ID_84754 0x84754
   7785 #define PHY84740_ID_84753 0x84753
   7786 #define PHY84740_ID_84752 0x84752
   7787 
   7788 /* Other variants */
   7789 #define PHY84740_ID_84780 0x84780
   7790 #define PHY84740_ID_84784 0x84784
   7791 #define PHY84740_ID_84758 0x84758
   7792 #define PHY84740_ID_84164 0x84164
   7793 #define PHY84740_ID_84168 0x84168
   7794 #define PHY84740_ID_84741 0x84741
   7795 #define PHY84740_ID_84744 0x84744
   7796 
   7797 #define PHY84740_IS_QUADRA(devid)\
   7798 ((devid) == PHY84740_ID_84780 ||\
   7799  (devid) == PHY84740_ID_84784 ||\
   7800  (devid) == PHY84740_ID_84758 ||\
   7801  (devid) == PHY84740_ID_84164 ||\
   7802  (devid) == PHY84740_ID_84168 )
   7803 
   7804 #define PHY84740_IS_MONTREAL(devid)\
   7805 ((devid) == PHY84740_ID_84741 ||\
   7806  (devid) == PHY84740_ID_84744 )
   7807 
   7808 
   7809 /* typedefs */
   7810 typedef struct {
   7811     int rx_los;
   7812     int rx_los_invert;
   7813     int mod_abs;
   7814     int mod_abs_invert;
   7815     int p2l_map[NUM_LANES];  /* index: physical lane, array element: logical lane */
   7816     int pcs_repeater;
   7817     int reverse_mode;
   7818     int mod_auto_detect;
   7819     int mod_auto_detect_msg;
   7820     int software_rx_los;
   7821     int fcmap_passthrough;
   7822     int single_lpmode;
   7823     int skip_fw_dload;
   7824 } PHY84740_DEV_DESC_t; 
   7825 
   7826 /* device field macros */
   7827 #define RX_LOS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->rx_los)
   7828 #define RX_LOS_INVERT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->rx_los_invert)
   7829 #define MOD_ABS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_abs)
   7830 #define MOD_ABS_INVERT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_abs_invert)
   7831 #define P2L_MAP(_pc,_ix) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->p2l_map[(_ix)])
   7832 #define PCS_REPEATER(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->pcs_repeater)
   7833 #define REVERSE_MODE(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->reverse_mode)
   7834 #define MOD_AUTO_DETECT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_auto_detect)
   7835 #define MOD_AUTO_DETECT_MSG(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_auto_detect_msg)
   7836 #define SOFTWARE_RX_LOS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->software_rx_los)
   7837 #define FCMAP_PASSTHROUGH(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->fcmap_passthrough)
   7838 #define SINGLE_LPMODE(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->single_lpmode)
   7839 #define SKIP_FW_DLOAD(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->skip_fw_dload)
   7840 
   7841 #define PHY84740_FCS_ERROR_WAR
   7842 
   7843 /* callback to deliever the firmware by application 
   7844  * return value: TRUE  successfully delivered
   7845  *               FALSE fail to deliver
   7846  *
   7847  * Example:
   7848  *
   7849  * int user_firmware_send (int unit,int port,int flag,unsigned char **data,int *len)
   7850  * {
   7851  *     *data = phy84740_ucode_bin;
   7852  *     *len  = phy84740_ucode_bin_len;
   7853  *     return TRUE;
   7854  * }
   7855  * Then initialize the function pointer before the BCM port initialization: 
   7856  * phy_84741_uc_firmware_hook = user_firmware_send;
   7857  */
   7858 int (*phy_84741_uc_firmware_hook)(
   7859        int unit, /* switch number */
   7860        int port, /* port number */
   7861        int flag, /* any information need to ba passed. Not used for now*/
   7862        unsigned char **addr,  /* starting address of delivered firmware */
   7863        int *len               /* length of the firmware */
   7864        ) = NULL;          
   7865 
   7866 static int write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, 
   7867                          uint16 *rddata);
   7868                                                                                 
   7869 
   7870 STATIC int phy_84741_speed_get(int, soc_port_t, int *);
   7871 STATIC int
   7872 _phy_84741_firmware_to_rom(int unit, int port, int offset, uint8 *array,int datalen);
   7873 STATIC int
   7874 _phy84741_mdio_lane_firmware_download(int unit, int port, phy_ctrl_t *pc,
   7875                                 uint8 *new_fw, uint32 fw_length);
   7876 
   7877 extern unsigned char phy84740_ucode_bin[];
   7878 extern unsigned int phy84740_ucode_bin_len;
   7879 extern unsigned char phy84754_ucode_bin[];
   7880 extern unsigned int phy84754_ucode_bin_len;
   7881 extern unsigned char phy84753_ucode_bin[];
   7882 extern unsigned int phy84753_ucode_bin_len;
   7883 extern unsigned char phy84064_ucode_bin[];
   7884 extern unsigned int phy84064_ucode_bin_len;
   7885 extern unsigned char phy84752_ucode_bin[];
   7886 extern unsigned int phy84752_ucode_bin_len;
   7887 extern unsigned char phy84758_ucode_bin[];
   7888 extern unsigned int phy84758_ucode_bin_len;
   7889 extern unsigned char phy84780_ucode_bin[];
   7890 extern unsigned int phy84780_ucode_bin_len;
   7891 extern unsigned char phy84784_ucode_bin[];
   7892 extern unsigned int phy84784_ucode_bin_len;
   7893 
   7894 static char *dev_name_84740 = "BCM84740";
   7895 static char *dev_name_84752 = "BCM84752";
   7896 static char *dev_name_84753 = "BCM84753";
   7897 static char *dev_name_84754 = "BCM84754";
   7898 static char *dev_name_84064 = "BCM84064";
   7899 static char *dev_name_84784 = "BCM84784";
   7900 
   7901 static char *dev_name_84741 = "BCM84741";
   7902 static char *dev_name_84744 = "BCM84744";
   7903 
   7904 STATIC int
   7905 _phy_84741_config_devid(int unit,soc_port_t port,phy_ctrl_t *pc, uint32 *devid)
   7906 {
   7907     uint16 data16;
   7908 
   7909     if (soc_property_port_get(unit, port,spn_PHY_84740, FALSE)) {
   7910         *devid = PHY84740_ID_84740;
   7911     } else if (soc_property_port_get(unit, port,spn_PHY_84752, FALSE)) {
   7912         *devid = PHY84740_ID_84752;
   7913     } else if (soc_property_port_get(unit, port,spn_PHY_84753, FALSE)) {
   7914         *devid = PHY84740_ID_84753;
   7915     } else if (soc_property_port_get(unit, port,spn_PHY_84754, FALSE)) {
   7916         *devid = PHY84740_ID_84754;
   7917     } else if (soc_property_port_get(unit, port,spn_PHY_84064, FALSE)) {
   7918         *devid = PHY84740_ID_84064;
   7919     } else {
   7920 
   7921         /* read Other chip id */
   7922         SOC_IF_ERROR_RETURN
   7923             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc802, &data16));
   7924 
   7925         if (PHY84740_IS_QUADRA(0x80000 | data16)) {
   7926             *devid = 0x80000 | data16;
   7927         } else if (PHY84740_IS_MONTREAL(0x80000 | data16)) {
   7928             *devid = 0x80000 | data16;
   7929         } else {
   7930             *devid = 0;
   7931         }
   7932     }
   7933     return SOC_E_NONE;
   7934 }
   7935 
   7936 STATIC int
   7937 _phy_84741_single_to_quad_mode(int unit,soc_port_t port, phy_ctrl_t *pc)
   7938 {
   7939     int            ix;
   7940     uint16         saved_phy_addr; 
   7941     uint16 mask16;
   7942     uint16 data16;
   7943     uint32 devid;
   7944 
   7945     if (pc == NULL) {
   7946         pc = EXT_PHY_SW_STATE(unit, port);
   7947     }
   7948 
   7949     /* probe routine should block any invalid devids. 
   7950      * devids should be always valid here
   7951      */
   7952     SOC_IF_ERROR_RETURN(
   7953         _phy_84741_config_devid(pc->unit,pc->port, pc,  &devid));
   7954 
   7955     mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK;
   7956     if (devid == PHY84740_ID_84064) {
   7957         data16 = PHY84740_PMAD_BKPLANE_MODE_MASK;
   7958     } else {
   7959         data16 = 0;
   7960     }
   7961 
   7962     /* config DAC mode/backplane mode first. This is a bcst register in single mode */
   7963     SOC_IF_ERROR_RETURN(
   7964         MODIFY_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   7965               data16, mask16));
   7966 
   7967     /* then configure quad chip mode */
   7968     SOC_IF_ERROR_RETURN(
   7969         MODIFY_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   7970               0, PHY84740_PMAD_CHIP_MODE_MASK));
   7971 
   7972     /* once this mode register is configured with quad mode, each lane is
   7973      * accessable by the lane specific MDIO address
   7974      */
   7975     saved_phy_addr = pc->phy_id;
   7976     /* Reset all 4 lanes. Only after reset, the mode is actually switched */
   7977     for (ix = 0; ix < 4; ix++) {
   7978         pc->phy_id = (saved_phy_addr & (~0x3)) + ix;
   7979         SOC_IF_ERROR_RETURN
   7980             (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc,
   7981                               MII_CTRL_RESET, MII_CTRL_RESET));
   7982     }
   7983     pc->phy_id = saved_phy_addr;
   7984 
   7985     return SOC_E_NONE;
   7986 }
   7987 
   7988 STATIC int
   7989 _phy_84741_quad_to_single_mode(int unit,soc_port_t port)
   7990 {
   7991     int            ix;
   7992     uint16         saved_phy_addr;
   7993     phy_ctrl_t     *pc;
   7994     uint16 mask16;
   7995     uint16 data16;
   7996     uint32 devid;
   7997 
   7998     pc = EXT_PHY_SW_STATE(unit, port);
   7999 
   8000     SOC_IF_ERROR_RETURN(
   8001         _phy_84741_config_devid(pc->unit,pc->port, pc, &devid));
   8002 
   8003     saved_phy_addr = pc->phy_id;
   8004     /* configure all four lanes to bcst mode */
   8005     for (ix = 0; ix < 4; ix++) {
   8006         pc->phy_id = (saved_phy_addr & (~0x3)) + ix;
   8007         SOC_IF_ERROR_RETURN
   8008             (WRITE_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc,
   8009                               PHY84740_PMAD_BCST_REG, 0xffff));
   8010     }
   8011     pc->phy_id = saved_phy_addr;
   8012 
   8013     /* then configure single mode */
   8014     SOC_IF_ERROR_RETURN(
   8015         MODIFY_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   8016               PHY84740_PMAD_MODE_40G, PHY84740_PMAD_CHIP_MODE_MASK));
   8017 
   8018     mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK;
   8019     if (devid == PHY84740_ID_84064) {
   8020         data16 = PHY84740_PMAD_BKPLANE_MODE_MASK;
   8021     } else {
   8022         data16 = 0;
   8023     }
   8024 
   8025     /* config DAC mode and backplane mode for LR4/SR4 */
   8026     SOC_IF_ERROR_RETURN(
   8027         MODIFY_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   8028               data16, mask16));
   8029 
   8030     /* do a soft reset to switch to the configured mode
   8031      * The reset should also clear the bcst register configuration
   8032      */
   8033     SOC_IF_ERROR_RETURN
   8034         (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc,
   8035                           MII_CTRL_RESET, MII_CTRL_RESET));
   8036 
   8037     return SOC_E_NONE;
   8038 }
   8039 STATIC int
   8040 _phy84741_mdio_firmware_download(int unit, int port, phy_ctrl_t *pc,
   8041                                 uint8 *new_fw, uint32 fw_length)
   8042 {
   8043     uint16 data16;
   8044     uint16 mask16;
   8045     int lane;
   8046     int rv = SOC_E_NONE;
   8047 
   8048     if (new_fw == NULL || fw_length == 0) {
   8049         LOG_WARN(BSL_LS_SOC_PHY,
   8050                  (BSL_META_U(unit,
   8051                              "u=%d p=%d MDIO firmware download: invalid firmware\n"),
   8052                              unit, port));
   8053         return SOC_E_NONE;
   8054     }
   8055 
   8056     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8057         /* point to lane 0 */
   8058         SOC_IF_ERROR_RETURN
   8059             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 
   8060                                         0));
   8061     }
   8062 
   8063     /* clear SPA ctrl reg bit 15 and bit 13. 
   8064      * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM 
   8065      * bit 13, 0 clear download done status, 1 skip download 
   8066      */
   8067     mask16 = (1 << 13) | (1 << 15);
   8068     data16 = 0;
   8069     SOC_IF_ERROR_RETURN
   8070         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG, 
   8071                                         data16,mask16));
   8072 
   8073     /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */
   8074     mask16 = 1 << 14;
   8075     data16 = mask16;
   8076     SOC_IF_ERROR_RETURN
   8077         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG, 
   8078                                         data16,mask16));
   8079 
   8080     /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */
   8081     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8082         for (lane = 0; lane < NUM_LANES; lane++) {
   8083             SOC_IF_ERROR_RETURN
   8084             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, lane));
   8085             mask16 = 1 << 3;
   8086             data16 = mask16;
   8087             SOC_IF_ERROR_RETURN
   8088                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, 
   8089                                            data16,mask16));
   8090         }
   8091     } else {
   8092         mask16 = 1 << 3;
   8093         data16 = mask16;
   8094         SOC_IF_ERROR_RETURN
   8095             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, 
   8096                                            data16,mask16));
   8097     }
   8098     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8099         /* apply bcst Reset to start download code from MDIO */
   8100         SOC_IF_ERROR_RETURN
   8101             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   8102     }
   8103     SOC_IF_ERROR_RETURN
   8104         (WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, 0x8000));
   8105 
   8106     /* wait for 2ms for M8051 start and 5ms to initialize the RAM */
   8107     sal_usleep(10000); /* Wait for 10ms */
   8108 
   8109 
   8110     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8111         for (lane = 0; lane < NUM_LANES; lane++) {
   8112             SOC_IF_ERROR_RETURN
   8113             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, lane));
   8114             /* download the firmware to the specific lane */
   8115             rv = _phy84741_mdio_lane_firmware_download(unit,port,pc,new_fw,fw_length);
   8116         }
   8117 
   8118         /* point back to lane0 */
   8119         SOC_IF_ERROR_RETURN
   8120             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   8121     } else {
   8122         SOC_IF_ERROR_RETURN
   8123             (_phy84741_mdio_lane_firmware_download(unit,port,pc,new_fw,fw_length));
   8124     }
   8125     return rv;
   8126 }
   8127 
   8128 STATIC int
   8129 _phy84741_mdio_lane_firmware_download(int unit, int port, phy_ctrl_t *pc,
   8130                                 uint8 *new_fw, uint32 fw_length)
   8131 
   8132 {
   8133     uint16 data16;
   8134     int j;
   8135     uint16 num_words;
   8136 
   8137 
   8138     /* Write Starting Address, where the Code will reside in SRAM */
   8139     data16 = 0x8000;
   8140     SOC_IF_ERROR_RETURN
   8141         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
   8142 
   8143     /* make sure address word is read by the micro */
   8144     sal_udelay(10); /* Wait for 10us */
   8145 
   8146     /* Write SPI SRAM Count Size */
   8147     data16 = (fw_length)/2;
   8148     SOC_IF_ERROR_RETURN
   8149         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
   8150 
   8151     /* make sure read by the micro */
   8152     sal_udelay(10); /* Wait for 10us */
   8153 
   8154     /* Fill in the SRAM */
   8155     num_words = (fw_length - 1);
   8156     for (j = 0; j < num_words; j+=2) {
   8157         /* Make sure the word is read by the Micro */
   8158         sal_udelay(10);
   8159 
   8160         data16 = (new_fw[j] << 8) | new_fw[j+1];
   8161         SOC_IF_ERROR_RETURN
   8162             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, 
   8163                  data16));
   8164     }
   8165 
   8166     /* make sure last code word is read by the micro */
   8167     sal_udelay(20);
   8168 
   8169     /* Read Hand-Shake message (Done) from Micro */
   8170     SOC_IF_ERROR_RETURN
   8171         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_M8051_MSGOUT_REG, &data16));
   8172 
   8173     /* Download done message */
   8174     LOG_INFO(BSL_LS_SOC_PHY,
   8175              (BSL_META_U(unit,
   8176                          "u=%d p=%d MDIO firmware download done message: 0x%x\n"),
   8177                          unit, port,data16));
   8178 
   8179     /* Clear LASI status */
   8180     SOC_IF_ERROR_RETURN
   8181         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
   8182 
   8183     /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */
   8184     sal_udelay(100); /* Wait for 100 usecs */
   8185 
   8186     SOC_IF_ERROR_RETURN
   8187         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_M8051_MSGOUT_REG, &data16));
   8188 
   8189     /* Need to check if checksum is correct */
   8190     SOC_IF_ERROR_RETURN
   8191         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16));
   8192 
   8193     if (data16 != 0x600D) {
   8194         /* Bad CHECKSUM */
   8195         LOG_CLI((BSL_META_U(unit,
   8196                             "MDIO Firmware downlad failure:"
   8197                  "Incorrect Checksum %x\n"), data16));
   8198         return SOC_E_FAIL;
   8199     }
   8200 
   8201     /* read Rev-ID */
   8202     SOC_IF_ERROR_RETURN
   8203         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16));
   8204     LOG_INFO(BSL_LS_SOC_PHY,
   8205              (BSL_META_U(unit,
   8206                          "u=%d p=%d MDIO Firmware download revID: 0x%x\n"),
   8207                          unit, port,data16));
   8208 
   8209     return SOC_E_NONE;
   8210 }
   8211 
   8212 STATIC int
   8213 _phy84741_rom_firmware_download(int unit, int port, phy_ctrl_t *pc)
   8214 {
   8215     int lane;
   8216     uint16 data16;
   8217     uint16 mask16;
   8218     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8219         for (lane = 3; lane >= 0; lane--) {
   8220             SOC_IF_ERROR_RETURN
   8221                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
   8222                                            PHY84740_PMAD_AER_ADDR_REG, lane));
   8223 
   8224             /* 0xca85[3]=1, 32K download */ 
   8225             mask16 = (1 << 3);
   8226             data16 = mask16;
   8227             SOC_IF_ERROR_RETURN
   8228                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA85, data16,mask16));
   8229         }
   8230 
   8231         /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */
   8232         mask16 = (1 << 15) | (1 << 14);
   8233         data16 = mask16;
   8234 
   8235         /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */
   8236         mask16 |= (1 << 13) | (1 << 2);
   8237         SOC_IF_ERROR_RETURN
   8238             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16));
   8239 
   8240         /* apply software reset to download code from SPI-ROM */
   8241         SOC_IF_ERROR_RETURN
   8242             (WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, MII_CTRL_RESET));
   8243 
   8244         for (lane = 0; lane < NUM_LANES; lane++) {
   8245             SOC_IF_ERROR_RETURN
   8246                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
   8247                                            PHY84740_PMAD_AER_ADDR_REG, lane));
   8248             /* wait for at least 50ms */
   8249             sal_usleep(100000); 
   8250             SOC_IF_ERROR_RETURN
   8251                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
   8252             LOG_INFO(BSL_LS_SOC_PHY,
   8253                      (BSL_META_U(unit,
   8254                                  "u=%d p=%d lane%d SPI-ROM download done msg 0x%x\n"),
   8255                                  unit, port,lane,data16));
   8256             SOC_IF_ERROR_RETURN
   8257                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16));
   8258             SOC_IF_ERROR_RETURN
   8259                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16));
   8260         }
   8261         SOC_IF_ERROR_RETURN
   8262             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
   8263                                            PHY84740_PMAD_AER_ADDR_REG, 0));
   8264     } else { /* single lane */
   8265         /* 0xca85[3]=1, 32K download */
   8266         mask16 = (1 << 3);
   8267         data16 = mask16;
   8268         SOC_IF_ERROR_RETURN
   8269             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA85, data16,mask16));
   8270 
   8271         /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */
   8272         mask16 = (1 << 15) | (1 << 14);
   8273         data16 = mask16;
   8274         SOC_IF_ERROR_RETURN
   8275             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16));
   8276 
   8277         /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */
   8278         mask16 = (1 << 13) | (1 << 2);
   8279         data16 = 0;
   8280         SOC_IF_ERROR_RETURN
   8281             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16));
   8282 
   8283         /* apply software reset to download code from SPI-ROM */
   8284         SOC_IF_ERROR_RETURN
   8285             (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc,
   8286                                   MII_CTRL_RESET, MII_CTRL_RESET));
   8287 
   8288         /* wait for at least 50ms */
   8289         sal_usleep(100000);
   8290         SOC_IF_ERROR_RETURN
   8291             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
   8292         LOG_INFO(BSL_LS_SOC_PHY,
   8293                  (BSL_META_U(unit,
   8294                              "u=%d p=%d SPI-ROM download done msg 0x%x\n"),
   8295                              unit, port,data16));
   8296 
   8297     }
   8298     return SOC_E_NONE;
   8299 }
   8300 
   8301 /*
   8302  * Flip the tx/rx polarities based on the configuration.
   8303  */ 
   8304 STATIC int
   8305 _phy_84741_polarity_flip_set(int unit,soc_port_t port)
   8306 {
   8307     int            lane;
   8308     phy_ctrl_t     *pc;
   8309     uint16 tx_pol,rx_pol;
   8310     uint16 data16,mask16;
   8311 
   8312     pc = EXT_PHY_SW_STATE(unit, port);
   8313 
   8314 
   8315     tx_pol = 0;
   8316     rx_pol = 0;
   8317 
   8318     /* get the reset default value. The 84740 device has the TX polarity flipped
   8319      * by default. Construct the init default value 
   8320      */
   8321 
   8322     if ((PHY84740_SINGLE_PORT_MODE(pc))) {
   8323         for (lane = 0; lane < NUM_LANES; lane++) { 
   8324             /* point to the each lane starting at lane0 */
   8325             SOC_IF_ERROR_RETURN
   8326                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8327                                 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane)));
   8328 
   8329             /* read both TX/RX polarities */
   8330             SOC_IF_ERROR_RETURN(
   8331                 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_DIG_CTRL_REG,
   8332                            &data16));
   8333             if (data16 & PHY84740_TX_POLARITY_FLIP_MASK) {
   8334                 tx_pol |= POL_CONFIG_LANE_MASK(lane); 
   8335             } 
   8336             if (data16 & PHY84740_RX_POLARITY_FLIP_MASK) {
   8337                 rx_pol |= POL_CONFIG_LANE_MASK(lane); 
   8338             } 
   8339         }
   8340     } else {  /* quad mode */
   8341         SOC_IF_ERROR_RETURN(
   8342             READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_DIG_CTRL_REG,
   8343                             &data16));
   8344         if (data16 & PHY84740_TX_POLARITY_FLIP_MASK) {
   8345             tx_pol = POL_CONFIG_ALL_LANES;
   8346         } 
   8347         if (data16 & PHY84740_RX_POLARITY_FLIP_MASK) {
   8348             rx_pol = POL_CONFIG_ALL_LANES;
   8349         } 
   8350     }
   8351 
   8352     tx_pol = soc_property_port_get(unit, port,
   8353                                     spn_PHY_PCS_TX_POLARITY_FLIP, tx_pol);
   8354     rx_pol = soc_property_port_get(unit, port,
   8355                                     spn_PHY_PCS_RX_POLARITY_FLIP, rx_pol);
   8356 
   8357     mask16 = PHY84740_TX_POLARITY_FLIP_MASK | 
   8358              PHY84740_RX_POLARITY_FLIP_MASK;
   8359 
   8360     if ((PHY84740_SINGLE_PORT_MODE(pc))) {
   8361         for (lane = 0; lane < NUM_LANES; lane++) { 
   8362             data16 = 0;
   8363 
   8364             /* point to the each lane starting at lane0 */
   8365             SOC_IF_ERROR_RETURN
   8366                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8367                             PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane)));
   8368 
   8369             if ((tx_pol == POL_CONFIG_ALL_LANES) || 
   8370                 ((tx_pol & POL_CONFIG_LANE_MASK(lane)) ==
   8371                 POL_CONFIG_LANE_MASK(lane)) ) {  
   8372                 data16 = PHY84740_TX_POLARITY_FLIP_MASK;
   8373             }
   8374             if ((rx_pol == POL_CONFIG_ALL_LANES) || 
   8375                 ((rx_pol & POL_CONFIG_LANE_MASK(lane)) ==
   8376                 POL_CONFIG_LANE_MASK(lane)) ) {  
   8377                 data16 |= PHY84740_RX_POLARITY_FLIP_MASK;
   8378             }
   8379             SOC_IF_ERROR_RETURN(
   8380                 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 
   8381                                      PHY84740_DIG_CTRL_REG,
   8382                                      data16,mask16));
   8383         }
   8384         /* point back to lane0 */
   8385         SOC_IF_ERROR_RETURN
   8386             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   8387     } else {  /* quad-port mode */
   8388         data16 = 0;
   8389         tx_pol = PHY84740_10G_POL_CFG_GET(pc, tx_pol);
   8390         if (tx_pol) {
   8391             data16 = PHY84740_TX_POLARITY_FLIP_MASK;
   8392         }
   8393         rx_pol = PHY84740_10G_POL_CFG_GET(pc, rx_pol);
   8394         if (rx_pol) {
   8395             data16 |= PHY84740_RX_POLARITY_FLIP_MASK;
   8396         }
   8397         SOC_IF_ERROR_RETURN(
   8398             MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_DIG_CTRL_REG,
   8399                                  data16,mask16));
   8400     }
   8401    
   8402     return SOC_E_NONE;
   8403 }
   8404 
   8405 /*
   8406  * Squelch enable/disable
   8407  */
   8408 STATIC int _phy_84741_squelch_enable(int unit, soc_port_t port,
   8409                                      int intf, int enable, int force)
   8410 {
   8411     phy_ctrl_t *pc;
   8412     int ix;
   8413     int repeater_mode;
   8414     uint16 data16, mask16,bit,speed_val;
   8415     uint32 devid;
   8416 
   8417     pc = EXT_PHY_SW_STATE(unit, port);
   8418     SOC_IF_ERROR_RETURN(_phy_84741_config_devid
   8419                         (pc->unit, pc->port, pc, &devid));
   8420 
   8421     if (PHY84740_IS_QUADRA(devid)) { 
   8422         if ((PHY_DIAG_INTF_LINE == intf || REVERSE_MODE(pc)) &&
   8423             PHY_DIAG_INTF_SYS != intf) {
   8424             if(PHY84740_SINGLE_PORT_MODE(pc)) {
   8425                 mask16 = (1 << 6);
   8426                 data16 = enable ? mask16 : 0;
   8427                 for (ix = 0; ix < NUM_LANES; ix++) {
   8428                     SOC_IF_ERROR_RETURN
   8429                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8430                                                     PHY84740_PMAD_AER_ADDR_REG,
   8431                                                     ix));
   8432                     SOC_IF_ERROR_RETURN
   8433                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8434                                                      0xcd18, data16, mask16));
   8435                     SOC_IF_ERROR_RETURN
   8436                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8437                                                      0xcd16,
   8438                                                      enable ? (1 << 4) : 0,
   8439                                                      (1 << 4)));
   8440                 }
   8441                /* point back to lane0 */
   8442                SOC_IF_ERROR_RETURN
   8443                    (WRITE_PHY84740_MMF_PMA_PMD_REG
   8444                    (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 
   8445 
   8446             } else {/*quad ports**/
   8447                 SOC_IF_ERROR_RETURN
   8448                     (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
   8449                 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE;
   8450                 if (repeater_mode) {
   8451                    SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   8452                             (unit, pc, 0xc81f, &speed_val));
   8453                    bit = (speed_val & (1 << 2)) ? 3 : 4; 
   8454                     mask16 = (1 << bit) | (1 << 6);
   8455                     data16 = enable ? mask16 : 0;
   8456                     SOC_IF_ERROR_RETURN
   8457                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8458                                                      0xcd18, data16, mask16));
   8459                 }                
   8460             }
   8461         } else { /*system side or not reverse mode*/
   8462             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8463                 mask16 = (1 << 6) | (1 << 11);
   8464                 data16 = enable ? mask16 : 0;
   8465                 for (ix = 0; ix < NUM_LANES; ix++) {
   8466                     SOC_IF_ERROR_RETURN
   8467                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8468                                                    PHY84740_PMAD_AER_ADDR_REG,
   8469                                                    ix));
   8470                     SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   8471                     SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit,
   8472                                                                    pc,
   8473                                                                    0xcd18,
   8474                                                                    data16,
   8475                                                                    mask16));
   8476                     SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   8477                 }
   8478                  /* point back to lane0 */
   8479                 SOC_IF_ERROR_RETURN
   8480                     (WRITE_PHY84740_MMF_PMA_PMD_REG
   8481                     (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   8482             } else {/* quad port*/
   8483                 SOC_IF_ERROR_RETURN
   8484                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
   8485                 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE;
   8486                 if (repeater_mode) {
   8487                     SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   8488                             (unit, pc, 0xc81f, &speed_val));
   8489                     bit = (speed_val & (1 << 2)) ? 3 : 4; 
   8490                     mask16 = (1 << bit) | (1 << 6);
   8491                     data16 = enable ? mask16 : 0;
   8492                     SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   8493                     SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, pc,
   8494                                                                   0xcd18,
   8495                                                                   data16,
   8496                                                                   mask16));
   8497                     SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   8498                }
   8499             }
   8500         }
   8501     } else { 
   8502         if ((PHY_DIAG_INTF_LINE == intf || REVERSE_MODE(pc)) &&
   8503             PHY_DIAG_INTF_SYS != intf) {
   8504             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8505 
   8506                 /* Note: following line needed as workaround */
   8507                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   8508 
   8509                 mask16 = (1 << 6);
   8510                 data16 = enable ? mask16 : 0;
   8511 
   8512                 for (ix = 0; ix < NUM_LANES; ix++) {
   8513                     SOC_IF_ERROR_RETURN
   8514                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8515                                                     PHY84740_PMAD_AER_ADDR_REG,
   8516                                                     ix));
   8517 
   8518                     SOC_IF_ERROR_RETURN
   8519                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8520                                                      0xcd18, data16, mask16));
   8521 
   8522                     SOC_IF_ERROR_RETURN
   8523                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8524                                                      0xcd16,
   8525                                                      enable ?
   8526                                                      (force ?((1 << 3)|(1 << 4))
   8527                                                      :(1 << 4))
   8528                                                      : 0,
   8529                                                      (1 << 3)|(1 << 4)));
   8530                }
   8531                /* point back to lane0 */
   8532                SOC_IF_ERROR_RETURN
   8533                    (WRITE_PHY84740_MMF_PMA_PMD_REG
   8534                    (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   8535             } else {
   8536                 SOC_IF_ERROR_RETURN
   8537                     (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
   8538 
   8539                 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE;
   8540                 if (repeater_mode) {
   8541                     mask16 = (1 << 4) | (1 << 6);
   8542                     data16 = enable ? mask16 : 0;
   8543 
   8544                     SOC_IF_ERROR_RETURN
   8545                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8546                                                      0xcd18, data16, mask16));
   8547                 }
   8548             }
   8549 
   8550           } else { /*system side or not reverse mode*/
   8551               if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8552 
   8553                  mask16 = (1 << 6) | (1 << 11);
   8554                  data16 = enable ? mask16 : 0;
   8555 
   8556                  for (ix = 0; ix < NUM_LANES; ix++) {
   8557                      SOC_IF_ERROR_RETURN
   8558                          (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8559                                                     PHY84740_PMAD_AER_ADDR_REG,
   8560                                                     ix));
   8561 
   8562                      SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   8563                      SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit,
   8564                                                                     pc,
   8565                                                                     0xcd18,
   8566                                                                     data16,
   8567                                                                     mask16));
   8568 
   8569                      SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   8570                  }
   8571                  /* point back to lane0 */
   8572                  SOC_IF_ERROR_RETURN
   8573                      (WRITE_PHY84740_MMF_PMA_PMD_REG
   8574                      (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   8575               } else {
   8576                   SOC_IF_ERROR_RETURN
   8577                       (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
   8578 
   8579                   repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE;
   8580                   if (repeater_mode) {
   8581                       mask16 = (1 << 4) | (1 << 6);
   8582                       data16 = enable ? mask16 : 0;
   8583 
   8584                       SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   8585                       SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, pc,
   8586                                                                     0xcd18,
   8587                                                                     data16,
   8588                                                                     mask16));
   8589 
   8590                       SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   8591                  }
   8592               }
   8593           }
   8594     }
   8595     return SOC_E_NONE;
   8596 }
   8597 
   8598 
   8599 STATIC int
   8600 _phy_84741_firmware_is_downloaded(int unit, soc_port_t port, int ext_rom)
   8601 {
   8602     int rv = 0;
   8603     uint16 data16;
   8604     phy_ctrl_t *pc;
   8605 
   8606     pc = EXT_PHY_SW_STATE(unit, port);
   8607 
   8608     if (soc_property_port_get(unit, port,spn_PHY_FORCE_FIRMWARE_LOAD, TRUE)) {
   8609         return 0;
   8610     }
   8611 
   8612     /*
   8613      * To determine whether the firmware has been downloaded, it must
   8614      * pass the following:
   8615      * 1. firmware is in RAM: 1.c848.13==1
   8616      * 2. expected checksum:  1.ca1c==600d
   8617      * 3. version is non-zero:  1.ca1a!=0
   8618      */
   8619 
   8620     /* 1. Firmware download status */
   8621     rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, &data16);
   8622     if (rv != SOC_E_NONE) {
   8623         return 0;
   8624     }
   8625     if (ext_rom){
   8626         if ((data16 & 0xa000) != 0xa000) {
   8627             return 0;
   8628         }
   8629     } else if ((data16 & 0x6000) != 0x6000) {
   8630             return 0;
   8631     }
   8632     LOG_INFO(BSL_LS_SOC_PHY,
   8633              (BSL_META_U(unit,
   8634                          "84741 FW download status=%x: u=%d p=%d\n"), data16, unit, port));
   8635 
   8636     /* 2. Expected checksum */
   8637     rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16);
   8638     if ((rv != SOC_E_NONE) || (data16 != 0x600D)) {
   8639         return 0;
   8640     }
   8641     LOG_INFO(BSL_LS_SOC_PHY,
   8642              (BSL_META_U(unit,
   8643                          "84741 FW checksum=%x: u=%d p=%d\n"), data16, unit, port));
   8644 
   8645     /* 3. non-zero version */
   8646     rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16);
   8647     if ((rv != SOC_E_NONE) || (data16 == 0)) {
   8648         return 0;
   8649     }
   8650     LOG_INFO(BSL_LS_SOC_PHY,
   8651              (BSL_META_U(unit,
   8652                          "84741 FW version=%x: u=%d p=%d\n"), data16, unit, port));
   8653 
   8654     return 1;
   8655 }
   8656 
   8657 /* Function:
   8658  *    phy_84741_init
   8659  * Purpose:    
   8660  *    Initialize 84740 phys
   8661  * Parameters:
   8662  *    unit - StrataSwitch unit #.
   8663  *    port - StrataSwitch port #. 
   8664  * Returns:    
   8665  *    SOC_E_NONE
   8666  */
   8667 
   8668 STATIC int
   8669 phy_84741_init(int unit, soc_port_t port)
   8670 {
   8671     soc_timeout_t  to;
   8672     int            rv = SOC_E_NONE;
   8673     uint16         data16,ucode_ver;
   8674     uint16         chip_mode;
   8675     phy_ctrl_t     *pc;
   8676     int            ix;
   8677     uint32         phy_ext_rom_boot = 0; 
   8678     uint16 mask16;
   8679     uint32 devid;
   8680     unsigned char *pdata;
   8681     int data_len;
   8682     uint32 l2p, l2p_map;
   8683 
   8684     pc = EXT_PHY_SW_STATE(unit, port);
   8685     LOG_INFO(BSL_LS_SOC_PHY,
   8686              (BSL_META_U(unit,
   8687                          "PHY84740 init: u=%d p=%d desc=0x%x\n"),
   8688               unit, port,PTR_TO_INT(pc + 1)));
   8689     SOC_IF_ERROR_RETURN(
   8690         _phy_84741_config_devid(pc->unit,pc->port, pc, &devid));
   8691 
   8692     /* initialize default p2l map */
   8693     for (ix = 0; ix < NUM_LANES; ix++) {
   8694         P2L_MAP(pc,ix) = ix;
   8695     }
   8696 
   8697     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) ||
   8698         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   8699         PCS_REPEATER(pc) = FALSE;
   8700         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8701             /* Always set repeater flag in single port mode */
   8702             PHY_FLAGS_SET(unit, port,  PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER);
   8703         } else {
   8704             PHY_FLAGS_SET(unit, port,  PHY_FLAGS_FIBER | PHY_FLAGS_C45);
   8705         }
   8706 
   8707         FCMAP_PASSTHROUGH(pc) = soc_property_port_get(unit, port, spn_PHY_FCMAP_PASSTHROUGH, 0);
   8708 
   8709         if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) {
   8710             LOG_INFO(BSL_LS_SOC_PHY,
   8711                      (BSL_META_U(unit,
   8712                                  "PHY84740 init pass1: u=%d p=%d\n"), unit, port));
   8713 
   8714             /* check if to use the bcst mode for RAM uC download */
   8715             phy_ext_rom_boot = soc_property_port_get(unit, port, 
   8716                                             spn_PHY_EXT_ROM_BOOT, 1);
   8717 
   8718             SKIP_FW_DLOAD(pc) = _phy_84741_firmware_is_downloaded(unit, port,
   8719                                                            phy_ext_rom_boot);
   8720 
   8721             /*
   8722             if (SKIP_FW_DLOAD(pc)) {
   8723                LOG_CLI((BSL_META_U(unit,
   8724                                    "u=%d, p=%d skipping firmware download\n"),
   8725                         unit, port));
   8726             }
   8727             */
   8728 
   8729             if (!phy_ext_rom_boot) {
   8730                 if (!SKIP_FW_DLOAD(pc)) {
   8731                     pc->flags |= PHYCTRL_MDIO_BCST;
   8732                 }
   8733             } else {
   8734                 /*
   8735                  * To enable firmware to be downloaded to ports which are out-of-order, 
   8736                  * 1.c848.13 must be set on all ports first. The first port within the core that
   8737                  * has 1.c848.13 clear has control over the SPI-ROM, so later when the 
   8738                  * firmware is actually being downloaded, that port will first clear 1.c848.13 
   8739                  * and obtain control over the SPI-ROM.
   8740                  */
   8741                 data16 = (1 << 15) | (1 << 14) | (1 << 13);
   8742                 mask16 = data16;
   8743                 SOC_IF_ERROR_RETURN
   8744                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16));
   8745             }
   8746 
   8747             /* configure to quad-port mode to prepare for the broadcast mode */
   8748             SOC_IF_ERROR_RETURN(
   8749                 READ_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc,
   8750                             PHY84740_PMAD_CHIP_MODE_REG,&chip_mode));
   8751 
   8752             /* switch to quad-port mode if not already in */
   8753             if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) == PHY84740_PMAD_MODE_40G) {
   8754                 SOC_IF_ERROR_RETURN(
   8755                     _phy_84741_single_to_quad_mode(pc->unit,pc->port,pc));
   8756                 LOG_INFO(BSL_LS_SOC_PHY,
   8757                          (BSL_META_U(unit,
   8758                                      "PHY84740 init pass1 mode S to Q switch: u=%d p=%d\n"), unit, port));
   8759             }
   8760 
   8761             /* indicate second pass of init is needed */
   8762             PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2);
   8763             return SOC_E_NONE;
   8764         }
   8765     }
   8766 
   8767     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) ||
   8768         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   8769         LOG_INFO(BSL_LS_SOC_PHY,
   8770                  (BSL_META_U(unit,
   8771                              "PHY84740 init pass2: u=%d p=%d\n"), unit, port));
   8772         SOC_IF_ERROR_RETURN(
   8773             READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&chip_mode));
   8774 
   8775         /* check the current chip mode */
   8776         if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) == PHY84740_PMAD_MODE_40G) {
   8777             /* 
   8778              * switch to configured mode(quad mode) if current chip mode is single mode 
   8779              * In quad mode, the supported speed modes are 10G and 1G forced, 1G autoneg.
   8780              * However 1G currently is only working with QSFP fiber cable not Cu cable.
   8781              */
   8782             if (!(PHY84740_SINGLE_PORT_MODE(pc))) {
   8783                 LOG_WARN(BSL_LS_SOC_PHY,
   8784                          (BSL_META_U(unit,
   8785                                      "PHY84740 init pass2 mode switch: u=%d p=%d\n"), unit, port));
   8786                 SOC_IF_ERROR_RETURN(
   8787                     _phy_84741_single_to_quad_mode(unit,port,NULL));
   8788 
   8789             } else {  /* configured mode is single mode */
   8790                 /* if configured mode(single mode) matches current chip mode. Make sure 
   8791                  * it is SR4/LR4. If a optical module is plugged in when the device is 
   8792                  * configured in CR4 mode, it may damage the optical module because of big
   8793                  * voltage sway in CR4 mode. For now, the device is configured in
   8794                  * LR4/SR4 mode by default. If a QSFP Cu is used, EDC mode should be set to
   8795                  * 0x55.  In case there is a need to go to CR4 mode, user can use interface
   8796                  * set function to change to the CR4 mode. In this mode, both autoneg and 
   8797                  * forced 40G speed is supported.
   8798                  */
   8799                 /* config DAC mode and backplane mode for LR4/SR4  */
   8800                 mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK;
   8801                 if (devid == PHY84740_ID_84064) {
   8802                     data16 = PHY84740_PMAD_BKPLANE_MODE_MASK;
   8803                 } else {
   8804                     data16 = 0;
   8805                 }
   8806     
   8807                 SOC_IF_ERROR_RETURN(
   8808                     MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   8809                           data16, mask16));
   8810 
   8811                 SOC_IF_ERROR_RETURN
   8812                     (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc,
   8813                                       MII_CTRL_RESET, MII_CTRL_RESET));
   8814             }
   8815         } else {  /* current chip mode is quad mode */
   8816             /* switch to configured mode(single mode) if current chip mode is quad mode */
   8817             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8818 
   8819                 SOC_IF_ERROR_RETURN(
   8820                     _phy_84741_quad_to_single_mode(unit,port));
   8821             } else { /* configured mode is quad mode */
   8822 
   8823                 /* chip already in configured mode. config DAC/backplane mode */
   8824                 mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK;
   8825                 if (devid == PHY84740_ID_84064) {
   8826                     data16 = PHY84740_PMAD_BKPLANE_MODE_MASK;
   8827                 } else {
   8828                     data16 = 0;
   8829                 }
   8830     
   8831                 SOC_IF_ERROR_RETURN(
   8832                     MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   8833                           data16, mask16));
   8834             }
   8835         }
   8836 
   8837         /* should be done before reset */
   8838         l2p = soc_property_port_get(unit, port,spn_PHY_LANE0_L2P_MAP, 0);
   8839         if (l2p >= NUM_LANES) {
   8840             LOG_ERROR(BSL_LS_SOC_PHY,
   8841                       (BSL_META_U(unit,
   8842                                   "PHY84740 invalid L2P lane configuration: u=%d p=%d, l2p=%d\n"),
   8843                        unit, port,l2p));
   8844             return SOC_E_PARAM;
   8845         }
   8846 
   8847         SINGLE_LPMODE(pc) = soc_property_port_get(unit, port, spn_PHY_TX_DISABLE_NO_LPMODE, 0);
   8848 
   8849         /*
   8850          * 1.c701
   8851          *    - Quebec devices specifies the physical channel number designated as
   8852          *      logical channel 0 
   8853          *    - Quadra devices specifies the mapping of all physical channels to 
   8854          *      logical channels 
   8855          */
   8856         data16 = 0;
   8857         l2p_map = 0;
   8858         if (PHY84740_IS_QUADRA(devid)) {
   8859             for (ix = 0; ix < NUM_LANES; ix++) {
   8860                 l2p_map |= ((l2p + ix) % NUM_LANES) << (ix * 4);
   8861             }
   8862             data16 = l2p_map;
   8863             mask16 = 0xffff;
   8864             for (ix = 0; ix < NUM_LANES; ix++) {
   8865                 P2L_MAP(pc,((l2p_map >> (ix * 4)) & 0xf)) = ix;
   8866             }
   8867         } else {
   8868             data16 = l2p;
   8869             mask16 = PHY84740_L2P_PHYSICAL_LANE_MASK;
   8870 
   8871             /* physical to logical lane map, index is physical lane */
   8872             for (ix = 0; ix < NUM_LANES; ix++) {
   8873                 P2L_MAP(pc,(l2p + ix) % NUM_LANES) = ix;
   8874             }
   8875         }
   8876 
   8877         SOC_IF_ERROR_RETURN(
   8878             MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_LANE0_L2P_REG,
   8879                                             data16, mask16));
   8880 
   8881         /* do a soft reset */
   8882         SOC_IF_ERROR_RETURN
   8883             (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc,
   8884                               MII_CTRL_RESET, MII_CTRL_RESET));
   8885 
   8886         /* Wait for device to come out of reset */
   8887         soc_timeout_init(&to, 10000, 0);
   8888         while (!soc_timeout_check(&to)) {
   8889             rv = READ_PHY84740_PMA_PMD_CTRLr(unit, pc, &data16);
   8890             if (((data16 & MII_CTRL_RESET) == 0) ||
   8891                 SOC_FAILURE(rv)) {
   8892                 break;
   8893             }
   8894         }
   8895         if (((data16 & MII_CTRL_RESET) != 0) || SOC_FAILURE(rv)) {
   8896             LOG_WARN(BSL_LS_SOC_PHY,
   8897                      (BSL_META_U(unit,
   8898                                  "PHY84740 reset failed: u=%d p=%d\n"),
   8899                       unit, port));
   8900             return SOC_E_FAIL;
   8901         }
   8902 
   8903         if (pc->flags & PHYCTRL_UCODE_BCST_DONE) {
   8904             /* ucode is already loaded thru bcst */
   8905 
   8906             /* Not clearing PHYCTRL_UCODE_BCST_DONE  -->
   8907                This bit can be checked again, in case init is called again,
   8908                to avoid an additional firmware download  */
   8909 
   8910             phy_ext_rom_boot = 0;
   8911         } else {
   8912             phy_ext_rom_boot = soc_property_port_get(unit, port, 
   8913                                             spn_PHY_EXT_ROM_BOOT, 1);
   8914 
   8915             if (SKIP_FW_DLOAD(pc)) {
   8916                 /* do nothing */
   8917             } else 
   8918             if (phy_ext_rom_boot) {
   8919                 SOC_IF_ERROR_RETURN
   8920                     (_phy84741_rom_firmware_download(unit, port, pc));
   8921             } else { /* MDIO download to RAM */
   8922                 /* check if the firmware is delivered by user */
   8923                 if (phy_84741_uc_firmware_hook && 
   8924                     phy_84741_uc_firmware_hook(unit,port,devid,&pdata,&data_len) ) {
   8925                     SOC_IF_ERROR_RETURN
   8926                          (_phy84741_mdio_firmware_download(unit,port,pc,pdata,data_len));
   8927                 } else if (PHY84740_IS_MONTREAL(devid)) {
   8928                     /* do nothing since bcst mdio download was skipped */
   8929                 } else {
   8930                     if (devid == PHY84740_ID_84754) {
   8931                         SOC_IF_ERROR_RETURN
   8932                              (_phy84741_mdio_firmware_download(unit,port,pc,phy84754_ucode_bin,
   8933                                phy84754_ucode_bin_len));
   8934                     } else if (devid == PHY84740_ID_84740) {
   8935                         /* do not use 84753/84754 ucode for 84740. There is a voltage differece */
   8936                         SOC_IF_ERROR_RETURN
   8937                              (_phy84741_mdio_firmware_download(unit,port,pc,phy84740_ucode_bin,
   8938                                phy84740_ucode_bin_len));
   8939                     } else if (devid == PHY84740_ID_84064) {
   8940                         SOC_IF_ERROR_RETURN
   8941                              (_phy84741_mdio_firmware_download(unit,port,pc,phy84064_ucode_bin,
   8942                                phy84064_ucode_bin_len));
   8943                     } else if (devid == PHY84740_ID_84753) {
   8944                         SOC_IF_ERROR_RETURN
   8945                              (_phy84741_mdio_firmware_download(unit,port,pc,phy84753_ucode_bin,
   8946                                phy84753_ucode_bin_len));
   8947                     } else if (devid == PHY84740_ID_84752) {
   8948                         SOC_IF_ERROR_RETURN
   8949                              (_phy84741_mdio_firmware_download(unit,port,pc,phy84752_ucode_bin,
   8950                                phy84752_ucode_bin_len));
   8951                     } else if (devid == PHY84740_ID_84784) {
   8952                         SOC_IF_ERROR_RETURN
   8953                              (_phy84741_mdio_firmware_download(unit,port,pc,phy84784_ucode_bin,
   8954                                phy84784_ucode_bin_len));
   8955                     } else if (devid == PHY84740_ID_84780) {
   8956                         SOC_IF_ERROR_RETURN
   8957                              (_phy84741_mdio_firmware_download(unit,port,pc,phy84780_ucode_bin,
   8958                                phy84780_ucode_bin_len));
   8959                     } else if (PHY84740_IS_QUADRA(devid)) {
   8960                         SOC_IF_ERROR_RETURN
   8961                              (_phy84741_mdio_firmware_download(unit,port,pc,phy84758_ucode_bin,
   8962                                phy84758_ucode_bin_len));
   8963                     } else {
   8964                         LOG_WARN(BSL_LS_SOC_PHY,
   8965                                  (BSL_META_U(unit,
   8966                                              "84740: p=%d unknown device id: 0x%x\n"),
   8967                                              port,devid));
   8968                     }
   8969                 }
   8970             }
   8971         }
   8972   
   8973         /* reset will restart the uC. wait a few ms for checksum to be written*/
   8974         sal_udelay(42000);
   8975 
   8976         /* read the microcode revision */
   8977         SOC_IF_ERROR_RETURN
   8978             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &ucode_ver));
   8979 
   8980         /* check the completion of the microcode download. */
   8981         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   8982             uint16 cksum[4];
   8983             int ret = SOC_E_NONE;
   8984 
   8985             for (ix = 0; ix < NUM_LANES; ix++) {
   8986                 SOC_IF_ERROR_RETURN
   8987                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, ix));
   8988 
   8989                 /* check the completion of the microcode download. */
   8990                 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &cksum[ix]);
   8991                 if (cksum[ix] != 0x600D || SOC_FAILURE(rv)) {
   8992                     ret = SOC_E_FAIL;
   8993                 }
   8994             }
   8995             if (ret == SOC_E_FAIL) {
   8996                 LOG_WARN(BSL_LS_SOC_PHY,
   8997                          (BSL_META_U(unit,
   8998                                      "84740: p=%d SPI-ROM load: Bad Checksum lane 0,1,2,3 (0x%x),"
   8999                                      "(0x%x), (0x%x), (0x%x)\n"),
   9000                           port, cksum[0],cksum[1],cksum[2],cksum[3]));
   9001                 return SOC_E_FAIL;
   9002             }
   9003         } else {
   9004             rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16);
   9005             if (data16 != 0x600D || SOC_FAILURE(rv)) {
   9006                 LOG_WARN(BSL_LS_SOC_PHY,
   9007                          (BSL_META_U(unit,
   9008                                      "84740: p=%d SPI-ROM load: Bad Checksum (0x%x)\n"),
   9009                                      port, data16));
   9010                 return SOC_E_FAIL;
   9011             }
   9012         }
   9013 
   9014         LOG_WARN(BSL_LS_SOC_PHY,
   9015                  (BSL_META_U(unit,
   9016                              "%x init u=%d port=%d rom code ver. 0x%x: %s boot\n"), devid,
   9017                              unit, port, ucode_ver,phy_ext_rom_boot? "SPI-ROM":"MDIO_TO_RAM"));
   9018 
   9019         if (!(PHY84740_SINGLE_PORT_MODE(pc))) {
   9020             /* clear 1.0xcd17 to enable the PCS */
   9021             SOC_IF_ERROR_RETURN(
   9022                 WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
   9023                             PHY84740_RESET_CONTROL_REGISTER, 0));
   9024         } else {
   9025             /* 40G no autoneg support */
   9026             /* EDC mode for SR4/LR4 0x44, done in ucode, no need to set for CR4 */
   9027             /* disable cl72 */
   9028             SOC_IF_ERROR_RETURN
   9029                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, 0x0000));
   9030             /* disable AN */
   9031             SOC_IF_ERROR_RETURN
   9032                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 0x0));
   9033         }
   9034 
   9035         REVERSE_MODE(pc) = soc_property_port_get(unit, port, spn_PORT_PHY_MODE_REVERSE, 0);
   9036 
   9037 
   9038         mask16 = PHY84740_RXLOS_OVERRIDE_MASK |
   9039                  PHY84740_MOD_ABS_OVERRIDE_MASK;
   9040         data16 = 0;
   9041 
   9042         RX_LOS(pc) = soc_property_port_get(unit, port,spn_PHY_RX_LOS, 0);
   9043         MOD_ABS(pc) = soc_property_port_get(unit, port,spn_PHY_MOD_ABS, 0);
   9044         RX_LOS_INVERT(pc) = soc_property_port_get(unit, port,spn_PHY_RX_LOS_INVERT, 0);
   9045         MOD_ABS_INVERT(pc) = soc_property_port_get(unit, port,spn_PHY_MOD_ABS_INVERT, 0);
   9046         MOD_AUTO_DETECT(pc) = soc_property_port_get(unit, port, spn_PHY_MOD_AUTO_DETECT, 0);
   9047 
   9048         /* default: override RX_LOS signalling */
   9049         if (!RX_LOS(pc)) {
   9050             data16 |= PHY84740_RXLOS_OVERRIDE_MASK;
   9051         } 
   9052         /* default: override MOD_ABS signalling */
   9053         if (!MOD_ABS(pc)) {
   9054             data16 |= PHY84740_MOD_ABS_OVERRIDE_MASK;
   9055         } 
   9056 
   9057         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9058             for (ix = 0; ix < NUM_LANES; ix++) {
   9059                 SOC_IF_ERROR_RETURN
   9060                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   9061                                 PHY84740_PMAD_AER_ADDR_REG, ix));
   9062                 SOC_IF_ERROR_RETURN
   9063                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
   9064                           PHY84740_PMAD_OPTICAL_CFG_REG, 
   9065                           data16, mask16));
   9066             }
   9067         } else {
   9068             SOC_IF_ERROR_RETURN
   9069                (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
   9070                                  PHY84740_PMAD_OPTICAL_CFG_REG, 
   9071                                  data16, mask16));
   9072         }   
   9073 
   9074         mask16 = PHY84740_RXLOS_LVL_MASK | PHY84740_MOD_ABS_LVL_MASK;
   9075         data16 = 0;
   9076         /* default: RX_LOS level high */
   9077         if (!RX_LOS_INVERT(pc)) {
   9078             data16 |= PHY84740_RXLOS_LVL_MASK;
   9079         }
   9080         /* default: MOD_ABS level high */
   9081         if (!MOD_ABS_INVERT(pc)) {
   9082             data16 |= PHY84740_MOD_ABS_LVL_MASK;
   9083         }
   9084 
   9085         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9086             for (ix = 0; ix < NUM_LANES; ix++) {
   9087                 SOC_IF_ERROR_RETURN
   9088                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   9089                                 PHY84740_PMAD_AER_ADDR_REG, ix));
   9090                 SOC_IF_ERROR_RETURN
   9091                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
   9092                           PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   9093                           data16, mask16));
   9094             }
   9095         /* point back to lane0 */
   9096         SOC_IF_ERROR_RETURN
   9097             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   9098         } else {
   9099             SOC_IF_ERROR_RETURN
   9100                (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
   9101                                  PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   9102                                  data16, mask16));
   9103         }
   9104 
   9105         if (soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, 0)) {
   9106             if (!PHY84740_SINGLE_PORT_MODE(pc)) {
   9107                 /* put device in repeat mode. Single port is already in repeat mode */
   9108                 SOC_IF_ERROR_RETURN(
   9109                     MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xc806, 0x6,0x6));
   9110                 /* in repeater mode, 84740 will use autoneg from internal serdes. But
   9111                  * 84064 will still use cl73/cl72 from ifself.
   9112                  */
   9113                 if (devid != PHY84740_ID_84064) {
   9114                     PCS_REPEATER(pc) = TRUE;
   9115                     PHY_FLAGS_SET(unit, port,  PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER);
   9116                 }
   9117             }
   9118         }
   9119 
   9120         SOC_IF_ERROR_RETURN(_phy_84741_squelch_enable(unit, port, -1, TRUE, FALSE));
   9121   
   9122         if (FCMAP_PASSTHROUGH(pc)) {
   9123             if ((!PHY84740_SINGLE_PORT_MODE(pc)) && (PHY84740_IS_QUADRA(devid))) {
   9124                 /* put device in the fcmap passthrough mode. */
   9125                 SOC_IF_ERROR_RETURN(
   9126                     MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0x3, 0x3));
   9127                 SOC_IF_ERROR_RETURN(
   9128                     MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, MII_CTRL_RESET, MII_CTRL_RESET));
   9129             } else {
   9130                 FCMAP_PASSTHROUGH(pc) = FALSE;
   9131             }
   9132         }
   9133   
   9134         /* Polarity configuration */
   9135         SOC_IF_ERROR_RETURN
   9136             (_phy_84741_polarity_flip_set(unit,port));
   9137 
   9138 
   9139         /* check if module auto detect enabled */
   9140         if (MOD_AUTO_DETECT(pc)) {
   9141             if ((ucode_ver & 0x0fff) < 0x105) {
   9142                 LOG_ERROR(BSL_LS_SOC_PHY,
   9143                           (BSL_META_U(unit,
   9144                                       "84740 module auto detect requires ucode ver 0x105 or newer: "
   9145                                       "u=%d p%d\n"), unit, port));
   9146             } else if (!(RX_LOS(pc) && MOD_ABS(pc))) {
   9147                 MOD_AUTO_DETECT(pc) = 0;
   9148                 LOG_ERROR(BSL_LS_SOC_PHY,
   9149                           (BSL_META_U(unit,
   9150                                       "84740 module auto detect requires mod_abs and rx_lost "
   9151                                       "to be configured: u=%d p%d\n"), unit, port));
   9152             } else if (PHY84740_SINGLE_PORT_MODE(pc)) { 
   9153                 LOG_INFO(BSL_LS_SOC_PHY,
   9154                          (BSL_META_U(unit,
   9155                                      "PHY84740 QSFP module auto detect enabled: u=%d p=%d\n"), 
   9156                                      unit, port));
   9157                 rv = MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_GEN_PURPOSE_REG, 
   9158                                                      PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN, 
   9159                                                      PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN);
   9160                 if (SOC_FAILURE(rv)) {
   9161                     LOG_ERROR(BSL_LS_SOC_PHY,
   9162                               (BSL_META_U(unit,
   9163                                           "PHY84740 setting QSP module auto detect failed: u=%d p%d\n"),
   9164                                unit, port));
   9165                 } else {
   9166                     MOD_AUTO_DETECT_MSG(pc) = 1;
   9167                 }
   9168             } else if (devid == PHY84740_ID_84754) {
   9169                 LOG_INFO(BSL_LS_SOC_PHY,
   9170                          (BSL_META_U(unit,
   9171                                      "PHY84740 SFP module auto detect on: u=%d p=%d\n"), 
   9172                                      unit, port));
   9173                 rv = MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_MOD_AUTO_DETECT_STS_REG,
   9174                                                      PHY84740_MOD_AUTO_DETECT_STS_SFP_EN, 
   9175                                                      PHY84740_MOD_AUTO_DETECT_STS_SFP_EN);
   9176                 if (SOC_FAILURE(rv)) {
   9177                     LOG_ERROR(BSL_LS_SOC_PHY,
   9178                               (BSL_META_U(unit,
   9179                                           "PHY84740 setting SFP module auto detect failed: u=%d p%d\n"),
   9180                                unit, port));
   9181                 } else {
   9182                     MOD_AUTO_DETECT_MSG(pc) = 1;
   9183                 }
   9184             } else {
   9185                 LOG_ERROR(BSL_LS_SOC_PHY,
   9186                           (BSL_META_U(unit,
   9187                                       "PHY84740 module auto detect not supported: u=%d p%d\n"),
   9188                            unit, port));
   9189             }
   9190         }
   9191     }
   9192     return SOC_E_NONE;
   9193 }
   9194 
   9195 /*
   9196  * Function:
   9197  *      phy_84741_an_get
   9198  * Purpose:
   9199  *      Get the current auto-negotiation status (enabled/busy)
   9200  * Parameters:
   9201  *      unit - StrataSwitch unit #.
   9202  *      port - StrataSwitch port #.
   9203  *      an   - (OUT) if true, auto-negotiation is enabled.
   9204  *      an_done - (OUT) if true, auto-negotiation is complete. This
   9205  *              value is undefined if an == false.
   9206  * Returns:
   9207  *      SOC_E_XXX
   9208  */
   9209 
   9210 STATIC int
   9211 phy_84741_an_get(int unit, soc_port_t port, int *an, int *an_done)
   9212 {
   9213     phy_ctrl_t *pc;
   9214     uint16 an_status;
   9215 
   9216     pc = EXT_PHY_SW_STATE(unit, port);
   9217 
   9218     if (FCMAP_PASSTHROUGH(pc)) {
   9219         *an = TRUE;
   9220         *an_done = TRUE;
   9221         return SOC_E_NONE;
   9222     }
   9223 
   9224     SOC_IF_ERROR_RETURN(
   9225         READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_INTR_VALUE_REG,
   9226                              &an_status));
   9227     *an_done = (an_status & PHY84740_AUTONEG_COMPLETE)? TRUE: FALSE;
   9228 
   9229     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9230         SOC_IF_ERROR_RETURN
   9231             (READ_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, &an_status));
   9232         *an = (an_status & PHY84740_AN_ENABLE)? TRUE: FALSE;
   9233     } else {
   9234         SOC_IF_ERROR_RETURN
   9235             (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, &an_status));
   9236         *an = (an_status & PHY84740_AN_ENABLE)? TRUE: FALSE;
   9237     }
   9238     return SOC_E_NONE;
   9239 }
   9240 
   9241 /*
   9242  * Function:
   9243  *      phy_84741_an_set
   9244  * Purpose:
   9245  *      Enable or disabled auto-negotiation on the specified port.
   9246  * Parameters:
   9247  *      unit - StrataSwitch unit #.
   9248  *      port - StrataSwitch port #.
   9249  *      an   - Boolean, if true, auto-negotiation is enabled
   9250  *              (and/or restarted). If false, autonegotiation is disabled.
   9251  * Returns:
   9252  *      SOC_E_XXX
   9253  */
   9254 STATIC int
   9255 phy_84741_an_set(int unit, soc_port_t port, int an)
   9256 {
   9257     phy_ctrl_t  *pc;
   9258     phy_ctrl_t  *int_pc;
   9259     uint16 mode;
   9260 
   9261     pc = EXT_PHY_SW_STATE(unit, port);
   9262 
   9263     LOG_INFO(BSL_LS_SOC_PHY,
   9264              (BSL_META_U(unit,
   9265                          "phy_84741_an_set: u=%d p=%d an=%d\n"),
   9266                          unit, port, an));
   9267     /* make sure internal autoneg is turned off always */
   9268     int_pc = INT_PHY_SW_STATE(unit, port);
   9269 
   9270     if (FCMAP_PASSTHROUGH(pc)) {
   9271         if (NULL != int_pc) {
   9272             SOC_IF_ERROR_RETURN(
   9273                 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, FALSE));
   9274         }
   9275         return SOC_E_NONE;
   9276     }
   9277 
   9278     if (REVERSE_MODE(pc) && IS_HG_PORT(unit, port)) {
   9279         /* Both WC and external phy need to set AN off @ 10G or 40G */
   9280         an = 0;
   9281         if (NULL != int_pc) {
   9282             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9283                 /* 
   9284                  * Internal Serdes needs to be in forced KR4 (a misnomer), meaning
   9285                  * DFE is enabled but cl73 (or cl37) are turned off. This enables
   9286                  * the equalizer as required for KR backplane interfaces
   9287                  */
   9288                 SOC_IF_ERROR_RETURN(
   9289                     PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, 0));
   9290                 SOC_IF_ERROR_RETURN(
   9291                     PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_KR4));
   9292                 SOC_IF_ERROR_RETURN(
   9293                     PHY_SPEED_SET(int_pc->pd, unit, port, 40000));
   9294 
   9295                 /* disable cl72: 1.96=0 (device 1, register 0x96) */
   9296                 SOC_IF_ERROR_RETURN
   9297                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, 0));
   9298                 /* disable AN: 7.0=0 (device 7, register 0) */
   9299                 SOC_IF_ERROR_RETURN
   9300                     (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 0));
   9301             }
   9302         }
   9303     }
   9304 
   9305     if (NULL != int_pc) {
   9306         if (REVERSE_MODE(pc)) {
   9307             SOC_IF_ERROR_RETURN(
   9308                 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an));
   9309         } else {
   9310             /* if in passthru mode, enable autoneg on internal serdes */
   9311             if (PCS_REPEATER(pc)) {
   9312                 SOC_IF_ERROR_RETURN(
   9313                     PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an));
   9314             } else {
   9315                 SOC_IF_ERROR_RETURN(
   9316                     PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, FALSE));
   9317             }
   9318         }
   9319     }
   9320 
   9321     /* 0xc700(0xc710 once firmware fixed), PCS link status overide for CR4 autoneg.
   9322      * bit 4 enable override, bit 1 status indication
   9323      * system side link status check in 40G 0xcd04, this is per lane register 
   9324      */
   9325     SOC_IF_ERROR_RETURN(
   9326         READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&mode));
   9327 
   9328     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9329         /* make sure internal speed is set to 40G */
   9330         if (an) {
   9331             if (NULL != int_pc) {
   9332                 if (!REVERSE_MODE(pc)) {
   9333                     if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) {
   9334                         PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_CR);
   9335                     }
   9336                     SOC_IF_ERROR_RETURN(
   9337                         PHY_SPEED_SET(int_pc->pd, unit, port, 40000));
   9338                 }
   9339             }
   9340         }
   9341 
   9342         /* autoneg only supported in CR4 mode */
   9343         /* no autoneg if in SR4/LR4 mode */    
   9344         if (!(mode & (PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK)) ||
   9345             (REVERSE_MODE(pc) && IS_HG_PORT(unit, port))) {
   9346             an = 0; 
   9347         }
   9348 
   9349         /* enable/disable cl72 */
   9350         SOC_IF_ERROR_RETURN
   9351             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, an? 2:0));
   9352         /* enable/disable AN */
   9353         SOC_IF_ERROR_RETURN
   9354             (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 
   9355                an? AN_ENABLE | AN_RESTART: 0x0));
   9356 
   9357         return SOC_E_NONE; 
   9358     } else { /* quad mode, cl73 for backplane */
   9359         if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   9360             /* make sure internal speed is set to 10G */
   9361             if (an) {
   9362                 if (NULL != int_pc) {
   9363                     if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) {
   9364                         PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_CR);
   9365                     }
   9366                     SOC_IF_ERROR_RETURN(
   9367                         PHY_SPEED_SET(int_pc->pd, unit, port, 10000));
   9368                 }
   9369             }
   9370 
   9371             /* enable/disable cl72 */
   9372             SOC_IF_ERROR_RETURN
   9373                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, an? 2:0));
   9374             /* enable/disable AN */
   9375             SOC_IF_ERROR_RETURN
   9376                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 
   9377                    an? AN_ENABLE | AN_RESTART: 0x0));
   9378         }
   9379     }
   9380 
   9381     if (an) {
   9382         /* Enable Clause 37 AN */
   9383         SOC_IF_ERROR_RETURN
   9384             (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, MII_CTRL_AE | MII_CTRL_RAN));
   9385         SOC_IF_ERROR_RETURN
   9386              (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8309, 0, (1 << 5)));
   9387     } else {
   9388         /* disable Clause 37 AN */
   9389         SOC_IF_ERROR_RETURN
   9390             (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, 0x0));
   9391 
   9392         /* Enable encoded forced speed derived from ieeeControl1 and ieeeControl2 */
   9393         SOC_IF_ERROR_RETURN
   9394              (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8309, (1 << 5), (1 << 5)));
   9395     }
   9396 
   9397     return SOC_E_NONE;
   9398 }
   9399 
   9400 /*
   9401  * Function:
   9402  *      phy_84741_ability_advert_get
   9403  * Purpose:
   9404  *      Get the current advertisement for auto-negotiation.
   9405  * Parameters:
   9406  *      unit - StrataSwitch unit #.
   9407  *      port - StrataSwitch port #.
   9408  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   9409  * Returns:
   9410  *      SOC_E_XXX
   9411  * Notes:
   9412  *      The advertisement is retrieved for the ACTIVE medium.
   9413  *      No synchronization performed at this level.
   9414  */
   9415 
   9416 STATIC int
   9417 phy_84741_ability_advert_get(int unit, soc_port_t port,
   9418                            soc_port_ability_t *ability)
   9419 {
   9420     uint16           an_adv;
   9421     soc_port_mode_t  mode;
   9422     phy_ctrl_t      *pc;
   9423 
   9424     if (NULL == ability) {
   9425         return (SOC_E_PARAM);
   9426     }
   9427     pc = EXT_PHY_SW_STATE(unit, port);
   9428 
   9429     if (FCMAP_PASSTHROUGH(pc)) {
   9430         ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   9431         ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   9432         return SOC_E_NONE;
   9433     }
   9434 
   9435     if (PCS_REPEATER(pc)) {
   9436         phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port);
   9437         if (NULL != int_pc) {
   9438             SOC_IF_ERROR_RETURN(
   9439                 PHY_ABILITY_ADVERT_GET(int_pc->pd, unit, port, ability));
   9440         }
   9441         return SOC_E_NONE;
   9442     }
   9443 
   9444     mode = 0;
   9445     ability->pause = 0;
   9446     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9447         /* advert register 1 */
   9448         SOC_IF_ERROR_RETURN
   9449             (READ_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, &an_adv));
   9450 
   9451         mode |= (an_adv & AN_ADVERT_40GCR4) ? SOC_PA_SPEED_40GB : 0;
   9452         mode |= (an_adv & AN_ADVERT_40GKR4) ? SOC_PA_SPEED_40GB : 0;
   9453         mode |= (an_adv & AN_ADVERT_10GKR) ? SOC_PA_SPEED_10GB : 0;
   9454         mode |= (an_adv & AN_ADVERT_1GKX) ? SOC_PA_SPEED_1000MB : 0;
   9455         ability->speed_full_duplex = mode;
   9456 
   9457         SOC_IF_ERROR_RETURN
   9458             (READ_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, &an_adv));
   9459 
   9460         switch (an_adv & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) {
   9461             case AN_ADVERT_PAUSE:
   9462                 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   9463                 break;
   9464             case AN_ADVERT_PAUSE_ASYM:
   9465                 ability->pause = SOC_PA_PAUSE_TX;
   9466                 break;
   9467             case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM:
   9468                 ability->pause = SOC_PA_PAUSE_RX;
   9469                 break;
   9470         }
   9471     } else {
   9472         /* check Full Duplex advertisement on Clause 37 */
   9473         SOC_IF_ERROR_RETURN
   9474             (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, &an_adv));
   9475         mode |= (an_adv & MII_ANA_C37_FD) ? SOC_PA_SPEED_1000MB : 0;
   9476 
   9477         ability->speed_full_duplex = mode;
   9478 
   9479         switch (an_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) {
   9480             case MII_ANA_C37_PAUSE:
   9481                 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   9482                 break;
   9483             case MII_ANA_C37_ASYM_PAUSE:
   9484                 ability->pause = SOC_PA_PAUSE_TX;
   9485                 break;
   9486             case MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE:
   9487                 ability->pause = SOC_PA_PAUSE_RX;
   9488                 break;
   9489         }
   9490     }
   9491 
   9492     LOG_INFO(BSL_LS_SOC_PHY,
   9493              (BSL_META_U(unit,
   9494                          "phy_84741_ability_advert_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"),
   9495               unit, port, ability->speed_full_duplex, ability->pause));
   9496     return SOC_E_NONE;
   9497 }
   9498 
   9499 /*
   9500 * Function:
   9501 *      phy_84741_ability_remote_get
   9502 * Purpose:
   9503 *      Get the device's complete abilities.
   9504 * Parameters:
   9505 *      unit - StrataSwitch unit #.
   9506 *      port - StrataSwitch port #.
   9507 *      ability - return device's abilities.
   9508 * Returns:
   9509 *      SOC_E_XXX
   9510 */
   9511 
   9512 STATIC int
   9513 phy_84741_ability_remote_get(int unit, soc_port_t port, 
   9514                             soc_port_ability_t *ability)
   9515 {
   9516     phy_ctrl_t *pc;
   9517     uint16      lp_abil;
   9518 
   9519     if (NULL == ability) {
   9520         return SOC_E_PARAM;
   9521     }
   9522 
   9523     pc = EXT_PHY_SW_STATE(unit, port);
   9524                                            
   9525     if (FCMAP_PASSTHROUGH(pc)) {
   9526         ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   9527         ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   9528         return SOC_E_NONE;
   9529     }
   9530 
   9531     if (PCS_REPEATER(pc)) {
   9532         phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port);
   9533         if (NULL != int_pc) {
   9534             SOC_IF_ERROR_RETURN(
   9535                 PHY_ABILITY_REMOTE_GET(int_pc->pd, unit, port, ability));
   9536         }
   9537         return SOC_E_NONE;
   9538     }
   9539 
   9540     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   9541 
   9542     /* check CL73 first */
   9543     SOC_IF_ERROR_RETURN
   9544         (READ_PHY84740_MMF_AN_REG(unit, pc, AN_LP_ABILITY_1_REG, &lp_abil));
   9545     ability->speed_full_duplex = (lp_abil & AN_ADVERT_40GCR4) ? SOC_PA_SPEED_40GB : 0;
   9546     ability->speed_full_duplex |= (lp_abil & AN_ADVERT_40GKR4) ? SOC_PA_SPEED_40GB : 0;
   9547     ability->speed_full_duplex |= (lp_abil & AN_ADVERT_10GKR) ? SOC_PA_SPEED_10GB : 0;
   9548     ability->speed_full_duplex |= (lp_abil & AN_ADVERT_1GKX) ? SOC_PA_SPEED_1000MB : 0;
   9549 
   9550     SOC_IF_ERROR_RETURN
   9551         (READ_PHY84740_MMF_AN_REG(unit, pc, AN_LP_ABILITY_0_REG, &lp_abil));
   9552 
   9553     ability->pause = 0;
   9554     switch (lp_abil & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) {
   9555         case AN_ADVERT_PAUSE:
   9556             ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   9557             break;
   9558         case AN_ADVERT_PAUSE_ASYM:
   9559             ability->pause = SOC_PA_PAUSE_TX;
   9560             break;
   9561         case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM:
   9562             ability->pause = SOC_PA_PAUSE_RX;
   9563             break;
   9564     }
   9565 
   9566     /* check CL37 */
   9567     SOC_IF_ERROR_RETURN
   9568         (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE5, &lp_abil));
   9569     ability->speed_full_duplex  |= (lp_abil & MII_ANA_C37_FD) ? 
   9570                                    SOC_PA_SPEED_1000MB : 0;
   9571 
   9572     switch (lp_abil & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) {
   9573         case MII_ANP_C37_PAUSE:
   9574             ability->pause |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   9575             break;
   9576         case MII_ANP_C37_ASYM_PAUSE:
   9577             ability->pause |= SOC_PA_PAUSE_TX;
   9578             break;
   9579         case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE:
   9580             ability->pause |= SOC_PA_PAUSE_RX;
   9581             break;
   9582     }
   9583 
   9584     LOG_INFO(BSL_LS_SOC_PHY,
   9585              (BSL_META_U(unit,
   9586                          "phy_84741_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"),
   9587               unit, port, ability->speed_full_duplex, ability->pause));
   9588 
   9589     return (SOC_E_NONE);
   9590 }
   9591 
   9592 /*
   9593  * Function:
   9594  *      phy_84741_ability_advert_set
   9595  * Purpose:
   9596  *      Set the current advertisement for auto-negotiation.
   9597  * Parameters:
   9598  *      unit - StrataSwitch unit #.
   9599  *      port - StrataSwitch port #.
   9600  *      mode - Port mode mask indicating supported options/speeds.
   9601  * Returns:
   9602  *      SOC_E_XXX
   9603  * Notes:
   9604  *      The advertisement is set only for the ACTIVE medium.
   9605  *      No synchronization performed at this level.
   9606  */
   9607 
   9608 STATIC int
   9609 phy_84741_ability_advert_set(int unit, soc_port_t port,
   9610                        soc_port_ability_t *ability)
   9611 {
   9612     uint16           an_adv,an_adv_cl37,mode;
   9613     phy_ctrl_t      *pc;
   9614 
   9615     if (NULL == ability) {
   9616         return (SOC_E_PARAM);
   9617     }
   9618 
   9619     pc = EXT_PHY_SW_STATE(unit, port);
   9620 
   9621     if (FCMAP_PASSTHROUGH(pc)) {
   9622         return SOC_E_NONE;
   9623     }
   9624 
   9625     if (PCS_REPEATER(pc)) {
   9626         phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port);
   9627         if (NULL != int_pc) {
   9628             SOC_IF_ERROR_RETURN(
   9629                 PHY_ABILITY_ADVERT_SET(int_pc->pd, unit, port, ability));
   9630         }
   9631         return SOC_E_NONE;
   9632     }
   9633 
   9634     SOC_IF_ERROR_RETURN(
   9635         READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&mode));
   9636 
   9637     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9638         if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   9639             an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_40GB) ?
   9640                        AN_ADVERT_40GKR4 : 0;
   9641             an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ?
   9642                        AN_ADVERT_10GKR : 0;
   9643         } else {
   9644 
   9645             /* only advertise 40G CR4 */
   9646             an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_40GB) ?
   9647                    AN_ADVERT_40GCR4 : 0;
   9648         }
   9649 
   9650         /* CL73 advert register 1 */
   9651         SOC_IF_ERROR_RETURN
   9652             (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, an_adv));
   9653 
   9654     } else { /* quad-port mode */
   9655         if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   9656             an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ?
   9657                        AN_ADVERT_10GKR : 0;
   9658             an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ?
   9659                        AN_ADVERT_1GKX : 0;
   9660 
   9661             /* CL73 advert register 1 */
   9662             SOC_IF_ERROR_RETURN
   9663                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, an_adv));
   9664         } 
   9665 
   9666         /* only 1G CL37 autoneg */
   9667         an_adv =  (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ?
   9668               AN_ADVERT_1G : 0;
   9669 
   9670         /* write Full Duplex advertisement on Clause 37 */
   9671         SOC_IF_ERROR_RETURN
   9672             (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4,an_adv));
   9673     }    
   9674 
   9675     an_adv = an_adv_cl37 = 0;
   9676     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   9677         case SOC_PA_PAUSE_TX:
   9678             an_adv = AN_ADVERT_PAUSE_ASYM;
   9679             an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE;
   9680             break;
   9681         case SOC_PA_PAUSE_RX:
   9682             an_adv = AN_ADVERT_PAUSE_ASYM | AN_ADVERT_PAUSE;
   9683             an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE;
   9684             break;
   9685         case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   9686             an_adv_cl37 = MII_ANA_C37_PAUSE;
   9687             an_adv = AN_ADVERT_PAUSE;
   9688             break;
   9689     }
   9690     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9691         SOC_IF_ERROR_RETURN
   9692             (MODIFY_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, an_adv,
   9693                                AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM));
   9694     } else {
   9695         if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   9696             SOC_IF_ERROR_RETURN
   9697                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, an_adv,
   9698                                AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM));
   9699         }
   9700 
   9701         /* write Pause advertisement on Clause 37 */
   9702         SOC_IF_ERROR_RETURN
   9703             (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, an_adv_cl37,
   9704                                 MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE));
   9705     }
   9706 
   9707     LOG_INFO(BSL_LS_SOC_PHY,
   9708              (BSL_META_U(unit,
   9709                          "phy_8072_ability_advert_set: u=%d p=%d pause=0x%08x adv_reg1=0x%04x\n"),
   9710               unit, port, ability->pause, an_adv));
   9711         
   9712     return SOC_E_NONE;
   9713 }
   9714 
   9715 /*
   9716  * Function:
   9717  *      phy_84741_ability_local_get
   9718  * Purpose:
   9719  *      Get the device's complete abilities.
   9720  * Parameters:
   9721  *      unit - StrataSwitch unit #.
   9722  *      port - StrataSwitch port #.
   9723  *      ability - return device's abilities.
   9724  * Returns:
   9725  *      SOC_E_XXX
   9726  */
   9727 
   9728 STATIC int
   9729 phy_84741_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   9730 {
   9731     phy_ctrl_t *pc;
   9732     phy_ctrl_t  *int_pc;
   9733     pc = EXT_PHY_SW_STATE(unit, port);
   9734     int_pc = INT_PHY_SW_STATE(unit, port);
   9735 
   9736     LOG_INFO(BSL_LS_SOC_PHY,
   9737              (BSL_META_U(unit,
   9738                          "phy_84741_ability_local_get: u=%d p=%d\n"),
   9739               unit, port));
   9740                                                                                
   9741     if (NULL == ability) {
   9742         return SOC_E_PARAM;
   9743     }
   9744 
   9745     if (FCMAP_PASSTHROUGH(pc)) {
   9746         ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   9747         ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   9748         return SOC_E_NONE;
   9749     }
   9750 
   9751     if (NULL != int_pc && PCS_REPEATER(pc)) {
   9752         SOC_IF_ERROR_RETURN(
   9753             PHY_ABILITY_LOCAL_GET(int_pc->pd, unit, port, ability));
   9754         return SOC_E_NONE;
   9755     }
   9756     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   9757                                                                                
   9758     switch(pc->speed_max) {
   9759         case 42000:
   9760         /* fall through */
   9761         case 40000:
   9762             ability->speed_full_duplex = SOC_PA_SPEED_40GB;
   9763             break;
   9764         case 10000:
   9765         default:
   9766             ability->speed_full_duplex  = SOC_PA_SPEED_1000MB;
   9767             ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   9768             break;
   9769     }
   9770                                                                                
   9771     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 
   9772     ability->interface = SOC_PA_INTF_XGMII;
   9773     ability->medium    = SOC_PA_MEDIUM_FIBER;
   9774     ability->loopback  = SOC_PA_LB_PHY;
   9775                                                                                
   9776     LOG_INFO(BSL_LS_SOC_PHY,
   9777              (BSL_META_U(unit,
   9778                          "phy_84741_ability_local_get: u=%d p=%d speed=0x%x\n"),
   9779               unit, port, ability->speed_full_duplex));
   9780                                                                                
   9781     return (SOC_E_NONE);
   9782 }
   9783 
   9784 STATIC int
   9785 _phy84741_mod_auto_detect_update(int unit, soc_port_t port)
   9786 {
   9787     phy_ctrl_t *pc;
   9788     uint16 data;
   9789     uint16 status;
   9790 
   9791     pc = EXT_PHY_SW_STATE(unit, port);
   9792 
   9793     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9794         /* point to lane 0 */
   9795         SOC_IF_ERROR_RETURN
   9796             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   9797     }
   9798  
   9799     /* check for presence */
   9800     SOC_IF_ERROR_RETURN
   9801         (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,
   9802                                        PHY84740_PMAD_OPTICAL_CFG_REG,&data));
   9803     if (data & PHY84740_PMAD_OPTICAL_CFG_MOD_PRESENCE) {
   9804         SOC_IF_ERROR_RETURN
   9805             (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,
   9806                                            PHY84740_MOD_AUTO_DETECT_STS_REG, &status));
   9807         /* make sure auto detection completed */
   9808         if (!(status & PHY84740_MOD_AUTO_DETECT_STS_NOT_DONE)) {
   9809             if (MOD_AUTO_DETECT_MSG(pc)) {
   9810                 /* present and must print message */
   9811                 MOD_AUTO_DETECT_MSG(pc) = 0;
   9812                 if (status & PHY84740_MOD_AUTO_DETECT_STS_NOT_RES) {
   9813                     uint16  mod_130 = 0, mod_131 = 0;
   9814                     (void) (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f2, &mod_130));
   9815                     (void) (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f3, &mod_131));
   9816                     LOG_ERROR(BSL_LS_SOC_PHY,
   9817                               (BSL_META_U(unit,
   9818                                           "PHY84740 could not detect module, "
   9819                                           "defaulting to SR(4): u=%d p=%d sts=0x%x (0x%x:0x%x)\n"), 
   9820                                unit, port, status, mod_130, mod_131));
   9821                 } else {
   9822                     /* auto detect done and successfully resolved */
   9823                     SOC_IF_ERROR_RETURN
   9824                         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&data));
   9825                     LOG_ERROR(BSL_LS_SOC_PHY,
   9826                               (BSL_META_U(unit,
   9827                                           "PHY84740 %s module detected: u=%d p=%d\n"), 
   9828                                (data & PHY84740_PMAD_DAC_MODE_MASK) ? "CR4" : "SR4",
   9829                                unit, port));
   9830                 }
   9831             }
   9832         } else if (!(status & PHY84740_MOD_AUTO_DETECT_STS_I2C_FAIL) &&
   9833                    (MOD_AUTO_DETECT_MSG(pc))) {
   9834             uint16  mod_130 = 0, mod_131 = 0;
   9835             (void) (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f2, &mod_130));
   9836             (void) (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f3, &mod_131));
   9837             MOD_AUTO_DETECT_MSG(pc) = 0;
   9838             LOG_ERROR(BSL_LS_SOC_PHY,
   9839                       (BSL_META_U(unit,
   9840                                   "PHY84740 i2c failed while detecting module, "
   9841                                   "defaulting to SR(4): u=%d p=%d sts=0x%x (0x%x:0x%x)\n"), 
   9842                        unit, port, status, mod_130, mod_131));
   9843         }
   9844     } else {
   9845         if (!MOD_AUTO_DETECT_MSG(pc)) {
   9846                 /* module not present */
   9847                 LOG_ERROR(BSL_LS_SOC_PHY,
   9848                           (BSL_META_U(unit,
   9849                                       "PHY84740 module removed u=%d p=%d\n"), unit, port));
   9850                 MOD_AUTO_DETECT_MSG(pc) = 1;
   9851         }
   9852     }
   9853     return SOC_E_NONE;
   9854 }
   9855 
   9856 /*
   9857  * Function:
   9858  *    phy_84741_link_get
   9859  * Purpose:
   9860  *    Get layer2 connection status.
   9861  * Parameters:
   9862  *    unit - StrataSwitch unit #.
   9863  *    port - StrataSwitch port #. 
   9864  *      link - address of memory to store link up/down state.
   9865  * Returns:    
   9866  *    SOC_E_NONE
   9867  */
   9868 STATIC int
   9869 phy_84741_link_get(int unit, soc_port_t port, int *link)
   9870 {
   9871     uint16      pma_mii_stat, pcs_mii_stat, link_stat;
   9872     phy_ctrl_t *pc;
   9873     phy_ctrl_t  *int_pc;
   9874     int cur_speed = 0;
   9875     int an = 0,an_done = 0;
   9876     uint16 speed_val; 
   9877     int rv;
   9878 
   9879     if (link == NULL) {
   9880         return SOC_E_NONE;
   9881     }
   9882 
   9883     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   9884         *link = FALSE;
   9885         return SOC_E_NONE;
   9886     }
   9887 
   9888     pc = EXT_PHY_SW_STATE(unit, port);
   9889     int_pc = INT_PHY_SW_STATE(unit, port);
   9890 
   9891     if (!REVERSE_MODE(pc)) {
   9892         if (PCS_REPEATER(pc)) {
   9893             rv = PHY_LINK_GET(int_pc->pd, unit, port, link);
   9894             return rv;
   9895         }
   9896     }
   9897     if (FCMAP_PASSTHROUGH(pc)) {
   9898         rv = PHY_LINK_GET(int_pc->pd, unit, port, link);
   9899         return rv;
   9900     }
   9901 
   9902     phy_84741_an_get(unit,port,&an,&an_done);
   9903 
   9904     /* only supports 40G. PHY PCS is not used. Check PMD link only  */
   9905     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   9906         int serdes_link = TRUE; 
   9907 
   9908         if (REVERSE_MODE(pc)) {
   9909             SOC_IF_ERROR_RETURN
   9910                 (PHY84740_XFI(unit,pc));
   9911         }
   9912 
   9913         SOC_IF_ERROR_RETURN
   9914             (READ_PHY84740_PMA_PMD_STATr(unit, pc, &pma_mii_stat));
   9915         *link = pma_mii_stat == 0xffff ? FALSE :
   9916                 ((pma_mii_stat & MII_STAT_LA) ? TRUE : FALSE);
   9917         
   9918         if (REVERSE_MODE(pc)) {
   9919             SOC_IF_ERROR_RETURN
   9920                 (PHY84740_MMF(unit,pc));
   9921         }
   9922 
   9923         if (!REVERSE_MODE(pc)) {
   9924             if ((NULL != int_pc) && an) {
   9925                 rv = PHY_LINK_GET(int_pc->pd, unit, port, &serdes_link);
   9926             }
   9927         } 
   9928 
   9929         if (MOD_AUTO_DETECT(pc)) {
   9930             _phy84741_mod_auto_detect_update(unit, port);
   9931         }
   9932 
   9933         *link = (*link) && serdes_link;
   9934         return SOC_E_NONE;
   9935     } 
   9936 
   9937     /* return link false if in the middle of autoneg */
   9938     if (an == TRUE && an_done == FALSE) {
   9939         *link = FALSE;
   9940         return SOC_E_NONE;
   9941     }
   9942 
   9943     /* AN only supports 1G */
   9944     if (!an) {
   9945         SOC_IF_ERROR_RETURN
   9946             (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_PMAD_CTRL2_REG, 
   9947                                           &speed_val));
   9948         if ((speed_val & PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK) !=
   9949                                        PHY84740_PMAD_CTRL2r_PMA_TYPE_1G_KX) {
   9950             cur_speed = 10000;
   9951         }
   9952     } else {
   9953         cur_speed = 1000;
   9954     }
   9955 
   9956     if (REVERSE_MODE(pc)) {
   9957         SOC_IF_ERROR_RETURN
   9958             (PHY84740_XFI(unit,pc));
   9959     }
   9960 
   9961     if (cur_speed == 10000) { /* check all 3 device's link status if 10G */
   9962 
   9963         /* MMF Link status */
   9964         /* Read Status 2 register to get rid of Local faults */
   9965         SOC_IF_ERROR_RETURN
   9966             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_STAT2_REG,
   9967                                           &pma_mii_stat));
   9968         SOC_IF_ERROR_RETURN
   9969             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_STAT2_REG,
   9970                                           &pma_mii_stat));
   9971         /* Receive Link status */
   9972         SOC_IF_ERROR_RETURN
   9973             (READ_PHY84740_PCS_STATr(unit, pc, &pcs_mii_stat));
   9974 
   9975         SOC_IF_ERROR_RETURN
   9976             (READ_PHY84740_PMA_PMD_STATr(unit, pc, &pma_mii_stat));
   9977 
   9978         /* MMF link status */
   9979         link_stat = pma_mii_stat & pcs_mii_stat;
   9980         *link = link_stat == 0xffff ? FALSE :
   9981                 ((link_stat & MII_STAT_LA) ? TRUE : FALSE);
   9982     } else {
   9983         SOC_IF_ERROR_RETURN
   9984             (READ_PHY84740_MMF_AN_REG(unit, pc, 0xffe1,
   9985                                      &link_stat));
   9986         *link = link_stat == 0xffff ? FALSE :
   9987                 ((link_stat & MII_STAT_LA) ? TRUE : FALSE);
   9988     } 
   9989 
   9990     if (REVERSE_MODE(pc)) {
   9991         SOC_IF_ERROR_RETURN
   9992             (PHY84740_MMF(unit,pc));
   9993     }
   9994 
   9995     if (MOD_AUTO_DETECT(pc)) {
   9996         _phy84741_mod_auto_detect_update(unit, port);
   9997     }
   9998     LOG_VERBOSE(BSL_LS_SOC_PHY,
   9999                 (BSL_META_U(unit,
  10000                             "phy_84741_link_get: u=%d port%d: link:%s\n"),
  10001                  unit, port, *link ? "Up": "Down"));
  10002 
  10003     return SOC_E_NONE;
  10004 }
  10005 
  10006 /*
  10007  * Function:
  10008  *    phy_84741_enable_set
  10009  * Purpose:
  10010  *    Enable/Disable phy 
  10011  * Parameters:
  10012  *    unit - StrataSwitch unit #.
  10013  *    port - StrataSwitch port #. 
  10014  *      enable - on/off state to set
  10015  * Returns:    
  10016  *    SOC_E_NONE
  10017  */
  10018 
  10019 STATIC int
  10020 phy_84741_enable_set(int unit, soc_port_t port, int enable)
  10021 {
  10022     uint16      data;       /* Holder for new value to write to PHY reg */
  10023     uint16      mask;       /* Holder for bit mask to update in PHY reg */
  10024     int ix;
  10025     uint16 tx_ctrl;
  10026     phy_ctrl_t *pc;
  10027 
  10028     pc = EXT_PHY_SW_STATE(unit, port);
  10029 
  10030     if (enable) {
  10031         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
  10032     } else {
  10033         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
  10034     }
  10035 
  10036     if (REVERSE_MODE(pc)) {
  10037         SOC_IF_ERROR_RETURN
  10038             (PHY84740_XFI(unit,pc));
  10039     }
  10040 
  10041     if (SINGLE_LPMODE(pc) && !(PHY84740_SINGLE_PORT_MODE(pc))) {
  10042         /* Use 1.cd16 to disable tx */
  10043         data = enable ? 0 : (1 << 3);
  10044         mask = 1 << 3;
  10045         SOC_IF_ERROR_RETURN
  10046             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_GENSIG_8071_REGISTER,
  10047                                              data, mask));
  10048     } else {
  10049         /* TX transmitter enable/disable. BCST register in single-port mode */
  10050         data = enable ? 0 : (1 << 0);
  10051         mask = 1 << 0; /* Global PMD transmit disable */
  10052         SOC_IF_ERROR_RETURN
  10053             (MODIFY_PHY84740_PMA_PMD_TX_DISABLEr(unit, pc, data, mask));
  10054     }
  10055 
  10056     if (REVERSE_MODE(pc)) {
  10057         SOC_IF_ERROR_RETURN
  10058             (PHY84740_MMF(unit,pc));
  10059     }
  10060 
  10061     for (ix = 0; ix < NUM_LANES; ix++) {
  10062         if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10063             SOC_IF_ERROR_RETURN
  10064                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10065                             PHY84740_PMAD_AER_ADDR_REG, ix));
  10066         }
  10067 
  10068         /* TxOn control */
  10069         SOC_IF_ERROR_RETURN
  10070             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  10071                              PHY84740_PMAD_OPTICAL_CFG_REG, 
  10072                              enable? 0: (1 << 12), 
  10073                              (1 << 12)));
  10074         if (enable) {
  10075             SOC_IF_ERROR_RETURN
  10076                 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  10077                              PHY84740_PMAD_OPTICAL_CFG_REG,&data));
  10078 
  10079             /* c8e4[4] indicates the TX active state, 0 means TX active, 1 means inactive. 
  10080              * This state = TxOnOff pin XOR c800[7] when c8e4[12]=0. 
  10081              * The default value of c800[7] is 1.
  10082              * If user straps the TxOnOff to 0,
  10083              * then the Tx won't be enabled until this function is called.
  10084              * Toggle 0xc800[7] to enable the Tx when c8e4[4]=1.
  10085              */
  10086             SOC_IF_ERROR_RETURN
  10087                 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  10088                          PHY84740_PMAD_OPTICAL_SIG_LVL_REG, &tx_ctrl));
  10089             tx_ctrl &= (1 << 7);
  10090             if (data & (1 << 4)) {
  10091                 SOC_IF_ERROR_RETURN
  10092                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  10093                          PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
  10094                          tx_ctrl? 0:(1 << 7),
  10095                          (1 << 7)));
  10096             }
  10097         } 
  10098         /* power on/off the lane */
  10099         SOC_IF_ERROR_RETURN
  10100             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  10101                              PHY84740_PMAD_OPTICAL_CFG_REG, 
  10102                              enable? 0: (1 << 4), 
  10103                              (1 << 4)));
  10104         if (!PHY84740_SINGLE_PORT_MODE(pc)) {
  10105             break;
  10106         }
  10107     }
  10108     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10109         /* point back to lane0 */
  10110         SOC_IF_ERROR_RETURN
  10111             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  10112     }
  10113     return (SOC_E_NONE);
  10114 }
  10115 
  10116 /*
  10117  * Function:
  10118  *    phy_84741_lb_set
  10119  * Purpose:
  10120  *    Put 84740 in PHY PMA/PMD loopback
  10121  * Parameters:
  10122  *    unit - StrataSwitch unit #.
  10123  *    port - StrataSwitch port #. 
  10124  *      enable - binary value for on/off (1/0)
  10125  * Returns:    
  10126  *    SOC_E_NONE
  10127  */
  10128 
  10129 STATIC int phy_84741_lb_set(int unit, soc_port_t port, int enable)
  10130 {
  10131     phy_ctrl_t *pc; 
  10132     uint16     tmp;
  10133     uint16     lane;
  10134     uint16     data16 = 0, mask16 = 0;
  10135     int intf_tx;
  10136     int intf_rx;
  10137 
  10138     pc = EXT_PHY_SW_STATE(unit, port);
  10139 
  10140     intf_tx = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ?
  10141         PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
  10142 
  10143     intf_rx = ( intf_tx ==  PHY_DIAG_INTF_LINE ) ?
  10144         PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
  10145 
  10146     /* TX Enable(Disable) Squelch(FORCE) when we  Enable(Disable) loopback */
  10147     SOC_IF_ERROR_RETURN
  10148         (_phy_84741_squelch_enable(unit, port,
  10149         intf_tx, enable ? TRUE : FALSE,  enable ? TRUE : FALSE ));
  10150 
  10151     /* RX Disable(Enable) Squelch when we  Enable(Disable) loopback */
  10152     SOC_IF_ERROR_RETURN
  10153         (_phy_84741_squelch_enable(unit, port,
  10154         intf_rx, enable ? FALSE : TRUE, /* force = */ FALSE));
  10155 
  10156     tmp = enable ? PHY84740_MII_CTRL_PMA_LOOPBACK : 0;
  10157 
  10158     if (REVERSE_MODE(pc)) {
  10159         SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
  10160     }
  10161 
  10162     SOC_IF_ERROR_RETURN
  10163         (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc,
  10164                                        tmp, PHY84740_MII_CTRL_PMA_LOOPBACK));
  10165 
  10166     if (PCS_REPEATER(pc)) {
  10167         if ((PHY84740_SINGLE_PORT_MODE(pc))) {
  10168             for (lane = 0; lane < NUM_LANES; lane++) { 
  10169                 data16 = 0;
  10170 
  10171                 /* point to the each lane starting at lane0 */
  10172                 SOC_IF_ERROR_RETURN
  10173                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10174                                 PHY84740_PMAD_AER_ADDR_REG, lane));
  10175 
  10176                 SOC_IF_ERROR_RETURN
  10177                        (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xcd0a,
  10178                        enable? 1:0, 1));
  10179 
  10180                 SOC_IF_ERROR_RETURN(
  10181                     READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 
  10182                                          PHY84740_DIG_CTRL_REG,
  10183                                          &data16));
  10184 
  10185                 /* 1.cd08.10 = 1.cd08.10  XOR 1.cd08.9 */
  10186                 tmp    = (data16 & PHY84740_RX_POLARITY_FLIP_MASK) << 1;
  10187                 data16 = (data16 & PHY84740_TX_POLARITY_FLIP_MASK) ^ tmp;
  10188                 mask16 = PHY84740_TX_POLARITY_FLIP_MASK;
  10189 
  10190 
  10191                 SOC_IF_ERROR_RETURN(
  10192                     MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 
  10193                                          PHY84740_DIG_CTRL_REG,
  10194                                          data16,mask16));
  10195             }
  10196             /* point back to lane0 */
  10197             SOC_IF_ERROR_RETURN
  10198                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  10199         } else {  /* quad-port mode */
  10200             data16 = 0;
  10201 
  10202             SOC_IF_ERROR_RETURN
  10203                    (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xcd0a,
  10204                    enable? 1:0, 1));
  10205 
  10206             SOC_IF_ERROR_RETURN(
  10207                 READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 
  10208                                      PHY84740_DIG_CTRL_REG,
  10209                                      &data16));
  10210 
  10211             /* 1.cd08.10 = 1.cd08.10  XOR 1.cd08.9 */
  10212             tmp    = (data16 & PHY84740_RX_POLARITY_FLIP_MASK) << 1;
  10213             data16 = (data16 & PHY84740_TX_POLARITY_FLIP_MASK) ^ tmp;
  10214             mask16 = PHY84740_TX_POLARITY_FLIP_MASK;
  10215 
  10216             SOC_IF_ERROR_RETURN(
  10217                 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_DIG_CTRL_REG,
  10218                                      data16,mask16));
  10219         }
  10220     }
  10221 
  10222     if (REVERSE_MODE(pc)) {
  10223         SOC_IF_ERROR_RETURN
  10224             (PHY84740_MMF(unit,pc));
  10225     }
  10226 
  10227     return SOC_E_NONE;
  10228 }
  10229 
  10230 /*
  10231  * Function:
  10232  *    phy_84741_lb_get
  10233  * Purpose:
  10234  *    Get 84740 PHY loopback state
  10235  * Parameters:
  10236  *    unit - StrataSwitch unit #.
  10237  *    port - StrataSwitch port #. 
  10238  *      enable - address of location to store binary value for on/off (1/0)
  10239  * Returns:    
  10240  *    SOC_E_NONE
  10241  */
  10242 
  10243 STATIC int
  10244 phy_84741_lb_get(int unit, soc_port_t port, int *enable)
  10245 {
  10246     uint16      tmp;
  10247     phy_ctrl_t *pc;
  10248 
  10249     pc = EXT_PHY_SW_STATE(unit, port);
  10250 
  10251     if (REVERSE_MODE(pc)) {
  10252         SOC_IF_ERROR_RETURN
  10253             (PHY84740_XFI(unit,pc));
  10254     }
  10255 
  10256     SOC_IF_ERROR_RETURN
  10257         (READ_PHY84740_PMA_PMD_CTRLr(unit, pc, &tmp));
  10258     /* ctrl != 0xffff check is to handle removable PHY daughter cards */
  10259     *enable = ((tmp != 0xffff) && 
  10260                (tmp & PHY84740_MII_CTRL_PMA_LOOPBACK)) ? TRUE : FALSE;
  10261 
  10262     if (REVERSE_MODE(pc)) {
  10263         SOC_IF_ERROR_RETURN
  10264             (PHY84740_MMF(unit,pc));
  10265     }
  10266 
  10267     LOG_INFO(BSL_LS_SOC_PHY,
  10268              (BSL_META_U(unit,
  10269                          "phy_84741_lb_get: u=%d port%d: loopback:%s\n"),
  10270               unit, port, *enable ? "Enabled": "Disabled"));
  10271     
  10272     return SOC_E_NONE;
  10273 }
  10274 
  10275 STATIC int
  10276 _phy_84741_control_tx_driver_set(int unit, soc_port_t port, int interface,
  10277                                 soc_phy_control_t type, uint32 value)
  10278 {
  10279     uint16       data;  /* Temporary holder of reg value to be written */
  10280     uint16       mask;  /* Bit mask of reg value to be updated */
  10281     int ix;
  10282     int lane;
  10283     int start;
  10284     int end;
  10285     uint16 post_pre_tap = 0, force_preemph = 0;
  10286     uint16 main_tap = 0;
  10287     phy_ctrl_t  *pc;    /* PHY software state */
  10288     int reg;
  10289       
  10290     pc = EXT_PHY_SW_STATE(unit, port);
  10291     
  10292     
  10293     switch(type) {
  10294         case SOC_PHY_CONTROL_DRIVER_CURRENT:
  10295         /* fall through */
  10296         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
  10297         /* fall through */
  10298         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
  10299         /* fall through */
  10300         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
  10301         /* fall through */
  10302         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
  10303             data = (uint16)(value & 0xf);
  10304             data = data << 12;
  10305             mask = 0xf000;
  10306             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
  10307             if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0) {
  10308                 lane = 0;
  10309             } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1) {
  10310                 lane = 1;
  10311             } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2) {
  10312                 lane = 2;
  10313             } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3) {
  10314                 lane = 3;
  10315             } else {  /* SOC_PHY_CONTROL_DRIVER_CURRENT */
  10316                 lane = 4; /* all lanes */
  10317             }
  10318             if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10319                 start = lane == 4? 0: lane;
  10320                 end   = lane == 4? 4: lane + 1;
  10321                 for (ix = start; ix < end; ix++) { 
  10322 
  10323                     PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10324 
  10325                     SOC_IF_ERROR_RETURN
  10326                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10327                                PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,ix)));
  10328                     
  10329                     PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10330 
  10331                     SOC_IF_ERROR_RETURN
  10332                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, data, mask));
  10333                 }
  10334             } else {
  10335                 SOC_IF_ERROR_RETURN
  10336                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, data, mask));
  10337             }
  10338             break;
  10339 
  10340         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
  10341         /* fall through */
  10342         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
  10343         /* fall through */
  10344         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
  10345         /* fall through */
  10346         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
  10347         /* fall through */
  10348         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
  10349             data = (uint16)(value & 0xf);
  10350             data = data << 8;
  10351             mask = 0x0f00;
  10352             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
  10353             if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0) {
  10354                 lane = 0;
  10355             } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1) {
  10356                 lane = 1;
  10357             } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2) {
  10358                 lane = 2;
  10359             } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3) {
  10360                 lane = 3;
  10361             } else {  /* SOC_PHY_CONTROL_PRE_DRIVER_CURRENT */
  10362                 lane = 4; /* all lanes */
  10363             }
  10364             if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10365                 start = lane == 4? 0: lane;
  10366                 end   = lane == 4? 4: lane + 1;
  10367                 for (ix = start; ix < end; ix++) {
  10368                 
  10369                     PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10370                     SOC_IF_ERROR_RETURN
  10371                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10372                                     PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,ix)));
  10373                 
  10374                     PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10375                     SOC_IF_ERROR_RETURN
  10376                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, data, mask));
  10377                 }
  10378             } else {
  10379                 SOC_IF_ERROR_RETURN
  10380                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, data, mask));
  10381             }
  10382             break;
  10383         case SOC_PHY_CONTROL_PREEMPHASIS:
  10384             /* fall through */
  10385         case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
  10386             /* fall through */
  10387         case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
  10388             /* fall through */
  10389         case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
  10390             /* fall through */
  10391         case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
  10392             /* The value format:
  10393              * bit 15:  1 enable forced preemphasis ctrl, 0 auto config
  10394              * bit 14:10:  post_tap value
  10395              * bit 09:04:  main tap value
  10396              * bit 03:00:  pre_tap value 
  10397              * 
  10398              * set 1.CA07[8] = 0, 1.CA02[15:11] for main_tap and 1.CA05[7:4] for post tap.
  10399              * main tap control is in the register field 0xCA02[15:11]. 
  10400              * If a wrong value is written to the same register, field 0xCA02[9:7],
  10401              *  it may DAMAGE the device. User must avoid writing to 0xCA02[9:7] 
  10402              */ 
  10403             /* Register bit8, 0 force preemphasis, 1 auto config, 1.CA07 */ 
  10404             force_preemph = PHY84740_PREEMPH_GET_FORCE(value)? 0:
  10405                        PHY84740_PREEMPH_REG_FORCE_MASK;
  10406 
  10407             /* add post tap value */
  10408             post_pre_tap = PHY84740_PREEMPH_GET_POST_TAP(value) << 
  10409                         PHY84740_PREEMPH_REG_POST_TAP_SHFT;
  10410 
  10411             /* add pre tap value */
  10412             post_pre_tap |=  PHY84740_PREEMPH_GET_PRE_TAP(value) << 
  10413                         PHY84740_PREEMPH_REG_PRE_TAP_SHFT;
  10414 
  10415             /* main tap in 1.CA02 */
  10416             main_tap = PHY84740_PREEMPH_GET_MAIN_TAP(value) <<
  10417                        PHY84740_PREEMPH_REG_MAIN_TAP_SHFT;
  10418                 
  10419             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca06;
  10420 
  10421             if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) {
  10422                 lane = 0;
  10423             } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) {
  10424                 lane = 1;
  10425             } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) {
  10426                 lane = 2;
  10427             } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) {
  10428                 lane = 3;
  10429             } else {  /* SOC_PHY_CONTROL_PREEMPHASIS_LANE */
  10430                 lane = 4; /* all lanes */
  10431             }
  10432             if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10433                 start = lane == 4? 0: lane;
  10434                 end   = lane == 4? 4: lane + 1;
  10435             } else {
  10436                 /* just make sure execute once */
  10437                 start = 0;
  10438                 end   = 1;
  10439             }
  10440             for (ix = start; ix < end; ix++) {
  10441                 if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10442                     
  10443                     PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10444                     SOC_IF_ERROR_RETURN
  10445                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10446                                     PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,ix)));
  10447                     PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10448                 }
  10449                 SOC_IF_ERROR_RETURN
  10450                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, 
  10451                             post_pre_tap, PHY84740_PREEMPH_REG_POST_TAP_MASK |
  10452                                         PHY84740_PREEMPH_REG_PRE_TAP_MASK));
  10453 
  10454                 /* N/A on system side */
  10455                 if( interface != PHY_DIAG_INTF_SYS) {
  10456                     SOC_IF_ERROR_RETURN
  10457                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca07, 
  10458                                force_preemph, PHY84740_PREEMPH_REG_FORCE_MASK));
  10459                 }
  10460 
  10461                 /* always clear tx_pwrdn bit. The read/modify/write may accidently
  10462                  * set the bit 0xCA02[10]. Because the CA02[10] read value is: 
  10463                  * CA02[10]_read_value = CA02[10] OR Digital_State_Machine 
  10464                  * The problem will occur when the Digital_State_Machine output is 1
  10465                  * at the time of reading this register.
  10466                  */ 
  10467                 SOC_IF_ERROR_RETURN
  10468                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  10469                             (interface == PHY_DIAG_INTF_SYS) ? 0xc90b : 0xca02, 
  10470                             main_tap, 
  10471                             PHY84740_PREEMPH_REG_MAIN_TAP_MASK |
  10472                             PHY84740_PREEMPH_REG_TX_PWRDN_MASK));
  10473             }   
  10474             break;
  10475         
  10476         default:
  10477             /* should never get here */
  10478             return SOC_E_PARAM;
  10479     }
  10480    
  10481 #ifdef PHY84740_FCS_ERROR_WAR   
  10482      /* Toggle Transmit lane output so that the link partner
  10483        resets itself to a good signal. Othwerise, it could 
  10484        sync to a sub optimal signal and can see FCS errors. 
  10485      */ 
  10486      if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10487          start = lane == 4? 0: lane;
  10488          end   = lane == 4? 4: lane + 1;
  10489      } else {
  10490      /* just make sure execute once */
  10491          start = 0;
  10492          end   = 1;
  10493     }
  10494     for (ix = start; ix < end; ix++) {
  10495         if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10496             
  10497             PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10498             SOC_IF_ERROR_RETURN
  10499                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10500                              PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,ix)));
  10501             PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10502             
  10503             data = mask = 0x1 << (12+ P2L_MAP(pc,ix)); /* per lane */
  10504             SOC_IF_ERROR_RETURN
  10505                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask));
  10506 
  10507             data = 0;
  10508             SOC_IF_ERROR_RETURN
  10509                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask));
  10510         } else {
  10511             data = mask = (lane == 4)? 
  10512                               0x1 << 11 : /* Global */ 
  10513                               0x1 << (12 + P2L_MAP(pc,lane)); /* per lane */
  10514             SOC_IF_ERROR_RETURN
  10515                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask));
  10516             data = 0;
  10517             SOC_IF_ERROR_RETURN
  10518                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask));
  10519         }
  10520     }
  10521 #endif /* PHY84740_FCS_ERROR_WAR */
  10522 
  10523     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10524         PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10525         /* point back to lane0 */
  10526         SOC_IF_ERROR_RETURN
  10527             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  10528                                             PHY84740_PMAD_AER_ADDR_REG, 0));
  10529         PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
  10530     }
  10531     return SOC_E_NONE;
  10532 }
  10533 
  10534 STATIC int
  10535 _phy_84741_control_tx_driver_get(int unit, soc_port_t port,
  10536                                 soc_phy_control_t type, uint32 *value)
  10537 {
  10538     uint16         data16;   /* Temporary holder of a reg value */
  10539     uint16         main_tap;
  10540     uint16         post_tap;
  10541     int lane;
  10542     phy_ctrl_t    *pc;       /* PHY software state */
  10543 
  10544     pc = EXT_PHY_SW_STATE(unit, port);
  10545 
  10546     data16 = 0;
  10547     switch(type) {
  10548         case SOC_PHY_CONTROL_PREEMPHASIS:
  10549         /* fall through */
  10550         case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
  10551         /* fall through */
  10552         case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
  10553         /* fall through */
  10554         case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
  10555         /* fall through */
  10556         case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
  10557             if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) {
  10558                 lane = 0;
  10559             } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) {
  10560                 lane = 1;
  10561             } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) {
  10562                 lane = 2;
  10563             } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) {
  10564                 lane = 3;
  10565             } else {
  10566                 lane = 0;
  10567             } 
  10568             /* 1.CA05[15] = 0, set 1.CA02[15:11] for main_tap and 
  10569              * 1.CA05[7:4] for postcursor 
  10570              */
  10571             if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10572                 SOC_IF_ERROR_RETURN
  10573                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10574                                   PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane)));
  10575             }
  10576             SOC_IF_ERROR_RETURN
  10577                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca02, &main_tap));
  10578             SOC_IF_ERROR_RETURN
  10579                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca05, &post_tap));
  10580 
  10581             /* bit15 force flag, 14:10 post_tap, 09:04 main tap */
  10582             *value = (post_tap & PHY84740_PREEMPH_REG_FORCE_MASK)? 0:
  10583                      (1 << PHY84740_PREEMPH_CTRL_FORCE_SHFT); 
  10584             *value |= ((post_tap & PHY84740_PREEMPH_REG_POST_TAP_MASK) >>
  10585                       PHY84740_PREEMPH_REG_POST_TAP_SHFT) << 
  10586                       PHY84740_PREEMPH_CTRL_POST_TAP_SHFT; 
  10587             *value |= ((main_tap & PHY84740_PREEMPH_REG_MAIN_TAP_MASK) >>
  10588                       PHY84740_PREEMPH_REG_MAIN_TAP_SHFT) <<
  10589                       PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT; 
  10590 
  10591         break;
  10592 
  10593         case SOC_PHY_CONTROL_DRIVER_CURRENT:
  10594             /* fall through */
  10595         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
  10596             /* fall through */
  10597         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
  10598             /* fall through */
  10599         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
  10600             /* fall through */
  10601         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
  10602             if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0) {
  10603                 lane = 0;
  10604             } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1) {
  10605                 lane = 1;
  10606             } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2) {
  10607                 lane = 2;
  10608             } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3) {
  10609                 lane = 3;
  10610             } else {
  10611                 lane = 0;
  10612             }
  10613             if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10614                 SOC_IF_ERROR_RETURN
  10615                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10616                                   PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane)));
  10617             }
  10618             SOC_IF_ERROR_RETURN
  10619                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca01, &data16));
  10620             *value = (data16 & 0xf000) >> 12;
  10621         break;
  10622 
  10623         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
  10624             /* fall through */
  10625         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
  10626             /* fall through */
  10627         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
  10628             /* fall through */
  10629         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
  10630             /* fall through */
  10631         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
  10632             if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0) {
  10633                 lane = 0;
  10634             } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1) {
  10635                 lane = 1;
  10636             } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2) {
  10637                 lane = 2;
  10638             } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3) {
  10639                 lane = 3;
  10640             } else {
  10641                 lane = 0;
  10642             }
  10643             if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10644                 SOC_IF_ERROR_RETURN
  10645                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10646                                   PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane)));
  10647             }
  10648             SOC_IF_ERROR_RETURN
  10649                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca01, &data16));
  10650             *value = (data16 & 0x0f00) >> 8;
  10651             break;
  10652 
  10653        default:
  10654          /* should never get here */
  10655          return SOC_E_PARAM;
  10656     }
  10657 
  10658     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10659         /* point back to lane0 */
  10660         SOC_IF_ERROR_RETURN
  10661             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  10662     }
  10663     return SOC_E_NONE;
  10664 }
  10665 
  10666 STATIC int
  10667 _phy_84741_control_edc_mode_set(int unit, soc_port_t port, uint32 value)
  10668 {
  10669     uint16         data16;
  10670     uint16         mask16;
  10671     phy_ctrl_t    *pc;       /* PHY software state */
  10672     int ix;
  10673 
  10674      pc = EXT_PHY_SW_STATE(unit, port);
  10675 
  10676     /* clear software overrides */
  10677     mask16 = 0;
  10678     if (!RX_LOS(pc)) {
  10679         mask16 |= PHY84740_RXLOS_OVERRIDE_MASK;
  10680     }
  10681     /* default: override MOD_ABS signalling */
  10682     if (!MOD_ABS(pc)) {
  10683         mask16 |= PHY84740_MOD_ABS_OVERRIDE_MASK;
  10684     }
  10685 
  10686     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10687         for (ix = 0; ix < NUM_LANES; ix++) {
  10688             SOC_IF_ERROR_RETURN
  10689                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10690                                 PHY84740_PMAD_AER_ADDR_REG, ix));
  10691             SOC_IF_ERROR_RETURN
  10692                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  10693                          PHY84740_PMAD_OPTICAL_CFG_REG, 0,
  10694                          mask16));
  10695         }
  10696     } else {
  10697         SOC_IF_ERROR_RETURN
  10698            (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  10699                          PHY84740_PMAD_OPTICAL_CFG_REG, 0,
  10700                          mask16));
  10701     }
  10702 
  10703     for (ix = 0; ix < NUM_LANES; ix++) {
  10704         if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10705             SOC_IF_ERROR_RETURN
  10706                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10707                             PHY84740_PMAD_AER_ADDR_REG, ix));
  10708         }
  10709 
  10710         /* EDC mode programming sequence*/     
  10711         mask16 = 1 << 9;
  10712 
  10713         /* induce LOS condition: toggle register bit 0xc800.9 */
  10714         SOC_IF_ERROR_RETURN         
  10715             (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 
  10716                  PHY84740_PMAD_OPTICAL_SIG_LVL_REG,&data16));
  10717 
  10718         /* only change toggled bit 9 */
  10719         SOC_IF_ERROR_RETURN
  10720             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 
  10721                  PHY84740_PMAD_OPTICAL_SIG_LVL_REG,~data16,mask16));
  10722 
  10723         /* program EDC mode */
  10724         SOC_IF_ERROR_RETURN
  10725           (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xCA1A,(uint16)value,
  10726                                   PHY84740_EDC_MODE_MASK));
  10727 
  10728         /* remove LOS condition: restore back original value of bit 0xc800.9 */
  10729         SOC_IF_ERROR_RETURN
  10730             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 
  10731                    PHY84740_PMAD_OPTICAL_SIG_LVL_REG,data16,mask16));
  10732 
  10733         if (!PHY84740_SINGLE_PORT_MODE(pc)) {
  10734             break;
  10735         }
  10736     }
  10737 
  10738     /* restore software override */
  10739     data16 = 0;
  10740     mask16 = PHY84740_RXLOS_OVERRIDE_MASK | PHY84740_MOD_ABS_OVERRIDE_MASK;
  10741     if (!RX_LOS(pc)) {
  10742         data16 |= PHY84740_RXLOS_OVERRIDE_MASK;
  10743     }
  10744     /* default: override MOD_ABS signalling */
  10745     if (!MOD_ABS(pc)) {
  10746         data16 |= PHY84740_MOD_ABS_OVERRIDE_MASK;
  10747     }
  10748 
  10749     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10750         for (ix = 0; ix < NUM_LANES; ix++) {
  10751             SOC_IF_ERROR_RETURN
  10752                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10753                                 PHY84740_PMAD_AER_ADDR_REG, ix));
  10754             SOC_IF_ERROR_RETURN
  10755                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  10756                           PHY84740_PMAD_OPTICAL_CFG_REG, 
  10757                           data16,
  10758                           mask16));
  10759         }
  10760 
  10761         /* point back to lane0 */
  10762         SOC_IF_ERROR_RETURN
  10763             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  10764     } else {
  10765         /* XXX temp 0xc0c0: RXLOS override: 0x0808 MOD_ABS override */
  10766         SOC_IF_ERROR_RETURN
  10767            (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  10768                          PHY84740_PMAD_OPTICAL_CFG_REG, 
  10769                          data16,
  10770                          mask16));
  10771     }
  10772 
  10773     return SOC_E_NONE;
  10774 }
  10775 
  10776 /*
  10777  * enable/disable syncE recoverd clock for 10G/40G modes.
  10778  */
  10779 STATIC int
  10780 _phy_84741_control_recovery_clock_set(int unit, soc_port_t port, int enable)
  10781 {
  10782     uint16 data16;
  10783     uint16 mask16;
  10784     int lane;
  10785     phy_ctrl_t    *pc;       /* PHY software state */
  10786 
  10787     pc = EXT_PHY_SW_STATE(unit, port);
  10788 
  10789    /* 
  10790     *  1.CB27[3]    = 0   to disable FC recovered clock to appear at TESTP/N.
  10791     *  1.CA1D[11]   = 0   to disable PLL clock to appear at TESTP/N.
  10792     *  1.CA1D[1:0]      = 00  to disable bandgap voltage and vco_control voltage appear at TESTP/N.
  10793     *  1.CB27[0]    = 1   enables rx recovered clock to come out of TESTP/N pads.
  10794     *  1.CB26[14:13]    = 11  for 156.25Mhz syncE divider select
  10795     *  1.CB26[12]   = 1   for syncE clock out.
  10796     */    
  10797   
  10798     for (lane = 0; lane < NUM_LANES; lane++) {
  10799         if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10800             SOC_IF_ERROR_RETURN
  10801                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10802                                             PHY84740_PMAD_AER_ADDR_REG, lane));
  10803         }
  10804         /* set to 0 in both enable/disable cases */
  10805 
  10806         /* disable FC recovered clock to appear at TESTP/N. */
  10807         SOC_IF_ERROR_RETURN
  10808            (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_REG, 
  10809                                             0,(1 << 3)));
  10810         /* disable PLL clock to appear at TESTP/N
  10811          * disable bandgap voltage and vco_control voltage appear at TESTP/N
  10812          */
  10813         mask16 = (1 << 11) | 0x3;
  10814         SOC_IF_ERROR_RETURN
  10815            (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,0xCA1D, 0,mask16));
  10816 
  10817         /* enables rx recovered clock to come out of TESTP/N pads*/
  10818         mask16 = PHY84740_RECOVERY_CLK_ENABLE_MASK;
  10819         data16 = enable? mask16: 0;
  10820         SOC_IF_ERROR_RETURN
  10821            (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_REG, 
  10822                                         data16,mask16));
  10823 
  10824         /* always use bits 14:13 to select the sync clock frequency */
  10825         mask16 = (0x1 << 12);
  10826         data16 = mask16;
  10827         SOC_IF_ERROR_RETURN
  10828            (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, 
  10829                                             data16,mask16));
  10830        if (!PHY84740_SINGLE_PORT_MODE(pc)) {
  10831            break;
  10832        }
  10833     }
  10834     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10835         /* point back to lane0 */
  10836         SOC_IF_ERROR_RETURN
  10837             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  10838     }
  10839     return SOC_E_NONE;
  10840 }
  10841 
  10842 /*
  10843  * set the frequency of the syncE recoverd clock.
  10844  */
  10845 STATIC int
  10846 _phy_84741_control_recovery_clock_freq_set(int unit, soc_port_t port, int freq)
  10847 {
  10848     phy_ctrl_t    *pc;       /* PHY software state */
  10849     int lane;
  10850     uint16 freq_ctrl;
  10851 
  10852     pc = EXT_PHY_SW_STATE(unit, port);
  10853     
  10854     /*  
  10855      * 1.CB26[14:13]
  10856      * Select the frequency of SyncE clock to be sent to the test port: 
  10857      * 00 :  Power down syncE clock dividers
  10858      * 01 :  125 MHz        (divide by 82.5) 
  10859      * 10 :  195.3125 MHz   (divide by 52.8)
  10860      * 11 :  156.25 MHz     (divide by 66)
  10861      */
  10862 
  10863     switch (freq) {
  10864         case 125000:
  10865             freq_ctrl = 0x1;
  10866             break;
  10867         case 195312:
  10868             freq_ctrl = 0x2;
  10869             break;
  10870         case 156250:
  10871             freq_ctrl = 0x3;
  10872             break;
  10873         default:
  10874             freq_ctrl = 0x0;
  10875             break;
  10876     }
  10877 
  10878     for (lane = 0; lane < NUM_LANES; lane++) {
  10879         if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10880             SOC_IF_ERROR_RETURN
  10881                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10882                                             PHY84740_PMAD_AER_ADDR_REG, lane));
  10883         }
  10884 
  10885         SOC_IF_ERROR_RETURN
  10886             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, 
  10887                       PHY84740_RECOVERY_CLK_FREQf(freq_ctrl),
  10888                       PHY84740_RECOVERY_CLK_FREQ_MASK));
  10889 
  10890         if (!PHY84740_SINGLE_PORT_MODE(pc)) {
  10891            break;
  10892         }
  10893     }
  10894     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10895         /* point back to lane0 */
  10896         SOC_IF_ERROR_RETURN
  10897             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  10898     }
  10899     return SOC_E_NONE;
  10900 }
  10901 
  10902 STATIC int
  10903 _phy_84741_control_prbs_tx_invert_data_set(int unit, soc_port_t port, int invert)
  10904 {
  10905     phy_ctrl_t    *pc;       /* PHY software state */
  10906     uint16 data16;
  10907 
  10908     pc = EXT_PHY_SW_STATE(unit, port);
  10909 
  10910     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10911         return SOC_E_UNAVAIL;
  10912     } else {  /* quad-port mode */
  10913         /* tx inversion */
  10914         data16 = invert? PHY84740_USER_PRBS_TX_INVERT: 0;
  10915         
  10916         SOC_IF_ERROR_RETURN
  10917             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  10918                   PHY84740_USER_PRBS_CONTROL_0_REGISTER, data16,
  10919                            PHY84740_USER_PRBS_TX_INVERT));
  10920     }
  10921     return SOC_E_NONE;
  10922 }
  10923 
  10924 STATIC int
  10925 _phy_84741_control_prbs_rx_invert_data_set(int unit, soc_port_t port, int invert)
  10926 {
  10927     phy_ctrl_t    *pc;       /* PHY software state */
  10928     uint16 data16;
  10929     uint16 mask16;
  10930 
  10931     pc = EXT_PHY_SW_STATE(unit, port);
  10932 
  10933     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10934         return SOC_E_UNAVAIL;
  10935     } else {  /* quad-port mode */
  10936         /* rx inversion */
  10937         data16 = invert? PHY84740_USER_PRBS_RX_INVERT: 0;
  10938         mask16 = PHY84740_USER_PRBS_RX_INVERT;
  10939         SOC_IF_ERROR_RETURN
  10940             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  10941                   PHY84740_USER_PRBS_CONTROL_0_REGISTER, data16,
  10942                            mask16));
  10943     }
  10944     return SOC_E_NONE;
  10945 }
  10946 
  10947 STATIC int
  10948 _phy_84741_control_prbs_polynomial_set(int unit, soc_port_t port,int poly_ctrl,
  10949          int tx)   /* tx or rx */
  10950 {
  10951     phy_ctrl_t    *pc;       /* PHY software state */
  10952     uint16 data16;
  10953     uint16 mask16;
  10954 
  10955         /*
  10956          * poly_ctrl:
  10957          *  0x0 = prbs7
  10958          *  0x1 = prbs15
  10959          *  0x2 = prbs23
  10960          *  0x3 = prbs31
  10961          */
  10962     pc = EXT_PHY_SW_STATE(unit, port);
  10963 
  10964     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  10965         /* only two types available PRBS9 and PRBS31 */
  10966         if (poly_ctrl == 3) {
  10967             data16 = PHY84740_40G_PRBS31;
  10968         } else {
  10969             data16 = PHY84740_40G_PRBS9;
  10970         }
  10971 
  10972         SOC_IF_ERROR_RETURN
  10973             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  10974                      PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, 
  10975                           data16,
  10976                           PHY84740_40G_PRBS9 | PHY84740_40G_PRBS31));
  10977     } else {  /* quad-port mode */
  10978         /* 001 : prbs7 
  10979            010 : prbs9
  10980            011 : prbs11
  10981            100 : prbs15
  10982            101 : prbs23
  10983            110 : prbs31
  10984          */
  10985 
  10986         if (poly_ctrl == 0) {
  10987             data16 = 1;
  10988         } else if (poly_ctrl == 1) {
  10989             data16 = 4;
  10990         } else if (poly_ctrl == 2) {
  10991             data16 = 5;
  10992         } else if (poly_ctrl == 3) {
  10993             data16 = 6;
  10994         } else {
  10995             return SOC_E_PARAM;
  10996         }  
  10997         mask16 = PHY84740_USER_PRBS_TYPE_MASK;
  10998 
  10999         /* default is tx */
  11000         if (!tx) {  /* rx */
  11001             data16 = data16 << 12;
  11002             mask16 = mask16 << 12;
  11003         }
  11004             
  11005         /* both tx/rx types */  
  11006         SOC_IF_ERROR_RETURN
  11007             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11008                     PHY84740_USER_PRBS_CONTROL_0_REGISTER, 
  11009                data16, mask16));
  11010     }
  11011     return SOC_E_NONE;
  11012 }
  11013 STATIC int
  11014 _phy_84741_control_prbs_enable_set(int unit, soc_port_t port, int enable)
  11015 {
  11016     phy_ctrl_t    *pc;       /* PHY software state */
  11017     int lane;
  11018     int repeater_mode;
  11019     uint16 data16;
  11020 
  11021     pc = EXT_PHY_SW_STATE(unit, port);
  11022 
  11023     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  11024         for (lane = 0; lane < NUM_LANES; lane++) {
  11025             SOC_IF_ERROR_RETURN
  11026                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  11027                                             PHY84740_PMAD_AER_ADDR_REG, lane));
  11028 
  11029             /* GENSIG_8071_REGISTER Clocks enable */
  11030             SOC_IF_ERROR_RETURN
  11031                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11032                      PHY84740_GENSIG_8071_REGISTER, enable? 0x3:0));
  11033 
  11034             /* RESET_CONTROL_REGISTER */
  11035             SOC_IF_ERROR_RETURN
  11036                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11037                                PHY84740_RESET_CONTROL_REGISTER, 0x0));
  11038 
  11039             /* DATA_MUX_SEL_CNTRL_REGISTER */
  11040             SOC_IF_ERROR_RETURN
  11041                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd58, enable?0x2:0));
  11042 
  11043             /* 40G_PRBS_PATTERN_TESTING_CONTROL_STATUS */
  11044             SOC_IF_ERROR_RETURN
  11045                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11046                      PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, 
  11047                      enable?PHY84740_40G_PRBS_ENABLE:0,
  11048                      0xf));
  11049         }
  11050         /* point back to lane0 */
  11051         SOC_IF_ERROR_RETURN
  11052             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  11053     } else { /* quad-port mode */
  11054         SOC_IF_ERROR_RETURN
  11055             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
  11056 
  11057         repeater_mode = ((data16 & 0x6) == 0x6)? TRUE: FALSE;
  11058         if (repeater_mode) {
  11059             /* Enable retimer prbs clocks inside SFI */
  11060             SOC_IF_ERROR_RETURN
  11061                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11062                           PHY84740_GENSIG_8071_REGISTER, 
  11063                                 enable?0x3:0,0x3));
  11064 
  11065             /* Enable the retimer datapath */
  11066             SOC_IF_ERROR_RETURN
  11067                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd58, 
  11068                             enable?0x2:0,0x3));
  11069         }
  11070         /* clear PRBS control if disabled */
  11071         if (!enable) {
  11072             SOC_IF_ERROR_RETURN
  11073                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11074                            PHY84740_USER_PRBS_CONTROL_0_REGISTER, 0,
  11075                              PHY84740_USER_PRBS_TYPE_MASK |
  11076                              PHY84740_USER_PRBS_TYPE_MASK << 12)); /* rx type*/
  11077         }         
  11078 
  11079         /*  program the PRBS enable */
  11080         SOC_IF_ERROR_RETURN
  11081             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11082                      PHY84740_USER_PRBS_CONTROL_0_REGISTER, 
  11083                      enable? PHY84740_USER_PRBS_ENABLE: 0,PHY84740_USER_PRBS_ENABLE));
  11084     }
  11085     return SOC_E_NONE;
  11086 }
  11087 
  11088 STATIC int
  11089 _phy_84741_control_prbs_enable_get(int unit, soc_port_t port, uint32 *value)
  11090 {
  11091     uint16 data16;
  11092     phy_ctrl_t    *pc;       /* PHY software state */
  11093 
  11094     pc = EXT_PHY_SW_STATE(unit, port);
  11095 
  11096     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  11097         SOC_IF_ERROR_RETURN
  11098             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11099                    PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, &data16));
  11100         if ((data16 & PHY84740_40G_PRBS_ENABLE) == PHY84740_40G_PRBS_ENABLE) {
  11101             *value = TRUE;
  11102         } else {
  11103             *value = FALSE;
  11104         }
  11105     } else {  /* quad-port mode */
  11106         SOC_IF_ERROR_RETURN
  11107             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11108                    PHY84740_USER_PRBS_CONTROL_0_REGISTER, &data16));
  11109         if (data16 & PHY84740_USER_PRBS_ENABLE) {
  11110             *value = TRUE;
  11111         } else {
  11112             *value = FALSE;
  11113         }
  11114     }
  11115 
  11116     return SOC_E_NONE;
  11117 }
  11118 STATIC int
  11119 _phy_84741_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value)
  11120 {
  11121     phy_ctrl_t    *pc;       /* PHY software state */
  11122     uint16 poly_ctrl;
  11123 
  11124     pc = EXT_PHY_SW_STATE(unit, port);
  11125 
  11126     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  11127         SOC_IF_ERROR_RETURN
  11128             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11129                    PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, &poly_ctrl));
  11130         if (poly_ctrl & PHY84740_40G_PRBS31) {
  11131             *value = 3;
  11132         } else {
  11133             *value = 0;  /* 0 indicates PRBS9 */
  11134         }
  11135     } else {  /* quad-port mode */
  11136         SOC_IF_ERROR_RETURN
  11137             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11138                        PHY84740_USER_PRBS_CONTROL_0_REGISTER, &poly_ctrl));
  11139         poly_ctrl &= PHY84740_USER_PRBS_TYPE_MASK;
  11140 
  11141         if (poly_ctrl == 1) {
  11142             *value = 0;
  11143         } else if (poly_ctrl == 4) {
  11144             *value = 1;
  11145         } else if (poly_ctrl == 5) {
  11146             *value = 2;
  11147         } else if (poly_ctrl == 6) {
  11148             *value = 3;
  11149         } else {
  11150             *value = poly_ctrl;
  11151         }
  11152     }
  11153 
  11154     return SOC_E_NONE;
  11155 }
  11156 
  11157 STATIC int
  11158 _phy_84741_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value)
  11159 {
  11160     phy_ctrl_t    *pc;       /* PHY software state */
  11161     uint16 data16;
  11162 
  11163     pc = EXT_PHY_SW_STATE(unit, port);
  11164 
  11165     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  11166         return SOC_E_UNAVAIL;
  11167     } else {  /* quad-port mode */
  11168         SOC_IF_ERROR_RETURN
  11169             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11170                       PHY84740_USER_PRBS_CONTROL_0_REGISTER, &data16));
  11171         if (data16 & PHY84740_USER_PRBS_TX_INVERT) {
  11172             *value = TRUE;
  11173         } else {
  11174             *value = FALSE;
  11175         }
  11176     }
  11177     return SOC_E_NONE;
  11178 }
  11179 
  11180 STATIC int
  11181 _phy_84741_control_prbs_rx_status_get(int unit, soc_port_t port, uint32 *value)
  11182 {
  11183     phy_ctrl_t    *pc;       /* PHY software state */
  11184     uint16 data16;
  11185     int lane;
  11186 
  11187     pc = EXT_PHY_SW_STATE(unit, port);
  11188 
  11189     *value = 0;
  11190     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  11191         for (lane = 0; lane < 4; lane++) {
  11192             SOC_IF_ERROR_RETURN
  11193                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11194                      PHY84740_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0 + lane, &data16));
  11195             if (!(data16 & 0xfff)) {
  11196                 /* PRBS is in sync */
  11197                 continue;
  11198             } else {
  11199                 /* Get errors */
  11200                 *value += (data16 & 0xfff);
  11201             }
  11202         }
  11203     } else {  /* quad-port mode */
  11204         SOC_IF_ERROR_RETURN
  11205             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
  11206                           PHY84740_USER_PRBS_STATUS_0_REGISTER, &data16));
  11207         if (data16 == 0x8000) { /* PRBS lock and error free */
  11208             *value = 0;
  11209         } else if (!(data16 & 0x8000)) {
  11210             *value = -1;
  11211         } else {
  11212             *value = data16 & 0x7fff;
  11213         }
  11214     }
  11215 
  11216     return SOC_E_NONE;
  11217 }
  11218 
  11219 STATIC int
  11220 _phy_84741_control_edc_mode_get(int unit, soc_port_t port, uint32 *value)
  11221 {
  11222     uint16         data16;
  11223     phy_ctrl_t    *pc;       /* PHY software state */
  11224 
  11225     pc = EXT_PHY_SW_STATE(unit, port);
  11226 
  11227     /* get EDC mode */     
  11228     SOC_IF_ERROR_RETURN
  11229       (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xCA1A,&data16));
  11230 
  11231     *value = data16 & PHY84740_EDC_MODE_MASK;
  11232 
  11233     return SOC_E_NONE;
  11234 }
  11235 
  11236 
  11237 STATIC int
  11238 _phy_84741_remote_loopback_set(int unit, soc_port_t port,int intf,uint32 enable)
  11239 {
  11240     phy_ctrl_t    *pc;       /* PHY software state */
  11241     int lane;
  11242 
  11243     pc = EXT_PHY_SW_STATE(unit, port);
  11244 
  11245     if (intf == PHY_DIAG_INTF_SYS) {
  11246         if ((PHY84740_SINGLE_PORT_MODE(pc))) {
  11247             for (lane = 0; lane < NUM_LANES; lane++) {
  11248                 /* targeted to the system side */
  11249                 SOC_IF_ERROR_RETURN
  11250                       (PHY84740_XFI(unit,pc));
  11251          
  11252                 SOC_IF_ERROR_RETURN
  11253                       (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  11254                                              PHY84740_PMAD_AER_ADDR_REG, lane));
  11255                 SOC_IF_ERROR_RETURN
  11256                        (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xcd0a,
  11257                        enable? 1:0, 1));
  11258      
  11259                 /* targeted to the system side, switch back */
  11260                 SOC_IF_ERROR_RETURN
  11261                        (PHY84740_MMF(unit,pc));
  11262             }
  11263         /* point back to lane0 */
  11264         SOC_IF_ERROR_RETURN
  11265             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  11266         } else {
  11267             SOC_IF_ERROR_RETURN
  11268                    (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xcd0a,
  11269                    enable? 1:0, 1));
  11270         }
  11271     }
  11272     return SOC_E_NONE;
  11273 }
  11274 
  11275 STATIC int
  11276 _phy_84741_debug_info(int unit, soc_port_t port)
  11277 {
  11278     phy_ctrl_t  *pc;
  11279     phy_ctrl_t  *int_pc;
  11280     int         lane;
  11281     const char  *if_names[] = SOC_PORT_IF_NAMES_INITIALIZER;
  11282     struct dbgi {
  11283         uint16 ucode_rev;
  11284         uint16 pl2_reg;
  11285         uint16 pma_mii_stat;
  11286         uint16 tx_polarity_reg[NUM_LANES];
  11287         uint16 rx_polarity_reg[NUM_LANES];
  11288         soc_port_if_t iif;
  11289         int    ilink;
  11290         int    ispeed;
  11291         int    ian;
  11292         int    ian_done;
  11293     } dbgi;
  11294 
  11295 
  11296     pc = EXT_PHY_SW_STATE(unit, port);
  11297     int_pc = INT_PHY_SW_STATE(unit, port);
  11298 
  11299      SOC_IF_ERROR_RETURN
  11300          (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &dbgi.ucode_rev));
  11301 
  11302      SOC_IF_ERROR_RETURN
  11303          (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_LANE0_L2P_REG, &dbgi.pl2_reg));
  11304 
  11305      for (lane = 0; lane < NUM_LANES; lane++) {
  11306          /* point to the each lane starting at lane0 */
  11307          SOC_IF_ERROR_RETURN
  11308              (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  11309                                              PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc, lane)));
  11310          
  11311          SOC_IF_ERROR_RETURN(
  11312              READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_DIG_CTRL_REG,
  11313                                            &dbgi.tx_polarity_reg[lane]));
  11314          SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
  11315          SOC_IF_ERROR_RETURN(
  11316              READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_DIG_CTRL_REG,
  11317                                            &dbgi.rx_polarity_reg[lane]));
  11318          SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
  11319      }
  11320 
  11321      LOG_CLI((BSL_META_U(unit,
  11322                          "Port %-3d(mdio=0x%x): ver(1.%04x)=0x%x, single lpmode=%d, "
  11323                          "p2lreg(1.%04x)=0x%04x, p2lmap=%d%d%d%d\n"),
  11324               port, pc->phy_id, 0xce00, dbgi.ucode_rev, 
  11325               SINGLE_LPMODE(pc),
  11326               PHY84740_PMAD_LANE0_L2P_REG, dbgi.pl2_reg,
  11327               P2L_MAP(pc, 3), P2L_MAP(pc, 2), P2L_MAP(pc, 1), P2L_MAP(pc, 0)));
  11328 
  11329      if (PHY84740_SINGLE_PORT_MODE(pc)) {
  11330          SOC_IF_ERROR_RETURN
  11331              (READ_PHY84740_PMA_PMD_STATr(unit, pc, &dbgi.pma_mii_stat));
  11332          SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &dbgi.ilink));
  11333          LOG_CLI((BSL_META_U(unit,
  11334                              "   pma_link(1.0x%04x)=0x%0x(%s), serdes_link=%s\n"),
  11335                   1, dbgi.pma_mii_stat, 
  11336                   (dbgi.pma_mii_stat & MII_STAT_LA) ? "up" : "down",
  11337                   dbgi.ilink ? "up" : "down"));
  11338          LOG_CLI((BSL_META_U(unit,
  11339                              "   line polarity(1.%04x)=(ln0=%04x, "
  11340                              "ln1=%04x, ln2=%04x, ln3=%04x)\n"),
  11341                   PHY84740_DIG_CTRL_REG,
  11342                   dbgi.tx_polarity_reg[0], dbgi.tx_polarity_reg[1], 
  11343                   dbgi.tx_polarity_reg[2], dbgi.tx_polarity_reg[3]));
  11344          LOG_CLI((BSL_META_U(unit,
  11345                              "   sys  polarity(1.%04x)=(ln0=%04x, "
  11346                              "ln1=%04x, ln2=%04x, ln3=%04x)\n"),
  11347                   PHY84740_DIG_CTRL_REG,
  11348                   dbgi.rx_polarity_reg[0], dbgi.rx_polarity_reg[1], 
  11349                   dbgi.tx_polarity_reg[2], dbgi.rx_polarity_reg[3]));
  11350      } else {
  11351          LOG_CLI((BSL_META_U(unit,
  11352                              "   line polarity(1.%04x)=%04x\n"),
  11353                   PHY84740_DIG_CTRL_REG, dbgi.tx_polarity_reg[0]));
  11354          LOG_CLI((BSL_META_U(unit,
  11355                              "   sys  polarity(1.%04x)=%04x\n"),
  11356                   PHY84740_DIG_CTRL_REG, dbgi.rx_polarity_reg[0]));
  11357      }
  11358      if (int_pc) {
  11359          SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET(int_pc->pd, unit, port, &dbgi.iif));
  11360          SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &dbgi.ispeed));
  11361          SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &dbgi.ian, &dbgi.ian_done));
  11362          LOG_CLI((BSL_META_U(unit,
  11363                              "   Internal: type=%s, speed=%d, an=%d\n"),
  11364                   if_names[dbgi.iif],
  11365                   dbgi.ispeed, dbgi.ian));
  11366      }
  11367      LOG_CLI((BSL_META_U(unit,
  11368                          "=======\n")));
  11369      return SOC_E_NONE;
  11370 }
  11371 
  11372 /*
  11373  * Function:
  11374  *      phy_84741_control_set
  11375  * Purpose:
  11376  *      Configure PHY device specific control fucntion.
  11377  * Parameters:
  11378  *      unit  - StrataSwitch unit #.
  11379  *      port  - StrataSwitch port #.
  11380  *      type  - Control to update
  11381  *      value - New setting for the control
  11382  * Returns:
  11383  *      SOC_E_NONE
  11384  */
  11385 STATIC int
  11386 _phy_84741_control_set(int unit, soc_port_t port, int intf,int lane,
  11387                      soc_phy_control_t type, uint32 value)
  11388 {
  11389     phy_ctrl_t    *pc;       /* PHY software state */
  11390     phy_ctrl_t    *int_pc;
  11391     int rv;
  11392 
  11393     pc = EXT_PHY_SW_STATE(unit, port);
  11394     int_pc = INT_PHY_SW_STATE(unit, port);
  11395 
  11396     PHY_CONTROL_TYPE_CHECK(type);
  11397 
  11398     rv = SOC_E_UNAVAIL;
  11399     if (intf == PHY_DIAG_INTF_SYS) {
  11400         /* if is targeted to the system side */
  11401         SOC_IF_ERROR_RETURN
  11402             (PHY84740_XFI(unit,pc));
  11403     }
  11404     switch(type) {
  11405     case SOC_PHY_CONTROL_PREEMPHASIS:
  11406         /* fall through */
  11407     case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
  11408         /* fall through */
  11409     case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
  11410         /* fall through */
  11411     case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
  11412         /* fall through */
  11413     case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
  11414         /* fall through */
  11415     case SOC_PHY_CONTROL_DRIVER_CURRENT:
  11416         /* fall through */
  11417     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
  11418         /* fall through */
  11419     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
  11420         /* fall through */
  11421     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
  11422         /* fall through */
  11423     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
  11424         /* fall through */
  11425     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
  11426         /* fall through */
  11427     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
  11428         /* fall through */
  11429     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
  11430         /* fall through */
  11431     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
  11432         /* fall through */
  11433     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
  11434         rv = _phy_84741_control_tx_driver_set(unit, port, intf, type, value);
  11435         break;
  11436     case SOC_PHY_CONTROL_EDC_MODE:
  11437         rv = _phy_84741_control_edc_mode_set(unit,port,value);
  11438         break;
  11439     case SOC_PHY_CONTROL_CLOCK_ENABLE:
  11440         rv = _phy_84741_control_recovery_clock_set(unit,port,value);
  11441         break;
  11442     case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
  11443         rv = _phy_84741_control_recovery_clock_freq_set(unit,port,value);
  11444         break;
  11445     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
  11446         /* on line side, rx poly type is auto-detected. On system side,
  11447          * need to enable the rx type as well.
  11448          */
  11449         rv = _phy_84741_control_prbs_polynomial_set(unit, port, value, TRUE);
  11450         if (intf == PHY_DIAG_INTF_SYS) {
  11451             rv = _phy_84741_control_prbs_polynomial_set(unit, port,value,FALSE);
  11452         }
  11453         break;
  11454     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
  11455         /* on line side, rx invertion is auto-detected. On system side,
  11456          * need to enable the rx as well.
  11457          */
  11458         rv = _phy_84741_control_prbs_tx_invert_data_set(unit, port, value);
  11459         if (intf == PHY_DIAG_INTF_SYS) {
  11460             rv = _phy_84741_control_prbs_rx_invert_data_set(unit, port, value);
  11461         }
  11462         break;
  11463     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
  11464         /* fall through */
  11465     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
  11466         /* tx/rx is enabled at the same time. no seperate control */
  11467         rv = _phy_84741_control_prbs_enable_set(unit, port, value);
  11468         break;
  11469     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
  11470         rv = _phy_84741_remote_loopback_set(unit, port,PHY_DIAG_INTF_SYS,value);
  11471         break;
  11472     case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
  11473         if(int_pc) {
  11474             SOC_IF_ERROR_RETURN
  11475                 (PHY_CONTROL_SET(int_pc->pd, unit, port, type, value));
  11476             SOFTWARE_RX_LOS(pc) = value ? 1 : 0;
  11477             rv = SOC_E_NONE;
  11478         }
  11479         break;     
  11480     case SOC_PHY_CONTROL_DUMP:
  11481         rv = _phy_84741_debug_info(unit, port);
  11482         break;
  11483 #ifdef PHY84756_UNTESTED_CODE
  11484     case SOC_PHY_CONTROL_TX_POLARITY:
  11485         if (PHY84740_IS_QUADRA(devid)) {    /* Quadra */
  11486             rv = phy_84741_tx_polarity_flip_set(unit, port, value);
  11487         } else {
  11488             rv = SOC_E_UNAVAIL;
  11489         }
  11490         break;
  11491     case SOC_PHY_CONTROL_RX_POLARITY:
  11492         if (PHY84740_IS_QUADRA(devid)) {    /* Quadra */
  11493             rv = phy_84741_rx_polarity_flip_set(unit, port, value);
  11494         } else {
  11495             rv = SOC_E_UNAVAIL;
  11496         }
  11497         break;
  11498 #endif /* PHY84756_UNTESTED_CODE */
  11499     case SOC_PHY_CONTROL_TX_LANE_SQUELCH:
  11500         rv = _phy_84741_squelch_enable(unit, port, intf, value, FALSE);
  11501         break;
  11502     default:
  11503         rv = SOC_E_UNAVAIL;
  11504         break;
  11505     }
  11506     if (intf == PHY_DIAG_INTF_SYS) {
  11507         /* if it is targeted to the system side, switch back */
  11508         SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
  11509     }
  11510     return rv;
  11511 }
  11512 
  11513 #ifdef PHY84756_UNTESTED_CODE
  11514 STATIC int phy_84741_tx_polarity_flip_set(int unit, int port, uint32 value)
  11515 {
  11516     int lane;
  11517     phy_ctrl_t *pc;
  11518     uint16 tx_pol;
  11519     uint16 data16, mask16;
  11520 
  11521     pc = EXT_PHY_SW_STATE(unit, port);
  11522     tx_pol = value;
  11523 
  11524     /* get the reset default value. The 84740 device has the TX polarity flipped
  11525      * by default. Construct the init default value 
  11526      */
  11527 
  11528     mask16 = PHY84740_TX_POLARITY_FLIP_MASK;
  11529 
  11530     if ((PHY84740_SINGLE_PORT_MODE(pc))) {
  11531         for (lane = 0; lane < NUM_LANES; lane++) {
  11532             data16 = 0;
  11533 
  11534             /* point to the each lane starting at lane0 */
  11535             SOC_IF_ERROR_RETURN
  11536                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  11537                                                 PHY84740_PMAD_AER_ADDR_REG,
  11538                                                 P2L_MAP(pc, lane)));
  11539 
  11540             if ((tx_pol == POL_CONFIG_ALL_LANES) ||
  11541                 ((tx_pol & POL_CONFIG_LANE_MASK(lane)) ==
  11542                  POL_CONFIG_LANE_MASK(lane))) {
  11543                 data16 = PHY84740_TX_POLARITY_FLIP_MASK;
  11544             }
  11545             SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  11546                                                                 PHY84740_DIG_CTRL_REG,
  11547                                                                 data16,
  11548                                                                 mask16));
  11549         }
  11550         /* point back to lane0 */
  11551         SOC_IF_ERROR_RETURN
  11552             (WRITE_PHY84740_MMF_PMA_PMD_REG
  11553              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  11554     } else {                    /* quad-port mode */
  11555         data16 = 0;
  11556         tx_pol = PHY84740_10G_POL_CFG_GET(pc, tx_pol);
  11557         if (tx_pol) {
  11558             data16 = PHY84740_TX_POLARITY_FLIP_MASK;
  11559         }
  11560         SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
  11561                             (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16));
  11562         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
  11563                             (unit, pc, PHY84740_DIG_CTRL_REG, &data16));
  11564     }
  11565 
  11566     return SOC_E_NONE;
  11567 }
  11568 
  11569 STATIC int phy_84741_rx_polarity_flip_set(int unit, int port, uint32 value)
  11570 {
  11571     int lane;
  11572     phy_ctrl_t *pc;
  11573     uint16 rx_pol;
  11574     uint16 data16, mask16;
  11575 
  11576     pc = EXT_PHY_SW_STATE(unit, port);
  11577 
  11578     rx_pol = value;
  11579     /* get the reset default value. The 84740 device has the TX polarity flipped
  11580      * by default. Construct the init default value 
  11581      */
  11582     mask16 = PHY84740_RX_POLARITY_FLIP_MASK;
  11583 
  11584     if ((PHY84740_SINGLE_PORT_MODE(pc))) {
  11585         for (lane = 0; lane < NUM_LANES; lane++) {
  11586             data16 = 0;
  11587 
  11588             /* point to the each lane starting at lane0 */
  11589             SOC_IF_ERROR_RETURN
  11590                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  11591                                                 PHY84740_PMAD_AER_ADDR_REG,
  11592                                                 P2L_MAP(pc, lane)));
  11593             if ((rx_pol == POL_CONFIG_ALL_LANES)
  11594                 || ((rx_pol & POL_CONFIG_LANE_MASK(lane)) ==
  11595                     POL_CONFIG_LANE_MASK(lane))) {
  11596                 data16 |= PHY84740_RX_POLARITY_FLIP_MASK;
  11597             }
  11598             SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  11599                                                                 PHY84740_DIG_CTRL_REG,
  11600                                                                 data16,
  11601                                                                 mask16));
  11602         }
  11603         /* point back to lane0 */
  11604         SOC_IF_ERROR_RETURN
  11605             (WRITE_PHY84740_MMF_PMA_PMD_REG
  11606              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  11607     } else {                    /* quad-port mode */
  11608         data16 = 0;
  11609         rx_pol = PHY84740_10G_POL_CFG_GET(pc, rx_pol);
  11610         if (rx_pol) {
  11611             data16 = PHY84740_RX_POLARITY_FLIP_MASK;
  11612         }
  11613         SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
  11614                             (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16));
  11615         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
  11616                             (unit, pc, PHY84740_DIG_CTRL_REG, &data16));
  11617     }
  11618     return SOC_E_NONE;
  11619 }
  11620 #endif /* PHY84756_UNTESTED_CODE */
  11621 
  11622 STATIC int
  11623 phy_84741_control_set(int unit, soc_port_t port,
  11624                      soc_phy_control_t type, uint32 value)
  11625 {
  11626     phy_ctrl_t    *pc;       /* PHY software state */
  11627     int intf;
  11628 
  11629     pc = EXT_PHY_SW_STATE(unit, port);
  11630 
  11631     intf = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL))? 
  11632            PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE;
  11633     SOC_IF_ERROR_RETURN
  11634         (_phy_84741_control_set(unit, port, intf,
  11635             PHY_DIAG_LN_DFLT, type, value));
  11636     return SOC_E_NONE;
  11637 }
  11638 /*
  11639  * Function:
  11640  *      phy_84741_control_get
  11641  * Purpose:
  11642  *      Get current control settign of the PHY.
  11643  * Parameters:
  11644  *      unit  - StrataSwitch unit #.
  11645  *      port  - StrataSwitch port #.
  11646  *      type  - Control to update
  11647  *      value - (OUT)Current setting for the control
  11648  * Returns:
  11649  *      SOC_E_NONE
  11650  */
  11651 STATIC int
  11652 _phy_84741_control_get(int unit, soc_port_t port, int intf,int lane,
  11653                      soc_phy_control_t type, uint32 *value)
  11654 {
  11655     phy_ctrl_t    *pc;       /* PHY software state */
  11656     int rv;
  11657     uint16 data16;
  11658 
  11659     pc = EXT_PHY_SW_STATE(unit, port);
  11660 
  11661     PHY_CONTROL_TYPE_CHECK(type);
  11662 
  11663     if (intf == PHY_DIAG_INTF_SYS) {
  11664         /* targeted to the system side */
  11665         SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
  11666     }
  11667     rv = SOC_E_UNAVAIL;
  11668     switch(type) {
  11669     case SOC_PHY_CONTROL_PREEMPHASIS:
  11670         /* fall through */
  11671     case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
  11672         /* fall through */
  11673     case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
  11674         /* fall through */
  11675     case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
  11676         /* fall through */
  11677     case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
  11678         /* fall through */
  11679     case SOC_PHY_CONTROL_DRIVER_CURRENT:
  11680         /* fall through */
  11681     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
  11682         /* fall through */
  11683     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
  11684         /* fall through */
  11685     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
  11686         /* fall through */
  11687     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
  11688         /* fall through */
  11689     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
  11690         /* fall through */
  11691     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
  11692         /* fall through */
  11693     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
  11694         /* fall through */
  11695     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
  11696         /* fall through */
  11697     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
  11698         rv = _phy_84741_control_tx_driver_get(unit, port, type, value);
  11699         break;
  11700     case SOC_PHY_CONTROL_EDC_MODE:
  11701         rv = _phy_84741_control_edc_mode_get(unit,port,value);
  11702         break;
  11703     case SOC_PHY_CONTROL_CLOCK_ENABLE:
  11704         SOC_IF_ERROR_RETURN
  11705            (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_REG, 
  11706                                           &data16));
  11707         *value = (data16 & PHY84740_RECOVERY_CLK_ENABLE_MASK)? TRUE: FALSE; 
  11708         rv = SOC_E_NONE;
  11709         break;
  11710     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
  11711         rv = _phy_84741_control_prbs_polynomial_get(unit, port, value);
  11712         break;
  11713     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
  11714         rv = _phy_84741_control_prbs_tx_invert_data_get(unit, port, value);
  11715         break;
  11716     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
  11717         /* fall through */
  11718     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
  11719         rv = _phy_84741_control_prbs_enable_get(unit, port, value);
  11720         break;
  11721     case SOC_PHY_CONTROL_PRBS_RX_STATUS:
  11722         rv = _phy_84741_control_prbs_rx_status_get(unit, port, value);
  11723         break;
  11724     case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
  11725         SOC_IF_ERROR_RETURN
  11726             (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, 
  11727                    &data16));
  11728         switch ((data16 >> PHY84740_RECOVERY_CLK_FREQ_SHIFT) & 0x3) {
  11729             case 0x1:
  11730                 *value = 125000;
  11731                 break;
  11732             case 0x2:
  11733                 *value = 195312;
  11734                 break;
  11735             case 0x3:
  11736                 *value = 156250;
  11737                 break;
  11738             default:
  11739                 *value = 0x0;
  11740                 break;
  11741         }
  11742         rv = SOC_E_NONE;
  11743         break;
  11744     case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
  11745         *value = SOFTWARE_RX_LOS(pc);
  11746         rv = SOC_E_NONE;
  11747         break;     
  11748 
  11749     default:
  11750         rv = SOC_E_UNAVAIL;
  11751         break;
  11752     }
  11753 
  11754     if (intf == PHY_DIAG_INTF_SYS) {
  11755         /* if it is targeted to the system side, switch back */
  11756         SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
  11757     }
  11758     return rv;
  11759 }
  11760 STATIC int
  11761 phy_84741_control_get(int unit, soc_port_t port,
  11762                      soc_phy_control_t type, uint32 *value)
  11763 {
  11764     int intf;
  11765     phy_ctrl_t    *pc;       /* PHY software state */
  11766 
  11767     pc = EXT_PHY_SW_STATE(unit, port);
  11768 
  11769     intf = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ?
  11770         PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
  11771 
  11772     SOC_IF_ERROR_RETURN
  11773         (_phy_84741_control_get(unit, port, intf,
  11774             PHY_DIAG_LN_DFLT, type, value));
  11775     return SOC_E_NONE;
  11776 }
  11777 
  11778 STATIC int
  11779 phy_84741_diag_ctrl(
  11780    int unit, /* unit */
  11781    soc_port_t port, /* port */
  11782    uint32 inst, /* the specific device block the control action directs to */
  11783    int op_type,  /* operation types: read,write or command sequence */
  11784    int op_cmd,   /* command code */
  11785    void *arg)     /* command argument  */
  11786 {
  11787     int lane;
  11788     int intf;
  11789 
  11790     LOG_INFO(BSL_LS_SOC_PHY,
  11791              (BSL_META_U(unit,
  11792                          "phy_84741_diag_ctrl: u=%d p=%d ctrl=0x%x\n"), 
  11793                          unit, port,op_cmd));
  11794    
  11795     lane = PHY_DIAG_INST_LN(inst);
  11796     intf = PHY_DIAG_INST_INTF(inst);
  11797     if (intf == PHY_DIAG_INTF_DFLT) {
  11798         intf = PHY_DIAG_INTF_LINE;
  11799     }
  11800 
  11801     if (op_type == PHY_DIAG_CTRL_GET) { 
  11802         SOC_IF_ERROR_RETURN
  11803             (_phy_84741_control_get(unit, port, intf, lane,
  11804                   op_cmd,(uint32 *)arg));
  11805     } else if (op_type == PHY_DIAG_CTRL_SET) {
  11806         SOC_IF_ERROR_RETURN
  11807             (_phy_84741_control_set(unit, port, intf, lane,
  11808                   op_cmd, PTR_TO_INT(arg)));
  11809     }
  11810     return SOC_E_NONE;
  11811 }
  11812 
  11813 /*
  11814  * Function:
  11815  *      phy_84741_speed_set
  11816  * Purpose:
  11817  *      Set PHY speed
  11818  * Parameters:
  11819  *      unit - StrataSwitch unit #.
  11820  *      port - StrataSwitch port #.
  11821  *      speed - link speed in Mbps
  11822  * Returns:
  11823  *      SOC_E_NONE
  11824  */
  11825 
  11826 STATIC int phy_84741_speed_set(int unit, soc_port_t port, int speed)
  11827 {
  11828     phy_ctrl_t  *pc;
  11829     phy_ctrl_t  *int_pc;
  11830     int rv = SOC_E_NONE;
  11831 
  11832     COMPILER_REFERENCE(unit);
  11833     COMPILER_REFERENCE(port); 
  11834 
  11835     int_pc = INT_PHY_SW_STATE(unit, port);
  11836     pc = EXT_PHY_SW_STATE(unit, port);
  11837 
  11838     LOG_INFO(BSL_LS_SOC_PHY,
  11839              (BSL_META_U(unit,
  11840                          "phy_84741_speed_set: u=%d p=%d speed=%d\n"), 
  11841                          unit, port,speed));
  11842 
  11843     if (FCMAP_PASSTHROUGH(pc)) {
  11844             return SOC_E_NONE;
  11845     }
  11846 
  11847     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  11848         if (speed != 40000) {
  11849             return SOC_E_PARAM;
  11850         }
  11851 
  11852         /* single port mode: doesn't use PCS. should be already in repeater mode */
  11853         /* it is always in 40G speed, make sure internal device is in 40G */
  11854         if (NULL != int_pc) {
  11855             if (REVERSE_MODE(pc)) {
  11856                 if (IS_HG_PORT(unit, port)) {
  11857                     SOC_IF_ERROR_RETURN
  11858                         (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_KR4));
  11859                 } else {
  11860                     SOC_IF_ERROR_RETURN
  11861                         (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_SR4));
  11862                 }
  11863             } else {
  11864                 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) {
  11865                         rv = PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_CR);
  11866                 }
  11867             }
  11868 
  11869             rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed);
  11870         }
  11871         return rv;
  11872     }
  11873 
  11874     /* quad lane mode */
  11875     if ((!(speed == 10000 || speed == 1000)) &&
  11876         (!PCS_REPEATER(pc))) {
  11877         return SOC_E_PARAM;
  11878     }
  11879 
  11880     if (speed == 10000) {
  11881         SOC_IF_ERROR_RETURN
  11882             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_PMAD_CTRL_REG,
  11883                                           MII_CTRL_SS_MSB |  MII_CTRL_SS_LSB));
  11884         SOC_IF_ERROR_RETURN
  11885             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_PMAD_CTRL2_REG,
  11886                                         PHY84740_PMAD_CTRL2r_PMA_TYPE_10G_LRM, 
  11887                                         PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK));
  11888 
  11889     } else {
  11890         SOC_IF_ERROR_RETURN
  11891             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_PMAD_CTRL2_REG,
  11892                                         PHY84740_PMAD_CTRL2r_PMA_TYPE_1G_KX,
  11893                                         PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK));
  11894         SOC_IF_ERROR_RETURN
  11895             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, MII_CTRL_REG,
  11896                                         0, MII_CTRL_SS_LSB));
  11897     }
  11898     /* need to set the internal phy's speed accordingly */
  11899 
  11900     if (NULL != int_pc) {
  11901         if (REVERSE_MODE(pc)) {
  11902             SOC_IF_ERROR_RETURN
  11903                 (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_SR));
  11904         } else {
  11905             /* For long XFI channel, it is best to use SFP+ DAC mode 
  11906              * in the serdes side to provide adequate Rx equalization
  11907              */
  11908             if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) {
  11909                 if (!PHY84740_SINGLE_PORT_MODE(pc)) {
  11910                     rv = PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_CR);
  11911                 }
  11912             }
  11913         }
  11914         rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed);
  11915     }
  11916     return rv;
  11917 }
  11918 
  11919 /*
  11920  * Function:
  11921  *      phy_84741_speed_get
  11922  * Purpose:
  11923  *      Get PHY speed
  11924  * Parameters:
  11925  *      unit - StrataSwitch unit #.
  11926  *      port - StrataSwitch port #.
  11927  *      speed - current link speed in Mbps
  11928  * Returns:
  11929  *      SOC_E_NONE
  11930  */
  11931 
  11932 STATIC int
  11933 phy_84741_speed_get(int unit, soc_port_t port, int *speed)
  11934 {
  11935     phy_ctrl_t  *pc;
  11936     uint16       speed_val;
  11937 
  11938     pc = EXT_PHY_SW_STATE(unit, port);
  11939 
  11940     if (PCS_REPEATER(pc)) {
  11941         phy_ctrl_t    *int_pc;
  11942 
  11943         int_pc = INT_PHY_SW_STATE(unit, port);
  11944         SOC_IF_ERROR_RETURN
  11945             (PHY_SPEED_GET(int_pc->pd, unit, port, speed));
  11946         return SOC_E_NONE;
  11947     } else if (FCMAP_PASSTHROUGH(pc)) {
  11948         *speed = 10000;
  11949         return SOC_E_NONE;
  11950     }
  11951 
  11952     /* this register contains the speed info for both single/quad modes */
  11953     SOC_IF_ERROR_RETURN
  11954         (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xc81f, &speed_val));
  11955 
  11956     if (speed_val & (1 << 5)) {
  11957         *speed = 40000;
  11958     } else if (speed_val & (1 << 4)) {
  11959         *speed = 10000;
  11960     } else if (speed_val & (1 << 2)) {
  11961         *speed = 1000;
  11962     } else { /* default */
  11963         if (PHY84740_SINGLE_PORT_MODE(pc)) {
  11964             *speed = 40000;
  11965         } else {
  11966             *speed = 10000;
  11967         }
  11968     }
  11969     return SOC_E_NONE;
  11970 }
  11971 
  11972 /*
  11973  * Function:
  11974  *      phy_84741_interface_set
  11975  * Purpose:
  11976  *      Set either CR4 interface or SR4/LR4. The valid interface are SOC_PORT_IF_CR4
  11977  *      and SOC_PORT_IF_XLAUI which put device in default mode: SR4/LR4 mode
  11978  * Parameters:
  11979  *      unit - StrataSwitch unit #.
  11980  *      port - StrataSwitch port #.
  11981  *      pif - one of SOC_PORT_IF_*
  11982  * Returns:
  11983  *      SOC_E_NONE - success
  11984  *      SOC_E_UNAVAIL - unsupported interface
  11985  */
  11986 
  11987 STATIC int
  11988 phy_84741_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
  11989 {
  11990     phy_ctrl_t     *pc;
  11991     phy_ctrl_t  *int_pc;
  11992     uint16 ucode_ver;
  11993     uint16 sig_lvl_reg[4];
  11994     uint16 rxlos_reg[4];
  11995     uint16 pol_reg[4];
  11996     int lane;
  11997     soc_port_ability_t ability;
  11998 
  11999     int_pc = INT_PHY_SW_STATE(unit, port);
  12000     pc = EXT_PHY_SW_STATE(unit, port);
  12001 
  12002     if (int_pc != NULL) {
  12003         if (REVERSE_MODE(pc)) {
  12004             SOC_IF_ERROR_RETURN
  12005                 (PHY_INTERFACE_SET(int_pc->pd, unit, port, pif));
  12006             SOC_IF_ERROR_RETURN(
  12007                 PHY_ABILITY_ADVERT_GET(int_pc->pd, unit, port, &ability));
  12008             SOC_IF_ERROR_RETURN(
  12009                 PHY_ABILITY_ADVERT_SET(int_pc->pd, unit, port, &ability));
  12010         }
  12011     }
  12012 
  12013     if (!(PHY84740_SINGLE_PORT_MODE(pc))) {
  12014         return phy_null_interface_set(unit,port,pif);
  12015     }
  12016 
  12017     switch (pif) {
  12018     case SOC_PORT_IF_CR4:
  12019         SOC_IF_ERROR_RETURN
  12020             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
  12021                    PHY84740_PMAD_DAC_MODE_MASK, PHY84740_PMAD_DAC_MODE_MASK));
  12022         break;
  12023  
  12024     case SOC_PORT_IF_XLAUI:
  12025         SOC_IF_ERROR_RETURN
  12026             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
  12027                    0, PHY84740_PMAD_DAC_MODE_MASK));
  12028         break;
  12029     default:
  12030         break;
  12031     }
  12032 
  12033     SOC_IF_ERROR_RETURN
  12034         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &ucode_ver));
  12035 
  12036     if (ucode_ver >= 0x0104) { 
  12037         /* For 40G mode, Do not reset the PHY if ucode is D104 on newer */
  12038         return SOC_E_NONE;
  12039     }
  12040    
  12041    
  12042     /* After switching mode, user need to redo the configuration */
  12043     if (pif == SOC_PORT_IF_CR4 || pif == SOC_PORT_IF_XLAUI) {
  12044 
  12045         /* save the register settings */
  12046         for (lane = 0; lane < NUM_LANES; lane++) {
  12047             /* point to the each lane starting at lane0 */
  12048             SOC_IF_ERROR_RETURN
  12049                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  12050                                 PHY84740_PMAD_AER_ADDR_REG, lane));
  12051             SOC_IF_ERROR_RETURN(
  12052                 READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  12053                                          PHY84740_DIG_CTRL_REG,
  12054                                          &pol_reg[lane]));
  12055 
  12056             SOC_IF_ERROR_RETURN
  12057                 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  12058                              PHY84740_PMAD_OPTICAL_CFG_REG,
  12059                              &rxlos_reg[lane]));
  12060             SOC_IF_ERROR_RETURN
  12061                 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  12062                              PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
  12063                              &sig_lvl_reg[lane]));
  12064         }
  12065 
  12066         /* perform IEEE reset */
  12067         SOC_IF_ERROR_RETURN
  12068             (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc,
  12069                               MII_CTRL_RESET, MII_CTRL_RESET));
  12070 
  12071         sal_udelay(100); /* Wait for 100us */
  12072 
  12073         /* restore back saved register values */
  12074         for (lane = 0; lane < NUM_LANES; lane++) {
  12075             /* point to the each lane starting at lane0 */
  12076             SOC_IF_ERROR_RETURN
  12077                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
  12078                                 PHY84740_PMAD_AER_ADDR_REG, lane));
  12079             SOC_IF_ERROR_RETURN(
  12080                 WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  12081                                          PHY84740_DIG_CTRL_REG,
  12082                                          pol_reg[lane]));
  12083 
  12084             SOC_IF_ERROR_RETURN
  12085                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  12086                              PHY84740_PMAD_OPTICAL_CFG_REG,
  12087                              rxlos_reg[lane]));
  12088             SOC_IF_ERROR_RETURN
  12089                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc,
  12090                              PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
  12091                              sig_lvl_reg[lane]));
  12092         }
  12093 
  12094         /* redo Polarity configuration */
  12095         SOC_IF_ERROR_RETURN
  12096             (_phy_84741_polarity_flip_set(unit,port));
  12097 
  12098         /* point back to lane0 */
  12099         SOC_IF_ERROR_RETURN
  12100             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  12101     }
  12102 
  12103     return SOC_E_NONE;
  12104 }
  12105 
  12106 /*
  12107  * Function:
  12108  *      phy_84741_interface_get
  12109  * Purpose:
  12110  *      Get the current operating mode of the PHY.
  12111  * Parameters:
  12112  *      unit - StrataSwitch unit #.
  12113  *      port - StrataSwitch port #.
  12114  *      pif - (OUT) one of SOC_PORT_IF_*
  12115  * Returns:
  12116  *      SOC_E_NONE
  12117  */
  12118 
  12119 STATIC int
  12120 phy_84741_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
  12121 {
  12122     phy_ctrl_t    *pc;
  12123     uint16 mode;
  12124 
  12125     pc = EXT_PHY_SW_STATE(unit, port);
  12126 
  12127     if (!(PHY84740_SINGLE_PORT_MODE(pc))) {
  12128         *pif = SOC_PORT_IF_XAUI;
  12129         return SOC_E_NONE;
  12130     }
  12131 
  12132     SOC_IF_ERROR_RETURN
  12133         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&mode));
  12134     if (mode & PHY84740_PMAD_DAC_MODE_MASK) {
  12135         *pif = SOC_PORT_IF_CR4;
  12136     } else {
  12137         *pif = SOC_PORT_IF_XLAUI;
  12138     }
  12139 
  12140     return SOC_E_NONE;
  12141 }
  12142 
  12143 /*
  12144  *  Function:  *      phy_84741_rom_wait
  12145  *
  12146  *  Purpose:
  12147  *      Wait for data to be written to the SPI-ROM.
  12148  *  Input:
  12149  *      unit, port
  12150  */
  12151 STATIC int
  12152 phy_84741_rom_wait(int unit, int port)
  12153 {
  12154     uint16     rd_data;     
  12155     uint16     wr_data;
  12156     uint16     data16;
  12157     int        count;     
  12158     phy_ctrl_t *pc;
  12159     soc_timeout_t to;     
  12160     int        SPI_READY; 
  12161 
  12162     pc = EXT_PHY_SW_STATE(unit, port);
  12163 
  12164     rd_data = 0;
  12165     soc_timeout_init(&to, WR_TIMEOUT, 0);
  12166     do {
  12167         /* Write SPI Control Register Read Command. */
  12168         count = 1;
  12169         wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
  12170         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12171         wr_data = SPI_CTRL_1_L;
  12172         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12173 
  12174         /* extra reads to clear the status */
  12175         SOC_IF_ERROR_RETURN
  12176             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
  12177         SOC_IF_ERROR_RETURN
  12178             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
  12179 
  12180         if (rd_data & 0x0100) {
  12181             break;
  12182         }
  12183     } while (!soc_timeout_check(&to));
  12184     if (!(rd_data & 0x0100)) {
  12185         LOG_ERROR(BSL_LS_SOC_PHY,
  12186                   (BSL_META_U(unit,
  12187                               "phy_84741_rom_program: u = %d p = %d "
  12188                               "timeout 1\n"), unit, port));
  12189         return SOC_E_TIMEOUT;
  12190     }
  12191 
  12192     SPI_READY = 1;
  12193     while (SPI_READY == 1) {
  12194         /* Set-up SPI Controller To Receive SPI EEPROM Status. */
  12195         count = 1;
  12196         wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count);
  12197         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12198         wr_data = SPI_CTRL_2_H;
  12199         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12200         wr_data = 0x0100;
  12201         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12202         /* Fill-up SPI Transmit Fifo To check SPI Status. */
  12203         count = 2;
  12204         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12205         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12206         /* Write Tx Fifo Register Address. */
  12207         wr_data = SPI_TXFIFO;
  12208         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12209 
  12210         /* Write SPI Tx Fifo Control Word-1. */
  12211         wr_data = ((1 * 0x0100) | MSGTYPE_HRD);
  12212         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12213         /* Write SPI Tx Fifo Control Word-2. */
  12214         wr_data = RDSR_OPCODE;
  12215         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12216         /* Write SPI Control Register Write Command. */
  12217         count = 2;
  12218         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12219         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12220         /* Write SPI Control -1 Register Address. */
  12221         wr_data = SPI_CTRL_1_L;
  12222         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12223         /* Write SPI Control -1 Register Word-1. */
  12224         wr_data = 0x0101;
  12225         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12226         /* Write SPI Control -1 Register Word-2. */
  12227         wr_data = 0x0100;
  12228         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12229         /* Write SPI Control Register Write Command. */
  12230         count = 1;
  12231         wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count);
  12232         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12233         /* Write SPI Control -1 Register Address. */
  12234         wr_data = SPI_CTRL_1_H;
  12235         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12236         /* Write SPI Control -1 Register Word-2. */
  12237         wr_data = 0x0103;
  12238         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12239         /* Wait For 64 bytes To be written.   */
  12240         rd_data = 0x0000;
  12241         soc_timeout_init(&to, WR_TIMEOUT, 0);
  12242         do {
  12243             count = 1;
  12244             wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
  12245             SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12246             wr_data = SPI_CTRL_1_L;
  12247             SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12248 
  12249             /* extra reads to clear the status */
  12250             SOC_IF_ERROR_RETURN
  12251                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
  12252             SOC_IF_ERROR_RETURN
  12253                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
  12254 
  12255             if (rd_data & 0x0100) {
  12256                 break;
  12257             }
  12258         } while (!soc_timeout_check(&to));
  12259         if (!(rd_data & 0x0100)) {
  12260             LOG_ERROR(BSL_LS_SOC_PHY,
  12261                       (BSL_META_U(unit,
  12262                                   "phy_84741_rom_program: u = %d p = %d "
  12263                                   "timeout 2\n"), unit, port));
  12264             return SOC_E_TIMEOUT;
  12265         }
  12266         /* Write SPI Control Register Read Command. */
  12267         count = 1;
  12268         wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
  12269         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12270         /* Write SPI Control -1 Register Address. */
  12271         wr_data = SPI_RXFIFO;
  12272 
  12273         SOC_IF_ERROR_RETURN         
  12274             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wr_data));
  12275         SOC_IF_ERROR_RETURN
  12276             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data));
  12277 
  12278         /* Clear LASI Message Out Status. */
  12279         SOC_IF_ERROR_RETURN
  12280             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &wr_data));
  12281 
  12282         if ((rd_data & 0x1) == 0) {
  12283             SPI_READY = 0;
  12284         }
  12285         /* extra reads to clear the status */
  12286         SOC_IF_ERROR_RETURN
  12287             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
  12288         SOC_IF_ERROR_RETURN
  12289             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
  12290     } /* SPI_READY  */
  12291     return SOC_E_NONE;
  12292 }
  12293 
  12294 
  12295 /*
  12296  * Function:
  12297  *      phy_84741_rom_write_enable_set
  12298  *
  12299  * Purpose:
  12300  *      Enable disable protection on SPI_EEPROM
  12301  *
  12302  * Input:
  12303  *      unit
  12304  *      port
  12305  *      enable
  12306  * Output:
  12307  *      SOC_E_xxx
  12308  *
  12309  * Notes:
  12310  *          25AA256 256Kbit Serial EEPROM
  12311  *          STATUS Register
  12312  *          +------------------------------------------+
  12313  *          | WPEN | x | x | x | BP1 | BP0 | WEL | WIP |
  12314  *          +------------------------------------------+
  12315  *      BP1 BP0  :   Protected Blocks
  12316  *       0   0   :  Protect None
  12317  *       1   1   :  Protect All
  12318  *
  12319  *      WEL : Write Latch Enable
  12320  *       0  : Do not allow writes
  12321  *       1  : Allow writes
  12322  */
  12323 
  12324 STATIC int
  12325 phy_84741_rom_write_enable_set(int unit, int port, int enable)
  12326 {
  12327     uint16     rd_data;
  12328     uint16     wr_data;
  12329     uint8      wrsr_data;
  12330     int        count;
  12331     phy_ctrl_t *pc;
  12332 
  12333     pc = EXT_PHY_SW_STATE(unit, port);
  12334 
  12335     /*
  12336      * Write SPI Control Register Write Command.
  12337      */
  12338     count = 2;
  12339     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12340     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12341 
  12342     /*
  12343      * Write SPI Control -2 Register Address.
  12344      */
  12345     wr_data = SPI_CTRL_2_L;
  12346     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12347 
  12348     /*
  12349      * Write SPI Control -2 Register Word-1.
  12350      */
  12351     wr_data = 0x8200;
  12352     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12353 
  12354     /*
  12355      * Write SPI Control -2 Register Word-2.
  12356      */
  12357     wr_data = 0x0100;
  12358     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12359 
  12360     /*
  12361      * Fill-up SPI Transmit Fifo With SPI EEPROM Messages.
  12362      * Write SPI Control Register Write Command.
  12363      */
  12364     count = 4;
  12365     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12366     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12367 
  12368     /*
  12369      * Write Tx Fifo Register Address.
  12370      */
  12371     wr_data = SPI_TXFIFO;
  12372     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12373 
  12374     /*
  12375      * Write SPI Tx Fifo Control Word-1.
  12376      */
  12377     wr_data = ((1 * 0x0100) | MSGTYPE_HWR);
  12378     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12379 
  12380     /*
  12381      * Write SPI Tx Fifo Control Word-2.
  12382      */
  12383     wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE);
  12384     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12385 
  12386     /*
  12387      * Write SPI Tx Fifo Control Word-3.
  12388      */
  12389     wr_data = ((WRSR_OPCODE * 0x100) | (0x2));
  12390     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12391 
  12392     /*
  12393      * Write SPI Tx Fifo Control Word-4.
  12394      */
  12395     wrsr_data = enable ? 0x2 : 0xc;
  12396     wr_data = ((wrsr_data * 0x0100) | wrsr_data);
  12397     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12398 
  12399     /*
  12400      * Write SPI Control Register Write Command.
  12401      */
  12402     count = 2;
  12403     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12404     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12405 
  12406     /*
  12407      * Write SPI Control -1 Register Address.
  12408      */
  12409     wr_data = SPI_CTRL_1_L;
  12410     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12411 
  12412     /*
  12413      * Write SPI Control -1 Register Word-1.
  12414      */
  12415     wr_data = 0x0101;
  12416     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12417 
  12418     /*
  12419      * Write SPI Control -1 Register Word-2.
  12420      */
  12421     wr_data = 0x0003;
  12422     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12423 
  12424     /*
  12425      * Wait For WRSR Command To be written.
  12426      */
  12427     SOC_IF_ERROR_RETURN(phy_84741_rom_wait(unit, port));
  12428 
  12429     return SOC_E_NONE;
  12430 }
  12431 
  12432 STATIC int
  12433 _phy84741_init_ucode_bcst(int unit, int port, int cmd)
  12434 {
  12435     uint16 data16;
  12436     uint16 mask16;
  12437     uint16 phy_id;
  12438     int j;
  12439     uint16 num_words;
  12440     int i;
  12441     uint16 chip_mode;
  12442     int num_lanes;
  12443     uint8 *fw_ptr;
  12444     int fw_length;
  12445     phy_ctrl_t *pc;
  12446 
  12447     pc = EXT_PHY_SW_STATE(unit, port);
  12448     num_lanes = PHY84740_SINGLE_PORT_MODE(pc) ? 4 : 1;
  12449 
  12450     if (cmd == PHYCTRL_UCODE_BCST_SETUP) {
  12451         SOC_IF_ERROR_RETURN(
  12452             READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&chip_mode));
  12453 
  12454         LOG_INFO(BSL_LS_SOC_PHY,
  12455                  (BSL_META_U(unit,
  12456                              "PHY84740 BCST start: u=%d p=%d\n"), unit, port));
  12457         /* check the current chip mode, switch to quad if in single port mode */
  12458         if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) == PHY84740_PMAD_MODE_40G) {
  12459             LOG_INFO(BSL_LS_SOC_PHY,
  12460                      (BSL_META_U(unit,
  12461                                  "PHY84740 BCST mode switch: u=%d p=%d\n"), unit, port));
  12462             SOC_IF_ERROR_RETURN(
  12463                 _phy_84741_single_to_quad_mode(unit,port,NULL));
  12464         }       
  12465 
  12466         /* program the bcst register. do 4 lanes for single port configuration */
  12467         phy_id = pc->phy_id;
  12468         /* configure all four ports  */
  12469         for (i = 0; i < num_lanes; i++) {
  12470             if (num_lanes > 1) {
  12471                 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */
  12472             }
  12473             SOC_IF_ERROR_RETURN
  12474                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0xffff));
  12475         }
  12476         /* restore the original phy_id */
  12477         pc->phy_id = phy_id;
  12478         return SOC_E_NONE;
  12479     } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) {
  12480         LOG_INFO(BSL_LS_SOC_PHY,
  12481                  (BSL_META_U(unit,
  12482                              "PHY84740 BCST1: u=%d p=%d\n"), unit, port));
  12483         /* clear SPA ctrl reg bit 15 and bit 13.
  12484          * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM
  12485          * bit 13, 0 clear download done status, 1 skip download
  12486          */
  12487         mask16 = (1 << 13) | (1 << 15);
  12488         data16 = 0;
  12489         SOC_IF_ERROR_RETURN
  12490             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG,
  12491                                         data16,mask16));
  12492 
  12493         /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */
  12494         mask16 = 1 << 14;
  12495         data16 = mask16;
  12496         SOC_IF_ERROR_RETURN
  12497             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG,
  12498                                         data16,mask16));
  12499 
  12500         /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */
  12501         mask16 = 1 << 3;
  12502         data16 = mask16;
  12503         SOC_IF_ERROR_RETURN
  12504             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_MISC_CTRL1_REG,
  12505                                            data16,mask16));
  12506 
  12507         /* apply bcst Reset to start download code from MDIO */
  12508         SOC_IF_ERROR_RETURN
  12509             (WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, 0x8000));
  12510         return SOC_E_NONE;
  12511     } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) {
  12512         LOG_INFO(BSL_LS_SOC_PHY,
  12513                  (BSL_META_U(unit,
  12514                              "PHY84740 BCST2: u=%d p=%d\n"), unit, port));
  12515 
  12516         /* reset clears bcst register */
  12517         /* restore bcst register after reset */
  12518         phy_id = pc->phy_id;
  12519         /* configure all four ports  */
  12520         for (i = 0; i < num_lanes; i++) {
  12521             if (num_lanes > 1) {
  12522                 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */
  12523             }
  12524             SOC_IF_ERROR_RETURN
  12525                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0xffff));
  12526         }
  12527         /* restore the original phy_id */
  12528         pc->phy_id = phy_id;
  12529         return SOC_E_NONE;
  12530     } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) {
  12531         LOG_INFO(BSL_LS_SOC_PHY,
  12532                  (BSL_META_U(unit,
  12533                              "firmware_bcst,device name %s: u=%d p=%d\n"),
  12534                              pc->dev_name? pc->dev_name: "NULL", unit, port));
  12535         /* find the right firmware */
  12536         if (pc->dev_name == dev_name_84740) {
  12537             fw_ptr = phy84740_ucode_bin;
  12538             fw_length = phy84740_ucode_bin_len;
  12539         } else if (pc->dev_name == dev_name_84752) {
  12540             fw_ptr = phy84752_ucode_bin;
  12541             fw_length = phy84752_ucode_bin_len;
  12542         } else if (pc->dev_name == dev_name_84753) {
  12543             fw_ptr = phy84753_ucode_bin;
  12544             fw_length = phy84753_ucode_bin_len;
  12545         } else if (pc->dev_name == dev_name_84754) {
  12546             fw_ptr = phy84754_ucode_bin;
  12547             fw_length = phy84754_ucode_bin_len;
  12548         } else if (pc->dev_name == dev_name_84064) {
  12549             fw_ptr = phy84064_ucode_bin;
  12550             fw_length = phy84064_ucode_bin_len;
  12551         } else if (pc->dev_name == dev_name_84784) {
  12552             fw_ptr = phy84784_ucode_bin;
  12553             fw_length = phy84784_ucode_bin_len;
  12554         } else {
  12555             /* invalid device name */
  12556             LOG_WARN(BSL_LS_SOC_PHY,
  12557                      (BSL_META_U(unit,
  12558                                  "firmware_bcst,invalid device name %s: u=%d p=%d\n"),
  12559                                  pc->dev_name? pc->dev_name: "NULL", unit, port));
  12560             return SOC_E_NONE;
  12561         }
  12562 
  12563         /* wait for 2ms for M8051 start and 5ms to initialize the RAM */
  12564         sal_usleep(10000); /* Wait for 10ms */
  12565 
  12566         /* Write Starting Address, where the Code will reside in SRAM */
  12567         data16 = 0x8000;
  12568         SOC_IF_ERROR_RETURN
  12569             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
  12570 
  12571         /* make sure address word is read by the micro */
  12572         sal_udelay(10); /* Wait for 10us */
  12573 
  12574         /* Write SPI SRAM Count Size */
  12575         data16 = (fw_length)/2;
  12576         SOC_IF_ERROR_RETURN
  12577             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
  12578 
  12579         /* make sure read by the micro */
  12580         sal_udelay(10); /* Wait for 10us */
  12581 
  12582         /* Fill in the SRAM */
  12583         num_words = (fw_length - 1);
  12584         for (j = 0; j < num_words; j+=2) {
  12585             /* Make sure the word is read by the Micro */
  12586             sal_udelay(10);
  12587 
  12588             data16 = (fw_ptr[j] << 8) | fw_ptr[j+1];
  12589 
  12590             SOC_IF_ERROR_RETURN
  12591                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG,
  12592                      data16));
  12593         }
  12594         return SOC_E_NONE;
  12595     } else if (cmd == PHYCTRL_UCODE_BCST_END) {
  12596         LOG_INFO(BSL_LS_SOC_PHY,
  12597                  (BSL_META_U(unit,
  12598                              "PHY84740 BCST end: u=%d p=%d\n"), unit, port));
  12599 
  12600         /* make sure last code word is read by the micro */
  12601         sal_udelay(20);
  12602 
  12603         /* first disable bcst mode */
  12604         phy_id = pc->phy_id;
  12605         for (i = 0; i < num_lanes; i++) {
  12606             if (num_lanes > 1) {
  12607                 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */
  12608             }
  12609             SOC_IF_ERROR_RETURN
  12610                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0x0));
  12611 
  12612             /* Read Hand-Shake message (Done) from Micro */
  12613             SOC_IF_ERROR_RETURN
  12614                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_M8051_MSGOUT_REG, 
  12615                         &data16));
  12616 
  12617             /* Download done message */
  12618             LOG_INFO(BSL_LS_SOC_PHY,
  12619                      (BSL_META_U(unit,
  12620                                  "u=%d p=%d MDIO firmware download done message: 0x%x\n"),
  12621                                  unit, port,data16));
  12622 
  12623             /* Clear LASI status */
  12624             SOC_IF_ERROR_RETURN
  12625                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
  12626         }
  12627         /* restore the original phy_id */
  12628         pc->phy_id = phy_id;
  12629 
  12630 
  12631         /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */
  12632         sal_udelay(100); /* Wait for 100 usecs */
  12633 
  12634         phy_id = pc->phy_id;
  12635         for (i = 0; i < num_lanes; i++) {
  12636             if (num_lanes > 1) {
  12637                 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */
  12638             }
  12639             SOC_IF_ERROR_RETURN
  12640                 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_M8051_MSGOUT_REG,&data16));
  12641 
  12642             /* Need to check if checksum is correct */
  12643             SOC_IF_ERROR_RETURN
  12644                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16));
  12645 
  12646             if (data16 != 0x600D) {
  12647                 /* Bad CHECKSUM */
  12648                 LOG_CLI((BSL_META_U(unit,
  12649                                     "firmware_bcst downlad failure: port %d "
  12650                                     "Incorrect Checksum %x\n"), port,data16));
  12651             return SOC_E_FAIL;
  12652             }
  12653 
  12654             /* read Rev-ID */
  12655             SOC_IF_ERROR_RETURN
  12656                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16));
  12657             LOG_INFO(BSL_LS_SOC_PHY,
  12658                      (BSL_META_U(unit,
  12659                                  "u=%d p=%d MDIO Firmware download revID: 0x%x\n"),
  12660                                  unit, port,data16));
  12661         }
  12662         /* restore the original phy_id */
  12663         pc->phy_id = phy_id;
  12664 
  12665         return SOC_E_NONE;
  12666     } else {
  12667         LOG_WARN(BSL_LS_SOC_PHY,
  12668                  (BSL_META_U(unit,
  12669                              "u=%d p=%d firmware_bcst: invalid cmd 0x%x\n"),
  12670                              unit, port,cmd));
  12671     }
  12672 
  12673     return SOC_E_FAIL;
  12674 }
  12675 
  12676 /*
  12677  * Function:
  12678  *      phy_84741_firmware_set
  12679  * Purpose:
  12680  *      program the given firmware into the SPI-ROM 
  12681  * Parameters:
  12682  *      unit - StrataSwitch unit #.
  12683  *      port - StrataSwitch port #.
  12684  *      offset - offset to the data stream
  12685  *      array  - the given data
  12686  *      datalen- the data length  
  12687  * Returns:
  12688  *      SOC_E_NONE
  12689  */
  12690 
  12691 STATIC int
  12692 phy_84741_firmware_set(int unit, int port, int offset, uint8 *array,int datalen)
  12693 {
  12694     uint16     saved_phy_addr;
  12695     int        ix;
  12696     phy_ctrl_t *pc;
  12697     uint32 devid;
  12698     uint32 uCode_devid;
  12699 
  12700     /* overload this function a littl bit if array == NULL 
  12701      * special handling for init. uCode broadcast. Internal use only 
  12702      */
  12703     if (array == NULL) {
  12704         return _phy84741_init_ucode_bcst(unit,port,offset);
  12705     }
  12706 
  12707     pc = EXT_PHY_SW_STATE(unit, port);
  12708 
  12709     SOC_IF_ERROR_RETURN(
  12710         _phy_84741_config_devid(pc->unit,pc->port, pc,  &devid));
  12711 
  12712     /* first validate the firmware is for the configured device
  12713      * 84740 has 1.5V from TXDRV pin, 84754 is internally wired at 1.0V.
  12714      * If the 84754 firmware which programs chip for 1.0V is loaded
  12715      * to the 84740, then it may damage the device and module.
  12716      * 
  12717      *  Chip ID is at addresses 0x7FF9, 0x7FFA, 0x7FFB.e.g. 
  12718      *  for 84740, [0x7FF9] = 0x08, [0x7FFA] = 0x47, [0x7FFB] = 0x40. 
  12719      *  Version number is at 0x7FFC-0x7FFD
  12720      */
  12721 
  12722     /* length should be at least 0xFFFE */
  12723     if (datalen < PHY84740_UCODE_DEVID_ADDR+3) {
  12724         LOG_WARN(BSL_LS_SOC_PHY,
  12725                  (BSL_META_U(unit,
  12726                              "firmware_set, wrong firmware len=0x%x : u=%d p=%d\n"),
  12727                              datalen, unit, port));
  12728         return SOC_E_PARAM;
  12729     }
  12730 
  12731     /* check the firmware devid matches the configured devid */
  12732     ix = PHY84740_UCODE_DEVID_ADDR;
  12733     uCode_devid = (array[ix] << 16) | (array[ix+1] << 8) |
  12734                   array[ix+2];
  12735 
  12736     if (uCode_devid != devid) {
  12737         LOG_WARN(BSL_LS_SOC_PHY,
  12738                  (BSL_META_U(unit,
  12739                              "firmware_set,u=%d p=%d:  Firmware device "
  12740                              "type(0x%x) does not match configured device type(0x%x)\n"),
  12741                   unit, port,uCode_devid,devid));
  12742         return SOC_E_PARAM;
  12743     }
  12744 
  12745     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  12746         /* switch to quad-mode */
  12747         SOC_IF_ERROR_RETURN(
  12748             _phy_84741_single_to_quad_mode(unit,port,NULL));
  12749     }
  12750     saved_phy_addr = pc->phy_id;
  12751 
  12752     LOG_INFO(BSL_LS_SOC_PHY,
  12753              (BSL_META_U(unit,
  12754                          "firmware_set init,quad port : u=%d p=%d\n"),
  12755                          unit, port));
  12756     /* configure all four lanes to bcst mode */
  12757     for (ix = 0; ix < 4; ix++) {
  12758         pc->phy_id = (saved_phy_addr & (~0x3)) + ix;
  12759         SOC_IF_ERROR_RETURN
  12760             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_BCST_REG,0xffff));
  12761     }
  12762     pc->phy_id = saved_phy_addr;
  12763 
  12764     /* place all uC in reset */
  12765     SOC_IF_ERROR_RETURN
  12766         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0x018f));
  12767 
  12768     /* disable all port's SPI */
  12769     SOC_IF_ERROR_RETURN
  12770         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x000f));
  12771   
  12772     SOC_IF_ERROR_RETURN
  12773         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x000c));
  12774 
  12775     /* Set bit 0 (spa enable) in C848 for master channel ? */
  12776     SOC_IF_ERROR_RETURN
  12777         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0x2000,0x2000));
  12778 
  12779     /* disable the bcst mode for all channels */
  12780     SOC_IF_ERROR_RETURN
  12781         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_BCST_REG,0xfffe));
  12782 
  12783     SOC_IF_ERROR_RETURN
  12784         (_phy_84741_firmware_to_rom(unit,port,offset,array,datalen));
  12785 
  12786     /* switch back to single mode */
  12787     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  12788         /* switch to quad-mode */
  12789         SOC_IF_ERROR_RETURN(
  12790             _phy_84741_quad_to_single_mode(unit,port));
  12791     }
  12792     return SOC_E_NONE;
  12793 }
  12794 STATIC int
  12795 _phy_84741_firmware_to_rom(int unit, int port, int offset, uint8 *array,int datalen)
  12796 {
  12797     uint16     rd_data;
  12798     uint16     wr_data;
  12799     int        j;
  12800     int        i = 0;
  12801     int        count;
  12802     uint8      spi_values[WR_BLOCK_SIZE];
  12803     uint16     data16;
  12804     soc_timeout_t to;
  12805     phy_ctrl_t *pc;
  12806 
  12807     pc = EXT_PHY_SW_STATE(unit, port);
  12808 
  12809     /*
  12810      * Enable SPI for Port0
  12811      */    
  12812     SOC_IF_ERROR_RETURN
  12813         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x0000));
  12814     SOC_IF_ERROR_RETURN
  12815         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x0000));
  12816     /*
  12817      * Remove M8051 resets for port 0.
  12818      * and wait for Micro to complete Init.
  12819      */
  12820     /* clear bits 3:0 */
  12821     SOC_IF_ERROR_RETURN
  12822         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0,0xf));
  12823     sal_usleep(10000);
  12824 
  12825     /* set bit(request) in 0xc848 for the required channel, remove done bit */
  12826     SOC_IF_ERROR_RETURN
  12827         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0,0x2000));
  12828 
  12829     /* enable SPI port enable */
  12830     SOC_IF_ERROR_RETURN
  12831             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0xc004,0xc004));
  12832 
  12833     /*
  12834      * Read LASI Status registers To clear initial Failure status.
  12835      */
  12836     SOC_IF_ERROR_RETURN
  12837         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data));
  12838     SOC_IF_ERROR_RETURN
  12839         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9004, &rd_data));
  12840     SOC_IF_ERROR_RETURN
  12841         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9005, &rd_data));
  12842 
  12843     /*
  12844      * Enable the LASI For Message out. 
  12845      */
  12846     SOC_IF_ERROR_RETURN
  12847         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9000, 0x0004));
  12848     /*
  12849      * 0x9002, bit 2 Is Rx Alarm enabled For LASI. 
  12850      */
  12851     SOC_IF_ERROR_RETURN
  12852         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9002, 0x0004));
  12853     /*
  12854      * Read Any Residual Message out register.
  12855      */
  12856     SOC_IF_ERROR_RETURN
  12857         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data));
  12858     /*
  12859      * Clear LASI Message Out Status. 
  12860      */
  12861     SOC_IF_ERROR_RETURN
  12862         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data));
  12863 
  12864     /* set SPI-ROM write enable */
  12865     SOC_IF_ERROR_RETURN(phy_84741_rom_write_enable_set(unit, port, 1));
  12866 
  12867     LOG_INFO(BSL_LS_SOC_PHY,
  12868              (BSL_META_U(unit,
  12869                          "init0: u=%d p=%d\n"),
  12870                          unit, port));
  12871 
  12872     for (j = 0; j < datalen; j += WR_BLOCK_SIZE) {
  12873         /*
  12874          * Setup SPI Controller. 
  12875          */
  12876         count = 2;
  12877         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12878         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12879 
  12880         /* Write SPI Control -2 Register Address.*/
  12881         wr_data = SPI_CTRL_2_L;
  12882         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12883 
  12884         /* Write SPI Control -2 Register Word-1. */
  12885         wr_data = 0x8200;
  12886         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12887 
  12888         /* Write SPI Control -2 Register Word-2. */
  12889         wr_data = 0x0100;
  12890         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12891 
  12892         /* Fill-up SPI Transmit Fifo.
  12893          * Write SPI Control Register Write Command.
  12894          */
  12895         count = 4 + (WR_BLOCK_SIZE / 2);
  12896         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12897         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12898 
  12899         /* Write Tx Fifo Register Address. */
  12900         wr_data = SPI_TXFIFO;
  12901         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12902 
  12903         /* Write SPI Tx Fifo Control Word-1. */
  12904         wr_data = ((1 * 0x0100) | MSGTYPE_HWR);
  12905         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12906 
  12907         /* Write SPI Tx Fifo Control Word-2. */
  12908         wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE);
  12909         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12910 
  12911         /* Write SPI Tx Fifo Control Word-3. */
  12912         wr_data = ((WR_OPCODE * 0x0100) | (0x3 + WR_BLOCK_SIZE));
  12913         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12914 
  12915         /* Write SPI Tx Fifo Control Word-4. */
  12916         wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100));
  12917         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12918 
  12919         LOG_INFO(BSL_LS_SOC_PHY,
  12920                  (BSL_META_U(unit,
  12921                              "loop: u=%d p=%d,inxj: %d,inxi:%d\n"),
  12922                              unit, port,j,i));
  12923 
  12924         if (datalen < (j + WR_BLOCK_SIZE)) {   /* last block */ 
  12925             sal_memset(spi_values,0,WR_BLOCK_SIZE);
  12926             sal_memcpy(spi_values,&array[j],datalen - j);
  12927 
  12928             for (i = 0; i < WR_BLOCK_SIZE; i += 2) {
  12929                 /* Write SPI Tx Fifo Data Word-4. */
  12930                 wr_data = ((spi_values[i+1] * 0x0100) | spi_values[i]);
  12931                 SOC_IF_ERROR_RETURN(write_message(unit, pc,wr_data, &rd_data));
  12932             }           
  12933         } else {        
  12934             for (i = 0; i < WR_BLOCK_SIZE; i += 2) {
  12935                 /* Write SPI Tx Fifo Data Word-4. */
  12936                 wr_data = ((array[j+i+1] * 0x0100) | array[j+i]);
  12937                 SOC_IF_ERROR_RETURN(write_message(unit, pc,wr_data, &rd_data));
  12938             }
  12939         }
  12940 
  12941         /* 
  12942          * Set-up SPI Controller To Transmit.
  12943          * Write SPI Control Register Write Command.
  12944          */
  12945         count = 2;
  12946         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12947         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12948 
  12949         wr_data = SPI_CTRL_1_L;
  12950         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12951 
  12952         /* Write SPI Control -1 Register Word-1. */
  12953         wr_data = 0x0501;
  12954         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12955 
  12956         /* Write SPI Control -1 Register Word-2. */
  12957         wr_data = 0x0003;
  12958         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12959 
  12960         /* Wait For 64 bytes To be written.   */
  12961         SOC_IF_ERROR_RETURN(phy_84741_rom_wait(unit,port));
  12962 
  12963     } /* SPI_WRITE */
  12964 
  12965     /* clear SPI-ROM write enable */
  12966     SOC_IF_ERROR_RETURN(phy_84741_rom_write_enable_set(unit, port, 0));
  12967 
  12968     /* Disable SPI EEPROM. */
  12969     count = 2;
  12970     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12971     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12972 
  12973     /* Write SPI Control -2 Register Address. */
  12974     wr_data = SPI_CTRL_2_L;
  12975     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12976 
  12977     /* Write SPI Control -2 Register Word-1. */
  12978     wr_data = 0x8200;
  12979     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12980 
  12981     /* Write SPI Control -2 Register Word-2. */
  12982     wr_data = 0x0100;
  12983     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12984 
  12985 
  12986     /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */
  12987     count = 2;
  12988     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  12989     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12990 
  12991     /* Write Tx Fifo Register Address. */
  12992     wr_data = SPI_TXFIFO;
  12993     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12994 
  12995     /* Write SPI Tx Fifo Control Word-1. */
  12996     wr_data = ((0x1*0x0100) | MSGTYPE_HWR);
  12997     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  12998 
  12999     /* Write SPI Tx Fifo Control Word-2. */
  13000     wr_data = WRDI_OPCODE;
  13001     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  13002 
  13003     /* Write SPI Control Register Write Command. */
  13004     count = 2;
  13005     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
  13006     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  13007 
  13008     /* Write SPI Control -1 Register Address. */
  13009     wr_data = SPI_CTRL_1_L;
  13010     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  13011 
  13012     /* Write SPI Control -1 Register Word-1. */
  13013     wr_data = 0x0101;
  13014     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  13015 
  13016     /* Write SPI Control -1 Register Word-2. */
  13017     wr_data = 0x0003;
  13018     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  13019 
  13020     /* Wait For WRDI Command To be written */
  13021     rd_data = 0;
  13022     soc_timeout_init(&to, WR_TIMEOUT, 0);
  13023     do {
  13024         /* Write SPI Control Register Read Command. */
  13025         count = 1;
  13026         wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
  13027         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  13028         wr_data = SPI_CTRL_1_L;
  13029         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
  13030 
  13031         /* extra reads to clear the status */
  13032         SOC_IF_ERROR_RETURN
  13033             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
  13034         SOC_IF_ERROR_RETURN
  13035             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
  13036 
  13037         if (rd_data & 0x0100) {
  13038             break;
  13039         }
  13040     } while (!soc_timeout_check(&to));
  13041 
  13042     if (!(rd_data & 0x0100)) {
  13043         LOG_ERROR(BSL_LS_SOC_PHY,
  13044                   (BSL_META_U(unit,
  13045                               "phy_84741_rom_program: u = %d p = %d "
  13046                               "WRDI command timeout\n"), unit, port));
  13047         return SOC_E_TIMEOUT;
  13048     }
  13049 
  13050     LOG_INFO(BSL_LS_SOC_PHY,
  13051              (BSL_META_U(unit,
  13052                          "phy_84741_rom_program: u=%d p=%d done\n"), unit, port));
  13053 
  13054     return SOC_E_NONE;
  13055 }
  13056 
  13057 static int
  13058 write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, uint16 *rddata)
  13059 {
  13060 
  13061     uint16     tmp_data = 0;
  13062     soc_timeout_t to;
  13063 
  13064     SOC_IF_ERROR_RETURN
  13065         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wrdata));
  13066 
  13067     soc_timeout_init(&to, WR_TIMEOUT, 0);
  13068     do {
  13069         SOC_IF_ERROR_RETURN
  13070             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9005, &tmp_data));
  13071         if (tmp_data & 0x4)
  13072             break;
  13073     } while (!soc_timeout_check(&to));
  13074     if (!(tmp_data & 0x4)) {
  13075         LOG_ERROR(BSL_LS_SOC_PHY,
  13076                   (BSL_META_U(unit,
  13077                               "write_message failed: wrdata %04x\n"), wrdata));
  13078         return SOC_E_FAIL;
  13079     }
  13080 
  13081     SOC_IF_ERROR_RETURN
  13082         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &tmp_data));
  13083     *rddata = tmp_data;
  13084     SOC_IF_ERROR_RETURN
  13085         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &tmp_data));
  13086 
  13087     return SOC_E_NONE;
  13088 }
  13089 
  13090 /*
  13091  * Function:
  13092  *      phy_84741_probe
  13093  * Purpose:
  13094  *      Complement the generic phy probe routine to identify this phy when its
  13095  *      phy id0 and id1 is same as some other phy's.
  13096  * Parameters:
  13097  *      unit - StrataSwitch unit #.
  13098  *      pc   - phy ctrl descriptor.
  13099  * Returns:
  13100  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
  13101  */
  13102 STATIC int
  13103 phy_84741_probe(int unit, phy_ctrl_t *pc)
  13104 {
  13105     uint32 devid;
  13106 
  13107     SOC_IF_ERROR_RETURN(
  13108         _phy_84741_config_devid(pc->unit,pc->port, pc,  &devid));
  13109 
  13110     if (devid == PHY84740_ID_84740) {
  13111         pc->dev_name = dev_name_84740;
  13112     } else if (devid == PHY84740_ID_84752) {
  13113         pc->dev_name = dev_name_84752;
  13114     } else if (devid == PHY84740_ID_84753) {
  13115         pc->dev_name = dev_name_84753;
  13116     } else if (devid == PHY84740_ID_84754) {
  13117         pc->dev_name = dev_name_84754;
  13118     } else if (devid == PHY84740_ID_84064) {
  13119         pc->dev_name = dev_name_84064;
  13120     } else if (PHY84740_IS_QUADRA(devid)) {
  13121         /*pc->dev_name = already set;*/
  13122     } else if (devid == PHY84740_ID_84741) {
  13123         pc->dev_name = dev_name_84741;
  13124     } else if (devid == PHY84740_ID_84744) {
  13125         pc->dev_name = dev_name_84744;
  13126     } else if (pc->size == -1) {
  13127         pc->size = 0;
  13128         return SOC_E_NOT_FOUND;
  13129     } else {  /* not found */
  13130         LOG_WARN(BSL_LS_SOC_PHY,
  13131                  (BSL_META_U(unit,
  13132                              "port %d: BCM84xxx type PHY device detected, please use "
  13133                              "phy_84<xxx> config variable to select the specific type\n"),
  13134                   pc->port));
  13135         return SOC_E_NOT_FOUND;
  13136     }
  13137     pc->size = sizeof(PHY84740_DEV_DESC_t);
  13138     return SOC_E_NONE;
  13139 }
  13140 
  13141 STATIC int
  13142 _phy_84741_bsc_rw(int unit, soc_port_t port, int dev_addr, int opr,
  13143                     int addr, int count, void *data_array,uint32 ram_start)
  13144 {
  13145     phy_ctrl_t  *pc;
  13146     soc_timeout_t  to;
  13147     uint16 data16;
  13148     int i;
  13149 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
  13150     sal_usecs_t start;
  13151     sal_usecs_t end;
  13152 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */
  13153     int access_type;
  13154     int data_type;
  13155 
  13156     LOG_INFO(BSL_LS_SOC_PHY,
  13157              (BSL_META_U(unit,
  13158                          "phy_84741_bsc_read: u=%d p=%d addr=%04x\n"),
  13159                          unit, port, addr));
  13160 
  13161     if (!data_array) {
  13162         return SOC_E_PARAM;
  13163     }
  13164 
  13165     if (count > PHY84740_BSC_XFER_MAX) {
  13166         return SOC_E_PARAM;
  13167     }
  13168 
  13169     pc = EXT_PHY_SW_STATE(unit, port);
  13170     data_type = PHY84740_I2C_DATA_TYPE(opr);
  13171     access_type = PHY84740_I2C_ACCESS_TYPE(opr);
  13172 
  13173     if (access_type == PHY84740_I2CDEV_WRITE) {
  13174         for (i = 0; i < count; i++) {
  13175             if (data_type == PHY84740_I2C_8BIT) {
  13176                 SOC_IF_ERROR_RETURN
  13177                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, ram_start + i,
  13178                           ((uint8 *)data_array)[i]));
  13179             } else {  /* 16 bit */
  13180                 SOC_IF_ERROR_RETURN
  13181                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, ram_start + i,
  13182                           ((uint16 *)data_array)[i]));
  13183             }
  13184         }
  13185     }
  13186 
  13187     data16 = ram_start;
  13188     SOC_IF_ERROR_RETURN
  13189         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8004, data16));
  13190     SOC_IF_ERROR_RETURN
  13191         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8003, addr));
  13192     SOC_IF_ERROR_RETURN
  13193         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8002, count));
  13194 
  13195     data16 = 1;
  13196     data16 |= (dev_addr<<9);
  13197     if (access_type == PHY84740_I2CDEV_WRITE) {
  13198         data16 |= PHY84740_WR_FREQ_400KHZ;
  13199     }
  13200 
  13201     SOC_IF_ERROR_RETURN
  13202         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc,0x8005,data16));
  13203 
  13204     if (access_type == PHY84740_I2CDEV_WRITE) {
  13205         data16 =  0x8000 | PHY84740_BSC_WRITE_OP;
  13206     } else {
  13207         data16 =  0x8000 | PHY84740_BSC_READ_OP;
  13208     }
  13209 
  13210     if (data_type == PHY84740_I2C_16BIT) {
  13211         data16 |= (1 << 12);
  13212     }
  13213 
  13214     /* for single port mode, there should be only one I2C interface active
  13215      * from lane0. The 0x800x register block is bcst type registers. If writing
  13216      * to 0x8000 directly, it will enable all four I2C masters. Use indirect access
  13217      * to enable only the lane 0.
  13218      */
  13219 
  13220     if (PHY84740_SINGLE_PORT_MODE(pc)) {
  13221 
  13222         /* point to lane 0 */
  13223         SOC_IF_ERROR_RETURN
  13224             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
  13225 
  13226         /* indirect access: 0x8000=data16 */ 
  13227         SOC_IF_ERROR_RETURN
  13228             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0c, 0x8000));
  13229         SOC_IF_ERROR_RETURN
  13230             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0d, data16));
  13231 
  13232         /* issue the indirect access command */  
  13233         SOC_IF_ERROR_RETURN
  13234             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd13, 0x3));
  13235 
  13236         soc_timeout_init(&to, 1000000, 0);
  13237         while (!soc_timeout_check(&to)) {
  13238             SOC_IF_ERROR_RETURN
  13239                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd13, &data16));
  13240             if (!data16) {
  13241                 break;
  13242             }
  13243         }
  13244         if (data16) {
  13245             LOG_WARN(BSL_LS_SOC_PHY,
  13246                      (BSL_META_U(unit,
  13247                                  "port %d: Fail register 0xcd13 status 0x%x\n"),
  13248                                  port,data16));
  13249             return SOC_E_TIMEOUT; 
  13250         }
  13251     } else { 
  13252         SOC_IF_ERROR_RETURN
  13253             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8000, data16));
  13254     }
  13255 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
  13256     start = sal_time_usecs();
  13257 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */
  13258     soc_timeout_init(&to, 1000000, 0);
  13259     while (!soc_timeout_check(&to)) {
  13260         SOC_IF_ERROR_RETURN
  13261             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8000, &data16));
  13262         if (((data16 & PHY84740_2W_STAT) == PHY84740_2W_STAT_COMPLETE)) {
  13263             break;
  13264         }
  13265     }
  13266 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
  13267     end = sal_time_usecs();
  13268 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */
  13269     /* need some delays */
  13270     sal_usleep(10000);
  13271 
  13272 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
  13273     LOG_INFO(BSL_LS_SOC_PHY,
  13274              (BSL_META_U(unit,
  13275                          "BSC command status %d time=%d\n"),
  13276                          (data16 & PHY84740_2W_STAT), SAL_USECS_SUB(end, start)));
  13277 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */
  13278 
  13279     if (access_type == PHY84740_I2CDEV_WRITE) {
  13280         return SOC_E_NONE;
  13281     }
  13282 
  13283     if ((data16 & PHY84740_2W_STAT) == PHY84740_2W_STAT_COMPLETE) {
  13284         for (i = 0; i < count; i++) {
  13285             SOC_IF_ERROR_RETURN
  13286                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, (ram_start+i), &data16));
  13287             if (data_type == PHY84740_I2C_16BIT) {
  13288                 ((uint16 *)data_array)[i] = data16;
  13289                 LOG_INFO(BSL_LS_SOC_PHY,
  13290                          (BSL_META_U(unit,
  13291                                      "%04x "), data16));
  13292             } else {
  13293                 ((uint8 *)data_array)[i] = (uint8)data16;
  13294                 LOG_INFO(BSL_LS_SOC_PHY,
  13295                          (BSL_META_U(unit,
  13296                                      "%02x "), data16));
  13297             }
  13298         }
  13299     }
  13300     return SOC_E_NONE;
  13301 }
  13302 
  13303 /*
  13304  * Read a slave device such as NVRAM/EEPROM connected to the 84740's I2C
  13305  * interface. This function will be mainly used for diagnostic or workaround
  13306  * purpose.
  13307  * Note:
  13308  * The size of read_array buffer must be greater than or equal to the
  13309  * parameter nbytes.
  13310  * usage example:
  13311  *   Retrieve the first 100 byte data of the non-volatile storage device with
  13312  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
  13313  *   port 2.
  13314  *   uint8 data8[100];
  13315  *   phy_84741_i2cdev_read(0,2,0x50,0,100,data8);
  13316  */
  13317 int
  13318 phy_84741_i2cdev_read(int unit,
  13319                      soc_port_t port,
  13320                      int dev_addr,  /* 7 bit I2C bus device address */
  13321                      int offset,    /* starting data address to read */
  13322                      int nbytes,    /* number of bytes to read */
  13323                      uint8 *read_array)   /* buffer to hold retrieved data */
  13324 {
  13325     return _phy_84741_bsc_rw(unit, port, dev_addr,PHY84740_I2CDEV_READ,
  13326              offset, nbytes, (void *)read_array,PHY84740_READ_START_ADDR);
  13327 
  13328 }
  13329 
  13330 /*
  13331  * Write to a slave device such as NVRAM/EEPROM connected to the 84740's I2C
  13332  * interface. This function will be mainly used for diagnostic or workaround
  13333  * purpose.
  13334  * Note:
  13335  * The size of write_array buffer should be equal to the parameter nbytes.
  13336  * The EEPROM may limit the maximun write size to 16 bytes
  13337  * usage example:
  13338  *   Write to first 100 byte space of the non-volatile storage device with
  13339  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
  13340  *   port 2, with written data specified in array data8.
  13341  *   uint8 data8[100];
  13342  *   *** initialize the data8 array with written data ***
  13343  *
  13344  *   phy_84741_i2cdev_write(0,2,0x50,0,100,data8);
  13345  */
  13346 
  13347 int
  13348 phy_84741_i2cdev_write(int unit,
  13349                      soc_port_t port,
  13350                      int dev_addr,  /* I2C bus device address */
  13351                      int offset,    /* starting data address to write to */
  13352                      int nbytes,    /* number of bytes to write */
  13353                      uint8 *write_array)   /* buffer to hold written data */
  13354 {
  13355     int j;
  13356     int rv = SOC_E_NONE;
  13357 
  13358     for (j = 0; j < (nbytes/PHY84740_BSC_WR_MAX); j++) {
  13359         rv = _phy_84741_bsc_rw(unit, port, dev_addr,PHY84740_I2CDEV_WRITE,
  13360                     offset + j * PHY84740_BSC_WR_MAX, PHY84740_BSC_WR_MAX,
  13361                     (void *)(write_array + j * PHY84740_BSC_WR_MAX),
  13362                     PHY84740_WRITE_START_ADDR);
  13363         if (rv != SOC_E_NONE) {
  13364             return rv;
  13365         }
  13366         sal_usleep(20000);
  13367     }
  13368     if (nbytes%PHY84740_BSC_WR_MAX) {
  13369         rv = _phy_84741_bsc_rw(unit, port, dev_addr,PHY84740_I2CDEV_WRITE,
  13370                 offset + j * PHY84740_BSC_WR_MAX, nbytes%PHY84740_BSC_WR_MAX,
  13371                 (void *)(write_array + j * PHY84740_BSC_WR_MAX),
  13372                 PHY84740_WRITE_START_ADDR);
  13373     }
  13374     return rv;
  13375 }
  13376 
  13377 /*
  13378  *   Callout interface to phy_84741_i2cdev_read(); 
  13379  *   TBD: Extend to handle max_size > PHY84740_BSC_XFER_MAX. 
  13380  */
  13381 
  13382 STATIC int
  13383 phy_84741_multi_get(int unit, soc_port_t port, uint32 flags,
  13384                  uint32 dev_addr, uint32 offset, int max_size, uint8 *data, int *actual_size)
  13385 {
  13386     int rv;
  13387 
  13388     rv = phy_84741_i2cdev_read(unit, port,(int)dev_addr,(int)offset, max_size, data);
  13389 
  13390     if (SOC_FAILURE(rv)) {
  13391         *actual_size = 0;
  13392         return SOC_E_FAIL;
  13393     }
  13394 
  13395     *actual_size = max_size;
  13396     return SOC_E_NONE;
  13397 }
  13398 
  13399 /*
  13400  * Function:
  13401  *      phy_84741_reg_read
  13402  * Purpose:
  13403  *      Routine to read PHY register
  13404  * Parameters:
  13405  *      uint         - BCM unit number
  13406  *      port         - port number
  13407  *      flags        - Flags which specify the register type
  13408  *      phy_reg_addr - Encoded register address
  13409  *      phy_data     - (OUT) Value read from PHY register
  13410  * Note:
  13411  *      This register read function is not thread safe. Higher level
  13412  * function that calls this function must obtain a per port lock
  13413  * to avoid overriding register page mapping between threads.
  13414  */
  13415 STATIC int
  13416 phy_84741_reg_read(int unit, soc_port_t port, uint32 flags,
  13417                   uint32 phy_reg_addr, uint32 *phy_data)
  13418 {
  13419     uint16               data16;
  13420     uint16               regdata;
  13421     phy_ctrl_t          *pc;      /* PHY software state */
  13422     int rv = SOC_E_NONE;
  13423     int rd_cnt;
  13424 
  13425     pc = EXT_PHY_SW_STATE(unit, port);
  13426 
  13427     rd_cnt = 1;
  13428 
  13429     if (flags & SOC_PHY_I2C_DATA8) {
  13430 
  13431         SOC_IF_ERROR_RETURN
  13432             (phy_84741_i2cdev_read(unit, port,
  13433                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
  13434                         SOC_PHY_I2C_REGAD(phy_reg_addr),
  13435                         rd_cnt,
  13436                         (uint8 *)&data16));
  13437         *phy_data = *((uint8 *)&data16);
  13438 
  13439     } else if (flags & SOC_PHY_I2C_DATA16) {
  13440         /* This operation is generally targeted to access 16-bit device,
  13441          * such as PHY IC inside the SFP.  However there is no 16-bit
  13442          * scratch register space on the device.  Use 1.800e
  13443          * for this operation.
  13444          */
  13445         SOC_IF_ERROR_RETURN
  13446             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM,
  13447                    &regdata));
  13448 
  13449         rv = _phy_84741_bsc_rw(unit, port,
  13450                SOC_PHY_I2C_DEVAD(phy_reg_addr),
  13451                PHY84740_I2C_OP_TYPE(PHY84740_I2CDEV_READ,PHY84740_I2C_16BIT),
  13452                SOC_PHY_I2C_REGAD(phy_reg_addr),1,
  13453                (void *)&data16,PHY84740_I2C_TEMP_RAM);
  13454 
  13455         *phy_data = data16;
  13456 
  13457         /* restore the ram register value */
  13458         SOC_IF_ERROR_RETURN
  13459             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM,
  13460                  regdata));
  13461     } else {
  13462         SOC_IF_ERROR_RETURN
  13463             (READ_PHY_REG(unit, pc, phy_reg_addr, &data16));
  13464         *phy_data = data16;
  13465     }
  13466 
  13467     return rv;
  13468 }
  13469 
  13470 /*
  13471  * Function:
  13472  *      phy_84741_reg_write
  13473  * Purpose:
  13474  *      Routine to write PHY register
  13475  * Parameters:
  13476  *      uint         - BCM unit number
  13477  *      port         - port number
  13478  *      flags        - Flags which specify the register type
  13479  *      phy_reg_addr - Encoded register address
  13480  *      phy_data     - Value write to PHY register
  13481  * Note:
  13482  *      This register read function is not thread safe. Higher level
  13483  * function that calls this function must obtain a per port lock
  13484  * to avoid overriding register page mapping between threads.
  13485  */
  13486 STATIC int
  13487 phy_84741_reg_write(int unit, soc_port_t port, uint32 flags,
  13488                    uint32 phy_reg_addr, uint32 phy_data)
  13489 {
  13490     uint8  data8[4];
  13491     uint16 data16[2];
  13492     uint16 regdata[2];
  13493     phy_ctrl_t          *pc;      /* PHY software state */
  13494     int rv = SOC_E_NONE;
  13495     int wr_cnt;
  13496 
  13497 #if defined (BCM_WARM_BOOT_SUPPORT)  /*  */
  13498     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
  13499         return SOC_E_NONE;
  13500     }
  13501 #endif /* BCM_WARM_BOOT_SUPPORT */
  13502 
  13503     pc = EXT_PHY_SW_STATE(unit, port);
  13504 
  13505     wr_cnt = 1;
  13506 
  13507     if (flags & SOC_PHY_I2C_DATA8) {
  13508         data8[0] = (uint8)phy_data;
  13509         SOC_IF_ERROR_RETURN
  13510             (phy_84741_i2cdev_write(unit, port,
  13511                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
  13512                         SOC_PHY_I2C_REGAD(phy_reg_addr),
  13513                         wr_cnt,
  13514                         data8));
  13515     } else if (flags & SOC_PHY_I2C_DATA16) {
  13516         /* This operation is generally targeted to access 16-bit device,
  13517          * such as PHY IC inside the SFP.  However there is no 16-bit
  13518          * scratch register space on the device.  Use 1.800e
  13519          * for this operation.
  13520          */
  13521         /* save the temp ram register */
  13522         SOC_IF_ERROR_RETURN
  13523             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM,
  13524                  &regdata[0]));
  13525         data16[0] = phy_data;
  13526         rv = _phy_84741_bsc_rw(unit, port,
  13527               SOC_PHY_I2C_DEVAD(phy_reg_addr),
  13528               PHY84740_I2C_OP_TYPE(PHY84740_I2CDEV_WRITE,PHY84740_I2C_16BIT),
  13529               SOC_PHY_I2C_REGAD(phy_reg_addr),wr_cnt,
  13530               (void *)data16,PHY84740_I2C_TEMP_RAM);
  13531 
  13532         /* restore the ram register value */
  13533         SOC_IF_ERROR_RETURN
  13534             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM,
  13535                   regdata[0]));
  13536     } else {
  13537         SOC_IF_ERROR_RETURN
  13538             (WRITE_PHY_REG(unit, pc, phy_reg_addr, (uint16)phy_data));
  13539     }
  13540 
  13541     return rv;
  13542 }
  13543 
  13544 /*
  13545  * Variable:
  13546  *    phy_84741_drv
  13547  * Purpose:
  13548  *    Phy Driver for 40G PHY.
  13549  */
  13550 
  13551 phy_driver_t phy_84741drv_xe = {
  13552     "84740 10-Gigabit PHY Driver",
  13553     phy_84741_init,        /* Init */
  13554     phy_null_reset,       /* Reset (dummy) */
  13555     phy_84741_link_get,    /* Link get   */
  13556     phy_84741_enable_set,  /* Enable set */
  13557     phy_null_enable_get,  /* Enable get */
  13558     phy_null_set,         /* Duplex set */
  13559     phy_null_one_get,     /* Duplex get */
  13560     phy_84741_speed_set,   /* Speed set  */
  13561     phy_84741_speed_get,   /* Speed get  */
  13562     phy_null_set,         /* Master set */
  13563     phy_null_zero_get,    /* Master get */
  13564     phy_84741_an_set,      /* ANA set */
  13565     phy_84741_an_get,      /* ANA get */
  13566     NULL,                 /* Local Advert set */
  13567     NULL,                 /* Local Advert get */
  13568     phy_null_mode_get,    /* Remote Advert get */
  13569     phy_84741_lb_set,      /* PHY loopback set */
  13570     phy_84741_lb_get,      /* PHY loopback set */
  13571     phy_84741_interface_set, /* IO Interface set */
  13572     phy_84741_interface_get, /* IO Interface get */
  13573     NULL,   /* PHY abilities mask */
  13574     NULL,
  13575     NULL,
  13576     phy_null_mdix_set,
  13577     phy_null_mdix_get,
  13578     phy_null_mdix_status_get,
  13579     NULL,
  13580     NULL,
  13581     phy_null_medium_get,
  13582     NULL,                    /* phy_cable_diag  */
  13583     NULL,                    /* phy_link_change */
  13584     phy_84741_control_set,    /* phy_control_set */
  13585     phy_84741_control_get,    /* phy_control_get */
  13586     phy_84741_reg_read,       /* phy_reg_read */
  13587     phy_84741_reg_write,      /* phy_reg_write */
  13588     NULL,                    /* phy_reg_modify */
  13589     NULL,                    /* phy_notify */
  13590     phy_84741_probe,         /* pd_probe  */
  13591     phy_84741_ability_advert_set,  /* pd_ability_advert_set */
  13592     phy_84741_ability_advert_get,  /* pd_ability_advert_get */
  13593     phy_84741_ability_remote_get,  /* pd_ability_remote_get */
  13594     phy_84741_ability_local_get,   /* pd_ability_local_get  */
  13595     phy_84741_firmware_set,        /* pd_firmware_set */
  13596     NULL,                          /* pd_timesync_config_set */
  13597     NULL,                          /* pd_timesync_config_get */
  13598     NULL,                          /* pd_timesync_control_set */
  13599     NULL,                          /* pd_timesync_control_get */
  13600     phy_84741_diag_ctrl,           /* pd_diag_ctrl */
  13601     NULL,                          /* pd_lane_control_set */
  13602     NULL,                          /* pd_lane_control_get */
  13603     NULL,                          /* pd_lane_reg_read */
  13604     NULL,                          /* pd_lane_reg_write */
  13605     NULL,                          /* pd_oam_config_set */
  13606     NULL,                          /* pd_oam_config_get */
  13607     NULL,                          /* pd_oam_control_set */
  13608     NULL,                          /* pd_oam_control_get */
  13609     NULL,                          /* pd_timesync_enhanced_capture_get */
  13610     phy_84741_multi_get            /* pd_multi_get */
  13611 };
  13612 
  13613 #else /* INCLUDE_PHY_84756 */
  13614 int _phy_84741_not_empty;
  13615 #endif /* INCLUDE_PHY_84756 */
  13616 
  13617 
  13618 #else /* INCLUDE_PHY_84756 */
  13619 int _phy_84756_fcmap_not_empty;
  13620 #endif /* INCLUDE_PHY_84756 */
  13621 #endif /* INCLUDE_FCMAP */