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

tsn_taf.c (131136B)


      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  * Purpose:
      8  * Manage chip specific functionality for TSN TAF implementation on GH2.
      9  */
     10 
     11 #include <soc/drv.h>
     12 #include <bcm/error.h>
     13 #include <bcm/types.h>
     14 #include <bcm/tsn.h>
     15 #include <bcm_int/esw/port.h>
     16 #include <bcm_int/esw/tsn.h>
     17 #include <bcm_int/esw/tsn_taf.h>
     18 #include <bcm_int/esw_dispatch.h>
     19 #include <soc/profile_mem.h>
     20 #include <shared/bsl.h>
     21 #include <shared/shr_res_bitmap.h>
     22 #ifdef BCM_WARM_BOOT_SUPPORT
     23 #include <soc/scache.h>
     24 #include <bcm_int/esw/switch.h>
     25 #endif /* BCM_WARM_BOOT_SUPPORT */
     26 
     27 #if defined(BCM_TSN_SUPPORT)
     28 #define WRITE_PTR(__ptr__, __type__, __data__)    \
     29         do {                                      \
     30           *((__type__*)(__ptr__)) = (__data__);   \
     31           (__ptr__) += sizeof(__type__);          \
     32         } while (0)
     33 
     34 #define WRITE_PTR_RANGE(__ptr__, __size__, __data__)       \
     35         do {                                               \
     36           sal_memcpy((__ptr__), (__data__), (__size__));   \
     37           (__ptr__) += (__size__);                         \
     38         } while (0)
     39 
     40 #define READ_PTR(__ptr__, __type__, __dest__)     \
     41         do {                                      \
     42           (__dest__) = *((__type__*)(__ptr__));   \
     43           (__ptr__) += sizeof(__type__);          \
     44         } while (0)
     45 
     46 #define READ_PTR_RANGE(__ptr__, __size__, __dest__)        \
     47         do {                                               \
     48           sal_memcpy((__dest__), (__ptr__), (__size__));   \
     49           (__ptr__) += (__size__);                         \
     50         } while (0)
     51 
     52 /* GCLT time interval resolution : 8 ns */
     53 #define TAF_GCLT_TICKS  (8)
     54 
     55 /*
     56  * taf gate
     57  */
     58 #define TAF_GATE_RESERVED_ID        (0)
     59 STATIC shr_res_bitmap_handle_t taf_gate_bitmap[SOC_MAX_NUM_DEVICES];
     60 STATIC uint32 taf_gate_refcount[SOC_MAX_NUM_DEVICES][BCMI_TSN_TAF_GATE_NUM];
     61 
     62 /*
     63  * taf gate pri map
     64  */
     65 #define TAF_GATE_PRI_MAP_PROFILE_OFFSET     (0)
     66 #define TAF_GATE_PRI_MAP_PROFILE_WIDTH      (7)
     67 #define TAF_GATE_PRI_MAP_PROFILE_INVALID_ID (0)
     68 #define TAF_GATE_PRI_MAP_PROFILE_NUM    (1 << TAF_GATE_PRI_MAP_PROFILE_WIDTH)
     69 #define TAF_GATE_PRI_MAP_PROFILE_MASK                       \
     70             (((1 << TAF_GATE_PRI_MAP_PROFILE_WIDTH) - 1) << \
     71              TAF_GATE_PRI_MAP_PROFILE_OFFSET)
     72 #define TAF_GATE_PRI_MAP_INTPRI_OFFSET (7)
     73 #define TAF_GATE_PRI_MAP_INTPRI_WIDTH  (4)
     74 #define TAF_GATE_PRI_MAP_INTPRI_NUM    (1 << TAF_GATE_PRI_MAP_INTPRI_WIDTH)
     75 #define TAF_GATE_PRI_MAP_INTPRI_MASK                       \
     76             (((1 << TAF_GATE_PRI_MAP_INTPRI_WIDTH) - 1) << \
     77              TAF_GATE_PRI_MAP_INTPRI_OFFSET)
     78 #define TAF_GATE_PRI_MAP_PREEMPT_OFFSET (11)
     79 #define TAF_GATE_PRI_MAP_PREEMPT_WIDTH  (1)
     80 #define TAF_GATE_PRI_MAP_PREEMPT_NUM    (1 << TAF_GATE_PRI_MAP_PREEMPT_WIDTH)
     81 #define TAF_GATE_PRI_MAP_PREEMPT_MASK                       \
     82             (((1 << TAF_GATE_PRI_MAP_PREEMPT_WIDTH) - 1) << \
     83              TAF_GATE_PRI_MAP_PREEMPT_OFFSET)
     84 STATIC const soc_mem_t taf_gate_pri_map_mem = TAF_GATE_ID_LOOKUPm;
     85 
     86 /*
     87  * taf max bytes profile
     88  */
     89 #define TAF_MAXBYTE_PROFILE_RESERVED_ID        (0)
     90 #define TAF_MAXBYTE_PROFILE_NUM                (4)
     91 STATIC shr_res_bitmap_handle_t taf_maxbyte_profile_bitmap
     92                                           [SOC_MAX_NUM_DEVICES]
     93                                           [BCMI_TSN_TAF_GATE_NUM];
     94 STATIC uint32 taf_maxbyte_profile_refcount[SOC_MAX_NUM_DEVICES]
     95                                           [BCMI_TSN_TAF_GATE_NUM]
     96                                           [TAF_MAXBYTE_PROFILE_NUM];
     97 STATIC const soc_field_t taf_maxbyte_profile_field[TAF_MAXBYTE_PROFILE_NUM]
     98                            = {TAF_GATE_MAXBYTES_0f, TAF_GATE_MAXBYTES_1f,
     99                               TAF_GATE_MAXBYTES_2f, TAF_GATE_MAXBYTES_3f};
    100 STATIC const soc_mem_t taf_maxbyte_profile_mem = TAF_GATE_CONTROLm;
    101 
    102 /*
    103  * taf CosQ profile
    104  */
    105 #define TAF_COSQ_INTPRI_OFFSET (0)
    106 #define TAF_COSQ_INTPRI_WIDTH  (4)
    107 #define TAF_COSQ_INTPRI_NUM    (1 << TAF_COSQ_INTPRI_WIDTH)
    108 #define TAF_COSQ_INTPRI_MASK                       \
    109             (((1 << TAF_COSQ_INTPRI_WIDTH) - 1) << \
    110              TAF_COSQ_INTPRI_OFFSET)
    111 
    112 #define TAF_COSQ_SELECT_OFFSET (4)
    113 #define TAF_COSQ_SELECT_WIDTH  (2)
    114 #define TAF_COSQ_SELECT_NUM    (1 << TAF_COSQ_SELECT_WIDTH)
    115 #define TAF_COSQ_SELECT_MASK                       \
    116             (((1 << TAF_COSQ_SELECT_WIDTH) - 1) << \
    117              TAF_COSQ_SELECT_OFFSET)
    118 
    119 #define TAF_COSQ_PROFILE_RESERVED_ID   (0)
    120 #define TAF_COSQ_PROFILE_OFFSET        (6)
    121 #define TAF_COSQ_PROFILE_WIDTH         (4)
    122 #define TAF_COSQ_PROFILE_NUM           (1 << TAF_COSQ_PROFILE_WIDTH)
    123 #define TAF_COSQ_PROFILE_MASK                       \
    124             (((1 << TAF_COSQ_PROFILE_WIDTH) - 1) << \
    125              TAF_COSQ_PROFILE_OFFSET)
    126 
    127 #define TAF_COSQ_HW_INDEX(_profile_id_, _select_, _prio_)                \
    128                           (((_profile_id_) << TAF_COSQ_PROFILE_OFFSET) | \
    129                            ((_select_) << TAF_COSQ_SELECT_OFFSET)      | \
    130                            ((_prio_) << TAF_COSQ_INTPRI_OFFSET))
    131 
    132 STATIC shr_res_bitmap_handle_t taf_cosq_profile_bitmap[SOC_MAX_NUM_DEVICES];
    133 STATIC uint32 taf_cosq_profile_refcount[SOC_MAX_NUM_DEVICES]
    134                                        [TAF_COSQ_PROFILE_NUM];
    135 STATIC const soc_mem_t taf_cosq_profile_mem = PORT_COS_MAPm;
    136 STATIC const soc_field_t taf_cosq_profile_field = COSf;
    137 
    138 /*
    139  * taf schedule profile
    140  */
    141 STATIC shr_res_bitmap_handle_t taf_schedule_profile_bitmap
    142                                [SOC_MAX_NUM_DEVICES];
    143 STATIC bcmi_tsn_taf_profile_t *taf_schedule_profile
    144                                [SOC_MAX_NUM_DEVICES]
    145                                [BCMI_TSN_TAF_PROFILE_NUM_MAX];
    146 
    147 /*
    148  * taf schedule timelime
    149  */
    150 #define TAF_SCHEDULE_CALENDAR_ENTIRES    (16)         /* GCLT table size */
    151 #define TAF_SCHEDULE_HW_RESPONSE_TIME    (500000)     /*     500000 ns */
    152 #define TAF_SCHEDULE_SW_RESPONSE_TIME    (1000000000) /* 1000000000 ns */
    153 #define TAF_SCHEDULE_NANOSEC_MAX         (1000000000) /* 10^9 */
    154 
    155 #define TAF_SCHEDULE_SEC_WIDTH           (6)    /* GH2 only support 6 bit
    156                                                  * second value
    157                                                  */
    158 #define TAF_SCHEDULE_SEC_MASK            ((1 << TAF_SCHEDULE_SEC_WIDTH) - 1)
    159 STATIC bcmi_tsn_taf_schedule_entry_t *taf_schedule_timeline
    160                                       [SOC_MAX_NUM_DEVICES]
    161                                       [BCMI_TSN_TAF_GATE_NUM];
    162 STATIC uint8 *taf_schedule_calendar_buf[SOC_MAX_NUM_DEVICES];
    163 STATIC const soc_mem_t taf_schedule_calendar_mem[2][BCMI_TSN_TAF_GATE_NUM]
    164     = {{TAF_GATE_CTL_TBL0_P0m, TAF_GATE_CTL_TBL0_P1m,
    165         TAF_GATE_CTL_TBL0_P2m, TAF_GATE_CTL_TBL0_P3m,
    166         TAF_GATE_CTL_TBL0_P4m, TAF_GATE_CTL_TBL0_P5m,
    167         TAF_GATE_CTL_TBL0_P6m, TAF_GATE_CTL_TBL0_P7m,
    168         TAF_GATE_CTL_TBL0_P8m, TAF_GATE_CTL_TBL0_P9m,
    169         TAF_GATE_CTL_TBL0_P10m, TAF_GATE_CTL_TBL0_P11m,
    170         TAF_GATE_CTL_TBL0_P12m, TAF_GATE_CTL_TBL0_P13m,
    171         TAF_GATE_CTL_TBL0_P14m, TAF_GATE_CTL_TBL0_P15m,
    172         TAF_GATE_CTL_TBL0_P16m, TAF_GATE_CTL_TBL0_P17m,
    173         TAF_GATE_CTL_TBL0_P18m, TAF_GATE_CTL_TBL0_P19m,
    174         TAF_GATE_CTL_TBL0_P20m, TAF_GATE_CTL_TBL0_P21m,
    175         TAF_GATE_CTL_TBL0_P22m, TAF_GATE_CTL_TBL0_P23m,
    176         TAF_GATE_CTL_TBL0_P24m, TAF_GATE_CTL_TBL0_P25m,
    177         TAF_GATE_CTL_TBL0_P26m, TAF_GATE_CTL_TBL0_P27m,
    178         TAF_GATE_CTL_TBL0_P28m, TAF_GATE_CTL_TBL0_P29m,
    179         TAF_GATE_CTL_TBL0_P30m, TAF_GATE_CTL_TBL0_P31m,
    180         TAF_GATE_CTL_TBL0_P32m, TAF_GATE_CTL_TBL0_P33m,
    181         TAF_GATE_CTL_TBL0_P34m, TAF_GATE_CTL_TBL0_P35m,
    182         TAF_GATE_CTL_TBL0_P36m, TAF_GATE_CTL_TBL0_P37m,
    183         TAF_GATE_CTL_TBL0_P38m, TAF_GATE_CTL_TBL0_P39m,
    184         TAF_GATE_CTL_TBL0_P40m, TAF_GATE_CTL_TBL0_P41m,
    185         TAF_GATE_CTL_TBL0_P42m, TAF_GATE_CTL_TBL0_P43m,
    186         TAF_GATE_CTL_TBL0_P44m, TAF_GATE_CTL_TBL0_P45m,
    187         TAF_GATE_CTL_TBL0_P46m, TAF_GATE_CTL_TBL0_P47m,
    188         TAF_GATE_CTL_TBL0_P48m, TAF_GATE_CTL_TBL0_P49m,
    189         TAF_GATE_CTL_TBL0_P50m, TAF_GATE_CTL_TBL0_P51m,
    190         TAF_GATE_CTL_TBL0_P52m, TAF_GATE_CTL_TBL0_P53m,
    191         TAF_GATE_CTL_TBL0_P54m, TAF_GATE_CTL_TBL0_P55m,
    192         TAF_GATE_CTL_TBL0_P56m, TAF_GATE_CTL_TBL0_P57m,
    193         TAF_GATE_CTL_TBL0_P58m, TAF_GATE_CTL_TBL0_P59m,
    194         TAF_GATE_CTL_TBL0_P60m, TAF_GATE_CTL_TBL0_P61m,
    195         TAF_GATE_CTL_TBL0_P62m, TAF_GATE_CTL_TBL0_P63m,
    196         TAF_GATE_CTL_TBL0_P64m, TAF_GATE_CTL_TBL0_P65m,
    197         TAF_GATE_CTL_TBL0_P66m, TAF_GATE_CTL_TBL0_P67m,
    198         TAF_GATE_CTL_TBL0_P68m, TAF_GATE_CTL_TBL0_P69m,
    199         TAF_GATE_CTL_TBL0_P70m, TAF_GATE_CTL_TBL0_P71m,
    200         TAF_GATE_CTL_TBL0_P72m, TAF_GATE_CTL_TBL0_P73m,
    201         TAF_GATE_CTL_TBL0_P74m, TAF_GATE_CTL_TBL0_P75m,
    202         TAF_GATE_CTL_TBL0_P76m, TAF_GATE_CTL_TBL0_P77m,
    203         TAF_GATE_CTL_TBL0_P78m, TAF_GATE_CTL_TBL0_P79m,
    204         TAF_GATE_CTL_TBL0_P80m, TAF_GATE_CTL_TBL0_P81m,
    205         TAF_GATE_CTL_TBL0_P82m, TAF_GATE_CTL_TBL0_P83m,
    206         TAF_GATE_CTL_TBL0_P84m, TAF_GATE_CTL_TBL0_P85m,
    207         TAF_GATE_CTL_TBL0_P86m, TAF_GATE_CTL_TBL0_P87m,
    208         TAF_GATE_CTL_TBL0_P88m, TAF_GATE_CTL_TBL0_P89m,
    209         TAF_GATE_CTL_TBL0_P90m, TAF_GATE_CTL_TBL0_P91m,
    210         TAF_GATE_CTL_TBL0_P92m, TAF_GATE_CTL_TBL0_P93m,
    211         TAF_GATE_CTL_TBL0_P94m, TAF_GATE_CTL_TBL0_P95m,
    212         TAF_GATE_CTL_TBL0_P96m, TAF_GATE_CTL_TBL0_P97m,
    213         TAF_GATE_CTL_TBL0_P98m, TAF_GATE_CTL_TBL0_P99m,
    214         TAF_GATE_CTL_TBL0_P100m, TAF_GATE_CTL_TBL0_P101m,
    215         TAF_GATE_CTL_TBL0_P102m, TAF_GATE_CTL_TBL0_P103m,
    216         TAF_GATE_CTL_TBL0_P104m, TAF_GATE_CTL_TBL0_P105m,
    217         TAF_GATE_CTL_TBL0_P106m, TAF_GATE_CTL_TBL0_P107m,
    218         TAF_GATE_CTL_TBL0_P108m, TAF_GATE_CTL_TBL0_P109m,
    219         TAF_GATE_CTL_TBL0_P110m, TAF_GATE_CTL_TBL0_P111m,
    220         TAF_GATE_CTL_TBL0_P112m, TAF_GATE_CTL_TBL0_P113m,
    221         TAF_GATE_CTL_TBL0_P114m, TAF_GATE_CTL_TBL0_P115m,
    222         TAF_GATE_CTL_TBL0_P116m, TAF_GATE_CTL_TBL0_P117m,
    223         TAF_GATE_CTL_TBL0_P118m, TAF_GATE_CTL_TBL0_P119m,
    224         TAF_GATE_CTL_TBL0_P120m, TAF_GATE_CTL_TBL0_P121m,
    225         TAF_GATE_CTL_TBL0_P122m, TAF_GATE_CTL_TBL0_P123m,
    226         TAF_GATE_CTL_TBL0_P124m, TAF_GATE_CTL_TBL0_P125m,
    227         TAF_GATE_CTL_TBL0_P126m, TAF_GATE_CTL_TBL0_P127m},
    228        {TAF_GATE_CTL_TBL1_P0m, TAF_GATE_CTL_TBL1_P1m,
    229         TAF_GATE_CTL_TBL1_P2m, TAF_GATE_CTL_TBL1_P3m,
    230         TAF_GATE_CTL_TBL1_P4m, TAF_GATE_CTL_TBL1_P5m,
    231         TAF_GATE_CTL_TBL1_P6m, TAF_GATE_CTL_TBL1_P7m,
    232         TAF_GATE_CTL_TBL1_P8m, TAF_GATE_CTL_TBL1_P9m,
    233         TAF_GATE_CTL_TBL1_P10m, TAF_GATE_CTL_TBL1_P11m,
    234         TAF_GATE_CTL_TBL1_P12m, TAF_GATE_CTL_TBL1_P13m,
    235         TAF_GATE_CTL_TBL1_P14m, TAF_GATE_CTL_TBL1_P15m,
    236         TAF_GATE_CTL_TBL1_P16m, TAF_GATE_CTL_TBL1_P17m,
    237         TAF_GATE_CTL_TBL1_P18m, TAF_GATE_CTL_TBL1_P19m,
    238         TAF_GATE_CTL_TBL1_P20m, TAF_GATE_CTL_TBL1_P21m,
    239         TAF_GATE_CTL_TBL1_P22m, TAF_GATE_CTL_TBL1_P23m,
    240         TAF_GATE_CTL_TBL1_P24m, TAF_GATE_CTL_TBL1_P25m,
    241         TAF_GATE_CTL_TBL1_P26m, TAF_GATE_CTL_TBL1_P27m,
    242         TAF_GATE_CTL_TBL1_P28m, TAF_GATE_CTL_TBL1_P29m,
    243         TAF_GATE_CTL_TBL1_P30m, TAF_GATE_CTL_TBL1_P31m,
    244         TAF_GATE_CTL_TBL1_P32m, TAF_GATE_CTL_TBL1_P33m,
    245         TAF_GATE_CTL_TBL1_P34m, TAF_GATE_CTL_TBL1_P35m,
    246         TAF_GATE_CTL_TBL1_P36m, TAF_GATE_CTL_TBL1_P37m,
    247         TAF_GATE_CTL_TBL1_P38m, TAF_GATE_CTL_TBL1_P39m,
    248         TAF_GATE_CTL_TBL1_P40m, TAF_GATE_CTL_TBL1_P41m,
    249         TAF_GATE_CTL_TBL1_P42m, TAF_GATE_CTL_TBL1_P43m,
    250         TAF_GATE_CTL_TBL1_P44m, TAF_GATE_CTL_TBL1_P45m,
    251         TAF_GATE_CTL_TBL1_P46m, TAF_GATE_CTL_TBL1_P47m,
    252         TAF_GATE_CTL_TBL1_P48m, TAF_GATE_CTL_TBL1_P49m,
    253         TAF_GATE_CTL_TBL1_P50m, TAF_GATE_CTL_TBL1_P51m,
    254         TAF_GATE_CTL_TBL1_P52m, TAF_GATE_CTL_TBL1_P53m,
    255         TAF_GATE_CTL_TBL1_P54m, TAF_GATE_CTL_TBL1_P55m,
    256         TAF_GATE_CTL_TBL1_P56m, TAF_GATE_CTL_TBL1_P57m,
    257         TAF_GATE_CTL_TBL1_P58m, TAF_GATE_CTL_TBL1_P59m,
    258         TAF_GATE_CTL_TBL1_P60m, TAF_GATE_CTL_TBL1_P61m,
    259         TAF_GATE_CTL_TBL1_P62m, TAF_GATE_CTL_TBL1_P63m,
    260         TAF_GATE_CTL_TBL1_P64m, TAF_GATE_CTL_TBL1_P65m,
    261         TAF_GATE_CTL_TBL1_P66m, TAF_GATE_CTL_TBL1_P67m,
    262         TAF_GATE_CTL_TBL1_P68m, TAF_GATE_CTL_TBL1_P69m,
    263         TAF_GATE_CTL_TBL1_P70m, TAF_GATE_CTL_TBL1_P71m,
    264         TAF_GATE_CTL_TBL1_P72m, TAF_GATE_CTL_TBL1_P73m,
    265         TAF_GATE_CTL_TBL1_P74m, TAF_GATE_CTL_TBL1_P75m,
    266         TAF_GATE_CTL_TBL1_P76m, TAF_GATE_CTL_TBL1_P77m,
    267         TAF_GATE_CTL_TBL1_P78m, TAF_GATE_CTL_TBL1_P79m,
    268         TAF_GATE_CTL_TBL1_P80m, TAF_GATE_CTL_TBL1_P81m,
    269         TAF_GATE_CTL_TBL1_P82m, TAF_GATE_CTL_TBL1_P83m,
    270         TAF_GATE_CTL_TBL1_P84m, TAF_GATE_CTL_TBL1_P85m,
    271         TAF_GATE_CTL_TBL1_P86m, TAF_GATE_CTL_TBL1_P87m,
    272         TAF_GATE_CTL_TBL1_P88m, TAF_GATE_CTL_TBL1_P89m,
    273         TAF_GATE_CTL_TBL1_P90m, TAF_GATE_CTL_TBL1_P91m,
    274         TAF_GATE_CTL_TBL1_P92m, TAF_GATE_CTL_TBL1_P93m,
    275         TAF_GATE_CTL_TBL1_P94m, TAF_GATE_CTL_TBL1_P95m,
    276         TAF_GATE_CTL_TBL1_P96m, TAF_GATE_CTL_TBL1_P97m,
    277         TAF_GATE_CTL_TBL1_P98m, TAF_GATE_CTL_TBL1_P99m,
    278         TAF_GATE_CTL_TBL1_P100m, TAF_GATE_CTL_TBL1_P101m,
    279         TAF_GATE_CTL_TBL1_P102m, TAF_GATE_CTL_TBL1_P103m,
    280         TAF_GATE_CTL_TBL1_P104m, TAF_GATE_CTL_TBL1_P105m,
    281         TAF_GATE_CTL_TBL1_P106m, TAF_GATE_CTL_TBL1_P107m,
    282         TAF_GATE_CTL_TBL1_P108m, TAF_GATE_CTL_TBL1_P109m,
    283         TAF_GATE_CTL_TBL1_P110m, TAF_GATE_CTL_TBL1_P111m,
    284         TAF_GATE_CTL_TBL1_P112m, TAF_GATE_CTL_TBL1_P113m,
    285         TAF_GATE_CTL_TBL1_P114m, TAF_GATE_CTL_TBL1_P115m,
    286         TAF_GATE_CTL_TBL1_P116m, TAF_GATE_CTL_TBL1_P117m,
    287         TAF_GATE_CTL_TBL1_P118m, TAF_GATE_CTL_TBL1_P119m,
    288         TAF_GATE_CTL_TBL1_P120m, TAF_GATE_CTL_TBL1_P121m,
    289         TAF_GATE_CTL_TBL1_P122m, TAF_GATE_CTL_TBL1_P123m,
    290         TAF_GATE_CTL_TBL1_P124m, TAF_GATE_CTL_TBL1_P125m,
    291         TAF_GATE_CTL_TBL1_P126m, TAF_GATE_CTL_TBL1_P127m}};
    292 STATIC const soc_reg_t taf_reg_base_sec[2] = {TAF_BASE_TIME_SEC_0r,
    293                                               TAF_BASE_TIME_SEC_1r};
    294 STATIC const soc_reg_t taf_reg_base_frac[2] = {TAF_BASE_TIME_FRAC_0r,
    295                                                TAF_BASE_TIME_FRAC_1r};
    296 STATIC const soc_reg_t taf_reg_cycle[2] = {TAF_CYCLE_TIME_0r,
    297                                            TAF_CYCLE_TIME_1r};
    298 STATIC const soc_reg_t taf_reg_ext[2] = {TAF_CYCLE_TIME_EXTENSION_0r,
    299                                          TAF_CYCLE_TIME_EXTENSION_1r};
    300 
    301 /*
    302  * taf event handler
    303  */
    304 STATIC bcmi_tsn_taf_event_handler_t *taf_event_handler_list
    305                                         [SOC_MAX_NUM_DEVICES]
    306                                         [BCMI_TSN_TAF_GATE_NUM]
    307                                         [bcmTsnTafEventCount];
    308 
    309 /*
    310  * taf hw interrupt info
    311  */
    312 #define TAF_INTERRUPT_SUB_FIELD_WIDTH (32)
    313 #define TAF_INTERRUPT_SUB_FIELD_NUM \
    314         ((BCMI_TSN_TAF_GATE_NUM + TAF_INTERRUPT_SUB_FIELD_WIDTH - 1)\
    315          / TAF_INTERRUPT_SUB_FIELD_WIDTH) /* ceiling of (128/32) = 4 */
    316 
    317 typedef enum gh2_taf_interrupt_type_e {
    318     TafInterruptSwitchDone = 0,
    319     TafInterruptTodWindow = 1,
    320     TafInterruptNextCycleTimeError = 2,
    321     TafInterruptBaseTimeError = 3,
    322     TafInterruptParityError = 4,
    323     TafInterruptTblPtrError = 5,
    324     TafInterruptCount = 6
    325 } gh2_taf_interrupt_type_t;
    326 
    327 typedef struct gh2_taf_interrupt_mapping_s {
    328     /* mask field of MEMFAILINTMASKr */
    329     soc_field_t mask_field;
    330     /* status field of MEMFAILINTSTATUSr */
    331     soc_field_t status_field;
    332     /* clear field of MEMFAILINT_CLRr */
    333     soc_field_t clear_field;
    334     /* sub status registers to indicate individual status */
    335     soc_reg_t   sub_status_regs[TAF_INTERRUPT_SUB_FIELD_NUM];
    336     /* sub clear registers to clear individual status */
    337     soc_reg_t   sub_clear_regs[TAF_INTERRUPT_SUB_FIELD_NUM];
    338 } gh2_taf_interrupt_mapping_t;
    339 
    340 STATIC const
    341 gh2_taf_interrupt_mapping_t taf_interrupt_mapping[TafInterruptCount] = {
    342     {TAF_TBL_SWITCH_DONE_INTMASKf,
    343      TAF_TBL_SWITCH_DONEf,
    344      TAF_TBL_SWITCH_DONE_CLRf,
    345      {TAF_TBL_SWITCH_DONE_0r, TAF_TBL_SWITCH_DONE_1r,
    346       TAF_TBL_SWITCH_DONE_2r, TAF_TBL_SWITCH_DONE_3r},
    347      {TAF_TBL_SWITCH_DONE_CLR_0r, TAF_TBL_SWITCH_DONE_CLR_1r,
    348       TAF_TBL_SWITCH_DONE_CLR_2r, TAF_TBL_SWITCH_DONE_CLR_3r},
    349     },
    350     {TAF_TOD_WINDOW_INTERRUPT_INTMASKf,
    351      TAF_TOD_WINDOW_INTERRUPTf,
    352      TAF_TOD_WINDOW_INTERRUPT_CLRf,
    353      {INVALIDr},
    354      {INVALIDr},
    355     },
    356     {TAF_SET_NEXT_CYCLE_TIME_ERROR_INTMASKf,
    357      TAF_SET_NEXT_CYCLE_TIME_ERRORf,
    358      TAF_SET_NEXT_CYCLE_TIME_ERROR_CLRf,
    359      {TAF_SET_NEXT_CYCLE_TIME_ERROR_0r, TAF_SET_NEXT_CYCLE_TIME_ERROR_1r,
    360       TAF_SET_NEXT_CYCLE_TIME_ERROR_2r, TAF_SET_NEXT_CYCLE_TIME_ERROR_3r},
    361      {TAF_SET_NEXT_CYCLE_TIME_ERROR_CLR_0r,
    362       TAF_SET_NEXT_CYCLE_TIME_ERROR_CLR_1r,
    363       TAF_SET_NEXT_CYCLE_TIME_ERROR_CLR_2r,
    364       TAF_SET_NEXT_CYCLE_TIME_ERROR_CLR_3r},
    365     },
    366     {TAF_SET_BASE_TIME_ERROR_INTMASKf,
    367      TAF_SET_BASE_TIME_ERRORf,
    368      TAF_SET_BASE_TIME_ERROR_CLRf,
    369      {TAF_SET_BASE_TIME_ERROR_0r, TAF_SET_BASE_TIME_ERROR_1r,
    370       TAF_SET_BASE_TIME_ERROR_2r, TAF_SET_BASE_TIME_ERROR_3r},
    371      {TAF_SET_BASE_TIME_ERROR_CLR_0r, TAF_SET_BASE_TIME_ERROR_CLR_1r,
    372       TAF_SET_BASE_TIME_ERROR_CLR_2r, TAF_SET_BASE_TIME_ERROR_CLR_3r}
    373     },
    374     {TAF_PARITY_ERR_INTMASKf,
    375      TAF_PARITY_ERRf,
    376      TAF_PARITY_ERR_CLRf,
    377      {TAF_PARITY_ERR_VLD_0r, TAF_PARITY_ERR_VLD_1r,
    378       TAF_PARITY_ERR_VLD_2r, TAF_PARITY_ERR_VLD_3r},
    379      {TAF_PARITY_ERR_CLR_0r, TAF_PARITY_ERR_CLR_1r,
    380       TAF_PARITY_ERR_CLR_2r, TAF_PARITY_ERR_CLR_3r}
    381     },
    382     {TAF_CTL_TBL_PTR_ERR_INTMASKf,
    383      TAF_CTL_TBL_PTR_ERRf,
    384      TAF_CTL_TBL_PTR_ERR_CLRf,
    385      {TAF_CTL_TBL_PTR_ERR_0r, TAF_CTL_TBL_PTR_ERR_1r,
    386       TAF_CTL_TBL_PTR_ERR_2r, TAF_CTL_TBL_PTR_ERR_3r},
    387      {TAF_CTL_TBL_PTR_ERR_CLR_0r, TAF_CTL_TBL_PTR_ERR_CLR_1r,
    388       TAF_CTL_TBL_PTR_ERR_CLR_2r, TAF_CTL_TBL_PTR_ERR_CLR_3r}
    389     }
    390 };
    391 
    392 STATIC uint32 taf_interrupt_handling[SOC_MAX_NUM_DEVICES] = {0};
    393 STATIC uint32 taf_interrupt_status[SOC_MAX_NUM_DEVICES];
    394 STATIC uint32 taf_interrupt_substatus[SOC_MAX_NUM_DEVICES]
    395                                      [TafInterruptCount]
    396                                      [TAF_INTERRUPT_SUB_FIELD_NUM];
    397 
    398 /* TSN TAF Gate stat table contents for GH2 */
    399 STATIC const soc_mem_t taf_gate_cnt_mem[bcmTsnTafGateStatCount] =
    400                         {TAF_GATE_PASSED_PACKET_COUNTERm,
    401                          TAF_GATE_DROP_PACKET_COUNTERm};
    402 STATIC const soc_mem_t taf_gate_cnt_field[bcmTsnTafGateStatCount] =
    403                         {TAF_GATE_PASSED_PKTf, TAF_GATE_DROP_PKTf};
    404 
    405 /* sw database for taf gate counter */
    406 STATIC uint64 *taf_gate_counter[SOC_MAX_NUM_DEVICES][bcmTsnTafGateStatCount];
    407 STATIC uint8 *taf_gate_counter_dma_buffer[SOC_MAX_NUM_DEVICES]
    408                                          [bcmTsnTafGateStatCount];
    409 
    410 
    411 /*
    412  * helper macro
    413  */
    414 #define ERROR_RETURN_WITH_EXTRA_CLEAN(_op_, _extra_clean_) \
    415             do {                                           \
    416                 int _rv_ = (_op_);                         \
    417                 if (BCM_FAILURE(_rv_)) {                   \
    418                     (_extra_clean_);                       \
    419                     return (_rv_);                         \
    420                 }                                          \
    421             } while (0)
    422 
    423 #define TAF_INIT_ERROR_RETURN_WITH_CLEAN(_op_)             \
    424             ERROR_RETURN_WITH_EXTRA_CLEAN((_op_), bcmi_gh2_taf_cleanup(unit))
    425 
    426 /* allocate TAF gate */
    427 STATIC int
    428 bcmi_gh2_taf_gate_create(int unit, int flags, int *taf_gate_id)
    429 {
    430     uint32 shr_flags = 0;
    431 
    432     if (NULL == taf_gate_id) {
    433         return BCM_E_PARAM;
    434     }
    435 
    436     if (flags & BCM_TSN_TAF_WITH_ID) {
    437         shr_flags = SHR_RES_BITMAP_ALLOC_WITH_ID;
    438     }
    439 
    440     BCM_IF_ERROR_RETURN(
    441         shr_res_bitmap_alloc(taf_gate_bitmap[unit], shr_flags,
    442                              1, (int *)taf_gate_id));
    443 
    444     if (*taf_gate_id < 0 || *taf_gate_id >= BCMI_TSN_TAF_GATE_NUM ||
    445         *taf_gate_id == TAF_GATE_RESERVED_ID) {
    446         return BCM_E_INTERNAL;
    447     }
    448     taf_gate_refcount[unit][*taf_gate_id] = 1;
    449 
    450     return BCM_E_NONE;
    451 }
    452 
    453 /* traverse TAF gate */
    454 STATIC int
    455 bcmi_gh2_taf_gate_traverse(
    456     int unit,
    457     bcm_tsn_taf_gate_traverse_cb cb,
    458     void *user_data)
    459 {
    460     int taf_gate_id;
    461 
    462     if (NULL == cb) {
    463         return BCM_E_PARAM;
    464     }
    465 
    466     for (taf_gate_id = 0; taf_gate_id < BCMI_TSN_TAF_GATE_NUM; taf_gate_id++) {
    467         if (TAF_GATE_RESERVED_ID == taf_gate_id) {
    468             continue;
    469         }
    470         if (0 == taf_gate_refcount[unit][taf_gate_id]) {
    471             continue;
    472         }
    473         BCM_IF_ERROR_RETURN(cb(unit, taf_gate_id, user_data));
    474     }
    475 
    476     return BCM_E_NONE;
    477 }
    478 
    479 /* free TAF gate */
    480 STATIC int
    481 bcmi_gh2_taf_gate_destroy(int unit, int taf_gate_id)
    482 {
    483     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
    484 
    485     if (taf_gate_refcount[unit][taf_gate_id] == 0) {
    486         return BCM_E_NOT_FOUND;
    487     } else if (taf_gate_refcount[unit][taf_gate_id] > 1) {
    488         return BCM_E_BUSY;
    489     }
    490 
    491     BCM_IF_ERROR_RETURN(
    492         shr_res_bitmap_free(taf_gate_bitmap[unit], 1, taf_gate_id));
    493     taf_gate_refcount[unit][taf_gate_id] = 0;
    494 
    495     return BCM_E_NONE;
    496 }
    497 
    498 /* taf gate id valid check */
    499 STATIC int
    500 bcmi_gh2_taf_gate_check(
    501     int unit,
    502     int taf_gate_id)
    503 {
    504     if (taf_gate_id < 0 ||
    505         taf_gate_id == TAF_GATE_RESERVED_ID ||
    506         taf_gate_id >= BCMI_TSN_TAF_GATE_NUM) {
    507         return BCM_E_PARAM;
    508     }
    509 
    510     if (taf_gate_refcount[unit][taf_gate_id] == 0) {
    511         return BCM_E_NOT_FOUND;
    512     }
    513 
    514     return BCM_E_NONE;
    515 }
    516 
    517 /* get current time */
    518 STATIC int
    519 bcmi_gh2_taf_ptp_time_get(
    520     int unit,
    521     bcm_ptp_timestamp_t *ret_time)
    522 {
    523     if (NULL == ret_time) {
    524         return BCM_E_PARAM;
    525     }
    526 
    527 #if defined(INCLUDE_PTP)
    528     if (soc_feature(unit, soc_feature_ptp) ||
    529         soc_feature(unit, soc_feature_use_local_1588)) {
    530         return bcm_esw_ptp_clock_time_get(unit, 0, 0, ret_time);
    531     }
    532 #endif /* INCLUDE_PTP */
    533 
    534     return BCM_E_UNAVAIL;
    535 }
    536 
    537 /* check if ptp_time_1 > ptp_time_2
    538  * note. for speed, caller need to ensure that these pointer are not NULL
    539  */
    540 STATIC INLINE int
    541 bcmi_gh2_taf_ptp_time_gt(
    542     bcm_ptp_timestamp_t *ptp_time_1,
    543     bcm_ptp_timestamp_t *ptp_time_2)
    544 {
    545     if (COMPILER_64_GT(ptp_time_1->seconds, ptp_time_2->seconds)) {
    546         return TRUE;
    547     } else if (COMPILER_64_EQ(ptp_time_1->seconds, ptp_time_2->seconds)) {
    548         if (ptp_time_1->nanoseconds > ptp_time_2->nanoseconds) {
    549             return TRUE;
    550         }
    551     }
    552     return FALSE;
    553 }
    554 
    555 /* check if ptp_time_1 >= ptp_time_2
    556  * note. for speed, caller need to ensure that these pointer are not NULL
    557  */
    558 STATIC INLINE int
    559 bcmi_gh2_taf_ptp_time_ge(
    560     bcm_ptp_timestamp_t *ptp_time_1,
    561     bcm_ptp_timestamp_t *ptp_time_2)
    562 {
    563     if (COMPILER_64_GT(ptp_time_1->seconds, ptp_time_2->seconds)) {
    564         return TRUE;
    565     } else if (COMPILER_64_EQ(ptp_time_1->seconds, ptp_time_2->seconds)) {
    566         if (ptp_time_1->nanoseconds >= ptp_time_2->nanoseconds) {
    567             return TRUE;
    568         }
    569     }
    570     return FALSE;
    571 }
    572 
    573 /* assign ptp_time_dst as ptp_time_src
    574  * note. for speed, caller need to ensure that these pointer are not NULL
    575  */
    576 STATIC INLINE void
    577 bcmi_gh2_taf_ptp_time_assign(
    578     bcm_ptp_timestamp_t *ptp_time_dst,
    579     bcm_ptp_timestamp_t *ptp_time_src)
    580 {
    581     COMPILER_64_COPY(ptp_time_dst->seconds, ptp_time_src->seconds);
    582     ptp_time_dst->nanoseconds = ptp_time_src->nanoseconds;
    583 }
    584 
    585 /* ptp_time_dst = ptp_time_dst + time_diff(ns)
    586  * note. for speed, caller need to ensure that these pointer are not NULL
    587  */
    588 STATIC INLINE void
    589 bcmi_gh2_taf_ptp_time_add(
    590     bcm_ptp_timestamp_t *ptp_time_dst,
    591     uint32 time_diff)
    592 {
    593     ptp_time_dst->nanoseconds += time_diff;
    594     if (ptp_time_dst->nanoseconds >= TAF_SCHEDULE_NANOSEC_MAX) {
    595         ptp_time_dst->nanoseconds -= TAF_SCHEDULE_NANOSEC_MAX;
    596         COMPILER_64_ADD_32(ptp_time_dst->seconds, 1);
    597     }
    598 }
    599 
    600 /* ptp_time_dst = ptp_time_dst - time_diff(ns)
    601  * note. for speed, caller need to ensure that these pointer are not NULL
    602  */
    603 STATIC INLINE void
    604 bcmi_gh2_taf_ptp_time_sub(
    605     bcm_ptp_timestamp_t *ptp_time_dst,
    606     uint32 time_diff)
    607 {
    608     if (ptp_time_dst->nanoseconds >= time_diff) {
    609         ptp_time_dst->nanoseconds -= time_diff;
    610     } else {
    611         ptp_time_dst->nanoseconds += TAF_SCHEDULE_NANOSEC_MAX;
    612         ptp_time_dst->nanoseconds -= time_diff;
    613         COMPILER_64_SUB_32(ptp_time_dst->seconds, 1);
    614     }
    615 }
    616 
    617 /* return the ToD (Time of Day) index of the ptp time
    618  * note. for speed, caller need to ensure that these pointer are not NULL
    619  */
    620 STATIC INLINE void
    621 bcmi_gh2_taf_ptp_time_to_tod(
    622     bcm_ptp_timestamp_t *ptp_time, uint64 *ret_tod)
    623 {
    624     /* In GH2, ToD is a 64sec window
    625      * ToD 0 : 0  ~  64sec
    626      * ToD 1 : 64 ~ 128sec
    627      * ....
    628      */
    629     COMPILER_64_COPY(*ret_tod, ptp_time->seconds);
    630     COMPILER_64_SHR(*ret_tod, TAF_SCHEDULE_SEC_WIDTH); /* >> 6 */
    631 }
    632 
    633 /* return ptp time of the specfic ToD
    634  * note. for speed, caller need to ensure that these pointer are not NULL
    635  */
    636 STATIC INLINE void
    637 bcmi_gh2_taf_ptp_time_from_tod(
    638     uint64 *tod, bcm_ptp_timestamp_t *ret_ptp_time)
    639 {
    640     ret_ptp_time->nanoseconds = 0;
    641     COMPILER_64_COPY(ret_ptp_time->seconds, *tod);
    642     COMPILER_64_SHL(ret_ptp_time->seconds, TAF_SCHEDULE_SEC_WIDTH); /* << 6 */
    643 }
    644 
    645 
    646 
    647 STATIC int
    648 bcmi_gh2_taf_event_register(
    649     int unit,
    650     int taf_gate,
    651     bcm_tsn_taf_event_types_t event_types,
    652     bcm_tsn_taf_event_cb cb,
    653     void *user_data)
    654 {
    655     bcm_tsn_taf_event_type_t event_iter;
    656 
    657     if (NULL == cb) {
    658         return BCM_E_PARAM;
    659     }
    660 
    661     assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM);
    662 
    663     /* duplicate check */
    664     SHR_BIT_ITER(event_types.w, bcmTsnTafEventCount, event_iter) {
    665         bcmi_tsn_taf_event_handler_t *event_handler_iter;
    666 
    667         event_handler_iter = taf_event_handler_list[unit][taf_gate][event_iter];
    668         while (NULL != event_handler_iter) {
    669             if (event_handler_iter->cb == cb) {
    670                 break;
    671             }
    672             event_handler_iter = event_handler_iter->next;
    673         }
    674         if (NULL != event_handler_iter) {
    675             return BCM_E_EXISTS;
    676         }
    677     }
    678 
    679     /* insert new event handler at the tail */
    680     SHR_BIT_ITER(event_types.w, bcmTsnTafEventCount, event_iter) {
    681         bcmi_tsn_taf_event_handler_t *event_handler_iter;
    682         bcmi_tsn_taf_event_handler_t *event_handler_new;
    683 
    684         event_handler_new = sal_alloc(sizeof(bcmi_tsn_taf_event_handler_t),
    685                                       "TAF event handler entry");
    686         if (NULL == event_handler_new) {
    687             return BCM_E_MEMORY;
    688         }
    689         event_handler_new->cb = cb;
    690         event_handler_new->user_data = user_data;
    691         event_handler_new->next = NULL;
    692 
    693         if (NULL == taf_event_handler_list[unit][taf_gate][event_iter]) {
    694             taf_event_handler_list
    695                 [unit][taf_gate][event_iter] = event_handler_new;
    696         } else {
    697             event_handler_iter = taf_event_handler_list
    698                                     [unit][taf_gate][event_iter];
    699             while (NULL != event_handler_iter->next) {
    700                 event_handler_iter = event_handler_iter->next;
    701             }
    702             event_handler_iter->next = event_handler_new;
    703         }
    704     }
    705 
    706     return BCM_E_NONE;
    707 }
    708 
    709 STATIC int
    710 bcmi_gh2_taf_event_unregister(
    711     int unit,
    712     int taf_gate,
    713     bcm_tsn_taf_event_types_t event_types,
    714     bcm_tsn_taf_event_cb cb)
    715 {
    716     bcm_tsn_taf_event_type_t event_iter;
    717     int found = 0;
    718 
    719     if (NULL == cb) {
    720         return BCM_E_PARAM;
    721     }
    722 
    723     assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM);
    724 
    725     SHR_BIT_ITER(event_types.w, bcmTsnTafEventCount, event_iter) {
    726         bcmi_tsn_taf_event_handler_t *event_handler_iter;
    727         bcmi_tsn_taf_event_handler_t *event_handler_prev;
    728 
    729         event_handler_prev = NULL;
    730         event_handler_iter = taf_event_handler_list[unit][taf_gate][event_iter];
    731         while (NULL != event_handler_iter) {
    732             if (event_handler_iter->cb == cb) {
    733                 break;
    734             }
    735             event_handler_prev = event_handler_iter;
    736             event_handler_iter = event_handler_iter->next;
    737         }
    738         if (NULL != event_handler_iter) {
    739             if (event_handler_iter == taf_event_handler_list
    740                                         [unit][taf_gate][event_iter]) {
    741                 taf_event_handler_list
    742                     [unit][taf_gate][event_iter] = event_handler_iter->next;
    743                 sal_free(event_handler_iter);
    744             } else {
    745                 event_handler_prev->next = event_handler_iter->next;
    746                 sal_free(event_handler_iter);
    747             }
    748             found = 1;
    749         }
    750     }
    751     if (1 == found) {
    752         return BCM_E_NONE;
    753     } else {
    754         return BCM_E_NOT_FOUND;
    755     }
    756 }
    757 
    758 STATIC int
    759 bcmi_gh2_taf_event_notify(
    760     int unit,
    761     int taf_gate,
    762     bcm_tsn_taf_event_type_t event_type)
    763 {
    764     bcmi_tsn_taf_event_handler_t *event_handler_iter;
    765 
    766     if (event_type < 0 || event_type >= bcmTsnTafEventCount) {
    767         return BCM_E_PARAM;
    768     }
    769     assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM);
    770 
    771     event_handler_iter = taf_event_handler_list[unit][taf_gate][event_type];
    772     while (NULL != event_handler_iter) {
    773         BCM_IF_ERROR_RETURN(
    774             event_handler_iter->cb(unit, event_type, taf_gate,
    775                                    event_handler_iter->user_data));
    776         event_handler_iter = event_handler_iter->next;
    777     }
    778     return BCM_E_NONE;
    779 }
    780 
    781 /* get taf gate status */
    782 STATIC int
    783 bcmi_gh2_taf_gate_status_get(
    784     int unit,
    785     int taf_gate_id,
    786     bcm_tsn_taf_status_t type,
    787     uint32 *arg)
    788 {
    789     uint32 regval;
    790     taf_gate_bytes_left_entry_t mem_entry;
    791 
    792     if (NULL == arg) {
    793          return BCM_E_PARAM;
    794     }
    795 
    796     BCM_IF_ERROR_RETURN(
    797         soc_reg32_get(unit, TAF_GSG_STATUSr, REG_PORT_ANY,
    798                       taf_gate_id, &regval));
    799 
    800     switch (type) {
    801         case bcmTsnTafStatusGateState:
    802             *arg = soc_reg_field_get(unit, TAF_GSG_STATUSr,
    803                                      regval, TAF_GATE_STATEf);
    804             break;
    805         case bcmTsnTafStatusGateStateSet:
    806             *arg = soc_reg_field_get(unit, TAF_GSG_STATUSr,
    807                                      regval, GATE_STATE_SELECTf);
    808             break;
    809         case bcmTsnTafStatusGateCosProfile:
    810             *arg = soc_reg_field_get(unit, TAF_GSG_STATUSr,
    811                                      regval, TAF_COS_PROFILEf);
    812             break;
    813         case bcmTsnTafStatusGateMaxBytesProfile:
    814             *arg = soc_reg_field_get(unit, TAF_GSG_STATUSr,
    815                                      regval, TAF_MAXBYTES_SELECTf);
    816             break;
    817         case bcmTsnTafStatusTickGranularity:
    818             *arg = TAF_GCLT_TICKS;
    819             break;
    820         case bcmTsnTafStatusMaxCalendarEntries:
    821             *arg = TAF_SCHEDULE_CALENDAR_ENTIRES;
    822             break;
    823         case bcmTsnTafStatusGatMaxBytesLeft:
    824             SOC_IF_ERROR_RETURN(
    825                 soc_mem_read(unit, TAF_GATE_BYTES_LEFTm, MEM_BLOCK_ANY,
    826                              taf_gate_id, &mem_entry));
    827 
    828             *arg = soc_mem_field32_get(unit, TAF_GATE_BYTES_LEFTm, &mem_entry,
    829                                        GATE_BYTES_LEFTf);
    830             break;
    831         default:
    832             return BCM_E_PARAM;
    833     }
    834 
    835     return BCM_E_NONE;
    836 }
    837 
    838 /* taf port control set */
    839 STATIC int
    840 bcmi_gh2_taf_port_control_set(
    841     int unit,
    842     bcm_gport_t gport,
    843     bcm_tsn_control_t type,
    844     uint32 arg)
    845 {
    846     bcm_port_t port;
    847 
    848     BCM_IF_ERROR_RETURN(
    849         _bcm_esw_port_gport_validate(unit, gport, &port));
    850 
    851     switch (type) {
    852         case bcmTsnControlTafEnable:
    853             SOC_IF_ERROR_RETURN(
    854                 soc_mem_field32_modify(unit, PORT_TABm, port,
    855                                        TAF_ENABLEf, arg));
    856             break;
    857         case bcmTsnControlTafGatePriMap:
    858             SOC_IF_ERROR_RETURN(
    859                 soc_mem_field32_modify(unit, PORT_TABm, port,
    860                                        TAF_GATE_ID_PROFILEf, arg));
    861             break;
    862         case bcmTsnControlTafGatePriMapL2Select:
    863             SOC_IF_ERROR_RETURN(
    864                 soc_mem_field32_modify(unit, PORT_TABm, port,
    865                                        L2_ENTRY_GATE_ID_SELECTf, arg));
    866             break;
    867         default:
    868             return BCM_E_UNAVAIL;
    869     }
    870     return BCM_E_NONE;
    871 }
    872 
    873 /* taf port control get */
    874 STATIC int
    875 bcmi_gh2_taf_port_control_get(
    876     int unit,
    877     bcm_gport_t gport,
    878     bcm_tsn_control_t type,
    879     uint32 *arg)
    880 {
    881     bcm_port_t port;
    882     port_tab_entry_t entry;
    883 
    884     if (NULL == arg) {
    885         return BCM_E_PARAM;
    886     }
    887 
    888     BCM_IF_ERROR_RETURN(
    889         _bcm_esw_port_gport_validate(unit, gport, &port));
    890 
    891     SOC_IF_ERROR_RETURN(
    892         soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &entry));
    893 
    894     switch (type) {
    895         case bcmTsnControlTafEnable:
    896             *arg = soc_mem_field32_get(unit, PORT_TABm, &entry,
    897                                        TAF_ENABLEf);
    898             break;
    899          case bcmTsnControlTafGatePriMap:
    900             *arg = soc_mem_field32_get(unit, PORT_TABm, &entry,
    901                                        TAF_GATE_ID_PROFILEf);
    902             break;
    903         case bcmTsnControlTafGatePriMapL2Select:
    904             *arg = soc_mem_field32_get(unit, PORT_TABm, &entry,
    905                                        L2_ENTRY_GATE_ID_SELECTf);
    906             break;
    907         default:
    908             return BCM_E_UNAVAIL;
    909     }
    910     return BCM_E_NONE;
    911 }
    912 
    913 
    914 /* taf gate control set */
    915 STATIC int
    916 bcmi_gh2_taf_gate_control_set(
    917     int unit,
    918     int taf_gate_id,
    919     bcm_tsn_taf_control_t type,
    920     uint32 arg)
    921 {
    922     uint32 regval;
    923     uint32 field_value;
    924 
    925     switch (type) {
    926         case bcmTsnTafControlEnable:
    927             BCM_IF_ERROR_RETURN(
    928                 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY,
    929                               taf_gate_id, &regval));
    930             soc_reg_field_set(unit, TAF_CONFIG_0r, &regval,
    931                               GATE_ENABLEDf, arg);
    932             BCM_IF_ERROR_RETURN(
    933                 soc_reg32_set(unit, TAF_CONFIG_0r, REG_PORT_ANY,
    934                               taf_gate_id, regval));
    935             break;
    936         case bcmTsnTafControlUsePTPTime:
    937             BCM_IF_ERROR_RETURN(
    938                 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY,
    939                               taf_gate_id, &regval));
    940             soc_reg_field_set(unit, TAF_CONFIG_0r, &regval,
    941                               PTP_ACTIVEf, arg);
    942             BCM_IF_ERROR_RETURN(
    943                 soc_reg32_set(unit, TAF_CONFIG_0r, REG_PORT_ANY,
    944                               taf_gate_id, regval));
    945             break;
    946         case bcmTsnTafControlInitGateState:
    947             BCM_IF_ERROR_RETURN(
    948                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    949                               taf_gate_id, &regval));
    950             soc_reg_field_set(unit, TAF_CONFIG_2r, &regval,
    951                               INIT_TAF_GATE_STATEf, arg);
    952             BCM_IF_ERROR_RETURN(
    953                 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    954                               taf_gate_id, regval));
    955             break;
    956         case bcmTsnTafControlInitCosProfile:
    957             BCM_IF_ERROR_RETURN(
    958                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    959                               taf_gate_id, &regval));
    960             soc_reg_field_set(unit, TAF_CONFIG_2r, &regval,
    961                               INIT_TAF_COS_PROFILEf, arg);
    962             BCM_IF_ERROR_RETURN(
    963                 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    964                               taf_gate_id, regval));
    965             break;
    966         case bcmTsnTafControlInitMaxBytesProfile:
    967             BCM_IF_ERROR_RETURN(
    968                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    969                               taf_gate_id, &regval));
    970             soc_reg_field_set(unit, TAF_CONFIG_2r, &regval,
    971                               INIT_TAF_MAXBYTES_SELECTf, arg);
    972             BCM_IF_ERROR_RETURN(
    973                 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    974                               taf_gate_id, regval));
    975             break;
    976         case bcmTsnTafControlErrGateState:
    977             BCM_IF_ERROR_RETURN(
    978                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    979                               taf_gate_id, &regval));
    980             soc_reg_field_set(unit, TAF_CONFIG_2r, &regval,
    981                               ERR_TAF_GATE_STATEf, arg);
    982             BCM_IF_ERROR_RETURN(
    983                 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    984                               taf_gate_id, regval));
    985             break;
    986         case bcmTsnTafControlErrCosProfile:
    987             BCM_IF_ERROR_RETURN(
    988                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    989                               taf_gate_id, &regval));
    990             soc_reg_field_set(unit, TAF_CONFIG_2r, &regval,
    991                               ERR_TAF_COS_PROFILEf, arg);
    992             BCM_IF_ERROR_RETURN(
    993                 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    994                               taf_gate_id, regval));
    995             break;
    996         case bcmTsnTafControlErrMaxByteProfile:
    997             BCM_IF_ERROR_RETURN(
    998                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
    999                               taf_gate_id, &regval));
   1000             soc_reg_field_set(unit, TAF_CONFIG_2r, &regval,
   1001                               ERR_TAF_MAXBYTES_SELECTf, arg);
   1002             BCM_IF_ERROR_RETURN(
   1003                 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY,
   1004                               taf_gate_id, regval));
   1005             break;
   1006         case bcmTsnTafControlGateCloseControl:
   1007             BCM_IF_ERROR_RETURN(
   1008                 soc_mem_field32_modify(unit, TAF_GATE_CONTROLm, taf_gate_id,
   1009                                        TAF_GATE_CLOSE_CONTROLf, arg));
   1010             break;
   1011         case bcmTsnTafControlBytesLeftCheckEnable:
   1012             BCM_IF_ERROR_RETURN(
   1013                 soc_mem_field32_modify(unit, TAF_GATE_CONTROLm, taf_gate_id,
   1014                                        TAF_MAXBYTE_CHECK_ENABLEf, arg));
   1015             break;
   1016         case bcmTsnTafControlGateControlTickInterval:
   1017             /* From Arch document, period should be STATIC config and
   1018              *  not allowed to be changed when TAF is enabled.
   1019              */
   1020             BCM_IF_ERROR_RETURN(
   1021                 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY,
   1022                               taf_gate_id, &regval));
   1023             if (soc_reg_field_get(unit, TAF_CONFIG_0r, regval, GATE_ENABLEDf)) {
   1024                 LOG_ERROR(BSL_LS_BCM_TSN,
   1025                           (BSL_META("Tick Interval is not allowed "
   1026                                     "to be changed when TAF is enabled.\n")));
   1027                 return BCM_E_BUSY;
   1028             }
   1029 
   1030             /* Clock Period = (field_value + 1) * 8 nsec */
   1031             if (arg % TAF_GCLT_TICKS != 0) {
   1032                 return BCM_E_PARAM;
   1033             }
   1034             field_value = (arg / TAF_GCLT_TICKS) - 1;
   1035 
   1036             SOC_IF_ERROR_RETURN(
   1037                 soc_reg_field_validate(unit, TAF_GATE_CTRL_PERIODr,
   1038                                        PERIODf, field_value));
   1039             BCM_IF_ERROR_RETURN(
   1040                 soc_reg32_get(unit, TAF_GATE_CTRL_PERIODr, REG_PORT_ANY,
   1041                               taf_gate_id, &regval));
   1042             soc_reg_field_set(unit, TAF_GATE_CTRL_PERIODr, &regval,
   1043                               PERIODf, field_value);
   1044             BCM_IF_ERROR_RETURN(
   1045                 soc_reg32_set(unit, TAF_GATE_CTRL_PERIODr, REG_PORT_ANY,
   1046                               taf_gate_id, regval));
   1047             break;
   1048         default:
   1049             return BCM_E_PARAM;
   1050     }
   1051 
   1052     return BCM_E_NONE;
   1053 }
   1054 
   1055 /* taf gate control get */
   1056 STATIC int
   1057 bcmi_gh2_taf_gate_control_get(
   1058     int unit,
   1059     int taf_gate_id,
   1060     bcm_tsn_taf_control_t type,
   1061     uint32 *arg)
   1062 {
   1063     uint32 regval;
   1064     taf_gate_control_entry_t mem_entry;
   1065 
   1066     if (NULL == arg) {
   1067         return BCM_E_PARAM;
   1068     }
   1069 
   1070     switch (type) {
   1071         case bcmTsnTafControlEnable:
   1072             BCM_IF_ERROR_RETURN(
   1073                 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY,
   1074                               taf_gate_id, &regval));
   1075             *arg = soc_reg_field_get(unit, TAF_CONFIG_0r,
   1076                                      regval, GATE_ENABLEDf);
   1077             break;
   1078         case bcmTsnTafControlUsePTPTime:
   1079             BCM_IF_ERROR_RETURN(
   1080                 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY,
   1081                               taf_gate_id, &regval));
   1082             *arg = soc_reg_field_get(unit, TAF_CONFIG_0r,
   1083                                      regval, PTP_ACTIVEf);
   1084             break;
   1085         case bcmTsnTafControlInitGateState:
   1086             BCM_IF_ERROR_RETURN(
   1087                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
   1088                               taf_gate_id, &regval));
   1089             *arg = soc_reg_field_get(unit, TAF_CONFIG_2r,
   1090                                      regval, INIT_TAF_GATE_STATEf);
   1091             break;
   1092         case bcmTsnTafControlInitCosProfile:
   1093             BCM_IF_ERROR_RETURN(
   1094                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
   1095                               taf_gate_id, &regval));
   1096             *arg = soc_reg_field_get(unit, TAF_CONFIG_2r,
   1097                                      regval, INIT_TAF_COS_PROFILEf);
   1098             break;
   1099         case bcmTsnTafControlInitMaxBytesProfile:
   1100             BCM_IF_ERROR_RETURN(
   1101                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
   1102                               taf_gate_id, &regval));
   1103             *arg = soc_reg_field_get(unit, TAF_CONFIG_2r,
   1104                                      regval, INIT_TAF_MAXBYTES_SELECTf);
   1105             break;
   1106         case bcmTsnTafControlErrGateState:
   1107             BCM_IF_ERROR_RETURN(
   1108                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
   1109                               taf_gate_id, &regval));
   1110             *arg = soc_reg_field_get(unit, TAF_CONFIG_2r,
   1111                                      regval, ERR_TAF_GATE_STATEf);
   1112             break;
   1113         case bcmTsnTafControlErrCosProfile:
   1114             BCM_IF_ERROR_RETURN(
   1115                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
   1116                               taf_gate_id, &regval));
   1117             *arg = soc_reg_field_get(unit, TAF_CONFIG_2r,
   1118                                      regval, ERR_TAF_COS_PROFILEf);
   1119             break;
   1120         case bcmTsnTafControlErrMaxByteProfile:
   1121             BCM_IF_ERROR_RETURN(
   1122                 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY,
   1123                               taf_gate_id, &regval));
   1124             *arg = soc_reg_field_get(unit, TAF_CONFIG_2r,
   1125                                      regval, ERR_TAF_MAXBYTES_SELECTf);
   1126             break;
   1127         case bcmTsnTafControlGateCloseControl:
   1128             BCM_IF_ERROR_RETURN(
   1129                 soc_mem_read(unit, TAF_GATE_CONTROLm, MEM_BLOCK_ANY,
   1130                              taf_gate_id, &mem_entry));
   1131             *arg = soc_mem_field32_get(unit, TAF_GATE_CONTROLm, &mem_entry,
   1132                                        TAF_GATE_CLOSE_CONTROLf);
   1133             break;
   1134         case bcmTsnTafControlBytesLeftCheckEnable:
   1135             BCM_IF_ERROR_RETURN(
   1136                 soc_mem_read(unit, TAF_GATE_CONTROLm, MEM_BLOCK_ANY,
   1137                              taf_gate_id, &mem_entry));
   1138             *arg = soc_mem_field32_get(unit, TAF_GATE_CONTROLm, &mem_entry,
   1139                                        TAF_MAXBYTE_CHECK_ENABLEf);
   1140             break;
   1141         case bcmTsnTafControlGateControlTickInterval:
   1142             BCM_IF_ERROR_RETURN(
   1143                 soc_reg32_get(unit, TAF_GATE_CTRL_PERIODr, REG_PORT_ANY,
   1144                               taf_gate_id, &regval));
   1145             *arg = soc_reg_field_get(unit, TAF_GATE_CTRL_PERIODr,
   1146                                      regval, PERIODf);
   1147             *arg = (*arg + 1) * TAF_GCLT_TICKS;
   1148             break;
   1149         default:
   1150             return BCM_E_PARAM;
   1151     }
   1152 
   1153     return BCM_E_NONE;
   1154 }
   1155 
   1156 /* taf global control set */
   1157 STATIC int
   1158 bcmi_gh2_taf_global_control_set(
   1159     int unit,
   1160     bcm_tsn_taf_control_t type,
   1161     uint32 arg)
   1162 {
   1163     uint32 regval;
   1164 
   1165     switch (type) {
   1166         case bcmTsnTafControlTAFPTPLock:
   1167             BCM_IF_ERROR_RETURN(
   1168                 soc_reg32_get(unit, TAF_PTP_LOCKr, REG_PORT_ANY,
   1169                               0, &regval));
   1170             soc_reg_field_set(unit, TAF_PTP_LOCKr, &regval,
   1171                               PTP_LOCKf, arg);
   1172             BCM_IF_ERROR_RETURN(
   1173                 soc_reg32_set(unit, TAF_PTP_LOCKr, REG_PORT_ANY,
   1174                               0, regval));
   1175             break;
   1176         default:
   1177             return BCM_E_PARAM;
   1178     }
   1179 
   1180     return BCM_E_NONE;
   1181 }
   1182 
   1183 /* taf global control get */
   1184 STATIC int
   1185 bcmi_gh2_taf_global_control_get(
   1186     int unit,
   1187     bcm_tsn_taf_control_t type,
   1188     uint32 *arg)
   1189 {
   1190     uint32 regval;
   1191 
   1192     if (NULL == arg) {
   1193         return BCM_E_PARAM;
   1194     }
   1195 
   1196     switch (type) {
   1197         case bcmTsnTafControlTAFPTPLock:
   1198             BCM_IF_ERROR_RETURN(
   1199                 soc_reg32_get(unit, TAF_PTP_LOCKr, REG_PORT_ANY, 0, &regval));
   1200             *arg = soc_reg_field_get(unit, TAF_PTP_LOCKr,
   1201                                      regval, PTP_LOCKf);
   1202             break;
   1203         default:
   1204             return BCM_E_PARAM;
   1205     }
   1206 
   1207     return BCM_E_NONE;
   1208 }
   1209 
   1210 /* get hw index of taf gate pri map
   1211  * ex. TAF_GATE_ID_LOOKUP
   1212  * Key:  PREEMPTABLE_CELL (1 bit) +
   1213  * INT_PRI (4 bit) +
   1214  * TAF_GATE_ID_PROFILE (7 bit)
   1215  *
   1216  * TAF_GATE_ID_PROFILE is at LSB, so sw/hw index is the same
   1217  */
   1218 int
   1219 bcmi_gh2_taf_gate_pri_map_hw_idx_get(
   1220     int unit,
   1221     uint32 sw_idx,
   1222     uint32 *hw_idx)
   1223 {
   1224     if (NULL == hw_idx ||
   1225         TAF_GATE_PRI_MAP_PROFILE_NUM <= sw_idx ||
   1226         TAF_GATE_PRI_MAP_PROFILE_INVALID_ID == sw_idx) {
   1227         return BCM_E_PARAM;
   1228     }
   1229 
   1230     *hw_idx = sw_idx;
   1231 
   1232     return BCM_E_NONE;
   1233 }
   1234 
   1235 /* get sw index of taf gate pri map */
   1236 int
   1237 bcmi_gh2_taf_gate_pri_map_sw_idx_get(
   1238     int unit,
   1239     uint32 hw_idx,
   1240     uint32 *sw_idx)
   1241 {
   1242     if (NULL == sw_idx) {
   1243         return BCM_E_PARAM;
   1244     }
   1245 
   1246     /* hw index should be located in the range 1~127 */
   1247     if (hw_idx >= TAF_GATE_PRI_MAP_PROFILE_NUM ||
   1248         hw_idx == TAF_GATE_PRI_MAP_PROFILE_INVALID_ID) {
   1249         return BCM_E_PARAM;
   1250     }
   1251     *sw_idx = hw_idx;
   1252 
   1253     return BCM_E_NONE;
   1254 }
   1255 
   1256 
   1257 /* helper function of bcmi_gh2_taf_gate_pri_map_set */
   1258 STATIC int
   1259 bcmi_gh2_taf_gate_pri_map_change(
   1260     int unit,
   1261     uint32 profile_idx,
   1262     uint32 priority,
   1263     uint32 preempt,
   1264     uint32 new_gate_id)
   1265 {
   1266     taf_gate_id_lookup_entry_t hw_entry;
   1267     uint32 old_gate_id;
   1268     uint32 hw_idx;
   1269 
   1270     if (preempt >= TAF_GATE_PRI_MAP_PREEMPT_NUM ||
   1271         priority >= TAF_GATE_PRI_MAP_INTPRI_NUM ||
   1272         profile_idx >= TAF_GATE_PRI_MAP_PROFILE_NUM ||
   1273         profile_idx == TAF_GATE_PRI_MAP_PROFILE_INVALID_ID) {
   1274         return BCM_E_PARAM;
   1275     }
   1276     hw_idx = (preempt << TAF_GATE_PRI_MAP_PREEMPT_OFFSET) |
   1277              (priority << TAF_GATE_PRI_MAP_INTPRI_OFFSET) |
   1278              (profile_idx << TAF_GATE_PRI_MAP_PROFILE_OFFSET);
   1279 
   1280     BCM_IF_ERROR_RETURN(
   1281         soc_mem_read(unit, taf_gate_pri_map_mem, MEM_BLOCK_ANY,
   1282                      hw_idx, &hw_entry));
   1283 
   1284     old_gate_id = soc_mem_field32_get(unit, taf_gate_pri_map_mem,
   1285                                       &hw_entry, TAF_GATE_IDf);
   1286 
   1287     /* change to new gate id */
   1288     BCM_IF_ERROR_RETURN(
   1289         soc_mem_field32_fit(
   1290             unit, taf_gate_pri_map_mem, TAF_GATE_IDf, new_gate_id));
   1291     soc_mem_field32_set(
   1292         unit, taf_gate_pri_map_mem,
   1293         &hw_entry, TAF_GATE_IDf, new_gate_id);
   1294     if (new_gate_id != TAF_GATE_RESERVED_ID) {
   1295         taf_gate_refcount[unit][new_gate_id]++;
   1296     }
   1297 
   1298 
   1299     /* de-ref old gate id */
   1300     if (old_gate_id != TAF_GATE_RESERVED_ID) {
   1301         taf_gate_refcount[unit][old_gate_id]--;
   1302     }
   1303 
   1304     BCM_IF_ERROR_RETURN(
   1305         soc_mem_write(unit, taf_gate_pri_map_mem, MEM_BLOCK_ALL,
   1306                       hw_idx, &hw_entry));
   1307 
   1308     return BCM_E_NONE;
   1309 }
   1310 
   1311 /* helper function of bcmi_gh2_taf_gate_pri_map_get
   1312  */
   1313 STATIC int
   1314 bcmi_gh2_taf_gate_pri_map_retrieve(
   1315     int unit,
   1316     uint32 profile_idx,
   1317     uint32 priority,
   1318     uint32 preempt,
   1319     uint32 *output_gate_id)
   1320 {
   1321     taf_gate_id_lookup_entry_t hw_entry;
   1322     uint32 hw_idx;
   1323 
   1324     if (output_gate_id == NULL) {
   1325         return BCM_E_PARAM;
   1326     }
   1327 
   1328     if (preempt >= TAF_GATE_PRI_MAP_PREEMPT_NUM ||
   1329         priority >= TAF_GATE_PRI_MAP_INTPRI_NUM ||
   1330         profile_idx >= TAF_GATE_PRI_MAP_PROFILE_NUM ||
   1331         profile_idx == TAF_GATE_PRI_MAP_PROFILE_INVALID_ID) {
   1332         return BCM_E_PARAM;
   1333     }
   1334 
   1335     hw_idx = (preempt << TAF_GATE_PRI_MAP_PREEMPT_OFFSET) |
   1336              (priority << TAF_GATE_PRI_MAP_INTPRI_OFFSET) |
   1337              (profile_idx << TAF_GATE_PRI_MAP_PROFILE_OFFSET);
   1338 
   1339     BCM_IF_ERROR_RETURN(
   1340         soc_mem_read(unit, taf_gate_pri_map_mem, MEM_BLOCK_ANY,
   1341                      hw_idx, &hw_entry));
   1342 
   1343     *output_gate_id = soc_mem_field32_get(unit, taf_gate_pri_map_mem,
   1344                                           &hw_entry, TAF_GATE_IDf);
   1345 
   1346     return BCM_E_NONE;
   1347 }
   1348 
   1349 
   1350 /* set taf gate pri map */
   1351 STATIC int
   1352 bcmi_gh2_taf_gate_pri_map_set(
   1353     int unit,
   1354     uint32 sw_idx,
   1355     bcm_tsn_pri_map_config_t *config)
   1356 {
   1357     uint32 hw_idx, prio;
   1358 
   1359     if (NULL == config) {
   1360         return BCM_E_PARAM;
   1361     }
   1362 
   1363     if (config->num_map_entries != TAF_GATE_PRI_MAP_INTPRI_NUM) {
   1364         return BCM_E_PARAM;
   1365     }
   1366 
   1367     if (config->map_type != bcmTsnPriMapTypeTafGate) {
   1368         return BCM_E_INTERNAL;
   1369     }
   1370 
   1371     BCM_IF_ERROR_RETURN(
   1372         bcmi_gh2_taf_gate_pri_map_hw_idx_get(unit, sw_idx, &hw_idx));
   1373 
   1374 
   1375     /* set config according to the input from user */
   1376     for (prio = 0; prio < TAF_GATE_PRI_MAP_INTPRI_NUM; prio++) {
   1377 
   1378         if (config->map_entries[prio].flags &
   1379             BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_EXPRESS) {
   1380             BCM_IF_ERROR_RETURN(
   1381                 bcmi_gh2_taf_gate_pri_map_change(
   1382                     unit, hw_idx, prio, 0,
   1383                     config->map_entries[prio].taf_gate_express));
   1384         } else {
   1385             BCM_IF_ERROR_RETURN(
   1386                 bcmi_gh2_taf_gate_pri_map_change(
   1387                     unit, hw_idx, prio, 0,
   1388                     TAF_GATE_RESERVED_ID));
   1389         }
   1390 
   1391         if (config->map_entries[prio].flags &
   1392             BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_PREEMPT) {
   1393             BCM_IF_ERROR_RETURN(
   1394                 bcmi_gh2_taf_gate_pri_map_change(
   1395                     unit, hw_idx, prio, 1,
   1396                     config->map_entries[prio].taf_gate_preempt));
   1397         } else {
   1398             BCM_IF_ERROR_RETURN(
   1399                 bcmi_gh2_taf_gate_pri_map_change(
   1400                     unit, hw_idx, prio, 1,
   1401                     TAF_GATE_RESERVED_ID));
   1402         }
   1403     }
   1404 
   1405     return BCM_E_NONE;
   1406 }
   1407 
   1408 /* get taf gate pri map */
   1409 STATIC int
   1410 bcmi_gh2_taf_gate_pri_map_get(
   1411     int unit,
   1412     uint32 sw_idx,
   1413     bcm_tsn_pri_map_config_t *config)
   1414 {
   1415     uint32 hw_indx, prio;
   1416 
   1417     if (NULL == config) {
   1418         return BCM_E_PARAM;
   1419     }
   1420     bcm_tsn_pri_map_config_t_init(config);
   1421 
   1422     BCM_IF_ERROR_RETURN(
   1423         bcmi_gh2_taf_gate_pri_map_hw_idx_get(unit, sw_idx, &hw_indx));
   1424 
   1425     config->map_type = bcmTsnPriMapTypeTafGate;
   1426     config->num_map_entries = TAF_GATE_PRI_MAP_INTPRI_NUM;
   1427 
   1428     for (prio = 0; prio < TAF_GATE_PRI_MAP_INTPRI_NUM; prio++) {
   1429         uint32 output_gate_id;
   1430 
   1431         config->map_entries[prio].flags = 0;
   1432 
   1433         BCM_IF_ERROR_RETURN(
   1434             bcmi_gh2_taf_gate_pri_map_retrieve(
   1435                 unit, hw_indx, prio, 0, &output_gate_id));
   1436 
   1437         if (output_gate_id != TAF_GATE_RESERVED_ID) {
   1438             config->map_entries[prio].taf_gate_express = output_gate_id;
   1439             config->map_entries[prio].flags |=
   1440                 BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_EXPRESS;
   1441         } else {
   1442             config->map_entries[prio].taf_gate_express = -1;
   1443         }
   1444 
   1445         BCM_IF_ERROR_RETURN(
   1446             bcmi_gh2_taf_gate_pri_map_retrieve(
   1447                 unit, hw_indx, prio, 1, &output_gate_id));
   1448 
   1449         if (output_gate_id != TAF_GATE_RESERVED_ID) {
   1450             config->map_entries[prio].taf_gate_preempt = output_gate_id;
   1451             config->map_entries[prio].flags |=
   1452                 BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_PREEMPT;
   1453         } else {
   1454             config->map_entries[prio].taf_gate_preempt = -1;
   1455         }
   1456     }
   1457 
   1458     return BCM_E_NONE;
   1459 }
   1460 
   1461 /* delete taf gate pri map */
   1462 STATIC int
   1463 bcmi_gh2_taf_gate_pri_map_delete(
   1464     int unit,
   1465     uint32 sw_idx)
   1466 {
   1467     uint32 hw_idx, prio;
   1468 
   1469     BCM_IF_ERROR_RETURN(
   1470         bcmi_gh2_taf_gate_pri_map_hw_idx_get(unit, sw_idx, &hw_idx));
   1471 
   1472     /* rollback to default gate */
   1473     for (prio = 0; prio < TAF_GATE_PRI_MAP_INTPRI_NUM; prio++) {
   1474         BCM_IF_ERROR_RETURN(
   1475             bcmi_gh2_taf_gate_pri_map_change(
   1476                 unit, hw_idx, prio, 0,
   1477                 TAF_GATE_RESERVED_ID));
   1478 
   1479          BCM_IF_ERROR_RETURN(
   1480              bcmi_gh2_taf_gate_pri_map_change(
   1481                  unit, hw_idx, prio, 1,
   1482                  TAF_GATE_RESERVED_ID));
   1483     }
   1484 
   1485     return BCM_E_NONE;
   1486 }
   1487 
   1488 /* kick off a new calendar setting into hw
   1489  * Note. this function would not modify profile state
   1490  */
   1491 STATIC int
   1492 bcmi_gh2_taf_calendar_kickoff(
   1493     int unit,
   1494     int taf_gate_id,
   1495     bcmi_tsn_taf_profile_t *profile)
   1496 {
   1497     uint32 regval, setup_set, i, entry_byte;
   1498     soc_mem_t setup_mem;
   1499     soc_memacc_t memacc_cos, memacc_interval, memacc_gstate, memacc_maxbyte;
   1500     uint32 *entry_ptr;
   1501     bcm_tsn_taf_profile_t *calendar;
   1502     bcmi_tsn_taf_schedule_entry_t *schedule;
   1503 
   1504     if (NULL == profile) {
   1505         return BCM_E_PARAM;
   1506     }
   1507     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
   1508 
   1509     calendar = &(profile->data);
   1510     schedule = profile->schedule;
   1511 
   1512     /* read active set, select another inactive set to setup */
   1513     BCM_IF_ERROR_RETURN(
   1514         soc_reg32_get(unit, TAF_CONFIG_1r, REG_PORT_ANY, taf_gate_id, &regval));
   1515     setup_set = soc_reg_field_get(unit, TAF_CONFIG_1r,
   1516                                   regval, ACTIVE_SETf);
   1517     setup_set = 1 - setup_set;
   1518 
   1519     /* init mem */
   1520     setup_mem = (setup_set == 1) ? taf_schedule_calendar_mem[1][taf_gate_id]
   1521                                  : taf_schedule_calendar_mem[0][taf_gate_id];
   1522     BCM_IF_ERROR_RETURN(
   1523         soc_memacc_init(unit, setup_mem, TIME_INTERVALf, &memacc_interval));
   1524     BCM_IF_ERROR_RETURN(
   1525         soc_memacc_init(unit, setup_mem, GATE_STATEf, &memacc_gstate));
   1526     BCM_IF_ERROR_RETURN(
   1527         soc_memacc_init(unit, setup_mem, COS_PROFILEf, &memacc_cos));
   1528     BCM_IF_ERROR_RETURN(
   1529         soc_memacc_init(unit, setup_mem, MAXBYTES_SELECTf, &memacc_maxbyte));
   1530 
   1531     /* write calendar */
   1532     entry_byte = WORDS2BYTES(soc_mem_entry_words(unit, setup_mem));
   1533     sal_memset(taf_schedule_calendar_buf[unit], 0,
   1534                TAF_SCHEDULE_CALENDAR_ENTIRES * entry_byte);
   1535     for (i = 0; i < calendar->num_entries; i++) {
   1536         entry_ptr = &(((uint32 *)(taf_schedule_calendar_buf[unit]))
   1537                       [i * soc_mem_entry_words(unit, setup_mem)]);
   1538         if ((calendar->entries)[i].ticks == BCM_TSN_TAF_ENTRY_TICKS_STAY) {
   1539             int field_len = soc_mem_field_length(unit, setup_mem,
   1540                                                  TIME_INTERVALf);
   1541 
   1542             soc_memacc_field32_set(&memacc_interval, entry_ptr,
   1543                                    (1 << field_len) - 1);
   1544         } else {
   1545             soc_memacc_field32_set(&memacc_interval, entry_ptr,
   1546                                    calendar->entries[i].ticks);
   1547         }
   1548         soc_memacc_field32_set(&memacc_gstate, entry_ptr,
   1549                                calendar->entries[i].state);
   1550         soc_memacc_field32_set(&memacc_cos, entry_ptr,
   1551                                calendar->entries[i].cos_profile);
   1552         soc_memacc_field32_set(&memacc_maxbyte, entry_ptr,
   1553                                calendar->entries[i].maxbyte_profile);
   1554     }
   1555 
   1556     BCM_IF_ERROR_RETURN(
   1557         soc_mem_write_range(unit, setup_mem, MEM_BLOCK_ALL, 0,
   1558                             TAF_SCHEDULE_CALENDAR_ENTIRES - 1,
   1559                             taf_schedule_calendar_buf[unit]));
   1560 
   1561     /* write time related parameter if operated in ptp mode */
   1562     if (NULL != schedule) {
   1563         uint32 sec_32 = COMPILER_64_LO(schedule->schedule_time.seconds);
   1564 
   1565         BCM_IF_ERROR_RETURN(
   1566             soc_reg32_get(unit, taf_reg_base_sec[setup_set], REG_PORT_ANY,
   1567                           taf_gate_id, &regval));
   1568         soc_reg_field_set(unit, taf_reg_base_sec[setup_set], &regval,
   1569                           SECf, sec_32 & TAF_SCHEDULE_SEC_MASK);
   1570         BCM_IF_ERROR_RETURN(
   1571             soc_reg32_set(unit, taf_reg_base_sec[setup_set], REG_PORT_ANY,
   1572                           taf_gate_id, regval));
   1573 
   1574         BCM_IF_ERROR_RETURN(
   1575             soc_reg32_get(unit, taf_reg_base_frac[setup_set], REG_PORT_ANY,
   1576                           taf_gate_id, &regval));
   1577         soc_reg_field_set(unit, taf_reg_base_frac[setup_set], &regval,
   1578                           FRACTIONf, schedule->schedule_time.nanoseconds);
   1579         BCM_IF_ERROR_RETURN(
   1580             soc_reg32_set(unit, taf_reg_base_frac[setup_set], REG_PORT_ANY,
   1581                           taf_gate_id, regval));
   1582 
   1583         BCM_IF_ERROR_RETURN(
   1584             soc_reg32_get(unit, taf_reg_cycle[setup_set], REG_PORT_ANY,
   1585                           taf_gate_id, &regval));
   1586         soc_reg_field_set(unit, taf_reg_cycle[setup_set], &regval,
   1587                           CYCLE_TIMEf, calendar->ptp_cycle_time);
   1588         BCM_IF_ERROR_RETURN(
   1589             soc_reg32_set(unit, taf_reg_cycle[setup_set], REG_PORT_ANY,
   1590                           taf_gate_id, regval));
   1591 
   1592         BCM_IF_ERROR_RETURN(
   1593             soc_reg32_get(unit, taf_reg_ext[setup_set], REG_PORT_ANY,
   1594                           taf_gate_id, &regval));
   1595         soc_reg_field_set(unit, taf_reg_ext[setup_set], &regval,
   1596                           CYCLE_TIME_EXTENSIONf,
   1597                           calendar->ptp_max_cycle_extension);
   1598         BCM_IF_ERROR_RETURN(
   1599             soc_reg32_set(unit, taf_reg_ext[setup_set], REG_PORT_ANY,
   1600                           taf_gate_id, regval));
   1601 
   1602     }
   1603 
   1604     /* HW detect 0 to 1 change to start switching to new cycles.*/
   1605     BCM_IF_ERROR_RETURN(
   1606         soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY,
   1607                       taf_gate_id, &regval));
   1608     soc_reg_field_set(unit, TAF_CONFIG_0r, &regval,
   1609                       CONFIG_CHANGEf, 0);
   1610     BCM_IF_ERROR_RETURN(
   1611         soc_reg32_set(unit, TAF_CONFIG_0r, REG_PORT_ANY,
   1612                       taf_gate_id, regval));
   1613 
   1614     BCM_IF_ERROR_RETURN(
   1615         soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY,
   1616                       taf_gate_id, &regval));
   1617     soc_reg_field_set(unit, TAF_CONFIG_0r, &regval,
   1618                       CONFIG_CHANGEf, 1);
   1619     BCM_IF_ERROR_RETURN(
   1620         soc_reg32_set(unit, TAF_CONFIG_0r, REG_PORT_ANY,
   1621                       taf_gate_id, regval));
   1622 
   1623     return BCM_E_NONE;
   1624 }
   1625 
   1626 /* check the parameter of calendar */
   1627 STATIC int
   1628 bcmi_gh2_taf_calendar_param_check(
   1629     int unit,
   1630     int taf_gate,
   1631     bcm_tsn_taf_profile_t *calendar)
   1632 {
   1633     int i;
   1634     soc_mem_t mem;
   1635 
   1636     if (NULL == calendar) {
   1637         return BCM_E_PARAM;
   1638     }
   1639 
   1640     if (calendar->num_entries <= 0 ||
   1641         calendar->num_entries > TAF_SCHEDULE_CALENDAR_ENTIRES) {
   1642         return BCM_E_PARAM;
   1643     }
   1644 
   1645     if (calendar->entries[0].ticks == BCM_TSN_TAF_ENTRY_TICKS_GO_FIRST) {
   1646         return BCM_E_PARAM;
   1647     }
   1648 
   1649     assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM);
   1650 
   1651     mem = taf_schedule_calendar_mem[0][0];
   1652     for (i = 0; i < calendar->num_entries; i++) {
   1653         if (calendar->entries[i].ticks != BCM_TSN_TAF_ENTRY_TICKS_STAY) {
   1654             BCM_IF_ERROR_RETURN(
   1655                 soc_mem_field32_fit(unit, mem, TIME_INTERVALf,
   1656                                     calendar->entries[i].ticks));
   1657         }
   1658         BCM_IF_ERROR_RETURN(
   1659             soc_mem_field32_fit(unit, mem, GATE_STATEf,
   1660                                 calendar->entries[i].state));
   1661         BCM_IF_ERROR_RETURN(
   1662             soc_mem_field32_fit(unit, mem, COS_PROFILEf,
   1663                                 calendar->entries[i].cos_profile));
   1664         BCM_IF_ERROR_RETURN(
   1665             soc_mem_field32_fit(unit, mem, MAXBYTES_SELECTf,
   1666                                 calendar->entries[i].maxbyte_profile));
   1667 
   1668         if (0 != calendar->entries[i].cos_profile) {
   1669             if (calendar->entries[i].cos_profile >= TAF_COSQ_PROFILE_NUM) {
   1670                 return BCM_E_PARAM;
   1671             }
   1672             if (0 == taf_cosq_profile_refcount
   1673                      [unit][calendar->entries[i].cos_profile]) {
   1674                 return BCM_E_PARAM;
   1675             }
   1676         }
   1677 
   1678         if (0 != calendar->entries[i].maxbyte_profile) {
   1679             if (calendar->entries[i].maxbyte_profile >= TAF_MAXBYTE_PROFILE_NUM)
   1680             {
   1681                 return BCM_E_PARAM;
   1682             }
   1683             if (0 == taf_maxbyte_profile_refcount
   1684                      [unit][taf_gate][calendar->entries[i].maxbyte_profile]) {
   1685                 return BCM_E_PARAM;
   1686             }
   1687         }
   1688     }
   1689 
   1690     BCM_IF_ERROR_RETURN(
   1691         soc_reg_field_validate(unit, TAF_CYCLE_TIME_0r, CYCLE_TIMEf,
   1692                                calendar->ptp_cycle_time));
   1693     BCM_IF_ERROR_RETURN(
   1694         soc_reg_field_validate(unit, TAF_CYCLE_TIME_EXTENSION_0r,
   1695                                CYCLE_TIME_EXTENSIONf,
   1696                                calendar->ptp_max_cycle_extension));
   1697     if (calendar->ptp_base_time.nanoseconds >= TAF_SCHEDULE_NANOSEC_MAX) {
   1698         return BCM_E_PARAM;
   1699     }
   1700     return BCM_E_NONE;
   1701 }
   1702 
   1703 /* for the profile (maxbyte and CosQ) in calendar, increase the ref_cnt
   1704  *  Note. this function assume that the profile id is valid.
   1705  *        the caller need to ensure that
   1706  */
   1707 STATIC int
   1708 bcmi_gh2_taf_calendar_resource_alloc(
   1709     int unit,
   1710     int taf_gate,
   1711     bcm_tsn_taf_profile_t *calendar)
   1712 {
   1713     int i;
   1714 
   1715     if (NULL == calendar) {
   1716         return BCM_E_PARAM;
   1717     }
   1718 
   1719     assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM);
   1720 
   1721     for (i = 0; i < calendar->num_entries; i++) {
   1722         if (0 != calendar->entries[i].cos_profile) {
   1723             assert(calendar->entries[i].cos_profile < TAF_COSQ_PROFILE_NUM);
   1724             assert(taf_cosq_profile_refcount
   1725                    [unit][calendar->entries[i].cos_profile] != 0);
   1726             taf_cosq_profile_refcount
   1727                     [unit][calendar->entries[i].cos_profile]++;
   1728         }
   1729 
   1730         if (0 != calendar->entries[i].maxbyte_profile) {
   1731             assert(calendar->entries[i].maxbyte_profile
   1732                     < TAF_MAXBYTE_PROFILE_NUM);
   1733             assert(taf_maxbyte_profile_refcount
   1734                    [unit][taf_gate][calendar->entries[i].maxbyte_profile] != 0);
   1735             taf_maxbyte_profile_refcount
   1736                    [unit][taf_gate][calendar->entries[i].maxbyte_profile]++;
   1737         }
   1738     }
   1739 
   1740     return BCM_E_NONE;
   1741 }
   1742 
   1743 /* for the profile (maxbyte and CosQ) in calendar, decrease the ref_cnt
   1744  *  Note. this function assume that the profile id is valid.
   1745  *        the caller need to ensure that
   1746  */
   1747 STATIC int
   1748 bcmi_gh2_taf_calendar_resource_free(
   1749     int unit,
   1750     int taf_gate,
   1751     bcm_tsn_taf_profile_t *calendar)
   1752 {
   1753     int i;
   1754 
   1755     if (NULL == calendar) {
   1756         return BCM_E_PARAM;
   1757     }
   1758 
   1759     assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM);
   1760 
   1761     for (i = 0; i < calendar->num_entries; i++) {
   1762         if (0 != calendar->entries[i].cos_profile) {
   1763             assert(calendar->entries[i].cos_profile < TAF_COSQ_PROFILE_NUM);
   1764             assert(taf_cosq_profile_refcount
   1765                    [unit][calendar->entries[i].cos_profile] != 0);
   1766             taf_cosq_profile_refcount
   1767                     [unit][calendar->entries[i].cos_profile]--;
   1768         }
   1769 
   1770         if (0 != calendar->entries[i].maxbyte_profile) {
   1771             assert(calendar->entries[i].maxbyte_profile
   1772                     < TAF_MAXBYTE_PROFILE_NUM);
   1773             assert(taf_maxbyte_profile_refcount
   1774                    [unit][taf_gate][calendar->entries[i].maxbyte_profile] != 0);
   1775             taf_maxbyte_profile_refcount
   1776                    [unit][taf_gate][calendar->entries[i].maxbyte_profile]--;
   1777         }
   1778     }
   1779 
   1780     return BCM_E_NONE;
   1781 }
   1782 
   1783 /* create a profile according to user's profile */
   1784 STATIC int
   1785 bcmi_gh2_taf_calendar_profile_create(
   1786     int unit,
   1787     bcm_tsn_taf_profile_t *calendar,
   1788     bcm_tsn_taf_profile_id_t *ret_pid,
   1789     bcmi_tsn_taf_profile_t **ret_profile)
   1790 {
   1791     int profile_index;
   1792     bcmi_tsn_taf_profile_t *new_profile = NULL;
   1793 
   1794     if (NULL == calendar || NULL == ret_profile || NULL == ret_pid) {
   1795         return BCM_E_PARAM;
   1796     }
   1797 
   1798     BCM_IF_ERROR_RETURN(
   1799         shr_res_bitmap_alloc(
   1800             taf_schedule_profile_bitmap[unit], 0, 1, &profile_index));
   1801 
   1802     if (profile_index < 0 || profile_index >= BCMI_TSN_TAF_PROFILE_NUM_MAX) {
   1803         return BCM_E_INTERNAL;
   1804     }
   1805 
   1806     new_profile = sal_alloc(sizeof(bcmi_tsn_taf_profile_t), "TAF profile");
   1807     if (NULL == new_profile) {
   1808         return BCM_E_MEMORY;
   1809     }
   1810     sal_memset(new_profile, 0, sizeof(bcmi_tsn_taf_profile_t));
   1811     taf_schedule_profile[unit][profile_index] = new_profile;
   1812     *ret_profile = new_profile;
   1813     *ret_pid = profile_index;
   1814 
   1815     return BCM_E_NONE;
   1816 }
   1817 
   1818 /* get profile according to profile id */
   1819 STATIC int
   1820 bcmi_gh2_taf_calendar_profile_get(
   1821     int unit,
   1822     bcm_tsn_taf_profile_id_t profile_id,
   1823     bcmi_tsn_taf_profile_t **ret_profile)
   1824 {
   1825     if (NULL == ret_profile) {
   1826         return BCM_E_PARAM;
   1827     }
   1828 
   1829     assert(profile_id >= 0 && profile_id < BCMI_TSN_TAF_PROFILE_NUM_MAX);
   1830 
   1831     if (NULL == taf_schedule_profile[unit][profile_id]) {
   1832         return BCM_E_NOT_FOUND;
   1833     }
   1834 
   1835     *ret_profile = taf_schedule_profile[unit][profile_id];
   1836     return BCM_E_NONE;
   1837 }
   1838 
   1839 /* destroy a existing profile */
   1840 STATIC int
   1841 bcmi_gh2_taf_calendar_profile_destroy(
   1842     int unit,
   1843     bcm_tsn_taf_profile_id_t profile_id)
   1844 {
   1845     assert(profile_id >= 0 && profile_id < BCMI_TSN_TAF_PROFILE_NUM_MAX);
   1846 
   1847     if (NULL == taf_schedule_profile[unit][profile_id]) {
   1848         return BCM_E_NOT_FOUND;
   1849     }
   1850 
   1851     BCM_IF_ERROR_RETURN(
   1852         shr_res_bitmap_free(taf_schedule_profile_bitmap[unit], 1, profile_id));
   1853     sal_free(taf_schedule_profile[unit][profile_id]);
   1854     taf_schedule_profile[unit][profile_id] = NULL;
   1855 
   1856     return BCM_E_NONE;
   1857 }
   1858 
   1859 /* traverse existing profiles */
   1860 STATIC int
   1861 bcmi_gh2_taf_calendar_profile_traverse(
   1862     int unit,
   1863     int taf_gate,
   1864     bcm_tsn_taf_profile_traverse_cb cb,
   1865     void *user_data)
   1866 {
   1867     int i;
   1868 
   1869     if (NULL == cb) {
   1870         return BCM_E_PARAM;
   1871     }
   1872 
   1873     for (i = 0; i < BCMI_TSN_TAF_PROFILE_NUM_MAX; i++) {
   1874         if (NULL != taf_schedule_profile[unit][i] &&
   1875             taf_schedule_profile[unit][i]->taf_gate == taf_gate) {
   1876             BCM_IF_ERROR_RETURN(
   1877                 cb(unit, taf_gate, i, user_data));
   1878         }
   1879     }
   1880 
   1881     return BCM_E_NONE;
   1882 }
   1883 
   1884 /* remove a calendar entry from timeline
   1885  * Note. we skip check whether entry_remove exitsed in
   1886  *       taf_schedule_timeline[unit][taf_gate_id] or not.
   1887  *        ==> The caller need to ensure this.
   1888  */
   1889 STATIC int
   1890 bcmi_gh2_taf_schedule_remove(
   1891     int unit,
   1892     int taf_gate_id,
   1893     bcmi_tsn_taf_profile_t *profile)
   1894 {
   1895     bcmi_tsn_taf_schedule_entry_t *entry_remove;
   1896 
   1897     if (NULL == profile) {
   1898         return BCM_E_PARAM;
   1899     }
   1900     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
   1901 
   1902     entry_remove = profile->schedule;
   1903     if (NULL == entry_remove) {
   1904         return BCM_E_INTERNAL;
   1905     }
   1906 
   1907     if (entry_remove->prev != NULL) {
   1908         entry_remove->prev->next = entry_remove->next;
   1909     } else {
   1910         taf_schedule_timeline[unit][taf_gate_id] = entry_remove->next;
   1911     }
   1912 
   1913     if (entry_remove->next != NULL) {
   1914         entry_remove->next->prev = entry_remove->prev;
   1915     }
   1916 
   1917     sal_free(entry_remove);
   1918     profile->schedule = NULL;
   1919     return BCM_E_NONE;
   1920 }
   1921 
   1922 
   1923 /* check if this profile has already has scheduled in timeline
   1924  * (only possible in ptp mode)
   1925  */
   1926 STATIC int
   1927 bcmi_gh2_taf_schedule_exist(
   1928     int unit,
   1929     bcmi_tsn_taf_profile_t *profile,
   1930     int *ret_is_exist)
   1931 {
   1932     if (NULL == profile || NULL == ret_is_exist) {
   1933         return BCM_E_PARAM;
   1934     } else if (NULL == profile->schedule) {
   1935         *ret_is_exist = 0;
   1936     } else {
   1937         *ret_is_exist = 1;
   1938     }
   1939 
   1940     return BCM_E_NONE;
   1941 }
   1942 
   1943 /* return actual scheduling time
   1944  * if this profile has already has been scheduled
   1945  */
   1946 STATIC int
   1947 bcmi_gh2_taf_schedule_get(
   1948     int unit,
   1949     bcmi_tsn_taf_profile_t *profile,
   1950     bcm_ptp_timestamp_t *ret_schedule_time)
   1951 {
   1952     if (NULL == profile || NULL == ret_schedule_time) {
   1953         return BCM_E_PARAM;
   1954     }
   1955 
   1956     if (NULL == profile->schedule) {
   1957         return BCM_E_PARAM;
   1958     }
   1959 
   1960     bcmi_gh2_taf_ptp_time_assign(ret_schedule_time,
   1961                                  &(profile->schedule->schedule_time));
   1962 
   1963     return BCM_E_NONE;
   1964 }
   1965 
   1966 
   1967 /* create a new calendar entry and insert it into timeline */
   1968 STATIC int
   1969 bcmi_gh2_taf_schedule_insert(
   1970     int unit,
   1971     int taf_gate_id,
   1972     bcm_ptp_timestamp_t *schedule_basetime,
   1973     bcmi_tsn_taf_profile_t *profile)
   1974 {
   1975     bcm_ptp_timestamp_t curr_time;
   1976     bcmi_tsn_taf_schedule_entry_t *entry_iter = NULL;
   1977     bcmi_tsn_taf_schedule_entry_t *entry_pos = NULL;
   1978     bcmi_tsn_taf_schedule_entry_t *entry_tail = NULL;
   1979     bcmi_tsn_taf_schedule_entry_t *entry_new = NULL;
   1980 
   1981     if (NULL == profile || NULL == schedule_basetime) {
   1982         return BCM_E_PARAM;
   1983     }
   1984 
   1985     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
   1986 
   1987     {
   1988         BCM_IF_ERROR_RETURN(
   1989             bcmi_gh2_taf_ptp_time_get(unit, &curr_time));
   1990     }
   1991 
   1992     if (TRUE == bcmi_gh2_taf_ptp_time_gt(&curr_time, schedule_basetime)) {
   1993         return BCM_E_PARAM;
   1994     }
   1995 
   1996     /* find the position to insert
   1997      *    ex. there have already four entry in timeline
   1998      *
   1999      *         basetime     10s         20s         25s         30s         40s
   2000      *                   ----|------------|----------|-----------|-----------|-
   2001      *                       A            B          C           D           E
   2002      *
   2003      *         if schedule_basetime = 25s, entry_pos would be D
   2004      */
   2005     entry_iter = taf_schedule_timeline[unit][taf_gate_id];
   2006     while (entry_iter != NULL) {
   2007         if (TRUE == bcmi_gh2_taf_ptp_time_ge(
   2008                         schedule_basetime,
   2009                         &(entry_iter->schedule_time))) {
   2010             if (NULL == entry_iter->next) {
   2011                 entry_tail = entry_iter;
   2012             }
   2013             entry_iter = entry_iter->next;
   2014         } else {
   2015             break; /* find out the position */
   2016         }
   2017     }
   2018     entry_pos = entry_iter;
   2019 
   2020     /* insert new entry */
   2021     entry_new = sal_alloc(sizeof(bcmi_tsn_taf_schedule_entry_t),
   2022                           "TAF schedule entry");
   2023     if (NULL == entry_new) {
   2024         return BCM_E_MEMORY;
   2025     }
   2026     bcmi_gh2_taf_ptp_time_assign(&(entry_new->schedule_time),
   2027                                  schedule_basetime);
   2028     if (NULL == taf_schedule_timeline[unit][taf_gate_id]) {
   2029         /* entry_new is a first entry in timline */
   2030         entry_new->prev = NULL;
   2031         entry_new->next = NULL;
   2032         taf_schedule_timeline[unit][taf_gate_id] = entry_new;
   2033     } else {
   2034         if (entry_pos == NULL) {
   2035             /* insert entry_new at tail */
   2036             entry_new->prev = entry_tail;
   2037             entry_new->next = NULL;
   2038             entry_tail->next = entry_new;
   2039         } else {
   2040             /* add entry_new before entry_pos */
   2041             entry_new->prev = entry_pos->prev;
   2042             entry_new->next = entry_pos;
   2043             if (entry_pos->prev == NULL) {
   2044                 taf_schedule_timeline[unit][taf_gate_id] = entry_new;
   2045             } else {
   2046                 entry_pos->prev->next = entry_new;
   2047             }
   2048             entry_pos->prev = entry_new;
   2049         }
   2050     }
   2051 
   2052     /* remove old schedule if need */
   2053     if (profile->schedule != NULL) {
   2054         BCM_IF_ERROR_RETURN(
   2055             bcmi_gh2_taf_schedule_remove(unit, taf_gate_id, profile));
   2056     }
   2057 
   2058     /* setup connection */
   2059     entry_new->taf_profile = profile;
   2060     profile->schedule = entry_new;
   2061     return BCM_E_NONE;
   2062 }
   2063 
   2064 /* select a candidate entry from timeline
   2065  *  which is able to be scheduled as "pending"
   2066  *     Note. 1. after decide candidate,
   2067  *              it is possible that it just update its scheduling time
   2068  *              and not write into hw yet
   2069  *           2. this function maybe remove some entries
   2070  *              and change their state to expired
   2071  */
   2072 STATIC int
   2073 bcmi_gh2_taf_schedule_pick(
   2074     int unit,
   2075     int taf_gate_id,
   2076     bcmi_tsn_taf_profile_t *active_profile,
   2077     bcmi_tsn_taf_profile_t **candidate_profile)
   2078 {
   2079     bcm_ptp_timestamp_t curr_time;
   2080     bcm_ptp_timestamp_t candidate_time;
   2081     bcmi_tsn_taf_schedule_entry_t *entry_candidate = NULL;
   2082     bcmi_tsn_taf_schedule_entry_t *entry_iter = NULL;
   2083     bcmi_tsn_taf_schedule_entry_t *entry_back = NULL;
   2084     bcmi_tsn_taf_schedule_entry_t *entry_fore = NULL;
   2085     uint32 need_recheck_candicate = FALSE;
   2086     uint64 tod_curr;
   2087     uint64 tod_candidate;
   2088     uint32 okay_to_kick_off = FALSE;
   2089 
   2090     if (NULL == candidate_profile) {
   2091         return BCM_E_PARAM;
   2092     }
   2093 
   2094     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
   2095 
   2096     /* find candidate
   2097      *    step 1. according to the current time, traverse backward fisrt
   2098      *    step 2. if it cannot find anything in step 1, traverse foreward
   2099      *
   2100      *     ex 1.
   2101      *         1       2
   2102      *       --|-------|-------|---         ==> pick entry 2
   2103      *                     curr_time
   2104      *
   2105      *     ex 2.
   2106      *                1              2
   2107      *       ---------|-------|------|-     ==> pick entry 1
   2108      *                     curr_time
   2109      *     ex 3.
   2110      *         1      2               3
   2111      *       --|-------|-------|------|-    ==> pick entry 2
   2112      *                     curr_time
   2113      */
   2114 
   2115 
   2116     {
   2117         BCM_IF_ERROR_RETURN(
   2118             bcmi_gh2_taf_ptp_time_get(unit, &curr_time));
   2119     }
   2120 
   2121     entry_iter = taf_schedule_timeline[unit][taf_gate_id];
   2122     while (entry_iter != NULL) {
   2123 
   2124         if (TRUE == bcmi_gh2_taf_ptp_time_gt(
   2125                         &(entry_iter->schedule_time), &curr_time)) {
   2126             entry_fore = entry_iter;
   2127             entry_back = entry_iter->prev;
   2128             break;
   2129         } else {
   2130             if (NULL == entry_iter->next) {
   2131                 entry_fore = NULL;
   2132                 entry_back = entry_iter;
   2133                 break;
   2134             } else {
   2135                 entry_iter = entry_iter->next;
   2136             }
   2137         }
   2138     }
   2139     if (NULL != entry_back) {
   2140         entry_candidate = entry_back;
   2141     } else {
   2142         entry_candidate = entry_fore;
   2143     }
   2144 
   2145     if (NULL == entry_candidate) {
   2146         /* cannot find out any candidate */
   2147         return BCM_E_NONE;
   2148     }
   2149 
   2150     /*  Calaulate the actual scheduling time of candidate.
   2151      *     because of GH2 hw limitaion, maybe we need to delay scheduling time
   2152      *     [rule] the actual scheduling time needs to be at least
   2153      *            "2 * old-cycle + hw process + sw process time"
   2154      *            far away from the current time
   2155      *
   2156      *  After moving scheduling time foreward,
   2157      *  maybe we needs to select the new candidate
   2158      *
   2159      *     ex. At first, we select entry 2 as a candidate.
   2160      *
   2161      *               2(c)                 3(c)    4(c)    5(c)
   2162      *       --|-------|-------|------------|-------|-------|-------
   2163      *                20s   curr_time(30s)  40s     50s    60s
   2164      *
   2165      *        Assume that after calculating, the new scheduling time is at 55s
   2166      *        Then we need to select entry 4 as new candidate instead.
   2167      *        And re-calaulate the actual scheduling time of entry 4
   2168      *
   2169      *                                            4(c)    5(c)
   2170      *       --|---------------|--------------------|-------|-------
   2171      *                      curr_time(30s)          50s    60s
   2172      *
   2173      *        remove entry 2 and 3 from timelime (mark their status as expired)
   2174      *        at the end of this function
   2175      */
   2176      need_recheck_candicate = TRUE;
   2177      while (TRUE == need_recheck_candicate) {
   2178         bcm_ptp_timestamp_t schedule_time_at_least;
   2179 
   2180         bcmi_gh2_taf_ptp_time_assign(&(candidate_time),
   2181                                      &(entry_candidate->schedule_time));
   2182 
   2183         /* calculate the actual scheduling time of candidate */
   2184         {
   2185             BCM_IF_ERROR_RETURN(
   2186                 bcmi_gh2_taf_ptp_time_get(unit, &curr_time));
   2187         }
   2188 
   2189         LOG_VERBOSE(BSL_LS_BCM_TSN,
   2190             (BSL_META("[taf_schedule_pick] curr_time : \
   2191                        sec:%d %d, nano:%d\n"),
   2192                        COMPILER_64_HI(curr_time.seconds),
   2193                        COMPILER_64_LO(curr_time.seconds),
   2194                        curr_time.nanoseconds));
   2195 
   2196         /* schedule_time_at_least =
   2197          *  curr_time + 2 * old-cycle + hw process + sw process time
   2198          */
   2199         bcmi_gh2_taf_ptp_time_assign(&schedule_time_at_least, &curr_time);
   2200         if (active_profile != NULL) {
   2201             bcmi_gh2_taf_ptp_time_add(
   2202                 &schedule_time_at_least,
   2203                 2 * (active_profile->data.ptp_cycle_time));
   2204         }
   2205 
   2206         {
   2207             bcmi_gh2_taf_ptp_time_add(&schedule_time_at_least,
   2208                                       TAF_SCHEDULE_HW_RESPONSE_TIME);
   2209             bcmi_gh2_taf_ptp_time_add(&schedule_time_at_least,
   2210                                       TAF_SCHEDULE_SW_RESPONSE_TIME);
   2211         }
   2212 
   2213         LOG_VERBOSE(BSL_LS_BCM_TSN,
   2214             (BSL_META("[taf_schedule_pick] schedule_time_at_least : \
   2215                        sec:%d %d, nano:%d\n"),
   2216                        COMPILER_64_HI(schedule_time_at_least.seconds),
   2217                        COMPILER_64_LO(schedule_time_at_least.seconds),
   2218                        schedule_time_at_least.nanoseconds));
   2219 
   2220         while (TRUE == bcmi_gh2_taf_ptp_time_gt(&schedule_time_at_least,
   2221                                                 &candidate_time)) {
   2222             /* Add N x new_cycle_time until > schedule_time_at_least */
   2223             bcmi_gh2_taf_ptp_time_add(
   2224                 &candidate_time,
   2225                 entry_candidate->taf_profile->data.ptp_cycle_time);
   2226         }
   2227 
   2228         LOG_VERBOSE(BSL_LS_BCM_TSN,
   2229             (BSL_META("[taf_schedule_pick] candidate_time : \
   2230                        sec:%d %d, nano:%d\n"),
   2231                        COMPILER_64_HI(candidate_time.seconds),
   2232                        COMPILER_64_LO(candidate_time.seconds),
   2233                        candidate_time.nanoseconds));
   2234 
   2235         /* check this new scheduling time would not be larger
   2236          * than the next entries
   2237          */
   2238         need_recheck_candicate = FALSE;
   2239         entry_iter = entry_candidate;
   2240         while (NULL != entry_iter) {
   2241             if (NULL == entry_iter->next) {
   2242                 break;
   2243             }
   2244             if (TRUE == bcmi_gh2_taf_ptp_time_gt(
   2245                             &candidate_time,
   2246                             &(entry_iter->next->schedule_time))) {
   2247                 need_recheck_candicate = TRUE;
   2248                 entry_iter = entry_iter->next;
   2249             } else {
   2250                 break;
   2251             }
   2252         }
   2253         if (TRUE == need_recheck_candicate) {
   2254             entry_candidate = entry_iter; /* new candidate */
   2255         }
   2256     }
   2257 
   2258     if (NULL == entry_candidate) {
   2259         return BCM_E_INTERNAL;
   2260     }
   2261 
   2262     /* for this candidate
   2263      *   1. udpate its scheduling time
   2264      *   2. kick off this new scheduling time if okay
   2265      *      [rule]
   2266      *          1) need to locate in the same TOD
   2267      *          2) actual schedule time need to be 1 old-cycle time
   2268      *             far away from the boundary of ToD
   2269      *      ex.
   2270      *        -----|-----------|-----------|-----------
   2271      *            64s    ^   128s    ^    192s
   2272      *                   |           |
   2273      *                 candidate    cur_time (130s)
   2274      *
   2275      *        Assume that the old cycle time is 100ns
   2276      *        After calculating in the previous step:
   2277      *        Case A. the scheduling time is updated to 140s
   2278      *                  ==> it is okay to kick off
   2279      *        Case B. the scheduling time is updated to 193s
   2280      *                  ==> just update its scheduling time
   2281      *                      delay its kick-off until the next ToD interrupt
   2282      */
   2283     okay_to_kick_off = FALSE;
   2284     bcmi_gh2_taf_ptp_time_assign(
   2285         &(entry_candidate->schedule_time), &candidate_time);
   2286     bcmi_gh2_taf_ptp_time_to_tod(&curr_time, &tod_curr);
   2287     bcmi_gh2_taf_ptp_time_to_tod(&candidate_time, &tod_candidate);
   2288     if (COMPILER_64_EQ(tod_curr, tod_candidate)) {
   2289         if (active_profile != NULL) {
   2290             bcm_ptp_timestamp_t tod_boundary;
   2291             uint64 tod_next;
   2292 
   2293             COMPILER_64_COPY(tod_next, tod_curr);
   2294             COMPILER_64_ADD_32(tod_next, 1);
   2295             bcmi_gh2_taf_ptp_time_from_tod(&tod_next, &tod_boundary);
   2296             bcmi_gh2_taf_ptp_time_sub(
   2297                 &tod_boundary,
   2298                 active_profile->data.ptp_cycle_time);
   2299             if (TRUE == bcmi_gh2_taf_ptp_time_gt(&tod_boundary,
   2300                                                  &candidate_time)) {
   2301                 okay_to_kick_off = TRUE;
   2302             }
   2303         } else {
   2304             okay_to_kick_off = TRUE;
   2305         }
   2306     }
   2307     if (TRUE == okay_to_kick_off) {
   2308         *candidate_profile = entry_candidate->taf_profile;
   2309     } else {
   2310         *candidate_profile = NULL;
   2311     }
   2312 
   2313     LOG_VERBOSE(BSL_LS_BCM_TSN,
   2314         (BSL_META("[taf_schedule_pick] okay_to_kick_off : %s\n"),
   2315                    (TRUE == okay_to_kick_off) ? "Yes" : "No"));
   2316 
   2317     /*
   2318      * delete all entries before this candidate from timeline
   2319      */
   2320     entry_iter = entry_candidate->prev;
   2321     while (NULL != entry_iter) {
   2322         bcmi_tsn_taf_schedule_entry_t *entry_prev = entry_iter->prev;
   2323 
   2324         BCM_IF_ERROR_RETURN(
   2325             bcmi_gh2_taf_schedule_remove(
   2326                 unit, taf_gate_id, entry_iter->taf_profile));
   2327         entry_iter->taf_profile->status = bcmTsnTafProfileExpired;
   2328         entry_iter = entry_prev;
   2329     }
   2330 
   2331     return BCM_E_NONE;
   2332 }
   2333 
   2334 /* the 1st function need to be invoked to handle hw interrupt */
   2335 STATIC int
   2336 bcmi_gh2_taf_interrupt_handle_start(int unit)
   2337 {
   2338     uint32 status;
   2339     uint32 mask;
   2340     gh2_taf_interrupt_type_t iter;
   2341 
   2342     if (1 == taf_interrupt_handling[unit]) {
   2343         return BCM_E_INTERNAL;
   2344     }
   2345 
   2346     BCM_IF_ERROR_RETURN(
   2347         soc_reg32_get(unit, TAF_MEMFAILINTSTATUSr, REG_PORT_ANY, 0, &status));
   2348 
   2349     BCM_IF_ERROR_RETURN(
   2350         soc_reg32_get(unit, TAF_MEMFAILINTMASKr, REG_PORT_ANY, 0, &mask));
   2351 
   2352     taf_interrupt_status[unit] = status & mask;
   2353 
   2354     for (iter = 0; iter < TafInterruptCount; iter++) {
   2355         if (taf_interrupt_mapping[iter].sub_status_regs[0] != INVALIDr) {
   2356             int index;
   2357 
   2358             if (soc_reg_field_get(
   2359                     unit, TAF_MEMFAILINTSTATUSr, taf_interrupt_status[unit],
   2360                     taf_interrupt_mapping[iter].status_field)) {
   2361 
   2362                 for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) {
   2363                     BCM_IF_ERROR_RETURN(
   2364                         soc_reg32_get(
   2365                             unit,
   2366                             taf_interrupt_mapping[iter].sub_status_regs[index],
   2367                             REG_PORT_ANY, 0,
   2368                             &taf_interrupt_substatus[unit][iter][index]));
   2369                 }
   2370             } else {
   2371                 for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) {
   2372                     taf_interrupt_substatus[unit][iter][index] = 0;
   2373                 }
   2374             }
   2375         }
   2376     }
   2377 
   2378     taf_interrupt_handling[unit] = 1;
   2379     return BCM_E_NONE;
   2380 }
   2381 
   2382 /* indicate that whether need to handle Tod window interupt event */
   2383 STATIC int
   2384 bcmi_gh2_taf_interrupt_handle_tod(int unit, int *ret_need)
   2385 {
   2386     if (1 != taf_interrupt_handling[unit]) {
   2387         return BCM_E_INTERNAL;
   2388     }
   2389     if (NULL == ret_need) {
   2390         return BCM_E_PARAM;
   2391     }
   2392 
   2393     *ret_need = soc_reg_field_get(
   2394                     unit, TAF_MEMFAILINTSTATUSr, taf_interrupt_status[unit],
   2395                     taf_interrupt_mapping[TafInterruptTodWindow].status_field);
   2396 
   2397     return BCM_E_NONE;
   2398 }
   2399 
   2400 /* indicate that whether need to handle profile switch done event
   2401  *   ret_need(OUT)        : whether to handle profile switch
   2402  *   ret_bmp_gate(IN/OUT) : return the bitmap of taf_gate need to handle
   2403  *   bmp_size(IN)         : the size of bitmap
   2404  */
   2405 STATIC int
   2406 bcmi_gh2_taf_interrupt_handle_switch(
   2407     int unit,
   2408     int *ret_need,
   2409     SHR_BITDCL *ret_bmp_gate,
   2410     uint32 bmp_size)
   2411 {
   2412     int index;
   2413 
   2414     if (1 != taf_interrupt_handling[unit]) {
   2415         return BCM_E_INTERNAL;
   2416     }
   2417     if (NULL == ret_need || NULL == ret_bmp_gate) {
   2418         return BCM_E_PARAM;
   2419     }
   2420     if (bmp_size < _SHR_BITDCLSIZE(BCMI_TSN_TAF_GATE_NUM)) {
   2421         return BCM_E_PARAM;
   2422     }
   2423 
   2424     for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) {
   2425         ret_bmp_gate[index] =
   2426           taf_interrupt_substatus[unit][TafInterruptSwitchDone][index];
   2427     }
   2428 
   2429     SHR_BITTEST_RANGE(ret_bmp_gate, 0, BCMI_TSN_TAF_GATE_NUM, *ret_need);
   2430     return BCM_E_NONE;
   2431 }
   2432 
   2433 /* indicate that whether need to handle profile become error
   2434  *   ret_need(OUT)        : whether to handle profile error
   2435  *   ret_bmp_gate(IN/OUT) : return the bitmap of taf_gate need to handle
   2436  *   bmp_size(IN)         : the size of bitmap
   2437  */
   2438 STATIC int
   2439 bcmi_gh2_taf_interrupt_handle_error(
   2440     int unit,
   2441     int *ret_need,
   2442     SHR_BITDCL *ret_bmp_gate,
   2443     uint32 bmp_size)
   2444 {
   2445     int index;
   2446 
   2447     if (1 != taf_interrupt_handling[unit]) {
   2448         return BCM_E_INTERNAL;
   2449     }
   2450     if (NULL == ret_need || NULL == ret_bmp_gate) {
   2451         return BCM_E_PARAM;
   2452     }
   2453     if (bmp_size < _SHR_BITDCLSIZE(BCMI_TSN_TAF_GATE_NUM)) {
   2454         return BCM_E_PARAM;
   2455     }
   2456 
   2457     for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) {
   2458         ret_bmp_gate[index] =
   2459           taf_interrupt_substatus[unit][TafInterruptNextCycleTimeError][index] |
   2460           taf_interrupt_substatus[unit][TafInterruptParityError][index] |
   2461           taf_interrupt_substatus[unit][TafInterruptTblPtrError][index] |
   2462           taf_interrupt_substatus[unit][TafInterruptBaseTimeError][index];
   2463     }
   2464 
   2465     SHR_BITTEST_RANGE(ret_bmp_gate, 0, BCMI_TSN_TAF_GATE_NUM, *ret_need);
   2466     return BCM_E_NONE;
   2467 }
   2468 
   2469 /* invoke the callback function hooked by the user */
   2470 STATIC int
   2471 bcmi_gh2_taf_interrupt_handle_user_cb(int unit)
   2472 {
   2473     gh2_taf_interrupt_type_t iter;
   2474 
   2475     if (1 != taf_interrupt_handling[unit]) {
   2476         return BCM_E_INTERNAL;
   2477     }
   2478 
   2479     for (iter = 0; iter < TafInterruptCount; iter++) {
   2480         bcm_tsn_taf_event_type_t event;
   2481         int i, j;
   2482 
   2483         switch (iter) {
   2484             case TafInterruptSwitchDone:
   2485                 event = bcmTsnTafEventTAFProfileChange;
   2486                 break;
   2487             case TafInterruptNextCycleTimeError:
   2488                 event = bcmTsnTafEventTAFNextCycleTimeErr;
   2489                 break;
   2490             case TafInterruptBaseTimeError:
   2491                 event = bcmTsnTafEventTAFBaseTimeErr;
   2492                 break;
   2493             case TafInterruptParityError:
   2494                 event = bcmTsnTafEventTAFECCErr;
   2495                 break;
   2496             case TafInterruptTblPtrError:
   2497                 event = bcmTsnTafEventTAFProfilePtrErr;
   2498                 break;
   2499             default: /* user would not register cb for TafInterruptTodWindow */
   2500                 continue;
   2501         }
   2502         if (0 == soc_reg_field_get(
   2503             unit, TAF_MEMFAILINTSTATUSr,
   2504             taf_interrupt_status[unit],
   2505             taf_interrupt_mapping[iter].status_field)) {
   2506             continue;
   2507         }
   2508         for (i = 0; i < TAF_INTERRUPT_SUB_FIELD_NUM; i++) {
   2509             for (j = 0; j < TAF_INTERRUPT_SUB_FIELD_WIDTH; j++) {
   2510                 if (taf_interrupt_substatus[unit][iter][i] & (1 << j)) {
   2511                     BCM_IF_ERROR_RETURN(
   2512                         bcmi_gh2_taf_event_notify(
   2513                             unit,
   2514                             i * TAF_INTERRUPT_SUB_FIELD_WIDTH + j,
   2515                             event));
   2516                 }
   2517             }
   2518         }
   2519     }
   2520     return BCM_E_NONE;
   2521 }
   2522 
   2523 /* the last function should be invoked after finish handling */
   2524 STATIC int
   2525 bcmi_gh2_taf_interrupt_handle_finish(int unit)
   2526 {
   2527     gh2_taf_interrupt_type_t iter;
   2528     uint32 reg_value;
   2529 
   2530     if (1 != taf_interrupt_handling[unit]) {
   2531         return BCM_E_INTERNAL;
   2532     }
   2533 
   2534     /* clear interrupt for subfiled */
   2535     for (iter = 0; iter < TafInterruptCount; iter++) {
   2536         if (taf_interrupt_mapping[iter].sub_status_regs[0] != INVALIDr) {
   2537             int index;
   2538 
   2539             for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) {
   2540                 reg_value = taf_interrupt_substatus[unit][iter][index];
   2541                 if (0 == reg_value) {
   2542                     continue;
   2543                 }
   2544 
   2545                 BCM_IF_ERROR_RETURN(
   2546                     soc_reg32_set(
   2547                         unit,
   2548                         taf_interrupt_mapping[iter].sub_clear_regs[index],
   2549                         REG_PORT_ANY, 0, reg_value));
   2550             }
   2551         }
   2552     }
   2553 
   2554     /* clear interrupt */
   2555     reg_value = taf_interrupt_status[unit];
   2556     BCM_IF_ERROR_RETURN(
   2557         soc_reg32_set(unit, TAF_MEMFAILINT_CLRr,
   2558                       REG_PORT_ANY, 0, reg_value));
   2559 
   2560     taf_interrupt_handling[unit] = 0;
   2561     return BCM_E_NONE;
   2562 }
   2563 
   2564 /* helper function to set maximum bytes */
   2565 STATIC int
   2566 _bcmi_gh2_taf_gate_max_bytes_profile_set(
   2567     int unit, int taf_gate_id, int profile_id, uint64 max_bytes)
   2568 {
   2569     taf_gate_control_entry_t mem_entry;
   2570     int field_len;
   2571     uint64 field_mask64;
   2572     uint64 value_mask64;
   2573 
   2574     assert(profile_id >= 0 && profile_id < TAF_MAXBYTE_PROFILE_NUM);
   2575 
   2576     /* check value range */
   2577     field_len = soc_mem_field_length(
   2578                     unit, taf_maxbyte_profile_mem,
   2579                     taf_maxbyte_profile_field[profile_id]);
   2580     COMPILER_64_SET(field_mask64, 0, 1);
   2581     COMPILER_64_SHL(field_mask64, field_len);
   2582     COMPILER_64_SUB_32(field_mask64, 1);
   2583 
   2584     COMPILER_64_COPY(value_mask64, max_bytes);
   2585     COMPILER_64_AND(value_mask64, field_mask64);
   2586     if (COMPILER_64_NE(value_mask64, max_bytes)) {
   2587         return BCM_E_PARAM;
   2588     }
   2589 
   2590     /* write field */
   2591     BCM_IF_ERROR_RETURN(
   2592         soc_mem_read(unit, taf_maxbyte_profile_mem, MEM_BLOCK_ANY,
   2593                      taf_gate_id, &mem_entry));
   2594 
   2595     soc_mem_field64_set(
   2596         unit, taf_maxbyte_profile_mem, &mem_entry,
   2597         taf_maxbyte_profile_field[profile_id], max_bytes);
   2598 
   2599     BCM_IF_ERROR_RETURN(
   2600         soc_mem_write(unit, taf_maxbyte_profile_mem, MEM_BLOCK_ALL,
   2601                       taf_gate_id, &mem_entry));
   2602 
   2603     return BCM_E_NONE;
   2604 }
   2605 
   2606 /* helper function to get maximum bytes */
   2607 STATIC int
   2608 _bcmi_gh2_taf_gate_max_bytes_profile_get(
   2609     int unit, int taf_gate_id, int profile_id, uint64 *max_bytes)
   2610 {
   2611     taf_gate_control_entry_t mem_entry;
   2612 
   2613     if (NULL == max_bytes) {
   2614         return BCM_E_PARAM;
   2615     }
   2616     assert(profile_id >= 0 && profile_id < TAF_MAXBYTE_PROFILE_NUM);
   2617 
   2618     BCM_IF_ERROR_RETURN(
   2619         soc_mem_read(unit, taf_maxbyte_profile_mem, MEM_BLOCK_ANY,
   2620                      taf_gate_id, &mem_entry));
   2621 
   2622     soc_mem_field64_get(unit, taf_maxbyte_profile_mem, &mem_entry,
   2623                         taf_maxbyte_profile_field[profile_id], max_bytes);
   2624 
   2625     return BCM_E_NONE;
   2626 }
   2627 
   2628 /* create profile of maximum bytes */
   2629 STATIC int
   2630 bcmi_gh2_taf_gate_max_bytes_profile_create(
   2631     int unit, int taf_gate_id, uint64 max_bytes, int *profile_id)
   2632 {
   2633     if (NULL == profile_id) {
   2634         return BCM_E_PARAM;
   2635     }
   2636     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
   2637 
   2638     BCM_IF_ERROR_RETURN(
   2639         shr_res_bitmap_alloc(taf_maxbyte_profile_bitmap[unit][taf_gate_id],
   2640                              0, 1, profile_id));
   2641 
   2642     if (*profile_id < 0 || *profile_id >= TAF_MAXBYTE_PROFILE_NUM ||
   2643         *profile_id == TAF_MAXBYTE_PROFILE_RESERVED_ID) {
   2644         return BCM_E_INTERNAL;
   2645     }
   2646 
   2647     ERROR_RETURN_WITH_EXTRA_CLEAN(
   2648         _bcmi_gh2_taf_gate_max_bytes_profile_set(
   2649             unit, taf_gate_id, *profile_id, max_bytes),
   2650         shr_res_bitmap_free(taf_maxbyte_profile_bitmap[unit][taf_gate_id],
   2651                             1, *profile_id));
   2652 
   2653     taf_maxbyte_profile_refcount[unit][taf_gate_id][*profile_id] = 1;
   2654 
   2655     return BCM_E_NONE;
   2656 }
   2657 
   2658 /* set profile of maximum bytes */
   2659 STATIC int
   2660 bcmi_gh2_taf_gate_max_bytes_profile_set(
   2661     int unit, int taf_gate_id, int profile_id, uint64 max_bytes)
   2662 {
   2663     if (profile_id < 0 || profile_id >= TAF_MAXBYTE_PROFILE_NUM ||
   2664         profile_id == TAF_MAXBYTE_PROFILE_RESERVED_ID) {
   2665         return BCM_E_PARAM;
   2666     }
   2667     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
   2668 
   2669     if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] == 0) {
   2670         return BCM_E_PARAM;
   2671     }
   2672 
   2673     BCM_IF_ERROR_RETURN(
   2674         _bcmi_gh2_taf_gate_max_bytes_profile_set(
   2675             unit, taf_gate_id, profile_id, max_bytes));
   2676 
   2677     return BCM_E_NONE;
   2678 }
   2679 
   2680 /* get profile of maximum bytes */
   2681 STATIC int
   2682 bcmi_gh2_taf_gate_max_bytes_profile_get(
   2683     int unit, int taf_gate_id, int profile_id, uint64 *max_bytes)
   2684 {
   2685     if (profile_id < 0 || profile_id >= TAF_MAXBYTE_PROFILE_NUM ||
   2686         profile_id == TAF_MAXBYTE_PROFILE_RESERVED_ID) {
   2687         return BCM_E_PARAM;
   2688     }
   2689     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
   2690 
   2691     if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] == 0) {
   2692         return BCM_E_NOT_FOUND;
   2693     }
   2694 
   2695     BCM_IF_ERROR_RETURN(
   2696         _bcmi_gh2_taf_gate_max_bytes_profile_get(
   2697             unit, taf_gate_id, profile_id, max_bytes));
   2698 
   2699     return BCM_E_NONE;
   2700 }
   2701 
   2702 /* traverse profile of maximum bytes */
   2703 STATIC int
   2704 bcmi_gh2_taf_gate_max_bytes_profile_traverse(
   2705     int unit, int taf_gate_id,
   2706     bcm_tsn_taf_gate_max_bytes_profile_traverse_cb cb,
   2707     void *user_data)
   2708 {
   2709     int profile_id;
   2710 
   2711     if (NULL == cb) {
   2712         return BCM_E_PARAM;
   2713     }
   2714 
   2715     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
   2716 
   2717     for (profile_id = 0; profile_id < TAF_MAXBYTE_PROFILE_NUM; profile_id++) {
   2718         if (TAF_MAXBYTE_PROFILE_RESERVED_ID == profile_id) {
   2719             continue;
   2720         }
   2721         if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] == 0) {
   2722             continue;
   2723         }
   2724         BCM_IF_ERROR_RETURN(
   2725             cb(unit, taf_gate_id, profile_id, user_data));
   2726     }
   2727 
   2728     return BCM_E_NONE;
   2729 }
   2730 
   2731 /* destroy profile of maximum bytes */
   2732 STATIC int
   2733 bcmi_gh2_taf_gate_max_bytes_profile_destroy(
   2734     int unit, int taf_gate_id, int profile_id)
   2735 {
   2736     if (profile_id < 0 || profile_id >= TAF_MAXBYTE_PROFILE_NUM ||
   2737         profile_id == TAF_MAXBYTE_PROFILE_RESERVED_ID) {
   2738         return BCM_E_PARAM;
   2739     }
   2740 
   2741     assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM);
   2742 
   2743     if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] == 0) {
   2744         return BCM_E_NOT_FOUND;
   2745     }
   2746     else if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] > 1) {
   2747         return BCM_E_BUSY;
   2748     }
   2749 
   2750     BCM_IF_ERROR_RETURN(
   2751         shr_res_bitmap_free(taf_maxbyte_profile_bitmap[unit][taf_gate_id],
   2752                             1, profile_id));
   2753     taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] = 0;
   2754 
   2755     return BCM_E_NONE;
   2756 }
   2757 
   2758 /* helper function to set cosq mapping */
   2759 STATIC int
   2760 _bcmi_gh2_taf_cosq_profile_set(
   2761     int unit, int profile_id, bcm_cos_t prio, bcm_cos_queue_t cosq)
   2762 {
   2763     int select;
   2764 
   2765     if (profile_id < 0 || profile_id >= TAF_COSQ_PROFILE_NUM ||
   2766         prio < 0 || prio >= TAF_COSQ_INTPRI_NUM) {
   2767         return BCM_E_PARAM;
   2768     }
   2769 
   2770     BCM_IF_ERROR_RETURN(
   2771         soc_mem_field32_fit(unit, taf_cosq_profile_mem,
   2772                             taf_cosq_profile_field, cosq));
   2773 
   2774     for (select = 0; select < TAF_COSQ_SELECT_NUM; select++) {
   2775         BCM_IF_ERROR_RETURN(
   2776             soc_mem_field32_modify(
   2777                 unit, taf_cosq_profile_mem,
   2778                 TAF_COSQ_HW_INDEX(profile_id, select, prio),
   2779                 taf_cosq_profile_field, cosq));
   2780     }
   2781     return BCM_E_NONE;
   2782 }
   2783 
   2784 /* helper function to get cosq mapping */
   2785 STATIC int
   2786 _bcmi_gh2_taf_cosq_profile_get(
   2787     int unit, int profile_id, bcm_cos_t prio, bcm_cos_queue_t *cosq)
   2788 {
   2789     port_cos_map_entry_t mem_entry;
   2790 
   2791     if (profile_id < 0 || profile_id >= TAF_COSQ_PROFILE_NUM ||
   2792         prio < 0 || prio >= TAF_COSQ_INTPRI_NUM) {
   2793         return BCM_E_PARAM;
   2794     }
   2795 
   2796     if (NULL == cosq) {
   2797         return BCM_E_PARAM;
   2798     }
   2799 
   2800     BCM_IF_ERROR_RETURN(
   2801         soc_mem_read(unit, taf_cosq_profile_mem, MEM_BLOCK_ANY,
   2802                      TAF_COSQ_HW_INDEX(profile_id, 0, prio),
   2803                      &mem_entry));
   2804 
   2805     *cosq = soc_mem_field32_get(unit, taf_cosq_profile_mem, &mem_entry,
   2806                                 taf_cosq_profile_field);
   2807     return BCM_E_NONE;
   2808 }
   2809 
   2810 /* create profile of cosq mapping */
   2811 STATIC int
   2812 bcmi_gh2_taf_cosq_mapping_profile_create(
   2813     int unit, int *cosq_profile)
   2814 {
   2815     if (NULL == cosq_profile) {
   2816         return BCM_E_PARAM;
   2817     }
   2818 
   2819     BCM_IF_ERROR_RETURN(
   2820         shr_res_bitmap_alloc(taf_cosq_profile_bitmap[unit],
   2821                              0, 1, cosq_profile));
   2822 
   2823     if (*cosq_profile < 0 || *cosq_profile >= TAF_COSQ_PROFILE_NUM ||
   2824         *cosq_profile == TAF_COSQ_PROFILE_RESERVED_ID) {
   2825         return BCM_E_INTERNAL;
   2826     }
   2827 
   2828     taf_cosq_profile_refcount[unit][*cosq_profile] = 1;
   2829 
   2830     return BCM_E_NONE;
   2831 }
   2832 
   2833 /* set profile of cosq mapping */
   2834 STATIC int
   2835 bcmi_gh2_taf_cosq_mapping_profile_set(
   2836     int unit, int cosq_profile, bcm_cos_t priority, bcm_cos_queue_t cosq)
   2837 {
   2838     if (cosq_profile < 0 || cosq_profile >= TAF_COSQ_PROFILE_NUM ||
   2839         cosq_profile == TAF_COSQ_PROFILE_RESERVED_ID) {
   2840         return BCM_E_PARAM;
   2841     }
   2842 
   2843     if (taf_cosq_profile_refcount[unit][cosq_profile] == 0) {
   2844         return BCM_E_PARAM;
   2845     }
   2846 
   2847     BCM_IF_ERROR_RETURN(
   2848         _bcmi_gh2_taf_cosq_profile_set(
   2849             unit, cosq_profile, priority, cosq));
   2850 
   2851     return BCM_E_NONE;
   2852 }
   2853 
   2854 /* get profile of cosq mapping */
   2855 STATIC int
   2856 bcmi_gh2_taf_cosq_mapping_profile_get(
   2857     int unit, int cosq_profile, bcm_cos_t priority, bcm_cos_queue_t *cosq)
   2858 {
   2859     if (cosq_profile < 0 || cosq_profile >= TAF_COSQ_PROFILE_NUM ||
   2860         cosq_profile == TAF_COSQ_PROFILE_RESERVED_ID) {
   2861         return BCM_E_PARAM;
   2862     }
   2863 
   2864     if (taf_cosq_profile_refcount[unit][cosq_profile] == 0) {
   2865         return BCM_E_NOT_FOUND;
   2866     }
   2867 
   2868     BCM_IF_ERROR_RETURN(
   2869         _bcmi_gh2_taf_cosq_profile_get(
   2870             unit, cosq_profile, priority, cosq));
   2871 
   2872     return BCM_E_NONE;
   2873 }
   2874 
   2875 /* traverse profile of cosq mapping */
   2876 STATIC int
   2877 bcmi_gh2_taf_cosq_mapping_profile_traverse(
   2878     int unit,
   2879     bcm_tsn_taf_cosq_mapping_profile_traverse_cb cb,
   2880     void *user_data)
   2881 {
   2882     int profile_id;
   2883 
   2884     if (NULL == cb) {
   2885         return BCM_E_PARAM;
   2886     }
   2887 
   2888     for (profile_id = 0; profile_id < TAF_COSQ_PROFILE_NUM; profile_id++) {
   2889         if (TAF_COSQ_PROFILE_RESERVED_ID == profile_id) {
   2890             continue;
   2891         }
   2892         if (taf_cosq_profile_refcount[unit][profile_id] == 0) {
   2893             continue;
   2894         }
   2895         BCM_IF_ERROR_RETURN(cb(unit, profile_id, user_data));
   2896     }
   2897 
   2898     return BCM_E_NONE;
   2899 }
   2900 
   2901 /* destroy profile of cosq mapping */
   2902 STATIC int
   2903 bcmi_gh2_taf_cosq_mapping_profile_destroy(
   2904     int unit, int cosq_profile)
   2905 {
   2906     if (cosq_profile < 0 || cosq_profile >= TAF_COSQ_PROFILE_NUM ||
   2907         cosq_profile == TAF_COSQ_PROFILE_RESERVED_ID) {
   2908         return BCM_E_PARAM;
   2909     }
   2910 
   2911     if (taf_cosq_profile_refcount[unit][cosq_profile] == 0) {
   2912         return BCM_E_NOT_FOUND;
   2913     } else if (taf_cosq_profile_refcount[unit][cosq_profile] > 1) {
   2914         return BCM_E_BUSY;
   2915     }
   2916 
   2917     BCM_IF_ERROR_RETURN(
   2918         shr_res_bitmap_free(taf_cosq_profile_bitmap[unit], 1, cosq_profile));
   2919     taf_cosq_profile_refcount[unit][cosq_profile] = 0;
   2920 
   2921     return BCM_E_NONE;
   2922 }
   2923 
   2924 /*
   2925  * update flow counter for both hw table and sw database(taf_gate_counter)
   2926  *
   2927  * if is_write = 0 : read hw data and sync back to sw
   2928  * if is_write = 1 : write parameter "write_val" into both sw/hw
   2929  */
   2930 STATIC int
   2931 bcmi_gh2_taf_gate_stat_counter_update(
   2932     int unit,
   2933     int taf_gate_id,
   2934     bcm_tsn_taf_gate_stat_t stat_type_min,
   2935     bcm_tsn_taf_gate_stat_t stat_type_max,
   2936     int is_write,
   2937     uint64 write_val)
   2938 {
   2939     bcm_tsn_taf_gate_stat_t stat_type;
   2940 
   2941     if (taf_gate_id < 0 ||
   2942         taf_gate_id >= BCMI_TSN_TAF_GATE_NUM ||
   2943         stat_type_min >= bcmTsnTafGateStatCount ||
   2944         stat_type_max >= bcmTsnTafGateStatCount ||
   2945         stat_type_min > stat_type_max) {
   2946         return BCM_E_PARAM;
   2947     }
   2948 
   2949     for (stat_type = stat_type_min; stat_type <= stat_type_max; stat_type++) {
   2950         soc_mem_t mem = taf_gate_cnt_mem[stat_type];
   2951         soc_field_t field = taf_gate_cnt_field[stat_type];
   2952         soc_memacc_t memacc_count;
   2953         uint64 *update_array_ptr = taf_gate_counter[unit][stat_type];
   2954         uint8 *buffer_ptr = taf_gate_counter_dma_buffer[unit][stat_type];
   2955         uint64 count_mask64;
   2956 
   2957         BCM_IF_ERROR_RETURN(
   2958             soc_memacc_init(unit, mem, field, &memacc_count));
   2959 
   2960         COMPILER_64_SET(count_mask64, 0, 1);
   2961         COMPILER_64_SHL(count_mask64, soc_mem_field_length(unit, mem, field));
   2962         COMPILER_64_SUB_32(count_mask64, 1);
   2963 
   2964         if (0 == is_write) {
   2965             /* read hw data and sync to sw */
   2966             uint64 hw_count, sw_last_count;
   2967 
   2968             BCM_IF_ERROR_RETURN(
   2969                 soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   2970                              taf_gate_id, buffer_ptr));
   2971             soc_memacc_field64_get(&memacc_count, buffer_ptr, &hw_count);
   2972             COMPILER_64_COPY(sw_last_count, update_array_ptr[taf_gate_id]);
   2973             COMPILER_64_AND(sw_last_count, count_mask64);
   2974 
   2975             if (COMPILER_64_GT(sw_last_count, hw_count)) {
   2976                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   2977                             (BSL_META_U(unit,
   2978                                         "Roll over happened\n")));
   2979                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   2980                             (BSL_META_U(unit,
   2981                                         ".Read Packet64 Count: %x:%x\n"),
   2982                              COMPILER_64_HI(hw_count),
   2983                              COMPILER_64_LO(hw_count)));
   2984                 COMPILER_64_ADD_64(hw_count, count_mask64);
   2985                 COMPILER_64_ADD_32(hw_count, 1);
   2986                 COMPILER_64_SUB_64(hw_count, sw_last_count);
   2987                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   2988                             (BSL_META_U(unit,
   2989                                         ".Diffed 64-Packet Count: %x:%x\n"),
   2990                              COMPILER_64_HI(hw_count),
   2991                              COMPILER_64_LO(hw_count)));
   2992             } else {
   2993                 COMPILER_64_SUB_64(hw_count, sw_last_count);
   2994             }
   2995 
   2996             /* Add difference (if it is) */
   2997             if (!COMPILER_64_IS_ZERO(hw_count)) {
   2998                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   2999                             (BSL_META_U(unit,
   3000                                         "gate id:%d==>"
   3001                                         "Old 64-Packet Count Value%x:%x\t"),
   3002                              taf_gate_id,
   3003                              COMPILER_64_HI(update_array_ptr[taf_gate_id]),
   3004                              COMPILER_64_LO(update_array_ptr[taf_gate_id])));
   3005                 COMPILER_64_ADD_64(update_array_ptr[taf_gate_id], hw_count);
   3006                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   3007                             (BSL_META_U(unit,
   3008                                        "New 64-Packet Value : %x:%x\n"),
   3009                              COMPILER_64_HI(update_array_ptr[taf_gate_id]),
   3010                              COMPILER_64_LO(update_array_ptr[taf_gate_id])));
   3011             }
   3012         } else {
   3013             /* write hw */
   3014             uint64 write_val_after_mask;
   3015 
   3016             COMPILER_64_COPY(write_val_after_mask, write_val);
   3017             COMPILER_64_AND(write_val_after_mask, count_mask64);
   3018             if (COMPILER_64_NE(write_val_after_mask, write_val)) {
   3019                 return BCM_E_PARAM;
   3020             }
   3021             soc_memacc_field64_set(&memacc_count, buffer_ptr,
   3022                                    write_val_after_mask);
   3023             BCM_IF_ERROR_RETURN(
   3024                 soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   3025                               taf_gate_id, buffer_ptr));
   3026 
   3027             /* write sw */
   3028             COMPILER_64_COPY(update_array_ptr[taf_gate_id], write_val);
   3029         }
   3030     }
   3031 
   3032     return BCM_E_NONE;
   3033 }
   3034 
   3035 /* helper function for taf gate counter access */
   3036 STATIC int
   3037 bcmi_gh2_taf_gate_stat_counter_access(
   3038     int unit,
   3039     int taf_gate_id,
   3040     uint32 arr_cnt,
   3041     bcm_tsn_taf_gate_stat_t *stat_type_arr,
   3042     uint64 *stat_value_arr,
   3043     bcmi_tsn_stat_counter_action_t action)
   3044 {
   3045     int arr_idx;
   3046 
   3047     if (NULL == stat_type_arr || NULL == stat_value_arr ||
   3048         taf_gate_id >= BCMI_TSN_TAF_GATE_NUM ||
   3049         taf_gate_id < 0) {
   3050         return BCM_E_PARAM;
   3051     }
   3052 
   3053     for (arr_idx = 0; arr_idx < arr_cnt; arr_idx++) {
   3054         int is_write = 0;
   3055 
   3056         if (stat_type_arr[arr_idx] < 0 ||
   3057             stat_type_arr[arr_idx] >= bcmTsnTafGateStatCount) {
   3058             return BCM_E_PARAM;
   3059         }
   3060 
   3061         /* update taf gate counter for both hw table and sw database */
   3062         switch (action) {
   3063             case bcmiTsnStatCounterActionWrite:
   3064                 is_write = 1;
   3065                 /* fall through */
   3066             case bcmiTsnStatCounterActionReadSync:
   3067                 BCM_IF_ERROR_RETURN(
   3068                     bcmi_gh2_taf_gate_stat_counter_update(
   3069                         unit, taf_gate_id,
   3070                         stat_type_arr[arr_idx], stat_type_arr[arr_idx],
   3071                         is_write, stat_value_arr[arr_idx]));
   3072                 break;
   3073            case bcmiTsnStatCounterActionRead:
   3074                 break;
   3075            default:
   3076                 return BCM_E_INTERNAL;
   3077         }
   3078 
   3079         /* read sw database if need */
   3080         if (bcmiTsnStatCounterActionWrite != action) {
   3081             uint64 *sw_array_ptr =
   3082                 taf_gate_counter[unit][stat_type_arr[arr_idx]];
   3083             COMPILER_64_COPY(stat_value_arr[arr_idx],
   3084                              sw_array_ptr[taf_gate_id]);
   3085         }
   3086     }
   3087 
   3088     return BCM_E_NONE;
   3089 }
   3090 
   3091 /* callback for taf gate counter, just need to update the enabled gate */
   3092 STATIC int
   3093 bcmi_gh2_taf_gate_stat_counter_sync(int unit, int taf_gate_id)
   3094 {
   3095     uint64 value_64_zero;
   3096 
   3097     COMPILER_64_ZERO(value_64_zero);
   3098 
   3099     BCM_IF_ERROR_RETURN(
   3100         bcmi_gh2_taf_gate_stat_counter_update(
   3101             unit, taf_gate_id,
   3102             0, bcmTsnTafGateStatCount -1, 0, value_64_zero));
   3103 
   3104     return BCM_E_NONE;
   3105 }
   3106 
   3107 /* cleanup the resource for TAF */
   3108 STATIC int
   3109 bcmi_gh2_taf_cleanup(int unit)
   3110 {
   3111     int i, j;
   3112     gh2_taf_interrupt_type_t iter;
   3113     bcm_tsn_taf_gate_stat_t stat_type;
   3114 
   3115     /* disable interupt mask */
   3116     for (iter = 0; iter < TafInterruptCount; iter++) {
   3117         soc_reg_field32_modify(
   3118             unit, TAF_MEMFAILINTMASKr, REG_PORT_ANY,
   3119             taf_interrupt_mapping[iter].mask_field, 0);
   3120     }
   3121 
   3122     /* taf gate alloc bitmap */
   3123     if (NULL != taf_gate_bitmap[unit]) {
   3124         shr_res_bitmap_free(taf_gate_bitmap[unit], 1,
   3125                             TAF_GATE_RESERVED_ID);
   3126         shr_res_bitmap_destroy(taf_gate_bitmap[unit]);
   3127         taf_gate_bitmap[unit] = NULL;
   3128     }
   3129 
   3130     /* taf calendar */
   3131     if (NULL != taf_schedule_calendar_buf[unit]) {
   3132         soc_cm_sfree(unit, taf_schedule_calendar_buf[unit]);
   3133         taf_schedule_calendar_buf[unit] = NULL;
   3134     }
   3135 
   3136     for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) {
   3137         bcmi_tsn_taf_schedule_entry_t *entry_iter = NULL;
   3138         bcmi_tsn_taf_schedule_entry_t *entry_next = NULL;
   3139 
   3140         entry_iter = taf_schedule_timeline[unit][i];
   3141         while (entry_iter != NULL) {
   3142             entry_next = entry_iter->next;
   3143             sal_free(entry_iter);
   3144             entry_iter = entry_next;
   3145         }
   3146         taf_schedule_timeline[unit][i] = NULL;
   3147     }
   3148 
   3149     /* taf profile */
   3150     if (NULL != taf_schedule_profile_bitmap[unit]) {
   3151         shr_res_bitmap_destroy(taf_schedule_profile_bitmap[unit]);
   3152         taf_schedule_profile_bitmap[unit] = NULL;
   3153     }
   3154     for (i = 0; i < BCMI_TSN_TAF_PROFILE_NUM_MAX; i++) {
   3155         if (NULL != taf_schedule_profile[unit][i]) {
   3156             sal_free(taf_schedule_profile[unit][i]);
   3157             taf_schedule_profile[unit][i] = NULL;
   3158         }
   3159     }
   3160     /* taf event handler */
   3161     for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) {
   3162         for (j = 0; j < bcmTsnTafEventCount; j++) {
   3163             if (NULL != taf_event_handler_list[unit][i][j]) {
   3164                 bcmi_tsn_taf_event_handler_t *event_handler_iter;
   3165                 bcmi_tsn_taf_event_handler_t *event_handler_next;
   3166 
   3167                 event_handler_iter = taf_event_handler_list[unit][i][j];
   3168                 while (NULL != event_handler_iter) {
   3169                     event_handler_next = event_handler_iter->next;
   3170                     sal_free(event_handler_iter);
   3171                     event_handler_iter = event_handler_next;
   3172                 }
   3173                 taf_event_handler_list[unit][i][j] = NULL;
   3174             }
   3175         }
   3176     }
   3177     /* taf interrupt handler */
   3178     taf_interrupt_handling[unit] = 0;
   3179 
   3180     /* maxbyte profile */
   3181     for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) {
   3182         if (NULL != taf_maxbyte_profile_bitmap[unit][i]) {
   3183             shr_res_bitmap_free(taf_maxbyte_profile_bitmap[unit][i], 1,
   3184                                 TAF_MAXBYTE_PROFILE_RESERVED_ID);
   3185             shr_res_bitmap_destroy(taf_maxbyte_profile_bitmap[unit][i]);
   3186             taf_maxbyte_profile_bitmap[unit][i] = NULL;
   3187         }
   3188     }
   3189 
   3190     /* cosq profile */
   3191     if (NULL != taf_cosq_profile_bitmap[unit]) {
   3192         shr_res_bitmap_free(taf_cosq_profile_bitmap[unit], 1,
   3193                             TAF_COSQ_PROFILE_RESERVED_ID);
   3194         shr_res_bitmap_destroy(taf_cosq_profile_bitmap[unit]);
   3195         taf_cosq_profile_bitmap[unit] = NULL;
   3196     }
   3197 
   3198     /* gate stat */
   3199     for (stat_type = 0; stat_type < bcmTsnTafGateStatCount; stat_type++) {
   3200         if (NULL != taf_gate_counter[unit][stat_type]) {
   3201             sal_free(taf_gate_counter[unit][stat_type]);
   3202             taf_gate_counter[unit][stat_type] = NULL;
   3203         }
   3204         if (NULL != taf_gate_counter_dma_buffer[unit][stat_type]) {
   3205             soc_cm_sfree(unit, taf_gate_counter_dma_buffer[unit][stat_type]);
   3206             taf_gate_counter_dma_buffer[unit][stat_type] = NULL;
   3207         }
   3208     }
   3209 
   3210     return BCM_E_NONE;
   3211 }
   3212 
   3213 /* init the resource for TAF */
   3214 STATIC int
   3215 bcmi_gh2_taf_init(int unit)
   3216 {
   3217     int i, j, entry_count, default_gate, entry_byte, default_profile;
   3218     gh2_taf_interrupt_type_t iter;
   3219     bcm_tsn_taf_gate_stat_t stat_type;
   3220 
   3221     /* taf gate alloc bitmap */
   3222     default_gate = TAF_GATE_RESERVED_ID;
   3223     TAF_INIT_ERROR_RETURN_WITH_CLEAN(
   3224         shr_res_bitmap_create(&taf_gate_bitmap[unit], 0,
   3225                               BCMI_TSN_TAF_GATE_NUM));
   3226     TAF_INIT_ERROR_RETURN_WITH_CLEAN(
   3227         shr_res_bitmap_alloc(taf_gate_bitmap[unit],
   3228                              SHR_RES_BITMAP_ALLOC_WITH_ID, 1, &default_gate));
   3229     for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) {
   3230         taf_gate_refcount[unit][i] = 0;
   3231     }
   3232 
   3233     /* taf primap */
   3234     entry_count = soc_mem_index_count(unit, taf_gate_pri_map_mem);
   3235     if ((TAF_GATE_PRI_MAP_PROFILE_MASK | TAF_GATE_PRI_MAP_INTPRI_MASK |
   3236          TAF_GATE_PRI_MAP_PREEMPT_MASK) >= entry_count) {
   3237         TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL);
   3238     }
   3239 
   3240     /* taf profile */
   3241     TAF_INIT_ERROR_RETURN_WITH_CLEAN(
   3242         shr_res_bitmap_create(&taf_schedule_profile_bitmap[unit],
   3243                               0, BCMI_TSN_TAF_PROFILE_NUM_MAX));
   3244 
   3245     /* taf calendar */
   3246     entry_byte = WORDS2BYTES(
   3247                     soc_mem_entry_words(unit, taf_schedule_calendar_mem[0][0]));
   3248     taf_schedule_calendar_buf[unit] =
   3249         soc_cm_salloc(unit, TAF_SCHEDULE_CALENDAR_ENTIRES * entry_byte,
   3250                       "taf schedule calendar buffer");
   3251     if (NULL == taf_schedule_calendar_buf[unit]) {
   3252         TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL);
   3253     }
   3254 
   3255     /* enable interupt mask */
   3256     for (iter = 0; iter < TafInterruptCount; iter++) {
   3257         soc_reg_field32_modify(
   3258             unit, TAF_MEMFAILINTMASKr, REG_PORT_ANY,
   3259             taf_interrupt_mapping[iter].mask_field, 1);
   3260     }
   3261 
   3262     /* maxbyte profile */
   3263     default_profile = TAF_MAXBYTE_PROFILE_RESERVED_ID;
   3264     for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) {
   3265         uint64 default_value;
   3266         int field_len;
   3267 
   3268         TAF_INIT_ERROR_RETURN_WITH_CLEAN(
   3269             shr_res_bitmap_create(&taf_maxbyte_profile_bitmap[unit][i], 0,
   3270                                   TAF_MAXBYTE_PROFILE_NUM));
   3271         TAF_INIT_ERROR_RETURN_WITH_CLEAN(
   3272             shr_res_bitmap_alloc(taf_maxbyte_profile_bitmap[unit][i],
   3273                                  SHR_RES_BITMAP_ALLOC_WITH_ID, 1,
   3274                                  &default_profile));
   3275         for (j = 0; j < TAF_MAXBYTE_PROFILE_NUM; j++) {
   3276             taf_maxbyte_profile_refcount[unit][i][j] = 0;
   3277         }
   3278 
   3279         /* set default_value to 0xFFFFFFFFF */
   3280         field_len = soc_mem_field_length(
   3281                         unit, taf_maxbyte_profile_mem,
   3282                         taf_maxbyte_profile_field[default_profile]);
   3283         COMPILER_64_SET(default_value, 0, 1);
   3284         COMPILER_64_SHL(default_value, field_len);
   3285         COMPILER_64_SUB_32(default_value, 1);
   3286         TAF_INIT_ERROR_RETURN_WITH_CLEAN(
   3287             _bcmi_gh2_taf_gate_max_bytes_profile_set(
   3288                 unit, i, default_profile, default_value));
   3289     }
   3290 
   3291     /* cosq profile */
   3292     entry_count = soc_mem_index_count(unit, taf_cosq_profile_mem);
   3293     if ((TAF_COSQ_INTPRI_MASK | TAF_COSQ_SELECT_MASK |
   3294          TAF_COSQ_PROFILE_MASK) >= entry_count) {
   3295         TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL);
   3296     }
   3297 
   3298     default_profile = TAF_COSQ_PROFILE_RESERVED_ID;
   3299     TAF_INIT_ERROR_RETURN_WITH_CLEAN(
   3300         shr_res_bitmap_create(&taf_cosq_profile_bitmap[unit], 0,
   3301                               TAF_COSQ_PROFILE_NUM));
   3302     TAF_INIT_ERROR_RETURN_WITH_CLEAN(
   3303         shr_res_bitmap_alloc(taf_cosq_profile_bitmap[unit],
   3304                              SHR_RES_BITMAP_ALLOC_WITH_ID, 1,
   3305                              &default_profile));
   3306     for (i = 0; i < TAF_COSQ_PROFILE_NUM; i++) {
   3307         taf_cosq_profile_refcount[unit][i] = 0;
   3308     }
   3309 
   3310     /* gate stat */
   3311     for (stat_type = 0; stat_type < bcmTsnTafGateStatCount; stat_type++) {
   3312         /* verify memory informaion */
   3313         if (soc_mem_index_count(unit, taf_gate_cnt_mem[stat_type])
   3314             != BCMI_TSN_TAF_GATE_NUM) {
   3315             TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL);
   3316         }
   3317 
   3318         if (!soc_mem_field_valid(unit, taf_gate_cnt_mem[stat_type],
   3319                                  taf_gate_cnt_field[stat_type])) {
   3320             TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL);
   3321         }
   3322 
   3323         /* allocate sw database */
   3324         taf_gate_counter[unit][stat_type] =
   3325                 sal_alloc(BCMI_TSN_TAF_GATE_NUM * sizeof(uint64),
   3326                           "taf gate counter");
   3327         if (NULL == taf_gate_counter[unit][stat_type]) {
   3328             TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   3329         }
   3330 
   3331         taf_gate_counter_dma_buffer[unit][stat_type] =
   3332             soc_cm_salloc(unit, BCMI_TSN_TAF_GATE_NUM *
   3333                           WORDS2BYTES(
   3334                             soc_mem_entry_words(unit,
   3335                                                 taf_gate_cnt_mem[stat_type])),
   3336                           "taf gate counter buffer");
   3337         if (NULL == taf_gate_counter_dma_buffer[unit][stat_type]) {
   3338              TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   3339         }
   3340     }
   3341 
   3342     return BCM_E_NONE;
   3343 }
   3344 
   3345 #if defined(BCM_WARM_BOOT_SUPPORT)
   3346 STATIC int
   3347 bcmi_gh2_taf_get_scache_size(
   3348     int unit, int *size)
   3349 {
   3350     if (NULL == size) {
   3351         return BCM_E_PARAM;
   3352     }
   3353 
   3354     *size = 0;
   3355 
   3356     /* taf gate */
   3357     *size += BCMI_TSN_TAF_GATE_NUM * sizeof(uint32);
   3358 
   3359     /* maxbyte profile */
   3360     *size += BCMI_TSN_TAF_GATE_NUM * TAF_MAXBYTE_PROFILE_NUM * sizeof(uint32);
   3361 
   3362     /* cosq profile */
   3363     *size += TAF_COSQ_PROFILE_NUM * sizeof(uint32);
   3364 
   3365     /* taf schedule timelime
   3366      *    max possible =
   3367      *      total count (32 bit) +
   3368      *          profile_max_num * (gate id (32 bit) + count N (32 bit) +
   3369      *                             basetime (96 bit))
   3370      */
   3371     *size += sizeof(uint32);
   3372     *size += BCMI_TSN_TAF_PROFILE_NUM_MAX * (sizeof(uint32) * 5);
   3373 
   3374     /* taf schedule profile
   3375      *   max possible =
   3376      *      total count (32 bit) +
   3377      *      profile_max_num * (profile id(32 bit) + taf_gate(32 bit) +
   3378      *                         status(32 bit) + config_change_time(96 bit) +
   3379      *                         data + schedule_index(32 bit))
   3380      */
   3381     *size += sizeof(uint32);
   3382     *size += BCMI_TSN_TAF_PROFILE_NUM_MAX *
   3383               (sizeof(uint32) * 7 + sizeof(bcm_tsn_taf_profile_t));
   3384     return BCM_E_NONE;
   3385 }
   3386 
   3387 
   3388 /* sync taf info to scache */
   3389 STATIC int
   3390 bcmi_gh2_taf_sync(
   3391     int unit, uint8 *scache_ptr)
   3392 {
   3393     int conut_schedule, conut_profile, profile_id, schedule_id;
   3394     uint32 gate_id;
   3395     bcmi_tsn_taf_schedule_entry_t *schedule_entry_cache
   3396                                   [BCMI_TSN_TAF_PROFILE_NUM_MAX];
   3397 
   3398     if (NULL == scache_ptr) {
   3399         return BCM_E_PARAM;
   3400     }
   3401     sal_memset(schedule_entry_cache, 0,
   3402                BCMI_TSN_TAF_PROFILE_NUM_MAX *
   3403                sizeof(bcmi_tsn_taf_schedule_entry_t *));
   3404 
   3405     /* taf gate */
   3406     WRITE_PTR_RANGE(scache_ptr, BCMI_TSN_TAF_GATE_NUM * sizeof(uint32),
   3407                     taf_gate_refcount[unit]);
   3408 
   3409     /* maxbyte profile */
   3410     for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) {
   3411         WRITE_PTR_RANGE(scache_ptr, TAF_MAXBYTE_PROFILE_NUM * sizeof(uint32),
   3412                         taf_maxbyte_profile_refcount[unit][gate_id]);
   3413     }
   3414 
   3415     /* cosq profile */
   3416     WRITE_PTR_RANGE(scache_ptr, TAF_COSQ_PROFILE_NUM * sizeof(uint32),
   3417                     taf_cosq_profile_refcount[unit]);
   3418 
   3419     /* taf schedule timelime
   3420      *  Format : count (32 bit) +
   3421      *           [ gate id (32 bit) + count N (32 bit) +
   3422      *             basetime_1(96 bit) + ... + basetime_N(96 bit) ]
   3423      *
   3424      *  ex. gate 1 : basetime_0, basetime_1, basetime_2
   3425      *      gate 3 : basetime_3
   3426      *
   3427      *    ==> In scache:
   3428      *       1 (32 bit)  3 (32 bit)  basetime_1(96 bit)  basetime_2(96 bit)
   3429      *       basetime_3(96 bit)  3 (32 bit)  1 (32 bit)  basetime_4(96 bit)
   3430      *
   3431      *   BTW, we'll have another cache array to record all schedule entries
   3432      */
   3433     conut_schedule = 0;
   3434     for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) {
   3435         if (NULL != taf_schedule_timeline[unit][gate_id]) {
   3436             bcmi_tsn_taf_schedule_entry_t *iter;
   3437 
   3438             iter = taf_schedule_timeline[unit][gate_id];
   3439             while (iter != NULL) {
   3440                 conut_schedule++;
   3441                 iter = iter->next;
   3442             }
   3443         }
   3444     }
   3445 
   3446     WRITE_PTR(scache_ptr, uint32, conut_schedule);
   3447     schedule_id = 0;
   3448     for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) {
   3449         if (NULL != taf_schedule_timeline[unit][gate_id]) {
   3450             uint32 count_per_gate = 0;
   3451             bcmi_tsn_taf_schedule_entry_t *iter;
   3452 
   3453             /* write "gate id" and "count" into scache */
   3454             iter = taf_schedule_timeline[unit][gate_id];
   3455             while (iter != NULL) {
   3456                 count_per_gate++;
   3457                 iter = iter->next;
   3458             }
   3459 
   3460             WRITE_PTR(scache_ptr, uint32, gate_id);
   3461             WRITE_PTR(scache_ptr, uint32, count_per_gate);
   3462 
   3463             /* write each "basetime" into scache */
   3464             iter = taf_schedule_timeline[unit][gate_id];
   3465             while (iter != NULL) {
   3466                 WRITE_PTR(scache_ptr, uint32,
   3467                           COMPILER_64_LO(iter->schedule_time.seconds));
   3468                 WRITE_PTR(scache_ptr, uint32,
   3469                           COMPILER_64_HI(iter->schedule_time.seconds));
   3470                 WRITE_PTR(scache_ptr, uint32,
   3471                           iter->schedule_time.nanoseconds);
   3472 
   3473                 assert(schedule_id < BCMI_TSN_TAF_PROFILE_NUM_MAX);
   3474                 schedule_entry_cache[schedule_id++] = iter;
   3475 
   3476                 iter = iter->next;
   3477             }
   3478         }
   3479     }
   3480 
   3481     /* taf schedule profile
   3482      *  Format : count (32 bit) +
   3483      *           [ profile id (32 bit) + taf_gate (32 bit) + status (32 bit) +
   3484      *             config_change_time(96 bit) +
   3485      *             data(bcm_tsn_taf_profile_t) + schedule_entry index (32 bit) ]
   3486      *
   3487      *  ex. profile 0 : schedule = NULL
   3488      *      profile 1 : schedule = basetime_2
   3489      *      profile 2 : schedule = basetime_3
   3490      *      profile 4 : schedule = NULL
   3491      *      profile 6 : schedule = basetime_1
   3492      *      profile 7 : schedule = basetime_0
   3493      *
   3494      *    ==> In scache:
   3495      *       6 (32 bit)
   3496      *       0 (32 bit)  taf_gate  status  data  -1(32 bit)
   3497      *       1 (32 bit)  taf_gate  status  data  2(32 bit)
   3498      *       2 (32 bit)  taf_gate  status  data  3(32 bit)
   3499      *       4 (32 bit)  taf_gate  status  data  -1(32 bit)
   3500      *       6 (32 bit)  taf_gate  status  data  1(32 bit)
   3501      *       7 (32 bit)  taf_gate  status  data  0(32 bit)
   3502      */
   3503     conut_profile = 0;
   3504     for (profile_id = 0; profile_id < BCMI_TSN_TAF_PROFILE_NUM_MAX;
   3505          profile_id++) {
   3506         if (NULL != taf_schedule_profile[unit][profile_id]) {
   3507             conut_profile++;
   3508         }
   3509     }
   3510 
   3511     WRITE_PTR(scache_ptr, uint32, conut_profile);
   3512 
   3513     for (profile_id = 0; profile_id < BCMI_TSN_TAF_PROFILE_NUM_MAX;
   3514          profile_id++) {
   3515         bcmi_tsn_taf_profile_t *iter = taf_schedule_profile[unit][profile_id];
   3516 
   3517         if (NULL == iter) {
   3518            continue;
   3519         }
   3520 
   3521         WRITE_PTR(scache_ptr, uint32, profile_id);
   3522         WRITE_PTR(scache_ptr, uint32, (uint32)(iter->taf_gate));
   3523         WRITE_PTR(scache_ptr, uint32, (uint32)(iter->status));
   3524         WRITE_PTR(scache_ptr, uint32,
   3525                   COMPILER_64_LO(iter->config_change_time.seconds));
   3526         WRITE_PTR(scache_ptr, uint32,
   3527                   COMPILER_64_HI(iter->config_change_time.seconds));
   3528         WRITE_PTR(scache_ptr, uint32,
   3529                   iter->config_change_time.nanoseconds);
   3530         WRITE_PTR_RANGE(scache_ptr, sizeof(bcm_tsn_taf_profile_t),
   3531                         &(iter->data));
   3532 
   3533         if (NULL == iter->schedule) {
   3534             WRITE_PTR(scache_ptr, uint32, (uint32)-1);
   3535         } else {
   3536             /* search the index */
   3537             int found = -1;
   3538 
   3539             for (schedule_id = 0; schedule_id < conut_schedule; schedule_id++) {
   3540                 if (schedule_entry_cache[schedule_id] == iter->schedule) {
   3541                     found = schedule_id;
   3542                     break;
   3543                 }
   3544             }
   3545             if (-1 == found) {
   3546                 return BCM_E_INTERNAL; /* should not happen */
   3547             }
   3548 
   3549             WRITE_PTR(scache_ptr, uint32, found);
   3550         }
   3551     }
   3552 
   3553     return BCM_E_NONE;
   3554 }
   3555 
   3556 /* restore taf info from scache and hw */
   3557 STATIC int
   3558 bcmi_gh2_taf_reload(
   3559     int unit, uint8 *scache_ptr)
   3560 {
   3561     int gate_id, profile_id, entry_index, schedule_id;
   3562     uint32 conut_schedule, conut_profile;
   3563     bcmi_tsn_taf_schedule_entry_t *schedule_entry_cache
   3564                                   [BCMI_TSN_TAF_PROFILE_NUM_MAX];
   3565 
   3566     if (NULL == scache_ptr) {
   3567         return BCM_E_PARAM;
   3568     }
   3569     sal_memset(schedule_entry_cache, 0,
   3570                BCMI_TSN_TAF_PROFILE_NUM_MAX *
   3571                sizeof(bcmi_tsn_taf_schedule_entry_t *));
   3572 
   3573     /* taf gate */
   3574     READ_PTR_RANGE(scache_ptr, BCMI_TSN_TAF_GATE_NUM * sizeof(uint32),
   3575                    taf_gate_refcount[unit]);
   3576 
   3577     for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) {
   3578         if (taf_gate_refcount[unit][gate_id] != 0) {
   3579             BCM_IF_ERROR_RETURN(
   3580                 shr_res_bitmap_alloc(taf_gate_bitmap[unit],
   3581                                      SHR_RES_BITMAP_ALLOC_WITH_ID,
   3582                                      1, (int *)&gate_id));
   3583         }
   3584     }
   3585 
   3586     /* maxbyte profile */
   3587     for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) {
   3588         READ_PTR_RANGE(scache_ptr, TAF_MAXBYTE_PROFILE_NUM * sizeof(uint32),
   3589                        taf_maxbyte_profile_refcount[unit][gate_id]);
   3590 
   3591         for (profile_id = 0; profile_id < TAF_MAXBYTE_PROFILE_NUM;
   3592              profile_id++) {
   3593             if (taf_maxbyte_profile_refcount[unit][gate_id][profile_id] != 0) {
   3594                 BCM_IF_ERROR_RETURN(
   3595                     shr_res_bitmap_alloc(
   3596                         taf_maxbyte_profile_bitmap[unit][gate_id],
   3597                          SHR_RES_BITMAP_ALLOC_WITH_ID, 1, (int *)&profile_id));
   3598             }
   3599         }
   3600     }
   3601 
   3602     /* cosq profile */
   3603     READ_PTR_RANGE(scache_ptr, TAF_COSQ_PROFILE_NUM * sizeof(uint32),
   3604                    taf_cosq_profile_refcount[unit]);
   3605 
   3606     for (profile_id = 0; profile_id < TAF_COSQ_PROFILE_NUM; profile_id++) {
   3607         if (taf_cosq_profile_refcount[unit][profile_id] != 0) {
   3608             BCM_IF_ERROR_RETURN(
   3609                 shr_res_bitmap_alloc(taf_cosq_profile_bitmap[unit],
   3610                                      SHR_RES_BITMAP_ALLOC_WITH_ID,
   3611                                      1, (int *)&profile_id));
   3612         }
   3613     }
   3614 
   3615     /* taf schedule timelime
   3616      *  Format : count (32 bit) +
   3617      *           [ gate id (32 bit) + count N (32 bit) +
   3618      *             basetime_1(96 bit) + ... + basetime_N(96 bit) ]
   3619      */
   3620     schedule_id = 0;
   3621     READ_PTR(scache_ptr, uint32, conut_schedule);
   3622     while (schedule_id < conut_schedule) {
   3623         int i;
   3624         uint32 gate_id, count_per_gate;
   3625         uint32 sec_lo, sec_hi;
   3626         bcmi_tsn_taf_schedule_entry_t *entry_tail = NULL;
   3627 
   3628         READ_PTR(scache_ptr, uint32, gate_id);
   3629         READ_PTR(scache_ptr, uint32, count_per_gate);
   3630         entry_tail = taf_schedule_timeline[unit][gate_id];
   3631 
   3632         for (i = 0; i < count_per_gate; i++) {
   3633             bcmi_tsn_taf_schedule_entry_t *entry_new = NULL;
   3634 
   3635             if (schedule_id >= conut_schedule) {
   3636                 return BCM_E_INTERNAL; /* should not happen */
   3637             }
   3638 
   3639             entry_new = sal_alloc(sizeof(bcmi_tsn_taf_schedule_entry_t),
   3640                         "TAF schedule entry");
   3641             if (NULL == entry_new) {
   3642                 return BCM_E_MEMORY;
   3643             }
   3644 
   3645             READ_PTR(scache_ptr, uint32, sec_lo);
   3646             READ_PTR(scache_ptr, uint32, sec_hi);
   3647             READ_PTR(scache_ptr, uint32, entry_new->schedule_time.nanoseconds);
   3648             COMPILER_64_SET(entry_new->schedule_time.seconds, sec_hi, sec_lo);
   3649 
   3650             if (NULL == entry_tail) {
   3651                 /* this the first entry */
   3652                 entry_new->prev = NULL;
   3653                 entry_new->next = NULL;
   3654                 taf_schedule_timeline[unit][gate_id] = entry_new;
   3655             } else {
   3656                 /* add new entry at the tail */
   3657                 entry_tail->next = entry_new;
   3658                 entry_new->prev = entry_tail;
   3659                 entry_new->next = NULL;
   3660             }
   3661             entry_tail = entry_new;
   3662 
   3663             /* cache this new entry, then ready to process the next one */
   3664             schedule_entry_cache[schedule_id] = entry_new;
   3665             schedule_id++;
   3666         }
   3667     }
   3668 
   3669     /* taf schedule profile
   3670      *  Format : count (32 bit) +
   3671      *           [ profile id (32 bit) + taf_gate (32 bit) + status (32 bit) +
   3672      *             config_change_time(96 bit) +
   3673      *             data(bcm_tsn_taf_profile_t) + schedule_entry index (32 bit) ]
   3674      */
   3675     entry_index = 0;
   3676     READ_PTR(scache_ptr, uint32, conut_profile);
   3677     for (entry_index = 0; entry_index < conut_profile; entry_index++) {
   3678         uint32 profile_id;
   3679         bcmi_tsn_taf_profile_t *new_profile = NULL;
   3680         uint32 sec_lo, sec_hi;
   3681 
   3682         READ_PTR(scache_ptr, uint32, profile_id);
   3683 
   3684         new_profile = sal_alloc(sizeof(bcmi_tsn_taf_profile_t), "TAF profile");
   3685         if (NULL == new_profile) {
   3686             return BCM_E_MEMORY;
   3687         }
   3688         taf_schedule_profile[unit][profile_id] = new_profile;
   3689 
   3690         BCM_IF_ERROR_RETURN(
   3691             shr_res_bitmap_alloc(
   3692                 taf_schedule_profile_bitmap[unit],
   3693                 SHR_RES_BITMAP_ALLOC_WITH_ID, 1, (int *)&profile_id));
   3694 
   3695         /* recover taf_gate, status, config_change_time, data */
   3696         READ_PTR(scache_ptr, uint32, new_profile->taf_gate);
   3697         READ_PTR(scache_ptr, uint32, new_profile->status);
   3698         READ_PTR(scache_ptr, uint32, sec_lo);
   3699         READ_PTR(scache_ptr, uint32, sec_hi);
   3700         READ_PTR(scache_ptr, uint32,
   3701                  new_profile->config_change_time.nanoseconds);
   3702         COMPILER_64_SET(new_profile->config_change_time.seconds,
   3703                         sec_hi, sec_lo);
   3704         READ_PTR_RANGE(scache_ptr, sizeof(bcm_tsn_taf_profile_t),
   3705                        &(new_profile->data));
   3706 
   3707         /* recover schedule entry */
   3708         READ_PTR(scache_ptr, uint32, schedule_id);
   3709         if (schedule_id == (uint32)-1) {
   3710             new_profile->schedule = NULL;
   3711         } else {
   3712             if (schedule_id >= conut_schedule) {
   3713                 return BCM_E_INTERNAL; /* should not happen */
   3714             }
   3715             if (NULL == schedule_entry_cache[schedule_id]) {
   3716                 return BCM_E_INTERNAL; /* should not happen */
   3717             }
   3718             new_profile->schedule = schedule_entry_cache[schedule_id];
   3719             new_profile->schedule->taf_profile = new_profile;
   3720         }
   3721     }
   3722 
   3723     return BCM_E_NONE;
   3724 }
   3725 #endif /* BCM_WARM_BOOT_SUPPORT */
   3726 
   3727 
   3728 /* Per-chip TAF device info */
   3729 STATIC const bcmi_tsn_taf_dev_info_t gh2_taf_devinfo = {
   3730     /* function set */
   3731     bcmi_gh2_taf_init,
   3732     bcmi_gh2_taf_cleanup,
   3733     bcmi_gh2_taf_gate_create,
   3734     bcmi_gh2_taf_gate_traverse,
   3735     bcmi_gh2_taf_gate_destroy,
   3736     bcmi_gh2_taf_gate_check,
   3737     bcmi_gh2_taf_gate_status_get,
   3738     bcmi_gh2_taf_global_control_get,
   3739     bcmi_gh2_taf_global_control_set,
   3740     bcmi_gh2_taf_port_control_get,
   3741     bcmi_gh2_taf_port_control_set,
   3742     bcmi_gh2_taf_gate_control_get,
   3743     bcmi_gh2_taf_gate_control_set,
   3744     bcmi_gh2_taf_gate_pri_map_set,
   3745     bcmi_gh2_taf_gate_pri_map_get,
   3746     bcmi_gh2_taf_gate_pri_map_delete,
   3747     bcmi_gh2_taf_calendar_param_check,
   3748     bcmi_gh2_taf_calendar_resource_alloc,
   3749     bcmi_gh2_taf_calendar_resource_free,
   3750     bcmi_gh2_taf_calendar_kickoff,
   3751     bcmi_gh2_taf_calendar_profile_create,
   3752     bcmi_gh2_taf_calendar_profile_get,
   3753     bcmi_gh2_taf_calendar_profile_destroy,
   3754     bcmi_gh2_taf_calendar_profile_traverse,
   3755     bcmi_gh2_taf_schedule_insert,
   3756     bcmi_gh2_taf_schedule_remove,
   3757     bcmi_gh2_taf_schedule_pick,
   3758     bcmi_gh2_taf_schedule_exist,
   3759     bcmi_gh2_taf_schedule_get,
   3760     bcmi_gh2_taf_event_register,
   3761     bcmi_gh2_taf_event_unregister,
   3762     bcmi_gh2_taf_event_notify,
   3763     bcmi_gh2_taf_interrupt_handle_start,
   3764     bcmi_gh2_taf_interrupt_handle_tod,
   3765     bcmi_gh2_taf_interrupt_handle_switch,
   3766     bcmi_gh2_taf_interrupt_handle_error,
   3767     bcmi_gh2_taf_interrupt_handle_user_cb,
   3768     bcmi_gh2_taf_interrupt_handle_finish,
   3769     bcmi_gh2_taf_gate_max_bytes_profile_create,
   3770     bcmi_gh2_taf_gate_max_bytes_profile_set,
   3771     bcmi_gh2_taf_gate_max_bytes_profile_get,
   3772     bcmi_gh2_taf_gate_max_bytes_profile_destroy,
   3773     bcmi_gh2_taf_gate_max_bytes_profile_traverse,
   3774     bcmi_gh2_taf_cosq_mapping_profile_create,
   3775     bcmi_gh2_taf_cosq_mapping_profile_set,
   3776     bcmi_gh2_taf_cosq_mapping_profile_get,
   3777     bcmi_gh2_taf_cosq_mapping_profile_destroy,
   3778     bcmi_gh2_taf_cosq_mapping_profile_traverse,
   3779     bcmi_gh2_taf_gate_stat_counter_sync,
   3780     bcmi_gh2_taf_gate_stat_counter_access,
   3781 #if defined(BCM_WARM_BOOT_SUPPORT)
   3782     bcmi_gh2_taf_get_scache_size,
   3783     bcmi_gh2_taf_sync,
   3784     bcmi_gh2_taf_reload,
   3785 #endif /* BCM_WARM_BOOT_SUPPORT */
   3786     /* data set */
   3787     TAF_GATE_PRI_MAP_PROFILE_NUM, /* exclude invalid index 0 */
   3788     TAF_GATE_PRI_MAP_INTPRI_NUM
   3789 };
   3790 
   3791 /*
   3792  * Function:
   3793  *    bcmi_gh2_taf_info_init
   3794  * Description:
   3795  *    Setup the chip specific info for TAF.
   3796  * Parameters:
   3797  *    unit - (IN) Unit number
   3798  *    devinfo - (OUT) device info structure.
   3799  * Returns:
   3800  *    BCM_E_XXX
   3801  */
   3802 int
   3803 bcmi_gh2_taf_info_init(
   3804     int unit,
   3805     const bcmi_tsn_taf_dev_info_t **devinfo)
   3806 {
   3807     int rv = BCM_E_NONE;
   3808 
   3809     if (devinfo == NULL) {
   3810         return BCM_E_PARAM;
   3811     }
   3812 
   3813     /* Return the chip info structure for TSN stat */
   3814     *devinfo = &gh2_taf_devinfo;
   3815 
   3816     return rv;
   3817 }
   3818 #endif /* BCM_TSN_SUPPORT */