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

trident3_tdm.c (87116B)


      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:        trident3_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_TRIDENT3_SUPPORT)
     20 #include <soc/trident3.h>
     21 #include <soc/trident3_tdm.h>
     22 #include <soc/tdm/trident3/tdm_td3_defines.h>
     23 
     24 
     25 /*** START SDK API COMMON CODE ***/
     26 
     27 /*! @fn void _soc_td3_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_td3_tdm_print_port_map(int unit, soc_port_map_type_t *port_map)
     36 {
     37     int port;
     38     int is_hg2, is_ovs, is_mgm;
     39     int speed, phy_port, idb_port, mmu_port, num_lanes, pblk;
     40     int phy_bmap, p2l_map, m2p_map;
     41 
     42     for (port = 0; port < SOC_MAX_NUM_PORTS; port++) {
     43         is_mgm = SOC_PBMP_MEMBER(port_map->management_pbm, port) ? 1 : 0;
     44         if ((is_mgm == 1) || (port_map->log_port_speed[port] > 0)) {
     45             speed     = is_mgm ? 10 : port_map->log_port_speed[port]/1000;
     46             phy_port  = port_map->port_l2p_mapping[port];
     47             idb_port  = port_map->port_l2i_mapping[port];
     48             mmu_port  = port_map->port_p2m_mapping[phy_port];
     49             num_lanes = port_map->port_num_lanes[port];
     50             pblk      = port_map->port_p2PBLK_inst_mapping[phy_port];
     51             phy_bmap  = SOC_PBMP_MEMBER(port_map->physical_pbm, phy_port) ? 1 : 0;
     52             is_hg2    = SOC_PBMP_MEMBER(port_map->hg2_pbm, port) ? 1 : 0;
     53             is_ovs    = SOC_PBMP_MEMBER(port_map->oversub_pbm, port) ? 1 : 0;
     54             p2l_map   = port_map->port_p2l_mapping[phy_port];
     55             m2p_map   = port_map->port_m2p_mapping[mmu_port];
     56             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
     57                                 "log_port=%3d phy_port=%3d speed=%3dG "
     58                                 "%s %s idb_port=%3d mmu_port=%3d "
     59                                 "num_lanes=%1d pblk=%3d phy_bmap=%1d "
     60                                 "p2l_map=%3d "),
     61                                 port, phy_port, speed,
     62                                 (is_hg2==1) ? "HG2" : "ETH",
     63                                 (is_ovs==1) ? "OVS" : " LR",
     64                                 idb_port, mmu_port, num_lanes, pblk,
     65                                 phy_bmap, p2l_map));
     66             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "m2p_map=%3d %s\n"),
     67                                 m2p_map, (is_mgm==1) ? "MGM" : "" ));
     68         }
     69     }
     70 
     71 }
     72 
     73 
     74 /*! @fn void _soc_td3_tdm_print_tdm_info(
     75         int unit,
     76         soc_tdm_schedule_t *tdm_info,
     77         int hpipe,
     78         int is_ing)
     79     @param unit Chip unit number.
     80     @param tdm_info Pointer to a soc_tdm_schedule_t struct variable.
     81     @param hpipe Half Pipe.
     82     @param is_ing distinguishes between IP and EP schedulers
     83     @brief Debug API to print soc_tdm_schedule_t
     84  */
     85 void
     86 _soc_td3_tdm_print_tdm_info(int unit, soc_tdm_schedule_t *tdm_info,
     87                             int hpipe, int is_ing)
     88 {
     89     int cal_len, j, m;
     90 
     91     if (hpipe == 0) {
     92         for (cal_len = tdm_info->cal_len; cal_len > 0; cal_len--) {
     93             if (tdm_info->linerate_schedule[cal_len - 1] != TD3_NUM_EXT_PORTS) {
     94                 break;
     95             }
     96         }
     97 
     98         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
     99                             "\tMAIN CALENDAR: cal_len=%3d \n"),
    100                             cal_len ));
    101         for (j=0; j < cal_len; j++) {
    102             if (j%16==0) {
    103                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    104                                     "\n %3d : %3d\t"),
    105                                     j, j+15));
    106             }
    107             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    108                                 "%5d"),
    109                                 tdm_info->linerate_schedule[j]));
    110         }
    111     }
    112 
    113     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    114                         "\n\n\tOVS TABLES: HPIPE= %3d \n"),
    115                         hpipe ));
    116     for (j=0; j< tdm_info->num_ovs_groups; j++) {
    117         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    118                             "\nOVS_CAL[%d]:\t"),
    119                             j ));
    120         for (m=0; m< tdm_info->ovs_group_len; m++) {
    121             if (tdm_info->oversub_schedule[j][m] != TD3_NUM_EXT_PORTS) {
    122                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    123                                     "%d\t"),
    124                                     tdm_info->oversub_schedule[j][m] ));
    125             } else {
    126                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    127                                     "---\t")));
    128             }
    129         }
    130     }
    131 
    132     if (is_ing == 1) {
    133         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    134                             "\n\n\tPKT_SCHEDULER: HPIPE= %3d \n"),
    135                             hpipe ));
    136         for (j=0; j<tdm_info->pkt_sch_or_ovs_space_len; j++) {
    137             if (j%16==0) {
    138                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    139                                     "\n %3d : %3d\t"),
    140                                     j, j+15 ));
    141             }
    142             if (tdm_info->pkt_sch_or_ovs_space[0][j] != TD3_NUM_EXT_PORTS) {
    143                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    144                                     "\t%d"),
    145                                     tdm_info->pkt_sch_or_ovs_space[0][j] ));
    146             } else {
    147                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    148                                     "\t---")));
    149             }
    150         }
    151     }
    152     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,"\n")));
    153 }
    154 
    155 
    156 /*! @fn void _soc_td3_tdm_print_port_resource(
    157         int unit,
    158         soc_port_resource_t *port_info,
    159         int entry_num)
    160     @param unit Chip unit number.
    161     @param port_info Pointer to a soc_port_resource_t struct variable.
    162     @param entry_num entry number.
    163     @brief Debug API to print soc_port_resource_t
    164  */
    165 void
    166 _soc_td3_tdm_print_port_resource(int unit,
    167                                  soc_port_resource_t *port_info,
    168                                  int entry_num)
    169 {
    170     int is_hg2, lane;
    171 
    172     is_hg2 = 0;
    173     if (port_info->encap == _SHR_PORT_ENCAP_HIGIG2) {
    174         is_hg2=1;
    175     }
    176 
    177     if (port_info->physical_port == -1) {
    178         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    179                             "nport=%3d DOWN: "
    180                             "logical_port=%3d physical_port=%3d\n"),
    181                             entry_num, port_info->logical_port,
    182                             port_info->physical_port));
    183     } else {
    184         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    185                             "nport=%3d  UP : "
    186                             "logical_port=%3d physical_port=%3d mmu_port=%3d "),
    187                             entry_num, port_info->logical_port,
    188                             port_info->physical_port,
    189                             port_info->mmu_port ));
    190         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    191                             "idb_port=%3d pipe=%3d speed=%3d num_lanes=%1d "
    192                             "%s  %s\n"),
    193                             port_info->idb_port,
    194                             port_info->pipe, port_info->speed/1000,
    195                             port_info->num_lanes,
    196                             (is_hg2==1) ? "HG2": "ETH",
    197                             (port_info->oversub==1) ? "OVS": " LR" ));
    198         for (lane = 0; lane < SOC_PORT_RESOURCE_LANES_MAX; lane++) {
    199             if (port_info->lane_info[lane] != NULL) {
    200                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    201                                     "nport=%3d lane_info[%d]: pgw=%3d"
    202                                     "xlp=%3d port_index=%3d\n"),
    203                                     entry_num, lane,
    204                                     port_info->lane_info[lane]->pgw,
    205                                     port_info->lane_info[lane]->xlp,
    206                                     port_info->lane_info[lane]->port_index));
    207             }
    208         }
    209     }
    210 }
    211 
    212 
    213 /*! @fn void _soc_td3_tdm_print_schedule_state(
    214         int unit,
    215         soc_port_schedule_state_t *sch_info)
    216     @param unit Chip unit number.
    217     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    218     @brief Debug API to print sch_info
    219  */
    220 void
    221 _soc_td3_tdm_print_schedule_state(int unit,
    222                                   soc_port_schedule_state_t *sch_info)
    223 {
    224     int i, pipe, hpipe, print_tdm;
    225     soc_tdm_schedule_t *tdm_schedule;
    226 
    227     print_tdm = 1;
    228 
    229     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    230                         "\n\nPRINTING soc_port_schedule_state_t \n")));
    231     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    232                         "nport= %3d\n"),
    233                         sch_info->nport));
    234     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    235                         "frequency= %4dMHz\n"),
    236                         sch_info->frequency));
    237     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    238                         "bandwidth= %4d\n"),
    239                         sch_info->bandwidth));
    240     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    241                         "io_bandwidth= %4d\n"),
    242                         sch_info->io_bandwidth));
    243     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    244                         "lossless= %1d\n"),
    245                         sch_info->lossless));
    246     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    247                         "is_flexport= %1d\n"),
    248                         sch_info->is_flexport));
    249 
    250     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    251                         "\nPRINTING soc_port_schedule_state_t"
    252                         "::[in_port_map]\n")));
    253     _soc_td3_tdm_print_port_map(unit, &sch_info->in_port_map);
    254 
    255     if (sch_info->is_flexport == 1) {
    256         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    257                             "\nPRINTING soc_port_schedule_state_t"
    258                             "::[out_port_map]\n")));
    259         _soc_td3_tdm_print_port_map(unit, &sch_info->out_port_map);
    260     }
    261 
    262     if (print_tdm == 1) {
    263         for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
    264              LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    265                                  "\n====== TDM Tables PIPE=%1d INGRESS\n"),
    266                                  pipe));
    267             for (hpipe = 0; hpipe< MAX_SCH_SLICES; hpipe++) {
    268                 tdm_schedule = &(sch_info->tdm_ingress_schedule_pipe[
    269 											pipe].tdm_schedule_slice[hpipe]);
    270                 _soc_td3_tdm_print_tdm_info(unit, tdm_schedule, hpipe, 1);
    271             }
    272             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    273                                 "\n====== TDM Tables PIPE=%1d  EGRESS\n"),
    274                                 pipe));
    275             for (hpipe = 0; hpipe< MAX_SCH_SLICES; hpipe++) {
    276                 tdm_schedule = &(sch_info->tdm_egress_schedule_pipe[
    277 											pipe].tdm_schedule_slice[hpipe]);
    278                 _soc_td3_tdm_print_tdm_info(unit, tdm_schedule, hpipe, 0);
    279             }
    280         }
    281     }
    282 
    283     if ((sch_info->is_flexport == 1) && (sch_info->nport > 0)) {
    284         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    285                             "\n====== FLEXPORT RESOURCES ===== "
    286                             "num entries= %d = \n"),
    287                             sch_info->nport));
    288         for (i = 0; i < sch_info->nport; i++) {
    289             _soc_td3_tdm_print_port_resource(unit, &sch_info->resource[i], i);
    290         }
    291     }
    292 }
    293 
    294 
    295 /*! @fn void soc_td3_tdm_get_port_ratio(
    296         int unit,
    297         soc_port_schedule_state_t *sch_info,
    298         int pm_num,
    299         int *pm_mode,
    300         int prev_or_new)
    301     @param unit   Chip unit number.
    302     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    303     @param pm_num PM block_id (0 to 31)
    304     @param *pm_mode mode to be returned.
    305     @param prev_or_new function looks in in_port_map or out_port_map.
    306     @brief Help function to get port ratio.
    307  */
    308 
    309 /*
    310  * #1   single: 100  -   x  -   x  -   x  SOC_TD3_PORT_RATIO_SINGLE
    311  * #2   single:  40  -   x  -   x  -   x  SOC_TD3_PORT_RATIO_TRI_023_2_1_1
    312  * #3   dual:    50  -   x  -  50  -   x  SOC_TD3_PORT_RATIO_DUAL_1_1
    313  * #4   dual:    40  -   x  -  40  -   x  SOC_TD3_PORT_RATIO_DUAL_1_1
    314  * #5   dual:    20  -   x  -  20  -   x  SOC_TD3_PORT_RATIO_DUAL_1_1
    315  * #6   dual:    40  -   x  -  20  -   x  SOC_TD3_PORT_RATIO_DUAL_2_1
    316  * #7   dual:    20  -   x  -  40  -   x  SOC_TD3_PORT_RATIO_DUAL_1_2
    317  * #8   tri:     50  -   x  - 25/x - 25/x SOC_TD3_PORT_RATIO_TRI_023_2_1_1
    318  * #9   tri:     20  -   x  - 10/x - 10/x SOC_TD3_PORT_RATIO_TRI_023_2_1_1
    319  * #10  tri:     40  -   x  - 10/x - 10/x SOC_TD3_PORT_RATIO_TRI_023_4_1_1
    320  * #11  tri:    25/x - 25/x -  50  -   x  SOC_TD3_PORT_RATIO_TRI_012_1_1_2
    321  * #12  tri:    10/x - 10/x -  20  -   x  SOC_TD3_PORT_RATIO_TRI_012_1_1_2
    322  * #13  tri:    10/x - 10/x -  40  -   x  SOC_TD3_PORT_RATIO_TRI_012_1_1_4
    323  * #14  quad:   25/x - 25/x - 25/x - 25/x SOC_TD3_PORT_RATIO_QUAD
    324  * #15  quad:   10/x - 10/x - 10/x - 10/x SOC_TD3_PORT_RATIO_QUAD
    325  */
    326 void
    327 soc_td3_tdm_get_port_ratio(int unit,
    328                             soc_port_schedule_state_t *sch_info,
    329                             int pm_num, int *pm_mode, int prev_or_new)
    330 {
    331     int port, phy_port_base, lane, mode = 0;
    332     int num_lanes[TRIDENT3_TDM_PORTS_PER_PBLK];
    333     int speed_max[TRIDENT3_TDM_PORTS_PER_PBLK];
    334     soc_port_map_type_t *port_map;
    335     int l_speed = 0, l_num_lanes = 0;
    336 
    337     sal_memset(num_lanes, 0, TRIDENT3_TDM_PORTS_PER_PBLK*sizeof(int));
    338     sal_memset(speed_max, 0, TRIDENT3_TDM_PORTS_PER_PBLK*sizeof(int));
    339 
    340     if (prev_or_new == 1) {
    341         port_map = &(sch_info->in_port_map);
    342     } else {
    343         port_map = &(sch_info->out_port_map);
    344     }
    345 
    346     phy_port_base = 1 + (pm_num * TRIDENT3_TDM_PORTS_PER_PBLK);
    347     for (lane = 0; lane < TRIDENT3_TDM_PORTS_PER_PBLK; lane += 2) {
    348         port = port_map->port_p2l_mapping[phy_port_base + lane];
    349         if ( (port == -1) || (port_map->log_port_speed[port]==0) ) {
    350             num_lanes[lane] = -1;
    351             speed_max[lane] = -1;
    352         } else {
    353             soc_td3_tdm_get_log_port_speed(unit, sch_info, port,
    354                 prev_or_new, &l_speed, &l_num_lanes);
    355             num_lanes[lane] = l_num_lanes;
    356             speed_max[lane] = l_speed;
    357         }
    358     }
    359 
    360     if (num_lanes[0] == 4) {
    361         mode = SOC_TD3_PORT_RATIO_SINGLE;
    362     } else if (num_lanes[0] == 2 && num_lanes[2] == 2) {
    363         if (speed_max[0] == speed_max[2]) {
    364             mode = SOC_TD3_PORT_RATIO_DUAL_1_1;
    365         } else if (speed_max[0] > speed_max[2]) {
    366             mode = SOC_TD3_PORT_RATIO_DUAL_2_1;
    367         } else {
    368             mode = SOC_TD3_PORT_RATIO_DUAL_1_2;
    369         }
    370     } else if (num_lanes[0] == 2) {
    371         if (num_lanes[2] == -1) {
    372             mode = SOC_TD3_PORT_RATIO_DUAL_1_1;
    373         } else {
    374             mode = (speed_max[0] == 20000 || speed_max[0] == 21000 ||
    375                     speed_max[0] == 50000 || speed_max[0] == 53000) ?
    376                    SOC_TD3_PORT_RATIO_TRI_023_2_1_1 :
    377                    SOC_TD3_PORT_RATIO_TRI_023_4_1_1;
    378         }
    379     } else if (num_lanes[2] == 2) {
    380         if (num_lanes[0] == -1) {
    381             mode = SOC_TD3_PORT_RATIO_DUAL_1_1;
    382         } else {
    383             mode = (speed_max[2] == 20000 || speed_max[2] == 21000 ||
    384                     speed_max[2] == 50000 || speed_max[2] == 53000) ?
    385                    SOC_TD3_PORT_RATIO_TRI_012_1_1_2 :
    386                    SOC_TD3_PORT_RATIO_TRI_012_1_1_4;
    387         }
    388     } else {
    389         mode = SOC_TD3_PORT_RATIO_QUAD;
    390     }
    391 
    392     *pm_mode = mode;
    393 }
    394 
    395 
    396 /*! @fn void _soc_td3_tdm_get_pipe_map(
    397         int unit,
    398         soc_port_schedule_state_t *sch_info,
    399         uint32 *pipe_map)
    400     @param unit Chip unit number.
    401     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    402     @param pipe_map Returned pipe map.
    403     @brief Returns pipe bitmap.
    404  * Description:
    405         For init, a pipe gets 1 if exists active port within that pipe.
    406         For flexport, a pipe gets 1 if exists flexed port within that pipe.
    407  */
    408 void
    409 _soc_td3_tdm_get_pipe_map(int unit,
    410                           soc_port_schedule_state_t *sch_info,
    411                           uint32 *pipe_map)
    412 {
    413     uint32 port, pipe, i, pipe_bmap = 0;
    414 
    415     if (sch_info->is_flexport == 0) { /* Init */
    416         for (port = 0; port < TRIDENT3_TDM_PHY_PORTS_PER_DEV; port++) {
    417             if (sch_info->out_port_map.log_port_speed[port] > 0 ) {
    418                 pipe = port / TRIDENT3_TDM_PHY_PORTS_PER_PIPE;
    419                 pipe_bmap |= 1 << pipe;
    420             }
    421         }
    422     } else { /* FlexPort */
    423         for (i = 0; i < sch_info->nport; i++) {
    424             port = sch_info->resource[i].logical_port;
    425             pipe = port / TRIDENT3_TDM_PHY_PORTS_PER_PIPE;
    426             pipe_bmap |= 1 << pipe;
    427         }
    428     }
    429     *pipe_map = pipe_bmap;
    430 }
    431 
    432 
    433 /*! @fn void _soc_td3_tdm_get_ovs_pipe_map(
    434         int unit,
    435         soc_port_schedule_state_t *sch_info,
    436         uint32 *ovs_pipe_map)
    437     @param unit Chip unit number.
    438     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    439     @param ovs_pipe_map Returned pipe map.
    440     @brief Returns OVS pipe bitmap.
    441  * Description:
    442         For init, a pipe gets 1 if exists oversub port within that pipe.
    443  */
    444 void
    445 _soc_td3_tdm_get_ovs_pipe_map(int unit,
    446                               soc_port_schedule_state_t *sch_info,
    447                               uint32 *ovs_pipe_map)
    448 {
    449     uint32 port, pipe, pipe_bmap = 0;
    450     int is_ovs_map;
    451 
    452     if (sch_info->is_flexport == 0) { /* Init */
    453         for (port = 0; port < TRIDENT3_TDM_PHY_PORTS_PER_DEV; port++) {
    454             is_ovs_map = SOC_PBMP_MEMBER(sch_info->out_port_map.oversub_pbm,
    455 															port) ? 1 : 0;
    456             if ((sch_info->out_port_map.log_port_speed[port] > 0) &&
    457                 (1 == is_ovs_map) ) {
    458                 pipe = port / TRIDENT3_TDM_PHY_PORTS_PER_PIPE;
    459                 pipe_bmap |= 1 << pipe;
    460             }
    461         }
    462     }
    463     *ovs_pipe_map = pipe_bmap;
    464 }
    465 
    466 
    467 /*! @fn int _soc_td3_tdm_get_speed_ovs_class(
    468         int unit,
    469         int speed)
    470     @param unit   Chip unit number.
    471     @param speed Speed
    472     @return port_speed_class to be returned
    473     @brief Help function to determine ovs class
    474  * Description:
    475     Oversubscription speed group class encoding
    476         0 - 0
    477         1 - 2 (1G/10G)
    478         2 - 4 (20G)
    479         3 - 5 (25G)
    480         4 - 8 (40G)
    481         5 - 10 (50G)
    482         6 - 20 (100G)
    483  */
    484 int
    485 _soc_td3_tdm_get_speed_ovs_class(int unit, int speed)
    486 {
    487     int speed_class = 0;
    488 
    489     if (speed >= 40000) {
    490         if (speed >= 100000) {
    491             speed_class = 6;
    492         } else if (speed >= 50000) {
    493             speed_class = 5;
    494         } else {
    495             speed_class = 4;
    496         }
    497     } else {
    498         if (speed >= 25000) {
    499             speed_class = 3;
    500         } else if (speed >= 20000) {
    501             speed_class = 2;
    502         } else if (speed >= 10000) {
    503             speed_class = 1;
    504         } else if (speed >= 1000) {
    505             speed_class = 1;
    506         }
    507     }
    508 
    509     /* 1G and 10G are always treated as 25G. */
    510     if (speed_class == 1) {
    511         speed_class = 3;
    512     }
    513 
    514     return (speed_class);
    515 }
    516 
    517 
    518 /*! @fn int _soc_td3_tdm_check_is_hsp_port_e(
    519         int unit,
    520         int speed)
    521     @param unit   Chip unit number.
    522     @param speed Speed
    523     @return 1->high speed port; 0->not high speed port;
    524     @brief To determine the same port spacing for egress pipe
    525  * Description:
    526     Oversubscription speed group class encoding
    527         0 - 0
    528         1 - 2 (10G)
    529         2 - 4 (20G)
    530         3 - 5 (25G)
    531         4 - 8 (40G)
    532         5 - 10 (50G)
    533         6 - 20 (100G)
    534  */
    535 STATIC int
    536 _soc_td3_tdm_check_is_hsp_port_e(int unit, int speed)
    537 {
    538     int speed_class, port_is_hsp = 0;
    539 
    540     speed_class = _soc_td3_tdm_get_speed_ovs_class(unit, speed);
    541     switch (speed_class) {
    542         case 2: /* 20G */
    543         case 4: /* 40G */
    544         case 5: /* 50G */
    545         case 6: /* 100G */
    546             port_is_hsp = 1;
    547             break;
    548         default:
    549             port_is_hsp = 0;
    550             break;
    551     }
    552 
    553     return (port_is_hsp);
    554 }
    555 
    556 
    557 /*! @fn int _soc_td3_tdm_check_2nd_mgmt_enable(
    558         int unit,
    559         soc_port_schedule_state_t *sch_info)
    560     @param unit   Chip unit number.
    561     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    562     @return 1-> 2nd management port enabled; 0 -> otherwise
    563     @brief Help function to determine if 2nd management port is enabled.
    564  */
    565 STATIC int
    566 _soc_td3_tdm_check_2nd_mgmt_enable(int unit,
    567 					soc_port_schedule_state_t *sch_info)
    568 {
    569     int port;
    570     int mgmt_port_cnt = 0;
    571     int mgmt_2nd_port_en = 0;
    572 
    573     SOC_PBMP_ITER(sch_info->in_port_map.management_pbm, port) {
    574         mgmt_port_cnt++;
    575     }
    576     if (mgmt_port_cnt>1) {
    577         mgmt_2nd_port_en = 1;
    578     }
    579 
    580     return (mgmt_2nd_port_en);
    581 }
    582 
    583 
    584 /*! @fn int _soc_td3_tdm_get_same_port_spacing_e(
    585         int unit,
    586         int speed)
    587     @param unit   Chip unit number.
    588     @param speed Speed
    589     @return same port spacing of the given speed port
    590     @brief To determine the same port spacing for egress pipe
    591            - 8 for high speed port
    592            - 14 for not high speed port
    593  */
    594 int
    595 _soc_td3_tdm_get_same_port_spacing_e(int unit, int speed)
    596 {
    597     int port_same_spacing = 0;
    598 
    599     if (_soc_td3_tdm_check_is_hsp_port_e(unit, speed) == 1) {
    600         port_same_spacing = 8;
    601     } else {
    602         port_same_spacing = 14;
    603     }
    604 
    605     return (port_same_spacing);
    606 }
    607 
    608 
    609 /*! @fn int _soc_td3_tdm_calculation(
    610         int unit,
    611         soc_port_schedule_state_t *sch_info)
    612     @param unit Chip unit number.
    613     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    614     @brief API to calculate TDM tables.
    615  */
    616 int
    617 _soc_td3_tdm_calculation(int unit, soc_port_schedule_state_t *sch_info)
    618 {
    619     int i, j, pm_num, phy_port, lgc_port, phy_port_tmp;
    620     int pipe, hpipe;
    621     int lane, group, index;
    622     int mgmt_pm_hg = 0, mgmt_mode = 0;
    623     int tdm_idb_cal_len, tdm_mmu_cal_len, tdm_pipe_grp_num, tdm_pipe_grp_len;
    624     int tdm_chk_en = 0;
    625     int *tdm_idb_pipe_main, *tdm_mmu_pipe_main;
    626     int **tdm_pipe_ovs_group;
    627     tdm_soc_t _chip_pkg;
    628     tdm_mod_t *_tdm_pkg;
    629     uint32 port_speeds[TRIDENT3_TDM_PHY_PORTS_PER_DEV];
    630     uint32 port_states[TRIDENT3_TDM_PHY_PORTS_PER_DEV];
    631     int l_speed = 0, l_num_lanes = 0, prev_or_new = 1;
    632 
    633     sal_memset(port_speeds, 0, TRIDENT3_TDM_PHY_PORTS_PER_DEV*sizeof(uint32));
    634     sal_memset(port_states, 0, TRIDENT3_TDM_PHY_PORTS_PER_DEV*sizeof(uint32));
    635 
    636     /* Remap input speeds to ETH bitrates */
    637     soc_trident3_port_schedule_speed_remap(unit, sch_info);
    638 
    639     /* Set port states and speeds */
    640     for (lgc_port = 0; lgc_port < TRIDENT3_TDM_PHY_PORTS_PER_DEV; lgc_port++) {
    641         phy_port = sch_info->in_port_map.port_l2p_mapping[lgc_port];
    642         if (phy_port < TRIDENT3_TDM_PHY_PORTS_PER_DEV) {
    643             if (sch_info->in_port_map.log_port_speed[lgc_port] > 0 ) {
    644                 if (SOC_PBMP_MEMBER(sch_info->in_port_map.hg2_pbm,lgc_port)) {
    645                     port_states[phy_port] =
    646                         SOC_PBMP_MEMBER(sch_info->in_port_map.oversub_pbm,
    647 							lgc_port) ? PORT_STATE__OVERSUB_HG :
    648 										PORT_STATE__LINERATE_HG;
    649                 } else {
    650                     port_states[phy_port] =
    651                         SOC_PBMP_MEMBER(sch_info->in_port_map.oversub_pbm,
    652 							lgc_port) ? PORT_STATE__OVERSUB :
    653 										PORT_STATE__LINERATE;
    654                 }
    655 
    656                 soc_td3_tdm_get_log_port_speed(unit, sch_info, lgc_port,
    657                     prev_or_new, &l_speed, &l_num_lanes);
    658                 for (lane = 1; lane < l_num_lanes; lane++) {
    659                     phy_port_tmp = phy_port + lane;
    660                     if (phy_port_tmp < TRIDENT3_TDM_PHY_PORTS_PER_DEV) {
    661                         port_states[phy_port_tmp] = PORT_STATE__COMBINE;
    662                     }
    663                 }
    664                 port_speeds[phy_port] = l_speed;
    665             }
    666             if (SOC_PBMP_MEMBER(sch_info->in_port_map.management_pbm, lgc_port)) {
    667                     if (SOC_PBMP_MEMBER(sch_info->in_port_map.hg2_pbm, lgc_port)) {
    668                         mgmt_pm_hg = 1; /* HIGIG2 : ETHERNET */
    669                     }
    670                     port_speeds[phy_port] = 0;
    671                     port_states[phy_port] = 0;
    672             }
    673         }
    674     }
    675     /* Print input config */
    676     if (LOG_CHECK(BSL_LS_SOC_TDM | BSL_INFO)) {
    677         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    678                             "frequency: %dMHz\n"),
    679                             sch_info->frequency));
    680         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    681                             "%8s%8s%8s\n"),
    682                             "port", "speed", "state"));
    683         for (phy_port = 0; phy_port < TRIDENT3_TDM_PHY_PORTS_PER_DEV;
    684 									phy_port++) {
    685             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    686                                 "%8d%8d%8d\n"),
    687                                 phy_port, port_speeds[phy_port]/1000,
    688                                 port_states[phy_port]));
    689         }
    690         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    691     }
    692     /* Initialize input variables for SW TDM Generation:
    693        -- unit
    694        -- num_ext_ports
    695        -- state
    696        -- speed
    697        -- clk_freq
    698        -- flex_port_en: 0->init, 1->flex
    699        -- mgmt_pm_hg: 0->Ethernet mgmt, 1->HiGig2 mgmt
    700        -- mgmt_mode: 0->two Ethernet mgmt ports
    701                      1->one Ethernet mgmt port
    702                      2->two Higig mgmt ports
    703                      3->one Higig mgmt port
    704     */
    705     sal_memset(&_chip_pkg, 0, sizeof(tdm_soc_t));
    706     _chip_pkg.unit          = unit;
    707     _chip_pkg.num_ext_ports = TD3_NUM_EXT_PORTS;
    708     _chip_pkg.state = sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int),
    709                                 "port state list");
    710     if (_chip_pkg.state == NULL) {
    711         return SOC_E_MEMORY;
    712     }
    713     _chip_pkg.speed = sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int),
    714                                 "port speed list");
    715     if (_chip_pkg.speed == NULL) {
    716         sal_free(_chip_pkg.state);
    717         return SOC_E_MEMORY;
    718     }
    719     for (index = 0; index < _chip_pkg.num_ext_ports; index++) {
    720         _chip_pkg.state[index] = 0;
    721         _chip_pkg.speed[index] = 0;
    722     }
    723     for (index = 0; index < _chip_pkg.num_ext_ports &&
    724                     index < TRIDENT3_TDM_PHY_PORTS_PER_DEV; index++) {
    725         _chip_pkg.state[index] = port_states[index];
    726         _chip_pkg.speed[index] = port_speeds[index];
    727     }
    728     /* Shift port state to left one position; required by C_TDM */
    729     for (index = 1; index < _chip_pkg.num_ext_ports; index++) {
    730         _chip_pkg.state[index - 1] = _chip_pkg.state[index];
    731     }
    732     _chip_pkg.clk_freq               = sch_info->frequency;
    733     _chip_pkg.flex_port_en           = sch_info->is_flexport;
    734     _chip_pkg.soc_vars.td3.tdm_chk_en= tdm_chk_en;
    735     _chip_pkg.soc_vars.td3.mgmt_pm_hg= mgmt_pm_hg;
    736     mgmt_mode = mgmt_pm_hg == 1 ? 2 : 0;
    737     _chip_pkg.soc_vars.td3.mgmt_mode =
    738         (_soc_td3_tdm_check_2nd_mgmt_enable(unit, sch_info) == 1) ?
    739         (mgmt_mode + 0) : (mgmt_mode + 1);
    740 
    741     /* Populate TDM tables by invoking SW TDM API */
    742     /* coverity[dont_call : FALSE] */
    743     _tdm_pkg = _soc_set_tdm_tbl(SOC_SEL_TDM(&_chip_pkg));
    744 
    745     /* Free the memory allocated to port states and speeds */
    746     sal_free(_chip_pkg.state);
    747     sal_free(_chip_pkg.speed);
    748 
    749     /* Copy TDM result into output structure */
    750     if (_tdm_pkg == NULL) {
    751         LOG_CLI((BSL_META_U(unit,
    752                  "Unsupported config for TDM calendar generation\n")));
    753         return SOC_E_FAIL;
    754     } else {
    755         /* IDB calendar (0-3), MMU calendar (4-7) */
    756         for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
    757             switch (pipe) {
    758                 /* IDB_PIPE_0, MMU_PIPE_0 */
    759                 case 0:
    760                     tdm_pipe_ovs_group = _tdm_pkg->_chip_data.cal_0.cal_grp;
    761                     tdm_pipe_grp_num   = _tdm_pkg->_chip_data.cal_0.grp_num;
    762                     tdm_pipe_grp_len   = _tdm_pkg->_chip_data.cal_0.grp_len;
    763                     tdm_idb_pipe_main  = _tdm_pkg->_chip_data.cal_0.cal_main;
    764                     tdm_idb_cal_len    = _tdm_pkg->_chip_data.cal_0.cal_len;
    765                     tdm_mmu_pipe_main  = _tdm_pkg->_chip_data.cal_4.cal_main;
    766                     tdm_mmu_cal_len    = _tdm_pkg->_chip_data.cal_4.cal_len;
    767                     break;
    768                 /* IDB_PIPE_1, MMU_PIPE_1 */
    769                 default:
    770                     tdm_pipe_ovs_group = _tdm_pkg->_chip_data.cal_1.cal_grp;
    771                     tdm_pipe_grp_num   = _tdm_pkg->_chip_data.cal_1.grp_num;
    772                     tdm_pipe_grp_len   = _tdm_pkg->_chip_data.cal_1.grp_len;
    773                     tdm_idb_pipe_main  = _tdm_pkg->_chip_data.cal_1.cal_main;
    774                     tdm_idb_cal_len    = _tdm_pkg->_chip_data.cal_1.cal_len;
    775                     tdm_mmu_pipe_main  = _tdm_pkg->_chip_data.cal_5.cal_main;
    776                     tdm_mmu_cal_len    = _tdm_pkg->_chip_data.cal_5.cal_len;
    777                     break;
    778             }
    779             if (tdm_pipe_ovs_group == NULL ||
    780                 tdm_idb_pipe_main == NULL ||
    781                 tdm_mmu_pipe_main == NULL) {
    782                 LOG_CLI((BSL_META_U(unit,
    783                          "Unsupported config for TDM calendar generation\n")));
    784                 tdm_td3_main_free(_tdm_pkg);
    785                 sal_free(_tdm_pkg);
    786                 return SOC_E_FAIL;
    787             } else {
    788                 /* IDB TDM main calendar */
    789                 for (index = 0; index < tdm_idb_cal_len; index++) {
    790                     sch_info->tdm_ingress_schedule_pipe[pipe].tdm_schedule_slice[
    791 						0].linerate_schedule[index] = tdm_idb_pipe_main[index];
    792                 }
    793                 /* MMU TDM main calendar */
    794                 for (index = 0; index < tdm_mmu_cal_len; index++) {
    795                     sch_info->tdm_egress_schedule_pipe[pipe].tdm_schedule_slice[
    796 						0].linerate_schedule[index] = tdm_mmu_pipe_main[index];
    797                 }
    798 
    799                 /* IDB and MMU OverSub Groups */
    800                 for (i = 0; i < tdm_pipe_grp_num; i++) {
    801                     /* Group 0:5 -> hpipe 0, Group 6:11 -> hpipe1 */
    802                     hpipe = i / TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE;
    803                     group = i % TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE;
    804                     for (j = 0; j < tdm_pipe_grp_len; j++) {
    805                         sch_info->tdm_ingress_schedule_pipe[
    806 								pipe].tdm_schedule_slice[hpipe].oversub_schedule[
    807 								group][j] = tdm_pipe_ovs_group[i][j];
    808                         sch_info->tdm_egress_schedule_pipe[
    809 								pipe].tdm_schedule_slice[hpipe].oversub_schedule[
    810 								group][j] = tdm_pipe_ovs_group[i][j];
    811                     }
    812                 }
    813 
    814                 /* Packet shaper */
    815                 for (hpipe = 0; hpipe < 2; hpipe++) {
    816                     for (j = 0; j < TD3_SHAPING_GRP_LEN; j++) {
    817                         sch_info->tdm_ingress_schedule_pipe[
    818 							pipe].tdm_schedule_slice[hpipe].pkt_sch_or_ovs_space[
    819 							0][j] = tdm_pipe_ovs_group[hpipe+
    820 										TD3_SHAPING_GRP_IDX_0][j];
    821                     }
    822                 }
    823             }
    824         }
    825         /* Re-evaluate this at FlexPort;
    826          * Before calling FlexPort sch_info->in_port_map.port_p2PBLK_inst_mapping should be copied in pm_num_to_pblk
    827          * After FlexPort pm_num_to_pblk should be copied back to sch_info->out_port_map.port_p2PBLK_inst_mapping
    828          */
    829         sal_memset(sch_info->out_port_map.port_p2PBLK_inst_mapping,
    830                    0, sizeof(int) * SOC_MAX_NUM_PORTS);
    831         for (pm_num = 0; pm_num < TD3_NUM_PHY_PM; pm_num++) {
    832             for (lane = 0; lane < TRIDENT3_TDM_PORTS_PER_PBLK; lane++) {
    833                 sch_info->out_port_map.port_p2PBLK_inst_mapping[
    834 				(pm_num * TRIDENT3_TDM_PORTS_PER_PBLK) + 1 + lane] =
    835                 _tdm_pkg->_chip_data.soc_pkg.soc_vars.td3.pm_num_to_pblk[pm_num];
    836             }
    837         }
    838         /* Free the memory allocated in TDM algorithm code */
    839         tdm_td3_main_free(_tdm_pkg); /* This function frees all pointers allocated during _soc_set_tdm_tbl call */
    840         sal_free(_tdm_pkg);
    841     }
    842 
    843     /* Print TDM result */
    844     if (LOG_CHECK(BSL_LS_SOC_TDM | BSL_INFO)) {
    845         for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
    846             /* IDB TDM main calendar */
    847             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    848                                 "Pipe %d [IDB TDM main calendar]\n"),
    849                                 pipe));
    850             for (index = 0; index < MAX_CAL_LEN; index++) {
    851                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    852                                     " %3d"),
    853                                     sch_info->tdm_ingress_schedule_pipe[
    854 						pipe].tdm_schedule_slice[0].linerate_schedule[index]));
    855                 if (index % 16 == 0 && index > 0) {
    856                     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    857                 }
    858             }
    859             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    860             /* Oversub groups */
    861             for (hpipe = 0; hpipe < TRIDENT3_TDM_HPIPES_PER_PIPE; hpipe++) {
    862                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    863                               "Pipe %d Half-Pipe %d [IDB TDM Oversub Groups]\n"),
    864                               pipe, hpipe));
    865                 for (group = 0; group < TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE;
    866 																group++) {
    867                     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    868                                         "oversub group %d: "),
    869                                         group));
    870                     for (index = 0; index < TRIDENT3_TDM_OVS_GROUP_LENGTH;
    871 																index++) {
    872                         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    873                                             " %3d"),
    874                 sch_info->tdm_ingress_schedule_pipe[pipe].tdm_schedule_slice[
    875 				hpipe].oversub_schedule[group][index]));
    876                     }
    877                     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    878                 }
    879                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    880             }
    881             /* Packet scheduler */
    882             for (hpipe = 0; hpipe < TRIDENT3_TDM_HPIPES_PER_PIPE; hpipe++) {
    883                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    884                             "Pipe %d Half-Pipe %d [IDB TDM PKT SCHEDULER]\n"),
    885                                     pipe, hpipe));
    886                 for (index = 0; index < TD3_SHAPING_GRP_LEN; index++) {
    887                     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    888                                         " %3d"),
    889                     sch_info->tdm_ingress_schedule_pipe[
    890 					pipe].tdm_schedule_slice[hpipe].pkt_sch_or_ovs_space[0][index]));
    891                     if (index % 16 == 0 && index > 0) {
    892                         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    893                     }
    894                 }
    895                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    896             }
    897             /* MMU TDM main calendar */
    898             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
    899                         "Pipe %d [MMU TDM main calendar]:\n"), pipe));
    900             for (index = 0; index < MAX_CAL_LEN; index++) {
    901                 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, " %3d"),
    902                             sch_info->tdm_egress_schedule_pipe[pipe].
    903                             tdm_schedule_slice[0].linerate_schedule[index]));
    904                 if (index % 16 == 0 && index > 0) {
    905                     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    906                 }
    907             }
    908             LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n")));
    909         }
    910     }
    911 
    912     /* If init then just copy in_port_map to out_port_map*/
    913     if (sch_info->is_flexport == 0) {
    914         for (i= 0; i< SOC_MAX_NUM_PORTS;i++) {
    915             sch_info->out_port_map.log_port_speed[i]   =
    916 					sch_info->in_port_map.log_port_speed[i];
    917             sch_info->out_port_map.port_p2l_mapping[i] =
    918 					sch_info->in_port_map.port_p2l_mapping[i];
    919             sch_info->out_port_map.port_l2p_mapping[i] =
    920 					sch_info->in_port_map.port_l2p_mapping[i];
    921             sch_info->out_port_map.port_p2m_mapping[i] =
    922 					sch_info->in_port_map.port_p2m_mapping[i];
    923             sch_info->out_port_map.port_num_lanes[i]   =
    924 					sch_info->in_port_map.port_num_lanes[i];
    925             sch_info->out_port_map.port_l2i_mapping[i] =
    926 					sch_info->in_port_map.port_l2i_mapping[i];
    927         }
    928         for (i = 0; i < SOC_MAX_NUM_MMU_PORTS; i++) {
    929             sch_info->out_port_map.port_m2p_mapping[i] =
    930 					sch_info->in_port_map.port_m2p_mapping[i];
    931         }
    932         for (i = 0; i < _SHR_PBMP_WORD_MAX; i++) {
    933             sch_info->out_port_map.physical_pbm.pbits[i]   =
    934 					sch_info->in_port_map.physical_pbm.pbits[i];
    935             sch_info->out_port_map.hg2_pbm.pbits[i]        =
    936 					sch_info->in_port_map.hg2_pbm.pbits[i];
    937             sch_info->out_port_map.management_pbm.pbits[i] =
    938 					sch_info->in_port_map.management_pbm.pbits[i];
    939             sch_info->out_port_map.oversub_pbm.pbits[i]    =
    940 					sch_info->in_port_map.oversub_pbm.pbits[i];
    941         }
    942     }
    943     /*
    944      * else {
    945      *    HERE future handling of FlexPort between in_port_map to out_port_map
    946      * }
    947     */
    948 
    949     _soc_td3_tdm_print_schedule_state(unit, sch_info);
    950     return SOC_E_NONE;
    951 }
    952 
    953 
    954 /*! @fn int _soc_td3_tdm_set_idb_calendar(
    955         int unit,
    956         soc_port_schedule_state_t *sch_info)
    957     @param unit Chip unit number.
    958     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
    959     @brief API to initialize the TD3 IDB main calendar.
    960  */
    961 int
    962 _soc_td3_tdm_set_idb_calendar(int unit, soc_port_schedule_state_t *sch_info)
    963 {
    964     uint32 pipe_map;
    965     uint32 cal_len;
    966     soc_mem_t mem;
    967     soc_reg_t reg;
    968     soc_field_t cal_end_field;
    969     int pipe, slot, id, length, calendar_id;
    970     int phy_port, idb_port;
    971     int port;
    972     uint32 rval;
    973     uint32 memfld;
    974     uint32 entry[SOC_MAX_MEM_WORDS];
    975     uint32 mem_indx;
    976     static const soc_mem_t idb_tdm_cal_mem[TRIDENT3_TDM_PIPES_PER_DEV][2] = {
    977         {IS_TDM_CALENDAR0_PIPE0m, IS_TDM_CALENDAR1_PIPE0m},
    978         {IS_TDM_CALENDAR0_PIPE1m, IS_TDM_CALENDAR1_PIPE1m}
    979     };
    980     static const soc_reg_t idb_tdm_cfg_reg[TRIDENT3_TDM_PIPES_PER_DEV] = {
    981         IS_TDM_CONFIG_PIPE0r, IS_TDM_CONFIG_PIPE1r
    982     };
    983     static const soc_field_t calendar_end_fields[] = {
    984         CAL0_ENDf, CAL1_ENDf
    985     };
    986 
    987     _soc_td3_tdm_get_pipe_map(unit, sch_info, &pipe_map);
    988     sal_memset(entry, 0, sizeof(uint32) * soc_mem_entry_words(unit,
    989 								IS_TDM_CALENDAR0_PIPE0m));
    990 
    991     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
    992         /* coverity[overrun-local : FALSE] */
    993         reg = idb_tdm_cfg_reg[pipe];
    994         /* Pipe is empty */
    995         if ((pipe_map & (1 << pipe)) == 0) {
    996             /* At init, even if the pipe doesn't have active ports,
    997              * enable scheduler for sbus accesses to PP IPIPE
    998              */
    999             if (sch_info->is_flexport == 0) {
   1000                 rval = 0;
   1001                 soc_reg_field_set(unit, reg, &rval, ENABLEf, 1);
   1002                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   1003 											0, rval));
   1004             }
   1005             continue;
   1006         }
   1007         /* Determine calendar_id : 0 or 1 */
   1008         if (sch_info->is_flexport == 1) { /* choose "the other calendar" */
   1009             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY,
   1010 											0, &rval));
   1011             calendar_id = soc_reg_field_get(unit, reg, rval, CURR_CALf) ^ 1;
   1012         } else {
   1013             /* At init use calendar_id=0 */
   1014             calendar_id = 0;
   1015             /* Also, before writing the TDM calendar entries, make sure
   1016              * calendar is disabled again;
   1017              * IDB scheduler may be already enabled at this point to allow
   1018              * sbus access to IPIPE for reset purpose (Sec. 3.1.2 SW_init doc)
   1019              */
   1020             rval = 0;
   1021             soc_reg_field_set(unit, reg, &rval, ENABLEf, 0);
   1022             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1023         }
   1024         /* coverity[overrun-local : FALSE] */
   1025         mem = idb_tdm_cal_mem[pipe][calendar_id];
   1026         cal_end_field = calendar_end_fields[calendar_id];
   1027 
   1028         /* TDM Calendar is always taken from slice 0 */
   1029         cal_len = sch_info->tdm_ingress_schedule_pipe[pipe].tdm_schedule_slice[
   1030 																0].cal_len;
   1031         for (length = cal_len; length > 0; length--) {
   1032             if (sch_info->tdm_ingress_schedule_pipe[pipe].tdm_schedule_slice[
   1033 					0].linerate_schedule[length - 1] != TD3_NUM_EXT_PORTS) {
   1034                 break;
   1035             }
   1036         }
   1037         for (slot = 0; slot < length; slot += 2) {
   1038             /* EVEN */
   1039             phy_port = sch_info->tdm_ingress_schedule_pipe[
   1040 				pipe].tdm_schedule_slice[0].linerate_schedule[slot];
   1041             if (phy_port == TD3_OVSB_TOKEN) {
   1042                 idb_port = TRIDENT3_TDM_IDB_OVSB_TOKEN;
   1043             } else if (phy_port == TD3_IDL1_TOKEN) {
   1044                 idb_port = TRIDENT3_TDM_IDB_SBUS_TOKEN;
   1045             } else if (phy_port == TD3_IDL2_TOKEN) {
   1046                 idb_port = TRIDENT3_TDM_IDB_UNUSED_TOKEN;
   1047             } else if (phy_port == TD3_NULL_TOKEN) {
   1048                 idb_port = TRIDENT3_TDM_IDB_NULL_TOKEN;
   1049             } else if (phy_port >= TD3_NUM_EXT_PORTS) {
   1050                 idb_port = TRIDENT3_TDM_IDB_UNUSED_TOKEN;
   1051             } else if (phy_port == TD3_MGM1_TOKEN) {
   1052                 /* TDM code always allocates slots for management port.
   1053                  * If mgmt ports are omitted from config, this mapping
   1054                  * is not set up.
   1055                  */
   1056                 idb_port = TRIDENT3_TDM_IDB_MGMT1_TOKEN;
   1057             } else {
   1058                 port = sch_info->out_port_map.port_p2l_mapping[phy_port];
   1059                 idb_port = sch_info->out_port_map.port_l2i_mapping[port] & 0x7f;
   1060             }
   1061             if (idb_port > 63) { /* Not a general front panel port */
   1062                 id = 0xf;
   1063             } else {
   1064                 id = (phy_port - 1) / TRIDENT3_TDM_PORTS_PER_PBLK;
   1065             }
   1066             memfld = idb_port & 0x7f; /* [0,69] && 127 */
   1067             soc_mem_field_set(unit, mem, entry, PORT_NUM_EVENf, &memfld);
   1068             memfld = id & 0xf;
   1069             soc_mem_field_set(unit, mem, entry, PHY_PORT_ID_EVENf, &memfld);
   1070             /* ODD */
   1071             phy_port = sch_info->tdm_ingress_schedule_pipe[pipe].tdm_schedule_slice[0].linerate_schedule[slot + 1];
   1072             if (phy_port == TD3_OVSB_TOKEN) {
   1073                 idb_port = TRIDENT3_TDM_IDB_OVSB_TOKEN;
   1074             } else if (phy_port == TD3_IDL1_TOKEN) {
   1075                 idb_port = TRIDENT3_TDM_IDB_SBUS_TOKEN;
   1076             } else if (phy_port == TD3_IDL2_TOKEN) {
   1077                 idb_port = TRIDENT3_TDM_IDB_UNUSED_TOKEN;
   1078             } else if (phy_port == TD3_NULL_TOKEN) {
   1079                 idb_port = TRIDENT3_TDM_IDB_NULL_TOKEN;
   1080             } else if (phy_port >= TD3_NUM_EXT_PORTS) {
   1081                 idb_port = TRIDENT3_TDM_IDB_UNUSED_TOKEN;
   1082             } else if (phy_port == TD3_MGM1_TOKEN) {
   1083                 /* TDM code always allocates slots for management port.
   1084                  * If mgmt ports are omitted from config, this mapping
   1085                  * is not set up.
   1086                  */
   1087                 idb_port = TRIDENT3_TDM_IDB_MGMT1_TOKEN;
   1088             } else {
   1089                 port = sch_info->out_port_map.port_p2l_mapping[phy_port];
   1090                 idb_port = sch_info->out_port_map.port_l2i_mapping[port] & 0x7f;
   1091             }
   1092             if (idb_port > 63) { /* Not a general front panel port */
   1093                 id = 0xf;
   1094             } else {
   1095                 id = (phy_port - 1) / TRIDENT3_TDM_PORTS_PER_PBLK;
   1096             }
   1097             memfld = idb_port & 0x7f; /* [0,69] && 127 */
   1098             soc_mem_field_set(unit, mem, entry, PORT_NUM_ODDf, &memfld);
   1099             memfld = id & 0xf;
   1100             soc_mem_field_set(unit, mem, entry, PHY_PORT_ID_ODDf, &memfld);
   1101             /* Memory entry */
   1102             mem_indx = slot / 2;
   1103             SOC_IF_ERROR_RETURN
   1104                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_indx, entry));
   1105         }
   1106 
   1107         /* set for 2nd management port */
   1108         if (_soc_td3_tdm_check_2nd_mgmt_enable(unit, sch_info) == 1 &&
   1109             pipe == (TRIDENT3_TDM_PIPES_PER_DEV - 1)) {
   1110             /* reg: IS_TDM_CONFIG_PIPExr */
   1111             soc_reg_field_set(unit, reg, &rval, MGMT_2ND_PORT_ENABLEf, 1);
   1112         }
   1113 
   1114         soc_reg_field_set(unit, reg, &rval, cal_end_field, length-1);
   1115         soc_reg_field_set(unit, reg, &rval, CURR_CALf, calendar_id);
   1116         soc_reg_field_set(unit, reg, &rval, ENABLEf, 1);
   1117         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1118     }
   1119 
   1120     return SOC_E_NONE;
   1121 }
   1122 
   1123 
   1124 /*! @fn int _soc_td3_tdm_set_idb_hsp(
   1125         int unit,
   1126         soc_port_schedule_state_t *sch_info)
   1127     @param unit Chip unit number.
   1128     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
   1129     @brief API to initialize the TD3 IDB HSP.
   1130  */
   1131 int
   1132 _soc_td3_tdm_set_idb_hsp(int unit, soc_port_schedule_state_t *sch_info)
   1133 {
   1134     soc_reg_t reg;
   1135     uint32 pipe_map;
   1136     int pipe;
   1137     uint32 pmap;
   1138     uint32 rval = 0;
   1139 
   1140     static const soc_reg_t idb_tdm_hsp[TRIDENT3_TDM_PIPES_PER_DEV][2] = {
   1141         {IS_TDM_HSP_0_PIPE0r, IS_TDM_HSP_0_PIPE1r},
   1142         {IS_TDM_HSP_1_PIPE0r, IS_TDM_HSP_1_PIPE1r}
   1143     };
   1144 
   1145     /* IDB always configures PORT_BMPf field for idb_tdm_hsp regs
   1146      * to 0xFFFF_FFFF_FFFF_FFFF, independent of the port's speed.
   1147      */
   1148     pmap = 0xffffffff; /* up to 32 ports */
   1149 
   1150     _soc_td3_tdm_get_pipe_map(unit, sch_info, &pipe_map);
   1151     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1152         if (!(pipe_map & (1 << pipe))) {
   1153             continue;
   1154         }
   1155         reg = idb_tdm_hsp[pipe][0];
   1156         soc_reg_field_set(unit, reg, &rval, PORT_BMPf, pmap);
   1157         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1158 
   1159         reg = idb_tdm_hsp[pipe][1];
   1160         soc_reg_field_set(unit, reg, &rval, PORT_BMPf, pmap);
   1161         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1162     }
   1163 
   1164     return SOC_E_NONE;
   1165 }
   1166 
   1167 
   1168 /*! @fn int _soc_td3_tdm_set_idb_ppe_credit(
   1169         int unit,
   1170         soc_port_schedule_state_t
   1171         *sch_info,
   1172         int full_credit_threshold_0,
   1173         int opp_credit_threshold_0,
   1174         int full_credit_threshold_1,
   1175         int opp_credit_threshold_1 )
   1176     @param unit Chip unit number.
   1177     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
   1178     @param full_credit_threshold_0
   1179     @param opp_credit_threshold_0
   1180     @param full_credit_threshold_1
   1181     @param opp_credit_threshold_1
   1182     @brief API to initialize the TD3 IDB PPE Credit Config register.
   1183            Regs/Mems configured:PPE_CREDIT_CONFIG_PIPE<pipe>
   1184  */
   1185 int
   1186 _soc_td3_tdm_set_idb_ppe_credit(int unit,
   1187                                 soc_port_schedule_state_t *sch_info,
   1188                                 int full_credit_threshold_0,
   1189                                 int opp_credit_threshold_0,
   1190                                 int full_credit_threshold_1,
   1191                                 int opp_credit_threshold_1 )
   1192 {
   1193     soc_reg_t reg;
   1194     uint32 pipe_map;
   1195     int pipe;
   1196     uint32 rval;
   1197     static const soc_reg_t idb_ppe_credit[TRIDENT3_TDM_PIPES_PER_DEV] = {
   1198         PPE_CREDIT_CONFIG_PIPE0r, PPE_CREDIT_CONFIG_PIPE1r
   1199     };
   1200 
   1201     _soc_td3_tdm_get_pipe_map(unit, sch_info, &pipe_map);
   1202 
   1203     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1204         if (!(pipe_map & (1 << pipe))) {
   1205             continue;
   1206         }
   1207         reg = idb_ppe_credit[pipe];
   1208         rval = 0;
   1209         /*SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));*/
   1210         soc_reg_field_set(unit, reg, &rval, FULL_CREDIT_THRESHOLD_0f,
   1211 											full_credit_threshold_0);
   1212         soc_reg_field_set(unit, reg, &rval, OPP_CREDIT_THRESHOLD_0f,
   1213 											opp_credit_threshold_0);
   1214         soc_reg_field_set(unit, reg, &rval, FULL_CREDIT_THRESHOLD_1f,
   1215 											full_credit_threshold_1);
   1216         soc_reg_field_set(unit, reg, &rval, OPP_CREDIT_THRESHOLD_1f,
   1217 											opp_credit_threshold_1);
   1218         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0,
   1219 											rval));
   1220     }
   1221 
   1222     return SOC_E_NONE;
   1223 }
   1224 
   1225 
   1226 /*! @fn int _soc_td3_tdm_set_idb_opportunistic(
   1227         int unit,
   1228         soc_port_schedule_state_t *sch_info,
   1229         int cpu_op_en,
   1230         int lb_opp_en,
   1231         int opp1_port_en,
   1232         int opp2_port_en,
   1233         int opp_ovr_sub_en)
   1234     @param unit Chip unit number.
   1235     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
   1236     @param cpu_op_en
   1237     @param lb_opp_en
   1238     @param opp1_port_en
   1239     @param opp2_port_en
   1240     @param opp_ovr_sub_en
   1241     @brief API to initialize the TD3 IDB Opportunistic related registers
   1242            Regs/Mems configured: IS_CPU_LB_OPP_CFG_PIPE<pipe>
   1243                                  IS_OPP_SCHED_CFG_PIPE<pipe>
   1244  */
   1245 int
   1246 _soc_td3_tdm_set_idb_opportunistic(int unit,
   1247                                    soc_port_schedule_state_t *sch_info,
   1248                                    int cpu_op_en,
   1249                                    int lb_opp_en,
   1250                                    int opp1_port_en,
   1251                                    int opp2_port_en,
   1252                                    int opp_ovr_sub_en)
   1253 {
   1254     soc_reg_t reg;
   1255     uint32 pipe_map;
   1256     int pipe;
   1257     uint32 rval;
   1258     static const soc_reg_t idb_cpu_lb_opp_cfg[TRIDENT3_TDM_PIPES_PER_DEV] = {
   1259         IS_CPU_LB_OPP_CFG_PIPE0r, IS_CPU_LB_OPP_CFG_PIPE1r
   1260     };
   1261     static const soc_reg_t idb_opp_sched_cfg[TRIDENT3_TDM_PIPES_PER_DEV] = {
   1262         IS_OPP_SCHED_CFG_PIPE0r, IS_OPP_SCHED_CFG_PIPE1r
   1263     };
   1264 
   1265     _soc_td3_tdm_get_pipe_map(unit, sch_info, &pipe_map);
   1266 
   1267     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   1268         if ((pipe_map & (1 << pipe)) == 0) {
   1269             /* Enable OPP1 to enable sbus access to the rest of IPIPE*/
   1270             reg = idb_opp_sched_cfg[pipe];
   1271             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1272             soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf,
   1273 												(opp1_port_en == 1) ? 1 : 0);
   1274             soc_reg_field_set(unit, reg, &rval, OPP1_SPACINGf, 8);
   1275             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1276             continue;
   1277         }
   1278 
   1279         reg = idb_cpu_lb_opp_cfg[pipe];
   1280         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1281         soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf,
   1282 												(cpu_op_en == 1) ? 1 : 0);
   1283         soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf,
   1284 												(lb_opp_en == 1) ? 1 : 0);
   1285         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1286 
   1287         reg = idb_opp_sched_cfg[pipe];
   1288         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1289         soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf,
   1290 												(opp1_port_en == 1) ? 1 : 0);
   1291         soc_reg_field_set(unit, reg, &rval, OPP1_SPACINGf, 8);
   1292         soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf,
   1293 												(opp2_port_en == 1) ? 1 : 0);
   1294         soc_reg_field_set(unit, reg, &rval, OPP2_SPACINGf, 0);
   1295         soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf,
   1296 												(opp_ovr_sub_en == 1) ? 1 : 0);
   1297         soc_reg_field_set(unit, reg, &rval, OPP_STRICT_PRIf, 1);
   1298         soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 67); /* NULL port */
   1299         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1300     }
   1301 
   1302     return SOC_E_NONE;
   1303 }
   1304 
   1305 
   1306 /*! @fn int _soc_td3_tdm_set_idb_pkt_calendar(
   1307         int unit,
   1308         soc_port_schedule_state_t *sch_info)
   1309     @param unit Chip unit number.
   1310     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
   1311     @brief API to initialize the TD3 IDB Packet Shaper calendar.
   1312            Regs/Mems configured: IDB PKT_SCH_CALENDAR
   1313  */
   1314 int
   1315 _soc_td3_tdm_set_idb_pkt_calendar(int unit,
   1316                                   soc_port_schedule_state_t *sch_info)
   1317 {
   1318     uint32 pipe_map;
   1319     soc_mem_t mem;
   1320     int pipe, slot, hpipe;
   1321     int port, phy_port, idb_port;
   1322     uint32 memfld;
   1323     uint32 entry[SOC_MAX_MEM_WORDS];
   1324     static const soc_mem_t idb_pkt_shaper_mems[TRIDENT3_TDM_PIPES_PER_DEV][2] = {
   1325         {PKT_SCH_CALENDAR0_PIPE0m, PKT_SCH_CALENDAR1_PIPE0m},
   1326         {PKT_SCH_CALENDAR0_PIPE1m, PKT_SCH_CALENDAR1_PIPE1m}
   1327     };
   1328 
   1329     _soc_td3_tdm_get_pipe_map(unit, sch_info, &pipe_map);
   1330 
   1331     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1332         if (!(pipe_map & (1 << pipe))) {
   1333             continue;
   1334         }
   1335         /* Configure packet shaper calendar */
   1336         for (hpipe = 0; hpipe < TRIDENT3_TDM_HPIPES_PER_PIPE; hpipe++) {
   1337             mem = idb_pkt_shaper_mems[pipe][hpipe];
   1338             for (slot = 0; slot < TD3_SHAPING_GRP_LEN; slot ++) {
   1339                 phy_port = sch_info->tdm_ingress_schedule_pipe[
   1340 				pipe].tdm_schedule_slice[hpipe].pkt_sch_or_ovs_space[0][slot];
   1341                 if ((phy_port >= TD3_NUM_EXT_PORTS) || (phy_port <= 0)) {
   1342                     idb_port = TRIDENT3_TDM_IDB_UNUSED_TOKEN;
   1343                 } else {
   1344                     port = sch_info->in_port_map.port_p2l_mapping[phy_port];
   1345                     idb_port = sch_info->in_port_map.port_l2i_mapping[port] & 0x1f;
   1346                 }
   1347                 sal_memset(entry, 0, sizeof(uint32) * soc_mem_entry_words(unit,
   1348 											PKT_SCH_CALENDAR0_PIPE0m));
   1349                 memfld = idb_port & 0x3f;
   1350                 soc_mem_field_set(unit, mem, entry, PORT_NUMf, &memfld);
   1351                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   1352 										slot, entry));
   1353             }
   1354         }
   1355     }
   1356 
   1357     return SOC_E_NONE;
   1358 }
   1359 
   1360 
   1361 /*! @fn int _soc_td3_tdm_set_ovs_group_sel(
   1362         int unit,
   1363         soc_port_schedule_state_t *sch_info,
   1364         int set_idb,
   1365         int set_mmu)
   1366     @param unit Chip unit number.
   1367     @param sch_info : Pointer to a soc_port_schedule_state_t struct variable.
   1368     @param set_idb if 1 then IDB OVS tables are configured
   1369     @param set_mmu if 1 then MMU OVS tables are configured
   1370     @brief API to initialize the TD3 MMU &/or IDB OVS tables.
   1371             Regs/Mems configured: IDB HPIPE0/1_OVR_SUB_GRP_CFG,
   1372                                   HPIPE0/1_OVR_SUB_GRP_CFG
   1373                                   PBLK<n>_CALENDAR
   1374  */
   1375 int
   1376 _soc_td3_tdm_set_ovs_group_sel(int unit,
   1377                                soc_port_schedule_state_t *sch_info,
   1378                                int set_idb, int set_mmu)
   1379 {
   1380     uint32 pipe_map, ovs_pipe_map;
   1381     soc_reg_t reg, reg1;
   1382     int pipe, hpipe, group, lane, slot, id = 0, mode;
   1383     int port, phy_port, phy_port_base, idb_port, mmu_port, inst;
   1384     int speed_max;
   1385     uint32 rval, rval1;
   1386     int pblks[TRIDENT3_TDM_PIPES_PER_DEV][2][TRIDENT3_TDM_PBLKS_PER_HPIPE];
   1387     int pm_num, pblk_cal_idx;
   1388     int pblk_valid, pblk_spacing;
   1389     int port_speed_class, port_same_spacing, port_sister_spacing;
   1390     int l_speed = 0, l_num_lanes = 0, prev_or_new = 0;
   1391 
   1392     static const soc_reg_t idb_grp_cfg_regs[TRIDENT3_TDM_PIPES_PER_DEV][2] = {
   1393         {IS_HPIPE0_OVR_SUB_GRP_CFG_PIPE0r, IS_HPIPE1_OVR_SUB_GRP_CFG_PIPE0r},
   1394         {IS_HPIPE0_OVR_SUB_GRP_CFG_PIPE1r, IS_HPIPE1_OVR_SUB_GRP_CFG_PIPE1r}
   1395     };
   1396 
   1397     static const soc_reg_t mmu_grp_cfg_regs[2] = {
   1398         HPIPE0_OVR_SUB_GRP_CFGr, HPIPE1_OVR_SUB_GRP_CFGr
   1399     };
   1400 
   1401     static const soc_reg_t idb_grp_ovs_regs[TRIDENT3_TDM_PIPES_PER_DEV][2][6] = {
   1402         {
   1403             {IS_HPIPE0_OVR_SUB_GRP0_TBL_PIPE0r, IS_HPIPE0_OVR_SUB_GRP1_TBL_PIPE0r,
   1404              IS_HPIPE0_OVR_SUB_GRP2_TBL_PIPE0r, IS_HPIPE0_OVR_SUB_GRP3_TBL_PIPE0r,
   1405              IS_HPIPE0_OVR_SUB_GRP4_TBL_PIPE0r, IS_HPIPE0_OVR_SUB_GRP5_TBL_PIPE0r },
   1406             {IS_HPIPE1_OVR_SUB_GRP0_TBL_PIPE0r, IS_HPIPE1_OVR_SUB_GRP1_TBL_PIPE0r,
   1407              IS_HPIPE1_OVR_SUB_GRP2_TBL_PIPE0r, IS_HPIPE1_OVR_SUB_GRP3_TBL_PIPE0r,
   1408              IS_HPIPE1_OVR_SUB_GRP4_TBL_PIPE0r, IS_HPIPE1_OVR_SUB_GRP5_TBL_PIPE0r }
   1409         },
   1410         {
   1411             {IS_HPIPE0_OVR_SUB_GRP0_TBL_PIPE1r, IS_HPIPE0_OVR_SUB_GRP1_TBL_PIPE1r,
   1412              IS_HPIPE0_OVR_SUB_GRP2_TBL_PIPE1r, IS_HPIPE0_OVR_SUB_GRP3_TBL_PIPE1r,
   1413              IS_HPIPE0_OVR_SUB_GRP4_TBL_PIPE1r, IS_HPIPE0_OVR_SUB_GRP5_TBL_PIPE1r },
   1414             {IS_HPIPE1_OVR_SUB_GRP0_TBL_PIPE1r, IS_HPIPE1_OVR_SUB_GRP1_TBL_PIPE1r,
   1415              IS_HPIPE1_OVR_SUB_GRP2_TBL_PIPE1r, IS_HPIPE1_OVR_SUB_GRP3_TBL_PIPE1r,
   1416              IS_HPIPE1_OVR_SUB_GRP4_TBL_PIPE1r, IS_HPIPE1_OVR_SUB_GRP5_TBL_PIPE1r }
   1417         }
   1418     };
   1419 
   1420     static const soc_reg_t mmu_grp_ovs_regs[2][6] = {
   1421         {HPIPE0_OVR_SUB_GRP0_TBLr, HPIPE0_OVR_SUB_GRP1_TBLr,
   1422          HPIPE0_OVR_SUB_GRP2_TBLr, HPIPE0_OVR_SUB_GRP3_TBLr,
   1423          HPIPE0_OVR_SUB_GRP4_TBLr, HPIPE0_OVR_SUB_GRP5_TBLr },
   1424         {HPIPE1_OVR_SUB_GRP0_TBLr, HPIPE1_OVR_SUB_GRP1_TBLr,
   1425          HPIPE1_OVR_SUB_GRP2_TBLr, HPIPE1_OVR_SUB_GRP3_TBLr,
   1426          HPIPE1_OVR_SUB_GRP4_TBLr, HPIPE1_OVR_SUB_GRP5_TBLr }
   1427     };
   1428 
   1429     static const soc_reg_t idb_pblk_cal_regs[TRIDENT3_TDM_PIPES_PER_DEV][2][8] = {
   1430         {
   1431             {IS_HPIPE0_PBLK0_CALENDAR_PIPE0r, IS_HPIPE0_PBLK1_CALENDAR_PIPE0r,
   1432              IS_HPIPE0_PBLK2_CALENDAR_PIPE0r, IS_HPIPE0_PBLK3_CALENDAR_PIPE0r,
   1433              IS_HPIPE0_PBLK4_CALENDAR_PIPE0r, IS_HPIPE0_PBLK5_CALENDAR_PIPE0r,
   1434              IS_HPIPE0_PBLK6_CALENDAR_PIPE0r, IS_HPIPE0_PBLK7_CALENDAR_PIPE0r },
   1435             {IS_HPIPE1_PBLK0_CALENDAR_PIPE0r, IS_HPIPE1_PBLK1_CALENDAR_PIPE0r,
   1436              IS_HPIPE1_PBLK2_CALENDAR_PIPE0r, IS_HPIPE1_PBLK3_CALENDAR_PIPE0r,
   1437              IS_HPIPE1_PBLK4_CALENDAR_PIPE0r, IS_HPIPE1_PBLK5_CALENDAR_PIPE0r,
   1438              IS_HPIPE1_PBLK6_CALENDAR_PIPE0r, IS_HPIPE1_PBLK7_CALENDAR_PIPE0r }
   1439         },
   1440         {
   1441             {IS_HPIPE0_PBLK0_CALENDAR_PIPE1r, IS_HPIPE0_PBLK1_CALENDAR_PIPE1r,
   1442              IS_HPIPE0_PBLK2_CALENDAR_PIPE1r, IS_HPIPE0_PBLK3_CALENDAR_PIPE1r,
   1443              IS_HPIPE0_PBLK4_CALENDAR_PIPE1r, IS_HPIPE0_PBLK5_CALENDAR_PIPE1r,
   1444              IS_HPIPE0_PBLK6_CALENDAR_PIPE1r, IS_HPIPE0_PBLK7_CALENDAR_PIPE1r },
   1445             {IS_HPIPE1_PBLK0_CALENDAR_PIPE1r, IS_HPIPE1_PBLK1_CALENDAR_PIPE1r,
   1446              IS_HPIPE1_PBLK2_CALENDAR_PIPE1r, IS_HPIPE1_PBLK3_CALENDAR_PIPE1r,
   1447              IS_HPIPE1_PBLK4_CALENDAR_PIPE1r, IS_HPIPE1_PBLK5_CALENDAR_PIPE1r,
   1448              IS_HPIPE1_PBLK6_CALENDAR_PIPE1r, IS_HPIPE1_PBLK7_CALENDAR_PIPE1r }
   1449         }
   1450     };
   1451 
   1452     static const soc_reg_t mmu_pblk_cal_regs[2][8] = {
   1453         {HPIPE0_PBLK0_CALENDARr, HPIPE0_PBLK1_CALENDARr,
   1454          HPIPE0_PBLK2_CALENDARr, HPIPE0_PBLK3_CALENDARr,
   1455          HPIPE0_PBLK4_CALENDARr, HPIPE0_PBLK5_CALENDARr,
   1456          HPIPE0_PBLK6_CALENDARr, HPIPE0_PBLK7_CALENDARr },
   1457         {HPIPE1_PBLK0_CALENDARr, HPIPE1_PBLK1_CALENDARr,
   1458          HPIPE1_PBLK2_CALENDARr, HPIPE1_PBLK3_CALENDARr,
   1459          HPIPE1_PBLK4_CALENDARr, HPIPE1_PBLK5_CALENDARr,
   1460          HPIPE1_PBLK6_CALENDARr, HPIPE1_PBLK7_CALENDARr }
   1461     };
   1462 
   1463     static int pblk_slots[SOC_TD3_PORT_RATIO_COUNT][7] = {
   1464         { 0, -1,  0,  0, -1,  0, -1 }, /* SOC_TD3_PORT_RATIO_SINGLE */
   1465         { 0, -1,  2,  0, -1,  2, -1 }, /* SOC_TD3_PORT_RATIO_DUAL_1_1 */
   1466         { 0,  0,  2,  0,  0,  2, -1 }, /* SOC_TD3_PORT_RATIO_DUAL_2_1 */
   1467         { 0,  2,  2,  0,  2,  2, -1 }, /* SOC_TD3_PORT_RATIO_DUAL_1_2 */
   1468         { 0, -1,  2,  0, -1,  3, -1 }, /* SOC_TD3_PORT_RATIO_TRI_023_2_1_1 */
   1469         { 0,  0,  2,  0,  0,  3, -1 }, /* SOC_TD3_PORT_RATIO_TRI_023_4_1_1 */
   1470         { 0, -1,  2,  1, -1,  2, -1 }, /* SOC_TD3_PORT_RATIO_TRI_012_1_1_2 */
   1471         { 0,  2,  2,  1,  2,  2, -1 }, /* SOC_TD3_PORT_RATIO_TRI_012_1_1_4 */
   1472         { 0, -1,  2,  1, -1,  3, -1 }  /* SOC_TD3_PORT_RATIO_QUAD */
   1473     };
   1474 
   1475     _soc_td3_tdm_get_pipe_map(unit, sch_info, &pipe_map);
   1476     _soc_td3_tdm_get_ovs_pipe_map(unit, sch_info, &ovs_pipe_map);
   1477 
   1478     /* OVS tables  */
   1479     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1480         if (!(ovs_pipe_map & (1 << pipe))) {
   1481             continue;
   1482         }
   1483         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   1484         for (hpipe = 0; hpipe < TRIDENT3_TDM_HPIPES_PER_PIPE; hpipe++) {
   1485             for (group = 0; group < TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE; group++) {
   1486                 for (slot = 0; slot < TRIDENT3_TDM_OVS_GROUP_LENGTH; slot++) {
   1487                     phy_port = sch_info->tdm_ingress_schedule_pipe[
   1488 					pipe].tdm_schedule_slice[hpipe].oversub_schedule[group][slot];
   1489                     /* PORT_NUMf restricts port numbering within [0-31] & 0x3f
   1490                      *      HPIPE0 port 0-31 maps to mmu/idb port 0-31
   1491                      *      HPIPE1 port 0-31 maps to mmu/idb port 32-63
   1492                      * PHY_PORT_IDf restricts port block id within [0-7]
   1493                      */
   1494                     if (phy_port > TD3_NUM_PHY_PORTS) {
   1495                         idb_port = 0x3f;
   1496                         mmu_port = 0x3f;
   1497                         id = 0x7;
   1498                     } else {
   1499                         port = sch_info->in_port_map.port_p2l_mapping[phy_port];
   1500                         idb_port = sch_info->in_port_map.port_l2i_mapping[
   1501 															port] & 0x1f;
   1502                         mmu_port = sch_info->in_port_map.port_p2m_mapping[
   1503 															phy_port] & 0x1f;
   1504                         id = sch_info->out_port_map.port_p2PBLK_inst_mapping[
   1505 															phy_port] & 0x7;
   1506                     }
   1507                     /* IDB OverSub Groups */
   1508                     if (set_idb == 1) {
   1509                         rval = 0;
   1510                         reg = idb_grp_ovs_regs[pipe][hpipe][group];
   1511                         soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id);
   1512                         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port);
   1513                         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   1514 															slot, rval));
   1515                     }
   1516                     /* MMU OverSub Groups */
   1517                     if (set_mmu == 1) {
   1518                         rval = 0;
   1519                         reg = mmu_grp_ovs_regs[hpipe][group];
   1520                         soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id);
   1521                         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port);
   1522                         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst,
   1523 																slot, rval));
   1524                     }
   1525                 }
   1526 
   1527                 /* Handle the case where the first element in the group
   1528                  * is invalid but other valid ports exist in the group.
   1529                  */
   1530                 for (slot = 0; slot < TRIDENT3_TDM_OVS_GROUP_LENGTH; slot++) {
   1531                     phy_port = sch_info->tdm_ingress_schedule_pipe[
   1532 					pipe].tdm_schedule_slice[hpipe].oversub_schedule[group][slot];
   1533                     if (phy_port < TD3_NUM_EXT_PORTS) {
   1534                         break;
   1535                     }
   1536                 }
   1537 
   1538                 /* No valid ports found, skip group */
   1539                 if (TRIDENT3_TDM_OVS_GROUP_LENGTH == slot) {
   1540                     port_speed_class = 0;
   1541                     port_same_spacing = 0;
   1542                     port_sister_spacing = 0;
   1543                 } else {
   1544                     port = sch_info->in_port_map.port_p2l_mapping[phy_port];
   1545                     prev_or_new = 1;
   1546                     soc_td3_tdm_get_log_port_speed(unit, sch_info, port,
   1547                         prev_or_new, &l_speed, &l_num_lanes);
   1548                     speed_max = 25000 * l_num_lanes;
   1549                     if (speed_max > l_speed) speed_max = l_speed;
   1550 
   1551                     port_speed_class =
   1552                         _soc_td3_tdm_get_speed_ovs_class(unit, speed_max);
   1553                     port_same_spacing =
   1554                         _soc_td3_tdm_get_same_port_spacing_e(unit, speed_max);
   1555                     port_sister_spacing = 4;
   1556                 }
   1557                 if (set_idb == 1) {
   1558                     rval = 0;
   1559                     reg = idb_grp_cfg_regs[pipe][hpipe];
   1560                     soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf, 8); /* on ingress, all ports have same spacing */
   1561                     soc_reg_field_set(unit, reg, &rval, SISTER_SPACINGf,
   1562 														port_sister_spacing);
   1563                     soc_reg_field_set(unit, reg, &rval, SPEEDf,
   1564 														port_speed_class);
   1565                     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   1566 														group, rval));
   1567                 }
   1568                 if (set_mmu == 1) {
   1569                     rval = 0;
   1570                     reg = mmu_grp_cfg_regs[hpipe];
   1571                     soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf,
   1572 														port_same_spacing);
   1573                     soc_reg_field_set(unit, reg, &rval, SISTER_SPACINGf,
   1574 														port_sister_spacing);
   1575                     soc_reg_field_set(unit, reg, &rval, SPEEDf,
   1576 														port_speed_class);
   1577                     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst,
   1578 														group, rval));
   1579                 }
   1580             }
   1581         }
   1582     }
   1583 
   1584     /* 16 Port-blocks are supported, with each instance of Oversubscription
   1585      * Cell Scheduler supports up to 8 Portblocks. */
   1586 
   1587     /* First get pblk_cal_idx to pm_num mapping from
   1588      * pm_num to pblk_cal_idx
   1589      * and **oversub_schedule
   1590      */
   1591     /* sal_memset(pblks, -1, sizeof(pblks)); */
   1592     sal_memset(pblks, -1, sizeof(int) * TRIDENT3_TDM_PIPES_PER_DEV * 2 *
   1593                TRIDENT3_TDM_PBLKS_PER_HPIPE);
   1594     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1595         if (!(ovs_pipe_map & (1 << pipe))) {
   1596             continue;
   1597         }
   1598         for (hpipe = 0; hpipe < TRIDENT3_TDM_HPIPES_PER_PIPE; hpipe++) {
   1599             for (group = 0; group < TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE; group++) {
   1600                 for (slot = 0; slot < TRIDENT3_TDM_OVS_GROUP_LENGTH; slot++) {
   1601                     phy_port = sch_info->tdm_ingress_schedule_pipe[
   1602 					pipe].tdm_schedule_slice[hpipe].oversub_schedule[group][slot];
   1603                     if (phy_port < TD3_NUM_EXT_PORTS) {
   1604                         pm_num = (phy_port - 1) / TRIDENT3_TDM_PORTS_PER_PBLK;
   1605                         pblk_cal_idx =
   1606 						sch_info->out_port_map.port_p2PBLK_inst_mapping[phy_port];
   1607                         if (pblk_cal_idx >= 0 &&
   1608                             pblk_cal_idx < TRIDENT3_TDM_PBLKS_PER_HPIPE) {
   1609                             pblks[pipe][hpipe][pblk_cal_idx] = pm_num;
   1610                         } else {
   1611                             return SOC_E_FAIL; /* invalid mapping */
   1612                         }
   1613                     }
   1614                 }
   1615             }
   1616         }
   1617     }
   1618 
   1619     /* Configure PBLKs */
   1620     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1621         if (!(ovs_pipe_map & (1 << pipe))) {
   1622             continue;
   1623         }
   1624 
   1625         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   1626         for (hpipe = 0; hpipe < TRIDENT3_TDM_HPIPES_PER_PIPE; hpipe++) {
   1627             for (pblk_cal_idx = 0; pblk_cal_idx < TRIDENT3_TDM_PBLKS_PER_HPIPE;
   1628                     pblk_cal_idx++) {
   1629                 pm_num = pblks[pipe][hpipe][pblk_cal_idx];
   1630                 phy_port_base = 1 + (pm_num * TRIDENT3_TDM_PORTS_PER_PBLK);
   1631                 /* Get port ratio for this Port Macro */
   1632                 soc_td3_tdm_get_port_ratio(unit, sch_info, pm_num, &mode, 1);
   1633                 reg  = idb_pblk_cal_regs[pipe][hpipe][pblk_cal_idx];
   1634                 reg1 = mmu_pblk_cal_regs[hpipe][pblk_cal_idx];
   1635                 /* Write PBLK regs
   1636                  *      Only first 6 out of 7 slots could be valid
   1637                  */
   1638                 if ((pm_num < 0) || (pm_num > TRIDENT3_TDM_PBLKS_PER_DEV)) {
   1639                     /* To speed-up init this branch could be skipped */
   1640                     for (slot = 0; slot < 6; slot++) {
   1641                         rval = 0;
   1642                         rval1 = 0;
   1643                         if (set_idb == 1) {
   1644                             soc_reg_field_set(unit, reg,  &rval,  PORT_NUMf,
   1645 																	0x3f);
   1646                             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg,
   1647 											REG_PORT_ANY, slot, rval));
   1648                         }
   1649                         if (set_mmu == 1) {
   1650                             soc_reg_field_set(unit, reg1,  &rval1,  PORT_NUMf,
   1651 																	 0x3f);
   1652                             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg1,
   1653 													inst, slot, rval1));
   1654                         }
   1655                     }
   1656                 } else {
   1657                     for (slot = 0; slot < 6; slot++) {
   1658                         rval = 0;
   1659                         rval1 = 0;
   1660                         lane = pblk_slots[mode][slot];
   1661                         if (lane == -1) {
   1662                             pblk_valid = 0;
   1663                             idb_port = 0x3f;
   1664                             mmu_port = 0x3f;
   1665                             pblk_spacing = 0; /* same spacing */
   1666                         } else {
   1667                             pblk_valid = 1;
   1668                             port = sch_info->in_port_map.port_p2l_mapping[
   1669 												phy_port_base + lane];
   1670                             idb_port = sch_info->in_port_map.port_l2i_mapping[
   1671 												port] & 0x1f;
   1672                             mmu_port = sch_info->in_port_map.port_p2m_mapping[
   1673 												phy_port_base + lane] & 0x1f;
   1674 
   1675                             prev_or_new = 1;
   1676                             soc_td3_tdm_get_log_port_speed(unit, sch_info,
   1677                                 port, prev_or_new, &l_speed, &l_num_lanes);
   1678                             speed_max = 25000 * l_num_lanes;
   1679                             if (speed_max > l_speed) speed_max = l_speed;
   1680 
   1681                             port_speed_class =
   1682                                 _soc_td3_tdm_get_speed_ovs_class(unit,
   1683 											speed_max);
   1684                             pblk_spacing =
   1685                                 _soc_td3_tdm_get_same_port_spacing_e(unit,
   1686 											speed_max);
   1687                         }
   1688 
   1689                         soc_reg_field_set(unit, reg,  &rval,  VALIDf,
   1690 																pblk_valid);
   1691                         soc_reg_field_set(unit, reg,  &rval,  SPACINGf,
   1692 																8);
   1693                         soc_reg_field_set(unit, reg,  &rval,  PORT_NUMf,
   1694 																idb_port);
   1695 
   1696                         soc_reg_field_set(unit, reg1, &rval1, VALIDf,
   1697 																pblk_valid);
   1698                         soc_reg_field_set(unit, reg1, &rval1, SPACINGf,
   1699 																pblk_spacing);
   1700                         soc_reg_field_set(unit, reg1, &rval1, PORT_NUMf,
   1701 																mmu_port);
   1702                         if (set_idb == 1) {
   1703                             SOC_IF_ERROR_RETURN
   1704                                 (soc_reg32_set(unit, reg, REG_PORT_ANY,
   1705 															slot, rval));
   1706                         }
   1707                         if (set_mmu == 1) {
   1708                             SOC_IF_ERROR_RETURN
   1709                                 (soc_reg32_set(unit, reg1, inst,
   1710 														slot, rval1));
   1711                         }
   1712                     }
   1713                 }
   1714             }
   1715         }
   1716     }
   1717 
   1718     return SOC_E_NONE;
   1719 }
   1720 
   1721 
   1722 /*! @fn int _soc_td3_tdm_set_ovs_group(
   1723         int unit,
   1724         soc_port_schedule_state_t *sch_info)
   1725     @param unit Chip unit number.
   1726     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
   1727     @brief API to initialize the TD3 MMU & IDB OVS tables.
   1728             Regs/Mems configured: IDB HPIPE0/1_OVR_SUB_GRP_CFG
   1729                                   HPIPE0/1_OVR_SUB_GRP_CFG
   1730                                   PBLK<n>_CALENDAR
   1731  */
   1732 int
   1733 _soc_td3_tdm_set_ovs_group(int unit, soc_port_schedule_state_t *sch_info)
   1734 {
   1735     return (_soc_td3_tdm_set_ovs_group_sel(unit, sch_info, 1, 1));
   1736 }
   1737 
   1738 
   1739 /*! @fn int _soc_td3_tdm_set_mmu_calendar(
   1740         int unit,
   1741         soc_port_schedule_state_t *sch_info)
   1742     @param unit Chip unit number.
   1743     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
   1744     @brief API to initialize the TD3 MMU main calendar.
   1745             Regs/Mems configured: MMU TDM_CALENDAR
   1746                                   TDM_CONFIG
   1747  */
   1748 int
   1749 _soc_td3_tdm_set_mmu_calendar(int unit, soc_port_schedule_state_t *sch_info)
   1750 {
   1751     uint32 pipe_map;
   1752     uint32 cal_len;
   1753     soc_mem_t mem;
   1754     soc_reg_t reg;
   1755     soc_field_t cal_end_field;
   1756     int pipe, slot, id, length, calendar_id;
   1757     int phy_port, mmu_port, inst;
   1758     uint32 rval;
   1759     uint32 memfld;
   1760     uint32 entry[SOC_MAX_MEM_WORDS];
   1761     uint32 mem_indx;
   1762     static const soc_mem_t calendar_mems[] = {
   1763         TDM_CALENDAR0_PIPE0m,
   1764         TDM_CALENDAR0_PIPE1m,
   1765         TDM_CALENDAR1_PIPE0m,
   1766         TDM_CALENDAR1_PIPE1m
   1767     };
   1768     static const soc_field_t calendar_end_fields[] = {
   1769         CAL0_ENDf, CAL1_ENDf
   1770     };
   1771 
   1772     _soc_td3_tdm_get_pipe_map(unit, sch_info, &pipe_map);
   1773     sal_memset(entry, 0, sizeof(uint32) * soc_mem_entry_words(unit,
   1774 								TDM_CALENDAR0_PIPE0m));
   1775     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1776         if (!(pipe_map & (1 << pipe))) {
   1777             continue;
   1778         }
   1779 
   1780         /* Determine calendar_id: 0 or 1 */
   1781         reg = TDM_CONFIGr;
   1782         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   1783         if (sch_info->is_flexport == 1) { /* choose "the other one" */
   1784             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   1785             calendar_id = soc_reg_field_get(unit, reg, rval, CURR_CALf) ^ 1;
   1786         } else {
   1787             calendar_id = 0; /* At init use calendar_id=0 */
   1788             rval = 0;
   1789         }
   1790         mem = calendar_mems[(calendar_id * TRIDENT3_TDM_PIPES_PER_DEV) + pipe];
   1791         cal_end_field = calendar_end_fields[calendar_id];
   1792 
   1793         /* TDM Calendar is always taken from slice 0 */
   1794         cal_len = sch_info->tdm_egress_schedule_pipe[
   1795 					pipe].tdm_schedule_slice[0].cal_len;
   1796         for (length = cal_len; length > 0; length--) {
   1797             if (sch_info->tdm_egress_schedule_pipe[pipe].tdm_schedule_slice[
   1798 					0].linerate_schedule[length - 1] != TD3_NUM_EXT_PORTS) {
   1799                 break;
   1800             }
   1801         }
   1802         for (slot = 0; slot < length; slot += 2) {
   1803             /* EVEN */
   1804             phy_port = sch_info->tdm_egress_schedule_pipe[
   1805 				pipe].tdm_schedule_slice[0].linerate_schedule[slot];
   1806             if (phy_port == TD3_OVSB_TOKEN) {
   1807                 mmu_port = TRIDENT3_TDM_MMU_OVSB_TOKEN;
   1808             } else if (phy_port == TD3_IDL1_TOKEN) {
   1809                 mmu_port = TRIDENT3_TDM_MMU_PURG_TOKEN;
   1810             } else if (phy_port == TD3_IDL2_TOKEN) {
   1811                 mmu_port = TRIDENT3_TDM_MMU_UNUSED_TOKEN;
   1812             } else if (phy_port == TD3_NULL_TOKEN) {
   1813                 mmu_port = TRIDENT3_TDM_MMU_NULL_TOKEN;
   1814             } else if (phy_port >= TD3_NUM_EXT_PORTS) {
   1815                 mmu_port = TRIDENT3_TDM_MMU_UNUSED_TOKEN;
   1816             } else if (phy_port == TD3_MGM1_TOKEN) {
   1817                 /* TDM code always allocates slots for management port.
   1818                  * If mgmt ports are omitted from config, this mapping
   1819                  * is not set up.
   1820                  */
   1821                 mmu_port = TRIDENT3_TDM_MMU_MGMT1_TOKEN;
   1822             } else {
   1823                 /* [0,69] && 127 */
   1824                 mmu_port = sch_info->out_port_map.port_p2m_mapping[
   1825 						phy_port] & 0x7f;
   1826             }
   1827             if (mmu_port > 63) {
   1828                 id = 0xf;
   1829             } else {
   1830                 id = (phy_port - 1) / TRIDENT3_TDM_PORTS_PER_PBLK;
   1831             }
   1832             memfld = mmu_port & 0x7f;
   1833             soc_mem_field_set(unit, mem, entry, PORT_NUM_EVENf, &memfld);
   1834             memfld = id & 0xf;
   1835             soc_mem_field_set(unit, mem, entry, PHY_PORT_ID_EVENf, &memfld);
   1836             /* ODD */
   1837             phy_port = sch_info->tdm_egress_schedule_pipe[
   1838 					pipe].tdm_schedule_slice[0].linerate_schedule[slot + 1];
   1839             if (phy_port == TD3_OVSB_TOKEN) {
   1840                 mmu_port = TRIDENT3_TDM_MMU_OVSB_TOKEN;
   1841             } else if (phy_port == TD3_IDL1_TOKEN) {
   1842                 mmu_port = TRIDENT3_TDM_MMU_PURG_TOKEN;
   1843             } else if (phy_port == TD3_IDL2_TOKEN) {
   1844                 mmu_port = TRIDENT3_TDM_MMU_UNUSED_TOKEN;
   1845             } else if (phy_port == TD3_NULL_TOKEN) {
   1846                 mmu_port = TRIDENT3_TDM_MMU_NULL_TOKEN;
   1847             } else if (phy_port >= TD3_NUM_EXT_PORTS) {
   1848                 mmu_port = TRIDENT3_TDM_MMU_UNUSED_TOKEN;
   1849             } else if (phy_port == TD3_MGM1_TOKEN) {
   1850                 /* TDM code always allocates slots for management port.
   1851                  * If mgmt ports are omitted from config, this mapping
   1852                  * is not set up.
   1853                  */
   1854                 mmu_port = TRIDENT3_TDM_MMU_MGMT1_TOKEN;
   1855             } else {
   1856                 /* [0,69] && 127 */
   1857                 mmu_port = sch_info->out_port_map.port_p2m_mapping[
   1858 								phy_port] & 0x7f;
   1859             }
   1860             if (mmu_port > 63) {
   1861                 id = 0xf;
   1862             } else {
   1863                 id = (phy_port - 1) / TRIDENT3_TDM_PORTS_PER_PBLK;
   1864             }
   1865             memfld = mmu_port & 0x7f;
   1866             soc_mem_field_set(unit, mem, entry, PORT_NUM_ODDf, &memfld);
   1867             memfld = id & 0xf;
   1868             soc_mem_field_set(unit, mem, entry, PHY_PORT_ID_ODDf, &memfld);
   1869             /* Memory entry */
   1870             mem_indx = slot / 2;
   1871             SOC_IF_ERROR_RETURN
   1872                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_indx, entry));
   1873         }
   1874 
   1875         /* set for 2nd management port */
   1876         if (_soc_td3_tdm_check_2nd_mgmt_enable(unit, sch_info) == 1 &&
   1877             pipe == (TRIDENT3_TDM_PIPES_PER_DEV - 1)) {
   1878             soc_reg_field_set(unit, reg, &rval, MGMT_2ND_PORT_ENABLEf, 1);
   1879         }
   1880 
   1881         soc_reg_field_set(unit, reg, &rval, cal_end_field, length-1);
   1882         soc_reg_field_set(unit, reg, &rval, CURR_CALf, calendar_id);
   1883         soc_reg_field_set(unit, reg, &rval, ENABLEf, 1);
   1884         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   1885     }
   1886 
   1887     return SOC_E_NONE;
   1888 }
   1889 
   1890 
   1891 /*! @fn int _soc_td3_tdm_set_mmu_hsp(
   1892         int unit,
   1893         soc_port_schedule_state_t *sch_info)
   1894     @param unit Chip unit number.
   1895     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
   1896     @brief API to initialize the TD3 MMU HSP.
   1897             Regs/Mems configured: TDM_HSP_PIPE
   1898  */
   1899 int
   1900 _soc_td3_tdm_set_mmu_hsp(int unit,
   1901                          soc_port_schedule_state_t *sch_info)
   1902 {
   1903     soc_reg_t reg;
   1904     uint32 pipe_map;
   1905     int pipe, hpipe, inst;
   1906     int port, mmu_port, phy_port;
   1907     uint32 port_map[TRIDENT3_TDM_PIPES_PER_DEV][2];
   1908     uint32 rval = 0;
   1909     int l_speed = 0, l_num_lanes = 0, prev_or_new = 0;
   1910 
   1911     _soc_td3_tdm_get_pipe_map(unit, sch_info, &pipe_map);
   1912 
   1913     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1914         port_map[pipe][0] = 0;
   1915         port_map[pipe][1] = 0;
   1916     }
   1917 
   1918     for (port=0; port<TRIDENT3_TDM_PHY_PORTS_PER_DEV; port++) {
   1919         if (sch_info->out_port_map.log_port_speed[port] > 0) {
   1920             soc_td3_tdm_get_log_port_speed(unit, sch_info, port,
   1921                 prev_or_new, &l_speed, &l_num_lanes);
   1922             if (_soc_td3_tdm_check_is_hsp_port_e(unit, l_speed) == 1) {
   1923                 phy_port = sch_info->out_port_map.port_l2p_mapping[port];
   1924                 if ((phy_port >= 1) && (phy_port <= TRIDENT3_TDM_GPORTS_PER_DEV)) {
   1925                     pipe = (phy_port - 1) / TRIDENT3_TDM_GPORTS_PER_PIPE;
   1926                     hpipe = ((phy_port - 1) & 0x3f) /
   1927                             TRIDENT3_TDM_GPORTS_PER_HPIPE;
   1928                     mmu_port = sch_info->out_port_map.port_p2m_mapping[
   1929 							phy_port] & 0x1f;
   1930                     if (pipe < TRIDENT3_TDM_PIPES_PER_DEV && hpipe < 2) {
   1931                         port_map[pipe][hpipe] |= 1 << mmu_port;
   1932                     }
   1933                 }
   1934             }
   1935         }
   1936     }
   1937 
   1938     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1939         if (!(pipe_map & (1 << pipe))) {
   1940             continue;
   1941         }
   1942         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   1943 
   1944         reg = TDM_HSP_0r;
   1945         soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[pipe][0]);
   1946         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   1947 
   1948         reg = TDM_HSP_1r;
   1949         soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[pipe][1]);
   1950         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   1951     }
   1952 
   1953     return SOC_E_NONE;
   1954 }
   1955 
   1956 
   1957 /*! @fn int _soc_td3_tdm_set_mmu_opportunistic(
   1958         int unit,
   1959         soc_port_schedule_state_t *sch_info,
   1960         int cpu_op_en,
   1961         int lb_opp_en,
   1962         int opp1_port_en,
   1963         int opp2_port_en,
   1964         int opp_ovr_sub_en)
   1965     @param unit Chip unit number.
   1966     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
   1967     @param cpu_op_en
   1968     @param lb_opp_en
   1969     @param opp1_port_en
   1970     @param opp2_port_en
   1971     @param opp_ovr_sub_en
   1972     @brief API to initialize the TD3 MMU Opportunistic related registers
   1973             Regs/Mems configured: CPU_LB_OPP_CFG
   1974                                   OPP_SCHED_CFG
   1975  */
   1976 int
   1977 _soc_td3_tdm_set_mmu_opportunistic(int unit,
   1978                                    soc_port_schedule_state_t *sch_info,
   1979                                    int cpu_op_en,
   1980                                    int lb_opp_en,
   1981                                    int opp1_port_en,
   1982                                    int opp2_port_en,
   1983                                    int opp_ovr_sub_en)
   1984 {
   1985     uint32 pipe_map;
   1986     soc_reg_t reg;
   1987     int pipe;
   1988     int inst;
   1989     uint32 rval;
   1990 
   1991     _soc_td3_tdm_get_pipe_map(unit, sch_info, &pipe_map);
   1992 
   1993     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
   1994         if (!(pipe_map & (1 << pipe))) {
   1995             continue;
   1996         }
   1997 
   1998         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   1999 
   2000         reg = CPU_LB_OPP_CFGr;
   2001         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   2002         soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf,
   2003 										(cpu_op_en == 1) ? 1 : 0);
   2004         soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf,
   2005 										(lb_opp_en == 1) ? 1 : 0);
   2006         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   2007 
   2008         reg = OPP_SCHED_CFGr;
   2009         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   2010         soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf,
   2011 											(opp1_port_en == 1) ? 1 : 0);
   2012         soc_reg_field_set(unit, reg, &rval, OPP1_SPACINGf, 6);
   2013         soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf,
   2014 											(opp2_port_en == 1) ? 1 : 0);
   2015         soc_reg_field_set(unit, reg, &rval, OPP2_SPACINGf, 0);
   2016         soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf,
   2017 											(opp_ovr_sub_en == 1) ? 1 : 0);
   2018         soc_reg_field_set(unit, reg, &rval, OPP_STRICT_PRIf, 0);
   2019         soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 67);
   2020         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   2021     }
   2022 
   2023     return SOC_E_NONE;
   2024 }
   2025 
   2026 
   2027 /*! @fn int soc_td3_tdm_init(
   2028         int unit,
   2029         soc_port_schedule_state_t *sch_info)
   2030     @param unit Chip unit number.
   2031     @param sch_info Pointer to a soc_port_schedule_state_t struct variable.
   2032     @brief Main API for TDM init
   2033  */
   2034 int soc_td3_tdm_init(int unit, soc_port_schedule_state_t *sch_info)
   2035 {
   2036     SOC_IF_ERROR_RETURN(_soc_td3_tdm_calculation(unit, sch_info));
   2037 
   2038     SOC_IF_ERROR_RETURN(_soc_td3_tdm_set_idb_calendar(unit, sch_info));
   2039     SOC_IF_ERROR_RETURN(_soc_td3_tdm_set_idb_hsp(unit, sch_info));
   2040     SOC_IF_ERROR_RETURN(_soc_td3_tdm_set_idb_pkt_calendar(unit, sch_info));
   2041     SOC_IF_ERROR_RETURN(_soc_td3_tdm_set_idb_ppe_credit(unit, sch_info,
   2042                                                         16, 9, 16, 9));
   2043     /* IDB opp1_port_en should always be 1 to enable sbus access to the rest of IPIPE*/
   2044     SOC_IF_ERROR_RETURN(_soc_td3_tdm_set_idb_opportunistic(unit, sch_info,
   2045                                                            1, 1, 1, 1, 1));
   2046 
   2047     SOC_IF_ERROR_RETURN(_soc_td3_tdm_set_ovs_group(unit, sch_info));
   2048     SOC_IF_ERROR_RETURN(_soc_td3_tdm_set_mmu_calendar(unit, sch_info));
   2049     SOC_IF_ERROR_RETURN(_soc_td3_tdm_set_mmu_hsp(unit, sch_info));
   2050     SOC_IF_ERROR_RETURN(_soc_td3_tdm_set_mmu_opportunistic(unit, sch_info,
   2051                                                            1, 1, 1, 1, 1));
   2052 
   2053     return SOC_E_NONE;
   2054 }
   2055 
   2056 /*! @fn int soc_trident3_port_speed_higig2eth(int speed)
   2057  *  @param int speed
   2058  *  @brief Map port speed to ETH bitrates
   2059  */
   2060 static int
   2061 soc_trident3_port_speed_higig2eth(int speed)
   2062 {
   2063     switch (speed) {
   2064     case 11000:
   2065         /* 10G */
   2066         return 10000;
   2067     case 21000:
   2068         /* 20G */
   2069         return 20000;
   2070     case 27000:
   2071         /* 25G */
   2072         return 25000;
   2073     case 42000:
   2074         /* 40G */
   2075         return 40000;
   2076     case 53000:
   2077         /* 50G */
   2078         return 50000;
   2079     case 106000:
   2080         /* 100G */
   2081         return 100000;
   2082     default:
   2083         return speed;
   2084     }
   2085 }
   2086 
   2087 /*! @fn void soc_trident3_port_schedule_speed_remap(int unit,
   2088  *               soc_port_schedule_state_t *port_schedule_state)
   2089  *  @param unit Chip unit number.
   2090  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
   2091  *         variable.
   2092  *  @brief API to remap speeds to ETH bitrates
   2093  */
   2094 void
   2095 soc_trident3_port_schedule_speed_remap(
   2096     int  unit,
   2097     soc_port_schedule_state_t *port_schedule_state)
   2098 {
   2099     int i, port;
   2100 
   2101     /* Speed remap for in_port_map*/
   2102     for (port=0; port < SOC_MAX_NUM_PORTS; port++) {
   2103         port_schedule_state->in_port_map.log_port_speed[port] =
   2104             soc_trident3_port_speed_higig2eth(
   2105 				port_schedule_state->in_port_map.log_port_speed[port]);
   2106     }
   2107 
   2108     if (port_schedule_state->is_flexport == 1) {
   2109         /* Speed remap for out_port_map*/
   2110         for (port=0; port < SOC_MAX_NUM_PORTS; port++) {
   2111             port_schedule_state->out_port_map.log_port_speed[port] =
   2112                 soc_trident3_port_speed_higig2eth(
   2113 				port_schedule_state->out_port_map.log_port_speed[port]);
   2114         }
   2115         /* Speed remap for resource */
   2116         for (i = 0; i < port_schedule_state->nport; i++) {
   2117             if (-1 != port_schedule_state->resource[i].physical_port) { /* that is, port up */
   2118                 port_schedule_state->resource[i].speed =
   2119                     soc_trident3_port_speed_higig2eth(
   2120 						port_schedule_state->resource[i].speed);
   2121             }
   2122         }
   2123     }
   2124 }
   2125 
   2126 /*! @fn int soc_td3_tdm_get_log_port_speed(int unit,
   2127  *   soc_port_schedule_state_t *port_schedule_state,
   2128  *  int log_port,
   2129  *  int prev_or_new,
   2130  *  int *speed,
   2131  *  int *num_lanes)
   2132  *  @param unit Chip unit number.
   2133  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
   2134  *         variable.
   2135  *  @param log_port: logical port
   2136  *  @param prev_or_new: if = 1 use in_port_map, otherwise use out_port_map.
   2137  *  int *speed: port speed returned
   2138  *  int *num_lanes: num lanes returned
   2139  *  @brief helper func to get the scheduler speed and num lanes
   2140  */
   2141 int
   2142 soc_td3_tdm_get_log_port_speed(
   2143     int unit,
   2144     soc_port_schedule_state_t *port_schedule_state,
   2145     int log_port,
   2146     int prev_or_new,
   2147     int *speed,
   2148     int *num_lanes)
   2149 {
   2150     soc_port_map_type_t *port_map;
   2151 
   2152     if (prev_or_new == 1) {
   2153         port_map = &port_schedule_state->in_port_map;
   2154     } else {
   2155         port_map = &port_schedule_state->out_port_map;
   2156     }
   2157 
   2158     *speed = port_map->log_port_speed[log_port];
   2159     *num_lanes = port_map->port_num_lanes[log_port];
   2160 
   2161     /* If 25G should act as 50G in the scheduler, change speed and num_lanes */
   2162     if (SOC_PBMP_MEMBER(port_map->physical_pbm, log_port) &&
   2163         (*speed == 25000) ) {
   2164         *speed = 50000;
   2165         *num_lanes = 2;
   2166     }
   2167 
   2168     return SOC_E_NONE;
   2169 }
   2170 
   2171 /*** END SDK API COMMON CODE ***/
   2172 
   2173 #endif /* BCM_TRIDENT3_SUPPORT */