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

phy82109.c (90710B)


      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:        phy82109.c
      8  * Purpose:     Support for Huracan external PHY 
      9  */
     10 
     11 /*
     12  *   This module implements an NTSW SDK Phy driver for the phy82109 External PHY.
     13  *  
     14  *   LAYERING.
     15  *
     16  *   This driver is built on top of the PHYMOD library, which is a PHY
     17  *   driver library that can operate on a family of PHYs, including
     18  *   phy82109 and Sesto and etc..,  PHYMOD can be built in a standalone enviroment and be
     19  *   provided independently from the SDK.  PHYMOD APIs consist of
     20  *   "core" APIs and "phy" APIs.
     21  *
     22  *
     23  *   KEY IDEAS AND MAIN FUNCTIONS
     24  *
     25  *   Some key ideas in this architecture are:
     26  *
     27  *   o A PHMOD "phy" consists of one more more lanes, all residing in a single
     28  *     core.  An SDK "phy" is a logical port, which can consist of one or
     29  *     more lanes in a single core, OR, can consist of multiples lanes in
     30  *     more than one core.
     31  *   o PHYMOD code is "stateless" in the sense that all calls to PHYMOD
     32  *     APIs are fully parameterized and no per-phy state is held by a PHYMOD
     33  *     driver.
     34  *   o PHYMOD APIs do not map 1-1 with SDK .pd_control_set or .pd_control_get
     35  *     APIs (nor ".pd_xx" calls, nor to .phy82109_per_lane_control_set and
     36  *     .phy82109_per_lane_control_get APIs.
     37  *
     38  *   The purpose of this code, then, is to provide the necessary translations
     39  *   between the SDK interfaces and the PHYMOD interfaces.  This includes:
     40  * 
     41  *   o Looping over the cores in a logical PHY in order to operate on the
     42  *     supporting PHMOD PHYs
     43  *   o Determining the configuration data for the phy, based on programmed
     44  *     defaults and SOC properties.
     45  *   o Managing the allocation and freeing of phy data structures required for
     46  *     working storage.  Locating these structures on procedure invocation.
     47  *   o Mapping SDK API concepts to PHYMOD APIs.  In some cases, local state is
     48  *     required in this module in order to present the legacy API.
     49  *
     50  * 
     51  *   MAIN DATA STRUCTURES
     52  * 
     53  *   phy_ctrl_t
     54  *   The PHY control structure defines the SDK notion of a PHY
     55  *   (existing) structure owned by SDK phy driver modules.  In order
     56  *   to support PHYMOD PHYs, one addition was made to this structure
     57  *   (soc_phymod_ctrl_t phymod_ctrl;)
     58  *
     59  *   xxx_config_t
     60  *   Driver specific data.  This structure is used by Huracan to hold
     61  *   logical port specific working storage.
     62  *
     63  *   soc_phymod_ctrl_t
     64  *   PHYMOD drivers.  Resides in phy_ctrl_t specifies how many cores
     65  *   are in this phy and contains an array of pointers to
     66  *   soc_phymod_phy_t structures, which define a PHYMOD PHY.
     67  *
     68  *   soc_phymod_phy_t
     69  *   This structure contains a pointer to phymod_phy_access_t and a
     70  *   pointer to the associated soc_phymod_core_t.  Instances if this
     71  *   structure are created during device probe/init and are maintained
     72  *   by the SOC.
     73  *
     74  *   soc_phymod_core_t
     75  *   This structure contains per-core information.  Multiple PHYMOD
     76  *   PHYS can point to a single core.
     77  *
     78  *   phymod_phy_access_t
     79  *   This structure contains information about how to read/write PHY
     80  *   registers.  A required parameter for PHYMOD PHY APIs
     81  * 
     82  *   phymod_core_access_t
     83  *   This structure contains information about how to read/write PHY
     84  *   registers.  A required parameter for PHYMOD core APIs.
     85  */
     86 
     87 #include <shared/bsl.h>
     88 
     89 #include <sal/types.h>
     90 #include <sal/types.h>
     91 #include <sal/core/spl.h>
     92 #include <shared/bsl.h>
     93 #include <soc/drv.h>
     94 #include <soc/debug.h>
     95 #include <soc/error.h>
     96 #include <soc/phyreg.h>
     97 #include <soc/port_ability.h>
     98 #include <soc/phy.h>
     99 #include <soc/phy/phyctrl.h>
    100 #include <soc/phy/drv.h>
    101 #include <soc/phy/phymod_ids.h>
    102 
    103 #include "phydefs.h"      /* Must include before other phy related includes */ 
    104 
    105 #include "phyconfig.h"     /* Must include before other phy related includes */
    106 #include "phyident.h"
    107 #include "phyreg.h"
    108 #include "phynull.h"
    109 #include "xgxs.h"
    110 
    111 #define PHYMOD_HURACAN_SUPPORT
    112 
    113 #if defined(INCLUDE_PHY_82109) 
    114 
    115 #include <phymod/phymod.h>
    116 #include <phymod/phymod_debug.h>
    117 #include <phymod/phymod_diagnostics.h>
    118 
    119 #define NUM_LANES                           4    /* num of lanes per core */
    120 #define MAX_NUM_LANES                       4    /* max num of lanes per port */
    121 #define PHY82109_NO_CFG_VALUE               (-1)
    122 #define PHY82109_DBG_REGACC                 0x2
    123 #define PHY82109_DBG_MEM                    0x3
    124 #define PHY82109_PORT_NO_LANES_4            4
    125 #define PHY82109_PORT_NO_LANES_2            2
    126 #define PHY82109_PORT_NO_LANES_1            1
    127 #define PHY82109_SPD_100G                   100000
    128 #define PHY82109_SPD_10G                    10000
    129 #define PHY82109_SPD_20G                    20000
    130 #define PHY82109_SPD_25G                    25000
    131 #define PHY82109_SPD_40G                    40000
    132 #define PHY82109_SPD_50G                    50000
    133 #define PHY82109_SPD_6G                     6000
    134 #define INTERFACE_SIDE_SHIFT                31
    135 #define HURACAN_ID_82109                    0x82109
    136 #define PHY82109_MAX_LANE                   8
    137 #define PHY82109_CHIP_ID_SIZE               25
    138 typedef struct phy82109_speed_config_s {
    139     uint32  port_refclk_int;
    140     int     speed;
    141     int     port_num_lanes;
    142     uint32  line_interface;
    143     int     pll_divider_req  ;
    144     int     higig_port;
    145 } phy82109_speed_config_t;
    146 
    147 typedef enum PHY82109_INTF_SIDE {
    148     PHY82109_LINE_SIDE,
    149     PHY82109_SYS_SIDE 
    150 }PHY82109_INTF_SIDE;
    151 
    152 
    153 #define HURACAN_IS_SIMPLEX(devid)\
    154 ((devid) == HURACAN_ID_82109)
    155 
    156 #define HURACAN_IS_DUPLEX(devid)\
    157 ((devid) != HURACAN_ID_82109)
    158 
    159 /*
    160    Config - per logical port
    161 */
    162 typedef struct {
    163     phymod_polarity_t               phy_polarity_config;
    164     phymod_phy_reset_t              phy_reset_config;
    165     phy82109_speed_config_t         speed_config;
    166     int                             an_master_lane;
    167     int                             ull_datapath;
    168     uint32_t                             devid;
    169     char                            dev_name[PHY82109_CHIP_ID_SIZE];
    170     int                             auto_mod_detect;
    171     int                             simplex_tx;
    172     unsigned int                    port_phy_lane_mask;
    173 } phy82109_config_t;
    174 
    175 #define DEVID(_pc)           (((phy82109_config_t *)((_pc) + 1))->devid)
    176 #define DEV_NAME(_pc)        (((phy82109_config_t *)((_pc) + 1))->dev_name)
    177 #define SIMPLEX_TX(_pc)   (((phy82109_config_t *)((_pc) + 1))->simplex_tx) 
    178 #define PORT_PHY_LANE_MASK(_pc)   (((phy82109_config_t *)((_pc) + 1))->port_phy_lane_mask) 
    179 /* int is_eye_scan_enabled = 0; */
    180 
    181 STATIC int
    182 phy_82109_ability_advert_set(int unit, soc_port_t port,
    183                           soc_port_ability_t *ability);
    184 
    185 STATIC int
    186 phy_82109_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability);
    187 STATIC int
    188 _phy_82109_find_soc_phy_lane(soc_phymod_ctrl_t *pmc, uint32_t lane, 
    189                         soc_phymod_phy_t **p_phy, uint32 *lane_map);
    190 
    191 STATIC int
    192 phy_82109_power_set(phy_ctrl_t *pc, int32 intf, uint32 value);
    193 STATIC int
    194 phy_82109_power_get(phy_ctrl_t *pc, int32 intf, uint32 *value);
    195 STATIC int
    196 phy_82109_tx_lane_squelch_get(phy_ctrl_t *pc, int32 intf, uint32 *value);
    197 STATIC int
    198 phy_82109_per_lane_tx_lane_squelch_get(phy_ctrl_t *pc, int32 intf, int lane, uint32 *value);
    199 STATIC int
    200 _phy_82109_get_intf_side(uint32_t chip_id, int32 intf, uint32 simplex_tx, uint32 tx_rx, uint32_t *if_side);
    201 
    202 /*
    203  * Function:
    204  *      _phy82109_reg_read
    205  * Doc:
    206  *      register read operations
    207  * Parameters:
    208  *      unit            - (IN)  unit number
    209  *      core_addr       - (IN)  core address
    210  *      reg_addr        - (IN)  address to read
    211  *      val             - (OUT) read value
    212  */
    213 STATIC int 
    214 _phy82109_reg_read(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t *val)
    215 {
    216     uint16 data16;
    217     int rv;
    218     soc_phymod_core_t *core = (soc_phymod_core_t *)user_acc;
    219 
    220     rv = core->read(core->unit, core_addr, reg_addr, &data16);
    221     *val = data16;
    222     PHYMOD_VDBG(PHY82109_DBG_REGACC, NULL,("-22%s: core_addr: 0x%08x reg_addr: 0x%08x, data: 0x%04x\n", __func__, core_addr, reg_addr, *val ));
    223 
    224     return rv;
    225 }
    226 
    227 /*
    228  * Function:
    229  *      _phy82109_reg_write
    230  * Doc:
    231  *      register write operations
    232  * Parameters:
    233  *      unit            - (IN)  unit number
    234  *      core_addr       - (IN)  core address
    235  *      reg_addr        - (IN)  address to write
    236  *      val             - (IN)  write value
    237  */
    238 STATIC int 
    239 _phy82109_reg_write(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t val)
    240 {
    241     soc_phymod_core_t *core = (soc_phymod_core_t *)user_acc;
    242     uint16 data16 = (uint16)val;
    243     uint16 mask = (uint16)(val >> 16);
    244 
    245     if (mask) {
    246         if (core->wrmask) {
    247             return core->wrmask(core->unit, core_addr, reg_addr, data16, mask);
    248         }
    249         (void)core->read(core->unit, core_addr, reg_addr, &data16);
    250         data16 &= ~mask;
    251         data16 |= (val & mask);
    252     }
    253     PHYMOD_VDBG(PHY82109_DBG_REGACC, NULL,("-22%s: core_addr: 0x%08x reg_addr: 0x%08x, data: 0x%04x\n", __func__, core_addr, reg_addr, val ));
    254     return core->write(core->unit, core_addr, reg_addr, data16);
    255 }
    256 
    257 /*
    258  * Function:
    259  *      phy82109_speed_set
    260  * Purpose:
    261  *      Set PHY speed
    262  * Parameters:
    263  *      unit - BCM unit number.
    264  *      port - Port number. 
    265  *      speed - link speed in Mbps
    266  * Returns:     
    267  *      SOC_E_XXX
    268  */
    269 
    270 STATIC int
    271 phy82109_speed_set(int unit, soc_port_t port, int speed)
    272 {
    273     phy_ctrl_t                *int_pc;
    274     int int_speed;
    275     /* locate phy control */
    276     int_pc = INT_PHY_SW_STATE(unit, port);
    277     if (int_pc == NULL) {
    278         return SOC_E_INTERNAL;
    279     }
    280 
    281     if (speed == 0) {
    282         return SOC_E_NONE; 
    283     }
    284     SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &int_speed));
    285     
    286     if (int_speed != speed) {
    287         SOC_IF_ERROR_RETURN(PHY_SPEED_SET(int_pc->pd, unit, port, speed));
    288         SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &int_speed));
    289         if (int_speed != speed) {
    290             return SOC_E_CONFIG;
    291         }
    292     }
    293     return (SOC_E_NONE);
    294 }
    295 
    296 
    297 /*
    298  * Function:
    299  *      phy82109_speed_get
    300  * Purpose:
    301  *      Get PHY speed
    302  * Parameters:
    303  *      unit - BCM unit number.
    304  *      port - Port number. 
    305  *      speed - current link speed in Mbps
    306  * Returns:     
    307  *      SOC_E_XXX
    308  */
    309 STATIC int
    310 phy82109_speed_get(int unit, soc_port_t port, int *speed)
    311 {
    312     phy_ctrl_t               *int_pc;
    313     int int_speed;
    314     
    315     /* locate phy control */
    316     int_pc = INT_PHY_SW_STATE(unit, port);
    317     if (int_pc == NULL) {
    318         return SOC_E_INTERNAL;
    319     }
    320     SOC_IF_ERROR_RETURN
    321         (PHY_SPEED_GET(int_pc->pd, unit, port, &int_speed));
    322     *speed = int_speed;
    323     return (SOC_E_NONE);
    324 
    325 }
    326 
    327 /*
    328  * Function:
    329  *      phy82109_interface_set
    330  * Purpose:
    331  *      Set PHY interface type
    332  * Parameters:
    333  *      unit - BCM unit number.
    334  *      port - Port number. 
    335  *      interface -  soc interface type
    336  * Returns:     
    337  *      SOC_E_XXX
    338  */
    339 
    340 
    341 STATIC int
    342 phy82109_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
    343 {
    344     phy_ctrl_t      *int_pc;
    345     int_pc = INT_PHY_SW_STATE(unit,port);
    346     if (int_pc == NULL) {
    347         return SOC_E_INTERNAL;
    348     }
    349     if (pif >= SOC_PORT_IF_COUNT) {
    350         return SOC_E_PARAM;
    351     }
    352     if (pif == SOC_PORT_IF_MII || pif == SOC_PORT_IF_XGMII || pif == SOC_PORT_IF_GMII) {
    353 		return phy_null_interface_set(unit, port, pif);
    354 	}
    355     SOC_IF_ERROR_RETURN
    356         (PHY_INTERFACE_SET(int_pc->pd,unit,port,pif));
    357     return SOC_E_NONE;
    358 }
    359 
    360 /*
    361  * Function:
    362  *      phy82109_interface_get
    363  * Purpose:
    364  *      Get PHY interface type
    365  * Parameters:
    366  *      unit - BCM unit number.
    367  *      port - Port number. 
    368  *      pif - (OUT) interface type
    369  * Returns:     
    370  *      SOC_E_XXX
    371  */
    372 
    373 STATIC int
    374 phy82109_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
    375 {
    376     phy_ctrl_t                *int_pc;
    377     /* locate phy control */
    378     int_pc = INT_PHY_SW_STATE(unit,port);
    379     if (int_pc == NULL) {
    380         return SOC_E_INTERNAL;
    381     }
    382     SOC_IF_ERROR_RETURN
    383         (PHY_INTERFACE_GET(int_pc->pd,unit,port,pif));
    384     return (SOC_E_NONE);
    385 
    386 }
    387 
    388 /*
    389  * Function:
    390  *      phy82109_reg_read
    391  * Purpose:
    392  *      Routine to read PHY register
    393  * Parameters:
    394  *      unit         - BCM unit number
    395  *      port         - Port number
    396  *      flags        - Flags which specify the register type
    397  *      phy_reg_addr - Encoded register address
    398  *      phy_data     - (OUT) Value read from PHY register
    399  * Returns:
    400  *          SOC_E_XXX
    401  * Note:
    402  *      This register read function is not thread safe. Higher level
    403  * function that calls this function must obtain a per port lock
    404  * to avoid overriding register page mapping between threads.
    405  */
    406 STATIC int
    407 phy82109_reg_read(int unit, soc_port_t port, uint32 flags,
    408                   uint32 phy_reg_addr, uint32 *phy_reg_data)
    409 {
    410     phy_ctrl_t *pc;
    411     soc_phymod_ctrl_t *pmc;
    412     phymod_phy_access_t *pm_phy;
    413     int idx = 0;
    414 
    415     pc = EXT_PHY_SW_STATE(unit, port);
    416     if (pc == NULL) {
    417         return SOC_E_INTERNAL;
    418     }
    419 
    420     pmc = &pc->phymod_ctrl;
    421     idx = pmc->main_phy ;
    422     pm_phy = &pmc->phy[idx]->pm_phy;
    423     
    424     SOC_IF_ERROR_RETURN
    425         (phymod_phy_reg_read(pm_phy, phy_reg_addr, phy_reg_data));
    426     return SOC_E_NONE;
    427 }
    428 
    429 /*
    430  * Function:
    431  *      phy82109_reg_write
    432  * Purpose:
    433  *      Routine to write PHY register
    434  * Parameters:
    435  *      uint         - BCM unit number
    436  *      pc           - PHY state
    437  *      flags        - Flags which specify the register type
    438  *      phy_reg_addr - Encoded register address
    439  *      phy_data     - Value write to PHY register
    440  * Returns:
    441  *          SOC_E_XXX
    442  * Note:
    443  *      This register read function is not thread safe. Higher level
    444  * function that calls this function must obtain a per port lock
    445  * to avoid overriding register page mapping between threads.
    446  */
    447 STATIC int
    448 phy82109_reg_write(int unit, soc_port_t port, uint32 flags,
    449                    uint32 phy_reg_addr, uint32 phy_reg_data)
    450 {
    451     phy_ctrl_t *pc;
    452     soc_phymod_ctrl_t *pmc;
    453     phymod_phy_access_t *pm_phy;
    454     int idx;
    455     pc = EXT_PHY_SW_STATE(unit, port);
    456     if (pc == NULL) {
    457         return SOC_E_INTERNAL;
    458     }
    459 
    460     pmc = &pc->phymod_ctrl;
    461     for (idx = 0; idx < pmc->num_phys; idx++) {
    462         pm_phy = &pmc->phy[idx]->pm_phy;
    463         SOC_IF_ERROR_RETURN
    464             (phymod_phy_reg_write(pm_phy, phy_reg_addr, phy_reg_data));
    465     }
    466     return SOC_E_NONE;
    467 }
    468 
    469 /*
    470  * Function:
    471  *      phy82109_reg_modify
    472  * Purpose:
    473  *      Routine to write PHY register
    474  * Parameters:
    475  *      uint         - BCM unit number
    476  *      pc           - PHY state
    477  *      flags        - Flags which specify the register type
    478  *      phy_reg_addr - Encoded register address
    479  *      phy_mo_data  - New value for the bits specified in phy_mo_mask
    480  *      phy_mo_mask  - Bit mask to modify
    481  * Returns:
    482  *          SOC_E_XXX
    483  * Note:
    484  *      This function is not thread safe. Higher level
    485  * function that calls this function must obtain a per port lock
    486  * to avoid overriding register page mapping between threads.
    487  */
    488 STATIC int
    489 phy82109_reg_modify(int unit, soc_port_t port, uint32 flags,
    490                     uint32 phy_reg_addr, uint32 phy_data,
    491                     uint32 phy_data_mask)
    492 {
    493     phy_ctrl_t *pc;
    494     soc_phymod_ctrl_t *pmc;
    495     phymod_phy_access_t *pm_phy;
    496     uint32 data32, tmp;
    497     int idx;
    498 
    499     pc = EXT_PHY_SW_STATE(unit, port);
    500     if (pc == NULL) {
    501         return SOC_E_INTERNAL;
    502     }
    503 
    504     pmc = &pc->phymod_ctrl;
    505     for (idx = 0; idx < pmc->num_phys; idx++) {
    506         pm_phy = &pmc->phy[idx]->pm_phy;
    507         SOC_IF_ERROR_RETURN
    508             (phymod_phy_reg_read(pm_phy, phy_reg_addr, &data32));
    509         tmp = data32;
    510         data32 &= ~(phy_data_mask);
    511         data32 |= (phy_data & phy_data_mask);
    512         if (data32 != tmp) {
    513             SOC_IF_ERROR_RETURN
    514                 (phymod_phy_reg_write(pm_phy, phy_reg_addr, data32));
    515         }
    516     }
    517     return SOC_E_NONE;
    518 }
    519 
    520 /*
    521  * Function:
    522  *      phy82109_core_init
    523  * Purpose:
    524  *         initializes phy mode core object
    525  * Parameters:
    526  *      pc - pointer to phy control structure
    527  *      core - pointer to soc phy mode core object
    528  *      core_bus - pointer to phy mode bus driver struct
    529  *      core_addr - address of the phy mode core
    530  * Returns:
    531  *          none
    532  */  
    533 STATIC void
    534 phy82109_core_init(phy_ctrl_t *pc, soc_phymod_core_t *core,
    535                    phymod_bus_t *core_bus, uint32 core_addr)
    536 {
    537     phymod_core_access_t *pm_core;
    538     phymod_access_t *pm_acc;
    539 
    540     core->unit = pc->unit;
    541     core->port = pc->port;
    542     core->read = pc->read;
    543     core->write = pc->write;
    544     core->wrmask = pc->wrmask;
    545 
    546     pm_core = &core->pm_core;
    547     phymod_core_access_t_init(pm_core);
    548     pm_acc = &pm_core->access;
    549     phymod_access_t_init(pm_acc);
    550     PHYMOD_ACC_USER_ACC(pm_acc) = core;
    551     PHYMOD_ACC_BUS(pm_acc) = core_bus;
    552     PHYMOD_ACC_ADDR(pm_acc) = core_addr;
    553 
    554     if (soc_property_port_get(pc->unit, pc->port, "phy82109", 0) == 45) {
    555         PHYMOD_ACC_F_CLAUSE45_SET(pm_acc);
    556     }
    557 
    558     return;
    559 }
    560 /*
    561  * Function:
    562  *      phy82109_cleanup
    563  * Purpose:
    564  *         clean up phy device and phy mode core object
    565  * Parameters:
    566  *      pmc - pointer to soc phy mode control structure 
    567  * Returns:
    568  *          SOC_E_XXX
    569  */  
    570 STATIC void
    571 phy82109_cleanup(soc_phymod_ctrl_t *pmc)
    572 {
    573     int idx;
    574     soc_phymod_phy_t *phy;
    575     soc_phymod_core_t *core;
    576     for (idx = 0; idx < pmc->num_phys ; idx++) {
    577         phy = pmc->phy[idx];
    578         if (phy == NULL) {
    579             LOG_WARN(BSL_LS_SOC_PHY,
    580                      (BSL_META_U(pmc->unit,
    581                                  "phy object is empty")));
    582             continue;
    583         }
    584 
    585         core = phy->core;
    586         /* Destroy core object if not used anymore */
    587         if (core && core->ref_cnt) {
    588             if (--core->ref_cnt == 0) {
    589                 PHYMOD_VDBG(PHY82109_DBG_MEM, NULL,("clean_up core_p=%p\n", (void *)core)) ;
    590                 
    591                 soc_phymod_core_destroy(pmc->unit, core);
    592             }
    593         }
    594 
    595         /* Destroy phy object */
    596         if (phy) {
    597             PHYMOD_VDBG(PHY82109_DBG_MEM, NULL,("clean_up phy=%p\n", (void *)phy)) ;
    598             soc_phymod_phy_destroy(pmc->unit, phy);
    599         }
    600     }
    601     pmc->num_phys = 0;
    602 }
    603 
    604 /*
    605  * Function:
    606  *      _phy82109_chip_id_get
    607  * Purpose:
    608  *         read phy chip id
    609  * Parameters:
    610  *      pm_phy - pointer to phy mode phy structure 
    611  *      unit   -  switch unit number 
    612  *      chip_id -    (OUT) chip id after read
    613  * Returns:
    614  *          SOC_E_XXX
    615  */  
    616 STATIC int32
    617 _phy_82109_chip_id_get(phymod_phy_access_t *pm_phy, uint32 *chip_id)
    618 {
    619     uint32 chip_id_msb = 0, chip_id_lsb = 0;
    620 
    621     chip_id_msb = (chip_id_msb & 0xF000) >> 12;
    622  
    623     SOC_IF_ERROR_RETURN(
    624        phymod_phy_reg_read(pm_phy, 0x8000, &chip_id_lsb));
    625 
    626     if (chip_id_msb == 0x0) {
    627         if (chip_id_lsb == 0x2109) {
    628             *chip_id = 0x82109;
    629         } 
    630     } else {
    631         LOG_WARN(BSL_LS_SOC_PHY, (BSL_META_U(0,
    632                  "Chip ID not found for \n")));
    633         return SOC_E_NOT_FOUND;
    634     }
    635 
    636     return SOC_E_NONE;
    637 }
    638 
    639 /*
    640  * Function:
    641  *      phy82109_probe
    642  * Purpose:
    643  *      xx
    644  * Parameters:
    645  *      pc->phy_id   (IN)
    646  *      pc->unit     (IN)
    647  *      pc->port     (IN)
    648  *      pc->size     (OUT) - memory required by phy port
    649  *      pc->dev_name (OUT) - set to port device name
    650  * Returns:
    651  *          SOC_E_XXX
    652  *  
    653  * Note:
    654  */
    655 STATIC int
    656 phy82109_probe(int unit, phy_ctrl_t *pc)
    657 {
    658     int rv, idx;
    659     uint32 lane_map, num_phys, core_id, phy_id, found;
    660     phymod_bus_t core_bus;
    661     phymod_dispatch_type_t phy_type;
    662     phymod_core_access_t *pm_core;
    663     phymod_phy_access_t *pm_phy;
    664     phymod_access_t *pm_acc;
    665     soc_phymod_ctrl_t *pmc;
    666     soc_phymod_phy_t *phy;
    667     soc_phymod_core_t *core;
    668     soc_phymod_core_t core_probe;
    669     soc_info_t *si;
    670     phyident_core_info_t core_info[8];  
    671     int array_max = 8;
    672     int array_size = 0;
    673     int port;
    674     int phy_port;  /* physical port number */
    675     uint16 chip_id = 0;
    676     /* Initialize PHY bus */
    677     SOC_IF_ERROR_RETURN(phymod_bus_t_init(&core_bus));
    678     core_bus.bus_name = "phy82109"; 
    679     core_bus.read = _phy82109_reg_read; 
    680     core_bus.write = _phy82109_reg_write;
    681 
    682     /* Configure PHY bus properties */
    683     if (pc->wrmask) {
    684         PHYMOD_BUS_CAP_WR_MODIFY_SET(&core_bus);
    685         PHYMOD_BUS_CAP_LANE_CTRL_SET(&core_bus);
    686     }
    687 
    688     LOG_WARN(BSL_LS_SOC_PHY,
    689          (BSL_META_U(unit,
    690                      "port %d: probe  82109  enter !!\n"),
    691           pc->port));
    692 
    693     port = pc->port;
    694     pmc = &pc->phymod_ctrl;
    695     si = &SOC_INFO(unit);
    696     if (soc_feature(unit, soc_feature_logical_port_num)) {
    697         phy_port = si->port_l2p_mapping[port];
    698     } else {
    699         phy_port = port;
    700     }
    701     /* Install clean up function */
    702     pmc->unit = pc->unit;
    703     pmc->cleanup = phy82109_cleanup;
    704     /*pmc->symbols = &bcmi_tscf_xgxs_symbols;*/ 
    705     
    706     pc->lane_num = SOC_PORT_BINDEX(unit, phy_port);
    707     pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port));
    708 
    709     /* request memory for the configuration structure */
    710     pc->size = sizeof(phy82109_config_t);
    711     /* Read the lane_mask config variable */
    712     PORT_PHY_LANE_MASK(pc) = soc_property_port_get(unit, port, spn_PORT_PHY_LANE_MASK, 0);
    713 
    714     /* Bit N corresponds to lane N in lane_map */
    715     lane_map = 0xf;
    716     num_phys = 1;
    717     switch (si->port_num_lanes[port]) {
    718         case 10:
    719             pc->phy_mode = PHYCTRL_MULTI_CORE_PORT; 
    720             break;
    721         case 4:
    722             pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 
    723             break;
    724         case 2:
    725             lane_map = 0x3;
    726             pc->phy_mode = PHYCTRL_DUAL_LANE_PORT;
    727             break;
    728         case 1:
    729         case 0:
    730             lane_map = 0x1;
    731             pc->phy_mode = PHYCTRL_ONE_LANE_PORT;
    732             break;
    733         default:
    734             return SOC_E_CONFIG;
    735     }
    736     SOC_IF_ERROR_RETURN(
    737         READ_PHY_REG(unit, pc,0x18000 ,&chip_id));
    738 
    739     if (!PORT_PHY_LANE_MASK(pc)) {
    740         if (chip_id == 0x2109) {
    741             lane_map <<= (pc->lane_num | (4 * (pc->chip_num%2)));
    742         } else {
    743             lane_map <<= pc->lane_num;
    744         }
    745     } else {
    746         lane_map = PORT_PHY_LANE_MASK(pc);
    747     }
    748     /* we need to get the other core id if more than 1 core per port */
    749     if (num_phys > 1) {
    750         /* get the other core address */
    751         SOC_IF_ERROR_RETURN
    752         /*
    753          * COVERITY
    754          * This is unreachable. It is kept intentionally as a defensive 
    755          * default for future development.
    756          */
    757         /* coverity[dead_error_begin] */
    758             (soc_phy_addr_multi_get(unit, port, array_max, &array_size, &core_info[0]));
    759     } else {
    760         core_info[0].mdio_addr = pc->phy_id;
    761     }
    762 
    763     phy_type = phymodDispatchTypeHuracan;
    764 
    765     /* Probe cores */
    766     for (idx = 0; idx < num_phys ; idx++) {
    767         phy82109_core_init(pc, &core_probe, &core_bus,
    768                            core_info[idx].mdio_addr);
    769         /* Check that core is indeed an Huracan core */
    770         pm_core = &core_probe.pm_core;
    771         pm_core->type = phy_type;
    772         rv = phymod_core_identify(pm_core, 0, &found);
    773         if (SOC_FAILURE(rv)) {
    774             LOG_WARN(BSL_LS_SOC_PHY,
    775                  (BSL_META_U(unit,
    776                              "port %d: ERROR!!!\n"),
    777                   pc->port));
    778 
    779             return rv;
    780         }
    781         if (!found) {
    782             LOG_WARN(BSL_LS_SOC_PHY,
    783                  (BSL_META_U(unit,
    784                              "port %d: NOT FOUND!!\n"),
    785                   pc->port));
    786 
    787             return SOC_E_NOT_FOUND;
    788         }
    789     }
    790 
    791     rv = SOC_E_NONE;
    792     for (idx = 0; idx < num_phys ; idx++) {
    793         /* Set core and phy IDs based on PHY address */
    794         core_id = pc->phy_id + idx;
    795         phy_id = (lane_map << 16) | core_id;
    796         /* Create PHY object */
    797         rv = soc_phymod_phy_create(unit, phy_id, &pmc->phy[idx]);
    798         if (SOC_FAILURE(rv)) {
    799             break;
    800         }
    801         pmc->num_phys++;
    802 
    803         /* Initialize phy object */
    804         phy = pmc->phy[idx];
    805         pm_phy = &phy->pm_phy;
    806         phymod_phy_access_t_init(pm_phy);
    807 
    808         /* Find or create associated core object */
    809         rv = soc_phymod_core_find_by_id(unit, core_id, &phy->core);
    810         if (rv == SOC_E_NOT_FOUND) {
    811             rv = soc_phymod_core_create(unit, core_id, &phy->core);
    812         }
    813         if (SOC_FAILURE(rv)) {
    814             break;
    815         }        
    816     }
    817     if (SOC_FAILURE(rv)) {
    818         phy82109_cleanup(pmc);
    819         return rv;
    820     }
    821 
    822     for (idx = 0; idx < num_phys ; idx++) {
    823         phy = pmc->phy[idx];
    824         core = phy->core;
    825         pm_core = &core->pm_core;
    826 
    827         /* Initialize core object if newly created */
    828         if (core->ref_cnt == 0) {
    829             sal_memcpy(&core->pm_bus, &core_bus, sizeof(core->pm_bus));
    830             phy82109_core_init(pc, core, &core->pm_bus,
    831                                core_info[idx].mdio_addr);
    832             /* Set dispatch type */
    833             pm_core->type = phy_type;
    834         }
    835         core->port = pc->port;  
    836         core->ref_cnt++;        
    837 
    838         /* Initialize phy access based on associated core */
    839         pm_acc = &phy->pm_phy.access;
    840         sal_memcpy(pm_acc, &pm_core->access, sizeof(*pm_acc));
    841         phy->pm_phy.type = phy_type;
    842         PHYMOD_ACC_LANE_MASK(pm_acc) = lane_map;
    843     }
    844 
    845     return SOC_E_NONE;
    846 }
    847 
    848 
    849 /*
    850  * Function:
    851  *      phy82109_config_init
    852  * Purpose:     
    853  *      Determine phy configuration data for purposes of PHYMOD initialization.
    854  * 
    855  *      A side effect of this procedure is to save some per-logical port
    856  *      information in (phy82109_cfg_t *) &pc->driver_data;
    857  *
    858  * Parameters:
    859  *      unit                  - BCM unit number.
    860  *      port                  - Port number.
    861  *      logical_lane_offset   - starting logical lane number
    862  * Returns:     
    863  *      SOC_E_XXX
    864  */
    865 STATIC int
    866 phy82109_config_init(int unit, soc_port_t port, int logical_lane_offset,
    867                  phymod_core_init_config_t *core_init_config, 
    868                  phymod_phy_init_config_t  *pm_phy_init_config)
    869 {
    870     phy_ctrl_t *pc;
    871     phy82109_speed_config_t *speed_config;
    872     phy82109_config_t *pCfg;
    873     int port_num_lanes;
    874     int core_num;
    875     int phy_num_lanes;
    876 
    877     pc = EXT_PHY_SW_STATE(unit, port);
    878     if (pc == NULL) {
    879         return SOC_E_INTERNAL;
    880     }
    881     pCfg = (phy82109_config_t *) pc->driver_data;
    882 
    883     port_num_lanes = SOC_INFO(unit).port_num_lanes[port];
    884 
    885     /* figure out how many lanes are in this phy */
    886     core_num = (logical_lane_offset / 4);
    887     phy_num_lanes = (port_num_lanes - logical_lane_offset);
    888     if (phy_num_lanes > MAX_NUM_LANES) {
    889        phy_num_lanes = MAX_NUM_LANES;
    890     }
    891     
    892     SIMPLEX_TX(pc) = soc_property_port_get(unit, port, spn_PORT_PHY_MODE_REVERSE, 0);
    893     /*CORE configuration*/
    894     phymod_core_init_config_t_init(core_init_config);
    895     core_init_config->firmware_load_method  = phymodFirmwareLoadMethodNone;
    896     core_init_config->lane_map.num_of_lanes = NUM_LANES;
    897     core_init_config->flags = PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY;
    898 
    899     speed_config = &(pCfg->speed_config);
    900     speed_config->port_refclk_int  = 156;
    901     speed_config->port_num_lanes   = phy_num_lanes;
    902     if (port_num_lanes == 1) {
    903         if (pc->speed_max == PHY82109_SPD_25G) {
    904             speed_config->line_interface =  SOC_PORT_IF_LR;
    905             speed_config->speed = PHY82109_SPD_25G;
    906         } else {
    907             speed_config->line_interface =  SOC_PORT_IF_SR;
    908             speed_config->speed = PHY82109_SPD_10G;
    909         }
    910     } else if (port_num_lanes == 4) {
    911         if (pc->speed_max == PHY82109_SPD_40G) {
    912            speed_config->speed = PHY82109_SPD_40G;
    913            speed_config->line_interface =  SOC_PORT_IF_SR4;
    914         } else {
    915            speed_config->speed = PHY82109_SPD_100G;
    916            speed_config->line_interface =  SOC_PORT_IF_LR4;
    917         }
    918     } else if (port_num_lanes == 2) {
    919         if (pc->speed_max == PHY82109_SPD_50G) {
    920             speed_config->speed = PHY82109_SPD_50G;
    921             speed_config->line_interface =  SOC_PORT_IF_KR2;
    922         } else {
    923             speed_config->speed = PHY82109_SPD_20G;
    924             speed_config->line_interface =  SOC_PORT_IF_LR;
    925         }
    926     } else {
    927         LOG_CLI((BSL_META_U(unit,"Invalid number of lanes:%d\n "), port_num_lanes));
    928         return SOC_E_CONFIG;
    929     }
    930         LOG_CLI((BSL_META_U(unit,"number of lanes:%d\n "), port_num_lanes));
    931 
    932     /* PHY configuration */
    933     phymod_phy_init_config_t_init(pm_phy_init_config);
    934 
    935     pm_phy_init_config->polarity.rx_polarity 
    936                                  = soc_property_port_get(unit, port,
    937                                    spn_PHY_RX_POLARITY_FLIP,
    938                                    0xFFFF);
    939     pm_phy_init_config->polarity.tx_polarity 
    940                                  = soc_property_port_get(unit, port,
    941                                    spn_PHY_TX_POLARITY_FLIP,
    942                                    0xFFFF);
    943 
    944      /* Only do this once, for the first core of the logical port*/
    945     if (core_num == 0) {
    946         /* phy_mode, PHYCTRL_MDIO_ADDR_SHARE, PHY_FLAGS_INDEPENDENT_LANE */
    947         if (port_num_lanes == 4) {
    948             pc->phy_mode = PHYCTRL_QUAD_LANE_PORT;
    949             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_INDEPENDENT_LANE);
    950         } else if (port_num_lanes == 2) {
    951             pc->phy_mode = PHYCTRL_DUAL_LANE_PORT;
    952             pc->flags |= PHYCTRL_MDIO_ADDR_SHARE;
    953             PHY_FLAGS_SET(unit, port, PHY_FLAGS_INDEPENDENT_LANE);
    954         } else if (port_num_lanes == 1) {
    955             pc->phy_mode = PHYCTRL_ONE_LANE_PORT;
    956             pc->flags |= PHYCTRL_MDIO_ADDR_SHARE;
    957             PHY_FLAGS_SET(unit, port, PHY_FLAGS_INDEPENDENT_LANE);
    958         }
    959 
    960     }
    961         
    962     return SOC_E_NONE;
    963 }
    964 
    965 /*
    966  * Function:
    967  *      _phy82109_init_pass1
    968  * Purpose:     
    969  *      pass1 of multipass phy initialization.
    970  * 
    971  * Parameters:
    972  *      unit                  - BCM unit number.
    973  *      port                  - Port number.
    974  * Returns:     
    975  *      SOC_E_XXX
    976  */      
    977 STATIC int
    978 _phy_82109_init_pass1(int unit, soc_port_t port)
    979 {
    980     phy_ctrl_t *pc; 
    981     soc_phymod_ctrl_t *pmc;
    982     soc_phymod_phy_t *phy = NULL;
    983     soc_phymod_core_t *core;
    984     phy82109_config_t *pCfg;
    985     phymod_phy_inf_config_t interface_config;
    986     phymod_core_status_t core_status;
    987     phymod_core_info_t core_info;
    988     int idx;
    989     int logical_lane_offset;
    990     soc_port_ability_t ability;
    991     soc_phy_info_t *pi;
    992     char *dev_name;
    993     int len = 0;
    994     uint32 chip_id = 0;
    995 
    996     pc = EXT_PHY_SW_STATE(unit, port);
    997 
    998     if (pc == NULL) {
    999         return SOC_E_INTERNAL;
   1000     }
   1001 
   1002     pc->driver_data = (void*)(pc+1);
   1003     pmc = &pc->phymod_ctrl;
   1004     pCfg = (phy82109_config_t *) pc->driver_data;
   1005     
   1006     sal_memset(pCfg, 0, sizeof(*pCfg));
   1007 
   1008     sal_memset(&ability, 0, sizeof(ability));
   1009     sal_memset(&interface_config, 0, sizeof(interface_config));
   1010 
   1011     dev_name = DEV_NAME(pc);
   1012     phy = pmc->phy[0];
   1013 
   1014     SOC_IF_ERROR_RETURN(
   1015          _phy_82109_chip_id_get(&phy->pm_phy, &chip_id));
   1016     DEVID(pc) = chip_id;
   1017 
   1018     pi = &SOC_PHY_INFO(unit, port);
   1019     if (DEVID(pc) == HURACAN_ID_82109) { 
   1020         /* coverity[secure_coding] */
   1021         sal_strncpy (dev_name, "BCM82109", sal_strlen("BCM82109"));
   1022     } else {
   1023         /* coverity[secure_coding] */
   1024         sal_strncpy (dev_name, "Huracan", sal_strlen("Huracan"));
   1025     }
   1026     
   1027     len = sal_strlen(dev_name);
   1028 
   1029     dev_name[len++] = '/';
   1030     dev_name[len++] = pc->lane_num + '0';
   1031     dev_name[len] = 0;
   1032     pc->dev_name = dev_name;  /* string terminator */
   1033     pi->phy_name = dev_name;
   1034 
   1035     /* Loop through all phymod phys that support this SDK phy */
   1036     logical_lane_offset = 0;
   1037     for (idx = 0; idx < pmc->num_phys; idx++) {
   1038         phy = pmc->phy[idx];
   1039         core = phy->core;
   1040         /* determine configuration data structure to default values, based on SOC properties */
   1041         SOC_IF_ERROR_RETURN
   1042             (phy82109_config_init(unit, port,
   1043                               logical_lane_offset,
   1044                               &core->init_config, &phy->init_config));
   1045         /* set the port to its max or init_speed */
   1046         interface_config.interface_type = phymodInterfaceXFI;
   1047         interface_config.ref_clock = phymodRefClk106Mhz;
   1048         sal_memcpy(&core->init_config.interface, &interface_config, sizeof(interface_config));
   1049         
   1050         if (!core->init) {
   1051            core_status.pmd_active = 0;
   1052            SOC_IF_ERROR_RETURN
   1053                (phymod_core_init(&core->pm_core, &core->init_config, &core_status));
   1054            core->init = TRUE;
   1055         }
   1056         
   1057         /*phy->init_config.an_link_qualifier*/
   1058         SOC_IF_ERROR_RETURN
   1059             (phymod_phy_init(&phy->pm_phy, &phy->init_config));
   1060        
   1061         /*read serdes id info */
   1062         SOC_IF_ERROR_RETURN
   1063             (phymod_core_info_get(&core->pm_core, &core_info)); 
   1064 
   1065         /* for multicore phys, need to ratchet up to the next batch of lanes */
   1066         logical_lane_offset += core->init_config.lane_map.num_of_lanes;
   1067     }
   1068 	/* indicate second pass of init is needed */
   1069     PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2);
   1070 
   1071     return SOC_E_NONE;
   1072 }
   1073 /*
   1074  * Function:
   1075  *      _phy82109_init_pass2
   1076  * Purpose:     
   1077  *      pass2 of multipass phy initialization.
   1078  * 
   1079  * Parameters:
   1080  *      unit                  - BCM unit number.
   1081  *      port                  - Port number.
   1082  * Returns:     
   1083  *      SOC_E_XXX
   1084  */      
   1085 STATIC int
   1086 _phy_82109_init_pass2(int unit, soc_port_t port)
   1087 {
   1088     phy_ctrl_t *pc; 
   1089     soc_phymod_ctrl_t *pmc;
   1090     soc_phymod_phy_t *phy = NULL;
   1091     phymod_phy_inf_config_t interface_config;
   1092     soc_port_ability_t ability;
   1093 
   1094     pc = EXT_PHY_SW_STATE(unit, port);
   1095 
   1096     if (pc == NULL) {
   1097         return SOC_E_INTERNAL;
   1098     }
   1099 
   1100     sal_memset(&interface_config, 0, sizeof(interface_config));
   1101     sal_memset(&ability, 0, sizeof(ability));
   1102     pc->driver_data = (void*)(pc+1);
   1103     pmc = &pc->phymod_ctrl;
   1104     phy = pmc->phy[0];
   1105     
   1106     /*
   1107      * even though huracan does not has any interface type
   1108      * phymod layer expects a valid interface config, without
   1109      * which core initialization can not happen, so 
   1110      * initializing interface type with valid values for 
   1111      * phymod. Huracan does not make use of this interface
   1112      * settings.
   1113      */
   1114     
   1115     interface_config.interface_type = phymodInterfaceXFI;
   1116     interface_config.ref_clock = phymodRefClk106Mhz;
   1117     SOC_IF_ERROR_RETURN
   1118         (phymod_phy_interface_config_set(&phy->pm_phy,
   1119                              0 /* flags */, &interface_config));
   1120     /* setup the port's an cap */
   1121     SOC_IF_ERROR_RETURN
   1122         (phy_82109_ability_local_get(unit, port, &ability));
   1123 
   1124     LOG_INFO(BSL_LS_SOC_PHY,
   1125              (BSL_META_U(pc->unit,
   1126                          "phy82109_init_pass2: u=%d p=%d\n"), unit, port));
   1127 
   1128     if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) {
   1129         /* indicate third  pass of init is needed */
   1130         PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS3);
   1131     }
   1132 
   1133     return SOC_E_NONE;
   1134 }
   1135 
   1136 /*
   1137  * Function:
   1138  *      _phy82109_init_pass3
   1139  * Purpose:     
   1140  *      pass3 of multipass phy initialization.
   1141  * 
   1142  * Parameters:
   1143  *      unit                  - BCM unit number.
   1144  *      port                  - Port number.
   1145  * Returns:     
   1146  *      SOC_E_XXX
   1147  */      
   1148 STATIC int
   1149 _phy_82109_init_pass3(int unit, soc_port_t port)
   1150 {
   1151     phy_ctrl_t *pc; 
   1152     pc = EXT_PHY_SW_STATE(unit, port);
   1153 
   1154     if (pc == NULL) {
   1155         return SOC_E_INTERNAL;
   1156     }
   1157 	return SOC_E_NONE;
   1158 }
   1159 
   1160 /*
   1161  * Function:
   1162  *      phy82109_init
   1163  *  
   1164  *      An SDK "phy" is a logical port, which can consist of from 1-10 lanes,
   1165  *          (A phy with more than 4 lanes requires more than one core).
   1166  *      Per-logical port information is saved in &pc->driver_data.
   1167  *      An SDK phy is implemented as one or more PHYMOD "phy"s.
   1168  *  
   1169  *      A PHYMOD "phy" resides completely within a single core, which can be
   1170  *      from 1 to 4 lanes.
   1171  *      Per-phymod phy information is kept in (soc_phymod_ctrl_t) *pc->phymod_ctrl
   1172  *      A phymod phy points to its core.  Up to 4 phymod phys can be on a single core
   1173  *  
   1174  * Purpose:     
   1175  *      Initialize a phy82109
   1176  * Parameters:
   1177  *      unit - BCM unit number.
   1178  *      port - Port number. 
   1179  * Returns:     
   1180  *      SOC_E_XXX
   1181  */
   1182 STATIC int
   1183 phy_82109_init(int unit, soc_port_t port)
   1184 {
   1185     phy_ctrl_t *pc; 
   1186 
   1187     pc = EXT_PHY_SW_STATE(unit, port);
   1188     if (pc == NULL) {
   1189         return SOC_E_INTERNAL;
   1190     }
   1191     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) ||
   1192         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1193         
   1194         PHY_FLAGS_SET(unit, port,  PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER);
   1195         SOC_IF_ERROR_RETURN(_phy_82109_init_pass1(unit, port));
   1196 
   1197         if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) {
   1198             return SOC_E_NONE;
   1199         }
   1200     }
   1201     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) ||
   1202         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1203 
   1204         SOC_IF_ERROR_RETURN( _phy_82109_init_pass2(unit, port));
   1205 
   1206         LOG_INFO(BSL_LS_SOC_PHY,
   1207                  (BSL_META_U(unit,
   1208                              "82109 init pass2 completed: u=%d p=%d\n"), unit, port));
   1209         if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) {
   1210             return SOC_E_NONE;
   1211         }
   1212     }
   1213 
   1214     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS3) ||
   1215         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1216 
   1217         SOC_IF_ERROR_RETURN(_phy_82109_init_pass3(unit, port));
   1218 
   1219         LOG_INFO(BSL_LS_SOC_PHY,
   1220                  (BSL_META_U(unit,
   1221                              "PHY82109 init pass3 completed: u=%d p=%d\n"), unit, port));
   1222         PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_DEFAULT);
   1223         return SOC_E_NONE;
   1224     }
   1225     return SOC_E_NONE;
   1226 }
   1227 
   1228 /*
   1229  * Function:
   1230  *      phy_82109_ability_local_get
   1231  * Purpose:
   1232  *         returns soc local port ability
   1233  * Parameters:
   1234  *      unit - BCM unit number.
   1235  *      port - Port number. 
   1236  *      ability - (OUT) soc port ability structure
   1237  * Returns:     
   1238  *      SOC_E_XXX
   1239  */
   1240 STATIC int
   1241 phy_82109_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1242 {
   1243     phy_ctrl_t          *pc; 
   1244     uint32_t pa_speed = 0;
   1245 
   1246     pc = EXT_PHY_SW_STATE(unit, port);
   1247 
   1248     if (NULL == ability) {
   1249         return SOC_E_PARAM;
   1250     }
   1251 
   1252     sal_memset(ability, 0, sizeof(*ability));
   1253     if (pc->speed_max == PHY82109_SPD_100G) {
   1254         pa_speed = SOC_PA_SPEED_100GB | SOC_PA_SPEED_40GB | SOC_PA_SPEED_20GB
   1255             | SOC_PA_SPEED_25GB | SOC_PA_SPEED_50GB | SOC_PA_SPEED_10GB 
   1256             | SOC_PA_SPEED_6000MB | SOC_PA_SPEED_1000MB;
   1257     } else if (pc->speed_max == PHY82109_SPD_50G) {
   1258         pa_speed = SOC_PA_SPEED_50GB | SOC_PA_SPEED_40GB | SOC_PA_SPEED_20GB
   1259             | SOC_PA_SPEED_25GB | SOC_PA_SPEED_10GB | SOC_PA_SPEED_6000MB | SOC_PA_SPEED_1000MB;
   1260     } else if (pc->speed_max == PHY82109_SPD_40G) {
   1261         pa_speed = SOC_PA_SPEED_40GB | SOC_PA_SPEED_20GB
   1262             | SOC_PA_SPEED_25GB | SOC_PA_SPEED_10GB | SOC_PA_SPEED_6000MB | 
   1263             SOC_PA_SPEED_1000MB;
   1264     } else if (pc->speed_max == PHY82109_SPD_25G) {
   1265         pa_speed = SOC_PA_SPEED_20GB | SOC_PA_SPEED_6000MB | SOC_PA_SPEED_1000MB
   1266             | SOC_PA_SPEED_25GB | SOC_PA_SPEED_10GB;
   1267     } else if (pc->speed_max == PHY82109_SPD_20G) {
   1268         pa_speed = SOC_PA_SPEED_20GB | SOC_PA_SPEED_10GB | SOC_PA_SPEED_6000MB | SOC_PA_SPEED_1000MB;
   1269     } else if (pc->speed_max == PHY82109_SPD_10G) {
   1270         pa_speed = SOC_PA_SPEED_10GB | SOC_PA_SPEED_6000MB | SOC_PA_SPEED_1000MB;
   1271     } else {
   1272         pa_speed = SOC_PA_SPEED_100GB | SOC_PA_SPEED_40GB | SOC_PA_SPEED_20GB
   1273             | SOC_PA_SPEED_25GB | SOC_PA_SPEED_50GB | SOC_PA_SPEED_10GB 
   1274             | SOC_PA_SPEED_6000MB | SOC_PA_SPEED_1000MB;
   1275     }
   1276 
   1277     ability->loopback  = SOC_PA_LB_PHY;
   1278     ability->medium    = SOC_PA_MEDIUM_COPPER;
   1279     ability->pause     = 0;
   1280     ability->flags     = SOC_PA_AUTONEG;
   1281     ability->speed_full_duplex = pa_speed;
   1282 
   1283 
   1284     LOG_INFO(BSL_LS_SOC_PHY,
   1285              (BSL_META_U(pc->unit,
   1286                          "phy82109_ability_local_get:unit=%d p=%d sp=%08x\n"),
   1287               unit, port, ability->speed_full_duplex));
   1288     return (SOC_E_NONE);
   1289 }
   1290 
   1291 /*
   1292  * Function:
   1293  *      phy_82109_link_get
   1294  * Purpose: gets the phy link
   1295  *          state
   1296  *      
   1297  * Parameters:
   1298  *      unit - BCM unit number.
   1299  *      port - Port number. 
   1300  *      link - (OUT) link state
   1301  * Returns:     
   1302  *      SOC_E_XXX
   1303  */
   1304 STATIC int
   1305 phy_82109_link_get(int unit, soc_port_t port, int *link)
   1306 {
   1307     phy_ctrl_t                *pc;
   1308     soc_phymod_ctrl_t         *pmc;
   1309     phymod_phy_access_t       *pm_phy;
   1310     phy_ctrl_t *int_pc;
   1311     int32 int_phy_link = 0;
   1312     uint32 chip_id = 0;
   1313     *link = 0;
   1314     int_pc = INT_PHY_SW_STATE(unit, port);
   1315     pc = EXT_PHY_SW_STATE(unit, port);
   1316     if (pc == NULL) {
   1317         return SOC_E_INTERNAL;
   1318     }
   1319     pmc = &pc->phymod_ctrl;
   1320     pm_phy = &pmc->phy[pmc->main_phy]->pm_phy;
   1321     if (int_pc != NULL) {
   1322 		SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &int_phy_link));
   1323     }
   1324     chip_id = DEVID(pc); 
   1325     if (HURACAN_IS_SIMPLEX(chip_id) && (!SIMPLEX_TX(pc))) {
   1326         /* why we need to clear it ???*/
   1327        pm_phy->access.flags &= ~(1 << INTERFACE_SIDE_SHIFT);
   1328        pm_phy->access.flags |= (1 << INTERFACE_SIDE_SHIFT);
   1329     } 
   1330     /* Get the external phy link status if external phy is duplex or simplex package connected in Rx side */ 
   1331     if (HURACAN_IS_DUPLEX(chip_id) || (HURACAN_IS_SIMPLEX(chip_id) && (!SIMPLEX_TX(pc)))) {
   1332         SOC_IF_ERROR_RETURN
   1333             (phymod_phy_link_status_get(pm_phy, (uint32_t *) link));
   1334         /* When PMD lock of 82109 is not Set, Leave the port link as
   1335          * PMD status of 82109. When PMD lock of 82109 is set use
   1336          * PCS status of internal serdes as port link status.
   1337          * When internal serdes is not there use 82109 PMS as link status*/
   1338 #ifdef PHY82109_DEBUG    
   1339         if (*link == 1 && int_phy_link == 0) {
   1340             LOG_CLI((BSL_META_U(unit,"PMD UP PCS Down: port:%d\n "), port));
   1341         }
   1342         if (*link == 0 && int_phy_link == 1) {
   1343             LOG_CLI((BSL_META_U(unit,"PMD DOWN PCS UP port:%d\n "), port));
   1344         }
   1345 #endif
   1346         if (*link && int_pc) {
   1347             *link = int_phy_link;
   1348         }
   1349     } else {
   1350         *link = int_phy_link;
   1351     }
   1352     pm_phy->access.flags &= ~(1 << INTERFACE_SIDE_SHIFT);
   1353     return SOC_E_NONE;
   1354 }
   1355 
   1356 /*
   1357  * Function:
   1358  *      phy_82109_enable_set
   1359  * Purpose: set's Phy's power 
   1360  *          state
   1361  * Parameters:
   1362  *      unit - BCM unit number.
   1363  *      port - Port number. 
   1364  *      enable - value to be set
   1365  *               (on/off)
   1366  * Returns:     
   1367  *      SOC_E_XXX
   1368  */
   1369 STATIC int
   1370 phy_82109_enable_set(int unit, soc_port_t port, int enable)
   1371 {
   1372     phy_ctrl_t                *pc;
   1373     int32 intf;
   1374     phy_ctrl_t                *int_pc;
   1375     /* locate phy control */
   1376     int_pc = INT_PHY_SW_STATE(unit, port);
   1377     pc = EXT_PHY_SW_STATE(unit, port);
   1378     if (pc == NULL) {
   1379         return SOC_E_INTERNAL;
   1380     }
   1381     intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82109_SYS_SIDE : PHY82109_LINE_SIDE; 
   1382 
   1383 
   1384     SOC_IF_ERROR_RETURN
   1385         (phy_82109_power_set(pc, intf, enable));
   1386     SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, enable));
   1387 
   1388     if (enable) {
   1389         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
   1390 	} else {
   1391         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
   1392     }
   1393 
   1394     return SOC_E_NONE;
   1395 }
   1396 
   1397 /*
   1398  * Function:
   1399  *      phy_82109_enable_get
   1400  * Purpose: read's Phy's power 
   1401  *          state
   1402  * Parameters:
   1403  *      unit - BCM unit number.
   1404  *      port - Port number. 
   1405  *      enable - (OUT)returned value
   1406  *               (on/off)
   1407  * Returns:     
   1408  *      SOC_E_XXX
   1409  */
   1410 STATIC int
   1411 phy_82109_enable_get(int unit, soc_port_t port, int *enable)
   1412 {
   1413     phy_ctrl_t                *pc;
   1414     int32 intf;
   1415     uint32_t ena_dis;
   1416     *enable = 0;
   1417 
   1418     /* locate phy control */
   1419     pc = EXT_PHY_SW_STATE(unit, port);
   1420     if (pc == NULL) {
   1421         return SOC_E_INTERNAL;
   1422     }
   1423     intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82109_SYS_SIDE : PHY82109_LINE_SIDE; 
   1424     SOC_IF_ERROR_RETURN
   1425         (phy_82109_power_get(pc, intf, &ena_dis));
   1426     *enable = ena_dis;
   1427     return SOC_E_NONE;
   1428 }
   1429 
   1430 /*
   1431  * Function:
   1432  *      phy_82109_lb_set
   1433  * Purpose: sets loopback 
   1434  *          
   1435  * Parameters:
   1436  *      unit - BCM unit number.
   1437  *      port - Port number. 
   1438  *      enable - (OUT)value to set
   1439  *               (on/off)
   1440  * Returns:     
   1441  *      SOC_E_XXX
   1442  */
   1443 STATIC int
   1444 phy_82109_lb_set(int unit, soc_port_t port, int enable)
   1445 {
   1446     return SOC_E_NONE;
   1447 }
   1448 
   1449 /*
   1450  * Function:
   1451  *      phy_82109_firmware_set
   1452  * Purpose:
   1453  *      Sets firmware for phy download. 
   1454  * Parameters:
   1455  *      unit - BCM unit number
   1456  *      port - Port number
   1457  *      array - pointer to firmware c array
   1458  *      offset  - byte offset in the array .
   1459  *      datalen - length of the firmware array 
   1460  * Returns:     
   1461  *      SOC_E_XXX
   1462  */      
   1463 STATIC int
   1464 phy_82109_firmware_set(int unit, int port, int offset, uint8 *array,int datalen)
   1465 {
   1466     return SOC_E_UNAVAIL;
   1467    
   1468 }
   1469 
   1470 /*
   1471  * Function:
   1472  *      phy_82109_rx_seq_done_get
   1473  * Purpose:
   1474  *      Reads the rx pmd lock status. 
   1475  * Parameters:
   1476  *      pc  - phy control structure.
   1477  *      value - (OUT) value returned 
   1478  *      after read
   1479  *      intf - interface side
   1480  * Returns:     
   1481  *      SOC_E_XXX
   1482  */      
   1483 STATIC int
   1484 phy_82109_rx_seq_done_get(phy_ctrl_t *pc, int32 intf, uint32 *value)
   1485 {
   1486     phymod_phy_access_t  *pm_phy;
   1487     phymod_phy_access_t pm_phy_copy;
   1488     uint32_t if_side = 0;
   1489     uint32_t chip_id = 0;
   1490     uint32 simplex_tx = 0;
   1491     soc_phymod_ctrl_t *pmc;
   1492     pmc = &pc->phymod_ctrl;
   1493 
   1494 
   1495     /* just take the value from the first phy */
   1496     if (pmc->phy[0] == NULL) {
   1497         return SOC_E_INTERNAL;
   1498     }
   1499     pm_phy = &pmc->phy[0]->pm_phy;
   1500 
   1501     if (pm_phy == NULL) {
   1502          return SOC_E_INTERNAL;
   1503     }
   1504 
   1505     simplex_tx = SIMPLEX_TX(pc);
   1506     chip_id = DEVID(pc);
   1507     SOC_IF_ERROR_RETURN
   1508         (_phy_82109_get_intf_side(chip_id, intf, simplex_tx, 1, &if_side));
   1509 
   1510     sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   1511     pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1512     pm_phy_copy.access.flags |= if_side; 
   1513 
   1514     SOC_IF_ERROR_RETURN(phymod_phy_rx_pmd_locked_get(&pm_phy_copy, value));
   1515 
   1516     return(SOC_E_NONE);
   1517 }
   1518 /*
   1519  * Function:
   1520  *      phy_82109_rx_signal_detect_get
   1521  * Purpose:
   1522  *      Reads the rx signal detect status. 
   1523  * Parameters:
   1524  *      intf - interface side
   1525  *      pc  - phy control structure.
   1526  *      value - (OUT) value returned 
   1527  *      after read
   1528  * Returns:     
   1529  *      SOC_E_XXX
   1530  */
   1531 STATIC int
   1532 phy_82109_rx_signal_detect_get(phy_ctrl_t *pc, int32 intf, uint32 *value)
   1533 {
   1534    /* $$$ Need to add diagnostic API */
   1535    return(SOC_E_UNAVAIL);
   1536 }
   1537 /* 
   1538  * phy_82109_rx_ppm_get
   1539  */
   1540 STATIC int
   1541 phy_82109_rx_ppm_get(phy_ctrl_t *pc, int32 intf, uint32 *value)
   1542 {
   1543     /* $$$ Need to add diagnostic API */
   1544     return(SOC_E_UNAVAIL);
   1545 }
   1546 /*
   1547  * Function:
   1548  *      phy_82109_per_lane_power_get
   1549  * Purpose:
   1550  *      Reads the lanewise power state of phy. 
   1551  * Parameters:
   1552  *      intf - interface side
   1553  *      pc  - phy control structure.
   1554  *      value - (OUT) value returned 
   1555  *      after read
   1556  * Returns:     
   1557  *      SOC_E_XXX
   1558  */
   1559 STATIC int
   1560 phy_82109_per_lane_power_get(phy_ctrl_t *pc, int32 intf, int lane, uint32 *value)
   1561 {
   1562     phymod_phy_access_t     *pm_phy;
   1563     phymod_phy_power_t      power;
   1564     soc_phymod_phy_t    *p_phy;
   1565     uint32              lane_map;
   1566     phymod_phy_access_t pm_phy_copy;
   1567     uint32_t if_side = 0;
   1568     uint32_t chip_id = 0;
   1569     uint32 simplex_tx = 0;
   1570     soc_phymod_ctrl_t *pmc;
   1571     pmc = &pc->phymod_ctrl;
   1572     *value = 0;
   1573     /* locate the desired phy and lane */
   1574     SOC_IF_ERROR_RETURN(_phy_82109_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map));
   1575 
   1576     /* Make a copy of the phy access and overwrite the desired lane */
   1577     pm_phy = &p_phy->pm_phy;
   1578 
   1579     simplex_tx = SIMPLEX_TX(pc);
   1580     chip_id = DEVID(pc);
   1581     if(HURACAN_IS_SIMPLEX(chip_id)){
   1582         if (!simplex_tx) { /* Rx simplex package */
   1583             if (intf == PHY82109_SYS_SIDE) {
   1584                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1585             } else {
   1586                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1587                 if_side |= (1 << INTERFACE_SIDE_SHIFT);
   1588             } 
   1589         } else { /* Tx simplex package */
   1590             if (intf == PHY82109_SYS_SIDE) {
   1591                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1592                 if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   1593             } else {
   1594                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1595             } 
   1596         } 
   1597     } else {
   1598         if (intf == PHY82109_SYS_SIDE) {
   1599             if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1600             if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   1601         } else {
   1602             if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1603         }
   1604     } 
   1605     sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   1606     pm_phy_copy.access.lane_mask = lane_map;
   1607     pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1608     pm_phy_copy.access.flags |= if_side; 
   1609 
   1610     phymod_phy_power_t_init(&power);
   1611 
   1612     SOC_IF_ERROR_RETURN(phymod_phy_power_get(&pm_phy_copy, &power));
   1613 
   1614     if(HURACAN_IS_SIMPLEX(chip_id)) {
   1615         if(simplex_tx) {
   1616             if(intf == PHY82109_SYS_SIDE) {
   1617                 if(power.rx == phymodPowerOn)
   1618                     *value = 1;
   1619             } else {
   1620                 if(power.tx == phymodPowerOn)
   1621                     *value = 1;
   1622             }
   1623         } else {
   1624             if(intf == PHY82109_SYS_SIDE) {
   1625                 if(power.tx == phymodPowerOn)
   1626                     *value = 1;
   1627             } else {
   1628                 if(power.rx == phymodPowerOn)
   1629                     *value = 1;
   1630             }
   1631         }
   1632     } else {
   1633         if(power.tx == phymodPowerOn && power.rx == phymodPowerOn) {
   1634             *value = 1;
   1635         } else {
   1636             *value = 0;
   1637         }
   1638     }
   1639     return(SOC_E_NONE);
   1640 }
   1641 /*
   1642  * Function:
   1643  *      phy_82109_power_get
   1644  * Purpose:
   1645  *      Reads the power phy's state. 
   1646  * Parameters:
   1647  *      intf - interface side
   1648  *      pc  - phy control structure.
   1649  *      value - (OUT) value returned 
   1650  *      after read
   1651  * Returns:     
   1652  *      SOC_E_XXX
   1653  */
   1654 STATIC int
   1655 phy_82109_power_get(phy_ctrl_t *pc, int32 intf, uint32 *value)
   1656 {
   1657     phymod_phy_access_t     *pm_phy;
   1658     phymod_phy_power_t      power;
   1659     phymod_phy_access_t pm_phy_copy;
   1660     uint32_t if_side = 0;
   1661     uint32_t chip_id = 0;
   1662     uint32 simplex_tx = 0;
   1663     soc_phymod_ctrl_t *pmc;
   1664     pmc = &pc->phymod_ctrl;
   1665     *value = 0;
   1666 
   1667     /* just take the value from the first phy */
   1668     if (pmc->phy[0] == NULL) {
   1669         return SOC_E_INTERNAL;
   1670     }
   1671     pm_phy = &pmc->phy[0]->pm_phy;
   1672 
   1673     if (pm_phy == NULL) {
   1674         return SOC_E_INTERNAL;
   1675     }
   1676 
   1677 
   1678     simplex_tx = SIMPLEX_TX(pc);
   1679     chip_id = DEVID(pc);
   1680     if(HURACAN_IS_SIMPLEX(chip_id)){
   1681         if (!simplex_tx) { /* Rx simplex package */
   1682             if (intf == PHY82109_SYS_SIDE) {
   1683                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1684             } else {
   1685                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1686                 if_side |= (1 << INTERFACE_SIDE_SHIFT);
   1687             } 
   1688         } else { /* Tx simplex package */
   1689             if (intf == PHY82109_SYS_SIDE) {
   1690                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1691                 if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   1692             } else {
   1693                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1694             } 
   1695         } 
   1696     } else {
   1697         if (intf == PHY82109_SYS_SIDE) {
   1698             if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1699             if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   1700         } else {
   1701             if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1702         }
   1703     } 
   1704 
   1705     sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   1706     phymod_phy_power_t_init(&power);
   1707     pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   1708     pm_phy_copy.access.flags |= if_side; 
   1709 
   1710     SOC_IF_ERROR_RETURN(phymod_phy_power_get(&pm_phy_copy, &power));
   1711    
   1712     if(HURACAN_IS_SIMPLEX(chip_id)) {
   1713         if(simplex_tx) {
   1714             if(intf == PHY82109_SYS_SIDE) {
   1715                 if(power.rx == phymodPowerOn)
   1716                     *value = 1;
   1717             } else {
   1718                 if(power.tx == phymodPowerOn)
   1719                     *value = 1;
   1720             }
   1721         } else {
   1722             if(intf == PHY82109_SYS_SIDE) {
   1723                 if(power.tx == phymodPowerOn)
   1724                     *value = 1;
   1725             } else {
   1726                 if(power.rx == phymodPowerOn)
   1727                     *value = 1;
   1728             }
   1729         }
   1730     } else {
   1731         if(power.tx == phymodPowerOn && power.rx == phymodPowerOn) {
   1732             *value = 1;
   1733         } else {
   1734             *value = 0;
   1735         }
   1736     }
   1737     return(SOC_E_NONE);
   1738 }
   1739 
   1740 /*
   1741  * Function:
   1742  *      phy_82109_gpio_config_get
   1743  * Purpose:
   1744  *      Reads the gpio line config. 
   1745  * Parameters:
   1746  *      pc  - phy control structure.
   1747  *      value - (OUT) value returned 
   1748  *      after read
   1749  * Returns:     
   1750  *      SOC_E_XXX
   1751  */
   1752 STATIC int 
   1753 phy_82109_gpio_config_get(phy_ctrl_t *pc, uint32 *value)
   1754 {
   1755     phymod_phy_access_t  *pm_phy;
   1756     phymod_phy_access_t pm_phy_copy;
   1757     phymod_gpio_mode_t gpio_mode;
   1758     int gpio_pin_no = 0;
   1759     soc_phymod_ctrl_t *pmc;
   1760     pmc = &pc->phymod_ctrl;
   1761     *value = 0;
   1762 
   1763     /* just take the value from the first phy */
   1764     if (pmc->phy[0] == NULL) {
   1765         return SOC_E_INTERNAL;
   1766     }
   1767     pm_phy = &pmc->phy[0]->pm_phy;
   1768 
   1769     if (pm_phy == NULL) {
   1770         return SOC_E_INTERNAL;
   1771     }
   1772     sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   1773 
   1774     for (gpio_pin_no = 0; gpio_pin_no < 2; gpio_pin_no++) {
   1775         SOC_IF_ERROR_RETURN(phymod_phy_gpio_config_get(&pm_phy_copy, gpio_pin_no, &gpio_mode));
   1776         *value |= (gpio_mode << (4 * gpio_pin_no));
   1777     }
   1778 
   1779     return(SOC_E_NONE);
   1780 }
   1781 /*
   1782  * Function:
   1783  *      phy_82109_gpio_value_get
   1784  * Purpose:
   1785  *      Programmes the gpio pin. 
   1786  * Parameters:
   1787  *      pc  - phy control structure.
   1788  *      value - (OUT)returned value after 
   1789  *      read 
   1790  * Returns:     
   1791  *      SOC_E_XXX
   1792  */
   1793 STATIC int 
   1794 phy_82109_gpio_value_get(phy_ctrl_t *pc, uint32 *value)
   1795 {
   1796     phymod_phy_access_t  *pm_phy;
   1797     phymod_phy_access_t pm_phy_copy;
   1798     int gpio_pin_no = 0;
   1799     int pin_value = 0;
   1800     soc_phymod_ctrl_t *pmc;
   1801     pmc = &pc->phymod_ctrl;
   1802     *value = 0;
   1803 
   1804     /* just take the value from the first phy */
   1805     if (pmc->phy[0] == NULL) {
   1806         return SOC_E_INTERNAL;
   1807     }
   1808     pm_phy = &pmc->phy[0]->pm_phy;
   1809 
   1810     if (pm_phy == NULL) {
   1811         return SOC_E_INTERNAL;
   1812     }
   1813 
   1814     sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   1815 
   1816     for (gpio_pin_no = 0; gpio_pin_no < 2; gpio_pin_no++) {
   1817         SOC_IF_ERROR_RETURN(phymod_phy_gpio_pin_value_get(&pm_phy_copy, gpio_pin_no, &pin_value));
   1818         *value |= (pin_value << (4 * gpio_pin_no));
   1819     }
   1820 
   1821     return(SOC_E_NONE);
   1822 }
   1823 /*
   1824  * Function:
   1825  *      phy82109_control_get
   1826  * Purpose:
   1827  *      Get current control settings of the PHY. 
   1828  * Parameters:
   1829  *      unit  - BCM unit number.
   1830  *      port  - Port number. 
   1831  *      type  - Control to update 
   1832  *      value - (OUT) Current setting for the control 
   1833  * Returns:     
   1834  *      SOC_E_XXX
   1835  */
   1836 STATIC int
   1837 phy_82109_control_get(int unit, soc_port_t port, soc_phy_control_t type, uint32 *value)
   1838 {
   1839     int                 rv = SOC_E_UNAVAIL;
   1840     phy_ctrl_t          *pc;
   1841     int32 intf;
   1842     *value = 0;
   1843     PHY_CONTROL_TYPE_CHECK(type);
   1844 
   1845     /* locate phy control */
   1846     pc = EXT_PHY_SW_STATE(unit, port);
   1847     if (pc == NULL) {
   1848         return SOC_E_INTERNAL;
   1849     }
   1850     intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82109_SYS_SIDE : PHY82109_LINE_SIDE; 
   1851 
   1852     switch(type) {
   1853     /* RX SIGNAL DETECT */
   1854     case SOC_PHY_CONTROL_RX_SIGNAL_DETECT:
   1855       rv = phy_82109_rx_signal_detect_get(pc, intf, value);
   1856       break;
   1857     case SOC_PHY_CONTROL_RX_SEQ_DONE:
   1858       rv = phy_82109_rx_seq_done_get(pc, intf, value);
   1859       break;
   1860     case SOC_PHY_CONTROL_RX_PPM:
   1861       rv = phy_82109_rx_ppm_get(pc, intf, value);
   1862       break;
   1863     case SOC_PHY_CONTROL_POWER:
   1864        rv = phy_82109_power_get(pc, intf, value);
   1865        break;
   1866     case SOC_PHY_CONTROL_TX_LANE_SQUELCH:
   1867         rv = phy_82109_tx_lane_squelch_get(pc, intf, value);
   1868     break;
   1869     case SOC_PHY_CONTROL_GPIO_CONFIG:
   1870         rv = phy_82109_gpio_config_get(pc, value);
   1871     break;
   1872     case SOC_PHY_CONTROL_GPIO_VALUE:
   1873         rv = phy_82109_gpio_value_get(pc, value);
   1874     break;
   1875     default:
   1876        rv = SOC_E_UNAVAIL;
   1877        break;
   1878     }
   1879     return rv;
   1880 }
   1881 
   1882 /*
   1883  * Function:
   1884  *      phy_82109_per_lane_control_get
   1885  * Purpose:
   1886  *      Configure PHY device specific control fucntion. 
   1887  * Parameters:
   1888  *      unit  - StrataSwitch unit #.
   1889  *      port  - StrataSwitch port #. 
   1890  *      lane  - lane number
   1891  *      type  - Control to update 
   1892  *      value - New setting for the control 
   1893  * Returns:     
   1894  *      SOC_E_XXX
   1895  */
   1896 STATIC int
   1897 phy_82109_per_lane_control_get(int unit, soc_port_t port, int lane,
   1898                      soc_phy_control_t type, uint32 *value)
   1899 {
   1900     int                 rv = SOC_E_UNAVAIL;
   1901     phy_ctrl_t          *pc;
   1902     int32 intf;
   1903     *value = 0;
   1904 
   1905     /* locate phy control, phymod control, and the configuration data */
   1906     pc = EXT_PHY_SW_STATE(unit, port);
   1907     if (pc == NULL) {
   1908         return SOC_E_INTERNAL;
   1909     }
   1910     PHY_CONTROL_TYPE_CHECK(type);
   1911     intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82109_SYS_SIDE : PHY82109_LINE_SIDE; 
   1912     
   1913     switch(type) {
   1914     case SOC_PHY_CONTROL_POWER:
   1915 
   1916        rv = phy_82109_per_lane_power_get(pc, intf, lane, value);
   1917        break;
   1918     case SOC_PHY_CONTROL_TX_LANE_SQUELCH:
   1919         rv = phy_82109_per_lane_tx_lane_squelch_get(pc, intf, lane, value);
   1920         break;
   1921 
   1922     default:
   1923         rv = SOC_E_UNAVAIL;
   1924         break; 
   1925     }
   1926     return rv;
   1927 }
   1928 
   1929 /*
   1930  * Function:
   1931  *      phy82109_duplex_get
   1932  * Purpose:
   1933  *      Get PHY duplex mode
   1934  * Parameters:
   1935  *      unit - BCM unit number.
   1936  *      port - Port number. 
   1937  *      duplex - current duplex mode
   1938  * Returns:     
   1939  *      SOC_E_XXX
   1940  */
   1941 STATIC int
   1942 phy82109_duplex_get(int unit, soc_port_t port, int *duplex)
   1943 {
   1944     *duplex = TRUE;
   1945     return SOC_E_NONE;
   1946 }
   1947 
   1948 /*
   1949  * Function:    
   1950  *      phy_82109_an_set
   1951  * Purpose:     
   1952  *      Enable or disable auto-negotiation on the specified port.
   1953  * Parameters:
   1954  *      unit - BCM unit number.
   1955  *      port - Port number. 
   1956  *      an   - Boolean, if true, auto-negotiation is enabled 
   1957  *              (and/or restarted). If false, autonegotiation is disabled.
   1958  * Returns:     
   1959  *      SOC_E_XXX  _soc_triumph_tx
   1960  */
   1961 STATIC int
   1962 phy_82109_an_set(int unit, soc_port_t port, int enable)
   1963 {
   1964     return (SOC_E_NONE);
   1965 }
   1966 /*
   1967  * Function:    
   1968  *      phy_82109_an_get
   1969  * Purpose:     
   1970  *      Get the current auto-negotiation status (enabled/busy)
   1971  * Parameters:
   1972  *      unit - BCM unit number.
   1973  *      port - Port number. 
   1974  *      an   - (OUT) if true, auto-negotiation is enabled.
   1975  *      an_done - (OUT) if true, auto-negotiation is complete. This
   1976  *              value is undefined if an == false.
   1977  * Returns:     
   1978  *      SOC_E_XXX
   1979  */
   1980 
   1981 STATIC int
   1982 phy_82109_an_get(int unit, soc_port_t port, int *an, int *an_done)
   1983 {
   1984     *an = 0;
   1985     *an_done = 0;
   1986     return SOC_E_NONE;
   1987 }
   1988 /*
   1989  * Function:
   1990  *      phy_82109_ability_advert_set
   1991  * Purpose:
   1992  *      Set the current advertisement for auto-negotiation.
   1993  * Parameters:
   1994  *      unit - BCM unit number.
   1995  *      port - Port number.
   1996  *      ability - Port mode mask indicating supported options/speeds.
   1997  * Returns:
   1998  *      SOC_E_XXX
   1999  * Notes:
   2000  *      The advertisement is set only for the ACTIVE medium.
   2001  *      No synchronization performed at this level.
   2002  */
   2003 
   2004 STATIC int
   2005 phy_82109_ability_advert_set(int unit, soc_port_t port,
   2006                           soc_port_ability_t *ability)
   2007 {
   2008     return SOC_E_NONE;
   2009 }
   2010 
   2011 /*
   2012  * Function:
   2013  *      phy_82109_ability_advert_get
   2014  * Purpose:
   2015  *      Get the current advertisement for auto-negotiation.
   2016  * Parameters:
   2017  *      unit - BCM unit number.
   2018  *      port - Port number.
   2019  *      ability - (OUT) Port mode mask indicating supported options/speeds.
   2020  * Returns:
   2021  *      SOC_E_XXX
   2022  * Notes:
   2023  *      The advertisement is retrieved for the ACTIVE medium.
   2024  *      No synchronization performed at this level.
   2025  */
   2026 
   2027 STATIC int
   2028 phy_82109_ability_advert_get(int unit, soc_port_t port,
   2029                               soc_port_ability_t *ability)
   2030 {
   2031     return SOC_E_NONE;
   2032 }
   2033 
   2034 /*
   2035  * Function:
   2036  *      phy82109_lb_get
   2037  * Purpose:
   2038  *      Get current PHY loopback mode
   2039  * Parameters:
   2040  *      unit - BCM unit number.
   2041  *      port - Port number. 
   2042  *      enable - address of location to store binary value for on/off (1/0)
   2043  * Returns:     
   2044  *      SOC_E_XXX
   2045  */
   2046 STATIC int
   2047 phy82109_lb_get(int unit, soc_port_t port, int *enable)
   2048 {
   2049     *enable = 0;
   2050     return SOC_E_NONE;
   2051 }
   2052 
   2053 STATIC int
   2054 _phy_82109_get_intf_side(uint32_t chip_id, int32 intf, uint32 simplex_tx, uint32 tx_rx, uint32_t *if_side)
   2055 {
   2056     *if_side = 0;
   2057     if (HURACAN_IS_SIMPLEX(chip_id)) {  /* Simplex package */
   2058         if (tx_rx) { /* Rx side */
   2059             if (!simplex_tx) { /* Simplex Rx package */
   2060                 if (intf == PHY82109_SYS_SIDE) {
   2061                     LOG_CLI((BSL_META_U(0,"No Rx available at SYS SIDE in Simplex Rx package\n")));
   2062                     return SOC_E_UNAVAIL; 
   2063                 } else {
   2064                     *if_side |= (1 << INTERFACE_SIDE_SHIFT);
   2065                 } 
   2066             } else { /* Simplex Tx package */
   2067                 if (intf == PHY82109_SYS_SIDE) {
   2068                     *if_side |= (1 << INTERFACE_SIDE_SHIFT);
   2069                 } else {
   2070                     LOG_CLI((BSL_META_U(0,"No Rx available at LINE SIDE in Simplex Tx package\n")));
   2071                     return SOC_E_UNAVAIL; 
   2072                 }
   2073             } 
   2074         } else { /* Tx side */
   2075             if (!simplex_tx) { /* Simplex Rx package */
   2076                 if (intf == PHY82109_SYS_SIDE) {
   2077                     *if_side &= ~(1 << INTERFACE_SIDE_SHIFT);
   2078                 } else {
   2079                     LOG_CLI((BSL_META_U(0,"No Tx available at LINE SIDE in Simplex Rx package\n")));
   2080                     return SOC_E_UNAVAIL; 
   2081                 } 
   2082             } else {  /* Simplex Tx package */
   2083                 if (intf == PHY82109_SYS_SIDE) {
   2084                     LOG_CLI((BSL_META_U(0, "No Tx available at SYS SIDE in Simplex Tx package\n")));
   2085                     return SOC_E_UNAVAIL; 
   2086                 } else {
   2087                     *if_side &= ~(1 << INTERFACE_SIDE_SHIFT);
   2088                 } 
   2089             } 
   2090         } 
   2091     } else { /* Duplex package */
   2092         if (intf == PHY82109_SYS_SIDE) {
   2093             *if_side |= (1 << INTERFACE_SIDE_SHIFT);
   2094         } else {
   2095             *if_side &= ~(1 << INTERFACE_SIDE_SHIFT);
   2096         }
   2097     }
   2098     return(SOC_E_NONE);
   2099 }
   2100 
   2101 /*
   2102  * Function:
   2103  *      phy_82109_find_soc_phy_lane
   2104  * Purpose:
   2105  *          given a pc (phymod_ctrl_t) and logical lane number, 
   2106  *          find the correct soc_phymod_phy_t object and lane
   2107  * Parameters:
   2108  *      pmc  - soc phy control structure.
   2109  *      lane - lane number
   2110  *      lane_map - lane map
   2111  *      p_phy - (OUT)soc phy mod phy structure
   2112  * Returns:     
   2113  *      SOC_E_XXX
   2114  */
   2115 STATIC int
   2116 _phy_82109_find_soc_phy_lane(soc_phymod_ctrl_t *pmc, uint32_t lane, 
   2117                         soc_phymod_phy_t **p_phy, uint32 *lane_map)
   2118 {
   2119     phymod_phy_access_t *pm_phy;
   2120     int idx, lnx, ln_cnt, found;
   2121     uint32 lane_map_copy;
   2122     uint32 chip_id = 0;
   2123     int num_lanes = 0;
   2124     /* Traverse lanes belonging to this port */
   2125     found = 0;
   2126     ln_cnt = 0;
   2127     for (idx = 0; idx < pmc->num_phys; idx++) {
   2128         pm_phy = &pmc->phy[idx]->pm_phy;
   2129         if (pm_phy == NULL) {
   2130             return SOC_E_INTERNAL;
   2131         }
   2132         lane_map_copy = pm_phy->access.lane_mask;
   2133         SOC_IF_ERROR_RETURN(
   2134              _phy_82109_chip_id_get(pm_phy, &chip_id));
   2135         if(HURACAN_IS_SIMPLEX(chip_id)){
   2136            num_lanes = 8;
   2137         } else {
   2138            num_lanes = 4;
   2139         }
   2140         for (lnx = 0; lnx < num_lanes; lnx++) {
   2141             if ((1 << lnx) & lane_map_copy) {
   2142                 if ((ln_cnt == lane) || (lane == 0)) {
   2143                     found = 1;
   2144                     break;
   2145                 }
   2146                 ln_cnt++;
   2147             }
   2148         }
   2149         if (found) {
   2150             *p_phy = pmc->phy[idx];
   2151             *lane_map = (1 << lnx);
   2152             break;
   2153         }
   2154     } 
   2155 
   2156     if (!found) {
   2157         LOG_CLI((BSL_META_U(pmc->unit,"\nInvalid lane \n")));
   2158         /* No such lane */
   2159         return SOC_E_PARAM;
   2160     }
   2161     return (SOC_E_NONE);
   2162 }
   2163 /*
   2164  * Function:
   2165  *      phy_82109_per_lane_tx_lane_squelch
   2166  * Purpose:
   2167  *      sets/clears lanewise tx squelch 
   2168  *      
   2169  * Parameters:
   2170  *      pc  - phy control structure.
   2171  *      intf - interface side
   2172  *      lane - lane number
   2173  *      value - value to set
   2174  * Returns:     
   2175  *      SOC_E_XXX
   2176  */
   2177 STATIC int
   2178 phy_82109_per_lane_tx_lane_squelch(phy_ctrl_t *pc, int32 intf, int lane, uint32 value)
   2179 {
   2180     phymod_phy_access_t *pm_phy;
   2181     phymod_phy_tx_lane_control_t  tx_control;
   2182     int                 idx;
   2183     phymod_phy_access_t pm_phy_copy;
   2184     soc_phymod_phy_t    *p_phy;
   2185     uint32              lane_map;
   2186     uint32_t if_side = 0;
   2187     uint32_t chip_id = 0;
   2188     uint32 simplex_tx = 0;
   2189     soc_phymod_ctrl_t *pmc;
   2190     pmc = &pc->phymod_ctrl;
   2191 
   2192 
   2193     /* locate the desired phy and lane */
   2194     SOC_IF_ERROR_RETURN(_phy_82109_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map));
   2195 
   2196     /* loop through all cores */
   2197     for (idx = 0; idx < pmc->num_phys; idx++) {
   2198         pm_phy = &pmc->phy[idx]->pm_phy;
   2199 
   2200         if (pm_phy == NULL) {
   2201             return SOC_E_INTERNAL;
   2202         }
   2203 
   2204         simplex_tx = SIMPLEX_TX(pc);
   2205         chip_id = DEVID(pc);
   2206         SOC_IF_ERROR_RETURN
   2207             (_phy_82109_get_intf_side(chip_id, intf, simplex_tx, 0, &if_side));
   2208 
   2209         sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2210         pm_phy_copy.access.lane_mask = lane_map;
   2211         pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2212         pm_phy_copy.access.flags |= if_side; 
   2213 
   2214         if (value == 1) {
   2215             tx_control = phymodTxSquelchOn;
   2216         } else {
   2217             tx_control = phymodTxSquelchOff;
   2218         }
   2219         SOC_IF_ERROR_RETURN
   2220             (phymod_phy_tx_lane_control_set(&pm_phy_copy, tx_control));
   2221 
   2222     }
   2223     return(SOC_E_NONE);
   2224 } 
   2225 
   2226 /*
   2227  * Function:
   2228  *      phy_82109_per_lane_tx_lane_squelch_get
   2229  * Purpose:
   2230  *      gets lanewise tx squelch status 
   2231  *      
   2232  * Parameters:
   2233  *      pc  - phy control structure.
   2234  *      intf - interface side
   2235  *      lane - lane number
   2236  *      value - (OUT) returned value after read
   2237  * Returns:     
   2238  *      SOC_E_XXX
   2239  */
   2240 STATIC int
   2241 phy_82109_per_lane_tx_lane_squelch_get(phy_ctrl_t *pc, int32 intf, int lane, uint32 *value)
   2242 {
   2243     phymod_phy_access_t *pm_phy;
   2244     phymod_phy_tx_lane_control_t  tx_control;
   2245     int                 idx;
   2246     phymod_phy_access_t pm_phy_copy;
   2247     soc_phymod_phy_t    *p_phy;
   2248     uint32              lane_map;
   2249     uint32_t if_side = 0;
   2250     uint32_t chip_id = 0;
   2251     uint32 simplex_tx = 0;
   2252     soc_phymod_ctrl_t *pmc;
   2253     pmc = &pc->phymod_ctrl;
   2254 
   2255 
   2256     /* locate the desired phy and lane */
   2257     SOC_IF_ERROR_RETURN(_phy_82109_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map));
   2258 
   2259     /* loop through all cores */
   2260     for (idx = 0; idx < pmc->num_phys; idx++) {
   2261         pm_phy = &pmc->phy[idx]->pm_phy;
   2262 
   2263         if (pm_phy == NULL) {
   2264             return SOC_E_INTERNAL;
   2265         }
   2266         simplex_tx = SIMPLEX_TX(pc);
   2267         chip_id = DEVID(pc);
   2268         SOC_IF_ERROR_RETURN
   2269             (_phy_82109_get_intf_side(chip_id, intf, simplex_tx, 0, &if_side));
   2270 
   2271         sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2272         pm_phy_copy.access.lane_mask = lane_map;
   2273         pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2274         pm_phy_copy.access.flags |= if_side; 
   2275 
   2276         tx_control = phymodTxSquelchOn;
   2277         SOC_IF_ERROR_RETURN
   2278             (phymod_phy_tx_lane_control_get(&pm_phy_copy, &tx_control));
   2279         *value = tx_control;
   2280     }
   2281     return(SOC_E_NONE);
   2282 } 
   2283 
   2284 /*
   2285  * Function:
   2286  *      phy_82109_tx_lane_squelch
   2287  * Purpose:
   2288  *      sets/clear's tx lane squelch 
   2289  *      
   2290  * Parameters:
   2291  *      pc  - phy control structure.
   2292  *      intf - interface side
   2293  *      lane - 
   2294  *      value - value to be programmed (on/off)
   2295  * Returns:     
   2296  *      SOC_E_XXX
   2297  */      
   2298 STATIC int
   2299 phy_82109_tx_lane_squelch(phy_ctrl_t *pc, int32 intf, uint32 value)
   2300 {
   2301     phymod_phy_access_t *pm_phy;
   2302     phymod_phy_tx_lane_control_t  tx_control;
   2303     int                 idx;
   2304     phymod_phy_access_t pm_phy_copy;
   2305     uint32_t if_side = 0;
   2306     uint32_t chip_id = 0;
   2307     uint32 simplex_tx = 0;
   2308     soc_phymod_ctrl_t *pmc;
   2309     pmc = &pc->phymod_ctrl;
   2310 
   2311     /* loop through all cores */
   2312     for (idx = 0; idx < pmc->num_phys; idx++) {
   2313         pm_phy = &pmc->phy[idx]->pm_phy;
   2314 
   2315         if (pm_phy == NULL) {
   2316             return SOC_E_INTERNAL;
   2317         }
   2318 
   2319         simplex_tx = SIMPLEX_TX(pc);
   2320         chip_id = DEVID(pc);
   2321         SOC_IF_ERROR_RETURN
   2322             (_phy_82109_get_intf_side(chip_id, intf, simplex_tx, 0, &if_side));
   2323         sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2324         pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2325         pm_phy_copy.access.flags |= if_side; 
   2326 
   2327         if (value == 1) {
   2328             tx_control = phymodTxSquelchOn;
   2329         } else {
   2330             tx_control = phymodTxSquelchOff;
   2331         }
   2332         SOC_IF_ERROR_RETURN
   2333             (phymod_phy_tx_lane_control_set(&pm_phy_copy, tx_control));
   2334 
   2335     }
   2336     return(SOC_E_NONE);
   2337 }
   2338 
   2339 /*
   2340  * Function:
   2341  *      phy_82109_per_lane_power_set
   2342  * Purpose:
   2343  *      Sets the lanewise interface side 
   2344  *      power state. 
   2345  * Parameters:
   2346  *      pc  - phy control structure.
   2347  *      intf - interface side
   2348  *      lane - lane number
   2349  *      value - value to be programmed (on/off)
   2350  * Returns:     
   2351  *      SOC_E_XXX
   2352  */
   2353 STATIC int
   2354 phy_82109_tx_lane_squelch_get(phy_ctrl_t *pc, int32 intf, uint32 *value)
   2355 {
   2356     phymod_phy_access_t *pm_phy;
   2357     phymod_phy_tx_lane_control_t  tx_control;
   2358     int                 idx;
   2359     phymod_phy_access_t pm_phy_copy;
   2360     uint32_t if_side = 0;
   2361     uint32_t chip_id = 0;
   2362     uint32 simplex_tx = 0;
   2363     soc_phymod_ctrl_t *pmc;
   2364     pmc = &pc->phymod_ctrl;
   2365 
   2366     /* loop through all cores */
   2367     for (idx = 0; idx < pmc->num_phys; idx++) {
   2368         pm_phy = &pmc->phy[idx]->pm_phy;
   2369 
   2370         if (pm_phy == NULL) {
   2371             return SOC_E_INTERNAL;
   2372         }
   2373         simplex_tx = SIMPLEX_TX(pc);
   2374         chip_id = DEVID(pc);
   2375         SOC_IF_ERROR_RETURN
   2376             (_phy_82109_get_intf_side(chip_id, intf, simplex_tx, 0, &if_side));
   2377         sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2378         pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2379         pm_phy_copy.access.flags |= if_side; 
   2380         tx_control = phymodTxSquelchOn;
   2381         SOC_IF_ERROR_RETURN
   2382             (phymod_phy_tx_lane_control_get(&pm_phy_copy, &tx_control));
   2383         *value = tx_control;
   2384     }
   2385     return(SOC_E_NONE);
   2386 }
   2387 /*
   2388  * Function:
   2389  *      phy_82109_per_lane_power_set
   2390  * Purpose:
   2391  *      Sets the lanewise interface side 
   2392  *      power state. 
   2393  * Parameters:
   2394  *      pc  - phy control structure.
   2395  *      intf - interface side
   2396  *      lane - lane number
   2397  *      value - value to be programmed (on/off)
   2398  * Returns:     
   2399  *      SOC_E_XXX
   2400  */
   2401 STATIC int
   2402 phy_82109_per_lane_power_set(phy_ctrl_t *pc, int32 intf, int lane, uint32 value)
   2403 {
   2404     phymod_phy_access_t     *pm_phy;
   2405     phymod_phy_power_t      power;
   2406     uint32              lane_map;
   2407     phymod_phy_access_t pm_phy_copy;
   2408     soc_phymod_phy_t    *p_phy;
   2409     uint32_t if_side = 0;
   2410     uint32_t chip_id = 0;
   2411     uint32 simplex_tx = 0;
   2412     soc_phymod_ctrl_t *pmc;
   2413     pmc = &pc->phymod_ctrl;
   2414 
   2415     /* locate the desired phy and lane */
   2416     SOC_IF_ERROR_RETURN(_phy_82109_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map));
   2417 
   2418     /* Make a copy of the phy access and overwrite the desired lane */
   2419     pm_phy = &p_phy->pm_phy;
   2420 
   2421     simplex_tx = SIMPLEX_TX(pc);
   2422     chip_id = DEVID(pc);
   2423 
   2424     phymod_phy_power_t_init(&power);
   2425     if(HURACAN_IS_SIMPLEX(chip_id)){
   2426         if (!simplex_tx) { /* Rx simplex package */
   2427             if (intf == PHY82109_SYS_SIDE) {
   2428                if (value) {
   2429                    power.tx = phymodPowerOn;
   2430                    power.rx = phymodPowerOn;
   2431                } else {
   2432                    power.tx = phymodPowerOff;
   2433                    power.rx = phymodPowerOn;
   2434                }
   2435                if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2436             } else {
   2437                 if (value) {
   2438                    power.rx = phymodPowerOn;
   2439                    power.tx = phymodPowerOn;
   2440                 } else {
   2441                    power.rx = phymodPowerOff;
   2442                    power.tx = phymodPowerOn;
   2443                 }
   2444                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2445                 if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   2446             } 
   2447         } else { /* Tx simplex package */
   2448             if (intf == PHY82109_SYS_SIDE) {
   2449                if (value) {
   2450                    power.rx = phymodPowerOn;
   2451                    power.tx = phymodPowerOn;
   2452                } else {
   2453                    power.rx = phymodPowerOff;
   2454                    power.tx = phymodPowerOn;
   2455                }
   2456                if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2457                if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   2458             } else {
   2459                 if (value) {
   2460                    power.tx = phymodPowerOn;
   2461                    power.rx = phymodPowerOn;
   2462                 } else {
   2463                    power.tx = phymodPowerOff;
   2464                    power.rx = phymodPowerOn;
   2465                 }
   2466                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2467             } 
   2468         } 
   2469     } else {
   2470         if (value) {
   2471             power.tx = phymodPowerOn;
   2472             power.rx = phymodPowerOn;
   2473         } else {
   2474             power.tx = phymodPowerOff;
   2475             power.rx = phymodPowerOff;
   2476         }
   2477         if (intf == PHY82109_SYS_SIDE) {
   2478            if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2479            if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   2480         } else {
   2481            if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2482         }
   2483     } 
   2484 
   2485     sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2486     pm_phy_copy.access.lane_mask = lane_map;
   2487     pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2488     pm_phy_copy.access.flags |= if_side; 
   2489 
   2490     SOC_IF_ERROR_RETURN(phymod_phy_power_set(&pm_phy_copy, &power));
   2491 
   2492     return(SOC_E_NONE);
   2493 }
   2494 /*
   2495  * Function:
   2496  *      phy_82109_power_set
   2497  * Purpose:
   2498  *      Sets the interface side power state. 
   2499  * Parameters:
   2500  *      pc  - phy control structure.
   2501  *      intf - interface side
   2502  *      value - value to be programmed (on/off)
   2503  * Returns:     
   2504  *      SOC_E_XXX
   2505  */
   2506 STATIC int
   2507 phy_82109_power_set(phy_ctrl_t *pc, int32 intf, uint32 value)
   2508 {
   2509     phymod_phy_access_t     *pm_phy;
   2510     phymod_phy_power_t      power;
   2511     int                     idx;
   2512     phymod_phy_access_t pm_phy_copy;
   2513     uint32_t if_side = 0;
   2514     uint32_t chip_id = 0;
   2515     uint32 simplex_tx = 0;
   2516     soc_phymod_ctrl_t *pmc;
   2517     pmc = &pc->phymod_ctrl;
   2518 
   2519     /* loop through all cores */
   2520     for (idx = 0; idx < pmc->num_phys; idx++) {
   2521         pm_phy = &pmc->phy[idx]->pm_phy;
   2522 
   2523         if (pm_phy == NULL) {
   2524             return SOC_E_INTERNAL;
   2525         }
   2526 
   2527         simplex_tx = SIMPLEX_TX(pc);
   2528         chip_id = DEVID(pc);
   2529 
   2530         phymod_phy_power_t_init(&power);
   2531         if(HURACAN_IS_SIMPLEX(chip_id)){
   2532             if (!simplex_tx) { /* Rx simplex package */
   2533                 if (intf == PHY82109_SYS_SIDE) {
   2534                     if (value) {
   2535                         power.tx = phymodPowerOn;
   2536                     } else {
   2537                         power.tx = phymodPowerOff;
   2538                     }
   2539                     power.rx = phymodPowerNoChange;
   2540                     if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2541                 } else {
   2542                     if (value) {
   2543                         power.rx = phymodPowerOn;
   2544                     } else {
   2545                         power.rx = phymodPowerOff;
   2546                     }
   2547                     power.tx = phymodPowerNoChange;
   2548                     if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2549                     if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   2550                 } 
   2551             } else { /* Tx simplex package */
   2552                 if (intf == PHY82109_SYS_SIDE) {
   2553                     if (value) {
   2554                         power.rx = phymodPowerOn;
   2555                     } else {
   2556                         power.rx = phymodPowerOff;
   2557                     }
   2558                     power.tx = phymodPowerNoChange;
   2559                     if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2560                     if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   2561                 } else {
   2562                     if (value) {
   2563                         power.tx = phymodPowerOn;
   2564                     } else {
   2565                         power.tx = phymodPowerOff;
   2566                     }
   2567                     power.rx = phymodPowerNoChange;
   2568                     if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2569                 } 
   2570             } 
   2571         } else {
   2572             if (value) {
   2573                 power.tx = phymodPowerOn;
   2574                 power.rx = phymodPowerOn;
   2575             } else {
   2576                 power.tx = phymodPowerOff;
   2577                 power.rx = phymodPowerOff;
   2578             }
   2579             if (intf == PHY82109_SYS_SIDE) {
   2580                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2581                 if_side |= (1 << INTERFACE_SIDE_SHIFT); 
   2582             } else {
   2583                 if_side &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2584             }
   2585         } 
   2586 
   2587         sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2588         pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2589         pm_phy_copy.access.flags |= if_side; 
   2590         /*sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));*/
   2591  
   2592         SOC_IF_ERROR_RETURN(phymod_phy_power_set(&pm_phy_copy, &power));
   2593     }
   2594 
   2595     return(SOC_E_NONE);
   2596 }
   2597 /*
   2598  * Function:
   2599  *      phy_82109_phy_dump
   2600  * Purpose:
   2601  *      Reads the phy registers. 
   2602  * Parameters:
   2603  *      pc  - phy control structure.
   2604  *      intf - interface side
   2605  * Returns:     
   2606  *      SOC_E_XXX
   2607  */
   2608 STATIC int
   2609 phy_82109_phy_dump(phy_ctrl_t *pc, int32 intf)
   2610 {
   2611     phymod_phy_access_t     *pm_phy;
   2612     int                     idx;
   2613     phymod_phy_access_t pm_phy_copy;
   2614     soc_phymod_ctrl_t *pmc;
   2615     pmc = &pc->phymod_ctrl;
   2616 
   2617     /* loop through all cores */
   2618     for (idx = 0; idx < pmc->num_phys; idx++) {
   2619         pm_phy = &pmc->phy[idx]->pm_phy;
   2620 
   2621         if (pm_phy == NULL) {
   2622             return SOC_E_INTERNAL;
   2623         }
   2624 
   2625         sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2626         pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2627         if(intf == PHY82109_SYS_SIDE) {
   2628             pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 
   2629         }
   2630         SOC_IF_ERROR_RETURN(phymod_phy_status_dump(&pm_phy_copy));
   2631 
   2632     }
   2633 
   2634     return(SOC_E_NONE);
   2635 }
   2636 /*
   2637  * Function:
   2638  *      phy_82109_per_lane_phy_dump
   2639  * Purpose:
   2640  *      Reads the lanewise phy registers. 
   2641  * Parameters:
   2642  *      pc  - phy control structure.
   2643  *      lane - lane number 
   2644  *      intf - interface side
   2645  * Returns:     
   2646  *      SOC_E_XXX
   2647  */
   2648 STATIC int
   2649 phy_82109_per_lane_phy_dump(phy_ctrl_t *pc, int32 intf, int lane)
   2650 {
   2651     phymod_phy_access_t     *pm_phy;
   2652     uint32              lane_map;
   2653     phymod_phy_access_t pm_phy_copy;
   2654     soc_phymod_phy_t    *p_phy;
   2655     soc_phymod_ctrl_t *pmc;
   2656     pmc = &pc->phymod_ctrl;
   2657 
   2658     /* locate the desired phy and lane */
   2659     SOC_IF_ERROR_RETURN(_phy_82109_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map));
   2660 
   2661     /* Make a copy of the phy access and overwrite the desired lane */
   2662     pm_phy = &p_phy->pm_phy;
   2663     sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2664     pm_phy_copy.access.lane_mask = lane_map;
   2665     pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 
   2666     if(intf == PHY82109_SYS_SIDE) {
   2667         pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 
   2668     } 
   2669 
   2670     SOC_IF_ERROR_RETURN(phymod_phy_status_dump(&pm_phy_copy));
   2671     return(SOC_E_NONE);
   2672 }
   2673 /*
   2674  * Function:
   2675  *      phy_82109_gpio_config_set
   2676  * Purpose:
   2677  *      Configures the gpio line. 
   2678  * Parameters:
   2679  *      pc  - phy control structure.
   2680  *      value - value to be programmed 
   2681  * Returns:     
   2682  *      SOC_E_XXX
   2683  */
   2684 STATIC int
   2685 phy_82109_gpio_config_set(phy_ctrl_t *pc, uint32 value)
   2686 {
   2687     phymod_phy_access_t  *pm_phy;
   2688     int                  idx;
   2689     phymod_phy_access_t pm_phy_copy;
   2690     int gpio_mode = 0;
   2691     int gpio_pin_no = 0;
   2692     soc_phymod_ctrl_t *pmc;
   2693     pmc = &pc->phymod_ctrl;
   2694 
   2695     /* loop through all cores */
   2696     for (idx = 0; idx < pmc->num_phys; idx++) {
   2697         pm_phy = &pmc->phy[idx]->pm_phy;
   2698 
   2699         if (pm_phy == NULL) {
   2700             return SOC_E_INTERNAL;
   2701         }
   2702 
   2703         sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2704  
   2705         for (gpio_pin_no = 0; gpio_pin_no < 2; gpio_pin_no++) {
   2706             gpio_mode = (value >> (4 * gpio_pin_no)) & 0xF;
   2707             SOC_IF_ERROR_RETURN(phymod_phy_gpio_config_set(&pm_phy_copy, gpio_pin_no, (phymod_gpio_mode_t)gpio_mode));
   2708         }
   2709     }
   2710 
   2711     return(SOC_E_NONE);
   2712 }
   2713 
   2714 /*
   2715  * Function:
   2716  *      phy_82109_gpio_value_set
   2717  * Purpose:
   2718  *      Programmes the gpio pin. 
   2719  * Parameters:
   2720  *      pc  - phy control structure.
   2721  *      value - value to be programmed 
   2722  * Returns:     
   2723  *      SOC_E_XXX
   2724  */
   2725 STATIC int
   2726 phy_82109_gpio_value_set(phy_ctrl_t *pc, uint32 value)
   2727 {
   2728     phymod_phy_access_t  *pm_phy;
   2729     int                  idx;
   2730     phymod_phy_access_t pm_phy_copy;
   2731     int pin_value = 0;
   2732     int gpio_pin_no = 0;
   2733     soc_phymod_ctrl_t *pmc;
   2734     pmc = &pc->phymod_ctrl;
   2735 
   2736     /* loop through all cores */
   2737     for (idx = 0; idx < pmc->num_phys; idx++) {
   2738         pm_phy = &pmc->phy[idx]->pm_phy;
   2739 
   2740         if (pm_phy == NULL) {
   2741             return SOC_E_INTERNAL;
   2742         }
   2743 
   2744         sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy));
   2745 
   2746         for (gpio_pin_no = 0; gpio_pin_no < 2; gpio_pin_no++) {
   2747             pin_value = (value >> (4 * gpio_pin_no)) & 0xF;
   2748             SOC_IF_ERROR_RETURN(phymod_phy_gpio_pin_value_set(&pm_phy_copy, gpio_pin_no, pin_value));
   2749         }
   2750     }
   2751 
   2752     return(SOC_E_NONE);
   2753 }
   2754 /*
   2755  * Function:
   2756  *      phy_82109_control_set
   2757  * Purpose:
   2758  *      Configure PHY device specific control function. 
   2759  * Parameters:
   2760  *      unit  - BCM unit number.
   2761  *      port  - Port number. 
   2762  *      type  - Control to update 
   2763  *      value - New setting for the control 
   2764  * Returns:     
   2765  *      SOC_E_XXX
   2766  */
   2767 STATIC int
   2768 phy_82109_control_set(int unit, soc_port_t port, soc_phy_control_t type, uint32 value)
   2769 {
   2770     int                 rv;
   2771     phy_ctrl_t          *pc;
   2772     int32 intf;
   2773     rv = SOC_E_UNAVAIL;
   2774     PHY_CONTROL_TYPE_CHECK(type);
   2775     /* locate phy control, phymod control, and the configuration data */
   2776     pc = EXT_PHY_SW_STATE(unit, port);
   2777     if (pc == NULL) {
   2778         return SOC_E_INTERNAL;
   2779     }
   2780     intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82109_SYS_SIDE : PHY82109_LINE_SIDE;
   2781     switch(type) {
   2782     /* TX LANE SQUELCH */
   2783     case SOC_PHY_CONTROL_TX_LANE_SQUELCH:
   2784         rv = phy_82109_tx_lane_squelch(pc, intf, value);
   2785         break;
   2786     /* POWER */
   2787     case SOC_PHY_CONTROL_POWER:
   2788        {
   2789            phy_ctrl_t                *int_pc;
   2790            int_pc = INT_PHY_SW_STATE(unit, port);
   2791            SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, value));
   2792            rv = phy_82109_power_set(pc, intf, value);
   2793        }
   2794        break;
   2795     case SOC_PHY_CONTROL_DUMP:
   2796         rv = phy_82109_phy_dump(pc, intf);
   2797     break;
   2798     case SOC_PHY_CONTROL_GPIO_CONFIG:
   2799         rv = phy_82109_gpio_config_set(pc, value);
   2800     break;
   2801     case SOC_PHY_CONTROL_GPIO_VALUE:
   2802         rv = phy_82109_gpio_value_set(pc, value);
   2803     break;
   2804     default:
   2805         rv = SOC_E_UNAVAIL;
   2806         break; 
   2807     }
   2808     return rv;
   2809 }
   2810 /*
   2811  * Function:
   2812  *      phy_82109_per_lane_control_set
   2813  * Purpose:
   2814  *      Configure PHY device specific control function. 
   2815  * Parameters:
   2816  *      unit  - StrataSwitch unit #.
   2817  *      port  - StrataSwitch port #. 
   2818  *      lane  - lane number
   2819  *      type  - Control to update 
   2820  *      value - New setting for the control 
   2821  * Returns:     
   2822  *      SOC_E_XXX
   2823  */
   2824 STATIC int
   2825 phy_82109_per_lane_control_set(int unit, soc_port_t port, int lane, soc_phy_control_t type, uint32 value)
   2826 {
   2827     int                 rv = SOC_E_UNAVAIL;
   2828     phy_ctrl_t          *pc;
   2829     int32 intf;
   2830     /* locate phy control, phymod control, and the configuration data */
   2831     pc = EXT_PHY_SW_STATE(unit, port);
   2832     if (pc == NULL) {
   2833         return SOC_E_INTERNAL;
   2834     }
   2835     PHY_CONTROL_TYPE_CHECK(type);
   2836 
   2837     intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82109_SYS_SIDE : PHY82109_LINE_SIDE; 
   2838 
   2839     switch(type) {
   2840     /* TX LANE SQUELCH */
   2841     case SOC_PHY_CONTROL_TX_LANE_SQUELCH:
   2842         rv = phy_82109_per_lane_tx_lane_squelch(pc, intf, lane, value);
   2843         break;
   2844     /*POWER */
   2845     case SOC_PHY_CONTROL_POWER:
   2846        rv = phy_82109_per_lane_power_set(pc, intf, lane, value);
   2847        break;
   2848     case SOC_PHY_CONTROL_DUMP:
   2849         rv = phy_82109_per_lane_phy_dump(pc, intf, lane);
   2850     break;
   2851     default:
   2852         rv = SOC_E_UNAVAIL;
   2853         break; 
   2854     }
   2855 
   2856     return rv;
   2857 }
   2858 /*
   2859  * Function:
   2860  *      phy_82109_diag_ctrl
   2861  * Purpose:
   2862  *      xx
   2863  * Parameters:
   2864  *      unit - BCM unit number.
   2865  *      port - Port number. 
   2866 
   2867  * Returns:     
   2868  *      SOC_E_XXX
   2869  */
   2870 
   2871 STATIC int
   2872 phy_82109_diag_ctrl(
   2873     int unit,        /* unit */
   2874     soc_port_t port, /* port */
   2875     uint32 inst,     /* the specific device block the control action directs to */
   2876     int op_type,     /* operation types: read,write or command sequence */
   2877     int op_cmd,      /* command code */
   2878     void *arg)       /* command argument based on op_type/op_cmd */
   2879 {
   2880     int rv = -1;
   2881     phy_ctrl_t          *pc;
   2882     /* locate phy control, phymod control, and the configuration data */
   2883     pc = EXT_PHY_SW_STATE(unit, port);
   2884     if (pc == NULL) {
   2885         return SOC_E_INTERNAL;
   2886     }
   2887     switch(op_cmd) {
   2888         case PHY_DIAG_CTRL_DSC:
   2889         case PHY_DIAG_CTRL_LINKMON_MODE:
   2890         case PHY_DIAG_CTRL_LINKMON_STATUS:
   2891             rv = SOC_E_UNAVAIL;
   2892             break;
   2893         default:
   2894             if (op_type == PHY_DIAG_CTRL_SET) {
   2895                     rv = phy_82109_control_set(unit,port,op_cmd,PTR_TO_INT(arg));
   2896             } else if (op_type == PHY_DIAG_CTRL_GET) {
   2897                     rv = phy_82109_control_get(unit,port,op_cmd,(uint32 *)arg);
   2898             }
   2899             break ;
   2900         }
   2901     return rv;
   2902 }
   2903 
   2904 /*
   2905 * Function:
   2906 *      _phy_82109_core_reset
   2907 * Purpose:
   2908 *      Reset's the phy core.
   2909 * Parameters:
   2910 *      unit - StrataSwitch unit #.
   2911 *      port - StrataSwitch port #.
   2912 *      not_used - don't care.
   2913 * Returns:
   2914 *      SOC_E_XXX
   2915 */
   2916 int32 phy_82109_core_reset(int32 unit, soc_port_t port, void *not_used)
   2917 {
   2918     phy_ctrl_t                *pc;
   2919     soc_phymod_core_t *pmc_core;
   2920     int                  idx;
   2921     phymod_core_access_t *pm_core;
   2922     soc_phymod_ctrl_t *pmc;
   2923     phymod_reset_direction_t reset_direction;
   2924     /* locate phy control */
   2925     pc = EXT_PHY_SW_STATE(unit, port);
   2926     if (pc == NULL) {
   2927         return SOC_E_INTERNAL;
   2928     }
   2929     reset_direction = phymodResetDirectionIn;
   2930     pmc = &pc->phymod_ctrl; 
   2931 
   2932     /* loop through all cores */
   2933     for (idx = 0; idx < pmc->num_phys; idx++) {
   2934         pmc_core = pmc->phy[idx]->core;
   2935         pm_core = &pmc_core->pm_core;
   2936         if (pm_core == NULL) {
   2937             return SOC_E_INTERNAL;
   2938         }
   2939         /* Soft reset is not supported in Huracan */
   2940         SOC_IF_ERROR_RETURN(phymod_core_reset_set(pm_core, phymodResetModeHard, reset_direction));
   2941     }
   2942     return(SOC_E_NONE);
   2943 }
   2944 /*
   2945 * Function:
   2946 *      _phy_82109_ability_remote_get
   2947 * Purpose:
   2948 *      Get the device's complete abilities.
   2949 * Parameters:
   2950 *      unit - StrataSwitch unit #.
   2951 *      port - StrataSwitch port #.
   2952 *      ability - return device's abilities.
   2953 * Returns:
   2954 *      SOC_E_XXX
   2955 */
   2956 STATIC int
   2957 phy_82109_ability_remote_get(int unit, soc_port_t port, 
   2958                                   soc_port_ability_t *ability)
   2959 {
   2960     return SOC_E_NONE;
   2961 }
   2962 /*
   2963  * Variable:
   2964  *      phy82109_drv
   2965  * Purpose:
   2966  *      Phy Driver for phy82109 
   2967  */
   2968 phy_driver_t phy82109_drv = {
   2969     /* .drv_name                      = */ "PHY82109 PHYMOD PHY Driver",
   2970     /* .pd_init                       = */ phy_82109_init,
   2971     /* .pd_reset                      = */ phy_82109_core_reset,
   2972     /* .pd_link_get                   = */ phy_82109_link_get,
   2973     /* .pd_enable_set                 = */ phy_82109_enable_set,
   2974     /* .pd_enable_get                 = */ phy_82109_enable_get,
   2975     /* .pd_duplex_set                 = */ phy_null_set,
   2976     /* .pd_duplex_get                 = */ phy82109_duplex_get,
   2977     /* .pd_speed_set                  = */ phy82109_speed_set,
   2978     /* .pd_speed_get                  = */ phy82109_speed_get,
   2979     /* .pd_master_set                 = */ phy_null_set,
   2980     /* .pd_master_get                 = */ phy_null_zero_get,
   2981     /* .pd_an_set                     = */ phy_82109_an_set,
   2982     /* .pd_an_get                     = */ phy_82109_an_get,
   2983 
   2984     /* .pd_adv_local_set              = */ NULL, /* Deprecated */
   2985     /* .pd_adv_local_get              = */ NULL, /* Deprecated */
   2986     /* .pd_adv_remote_get             = */ NULL, /* Deprecated */ 
   2987     /* .pd_lb_set                     = */ phy_82109_lb_set,
   2988     /* .pd_lb_get                     = */ phy82109_lb_get,
   2989     /* .pd_interface_set              = */ phy82109_interface_set,
   2990     /* .pd_interface_get              = */ phy82109_interface_get,
   2991     /* .pd_ability                    = */ NULL, /* Deprecated */ 
   2992     /* .pd_linkup_evt                 = */ NULL,
   2993     /* .pd_linkdn_evt                 = */ NULL,
   2994     /* .pd_mdix_set                   = */ phy_null_mdix_set,
   2995     /* .pd_mdix_get                   = */ phy_null_mdix_get,
   2996     /* .pd_mdix_status_get            = */ phy_null_mdix_status_get,
   2997     /* .pd_medium_config_set          = */ NULL,
   2998     /* .pd_medium_config_get          = */ NULL,
   2999     /* .pd_medium_get                 = */ phy_null_medium_get,
   3000     /* .pd_cable_diag                 = */ NULL,
   3001     /* .pd_link_change                = */ NULL,
   3002     /* .pd_control_set                = */ phy_82109_control_set,
   3003     /* .pd_control_get                = */ phy_82109_control_get,
   3004     /* .pd_reg_read                   = */ phy82109_reg_read,
   3005     /* .pd_reg_write                  = */ phy82109_reg_write,
   3006     /* .pd_reg_modify                 = */ phy82109_reg_modify,
   3007     /* .pd_notify                     = */ NULL,
   3008     /* .pd_probe                      = */ phy82109_probe,
   3009     /* .pd_ability_advert_set         = */ phy_82109_ability_advert_set, 
   3010     /* .pd_ability_advert_get         = */ phy_82109_ability_advert_get,
   3011     /* .pd_ability_remote_get         = */ phy_82109_ability_remote_get,
   3012     /* .pd_ability_local_get          = */ phy_82109_ability_local_get,
   3013     /* .pd_firmware_set               = */ phy_82109_firmware_set,
   3014     /* .pd_timesync_config_set        = */ NULL,
   3015     /* .pd_timesync_config_get        = */ NULL,
   3016     /* .pd_timesync_control_set       = */ NULL,
   3017     /* .pd_timesync_control_set       = */ NULL,
   3018     /* .pd_diag_ctrl                  = */ phy_82109_diag_ctrl,
   3019     /* .pd_lane_control_set           = */ phy_82109_per_lane_control_set,    
   3020     /* .pd_lane_control_get           = */ phy_82109_per_lane_control_get 
   3021 };
   3022 
   3023 #else
   3024 int _phy82109_not_empty;
   3025 
   3026 #endif /*  INCLUDE_PHY_82109 */
   3027