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

greyhound2_tdm.c (17718B)


      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:        greyhound2_tdm.c
      8  * Purpose:
      9  * Requires:
     10  */
     11 
     12 
     13 #include <shared/bsl.h>
     14 #include <soc/tdm/core/tdm_top.h>
     15 
     16 #include <soc/defs.h>
     17 #include <soc/mem.h>
     18 
     19 #if defined(BCM_GREYHOUND2_SUPPORT)
     20 #include <soc/greyhound2.h>
     21 #include <soc/greyhound2_tdm.h>
     22 #include <soc/tdm/greyhound2/tdm_gh2_defines.h>
     23 
     24 
     25 /*** START SDK API COMMON CODE ***/
     26 
     27 /*! @fn void _soc_gh2_tdm_print_port_map(
     28         int unit,
     29         soc_port_map_type_t *port_map)
     30     @param unit Chip unit number.
     31     @param port_map Pointer to a soc_port_map_type_t struct variable.
     32     @brief Debug API to print soc_port_map_type_t
     33  */
     34 void
     35 _soc_gh2_tdm_print_port_map(int unit, soc_port_map_type_t *port_map)
     36 {
     37     int port;
     38     int is_hg2;
     39     int speed, phy_port, idb_port, mmu_port, num_lanes;
     40     int phy_bmap, p2l_map, m2p_map;
     41 
     42     for (port = 0; port < GREYHOUND2_TDM_LOG_PORTS_PER_DEV; port++) {
     43         if (port_map->log_port_speed[port] > 0) {
     44             speed = port_map->log_port_speed[port] / 1000;
     45             phy_port = port_map->port_l2p_mapping[port];
     46             idb_port = port_map->port_l2i_mapping[port];
     47             mmu_port = port_map->port_p2m_mapping[phy_port];
     48             num_lanes = port_map->port_num_lanes[port];
     49             phy_bmap = SOC_PBMP_MEMBER(port_map->physical_pbm,
     50                                        phy_port) ? 1 : 0;
     51             is_hg2 = SOC_PBMP_MEMBER(port_map->hg2_pbm, port) ? 1 : 0;
     52             p2l_map = port_map->port_p2l_mapping[phy_port];
     53             m2p_map = port_map->port_m2p_mapping[mmu_port];
     54             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
     55                         "log_port=%3d phy_port=%3d speed=%3dG "
     56                         "%s idb_port=%3d mmu_port=%3d "
     57                         "num_lanes=%1d phy_bmap=%1d "
     58                         "p2l_map=%3d "),
     59                         port, phy_port, speed,
     60                         (is_hg2 == 1) ? "HG2" : "ETH",
     61                         idb_port, mmu_port, num_lanes,
     62                         phy_bmap, p2l_map));
     63             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
     64                         "m2p_map=%3d\n"),
     65                          m2p_map));
     66         }
     67     }
     68 }
     69 
     70 /*! @fn void _soc_gh2_tdm_print_tdm_info(
     71         int unit,
     72         soc_tdm_schedule_t *tdm_info)
     73     @param unit Chip unit number.
     74     @param tdm_info Pointer to a soc_tdm_schedule_t struct variable.
     75     @brief Debug API to print soc_tdm_schedule_t
     76  */
     77 void
     78 _soc_gh2_tdm_print_tdm_info(int unit, soc_tdm_schedule_t *tdm_info)
     79 {
     80     int cal_len, j;
     81 
     82     for (cal_len = tdm_info->cal_len; cal_len > 0; cal_len--) {
     83         if (tdm_info->linerate_schedule[cal_len - 1] != GH2_NUM_EXT_PORTS) {
     84             break;
     85         }
     86     }
     87 
     88     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
     89                 "\tMAIN CALENDAR: cal_len=%3d \n"),
     90                 cal_len ));
     91     for (j = 0; j < cal_len; j++) {
     92         if (j % 16 == 0) {
     93             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
     94                         "\n%3d :%3d\t"),
     95                         j, j + 15));
     96         }
     97         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
     98                     "%4d"),
     99                     tdm_info->linerate_schedule[j]));
    100     }
    101 
    102     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    103 }
    104 
    105 
    106 /*! @fn void _soc_gh2_tdm_print_schedule_state(
    107         int unit,
    108         soc_port_schedule_state_t *sch_info)
    109     @param unit Chip unit number.
    110     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    111     @brief Debug API to print sch_info
    112  */
    113 void
    114 _soc_gh2_tdm_print_schedule_state(int unit,
    115                                   soc_port_schedule_state_t *sch_info)
    116 {
    117     int print_tdm;
    118     soc_tdm_schedule_t *tdm_schedule;
    119 
    120     print_tdm = 1;
    121 
    122     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    123                 "\n\nPRINTING soc_port_schedule_state_t \n")));
    124     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    125                 "nport= %3d\n"),
    126                 sch_info->nport));
    127     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    128                 "frequency= %4dMHz\n"),
    129                 sch_info->frequency));
    130     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    131                 "bandwidth= %4d\n"),
    132                 sch_info->bandwidth));
    133     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    134                 "io_bandwidth= %4d\n"),
    135                 sch_info->io_bandwidth));
    136 
    137     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    138                 "\nPRINTING soc_port_schedule_state_t"
    139                 "::[in_port_map]\n")));
    140     _soc_gh2_tdm_print_port_map(unit, &sch_info->in_port_map);
    141 
    142 
    143     if (print_tdm == 1) {
    144         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    145                     "\n====== TDM Tables \n")));
    146         tdm_schedule = &(sch_info->tdm_ingress_schedule_pipe[0]. \
    147                            tdm_schedule_slice[0]);
    148         _soc_gh2_tdm_print_tdm_info(unit, tdm_schedule);
    149     }
    150 }
    151 
    152 /*! @fn int _soc_gh2_tdm_calculation(
    153         int unit,
    154         soc_port_schedule_state_t *sch_info)
    155     @param unit Chip unit number.
    156     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    157     @brief API to calculate TDM tables.
    158  */
    159 int
    160 _soc_gh2_tdm_calculation(int unit, soc_port_schedule_state_t *sch_info)
    161 {
    162     int i, phy_port, lgc_port;
    163     int pipe = 0;
    164     int index;
    165     int mgmt_pm_hg = 0;
    166     int tdm_idb_cal_len;
    167     int *tdm_idb_pipe_main;
    168     tdm_soc_t _chip_pkg;
    169     tdm_mod_t *_tdm_pkg;
    170     uint32 port_speeds[GREYHOUND2_TDM_PHY_PORTS_PER_DEV];
    171     uint32 port_states[GREYHOUND2_TDM_PHY_PORTS_PER_DEV];
    172     int tdm_realloc = 0;
    173 
    174     sal_memset(port_speeds, 0,
    175                GREYHOUND2_TDM_PHY_PORTS_PER_DEV * sizeof(uint32));
    176     sal_memset(port_states, 0,
    177                GREYHOUND2_TDM_PHY_PORTS_PER_DEV * sizeof(uint32));
    178 
    179     /* Remap input speeds to ETH bitrates */
    180     soc_gh2_port_schedule_speed_remap(unit, sch_info);
    181 
    182     /* Check if TDM reallocation required. */
    183     tdm_realloc = soc_greyhound2_auto_tdm_realloc(unit);
    184     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    185                 "TDM reallocation %s.\n"),
    186                 tdm_realloc ? "on" : "off"));
    187 
    188     /* Set port states and speeds */
    189     for (lgc_port = 0;
    190         lgc_port < GREYHOUND2_TDM_PHY_PORTS_PER_DEV; lgc_port++) {
    191         if (sch_info->in_port_map.log_port_speed[lgc_port] > 0 ) {
    192             phy_port = sch_info->in_port_map.port_l2p_mapping[lgc_port];
    193 
    194             if (tdm_realloc) {
    195                 if ((sch_info->in_port_map.log_port_speed[lgc_port] == 1000) &&
    196                     (lgc_port != 0)) {
    197                     sch_info->in_port_map.log_port_speed[lgc_port] = 2500;
    198                     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    199                                 "TDM reallocation. "
    200                                 "Override lport(%d) speed to 2.5G\n"),
    201                                 lgc_port));
    202                 }
    203             }
    204 
    205             if (phy_port < GREYHOUND2_TDM_PHY_PORTS_PER_DEV) {
    206                 if (SOC_PBMP_MEMBER(sch_info->in_port_map.hg2_pbm, lgc_port)) {
    207                     port_states[phy_port] = PORT_STATE__LINERATE_HG;
    208                 } else {
    209                     port_states[phy_port] = PORT_STATE__LINERATE;
    210                 }
    211                 port_speeds[phy_port] = sch_info->in_port_map. \
    212                                             log_port_speed[lgc_port];
    213             }
    214         }
    215     }
    216     /* Print input config */
    217     if (LOG_CHECK(BSL_LS_SOC_TDM | BSL_INFO)) {
    218         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    219                     "frequency: %dMHz\n"),
    220                     sch_info->frequency));
    221         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    222                     "%8s%8s%8s\n"),
    223                     "port", "speed", "state"));
    224         for (phy_port = 0;
    225              phy_port < GREYHOUND2_TDM_PHY_PORTS_PER_DEV; phy_port++) {
    226             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    227                         "%8d%8d%8d\n"),
    228                         phy_port, port_speeds[phy_port] / 1000,
    229                         port_states[phy_port]));
    230         }
    231         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    232     }
    233     /* Initialize input variables for SW TDM Generation:
    234        -- unit
    235        -- num_ext_ports
    236        -- state
    237        -- speed
    238        -- clk_freq
    239     */
    240     _chip_pkg.unit = unit;
    241     _chip_pkg.num_ext_ports = GH2_NUM_EXT_PORTS;
    242     _chip_pkg.state = sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int),
    243                                 "port state list");
    244     if (_chip_pkg.state == NULL) {
    245         return SOC_E_MEMORY;
    246     }
    247     _chip_pkg.speed = sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int),
    248                                 "port speed list");
    249     if (_chip_pkg.speed == NULL) {
    250         sal_free(_chip_pkg.state);
    251         return SOC_E_MEMORY;
    252     }
    253     for (index = 0; index < _chip_pkg.num_ext_ports; index++) {
    254         _chip_pkg.state[index] = 0;
    255         _chip_pkg.speed[index] = 0;
    256     }
    257     for (index = 0;
    258          index < _chip_pkg.num_ext_ports &&
    259          index < GREYHOUND2_TDM_PHY_PORTS_PER_DEV; index++) {
    260         _chip_pkg.state[index] = port_states[index];
    261         _chip_pkg.speed[index] = port_speeds[index];
    262     }
    263     /* Shift port state to left one position; required by C_TDM */
    264     for (index = 1; index < _chip_pkg.num_ext_ports; index++) {
    265         _chip_pkg.state[index - 1] = _chip_pkg.state[index];
    266     }
    267     _chip_pkg.clk_freq = sch_info->frequency;
    268     _chip_pkg.soc_vars.gh2.mgmt_pm_hg = mgmt_pm_hg;
    269     _chip_pkg.soc_vars.gh2.tdm_chk_en = 1;
    270 
    271     /* Populate TDM tables by invoking SW TDM API */
    272     /* coverity[uninit_use_in_call : FALSE] */
    273     _tdm_pkg = _soc_set_tdm_tbl(SOC_SEL_TDM(&_chip_pkg));
    274 
    275     /* Free the memory allocated to port states and speeds */
    276     sal_free(_chip_pkg.state);
    277     sal_free(_chip_pkg.speed);
    278 
    279     /* Copy TDM result into output structure */
    280     if (_tdm_pkg == NULL) {
    281         LOG_CLI((BSL_META_U(unit,
    282                             "Unsupported config for TDM calendar "
    283                             "generation\n")));
    284         return SOC_E_FAIL;
    285     } else {
    286         /* IDB calendar (0) */
    287         tdm_idb_pipe_main = _tdm_pkg->_chip_data.cal_0.cal_main;
    288         tdm_idb_cal_len = _tdm_pkg->_chip_data.cal_0.cal_len;
    289 
    290         if (tdm_idb_pipe_main == NULL) {
    291             LOG_CLI((BSL_META_U(unit,
    292                                 "Unsupported config for TDM calendar "
    293                                 "generation\n")));
    294             tdm_gh2_free(_tdm_pkg);
    295             sal_free(_tdm_pkg);
    296             return SOC_E_FAIL;
    297         } else {
    298             /* IDB TDM main calendar */
    299             for (index = 0; index < tdm_idb_cal_len; index++) {
    300                 sch_info->tdm_ingress_schedule_pipe[pipe]. \
    301                     tdm_schedule_slice[0].linerate_schedule[index] = \
    302                 tdm_idb_pipe_main[index];
    303             }
    304             sch_info->tdm_ingress_schedule_pipe[pipe].tdm_schedule_slice[0]. \
    305                 cal_len = tdm_idb_cal_len;
    306         }
    307 
    308         /* Free the memory allocated in TDM algorithm code */
    309         tdm_gh2_free(_tdm_pkg);
    310         sal_free(_tdm_pkg);
    311     }
    312 
    313     /* Print TDM result */
    314     pipe = 0;
    315     /* IDB TDM main calendar */
    316     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    317                 "Pipe %d [IDB TDM main calendar]\n"),
    318                 pipe));
    319     for (index = 0; index < MAX_CAL_LEN; index++) {
    320         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    321                     " %3d"),
    322                     sch_info->tdm_ingress_schedule_pipe[pipe]. \
    323                       tdm_schedule_slice[0].linerate_schedule[index]));
    324         if (((index + 1) % 16 == 0) && index > 0) {
    325             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    326         }
    327     }
    328     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    329 
    330     /* If init then just copy in_port_map to out_port_map*/
    331     if (sch_info->is_flexport == 0) {
    332         for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
    333             sch_info->out_port_map.log_port_speed[i] =
    334                 sch_info->in_port_map.log_port_speed[i];
    335             sch_info->out_port_map.port_p2l_mapping[i] =
    336                 sch_info->in_port_map.port_p2l_mapping[i];
    337             sch_info->out_port_map.port_l2p_mapping[i] =
    338                 sch_info->in_port_map.port_l2p_mapping[i];
    339             sch_info->out_port_map.port_p2m_mapping[i] =
    340                 sch_info->in_port_map.port_p2m_mapping[i];
    341             sch_info->out_port_map.port_num_lanes[i] =
    342                 sch_info->in_port_map.port_num_lanes[i];
    343         }
    344         for (i = 0; i < SOC_MAX_NUM_MMU_PORTS; i++) {
    345             sch_info->out_port_map.port_m2p_mapping[i] =
    346                 sch_info->in_port_map.port_m2p_mapping[i];
    347         }
    348         for (i = 0; i < _SHR_PBMP_WORD_MAX; i++) {
    349             sch_info->out_port_map.physical_pbm.pbits[i] =
    350                 sch_info->in_port_map.physical_pbm.pbits[i];
    351             sch_info->out_port_map.hg2_pbm.pbits[i] =
    352                 sch_info->in_port_map.hg2_pbm.pbits[i];
    353         }
    354     }
    355 
    356     _soc_gh2_tdm_print_schedule_state(unit, sch_info);
    357 
    358     return SOC_E_NONE;
    359 }
    360 
    361 
    362 /*! @fn int _soc_gh2_tdm_set_idb_calendar(
    363         int unit,
    364         soc_port_schedule_state_t *sch_info)
    365     @param unit Chip unit number.
    366     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    367     @brief API to initialize the TD3 IDB main calendar.
    368  */
    369 int
    370 _soc_gh2_tdm_set_idb_calendar(int unit, soc_port_schedule_state_t *sch_info)
    371 {
    372     int rv = SOC_E_NONE;
    373     uint32 cal_len;
    374     int pipe, slot, length;
    375     uint32 rval;
    376     iarb_tdm_table_entry_t iarb_tdm;
    377     mmu_arb_tdm_table_entry_t mmu_arb_tdm;
    378     int mmu_port, phy_port;
    379     soc_info_t *si;
    380 
    381     si = &SOC_INFO(unit);
    382 
    383     pipe = 0;
    384     /* TDM Calendar is always taken from slice 0 */
    385     cal_len = sch_info->tdm_ingress_schedule_pipe[pipe]. \
    386                   tdm_schedule_slice[0].cal_len;
    387     for (length = cal_len; length > 0; length--) {
    388         if (sch_info->tdm_ingress_schedule_pipe[pipe].tdm_schedule_slice[
    389                 0].linerate_schedule[length - 1] != GH2_NUM_EXT_PORTS) {
    390             break;
    391         }
    392     }
    393 
    394     SOC_IF_ERROR_RETURN(READ_IARB_TDM_CONTROLr(unit, &rval));
    395     soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, DISABLEf, 1);
    396     soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, TDM_WRAP_PTRf, 83);
    397     SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_CONTROLr(unit, rval));
    398 
    399     for (slot = 0; slot < length; slot ++) {
    400         phy_port = sch_info->tdm_ingress_schedule_pipe[
    401             pipe].tdm_schedule_slice[0].linerate_schedule[slot];
    402         if (phy_port == -1) {
    403             /* Convert IDLE slot definition */
    404             phy_port = 127;
    405         }
    406         mmu_port = (phy_port != 127) ? si->port_p2m_mapping[phy_port] : 127;
    407 
    408         sal_memset(&iarb_tdm, 0, sizeof(iarb_tdm_table_entry_t));
    409         sal_memset(&mmu_arb_tdm, 0, sizeof(mmu_arb_tdm_table_entry_t));
    410 
    411         soc_IARB_TDM_TABLEm_field32_set(unit, &iarb_tdm, PORT_NUMf,
    412                                         phy_port);
    413         soc_MMU_ARB_TDM_TABLEm_field32_set(unit, &mmu_arb_tdm, PORT_NUMf,
    414                                         mmu_port);
    415 
    416         if (slot == length - 1) {
    417             soc_MMU_ARB_TDM_TABLEm_field32_set(unit, &mmu_arb_tdm, WRAP_ENf, 1);
    418         }
    419         SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_TABLEm(unit, SOC_BLOCK_ALL, slot,
    420                                                 &iarb_tdm));
    421         SOC_IF_ERROR_RETURN(WRITE_MMU_ARB_TDM_TABLEm(unit, SOC_BLOCK_ALL, slot,
    422                                                     &mmu_arb_tdm));
    423 
    424     }
    425     rval = 0;
    426     soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, DISABLEf, 0);
    427     soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, TDM_WRAP_PTRf,
    428                     length -1);
    429     SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_CONTROLr(unit, rval));
    430 
    431     /* Update TDM size info */
    432     rv = soc_gh2_tdm_size_set(unit, length);
    433 
    434     return rv;
    435 }
    436 
    437 /*! @fn int soc_gh2_tdm_init(
    438         int unit,
    439         soc_port_schedule_state_t *sch_info)
    440     @param unit Chip unit number.
    441     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    442     @brief Main API for TDM init
    443  */
    444 int soc_gh2_tdm_init(int unit, soc_port_schedule_state_t *sch_info)
    445 {
    446     SOC_IF_ERROR_RETURN(_soc_gh2_tdm_calculation(unit, sch_info));
    447 
    448     SOC_IF_ERROR_RETURN(_soc_gh2_tdm_set_idb_calendar(unit, sch_info));
    449 
    450     return SOC_E_NONE;
    451 }
    452 
    453 /*! @fn int soc_gh2_port_speed_higig2eth(int speed)
    454  *  @param int speed
    455  *  @brief Map port speed to ETH bitrates
    456  */
    457 static int
    458 soc_gh2_port_speed_higig2eth(int speed)
    459 {
    460     switch (speed) {
    461     case 11000:
    462         /* 10G */
    463         return 10000;
    464     case 21000:
    465         /* 20G */
    466         return 20000;
    467     case 42000:
    468         /* 40G */
    469         return 40000;
    470     case 53000:
    471         /* 50G */
    472         return 50000;
    473     default:
    474         return speed;
    475     }
    476 }
    477 
    478 /*! @fn void soc_gh2_port_schedule_speed_remap(int unit,
    479  *               soc_port_schedule_state_t *port_schedule_state)
    480  *  @param unit Chip unit number.
    481  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
    482  *         variable.
    483  *  @brief API to remap speeds to ETH bitrates
    484  */
    485 void
    486 soc_gh2_port_schedule_speed_remap(
    487     int  unit,
    488     soc_port_schedule_state_t *port_schedule_state)
    489 {
    490     int port;
    491 
    492     /* Speed remap for in_port_map*/
    493     for (port = 0; port < SOC_MAX_NUM_PORTS; port++) {
    494         port_schedule_state->in_port_map.log_port_speed[port] =
    495             soc_gh2_port_speed_higig2eth(
    496                 port_schedule_state->in_port_map.log_port_speed[port]);
    497     }
    498 
    499 }
    500 
    501 /*** END SDK API COMMON CODE ***/
    502 
    503 #endif /* BCM_GREYHOUND2_SUPPORT */