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

phy84740.c (329682B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        phy84740.c
      8  * Purpose:    Phys Driver support for Broadcom 84740 40Gig
      9  *             transceiver :XLAUI system side and PPI Line interface.
     10  * Note:       
     11  */
     12 
     13 #include <sal/types.h>
     14 
     15 #include <soc/drv.h>
     16 #include <soc/debug.h>
     17 #include <soc/error.h>
     18 #include <soc/phyreg.h>
     19 
     20 #include <soc/phy.h>
     21 #include <soc/phy/phyctrl.h>
     22 #include <soc/phy/drv.h>
     23 #include <shared/bsl.h>
     24 #include "phydefs.h"            /* Must include before other phy related includes */
     25 
     26 #if defined(INCLUDE_PHY_84740)
     27 #include "phyconfig.h"          /* Must be the first phy include after phydefs.h */
     28 #include "phyident.h"
     29 #include "phyreg.h"
     30 #include "phynull.h"
     31 #include "phyxehg.h"
     32 #include "phy84740.h"
     33 /*
     34  * SPI-ROM Program related defs
     35  */
     36 #define SPI_CTRL_1_L        0xC000
     37 #define SPI_CTRL_1_H        0xC002
     38 #define SPI_CTRL_2_L        0xC400
     39 #define SPI_CTRL_2_H        0xC402
     40 #define SPI_TXFIFO          0xD000
     41 #define SPI_RXFIFO          0xD400
     42 #define WR_CPU_CTRL_REGS    0x11
     43 #define RD_CPU_CTRL_REGS    0xEE
     44 #define WR_CPU_CTRL_FIFO    0x66
     45 
     46 /*
     47  * SPI Controller Commands(Messages).
     48  */
     49 #define MSGTYPE_HWR          0x40
     50 #define MSGTYPE_HRD          0x80
     51 #define WRSR_OPCODE          0x01
     52 #define WR_OPCODE            0x02
     53 #define WRDI_OPCODE          0x04
     54 #define RDSR_OPCODE          0x05
     55 #define WREN_OPCODE          0x06
     56 #define WR_BLOCK_SIZE        0x40
     57 #define TOTAL_WR_BYTE        0x4000
     58 
     59 #define WR_TIMEOUT   1000000
     60 
     61 /* CL73 autoneg */
     62 #define AN_ADVERT_40GCR4 (1 << 9)
     63 #define AN_ADVERT_40GKR4 (1 << 8)
     64 #define AN_ADVERT_10GKR  (1 << 7)
     65 #define AN_ADVERT_1GKX   (1 << 5)
     66 
     67 /* PRBS */
     68 #define PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS         0x0135
     69 #define PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER            0x05dd
     70 #define PHY84740_UDRCD_PRBS20_CONTROL_REGISTER                      0xcd60
     71 #define PHY84740_FORTYG_PRBS_RX_TESTING_ERROR_COUNTER_LANE0         0x06a4
     72 
     73 #define PHY84740_40G_PRBS31             (1 << 7)
     74 #define PHY84740_40G_PRBS9              (1 << 6)
     75 
     76 #define PHY84740_40G_SYS_PRBS31             (0x6)
     77 #define PHY84740_40G_SYS_PRBS23             (0x5)
     78 #define PHY84740_40G_SYS_PRBS15             (0x4)
     79 #define PHY84740_40G_SYS_PRBS11             (0x3)
     80 #define PHY84740_40G_SYS_PRBS9              (0x2)
     81 #define PHY84740_40G_SYS_PRBS7              (0x1)
     82 #define PHY84740_40G_SYS_PRBS_POLY_MASK     (0x7007)
     83 #define PHY84740_40G_SYS_PRBS_MASK          (0x7)
     84 #define PHY84740_40G_SYS_PRBS_ENABLE        (0x0005)
     85 #define PHY84740_40G_SYS_PRBS_ENABLE_MASK   (0x0005)
     86 #define PHY84740_40G_SYS_PRBS_LOCK_VALUE    (0x8000)
     87 #define PHY84740_40G_SYS_PRBS_LOCK_MASK     (0xf000)
     88 #define PHY84740_40G_SYS_PRBS_ERR_MASK      (0x0fff)
     89 #define PHY84740_40G_SYS_REP_MODE_ENABLE    (0x6)
     90 #define PHY84740_RX_REPEATER_MASK        (1 << 1)
     91 #define PHY84740_TX_REPEATER_MASK        (1 << 2)
     92 #define PHY84740_TX_REPEATER_ENABLE      (1 << 2)
     93 
     94 
     95 #define PHY84740_40G_PRBS_TX_ENABLE     (1 << 3)
     96 #define PHY84740_40G_PRBS_RX_ENABLE     (1 << 0)
     97 #define PHY84740_40G_PRBS_ENABLE     (PHY84740_40G_PRBS_RX_ENABLE | \
     98         PHY84740_40G_PRBS_TX_ENABLE)
     99 
    100 #define PHY84740_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0            0x0140
    101 #define PHY84740_USER_PRBS_CONTROL_0_REGISTER                       0xCD14
    102 #define PHY84740_USER_PRBS_TX_INVERT   (1 << 4)
    103 #define PHY84740_USER_PRBS_RX_INVERT   (1 << 15)
    104 #define PHY84740_USER_PRBS_INVERT      (1 << 4 | 1 << 15)
    105 #define PHY84740_USER_PRBS_ENABLE      (1 << 7)
    106 #define PHY84740_USER_PRBS_TYPE_MASK   (0x7)
    107 
    108 #define PHY84740_USER_PRBS_STATUS_0_REGISTER                        0xCD15
    109 #define PHY84740_GENSIG_8071_REGISTER                               0xCD16
    110 #define PHY84740_RESET_CONTROL_REGISTER                             0xCD17
    111 
    112 /* Module auto detect status */
    113 #define PHY84740_MOD_AUTO_DETECT_STS_REG                            0xc82b
    114 #define PHY84740_MOD_AUTO_DETECT_STS_NOT_DONE                       (1 << 15)
    115 #define PHY84740_MOD_AUTO_DETECT_STS_SFP_EN                         (1 << 10)
    116 #define PHY84740_MOD_AUTO_DETECT_STS_I2C_FAIL                       (1 << 9)
    117 #define PHY84740_MOD_AUTO_DETECT_STS_NOT_RES                        (1 << 0)
    118 
    119 /* Optical config */
    120 #define PHY84740_PMAD_OPTICAL_CFG_MOD_PRESENCE                      (1 << 3)
    121 
    122 /* General purpose register */
    123 #define PHY84740_PMAD_GEN_PURPOSE_REG                               0xc710
    124 #define PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN                (1 << 2)
    125 
    126 /* Polarity config */
    127 #define POL_CONFIG_LANE_WIDTH     0x4
    128 #define POL_CONFIG_LANE_MASK(_ln)   (0xf << ((_ln) * POL_CONFIG_LANE_WIDTH))
    129 #define POL_CONFIG_ALL_LANES    1
    130 /*
    131  * When a port is being flexed between 40G->10G, 
    132  * the polarity config syntax can be in
    133  * 40G syntax for first lane, so there is a need to parse 
    134  * both 10G and 40G polarity config syntax in 10G.
    135  */
    136 #define PHY84740_LN(_pc)         ((_pc)->phy_id & 0x3)
    137 #define PHY84740_POL_MASK(_pc)   POL_CONFIG_LANE_MASK(PHY84740_LN(_pc))
    138 #define PHY84740_10G_POL_CFG_GET(_pc, _pol) \
    139 (((_pol) == POL_CONFIG_ALL_LANES) ||  \
    140 (((_pol) & PHY84740_POL_MASK(_pc)) ==  PHY84740_POL_MASK(_pc)))
    141 
    142 /* I2C related defines */
    143 #define PHY84740_BSC_XFER_MAX     0x1F9
    144 #define PHY84740_BSC_WR_MAX       16
    145 #define PHY84740_WRITE_START_ADDR 0x8007
    146 #define PHY84740_READ_START_ADDR  0x8007
    147 #define PHY84740_WR_FREQ_400KHZ   0x0100
    148 #define PHY84740_2W_STAT          0x000C
    149 #define PHY84740_2W_STAT_IDLE     0x0000
    150 #define PHY84740_2W_STAT_COMPLETE 0x0004
    151 #define PHY84740_2W_STAT_IN_PRG   0x0008
    152 #define PHY84740_2W_STAT_FAIL     0x000C
    153 #define PHY84740_BSC_WRITE_OP     0x22
    154 #define PHY84740_BSC_READ_OP      0x2
    155 #define PHY84740_I2CDEV_WRITE     0x1
    156 #define PHY84740_I2CDEV_READ      0x0
    157 #define PHY84740_I2C_8BIT         0
    158 #define PHY84740_I2C_16BIT        1
    159 #define PHY84740_I2C_TEMP_RAM     0xE
    160 #define PHY84740_I2C_OP_TYPE(access_type,data_type) \
    161         ((access_type) | ((data_type) << 8))
    162 #define PHY84740_I2C_ACCESS_TYPE(op_type) ((op_type) & 0xff)
    163 #define PHY84740_I2C_DATA_TYPE(op_type)   (((op_type) >> 8) & 0xff)
    164 
    165 /* preemphasis control */
    166 #define PHY84740_PREEMPH_CTRL_POST_TAP2_SHFT 16
    167 #define PHY84740_PREEMP_GET_POST_TAP2(_val)\
    168         (((_val) >> PHY84740_PREEMPH_CTRL_POST_TAP2_SHFT) & 0x7)
    169 #define PHY84740_PREEMPH_REG_POST_TAP2_MASK (0x7 << PHY84740_PREEMPH_REG_POST_TAP2_SHFT)
    170 #define PHY84740_PREEMPH_REG_POST_TAP2_SHFT  0
    171 #define PHY84740_PREEMPH_CTRL_FORCE_SHFT       15
    172 #define PHY84740_PREEMPH_GET_FORCE(_val)  \
    173         (((_val) >> PHY84740_PREEMPH_CTRL_FORCE_SHFT) & 1)
    174 #define PHY84740_PREEMPH_CTRL_POST_TAP_SHFT    10
    175 #define PHY84740_PREEMPH_GET_POST_TAP(_val) \
    176         (((_val) >> PHY84740_PREEMPH_CTRL_POST_TAP_SHFT) & 0x1f)
    177 #define PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT    0
    178 #define PHY84740_PREEMPH_GET_PRE_TAP(_val) \
    179         (((_val) >> PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT) & 0xf)
    180 #define PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT    4
    181 #define PHY84740_PREEMPH_GET_MAIN_TAP(_val) \
    182         (((_val) >> PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT) & 0x3f)
    183 #define PHY84740_PREEMPH_REG_FORCE_MASK     (1 << 8)
    184 #define PHY84740_PREEMPH_REG_POST_TAP_SHFT  4
    185 #define PHY84740_PREEMPH_REG_POST_TAP_MASK  (0xf << PHY84740_PREEMPH_REG_POST_TAP_SHFT)
    186 #define PHY84740_PREEMPH_REG_PRE_TAP_SHFT  0
    187 #define PHY84740_PREEMPH_REG_PRE_TAP_MASK  (0x7 << PHY84740_PREEMPH_REG_PRE_TAP_SHFT)
    188 #define PHY84740_PREEMPH_REG_MAIN_TAP_SHFT  11
    189 #define PHY84740_PREEMPH_REG_MAIN_TAP_MASK  (0x1f << PHY84740_PREEMPH_REG_MAIN_TAP_SHFT)
    190 #define PHY84740_PREEMPH_REG_TX_PWRDN_MASK  (0x1 << 10)
    191 
    192 /* Misc. */
    193 #define PHY84740_AN_SPEED_1G_MASK                 0x11
    194 #define PHY84740_AN_SPEED_10G_MASK                0x44
    195 #define PHY84740_UCODE_DEVID_ADDR              0x7FF9
    196 
    197 #define PHY84740_SINGLE_PORT_MODE(_pc)  \
    198 (SOC_INFO((_pc)->unit).port_num_lanes[(_pc)->port] >= 4)
    199 #define PHY84740_EDC_MODE_MASK          0xff
    200 #define PHY84740_ID_84740 0x84740
    201 #define PHY84740_ID_84064 0x84064
    202 #define PHY84740_ID_84754 0x84754
    203 #define PHY84740_ID_84753 0x84753
    204 #define PHY84740_ID_84752 0x84752
    205 
    206 /* Other variants */
    207 #define PHY84740_ID_84780 0x84780
    208 #define PHY84740_ID_84784 0x84784
    209 #define PHY84740_ID_84758 0x84758
    210 #define PHY84740_ID_84164 0x84164
    211 #define PHY84740_ID_84168 0x84168
    212 #define PHY84740_ID_84318 0x84318
    213 
    214 #define PHY84740_IS_QUADRA(devid)\
    215 ((devid) == PHY84740_ID_84780 ||\
    216  (devid) == PHY84740_ID_84784 ||\
    217  (devid) == PHY84740_ID_84758 ||\
    218  (devid) == PHY84740_ID_84164 ||\
    219  (devid) == PHY84740_ID_84168 ||\
    220  (devid) == PHY84740_ID_84318)
    221 
    222 #define PHY84740_IS_QUADRA_BACKPLANE(devid)\
    223 ((devid) == PHY84740_ID_84164 ||\
    224  (devid) == PHY84740_ID_84168 )
    225 
    226 #define NUM_LANES  4
    227 
    228 /* typedefs */
    229 typedef struct {
    230     int rx_los;
    231     int rx_los_invert;
    232     int mod_abs;
    233     int mod_abs_invert;
    234     int p2l_map[NUM_LANES];     /* index: physical lane, array element: logical lane */
    235     int pcs_repeater;
    236     int reverse_mode;
    237     int mod_auto_detect;
    238     int mod_auto_detect_msg;
    239     int software_rx_los;
    240     int fcmap_passthrough;
    241     int single_lpmode;
    242     int skip_fw_dload;
    243 } PHY84740_DEV_DESC_t;
    244 
    245 /* device field macros */
    246 #define RX_LOS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->rx_los)
    247 #define RX_LOS_INVERT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->rx_los_invert)
    248 #define MOD_ABS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_abs)
    249 #define MOD_ABS_INVERT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_abs_invert)
    250 #define P2L_MAP(_pc,_ix) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->p2l_map[(_ix)])
    251 #define PCS_REPEATER(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->pcs_repeater)
    252 #define REVERSE_MODE(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->reverse_mode)
    253 #define MOD_AUTO_DETECT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_auto_detect)
    254 #define MOD_AUTO_DETECT_MSG(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_auto_detect_msg)
    255 #define SOFTWARE_RX_LOS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->software_rx_los)
    256 #define FCMAP_PASSTHROUGH(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->fcmap_passthrough)
    257 #define SINGLE_LPMODE(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->single_lpmode)
    258 #define SKIP_FW_DLOAD(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->skip_fw_dload)
    259 
    260 #define PHY84740_FCS_ERROR_WAR
    261 
    262 /* callback to deliever the firmware by application 
    263  * return value: TRUE  successfully delivered
    264  *               FALSE fail to deliver
    265  *
    266  * Example:
    267  *
    268  * int user_firmware_send (int unit,int port,int flag,unsigned char **data,int *len)
    269  * {
    270  *     *data = phy84740_ucode_bin;
    271  *     *len  = phy84740_ucode_bin_len;
    272      LOG_WARN(BSL_LS_SOC_PHY,
    273               (BSL_META_U(unit,
    274                           "port %d: user firmware hook routine called\n"),port));
    275  *     return TRUE;
    276  * }
    277  * Then initialize the function pointer before the BCM port initialization: 
    278  * phy_84740_uc_firmware_hook = user_firmware_send;
    279  */
    280 int (*phy_84740_uc_firmware_hook) (int unit,    /* switch number */
    281                                    int port,    /* port number */
    282                                    int flag,    /* any information need to ba passed. Not used for now */
    283                                    unsigned char **addr,        /* starting address of delivered firmware */
    284                                    int *len     /* length of the firmware */
    285     ) = NULL;
    286 
    287 static int write_message(int unit, phy_ctrl_t *pc, uint16 wrdata,
    288                          uint16 *rddata);
    289 
    290 STATIC int phy_84740_speed_get(int, soc_port_t, int *);
    291 STATIC int
    292 _phy_84740_firmware_to_rom(int unit, int port, int offset, uint8 *array,
    293                            int datalen);
    294 STATIC int _phy84740_mdio_lane_firmware_download(int unit, int port,
    295                                                  phy_ctrl_t *pc,
    296                                                  uint8 *new_fw,
    297                                                  uint32 fw_length);
    298 STATIC void _phy_84740_decode_syncout_mode(uint16 value,
    299                                            soc_port_phy_timesync_syncout_mode_t
    300                                            *mode);
    301 STATIC void _phy_84740_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t
    302                                            mode, uint16 *value);
    303 STATIC void _phy_84740_decode_framesync_mode(uint16 value,
    304                                              soc_port_phy_timesync_framesync_mode_t
    305                                              *mode);
    306 STATIC void
    307 _phy_84740_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode,
    308                                  uint16 *value);
    309 STATIC void _phy_84740_decode_gmode(uint16 value,
    310                                     soc_port_phy_timesync_global_mode_t *mode);
    311 STATIC void _phy_84740_encode_gmode(soc_port_phy_timesync_global_mode_t mode,
    312                                     uint16 *value);
    313 STATIC void _phy_84740_decode_ingress_message_mode(uint16 value, int offset,
    314                                                    soc_port_phy_timesync_event_message_ingress_mode_t
    315                                                    *mode);
    316 STATIC void _phy_84740_decode_egress_message_mode(uint16 value, int offset,
    317                                                   soc_port_phy_timesync_event_message_egress_mode_t
    318                                                   *mode);
    319 
    320 STATIC void
    321 _phy_84740_encode_ingress_message_mode
    322 (soc_port_phy_timesync_event_message_ingress_mode_t mode, int offset, uint16 *value);
    323 STATIC void
    324 _phy_84740_encode_egress_message_mode
    325 (soc_port_phy_timesync_event_message_egress_mode_t mode, int offset, uint16 *value);
    326 STATIC int phy_84740_tx_polarity_flip_set(int unit, int port, uint32 value);
    327 STATIC int phy_84740_rx_polarity_flip_set(int unit, int port, uint32 value);
    328 STATIC int phy_84740_enable_set(int unit, soc_port_t port, int enable);
    329 extern unsigned char phy84740_ucode_bin[];
    330 extern unsigned int phy84740_ucode_bin_len;
    331 extern unsigned char phy84754_ucode_bin[];
    332 extern unsigned int phy84754_ucode_bin_len;
    333 extern unsigned char phy84753_ucode_bin[];
    334 extern unsigned int phy84753_ucode_bin_len;
    335 extern unsigned char phy84064_ucode_bin[];
    336 extern unsigned int phy84064_ucode_bin_len;
    337 extern unsigned char phy84752_ucode_bin[];
    338 extern unsigned int phy84752_ucode_bin_len;
    339 extern unsigned char phy84758_ucode_bin[];
    340 extern unsigned int phy84758_ucode_bin_len;
    341 extern unsigned char phy84780_ucode_bin[];
    342 extern unsigned int phy84780_ucode_bin_len;
    343 extern unsigned char phy84784_ucode_bin[];
    344 extern unsigned int phy84784_ucode_bin_len;
    345 extern unsigned char phy84318_ucode_bin[];
    346 extern unsigned int phy84318_ucode_bin_len;
    347 
    348 static char *dev_name_84740 = "BCM84740";
    349 static char *dev_name_84752 = "BCM84752";
    350 static char *dev_name_84753 = "BCM84753";
    351 static char *dev_name_84754 = "BCM84754";
    352 static char *dev_name_84064 = "BCM84064";
    353 static char *dev_name_84784 = "BCM84784";
    354 STATIC int
    355 _phy_84740_config_devid(int unit, soc_port_t port, phy_ctrl_t *pc,
    356                         uint32 *devid)
    357 {
    358     uint16 data16;
    359 
    360     if (soc_property_port_get(unit, port, spn_PHY_84740, FALSE)) {
    361         *devid = PHY84740_ID_84740;
    362     } else if (soc_property_port_get(unit, port, spn_PHY_84752, FALSE)) {
    363         *devid = PHY84740_ID_84752;
    364     } else if (soc_property_port_get(unit, port, spn_PHY_84753, FALSE)) {
    365         *devid = PHY84740_ID_84753;
    366     } else if (soc_property_port_get(unit, port, spn_PHY_84754, FALSE)) {
    367         *devid = PHY84740_ID_84754;
    368     } else if (soc_property_port_get(unit, port, spn_PHY_84064, FALSE)) {
    369         *devid = PHY84740_ID_84064;
    370     } else {
    371 
    372         /* read Other chip id */
    373         SOC_IF_ERROR_RETURN
    374             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc802, &data16));
    375 
    376         if (PHY84740_IS_QUADRA(0x80000 | data16)) {
    377             *devid = 0x80000 | data16;
    378         } else {
    379             *devid = 0;
    380         }
    381     }
    382     return SOC_E_NONE;
    383 }
    384 
    385 STATIC int
    386 _phy_84740_single_to_quad_mode(int unit, soc_port_t port, phy_ctrl_t *pc)
    387 {
    388     int ix;
    389     uint16 saved_phy_addr;
    390     uint16 mask16;
    391     uint16 data16;
    392     uint32 devid;
    393 
    394     if (pc == NULL) {
    395         pc = EXT_PHY_SW_STATE(unit, port);
    396     }
    397 
    398     /* probe routine should block any invalid devids. 
    399      * devids should be always valid here
    400      */
    401     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
    402                         (pc->unit, pc->port, pc, &devid));
    403 
    404     mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK;
    405     if (devid == PHY84740_ID_84064) {
    406         data16 = PHY84740_PMAD_BKPLANE_MODE_MASK;
    407     } else {
    408         data16 = 0;
    409     }
    410 
    411     /* config DAC mode/backplane mode first. This is a bcst register in single mode */
    412     SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
    413                         (pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, data16,
    414                          mask16));
    415 
    416     /* then configure quad chip mode */
    417     SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
    418                         (pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0,
    419                          PHY84740_PMAD_CHIP_MODE_MASK));
    420 
    421     /* once this mode register is configured with quad mode, each lane is
    422      * accessable by the lane specific MDIO address
    423      */
    424     saved_phy_addr = pc->phy_id;
    425     /* Reset all 4 lanes. Only after reset, the mode is actually switched */
    426     for (ix = 0; ix < 4; ix++) {
    427         pc->phy_id = (saved_phy_addr & (~0x3)) + ix;
    428         SOC_IF_ERROR_RETURN
    429             (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc,
    430                                            MII_CTRL_RESET, MII_CTRL_RESET));
    431     }
    432     pc->phy_id = saved_phy_addr;
    433 
    434     return SOC_E_NONE;
    435 }
    436 
    437 STATIC int _phy_84740_quad_to_single_mode(int unit, soc_port_t port)
    438 {
    439     int ix;
    440     uint16 saved_phy_addr;
    441     phy_ctrl_t *pc;
    442     uint16 mask16;
    443     uint16 data16;
    444     uint32 devid;
    445 
    446     pc = EXT_PHY_SW_STATE(unit, port);
    447 
    448     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
    449                         (pc->unit, pc->port, pc, &devid));
    450 
    451     saved_phy_addr = pc->phy_id;
    452     /* configure all four lanes to bcst mode */
    453     for (ix = 0; ix < 4; ix++) {
    454         pc->phy_id = (saved_phy_addr & (~0x3)) + ix;
    455         SOC_IF_ERROR_RETURN
    456             (WRITE_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc,
    457                                             PHY84740_PMAD_BCST_REG, 0xffff));
    458     }
    459     pc->phy_id = saved_phy_addr;
    460 
    461     /* then configure single mode */
    462     SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
    463                         (pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
    464                          PHY84740_PMAD_MODE_40G, PHY84740_PMAD_CHIP_MODE_MASK));
    465 
    466     mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK;
    467     if (devid == PHY84740_ID_84064) {
    468         data16 = PHY84740_PMAD_BKPLANE_MODE_MASK;
    469     } else {
    470         data16 = 0;
    471     }
    472 
    473     /* config DAC mode and backplane mode for LR4/SR4 */
    474     SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
    475                         (pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, data16,
    476                          mask16));
    477 
    478     /* do a soft reset to switch to the configured mode
    479      * The reset should also clear the bcst register configuration
    480      */
    481     SOC_IF_ERROR_RETURN
    482         (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc,
    483                                        MII_CTRL_RESET, MII_CTRL_RESET));
    484 
    485     return SOC_E_NONE;
    486 }
    487 
    488 STATIC int
    489 _phy84740_mdio_firmware_download(int unit, int port, phy_ctrl_t *pc,
    490                                  uint8 *new_fw, uint32 fw_length)
    491 {
    492     uint16 data16;
    493     uint16 mask16;
    494     int lane;
    495     int rv = SOC_E_NONE;
    496 
    497     if (new_fw == NULL || fw_length == 0) {
    498         LOG_WARN(BSL_LS_SOC_PHY,
    499                  (BSL_META_U(unit,
    500                              "u=%d p=%d MDIO firmware download: invalid firmware\n"),
    501                   unit, port));
    502         return SOC_E_NONE;
    503     }
    504 
    505     if (PHY84740_SINGLE_PORT_MODE(pc)) {
    506         /* point to lane 0 */
    507         SOC_IF_ERROR_RETURN
    508             (WRITE_PHY84740_MMF_PMA_PMD_REG
    509              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
    510     }
    511 
    512     /* clear SPA ctrl reg bit 15 and bit 13. 
    513      * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM 
    514      * bit 13, 0 clear download done status, 1 skip download 
    515      */
    516     mask16 = (1 << 13) | (1 << 15);
    517     data16 = 0;
    518     SOC_IF_ERROR_RETURN
    519         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG,
    520                                          data16, mask16));
    521 
    522     /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */
    523     mask16 = 1 << 14;
    524     data16 = mask16;
    525     SOC_IF_ERROR_RETURN
    526         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG,
    527                                          data16, mask16));
    528 
    529     /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */
    530     if (PHY84740_SINGLE_PORT_MODE(pc)) {
    531         for (lane = 0; lane < NUM_LANES; lane++) {
    532             SOC_IF_ERROR_RETURN
    533                 (WRITE_PHY84740_MMF_PMA_PMD_REG
    534                  (unit, pc, PHY84740_PMAD_AER_ADDR_REG, lane));
    535             mask16 = 1 << 3;
    536             data16 = mask16;
    537             SOC_IF_ERROR_RETURN
    538                 (MODIFY_PHY84740_MMF_PMA_PMD_REG
    539                  (unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, data16, mask16));
    540         }
    541     } else {
    542         mask16 = 1 << 3;
    543         data16 = mask16;
    544         SOC_IF_ERROR_RETURN
    545             (MODIFY_PHY84740_MMF_PMA_PMD_REG
    546              (unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, data16, mask16));
    547     }
    548     if (PHY84740_SINGLE_PORT_MODE(pc)) {
    549         /* apply bcst Reset to start download code from MDIO */
    550         SOC_IF_ERROR_RETURN
    551             (WRITE_PHY84740_MMF_PMA_PMD_REG
    552              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
    553     }
    554     SOC_IF_ERROR_RETURN(WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, 0x8000));
    555 
    556     /* wait for 2ms for M8051 start and 5ms to initialize the RAM */
    557     sal_usleep(10000);          /* Wait for 10ms */
    558 
    559     if (PHY84740_SINGLE_PORT_MODE(pc)) {
    560         for (lane = 0; lane < NUM_LANES; lane++) {
    561             SOC_IF_ERROR_RETURN
    562                 (WRITE_PHY84740_MMF_PMA_PMD_REG
    563                  (unit, pc, PHY84740_PMAD_AER_ADDR_REG, lane));
    564             /* download the firmware to the specific lane */
    565             rv = _phy84740_mdio_lane_firmware_download(unit, port, pc, new_fw,
    566                                                        fw_length);
    567         }
    568 
    569         /* point back to lane0 */
    570         SOC_IF_ERROR_RETURN
    571             (WRITE_PHY84740_MMF_PMA_PMD_REG
    572              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
    573     } else {
    574         SOC_IF_ERROR_RETURN
    575             (_phy84740_mdio_lane_firmware_download
    576              (unit, port, pc, new_fw, fw_length));
    577     }
    578     return rv;
    579 }
    580 
    581 STATIC int
    582 _phy84740_mdio_lane_firmware_download(int unit, int port, phy_ctrl_t *pc,
    583                                       uint8 *new_fw, uint32 fw_length)
    584 {
    585     uint16 data16;
    586     int j;
    587     uint16 num_words;
    588 
    589     /* Write Starting Address, where the Code will reside in SRAM */
    590     data16 = 0x8000;
    591     SOC_IF_ERROR_RETURN
    592         (WRITE_PHY84740_MMF_PMA_PMD_REG
    593          (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
    594 
    595     /* make sure address word is read by the micro */
    596     sal_udelay(10);             /* Wait for 10us */
    597 
    598     /* Write SPI SRAM Count Size */
    599     data16 = (fw_length) / 2;
    600     SOC_IF_ERROR_RETURN
    601         (WRITE_PHY84740_MMF_PMA_PMD_REG
    602          (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
    603 
    604     /* make sure read by the micro */
    605     sal_udelay(10);             /* Wait for 10us */
    606 
    607     /* Fill in the SRAM */
    608     num_words = (fw_length - 1);
    609     for (j = 0; j < num_words; j += 2) {
    610         /* Make sure the word is read by the Micro */
    611         sal_udelay(10);
    612 
    613         data16 = (new_fw[j] << 8) | new_fw[j + 1];
    614         SOC_IF_ERROR_RETURN
    615             (WRITE_PHY84740_MMF_PMA_PMD_REG
    616              (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
    617     }
    618 
    619     /* make sure last code word is read by the micro */
    620     sal_udelay(20);
    621 
    622     /* Read Hand-Shake message (Done) from Micro */
    623     SOC_IF_ERROR_RETURN
    624         (READ_PHY84740_MMF_PMA_PMD_REG
    625          (unit, pc, PHY84740_PMAD_M8051_MSGOUT_REG, &data16));
    626 
    627     /* Download done message */
    628     LOG_INFO(BSL_LS_SOC_PHY,
    629              (BSL_META_U(unit,
    630                          "u=%d p=%d MDIO firmware download done message: 0x%x\n"),
    631               unit, port, data16));
    632 
    633     /* Clear LASI status */
    634     SOC_IF_ERROR_RETURN
    635         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
    636 
    637     /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */
    638     sal_udelay(100);            /* Wait for 100 usecs */
    639 
    640     SOC_IF_ERROR_RETURN
    641         (READ_PHY84740_MMF_PMA_PMD_REG
    642          (unit, pc, PHY84740_PMAD_M8051_MSGOUT_REG, &data16));
    643 
    644     /* Need to check if checksum is correct */
    645     SOC_IF_ERROR_RETURN
    646         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16));
    647 
    648     if (data16 != 0x600D) {
    649         /* Bad CHECKSUM */
    650         LOG_CLI((BSL_META_U(unit,
    651                             "MDIO Firmware downlad failure:"
    652                  "Incorrect Checksum %x\n"), data16));
    653         return SOC_E_FAIL;
    654     }
    655 
    656     /* read Rev-ID */
    657     SOC_IF_ERROR_RETURN
    658         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16));
    659     LOG_INFO(BSL_LS_SOC_PHY,
    660              (BSL_META_U(unit,
    661                          "u=%d p=%d MDIO Firmware download revID: 0x%x\n"),
    662                          unit, port, data16));
    663 
    664     return SOC_E_NONE;
    665 }
    666 
    667 STATIC int _phy84740_rom_firmware_download(int unit, int port, phy_ctrl_t *pc)
    668 {
    669     int lane;
    670     uint16 data16;
    671     uint16 mask16;
    672     if (PHY84740_SINGLE_PORT_MODE(pc)) {
    673         for (lane = 3; lane >= 0; lane--) {
    674             SOC_IF_ERROR_RETURN
    675                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    676                                                 PHY84740_PMAD_AER_ADDR_REG,
    677                                                 lane));
    678 
    679             /* 0xca85[3]=1, 32K download */
    680             mask16 = (1 << 3);
    681             data16 = mask16;
    682             SOC_IF_ERROR_RETURN
    683                 (MODIFY_PHY84740_MMF_PMA_PMD_REG
    684                  (unit, pc, 0xCA85, data16, mask16));
    685         }
    686 
    687         /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */
    688         mask16 = (1 << 15) | (1 << 14);
    689         data16 = mask16;
    690 
    691         /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */
    692         mask16 |= (1 << 13) | (1 << 2);
    693         SOC_IF_ERROR_RETURN
    694             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16));
    695 
    696         /* apply software reset to download code from SPI-ROM */
    697         SOC_IF_ERROR_RETURN
    698             (WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, MII_CTRL_RESET));
    699 
    700         for (lane = 0; lane < NUM_LANES; lane++) {
    701             SOC_IF_ERROR_RETURN
    702                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    703                                                 PHY84740_PMAD_AER_ADDR_REG,
    704                                                 lane));
    705             /* wait for at least 50ms */
    706             sal_usleep(100000);
    707             SOC_IF_ERROR_RETURN
    708                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
    709             LOG_INFO(BSL_LS_SOC_PHY,
    710                      (BSL_META_U(unit,
    711                                  "u=%d p=%d lane%d SPI-ROM download done msg 0x%x\n"),
    712                       unit, port, lane, data16));
    713             SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
    714                                 (unit, pc, 0xCA1C, &data16));
    715             SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
    716                                 (unit, pc, 0xCA1A, &data16));
    717         }
    718         SOC_IF_ERROR_RETURN
    719             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    720                                             PHY84740_PMAD_AER_ADDR_REG, 0));
    721     } else {                    /* single lane */
    722         /* 0xca85[3]=1, 32K download */
    723         mask16 = (1 << 3);
    724         data16 = mask16;
    725         SOC_IF_ERROR_RETURN
    726             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA85, data16, mask16));
    727 
    728         /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */
    729         mask16 = (1 << 15) | (1 << 14);
    730         data16 = mask16;
    731         SOC_IF_ERROR_RETURN
    732             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16));
    733 
    734         /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */
    735         mask16 = (1 << 13) | (1 << 2);
    736         data16 = 0;
    737         SOC_IF_ERROR_RETURN
    738             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16));
    739 
    740         /* apply software reset to download code from SPI-ROM */
    741         SOC_IF_ERROR_RETURN
    742             (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc,
    743                                            MII_CTRL_RESET, MII_CTRL_RESET));
    744 
    745         /* wait for at least 50ms */
    746         sal_usleep(100000);
    747         SOC_IF_ERROR_RETURN
    748             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
    749         LOG_INFO(BSL_LS_SOC_PHY,
    750                  (BSL_META_U(unit,
    751                              "u=%d p=%d SPI-ROM download done msg 0x%x\n"),
    752                              unit, port, data16));
    753 
    754     }
    755     return SOC_E_NONE;
    756 }
    757 
    758 /*
    759  * Flip the tx/rx polarities based on the configuration.
    760  */
    761 STATIC int _phy_84740_polarity_flip_set(int unit, soc_port_t port)
    762 {
    763     int lane;
    764     phy_ctrl_t *pc;
    765     uint16 tx_pol, rx_pol;
    766     uint16 data16, mask16;
    767 
    768     pc = EXT_PHY_SW_STATE(unit, port);
    769 
    770     tx_pol = 0;
    771     rx_pol = 0;
    772 
    773     /* get the reset default value. The 84740 device has the TX polarity flipped
    774      * by default. Construct the init default value 
    775      */
    776 
    777     if ((PHY84740_SINGLE_PORT_MODE(pc))) {
    778         for (lane = 0; lane < NUM_LANES; lane++) {
    779             /* point to the each lane starting at lane0 */
    780             SOC_IF_ERROR_RETURN
    781                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    782                                                 PHY84740_PMAD_AER_ADDR_REG,
    783                                                 P2L_MAP(pc, lane)));
    784 
    785             /* read both TX/RX polarities */
    786             SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
    787                                 (unit, pc, PHY84740_DIG_CTRL_REG, &data16));
    788             if (data16 & PHY84740_TX_POLARITY_FLIP_MASK) {
    789                 tx_pol |= POL_CONFIG_LANE_MASK(lane);
    790             }
    791             if (data16 & PHY84740_RX_POLARITY_FLIP_MASK) {
    792                 rx_pol |= POL_CONFIG_LANE_MASK(lane);
    793             }
    794         }
    795     } else {                    /* quad mode */
    796         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
    797                             (unit, pc, PHY84740_DIG_CTRL_REG, &data16));
    798         if (data16 & PHY84740_TX_POLARITY_FLIP_MASK) {
    799             tx_pol = POL_CONFIG_ALL_LANES;
    800         }
    801         if (data16 & PHY84740_RX_POLARITY_FLIP_MASK) {
    802             rx_pol = POL_CONFIG_ALL_LANES;
    803         }
    804     }
    805 
    806     tx_pol = soc_property_port_get(unit, port,
    807                                    spn_PHY_PCS_TX_POLARITY_FLIP, tx_pol);
    808     rx_pol = soc_property_port_get(unit, port,
    809                                    spn_PHY_PCS_RX_POLARITY_FLIP, rx_pol);
    810 
    811     mask16 = PHY84740_TX_POLARITY_FLIP_MASK | PHY84740_RX_POLARITY_FLIP_MASK;
    812 
    813     if ((PHY84740_SINGLE_PORT_MODE(pc))) {
    814         for (lane = 0; lane < NUM_LANES; lane++) {
    815             data16 = 0;
    816 
    817             /* point to the each lane starting at lane0 */
    818             SOC_IF_ERROR_RETURN
    819                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    820                                                 PHY84740_PMAD_AER_ADDR_REG,
    821                                                 P2L_MAP(pc, lane)));
    822 
    823             if ((tx_pol == POL_CONFIG_ALL_LANES) ||
    824                 ((tx_pol & POL_CONFIG_LANE_MASK(lane)) ==
    825                  POL_CONFIG_LANE_MASK(lane))) {
    826                 data16 = PHY84740_TX_POLARITY_FLIP_MASK;
    827             }
    828             if ((rx_pol == POL_CONFIG_ALL_LANES) ||
    829                 ((rx_pol & POL_CONFIG_LANE_MASK(lane)) ==
    830                  POL_CONFIG_LANE_MASK(lane))) {
    831                 data16 |= PHY84740_RX_POLARITY_FLIP_MASK;
    832             }
    833             SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    834                                                                 PHY84740_DIG_CTRL_REG,
    835                                                                 data16,
    836                                                                 mask16));
    837         }
    838         /* point back to lane0 */
    839         SOC_IF_ERROR_RETURN
    840             (WRITE_PHY84740_MMF_PMA_PMD_REG
    841              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
    842     } else {                    /* quad-port mode */
    843         data16 = 0;
    844         tx_pol = PHY84740_10G_POL_CFG_GET(pc, tx_pol);
    845         if (tx_pol) {
    846             data16 = PHY84740_TX_POLARITY_FLIP_MASK;
    847         }
    848         rx_pol = PHY84740_10G_POL_CFG_GET(pc, rx_pol);
    849         if (rx_pol) {
    850             data16 |= PHY84740_RX_POLARITY_FLIP_MASK;
    851         }
    852         SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
    853                             (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16));
    854     }
    855 
    856     return SOC_E_NONE;
    857 }
    858 
    859 /*
    860  * Squelch enable/disable
    861  */
    862 STATIC int _phy_84740_squelch_enable(int unit, soc_port_t port,
    863                                      int intf, int enable, int force)
    864 {
    865     phy_ctrl_t *pc;
    866     int ix;
    867     int repeater_mode;
    868     uint16 data16, mask16,bit,speed_val;
    869     uint32 devid;
    870 
    871     pc = EXT_PHY_SW_STATE(unit, port);
    872     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
    873                         (pc->unit, pc->port, pc, &devid));
    874 
    875     if (PHY84740_IS_QUADRA(devid)) { 
    876         if ((PHY_DIAG_INTF_LINE == intf || REVERSE_MODE(pc)) &&
    877             PHY_DIAG_INTF_SYS != intf) {
    878             if(PHY84740_SINGLE_PORT_MODE(pc)) {
    879                 mask16 = (1 << 6);
    880                 data16 = enable ? mask16 : 0;
    881                 for (ix = 0; ix < NUM_LANES; ix++) {
    882                     SOC_IF_ERROR_RETURN
    883                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    884                                                     PHY84740_PMAD_AER_ADDR_REG,
    885                                                     ix));
    886                     SOC_IF_ERROR_RETURN
    887                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    888                                                      0xcd18, data16, mask16));
    889                     SOC_IF_ERROR_RETURN
    890                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    891                                                      0xcd16,
    892                                                      enable ? (1 << 4) : 0,
    893                                                      (1 << 4)));
    894                 }
    895                /* point back to lane0 */
    896                SOC_IF_ERROR_RETURN
    897                    (WRITE_PHY84740_MMF_PMA_PMD_REG
    898                    (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 
    899 
    900             } else {/*quad ports**/
    901                 SOC_IF_ERROR_RETURN
    902                     (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
    903                 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE;
    904                 if (repeater_mode) {
    905                    SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
    906                             (unit, pc, 0xc81f, &speed_val));
    907                    bit = (speed_val & (1 << 2)) ? 3 : 4; 
    908                     mask16 = (1 << bit) | (1 << 6);
    909                     data16 = enable ? mask16 : 0;
    910                     SOC_IF_ERROR_RETURN
    911                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    912                                                      0xcd18, data16, mask16));
    913                 }                
    914             }
    915         } else { /*system side or not reverse mode*/
    916             if (PHY84740_SINGLE_PORT_MODE(pc)) {
    917                 mask16 = (1 << 6) | (1 << 11);
    918                 data16 = enable ? mask16 : 0;
    919                 for (ix = 0; ix < NUM_LANES; ix++) {
    920                     SOC_IF_ERROR_RETURN
    921                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    922                                                    PHY84740_PMAD_AER_ADDR_REG,
    923                                                    ix));
    924                     SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
    925                     SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit,
    926                                                                    pc,
    927                                                                    0xcd18,
    928                                                                    data16,
    929                                                                    mask16));
    930                     SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
    931                 }
    932                  /* point back to lane0 */
    933                 SOC_IF_ERROR_RETURN
    934                     (WRITE_PHY84740_MMF_PMA_PMD_REG
    935                     (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
    936             } else {/* quad port*/
    937                 SOC_IF_ERROR_RETURN
    938                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
    939                 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE;
    940                 if (repeater_mode) {
    941                     SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
    942                             (unit, pc, 0xc81f, &speed_val));
    943                     bit = (speed_val & (1 << 2)) ? 3 : 4; 
    944                     mask16 = (1 << bit) | (1 << 6);
    945                     data16 = enable ? mask16 : 0;
    946                     SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
    947                     SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, pc,
    948                                                                   0xcd18,
    949                                                                   data16,
    950                                                                   mask16));
    951                     SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
    952                }
    953             }
    954         }
    955     } else { 
    956         if ((PHY_DIAG_INTF_LINE == intf || REVERSE_MODE(pc)) &&
    957             PHY_DIAG_INTF_SYS != intf) {
    958             if (PHY84740_SINGLE_PORT_MODE(pc)) {
    959 
    960                 /* Note: following line needed as workaround */
    961                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
    962 
    963                 mask16 = (1 << 6);
    964                 data16 = enable ? mask16 : 0;
    965 
    966                 for (ix = 0; ix < NUM_LANES; ix++) {
    967                     SOC_IF_ERROR_RETURN
    968                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    969                                                     PHY84740_PMAD_AER_ADDR_REG,
    970                                                     ix));
    971 
    972                     SOC_IF_ERROR_RETURN
    973                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    974                                                      0xcd18, data16, mask16));
    975 
    976                     SOC_IF_ERROR_RETURN
    977                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    978                                                      0xcd16,
    979                                                      enable ?
    980                                                      (force ?((1 << 3)|(1 << 4))
    981                                                      :(1 << 4))
    982                                                      : 0,
    983                                                      (1 << 3)|(1 << 4)));
    984                }
    985                /* point back to lane0 */
    986                SOC_IF_ERROR_RETURN
    987                    (WRITE_PHY84740_MMF_PMA_PMD_REG
    988                    (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
    989             } else {
    990                 SOC_IF_ERROR_RETURN
    991                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
    992                                                      0xcd16,
    993                                                      force ? (1 << 3) : 0,
    994                                                      (1 << 3)));
    995                 SOC_IF_ERROR_RETURN
    996                     (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
    997 
    998                 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE;
    999                 if (repeater_mode) {
   1000                     mask16 = (1 << 4) | (1 << 6);
   1001                     data16 = enable ? mask16 : 0;
   1002 
   1003                     SOC_IF_ERROR_RETURN
   1004                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   1005                                                      0xcd18, data16, mask16));
   1006                 }
   1007             }
   1008 
   1009           } else { /*system side or not reverse mode*/
   1010               if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1011 
   1012                  mask16 = (1 << 6) | (1 << 11);
   1013                  data16 = enable ? mask16 : 0;
   1014 
   1015                  for (ix = 0; ix < NUM_LANES; ix++) {
   1016                      SOC_IF_ERROR_RETURN
   1017                          (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   1018                                                     PHY84740_PMAD_AER_ADDR_REG,
   1019                                                     ix));
   1020 
   1021                      SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   1022                      SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit,
   1023                                                                     pc,
   1024                                                                     0xcd18,
   1025                                                                     data16,
   1026                                                                     mask16));
   1027 
   1028                      SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   1029                  }
   1030                  /* point back to lane0 */
   1031                  SOC_IF_ERROR_RETURN
   1032                      (WRITE_PHY84740_MMF_PMA_PMD_REG
   1033                      (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   1034               } else {
   1035                   SOC_IF_ERROR_RETURN
   1036                       (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
   1037 
   1038                   repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE;
   1039                   if (repeater_mode) {
   1040                       mask16 = (1 << 4) | (1 << 6);
   1041                       data16 = enable ? mask16 : 0;
   1042 
   1043                       SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   1044                       SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, pc,
   1045                                                                     0xcd18,
   1046                                                                     data16,
   1047                                                                     mask16));
   1048 
   1049                       SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   1050                  }
   1051               }
   1052           }
   1053     }
   1054     return SOC_E_NONE;
   1055 }
   1056 
   1057 STATIC int
   1058 _phy_84740_firmware_is_downloaded(int unit, soc_port_t port, int ext_rom)
   1059 {
   1060     int rv = 0;
   1061     uint16 data16;
   1062     phy_ctrl_t *pc;
   1063 
   1064     pc = EXT_PHY_SW_STATE(unit, port);
   1065 
   1066     if (soc_property_port_get(unit, port,spn_PHY_FORCE_FIRMWARE_LOAD, TRUE)) {
   1067         return 0;
   1068     }
   1069 
   1070     /*
   1071      * To determine whether the firmware has been downloaded, it must
   1072      * pass the following:
   1073      * 1. firmware is in RAM: 1.c848.13==1
   1074      * 2. expected checksum:  1.ca1c==600d
   1075      * 3. version is non-zero:  1.ca1a!=0
   1076      */
   1077 
   1078     /* 1. Firmware download status */
   1079     rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, &data16);
   1080     if (rv != SOC_E_NONE) {
   1081         return 0;
   1082     }
   1083     if (ext_rom) {
   1084         if ((data16 & 0xa000) != 0xa000) {
   1085             return 0;
   1086         }
   1087     } else if ((data16 & 0xf000) != 0x7000) {
   1088         return 0;
   1089     }
   1090     LOG_INFO(BSL_LS_SOC_PHY,
   1091              (BSL_META_U(unit,
   1092                          "FW download status=%x: u=%d p=%d\n"), data16, unit, port));
   1093 
   1094     /* 2. Expected checksum */
   1095     rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16);
   1096     if ((rv != SOC_E_NONE) || (data16 != 0x600D)) {
   1097         return 0;
   1098     }
   1099     LOG_INFO(BSL_LS_SOC_PHY,
   1100              (BSL_META_U(unit,
   1101                          "FW checksum=%x: u=%d p=%d\n"), data16, unit, port));
   1102 
   1103     /* 3. non-zero version */
   1104     rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16);
   1105     if ((rv != SOC_E_NONE) || (data16 == 0)) {
   1106         return 0;
   1107     }
   1108     LOG_INFO(BSL_LS_SOC_PHY,
   1109              (BSL_META_U(unit,
   1110                          "FW version=%x: u=%d p=%d\n"), data16, unit, port));
   1111 
   1112     return 1;
   1113 }
   1114 
   1115 /* Function:
   1116  *    phy_84740_init
   1117  * Purpose:    
   1118  *    Initialize 84740 phys
   1119  * Parameters:
   1120  *    unit - StrataSwitch unit #.
   1121  *    port - StrataSwitch port #. 
   1122  * Returns:    
   1123  *    SOC_E_NONE
   1124  */
   1125 
   1126 STATIC int phy_84740_init(int unit, soc_port_t port)
   1127 {
   1128     soc_timeout_t to;
   1129     int rv = SOC_E_NONE;
   1130     uint16 data16, ucode_ver;
   1131     uint16 chip_mode;
   1132     phy_ctrl_t *pc;
   1133     int ix;
   1134     uint32 phy_ext_rom_boot = 0;
   1135     uint16 mask16;
   1136     uint32 devid;
   1137     unsigned char *pdata;
   1138     int data_len;
   1139     uint32 l2p, l2p_map;
   1140 
   1141     pc = EXT_PHY_SW_STATE(unit, port);
   1142     LOG_INFO(BSL_LS_SOC_PHY,
   1143              (BSL_META_U(unit,
   1144                          "PHY84740 init: u=%d p=%d desc=0x%x\n"),
   1145               unit, port, PTR_TO_INT(pc + 1)));
   1146     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   1147                         (pc->unit, pc->port, pc, &devid));
   1148 
   1149     /* initialize default p2l map */
   1150     for (ix = 0; ix < NUM_LANES; ix++) {
   1151         P2L_MAP(pc, ix) = ix;
   1152     }
   1153 
   1154     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) ||
   1155         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1156         PCS_REPEATER(pc) = FALSE;
   1157         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1158             /* Always set repeater flag in single port mode */
   1159             PHY_FLAGS_SET(unit, port,
   1160                           PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER);
   1161         } else {
   1162             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45);
   1163         }
   1164 
   1165         FCMAP_PASSTHROUGH(pc) =
   1166             soc_property_port_get(unit, port, spn_PHY_FCMAP_PASSTHROUGH, 0);
   1167 
   1168         if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) {
   1169             LOG_INFO(BSL_LS_SOC_PHY,
   1170                      (BSL_META_U(unit,
   1171                                  "PHY84740 init pass1: u=%d p=%d\n"), unit, port));
   1172 
   1173             /* check if to use the bcst mode for RAM uC download */
   1174             phy_ext_rom_boot = soc_property_port_get(unit, port,
   1175                                                      spn_PHY_EXT_ROM_BOOT, 1);
   1176 
   1177             SKIP_FW_DLOAD(pc) = _phy_84740_firmware_is_downloaded(unit, port,
   1178                                                                   phy_ext_rom_boot);
   1179 
   1180             /* 
   1181                if (SKIP_FW_DLOAD(pc)) {
   1182                LOG_CLI((BSL_META_U(unit,
   1183                                    "u=%d, p=%d skipping firmware download\n"),
   1184                         unit, port));
   1185                }
   1186              */
   1187 
   1188             if (!phy_ext_rom_boot) {
   1189                 if (!SKIP_FW_DLOAD(pc)) {
   1190                     pc->flags |= PHYCTRL_MDIO_BCST;
   1191                 }
   1192             } else {
   1193                 /*
   1194                  * To enable firmware to be downloaded to ports which are out-of-order, 
   1195                  * 1.c848.13 must be set on all ports first. The first port within the core that
   1196                  * has 1.c848.13 clear has control over the SPI-ROM, so later when the 
   1197                  * firmware is actually being downloaded, that port will first clear 1.c848.13 
   1198                  * and obtain control over the SPI-ROM.
   1199                  */
   1200                 data16 = (1 << 15) | (1 << 14) | (1 << 13);
   1201                 mask16 = data16;
   1202                 SOC_IF_ERROR_RETURN
   1203                     (MODIFY_PHY84740_MMF_PMA_PMD_REG
   1204                      (unit, pc, 0xc848, data16, mask16));
   1205             }
   1206 
   1207             /* configure to quad-port mode to prepare for the broadcast mode */
   1208             SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc,
   1209                                                               PHY84740_PMAD_CHIP_MODE_REG,
   1210                                                               &chip_mode));
   1211 
   1212             /* switch to quad-port mode if not already in */
   1213             if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) ==
   1214                 PHY84740_PMAD_MODE_40G) {
   1215                 SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode
   1216                                     (pc->unit, pc->port, pc));
   1217                 LOG_INFO(BSL_LS_SOC_PHY,
   1218                          (BSL_META_U(unit,
   1219                                      "PHY84740 init pass1 mode S to Q switch: u=%d p=%d\n"),
   1220                           unit, port));
   1221             }
   1222 
   1223             /* indicate second pass of init is needed */
   1224             PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_PASS2);
   1225             return SOC_E_NONE;
   1226         }
   1227     }
   1228 
   1229     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) ||
   1230         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1231         LOG_INFO(BSL_LS_SOC_PHY,
   1232                  (BSL_META_U(unit,
   1233                              "PHY84740 init pass2: u=%d p=%d\n"), unit, port));
   1234         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   1235                             (unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   1236                              &chip_mode));
   1237 
   1238         /* check the current chip mode */
   1239         if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) ==
   1240             PHY84740_PMAD_MODE_40G) {
   1241             /* 
   1242              * switch to configured mode(quad mode) if current chip mode is single mode 
   1243              * In quad mode, the supported speed modes are 10G and 1G forced, 1G autoneg.
   1244              * However 1G currently is only working with QSFP fiber cable not Cu cable.
   1245              */
   1246             if (!(PHY84740_SINGLE_PORT_MODE(pc))) {
   1247                 LOG_WARN(BSL_LS_SOC_PHY,
   1248                          (BSL_META_U(unit,
   1249                                      "PHY84740 init pass2 mode switch: u=%d p=%d\n"),
   1250                           unit, port));
   1251                 SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode
   1252                                     (unit, port, NULL));
   1253 
   1254             } else {            /* configured mode is single mode */
   1255                 /* if configured mode(single mode) matches current chip mode. Make sure 
   1256                  * it is SR4/LR4. If a optical module is plugged in when the device is 
   1257                  * configured in CR4 mode, it may damage the optical module because of big
   1258                  * voltage sway in CR4 mode. For now, the device is configured in
   1259                  * LR4/SR4 mode by default. If a QSFP Cu is used, EDC mode should be set to
   1260                  * 0x55.  In case there is a need to go to CR4 mode, user can use interface
   1261                  * set function to change to the CR4 mode. In this mode, both autoneg and 
   1262                  * forced 40G speed is supported.
   1263                  */
   1264                 /* config DAC mode and backplane mode for LR4/SR4  */
   1265                 mask16 =
   1266                     PHY84740_PMAD_DAC_MODE_MASK |
   1267                     PHY84740_PMAD_BKPLANE_MODE_MASK;
   1268                 if (devid == PHY84740_ID_84064) {
   1269                     data16 = PHY84740_PMAD_BKPLANE_MODE_MASK;
   1270                 } else {
   1271                     data16 = 0;
   1272                 }
   1273 
   1274                 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   1275                                     (unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   1276                                      data16, mask16));
   1277 
   1278                 SOC_IF_ERROR_RETURN
   1279                     (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc,
   1280                                                    MII_CTRL_RESET,
   1281                                                    MII_CTRL_RESET));
   1282             }
   1283         } else {                /* current chip mode is quad mode */
   1284             /* switch to configured mode(single mode) if current chip mode is quad mode */
   1285             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1286 
   1287                 SOC_IF_ERROR_RETURN(_phy_84740_quad_to_single_mode(unit, port));
   1288             } else {            /* configured mode is quad mode */
   1289 
   1290                 /* chip already in configured mode. config DAC/backplane mode */
   1291                 mask16 =
   1292                     PHY84740_PMAD_DAC_MODE_MASK |
   1293                     PHY84740_PMAD_BKPLANE_MODE_MASK;
   1294                 if (devid == PHY84740_ID_84064) {
   1295                     data16 = PHY84740_PMAD_BKPLANE_MODE_MASK;
   1296                 } else {
   1297                     data16 = 0;
   1298                 }
   1299 
   1300                 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   1301                                     (unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   1302                                      data16, mask16));
   1303             }
   1304         }
   1305 
   1306         /* should be done before reset */
   1307         l2p = soc_property_port_get(unit, port, spn_PHY_LANE0_L2P_MAP, 0);
   1308         if (l2p >= NUM_LANES) {
   1309             LOG_ERROR(BSL_LS_SOC_PHY,
   1310                       (BSL_META_U(unit,
   1311                                   "PHY84740 invalid L2P lane configuration: u=%d p=%d, l2p=%d\n"),
   1312                        unit, port, l2p));
   1313             return SOC_E_PARAM;
   1314         }
   1315 
   1316         SINGLE_LPMODE(pc) =
   1317             soc_property_port_get(unit, port, spn_PHY_TX_DISABLE_NO_LPMODE, 0);
   1318 
   1319         /*
   1320          * 1.c701
   1321          *    - Quebec devices specifies the physical channel number designated as
   1322          *      logical channel 0 
   1323          *    - Quadra devices specifies the mapping of all physical channels to 
   1324          *      logical channels 
   1325          */
   1326         data16 = 0;
   1327         l2p_map = 0;
   1328         if (PHY84740_IS_QUADRA(devid)) {
   1329             for (ix = 0; ix < NUM_LANES; ix++) {
   1330                 l2p_map |= ((l2p + ix) % NUM_LANES) << (ix * 4);
   1331             }
   1332             data16 = l2p_map;
   1333             mask16 = 0xffff;
   1334             for (ix = 0; ix < NUM_LANES; ix++) {
   1335                 P2L_MAP(pc, ((l2p_map >> (ix * 4)) & 0xf)) = ix;
   1336             }
   1337         } else {
   1338             data16 = l2p;
   1339             mask16 = PHY84740_L2P_PHYSICAL_LANE_MASK;
   1340 
   1341             /* physical to logical lane map, index is physical lane */
   1342             for (ix = 0; ix < NUM_LANES; ix++) {
   1343                 P2L_MAP(pc, (l2p + ix) % NUM_LANES) = ix;
   1344             }
   1345         }
   1346 
   1347         SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   1348                             (unit, pc, PHY84740_PMAD_LANE0_L2P_REG, data16,
   1349                              mask16));
   1350 
   1351         /* do a soft reset */
   1352         SOC_IF_ERROR_RETURN
   1353             (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc,
   1354                                            MII_CTRL_RESET, MII_CTRL_RESET));
   1355 
   1356         /* Wait for device to come out of reset */
   1357         soc_timeout_init(&to, 10000, 0);
   1358         while (!soc_timeout_check(&to)) {
   1359             rv = READ_PHY84740_PMA_PMD_CTRLr(unit, pc, &data16);
   1360             if (((data16 & MII_CTRL_RESET) == 0) || SOC_FAILURE(rv)) {
   1361                 break;
   1362             }
   1363         }
   1364         if (((data16 & MII_CTRL_RESET) != 0) || SOC_FAILURE(rv)) {
   1365             LOG_WARN(BSL_LS_SOC_PHY,
   1366                      (BSL_META_U(unit,
   1367                                  "PHY84740 reset failed: u=%d p=%d\n"),
   1368                       unit, port));
   1369             return SOC_E_FAIL;
   1370         }
   1371 
   1372         if (pc->flags & PHYCTRL_UCODE_BCST_DONE) {
   1373             /* ucode is already loaded thru bcst */
   1374 
   1375             /* Not clearing PHYCTRL_UCODE_BCST_DONE  -->
   1376                This bit can be checked again, in case init is called again,
   1377                to avoid an additional firmware download  */
   1378 
   1379             phy_ext_rom_boot = 0;
   1380         } else {
   1381             phy_ext_rom_boot = soc_property_port_get(unit, port,
   1382                                                      spn_PHY_EXT_ROM_BOOT, 1);
   1383 
   1384             if (SKIP_FW_DLOAD(pc)) {
   1385                 /* do nothing */
   1386             } else if (phy_ext_rom_boot) {
   1387                 SOC_IF_ERROR_RETURN
   1388                     (_phy84740_rom_firmware_download(unit, port, pc));
   1389             } else {            /* MDIO download to RAM */
   1390                 /* check if the firmware is delivered by user */
   1391                 if (phy_84740_uc_firmware_hook &&
   1392                     phy_84740_uc_firmware_hook(unit, port, devid, &pdata,
   1393                                                &data_len)) {
   1394                     SOC_IF_ERROR_RETURN(_phy84740_mdio_firmware_download
   1395                                         (unit, port, pc, pdata, data_len));
   1396                 } else {
   1397                     if (devid == PHY84740_ID_84754) {
   1398                         SOC_IF_ERROR_RETURN
   1399                             (_phy84740_mdio_firmware_download
   1400                              (unit, port, pc, phy84754_ucode_bin,
   1401                               phy84754_ucode_bin_len));
   1402                     } else if (devid == PHY84740_ID_84740) {
   1403                         /* do not use 84753/84754 ucode for 84740. There is a voltage differece */
   1404                         SOC_IF_ERROR_RETURN
   1405                             (_phy84740_mdio_firmware_download
   1406                              (unit, port, pc, phy84740_ucode_bin,
   1407                               phy84740_ucode_bin_len));
   1408                     } else if (devid == PHY84740_ID_84064) {
   1409                         SOC_IF_ERROR_RETURN
   1410                             (_phy84740_mdio_firmware_download
   1411                              (unit, port, pc, phy84064_ucode_bin,
   1412                               phy84064_ucode_bin_len));
   1413                     } else if (devid == PHY84740_ID_84753) {
   1414                         SOC_IF_ERROR_RETURN
   1415                             (_phy84740_mdio_firmware_download
   1416                              (unit, port, pc, phy84753_ucode_bin,
   1417                               phy84753_ucode_bin_len));
   1418                     } else if (devid == PHY84740_ID_84752) {
   1419                         SOC_IF_ERROR_RETURN
   1420                             (_phy84740_mdio_firmware_download
   1421                              (unit, port, pc, phy84752_ucode_bin,
   1422                               phy84752_ucode_bin_len));
   1423                     } else if (devid == PHY84740_ID_84784) {
   1424                         SOC_IF_ERROR_RETURN
   1425                             (_phy84740_mdio_firmware_download
   1426                              (unit, port, pc, phy84784_ucode_bin,
   1427                               phy84784_ucode_bin_len));
   1428                     } else if (devid == PHY84740_ID_84780) {
   1429                         SOC_IF_ERROR_RETURN
   1430                             (_phy84740_mdio_firmware_download
   1431                              (unit, port, pc, phy84780_ucode_bin,
   1432                               phy84780_ucode_bin_len));
   1433                     } else if (devid == PHY84740_ID_84318) {
   1434                         SOC_IF_ERROR_RETURN
   1435                              (_phy84740_mdio_firmware_download(unit,port,pc,phy84318_ucode_bin,
   1436                                phy84318_ucode_bin_len));
   1437                     } else if (PHY84740_IS_QUADRA(devid)) {
   1438                         SOC_IF_ERROR_RETURN
   1439                             (_phy84740_mdio_firmware_download
   1440                              (unit, port, pc, phy84758_ucode_bin,
   1441                               phy84758_ucode_bin_len));
   1442                     } else {
   1443                         LOG_WARN(BSL_LS_SOC_PHY,
   1444                                  (BSL_META_U(unit,
   1445                                              "84740: p=%d unknown device id: 0x%x\n"),
   1446                                              port,devid));
   1447                     }
   1448                 }
   1449             }
   1450         }
   1451 
   1452         /* reset will restart the uC. wait a few ms for checksum to be written */
   1453         sal_udelay(12000);
   1454 
   1455         REVERSE_MODE(pc) =
   1456             soc_property_port_get(unit, port, spn_PORT_PHY_MODE_REVERSE, 0);
   1457         if (!SOC_WARM_BOOT(unit)) {
   1458             /* Disable Tx */
   1459             SOC_IF_ERROR_RETURN(phy_84740_enable_set(unit, port, FALSE));
   1460         }
   1461 
   1462         /* read the microcode revision */
   1463         SOC_IF_ERROR_RETURN
   1464             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &ucode_ver));
   1465 
   1466         /* check the completion of the microcode download. */
   1467         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1468             uint16 cksum[4];
   1469             int ret = SOC_E_NONE;
   1470 
   1471             for (ix = 0; ix < NUM_LANES; ix++) {
   1472                 SOC_IF_ERROR_RETURN
   1473                     (WRITE_PHY84740_MMF_PMA_PMD_REG
   1474                      (unit, pc, PHY84740_PMAD_AER_ADDR_REG, ix));
   1475 
   1476                 /* check the completion of the microcode download. */
   1477                 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C,
   1478                                                    &cksum[ix]);
   1479                 if (cksum[ix] != 0x600D || SOC_FAILURE(rv)) {
   1480                     ret = SOC_E_FAIL;
   1481                 }
   1482             }
   1483             if (ret == SOC_E_FAIL) {
   1484                 LOG_WARN(BSL_LS_SOC_PHY,
   1485                          (BSL_META_U(unit,
   1486                                      "84740: p=%d SPI-ROM load: Bad Checksum lane 0,1,2,3 (0x%x),"
   1487                                      "(0x%x), (0x%x), (0x%x)\n"), port, cksum[0],
   1488                           cksum[1], cksum[2], cksum[3]));
   1489                 return SOC_E_FAIL;
   1490             }
   1491         } else {
   1492             rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16);
   1493             if (data16 != 0x600D || SOC_FAILURE(rv)) {
   1494                 LOG_WARN(BSL_LS_SOC_PHY,
   1495                          (BSL_META_U(unit,
   1496                                      "84740: p=%d SPI-ROM load: Bad Checksum (0x%x)\n"),
   1497                           port, data16));
   1498                 return SOC_E_FAIL;
   1499             }
   1500         }
   1501 
   1502         LOG_WARN(BSL_LS_SOC_PHY,
   1503                  (BSL_META_U(unit,
   1504                              "%x init u=%d port=%d rom code ver. 0x%x: %s boot\n"),
   1505                   devid, unit, port, ucode_ver,
   1506                   phy_ext_rom_boot ? "SPI-ROM" : "MDIO_TO_RAM"));
   1507 
   1508         if (!(PHY84740_SINGLE_PORT_MODE(pc))) {
   1509             /* clear 1.0xcd17 to enable the PCS */
   1510             SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   1511                                                                PHY84740_RESET_CONTROL_REGISTER,
   1512                                                                0));
   1513         } else {
   1514             /* 40G no autoneg support */
   1515             /* EDC mode for SR4/LR4 0x44, done in ucode, no need to set for CR4 */
   1516             /* disable cl72 */
   1517             SOC_IF_ERROR_RETURN
   1518                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, 0x0000));
   1519             /* disable AN */
   1520             SOC_IF_ERROR_RETURN
   1521                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 0x0));
   1522         }
   1523 
   1524 
   1525         mask16 = PHY84740_RXLOS_OVERRIDE_MASK | PHY84740_MOD_ABS_OVERRIDE_MASK;
   1526         data16 = 0;
   1527 
   1528         RX_LOS(pc) = soc_property_port_get(unit, port, spn_PHY_RX_LOS, 0);
   1529         MOD_ABS(pc) = soc_property_port_get(unit, port, spn_PHY_MOD_ABS, 0);
   1530         RX_LOS_INVERT(pc) =
   1531             soc_property_port_get(unit, port, spn_PHY_RX_LOS_INVERT, 0);
   1532         MOD_ABS_INVERT(pc) =
   1533             soc_property_port_get(unit, port, spn_PHY_MOD_ABS_INVERT, 0);
   1534         MOD_AUTO_DETECT(pc) =
   1535             soc_property_port_get(unit, port, spn_PHY_MOD_AUTO_DETECT, 0);
   1536 
   1537         /* default: override RX_LOS signalling */
   1538         if (!RX_LOS(pc)) {
   1539             data16 |= PHY84740_RXLOS_OVERRIDE_MASK;
   1540         }
   1541         /* default: override MOD_ABS signalling */
   1542         if (!MOD_ABS(pc)) {
   1543             data16 |= PHY84740_MOD_ABS_OVERRIDE_MASK;
   1544         }
   1545 
   1546         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1547             for (ix = 0; ix < NUM_LANES; ix++) {
   1548                 SOC_IF_ERROR_RETURN
   1549                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   1550                                                     PHY84740_PMAD_AER_ADDR_REG,
   1551                                                     ix));
   1552                 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   1553                                     (unit, pc, PHY84740_PMAD_OPTICAL_CFG_REG,
   1554                                      data16, mask16));
   1555             }
   1556         } else {
   1557             SOC_IF_ERROR_RETURN
   1558                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   1559                                                  PHY84740_PMAD_OPTICAL_CFG_REG,
   1560                                                  data16, mask16));
   1561         }
   1562 
   1563         mask16 = PHY84740_RXLOS_LVL_MASK | PHY84740_MOD_ABS_LVL_MASK;
   1564         data16 = 0;
   1565         /* default: RX_LOS level high */
   1566         if (!RX_LOS_INVERT(pc)) {
   1567             data16 |= PHY84740_RXLOS_LVL_MASK;
   1568         }
   1569         /* default: MOD_ABS level high */
   1570         if (!MOD_ABS_INVERT(pc)) {
   1571             data16 |= PHY84740_MOD_ABS_LVL_MASK;
   1572         }
   1573 
   1574         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1575             for (ix = 0; ix < NUM_LANES; ix++) {
   1576                 SOC_IF_ERROR_RETURN
   1577                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   1578                                                     PHY84740_PMAD_AER_ADDR_REG,
   1579                                                     ix));
   1580                 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   1581                                     (unit, pc,
   1582                                      PHY84740_PMAD_OPTICAL_SIG_LVL_REG, data16,
   1583                                      mask16));
   1584             }
   1585             /* point back to lane0 */
   1586             SOC_IF_ERROR_RETURN
   1587                 (WRITE_PHY84740_MMF_PMA_PMD_REG
   1588                  (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   1589         } else {
   1590             SOC_IF_ERROR_RETURN
   1591                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   1592                                                  PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   1593                                                  data16, mask16));
   1594         }
   1595 
   1596         if (soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, 0)) {
   1597             if (!PHY84740_SINGLE_PORT_MODE(pc)) {
   1598                 /* put device in repeat mode. Single port is already in repeat mode */
   1599                 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   1600                                     (unit, pc, 0xc806, 0x6, 0x6));
   1601                 /* in repeater mode, 84740 will use autoneg from internal serdes. But
   1602                  * 84064 will still use cl73/cl72 from ifself.
   1603                  */
   1604                 if (devid != PHY84740_ID_84064) {
   1605                     PCS_REPEATER(pc) = TRUE;
   1606                     PHY_FLAGS_SET(unit, port,
   1607                                   PHY_FLAGS_FIBER | PHY_FLAGS_C45 |
   1608                                   PHY_FLAGS_REPEATER);
   1609                 }
   1610             }
   1611         }
   1612 
   1613         SOC_IF_ERROR_RETURN(_phy_84740_squelch_enable(unit, port, -1, TRUE, FALSE));
   1614 
   1615         if (FCMAP_PASSTHROUGH(pc)) {
   1616             if ((!PHY84740_SINGLE_PORT_MODE(pc)) && (PHY84740_IS_QUADRA(devid))) {
   1617                 /* put device in the fcmap passthrough mode. */
   1618                 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   1619                                     (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0x3,
   1620                                      0x3));
   1621                 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_PMA_PMD_CTRLr
   1622                                     (unit, pc, MII_CTRL_RESET, MII_CTRL_RESET));
   1623             } else {
   1624                 FCMAP_PASSTHROUGH(pc) = FALSE;
   1625             }
   1626         }
   1627 
   1628         /* Polarity configuration */
   1629         SOC_IF_ERROR_RETURN(_phy_84740_polarity_flip_set(unit, port));
   1630 
   1631         /* check if module auto detect enabled */
   1632         if (MOD_AUTO_DETECT(pc)) {
   1633             if ((ucode_ver & 0x0fff) < 0x105) {
   1634                 LOG_ERROR(BSL_LS_SOC_PHY,
   1635                           (BSL_META_U(unit,
   1636                                       "84740 module auto detect requires ucode ver 0x105 or newer: "
   1637                                       "u=%d p%d\n"), unit, port));
   1638             } else if (!(RX_LOS(pc) && MOD_ABS(pc))) {
   1639                 MOD_AUTO_DETECT(pc) = 0;
   1640                 LOG_ERROR(BSL_LS_SOC_PHY,
   1641                           (BSL_META_U(unit,
   1642                                       "84740 module auto detect requires mod_abs and rx_lost "
   1643                                       "to be configured: u=%d p%d\n"), unit, port));
   1644             } else if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1645                 LOG_INFO(BSL_LS_SOC_PHY,
   1646                          (BSL_META_U(unit,
   1647                                      "PHY84740 QSFP module auto detect enabled: u=%d p=%d\n"),
   1648                           unit, port));
   1649                 rv = MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   1650                                                      PHY84740_PMAD_GEN_PURPOSE_REG,
   1651                                                      PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN,
   1652                                                      PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN);
   1653                 if (SOC_FAILURE(rv)) {
   1654                     LOG_ERROR(BSL_LS_SOC_PHY,
   1655                               (BSL_META_U(unit,
   1656                                           "PHY84740 setting QSP module auto detect failed: u=%d p%d\n"),
   1657                                unit, port));
   1658                 } else {
   1659                     MOD_AUTO_DETECT_MSG(pc) = 1;
   1660                 }
   1661             } else if (devid == PHY84740_ID_84754) {
   1662                 LOG_INFO(BSL_LS_SOC_PHY,
   1663                          (BSL_META_U(unit,
   1664                                      "PHY84740 SFP module auto detect on: u=%d p=%d\n"),
   1665                           unit, port));
   1666                 rv = MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   1667                                                      PHY84740_MOD_AUTO_DETECT_STS_REG,
   1668                                                      PHY84740_MOD_AUTO_DETECT_STS_SFP_EN,
   1669                                                      PHY84740_MOD_AUTO_DETECT_STS_SFP_EN);
   1670                 if (SOC_FAILURE(rv)) {
   1671                     LOG_ERROR(BSL_LS_SOC_PHY,
   1672                               (BSL_META_U(unit,
   1673                                           "PHY84740 setting SFP module auto detect failed: u=%d p%d\n"),
   1674                                unit, port));
   1675                 } else {
   1676                     MOD_AUTO_DETECT_MSG(pc) = 1;
   1677                 }
   1678             } else {
   1679                 LOG_ERROR(BSL_LS_SOC_PHY,
   1680                           (BSL_META_U(unit,
   1681                                       "PHY84740 module auto detect not supported: u=%d p%d\n"),
   1682                            unit, port));
   1683             }
   1684         }
   1685     }
   1686 
   1687     if (PHY84740_IS_QUADRA_BACKPLANE(devid)) {
   1688         mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK;
   1689         data16 = PHY84740_PMAD_BKPLANE_MODE_MASK;
   1690         SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   1691                             (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, data16,
   1692                              mask16));
   1693     }
   1694     return SOC_E_NONE;
   1695 }
   1696 
   1697 /*
   1698  * Function:
   1699  *      phy_84740_an_get
   1700  * Purpose:
   1701  *      Get the current auto-negotiation status (enabled/busy)
   1702  * Parameters:
   1703  *      unit - StrataSwitch unit #.
   1704  *      port - StrataSwitch port #.
   1705  *      an   - (OUT) if true, auto-negotiation is enabled.
   1706  *      an_done - (OUT) if true, auto-negotiation is complete. This
   1707  *              value is undefined if an == false.
   1708  * Returns:
   1709  *      SOC_E_XXX
   1710  */
   1711 
   1712 STATIC int phy_84740_an_get(int unit, soc_port_t port, int *an, int *an_done)
   1713 {
   1714     phy_ctrl_t *pc;
   1715     uint16 an_status;
   1716     uint32 devid;
   1717 
   1718     pc = EXT_PHY_SW_STATE(unit, port);
   1719 
   1720     if (FCMAP_PASSTHROUGH(pc)) {
   1721         *an = TRUE;
   1722         *an_done = TRUE;
   1723         return SOC_E_NONE;
   1724     }
   1725 
   1726     SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   1727                         (unit, pc, PHY84740_PMAD_INTR_VALUE_REG, &an_status));
   1728     *an_done = (an_status & PHY84740_AUTONEG_COMPLETE) ? TRUE : FALSE;
   1729 
   1730     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1731         SOC_IF_ERROR_RETURN
   1732             (READ_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, &an_status));
   1733         *an = (an_status & PHY84740_AN_ENABLE) ? TRUE : FALSE;
   1734     } else {
   1735         SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   1736                             (pc->unit, pc->port, pc, &devid));
   1737         if (PHY84740_IS_QUADRA_BACKPLANE(devid)) {
   1738             SOC_IF_ERROR_RETURN
   1739                 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, &an_status));
   1740 
   1741         } else {
   1742             SOC_IF_ERROR_RETURN
   1743                 (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, &an_status));
   1744         }
   1745         *an = (an_status & PHY84740_AN_ENABLE) ? TRUE : FALSE;
   1746 
   1747         /* Confirmed value from 7.0x8309[5]  */
   1748         if (*an == FALSE) {
   1749             SOC_IF_ERROR_RETURN
   1750                 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x8309, &an_status));
   1751             *an = (an_status & (1 << 5)) ?  FALSE : TRUE ;
   1752         }
   1753     }
   1754     return SOC_E_NONE;
   1755 }
   1756 
   1757 /*
   1758  * Function:
   1759  *      phy_84740_an_set
   1760  * Purpose:
   1761  *      Enable or disabled auto-negotiation on the specified port.
   1762  * Parameters:
   1763  *      unit - StrataSwitch unit #.
   1764  *      port - StrataSwitch port #.
   1765  *      an   - Boolean, if true, auto-negotiation is enabled
   1766  *              (and/or restarted). If false, autonegotiation is disabled.
   1767  * Returns:
   1768  *      SOC_E_XXX
   1769  */
   1770 STATIC int phy_84740_an_set(int unit, soc_port_t port, int an)
   1771 {
   1772     phy_ctrl_t *pc;
   1773     phy_ctrl_t *int_pc;
   1774     uint16 mode = 0;
   1775     uint32 devid = 0;
   1776 
   1777     pc = EXT_PHY_SW_STATE(unit, port);
   1778 
   1779     LOG_INFO(BSL_LS_SOC_PHY,
   1780              (BSL_META_U(unit,
   1781                          "phy_84740_an_set: u=%d p=%d an=%d\n"),
   1782                          unit, port, an));
   1783     /* make sure internal autoneg is turned off always */
   1784     int_pc = INT_PHY_SW_STATE(unit, port);
   1785 
   1786     if (FCMAP_PASSTHROUGH(pc)) {
   1787         if (NULL != int_pc) {
   1788             SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET
   1789                                 (int_pc->pd, unit, port, FALSE));
   1790         }
   1791         return SOC_E_NONE;
   1792     }
   1793 
   1794     if (REVERSE_MODE(pc) && IS_HG_PORT(unit, port)) {
   1795         /* Both WC and external phy need to set AN off @ 10G or 40G */
   1796         an = 0;
   1797         if (NULL != int_pc) {
   1798             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1799                 /* 
   1800                  * Internal Serdes needs to be in forced KR4 (a misnomer), meaning
   1801                  * DFE is enabled but cl73 (or cl37) are turned off. This enables
   1802                  * the equalizer as required for KR backplane interfaces
   1803                  */
   1804                 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET
   1805                                     (int_pc->pd, unit, port, 0));
   1806                 SOC_IF_ERROR_RETURN(PHY_INTERFACE_SET
   1807                                     (int_pc->pd, unit, port, SOC_PORT_IF_KR4));
   1808                 SOC_IF_ERROR_RETURN(PHY_SPEED_SET
   1809                                     (int_pc->pd, unit, port, 40000));
   1810 
   1811                 /* disable cl72: 1.96=0 (device 1, register 0x96) */
   1812                 SOC_IF_ERROR_RETURN
   1813                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, 0));
   1814                 /* disable AN: 7.0=0 (device 7, register 0) */
   1815                 SOC_IF_ERROR_RETURN
   1816                     (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 0));
   1817             }
   1818         }
   1819     }
   1820 
   1821     if (NULL != int_pc) {
   1822         if (REVERSE_MODE(pc)) {
   1823             SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET
   1824                                 (int_pc->pd, unit, port, an));
   1825         } else {
   1826             /* if in passthru mode, enable autoneg on internal serdes */
   1827             if (PCS_REPEATER(pc)) {
   1828                 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET
   1829                                     (int_pc->pd, unit, port, an));
   1830             } else {
   1831                 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET
   1832                                     (int_pc->pd, unit, port, FALSE));
   1833             }
   1834         }
   1835     }
   1836 
   1837     /* 0xc700(0xc710 once firmware fixed), PCS link status overide for CR4 autoneg.
   1838      * bit 4 enable override, bit 1 status indication
   1839      * system side link status check in 40G 0xcd04, this is per lane register 
   1840      */
   1841     SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   1842                         (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, &mode));
   1843 
   1844     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1845         /* make sure internal speed is set to 40G */
   1846         if (an) {
   1847             if (NULL != int_pc) {
   1848                 if (!REVERSE_MODE(pc)) {
   1849                     if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) {
   1850                         PHY_INTERFACE_SET(int_pc->pd, unit, port,
   1851                                           SOC_PORT_IF_CR);
   1852                     }
   1853                     SOC_IF_ERROR_RETURN(PHY_SPEED_SET
   1854                                         (int_pc->pd, unit, port, 40000));
   1855                 }
   1856             }
   1857         }
   1858 
   1859         /* autoneg only supported in CR4 mode */
   1860         /* no autoneg if in SR4/LR4 mode */
   1861         if (!(mode &
   1862               (PHY84740_PMAD_DAC_MODE_MASK |
   1863                PHY84740_PMAD_BKPLANE_MODE_MASK)) ||
   1864                (REVERSE_MODE(pc) && IS_HG_PORT(unit, port))) {
   1865             an = 0;
   1866         }
   1867 
   1868         /* enable/disable cl72 */
   1869         SOC_IF_ERROR_RETURN
   1870             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, an ? 2 : 0));
   1871         /* enable/disable AN */
   1872         SOC_IF_ERROR_RETURN
   1873             (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG,
   1874                                        an ? AN_ENABLE | AN_RESTART : 0x0));
   1875 
   1876         return SOC_E_NONE;
   1877     } else {                    /* quad mode, cl73 for backplane */
   1878         if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   1879             /* make sure internal speed is set to 10G */
   1880             if (an) {
   1881                 if (NULL != int_pc) {
   1882                     if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) {
   1883                         PHY_INTERFACE_SET(int_pc->pd, unit, port,
   1884                                           SOC_PORT_IF_CR);
   1885                     }
   1886                     SOC_IF_ERROR_RETURN(PHY_SPEED_SET
   1887                                         (int_pc->pd, unit, port, 10000));
   1888                 }
   1889             }
   1890 
   1891             /* enable/disable cl72 */
   1892             SOC_IF_ERROR_RETURN
   1893                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, an ? 2 : 0));
   1894             /* enable/disable AN */
   1895             SOC_IF_ERROR_RETURN
   1896                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG,
   1897                                            an ? AN_ENABLE | AN_RESTART : 0x0));
   1898         }
   1899     }
   1900 
   1901     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   1902                         (pc->unit, pc->port, pc, &devid));
   1903 
   1904     if (an) {
   1905         /* Enable Clause 37 AN */
   1906         if (!(PHY84740_IS_QUADRA_BACKPLANE(devid))) {
   1907             SOC_IF_ERROR_RETURN
   1908                 (WRITE_PHY84740_MMF_AN_REG
   1909                  (unit, pc, 0xFFE0, MII_CTRL_AE | MII_CTRL_RAN));
   1910         }
   1911         SOC_IF_ERROR_RETURN
   1912             (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8309, 0, (1 << 5)));
   1913     } else {
   1914         /* disable Clause 37 AN */
   1915         if (!(PHY84740_IS_QUADRA_BACKPLANE(devid))) {
   1916             SOC_IF_ERROR_RETURN
   1917                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, 0x0));
   1918         }
   1919         /* Enable encoded forced speed derived from ieeeControl1 and ieeeControl2 */
   1920         SOC_IF_ERROR_RETURN
   1921             (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8309, (1 << 5), (1 << 5)));
   1922     }
   1923 
   1924     return SOC_E_NONE;
   1925 }
   1926 
   1927 /*
   1928  * Function:
   1929  *      phy_84740_ability_advert_get
   1930  * Purpose:
   1931  *      Get the current advertisement for auto-negotiation.
   1932  * Parameters:
   1933  *      unit - StrataSwitch unit #.
   1934  *      port - StrataSwitch port #.
   1935  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1936  * Returns:
   1937  *      SOC_E_XXX
   1938  * Notes:
   1939  *      The advertisement is retrieved for the ACTIVE medium.
   1940  *      No synchronization performed at this level.
   1941  */
   1942 
   1943 STATIC int
   1944 phy_84740_ability_advert_get(int unit, soc_port_t port,
   1945                              soc_port_ability_t *ability)
   1946 {
   1947     uint16 an_adv;
   1948     soc_port_mode_t mode;
   1949     phy_ctrl_t *pc;
   1950 
   1951     if (NULL == ability) {
   1952         return (SOC_E_PARAM);
   1953     }
   1954     pc = EXT_PHY_SW_STATE(unit, port);
   1955 
   1956     if (FCMAP_PASSTHROUGH(pc)) {
   1957         ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   1958         ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   1959         return SOC_E_NONE;
   1960     }
   1961 
   1962     if (PCS_REPEATER(pc)) {
   1963         phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port);
   1964         if (NULL != int_pc) {
   1965             SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_GET
   1966                                 (int_pc->pd, unit, port, ability));
   1967         }
   1968         return SOC_E_NONE;
   1969     }
   1970 
   1971     mode = 0;
   1972     ability->pause = 0;
   1973     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   1974         /* advert register 1 */
   1975         SOC_IF_ERROR_RETURN
   1976             (READ_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, &an_adv));
   1977 
   1978         mode |= (an_adv & AN_ADVERT_40GCR4) ? SOC_PA_SPEED_40GB : 0;
   1979         mode |= (an_adv & AN_ADVERT_40GKR4) ? SOC_PA_SPEED_40GB : 0;
   1980         mode |= (an_adv & AN_ADVERT_10GKR) ? SOC_PA_SPEED_10GB : 0;
   1981         mode |= (an_adv & AN_ADVERT_1GKX) ? SOC_PA_SPEED_1000MB : 0;
   1982         ability->speed_full_duplex = mode;
   1983 
   1984         SOC_IF_ERROR_RETURN
   1985             (READ_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, &an_adv));
   1986 
   1987         switch (an_adv & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) {
   1988             case AN_ADVERT_PAUSE:
   1989                 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   1990                 break;
   1991             case AN_ADVERT_PAUSE_ASYM:
   1992                 ability->pause = SOC_PA_PAUSE_TX;
   1993                 break;
   1994             case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM:
   1995                 ability->pause = SOC_PA_PAUSE_RX;
   1996                 break;
   1997         }
   1998     } else {
   1999         /* check Full Duplex advertisement on Clause 37 */
   2000         SOC_IF_ERROR_RETURN
   2001             (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, &an_adv));
   2002         mode |= (an_adv & MII_ANA_C37_FD) ? SOC_PA_SPEED_1000MB : 0;
   2003 
   2004         ability->speed_full_duplex = mode;
   2005 
   2006         switch (an_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) {
   2007             case MII_ANA_C37_PAUSE:
   2008                 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   2009                 break;
   2010             case MII_ANA_C37_ASYM_PAUSE:
   2011                 ability->pause = SOC_PA_PAUSE_TX;
   2012                 break;
   2013             case MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE:
   2014                 ability->pause = SOC_PA_PAUSE_RX;
   2015                 break;
   2016         }
   2017     }
   2018 
   2019     LOG_INFO(BSL_LS_SOC_PHY,
   2020              (BSL_META_U(unit,
   2021                          "phy_84740_ability_advert_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"),
   2022               unit, port, ability->speed_full_duplex, ability->pause));
   2023     return SOC_E_NONE;
   2024 }
   2025 
   2026 /*
   2027 * Function:
   2028 *      phy_84740_ability_remote_get
   2029 * Purpose:
   2030 *      Get the device's complete abilities.
   2031 * Parameters:
   2032 *      unit - StrataSwitch unit #.
   2033 *      port - StrataSwitch port #.
   2034 *      ability - return device's abilities.
   2035 * Returns:
   2036 *      SOC_E_XXX
   2037 */
   2038 
   2039 STATIC int
   2040 phy_84740_ability_remote_get(int unit, soc_port_t port,
   2041                              soc_port_ability_t *ability)
   2042 {
   2043     phy_ctrl_t *pc;
   2044     uint16 lp_abil;
   2045 
   2046     if (NULL == ability) {
   2047         return SOC_E_PARAM;
   2048     }
   2049 
   2050     pc = EXT_PHY_SW_STATE(unit, port);
   2051 
   2052     if (FCMAP_PASSTHROUGH(pc)) {
   2053         ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   2054         ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   2055         return SOC_E_NONE;
   2056     }
   2057 
   2058     if (PCS_REPEATER(pc)) {
   2059         phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port);
   2060         if (NULL != int_pc) {
   2061             SOC_IF_ERROR_RETURN(PHY_ABILITY_REMOTE_GET
   2062                                 (int_pc->pd, unit, port, ability));
   2063         }
   2064         return SOC_E_NONE;
   2065     }
   2066 
   2067     ability->speed_half_duplex = SOC_PA_ABILITY_NONE;
   2068 
   2069     /* check CL73 first */
   2070     SOC_IF_ERROR_RETURN
   2071         (READ_PHY84740_MMF_AN_REG(unit, pc, AN_LP_ABILITY_1_REG, &lp_abil));
   2072     ability->speed_full_duplex =
   2073         (lp_abil & AN_ADVERT_40GCR4) ? SOC_PA_SPEED_40GB : 0;
   2074     ability->speed_full_duplex |=
   2075         (lp_abil & AN_ADVERT_40GKR4) ? SOC_PA_SPEED_40GB : 0;
   2076     ability->speed_full_duplex |=
   2077         (lp_abil & AN_ADVERT_10GKR) ? SOC_PA_SPEED_10GB : 0;
   2078     ability->speed_full_duplex |=
   2079         (lp_abil & AN_ADVERT_1GKX) ? SOC_PA_SPEED_1000MB : 0;
   2080 
   2081     SOC_IF_ERROR_RETURN
   2082         (READ_PHY84740_MMF_AN_REG(unit, pc, AN_LP_ABILITY_0_REG, &lp_abil));
   2083 
   2084     ability->pause = 0;
   2085     switch (lp_abil & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) {
   2086         case AN_ADVERT_PAUSE:
   2087             ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   2088             break;
   2089         case AN_ADVERT_PAUSE_ASYM:
   2090             ability->pause = SOC_PA_PAUSE_TX;
   2091             break;
   2092         case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM:
   2093             ability->pause = SOC_PA_PAUSE_RX;
   2094             break;
   2095     }
   2096 
   2097     /* check CL37 */
   2098     SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE5, &lp_abil));
   2099     ability->speed_full_duplex |= (lp_abil & MII_ANA_C37_FD) ?
   2100         SOC_PA_SPEED_1000MB : 0;
   2101 
   2102     switch (lp_abil & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) {
   2103         case MII_ANP_C37_PAUSE:
   2104             ability->pause |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   2105             break;
   2106         case MII_ANP_C37_ASYM_PAUSE:
   2107             ability->pause |= SOC_PA_PAUSE_TX;
   2108             break;
   2109         case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE:
   2110             ability->pause |= SOC_PA_PAUSE_RX;
   2111             break;
   2112     }
   2113 
   2114     LOG_INFO(BSL_LS_SOC_PHY,
   2115              (BSL_META_U(unit,
   2116                          "phy_84740_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"),
   2117               unit, port, ability->speed_full_duplex, ability->pause));
   2118 
   2119     return (SOC_E_NONE);
   2120 }
   2121 
   2122 /*
   2123  * Function:
   2124  *      phy_84740_ability_advert_set
   2125  * Purpose:
   2126  *      Set the current advertisement for auto-negotiation.
   2127  * Parameters:
   2128  *      unit - StrataSwitch unit #.
   2129  *      port - StrataSwitch port #.
   2130  *      mode - Port mode mask indicating supported options/speeds.
   2131  * Returns:
   2132  *      SOC_E_XXX
   2133  * Notes:
   2134  *      The advertisement is set only for the ACTIVE medium.
   2135  *      No synchronization performed at this level.
   2136  */
   2137 
   2138 STATIC int
   2139 phy_84740_ability_advert_set(int unit, soc_port_t port,
   2140                              soc_port_ability_t *ability)
   2141 {
   2142     uint16 an_adv, an_adv_cl37, mode;
   2143     phy_ctrl_t *pc;
   2144 
   2145     if (NULL == ability) {
   2146         return (SOC_E_PARAM);
   2147     }
   2148 
   2149     pc = EXT_PHY_SW_STATE(unit, port);
   2150 
   2151     if (FCMAP_PASSTHROUGH(pc)) {
   2152         return SOC_E_NONE;
   2153     }
   2154 
   2155     if (PCS_REPEATER(pc)) {
   2156         phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port);
   2157         if (NULL != int_pc) {
   2158             SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_SET
   2159                                 (int_pc->pd, unit, port, ability));
   2160         }
   2161         return SOC_E_NONE;
   2162     }
   2163 
   2164     SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   2165                         (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, &mode));
   2166 
   2167     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2168         if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   2169             an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_40GB) ?
   2170                 AN_ADVERT_40GKR4 : 0;
   2171             an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ?
   2172                 AN_ADVERT_10GKR : 0;
   2173         } else {
   2174 
   2175             /* only advertise 40G CR4 */
   2176             an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_40GB) ?
   2177                 AN_ADVERT_40GCR4 : 0;
   2178         }
   2179 
   2180         /* CL73 advert register 1 */
   2181         SOC_IF_ERROR_RETURN
   2182             (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, an_adv));
   2183 
   2184     } else {                    /* quad-port mode */
   2185         if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   2186             an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ?
   2187                 AN_ADVERT_10GKR : 0;
   2188             an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ?
   2189                 AN_ADVERT_1GKX : 0;
   2190 
   2191             /* CL73 advert register 1 */
   2192             SOC_IF_ERROR_RETURN
   2193                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, an_adv));
   2194         }
   2195 
   2196         /* only 1G CL37 autoneg */
   2197         an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ?
   2198             AN_ADVERT_1G : 0;
   2199 
   2200         /* write Full Duplex advertisement on Clause 37 */
   2201         SOC_IF_ERROR_RETURN
   2202             (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, an_adv));
   2203     }
   2204 
   2205     an_adv = an_adv_cl37 = 0;
   2206     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   2207         case SOC_PA_PAUSE_TX:
   2208             an_adv = AN_ADVERT_PAUSE_ASYM;
   2209             an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE;
   2210             break;
   2211         case SOC_PA_PAUSE_RX:
   2212             an_adv = AN_ADVERT_PAUSE_ASYM | AN_ADVERT_PAUSE;
   2213             an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE;
   2214             break;
   2215         case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   2216             an_adv_cl37 = MII_ANA_C37_PAUSE;
   2217             an_adv = AN_ADVERT_PAUSE;
   2218             break;
   2219     }
   2220     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2221         SOC_IF_ERROR_RETURN
   2222             (MODIFY_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, an_adv,
   2223                                         AN_ADVERT_PAUSE |
   2224                                         AN_ADVERT_PAUSE_ASYM));
   2225     } else {
   2226         if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   2227             SOC_IF_ERROR_RETURN
   2228                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, an_adv,
   2229                                             AN_ADVERT_PAUSE |
   2230                                             AN_ADVERT_PAUSE_ASYM));
   2231         }
   2232 
   2233         /* write Pause advertisement on Clause 37 */
   2234         SOC_IF_ERROR_RETURN
   2235             (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, an_adv_cl37,
   2236                                         MII_ANA_C37_ASYM_PAUSE |
   2237                                         MII_ANA_C37_PAUSE));
   2238     }
   2239 
   2240     LOG_INFO(BSL_LS_SOC_PHY,
   2241              (BSL_META_U(unit,
   2242                          "phy_8072_ability_advert_set: u=%d p=%d pause=0x%08x adv_reg1=0x%04x\n"),
   2243               unit, port, ability->pause, an_adv));
   2244         
   2245     return SOC_E_NONE;
   2246 }
   2247 
   2248 /*
   2249  * Function:
   2250  *      phy_84740_ability_local_get
   2251  * Purpose:
   2252  *      Get the device's complete abilities.
   2253  * Parameters:
   2254  *      unit - StrataSwitch unit #.
   2255  *      port - StrataSwitch port #.
   2256  *      ability - return device's abilities.
   2257  * Returns:
   2258  *      SOC_E_XXX
   2259  */
   2260 
   2261 STATIC int
   2262 phy_84740_ability_local_get(int unit, soc_port_t port,
   2263                             soc_port_ability_t *ability)
   2264 {
   2265     phy_ctrl_t *pc;
   2266     phy_ctrl_t *int_pc;
   2267     uint32 pa_speed = 0;
   2268     
   2269     pc = EXT_PHY_SW_STATE(unit, port);
   2270     int_pc = INT_PHY_SW_STATE(unit, port);
   2271 
   2272     LOG_INFO(BSL_LS_SOC_PHY,
   2273              (BSL_META_U(unit,
   2274                          "phy_84740_ability_local_get: u=%d p=%d\n"),
   2275               unit, port));
   2276                                                                                
   2277     if (NULL == ability) {
   2278         return SOC_E_PARAM;
   2279     }
   2280 
   2281     if (FCMAP_PASSTHROUGH(pc)) {
   2282         ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   2283         ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   2284         return SOC_E_NONE;
   2285     }
   2286 
   2287     if (NULL != int_pc && PCS_REPEATER(pc)) {
   2288         SOC_IF_ERROR_RETURN(PHY_ABILITY_LOCAL_GET
   2289                             (int_pc->pd, unit, port, ability));
   2290         return SOC_E_NONE;
   2291     }
   2292     ability->speed_half_duplex = SOC_PA_ABILITY_NONE;
   2293 
   2294     pa_speed = PHY84740_SINGLE_PORT_MODE(pc) ? SOC_PA_SPEED_40GB : 
   2295                 SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB;
   2296     ability->speed_full_duplex = pa_speed;
   2297     
   2298     ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   2299     ability->interface = SOC_PA_INTF_XGMII;
   2300     ability->medium = SOC_PA_MEDIUM_FIBER;
   2301     ability->loopback = SOC_PA_LB_PHY;
   2302     ability->flags = SOC_PA_AUTONEG;
   2303 
   2304     LOG_INFO(BSL_LS_SOC_PHY,
   2305              (BSL_META_U(unit,
   2306                          "phy_84740_ability_local_get: u=%d p=%d speed=0x%x\n"),
   2307               unit, port, ability->speed_full_duplex));
   2308 
   2309     return (SOC_E_NONE);
   2310 }
   2311 
   2312 STATIC int _phy84740_mod_auto_detect_update(int unit, soc_port_t port)
   2313 {
   2314     phy_ctrl_t *pc;
   2315     uint16 data;
   2316     uint16 status;
   2317 
   2318     pc = EXT_PHY_SW_STATE(unit, port);
   2319 
   2320     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2321         /* point to lane 0 */
   2322         SOC_IF_ERROR_RETURN
   2323             (WRITE_PHY84740_MMF_PMA_PMD_REG
   2324              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   2325     }
   2326 
   2327     /* check for presence */
   2328     SOC_IF_ERROR_RETURN
   2329         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2330                                        PHY84740_PMAD_OPTICAL_CFG_REG, &data));
   2331     if (data & PHY84740_PMAD_OPTICAL_CFG_MOD_PRESENCE) {
   2332         SOC_IF_ERROR_RETURN
   2333             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2334                                            PHY84740_MOD_AUTO_DETECT_STS_REG,
   2335                                            &status));
   2336         /* make sure auto detection completed */
   2337         if (!(status & PHY84740_MOD_AUTO_DETECT_STS_NOT_DONE)) {
   2338             if (MOD_AUTO_DETECT_MSG(pc)) {
   2339                 /* present and must print message */
   2340                 MOD_AUTO_DETECT_MSG(pc) = 0;
   2341                 if (status & PHY84740_MOD_AUTO_DETECT_STS_NOT_RES) {
   2342                     uint16 mod_130 = 0, mod_131 = 0;
   2343                     (void)(READ_PHY84740_MMF_PMA_PMD_REG
   2344                            (unit, pc, 0x81f2, &mod_130));
   2345                     (void)(READ_PHY84740_MMF_PMA_PMD_REG
   2346                            (unit, pc, 0x81f3, &mod_131));
   2347                     LOG_ERROR(BSL_LS_SOC_PHY,
   2348                               (BSL_META_U(unit,
   2349                                           "PHY84740 could not detect module, "
   2350                                           "defaulting to SR(4): u=%d p=%d sts=0x%x (0x%x:0x%x)\n"),
   2351                                unit, port, status, mod_130, mod_131));
   2352                 } else {
   2353                     /* auto detect done and successfully resolved */
   2354                     SOC_IF_ERROR_RETURN
   2355                         (READ_PHY84740_MMF_PMA_PMD_REG
   2356                          (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, &data));
   2357                     LOG_VERBOSE(BSL_LS_SOC_PHY,
   2358                               (BSL_META_U(unit,
   2359                                           "PHY84740 %s module detected: u=%d p=%d\n"),
   2360                                (data & PHY84740_PMAD_DAC_MODE_MASK) ?
   2361                                "CR4" : "SR4", unit, port));
   2362                 }
   2363             }
   2364         } else if (!(status & PHY84740_MOD_AUTO_DETECT_STS_I2C_FAIL) &&
   2365                    (MOD_AUTO_DETECT_MSG(pc))) {
   2366             uint16 mod_130 = 0, mod_131 = 0;
   2367             (void)(READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f2, &mod_130));
   2368             (void)(READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f3, &mod_131));
   2369             MOD_AUTO_DETECT_MSG(pc) = 0;
   2370             LOG_ERROR(BSL_LS_SOC_PHY,
   2371                       (BSL_META_U(unit,
   2372                                   "PHY84740 i2c failed while detecting module, "
   2373                                   "defaulting to SR(4): u=%d p=%d sts=0x%x (0x%x:0x%x)\n"),
   2374                        unit, port, status, mod_130, mod_131));
   2375         }
   2376     } else {
   2377         if (!MOD_AUTO_DETECT_MSG(pc)) {
   2378             /* module not present */
   2379             LOG_VERBOSE(BSL_LS_SOC_PHY,
   2380                       (BSL_META_U(unit,
   2381                                   "PHY84740 module removed u=%d p=%d\n"),
   2382                        unit, port));
   2383             MOD_AUTO_DETECT_MSG(pc) = 1;
   2384         }
   2385     }
   2386     return SOC_E_NONE;
   2387 }
   2388 
   2389 /*
   2390  * Function:
   2391  *    phy_84740_link_get
   2392  * Purpose:
   2393  *    Get layer2 connection status.
   2394  * Parameters:
   2395  *    unit - StrataSwitch unit #.
   2396  *    port - StrataSwitch port #. 
   2397  *      link - address of memory to store link up/down state.
   2398  * Returns:    
   2399  *    SOC_E_NONE
   2400  */
   2401 STATIC int phy_84740_link_get(int unit, soc_port_t port, int *link)
   2402 {
   2403     uint16 pma_mii_stat, pcs_mii_stat, link_stat;
   2404     phy_ctrl_t *pc;
   2405     phy_ctrl_t *int_pc;
   2406     int cur_speed = 0;
   2407     int an = 0, an_done = 0;
   2408     uint16 speed_val;
   2409     uint32 devid;
   2410     int rv;
   2411 
   2412     if (link == NULL) {
   2413         return SOC_E_NONE;
   2414     }
   2415 
   2416     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   2417         *link = FALSE;
   2418         return SOC_E_NONE;
   2419     }
   2420 
   2421     pc = EXT_PHY_SW_STATE(unit, port);
   2422     int_pc = INT_PHY_SW_STATE(unit, port);
   2423 
   2424     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   2425                         (pc->unit, pc->port, pc, &devid));
   2426 
   2427     if (!REVERSE_MODE(pc)) {
   2428         if (PCS_REPEATER(pc)) {
   2429             rv = PHY_LINK_GET(int_pc->pd, unit, port, link);
   2430             return rv;
   2431         }
   2432         if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_REPEATER)) {
   2433             rv = PHY_LINK_GET(int_pc->pd, unit, port, link);
   2434         }
   2435     }
   2436     if (FCMAP_PASSTHROUGH(pc)) {
   2437         rv = PHY_LINK_GET(int_pc->pd, unit, port, link);
   2438         return rv;
   2439     }
   2440 
   2441     phy_84740_an_get(unit, port, &an, &an_done);
   2442 
   2443     /* only supports 40G. PHY PCS is not used. Check PMD link only  */
   2444     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2445         int serdes_link = TRUE;
   2446 
   2447         if (REVERSE_MODE(pc)) {
   2448             SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   2449         }
   2450 
   2451         SOC_IF_ERROR_RETURN
   2452             (READ_PHY84740_PMA_PMD_STATr(unit, pc, &pma_mii_stat));
   2453         *link = pma_mii_stat == 0xffff ? FALSE :
   2454             ((pma_mii_stat & MII_STAT_LA) ? TRUE : FALSE);
   2455 
   2456         if (REVERSE_MODE(pc)) {
   2457             SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   2458         }
   2459 
   2460         if ((NULL != int_pc) && an) {
   2461             PHY_LINK_GET(int_pc->pd, unit, port, &serdes_link);
   2462         }
   2463 
   2464         if (MOD_AUTO_DETECT(pc)) {
   2465             _phy84740_mod_auto_detect_update(unit, port);
   2466         }
   2467 
   2468         *link = (*link) && serdes_link;
   2469         return SOC_E_NONE;
   2470     }
   2471 
   2472     /* return link false if in the middle of autoneg */
   2473     if (an == TRUE && an_done == FALSE) {
   2474         *link = FALSE;
   2475         return SOC_E_NONE;
   2476     }
   2477 
   2478     /* AN only supports 1G */
   2479     if (!an) {
   2480         SOC_IF_ERROR_RETURN
   2481             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CTRL2_REG,
   2482                                            &speed_val));
   2483         if ((speed_val & PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK) !=
   2484             PHY84740_PMAD_CTRL2r_PMA_TYPE_1G_KX) {
   2485             cur_speed = 10000;
   2486         }
   2487     } else {
   2488         if (PHY84740_IS_QUADRA(devid)) {
   2489             SOC_IF_ERROR_RETURN
   2490                 (READ_PHY84740_MMF_PMA_PMD_REG
   2491                  (unit, pc, PHY84740_SPEED_LINK_DETECT_STAT_REG, &speed_val));
   2492 
   2493             if (speed_val & PHY84740_AN_SPEED_1G_MASK) {
   2494                 cur_speed = 1000;
   2495             } else if (speed_val & PHY84740_AN_SPEED_10G_MASK) {
   2496                 cur_speed = 10000;
   2497             } else {
   2498                 cur_speed = 1000;
   2499             }
   2500         } else {
   2501             cur_speed = 1000;
   2502         }
   2503     }
   2504 
   2505     if (REVERSE_MODE(pc)) {
   2506         SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   2507     }
   2508 
   2509     if (cur_speed == 10000) {   /* check all 3 device's link status if 10G */
   2510 
   2511         /* MMF Link status */
   2512         /* Read Status 2 register to get rid of Local faults */
   2513         SOC_IF_ERROR_RETURN
   2514             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_STAT2_REG,
   2515                                            &pma_mii_stat));
   2516         SOC_IF_ERROR_RETURN
   2517             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_STAT2_REG,
   2518                                            &pma_mii_stat));
   2519         /* Receive Link status */
   2520         SOC_IF_ERROR_RETURN(READ_PHY84740_PCS_STATr(unit, pc, &pcs_mii_stat));
   2521 
   2522         SOC_IF_ERROR_RETURN
   2523             (READ_PHY84740_PMA_PMD_STATr(unit, pc, &pma_mii_stat));
   2524 
   2525         /* MMF link status */
   2526         link_stat = pma_mii_stat & pcs_mii_stat;
   2527         *link = link_stat == 0xffff ? FALSE :
   2528             ((link_stat & MII_STAT_LA) ? TRUE : FALSE);
   2529     } else {
   2530         SOC_IF_ERROR_RETURN
   2531             (READ_PHY84740_MMF_AN_REG(unit, pc, 0xffe1, &link_stat));
   2532         *link = link_stat == 0xffff ? FALSE :
   2533             ((link_stat & MII_STAT_LA) ? TRUE : FALSE);
   2534     }
   2535 
   2536     if (REVERSE_MODE(pc)) {
   2537         SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   2538     }
   2539 
   2540 	if (MOD_AUTO_DETECT(pc)) {
   2541 		_phy84740_mod_auto_detect_update(unit, port);
   2542 	}
   2543     LOG_VERBOSE(BSL_LS_SOC_PHY,
   2544                 (BSL_META_U(unit,
   2545                             "phy_84740_link_get: u=%d port%d: link:%s\n"),
   2546                  unit, port, *link ? "Up": "Down"));
   2547 
   2548     return SOC_E_NONE;
   2549 }
   2550 
   2551 /*
   2552  * Function:
   2553  *    phy_84740_enable_set
   2554  * Purpose:
   2555  *    Enable/Disable phy 
   2556  * Parameters:
   2557  *    unit - StrataSwitch unit #.
   2558  *    port - StrataSwitch port #. 
   2559  *      enable - on/off state to set
   2560  * Returns:    
   2561  *    SOC_E_NONE
   2562  */
   2563 
   2564 STATIC int phy_84740_enable_set(int unit, soc_port_t port, int enable)
   2565 {
   2566     uint16 data;                /* Holder for new value to write to PHY reg */
   2567     uint16 mask;                /* Holder for bit mask to update in PHY reg */
   2568     int ix;
   2569     uint16 tx_ctrl;
   2570     phy_ctrl_t *pc;
   2571 
   2572     pc = EXT_PHY_SW_STATE(unit, port);
   2573     if (enable) {
   2574         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
   2575     } else {
   2576         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
   2577     }
   2578 
   2579     if (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) {
   2580         SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   2581     }
   2582 
   2583     if (SINGLE_LPMODE(pc) && !(PHY84740_SINGLE_PORT_MODE(pc))) {
   2584         /* Use 1.cd16 to disable tx */
   2585         data = enable ? 0 : (1 << 3);
   2586         mask = 1 << 3;
   2587         SOC_IF_ERROR_RETURN
   2588             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   2589              (unit, pc, PHY84740_GENSIG_8071_REGISTER, data, mask));
   2590     } else {
   2591         /* TX transmitter enable/disable. BCST register in single-port mode */
   2592         data = enable ? 0 : (1 << 0);
   2593         mask = 1 << 0;          /* Global PMD transmit disable */
   2594         SOC_IF_ERROR_RETURN
   2595             (MODIFY_PHY84740_PMA_PMD_TX_DISABLEr(unit, pc, data, mask));
   2596     }
   2597 
   2598     if (REVERSE_MODE(pc)) {
   2599         SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   2600     }
   2601 
   2602     for (ix = 0; ix < NUM_LANES; ix++) {
   2603         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2604             SOC_IF_ERROR_RETURN
   2605                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2606                                                 PHY84740_PMAD_AER_ADDR_REG,
   2607                                                 ix));
   2608         }
   2609 
   2610         /* TxOn control */
   2611         SOC_IF_ERROR_RETURN
   2612             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2613                                              PHY84740_PMAD_OPTICAL_CFG_REG,
   2614                                              enable ? 0 : (1 << 12),
   2615                                              (1 << 12)));
   2616         if (enable) {
   2617             SOC_IF_ERROR_RETURN
   2618                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2619                                                PHY84740_PMAD_OPTICAL_CFG_REG,
   2620                                                &data));
   2621 
   2622             /* c8e4[4] indicates the TX active state when c8e4[12]=0. 0 means TX 
   2623              * active, 1 means low power mode. This state = TxOnOff pin XOR c800[7]
   2624              * Toggle 0xc800[7] to enable the Tx when c8e4[4]=1.
   2625              * The default value of c800[7] is 1, if user straps the TxOnOff to 0,
   2626              * Then the Tx won't be enabled until this function is called.
   2627              */
   2628 
   2629             SOC_IF_ERROR_RETURN
   2630                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2631                                                PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   2632                                                &tx_ctrl));
   2633             tx_ctrl &= (1 << 7);
   2634             if (data & (1 << 4)) {
   2635                 SOC_IF_ERROR_RETURN
   2636                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2637                                                      PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   2638                                                      tx_ctrl ? 0 : (1 << 7),
   2639                                                      (1 << 7)));
   2640             }
   2641         }
   2642         /* power on/off the lane */
   2643         SOC_IF_ERROR_RETURN
   2644             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2645                                              PHY84740_PMAD_OPTICAL_CFG_REG,
   2646                                              enable ? 0 : (1 << 4), (1 << 4)));
   2647         if (!PHY84740_SINGLE_PORT_MODE(pc)) {
   2648             break;
   2649         }
   2650     }
   2651     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2652         /* point back to lane0 */
   2653         SOC_IF_ERROR_RETURN
   2654             (WRITE_PHY84740_MMF_PMA_PMD_REG
   2655              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   2656     }
   2657     return (SOC_E_NONE);
   2658 }
   2659 
   2660 /*
   2661  * Function:
   2662  *    phy_84740_lb_set
   2663  * Purpose:
   2664  *    Put 84740 in PHY PMA/PMD loopback
   2665  * Parameters:
   2666  *    unit - StrataSwitch unit #.
   2667  *    port - StrataSwitch port #. 
   2668  *      enable - binary value for on/off (1/0)
   2669  * Returns:    
   2670  *    SOC_E_NONE
   2671  */
   2672 
   2673 STATIC int phy_84740_lb_set(int unit, soc_port_t port, int enable)
   2674 {
   2675     phy_ctrl_t *pc;
   2676     uint16 tmp;
   2677     uint16 lane;
   2678     uint16 data16 = 0, mask16 = 0;
   2679     int intf_tx;
   2680     int intf_rx;
   2681 
   2682     pc = EXT_PHY_SW_STATE(unit, port);
   2683     
   2684     intf_tx = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ?
   2685         PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
   2686 
   2687     intf_rx = ( intf_tx ==  PHY_DIAG_INTF_LINE ) ?
   2688         PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
   2689 
   2690     /* TX Enable(Disable) Squelch(FORCE) when we  Enable(Disable) loopback */
   2691     SOC_IF_ERROR_RETURN
   2692         (_phy_84740_squelch_enable(unit, port,
   2693         intf_tx, enable ? TRUE : FALSE,  enable ? TRUE : FALSE ));
   2694 
   2695     /* RX Disable(Enable) Squelch when we  Enable(Disable) loopback */
   2696     SOC_IF_ERROR_RETURN
   2697         (_phy_84740_squelch_enable(unit, port,
   2698         intf_rx, enable ? FALSE : TRUE, /* force = */ FALSE));
   2699 
   2700     tmp = enable ? PHY84740_MII_CTRL_PMA_LOOPBACK : 0;
   2701 
   2702     if (REVERSE_MODE(pc)) {
   2703         SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   2704     }
   2705 
   2706     SOC_IF_ERROR_RETURN
   2707         (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc,
   2708                                        tmp, PHY84740_MII_CTRL_PMA_LOOPBACK));
   2709 
   2710     if (PCS_REPEATER(pc)) {
   2711         if ((PHY84740_SINGLE_PORT_MODE(pc))) {
   2712             for (lane = 0; lane < NUM_LANES; lane++) {
   2713                 data16 = 0;
   2714 
   2715                 /* point to the each lane starting at lane0 */
   2716                 SOC_IF_ERROR_RETURN
   2717                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2718                                                     PHY84740_PMAD_AER_ADDR_REG,
   2719                                                     lane));
   2720 
   2721                 SOC_IF_ERROR_RETURN
   2722                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0a,
   2723                                                      enable ? 1 : 0, 1));
   2724 
   2725                 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2726                                                                   PHY84740_DIG_CTRL_REG,
   2727                                                                   &data16));
   2728 
   2729                 /* 1.cd08.10 = 1.cd08.10  XOR 1.cd08.9 */
   2730                 tmp = (data16 & PHY84740_RX_POLARITY_FLIP_MASK) << 1;
   2731                 data16 = (data16 & PHY84740_TX_POLARITY_FLIP_MASK) ^ tmp;
   2732                 mask16 = PHY84740_TX_POLARITY_FLIP_MASK;
   2733 
   2734                 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2735                                                                     PHY84740_DIG_CTRL_REG,
   2736                                                                     data16,
   2737                                                                     mask16));
   2738             }
   2739             /* point back to lane0 */
   2740             SOC_IF_ERROR_RETURN
   2741                 (WRITE_PHY84740_MMF_PMA_PMD_REG
   2742                  (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   2743         } else {                /* quad-port mode */
   2744             data16 = 0;
   2745             SOC_IF_ERROR_RETURN
   2746                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0a,
   2747                                                  enable ? 1 : 0, 1));
   2748 
   2749             SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2750                                                               PHY84740_DIG_CTRL_REG,
   2751                                                               &data16));
   2752 
   2753             /* 1.cd08.10 = 1.cd08.10  XOR 1.cd08.9 */
   2754             tmp = (data16 & PHY84740_RX_POLARITY_FLIP_MASK) << 1;
   2755             data16 = (data16 & PHY84740_TX_POLARITY_FLIP_MASK) ^ tmp;
   2756             mask16 = PHY84740_TX_POLARITY_FLIP_MASK;
   2757 
   2758             SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   2759                                 (unit, pc, PHY84740_DIG_CTRL_REG, data16,
   2760                                  mask16));
   2761         }
   2762     }
   2763 
   2764     if (REVERSE_MODE(pc)) {
   2765         SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   2766     }
   2767 
   2768     return SOC_E_NONE;
   2769 }
   2770 
   2771 /*
   2772  * Function:
   2773  *    phy_84740_lb_get
   2774  * Purpose:
   2775  *    Get 84740 PHY loopback state
   2776  * Parameters:
   2777  *    unit - StrataSwitch unit #.
   2778  *    port - StrataSwitch port #. 
   2779  *      enable - address of location to store binary value for on/off (1/0)
   2780  * Returns:    
   2781  *    SOC_E_NONE
   2782  */
   2783 
   2784 STATIC int phy_84740_lb_get(int unit, soc_port_t port, int *enable)
   2785 {
   2786     uint16 tmp;
   2787     phy_ctrl_t *pc;
   2788 
   2789     pc = EXT_PHY_SW_STATE(unit, port);
   2790 
   2791     if (REVERSE_MODE(pc)) {
   2792         SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   2793     }
   2794 
   2795     SOC_IF_ERROR_RETURN(READ_PHY84740_PMA_PMD_CTRLr(unit, pc, &tmp));
   2796     /* ctrl != 0xffff check is to handle removable PHY daughter cards */
   2797     *enable = ((tmp != 0xffff) &&
   2798                (tmp & PHY84740_MII_CTRL_PMA_LOOPBACK)) ? TRUE : FALSE;
   2799 
   2800     if (REVERSE_MODE(pc)) {
   2801         SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   2802     }
   2803 
   2804     LOG_INFO(BSL_LS_SOC_PHY,
   2805              (BSL_META_U(unit,
   2806                          "phy_84740_lb_get: u=%d port%d: loopback:%s\n"),
   2807               unit, port, *enable ? "Enabled": "Disabled"));
   2808     
   2809     return SOC_E_NONE;
   2810 }
   2811 
   2812 STATIC int
   2813 _phy_84740_control_tx_driver_set(int unit, soc_port_t port, int interface,
   2814                                  soc_phy_control_t type, uint32 value)
   2815 {
   2816     uint16 data;                /* Temporary holder of reg value to be written */
   2817     uint16 mask;                /* Bit mask of reg value to be updated */
   2818     int ix;
   2819     int lane;
   2820     int start;
   2821     int end;
   2822     uint16 post_pre_tap = 0, force_preemph = 0;
   2823     uint16 main_tap = 0;
   2824     phy_ctrl_t *pc;             /* PHY software state */
   2825     int reg;
   2826     uint16 post_tap2 = 0;
   2827     uint32 devid = 0;
   2828 
   2829     pc = EXT_PHY_SW_STATE(unit, port);
   2830 
   2831     switch (type) {
   2832         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   2833             /* fall through */
   2834         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   2835             /* fall through */
   2836         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   2837             /* fall through */
   2838         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   2839             /* fall through */
   2840         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   2841             data = (uint16) (value & 0xf);
   2842             data = data << 12;
   2843             mask = 0xf000;
   2844             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
   2845             if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0) {
   2846                 lane = 0;
   2847             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1) {
   2848                 lane = 1;
   2849             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2) {
   2850                 lane = 2;
   2851             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3) {
   2852                 lane = 3;
   2853             } else {            /* SOC_PHY_CONTROL_DRIVER_CURRENT */
   2854                 lane = 4;       /* all lanes */
   2855             }
   2856             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2857                 start = lane == 4 ? 0 : lane;
   2858                 end = lane == 4 ? 4 : lane + 1;
   2859                 for (ix = start; ix < end; ix++) {
   2860 
   2861                     PHY84740_MMF_IF_INTF(unit, pc, interface,
   2862                                          PHY_DIAG_INTF_SYS);
   2863 
   2864                     SOC_IF_ERROR_RETURN
   2865                         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   2866                                                         PHY84740_PMAD_AER_ADDR_REG,
   2867                                                         P2L_MAP(pc, ix)));
   2868 
   2869                     PHY84740_XFI_IF_INTF(unit, pc, interface,
   2870                                          PHY_DIAG_INTF_SYS);
   2871 
   2872                     SOC_IF_ERROR_RETURN
   2873                         (MODIFY_PHY84740_MMF_PMA_PMD_REG
   2874                          (unit, pc, reg, data, mask));
   2875                 }
   2876             } else {
   2877                 SOC_IF_ERROR_RETURN
   2878                     (MODIFY_PHY84740_MMF_PMA_PMD_REG
   2879                      (unit, pc, reg, data, mask));
   2880             }
   2881             break;
   2882 
   2883         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   2884             /* fall through */
   2885         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   2886             /* fall through */
   2887         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   2888             /* fall through */
   2889         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   2890             /* fall through */
   2891         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   2892             data = (uint16) (value & 0xf);
   2893             data = data << 8;
   2894             mask = 0x0f00;
   2895             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
   2896             if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0) {
   2897                 lane = 0;
   2898             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1) {
   2899                 lane = 1;
   2900             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2) {
   2901                 lane = 2;
   2902             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3) {
   2903                 lane = 3;
   2904             } else {            /* SOC_PHY_CONTROL_PRE_DRIVER_CURRENT */
   2905                 lane = 4;       /* all lanes */
   2906             }
   2907             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2908                 start = lane == 4 ? 0 : lane;
   2909                 end = lane == 4 ? 4 : lane + 1;
   2910                 for (ix = start; ix < end; ix++) {
   2911 
   2912                     PHY84740_MMF_IF_INTF(unit, pc, interface,
   2913                                          PHY_DIAG_INTF_SYS);
   2914                     SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   2915                                         (unit, pc, PHY84740_PMAD_AER_ADDR_REG,
   2916                                          P2L_MAP(pc, ix)));
   2917 
   2918                     PHY84740_XFI_IF_INTF(unit, pc, interface,
   2919                                          PHY_DIAG_INTF_SYS);
   2920                     SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   2921                                         (unit, pc, reg, data, mask));
   2922                 }
   2923             } else {
   2924                 SOC_IF_ERROR_RETURN
   2925                     (MODIFY_PHY84740_MMF_PMA_PMD_REG
   2926                      (unit, pc, reg, data, mask));
   2927             }
   2928             break;
   2929         case SOC_PHY_CONTROL_PREEMPHASIS:
   2930             /* fall through */
   2931         case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   2932             /* fall through */
   2933         case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   2934             /* fall through */
   2935         case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   2936             /* fall through */
   2937         case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   2938             /* The value format:
   2939              * bit 16:18: post_tap2 value
   2940              * bit 15:  1 enable forced preemphasis ctrl, 0 auto config
   2941              * bit 14:10:  post_tap value
   2942              * bit 09:04:  main tap value
   2943              * bit 03:00:  pre_tap value 
   2944              * 
   2945              * set 1.CA07[8] = 0, 1.CA02[15:11] for main_tap and 1.CA05[7:4] for post tap.
   2946              * main tap control is in the register field 0xCA02[15:11]. 
   2947              * If a wrong value is written to the same register, field 0xCA02[9:7],
   2948              *  it may DAMAGE the device. User must avoid writing to 0xCA02[9:7] 
   2949              */
   2950             /* Register bit8, 0 force preemphasis, 1 auto config, 1.CA07 */
   2951             force_preemph = PHY84740_PREEMPH_GET_FORCE(value) ? 0 :
   2952                 PHY84740_PREEMPH_REG_FORCE_MASK;
   2953 
   2954             /* add post tap value */
   2955             post_pre_tap = PHY84740_PREEMPH_GET_POST_TAP(value) <<
   2956                 PHY84740_PREEMPH_REG_POST_TAP_SHFT;
   2957 
   2958             /* add pre tap value */
   2959             post_pre_tap |= PHY84740_PREEMPH_GET_PRE_TAP(value) <<
   2960                 PHY84740_PREEMPH_REG_PRE_TAP_SHFT;
   2961 
   2962             /* main tap in 1.CA02 */
   2963             main_tap = PHY84740_PREEMPH_GET_MAIN_TAP(value) <<
   2964                 PHY84740_PREEMPH_REG_MAIN_TAP_SHFT;
   2965 
   2966             post_tap2 = PHY84740_PREEMP_GET_POST_TAP2(value) <<
   2967                 PHY84740_PREEMPH_REG_POST_TAP2_SHFT;
   2968 
   2969             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca06;
   2970 
   2971             if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) {
   2972                 lane = 0;
   2973             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) {
   2974                 lane = 1;
   2975             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) {
   2976                 lane = 2;
   2977             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) {
   2978                 lane = 3;
   2979             } else {            /* SOC_PHY_CONTROL_PREEMPHASIS_LANE */
   2980                 lane = 4;       /* all lanes */
   2981             }
   2982             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2983                 start = lane == 4 ? 0 : lane;
   2984                 end = lane == 4 ? 4 : lane + 1;
   2985             } else {
   2986                 /* just make sure execute once */
   2987                 start = 0;
   2988                 end = 1;
   2989             }
   2990             for (ix = start; ix < end; ix++) {
   2991                 if (PHY84740_SINGLE_PORT_MODE(pc)) {
   2992 
   2993                     PHY84740_MMF_IF_INTF(unit, pc, interface,
   2994                                          PHY_DIAG_INTF_SYS);
   2995                     SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   2996                                         (unit, pc, PHY84740_PMAD_AER_ADDR_REG,
   2997                                          P2L_MAP(pc, ix)));
   2998                     PHY84740_XFI_IF_INTF(unit, pc, interface,
   2999                                          PHY_DIAG_INTF_SYS);
   3000                 }
   3001                 SOC_IF_ERROR_RETURN
   3002                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg,
   3003                                                      post_pre_tap,
   3004                                                      PHY84740_PREEMPH_REG_POST_TAP_MASK
   3005                                                      |
   3006                                                      PHY84740_PREEMPH_REG_PRE_TAP_MASK));
   3007 
   3008                 /* N/A on system side */
   3009                 if (interface != PHY_DIAG_INTF_SYS) {
   3010                     SOC_IF_ERROR_RETURN
   3011                         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca07,
   3012                                                          force_preemph,
   3013                                                          PHY84740_PREEMPH_REG_FORCE_MASK));
   3014                 }
   3015 
   3016                 /* always clear tx_pwrdn bit. The read/modify/write may accidently
   3017                  * set the bit 0xCA02[10]. Because the CA02[10] read value is: 
   3018                  * CA02[10]_read_value = CA02[10] OR Digital_State_Machine 
   3019                  * The problem will occur when the Digital_State_Machine output is 1
   3020                  * at the time of reading this register.
   3021                  */
   3022                 SOC_IF_ERROR_RETURN
   3023                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3024                                                      (interface ==
   3025                                                       PHY_DIAG_INTF_SYS) ?
   3026                                                      0xc90b : 0xca02, main_tap,
   3027                                                      PHY84740_PREEMPH_REG_MAIN_TAP_MASK
   3028                                                      |
   3029                                                      PHY84740_PREEMPH_REG_TX_PWRDN_MASK));
   3030 
   3031                 SOC_IF_ERROR_RETURN
   3032                     (_phy_84740_config_devid(pc->unit, pc->port, pc, &devid));
   3033 
   3034                 /* Only Quadra devices have post tap 2 */
   3035                 /* Initialize to zero if i) 40G ii) Backplane package iii) system side */
   3036                 if (PHY84740_IS_QUADRA(devid)) {
   3037                     if (PHY84740_SINGLE_PORT_MODE(pc) ||
   3038                         (interface == PHY_DIAG_INTF_SYS) ||
   3039                         (PHY84740_IS_QUADRA_BACKPLANE(devid))) {
   3040                         SOC_IF_ERROR_RETURN
   3041                             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3042                                                              0xca08,
   3043                                                              0x0,
   3044                                                              PHY84740_PREEMPH_REG_POST_TAP2_MASK));
   3045                     } else {
   3046                         SOC_IF_ERROR_RETURN
   3047                             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3048                                                              0xca08,
   3049                                                              post_tap2,
   3050                                                              PHY84740_PREEMPH_REG_POST_TAP2_MASK));
   3051                     }
   3052                 }
   3053             }
   3054             break;
   3055 
   3056         default:
   3057             /* should never get here */
   3058             return SOC_E_PARAM;
   3059     }
   3060 
   3061 #ifdef PHY84740_FCS_ERROR_WAR
   3062     /* Toggle Transmit lane output so that the link partner
   3063        resets itself to a good signal. Othwerise, it could 
   3064        sync to a sub optimal signal and can see FCS errors. 
   3065      */
   3066     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3067         start = lane == 4 ? 0 : lane;
   3068         end = lane == 4 ? 4 : lane + 1;
   3069     } else {
   3070         /* just make sure execute once */
   3071         start = 0;
   3072         end = 1;
   3073     }
   3074     for (ix = start; ix < end; ix++) {
   3075         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3076 
   3077             PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
   3078             SOC_IF_ERROR_RETURN
   3079                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3080                                                 PHY84740_PMAD_AER_ADDR_REG,
   3081                                                 P2L_MAP(pc, ix)));
   3082             PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
   3083 
   3084             data = mask = 0x1 << (12 + P2L_MAP(pc, ix));        /* per lane */
   3085             SOC_IF_ERROR_RETURN
   3086                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask));
   3087 
   3088             data = 0;
   3089             SOC_IF_ERROR_RETURN
   3090                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask));
   3091         } else {
   3092             data = mask = (lane == 4) ? 0x1 << 11 :     /* Global */
   3093                 0x1 << (12 + P2L_MAP(pc, lane));        /* per lane */
   3094             SOC_IF_ERROR_RETURN
   3095                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask));
   3096             data = 0;
   3097             SOC_IF_ERROR_RETURN
   3098                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask));
   3099         }
   3100     }
   3101 #endif                          /* PHY84740_FCS_ERROR_WAR */
   3102 
   3103     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3104         PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
   3105         /* point back to lane0 */
   3106         SOC_IF_ERROR_RETURN
   3107             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3108                                             PHY84740_PMAD_AER_ADDR_REG, 0));
   3109         PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS);
   3110     }
   3111     return SOC_E_NONE;
   3112 }
   3113 
   3114 STATIC int
   3115 _phy_84740_control_tx_driver_get(int unit, soc_port_t port, int interface,
   3116                                  soc_phy_control_t type, uint32 *value)
   3117 {
   3118     uint16 data16;              /* Temporary holder of a reg value */
   3119     uint16 main_tap;
   3120     uint16 post_tap;
   3121     int lane;
   3122     phy_ctrl_t *pc;             /* PHY software state */
   3123     uint16 post_tap2 = 0;
   3124     uint16 pre_tap = 0;
   3125     uint16 force_preemph = 0;
   3126     uint32 devid = 0;
   3127     int reg;
   3128 
   3129     pc = EXT_PHY_SW_STATE(unit, port);
   3130 
   3131     data16 = 0;
   3132     switch (type) {
   3133         case SOC_PHY_CONTROL_PREEMPHASIS:
   3134             /* fall through */
   3135         case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   3136             /* fall through */
   3137         case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   3138             /* fall through */
   3139         case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   3140             /* fall through */
   3141         case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   3142             if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) {
   3143                 lane = 0;
   3144             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) {
   3145                 lane = 1;
   3146             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) {
   3147                 lane = 2;
   3148             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) {
   3149                 lane = 3;
   3150             } else {
   3151                 lane = 0;
   3152             }
   3153             /* 1.CA05[15] = 0, set 1.CA02[15:11] for main_tap and 
   3154              * 1.CA05[7:4] for postcursor 
   3155              */
   3156             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3157                 SOC_IF_ERROR_RETURN
   3158                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3159                                                     PHY84740_PMAD_AER_ADDR_REG,
   3160                                                     P2L_MAP(pc, lane)));
   3161             }
   3162             SOC_IF_ERROR_RETURN
   3163                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3164                                                (interface ==
   3165                                                 PHY_DIAG_INTF_SYS) ? 0xc90b :
   3166                                                0xca02, &main_tap));
   3167             SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   3168                                 (unit, pc,
   3169                                  (interface ==
   3170                                   PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca06,
   3171                                  &post_tap));
   3172             SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   3173                                 (unit, pc,
   3174                                  (interface ==
   3175                                   PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca06,
   3176                                  &pre_tap));
   3177 
   3178             if (interface != PHY_DIAG_INTF_SYS) {
   3179                 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   3180                                 (unit, pc,
   3181                                  0xca07,
   3182                                  &force_preemph));
   3183                 /* bit15 force flag, 14:10 post_tap, 09:04 main tap */
   3184                 *value = (force_preemph & PHY84740_PREEMPH_REG_FORCE_MASK) ? 0 :
   3185                     (1 << PHY84740_PREEMPH_CTRL_FORCE_SHFT);
   3186             } else {
   3187                 *value = 0;
   3188             } 
   3189             *value |= ((post_tap & PHY84740_PREEMPH_REG_POST_TAP_MASK) >>
   3190                        PHY84740_PREEMPH_REG_POST_TAP_SHFT) <<
   3191                 PHY84740_PREEMPH_CTRL_POST_TAP_SHFT;
   3192             *value |= ((main_tap & PHY84740_PREEMPH_REG_MAIN_TAP_MASK) >>
   3193                        PHY84740_PREEMPH_REG_MAIN_TAP_SHFT) <<
   3194                 PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT;
   3195             *value |= ((pre_tap & PHY84740_PREEMPH_REG_PRE_TAP_MASK) >>
   3196                        PHY84740_PREEMPH_REG_PRE_TAP_SHFT) <<
   3197                 PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT;
   3198             SOC_IF_ERROR_RETURN
   3199                 (_phy_84740_config_devid(pc->unit, pc->port, pc, &devid));
   3200 
   3201             /* Only Quadra devices have post tap 2 */
   3202             /* Initialize to zero if i) 40G ii) Backplane package iii) system side */
   3203             if (PHY84740_IS_QUADRA(devid)) {
   3204                 if (PHY84740_SINGLE_PORT_MODE(pc) ||
   3205                     (interface == PHY_DIAG_INTF_SYS) ||
   3206                     (PHY84740_IS_QUADRA_BACKPLANE(devid))) {
   3207                     post_tap2 = 0;
   3208                 } else {
   3209                     SOC_IF_ERROR_RETURN
   3210                         (READ_PHY84740_MMF_PMA_PMD_REG
   3211                          (unit, pc, 0xca08, &post_tap2));
   3212                 }
   3213                 *value |= ((post_tap2 & PHY84740_PREEMPH_REG_POST_TAP2_MASK) >>
   3214                            PHY84740_PREEMPH_REG_POST_TAP2_SHFT) <<
   3215                     PHY84740_PREEMPH_CTRL_POST_TAP2_SHFT;
   3216             }
   3217             break;
   3218         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   3219             /* fall through */
   3220         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   3221             /* fall through */
   3222         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   3223             /* fall through */
   3224         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   3225             /* fall through */
   3226         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   3227             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
   3228             if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0) {
   3229                 lane = 0;
   3230             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1) {
   3231                 lane = 1;
   3232             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2) {
   3233                 lane = 2;
   3234             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3) {
   3235                 lane = 3;
   3236             } else {
   3237                 lane = 0;
   3238             }
   3239             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3240                 SOC_IF_ERROR_RETURN
   3241                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3242                                                     PHY84740_PMAD_AER_ADDR_REG,
   3243                                                     P2L_MAP(pc, lane)));
   3244             }
   3245             SOC_IF_ERROR_RETURN
   3246                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   3247             *value = (data16 & 0xf000) >> 12;
   3248             break;
   3249 
   3250         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   3251             /* fall through */
   3252         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   3253             /* fall through */
   3254         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   3255             /* fall through */
   3256         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   3257             /* fall through */
   3258         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   3259             reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01;
   3260             if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0) {
   3261                 lane = 0;
   3262             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1) {
   3263                 lane = 1;
   3264             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2) {
   3265                 lane = 2;
   3266             } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3) {
   3267                 lane = 3;
   3268             } else {
   3269                 lane = 0;
   3270             }
   3271             if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3272                 SOC_IF_ERROR_RETURN
   3273                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3274                                                     PHY84740_PMAD_AER_ADDR_REG,
   3275                                                     P2L_MAP(pc, lane)));
   3276             }
   3277             SOC_IF_ERROR_RETURN
   3278                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   3279             *value = (data16 & 0x0f00) >> 8;
   3280             break;
   3281 
   3282         default:
   3283             /* should never get here */
   3284             return SOC_E_PARAM;
   3285     }
   3286 
   3287     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3288         /* point back to lane0 */
   3289         SOC_IF_ERROR_RETURN
   3290             (WRITE_PHY84740_MMF_PMA_PMD_REG
   3291              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   3292     }
   3293     return SOC_E_NONE;
   3294 }
   3295 
   3296 STATIC int
   3297 _phy_84740_control_edc_mode_set(int unit, soc_port_t port, uint32 value)
   3298 {
   3299     uint16 data16;
   3300     uint16 mask16;
   3301     phy_ctrl_t *pc;             /* PHY software state */
   3302     int ix;
   3303 
   3304     pc = EXT_PHY_SW_STATE(unit, port);
   3305 
   3306     /* clear software overrides */
   3307     mask16 = 0;
   3308     if (!RX_LOS(pc)) {
   3309         mask16 |= PHY84740_RXLOS_OVERRIDE_MASK;
   3310     }
   3311     /* default: override MOD_ABS signalling */
   3312     if (!MOD_ABS(pc)) {
   3313         mask16 |= PHY84740_MOD_ABS_OVERRIDE_MASK;
   3314     }
   3315 
   3316     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3317         for (ix = 0; ix < NUM_LANES; ix++) {
   3318             SOC_IF_ERROR_RETURN
   3319                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3320                                                 PHY84740_PMAD_AER_ADDR_REG,
   3321                                                 ix));
   3322             SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   3323                                 (unit, pc, PHY84740_PMAD_OPTICAL_CFG_REG, 0,
   3324                                  mask16));
   3325         }
   3326     } else {
   3327         SOC_IF_ERROR_RETURN
   3328             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3329                                              PHY84740_PMAD_OPTICAL_CFG_REG, 0,
   3330                                              mask16));
   3331     }
   3332 
   3333     for (ix = 0; ix < NUM_LANES; ix++) {
   3334         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3335             SOC_IF_ERROR_RETURN
   3336                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3337                                                 PHY84740_PMAD_AER_ADDR_REG,
   3338                                                 ix));
   3339         }
   3340 
   3341         /* EDC mode programming sequence */
   3342         mask16 = 1 << 9;
   3343 
   3344         /* induce LOS condition: toggle register bit 0xc800.9 */
   3345         SOC_IF_ERROR_RETURN
   3346             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3347                                            PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   3348                                            &data16));
   3349 
   3350         /* only change toggled bit 9 */
   3351         SOC_IF_ERROR_RETURN
   3352             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3353                                              PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   3354                                              ~data16, mask16));
   3355 
   3356         /* program EDC mode */
   3357         SOC_IF_ERROR_RETURN
   3358             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, (uint16) value,
   3359                                              PHY84740_EDC_MODE_MASK));
   3360 
   3361         /* remove LOS condition: restore back original value of bit 0xc800.9 */
   3362         SOC_IF_ERROR_RETURN
   3363             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3364                                              PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   3365                                              data16, mask16));
   3366 
   3367         if (!PHY84740_SINGLE_PORT_MODE(pc)) {
   3368             break;
   3369         }
   3370     }
   3371 
   3372     /* restore software override */
   3373     data16 = 0;
   3374     mask16 = PHY84740_RXLOS_OVERRIDE_MASK | PHY84740_MOD_ABS_OVERRIDE_MASK;
   3375     if (!RX_LOS(pc)) {
   3376         data16 |= PHY84740_RXLOS_OVERRIDE_MASK;
   3377     }
   3378     /* default: override MOD_ABS signalling */
   3379     if (!MOD_ABS(pc)) {
   3380         data16 |= PHY84740_MOD_ABS_OVERRIDE_MASK;
   3381     }
   3382 
   3383     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3384         for (ix = 0; ix < NUM_LANES; ix++) {
   3385             SOC_IF_ERROR_RETURN
   3386                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3387                                                 PHY84740_PMAD_AER_ADDR_REG,
   3388                                                 ix));
   3389             SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   3390                                 (unit, pc, PHY84740_PMAD_OPTICAL_CFG_REG,
   3391                                  data16, mask16));
   3392         }
   3393 
   3394         /* point back to lane0 */
   3395         SOC_IF_ERROR_RETURN
   3396             (WRITE_PHY84740_MMF_PMA_PMD_REG
   3397              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   3398     } else {
   3399         /* XXX temp 0xc0c0: RXLOS override: 0x0808 MOD_ABS override */
   3400         SOC_IF_ERROR_RETURN
   3401             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3402                                              PHY84740_PMAD_OPTICAL_CFG_REG,
   3403                                              data16, mask16));
   3404     }
   3405 
   3406     return SOC_E_NONE;
   3407 }
   3408 
   3409 /*
   3410  * enable/disable syncE recoverd clock for 10G/40G modes.
   3411  */
   3412 STATIC int
   3413 _phy_84740_control_recovery_clock_set(int unit, soc_port_t port, int enable)
   3414 {
   3415     uint16 data16;
   3416     uint16 mask16;
   3417     int lane;
   3418     phy_ctrl_t *pc;             /* PHY software state */
   3419 
   3420     pc = EXT_PHY_SW_STATE(unit, port);
   3421 
   3422     /* 
   3423      *  1.CB27[3]        = 0   to disable FC recovered clock to appear at TESTP/N.
   3424      *  1.CA1D[11]       = 0   to disable PLL clock to appear at TESTP/N.
   3425      *  1.CA1D[1:0]      = 00  to disable bandgap voltage and vco_control voltage appear at TESTP/N.
   3426      *  1.CB27[0]        = 1   enables rx recovered clock to come out of TESTP/N pads.
   3427      *  1.CB26[14:13]    = 11  for 156.25Mhz syncE divider select
   3428      *  1.CB26[12]       = 1   for syncE clock out.
   3429      */
   3430 
   3431     for (lane = 0; lane < NUM_LANES; lane++) {
   3432         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3433             SOC_IF_ERROR_RETURN
   3434                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3435                                                 PHY84740_PMAD_AER_ADDR_REG,
   3436                                                 lane));
   3437         }
   3438         /* set to 0 in both enable/disable cases */
   3439 
   3440         /* disable FC recovered clock to appear at TESTP/N. */
   3441         SOC_IF_ERROR_RETURN
   3442             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   3443              (unit, pc, PHY84740_PMAD_RECOVERY_CLK_REG, 0, (1 << 3)));
   3444         /* disable PLL clock to appear at TESTP/N
   3445          * disable bandgap voltage and vco_control voltage appear at TESTP/N
   3446          */
   3447         mask16 = (1 << 11) | 0x3;
   3448         SOC_IF_ERROR_RETURN
   3449             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1D, 0, mask16));
   3450 
   3451         /* enables rx recovered clock to come out of TESTP/N pads */
   3452         mask16 = PHY84740_RECOVERY_CLK_ENABLE_MASK;
   3453         data16 = enable ? mask16 : 0;
   3454         SOC_IF_ERROR_RETURN
   3455             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   3456              (unit, pc, PHY84740_PMAD_RECOVERY_CLK_REG, data16, mask16));
   3457 
   3458         /* always use bits 14:13 to select the sync clock frequency */
   3459         mask16 = (0x1 << 12);
   3460         data16 = mask16;
   3461         SOC_IF_ERROR_RETURN
   3462             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   3463              (unit, pc, PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, data16, mask16));
   3464         if (!PHY84740_SINGLE_PORT_MODE(pc)) {
   3465             break;
   3466         }
   3467     }
   3468     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3469         /* point back to lane0 */
   3470         SOC_IF_ERROR_RETURN
   3471             (WRITE_PHY84740_MMF_PMA_PMD_REG
   3472              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   3473     }
   3474     return SOC_E_NONE;
   3475 }
   3476 
   3477 /*
   3478  * set the frequency of the syncE recoverd clock.
   3479  */
   3480 STATIC int
   3481 _phy_84740_control_recovery_clock_freq_set(int unit, soc_port_t port, int freq)
   3482 {
   3483     phy_ctrl_t *pc;             /* PHY software state */
   3484     int lane;
   3485     uint16 freq_ctrl;
   3486 
   3487     pc = EXT_PHY_SW_STATE(unit, port);
   3488 
   3489     /*  
   3490      * 1.CB26[14:13]
   3491      * Select the frequency of SyncE clock to be sent to the test port: 
   3492      * 00 :  Power down syncE clock dividers
   3493      * 01 :  125 MHz            (divide by 82.5) 
   3494      * 10 :  195.3125 MHz       (divide by 52.8)
   3495      * 11 :  156.25 MHz         (divide by 66)
   3496      */
   3497 
   3498     switch (freq) {
   3499         case 125000:
   3500             freq_ctrl = 0x1;
   3501             break;
   3502         case 195312:
   3503             freq_ctrl = 0x2;
   3504             break;
   3505         case 156250:
   3506             freq_ctrl = 0x3;
   3507             break;
   3508         default:
   3509             freq_ctrl = 0x0;
   3510             break;
   3511     }
   3512 
   3513     for (lane = 0; lane < NUM_LANES; lane++) {
   3514         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3515             SOC_IF_ERROR_RETURN
   3516                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3517                                                 PHY84740_PMAD_AER_ADDR_REG,
   3518                                                 lane));
   3519         }
   3520 
   3521         SOC_IF_ERROR_RETURN
   3522             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   3523              (unit, pc, PHY84740_PMAD_RECOVERY_CLK_FREQ_REG,
   3524               PHY84740_RECOVERY_CLK_FREQf(freq_ctrl),
   3525               PHY84740_RECOVERY_CLK_FREQ_MASK));
   3526 
   3527         if (!PHY84740_SINGLE_PORT_MODE(pc)) {
   3528             break;
   3529         }
   3530     }
   3531     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3532         /* point back to lane0 */
   3533         SOC_IF_ERROR_RETURN
   3534             (WRITE_PHY84740_MMF_PMA_PMD_REG
   3535              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   3536     }
   3537     return SOC_E_NONE;
   3538 }
   3539 
   3540 STATIC int
   3541 _phy_84740_control_prbs_tx_invert_data_set(int unit, soc_port_t port,
   3542                                            int intf, int invert)
   3543 {
   3544     phy_ctrl_t *pc;             /* PHY software state */
   3545     uint16 data16, speed_val, mask16 = 0x1 << 2;
   3546     uint32 devid;
   3547     int lane = 0;
   3548     pc = EXT_PHY_SW_STATE(unit, port);
   3549     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   3550                        (pc->unit, pc->port, pc, &devid));
   3551     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3552         if (PHY_DIAG_INTF_SYS == intf) {
   3553             data16 = invert ? PHY84740_USER_PRBS_TX_INVERT : 0;
   3554             mask16 = PHY84740_USER_PRBS_TX_INVERT;
   3555             for (lane = 0; lane < NUM_LANES; lane++) {
   3556                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   3557                 SOC_IF_ERROR_RETURN
   3558                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3559                                             PHY84740_PMAD_AER_ADDR_REG, lane));
   3560                 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   3561                 SOC_IF_ERROR_RETURN
   3562                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3563                             PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   3564                                                  data16, mask16));
   3565             }
   3566             SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   3567             SOC_IF_ERROR_RETURN
   3568                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3569                  PHY84740_PMAD_AER_ADDR_REG, 0));
   3570             SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   3571         } else {
   3572             if(PHY84740_IS_QUADRA(devid)) {
   3573            /*
   3574             * In Quadra PRBS TX is inverted in PACKAGE itself,
   3575             * by default bit no. 4 and bit no.3 in reg 0xcd60 is set to
   3576             * 1 (in this mode),which means twice inversion of PRBS TX
   3577             * (means no inversion in TX)
   3578             * only PRBS RX is inverted,so prbs lock won't happen,to avoid
   3579             * this situation we are clearing bit no.4 in 0xcd60,means
   3580             * both TX and RX inverted leads to zero prbs error.
   3581  
   3582             * NOTE:Bit no.6 in 0xcd60 is not considered in 40G mode.
   3583             *      The autodetect is forced to disable.
   3584             */
   3585                data16 = invert ? 0 : PHY84740_USER_PRBS_TX_INVERT;
   3586                mask16 = PHY84740_USER_PRBS_TX_INVERT;
   3587                for (lane = 0; lane < NUM_LANES; lane++) {
   3588                   SOC_IF_ERROR_RETURN
   3589                      (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3590                       PHY84740_PMAD_AER_ADDR_REG, lane));
   3591                   SOC_IF_ERROR_RETURN
   3592                      (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3593                       PHY84740_UDRCD_PRBS20_CONTROL_REGISTER,
   3594                       data16,mask16));
   3595                }
   3596                SOC_IF_ERROR_RETURN
   3597                   (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3598                    PHY84740_PMAD_AER_ADDR_REG, 0));
   3599             } else {
   3600                 return SOC_E_UNAVAIL;
   3601             }
   3602        }
   3603     } else {                    /* quad-port mode */
   3604         SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   3605                             (pc->unit, pc->port, pc, &devid));
   3606         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   3607                             (unit, pc, 0xc81f, &speed_val));
   3608         if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) {
   3609             data16 = invert ? mask16 : 0;
   3610             SOC_IF_ERROR_RETURN
   3611                 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8019, data16, mask16));
   3612         } else {
   3613             /* tx inversion */
   3614             data16 = invert ? PHY84740_USER_PRBS_TX_INVERT : 0;
   3615             SOC_IF_ERROR_RETURN
   3616                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3617                                                  PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   3618                                                  data16,
   3619                                                  PHY84740_USER_PRBS_TX_INVERT));
   3620         }
   3621     }
   3622     return SOC_E_NONE;
   3623 }
   3624 
   3625 STATIC int
   3626 _phy_84740_control_prbs_rx_invert_data_set(int unit, soc_port_t port,
   3627                                            int intf, int invert)
   3628 {
   3629     phy_ctrl_t *pc;             /* PHY software state */
   3630     uint16 data16;
   3631     uint16 mask16;
   3632     int lane = 0;
   3633     pc = EXT_PHY_SW_STATE(unit, port);
   3634 
   3635     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3636         if (PHY_DIAG_INTF_SYS == intf) {
   3637             data16 = invert ? PHY84740_USER_PRBS_RX_INVERT : 0;
   3638             mask16 = PHY84740_USER_PRBS_RX_INVERT;
   3639  
   3640             for (lane = 0; lane < NUM_LANES; lane++) {
   3641                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   3642                 SOC_IF_ERROR_RETURN
   3643                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3644                                             PHY84740_PMAD_AER_ADDR_REG, lane));
   3645                 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   3646                 SOC_IF_ERROR_RETURN
   3647                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3648                             PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   3649                             data16, mask16));
   3650             }
   3651             SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   3652             SOC_IF_ERROR_RETURN
   3653                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3654                  PHY84740_PMAD_AER_ADDR_REG, 0));
   3655        } else {
   3656              return SOC_E_UNAVAIL;
   3657        }
   3658     } else {                    /* quad-port mode */
   3659         /* rx inversion */
   3660         data16 = invert ? PHY84740_USER_PRBS_RX_INVERT : 0;
   3661         mask16 = PHY84740_USER_PRBS_RX_INVERT;
   3662         SOC_IF_ERROR_RETURN
   3663             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3664                                              PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   3665                                              data16, mask16));
   3666     }
   3667     return SOC_E_NONE;
   3668 }
   3669 
   3670 STATIC int
   3671 _phy_84740_control_prbs_polynomial_set(int unit, soc_port_t port, int poly_ctrl,
   3672                                        int intf, int tx)
   3673 {                               /* tx or rx */
   3674     phy_ctrl_t *pc;             /* PHY software state */
   3675     uint16 data16;
   3676     uint16 mask16, speed_val;
   3677     uint32 devid;
   3678     int lane=0; 
   3679     /*
   3680      * poly_ctrl:
   3681      *  0x0 = prbs7
   3682      *  0x1 = prbs15
   3683      *  0x2 = prbs23
   3684      *  0x3 = prbs31
   3685      *  0x4 = prbs9
   3686      *  0x5 = prbs11
   3687      */
   3688     pc = EXT_PHY_SW_STATE(unit, port);
   3689     SOC_IF_ERROR_RETURN(
   3690         _phy_84740_config_devid(pc->unit,pc->port, pc,  &devid));
   3691     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3692         if (PHY_DIAG_INTF_SYS == intf) {
   3693             mask16 = PHY84740_40G_SYS_PRBS_MASK;
   3694             if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1) {
   3695                 data16 = PHY84740_40G_SYS_PRBS31;
   3696             } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1) {
   3697                 data16 = PHY84740_40G_SYS_PRBS9; 
   3698             } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1) {
   3699                 data16 = PHY84740_40G_SYS_PRBS7;
   3700             } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1) {
   3701                 data16 = PHY84740_40G_SYS_PRBS15;
   3702             } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1) {
   3703                 data16 = PHY84740_40G_SYS_PRBS23;
   3704             } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1) {
   3705                 data16 = PHY84740_40G_SYS_PRBS11;
   3706             } else {
   3707                 return SOC_E_PARAM;
   3708             }
   3709             if (!tx) {
   3710                 data16 <<= 12;
   3711                 mask16 <<= 12;
   3712             }
   3713             for (lane = 0; lane < NUM_LANES; lane++) {
   3714                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   3715                 SOC_IF_ERROR_RETURN
   3716                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3717                                             PHY84740_PMAD_AER_ADDR_REG, lane));
   3718                 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   3719                 SOC_IF_ERROR_RETURN
   3720                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3721                             PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   3722                                                  data16,mask16));
   3723             }
   3724             SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   3725             SOC_IF_ERROR_RETURN
   3726                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3727                  PHY84740_PMAD_AER_ADDR_REG, 0));
   3728             SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   3729 
   3730         } else {
   3731             if(PHY84740_IS_QUADRA(devid)) {
   3732                mask16 = PHY84740_40G_PRBS31 | PHY84740_40G_PRBS9 ;
   3733                if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1) {
   3734                    data16 = PHY84740_40G_PRBS31;
   3735                } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1) {
   3736                    data16 = PHY84740_40G_PRBS9;
   3737                } else {
   3738                    return SOC_E_PARAM;
   3739                }
   3740                SOC_IF_ERROR_RETURN
   3741                    (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3742                      PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER,
   3743                      data16,mask16));
   3744             } else {
   3745                     /* only two types available PRBS9 and PRBS31 */
   3746                 if (poly_ctrl == 3) {
   3747                     data16 = PHY84740_40G_PRBS31;
   3748                 } else {
   3749                     data16 = PHY84740_40G_PRBS9;
   3750                 }
   3751                 SOC_IF_ERROR_RETURN
   3752                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3753                       PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS,
   3754                       data16, PHY84740_40G_PRBS9 | PHY84740_40G_PRBS31));
   3755             }
   3756        }
   3757     } else {                    /* quad-port mode */
   3758         SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   3759                             (pc->unit, pc->port, pc, &devid));
   3760         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   3761                             (unit, pc, 0xc81f, &speed_val));
   3762 
   3763         if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) {
   3764             if (poly_ctrl == 0) {
   3765                 poly_ctrl = 0;
   3766             } else if (poly_ctrl == 3) {
   3767                 poly_ctrl = 3;
   3768             } else if (poly_ctrl == 4) {
   3769                 poly_ctrl = 1;
   3770             } else if (poly_ctrl == 5) {
   3771                 poly_ctrl = 2;
   3772             } else {
   3773                 return SOC_E_PARAM;
   3774             }
   3775             SOC_IF_ERROR_RETURN
   3776                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x8015, 0x0010));
   3777             SOC_IF_ERROR_RETURN
   3778                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x8000, 0x2c22));
   3779             SOC_IF_ERROR_RETURN
   3780                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x8017, 0x0));
   3781             SOC_IF_ERROR_RETURN
   3782                 (MODIFY_PHY84740_MMF_AN_REG
   3783                  (unit, pc, 0x8019, poly_ctrl, 0x0003));
   3784         } else {
   3785             /* 001 : prbs7 
   3786                010 : prbs9
   3787                011 : prbs11
   3788                100 : prbs15
   3789                101 : prbs23
   3790                110 : prbs31
   3791              */
   3792             if (poly_ctrl == 0) {
   3793                 data16 = 1;
   3794             } else if (poly_ctrl == 1) {
   3795                 data16 = 4;
   3796             } else if (poly_ctrl == 2) {
   3797                 data16 = 5;
   3798             } else if (poly_ctrl == 3) {
   3799                 data16 = 6;
   3800             } else if (poly_ctrl == 4) {
   3801                 data16 = 2;
   3802             } else if (poly_ctrl == 5) {
   3803                 data16 = 3;
   3804             } else {
   3805                 return SOC_E_PARAM;
   3806             }
   3807             mask16 = PHY84740_USER_PRBS_TYPE_MASK;
   3808 
   3809             /* default is tx */
   3810             if (!tx) {          /* rx */
   3811                 data16 = data16 << 12;
   3812                 mask16 = mask16 << 12;
   3813             }
   3814 
   3815             /* both tx/rx types */
   3816             SOC_IF_ERROR_RETURN
   3817                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3818                                                  PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   3819                                                  data16, mask16));
   3820         }
   3821     }
   3822     return SOC_E_NONE;
   3823 }
   3824 
   3825 STATIC int
   3826 _phy_84740_control_prbs_enable_set(int unit, soc_port_t port,
   3827                                    int intf, int enable)
   3828 {
   3829     phy_ctrl_t *pc;             /* PHY software state */
   3830     int lane;
   3831     int repeater_mode;
   3832     uint16 data16, speed_val, regval=0,mask16;
   3833     uint32 devid;
   3834 
   3835     pc = EXT_PHY_SW_STATE(unit, port);
   3836     SOC_IF_ERROR_RETURN(
   3837         _phy_84740_config_devid(pc->unit,pc->port, pc,  &devid));
   3838     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   3839         if (PHY_DIAG_INTF_SYS == intf) {
   3840             for (lane = 0; lane < NUM_LANES; lane++) {
   3841                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   3842                 SOC_IF_ERROR_RETURN
   3843                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3844                                             PHY84740_PMAD_AER_ADDR_REG, lane));
   3845                 SOC_IF_ERROR_RETURN
   3846                     (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
   3847                 if ((data16 & PHY84740_40G_SYS_REP_MODE_ENABLE ) ==
   3848                     PHY84740_40G_SYS_REP_MODE_ENABLE ) {
   3849                     regval = enable ? PHY84740_40G_SYS_PRBS_ENABLE : 0;
   3850                     SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   3851                     SOC_IF_ERROR_RETURN
   3852                         (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x810c,regval));
   3853                 }
   3854             }
   3855             SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   3856             SOC_IF_ERROR_RETURN
   3857                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3858                                                 PHY84740_PMAD_AER_ADDR_REG,
   3859                                                 0));
   3860             SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   3861         } else {
   3862             if(PHY84740_IS_QUADRA(devid)) {
   3863                mask16 = PHY84740_40G_PRBS_ENABLE;
   3864                data16 = enable ? PHY84740_40G_PRBS_ENABLE : 0;
   3865                SOC_IF_ERROR_RETURN
   3866                    (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3867                        PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER,
   3868                        data16,mask16));
   3869            /*
   3870             * In Quadra PRBS TX is inverted in PACKAGE itself,
   3871             * by default bit no. 4 and bit no.3 in reg 0xcd60 is set to
   3872             * 1 in this mode,which means twice inversion of PRBS TX
   3873             * (means no inversion in TX)
   3874             * only PRBS RX is inverted,so prbs lock won't happen,to avoid
   3875             * this situation we are clearing bit no.4 in 0xcd60,means
   3876             * both TX and RX inverted leads to zero prbs error.
   3877  
   3878             * NOTE:Bit no.6 in 0xcd60 is not considered in 40G mode.
   3879             *      The autodetect is forced to disable.
   3880             */
   3881                data16 = enable ? 0 : PHY84740_USER_PRBS_TX_INVERT;
   3882                mask16 = PHY84740_USER_PRBS_TX_INVERT;
   3883                for (lane = 0; lane < NUM_LANES; lane++) {
   3884                   SOC_IF_ERROR_RETURN
   3885                       (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3886                             PHY84740_PMAD_AER_ADDR_REG, lane));
   3887                   SOC_IF_ERROR_RETURN
   3888                       (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3889                          PHY84740_UDRCD_PRBS20_CONTROL_REGISTER,
   3890                          data16,mask16));
   3891                }
   3892             } else {
   3893                 for (lane = 0; lane < NUM_LANES; lane++) {
   3894                    SOC_IF_ERROR_RETURN
   3895                        (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3896                                                     PHY84740_PMAD_AER_ADDR_REG,
   3897                                                     lane));
   3898 
   3899                    /* GENSIG_8071_REGISTER Clocks enable */
   3900                    SOC_IF_ERROR_RETURN
   3901                        (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3902                                                     PHY84740_GENSIG_8071_REGISTER,
   3903                                                     enable ? 0x3 : 0));
   3904                    /* RESET_CONTROL_REGISTER */
   3905                    SOC_IF_ERROR_RETURN
   3906                        (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3907                                                     PHY84740_RESET_CONTROL_REGISTER,
   3908                                                     0x0));
   3909 
   3910                    /* DATA_MUX_SEL_CNTRL_REGISTER */
   3911                    SOC_IF_ERROR_RETURN
   3912                        (WRITE_PHY84740_MMF_PMA_PMD_REG
   3913                        (unit, pc, 0xcd58, enable ? 0x2 : 0));
   3914 
   3915                    /* 40G_PRBS_PATTERN_TESTING_CONTROL_STATUS */
   3916                    SOC_IF_ERROR_RETURN
   3917                        (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3918                         PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS,
   3919                         enable ?
   3920                         PHY84740_40G_PRBS_ENABLE : 0,
   3921                         0xf));
   3922                  }
   3923               }
   3924         }
   3925         /* point back to lane0 */
   3926         SOC_IF_ERROR_RETURN
   3927             (WRITE_PHY84740_MMF_PMA_PMD_REG
   3928              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   3929     } else {                    /* quad-port mode */
   3930         SOC_IF_ERROR_RETURN
   3931             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
   3932 
   3933         repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE;
   3934         if (repeater_mode) {
   3935             /* Enable retimer prbs clocks inside SFI */
   3936             SOC_IF_ERROR_RETURN
   3937                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3938                                                  PHY84740_GENSIG_8071_REGISTER,
   3939                                                  enable ? 0x3 : 0, 0x3));
   3940 
   3941             /* Enable the retimer datapath */
   3942             SOC_IF_ERROR_RETURN
   3943                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd58,
   3944                                                  enable ? 0x2 : 0, 0x3));
   3945         }
   3946         SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   3947                             (pc->unit, pc->port, pc, &devid));
   3948 
   3949         SOC_IF_ERROR_RETURN
   3950             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81f, &speed_val));
   3951         if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) {
   3952             SOC_IF_ERROR_RETURN
   3953                (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
   3954             if (data16 & PHY84740_RX_REPEATER_MASK) {
   3955                SOC_IF_ERROR_RETURN
   3956                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc806,
   3957                  enable ? 0 : PHY84740_TX_REPEATER_ENABLE,
   3958                  PHY84740_TX_REPEATER_MASK));
   3959             }
   3960             SOC_IF_ERROR_RETURN
   3961                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x80b1, 0x0007));
   3962             if (enable) {
   3963                 SOC_IF_ERROR_RETURN
   3964                     (MODIFY_PHY84740_MMF_AN_REG
   3965                      (unit, pc, 0x8019, 0x0008, 0x0008));
   3966             } else {
   3967                 SOC_IF_ERROR_RETURN
   3968                     (MODIFY_PHY84740_MMF_AN_REG
   3969                      (unit, pc, 0x8019, 0x0000, 0x0008));
   3970             }
   3971 
   3972         } else {
   3973             /* clear PRBS control if disabled */
   3974             if (!enable) {
   3975                 SOC_IF_ERROR_RETURN
   3976                     (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
   3977                                                      PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   3978                                                      0,
   3979                                                      PHY84740_USER_PRBS_TYPE_MASK | PHY84740_USER_PRBS_TYPE_MASK << 12));    /* rx type */
   3980             }
   3981             /*  program the PRBS enable */
   3982             SOC_IF_ERROR_RETURN
   3983                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   3984                                                  PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   3985                                                  enable ?
   3986                                                  PHY84740_USER_PRBS_ENABLE : 0,
   3987                                                  PHY84740_USER_PRBS_ENABLE));
   3988         }
   3989     }
   3990     return SOC_E_NONE;
   3991 }
   3992 
   3993 STATIC int
   3994 _phy_84740_control_prbs_enable_get(int unit, soc_port_t port,int intf, uint32 *value)
   3995 {
   3996     uint16 data16, speed_val,temp=0;
   3997     phy_ctrl_t *pc;             /* PHY software state */
   3998     uint32 devid;
   3999     int lane = 0;
   4000 
   4001     pc = EXT_PHY_SW_STATE(unit, port);
   4002     SOC_IF_ERROR_RETURN(
   4003         _phy_84740_config_devid(pc->unit,pc->port, pc,  &devid));
   4004     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   4005         if (PHY_DIAG_INTF_SYS == intf) {
   4006             temp = PHY84740_40G_SYS_PRBS_ENABLE_MASK;
   4007             for (lane = 0; lane < NUM_LANES; lane++) {
   4008                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4009                 SOC_IF_ERROR_RETURN
   4010                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4011                                             PHY84740_PMAD_AER_ADDR_REG, lane));
   4012                 SOC_IF_ERROR_RETURN
   4013                     (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16));
   4014                 if ((data16 & PHY84740_40G_SYS_REP_MODE_ENABLE) ==
   4015                      PHY84740_40G_SYS_REP_MODE_ENABLE) {
   4016                     SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4017                     SOC_IF_ERROR_RETURN
   4018                         (READ_PHY84740_MMF_AN_REG(unit, pc, 0x810c, &data16));
   4019                     if ((temp & data16) != PHY84740_40G_SYS_PRBS_ENABLE) {
   4020                          *value  = FALSE;
   4021                          break;
   4022                     }
   4023                     *value = TRUE ;
   4024                 }
   4025             }
   4026             SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4027             SOC_IF_ERROR_RETURN
   4028                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4029                  PHY84740_PMAD_AER_ADDR_REG, 0));
   4030             SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4031         } else {
   4032             if(PHY84740_IS_QUADRA(devid)) {
   4033                SOC_IF_ERROR_RETURN
   4034                    (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4035                     PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER,
   4036                     &data16));
   4037                data16 = data16 & PHY84740_40G_PRBS_ENABLE;
   4038                *value = (data16 == PHY84740_40G_PRBS_ENABLE) ? TRUE : FALSE;
   4039             } else {
   4040                 SOC_IF_ERROR_RETURN
   4041                    (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4042                     PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS,
   4043                     &data16));
   4044                 if ((data16 & PHY84740_40G_PRBS_ENABLE) == PHY84740_40G_PRBS_ENABLE) {
   4045                    *value = TRUE;
   4046                 } else {
   4047                     *value = FALSE;
   4048                 }
   4049             }
   4050         }
   4051     } else {                    /* quad-port mode */
   4052         SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   4053                             (pc->unit, pc->port, pc, &devid));
   4054 
   4055         SOC_IF_ERROR_RETURN
   4056             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81f, &speed_val));
   4057 
   4058         if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) {
   4059             SOC_IF_ERROR_RETURN
   4060                 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x8019, &data16));
   4061             *value = (data16 & 0x0008) ? TRUE : FALSE;
   4062         } else {
   4063             SOC_IF_ERROR_RETURN
   4064                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4065                                                PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   4066                                                &data16));
   4067             if (data16 & PHY84740_USER_PRBS_ENABLE) {
   4068                 *value = TRUE;
   4069             } else {
   4070                 *value = FALSE;
   4071             }
   4072         }
   4073     }
   4074     return SOC_E_NONE;
   4075 }
   4076 
   4077 STATIC int
   4078 _phy_84740_control_prbs_polynomial_get(int unit, soc_port_t port,
   4079                                        int intf, uint32 *value)
   4080 {
   4081     phy_ctrl_t *pc;             /* PHY software state */
   4082     uint16 poly_ctrl, speed_val, data16=0;
   4083     uint32 devid;
   4084     int lane = 0;
   4085 
   4086     pc = EXT_PHY_SW_STATE(unit, port);
   4087     /*
   4088      * poly_ctrl:
   4089      *  0x0 = prbs7
   4090      *  0x1 = prbs15
   4091      *  0x2 = prbs23
   4092      *  0x3 = prbs31
   4093      *  0x4 = prbs9
   4094      *  0x5 = prbs11
   4095      */
   4096     SOC_IF_ERROR_RETURN(
   4097        _phy_84740_config_devid(pc->unit,pc->port, pc,  &devid));
   4098     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   4099         if (PHY_DIAG_INTF_SYS == intf) {
   4100             poly_ctrl = 0;
   4101             for (lane = 0; lane < NUM_LANES; lane++) {
   4102                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4103                 SOC_IF_ERROR_RETURN
   4104                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4105                                             PHY84740_PMAD_AER_ADDR_REG, lane));
   4106                 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4107                 SOC_IF_ERROR_RETURN
   4108                     (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4109                             PHY84740_USER_PRBS_CONTROL_0_REGISTER,&data16));
   4110                 poly_ctrl |= (data16 & PHY84740_40G_SYS_PRBS_POLY_MASK) ;
   4111             }
   4112             SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4113             SOC_IF_ERROR_RETURN
   4114                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4115                                                 PHY84740_PMAD_AER_ADDR_REG, 0));
   4116             SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4117 
   4118             if (poly_ctrl == (PHY84740_40G_SYS_PRBS31 |
   4119                               (PHY84740_40G_SYS_PRBS31 << 12))) {
   4120                 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1;
   4121             } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS23 |
   4122                                     (PHY84740_40G_SYS_PRBS23 << 12))) {
   4123                 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1;
   4124             } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS15 |
   4125                                     (PHY84740_40G_SYS_PRBS15 << 12))) {
   4126                 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1;
   4127             } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS11 |
   4128                                     (PHY84740_40G_SYS_PRBS11 << 12))) {
   4129                 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1;
   4130             } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS9 |
   4131                                     (PHY84740_40G_SYS_PRBS9 << 12))) {
   4132                 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1;
   4133             } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS7 |
   4134                                     (PHY84740_40G_SYS_PRBS7 << 12))) {
   4135                 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1;
   4136             } else {
   4137                 return SOC_E_INTERNAL;
   4138             }
   4139         } else {
   4140            if(PHY84740_IS_QUADRA(devid)) {
   4141               SOC_IF_ERROR_RETURN
   4142                   (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4143                    PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER,
   4144                    &poly_ctrl));
   4145               poly_ctrl &= (PHY84740_40G_PRBS31 | PHY84740_40G_PRBS9);
   4146               if (poly_ctrl == PHY84740_40G_PRBS31) {
   4147                   *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1;
   4148               } else if (poly_ctrl == PHY84740_40G_PRBS9) {
   4149                   *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1;
   4150               } else {
   4151                   return SOC_E_INTERNAL;
   4152               }
   4153            } else {
   4154                SOC_IF_ERROR_RETURN
   4155                    (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4156                    PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS,
   4157                    &poly_ctrl));
   4158                if (poly_ctrl & PHY84740_40G_PRBS31) {
   4159                    *value = 3;
   4160                } else {
   4161                    *value = 0;         /* 0 indicates PRBS9 */
   4162                }
   4163            }
   4164        }
   4165     } else {                    /* quad-port mode */
   4166         SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   4167                             (pc->unit, pc->port, pc, &devid));
   4168         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   4169                             (unit, pc, 0xc81f, &speed_val));
   4170 
   4171         if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) {
   4172             SOC_IF_ERROR_RETURN
   4173                 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x8019, &poly_ctrl));
   4174             *value = poly_ctrl & (uint16) 0x0003;
   4175             if (*value == 1)
   4176                 *value = 4;
   4177             if (*value == 2)
   4178                 *value = 5;
   4179 
   4180         } else {
   4181             SOC_IF_ERROR_RETURN
   4182                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4183                                                PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   4184                                                &poly_ctrl));
   4185             poly_ctrl &= PHY84740_USER_PRBS_TYPE_MASK;
   4186 
   4187             if (poly_ctrl == 1) {
   4188                 *value = 0;
   4189             } else if (poly_ctrl == 4) {
   4190                 *value = 1;
   4191             } else if (poly_ctrl == 5) {
   4192                 *value = 2;
   4193             } else if (poly_ctrl == 6) {
   4194                 *value = 3;
   4195             } else if (poly_ctrl == 2) {
   4196                 *value = 4;
   4197             } else if (poly_ctrl == 3) {
   4198                 *value = 5;
   4199 	    } else {
   4200 	        *value = poly_ctrl;
   4201 	    }
   4202         }
   4203     }
   4204 
   4205     return SOC_E_NONE;
   4206 }
   4207 
   4208 STATIC int
   4209 _phy_84740_control_prbs_tx_invert_data_get(int unit, soc_port_t port,
   4210                                            int intf, uint32 *value)
   4211 {
   4212     phy_ctrl_t *pc;             /* PHY software state */
   4213     uint16 data16, speed_val;
   4214     uint32 devid;
   4215     int lane = 0;   
   4216 
   4217     pc = EXT_PHY_SW_STATE(unit, port);
   4218     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   4219                        (pc->unit, pc->port, pc, &devid));
   4220     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   4221       if (PHY_DIAG_INTF_SYS == intf) {
   4222             *value = 0;
   4223             for (lane = 0; lane < NUM_LANES; lane++) {
   4224                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4225                 SOC_IF_ERROR_RETURN
   4226                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4227                                             PHY84740_PMAD_AER_ADDR_REG, lane));
   4228                 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4229                 SOC_IF_ERROR_RETURN
   4230                     (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4231                             PHY84740_USER_PRBS_CONTROL_0_REGISTER,&data16));
   4232                 *value |=  data16 &(uint16)PHY84740_USER_PRBS_TX_INVERT;
   4233             }
   4234             *value >>= 4;
   4235             SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4236             SOC_IF_ERROR_RETURN
   4237                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4238                  PHY84740_PMAD_AER_ADDR_REG, 0));
   4239             SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4240        } else {
   4241            if(PHY84740_IS_QUADRA(devid)) {
   4242               *value = 0;
   4243            /*
   4244             * In Quadra PRBS TX is inverted in PACKAGE itself,
   4245             * by default bit no. 4 and bit no.3 in reg 0xcd60 is set to
   4246             * 1 in this mode,which means twice inversion of PRBS TX
   4247             * (means no inversion in TX)
   4248             * only PRBS RX is inverted,so prbs lock won't happen,to avoid
   4249             * this situation we are clearing bit no.4 in 0xcd60,means
   4250             * both TX and RX inverted leads to zero prbs error.
   4251  
   4252             * NOTE:Bit no.6 in 0xcd60 is not considered in 40G mode.
   4253             *      The autodetect is forced to disable.
   4254             */
   4255               for (lane = 0; lane < NUM_LANES; lane++) {
   4256                   SOC_IF_ERROR_RETURN
   4257                      (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4258                       PHY84740_PMAD_AER_ADDR_REG, lane));
   4259                   SOC_IF_ERROR_RETURN
   4260                      (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4261                       PHY84740_UDRCD_PRBS20_CONTROL_REGISTER,
   4262                       &data16));
   4263                   *value |= data16;
   4264               }
   4265               *value &= PHY84740_USER_PRBS_TX_INVERT;
   4266               if( *value == PHY84740_USER_PRBS_TX_INVERT) {
   4267                   *value = FALSE;
   4268               } else {
   4269                   *value = TRUE;
   4270               }
   4271           } else {
   4272               return SOC_E_UNAVAIL;
   4273           }
   4274        }
   4275     } else {                    /* quad-port mode */
   4276         SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   4277                             (pc->unit, pc->port, pc, &devid));
   4278         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   4279                             (unit, pc, 0xc81f, &speed_val));
   4280 
   4281         if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) {
   4282             SOC_IF_ERROR_RETURN
   4283                 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x8019, &data16));
   4284             *value = (data16 & (uint16) 0x0004) ? TRUE : FALSE;
   4285         } else {
   4286             SOC_IF_ERROR_RETURN
   4287                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4288                                                PHY84740_USER_PRBS_CONTROL_0_REGISTER,
   4289                                                &data16));
   4290             if (data16 & PHY84740_USER_PRBS_TX_INVERT) {
   4291                 *value = TRUE;
   4292             } else {
   4293                 *value = FALSE;
   4294             }
   4295         }
   4296     }
   4297     return SOC_E_NONE;
   4298 }
   4299 
   4300 STATIC int
   4301 _phy_84740_control_prbs_rx_status_get(int unit, soc_port_t port,
   4302                                       int intf, uint32 *value)
   4303 {
   4304     phy_ctrl_t *pc;             /* PHY software state */
   4305     uint16 data16, speed_val;
   4306     int lane;
   4307     uint32 devid;
   4308 
   4309     pc = EXT_PHY_SW_STATE(unit, port);
   4310     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   4311                        (pc->unit, pc->port, pc, &devid));
   4312     *value = 0;
   4313     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   4314         if (PHY_DIAG_INTF_SYS == intf) {
   4315             for (lane = 0; lane < NUM_LANES; lane++) {
   4316                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4317                 SOC_IF_ERROR_RETURN
   4318                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4319                                             PHY84740_PMAD_AER_ADDR_REG, lane));
   4320                 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4321                 SOC_IF_ERROR_RETURN
   4322                     (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4323                             PHY84740_USER_PRBS_STATUS_0_REGISTER,&data16));
   4324                 if ((data16 & PHY84740_40G_SYS_PRBS_LOCK_MASK ) ==
   4325                       PHY84740_40G_SYS_PRBS_LOCK_VALUE ) {
   4326                     *value += data16 & PHY84740_40G_SYS_PRBS_ERR_MASK ;
   4327                 } else{
   4328                     *value = -1;
   4329                     break;
   4330                 }
   4331             }
   4332             SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4333             SOC_IF_ERROR_RETURN
   4334                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4335                  PHY84740_PMAD_AER_ADDR_REG, 0));
   4336             SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4337         } else {
   4338             if(PHY84740_IS_QUADRA(devid)) {
   4339                *value = 0;
   4340                for (lane = 0; lane < 4; lane++) {
   4341                   SOC_IF_ERROR_RETURN
   4342                       (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4343                        PHY84740_FORTYG_PRBS_RX_TESTING_ERROR_COUNTER_LANE0 + lane,
   4344                        &data16));
   4345                        *value |= data16;
   4346                }
   4347             } else {
   4348                 for (lane = 0; lane < 4; lane++) {
   4349                    SOC_IF_ERROR_RETURN
   4350                        (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4351                         PHY84740_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0
   4352                         + lane, &data16));
   4353                    if (!(data16 & 0xfff)) {
   4354                       /* PRBS is in sync */
   4355                        continue;
   4356                    } else {
   4357                        /* Get errors */
   4358                        *value += (data16 & 0xfff);
   4359                    }
   4360                 }
   4361             }
   4362         }
   4363      } else {                    /* quad-port mode */
   4364         SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   4365                             (pc->unit, pc->port, pc, &devid));
   4366         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   4367                             (unit, pc, 0xc81f, &speed_val));
   4368         if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) {
   4369             data16 = 0;
   4370             SOC_IF_ERROR_RETURN
   4371                 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x80b1, 0x0007));
   4372             SOC_IF_ERROR_RETURN
   4373                 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x80b0, &data16));
   4374             if (data16 & (uint16) 0x8000) {
   4375                 *value = data16 & (uint16) 0x3fff;
   4376             } else {
   4377                 *value = -1;
   4378             }
   4379         } else {
   4380             SOC_IF_ERROR_RETURN
   4381                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4382                                                PHY84740_USER_PRBS_STATUS_0_REGISTER,
   4383                                                &data16));
   4384             if (data16 == 0x8000) {     /* PRBS lock and error free */
   4385                 *value = 0;
   4386             } else if (!(data16 & 0x8000)) {
   4387                 *value = -1;
   4388             } else {
   4389                 *value = data16 & 0x7fff;
   4390             }
   4391         }
   4392     }
   4393     return SOC_E_NONE;
   4394 }
   4395 
   4396 STATIC int
   4397 _phy_84740_control_edc_mode_get(int unit, soc_port_t port, uint32 *value)
   4398 {
   4399     uint16 data16;
   4400     phy_ctrl_t *pc;             /* PHY software state */
   4401 
   4402     pc = EXT_PHY_SW_STATE(unit, port);
   4403 
   4404     /* get EDC mode */
   4405     SOC_IF_ERROR_RETURN
   4406         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16));
   4407 
   4408     *value = data16 & PHY84740_EDC_MODE_MASK;
   4409 
   4410     return SOC_E_NONE;
   4411 }
   4412 
   4413 STATIC int
   4414 _phy_84740_remote_loopback_set(int unit, soc_port_t port, int intf,
   4415                                uint32 enable)
   4416 {
   4417     phy_ctrl_t *pc;             /* PHY software state */
   4418     int lane;
   4419 
   4420     pc = EXT_PHY_SW_STATE(unit, port);
   4421 
   4422     if (intf == PHY_DIAG_INTF_SYS) {
   4423         if ((PHY84740_SINGLE_PORT_MODE(pc))) {
   4424             for (lane = 0; lane < NUM_LANES; lane++) {
   4425                 /* targeted to the system side */
   4426                 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4427 
   4428                 SOC_IF_ERROR_RETURN
   4429                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4430                                                     PHY84740_PMAD_AER_ADDR_REG,
   4431                                                     lane));
   4432                 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   4433                                     (unit, pc, 0xcd0a, enable ? 1 : 0, 1));
   4434 
   4435                 /* targeted to the system side, switch back */
   4436                 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4437             }
   4438             /* point back to lane0 */
   4439             SOC_IF_ERROR_RETURN
   4440                 (WRITE_PHY84740_MMF_PMA_PMD_REG
   4441                  (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   4442         } else {
   4443             SOC_IF_ERROR_RETURN
   4444                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0a,
   4445                                                  enable ? 1 : 0, 1));
   4446         }
   4447     }
   4448     return SOC_E_NONE;
   4449 }
   4450 
   4451 STATIC int _phy_84740_debug_info(int unit, soc_port_t port)
   4452 {
   4453     phy_ctrl_t *pc;
   4454     phy_ctrl_t *int_pc;
   4455     int lane;
   4456     const char *if_names[] = SOC_PORT_IF_NAMES_INITIALIZER;
   4457     struct dbgi {
   4458         uint16 ucode_rev;
   4459         uint16 pl2_reg;
   4460         uint16 pma_mii_stat;
   4461         uint16 tx_polarity_reg[NUM_LANES];
   4462         uint16 rx_polarity_reg[NUM_LANES];
   4463         soc_port_if_t iif;
   4464         int ilink;
   4465         int ispeed;
   4466         int ian;
   4467         int ian_done;
   4468     } dbgi;
   4469 
   4470     pc = EXT_PHY_SW_STATE(unit, port);
   4471     int_pc = INT_PHY_SW_STATE(unit, port);
   4472 
   4473     SOC_IF_ERROR_RETURN
   4474         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &dbgi.ucode_rev));
   4475 
   4476     SOC_IF_ERROR_RETURN
   4477         (READ_PHY84740_MMF_PMA_PMD_REG
   4478          (unit, pc, PHY84740_PMAD_LANE0_L2P_REG, &dbgi.pl2_reg));
   4479 
   4480     for (lane = 0; lane < NUM_LANES; lane++) {
   4481         /* point to the each lane starting at lane0 */
   4482         SOC_IF_ERROR_RETURN
   4483             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4484                                             PHY84740_PMAD_AER_ADDR_REG,
   4485                                             P2L_MAP(pc, lane)));
   4486 
   4487         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   4488                             (unit, pc, PHY84740_DIG_CTRL_REG,
   4489                              &dbgi.tx_polarity_reg[lane]));
   4490         SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4491         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   4492                             (unit, pc, PHY84740_DIG_CTRL_REG,
   4493                              &dbgi.rx_polarity_reg[lane]));
   4494         SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4495     }
   4496 
   4497    LOG_CLI((BSL_META_U(unit,
   4498                        "Port %-3d(mdio=0x%x): ver(1.%04x)=0x%x, single lpmode=%d, "
   4499                        "p2lreg(1.%04x)=0x%04x, p2lmap=%d%d%d%d\n"),
   4500             port, pc->phy_id, 0xce00, dbgi.ucode_rev,
   4501             SINGLE_LPMODE(pc),
   4502             PHY84740_PMAD_LANE0_L2P_REG, dbgi.pl2_reg,
   4503             P2L_MAP(pc, 3), P2L_MAP(pc, 2), P2L_MAP(pc, 1), P2L_MAP(pc,
   4504             0)));
   4505 
   4506     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   4507         SOC_IF_ERROR_RETURN
   4508             (READ_PHY84740_PMA_PMD_STATr(unit, pc, &dbgi.pma_mii_stat));
   4509         SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &dbgi.ilink));
   4510        LOG_CLI((BSL_META_U(unit,
   4511                            "   pma_link(1.0x%04x)=0x%0x(%s), serdes_link=%s\n"),
   4512                 1, dbgi.pma_mii_stat,
   4513                 (dbgi.pma_mii_stat & MII_STAT_LA) ? "up" : "down",
   4514                 dbgi.ilink ? "up" : "down"));
   4515         LOG_CLI((BSL_META_U(unit,
   4516                             "   line polarity(1.%04x)=(ln0=%04x, "
   4517                             "ln1=%04x, ln2=%04x, ln3=%04x)\n"),
   4518                  PHY84740_DIG_CTRL_REG, dbgi.tx_polarity_reg[0],
   4519                  dbgi.tx_polarity_reg[1], dbgi.tx_polarity_reg[2],
   4520                  dbgi.tx_polarity_reg[3]));
   4521         LOG_CLI((BSL_META_U(unit,
   4522                             "   sys  polarity(1.%04x)=(ln0=%04x, "
   4523                             "ln1=%04x, ln2=%04x, ln3=%04x)\n"),
   4524                  PHY84740_DIG_CTRL_REG, dbgi.rx_polarity_reg[0],
   4525                  dbgi.rx_polarity_reg[1], dbgi.tx_polarity_reg[2],
   4526                  dbgi.rx_polarity_reg[3]));
   4527     } else {
   4528         LOG_CLI((BSL_META_U(unit,
   4529                             "   line polarity(1.%04x)=%04x\n"), PHY84740_DIG_CTRL_REG,
   4530                  dbgi.tx_polarity_reg[0]));
   4531         LOG_CLI((BSL_META_U(unit,
   4532                             "   sys  polarity(1.%04x)=%04x\n"), PHY84740_DIG_CTRL_REG,
   4533                  dbgi.rx_polarity_reg[0]));
   4534     }
   4535     if (int_pc) {
   4536         SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET
   4537                             (int_pc->pd, unit, port, &dbgi.iif));
   4538         SOC_IF_ERROR_RETURN(PHY_SPEED_GET
   4539                             (int_pc->pd, unit, port, &dbgi.ispeed));
   4540         SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET
   4541                             (int_pc->pd, unit, port, &dbgi.ian,
   4542                              &dbgi.ian_done));
   4543        LOG_CLI((BSL_META_U(unit,
   4544                            "   Internal: type=%s, speed=%d, an=%d\n"),
   4545                 if_names[dbgi.iif], dbgi.ispeed, dbgi.ian));
   4546     }
   4547    LOG_CLI((BSL_META_U(unit,
   4548                        "=======\n")));
   4549     return SOC_E_NONE;
   4550 }
   4551 
   4552 /*
   4553  * Function:
   4554  *      phy_84740_control_set
   4555  * Purpose:
   4556  *      Configure PHY device specific control fucntion.
   4557  * Parameters:
   4558  *      unit  - StrataSwitch unit #.
   4559  *      port  - StrataSwitch port #.
   4560  *      type  - Control to update
   4561  *      value - New setting for the control
   4562  * Returns:
   4563  *      SOC_E_NONE
   4564  */
   4565 STATIC int
   4566 _phy_84740_control_set(int unit, soc_port_t port, int intf, int lane,
   4567                        soc_phy_control_t type, uint32 value)
   4568 {
   4569     phy_ctrl_t *pc;             /* PHY software state */
   4570     phy_ctrl_t *int_pc;
   4571     int rv;
   4572     uint32 devid;
   4573 
   4574     pc = EXT_PHY_SW_STATE(unit, port);
   4575     int_pc = INT_PHY_SW_STATE(unit, port);
   4576 
   4577     PHY_CONTROL_TYPE_CHECK(type);
   4578 
   4579     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   4580                         (pc->unit, pc->port, pc, &devid));
   4581 
   4582     rv = SOC_E_UNAVAIL;
   4583     if (intf == PHY_DIAG_INTF_SYS) {
   4584         /* if is targeted to the system side */
   4585         SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4586     }
   4587     switch (type) {
   4588         case SOC_PHY_CONTROL_PREEMPHASIS:
   4589             /* fall through */
   4590         case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   4591             /* fall through */
   4592         case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   4593             /* fall through */
   4594         case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   4595             /* fall through */
   4596         case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   4597             /* fall through */
   4598         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   4599             /* fall through */
   4600         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   4601             /* fall through */
   4602         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   4603             /* fall through */
   4604         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   4605             /* fall through */
   4606         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   4607             /* fall through */
   4608         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   4609             /* fall through */
   4610         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   4611             /* fall through */
   4612         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   4613             /* fall through */
   4614         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   4615             /* fall through */
   4616         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   4617             rv = _phy_84740_control_tx_driver_set(unit, port, intf, type,
   4618                                                   value);
   4619             break;
   4620         case SOC_PHY_CONTROL_EDC_MODE:
   4621             rv = _phy_84740_control_edc_mode_set(unit, port, value);
   4622             break;
   4623         case SOC_PHY_CONTROL_CLOCK_ENABLE:
   4624             rv = _phy_84740_control_recovery_clock_set(unit, port, value);
   4625             break;
   4626         case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   4627             rv = _phy_84740_control_recovery_clock_freq_set(unit, port, value);
   4628             break;
   4629         case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   4630             /* on line side, rx poly type is auto-detected. On system side,
   4631              * need to enable the rx type as well.
   4632              */
   4633             rv = _phy_84740_control_prbs_polynomial_set(unit, port,
   4634                                                         value, intf,
   4635                                                         TRUE);
   4636             if (intf == PHY_DIAG_INTF_SYS) {
   4637                 rv = _phy_84740_control_prbs_polynomial_set(unit, port, value,
   4638                                                             intf,
   4639                                                             FALSE);
   4640             }
   4641             break;
   4642         case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   4643             /* on line side, rx invertion is auto-detected. On system side,
   4644              * need to enable the rx as well.
   4645              */
   4646             rv = _phy_84740_control_prbs_tx_invert_data_set(unit,
   4647                                                             port,
   4648                                                             intf,
   4649                                                             value);
   4650             if (intf == PHY_DIAG_INTF_SYS) {
   4651                 rv = _phy_84740_control_prbs_rx_invert_data_set(unit, port,
   4652                                                                 intf, value);
   4653             }
   4654             break;
   4655         case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   4656             /* fall through */
   4657         case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   4658             /* tx/rx is enabled at the same time. no seperate control */
   4659             rv = _phy_84740_control_prbs_enable_set(unit, port, intf, value);
   4660             break;
   4661         case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   4662             rv = _phy_84740_remote_loopback_set(unit, port, PHY_DIAG_INTF_SYS,
   4663                                                 value);
   4664             break;
   4665         case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
   4666             if (int_pc) {
   4667                 SOC_IF_ERROR_RETURN
   4668                     (PHY_CONTROL_SET(int_pc->pd, unit, port, type, value));
   4669                 SOFTWARE_RX_LOS(pc) = value ? 1 : 0;
   4670                 rv = SOC_E_NONE;
   4671             }
   4672             break;
   4673         case SOC_PHY_CONTROL_DUMP:
   4674             rv = _phy_84740_debug_info(unit, port);
   4675             break;
   4676         case SOC_PHY_CONTROL_TX_POLARITY:
   4677             if (PHY84740_IS_QUADRA(devid)) {    /* Quadra */
   4678                 rv = phy_84740_tx_polarity_flip_set(unit, port, value);
   4679             } else {
   4680                 rv = SOC_E_UNAVAIL;
   4681             }
   4682             break;
   4683         case SOC_PHY_CONTROL_RX_POLARITY:
   4684             if (PHY84740_IS_QUADRA(devid)) {    /* Quadra */
   4685                 rv = phy_84740_rx_polarity_flip_set(unit, port, value);
   4686             } else {
   4687                 rv = SOC_E_UNAVAIL;
   4688             }
   4689             break;
   4690         case SOC_PHY_CONTROL_TX_LANE_SQUELCH:
   4691             /* inside the _phy_84740_squelch_enable function, check for Quadra */
   4692             rv = _phy_84740_squelch_enable(unit, port, intf, value, FALSE);
   4693             break;
   4694         default:
   4695             rv = SOC_E_UNAVAIL;
   4696             break;
   4697     }
   4698     if (intf == PHY_DIAG_INTF_SYS) {
   4699         /* if it is targeted to the system side, switch back */
   4700         SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4701     }
   4702     return rv;
   4703 }
   4704 
   4705 STATIC int phy_84740_tx_polarity_flip_set(int unit, int port, uint32 value)
   4706 {
   4707     int lane;
   4708     phy_ctrl_t *pc;
   4709     uint16 tx_pol;
   4710     uint16 data16, mask16;
   4711 
   4712     pc = EXT_PHY_SW_STATE(unit, port);
   4713     tx_pol = value;
   4714 
   4715     /* get the reset default value. The 84740 device has the TX polarity flipped
   4716      * by default. Construct the init default value 
   4717      */
   4718 
   4719     mask16 = PHY84740_TX_POLARITY_FLIP_MASK;
   4720 
   4721     if ((PHY84740_SINGLE_PORT_MODE(pc))) {
   4722         for (lane = 0; lane < NUM_LANES; lane++) {
   4723             data16 = 0;
   4724 
   4725             /* point to the each lane starting at lane0 */
   4726             SOC_IF_ERROR_RETURN
   4727                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4728                                                 PHY84740_PMAD_AER_ADDR_REG,
   4729                                                 P2L_MAP(pc, lane)));
   4730 
   4731             if ((tx_pol == POL_CONFIG_ALL_LANES) ||
   4732                 ((tx_pol & POL_CONFIG_LANE_MASK(lane)) ==
   4733                  POL_CONFIG_LANE_MASK(lane))) {
   4734                 data16 = PHY84740_TX_POLARITY_FLIP_MASK;
   4735             }
   4736             SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4737                                                                 PHY84740_DIG_CTRL_REG,
   4738                                                                 data16,
   4739                                                                 mask16));
   4740         }
   4741         /* point back to lane0 */
   4742         SOC_IF_ERROR_RETURN
   4743             (WRITE_PHY84740_MMF_PMA_PMD_REG
   4744              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   4745     } else {                    /* quad-port mode */
   4746         data16 = 0;
   4747         tx_pol = PHY84740_10G_POL_CFG_GET(pc, tx_pol);
   4748         if (tx_pol) {
   4749             data16 = PHY84740_TX_POLARITY_FLIP_MASK;
   4750         }
   4751         SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   4752                             (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16));
   4753         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   4754                             (unit, pc, PHY84740_DIG_CTRL_REG, &data16));
   4755     }
   4756 
   4757     return SOC_E_NONE;
   4758 }
   4759 
   4760 STATIC int phy_84740_rx_polarity_flip_set(int unit, int port, uint32 value)
   4761 {
   4762     int lane;
   4763     phy_ctrl_t *pc;
   4764     uint16 rx_pol;
   4765     uint16 data16, mask16;
   4766 
   4767     pc = EXT_PHY_SW_STATE(unit, port);
   4768 
   4769     rx_pol = value;
   4770     /* get the reset default value. The 84740 device has the TX polarity flipped
   4771      * by default. Construct the init default value 
   4772      */
   4773     mask16 = PHY84740_RX_POLARITY_FLIP_MASK;
   4774 
   4775     if ((PHY84740_SINGLE_PORT_MODE(pc))) {
   4776         for (lane = 0; lane < NUM_LANES; lane++) {
   4777             data16 = 0;
   4778 
   4779             /* point to the each lane starting at lane0 */
   4780             SOC_IF_ERROR_RETURN
   4781                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4782                                                 PHY84740_PMAD_AER_ADDR_REG,
   4783                                                 P2L_MAP(pc, lane)));
   4784             if ((rx_pol == POL_CONFIG_ALL_LANES)
   4785                 || ((rx_pol & POL_CONFIG_LANE_MASK(lane)) ==
   4786                     POL_CONFIG_LANE_MASK(lane))) {
   4787                 data16 |= PHY84740_RX_POLARITY_FLIP_MASK;
   4788             }
   4789             SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   4790                                                                 PHY84740_DIG_CTRL_REG,
   4791                                                                 data16,
   4792                                                                 mask16));
   4793         }
   4794         /* point back to lane0 */
   4795         SOC_IF_ERROR_RETURN
   4796             (WRITE_PHY84740_MMF_PMA_PMD_REG
   4797              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   4798     } else {                    /* quad-port mode */
   4799         data16 = 0;
   4800         rx_pol = PHY84740_10G_POL_CFG_GET(pc, rx_pol);
   4801         if (rx_pol) {
   4802             data16 = PHY84740_RX_POLARITY_FLIP_MASK;
   4803         }
   4804         SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG
   4805                             (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16));
   4806         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   4807                             (unit, pc, PHY84740_DIG_CTRL_REG, &data16));
   4808     }
   4809     return SOC_E_NONE;
   4810 }
   4811 
   4812 STATIC int
   4813 phy_84740_control_set(int unit, soc_port_t port,
   4814                       soc_phy_control_t type, uint32 value)
   4815 {
   4816     phy_ctrl_t *pc;             /* PHY software state */
   4817     int intf;
   4818 
   4819     pc = EXT_PHY_SW_STATE(unit, port);
   4820 
   4821     intf = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ?
   4822         PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
   4823     SOC_IF_ERROR_RETURN
   4824         (_phy_84740_control_set(unit, port, intf,
   4825                                 PHY_DIAG_LN_DFLT, type, value));
   4826     return SOC_E_NONE;
   4827 }
   4828 
   4829 /*
   4830  * Function:
   4831  *      phy_84740_control_get
   4832  * Purpose:
   4833  *      Get current control settign of the PHY.
   4834  * Parameters:
   4835  *      unit  - StrataSwitch unit #.
   4836  *      port  - StrataSwitch port #.
   4837  *      type  - Control to update
   4838  *      value - (OUT)Current setting for the control
   4839  * Returns:
   4840  *      SOC_E_NONE
   4841  */
   4842 STATIC int
   4843 _phy_84740_control_get(int unit, soc_port_t port, int intf, int lane,
   4844                        soc_phy_control_t type, uint32 *value)
   4845 {
   4846     phy_ctrl_t *pc;             /* PHY software state */
   4847     int rv;
   4848     uint16 data16;
   4849 
   4850     pc = EXT_PHY_SW_STATE(unit, port);
   4851 
   4852     PHY_CONTROL_TYPE_CHECK(type);
   4853 
   4854     if (intf == PHY_DIAG_INTF_SYS) {
   4855         /* targeted to the system side */
   4856         SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc));
   4857     }
   4858     rv = SOC_E_UNAVAIL;
   4859     switch (type) {
   4860         case SOC_PHY_CONTROL_PREEMPHASIS:
   4861             /* fall through */
   4862         case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   4863             /* fall through */
   4864         case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   4865             /* fall through */
   4866         case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   4867             /* fall through */
   4868         case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   4869             /* fall through */
   4870         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   4871             /* fall through */
   4872         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   4873             /* fall through */
   4874         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   4875             /* fall through */
   4876         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   4877             /* fall through */
   4878         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   4879             /* fall through */
   4880         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   4881             /* fall through */
   4882         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   4883             /* fall through */
   4884         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   4885             /* fall through */
   4886         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   4887             /* fall through */
   4888         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   4889             rv = _phy_84740_control_tx_driver_get(unit, port, intf, type,
   4890                                                   value);
   4891             break;
   4892         case SOC_PHY_CONTROL_EDC_MODE:
   4893             rv = _phy_84740_control_edc_mode_get(unit, port, value);
   4894             break;
   4895         case SOC_PHY_CONTROL_CLOCK_ENABLE:
   4896             SOC_IF_ERROR_RETURN
   4897                 (READ_PHY84740_MMF_PMA_PMD_REG
   4898                  (unit, pc, PHY84740_PMAD_RECOVERY_CLK_REG, &data16));
   4899             *value =
   4900                 (data16 & PHY84740_RECOVERY_CLK_ENABLE_MASK) ? TRUE : FALSE;
   4901             rv = SOC_E_NONE;
   4902             break;
   4903         case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   4904             rv = _phy_84740_control_prbs_polynomial_get(unit,
   4905                                                         port,
   4906                                                         intf,
   4907                                                         value);
   4908             break;
   4909         case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   4910             rv = _phy_84740_control_prbs_tx_invert_data_get(unit,
   4911                                                             port,
   4912                                                             intf,
   4913                                                             value);
   4914             break;
   4915         case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   4916             /* fall through */
   4917         case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   4918             rv = _phy_84740_control_prbs_enable_get(unit, port, intf, value);
   4919             break;
   4920         case SOC_PHY_CONTROL_PRBS_RX_STATUS:
   4921             rv = _phy_84740_control_prbs_rx_status_get(unit, port, intf, value);
   4922             break;
   4923         case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   4924             SOC_IF_ERROR_RETURN
   4925                 (READ_PHY84740_MMF_PMA_PMD_REG
   4926                  (unit, pc, PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, &data16));
   4927             switch ((data16 >> PHY84740_RECOVERY_CLK_FREQ_SHIFT) & 0x3) {
   4928                 case 0x1:
   4929                     *value = 125000;
   4930                     break;
   4931                 case 0x2:
   4932                     *value = 195312;
   4933                     break;
   4934                 case 0x3:
   4935                     *value = 156250;
   4936                     break;
   4937                 default:
   4938                     *value = 0x0;
   4939                     break;
   4940             }
   4941             rv = SOC_E_NONE;
   4942             break;
   4943         case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
   4944             *value = SOFTWARE_RX_LOS(pc);
   4945             rv = SOC_E_NONE;
   4946             break;
   4947 
   4948         default:
   4949             rv = SOC_E_UNAVAIL;
   4950             break;
   4951     }
   4952 
   4953     if (intf == PHY_DIAG_INTF_SYS) {
   4954         /* if it is targeted to the system side, switch back */
   4955         SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc));
   4956     }
   4957     return rv;
   4958 }
   4959 
   4960 STATIC int
   4961 phy_84740_control_get(int unit, soc_port_t port,
   4962                       soc_phy_control_t type, uint32 *value)
   4963 {
   4964     int intf;
   4965     phy_ctrl_t *pc;             /* PHY software state */
   4966 
   4967     pc = EXT_PHY_SW_STATE(unit, port);
   4968 
   4969     intf = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ?
   4970         PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
   4971 
   4972     SOC_IF_ERROR_RETURN
   4973         (_phy_84740_control_get(unit, port, intf,
   4974                                 PHY_DIAG_LN_DFLT, type, value));
   4975     return SOC_E_NONE;
   4976 }
   4977 
   4978 STATIC int phy_84740_diag_ctrl(int unit,        /* unit */
   4979                                soc_port_t port, /* port */
   4980                                uint32 inst,     /* the specific device block the control action directs to */
   4981                                int op_type,     /* operation types: read,write or command sequence */
   4982                                int op_cmd,      /* command code */
   4983                                void *arg)
   4984 {                               /* command argument  */
   4985     int lane;
   4986     int intf;
   4987 
   4988     LOG_INFO(BSL_LS_SOC_PHY,
   4989              (BSL_META_U(unit,
   4990                          "phy_84740_diag_ctrl: u=%d p=%d ctrl=0x%x\n"),
   4991               unit, port, op_cmd));
   4992 
   4993     lane = PHY_DIAG_INST_LN(inst);
   4994     intf = PHY_DIAG_INST_INTF(inst);
   4995     if (intf == PHY_DIAG_INTF_DFLT) {
   4996         intf = PHY_DIAG_INTF_LINE;
   4997     }
   4998 
   4999     if (op_type == PHY_DIAG_CTRL_GET) {
   5000         SOC_IF_ERROR_RETURN
   5001             (_phy_84740_control_get(unit, port, intf, lane,
   5002                                     op_cmd, (uint32 *) arg));
   5003     } else if (op_type == PHY_DIAG_CTRL_SET) {
   5004         SOC_IF_ERROR_RETURN
   5005             (_phy_84740_control_set(unit, port, intf, lane,
   5006                                     op_cmd, PTR_TO_INT(arg)));
   5007     }
   5008     return SOC_E_NONE;
   5009 }
   5010 
   5011 /*
   5012  * Function:
   5013  *      phy_84740_speed_set
   5014  * Purpose:
   5015  *      Set PHY speed
   5016  * Parameters:
   5017  *      unit - StrataSwitch unit #.
   5018  *      port - StrataSwitch port #.
   5019  *      speed - link speed in Mbps
   5020  * Returns:
   5021  *      SOC_E_NONE
   5022  */
   5023 
   5024 STATIC int phy_84740_speed_set(int unit, soc_port_t port, int speed)
   5025 {
   5026     phy_ctrl_t *pc;
   5027     phy_ctrl_t *int_pc;
   5028     int rv = SOC_E_NONE;
   5029 
   5030     COMPILER_REFERENCE(unit);
   5031     COMPILER_REFERENCE(port);
   5032 
   5033     int_pc = INT_PHY_SW_STATE(unit, port);
   5034     pc = EXT_PHY_SW_STATE(unit, port);
   5035 
   5036     LOG_INFO(BSL_LS_SOC_PHY,
   5037              (BSL_META_U(unit,
   5038                          "phy_84740_speed_set: u=%d p=%d speed=%d\n"),
   5039                          unit, port, speed));
   5040 
   5041     if (FCMAP_PASSTHROUGH(pc)) {
   5042         return SOC_E_NONE;
   5043     }
   5044 
   5045     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   5046         if (speed != 40000) {
   5047             return SOC_E_PARAM;
   5048         }
   5049 
   5050         /* single port mode: doesn't use PCS. should be already in repeater mode */
   5051         /* it is always in 40G speed, make sure internal device is in 40G */
   5052         if (NULL != int_pc) {
   5053             if (REVERSE_MODE(pc)) {
   5054                 if (IS_HG_PORT(unit, port)) {
   5055                     SOC_IF_ERROR_RETURN
   5056                         (PHY_INTERFACE_SET
   5057                          (int_pc->pd, unit, port, SOC_PORT_IF_KR4));
   5058                 } else {
   5059                     SOC_IF_ERROR_RETURN
   5060                         (PHY_INTERFACE_SET
   5061                          (int_pc->pd, unit, port, SOC_PORT_IF_SR4));
   5062                 }
   5063             } else {
   5064                 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) {
   5065                     rv = PHY_INTERFACE_SET(int_pc->pd, unit, port,
   5066                                            SOC_PORT_IF_CR);
   5067                 }
   5068             }
   5069 
   5070             rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed);
   5071         }
   5072         return rv;
   5073     }
   5074 
   5075     /* quad lane mode */
   5076     if ((!(speed == 10000 || speed == 1000)) && (!PCS_REPEATER(pc))) {
   5077         return SOC_E_PARAM;
   5078     }
   5079 
   5080     if (speed == 10000) {
   5081         SOC_IF_ERROR_RETURN
   5082             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CTRL_REG,
   5083                                             MII_CTRL_SS_MSB | MII_CTRL_SS_LSB,
   5084                                             MII_CTRL_SS_MSB | MII_CTRL_SS_LSB));
   5085         SOC_IF_ERROR_RETURN
   5086             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CTRL2_REG,
   5087                                              PHY84740_PMAD_CTRL2r_PMA_TYPE_10G_LRM,
   5088                                              PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK));
   5089 
   5090     } else {
   5091         SOC_IF_ERROR_RETURN
   5092             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CTRL2_REG,
   5093                                              PHY84740_PMAD_CTRL2r_PMA_TYPE_1G_KX,
   5094                                              PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK));
   5095         SOC_IF_ERROR_RETURN
   5096             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, MII_CTRL_REG,
   5097                                              0, MII_CTRL_SS_LSB));
   5098     }
   5099     /* need to set the internal phy's speed accordingly */
   5100 
   5101     if (NULL != int_pc) {
   5102         if (REVERSE_MODE(pc)) {
   5103             SOC_IF_ERROR_RETURN
   5104                 (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_SR));
   5105         } else {
   5106             /* For long XFI channel, it is best to use SFP+ DAC mode 
   5107              * in the serdes side to provide adequate Rx equalization
   5108              */
   5109             if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) {
   5110                 if (!PHY84740_SINGLE_PORT_MODE(pc)) {
   5111                     rv = PHY_INTERFACE_SET(int_pc->pd, unit, port,
   5112                                            SOC_PORT_IF_CR);
   5113                 }
   5114             }
   5115         }
   5116         rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed);
   5117     }
   5118     return rv;
   5119 }
   5120 
   5121 /*
   5122  * Function:
   5123  *      phy_84740_speed_get
   5124  * Purpose:
   5125  *      Get PHY speed
   5126  * Parameters:
   5127  *      unit - StrataSwitch unit #.
   5128  *      port - StrataSwitch port #.
   5129  *      speed - current link speed in Mbps
   5130  * Returns:
   5131  *      SOC_E_NONE
   5132  */
   5133 
   5134 STATIC int phy_84740_speed_get(int unit, soc_port_t port, int *speed)
   5135 {
   5136     phy_ctrl_t *pc;
   5137     uint16 speed_val;
   5138 
   5139     pc = EXT_PHY_SW_STATE(unit, port);
   5140 
   5141     if (PCS_REPEATER(pc)) {
   5142         phy_ctrl_t *int_pc;
   5143 
   5144         int_pc = INT_PHY_SW_STATE(unit, port);
   5145         SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, speed));
   5146         return SOC_E_NONE;
   5147     } else if (FCMAP_PASSTHROUGH(pc)) {
   5148         *speed = 10000;
   5149         return SOC_E_NONE;
   5150     }
   5151 
   5152     /* this register contains the speed info for both single/quad modes */
   5153     SOC_IF_ERROR_RETURN
   5154         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81f, &speed_val));
   5155 
   5156     if (speed_val & (1 << 5)) {
   5157         *speed = 40000;
   5158     } else if (speed_val & (1 << 4)) {
   5159         *speed = 10000;
   5160     } else if (speed_val & (1 << 2)) {
   5161         *speed = 1000;
   5162     } else {                    /* default */
   5163         if (PHY84740_SINGLE_PORT_MODE(pc)) {
   5164             *speed = 40000;
   5165         } else {
   5166             *speed = 10000;
   5167         }
   5168     }
   5169     return SOC_E_NONE;
   5170 }
   5171 
   5172 /*
   5173  * Function:
   5174  *      phy_84740_interface_set
   5175  * Purpose:
   5176  *      Set either CR4 interface or SR4/LR4. The valid interface are SOC_PORT_IF_CR4
   5177  *      and SOC_PORT_IF_XLAUI which put device in default mode: SR4/LR4 mode
   5178  * Parameters:
   5179  *      unit - StrataSwitch unit #.
   5180  *      port - StrataSwitch port #.
   5181  *      pif - one of SOC_PORT_IF_*
   5182  * Returns:
   5183  *      SOC_E_NONE - success
   5184  *      SOC_E_UNAVAIL - unsupported interface
   5185  */
   5186 
   5187 STATIC int phy_84740_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   5188 {
   5189     phy_ctrl_t *pc;
   5190     phy_ctrl_t *int_pc;
   5191     uint16 ucode_ver;
   5192     uint16 sig_lvl_reg[4];
   5193     uint16 rxlos_reg[4];
   5194     uint16 pol_reg[4];
   5195     int lane;
   5196     uint32 devid;
   5197     soc_port_ability_t ability;
   5198 
   5199     int_pc = INT_PHY_SW_STATE(unit, port);
   5200     pc = EXT_PHY_SW_STATE(unit, port);
   5201 
   5202     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   5203                         (pc->unit, pc->port, pc, &devid));
   5204 
   5205     if (int_pc != NULL) {
   5206         if (REVERSE_MODE(pc)) {
   5207             SOC_IF_ERROR_RETURN(PHY_INTERFACE_SET(int_pc->pd, unit, port, pif));
   5208             SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_GET
   5209                                 (int_pc->pd, unit, port, &ability));
   5210             SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_SET
   5211                                 (int_pc->pd, unit, port, &ability));
   5212         }
   5213     }
   5214 
   5215     if (PHY84740_IS_QUADRA(devid)) {    /* Quadra */
   5216         if (!(PHY84740_SINGLE_PORT_MODE(pc))) { /*1G/10G mode */
   5217             switch (pif) {
   5218                 case SOC_PORT_IF_CR:
   5219                     SOC_IF_ERROR_RETURN
   5220                         (MODIFY_PHY84740_MMF_PMA_PMD_REG
   5221                          (unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   5222                           PHY84740_PMAD_DAC_MODE_MASK,
   5223                           PHY84740_PMAD_DAC_MODE_MASK));
   5224                     break;
   5225                 case SOC_PORT_IF_SR:
   5226                 case SOC_PORT_IF_LR:
   5227                 case SOC_PORT_IF_XAUI:
   5228                     SOC_IF_ERROR_RETURN
   5229                         (MODIFY_PHY84740_MMF_PMA_PMD_REG
   5230                          (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0,
   5231                           PHY84740_PMAD_DAC_MODE_MASK));
   5232                     break;
   5233                 default:
   5234                     break;
   5235             }
   5236         } else {                /* 40G mode */
   5237             switch (pif) {
   5238                 case SOC_PORT_IF_CR4:
   5239                     SOC_IF_ERROR_RETURN
   5240                         (MODIFY_PHY84740_MMF_PMA_PMD_REG
   5241                          (unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   5242                           PHY84740_PMAD_DAC_MODE_MASK,
   5243                           PHY84740_PMAD_DAC_MODE_MASK));
   5244                     break;
   5245                 case SOC_PORT_IF_SR4:
   5246                 case SOC_PORT_IF_LR4:
   5247                 case SOC_PORT_IF_XLAUI:
   5248                     SOC_IF_ERROR_RETURN
   5249                         (MODIFY_PHY84740_MMF_PMA_PMD_REG
   5250                          (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0,
   5251                           PHY84740_PMAD_DAC_MODE_MASK));
   5252                     break;
   5253                 default:
   5254                     break;
   5255             }
   5256         }
   5257     } else {                    /* Quebec */
   5258         if (!(PHY84740_SINGLE_PORT_MODE(pc))) { /*1G/10G mode */
   5259             return phy_null_interface_set(unit, port, pif);
   5260         } else {                /* 40G mode */
   5261             switch (pif) {
   5262                 case SOC_PORT_IF_CR4:
   5263                     SOC_IF_ERROR_RETURN
   5264                         (MODIFY_PHY84740_MMF_PMA_PMD_REG
   5265                          (unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   5266                           PHY84740_PMAD_DAC_MODE_MASK,
   5267                           PHY84740_PMAD_DAC_MODE_MASK));
   5268                     break;
   5269 
   5270                 case SOC_PORT_IF_XLAUI:
   5271                     SOC_IF_ERROR_RETURN
   5272                         (MODIFY_PHY84740_MMF_PMA_PMD_REG
   5273                          (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0,
   5274                           PHY84740_PMAD_DAC_MODE_MASK));
   5275                     break;
   5276                 default:
   5277                     break;
   5278             }
   5279         }
   5280     }
   5281 
   5282     SOC_IF_ERROR_RETURN
   5283         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &ucode_ver));
   5284 
   5285     if (ucode_ver >= 0x0104) {
   5286         /* For 40G mode, Do not reset the PHY if ucode is D104 on newer */
   5287         return SOC_E_NONE;
   5288     }
   5289 
   5290     /* After switching mode, user need to redo the configuration */
   5291     if (pif == SOC_PORT_IF_CR4 || pif == SOC_PORT_IF_XLAUI) {
   5292 
   5293         /* save the register settings */
   5294         for (lane = 0; lane < NUM_LANES; lane++) {
   5295             /* point to the each lane starting at lane0 */
   5296             SOC_IF_ERROR_RETURN
   5297                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   5298                                                 PHY84740_PMAD_AER_ADDR_REG,
   5299                                                 lane));
   5300             SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   5301                                 (unit, pc, PHY84740_DIG_CTRL_REG,
   5302                                  &pol_reg[lane]));
   5303 
   5304             SOC_IF_ERROR_RETURN
   5305                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   5306                                                PHY84740_PMAD_OPTICAL_CFG_REG,
   5307                                                &rxlos_reg[lane]));
   5308             SOC_IF_ERROR_RETURN
   5309                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   5310                                                PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   5311                                                &sig_lvl_reg[lane]));
   5312         }
   5313 
   5314         /* perform IEEE reset */
   5315         SOC_IF_ERROR_RETURN
   5316             (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc,
   5317                                            MII_CTRL_RESET, MII_CTRL_RESET));
   5318 
   5319         sal_udelay(100);        /* Wait for 100us */
   5320 
   5321         /* restore back saved register values */
   5322         for (lane = 0; lane < NUM_LANES; lane++) {
   5323             /* point to the each lane starting at lane0 */
   5324             SOC_IF_ERROR_RETURN
   5325                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   5326                                                 PHY84740_PMAD_AER_ADDR_REG,
   5327                                                 lane));
   5328             SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   5329                                 (unit, pc, PHY84740_DIG_CTRL_REG,
   5330                                  pol_reg[lane]));
   5331 
   5332             SOC_IF_ERROR_RETURN
   5333                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   5334                                                 PHY84740_PMAD_OPTICAL_CFG_REG,
   5335                                                 rxlos_reg[lane]));
   5336             SOC_IF_ERROR_RETURN
   5337                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   5338                                                 PHY84740_PMAD_OPTICAL_SIG_LVL_REG,
   5339                                                 sig_lvl_reg[lane]));
   5340         }
   5341 
   5342         /* redo Polarity configuration */
   5343         SOC_IF_ERROR_RETURN(_phy_84740_polarity_flip_set(unit, port));
   5344 
   5345         /* point back to lane0 */
   5346         SOC_IF_ERROR_RETURN
   5347             (WRITE_PHY84740_MMF_PMA_PMD_REG
   5348              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   5349     }
   5350 
   5351     return SOC_E_NONE;
   5352 }
   5353 
   5354 /*
   5355  * Function:
   5356  *      phy_84740_interface_get
   5357  * Purpose:
   5358  *      Get the current operating mode of the PHY.
   5359  * Parameters:
   5360  *      unit - StrataSwitch unit #.
   5361  *      port - StrataSwitch port #.
   5362  *      pif - (OUT) one of SOC_PORT_IF_*
   5363  * Returns:
   5364  *      SOC_E_NONE
   5365  */
   5366 
   5367 STATIC int
   5368 phy_84740_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   5369 {
   5370     phy_ctrl_t *pc;
   5371     uint16 mode;
   5372     uint16 speed_val;
   5373     uint32 devid;
   5374 
   5375     pc = EXT_PHY_SW_STATE(unit, port);
   5376 
   5377     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   5378                         (pc->unit, pc->port, pc, &devid));
   5379 
   5380     SOC_IF_ERROR_RETURN
   5381         (READ_PHY84740_MMF_PMA_PMD_REG
   5382          (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, &mode));
   5383 
   5384     if (PHY84740_IS_QUADRA(devid)) {
   5385         if (!(PHY84740_SINGLE_PORT_MODE(pc))) { /*10G mode */
   5386             if (mode & PHY84740_PMAD_DAC_MODE_MASK) {
   5387                 *pif = SOC_PORT_IF_CR;
   5388             } else if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   5389                 SOC_IF_ERROR_RETURN
   5390                     (READ_PHY84740_MMF_PMA_PMD_REG
   5391                      (unit, pc, 0xc81f, &speed_val));
   5392                 if ((speed_val & (1 << 2))) {   /*10G/1G mode */
   5393                     *pif = SOC_PORT_IF_KX;
   5394                 } else {
   5395                     *pif = SOC_PORT_IF_KR;
   5396                 }
   5397             } else {
   5398                 *pif = SOC_PORT_IF_XAUI;
   5399             }
   5400         } else {                /*40G mode */
   5401             if (mode & PHY84740_PMAD_DAC_MODE_MASK) {
   5402                 *pif = SOC_PORT_IF_CR4;
   5403             } else if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) {
   5404                 *pif = SOC_PORT_IF_KR4;
   5405             } else {
   5406                 *pif = SOC_PORT_IF_XLAUI;
   5407             }
   5408         }
   5409     } else {                    /*Quebec */
   5410         if (!(PHY84740_SINGLE_PORT_MODE(pc))) {
   5411             *pif = SOC_PORT_IF_XAUI;
   5412         } else {                /*40G mode */
   5413             if (mode & PHY84740_PMAD_DAC_MODE_MASK) {
   5414                 *pif = SOC_PORT_IF_CR4;
   5415             } else {
   5416                 *pif = SOC_PORT_IF_XLAUI;
   5417             }
   5418         }
   5419     }
   5420     return SOC_E_NONE;
   5421 }
   5422 
   5423 /*
   5424  *  Function:  *      phy_84740_rom_wait
   5425  *
   5426  *  Purpose:
   5427  *      Wait for data to be written to the SPI-ROM.
   5428  *  Input:
   5429  *      unit, port
   5430  */
   5431 STATIC int phy_84740_rom_wait(int unit, int port)
   5432 {
   5433     uint16 rd_data;
   5434     uint16 wr_data;
   5435     uint16 data16;
   5436     int count;
   5437     phy_ctrl_t *pc;
   5438     soc_timeout_t to;
   5439     int SPI_READY;
   5440 
   5441     pc = EXT_PHY_SW_STATE(unit, port);
   5442 
   5443     rd_data = 0;
   5444     soc_timeout_init(&to, WR_TIMEOUT, 0);
   5445     do {
   5446         /* Write SPI Control Register Read Command. */
   5447         count = 1;
   5448         wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
   5449         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5450         wr_data = SPI_CTRL_1_L;
   5451         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5452 
   5453         /* extra reads to clear the status */
   5454         SOC_IF_ERROR_RETURN
   5455             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
   5456         SOC_IF_ERROR_RETURN
   5457             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
   5458 
   5459         if (rd_data & 0x0100) {
   5460             break;
   5461         }
   5462     } while (!soc_timeout_check(&to));
   5463     if (!(rd_data & 0x0100)) {
   5464         LOG_ERROR(BSL_LS_SOC_PHY,
   5465                   (BSL_META_U(unit,
   5466                               "phy_84740_rom_program: u = %d p = %d "
   5467                               "timeout 1\n"), unit, port));
   5468         return SOC_E_TIMEOUT;
   5469     }
   5470 
   5471     SPI_READY = 1;
   5472     while (SPI_READY == 1) {
   5473         /* Set-up SPI Controller To Receive SPI EEPROM Status. */
   5474         count = 1;
   5475         wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count);
   5476         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5477         wr_data = SPI_CTRL_2_H;
   5478         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5479         wr_data = 0x0100;
   5480         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5481         /* Fill-up SPI Transmit Fifo To check SPI Status. */
   5482         count = 2;
   5483         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   5484         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5485         /* Write Tx Fifo Register Address. */
   5486         wr_data = SPI_TXFIFO;
   5487         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5488 
   5489         /* Write SPI Tx Fifo Control Word-1. */
   5490         wr_data = ((1 * 0x0100) | MSGTYPE_HRD);
   5491         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5492         /* Write SPI Tx Fifo Control Word-2. */
   5493         wr_data = RDSR_OPCODE;
   5494         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5495         /* Write SPI Control Register Write Command. */
   5496         count = 2;
   5497         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   5498         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5499         /* Write SPI Control -1 Register Address. */
   5500         wr_data = SPI_CTRL_1_L;
   5501         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5502         /* Write SPI Control -1 Register Word-1. */
   5503         wr_data = 0x0101;
   5504         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5505         /* Write SPI Control -1 Register Word-2. */
   5506         wr_data = 0x0100;
   5507         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5508         /* Write SPI Control Register Write Command. */
   5509         count = 1;
   5510         wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count);
   5511         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5512         /* Write SPI Control -1 Register Address. */
   5513         wr_data = SPI_CTRL_1_H;
   5514         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5515         /* Write SPI Control -1 Register Word-2. */
   5516         wr_data = 0x0103;
   5517         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5518         /* Wait For 64 bytes To be written.   */
   5519         rd_data = 0x0000;
   5520         soc_timeout_init(&to, WR_TIMEOUT, 0);
   5521         do {
   5522             count = 1;
   5523             wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
   5524             SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5525             wr_data = SPI_CTRL_1_L;
   5526             SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5527 
   5528             /* extra reads to clear the status */
   5529             SOC_IF_ERROR_RETURN
   5530                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
   5531             SOC_IF_ERROR_RETURN
   5532                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
   5533 
   5534             if (rd_data & 0x0100) {
   5535                 break;
   5536             }
   5537         } while (!soc_timeout_check(&to));
   5538         if (!(rd_data & 0x0100)) {
   5539             LOG_ERROR(BSL_LS_SOC_PHY,
   5540                       (BSL_META_U(unit,
   5541                                   "phy_84740_rom_program: u = %d p = %d "
   5542                                   "timeout 2\n"), unit, port));
   5543             return SOC_E_TIMEOUT;
   5544         }
   5545         /* Write SPI Control Register Read Command. */
   5546         count = 1;
   5547         wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
   5548         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5549         /* Write SPI Control -1 Register Address. */
   5550         wr_data = SPI_RXFIFO;
   5551 
   5552         SOC_IF_ERROR_RETURN
   5553             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wr_data));
   5554         SOC_IF_ERROR_RETURN
   5555             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data));
   5556 
   5557         /* Clear LASI Message Out Status. */
   5558         SOC_IF_ERROR_RETURN
   5559             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &wr_data));
   5560 
   5561         if ((rd_data & 0x1) == 0) {
   5562             SPI_READY = 0;
   5563         }
   5564         /* extra reads to clear the status */
   5565         SOC_IF_ERROR_RETURN
   5566             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
   5567         SOC_IF_ERROR_RETURN
   5568             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
   5569     }                           /* SPI_READY  */
   5570     return SOC_E_NONE;
   5571 }
   5572 
   5573 /*
   5574  * Function:
   5575  *      phy_84740_rom_write_enable_set
   5576  *
   5577  * Purpose:
   5578  *      Enable disable protection on SPI_EEPROM
   5579  *
   5580  * Input:
   5581  *      unit
   5582  *      port
   5583  *      enable
   5584  * Output:
   5585  *      SOC_E_xxx
   5586  *
   5587  * Notes:
   5588  *          25AA256 256Kbit Serial EEPROM
   5589  *          STATUS Register
   5590  *          +------------------------------------------+
   5591  *          | WPEN | x | x | x | BP1 | BP0 | WEL | WIP |
   5592  *          +------------------------------------------+
   5593  *      BP1 BP0  :   Protected Blocks
   5594  *       0   0   :  Protect None
   5595  *       1   1   :  Protect All
   5596  *
   5597  *      WEL : Write Latch Enable
   5598  *       0  : Do not allow writes
   5599  *       1  : Allow writes
   5600  */
   5601 
   5602 STATIC int
   5603 phy_84740_rom_write_enable_set(int unit, int port, int enable)
   5604 {
   5605     uint16 rd_data;
   5606     uint16 wr_data;
   5607     uint8 wrsr_data;
   5608     int count;
   5609     phy_ctrl_t *pc;
   5610 
   5611     pc = EXT_PHY_SW_STATE(unit, port);
   5612 
   5613     /*
   5614      * Write SPI Control Register Write Command.
   5615      */
   5616     count = 2;
   5617     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   5618     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5619 
   5620     /*
   5621      * Write SPI Control -2 Register Address.
   5622      */
   5623     wr_data = SPI_CTRL_2_L;
   5624     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5625 
   5626     /*
   5627      * Write SPI Control -2 Register Word-1.
   5628      */
   5629     wr_data = 0x8200;
   5630     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5631 
   5632     /*
   5633      * Write SPI Control -2 Register Word-2.
   5634      */
   5635     wr_data = 0x0100;
   5636     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5637 
   5638     /*
   5639      * Fill-up SPI Transmit Fifo With SPI EEPROM Messages.
   5640      * Write SPI Control Register Write Command.
   5641      */
   5642     count = 4;
   5643     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   5644     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5645 
   5646     /*
   5647      * Write Tx Fifo Register Address.
   5648      */
   5649     wr_data = SPI_TXFIFO;
   5650     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5651 
   5652     /*
   5653      * Write SPI Tx Fifo Control Word-1.
   5654      */
   5655     wr_data = ((1 * 0x0100) | MSGTYPE_HWR);
   5656     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5657 
   5658     /*
   5659      * Write SPI Tx Fifo Control Word-2.
   5660      */
   5661     wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE);
   5662     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5663 
   5664     /*
   5665      * Write SPI Tx Fifo Control Word-3.
   5666      */
   5667     wr_data = ((WRSR_OPCODE * 0x100) | (0x2));
   5668     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5669 
   5670     /*
   5671      * Write SPI Tx Fifo Control Word-4.
   5672      */
   5673     wrsr_data = enable ? 0x2 : 0xc;
   5674     wr_data = ((wrsr_data * 0x0100) | wrsr_data);
   5675     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5676 
   5677     /*
   5678      * Write SPI Control Register Write Command.
   5679      */
   5680     count = 2;
   5681     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   5682     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5683 
   5684     /*
   5685      * Write SPI Control -1 Register Address.
   5686      */
   5687     wr_data = SPI_CTRL_1_L;
   5688     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5689 
   5690     /*
   5691      * Write SPI Control -1 Register Word-1.
   5692      */
   5693     wr_data = 0x0101;
   5694     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5695 
   5696     /*
   5697      * Write SPI Control -1 Register Word-2.
   5698      */
   5699     wr_data = 0x0003;
   5700     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   5701 
   5702     /*
   5703      * Wait For WRSR Command To be written.
   5704      */
   5705     SOC_IF_ERROR_RETURN(phy_84740_rom_wait(unit, port));
   5706 
   5707     return SOC_E_NONE;
   5708 }
   5709 
   5710 STATIC int _phy84740_init_ucode_bcst(int unit, int port, int cmd)
   5711 {
   5712     uint16 data16;
   5713     uint16 mask16;
   5714     uint16 phy_id;
   5715     int j;
   5716     uint16 num_words;
   5717     int i;
   5718     uint16 chip_mode;
   5719     int num_lanes;
   5720     uint8 *fw_ptr;
   5721     int fw_length;
   5722     phy_ctrl_t *pc;
   5723 
   5724     pc = EXT_PHY_SW_STATE(unit, port);
   5725     num_lanes = PHY84740_SINGLE_PORT_MODE(pc) ? 4 : 1;
   5726 
   5727 #ifdef BCM_WARM_BOOT_SUPPORT
   5728     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
   5729         return SOC_E_NONE;
   5730     }
   5731 #endif
   5732 
   5733     if (cmd == PHYCTRL_UCODE_BCST_SETUP) {
   5734         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   5735                             (unit, pc, PHY84740_PMAD_CHIP_MODE_REG,
   5736                              &chip_mode));
   5737 
   5738         LOG_INFO(BSL_LS_SOC_PHY,
   5739                  (BSL_META_U(unit,
   5740                              "PHY84740 BCST start: u=%d p=%d\n"), unit, port));
   5741         /* check the current chip mode, switch to quad if in single port mode */
   5742         if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) ==
   5743             PHY84740_PMAD_MODE_40G) {
   5744             LOG_INFO(BSL_LS_SOC_PHY,
   5745                      (BSL_META_U(unit,
   5746                                  "PHY84740 BCST mode switch: u=%d p=%d\n"),
   5747                                  unit, port));
   5748             SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode
   5749                                 (unit, port, NULL));
   5750         }
   5751 
   5752         /* program the bcst register. do 4 lanes for single port configuration */
   5753         phy_id = pc->phy_id;
   5754         /* configure all four ports  */
   5755         for (i = 0; i < num_lanes; i++) {
   5756             if (num_lanes > 1) {
   5757                 pc->phy_id = (phy_id & (~0x3)) + i;     /* Port 3, 2, 1 and 0 */
   5758             }
   5759             SOC_IF_ERROR_RETURN
   5760                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0xffff));
   5761         }
   5762         /* restore the original phy_id */
   5763         pc->phy_id = phy_id;
   5764         return SOC_E_NONE;
   5765     } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) {
   5766         LOG_INFO(BSL_LS_SOC_PHY,
   5767                  (BSL_META_U(unit,
   5768                              "PHY84740 BCST1: u=%d p=%d\n"), unit, port));
   5769         /* clear SPA ctrl reg bit 15 and bit 13.
   5770          * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM
   5771          * bit 13, 0 clear download done status, 1 skip download
   5772          */
   5773         mask16 = (1 << 13) | (1 << 15);
   5774         data16 = 0;
   5775         SOC_IF_ERROR_RETURN
   5776             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   5777              (unit, pc, PHY84740_PMAD_SPA_CTRL_REG, data16, mask16));
   5778 
   5779         /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */
   5780         mask16 = 1 << 14;
   5781         data16 = mask16;
   5782         SOC_IF_ERROR_RETURN
   5783             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   5784              (unit, pc, PHY84740_PMAD_SPA_CTRL_REG, data16, mask16));
   5785 
   5786         /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */
   5787         mask16 = 1 << 3;
   5788         data16 = mask16;
   5789         SOC_IF_ERROR_RETURN
   5790             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   5791              (unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, data16, mask16));
   5792 
   5793         /* apply bcst Reset to start download code from MDIO */
   5794         SOC_IF_ERROR_RETURN(WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, 0x8000));
   5795         return SOC_E_NONE;
   5796     } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) {
   5797         LOG_INFO(BSL_LS_SOC_PHY,
   5798                  (BSL_META_U(unit,
   5799                              "PHY84740 BCST2: u=%d p=%d\n"), unit, port));
   5800 
   5801         /* reset clears bcst register */
   5802         /* restore bcst register after reset */
   5803         phy_id = pc->phy_id;
   5804         /* configure all four ports  */
   5805         for (i = 0; i < num_lanes; i++) {
   5806             if (num_lanes > 1) {
   5807                 pc->phy_id = (phy_id & (~0x3)) + i;     /* Port 3, 2, 1 and 0 */
   5808             }
   5809             SOC_IF_ERROR_RETURN
   5810                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0xffff));
   5811         }
   5812         /* restore the original phy_id */
   5813         pc->phy_id = phy_id;
   5814         return SOC_E_NONE;
   5815     } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) {
   5816         LOG_INFO(BSL_LS_SOC_PHY,
   5817                  (BSL_META_U(unit,
   5818                              "firmware_bcst,device name %s: u=%d p=%d\n"),
   5819                              pc->dev_name ? pc->dev_name : "NULL", unit, port));
   5820         /* find the right firmware */
   5821         if (pc->dev_name == dev_name_84740) {
   5822             fw_ptr = phy84740_ucode_bin;
   5823             fw_length = phy84740_ucode_bin_len;
   5824         } else if (pc->dev_name == dev_name_84752) {
   5825             fw_ptr = phy84752_ucode_bin;
   5826             fw_length = phy84752_ucode_bin_len;
   5827         } else if (pc->dev_name == dev_name_84753) {
   5828             fw_ptr = phy84753_ucode_bin;
   5829             fw_length = phy84753_ucode_bin_len;
   5830         } else if (pc->dev_name == dev_name_84754) {
   5831             fw_ptr = phy84754_ucode_bin;
   5832             fw_length = phy84754_ucode_bin_len;
   5833         } else if (pc->dev_name == dev_name_84064) {
   5834             fw_ptr = phy84064_ucode_bin;
   5835             fw_length = phy84064_ucode_bin_len;
   5836         } else if (pc->dev_name == dev_name_84784) {
   5837             fw_ptr = phy84784_ucode_bin;
   5838             fw_length = phy84784_ucode_bin_len;
   5839         } else {
   5840             /* invalid device name */
   5841             LOG_WARN(BSL_LS_SOC_PHY,
   5842                      (BSL_META_U(unit,
   5843                                  "firmware_bcst,invalid device name %s: u=%d p=%d\n"),
   5844                       pc->dev_name ? pc->dev_name : "NULL", unit, port));
   5845             return SOC_E_NONE;
   5846         }
   5847 
   5848         /* wait for 2ms for M8051 start and 5ms to initialize the RAM */
   5849         sal_usleep(10000);      /* Wait for 10ms */
   5850 
   5851         /* Write Starting Address, where the Code will reside in SRAM */
   5852         data16 = 0x8000;
   5853         SOC_IF_ERROR_RETURN
   5854             (WRITE_PHY84740_MMF_PMA_PMD_REG
   5855              (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
   5856 
   5857         /* make sure address word is read by the micro */
   5858         sal_udelay(10);         /* Wait for 10us */
   5859 
   5860         /* Write SPI SRAM Count Size */
   5861         data16 = (fw_length) / 2;
   5862         SOC_IF_ERROR_RETURN
   5863             (WRITE_PHY84740_MMF_PMA_PMD_REG
   5864              (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
   5865 
   5866         /* make sure read by the micro */
   5867         sal_udelay(10);         /* Wait for 10us */
   5868 
   5869         /* Fill in the SRAM */
   5870         num_words = (fw_length - 1);
   5871         for (j = 0; j < num_words; j += 2) {
   5872             /* Make sure the word is read by the Micro */
   5873             sal_udelay(10);
   5874 
   5875             data16 = (fw_ptr[j] << 8) | fw_ptr[j + 1];
   5876 
   5877             SOC_IF_ERROR_RETURN
   5878                 (WRITE_PHY84740_MMF_PMA_PMD_REG
   5879                  (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16));
   5880         }
   5881         return SOC_E_NONE;
   5882     } else if (cmd == PHYCTRL_UCODE_BCST_END) {
   5883         LOG_INFO(BSL_LS_SOC_PHY,
   5884                  (BSL_META_U(unit,
   5885                              "PHY84740 BCST end: u=%d p=%d\n"), unit, port));
   5886 
   5887         /* make sure last code word is read by the micro */
   5888         sal_udelay(20);
   5889 
   5890         /* first disable bcst mode */
   5891         phy_id = pc->phy_id;
   5892         for (i = 0; i < num_lanes; i++) {
   5893             if (num_lanes > 1) {
   5894                 pc->phy_id = (phy_id & (~0x3)) + i;     /* Port 3, 2, 1 and 0 */
   5895             }
   5896             SOC_IF_ERROR_RETURN
   5897                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0x0));
   5898 
   5899             /* Read Hand-Shake message (Done) from Micro */
   5900             SOC_IF_ERROR_RETURN
   5901                 (READ_PHY84740_MMF_PMA_PMD_REG
   5902                  (unit, pc, PHY84740_PMAD_M8051_MSGOUT_REG, &data16));
   5903 
   5904             /* Download done message */
   5905             LOG_INFO(BSL_LS_SOC_PHY,
   5906                      (BSL_META_U(unit,
   5907                                  "u=%d p=%d MDIO firmware download done message: 0x%x\n"),
   5908                       unit, port, data16));
   5909 
   5910             /* Clear LASI status */
   5911             SOC_IF_ERROR_RETURN
   5912                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
   5913         }
   5914         /* restore the original phy_id */
   5915         pc->phy_id = phy_id;
   5916 
   5917         /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */
   5918         sal_udelay(100);        /* Wait for 100 usecs */
   5919 
   5920         phy_id = pc->phy_id;
   5921         for (i = 0; i < num_lanes; i++) {
   5922             if (num_lanes > 1) {
   5923                 pc->phy_id = (phy_id & (~0x3)) + i;     /* Port 3, 2, 1 and 0 */
   5924             }
   5925             SOC_IF_ERROR_RETURN
   5926                 (READ_PHY84740_MMF_PMA_PMD_REG
   5927                  (unit, pc, PHY84740_PMAD_M8051_MSGOUT_REG, &data16));
   5928 
   5929             /* Need to check if checksum is correct */
   5930             SOC_IF_ERROR_RETURN
   5931                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16));
   5932 
   5933             if (data16 != 0x600D) {
   5934                 /* Bad CHECKSUM */
   5935                LOG_CLI((BSL_META_U(unit,
   5936                                    "firmware_bcst downlad failure: port %d "
   5937                                    "Incorrect Checksum %x\n"), port, data16));
   5938                 return SOC_E_FAIL;
   5939             }
   5940 
   5941             /* read Rev-ID */
   5942             SOC_IF_ERROR_RETURN
   5943                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16));
   5944             LOG_INFO(BSL_LS_SOC_PHY,
   5945                      (BSL_META_U(unit,
   5946                                  "u=%d p=%d MDIO Firmware download revID: 0x%x\n"),
   5947                       unit, port, data16));
   5948         }
   5949         /* restore the original phy_id */
   5950         pc->phy_id = phy_id;
   5951 
   5952         return SOC_E_NONE;
   5953     } else {
   5954          LOG_WARN(BSL_LS_SOC_PHY,
   5955                   (BSL_META_U(unit,
   5956                               "u=%d p=%d firmware_bcst: invalid cmd 0x%x\n"),
   5957                               unit, port, cmd));
   5958     }
   5959 
   5960     return SOC_E_FAIL;
   5961 }
   5962 
   5963 /*
   5964  * Function:
   5965  *      phy_84740_firmware_set
   5966  * Purpose:
   5967  *      program the given firmware into the SPI-ROM 
   5968  * Parameters:
   5969  *      unit - StrataSwitch unit #.
   5970  *      port - StrataSwitch port #.
   5971  *      offset - offset to the data stream
   5972  *      array  - the given data
   5973  *      datalen- the data length  
   5974  * Returns:
   5975  *      SOC_E_NONE
   5976  */
   5977 
   5978 STATIC int
   5979 phy_84740_firmware_set(int unit, int port, int offset, uint8 *array,
   5980                        int datalen)
   5981 {
   5982     uint16 saved_phy_addr;
   5983     int ix;
   5984     phy_ctrl_t *pc;
   5985     uint32 devid;
   5986     uint32 uCode_devid;
   5987 
   5988     /* overload this function a littl bit if array == NULL 
   5989      * special handling for init. uCode broadcast. Internal use only 
   5990      */
   5991     if (array == NULL) {
   5992         return _phy84740_init_ucode_bcst(unit, port, offset);
   5993     }
   5994 
   5995     pc = EXT_PHY_SW_STATE(unit, port);
   5996 
   5997     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   5998                         (pc->unit, pc->port, pc, &devid));
   5999 
   6000     /* first validate the firmware is for the configured device
   6001      * 84740 has 1.5V from TXDRV pin, 84754 is internally wired at 1.0V.
   6002      * If the 84754 firmware which programs chip for 1.0V is loaded
   6003      * to the 84740, then it may damage the device and module.
   6004      * 
   6005      *  Chip ID is at addresses 0x7FF9, 0x7FFA, 0x7FFB.e.g. 
   6006      *  for 84740, [0x7FF9] = 0x08, [0x7FFA] = 0x47, [0x7FFB] = 0x40. 
   6007      *  Version number is at 0x7FFC-0x7FFD
   6008      */
   6009 
   6010     /* length should be at least 0xFFFE */
   6011     if (datalen < PHY84740_UCODE_DEVID_ADDR+3) {
   6012         LOG_WARN(BSL_LS_SOC_PHY,
   6013                  (BSL_META_U(unit,
   6014                              "firmware_set, wrong firmware len=0x%x : u=%d p=%d\n"),
   6015                              datalen, unit, port));
   6016         return SOC_E_PARAM;
   6017     }
   6018 
   6019     /* check the firmware devid matches the configured devid */
   6020     ix = PHY84740_UCODE_DEVID_ADDR;
   6021     uCode_devid = (array[ix] << 16) | (array[ix + 1] << 8) | array[ix + 2];
   6022 
   6023     if (uCode_devid != devid) {
   6024         LOG_WARN(BSL_LS_SOC_PHY,
   6025                  (BSL_META_U(unit,
   6026                              "firmware_set,u=%d p=%d:  Firmware device "
   6027                              "type(0x%x) does not match configured device type(0x%x)\n"),
   6028                   unit, port,uCode_devid,devid));
   6029         return SOC_E_PARAM;
   6030     }
   6031 
   6032     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   6033         /* switch to quad-mode */
   6034         SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode(unit, port, NULL));
   6035     }
   6036     saved_phy_addr = pc->phy_id;
   6037 
   6038     LOG_INFO(BSL_LS_SOC_PHY,
   6039              (BSL_META_U(unit,
   6040                          "firmware_set init,quad port : u=%d p=%d\n"),
   6041                          unit, port));
   6042     /* configure all four lanes to bcst mode */
   6043     for (ix = 0; ix < 4; ix++) {
   6044         pc->phy_id = (saved_phy_addr & (~0x3)) + ix;
   6045         SOC_IF_ERROR_RETURN
   6046             (WRITE_PHY84740_MMF_PMA_PMD_REG
   6047              (unit, pc, PHY84740_PMAD_BCST_REG, 0xffff));
   6048     }
   6049     pc->phy_id = saved_phy_addr;
   6050 
   6051     /* place all uC in reset */
   6052     SOC_IF_ERROR_RETURN
   6053         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0x018f));
   6054 
   6055     /* disable all port's SPI */
   6056     SOC_IF_ERROR_RETURN
   6057         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x000f));
   6058 
   6059     SOC_IF_ERROR_RETURN
   6060         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x000c));
   6061 
   6062     /* Set bit 0 (spa enable) in C848 for master channel ? */
   6063     SOC_IF_ERROR_RETURN
   6064         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0x2000, 0x2000));
   6065 
   6066     /* disable the bcst mode for all channels */
   6067     SOC_IF_ERROR_RETURN
   6068         (WRITE_PHY84740_MMF_PMA_PMD_REG
   6069          (unit, pc, PHY84740_PMAD_BCST_REG, 0xfffe));
   6070 
   6071     SOC_IF_ERROR_RETURN
   6072         (_phy_84740_firmware_to_rom(unit, port, offset, array, datalen));
   6073 
   6074     /* switch back to single mode */
   6075     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   6076         /* switch to quad-mode */
   6077         SOC_IF_ERROR_RETURN(_phy_84740_quad_to_single_mode(unit, port));
   6078     }
   6079     return SOC_E_NONE;
   6080 }
   6081 
   6082 STATIC int
   6083 _phy_84740_firmware_to_rom(int unit, int port, int offset, uint8 *array,
   6084                            int datalen)
   6085 {
   6086     uint16 rd_data;
   6087     uint16 wr_data;
   6088     int j;
   6089     int i = 0;
   6090     int count;
   6091     uint8 spi_values[WR_BLOCK_SIZE];
   6092     uint16 data16;
   6093     soc_timeout_t to;
   6094     phy_ctrl_t *pc;
   6095 
   6096     pc = EXT_PHY_SW_STATE(unit, port);
   6097 
   6098     /*
   6099      * Enable SPI for Port0
   6100      */
   6101     SOC_IF_ERROR_RETURN
   6102         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x0000));
   6103     SOC_IF_ERROR_RETURN
   6104         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x0000));
   6105     /*
   6106      * Remove M8051 resets for port 0.
   6107      * and wait for Micro to complete Init.
   6108      */
   6109     /* clear bits 3:0 */
   6110     SOC_IF_ERROR_RETURN
   6111         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0, 0xf));
   6112     sal_usleep(10000);
   6113 
   6114     /* set bit(request) in 0xc848 for the required channel, remove done bit */
   6115     SOC_IF_ERROR_RETURN
   6116         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0, 0x2000));
   6117 
   6118     /* enable SPI port enable */
   6119     SOC_IF_ERROR_RETURN
   6120         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0xc004, 0xc004));
   6121 
   6122     /*
   6123      * Read LASI Status registers To clear initial Failure status.
   6124      */
   6125     SOC_IF_ERROR_RETURN
   6126         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data));
   6127     SOC_IF_ERROR_RETURN
   6128         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9004, &rd_data));
   6129     SOC_IF_ERROR_RETURN
   6130         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9005, &rd_data));
   6131 
   6132     /*
   6133      * Enable the LASI For Message out. 
   6134      */
   6135     SOC_IF_ERROR_RETURN
   6136         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9000, 0x0004));
   6137     /*
   6138      * 0x9002, bit 2 Is Rx Alarm enabled For LASI. 
   6139      */
   6140     SOC_IF_ERROR_RETURN
   6141         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9002, 0x0004));
   6142     /*
   6143      * Read Any Residual Message out register.
   6144      */
   6145     SOC_IF_ERROR_RETURN
   6146         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data));
   6147     /*
   6148      * Clear LASI Message Out Status. 
   6149      */
   6150     SOC_IF_ERROR_RETURN
   6151         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data));
   6152 
   6153     /* set SPI-ROM write enable */
   6154     SOC_IF_ERROR_RETURN(phy_84740_rom_write_enable_set(unit, port, 1));
   6155 
   6156     LOG_INFO(BSL_LS_SOC_PHY,
   6157              (BSL_META_U(unit,
   6158                          "init0: u=%d p=%d\n"),
   6159                          unit, port));
   6160 
   6161     for (j = 0; j < datalen; j += WR_BLOCK_SIZE) {
   6162         /*
   6163          * Setup SPI Controller. 
   6164          */
   6165         count = 2;
   6166         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   6167         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6168 
   6169         /* Write SPI Control -2 Register Address. */
   6170         wr_data = SPI_CTRL_2_L;
   6171         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6172 
   6173         /* Write SPI Control -2 Register Word-1. */
   6174         wr_data = 0x8200;
   6175         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6176 
   6177         /* Write SPI Control -2 Register Word-2. */
   6178         wr_data = 0x0100;
   6179         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6180 
   6181         /* Fill-up SPI Transmit Fifo.
   6182          * Write SPI Control Register Write Command.
   6183          */
   6184         count = 4 + (WR_BLOCK_SIZE / 2);
   6185         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   6186         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6187 
   6188         /* Write Tx Fifo Register Address. */
   6189         wr_data = SPI_TXFIFO;
   6190         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6191 
   6192         /* Write SPI Tx Fifo Control Word-1. */
   6193         wr_data = ((1 * 0x0100) | MSGTYPE_HWR);
   6194         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6195 
   6196         /* Write SPI Tx Fifo Control Word-2. */
   6197         wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE);
   6198         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6199 
   6200         /* Write SPI Tx Fifo Control Word-3. */
   6201         wr_data = ((WR_OPCODE * 0x0100) | (0x3 + WR_BLOCK_SIZE));
   6202         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6203 
   6204         /* Write SPI Tx Fifo Control Word-4. */
   6205         wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100));
   6206         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6207 
   6208         LOG_INFO(BSL_LS_SOC_PHY,
   6209                  (BSL_META_U(unit,
   6210                              "loop: u=%d p=%d,inxj: %d,inxi:%d\n"),
   6211                              unit, port,j,i));
   6212 
   6213         if (datalen < (j + WR_BLOCK_SIZE)) {    /* last block */
   6214             sal_memset(spi_values, 0, WR_BLOCK_SIZE);
   6215             sal_memcpy(spi_values, &array[j], datalen - j);
   6216 
   6217             for (i = 0; i < WR_BLOCK_SIZE; i += 2) {
   6218                 /* Write SPI Tx Fifo Data Word-4. */
   6219                 wr_data = ((spi_values[i + 1] * 0x0100) | spi_values[i]);
   6220                 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6221             }
   6222         } else {
   6223             for (i = 0; i < WR_BLOCK_SIZE; i += 2) {
   6224                 /* Write SPI Tx Fifo Data Word-4. */
   6225                 wr_data = ((array[j + i + 1] * 0x0100) | array[j + i]);
   6226                 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6227             }
   6228         }
   6229 
   6230         /* 
   6231          * Set-up SPI Controller To Transmit.
   6232          * Write SPI Control Register Write Command.
   6233          */
   6234         count = 2;
   6235         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   6236         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6237 
   6238         wr_data = SPI_CTRL_1_L;
   6239         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6240 
   6241         /* Write SPI Control -1 Register Word-1. */
   6242         wr_data = 0x0501;
   6243         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6244 
   6245         /* Write SPI Control -1 Register Word-2. */
   6246         wr_data = 0x0003;
   6247         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6248 
   6249         /* Wait For 64 bytes To be written.   */
   6250         SOC_IF_ERROR_RETURN(phy_84740_rom_wait(unit, port));
   6251 
   6252     }                           /* SPI_WRITE */
   6253 
   6254     /* clear SPI-ROM write enable */
   6255     SOC_IF_ERROR_RETURN(phy_84740_rom_write_enable_set(unit, port, 0));
   6256 
   6257     /* Disable SPI EEPROM. */
   6258     count = 2;
   6259     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   6260     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6261 
   6262     /* Write SPI Control -2 Register Address. */
   6263     wr_data = SPI_CTRL_2_L;
   6264     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6265 
   6266     /* Write SPI Control -2 Register Word-1. */
   6267     wr_data = 0x8200;
   6268     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6269 
   6270     /* Write SPI Control -2 Register Word-2. */
   6271     wr_data = 0x0100;
   6272     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6273 
   6274     /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */
   6275     count = 2;
   6276     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   6277     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6278 
   6279     /* Write Tx Fifo Register Address. */
   6280     wr_data = SPI_TXFIFO;
   6281     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6282 
   6283     /* Write SPI Tx Fifo Control Word-1. */
   6284     wr_data = ((0x1 * 0x0100) | MSGTYPE_HWR);
   6285     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6286 
   6287     /* Write SPI Tx Fifo Control Word-2. */
   6288     wr_data = WRDI_OPCODE;
   6289     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6290 
   6291     /* Write SPI Control Register Write Command. */
   6292     count = 2;
   6293     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   6294     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6295 
   6296     /* Write SPI Control -1 Register Address. */
   6297     wr_data = SPI_CTRL_1_L;
   6298     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6299 
   6300     /* Write SPI Control -1 Register Word-1. */
   6301     wr_data = 0x0101;
   6302     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6303 
   6304     /* Write SPI Control -1 Register Word-2. */
   6305     wr_data = 0x0003;
   6306     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6307 
   6308     /* Wait For WRDI Command To be written */
   6309     rd_data = 0;
   6310     soc_timeout_init(&to, WR_TIMEOUT, 0);
   6311     do {
   6312         /* Write SPI Control Register Read Command. */
   6313         count = 1;
   6314         wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
   6315         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6316         wr_data = SPI_CTRL_1_L;
   6317         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   6318 
   6319         /* extra reads to clear the status */
   6320         SOC_IF_ERROR_RETURN
   6321             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16));
   6322         SOC_IF_ERROR_RETURN
   6323             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16));
   6324 
   6325         if (rd_data & 0x0100) {
   6326             break;
   6327         }
   6328     } while (!soc_timeout_check(&to));
   6329 
   6330     if (!(rd_data & 0x0100)) {
   6331         LOG_ERROR(BSL_LS_SOC_PHY,
   6332                   (BSL_META_U(unit,
   6333                               "phy_84740_rom_program: u = %d p = %d "
   6334                               "WRDI command timeout\n"), unit, port));
   6335         return SOC_E_TIMEOUT;
   6336     }
   6337 
   6338     LOG_INFO(BSL_LS_SOC_PHY,
   6339              (BSL_META_U(unit,
   6340                          "phy_84740_rom_program: u=%d p=%d done\n"), unit, port));
   6341 
   6342     return SOC_E_NONE;
   6343 }
   6344 
   6345 static int
   6346 write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, uint16 *rddata)
   6347 {
   6348 
   6349     uint16 tmp_data = 0;
   6350     soc_timeout_t to;
   6351 
   6352     SOC_IF_ERROR_RETURN
   6353         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wrdata));
   6354 
   6355     soc_timeout_init(&to, WR_TIMEOUT, 0);
   6356     do {
   6357         SOC_IF_ERROR_RETURN
   6358             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9005, &tmp_data));
   6359         if (tmp_data & 0x4)
   6360             break;
   6361     } while (!soc_timeout_check(&to));
   6362     if (!(tmp_data & 0x4)) {
   6363         LOG_ERROR(BSL_LS_SOC_PHY,
   6364                   (BSL_META_U(unit,
   6365                               "write_message failed: wrdata %04x\n"), wrdata));
   6366         return SOC_E_FAIL;
   6367     }
   6368 
   6369     SOC_IF_ERROR_RETURN
   6370         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &tmp_data));
   6371     *rddata = tmp_data;
   6372     SOC_IF_ERROR_RETURN
   6373         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &tmp_data));
   6374 
   6375     return SOC_E_NONE;
   6376 }
   6377 
   6378 /*
   6379  * Function:
   6380  *      phy_84740_precondition_before_probe
   6381  * Purpose:
   6382  *      When the device is in 40G, ie. after a power reset, and the 10G
   6383  *      port being probed does not have the 40G address in PRTAD, the
   6384  *      device will not respond until the port that has the 40G address
   6385  *      is probed. To avoid not programming ports correctly, make
   6386  *      sure the device is in quad (4x10G) PMD mode when the SDK port is 10G.
   6387  * Parameters:
   6388  *      unit - StrataSwitch unit #.
   6389  *      pc   - phy ctrl descriptor.
   6390  * Returns:
   6391  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   6392  */
   6393 
   6394 STATIC int
   6395 phy_84740_precondition_before_probe(int unit, phy_ctrl_t *pc)
   6396 {
   6397     int ids;
   6398     int rv = SOC_E_NOT_FOUND;
   6399     uint16 saved_phy_id;
   6400     uint16 id0, id1;
   6401     uint32 devid;
   6402 
   6403     /* Not required when the port is single PMD */
   6404     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   6405         LOG_INFO(BSL_LS_SOC_PHY,
   6406                  (BSL_META_U(unit,
   6407                              "PMD must not be called when in single PMD\n")));
   6408         return rv;
   6409     }
   6410 
   6411     saved_phy_id = pc->phy_id;
   6412 
   6413     /* Look for first address that responds */
   6414     for (ids = 0; ids < 4; ids++) {
   6415 
   6416         pc->phy_id = (saved_phy_id & ~0x3) + ids;
   6417         LOG_INFO(BSL_LS_SOC_PHY,
   6418                  (BSL_META_U(unit,
   6419                              "Try device with address %x\n"), pc->phy_id));
   6420 
   6421         SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   6422                             (pc->unit, pc->port, pc, &devid));
   6423 
   6424         
   6425         /* 
   6426          * Make sure the device has the correct dev IDs 
   6427          * Note that this is being called either because the soc probe found
   6428          * the ids or there was an id override. In the later case, the device
   6429          * might not have the 84740 ids so this PMD setup will not be supported
   6430          */
   6431         id0 = 0;
   6432         READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
   6433                                       2 /*PHY84740_DEV1_PMD_IDENTIFIER_REGISTER_0 */,
   6434                                       &id0);
   6435         if (id0 == 0xffff) {
   6436             continue;
   6437         }
   6438         id1 = 0;
   6439         READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 
   6440                                       3 /*PHY84740_DEV1_PMD_IDENTIFIER_REGISTER_1 */,
   6441                                       &id1);
   6442         if (id1 == 0xffff) {
   6443             continue;
   6444         }
   6445 
   6446         switch(devid) {
   6447             case PHY84740_ID_84740:
   6448             case PHY84740_ID_84752:
   6449             case PHY84740_ID_84753:
   6450             case PHY84740_ID_84754:
   6451             case PHY84740_ID_84064:
   6452                 break;
   6453             default:
   6454                if (PHY84740_IS_QUADRA(devid)) {
   6455                     break;
   6456                } else {  /* not found */
   6457                     LOG_WARN(BSL_LS_SOC_PHY,
   6458                          (BSL_META_U(unit,
   6459                                      "port %d: BCM84xxx type PHY device detected, please use "
   6460                                      "phy_84<xxx> config variable to select the specific type\n"),
   6461                           pc->port));
   6462                     continue;
   6463                }
   6464         }
   6465 
   6466         /* switch to quad-mode */
   6467         SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode(unit, pc->port, pc));
   6468 
   6469         /* Found the address that responds and the device now is in 4x10G */
   6470         rv = SOC_E_NONE;
   6471         break;
   6472     }
   6473 
   6474     pc->phy_id = saved_phy_id;
   6475 
   6476     return rv;
   6477 }
   6478 
   6479 
   6480 /*
   6481  * Function:
   6482  *      phy_84740_probe
   6483  * Purpose:
   6484  *      Complement the generic phy probe routine to identify this phy when its
   6485  *      phy id0 and id1 is same as some other phy's.
   6486  * Parameters:
   6487  *      unit - StrataSwitch unit #.
   6488  *      pc   - phy ctrl descriptor.
   6489  * Returns:
   6490  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   6491  */
   6492 STATIC int phy_84740_probe(int unit, phy_ctrl_t *pc)
   6493 {
   6494     uint32 devid;
   6495 
   6496     SOC_IF_ERROR_RETURN(_phy_84740_config_devid
   6497                         (pc->unit, pc->port, pc, &devid));
   6498 
   6499     if (devid == PHY84740_ID_84740) {
   6500         pc->dev_name = dev_name_84740;
   6501     } else if (devid == PHY84740_ID_84752) {
   6502         pc->dev_name = dev_name_84752;
   6503     } else if (devid == PHY84740_ID_84753) {
   6504         pc->dev_name = dev_name_84753;
   6505     } else if (devid == PHY84740_ID_84754) {
   6506         pc->dev_name = dev_name_84754;
   6507     } else if (devid == PHY84740_ID_84064) {
   6508         pc->dev_name = dev_name_84064;
   6509     } else if (PHY84740_IS_QUADRA(devid)) {
   6510         /*pc->dev_name = already set;*/
   6511     } else {  /* not found */
   6512         LOG_WARN(BSL_LS_SOC_PHY,
   6513                  (BSL_META_U(unit,
   6514                              "port %d: BCM84xxx type PHY device detected, please use "
   6515                              "phy_84<xxx> config variable to select the specific type\n"),
   6516                   pc->port));
   6517         return SOC_E_NOT_FOUND;
   6518     }
   6519     pc->size = sizeof(PHY84740_DEV_DESC_t);
   6520     return SOC_E_NONE;
   6521 }
   6522 
   6523 STATIC int
   6524 _phy_84740_bsc_rw(int unit, soc_port_t port, int dev_addr, int opr,
   6525                   int addr, int count, void *data_array, uint32 ram_start)
   6526 {
   6527     phy_ctrl_t *pc;
   6528     soc_timeout_t to;
   6529     uint16 data16;
   6530     int i;
   6531 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   6532     sal_usecs_t start;
   6533     sal_usecs_t end;
   6534 #endif                          /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */
   6535     int access_type;
   6536     int data_type;
   6537 
   6538     LOG_INFO(BSL_LS_SOC_PHY,
   6539              (BSL_META_U(unit,
   6540                          "phy_84740_bsc_read: u=%d p=%d addr=%04x\n"),
   6541                          unit, port, addr));
   6542 
   6543     if (!data_array) {
   6544         return SOC_E_PARAM;
   6545     }
   6546 
   6547     if (count > PHY84740_BSC_XFER_MAX) {
   6548         return SOC_E_PARAM;
   6549     }
   6550 
   6551     pc = EXT_PHY_SW_STATE(unit, port);
   6552     data_type = PHY84740_I2C_DATA_TYPE(opr);
   6553     access_type = PHY84740_I2C_ACCESS_TYPE(opr);
   6554 
   6555     if (access_type == PHY84740_I2CDEV_WRITE) {
   6556         for (i = 0; i < count; i++) {
   6557             if (data_type == PHY84740_I2C_8BIT) {
   6558                 SOC_IF_ERROR_RETURN
   6559                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, ram_start + i,
   6560                                                     ((uint8 *) data_array)[i]));
   6561             } else {            /* 16 bit */
   6562                 SOC_IF_ERROR_RETURN
   6563                     (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, ram_start + i,
   6564                                                     ((uint16 *)
   6565                                                      data_array)[i]));
   6566             }
   6567         }
   6568     }
   6569 
   6570     data16 = ram_start;
   6571     SOC_IF_ERROR_RETURN
   6572         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8004, data16));
   6573     SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8003, addr));
   6574     SOC_IF_ERROR_RETURN
   6575         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8002, count));
   6576 
   6577     data16 = 1;
   6578     data16 |= (dev_addr << 9);
   6579     if (access_type == PHY84740_I2CDEV_WRITE) {
   6580         data16 |= PHY84740_WR_FREQ_400KHZ;
   6581     }
   6582 
   6583     SOC_IF_ERROR_RETURN
   6584         (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8005, data16));
   6585 
   6586     if (access_type == PHY84740_I2CDEV_WRITE) {
   6587         data16 = 0x8000 | PHY84740_BSC_WRITE_OP;
   6588     } else {
   6589         data16 = 0x8000 | PHY84740_BSC_READ_OP;
   6590     }
   6591 
   6592     if (data_type == PHY84740_I2C_16BIT) {
   6593         data16 |= (1 << 12);
   6594     }
   6595 
   6596     /* for single port mode, there should be only one I2C interface active
   6597      * from lane0. The 0x800x register block is bcst type registers. If writing
   6598      * to 0x8000 directly, it will enable all four I2C masters. Use indirect access
   6599      * to enable only the lane 0.
   6600      */
   6601 
   6602     if (PHY84740_SINGLE_PORT_MODE(pc)) {
   6603 
   6604         /* point to lane 0 */
   6605         SOC_IF_ERROR_RETURN
   6606             (WRITE_PHY84740_MMF_PMA_PMD_REG
   6607              (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0));
   6608 
   6609         /* indirect access: 0x8000=data16 */
   6610         SOC_IF_ERROR_RETURN
   6611             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0c, 0x8000));
   6612         SOC_IF_ERROR_RETURN
   6613             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0d, data16));
   6614 
   6615         /* issue the indirect access command */
   6616         SOC_IF_ERROR_RETURN
   6617             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd13, 0x3));
   6618 
   6619         soc_timeout_init(&to, 1000000, 0);
   6620         while (!soc_timeout_check(&to)) {
   6621             SOC_IF_ERROR_RETURN
   6622                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd13, &data16));
   6623             if (!data16) {
   6624                 break;
   6625             }
   6626         }
   6627         if (data16) {
   6628             LOG_WARN(BSL_LS_SOC_PHY,
   6629                      (BSL_META_U(unit,
   6630                                  "port %d: Fail register 0xcd13 status 0x%x\n"),
   6631                                  port,data16));
   6632             return SOC_E_TIMEOUT; 
   6633         }
   6634     } else {
   6635         SOC_IF_ERROR_RETURN
   6636             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8000, data16));
   6637     }
   6638 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   6639     start = sal_time_usecs();
   6640 #endif                          /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */
   6641     soc_timeout_init(&to, 1000000, 0);
   6642     while (!soc_timeout_check(&to)) {
   6643         SOC_IF_ERROR_RETURN
   6644             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8000, &data16));
   6645         if (((data16 & PHY84740_2W_STAT) == PHY84740_2W_STAT_COMPLETE)) {
   6646             break;
   6647         }
   6648     }
   6649 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   6650     end = sal_time_usecs();
   6651 #endif                          /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */
   6652     /* need some delays */
   6653     sal_usleep(10000);
   6654 
   6655 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   6656     LOG_INFO(BSL_LS_SOC_PHY,
   6657              (BSL_META_U(unit,
   6658                          "BSC command status %d time=%d\n"),
   6659                          (data16 & PHY84740_2W_STAT), SAL_USECS_SUB(end, start)));
   6660 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */
   6661 
   6662     if (access_type == PHY84740_I2CDEV_WRITE) {
   6663         return SOC_E_NONE;
   6664     }
   6665 
   6666     if ((data16 & PHY84740_2W_STAT) == PHY84740_2W_STAT_COMPLETE) {
   6667         for (i = 0; i < count; i++) {
   6668             SOC_IF_ERROR_RETURN
   6669                 (READ_PHY84740_MMF_PMA_PMD_REG
   6670                  (unit, pc, (ram_start + i), &data16));
   6671             if (data_type == PHY84740_I2C_16BIT) {
   6672                 ((uint16 *)data_array)[i] = data16;
   6673                 LOG_INFO(BSL_LS_SOC_PHY,
   6674                          (BSL_META_U(unit,
   6675                                      "%04x "), data16));
   6676             } else {
   6677                 ((uint8 *)data_array)[i] = (uint8)data16;
   6678                 LOG_INFO(BSL_LS_SOC_PHY,
   6679                          (BSL_META_U(unit,
   6680                                      "%02x "), data16));
   6681             }
   6682         }
   6683     }
   6684     return SOC_E_NONE;
   6685 }
   6686 
   6687 /*
   6688  * Read a slave device such as NVRAM/EEPROM connected to the 84740's I2C
   6689  * interface. This function will be mainly used for diagnostic or workaround
   6690  * purpose.
   6691  * Note:
   6692  * The size of read_array buffer must be greater than or equal to the
   6693  * parameter nbytes.
   6694  * usage example:
   6695  *   Retrieve the first 100 byte data of the non-volatile storage device with
   6696  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
   6697  *   port 2.
   6698  *   uint8 data8[100];
   6699  *   phy_84740_i2cdev_read(0,2,0x50,0,100,data8);
   6700  */
   6701 int phy_84740_i2cdev_read(int unit, soc_port_t port, int dev_addr,      /* 7 bit I2C bus device address */
   6702                           int offset,   /* starting data address to read */
   6703                           int nbytes,   /* number of bytes to read */
   6704                           uint8 *read_array)
   6705 {                               /* buffer to hold retrieved data */
   6706     return _phy_84740_bsc_rw(unit, port, dev_addr, PHY84740_I2CDEV_READ,
   6707                              offset, nbytes, (void *)read_array,
   6708                              PHY84740_READ_START_ADDR);
   6709 
   6710 }
   6711 
   6712 /*
   6713  * Write to a slave device such as NVRAM/EEPROM connected to the 84740's I2C
   6714  * interface. This function will be mainly used for diagnostic or workaround
   6715  * purpose.
   6716  * Note:
   6717  * The size of write_array buffer should be equal to the parameter nbytes.
   6718  * The EEPROM may limit the maximun write size to 16 bytes
   6719  * usage example:
   6720  *   Write to first 100 byte space of the non-volatile storage device with
   6721  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
   6722  *   port 2, with written data specified in array data8.
   6723  *   uint8 data8[100];
   6724  *   *** initialize the data8 array with written data ***
   6725  *
   6726  *   phy_84740_i2cdev_write(0,2,0x50,0,100,data8);
   6727  */
   6728 
   6729 int phy_84740_i2cdev_write(int unit, soc_port_t port, int dev_addr,     /* I2C bus device address */
   6730                            int offset,  /* starting data address to write to */
   6731                            int nbytes,  /* number of bytes to write */
   6732                            uint8 *write_array)
   6733 {                               /* buffer to hold written data */
   6734     int j;
   6735     int rv = SOC_E_NONE;
   6736 
   6737     for (j = 0; j < (nbytes / PHY84740_BSC_WR_MAX); j++) {
   6738         rv = _phy_84740_bsc_rw(unit, port, dev_addr, PHY84740_I2CDEV_WRITE,
   6739                                offset + j * PHY84740_BSC_WR_MAX,
   6740                                PHY84740_BSC_WR_MAX,
   6741                                (void *)(write_array + j * PHY84740_BSC_WR_MAX),
   6742                                PHY84740_WRITE_START_ADDR);
   6743         if (rv != SOC_E_NONE) {
   6744             return rv;
   6745         }
   6746         sal_usleep(20000);
   6747     }
   6748     if (nbytes % PHY84740_BSC_WR_MAX) {
   6749         rv = _phy_84740_bsc_rw(unit, port, dev_addr, PHY84740_I2CDEV_WRITE,
   6750                                offset + j * PHY84740_BSC_WR_MAX,
   6751                                nbytes % PHY84740_BSC_WR_MAX,
   6752                                (void *)(write_array + j * PHY84740_BSC_WR_MAX),
   6753                                PHY84740_WRITE_START_ADDR);
   6754     }
   6755     return rv;
   6756 }
   6757 
   6758 /*
   6759  *   Callout interface to phy_84740_i2cdev_read(); 
   6760  *   TBD: Extend to handle max_size > PHY84740_BSC_XFER_MAX. 
   6761  */
   6762 
   6763 STATIC int
   6764 phy_84740_multi_get(int unit, soc_port_t port, uint32 flags,
   6765                     uint32 dev_addr, uint32 offset, int max_size, uint8 *data,
   6766                     int *actual_size)
   6767 {
   6768     int rv;
   6769 
   6770     rv = phy_84740_i2cdev_read(unit, port, (int)dev_addr, (int)offset, max_size,
   6771                                data);
   6772 
   6773     if (SOC_FAILURE(rv)) {
   6774         *actual_size = 0;
   6775         return SOC_E_FAIL;
   6776     }
   6777 
   6778     *actual_size = max_size;
   6779     return SOC_E_NONE;
   6780 }
   6781 
   6782 /*
   6783  * Function:
   6784  *      phy_84740_reg_read
   6785  * Purpose:
   6786  *      Routine to read PHY register
   6787  * Parameters:
   6788  *      uint         - BCM unit number
   6789  *      port         - port number
   6790  *      flags        - Flags which specify the register type
   6791  *      phy_reg_addr - Encoded register address
   6792  *      phy_data     - (OUT) Value read from PHY register
   6793  * Note:
   6794  *      This register read function is not thread safe. Higher level
   6795  * function that calls this function must obtain a per port lock
   6796  * to avoid overriding register page mapping between threads.
   6797  */
   6798 STATIC int
   6799 phy_84740_reg_read(int unit, soc_port_t port, uint32 flags,
   6800                    uint32 phy_reg_addr, uint32 *phy_data)
   6801 {
   6802     uint16 data16;
   6803     uint16 regdata;
   6804     phy_ctrl_t *pc;             /* PHY software state */
   6805     int rv = SOC_E_NONE;
   6806     int rd_cnt;
   6807 
   6808     pc = EXT_PHY_SW_STATE(unit, port);
   6809 
   6810     rd_cnt = 1;
   6811 
   6812     if (flags & SOC_PHY_I2C_DATA8) {
   6813 
   6814         SOC_IF_ERROR_RETURN
   6815             (phy_84740_i2cdev_read(unit, port,
   6816                                    SOC_PHY_I2C_DEVAD(phy_reg_addr),
   6817                                    SOC_PHY_I2C_REGAD(phy_reg_addr),
   6818                                    rd_cnt, (uint8 *) &data16));
   6819         *phy_data = *((uint8 *) &data16);
   6820 
   6821     } else if (flags & SOC_PHY_I2C_DATA16) {
   6822         /* This operation is generally targeted to access 16-bit device,
   6823          * such as PHY IC inside the SFP.  However there is no 16-bit
   6824          * scratch register space on the device.  Use 1.800e
   6825          * for this operation.
   6826          */
   6827         SOC_IF_ERROR_RETURN
   6828             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM,
   6829                                            &regdata));
   6830 
   6831         rv = _phy_84740_bsc_rw(unit, port,
   6832                                SOC_PHY_I2C_DEVAD(phy_reg_addr),
   6833                                PHY84740_I2C_OP_TYPE(PHY84740_I2CDEV_READ,
   6834                                                     PHY84740_I2C_16BIT),
   6835                                SOC_PHY_I2C_REGAD(phy_reg_addr), 1,
   6836                                (void *)&data16, PHY84740_I2C_TEMP_RAM);
   6837 
   6838         *phy_data = data16;
   6839 
   6840         /* restore the ram register value */
   6841         SOC_IF_ERROR_RETURN
   6842             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM,
   6843                                             regdata));
   6844     } else {
   6845         SOC_IF_ERROR_RETURN(READ_PHY_REG(unit, pc, phy_reg_addr, &data16));
   6846         *phy_data = data16;
   6847     }
   6848 
   6849     return rv;
   6850 }
   6851 
   6852 /*
   6853  * Function:
   6854  *      phy_84740_reg_write
   6855  * Purpose:
   6856  *      Routine to write PHY register
   6857  * Parameters:
   6858  *      uint         - BCM unit number
   6859  *      port         - port number
   6860  *      flags        - Flags which specify the register type
   6861  *      phy_reg_addr - Encoded register address
   6862  *      phy_data     - Value write to PHY register
   6863  * Note:
   6864  *      This register read function is not thread safe. Higher level
   6865  * function that calls this function must obtain a per port lock
   6866  * to avoid overriding register page mapping between threads.
   6867  */
   6868 STATIC int
   6869 phy_84740_reg_write(int unit, soc_port_t port, uint32 flags,
   6870                     uint32 phy_reg_addr, uint32 phy_data)
   6871 {
   6872     uint8 data8[4];
   6873     uint16 data16[2];
   6874     uint16 regdata[2];
   6875     phy_ctrl_t *pc;             /* PHY software state */
   6876     int rv = SOC_E_NONE;
   6877     int wr_cnt;
   6878 
   6879     pc = EXT_PHY_SW_STATE(unit, port);
   6880 #if defined (BCM_WARM_BOOT_SUPPORT)  /*  */
   6881     if ( SOC_WARM_BOOT(pc->unit) || SOC_IS_RELOADING(pc->unit) ) {
   6882         return SOC_E_NONE;
   6883     }
   6884 #endif /* BCM_WARM_BOOT_SUPPORT */
   6885 
   6886     wr_cnt = 1;
   6887 
   6888     if (flags & SOC_PHY_I2C_DATA8) {
   6889         data8[0] = (uint8) phy_data;
   6890         SOC_IF_ERROR_RETURN
   6891             (phy_84740_i2cdev_write(unit, port,
   6892                                     SOC_PHY_I2C_DEVAD(phy_reg_addr),
   6893                                     SOC_PHY_I2C_REGAD(phy_reg_addr),
   6894                                     wr_cnt, data8));
   6895     } else if (flags & SOC_PHY_I2C_DATA16) {
   6896         /* This operation is generally targeted to access 16-bit device,
   6897          * such as PHY IC inside the SFP.  However there is no 16-bit
   6898          * scratch register space on the device.  Use 1.800e
   6899          * for this operation.
   6900          */
   6901         /* save the temp ram register */
   6902         SOC_IF_ERROR_RETURN
   6903             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM,
   6904                                            &regdata[0]));
   6905         data16[0] = phy_data;
   6906         rv = _phy_84740_bsc_rw(unit, port,
   6907                                SOC_PHY_I2C_DEVAD(phy_reg_addr),
   6908                                PHY84740_I2C_OP_TYPE(PHY84740_I2CDEV_WRITE,
   6909                                                     PHY84740_I2C_16BIT),
   6910                                SOC_PHY_I2C_REGAD(phy_reg_addr), wr_cnt,
   6911                                (void *)data16, PHY84740_I2C_TEMP_RAM);
   6912 
   6913         /* restore the ram register value */
   6914         SOC_IF_ERROR_RETURN
   6915             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM,
   6916                                             regdata[0]));
   6917     } else {
   6918         SOC_IF_ERROR_RETURN
   6919             (WRITE_PHY_REG(unit, pc, phy_reg_addr, (uint16) phy_data));
   6920     }
   6921 
   6922     return rv;
   6923 }
   6924 
   6925 int
   6926 phy_84740_timesync_config_set(int unit, soc_port_t port,
   6927                               soc_port_phy_timesync_config_t *conf)
   6928 {
   6929     uint16 rx_control_reg = 0, tx_control_reg = 0, rx_tx_control_reg = 0,
   6930         capture_en_reg = 0, rx_ts_cap = 0, tx_ts_cap = 0,
   6931         nse_sc_8 = 0, nse_nco_3 = 0, value, mpls_control_reg = 0, temp = 0,
   6932         gmode = 0, framesync_mode = 0, syncout_mode = 0, mask = 0,
   6933         pulse_1_length, pulse_2_length;
   6934     uint32 interval;
   6935     int i;
   6936     phy_ctrl_t *pc;
   6937 
   6938     pc = EXT_PHY_SW_STATE(unit, port);
   6939 
   6940     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   6941 
   6942         if (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) {
   6943             SOC_IF_ERROR_RETURN
   6944                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc600, 0x0003));
   6945             nse_sc_8 |= (1U << 12);
   6946         }
   6947 
   6948         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) {
   6949             capture_en_reg |= 3U;
   6950         }
   6951 
   6952         /* TXRX SOP TS CAPTURE ENABLE reg */
   6953         SOC_IF_ERROR_RETURN
   6954             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   6955              (unit, pc, 0xc607, capture_en_reg, 3U));
   6956 
   6957         if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) {
   6958             nse_sc_8 |= (1U << 13);
   6959         }
   6960 
   6961         /* NSE SC 8 register */
   6962         SOC_IF_ERROR_RETURN
   6963             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, nse_sc_8,
   6964                                              (1U << 12) | (1U << 13)));
   6965 
   6966         if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) {
   6967             rx_tx_control_reg |= (1U << 3);
   6968         }
   6969 
   6970         /* RX TX CONTROL register */
   6971         SOC_IF_ERROR_RETURN
   6972             (MODIFY_PHY84740_MMF_PMA_PMD_REG
   6973              (unit, pc, 0xc61c, rx_tx_control_reg, (1U << 3)));
   6974 
   6975         if (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) {
   6976             rx_control_reg |= (1U << 3);
   6977             tx_control_reg |= (1U << 3);
   6978         }
   6979 
   6980         if (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) {
   6981             rx_control_reg |= (1U << 2);
   6982             tx_control_reg |= (1U << 2);
   6983         }
   6984 
   6985         if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) {
   6986             rx_control_reg |= (1U << 1);
   6987             tx_control_reg |= (1U << 1);
   6988         }
   6989 
   6990         if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) {
   6991             rx_control_reg |= (1U << 0);
   6992             tx_control_reg |= (1U << 0);
   6993         }
   6994 
   6995         /* TX CONTROL register */
   6996         SOC_IF_ERROR_RETURN
   6997             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc618, tx_control_reg));
   6998 
   6999         /* RX CONTROL register */
   7000         SOC_IF_ERROR_RETURN
   7001             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61a, rx_control_reg));
   7002 
   7003         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) {
   7004             nse_nco_3 &= ~(1U << 14);
   7005         } else {
   7006             nse_nco_3 |= (1U << 14);
   7007         }
   7008 
   7009         /* NSE NCO 3 register */
   7010         SOC_IF_ERROR_RETURN
   7011             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc630, nse_nco_3,
   7012                                              (1U << 14)));
   7013 
   7014         if (conf->flags & SOC_PORT_PHY_TIMESYNC_64BIT_TIMESTAMP_ENABLE) {
   7015             SOC_IF_ERROR_RETURN
   7016                 (WRITE_PHY84740_MMF_PMA_PMD_REG
   7017                  (unit, pc, 0xc609, (uint16) 0x2));
   7018             SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   7019                                 (unit, pc, 0xc608, (uint16) 0x2));
   7020         }
   7021         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_SYNC) {
   7022             tx_ts_cap |= (0x1U << 0);
   7023         }
   7024         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_DELAY_REQ) {
   7025             tx_ts_cap |= (0x1U << 1);
   7026         }
   7027         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_REQ) {
   7028             tx_ts_cap |= (0x1U << 2);
   7029         }
   7030         if (conf->
   7031             flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_RESP) {
   7032             tx_ts_cap |= (0x1U << 3);
   7033         }
   7034         SOC_IF_ERROR_RETURN
   7035             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc602, tx_ts_cap));
   7036 
   7037         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_SYNC) {
   7038             rx_ts_cap |= (0x1U << 0);
   7039         }
   7040         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_DELAY_REQ) {
   7041             rx_ts_cap |= (0x1U << 1);
   7042         }
   7043         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_REQ) {
   7044             rx_ts_cap |= (0x1U << 2);
   7045         }
   7046         if (conf->
   7047             flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_RESP) {
   7048             rx_ts_cap |= (0x1U << 3);
   7049         }
   7050         SOC_IF_ERROR_RETURN
   7051             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc604, rx_ts_cap));
   7052     }
   7053 
   7054     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   7055         /* VLAN TAG register */
   7056         SOC_IF_ERROR_RETURN
   7057             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61d, conf->itpid));
   7058     }
   7059 
   7060     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   7061         /* OUTER VLAN TAG register */
   7062         SOC_IF_ERROR_RETURN
   7063             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61e, conf->otpid));
   7064     }
   7065 
   7066     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   7067         /* INNER VLAN TAG register */
   7068         SOC_IF_ERROR_RETURN
   7069             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61f, conf->otpid2));
   7070     }
   7071 
   7072     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   7073         SOC_IF_ERROR_RETURN
   7074             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7075              (unit, pc, 0xc636, conf->ts_divider & 0xfff));
   7076     }
   7077 
   7078     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   7079         SOC_IF_ERROR_RETURN
   7080             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7081              (unit, pc, 0xc605, conf->rx_link_delay & 0xffff));
   7082         SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   7083                             (unit, pc, 0xc606,
   7084                              (conf->rx_link_delay >> 16) & 0xffff));
   7085     }
   7086 
   7087     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   7088 
   7089         /* TIME CODE 5 register */
   7090         SOC_IF_ERROR_RETURN
   7091             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7092              (unit, pc, 0xc610,
   7093               (uint16) (conf->original_timecode.nanoseconds & 0xffff)));
   7094 
   7095         /* TIME CODE 4 register */
   7096         SOC_IF_ERROR_RETURN
   7097             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7098              (unit, pc, 0xc60f,
   7099               (uint16) ((conf->original_timecode.nanoseconds >> 16) & 0xffff)));
   7100 
   7101         /* TIME CODE 3 register */
   7102         SOC_IF_ERROR_RETURN
   7103             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7104              (unit, pc, 0xc60e,
   7105               (uint16) (COMPILER_64_LO(conf->original_timecode.seconds) &
   7106                         0xffff)));
   7107 
   7108         /* TIME CODE 2 register */
   7109         SOC_IF_ERROR_RETURN
   7110             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7111              (unit, pc, 0xc60d,
   7112               (uint16) ((COMPILER_64_LO(conf->original_timecode.seconds) >> 16)
   7113                         & 0xffff)));
   7114 
   7115         /* TIME CODE 1 register */
   7116         SOC_IF_ERROR_RETURN
   7117             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7118              (unit, pc, 0xc60c,
   7119               (uint16) (COMPILER_64_HI(conf->original_timecode.seconds) &
   7120                         0xffff)));
   7121     }
   7122 
   7123     mask = 0;
   7124 
   7125     /* NSE SC 8 register */
   7126 
   7127     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   7128         _phy_84740_encode_gmode(conf->gmode, &gmode);
   7129         mask |= (0x3 << 14);
   7130     }
   7131 
   7132     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   7133         _phy_84740_encode_framesync_mode(conf->framesync.mode, &framesync_mode);
   7134         mask |= (0xf << 2) | (0x1 << 11) | (0x1 << 6);
   7135         SOC_IF_ERROR_RETURN
   7136             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7137              (unit, pc, 0xc63c, conf->framesync.length_threshold));
   7138         SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   7139                             (unit, pc, 0xc63b, conf->framesync.event_offset));
   7140     }
   7141 
   7142     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   7143         _phy_84740_encode_syncout_mode(conf->syncout.mode, &syncout_mode);
   7144         mask |= (0x3 << 0);
   7145 
   7146         /* Divide by 6.4 without floating point */
   7147         interval = (conf->syncout.interval * 10) / 64;
   7148         pulse_1_length = (conf->syncout.pulse_1_length * 10) / 64;
   7149         pulse_2_length = (conf->syncout.pulse_2_length * 10) / 64;
   7150 
   7151         SOC_IF_ERROR_RETURN
   7152             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7153              (unit, pc, 0xc635, interval & 0xffff));
   7154         SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   7155                             (unit, pc, 0xc634,
   7156                              ((pulse_2_length & 0x3) << 14) | ((interval >> 16)
   7157                                                                & 0x3fff)));
   7158         SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   7159                             (unit, pc, 0xc633,
   7160                              ((pulse_1_length & 0x1ff) << 7) |
   7161                              ((pulse_2_length >> 2) & 0x7f)));
   7162 
   7163         SOC_IF_ERROR_RETURN
   7164             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc639,
   7165                                             (uint16) (COMPILER_64_LO
   7166                                                       (conf->syncout.
   7167                                                        syncout_ts) & 0xfff0)));
   7168         SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   7169                             (unit, pc, 0xc638,
   7170                              (uint16) ((COMPILER_64_LO(conf->syncout.syncout_ts)
   7171                                         >> 16) & 0xffff)));
   7172         SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   7173                             (unit, pc, 0xc637,
   7174                              (uint16) (COMPILER_64_HI(conf->syncout.syncout_ts)
   7175                                        & 0xffff)));
   7176     }
   7177 
   7178     SOC_IF_ERROR_RETURN
   7179         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7180                                          0xc63a,
   7181                                          (gmode << 14) |
   7182                                          ((framesync_mode & 0x2) ? (1U << 11) : (1U << 6)) |   /* if bits 1 or 2 are set, turn off syncout */
   7183                                          (framesync_mode << 2) |
   7184                                          (syncout_mode << 0),
   7185                                          mask));
   7186 
   7187     mask = 0;
   7188 
   7189     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   7190         /* RX TS OFFSET register */
   7191         SOC_IF_ERROR_RETURN
   7192             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7193              (unit, pc, 0xc60b, (uint16) (conf->rx_timestamp_offset & 0xffff)));
   7194         mask |= 0xf000;
   7195     }
   7196 
   7197     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   7198         mask |= 0x0fff;
   7199     }
   7200 
   7201     /* TXRX TS OFFSET register */
   7202     SOC_IF_ERROR_RETURN
   7203         (MODIFY_PHY84740_MMF_PMA_PMD_REG
   7204          (unit, pc, 0xc60a,
   7205           (uint16) (((conf->rx_timestamp_offset & 0xf0000) >> 4) | (conf->
   7206                                                                     tx_timestamp_offset
   7207                                                                     & 0xfff)),
   7208           mask));
   7209     value = 0;
   7210     mask = 0;
   7211     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   7212         _phy_84740_encode_egress_message_mode(conf->tx_sync_mode, 0, &value);
   7213         mask |= 0x3 << 0;
   7214     }
   7215 
   7216     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   7217         _phy_84740_encode_egress_message_mode(conf->tx_delay_request_mode, 2,
   7218                                               &value);
   7219         mask |= 0x3 << 2;
   7220     }
   7221 
   7222     if (conf->
   7223         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   7224         _phy_84740_encode_egress_message_mode(conf->tx_pdelay_request_mode, 4,
   7225                                               &value);
   7226         mask |= 0x3 << 4;
   7227     }
   7228 
   7229     if (conf->
   7230         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   7231         _phy_84740_encode_egress_message_mode(conf->tx_pdelay_response_mode, 6,
   7232                                               &value);
   7233         mask |= 0x3 << 6;
   7234     }
   7235 
   7236     /* TX EVENT MESSAGE MODE SEL register */
   7237     SOC_IF_ERROR_RETURN
   7238         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc601, value, mask));
   7239 
   7240     value = 0;
   7241     mask = 0;
   7242 
   7243     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   7244         _phy_84740_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value);
   7245         mask |= 0x3 << 0;
   7246     }
   7247 
   7248     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   7249         _phy_84740_encode_ingress_message_mode(conf->rx_delay_request_mode, 2,
   7250                                                &value);
   7251         mask |= 0x3 << 2;
   7252     }
   7253 
   7254     if (conf->
   7255         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   7256         _phy_84740_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 4,
   7257                                                &value);
   7258         mask |= 0x3 << 4;
   7259     }
   7260 
   7261     if (conf->
   7262         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   7263         _phy_84740_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 6,
   7264                                                &value);
   7265         mask |= 0x3 << 6;
   7266     }
   7267 
   7268     /* RX EVENT MESSAGE MODE SEL register */
   7269     SOC_IF_ERROR_RETURN
   7270         (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc603, value, mask));
   7271 
   7272     if (conf->
   7273         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   7274 
   7275         /* Initial ref phase [15:0] */
   7276         SOC_IF_ERROR_RETURN
   7277             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7278              (unit, pc, 0xc623,
   7279               (uint16) (COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) &
   7280                         0xffff)));
   7281 
   7282         /* Initial ref phase [31:16]  */
   7283         SOC_IF_ERROR_RETURN
   7284             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7285              (unit, pc, 0xc622,
   7286               (uint16) ((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) &
   7287                         0xffff)));
   7288 
   7289         /*  Initial ref phase [47:32] */
   7290         SOC_IF_ERROR_RETURN
   7291             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7292              (unit, pc, 0xc621,
   7293               (uint16) (COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) &
   7294                         0xffff)));
   7295     }
   7296 
   7297     if (conf->
   7298         validity_mask &
   7299         SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   7300         SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   7301                             (unit, pc, 0xc625,
   7302                              conf->phy_1588_dpll_ref_phase_delta & 0xffff));
   7303         SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG
   7304                             (unit, pc, 0xc624,
   7305                              (conf->
   7306                               phy_1588_dpll_ref_phase_delta >> 16) & 0xffff));
   7307     }
   7308 
   7309     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   7310         /* DPLL K1 */
   7311         SOC_IF_ERROR_RETURN
   7312             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7313              (unit, pc, 0xc626, conf->phy_1588_dpll_k1 & 0xff));
   7314     }
   7315 
   7316     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   7317         /* DPLL K2 */
   7318         SOC_IF_ERROR_RETURN
   7319             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7320              (unit, pc, 0xc627, conf->phy_1588_dpll_k2 & 0xff));
   7321     }
   7322 
   7323     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   7324         /* DPLL K3 */
   7325         SOC_IF_ERROR_RETURN
   7326             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7327              (unit, pc, 0xc628, conf->phy_1588_dpll_k3 & 0xff));
   7328     }
   7329 
   7330     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) {
   7331 
   7332         /* MPLS controls */
   7333         if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE) {
   7334             mpls_control_reg |= (1U << 7) | (1U << 3);
   7335         }
   7336 
   7337         if (conf->mpls_control.
   7338             flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE) {
   7339             mpls_control_reg |= (1U << 6) | (1U << 2);
   7340         }
   7341 
   7342         if (conf->mpls_control.
   7343             flags & SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE) {
   7344             mpls_control_reg |= (1U << 4);
   7345         }
   7346 
   7347         if (conf->mpls_control.
   7348             flags & SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE) {
   7349             mpls_control_reg |= (1U << 5) | (1U << 1);
   7350         }
   7351         SOC_IF_ERROR_RETURN
   7352             (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc651, mpls_control_reg,
   7353                                              (1U << 7) | (1U << 3) | (1U << 6) |
   7354                                              (1U << 2) | (1U << 4) | (1U << 5) |
   7355                                              (1U << 1)));
   7356 
   7357         /* special label [19:16] */
   7358         SOC_IF_ERROR_RETURN
   7359             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7360              (unit, pc, 0xc653,
   7361               (uint16) ((conf->mpls_control.special_label >> 16) & 0xf)));
   7362 
   7363         /* special label [15:0] */
   7364         SOC_IF_ERROR_RETURN
   7365             (WRITE_PHY84740_MMF_PMA_PMD_REG
   7366              (unit, pc, 0xc652,
   7367               (uint16) (conf->mpls_control.special_label & 0xffff)));
   7368 
   7369         for (i = 0; i < 10; i++) {
   7370             SOC_IF_ERROR_RETURN
   7371                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7372                                                 0xc654 + i,
   7373                                                 (uint16) (conf->mpls_control.labels[i].value & 0xffff)));
   7374             SOC_IF_ERROR_RETURN
   7375                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7376                                                 0xc661 + i,
   7377                                                 (uint16) (conf->mpls_control.labels[i].mask & 0xffff)));
   7378         }
   7379 
   7380         SOC_IF_ERROR_RETURN
   7381             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7382                                             0xc65e, 
   7383                                             (uint16) (((conf->mpls_control.labels[3].value >> 4) & 0xf000) |
   7384                                                       ((conf->mpls_control.labels[2].value >> 8) & 0x0f00) |
   7385                                                       ((conf->mpls_control.labels[1].value >> 12) & 0x00f0) |
   7386                                                       ((conf->mpls_control.labels[0].value >> 16) & 0x000f))));
   7387 
   7388         SOC_IF_ERROR_RETURN
   7389             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7390                                             0xc65f,
   7391                                             (uint16) (((conf->mpls_control.labels[7].value >> 4) & 0xf000) |
   7392                                                       ((conf->mpls_control.labels[6].value >> 8) & 0x0f00) |
   7393                                                       ((conf->mpls_control.labels[5].value >> 12) & 0x00f0) |
   7394                                                       ((conf->mpls_control.labels[4].value >> 16) & 0x000f))));
   7395 
   7396         SOC_IF_ERROR_RETURN
   7397             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7398                                             0xc660,
   7399                                             (uint16) (((conf->mpls_control.labels[9].value >> 12) & 0x00f0) |
   7400                                                       ((conf->mpls_control.labels[8].value >> 16) & 0x000f))));
   7401         SOC_IF_ERROR_RETURN
   7402             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7403                                             0xc66b,
   7404                                             (uint16) (((conf->mpls_control.labels[3].mask >> 4) & 0xf000) |
   7405                                                       ((conf->mpls_control.labels[2].mask >> 8) & 0x0f00) |
   7406                                                       ((conf->mpls_control.labels[1].mask >> 12) & 0x00f0) |
   7407                                                       ((conf->mpls_control.labels[0].mask >> 16) & 0x000f))));
   7408 
   7409         SOC_IF_ERROR_RETURN
   7410             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7411                                             0xc66c,
   7412                                             (uint16) (((conf->mpls_control.labels[7].mask >> 4) & 0xf000) |
   7413                                                       ((conf->mpls_control.labels[6].mask >> 8) & 0x0f00) |
   7414                                                       ((conf->mpls_control.labels[5].mask >> 12) & 0x00f0) |
   7415                                                       ((conf->mpls_control.labels[4].mask >> 16) & 0x000f))));
   7416 
   7417         SOC_IF_ERROR_RETURN
   7418             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7419                                             0xc66d,
   7420                                             (uint16) (((conf->mpls_control.labels[9].mask >> 12) & 0x00f0) |
   7421                                                       ((conf->mpls_control.labels[8].mask >> 16) & 0x000f))));
   7422 
   7423         /* label flags */
   7424         temp = 0;
   7425         for (i = 0; i < 8; i++) {
   7426             temp |=
   7427                 conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT ? (0x2 << (i << 1)) : 0;
   7428             temp |=
   7429                 (conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN) ? (0x1 << (i << 1)) : 0;
   7430         }
   7431 
   7432         SOC_IF_ERROR_RETURN
   7433             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66e, temp));
   7434 
   7435         temp = 0;
   7436         for (i = 0; i < 2; i++) {
   7437             temp |=
   7438                 (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT) ? (0x2 << (i << 1)) : 0;
   7439             temp |=
   7440                 (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN) ? (0x1 << (i << 1)) : 0;
   7441         }
   7442 
   7443         SOC_IF_ERROR_RETURN
   7444             (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66f, temp));
   7445     }
   7446     return SOC_E_NONE;
   7447 }
   7448 
   7449 int
   7450 phy_84740_timesync_config_get(int unit, soc_port_t port,
   7451                               soc_port_phy_timesync_config_t *conf)
   7452 {
   7453     uint16 rx_tx_control_reg = 0, tx_control_reg = 0,
   7454         en_control_reg = 0, capture_en_reg = 0, rx_ts_cap = 0, tx_ts_cap = 0,
   7455         nse_sc_8 = 0, nse_nco_3 =
   7456         0, temp1, temp2, temp3, value, mpls_control_reg;
   7457     soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   7458     soc_port_phy_timesync_framesync_mode_t framesync_mode =
   7459         SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE;
   7460     soc_port_phy_timesync_syncout_mode_t syncout_mode =
   7461         SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   7462     int i;
   7463     phy_ctrl_t *pc;
   7464 
   7465     pc = EXT_PHY_SW_STATE(unit, port);
   7466 
   7467     conf->flags = 0;
   7468 
   7469     /* NSE SC 8 register */
   7470     SOC_IF_ERROR_RETURN
   7471         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, &nse_sc_8));
   7472 
   7473     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   7474         /* SLICE ENABLE CONTROL register */
   7475         SOC_IF_ERROR_RETURN
   7476             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc600, &en_control_reg));
   7477 
   7478         if (en_control_reg & 1U) {
   7479             conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE;
   7480         }
   7481 
   7482         /* TXRX SOP TS CAPTURE ENABLE reg */
   7483         SOC_IF_ERROR_RETURN
   7484             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc607, &capture_en_reg));
   7485 
   7486         if (capture_en_reg & 1U) {
   7487             conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE;
   7488         }
   7489 
   7490         /* NSE SC 8 register */
   7491         /* SOC_IF_ERROR_RETURN
   7492            (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, &nse_sc_8));
   7493          */
   7494 
   7495         if (nse_sc_8 & (1U << 13)) {
   7496             conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE;
   7497         }
   7498 
   7499         /* RX TX CONTROL register */
   7500         SOC_IF_ERROR_RETURN
   7501             (READ_PHY84740_MMF_PMA_PMD_REG
   7502              (unit, pc, 0xc61c, &rx_tx_control_reg));
   7503 
   7504         if (rx_tx_control_reg & (1U << 3)) {
   7505             conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE;
   7506         }
   7507 
   7508         /* TX CONTROL register */
   7509         SOC_IF_ERROR_RETURN
   7510             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc618, &tx_control_reg));
   7511 
   7512         if (tx_control_reg & (1U << 3)) {
   7513             conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE;
   7514         }
   7515 
   7516         if (tx_control_reg & (1U << 2)) {
   7517             conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE;
   7518         }
   7519 
   7520         if (tx_control_reg & (1U << 1)) {
   7521             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE;
   7522         }
   7523 
   7524         if (tx_control_reg & (1U << 0)) {
   7525             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE;
   7526         }
   7527 
   7528         SOC_IF_ERROR_RETURN
   7529             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc630, &nse_nco_3));
   7530 
   7531         if (!(nse_nco_3 & (1U << 14))) {
   7532             conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT;
   7533         }
   7534 
   7535         SOC_IF_ERROR_RETURN
   7536             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc609, &temp1));
   7537         SOC_IF_ERROR_RETURN
   7538             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc608, &temp2));
   7539         if (temp2 == 0x2 && temp1 == 0x2) {
   7540             conf->flags |= SOC_PORT_PHY_TIMESYNC_64BIT_TIMESTAMP_ENABLE;
   7541         }
   7542         SOC_IF_ERROR_RETURN
   7543             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc602, &tx_ts_cap));
   7544         if (tx_ts_cap & (0x1U << 0)) {
   7545             conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_SYNC;
   7546         }
   7547         if (tx_ts_cap & (0x1U << 1)) {
   7548             conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_DELAY_REQ;
   7549         }
   7550         if (tx_ts_cap & (0x1U << 2)) {
   7551             conf->flags |=
   7552                 SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_REQ;
   7553         }
   7554         if (tx_ts_cap & (0x1U << 3)) {
   7555             conf->flags |=
   7556                 SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_RESP;
   7557         }
   7558 
   7559         SOC_IF_ERROR_RETURN
   7560             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc604, &rx_ts_cap));
   7561         if (rx_ts_cap & (0x1U << 0)) {
   7562             conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_SYNC;
   7563         }
   7564         if (rx_ts_cap & (0x1U << 1)) {
   7565             conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_DELAY_REQ;
   7566         }
   7567         if (rx_ts_cap & (0x1U << 2)) {
   7568             conf->flags |=
   7569                 SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_REQ;
   7570         }
   7571         if (rx_ts_cap & (0x1U << 3)) {
   7572             conf->flags |=
   7573                 SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_RESP;
   7574         }
   7575     }
   7576 
   7577     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   7578         _phy_84740_decode_gmode((nse_sc_8 >> 14), &gmode);
   7579         conf->gmode = gmode;
   7580     }
   7581 
   7582     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   7583         _phy_84740_decode_framesync_mode((nse_sc_8 >> 2), &framesync_mode);
   7584         conf->framesync.mode = framesync_mode;
   7585         SOC_IF_ERROR_RETURN
   7586             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63c, &temp1));
   7587         SOC_IF_ERROR_RETURN
   7588             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63b, &temp2));
   7589         conf->framesync.length_threshold = temp1;
   7590         conf->framesync.event_offset = temp2;
   7591     }
   7592 
   7593     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   7594         _phy_84740_decode_syncout_mode((nse_sc_8 >> 0), &syncout_mode);
   7595         conf->syncout.mode = syncout_mode;
   7596 
   7597         SOC_IF_ERROR_RETURN
   7598             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc635, &temp1));
   7599         SOC_IF_ERROR_RETURN
   7600             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc634, &temp2));
   7601         SOC_IF_ERROR_RETURN
   7602             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc633, &temp3));
   7603         /* Multiply by 6.4 without floating point */
   7604         conf->syncout.pulse_1_length = (((temp3 >> 7) & 0x1ff) * 64) / 10;
   7605         conf->syncout.pulse_2_length =
   7606             ((((temp3 & 0x7f) << 2) | ((temp2 >> 14) & 0x3)) * 64) / 10;
   7607         conf->syncout.interval = ((((temp2 & 0x3fff) << 16) | temp1) * 64) / 10;
   7608 
   7609         SOC_IF_ERROR_RETURN
   7610             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc639, &temp1));
   7611         SOC_IF_ERROR_RETURN
   7612             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc638, &temp2));
   7613         SOC_IF_ERROR_RETURN
   7614             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc637, &temp3));
   7615 
   7616         COMPILER_64_SET(conf->syncout.syncout_ts, ((uint32) temp3),
   7617                         (((uint32) temp2 << 16) | ((uint32) temp1)));
   7618     }
   7619 
   7620     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   7621         /* VLAN TAG register */
   7622         SOC_IF_ERROR_RETURN
   7623             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61d, &conf->itpid));
   7624     }
   7625 
   7626     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   7627         /* OUTER VLAN TAG register */
   7628         SOC_IF_ERROR_RETURN
   7629             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61e, &conf->otpid));
   7630     }
   7631 
   7632     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   7633         /* INNER VLAN TAG register */
   7634         SOC_IF_ERROR_RETURN
   7635             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61f, &conf->otpid2));
   7636     }
   7637 
   7638     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   7639         SOC_IF_ERROR_RETURN
   7640             (READ_PHY84740_MMF_PMA_PMD_REG
   7641              (unit, pc, 0xc636, &conf->ts_divider));
   7642         conf->ts_divider &= 0xfff;
   7643     }
   7644 
   7645     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   7646         SOC_IF_ERROR_RETURN
   7647             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc605, &temp1));
   7648         SOC_IF_ERROR_RETURN
   7649             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc606, &temp2));
   7650 
   7651         conf->rx_link_delay = ((uint32) temp2 << 16) | temp1;
   7652     }
   7653 
   7654     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   7655         /* TIME CODE 5 register */
   7656         SOC_IF_ERROR_RETURN
   7657             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc610, &temp1));
   7658 
   7659         /* TIME CODE 4 register */
   7660         SOC_IF_ERROR_RETURN
   7661             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60f, &temp2));
   7662 
   7663         conf->original_timecode.nanoseconds = ((uint32) temp2 << 16) | temp1;
   7664 
   7665         /* TIME CODE 3 register */
   7666         SOC_IF_ERROR_RETURN
   7667             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60e, &temp1));
   7668 
   7669         /* TIME CODE 2 register */
   7670         SOC_IF_ERROR_RETURN
   7671             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60d, &temp2));
   7672 
   7673         /* TIME CODE 1 register */
   7674         SOC_IF_ERROR_RETURN
   7675             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60c, &temp3));
   7676 
   7677         /* conf->original_timecode.seconds = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */
   7678 
   7679         COMPILER_64_SET(conf->original_timecode.seconds, ((uint32) temp3),
   7680                         (((uint32) temp2 << 16) | ((uint32) temp1)));
   7681     }
   7682 
   7683     /* TXRX TS OFFSET register */
   7684     SOC_IF_ERROR_RETURN
   7685         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60a, &temp1));
   7686 
   7687     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   7688         /* RX TS OFFSET register */
   7689         SOC_IF_ERROR_RETURN
   7690             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60b, &temp2));
   7691         conf->rx_timestamp_offset = (((uint32) (temp1 & 0xf000)) << 4) | temp2;
   7692     }
   7693 
   7694     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   7695         conf->tx_timestamp_offset = temp1 & 0xfff;
   7696     }
   7697 
   7698     /* TX EVENT MESSAGE MODE SEL register */
   7699     SOC_IF_ERROR_RETURN
   7700         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc601, &value));
   7701 
   7702     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   7703         _phy_84740_decode_egress_message_mode(value, 0, &conf->tx_sync_mode);
   7704     }
   7705 
   7706     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   7707         _phy_84740_decode_egress_message_mode(value, 2,
   7708                                               &conf->tx_delay_request_mode);
   7709     }
   7710 
   7711     if (conf->
   7712         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   7713         _phy_84740_decode_egress_message_mode(value, 4,
   7714                                               &conf->tx_pdelay_request_mode);
   7715     }
   7716 
   7717     if (conf->
   7718         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   7719         _phy_84740_decode_egress_message_mode(value, 6,
   7720                                               &conf->tx_pdelay_response_mode);
   7721     }
   7722 
   7723     /* RX EVENT MESSAGE MODE SEL register */
   7724     SOC_IF_ERROR_RETURN
   7725         (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc603, &value));
   7726 
   7727     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   7728         _phy_84740_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode);
   7729     }
   7730 
   7731     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   7732         _phy_84740_decode_ingress_message_mode(value, 2,
   7733                                                &conf->rx_delay_request_mode);
   7734     }
   7735 
   7736     if (conf->
   7737         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   7738         _phy_84740_decode_ingress_message_mode(value, 4,
   7739                                                &conf->rx_pdelay_request_mode);
   7740     }
   7741 
   7742     if (conf->
   7743         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   7744         _phy_84740_decode_ingress_message_mode(value, 6,
   7745                                                &conf->rx_pdelay_response_mode);
   7746     }
   7747 
   7748     if (conf->
   7749         validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   7750         /* Initial ref phase [15:0] */
   7751         SOC_IF_ERROR_RETURN
   7752             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc623, &temp1));
   7753 
   7754         /* Initial ref phase [31:16] */
   7755         SOC_IF_ERROR_RETURN
   7756             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc622, &temp2));
   7757 
   7758         /* Initial ref phase [47:32] */
   7759         SOC_IF_ERROR_RETURN
   7760             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc621, &temp3));
   7761 
   7762         /* conf->phy_1588_dpll_phase_initial = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */
   7763 
   7764         COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((uint32) temp3),
   7765                         (((uint32) temp2 << 16) | ((uint32) temp1)));
   7766     }
   7767     if (conf->
   7768         validity_mask &
   7769         SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   7770         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   7771                             (unit, pc, 0xc625, &temp1));
   7772         SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG
   7773                             (unit, pc, 0xc624, &temp2));
   7774 
   7775         conf->phy_1588_dpll_ref_phase_delta = ((uint32) temp2 << 16) | temp1;
   7776     }
   7777 
   7778     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   7779         /* DPLL K1 */
   7780         SOC_IF_ERROR_RETURN
   7781             (READ_PHY84740_MMF_PMA_PMD_REG
   7782              (unit, pc, 0xc626, &conf->phy_1588_dpll_k1));
   7783         conf->phy_1588_dpll_k1 &= 0xff;
   7784     }
   7785 
   7786     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   7787         /* DPLL K2 */
   7788         SOC_IF_ERROR_RETURN
   7789             (READ_PHY84740_MMF_PMA_PMD_REG
   7790              (unit, pc, 0xc627, &conf->phy_1588_dpll_k2));
   7791         conf->phy_1588_dpll_k2 &= 0xff;
   7792     }
   7793 
   7794     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   7795         /* DPLL K3 */
   7796         SOC_IF_ERROR_RETURN
   7797             (READ_PHY84740_MMF_PMA_PMD_REG
   7798              (unit, pc, 0xc628, &conf->phy_1588_dpll_k3));
   7799         conf->phy_1588_dpll_k3 &= 0xff;
   7800     }
   7801 
   7802     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) {
   7803         SOC_IF_ERROR_RETURN
   7804             (READ_PHY84740_MMF_PMA_PMD_REG
   7805              (unit, pc, 0xc651, &mpls_control_reg));
   7806 
   7807         conf->mpls_control.flags = 0;
   7808 
   7809         if (mpls_control_reg & (1U << 7)) {
   7810             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE;
   7811         }
   7812 
   7813         if (mpls_control_reg & (1U << 6)) {
   7814             conf->mpls_control.flags |=
   7815                 SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE;
   7816         }
   7817 
   7818         if (mpls_control_reg & (1U << 4)) {
   7819             conf->mpls_control.flags |=
   7820                 SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE;
   7821         }
   7822 
   7823         if (mpls_control_reg & (1U << 5)) {
   7824             conf->mpls_control.flags |=
   7825                 SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE;
   7826         }
   7827 
   7828         /* special label [19:16] */
   7829         SOC_IF_ERROR_RETURN
   7830             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc653, &temp2));
   7831 
   7832         /* special label [15:0] */
   7833         SOC_IF_ERROR_RETURN
   7834             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc652, &temp1));
   7835 
   7836         conf->mpls_control.special_label =
   7837             ((uint32) (temp2 & 0x0f) << 16) | temp1;
   7838 
   7839         for (i = 0; i < 10; i++) {
   7840 
   7841             SOC_IF_ERROR_RETURN
   7842                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc654 + i, &temp1));
   7843             conf->mpls_control.labels[i].value = temp1;
   7844 
   7845             SOC_IF_ERROR_RETURN
   7846                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc661 + i, &temp1));
   7847             conf->mpls_control.labels[i].mask = temp1;
   7848         }
   7849 
   7850         /* now get [19:16] of labels */
   7851         SOC_IF_ERROR_RETURN
   7852             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc65e, &temp1));
   7853 
   7854         conf->mpls_control.labels[0].value |= ((uint32) (temp1 & 0x000f) << 16);
   7855         conf->mpls_control.labels[1].value |= ((uint32) (temp1 & 0x00f0) << 12);
   7856         conf->mpls_control.labels[2].value |= ((uint32) (temp1 & 0x0f00) << 8);
   7857         conf->mpls_control.labels[3].value |= ((uint32) (temp1 & 0xf000) << 4);
   7858 
   7859         SOC_IF_ERROR_RETURN
   7860             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc65f, &temp1));
   7861 
   7862         conf->mpls_control.labels[4].value |= ((uint32) (temp1 & 0x000f) << 16);
   7863         conf->mpls_control.labels[5].value |= ((uint32) (temp1 & 0x00f0) << 12);
   7864         conf->mpls_control.labels[6].value |= ((uint32) (temp1 & 0x0f00) << 8);
   7865         conf->mpls_control.labels[7].value |= ((uint32) (temp1 & 0xf000) << 4);
   7866 
   7867         SOC_IF_ERROR_RETURN
   7868             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc660, &temp1));
   7869 
   7870         conf->mpls_control.labels[8].value |= ((uint32) (temp1 & 0x000f) << 16);
   7871         conf->mpls_control.labels[9].value |= ((uint32) (temp1 & 0x00f0) << 12);
   7872 
   7873         /* now get [19:16] of masks */
   7874         SOC_IF_ERROR_RETURN
   7875             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66b, &temp1));
   7876 
   7877         conf->mpls_control.labels[0].mask |= ((uint32) (temp1 & 0x000f) << 16);
   7878         conf->mpls_control.labels[1].mask |= ((uint32) (temp1 & 0x00f0) << 12);
   7879         conf->mpls_control.labels[2].mask |= ((uint32) (temp1 & 0x0f00) << 8);
   7880         conf->mpls_control.labels[3].mask |= ((uint32) (temp1 & 0xf000) << 4);
   7881 
   7882         SOC_IF_ERROR_RETURN
   7883             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66c, &temp1));
   7884         conf->mpls_control.labels[4].mask |= ((uint32) (temp1 & 0x000f) << 16);
   7885         conf->mpls_control.labels[5].mask |= ((uint32) (temp1 & 0x00f0) << 12);
   7886         conf->mpls_control.labels[6].mask |= ((uint32) (temp1 & 0x0f00) << 8);
   7887         conf->mpls_control.labels[7].mask |= ((uint32) (temp1 & 0xf000) << 4);
   7888 
   7889         SOC_IF_ERROR_RETURN
   7890             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66d, &temp1));
   7891 
   7892         conf->mpls_control.labels[8].mask |= ((uint32) (temp1 & 0x000f) << 16);
   7893         conf->mpls_control.labels[9].mask |= ((uint32) (temp1 & 0x00f0) << 12);
   7894 
   7895         /* label flags */
   7896         SOC_IF_ERROR_RETURN
   7897             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66e, &temp1));
   7898         for (i = 0; i < 8; i++) {
   7899             conf->mpls_control.labels[i].flags |=
   7900                 temp1 & (0x2 << (i << 1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT: 0;
   7901             conf->mpls_control.labels[i].flags |=
   7902                 temp1 & (0x1 << (i << 1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN: 0;
   7903         }
   7904         SOC_IF_ERROR_RETURN
   7905             (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66f, &temp2));
   7906         for (i = 0; i < 2; i++) {
   7907             conf->mpls_control.labels[i + 8].flags |=
   7908                 temp2 & (0x2 << (i << 1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT: 0;
   7909             conf->mpls_control.labels[i + 8].flags |=
   7910                 temp2 & (0x1 << (i << 1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN: 0;
   7911         }
   7912 
   7913     }
   7914     return SOC_E_NONE;
   7915 }
   7916 
   7917 int
   7918 phy_84740_timesync_control_set(int unit, soc_port_t port,
   7919                                soc_port_control_phy_timesync_t type,
   7920                                uint64 value)
   7921 {
   7922     uint16 temp1, temp2;
   7923     uint32 value0;
   7924     phy_ctrl_t *pc;
   7925 
   7926     pc = EXT_PHY_SW_STATE(unit, port);
   7927 
   7928     switch (type) {
   7929 
   7930         case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   7931         case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   7932             return SOC_E_FAIL;
   7933 
   7934         case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   7935             SOC_IF_ERROR_RETURN
   7936                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7937                                                 0xc62f,
   7938                                                 (uint16) (COMPILER_64_LO(value) & 0xffff)));
   7939             SOC_IF_ERROR_RETURN
   7940                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7941                                                 0xc62e,
   7942                                                 (uint16) ((COMPILER_64_LO(value) >> 16) & 0xffff)));
   7943             break;
   7944 
   7945         case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC:
   7946 
   7947             SOC_IF_ERROR_RETURN
   7948                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, &temp1));
   7949             temp2 = ((temp1 |
   7950                      (0x3 << 14) |
   7951                      (0x1 << 12)) &
   7952                      ~(0xf << 2)) |
   7953                      (0x1 << 5);
   7954             SOC_IF_ERROR_RETURN
   7955                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, temp2));
   7956             sal_usleep(1);
   7957             temp2 &= ~((0x1 << 5) | (0x1 << 12));
   7958             SOC_IF_ERROR_RETURN
   7959                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, temp2));
   7960             sal_usleep(1);
   7961             SOC_IF_ERROR_RETURN
   7962                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, temp1));
   7963             break;
   7964 
   7965         case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   7966             /* COMPILER_64_SHR(value, 4); *//* shifting 4 bits extra, not required */
   7967             SOC_IF_ERROR_RETURN
   7968                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7969                                                 0xc632,
   7970                                                 (uint16) (COMPILER_64_LO(value) & 0xffff)));
   7971             SOC_IF_ERROR_RETURN
   7972                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7973                                                 0xc631,
   7974                                                 (uint16) ((COMPILER_64_LO(value) >> 16) &
   7975                                                 0xffff)));
   7976             SOC_IF_ERROR_RETURN
   7977                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   7978                                                  0xc630,
   7979                                                  (uint16) COMPILER_64_HI(value),
   7980                                                  0x0fff));
   7981             break;
   7982         case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   7983             temp1 = 0;
   7984             temp2 = 0;
   7985 
   7986             value0 = COMPILER_64_LO(value);
   7987 
   7988             if (value0 & SOC_PORT_PHY_TIMESYNC_TN_LOAD) {
   7989                 temp1 |= 1U << 11;
   7990             }
   7991             if (value0 & SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) {
   7992                 temp2 |= 1U << 11;
   7993             }
   7994             if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) {
   7995                 temp1 |= 1U << 10;
   7996             }
   7997             if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) {
   7998                 temp2 |= 1U << 10;
   7999             }
   8000             if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) {
   8001                 temp1 |= 1U << 9;
   8002             }
   8003             if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) {
   8004                 temp2 |= 1U << 9;
   8005             }
   8006             if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) {
   8007                 temp1 |= 1U << 8;
   8008             }
   8009             if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) {
   8010                 temp2 |= 1U << 8;
   8011             }
   8012             if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) {
   8013                 temp1 |= 1U << 7;
   8014             }
   8015             if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) {
   8016                 temp2 |= 1U << 7;
   8017             }
   8018             if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) {
   8019                 temp1 |= 1U << 6;
   8020             }
   8021             if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) {
   8022                 temp2 |= 1U << 6;
   8023             }
   8024             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) {
   8025                 temp1 |= 1U << 5;
   8026             }
   8027             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) {
   8028                 temp2 |= 1U << 5;
   8029             }
   8030             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) {
   8031                 temp1 |= 1U << 4;
   8032             }
   8033             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) {
   8034                 temp2 |= 1U << 4;
   8035             }
   8036             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) {
   8037                 temp1 |= 1U << 3;
   8038             }
   8039             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) {
   8040                 temp2 |= 1U << 3;
   8041             }
   8042             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) {
   8043                 temp1 |= 1U << 2;
   8044             }
   8045             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) {
   8046                 temp2 |= 1U << 2;
   8047             }
   8048             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) {
   8049                 temp1 |= 1U << 1;
   8050             }
   8051             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) {
   8052                 temp2 |= 1U << 1;
   8053             }
   8054             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) {
   8055                 temp1 |= 1U << 0;
   8056             }
   8057             if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) {
   8058                 temp2 |= 1U << 0;
   8059             }
   8060             SOC_IF_ERROR_RETURN
   8061                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc615, temp1));
   8062 
   8063             /* always load not supported at the moment */
   8064             /*
   8065                SOC_IF_ERROR_RETURN
   8066                (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc615, temp2));
   8067              */
   8068 
   8069             break;
   8070 
   8071         case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT:
   8072             temp1 = 0;
   8073 
   8074             value0 = COMPILER_64_LO(value);
   8075 
   8076             if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT) {
   8077                 temp1 |= 1U << 1;
   8078             }
   8079             if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT) {
   8080                 temp1 |= 1U << 0;
   8081             }
   8082             SOC_IF_ERROR_RETURN
   8083                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc617, temp1));
   8084             break;
   8085         case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   8086             temp1 = 0;
   8087 
   8088             value0 = COMPILER_64_LO(value);
   8089 
   8090             if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) {
   8091                 temp1 |= 1U << 1;
   8092             }
   8093             if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) {
   8094                 temp1 |= 1U << 0;
   8095             }
   8096             SOC_IF_ERROR_RETURN
   8097                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc616, temp1));
   8098             break;
   8099 
   8100         case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   8101             value0 = COMPILER_64_LO(value);
   8102 
   8103             SOC_IF_ERROR_RETURN
   8104                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8105                                                  0xc60a,
   8106                                                  (uint16) (value0 & 0x0fff),
   8107                                                  0x0fff));
   8108             break;
   8109 
   8110         case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   8111             value0 = COMPILER_64_LO(value);
   8112 
   8113             SOC_IF_ERROR_RETURN
   8114                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8115                                                 0xc60b,
   8116                                                 (uint16) (value0 & 0xffff)));
   8117             SOC_IF_ERROR_RETURN
   8118                 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc,
   8119                                                  0xc60a,
   8120                                                  (uint16) ((value0 >> 4) & 0xf000), 0xf000));
   8121             break;
   8122         default:
   8123             return SOC_E_NONE;
   8124             break;
   8125     }
   8126 
   8127     return SOC_E_NONE;
   8128 }
   8129 
   8130 int
   8131 phy_84740_timesync_control_get(int unit, soc_port_t port,
   8132                                soc_port_control_phy_timesync_t type,
   8133                                uint64 *value)
   8134 {
   8135     uint16 value0 = 0;
   8136     uint16 value1 = 0;
   8137     uint16 value2 = 0;
   8138     uint16 value3 = 0;
   8139     uint32 value4 = 0;
   8140     phy_ctrl_t *pc;
   8141 
   8142     pc = EXT_PHY_SW_STATE(unit, port);
   8143 
   8144     switch (type) {
   8145         case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   8146 
   8147             SOC_IF_ERROR_RETURN
   8148                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x4));
   8149 
   8150             SOC_IF_ERROR_RETURN
   8151                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc647, &value0));
   8152             SOC_IF_ERROR_RETURN
   8153                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc646, &value1));
   8154             SOC_IF_ERROR_RETURN
   8155                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc645, &value2));
   8156 
   8157             SOC_IF_ERROR_RETURN
   8158                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x8));
   8159             SOC_IF_ERROR_RETURN
   8160                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x0));
   8161 
   8162             /*    *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */
   8163             COMPILER_64_SET((*value),
   8164                             (((uint32) value3 << 16) | ((uint32) value2)),
   8165                             (((uint32) value1 << 16) | ((uint32) value0)));
   8166             break;
   8167         case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   8168 
   8169             SOC_IF_ERROR_RETURN
   8170                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x1));
   8171 
   8172             SOC_IF_ERROR_RETURN
   8173                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc640, &value0));
   8174             SOC_IF_ERROR_RETURN
   8175                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63f, &value1));
   8176             SOC_IF_ERROR_RETURN
   8177                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63e, &value2));
   8178 
   8179             SOC_IF_ERROR_RETURN
   8180                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x2));
   8181             SOC_IF_ERROR_RETURN
   8182                 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x0));
   8183 
   8184             /*   *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */
   8185             COMPILER_64_SET((*value),
   8186                             (((uint32) value3 << 16) | ((uint32) value2)),
   8187                             (((uint32) value1 << 16) | ((uint32) value0)));
   8188             break;
   8189 
   8190         case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   8191             SOC_IF_ERROR_RETURN
   8192                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc62f, &value0));
   8193             SOC_IF_ERROR_RETURN
   8194                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc62e, &value1));
   8195             COMPILER_64_SET((*value), 0,
   8196                             (((uint32) value1 << 16) | ((uint32) value0)));
   8197             break;
   8198 
   8199         case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   8200             SOC_IF_ERROR_RETURN
   8201                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc632, &value0));
   8202             SOC_IF_ERROR_RETURN
   8203                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc631, &value1));
   8204             SOC_IF_ERROR_RETURN
   8205                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc630, &value2));
   8206             COMPILER_64_SET((*value), ((uint32) (value2 & 0x0fff)),
   8207                             (((uint32) value1 << 16) | ((uint32) value0)));
   8208             COMPILER_64_SHL((*value), 4);
   8209             break;
   8210 
   8211         case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   8212 
   8213             SOC_IF_ERROR_RETURN
   8214                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc615, &value1));
   8215             /* always load not supported at the moment */
   8216             /*
   8217                SOC_IF_ERROR_RETURN
   8218                (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc615, &value2));
   8219              */
   8220             value2 = 0;
   8221 
   8222             value4 = 0;
   8223 
   8224             if (value1 & (1U << 11)) {
   8225                 value4 |= SOC_PORT_PHY_TIMESYNC_TN_LOAD;
   8226             }
   8227             if (value2 & (1U << 11)) {
   8228                 value4 |= SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD;
   8229             }
   8230             if (value1 & (1U << 10)) {
   8231                 value4 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD;
   8232             }
   8233             if (value2 & (1U << 10)) {
   8234                 value4 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD;
   8235             }
   8236             if (value1 & (1U << 9)) {
   8237                 value4 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD;
   8238             }
   8239             if (value2 & (1U << 9)) {
   8240                 value4 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD;
   8241             }
   8242             if (value1 & (1U << 8)) {
   8243                 value4 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD;
   8244             }
   8245             if (value1 & (1U << 8)) {
   8246                 value4 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD;
   8247             }
   8248             if (value1 & (1U << 7)) {
   8249                 value4 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD;
   8250             }
   8251             if (value1 & (1U << 7)) {
   8252                 value4 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD;
   8253             }
   8254             if (value1 & (1U << 6)) {
   8255                 value4 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD;
   8256             }
   8257             if (value2 & (1U << 6)) {
   8258                 value4 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD;
   8259             }
   8260             if (value1 & (1U << 5)) {
   8261                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD;
   8262             }
   8263             if (value2 & (1U << 5)) {
   8264                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD;
   8265             }
   8266             if (value1 & (1U << 4)) {
   8267                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD;
   8268             }
   8269             if (value2 & (1U << 4)) {
   8270                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD;
   8271             }
   8272             if (value1 & (1U << 3)) {
   8273                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD;
   8274             }
   8275             if (value2 & (1U << 3)) {
   8276                 value4 |=
   8277                     SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD;
   8278             }
   8279             if (value1 & (1U << 2)) {
   8280                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD;
   8281             }
   8282             if (value2 & (1U << 2)) {
   8283                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD;
   8284             }
   8285             if (value1 & (1U << 1)) {
   8286                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD;
   8287             }
   8288             if (value2 & (1U << 1)) {
   8289                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD;
   8290             }
   8291             if (value1 & (1U << 0)) {
   8292                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD;
   8293             }
   8294             if (value2 & (1U << 0)) {
   8295                 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD;
   8296             }
   8297             COMPILER_64_SET((*value), 0, value4);
   8298 
   8299             break;
   8300 
   8301         case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT:
   8302             SOC_IF_ERROR_RETURN
   8303                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc617, &value1));
   8304 
   8305             value0 = 0;
   8306 
   8307             if (value1 & (1U << 1)) {
   8308                 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT;
   8309             }
   8310             if (value1 & (1U << 0)) {
   8311                 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT;
   8312             }
   8313             COMPILER_64_SET((*value), 0, (uint32) value0);
   8314 
   8315             break;
   8316 
   8317         case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   8318             SOC_IF_ERROR_RETURN
   8319                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc616, &value1));
   8320             value0 = 0;
   8321 
   8322             if (value1 & (1U << 1)) {
   8323                 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK;
   8324             }
   8325             if (value1 & (1U << 0)) {
   8326                 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK;
   8327             }
   8328             COMPILER_64_SET((*value), 0, (uint32) value0);
   8329 
   8330             break;
   8331 
   8332         case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   8333             SOC_IF_ERROR_RETURN
   8334                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60a, &value0));
   8335 
   8336             COMPILER_64_SET((*value), 0, (uint32) (value0 & 0x0fff));
   8337             break;
   8338 
   8339         case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   8340             SOC_IF_ERROR_RETURN
   8341                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60b, &value0));
   8342 
   8343             SOC_IF_ERROR_RETURN
   8344                 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60a, &value1));
   8345 
   8346             COMPILER_64_SET((*value), 0,
   8347                             (uint32) (((((uint32) value1) << 4) & 0xf0000) |
   8348                                       value0));
   8349             break;
   8350 
   8351         default:
   8352             return SOC_E_FAIL;
   8353     }
   8354 
   8355     return SOC_E_NONE;
   8356 }
   8357 
   8358 void
   8359 _phy_84740_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode,
   8360                                       int offset, uint16 *value)
   8361 {
   8362 
   8363     switch (mode) {
   8364         case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE:
   8365             *value |= (0x0 << offset);
   8366             break;
   8367         case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD:
   8368             *value |=
   8369                 (0x1 << offset);
   8370             break;
   8371         case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN:
   8372             *value |=
   8373                 (0x2 << offset);
   8374             break;
   8375         case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP:
   8376             *value |= (0x3 << offset);
   8377             break;
   8378     }
   8379 
   8380 }
   8381 
   8382 void
   8383 _phy_84740_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode,
   8384                                        int offset, uint16 *value)
   8385 {
   8386 
   8387     switch (mode) {
   8388         case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE:
   8389             *value |= (0x0 << offset);
   8390             break;
   8391         case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD:
   8392             *value |=
   8393                 (0x1 << offset);
   8394             break;
   8395         case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP:
   8396             *value |= (0x2 << offset);
   8397             break;
   8398         case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME:
   8399             *value |= (0x3 << offset);
   8400             break;
   8401     }
   8402 
   8403 }
   8404 
   8405 void _phy_84740_decode_egress_message_mode(uint16 value, int offset,
   8406                                            soc_port_phy_timesync_event_message_egress_mode_t
   8407                                            *mode)
   8408 {
   8409 
   8410     switch ((value >> offset) & 0x3) {
   8411         case 0x0:
   8412             *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE;
   8413             break;
   8414         case 0x1:
   8415             *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD;
   8416             break;
   8417         case 0x2:
   8418             *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN;
   8419             break;
   8420         case 0x3:
   8421             *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP;
   8422             break;
   8423     }
   8424 
   8425 }
   8426 
   8427 void _phy_84740_decode_ingress_message_mode(uint16 value, int offset,
   8428                                             soc_port_phy_timesync_event_message_ingress_mode_t
   8429                                             *mode)
   8430 {
   8431 
   8432     switch ((value >> offset) & 0x3) {
   8433         case 0x0:
   8434             *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE;
   8435             break;
   8436         case 0x1:
   8437             *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD;
   8438             break;
   8439         case 0x2:
   8440             *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP;
   8441             break;
   8442         case 0x3:
   8443             *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME;
   8444             break;
   8445     }
   8446 
   8447 }
   8448 
   8449 void _phy_84740_encode_gmode(soc_port_phy_timesync_global_mode_t mode,
   8450                              uint16 *value)
   8451 {
   8452 
   8453     switch (mode) {
   8454         case SOC_PORT_PHY_TIMESYNC_MODE_FREE:
   8455             *value = 0x1;
   8456             break;
   8457         case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN:
   8458             *value = 0x2;
   8459             break;
   8460         case SOC_PORT_PHY_TIMESYNC_MODE_CPU:
   8461             *value = 0x3;
   8462             break;
   8463         default:
   8464             break;
   8465     }
   8466 
   8467 }
   8468 
   8469 void _phy_84740_decode_gmode(uint16 value,
   8470                              soc_port_phy_timesync_global_mode_t *mode)
   8471 {
   8472 
   8473     switch (value & 0x3) {
   8474         case 0x1:
   8475             *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   8476             break;
   8477         case 0x2:
   8478             *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN;
   8479             break;
   8480         case 0x3:
   8481             *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU;
   8482             break;
   8483         default:
   8484             break;
   8485     }
   8486 
   8487 }
   8488 
   8489 void _phy_84740_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t
   8490                                       mode, uint16 *value)
   8491 {
   8492 
   8493     switch (mode) {
   8494         case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0:
   8495             *value = 1U << 0;
   8496             break;
   8497         case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1:
   8498             *value = 1U << 1;
   8499             break;
   8500         case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT:
   8501             *value = 1U << 2;
   8502             break;
   8503         case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU:
   8504             *value = 1U << 3;
   8505             break;
   8506         default:
   8507             break;
   8508     }
   8509 
   8510 }
   8511 
   8512 void _phy_84740_decode_framesync_mode(uint16 value,
   8513                                       soc_port_phy_timesync_framesync_mode_t *mode)
   8514 {
   8515 
   8516     switch (value & 0xf) {
   8517         case 1U << 0:
   8518             *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0;
   8519             break;
   8520         case 1U << 1:
   8521             *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1;
   8522             break;
   8523         case 1U << 2:
   8524             *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT;
   8525             break;
   8526         case 1U << 3:
   8527             *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU;
   8528             break;
   8529         default:
   8530             break;
   8531     }
   8532 
   8533 }
   8534 
   8535 void _phy_84740_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode,
   8536                                     uint16 *value)
   8537 {
   8538 
   8539     switch (mode) {
   8540         case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE:
   8541             *value = 0x0;
   8542             break;
   8543         case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME:
   8544             *value = 0x1;
   8545             break;
   8546         case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN:
   8547             *value = 0x2;
   8548             break;
   8549         case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC:
   8550             *value = 0x3;
   8551             break;
   8552     }
   8553 
   8554 }
   8555 
   8556 void _phy_84740_decode_syncout_mode(uint16 value,
   8557                                     soc_port_phy_timesync_syncout_mode_t *mode)
   8558 {
   8559 
   8560     switch (value & 0x3) {
   8561         case 0x0:
   8562             *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   8563             break;
   8564         case 0x1:
   8565             *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME;
   8566             break;
   8567         case 0x2:
   8568             *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN;
   8569             break;
   8570         case 0x3:
   8571             *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC;
   8572             break;
   8573     }
   8574 
   8575 }
   8576 
   8577 /*
   8578  * Variable:
   8579  *    phy_84740_drv
   8580  * Purpose:
   8581  *    Phy Driver for 40G PHY.
   8582  */
   8583 
   8584 phy_driver_t phy_84740drv_xe = {
   8585     "84740 10-Gigabit PHY Driver",
   8586     phy_84740_init,             /* Init */
   8587     phy_null_reset,             /* Reset (dummy) */
   8588     phy_84740_link_get,         /* Link get   */
   8589     phy_84740_enable_set,       /* Enable set */
   8590     phy_null_enable_get,        /* Enable get */
   8591     phy_null_set,               /* Duplex set */
   8592     phy_null_one_get,           /* Duplex get */
   8593     phy_84740_speed_set,        /* Speed set  */
   8594     phy_84740_speed_get,        /* Speed get  */
   8595     phy_null_set,               /* Master set */
   8596     phy_null_zero_get,          /* Master get */
   8597     phy_84740_an_set,           /* ANA set */
   8598     phy_84740_an_get,           /* ANA get */
   8599     NULL,                       /* Local Advert set */
   8600     NULL,                       /* Local Advert get */
   8601     phy_null_mode_get,          /* Remote Advert get */
   8602     phy_84740_lb_set,           /* PHY loopback set */
   8603     phy_84740_lb_get,           /* PHY loopback set */
   8604     phy_84740_interface_set,    /* IO Interface set */
   8605     phy_84740_interface_get,    /* IO Interface get */
   8606     NULL,                       /* PHY abilities mask */
   8607     NULL,
   8608     NULL,
   8609     phy_null_mdix_set,
   8610     phy_null_mdix_get,
   8611     phy_null_mdix_status_get,
   8612     NULL,
   8613     NULL,
   8614     phy_null_medium_get,
   8615     NULL,                       /* phy_cable_diag  */
   8616     NULL,                       /* phy_link_change */
   8617     phy_84740_control_set,      /* phy_control_set */
   8618     phy_84740_control_get,      /* phy_control_get */
   8619     phy_84740_reg_read,         /* phy_reg_read */
   8620     phy_84740_reg_write,        /* phy_reg_write */
   8621     NULL,                       /* phy_reg_modify */
   8622     NULL,                       /* phy_notify */
   8623     phy_84740_probe,            /* pd_probe  */
   8624     phy_84740_ability_advert_set,       /* pd_ability_advert_set */
   8625     phy_84740_ability_advert_get,       /* pd_ability_advert_get */
   8626     phy_84740_ability_remote_get,       /* pd_ability_remote_get */
   8627     phy_84740_ability_local_get,        /* pd_ability_local_get  */
   8628     phy_84740_firmware_set,     /* pd_firmware_set */
   8629     phy_84740_timesync_config_set,      /* pd_timesync_config_set */
   8630     phy_84740_timesync_config_get,      /* pd_timesync_config_get */
   8631     phy_84740_timesync_control_set,     /* pd_timesync_control_set */
   8632     phy_84740_timesync_control_get,     /* pd_timesync_control_get */
   8633     phy_84740_diag_ctrl,        /* pd_diag_ctrl */
   8634     NULL,                       /* pd_lane_control_set */
   8635     NULL,                       /* pd_lane_control_get */
   8636     NULL,                       /* pd_lane_reg_read */
   8637     NULL,                       /* pd_lane_reg_write */
   8638     NULL,                       /* pd_oam_config_set */
   8639     NULL,                       /* pd_oam_config_get */
   8640     NULL,                       /* pd_oam_control_set */
   8641     NULL,                       /* pd_oam_control_get */
   8642     NULL,                       /* pd_timesync_enhanced_capture_get */
   8643     phy_84740_multi_get,         /* pd_multi_get */
   8644     phy_84740_precondition_before_probe /* pd_precondition_before_probe */
   8645 };
   8646 
   8647 #else                           /* INCLUDE_PHY_84740 */
   8648 int _phy_84740_not_empty;
   8649 #endif                          /* INCLUDE_PHY_84740 */