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

avs.c (132579B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        avs.c
      8  * Purpose:
      9  * Requires:
     10  */
     11 #include <shared/bsl.h>
     12 
     13 #ifdef  INCLUDE_AVS
     14 #include <soc/avs.h>
     15 #include <soc/i2c.h>
     16 
     17 #define AVS_LEGACY_THRESHOLD   (0)  /* Adopt the original threshold algorithm*/
     18 
     19 static soc_avs_control_t *soc_avs_ctrl[SOC_MAX_NUM_DEVICES];
     20 static soc_avs_functions_t *soc_avs_functions[SOC_MAX_NUM_DEVICES] = {NULL};
     21 static soc_avs_vrm_access_t *soc_vrm_access_functions[SOC_MAX_NUM_DEVICES] = {NULL};
     22 static uint32 _soc_last_set_voltage[SOC_MAX_NUM_DEVICES];
     23 
     24 
     25 static int _cent_freq_thr[] = {
     26      27368.00,    /* CENT_FREQ_THRESHOLD_0 */
     27      23800.00,    /* CENT_FREQ_THRESHOLD_1 */
     28      19704.00,    /* CENT_FREQ_THRESHOLD_2 */
     29      11384.50,    /* CENT_FREQ_THRESHOLD_3 */
     30      37474.00,    /* CENT_FREQ_THRESHOLD_4 */
     31      32060.50,    /* CENT_FREQ_THRESHOLD_5 */
     32      26603.00,    /* CENT_FREQ_THRESHOLD_6 */
     33      15597.00,    /* CENT_FREQ_THRESHOLD_7 */
     34     105960.00,    /* CENT_FREQ_THRESHOLD_8 */
     35      89260.00,    /* CENT_FREQ_THRESHOLD_9 */
     36      75010.00,    /* CENT_FREQ_THRESHOLD_10*/
     37      42939.00,    /* CENT_FREQ_THRESHOLD_11*/
     38      77610.00,    /* CENT_FREQ_THRESHOLD_12*/
     39      63710.00,    /* CENT_FREQ_THRESHOLD_13*/
     40      52685.00,    /* CENT_FREQ_THRESHOLD_14*/
     41      29877.50,    /* CENT_FREQ_THRESHOLD_15*/
     42      73335.00,    /* CENT_FREQ_THRESHOLD_16*/
     43      58880.00,    /* CENT_FREQ_THRESHOLD_17*/
     44      50385.00,    /* CENT_FREQ_THRESHOLD_18*/
     45      29011.50,    /* CENT_FREQ_THRESHOLD_19*/
     46      43638.00,    /* CENT_FREQ_THRESHOLD_20*/
     47      35133.50,    /* CENT_FREQ_THRESHOLD_21*/
     48      30099.00,    /* CENT_FREQ_THRESHOLD_22*/
     49      17083.00,    /* CENT_FREQ_THRESHOLD_23*/
     50      08787.00,    /* CENT_FREQ_THRESHOLD_24*/
     51      07574.50,    /* CENT_FREQ_THRESHOLD_25*/
     52      06485.00,    /* CENT_FREQ_THRESHOLD_26*/
     53      05713.50,    /* CENT_FREQ_THRESHOLD_27*/
     54      05986.00,    /* CENT_FREQ_THRESHOLD_28*/
     55      07330.50,    /* CENT_FREQ_THRESHOLD_29*/
     56      03933.15,    /* CENT_FREQ_THRESHOLD_30*/
     57      04304.60,    /* CENT_FREQ_THRESHOLD_31*/
     58      01610.80,    /* CENT_FREQ_THRESHOLD_32*/
     59      01273.10,    /* CENT_FREQ_THRESHOLD_33*/
     60      01610.80,    /* CENT_FREQ_THRESHOLD_34*/
     61      01273.10,    /* CENT_FREQ_THRESHOLD_35*/
     62 };
     63 
     64 static int _rmt_freq_thr[] = {
     65     23800.00,    /* RMT_FREQ_THRESHOLD_GS */
     66     11384.50,     /* RMT_FREQ_THRESHOLD_GH */
     67 };
     68 
     69 
     70 static int _cent_fth_slope[] = {
     71      72120,     /* CENT_FREQ_THRESHOLD_SLOPE_0 */
     72      82720,     /* CENT_FREQ_THRESHOLD_SLOPE_1 */
     73      71370,     /* CENT_FREQ_THRESHOLD_SLOPE_2 */
     74      66720,     /* CENT_FREQ_THRESHOLD_SLOPE_3 */
     75      97800,     /* CENT_FREQ_THRESHOLD_SLOPE_4 */
     76     109680,     /* CENT_FREQ_THRESHOLD_SLOPE_5 */
     77      94700,     /* CENT_FREQ_THRESHOLD_SLOPE_6 */
     78      89820,     /* CENT_FREQ_THRESHOLD_SLOPE_7 */
     79     277250,     /* CENT_FREQ_THRESHOLD_SLOPE_8 */
     80     301000,     /* CENT_FREQ_THRESHOLD_SLOPE_9 */
     81     269500,     /* CENT_FREQ_THRESHOLD_SLOPE_10*/
     82     245600,     /* CENT_FREQ_THRESHOLD_SLOPE_11*/
     83     214250,     /* CENT_FREQ_THRESHOLD_SLOPE_12*/
     84     231250,     /* CENT_FREQ_THRESHOLD_SLOPE_13*/
     85     201250,     /* CENT_FREQ_THRESHOLD_SLOPE_14*/
     86     180750,     /* CENT_FREQ_THRESHOLD_SLOPE_15*/
     87     205000,     /* CENT_FREQ_THRESHOLD_SLOPE_16*/
     88     216000,     /* CENT_FREQ_THRESHOLD_SLOPE_17*/
     89     189500,     /* CENT_FREQ_THRESHOLD_SLOPE_18*/
     90     172500,     /* CENT_FREQ_THRESHOLD_SLOPE_19*/
     91     122980,     /* CENT_FREQ_THRESHOLD_SLOPE_20*/
     92     128750,     /* CENT_FREQ_THRESHOLD_SLOPE_21*/
     93     114080,     /* CENT_FREQ_THRESHOLD_SLOPE_22*/
     94     101950,     /* CENT_FREQ_THRESHOLD_SLOPE_23*/
     95      28500,     /* CENT_FREQ_THRESHOLD_SLOPE_24*/
     96      29300,     /* CENT_FREQ_THRESHOLD_SLOPE_25*/
     97      34480,     /* CENT_FREQ_THRESHOLD_SLOPE_26*/
     98      32700,     /* CENT_FREQ_THRESHOLD_SLOPE_27*/
     99      33080,     /* CENT_FREQ_THRESHOLD_SLOPE_28*/
    100      33650,     /* CENT_FREQ_THRESHOLD_SLOPE_29*/
    101      32190,     /* CENT_FREQ_THRESHOLD_SLOPE_30*/
    102      35620,     /* CENT_FREQ_THRESHOLD_SLOPE_31*/
    103       7660,     /* CENT_FREQ_THRESHOLD_SLOPE_32*/
    104       5490,     /* CENT_FREQ_THRESHOLD_SLOPE_33*/
    105       8670,     /* CENT_FREQ_THRESHOLD_SLOPE_34*/
    106       7290,     /* CENT_FREQ_THRESHOLD_SLOPE_35*/
    107 };
    108 
    109 int
    110 soc_avs_inited(int unit)
    111 {
    112     if (!SOC_UNIT_VALID(unit)) {
    113         return(0);
    114     }
    115     if (SOC_AVS_CONTROL(unit) == NULL) {
    116         return (0);
    117     }
    118     return ((SOC_AVS_CONTROL(unit)->flags & SOC_AVS_F_INITED) != 0);
    119 }
    120 
    121 int
    122 soc_avs_track_inited(int unit)
    123 {
    124     if (!SOC_UNIT_VALID(unit)) {
    125         return(0);
    126     }
    127     if (SOC_AVS_CONTROL(unit) == NULL) {
    128         return (0);
    129     }
    130     return ((SOC_AVS_CONTROL(unit)->flags & SOC_AVS_F_TRACK_INITED) != 0);
    131 }
    132 #ifdef BCM_SBUSDMA_SUPPORT
    133 STATIC sbusdma_desc_handle_t
    134        _soc_avs_rosc_handles[SOC_MAX_NUM_DEVICES][SOC_AVS_ROSC_TYPE_ALL];
    135 
    136 void
    137 _soc_sbusdma_avs_cb(int unit, int status, sbusdma_desc_handle_t handle,
    138                     void *data)
    139 {
    140     soc_avs_control_t *avs;
    141     int i;
    142 
    143     avs = SOC_AVS_CONTROL(unit);
    144 
    145     if (status == SOC_E_NONE) {
    146         if(PTR_TO_INT(data) == SOC_AVS_ROSC_TYPE_REMOTE){
    147             avs->rmt_rosc_count_sync = 1;
    148         }
    149         if(PTR_TO_INT(data) == SOC_AVS_ROSC_TYPE_CENTRAL){
    150             avs->cent_rosc_count_sync= 1;
    151         }
    152     } else {
    153         LOG_ERROR(BSL_LS_SOC_AVS,
    154                   (BSL_META_U(unit,
    155                               "avs ROSC count SBUSDMA failed: type %d\n"),
    156                    PTR_TO_INT(data)));
    157         if (status == SOC_E_TIMEOUT) {
    158             (void)soc_sbusdma_desc_delete(unit, handle);
    159             for (i = 0; i < SOC_AVS_ROSC_TYPE_ALL; i++) {
    160                 if (_soc_avs_rosc_handles[unit][i] == handle) {
    161                     _soc_avs_rosc_handles[unit][i] = 0;
    162                     break;
    163                 }
    164             }
    165         }
    166     }
    167 }
    168 
    169 int
    170 _soc_avs_sbusdma_run(int unit, int type)
    171 {
    172     int ret=SOC_E_NONE;
    173     sal_usecs_t dma_timeout = 1000000;
    174     int  timer_started = 0;
    175     soc_timeout_t       to;
    176 
    177     do{
    178         ret = soc_sbusdma_desc_run(unit, _soc_avs_rosc_handles[unit][type]);
    179         if ((ret == SOC_E_BUSY) || (ret == SOC_E_INIT)) {
    180             if (ret == SOC_E_INIT) {
    181                 break;
    182             }
    183             /* timeout if sbus dma has been busy for too long. */
    184             if (!timer_started) {
    185                 soc_timeout_init(&to, 2 * dma_timeout, 0);
    186                 timer_started = 1;
    187             }
    188             if (soc_timeout_check(&to)) {
    189                 LOG_WARN(BSL_LS_SOC_AVS,
    190                          (BSL_META_U(unit,
    191                                      "sbusdma desc run operation timeout\n")));
    192                 break;
    193             }
    194             sal_usleep(10);
    195         }
    196     } while ((ret == SOC_E_BUSY) || (ret == SOC_E_INIT));
    197 
    198     return ret;
    199 }
    200 
    201 int
    202 soc_avs_sbusdma_desc_setup(int unit)
    203 {
    204     soc_sbusdma_desc_ctrl_t ctrl;
    205     soc_sbusdma_desc_cfg_t cfg;
    206     uint32 *buff;
    207     int alloc_size;
    208     uint8 cent_acc_type, rmt_acc_type;
    209     int cent_blkoff, rmt_blkoff;
    210     soc_reg_t cent_reg, rmt_reg;
    211     uint32 cent_addr, rmt_addr;
    212     soc_avs_control_t *avs;
    213     soc_avs_info_t  *avs_info;
    214 
    215     avs = SOC_AVS_CONTROL(unit);
    216     avs_info = SOC_AVS_INFO(unit);
    217 
    218     /* allocate memory */
    219     alloc_size = (avs_info->num_centrals + avs_info->num_remotes) *
    220                 sizeof(uint32);
    221     if ((buff = (uint32 *)soc_cm_salloc(unit, alloc_size,
    222                                         "Storage for _soc_avs_osc_count dma"))
    223                                         == NULL) {
    224         return (SOC_E_MEMORY);
    225     }
    226     sal_memset(buff, 0, alloc_size);
    227     avs->cent_desc_buff = buff;
    228     avs->rmt_desc_buff = &buff[avs_info->num_centrals];
    229 
    230     cent_reg = avs_info->cen_osc_reg;
    231     rmt_reg = avs_info->rmt_osc_reg;
    232 
    233     if (!SOC_REG_IS_VALID(unit, cent_reg) ||
    234         !SOC_REG_IS_VALID(unit, rmt_reg)) {
    235         return (SOC_E_INTERNAL);
    236     }
    237 
    238     cent_addr = soc_reg_addr_get(unit, cent_reg, REG_PORT_ANY, 0,
    239                                  SOC_REG_ADDR_OPTION_NONE,
    240                                  &cent_blkoff, &cent_acc_type);
    241 
    242     rmt_addr = soc_reg_addr_get(unit, rmt_reg, REG_PORT_ANY, 0,
    243                                 SOC_REG_ADDR_OPTION_NONE,
    244                                 &rmt_blkoff, &rmt_acc_type);
    245 
    246     /* central */
    247     sal_memset(&ctrl, 0, sizeof(soc_sbusdma_desc_ctrl_t));
    248     sal_memset(&cfg, 0, sizeof(soc_sbusdma_desc_cfg_t));
    249     ctrl.flags = 0;
    250     ctrl.cfg_count = 1;
    251     ctrl.buff = avs->cent_desc_buff;
    252     ctrl.cb = _soc_sbusdma_avs_cb;
    253     ctrl.data = INT_TO_PTR(SOC_AVS_ROSC_TYPE_CENTRAL);
    254     sal_strncpy(ctrl.name, "CROSC COUNTERS", sizeof(ctrl.name)-1);
    255     cfg.acc_type = cent_acc_type;
    256     cfg.blk = cent_blkoff;
    257     cfg.addr = cent_addr;
    258     cfg.width = SOC_REG_IS_64(unit, cent_reg) ? 2 : 1;
    259     cfg.count = avs_info->num_centrals;
    260     cfg.addr_shift = 10;
    261     SOC_AVS_FREE_IF_ERROR_RETURN
    262         (soc_sbusdma_desc_create(unit, &ctrl, &cfg,
    263                                  &_soc_avs_rosc_handles[unit][SOC_AVS_ROSC_TYPE_CENTRAL]),
    264                                  buff);
    265 
    266     /* remote */
    267     sal_memset(&ctrl, 0, sizeof(soc_sbusdma_desc_ctrl_t));
    268     sal_memset(&cfg, 0, sizeof(soc_sbusdma_desc_cfg_t));
    269     ctrl.flags = 0;
    270     ctrl.cfg_count = 1;
    271     ctrl.buff = avs->rmt_desc_buff;
    272     ctrl.cb = _soc_sbusdma_avs_cb;
    273     ctrl.data = INT_TO_PTR(SOC_AVS_ROSC_TYPE_REMOTE);
    274     sal_strncpy(ctrl.name, "RROSC COUNTERS", sizeof(ctrl.name)-1);
    275     cfg.acc_type = rmt_acc_type;
    276     cfg.blk = rmt_blkoff;
    277     cfg.addr = rmt_addr;
    278     cfg.width = SOC_REG_IS_64(unit, rmt_reg) ? 2 : 1;
    279     cfg.count = avs_info->num_remotes;
    280     cfg.addr_shift = 8;
    281     SOC_AVS_FREE_IF_ERROR_RETURN
    282         (soc_sbusdma_desc_create(unit, &ctrl, &cfg,
    283                                  &_soc_avs_rosc_handles[unit][SOC_AVS_ROSC_TYPE_REMOTE]),
    284                                  buff);
    285 
    286     avs->rmt_rosc_count_sync = 0;
    287     avs->cent_rosc_count_sync = 0;
    288 
    289     return SOC_E_NONE;
    290 }
    291 int
    292 soc_avs_sbusdma_desc_free(int unit)
    293 {
    294     uint8 i, state = 0;
    295     int ret, err = 0;
    296     soc_avs_control_t *avs;
    297 
    298     avs = SOC_AVS_CONTROL(unit);
    299 
    300     if (avs->cent_desc_buff != NULL) {
    301         soc_cm_sfree(unit, avs->cent_desc_buff);
    302         avs->cent_desc_buff = NULL;
    303         avs->rmt_desc_buff = NULL;
    304     }
    305     avs->cent_rosc_count_sync = 0;
    306     avs->rmt_rosc_count_sync = 0;
    307 
    308     for (i = 0; i < SOC_AVS_ROSC_TYPE_ALL; i++) {
    309         if (_soc_avs_rosc_handles[unit][i]) {
    310             do {
    311                 (void)soc_sbusdma_desc_get_state(unit,
    312                                                  _soc_avs_rosc_handles[unit][i],
    313                                                  &state);
    314                 if (state) {
    315                     sal_usleep(10);
    316                 }
    317             } while (state);
    318             ret = soc_sbusdma_desc_delete(unit,
    319                                           _soc_avs_rosc_handles[unit][i]);
    320             if (ret) {
    321                 err++;
    322             }
    323             _soc_avs_rosc_handles[unit][i] = 0;
    324         }
    325     }
    326     return err;
    327 }
    328 #endif
    329 
    330 /*
    331  * Function:
    332  *  _soc_avs_xbmp_check
    333  * Purpose:
    334  *  Check if the index of the ROSC in exclude bitmap or not
    335  * Parameters:
    336  *  type - (IN)SOC_AVS_ROSC_TYPE_REMOTE or SOC_AVS_ROSC_TYPE_CENTRAL
    337  *  index - (IN) index of ROSC
    338  * Returns:
    339  *  SOC_AVS_BOOL_TRUE  :the index should be exclude in the process
    340  *  SOC_AVS_BOOL_FALSE :the index should be used in the process
    341  */
    342 STATIC int
    343 _soc_avs_xbmp_check(int unit, int type, int index)
    344 {
    345     if (type == SOC_AVS_ROSC_TYPE_REMOTE) {
    346         return SOC_AVS_OSC_EXCLUDED(index,
    347             SOC_AVS_XBMP(unit)->rmt_xbmp[index/NUM_BITS_PER_XBMP] |
    348             SOC_AVS_INFO(unit)->rmt_xbmp[index/NUM_BITS_PER_XBMP]);
    349     }
    350     if (type == SOC_AVS_ROSC_TYPE_CENTRAL) {
    351         return SOC_AVS_OSC_EXCLUDED(index,
    352             SOC_AVS_XBMP(unit)->cent_xbmp[index/NUM_BITS_PER_XBMP] |
    353             SOC_AVS_INFO(unit)->cent_xbmp[index/NUM_BITS_PER_XBMP]);
    354     }
    355     return SOC_AVS_BOOL_TRUE;
    356 
    357 }
    358 
    359 int
    360 soc_avs_ioctl(int unit, soc_avs_ioctl_t opcode, void* data, int len)
    361 {
    362 
    363     if (!soc_avs_inited(unit)) {
    364         return SOC_E_INIT;
    365     }
    366 
    367     if ((SOC_AVS_FUNCTIONS(unit) != NULL) &&
    368         (SOC_AVS_FUNCTIONS(unit)->ioctl != NULL)) {
    369         return SOC_AVS_FUNCTIONS(unit)->ioctl(unit, opcode, data, len);
    370     }
    371     return (SOC_E_UNAVAIL);
    372 
    373 }
    374 
    375 /*
    376  * Function:
    377  *  _soc_avs_pvt_value_read
    378  * Purpose:
    379  *  Read the 10b data value for specified PVT_MON.
    380  * Parameters:
    381  *  pvtmon - (IN) specifies one of PVT_TEMPERATURE, PVT_1V_0, PVT_1V_1, etc
    382  *  data - (OUT) 10b pvtmon.data
    383  * Returns:
    384  *  data - (OUT) 10b pvtmon.data
    385  */
    386 #define _SOC_AVS_PVTMON_MAX_REREADS 10
    387 STATIC int
    388 _soc_avs_pvt_value_read(int unit, soc_avs_pvt_t pvtmon, uint32 *data)
    389 {
    390     int j;
    391     uint32 regval;
    392     uint32 valid_data = 0;
    393     uint32 done = 0;
    394 
    395     if (data == NULL) {
    396         return (SOC_E_PARAM);
    397     }
    398     *data = 0;
    399     regval = 0;
    400     for (j = 0; j < _SOC_AVS_PVTMON_MAX_REREADS; j++) {
    401         switch (pvtmon) {
    402         case SOC_AVS_PVT_TEMPERATURE:
    403             SOC_IF_ERROR_RETURN(
    404                 READ_AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr(unit,
    405                                                                          &regval));
    406             break;
    407         case SOC_AVS_PVT_1V_0:
    408             SOC_IF_ERROR_RETURN(
    409                 READ_AVS_REG_RO_REGISTERS_0_PVT_1V_0_MNTR_STATUSr(unit,
    410                                                                   &regval));
    411             break;
    412         default:
    413             *data = 0;
    414             return (SOC_E_PARAM);
    415         }
    416         /* all PVT monitor measurement status register have the same field format */
    417         valid_data = soc_reg_field_get(unit,
    418                                        AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr,
    419                                        regval, VALID_DATAf);
    420         done = soc_reg_field_get(unit,
    421                                  AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr,
    422                                  regval, DONEf);
    423 
    424         /* Wait for valid to be set */
    425         if (valid_data && done) {
    426             break;
    427         }
    428     }
    429     *data = soc_reg_field_get(unit,
    430                               AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr,
    431                               regval, DATAf);
    432     if (!valid_data) {
    433         return (SOC_E_FAIL);
    434     } else {
    435         return (SOC_E_NONE);
    436     }
    437 }
    438 
    439 /* This just assumes that the PVTMON sequencer did the measurement. */
    440 /* Get the value from PVTMON for the specified value */
    441 STATIC int
    442 _soc_avs_pvtmon_get(int unit, soc_avs_pvt_t pvtmon, uint32 *data)
    443 {
    444     int i;
    445     uint32 code, count, sum;
    446 
    447     /* Disable all but the particular measurement we're interested in */
    448     count = ~(1 << pvtmon) & 0x7F;
    449     SOC_IF_ERROR_RETURN(
    450         WRITE_AVS_REG_HW_MNTR_SEQUENCER_MASK_PVT_MNTRr(unit, count));
    451     SOC_IF_ERROR_RETURN(
    452         WRITE_AVS_REG_HW_MNTR_SEQUENCER_MASK_CEN_ROSC_0r(unit, SOC_AVS_ALL_ONES));
    453     SOC_IF_ERROR_RETURN(
    454         WRITE_AVS_REG_HW_MNTR_SEQUENCER_MASK_CEN_ROSC_1r(unit, SOC_AVS_ALL_ONES));
    455     sal_usleep(SOC_AVS_PVT_DISABLE_DELAY);
    456 
    457     sum = 0;
    458     for (i = 0; i < _SOC_AVS_PVTMON_MAX_REREADS; i ++) {
    459         SOC_IF_ERROR_RETURN(
    460             _soc_avs_pvt_value_read(unit, pvtmon, &code));
    461         sum += code;
    462         sal_usleep(SOC_AVS_PVT_DISABLE_DELAY);
    463     }
    464     code = sum / _SOC_AVS_PVTMON_MAX_REREADS;
    465     *data = code;
    466     /* Re-enable all of the other measurements */
    467     SOC_IF_ERROR_RETURN(
    468         WRITE_AVS_REG_HW_MNTR_SEQUENCER_MASK_PVT_MNTRr(unit, 0));
    469     SOC_IF_ERROR_RETURN(
    470         WRITE_AVS_REG_HW_MNTR_SEQUENCER_MASK_CEN_ROSC_0r(unit, 0));
    471     SOC_IF_ERROR_RETURN(
    472         WRITE_AVS_REG_HW_MNTR_SEQUENCER_MASK_CEN_ROSC_1r(unit, 0));
    473 
    474     return SOC_E_NONE;
    475 }
    476 STATIC int
    477 _soc_avs_reset_measurement(int unit, soc_avs_pvt_t pvtmon)
    478 {
    479     uint32 regval;
    480     uint32 m_init_pvt_mntr;
    481 
    482     /* set */
    483     SOC_IF_ERROR_RETURN(
    484         READ_AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr(unit, &regval));
    485 
    486     m_init_pvt_mntr = (soc_reg_field_get(unit,
    487                                          AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr,
    488                                          regval, M_INIT_PVT_MNTRf));
    489     m_init_pvt_mntr |= (0x1 << pvtmon);
    490 
    491     soc_reg_field_set(unit, AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr,
    492                       &regval, M_INIT_PVT_MNTRf, m_init_pvt_mntr);
    493 
    494     SOC_IF_ERROR_RETURN(
    495         WRITE_AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr(unit, regval));
    496 
    497     /* clr */
    498     SOC_IF_ERROR_RETURN(
    499         READ_AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr(unit, &regval));
    500 
    501     m_init_pvt_mntr = (soc_reg_field_get(unit,
    502                                          AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr,
    503                                          regval, M_INIT_PVT_MNTRf));
    504     m_init_pvt_mntr &= ~(0x1 << pvtmon);
    505 
    506     soc_reg_field_set(unit, AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr,
    507                       &regval, M_INIT_PVT_MNTRf, m_init_pvt_mntr);
    508 
    509     SOC_IF_ERROR_RETURN(
    510         WRITE_AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr(unit, regval));
    511 
    512     return (SOC_E_NONE);
    513 }
    514 
    515 /* Use Software Override to do measurements */
    516 /* This just reads the requested register with debounce */
    517 STATIC int
    518 _soc_avs_sw_takeover_measure(int unit, soc_avs_pvt_t pvtmon, uint32 *code)
    519 {
    520 #define _SOC_AVS_RETRY_LOOPS 5
    521     /* found that we sometimes don't get valid data even after the 26 tries */
    522 #define _SOC_AVS_AVERAGE_LOOPS 26
    523     /* the more loops the longer the process, but better the average */
    524 #define _SOC_AVS_HW_MNTR_SW_CONTROLS_RESET_VALUE 0
    525 #define _SOC_AVS_MAX_ITERATIONS 100
    526     /* don't let any loops run forever */
    527 
    528     int i, j, k;
    529     uint32 regval, busy = 1, count = 0, sum;
    530 
    531     if (code == NULL) {
    532         return (SOC_E_PARAM);
    533     }
    534     *code = 0;
    535 
    536     for (k = 0; k < _SOC_AVS_RETRY_LOOPS; k++) {
    537         *code = sum = count = 0;
    538 
    539         for (i = 0; i < _SOC_AVS_AVERAGE_LOOPS; i++) {
    540 
    541             /* These steps need to be done one-at-a-time */
    542             regval = 0;
    543             soc_reg_field_set(unit, AVS_REG_HW_MNTR_SW_CONTROLSr, &regval,
    544                               SW_TAKEOVERf, 1);
    545             SOC_IF_ERROR_RETURN(
    546                 WRITE_AVS_REG_HW_MNTR_SW_CONTROLSr(unit, regval));
    547 
    548             soc_reg_field_set(unit, AVS_REG_HW_MNTR_SW_CONTROLSr, &regval,
    549                               SW_SENSOR_IDXf, pvtmon);
    550                 /* sensors in 'PVT Monitor' group */
    551             SOC_IF_ERROR_RETURN(
    552                 WRITE_AVS_REG_HW_MNTR_SW_CONTROLSr(unit, regval));
    553 
    554             soc_reg_field_set(unit, AVS_REG_HW_MNTR_SW_CONTROLSr, &regval,
    555                               SW_DO_MEASUREf, 1);
    556             SOC_IF_ERROR_RETURN(
    557                 WRITE_AVS_REG_HW_MNTR_SW_CONTROLSr(unit, regval));
    558 
    559             /* _soc_avs_msec_sleep(500);
    560              * delay a bit before checking busy status */
    561             sal_usleep(1000);
    562                 /* delay a bit before checking busy status */
    563 
    564             /* The busy comes on during processing and goes off when done */
    565             for (j = 0; j < _SOC_AVS_MAX_ITERATIONS; j++) {
    566                 SOC_IF_ERROR_RETURN(
    567                     READ_AVS_REG_HW_MNTR_SW_MEASUREMENT_UNIT_BUSYr(unit,
    568                                                                    &regval));
    569                 busy = soc_reg_field_get(unit,
    570                                          AVS_REG_HW_MNTR_SW_MEASUREMENT_UNIT_BUSYr,
    571                                          regval, BUSYf);
    572                 if (busy == 0) break; /* from j for loop */
    573                 /* _soc_avs_msec_sleep(1); delay a bit before checking again! */
    574             }
    575 
    576             /* We sometimes see the busy stuck on for some reason
    577              * (if its still on, dismiss this data) */
    578             if (busy == 1) {
    579                 SOC_IF_ERROR_RETURN(
    580                     WRITE_AVS_REG_HW_MNTR_SW_CONTROLSr(unit,
    581                         _SOC_AVS_HW_MNTR_SW_CONTROLS_RESET_VALUE));
    582                 continue; /* with next averaging loop */
    583             }
    584 
    585             if (i < 10) {
    586                 continue; /* skip the first couple of results */
    587             }
    588 
    589             SOC_IF_ERROR_RETURN(_soc_avs_pvt_value_read(unit, pvtmon, code));
    590             if (*code == 0) {
    591                 continue;
    592             }
    593                 /* ignore results from this loop and continue with
    594                  * next averaging loop */
    595 
    596             sum += *code;
    597             count++;
    598 
    599             /*
    600              * LOG_VERBOSE(BSL_LS_SOC_AVS,
    601              * (BSL_META_U(unit,
    602              *             "i = %3d, code = %0d, sum = %0d, count = %0d"
    603              *             "\n"),
    604              *  i, *code, sum, count));
    605              */
    606 
    607             SOC_IF_ERROR_RETURN(
    608                 READ_AVS_REG_HW_MNTR_SW_CONTROLSr(unit, &regval));
    609             soc_reg_field_set(unit, AVS_REG_HW_MNTR_SW_CONTROLSr, &regval,
    610                               SW_DO_MEASUREf, 0);
    611             SOC_IF_ERROR_RETURN(
    612                 WRITE_AVS_REG_HW_MNTR_SW_CONTROLSr(unit, regval));
    613 
    614             /* enable this to just read it once
    615              * break;
    616              */
    617 
    618         } /* _SOC_AVS_AVERAGE_LOOPS */
    619 
    620         /* Use an average value to dismiss the variance in the reads (this is
    621          * called debouncing */
    622         if (count != 0) {
    623             *code = sum/count;
    624             break; /* from _SOC_AVS_RETRY_LOOPS */
    625         }
    626 
    627         /* If we failed to get valid from this pass, reset for next pass */
    628         SOC_IF_ERROR_RETURN(_soc_avs_reset_measurement(unit, pvtmon));
    629     } /* _SOC_AVS_RETRY_LOOPS */
    630 
    631 
    632     SOC_IF_ERROR_RETURN(
    633         READ_AVS_REG_HW_MNTR_SW_CONTROLSr(unit, &regval));
    634     soc_reg_field_set(unit, AVS_REG_HW_MNTR_SW_CONTROLSr, &regval,
    635                       SW_TAKEOVERf, 0);
    636     SOC_IF_ERROR_RETURN(
    637         WRITE_AVS_REG_HW_MNTR_SW_CONTROLSr(unit, regval));
    638 
    639     return (count == 0? SOC_E_FAIL : SOC_E_NONE);
    640 }
    641 
    642 int
    643 soc_avs_temperature_get(int unit, int *temperature)
    644 {
    645     uint32 value;
    646     soc_avs_info_t  *avs_info;
    647 
    648     if (!soc_avs_inited(unit)) {
    649         return SOC_E_INIT;
    650     }
    651     if (temperature == NULL) {
    652         return (SOC_E_PARAM);
    653     }
    654     avs_info = SOC_AVS_INFO(unit);
    655     *temperature = 0;
    656     if (avs_info->avs_flags & SOC_AVS_INFO_F_USE_SOFTWARE_TAKEOVER) {
    657         /* use software override to do measurements */
    658         SOC_IF_ERROR_RETURN(
    659             _soc_avs_sw_takeover_measure(unit, SOC_AVS_PVT_TEMPERATURE, &value));
    660     } else {
    661         /* PVTMON sequencer did the measurement. */
    662         SOC_IF_ERROR_RETURN(
    663             _soc_avs_pvtmon_get(unit, SOC_AVS_PVT_TEMPERATURE, &value));
    664     }
    665     SOC_IF_ERROR_RETURN(
    666         soc_avs_ioctl(unit, SOC_AVS_CTRL_PVTMON_TEMP_GET, &value, 0));
    667     *temperature = value;
    668     return SOC_E_NONE;
    669 }
    670 
    671 int
    672 soc_avs_pvtmon_voltage_get(int unit, uint32 *voltage)
    673 {
    674     uint32 value;
    675     soc_avs_info_t  *avs_info;
    676 
    677     if (!soc_avs_inited(unit)) {
    678         return SOC_E_INIT;
    679     }
    680     if (voltage == NULL) {
    681         return (SOC_E_PARAM);
    682     }
    683     avs_info = SOC_AVS_INFO(unit);
    684     *voltage = 0;
    685     if (avs_info->avs_flags & SOC_AVS_INFO_F_USE_SOFTWARE_TAKEOVER) {
    686         /* use software override to do measurements */
    687         SOC_IF_ERROR_RETURN(
    688             _soc_avs_sw_takeover_measure(unit, SOC_AVS_PVT_1V_0, &value));
    689     } else {
    690         /* PVTMON sequencer did the measurement. */
    691         SOC_IF_ERROR_RETURN(
    692             _soc_avs_pvtmon_get(unit, SOC_AVS_PVT_1V_0, &value));
    693     }
    694     SOC_IF_ERROR_RETURN(
    695         soc_avs_ioctl(unit, SOC_AVS_CTRL_PVTMON_VOLTAGE_GET, &value, 0));
    696     *voltage = value;
    697 
    698     LOG_VERBOSE(BSL_LS_SOC_AVS,
    699                 (BSL_META_U(unit,
    700                             "==== unit = %d, pvt get voltage = %0d (0.1 mV)\n"),
    701                  unit, *voltage));
    702     return SOC_E_NONE;
    703 }
    704 
    705 STATIC int
    706 _soc_avs_pvt_value_write(int unit, soc_avs_pvt_t pvtmon, uint32 data)
    707 {
    708     int rval;
    709 
    710     switch (pvtmon) {
    711     case SOC_AVS_PVT_1V_0:
    712         rval = 1;
    713         SOC_IF_ERROR_RETURN(WRITE_AVS_REG_PVT_MNTR_CONFIG_PVT_MNTR_CTRLr(unit, rval));
    714         SOC_IF_ERROR_RETURN(
    715                 WRITE_AVS_REG_PVT_MNTR_CONFIG_DAC_CODE_PROGRAMMING_ENABLEr(unit, rval));
    716 
    717         SOC_IF_ERROR_RETURN(WRITE_AVS_REG_PVT_MNTR_CONFIG_DAC_CODEr(unit, data));
    718         SOC_IF_ERROR_RETURN(WRITE_AVS_REG_PVT_MNTR_CONFIG_MIN_DAC_CODEr(unit, data));
    719         SOC_IF_ERROR_RETURN(WRITE_AVS_REG_PVT_MNTR_CONFIG_MAX_DAC_CODEr(unit, data));
    720 
    721         rval = 0x1180;
    722         /* PVTMON control bits : RMON_sel = 0x6; Mode = 0x4 */
    723         SOC_IF_ERROR_RETURN(WRITE_AVS_REG_PVT_MNTR_CONFIG_PVT_MNTR_CTRLr(unit, rval));
    724         break;
    725 
    726     default:
    727         return SOC_E_PARAM;
    728 
    729     }
    730 
    731     return SOC_E_NONE;
    732 }
    733 
    734 int
    735 soc_avs_pvtmon_voltage_set(int unit, uint32 voltage)
    736 {
    737     uint32 value;
    738 
    739     if (!soc_avs_inited(unit)) {
    740         return SOC_E_INIT;
    741     }
    742 
    743     value = voltage;
    744     SOC_IF_ERROR_RETURN(
    745         soc_avs_ioctl(unit, SOC_AVS_CTRL_PVTMON_VOLTAGE_SET, &value, 0));
    746 
    747     SOC_IF_ERROR_RETURN(
    748         _soc_avs_pvt_value_write(unit, SOC_AVS_PVT_1V_0, value));
    749 
    750     /* Delay for the voltage to get reflected. */
    751     sal_msleep(SOC_AVS_DAC_DELAY);
    752 
    753     return SOC_E_NONE;
    754 }
    755 
    756 #define AVS_V_TO_UV_SCALE   (1000000)
    757 #define AVS_SCALING_FACTOR  (100)
    758 /* voltage :(OUT) voltage value (0.1mV granularity)*/
    759 int
    760 soc_avs_voltage_get(int unit, uint32 *voltage)
    761 {
    762     if (voltage == NULL) {
    763         return SOC_E_PARAM;
    764     }
    765 
    766     if ((SOC_AVS_CONTROL(unit)->flags & SOC_AVS_F_VRM_INITED) == 0) {
    767         return SOC_E_UNAVAIL;
    768     }
    769 
    770     if (SOC_AVS_VRM_ACCESS(unit)) {
    771         if (SOC_AVS_VRM_ACCESS(unit)->voltage_get){
    772             return SOC_AVS_VRM_ACCESS(unit)->voltage_get(unit,
    773                                                          voltage);
    774         }
    775     }
    776     if (SOC_AVS_VRM_INFO(unit)) {
    777 #ifdef COMPILER_HAS_DOUBLE
    778         double volts;
    779 #else
    780         int volts;
    781 #endif
    782         int rv, fd;
    783 
    784         if ((SOC_AVS_VRM_INFO(unit)->mux_id != -1) &&
    785             SOC_AVS_VRM_INFO(unit)->profile.mux_enable_value) {
    786             fd = SOC_AVS_VRM_INFO(unit)->mux_id;
    787             rv = soc_i2c_device(unit, fd)->driver->write(unit, fd, 0,
    788                     &SOC_AVS_VRM_INFO(unit)->profile.mux_enable_value, 1);
    789             if (SOC_FAILURE(rv)) {
    790                 return rv;
    791             }
    792         }
    793 
    794         fd = SOC_AVS_VRM_INFO(unit)->vrm_id;
    795         *voltage = 0;
    796         rv = soc_i2c_device(unit, fd)->driver->ioctl(unit, fd,
    797                                                      PMBUS_IOC_READ_VOUT,
    798                                                      &volts, 0);
    799         if (SOC_FAILURE(rv)) {
    800             return rv;
    801         }
    802 
    803 #ifdef COMPILER_HAS_DOUBLE
    804         /* V -> 0.1mV */
    805         *voltage = (uint32)((volts * AVS_V_TO_UV_SCALE) / AVS_SCALING_FACTOR);
    806 #else
    807         /* uV -> 0.1mV */
    808         *voltage = volts / AVS_SCALING_FACTOR;
    809 #endif
    810         if (*voltage == 0) {
    811             /* Some i2c device report non-error on un-supported type */
    812             return SOC_E_UNAVAIL;
    813         }
    814     }
    815     return SOC_E_UNAVAIL;
    816 }
    817 
    818 /*
    819  * Function:
    820  *  soc_avs_voltage_set
    821  * Purpose:
    822  *  Set the voltage to external voltage supplier
    823  * Parameters
    824  *  voltage - (IN) voltage corresponding to desired voltage (0.1mV granularity)
    825  * Returns:
    826  *  SOC_E_xxx
    827  */
    828 int
    829 soc_avs_voltage_set(int unit, uint32 voltage)
    830 {
    831     int rv = SOC_E_UNAVAIL;
    832 
    833     if ((SOC_AVS_CONTROL(unit)->flags & SOC_AVS_F_VRM_INITED) == 0) {
    834         return SOC_E_UNAVAIL;
    835     }
    836     LOG_VERBOSE(BSL_LS_SOC_AVS,
    837         (BSL_META_U(unit,
    838                     "==== unit = %d, request to "
    839                     "set voltage = %0d (0.1 mV)\n"),
    840          unit, voltage));
    841 
    842     if (voltage > SOC_AVS_MAX_VOLTAGE) {
    843         LOG_WARN(BSL_LS_SOC_AVS,
    844                  (BSL_META_U(unit,
    845                              "Fail to set voltage %d "
    846                              "(> SOC_AVS_MAX_VOLTAGE) try %d \n"),
    847                   voltage, SOC_AVS_MAX_VOLTAGE));
    848         voltage = SOC_AVS_MAX_VOLTAGE;
    849     } else if(voltage < SOC_AVS_MIN_VOLTAGE){
    850         LOG_WARN(BSL_LS_SOC_AVS,
    851                  (BSL_META_U(unit,
    852                              "Fail to set voltage %d "
    853                              "(< SOC_AVS_MIN_VOLTAGE) try %d \n"),
    854                   voltage, SOC_AVS_MIN_VOLTAGE));
    855         voltage = SOC_AVS_MIN_VOLTAGE;
    856     }
    857     if (SOC_AVS_VRM_ACCESS(unit)) {
    858         if (SOC_AVS_VRM_ACCESS(unit)->voltage_get){
    859             rv = SOC_AVS_VRM_ACCESS(unit)->voltage_set(unit,
    860                                                        voltage);
    861         }
    862     } else if (SOC_AVS_VRM_INFO(unit)) {
    863 #ifdef COMPILER_HAS_DOUBLE
    864         double volts;
    865 #else
    866         int volts;
    867 #endif
    868         int fd;
    869 
    870         if ((SOC_AVS_VRM_INFO(unit)->mux_id != -1) &&
    871             SOC_AVS_VRM_INFO(unit)->profile.mux_enable_value) {
    872             fd = SOC_AVS_VRM_INFO(unit)->mux_id;
    873             rv = soc_i2c_device(unit, fd)->driver->write(unit, fd, 0,
    874                     &SOC_AVS_VRM_INFO(unit)->profile.mux_enable_value, 1);
    875             if (SOC_FAILURE(rv)) {
    876                 return rv;
    877             }
    878         }
    879 
    880 #ifdef COMPILER_HAS_DOUBLE
    881         /* 0.1mV -> V */
    882         volts = (double)voltage * AVS_SCALING_FACTOR / AVS_V_TO_UV_SCALE;
    883 #else
    884         /* 0.1mV -> uV */
    885         volts = voltage * AVS_SCALING_FACTOR;
    886 #endif
    887         fd = SOC_AVS_VRM_INFO(unit)->vrm_id;
    888         rv = soc_i2c_device(unit, fd)->driver->ioctl(unit, fd,
    889                                                      PMBUS_IOC_SET_VOUT,
    890                                                      &volts, 0);
    891     } else {
    892         rv = SOC_E_UNAVAIL;
    893     }
    894 
    895     if (SOC_FAILURE(rv)) {
    896         LOG_WARN(BSL_LS_SOC_AVS,
    897                  (BSL_META_U(unit,
    898                              "Fail to set voltage %d\n"),
    899                   voltage));
    900        return (rv);
    901     } else {
    902        /* remember last_set_voltage for avs_track voltage adjusment*/
    903        _soc_last_set_voltage[unit] = voltage;
    904        return (SOC_E_NONE);
    905     }
    906 }
    907 
    908 /*
    909  * Function:
    910  *  _soc_avs_calc_v3_for_ref_f3
    911  * Purpose:
    912  *  Computes voltage v3 corresponding to ref_freq f3.
    913  * Parameters:
    914  *  f2 - (IN)Frequency at low voltage
    915  *  v2 - (IN)Low voltage
    916  *  m - (IN)Slope
    917  *  f3 - (IN)Frequency at high voltage
    918  * Returns:
    919  *  Voltage v3 (units of 0.1mV)
    920  */
    921 STATIC uint32
    922 _soc_avs_calc_v3_for_ref_f3(uint32 f2, uint32 v2, uint32 m, uint32 f3)
    923 {
    924     uint32 v3;
    925     uint32 vdelta;
    926 
    927     /* find v3 corresponding to f3 */
    928     if (f2 >= f3) {
    929         vdelta = ((f2 - f3) * SOC_AVS_S2)/m;
    930         SOC_AVS_ASSERT(v2 > vdelta);
    931         v3 = v2 - vdelta;
    932     } else {
    933         vdelta = ((f3 - f2) * SOC_AVS_S2)/m;
    934         v3 = v2 + vdelta;
    935     }
    936 
    937     return (v3);
    938 }
    939 
    940 /* We need the frequency units to be in 10K but multiplying by 10K will cause
    941  * the numerator to overflow in frequency calculation.
    942  * So use 1K before division and multiply by 10 after.
    943  */
    944 #define SOC_AVS_FREQ_DIVIDER 1000U
    945 #define SOC_AVS_FREQ_DIVIDER_ADJUSTMENT 10U
    946 STATIC uint32
    947 _soc_avs_reg_to_freq(int unit, uint32 rosc_count)
    948 {
    949     uint32 freq;
    950     int rosc_count_mode;
    951     int ref_clk_freq; /* in MHz*/
    952     int max_ref_clk_counter;
    953     soc_avs_info_t  *avs_info;
    954 
    955     avs_info = SOC_AVS_INFO(unit);
    956     rosc_count_mode = avs_info->rosc_count_mode;
    957     ref_clk_freq = avs_info->ref_clk_freq;
    958     max_ref_clk_counter = (avs_info->measurement_time_control * 256U)
    959                           + 255U;
    960     freq = ( ((ref_clk_freq * rosc_count) * SOC_AVS_FREQ_DIVIDER) /
    961              (max_ref_clk_counter * rosc_count_mode)
    962            ) * SOC_AVS_FREQ_DIVIDER_ADJUSTMENT;
    963 
    964     return (freq);
    965 }
    966 
    967 STATIC uint32
    968 _soc_avs_freq_to_reg(int unit, uint32 freq)
    969 {
    970     uint32 reg;
    971     int rosc_count_mode;
    972     int ref_clk_freq; /* in MHz*/
    973     int max_ref_clk_counter;
    974     soc_avs_info_t  *avs_info;
    975 
    976     avs_info = SOC_AVS_INFO(unit);
    977     rosc_count_mode = avs_info->rosc_count_mode;
    978     ref_clk_freq = avs_info->ref_clk_freq;
    979     max_ref_clk_counter = (avs_info->measurement_time_control * 256U)
    980                           + 255U;
    981     reg = ((freq / ref_clk_freq) * (max_ref_clk_counter * rosc_count_mode)) /
    982           (SOC_AVS_FREQ_DIVIDER * SOC_AVS_FREQ_DIVIDER_ADJUSTMENT);
    983     return reg;
    984 }
    985 
    986 
    987 /*
    988  * Function:
    989  *  _soc_avs_get_cent_osc_ref_freq
    990  * Purpose:
    991  *  Get certain central ROSC's reference_frequency value
    992  * Parameters:
    993  *  osc_num - (IN)specifies one of the central_osc
    994  *  ref_freq - (OUT)reference_frequency_threshold
    995  * Returns:
    996  *  SOC_E_xxx
    997  */
    998 STATIC int
    999 _soc_avs_get_cent_osc_ref_freq(int unit, int osc_num, uint32 *ref_freq)
   1000 {
   1001     if (!soc_avs_inited(unit)) {
   1002         return SOC_E_INIT;
   1003     }
   1004 
   1005     if (ref_freq == NULL){
   1006         return (SOC_E_PARAM);
   1007     }
   1008     if (osc_num > SOC_AVS_INFO(unit)->num_centrals) {
   1009         return (SOC_E_PARAM);
   1010     }
   1011     *ref_freq = 0; /* default: consider it un-implemented osc */
   1012     *ref_freq = (SOC_AVS_CONTROL(unit)->cen_freq_thr[osc_num]);
   1013     return SOC_E_NONE;
   1014 }
   1015 
   1016 /*
   1017  * Function:
   1018  *  _soc_avs_get_rmt_osc_ref_freq
   1019  * Purpose:
   1020  *  Get certain Remote ROSC's HVT and SVT reference_frequency value
   1021  * Parameters:
   1022  *  osc_num - (IN)specifies one of the central_osc
   1023  *  ref_freq_h - (OUT)HVT reference_frequency_threshold
   1024  *  ref_freq_s - (OUT)SVT reference_frequency_threshold
   1025  * Returns:
   1026  *  SOC_E_xxx
   1027  */
   1028 STATIC int
   1029 _soc_avs_get_rmt_osc_ref_freq(int unit, int osc_num, uint32
   1030         *ref_freq_h, uint32 *ref_freq_s)
   1031 {
   1032     if ((ref_freq_h == NULL) || (ref_freq_s == NULL)) {
   1033         return (SOC_E_PARAM);
   1034     }
   1035     *ref_freq_h = 0;
   1036     *ref_freq_s = 0;
   1037     *ref_freq_h = (SOC_AVS_CONTROL(unit)->rmt_freq_thr[1]);
   1038     *ref_freq_s = (SOC_AVS_CONTROL(unit)->rmt_freq_thr[0]);
   1039     return SOC_E_NONE;
   1040 }
   1041 
   1042 /*
   1043  * There is a divide_by_2 for cent_rosc_counter in NTSW chips.
   1044  * so real_count_value = 2*value_that_we_read
   1045  */
   1046 #define SOC_AVS_CENT_OSC_COUNT_MULTIPLIER 2
   1047 
   1048 /*
   1049  * Function:
   1050  *  _soc_avs_cent_osc_count_get
   1051  * Purpose:
   1052  *  Get specified central ROSC count
   1053  * Parameters:
   1054  *  start_osc - (IN)specifies first central_osc
   1055  *  num_osc - (IN)specifies number of central_osc
   1056  *  ref_freq_s - (OUT)specifies array to return oscillator counts
   1057  * Returns:
   1058  *  SOC_E_xxx
   1059  */
   1060 
   1061 STATIC uint32
   1062 _soc_avs_cent_osc_count_get(int unit, int start_osc, int num_osc, uint32 *count)
   1063 {
   1064     int i, failed = 0, n;
   1065     soc_avs_info_t  *avs_info;
   1066 #ifdef BCM_SBUSDMA_SUPPORT
   1067     soc_avs_control_t *avs;
   1068     int use_dma = 0;
   1069     soc_timeout_t       to;
   1070     sal_usecs_t dma_timeout = 1000000;
   1071 #endif
   1072 
   1073     if (!soc_avs_inited(unit)) {
   1074         return SOC_E_INIT;
   1075     }
   1076 
   1077     avs_info = SOC_AVS_INFO(unit);
   1078     if (count == NULL) {
   1079         return (SOC_E_PARAM);
   1080     }
   1081     sal_memset(count, 0, num_osc*(sizeof(*count)));
   1082 
   1083 #ifdef BCM_SBUSDMA_SUPPORT
   1084     if (soc_feature(unit, soc_feature_sbusdma) &&
   1085         (avs_info->avs_flags & SOC_AVS_INFO_F_RSOC_COUNT_DMA)){
   1086         avs = SOC_AVS_CONTROL(unit);
   1087         use_dma = 1;
   1088         (void)_soc_avs_sbusdma_run(unit, SOC_AVS_ROSC_TYPE_CENTRAL);
   1089 
   1090         soc_timeout_init(&to, 2 * dma_timeout, 0);
   1091         for(;;) {
   1092             if(avs->cent_rosc_count_sync){
   1093                 avs->cent_rosc_count_sync = 0;
   1094                 break;
   1095             }
   1096             if (soc_timeout_check(&to)) {
   1097                 use_dma = 0;
   1098                 LOG_WARN(BSL_LS_SOC_AVS,
   1099                          (BSL_META_U(unit,
   1100                                      "cent rosc count read operation "
   1101                                      "timeout\n")));
   1102                 break;
   1103             }
   1104         }
   1105     }
   1106     if (use_dma) {
   1107         sal_memcpy(count, &SOC_AVS_CONTROL(unit)->cent_desc_buff[start_osc],
   1108                    num_osc * sizeof(uint32));
   1109 
   1110     }else
   1111 #endif
   1112     {
   1113         /* read osc_counts */
   1114         for (i = start_osc; i < start_osc + num_osc; i++) {
   1115             n = i - start_osc;
   1116             if (avs_info->avs_flags &
   1117                     SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   1118                 if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_CENTRAL, i)){
   1119                     count[n] = 0;
   1120                     continue;
   1121                 }
   1122             }
   1123             SOC_IF_ERROR_RETURN(
   1124                 READ_AVS_REG_RO_REGISTERS_0_CEN_ROSC_STATUSr(
   1125                     unit, i, &count[n]));
   1126         }
   1127     }
   1128     /* process the counts */
   1129     for (i = start_osc; i < start_osc + num_osc; i++) {
   1130         n = i - start_osc;
   1131         if (avs_info->avs_flags & SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   1132             if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_CENTRAL, i)){
   1133                 count[n] = 0;
   1134                 continue;
   1135             }
   1136         }
   1137         if (soc_reg_field_get(unit, AVS_REG_RO_REGISTERS_0_CEN_ROSC_STATUSr,
   1138                     count[n], VALIDf) == 0) {
   1139             failed = 1;
   1140             LOG_WARN(BSL_LS_SOC_AVS,
   1141                      (BSL_META_U(unit,
   1142                                  "Fail to get cent osc[%d] %x\n"),
   1143                       i, count[i]));
   1144         }
   1145         count[n] = SOC_AVS_CENT_OSC_COUNT_MULTIPLIER *
   1146                    soc_reg_field_get(unit, AVS_REG_RO_REGISTERS_0_CEN_ROSC_STATUSr,
   1147                                      count[n], DATAf);
   1148     }
   1149     if (failed == 1) {
   1150         return (SOC_E_FAIL);
   1151     } else {
   1152         return (SOC_E_NONE);
   1153     }
   1154 }
   1155 /*
   1156  * Function:
   1157  *  _soc_avs_rmt_osc_count_get
   1158  * Purpose:
   1159  *  Get specified remote ROSC COUNT_S, COUNT_H
   1160  * Parameters:
   1161  *  start_osc - (IN)specifies first central_osc
   1162  *  num_osc - (IN)specifies number of central_osc
   1163  *  count_h - (OUT)specifies array to return COUNT_H values
   1164  *  count_s - (OUT)specifies array to return COUNT_S values
   1165  * Returns:
   1166  *  SOC_E_xxx
   1167  */
   1168 
   1169 STATIC int
   1170 _soc_avs_rmt_osc_count_get(int unit, int start_osc, int num_osc,
   1171         uint32 *count_h, uint32 *count_s)
   1172 {
   1173     int i, n;
   1174     soc_avs_info_t  *avs_info;
   1175 #ifdef BCM_SBUSDMA_SUPPORT
   1176     soc_avs_control_t *avs;
   1177     int use_dma = 0;
   1178     soc_timeout_t       to;
   1179     sal_usecs_t dma_timeout = 1000000;
   1180 #endif
   1181 
   1182     if (!soc_avs_inited(unit)) {
   1183         return SOC_E_INIT;
   1184     }
   1185 
   1186     avs_info = SOC_AVS_INFO(unit);
   1187     if ((count_h == NULL) || (count_s == NULL)) {
   1188         return (SOC_E_PARAM);
   1189     }
   1190     sal_memset(count_h, 0, num_osc*(sizeof(*count_h)));
   1191     sal_memset(count_s, 0, num_osc*(sizeof(*count_s)));
   1192 
   1193 #ifdef BCM_SBUSDMA_SUPPORT
   1194     if (soc_feature(unit, soc_feature_sbusdma) &&
   1195         (avs_info->avs_flags & SOC_AVS_INFO_F_RSOC_COUNT_DMA)){
   1196         avs = SOC_AVS_CONTROL(unit);
   1197         use_dma = 1;
   1198         (void)_soc_avs_sbusdma_run(unit, SOC_AVS_ROSC_TYPE_REMOTE);
   1199 
   1200         soc_timeout_init(&to, 2 * dma_timeout, 0);
   1201         for(;;) {
   1202             if (avs->rmt_rosc_count_sync){
   1203                 avs->rmt_rosc_count_sync = 0;
   1204                 break;
   1205             }
   1206             if (soc_timeout_check(&to)) {
   1207                 use_dma = 0;
   1208                 LOG_WARN(BSL_LS_SOC_AVS,
   1209                          (BSL_META_U(unit,
   1210                                      "rmt rosc count read operation "
   1211                                      "timeout\n")));
   1212                 break;
   1213             }
   1214         }
   1215     }
   1216     if (use_dma) {
   1217         sal_memcpy(count_s, &SOC_AVS_CONTROL(unit)->rmt_desc_buff[start_osc],
   1218                    num_osc * sizeof(uint32));
   1219     }else
   1220 #endif
   1221     {
   1222         /* read count registers */
   1223         for (i = start_osc; i < start_osc + num_osc; i++) {
   1224             n = i - start_osc;
   1225             if (avs_info->avs_flags &
   1226                 SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   1227                 if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   1228                     count_h[n] = 0;
   1229                     count_s[n] = 0;
   1230                     continue;
   1231                 }
   1232             }
   1233             /* use (count_s + i) to hold regval */
   1234             SOC_IF_ERROR_RETURN(
   1235                 READ_AVS_REG_PMB_SLAVE_AVS_ROSC_COUNTr(unit, i, &count_s[n]));
   1236             sal_msleep(SOC_AVS_REMOTE_DELAY);
   1237         }
   1238     }
   1239     /* extract fields from regval */
   1240     for (i = start_osc; i < start_osc + num_osc; i++) {
   1241         n = i - start_osc;
   1242         if (avs_info->avs_flags & SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   1243             if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   1244                 count_h[n] = 0;
   1245                 count_s[n] = 0;
   1246                 continue;
   1247             }
   1248         }
   1249         count_h[n] = soc_reg_field_get(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_COUNTr,
   1250                                        count_s[n], COUNT_Hf);
   1251         count_s[n] = soc_reg_field_get(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_COUNTr,
   1252                                        count_s[n], COUNT_Sf);
   1253     }
   1254 
   1255     return (SOC_E_NONE);
   1256 
   1257 }
   1258 
   1259 int
   1260 soc_avs_osc_count_dump(int unit, int type)
   1261 {
   1262     int i, alloc_size;
   1263     uint32 *alloc_ptr = NULL,
   1264            *pcount_cent_osc = NULL,
   1265            *pcount_rmt_osc_h = NULL,
   1266            *pcount_rmt_osc_s = NULL;
   1267     soc_avs_info_t  *avs_info;
   1268 
   1269     if (!soc_avs_inited(unit)) {
   1270         return SOC_E_INIT;
   1271     }
   1272     avs_info = SOC_AVS_INFO(unit);
   1273 
   1274     /* allocate memory */
   1275     alloc_size = 3 * SOC_AVS_MAX(avs_info->num_centrals, avs_info->num_remotes)
   1276                     *sizeof(uint32);
   1277     if ((alloc_ptr = (uint32 *)sal_alloc(alloc_size,
   1278                     "Storage for _soc_avs_osc_count_dump")) == NULL) {
   1279         return (SOC_E_MEMORY);
   1280     }
   1281 
   1282     pcount_cent_osc = alloc_ptr;
   1283     pcount_rmt_osc_h = pcount_cent_osc +
   1284                        avs_info->num_centrals;
   1285     pcount_rmt_osc_s = pcount_rmt_osc_h +
   1286                        avs_info->num_remotes;
   1287 
   1288     sal_memset(alloc_ptr, 0, alloc_size);
   1289 
   1290     /* read all cent,rmt osc counts  */
   1291     if ((type == SOC_AVS_ROSC_TYPE_CENTRAL) || (type == SOC_AVS_ROSC_TYPE_ALL)) {
   1292         SOC_AVS_FREE_IF_ERROR_RETURN(
   1293             _soc_avs_cent_osc_count_get(unit, avs_info->first_cent,
   1294                                         avs_info->num_centrals,
   1295                                         pcount_cent_osc), alloc_ptr);
   1296     }
   1297     if ((type == SOC_AVS_ROSC_TYPE_REMOTE) || (type == SOC_AVS_ROSC_TYPE_ALL)) {
   1298         SOC_AVS_FREE_IF_ERROR_RETURN(
   1299             _soc_avs_rmt_osc_count_get(unit, avs_info->first_rmt,
   1300                                        avs_info->num_remotes,
   1301                                        pcount_rmt_osc_h, pcount_rmt_osc_s),
   1302                                        alloc_ptr);
   1303     }
   1304 
   1305     if ((type == SOC_AVS_ROSC_TYPE_CENTRAL) || (type == SOC_AVS_ROSC_TYPE_ALL)) {
   1306         LOG_CLI((BSL_META_U(unit, " index, cent_osc_count\n")));
   1307         for (i = avs_info->first_cent; i < avs_info->num_centrals; i++) {
   1308             LOG_CLI((BSL_META_U(unit, "%d, %05d \n"), i, pcount_cent_osc[i]));
   1309         }
   1310     }
   1311 
   1312     if ((type == SOC_AVS_ROSC_TYPE_REMOTE) || (type == SOC_AVS_ROSC_TYPE_ALL)) {
   1313         LOG_CLI((BSL_META_U(unit,
   1314                             " index, count_rmt_osc_h, count_rmt_osc_s\n")));
   1315         for (i = avs_info->first_rmt; i < avs_info->num_remotes; i++) {
   1316             LOG_CLI((BSL_META_U(unit,
   1317                                 "%d, %05d, %5d \n"),
   1318                                 i, pcount_rmt_osc_h[i],pcount_rmt_osc_s[i]));
   1319         }
   1320     }
   1321     sal_free(alloc_ptr);
   1322     return SOC_E_NONE;
   1323 }
   1324 
   1325 /*
   1326  * Function:
   1327  *  _soc_avs_reg_field_all_ones
   1328  * Purpose:
   1329  *  Get the all ones value of spefic register's field
   1330  * Parameters:
   1331  *  soc_reg_t - (IN)specifies register
   1332  *  soc_field_t - (IN)specifies field
   1333  * Returns:
   1334  *  return the all ones field value
   1335  */
   1336 uint32
   1337 _soc_avs_reg_field_all_ones(int unit, soc_reg_t reg, soc_field_t field)
   1338 {
   1339     soc_field_info_t *finfop;
   1340     uint32           mask;
   1341 
   1342     if (!SOC_REG_IS_VALID(unit, reg)) {
   1343 #if !defined(SOC_NO_NAMES)
   1344         LOG_CLI((BSL_META_U(unit,
   1345             "reg %s is invalid\n"), soc_reg_name[reg]));
   1346 #endif
   1347         assert(SOC_REG_IS_VALID(unit, reg));
   1348     }
   1349     SOC_FIND_FIELD(field,
   1350                    SOC_REG_INFO(unit, reg).fields,
   1351                    SOC_REG_INFO(unit, reg).nFields,
   1352                    finfop);
   1353     if (finfop->len < 32) {
   1354         mask = (1 << finfop->len) - 1;
   1355     } else {
   1356         mask = -1;
   1357     }
   1358     return mask;
   1359 }
   1360 
   1361 
   1362 #define SOC_AVS_ROSC_CONTROL_INIT_VALUE 0x7FFF50CF
   1363 
   1364 /*
   1365  * Function:
   1366  *  _soc_avs_initialize_oscs
   1367  * Purpose:
   1368  *  Initialiaze central, remote osc
   1369  * Parameters:
   1370  *  unit - (IN)specifies unit
   1371  * Returns:
   1372  *  SOC_E_xxx
   1373  */
   1374 int
   1375 _soc_avs_initialize_oscs(int unit)
   1376 {
   1377     soc_avs_info_t  *avs_info;
   1378     uint32 regval, fieldval;
   1379     soc_avs_reg_info_t *osc_cen_init_list,*osc_cen_thr_en_list;
   1380     int i;
   1381     soc_reg_t reg;
   1382     soc_field_t field;
   1383 
   1384     if (!soc_avs_inited(unit)) {
   1385         return SOC_E_INIT;
   1386     }
   1387     avs_info = SOC_AVS_INFO(unit);
   1388     /* AVS_MEASUREMENT_TIME_CONTROLr.LIMITf = AVS_MEASUREMENT_TIME_CONTROL*/
   1389     regval = 0;
   1390     soc_reg_field_set(unit, AVS_REG_HW_MNTR_ROSC_MEASUREMENT_TIME_CONTROLr,
   1391                       &regval, LIMITf, avs_info->measurement_time_control);
   1392     SOC_IF_ERROR_RETURN(
   1393         WRITE_AVS_REG_HW_MNTR_ROSC_MEASUREMENT_TIME_CONTROLr(unit,
   1394                                                              regval));
   1395 
   1396     /* AVS_REG_HW_MNTR_ROSC_COUNTING_MODEr.MODEf = avs_info->rosc_count_mode*/
   1397     regval = 0;
   1398     soc_reg_field_set(unit, AVS_REG_HW_MNTR_ROSC_COUNTING_MODEr, &regval,
   1399                       MODEf, avs_info->rosc_count_mode);
   1400     SOC_IF_ERROR_RETURN(
   1401         WRITE_AVS_REG_HW_MNTR_ROSC_COUNTING_MODEr(unit, regval));
   1402 
   1403     SOC_AVS_IF_ERROR_NOT_UNAVAIL_RETURN(
   1404         soc_avs_ioctl(unit, SOC_AVS_CTRL_OSC_INIT, NULL, 0));
   1405 
   1406     if (avs_info->osc_cen_init_info) {
   1407         /* always enable all oscillators at start-up */
   1408         osc_cen_init_list = avs_info->osc_cen_init_info;
   1409         for (i = 0; osc_cen_init_list[i].reg_name != -1 ; i++) {
   1410             reg = osc_cen_init_list[i].reg_name;
   1411             field = osc_cen_init_list[i].reg_field;
   1412             /* always enable all oscillators at start-up */
   1413             regval = 0;
   1414             fieldval = _soc_avs_reg_field_all_ones(unit, reg, field);
   1415             soc_reg_field_set(unit, reg,
   1416                 &regval, field, fieldval);
   1417             SOC_IF_ERROR_RETURN(soc_reg32_set(unit,
   1418                 reg, REG_PORT_ANY, 0, regval));
   1419             /* different form BCG, we don't clear this after enable */
   1420         }
   1421     }
   1422 
   1423     SOC_AVS_IF_ERROR_NOT_UNAVAIL_RETURN(
   1424         soc_avs_ioctl(unit, SOC_AVS_CTRL_OSC_THRESHOLD, NULL, 0));
   1425 
   1426     if (avs_info->osc_cen_thr_en_info) {
   1427         osc_cen_thr_en_list = avs_info->osc_cen_thr_en_info;
   1428         /* Set up the Threshold enables */
   1429         for (i = 0; osc_cen_thr_en_list[i].reg_name != -1 ; i++) {
   1430             reg = osc_cen_thr_en_list[i].reg_name;
   1431             field = osc_cen_thr_en_list[i].reg_field;
   1432             regval = 0;
   1433             if (avs_info->avs_flags & SOC_AVS_INFO_F_USE_SOFTWARE_TAKEOVER) {
   1434             /* If using software takeover then DISABLE all the
   1435                threshold enables */
   1436                 fieldval = 0;
   1437             } else {
   1438             /* If NOT using software takeover then ENABLE all the
   1439                threshold enables */
   1440                 fieldval = _soc_avs_reg_field_all_ones(unit, reg, field);
   1441             }
   1442             soc_reg_field_set(unit, reg,
   1443                               &regval, field, fieldval);
   1444             SOC_IF_ERROR_RETURN(
   1445                 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   1446         }
   1447     }
   1448 
   1449     /* Remote oscillators are on PMB bus on newer parts */
   1450     regval = SOC_AVS_ROSC_CONTROL_INIT_VALUE;
   1451     for (i = 0; i < avs_info->num_remotes; i++) {
   1452         if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   1453             continue;
   1454         }
   1455         SOC_IF_ERROR_RETURN(
   1456             WRITE_AVS_REG_PMB_SLAVE_AVS_ROSC_CONTROLr(unit, i, regval));
   1457 
   1458         sal_msleep(SOC_AVS_REMOTE_DELAY);
   1459     }
   1460 
   1461     return (SOC_E_NONE);
   1462 }
   1463 /* to determine v1s, v2s - local_fit */
   1464 #define SOC_AVS_VHIGH           SOC_AVS_UINT(10200)
   1465 #define SOC_AVS_V1_DIFF         SOC_AVS_UINT(200) /* 20 mV*/
   1466 #define SOC_AVS_V1_MINUS_V2     SOC_AVS_UINT(300) /* 30 mV */
   1467 /* lowest slow-slow part voltage */
   1468 #define SOC_AVS_VLOW_SS         SOC_AVS_INT(9400)
   1469 #define SOC_AVS_V2S_INC_FOR_2ND_PASS SOC_AVS_UINT(280); /* 28mV */
   1470 #define SOC_AVS_VLOW_DIFF       SOC_AVS_INT(600) /* 60 mV */
   1471 
   1472 #define SOC_AVS_VHI_VLO_MIN_DIFF    SOC_AVS_UINT(100) /* 10 mV */
   1473 
   1474 /*
   1475  * Function:
   1476  *  _soc_avs_predict_vpred
   1477  * Purpose:
   1478  *   Applies (v1, v2), records (f1, f2),
   1479  *   computes v3 for pre-defined ref f3, returns vpred = max(v3).
   1480  * Parameters:
   1481  *  dac_code_low - (IN)dac_code correspoding to v1
   1482  *  dac_code_high - (IN)dac_code correspoding to v2
   1483  *  vpred   - (OUT)The converged voltage
   1484  * Returns:
   1485  *  SOC_E_xxx
   1486  */
   1487 int
   1488 _soc_avs_predict_vpred(int unit, int pass, uint32 dac_code_low, uint32
   1489         dac_code_high, uint32 *vpred, uint32 *vlow, uint32 *vhigh)
   1490 {
   1491     soc_avs_control_t *avs;
   1492     soc_avs_info_t  *avs_info;
   1493     int32 v3_max_cent_osc, v3_max_rmt_osc;
   1494     int i, alloc_size;
   1495     uint32 *alloc_ptr = NULL,
   1496            *pcount_cent_osc_at_vhigh = NULL, *pcount_cent_osc_at_vlow = NULL,
   1497            *pcount_rmt_osc_at_vhigh_h = NULL, *pcount_rmt_osc_at_vlow_h = NULL,
   1498            *pcount_rmt_osc_at_vhigh_s = NULL, *pcount_rmt_osc_at_vlow_s = NULL;
   1499 
   1500     if (!soc_avs_inited(unit)) {
   1501         return SOC_E_INIT;
   1502     }
   1503     if (vpred == NULL){
   1504         return SOC_E_PARAM;
   1505     }
   1506     SOC_AVS_ASSERT(dac_code_high > dac_code_low);
   1507     avs = SOC_AVS_CONTROL(unit);
   1508     avs_info = SOC_AVS_INFO(unit);
   1509     /* Return Vpred value 0 in case of errors */
   1510     *vpred = 0;
   1511 
   1512     /* allocate memory */
   1513     alloc_size = (2 * avs_info->num_centrals + 4 * avs_info->num_remotes) *
   1514                  sizeof(uint32);
   1515     if ((alloc_ptr = (uint32 *)sal_alloc(alloc_size,
   1516                     "Storage for _soc_avs_predict_vpred")) == NULL) {
   1517         return (SOC_E_MEMORY);
   1518     }
   1519     pcount_cent_osc_at_vhigh = alloc_ptr;
   1520     pcount_cent_osc_at_vlow = pcount_cent_osc_at_vhigh +
   1521                               avs_info->num_centrals;
   1522     pcount_rmt_osc_at_vhigh_h = pcount_cent_osc_at_vlow +
   1523                                 avs_info->num_centrals;
   1524     pcount_rmt_osc_at_vlow_h = pcount_rmt_osc_at_vhigh_h +
   1525                                avs_info->num_remotes;
   1526     pcount_rmt_osc_at_vhigh_s = pcount_rmt_osc_at_vlow_h +
   1527                                 avs_info->num_remotes;
   1528     pcount_rmt_osc_at_vlow_s = pcount_rmt_osc_at_vhigh_s +
   1529                                avs_info->num_remotes;
   1530     sal_memset(alloc_ptr, 0, alloc_size);
   1531 
   1532     if ((pass == 0) || (pass == -1)){
   1533         /* Apply first voltage (high DAC is higher voltage) */
   1534         SOC_AVS_FREE_IF_ERROR_RETURN(
   1535             soc_avs_voltage_set(unit, dac_code_high), alloc_ptr);
   1536         SOC_AVS_FREE_IF_ERROR_RETURN(
   1537             soc_avs_voltage_get(unit, vhigh),alloc_ptr);
   1538         avs->v1r_cache = *vhigh;
   1539 
   1540         /* read all cent,rmt osc counts (at vhigh) */
   1541         SOC_AVS_FREE_IF_ERROR_RETURN(
   1542             _soc_avs_cent_osc_count_get(unit,avs_info->first_cent,
   1543                                         avs_info->num_centrals,
   1544                                         pcount_cent_osc_at_vhigh), alloc_ptr);
   1545         SOC_AVS_FREE_IF_ERROR_RETURN(
   1546             _soc_avs_rmt_osc_count_get(unit, avs_info->first_rmt,
   1547                                        avs_info->num_remotes,
   1548                                        pcount_rmt_osc_at_vhigh_h,
   1549                                        pcount_rmt_osc_at_vhigh_s), alloc_ptr);
   1550         if (pass == 0) {
   1551             /* save the v1s values to cache */
   1552             sal_memcpy(avs->cent_v1s_osc_cache, pcount_cent_osc_at_vhigh,
   1553                        avs_info->num_centrals * sizeof(uint32));
   1554             sal_memcpy(avs->rmt_v1s_h_osc_cache, pcount_rmt_osc_at_vhigh_h,
   1555                        avs_info->num_remotes * sizeof(uint32));
   1556             sal_memcpy(avs->rmt_v1s_s_osc_cache, pcount_rmt_osc_at_vhigh_s,
   1557                        avs_info->num_remotes * sizeof(uint32));
   1558         }
   1559     } else {
   1560         /* restore the v1s value from cache */
   1561         sal_memcpy(pcount_cent_osc_at_vhigh, avs->cent_v1s_osc_cache,
   1562                    avs_info->num_centrals * sizeof(uint32));
   1563         sal_memcpy(pcount_rmt_osc_at_vhigh_h, avs->rmt_v1s_h_osc_cache,
   1564                    avs_info->num_remotes * sizeof(uint32));
   1565         sal_memcpy(pcount_rmt_osc_at_vhigh_s, avs->rmt_v1s_s_osc_cache,
   1566                    avs_info->num_remotes * sizeof(uint32));
   1567         *vhigh = avs->v1r_cache;
   1568     }
   1569     /* Switch to the 2nd voltage and record the oscillator values
   1570      * (low DAC is lower voltage) */
   1571     SOC_AVS_FREE_IF_ERROR_RETURN(
   1572         soc_avs_voltage_set(unit, dac_code_low),alloc_ptr);
   1573     SOC_AVS_FREE_IF_ERROR_RETURN(
   1574         soc_avs_voltage_get(unit, vlow),alloc_ptr);
   1575 
   1576    /* average read-write delta */
   1577     avs_info->rw_delta = (((int)dac_code_high - (int)*vhigh) +
   1578                           ((int)dac_code_low - (int)*vlow))
   1579                           / 2;
   1580 
   1581     if (soc_property_get(unit,"use_rw_delta", 0) == 0){
   1582         avs_info->rw_delta = 0;
   1583     }
   1584     LOG_VERBOSE(BSL_LS_SOC_AVS,
   1585                 (BSL_META_U(unit,
   1586                             "dac_code_high %d dac_code_low %d "
   1587                             "vhigh %d vlow %d rw_delta %d\n"),
   1588                  dac_code_high, dac_code_low, *vhigh, *vlow,
   1589                  avs_info->rw_delta));
   1590     /* Verify that AVS hardware is enabled on this board!.
   1591      * If the difference in the two voltages is < 10mV then we don't do
   1592      * AVS on this part!. */
   1593     SOC_AVS_ASSERT(*vhigh > *vlow);
   1594     if ((*vhigh - *vlow) < SOC_AVS_VHI_VLO_MIN_DIFF) {
   1595         LOG_INFO(BSL_LS_SOC_AVS,
   1596                  (BSL_META_U(unit,
   1597                              "Voltage diff was < "
   1598                              "%0d mV -- stopping AVS processing!\n"),
   1599                   SOC_AVS_VHI_VLO_MIN_DIFF/10));
   1600         sal_free(alloc_ptr);
   1601         return (SOC_E_DISABLED);
   1602     }
   1603 
   1604     /* read all cent, rmt osc counts (at vlow) */
   1605     SOC_AVS_FREE_IF_ERROR_RETURN(
   1606         _soc_avs_cent_osc_count_get(unit, avs_info->first_cent,
   1607                                     avs_info->num_centrals,
   1608                                     pcount_cent_osc_at_vlow), alloc_ptr);
   1609     SOC_AVS_FREE_IF_ERROR_RETURN(
   1610         _soc_avs_rmt_osc_count_get(unit, avs_info->first_rmt,
   1611                                    avs_info->num_remotes,
   1612                                    pcount_rmt_osc_at_vlow_h,
   1613                                    pcount_rmt_osc_at_vlow_s), alloc_ptr);
   1614 
   1615     /* we want largest predicted voltage across all the usable oscillators */
   1616     v3_max_cent_osc = 0;
   1617     LOG_VERBOSE(BSL_LS_SOC_AVS,
   1618                 (BSL_META_U(unit,
   1619                             "cent_osc, v1, r_count1, f1, v2, r_count2,"
   1620                             " f2, f3, v3, exclude, h/s\n")));
   1621     for (i = avs_info->first_cent; i < avs_info->num_centrals; i++) {
   1622         uint32 freq_at_vhigh, freq_at_vlow;
   1623         uint32 f3;
   1624         uint32 slope;
   1625         uint32 v3;
   1626         if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_CENTRAL, i)){
   1627             LOG_VERBOSE(BSL_LS_SOC_AVS,
   1628                         (BSL_META_U(unit,
   1629                                     "%d, %d, %d, -, %d, %d, -, -, -, 1, -\n"),
   1630                          i, *vhigh, pcount_cent_osc_at_vhigh[i],
   1631                          *vlow, pcount_cent_osc_at_vlow[i]));
   1632             continue;
   1633         }
   1634         if ((pcount_cent_osc_at_vhigh[i] == 0) ||
   1635             (pcount_cent_osc_at_vlow[i] == 0)) {
   1636                 LOG_VERBOSE(BSL_LS_SOC_AVS,
   1637                             (BSL_META_U(unit,
   1638                                         "%d, %d, %d, -, "
   1639                                         "%d, %d, -, -, -, 0, -\n"),
   1640                              i, *vhigh, pcount_cent_osc_at_vhigh[i],
   1641                              *vlow, pcount_cent_osc_at_vlow[i]));
   1642             continue;
   1643         }
   1644 
   1645         freq_at_vhigh = _soc_avs_reg_to_freq(unit,
   1646                                              pcount_cent_osc_at_vhigh[i]);
   1647         freq_at_vlow = _soc_avs_reg_to_freq(unit,
   1648                                             pcount_cent_osc_at_vlow[i]);
   1649 
   1650         SOC_AVS_ASSERT(freq_at_vhigh > freq_at_vlow);
   1651 
   1652         /* m = (f1-f2)/(v1-v2)
   1653          * Scaling factor is added to improve accuracy.
   1654          * Must remember slope is now in 10,000th */
   1655         slope = (freq_at_vhigh - freq_at_vlow)*SOC_AVS_S2 / (*vhigh - *vlow);
   1656 
   1657         /* read pre-defined freq_threshold (f3) */
   1658         SOC_AVS_FREE_IF_ERROR_RETURN(
   1659             _soc_avs_get_cent_osc_ref_freq(unit, i, &f3), alloc_ptr);
   1660 
   1661         /* find v3 corresponding to f3 */
   1662         v3 = _soc_avs_calc_v3_for_ref_f3(freq_at_vlow, *vlow, slope, f3);
   1663 
   1664         avs->saved_voltage[i] = v3;
   1665         LOG_VERBOSE(BSL_LS_SOC_AVS,
   1666                     (BSL_META_U(unit,
   1667                                 "%d, %d, %d, %d, %d, %d, %d, %d, %d, 0, -\n"),
   1668                      i, *vhigh, pcount_cent_osc_at_vhigh[i], freq_at_vhigh,
   1669                      *vlow, pcount_cent_osc_at_vlow[i], freq_at_vlow, f3, v3));
   1670         /* max */
   1671         v3_max_cent_osc = SOC_AVS_MAX(v3, v3_max_cent_osc);
   1672     } /* for all cent_osc */
   1673     LOG_VERBOSE(BSL_LS_SOC_AVS,
   1674                 (BSL_META_U(unit,
   1675                             "Max voltage across "
   1676                             "Central oscillators = %0d\n"),
   1677                  v3_max_cent_osc));
   1678 
   1679     v3_max_rmt_osc = 0;
   1680     LOG_VERBOSE(BSL_LS_SOC_AVS,
   1681                 (BSL_META_U(unit,
   1682                             "rmt_osc, v1, r_count1, f1, v2, r_count2,"
   1683                             " f2, f3, v3, exclude, h/s\n")));
   1684     for (i = avs_info->first_rmt; i < avs_info->num_remotes; i++) {
   1685         uint32 freq_at_vhigh_s, freq_at_vhigh_h;
   1686         uint32 freq_at_vlow_s, freq_at_vlow_h;
   1687         uint32 f3_s, f3_h;
   1688         uint32 slope;
   1689         uint32 v3_s, v3_h;
   1690 
   1691         if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   1692             LOG_VERBOSE(BSL_LS_SOC_AVS,
   1693                         (BSL_META_U(unit,
   1694                                     "%d, %d, %d, -, %d, %d, -, -, -, 1, h\n"),
   1695                                     i, *vhigh, pcount_rmt_osc_at_vhigh_h[i],
   1696                                     *vlow, pcount_rmt_osc_at_vlow_h[i]));
   1697             LOG_VERBOSE(BSL_LS_SOC_AVS,
   1698                         (BSL_META_U(unit,
   1699                                     "%d, %d, %d, -, %d, %d, -, -, -, 1, s\n"),
   1700                                     i, *vhigh, pcount_rmt_osc_at_vhigh_s[i],
   1701                                     *vlow, pcount_rmt_osc_at_vlow_s[i]));
   1702             continue;
   1703         }
   1704 
   1705         freq_at_vhigh_h = _soc_avs_reg_to_freq(unit,
   1706                                                pcount_rmt_osc_at_vhigh_h[i]);
   1707         freq_at_vhigh_s = _soc_avs_reg_to_freq(unit,
   1708                                                pcount_rmt_osc_at_vhigh_s[i]);
   1709 
   1710         freq_at_vlow_h = _soc_avs_reg_to_freq(unit,
   1711                                               pcount_rmt_osc_at_vlow_h[i]);
   1712         freq_at_vlow_s = _soc_avs_reg_to_freq(unit,
   1713                                               pcount_rmt_osc_at_vlow_s[i]);
   1714 
   1715         SOC_AVS_FREE_IF_ERROR_RETURN(
   1716             _soc_avs_get_rmt_osc_ref_freq(unit, i, &f3_h, &f3_s), alloc_ptr);
   1717 
   1718         SOC_AVS_ASSERT(freq_at_vhigh_h > freq_at_vlow_h);
   1719         slope = (freq_at_vhigh_h - freq_at_vlow_h)*SOC_AVS_S2 / (*vhigh - *vlow);
   1720         v3_h = _soc_avs_calc_v3_for_ref_f3(freq_at_vlow_h, *vlow, slope, f3_h);
   1721 
   1722         SOC_AVS_ASSERT(freq_at_vhigh_s > freq_at_vlow_s);
   1723         slope = (freq_at_vhigh_s - freq_at_vlow_s)*SOC_AVS_S2 / (*vhigh - *vlow);
   1724         v3_s = _soc_avs_calc_v3_for_ref_f3(freq_at_vlow_s, *vlow, slope, f3_s);
   1725 
   1726 
   1727         LOG_VERBOSE(BSL_LS_SOC_AVS,
   1728                     (BSL_META_U(unit,
   1729                                 "%d, %d, %d, %d, %d, %d, %d, %d, %d, 0, h\n"),
   1730                      i, *vhigh, pcount_rmt_osc_at_vhigh_h[i], freq_at_vhigh_h,
   1731                      *vlow, pcount_rmt_osc_at_vlow_h[i],freq_at_vlow_h, f3_h,
   1732                      v3_h));
   1733 
   1734         LOG_VERBOSE(BSL_LS_SOC_AVS,
   1735                     (BSL_META_U(unit,
   1736                                 "%d, %d, %d, %d, %d, %d, %d, %d, %d, 0, s\n"),
   1737                      i, *vhigh, pcount_rmt_osc_at_vhigh_s[i], freq_at_vhigh_s,
   1738                      *vlow, pcount_rmt_osc_at_vlow_s[i],freq_at_vlow_s, f3_s,
   1739                      v3_s));
   1740 
   1741         v3_max_rmt_osc = SOC_AVS_MAX(v3_h, v3_max_rmt_osc);
   1742         v3_max_rmt_osc = SOC_AVS_MAX(v3_s, v3_max_rmt_osc);
   1743     }
   1744     LOG_VERBOSE(BSL_LS_SOC_AVS,
   1745                 (BSL_META_U(unit,
   1746                             "Max voltage across "
   1747                             "Remote oscillators = %0d\n"),
   1748                  v3_max_rmt_osc));
   1749     /* Final Vpred */
   1750     *vpred = SOC_AVS_MAX(v3_max_cent_osc, v3_max_rmt_osc);
   1751 
   1752     sal_free(alloc_ptr);
   1753 
   1754     LOG_INFO(BSL_LS_SOC_AVS,
   1755              (BSL_META_U(unit,
   1756                          "v1s=%0d, v2s=%0d, "
   1757                          "v1r=%0d, v2r=%0d, vpred=%0d\n"),
   1758               dac_code_high, dac_code_low, *vhigh, *vlow, *vpred));
   1759 
   1760     return (SOC_E_NONE);
   1761 }
   1762 #define DAC_CALIBRATION
   1763 /*
   1764  * Function:
   1765  *  _soc_avs_find_final_voltage
   1766  * Purpose:
   1767  *   Runs avs_predict_vpred, adds margins, sets voltage to computed Vavs
   1768  * Parameters:
   1769  *  vpred   - (OUT)Output from _soc_avs_predict_vpred
   1770  *  vavs_sv - (OUT)Output vpred plus margins
   1771  * Returns:
   1772  *  SOC_E_xxx
   1773  */
   1774 STATIC int
   1775 _soc_avs_find_final_voltage(int unit, uint32 *vpred, uint32 *vavs_sv)
   1776 {
   1777     soc_avs_control_t *avs;
   1778     soc_avs_info_t  *avs_info;
   1779     int32 new_vmin_avs;
   1780     uint32 ccv;
   1781     int32 v2s, v1s;
   1782     int pass;
   1783     int32 vsum, vavs;
   1784     int32 slope_avs, intercept_avs, vmargin;
   1785     int32 vmargin_high, vmargin_low;
   1786     int32 vlow, vhigh;
   1787 #ifdef DAC_CALIBRATION
   1788     int32 slope_dac;
   1789     int32 avs_dac_code;
   1790 #endif
   1791 
   1792     avs = SOC_AVS_CONTROL(unit);
   1793     avs_info = SOC_AVS_INFO(unit);
   1794 
   1795     new_vmin_avs = avs_info->vmin_avs;
   1796 
   1797     SOC_AVS_LOCK(avs);
   1798     if (SOC_AVS_MARGIN(unit)->vmargin_high){
   1799         vmargin_high = SOC_AVS_MARGIN(unit)->vmargin_high;
   1800     } else {
   1801         vmargin_high = avs_info->vmargin_high;
   1802     }
   1803     if (SOC_AVS_MARGIN(unit)->vmargin_low){
   1804         vmargin_low = SOC_AVS_MARGIN(unit)->vmargin_low;
   1805     } else {
   1806         vmargin_low = avs_info->vmargin_low;
   1807     }
   1808     slope_avs = ((vmargin_high - vmargin_low)*SOC_AVS_S2) /
   1809                 ((avs_info->vmax_avs - avs_info->vmin_avs) +
   1810                  (vmargin_low - vmargin_high));
   1811     avs->slope_margin = slope_avs;
   1812 
   1813     intercept_avs = vmargin_low -
   1814                     ((slope_avs * (avs_info->vmin_avs - vmargin_low)) /
   1815                      SOC_AVS_S2);
   1816     avs->intercept_margin = intercept_avs;
   1817 
   1818     SOC_AVS_UNLOCK(avs);
   1819     /* Read cur_core_voltage (will depend on OTP) */
   1820     SOC_IF_ERROR_RETURN(soc_avs_voltage_get(unit, &ccv));
   1821 
   1822     /* Determine v1s, v2s (voltage points for local fit) */
   1823     v1s = ccv + SOC_AVS_V1_DIFF;
   1824     v2s = v1s - SOC_AVS_V1_MINUS_V2;
   1825 
   1826     LOG_INFO(BSL_LS_SOC_AVS,
   1827              (BSL_META_U(unit,
   1828                          "ccv=%0d, "
   1829                          "v1s=%0d, v2s=%0d\n"),
   1830                          ccv, v1s, v2s));
   1831 
   1832     /* First pass uses rough values (local fit) and the second uses
   1833      * the more refined (wider range) values (global fit) */
   1834     for (pass = 0; pass < 2; pass++) {
   1835         SOC_IF_ERROR_RETURN(_soc_avs_predict_vpred(unit, pass, v2s,
   1836                     v1s, vpred, (uint32 *)&vlow, (uint32 *)&vhigh));
   1837         if (*vpred == 0) return 0;
   1838 
   1839         vmargin = (slope_avs * (int32)(*vpred))/SOC_AVS_S2 + intercept_avs;
   1840 
   1841         vsum = (int32)(*vpred) + vmargin;
   1842         /* Make sure this is NEVER outside the allowable voltage min/max
   1843          * values */
   1844         if (vsum < new_vmin_avs) {
   1845             vavs = new_vmin_avs;
   1846         } else if (vsum > avs_info->vmax_avs) {
   1847             vavs = avs_info->vmax_avs;
   1848         } else {
   1849             vavs = vsum;
   1850         }
   1851         LOG_INFO(BSL_LS_SOC_AVS,
   1852                  (BSL_META_U(unit,
   1853                              "pass=%0d, "
   1854                              "vpred=%0d, vavs=%0d, vmargin %0d\n"),
   1855                   pass, *vpred, vavs, vmargin));
   1856 #ifdef DAC_CALIBRATION
   1857         slope_dac = ((v1s - v2s) * SOC_AVS_S2) / (vhigh - vlow);
   1858         avs_dac_code = ((slope_dac * vavs) - (slope_dac * vlow))/SOC_AVS_S2 + v2s;
   1859 
   1860         if (vavs < SOC_AVS_VLOW_SS) {
   1861             v2s = avs_dac_code + SOC_AVS_V2S_INC_FOR_2ND_PASS;
   1862         }
   1863         LOG_VERBOSE(BSL_LS_SOC_AVS,
   1864                     (BSL_META_U(unit, "avs_dac_code calibration "
   1865                                 "slope_dac %d vavs %d avs_dac_code %d "
   1866                                 "v2s %d \n"),
   1867                      slope_dac, vavs, avs_dac_code, v2s));
   1868 #else
   1869         /* On next pass, adjust low value (v2s) to get more precise calculation
   1870          * on second pass */
   1871         /* This turns the process from a local fit to a global fit process */
   1872         /* For some chip boot from 0.9V, in below case, no need to do 2nd pass.
   1873                       orig: if(vavs  > 0.94)  exit;
   1874                       change to: voltage diff if(v2s-vavs) < 0.06 exit; */
   1875         if ((v2s - vavs) > SOC_AVS_VLOW_DIFF) {
   1876             SOC_AVS_ASSERT(vavs > 0);
   1877             v2s = (uint32)vavs + SOC_AVS_V2S_INC_FOR_2ND_PASS;
   1878             SOC_AVS_ASSERT(v1s > v2s);
   1879         } else {
   1880            /* no need to do 2nd pass - because v1s, v2s remain same as
   1881                       1st pass */
   1882             break;
   1883         }
   1884 #endif
   1885     }
   1886 
   1887     SOC_AVS_ASSERT(vavs > 0);
   1888     LOG_INFO(BSL_LS_SOC_AVS,
   1889              (BSL_META_U(unit,
   1890                          "set avs_dac_code %d (vavs %d)\n"),
   1891               avs_dac_code, vavs));
   1892     SOC_IF_ERROR_RETURN(soc_avs_voltage_set(unit, (uint32)avs_dac_code));
   1893     if (avs_info->avs_flags & SOC_AVS_INFO_F_USE_LVM_FLAG){
   1894         /* check LVM */
   1895         SOC_AVS_IF_ERROR_NOT_UNAVAIL_RETURN(
   1896             soc_avs_ioctl(unit, SOC_AVS_CTRL_LVM_MODE, NULL, 0));
   1897     }
   1898 
   1899     *vavs_sv = (uint32)*vpred;
   1900     SOC_IF_ERROR_RETURN(soc_avs_voltage_get(unit, (uint32 *)&vlow));
   1901     LOG_INFO(BSL_LS_SOC_AVS,
   1902              (BSL_META_U(unit, "Find Voltage %d\n"), vlow));
   1903     return SOC_E_NONE;
   1904 }
   1905 
   1906 /*
   1907  * Function:
   1908  *  _soc_avs_rmt_osc_thr_get
   1909  * Purpose:
   1910  *   Get hi, lo h, s thresholds for specified range of
   1911  *   remote_oscillators.
   1912  * Parameters:
   1913  *  start_osc   - (IN)specifies first remote_osc
   1914  *  num_osc  - (IN)specifies number of remote_osc
   1915  *  lo_thr_h - (OUT)low threshold_h
   1916  *  hi_thr_h - (OUT)high threshold_h
   1917  *  lo_thr_s - (OUT)low threshold_s
   1918  *  hi_thr_s - (OUT)high threshold_s
   1919  * Returns:
   1920  *  SOC_E_xxx
   1921  */
   1922 STATIC int
   1923 _soc_avs_rmt_osc_thr_get(int unit, int start_osc, int num_osc,
   1924         uint32 *lo_thr_h, uint32 *hi_thr_h, uint32 *lo_thr_s, uint32 *hi_thr_s)
   1925 {
   1926     int i, cached = 0, n;
   1927     soc_avs_control_t *avs;
   1928     soc_avs_info_t  *avs_info;
   1929 
   1930     avs = SOC_AVS_CONTROL(unit);
   1931     avs_info = SOC_AVS_INFO(unit);
   1932 
   1933     if ((lo_thr_h == NULL) || (hi_thr_h == NULL) || (lo_thr_s == NULL) ||
   1934             (hi_thr_s == NULL)) {
   1935         return (SOC_E_PARAM);
   1936     }
   1937     sal_memset(lo_thr_h, 0, num_osc*(sizeof(*lo_thr_h)));
   1938     sal_memset(hi_thr_h, 0, num_osc*(sizeof(*hi_thr_h)));
   1939     sal_memset(lo_thr_s, 0, num_osc*(sizeof(*lo_thr_s)));
   1940     sal_memset(hi_thr_s, 0, num_osc*(sizeof(*hi_thr_s)));
   1941 
   1942     if (avs_info->avs_flags &
   1943             SOC_AVS_INFO_F_RSOC_THRESHOLD_CACHE) {
   1944         if ((avs->rmt_h_thr_cache == NULL) ||
   1945             (avs->rmt_s_thr_cache == NULL)) {
   1946             cached = 0;
   1947         } else {
   1948             cached = 1;
   1949         }
   1950     }
   1951 
   1952     if (cached) {
   1953         sal_memcpy(lo_thr_h, &avs->rmt_h_thr_cache[start_osc],
   1954             num_osc * sizeof(uint32));
   1955         sal_memcpy(lo_thr_s, &avs->rmt_s_thr_cache[start_osc],
   1956             num_osc * sizeof(uint32));
   1957     } else {
   1958         /* read thr_h, thr_s registers */
   1959         for (i = start_osc; i < start_osc + num_osc; i++) {
   1960             n = i - start_osc;
   1961             if (SOC_AVS_INFO(unit)->avs_flags &
   1962                 SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   1963                 if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   1964                     continue;
   1965                 }
   1966             }
   1967             SOC_IF_ERROR_RETURN(
   1968                 READ_AVS_REG_PMB_SLAVE_AVS_ROSC_H_THRESHOLDr(unit, i,
   1969                 &lo_thr_h[n]));
   1970             sal_msleep(SOC_AVS_REMOTE_DELAY);
   1971 
   1972             SOC_IF_ERROR_RETURN(
   1973                 READ_AVS_REG_PMB_SLAVE_AVS_ROSC_S_THRESHOLDr(unit, i,
   1974                 &lo_thr_s[n]));
   1975             sal_msleep(SOC_AVS_REMOTE_DELAY);
   1976         }
   1977     }
   1978     /* extract hi,lo_thr_h from registers */
   1979     for (i = start_osc; i < start_osc + num_osc; i++) {
   1980         n = i - start_osc;
   1981         if (SOC_AVS_INFO(unit)->avs_flags &
   1982             SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   1983             if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   1984                 hi_thr_h[n] = 0;
   1985                 lo_thr_h[n] = 0;
   1986                 hi_thr_s[n] = 0;
   1987                 lo_thr_s[n] = 0;
   1988                 continue;
   1989             }
   1990         }
   1991 
   1992         hi_thr_h[n] = soc_reg_field_get(unit,
   1993                 AVS_REG_PMB_SLAVE_AVS_ROSC_H_THRESHOLDr, lo_thr_h[n],
   1994                 THRESH_HIf);
   1995         lo_thr_h[n] = soc_reg_field_get(unit,
   1996                 AVS_REG_PMB_SLAVE_AVS_ROSC_H_THRESHOLDr, lo_thr_h[n],
   1997                 THRESH_LOf);
   1998         hi_thr_s[n] = soc_reg_field_get(unit,
   1999                 AVS_REG_PMB_SLAVE_AVS_ROSC_S_THRESHOLDr, lo_thr_s[n],
   2000                 THRESH_HIf);
   2001         lo_thr_s[n] = soc_reg_field_get(unit,
   2002                 AVS_REG_PMB_SLAVE_AVS_ROSC_S_THRESHOLDr, lo_thr_s[n],
   2003                 THRESH_LOf);
   2004     }
   2005     return SOC_E_NONE;
   2006 }
   2007 
   2008 /*
   2009  * Function:
   2010  *  _soc_avs_cent_osc_thr_get
   2011  * Purpose:
   2012  *   Get hi, lo counter thresholds for specified range of central
   2013  *   oscillators
   2014  * Parameters:
   2015  *  start_osc   - (IN)specifies first remote_osc
   2016  *  num_osc  - (IN)specifies number of remote_osc
   2017  *  lo_thr - (OUT)low threshold
   2018  *  hi_thr - (OUT)high threshold
   2019  * Returns:
   2020  *  SOC_E_xxx
   2021  */
   2022 STATIC int
   2023 _soc_avs_cent_osc_thr_get(int unit, int start_osc, int num_osc,
   2024         uint32 *lo_thr, uint32 *hi_thr)
   2025 {
   2026     int i, cached = 0, n = 0;
   2027     soc_avs_control_t *avs;
   2028     soc_avs_info_t  *avs_info;
   2029 
   2030     avs = SOC_AVS_CONTROL(unit);
   2031     avs_info = SOC_AVS_INFO(unit);
   2032 
   2033     if ((lo_thr == NULL) || (hi_thr == NULL)) {
   2034         return (SOC_E_PARAM);
   2035     }
   2036     sal_memset(lo_thr, 0, num_osc*(sizeof(*lo_thr)));
   2037     sal_memset(hi_thr, 0, num_osc*(sizeof(*hi_thr)));
   2038 
   2039     if (avs_info->avs_flags &
   2040             SOC_AVS_INFO_F_RSOC_THRESHOLD_CACHE) {
   2041         if ((avs->cent_lo_thr_cache == NULL) ||
   2042             (avs->cent_hi_thr_cache == NULL)) {
   2043             cached = 0;
   2044         } else {
   2045             cached = 1;
   2046         }
   2047     }
   2048     if (cached) {
   2049         sal_memcpy(lo_thr, &avs->cent_lo_thr_cache[start_osc],
   2050                    num_osc * sizeof(uint32));
   2051         sal_memcpy(hi_thr, &avs->cent_hi_thr_cache[start_osc],
   2052                    num_osc * sizeof(uint32));
   2053     } else {
   2054         /* read lo_thr, hi_thr reg */
   2055         for (i = start_osc; i < start_osc + num_osc; i++) {
   2056             n = i - start_osc;
   2057             if (avs_info->avs_flags &
   2058                 SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   2059                 if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_CENTRAL, i)){
   2060                     continue;
   2061                 }
   2062             }
   2063             SOC_IF_ERROR_RETURN(
   2064                 READ_AVS_REG_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSCr(
   2065                     unit, i, &lo_thr[n]));
   2066 
   2067             SOC_IF_ERROR_RETURN(
   2068                 READ_AVS_REG_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSCr(
   2069                     unit, i, &hi_thr[n]));
   2070         }
   2071     }
   2072     /* Extract threshold field from registers */
   2073     for (i = start_osc; i < start_osc + num_osc; i++) {
   2074         n = i - start_osc;
   2075         if (avs_info->avs_flags &
   2076             SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   2077             if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_CENTRAL, i)){
   2078                 lo_thr[n] = 0;
   2079                 hi_thr[n] = 0;
   2080                 continue;
   2081             }
   2082         }
   2083         lo_thr[n] = soc_reg_field_get(unit,
   2084                 AVS_REG_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSCr, lo_thr[n],
   2085                 THRESHOLDf);
   2086         hi_thr[n] = soc_reg_field_get(unit,
   2087                 AVS_REG_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSCr, hi_thr[n],
   2088                 THRESHOLDf);
   2089     }
   2090     return SOC_E_NONE;
   2091 }
   2092 
   2093 #define _W_OP_HI    1
   2094 #define _W_OP_LO    2
   2095 #define _W_OP_ALL   3
   2096 /*
   2097  * Function:
   2098  *  _soc_avs_rmt_osc_thr_set
   2099  * Purpose:
   2100  *  Fill hi/lo s_, h_ thresholds into specified range of remote osc.
   2101  *  SAME value is copied into all registers.
   2102  * Parameters:
   2103  *  start_osc   - (IN)specifies first remote_osc
   2104  *  num_osc  - (IN)specifies number of remote_osc
   2105  *  write_op - (IN)specifies write fields of the register
   2106  *  regval_h - (IN)value to be programmed in ROSC_H_THRESHOLD register
   2107  *  regval_s - (IN)value to be programmed in ROSC_S_THRESHOLD register
   2108  * Returns:
   2109  *  SOC_E_xxx
   2110  */
   2111 
   2112 STATIC int
   2113 _soc_avs_rmt_osc_thr_set(int unit, int start_osc, int num_osc,
   2114                          int write_op,
   2115                          uint32 regval_h, uint32 regval_s)
   2116 {
   2117     int i, cached = 0;
   2118     soc_avs_control_t *avs;
   2119     soc_avs_info_t  *avs_info;
   2120     uint32 thr_h, thr_s;
   2121 
   2122     avs = SOC_AVS_CONTROL(unit);
   2123     avs_info = SOC_AVS_INFO(unit);
   2124 
   2125     if (avs_info->avs_flags &
   2126             SOC_AVS_INFO_F_RSOC_THRESHOLD_CACHE) {
   2127         if ((avs->rmt_h_thr_cache == NULL) ||
   2128             (avs->rmt_s_thr_cache == NULL)) {
   2129             cached = 0;
   2130         } else {
   2131             cached = 1;
   2132         }
   2133     }
   2134     /* write (same) regval_h, regval_s to all registers */
   2135     for (i = start_osc; i < start_osc + num_osc; i++) {
   2136         if (SOC_AVS_INFO(unit)->avs_flags &
   2137             SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   2138             if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   2139                 continue;
   2140             }
   2141         }
   2142         SOC_IF_ERROR_RETURN(
   2143             READ_AVS_REG_PMB_SLAVE_AVS_ROSC_H_THRESHOLDr(unit, i,
   2144                                                          &thr_h));
   2145         sal_msleep(SOC_AVS_REMOTE_DELAY);
   2146 
   2147         SOC_IF_ERROR_RETURN(
   2148             READ_AVS_REG_PMB_SLAVE_AVS_ROSC_S_THRESHOLDr(unit, i,
   2149                                                          &thr_s));
   2150         sal_msleep(SOC_AVS_REMOTE_DELAY);
   2151 
   2152         if (write_op == _W_OP_HI) {
   2153             soc_reg_field_set(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_H_THRESHOLDr,
   2154                               &thr_h, THRESH_HIf, regval_h);
   2155             soc_reg_field_set(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_S_THRESHOLDr,
   2156                               &thr_s, THRESH_HIf, regval_s);
   2157         } else if (write_op == _W_OP_LO) {
   2158             soc_reg_field_set(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_H_THRESHOLDr,
   2159                               &thr_h, THRESH_LOf, regval_h);
   2160             soc_reg_field_set(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_S_THRESHOLDr,
   2161                               &thr_s, THRESH_LOf, regval_s);
   2162         } else {
   2163             thr_h = regval_h;
   2164             thr_s = regval_s;
   2165         }
   2166         SOC_IF_ERROR_RETURN(
   2167             WRITE_AVS_REG_PMB_SLAVE_AVS_ROSC_H_THRESHOLDr(unit, i, thr_h));
   2168         sal_msleep(SOC_AVS_REMOTE_DELAY);
   2169         SOC_IF_ERROR_RETURN(
   2170             WRITE_AVS_REG_PMB_SLAVE_AVS_ROSC_S_THRESHOLDr(unit, i, thr_s));
   2171         sal_msleep(SOC_AVS_REMOTE_DELAY);
   2172         if (cached) {
   2173             avs->rmt_h_thr_cache[i] = thr_h;
   2174             avs->rmt_s_thr_cache[i] = thr_s;
   2175         }
   2176     }
   2177     return SOC_E_NONE;
   2178 }
   2179 
   2180 /*
   2181  * Function:
   2182  *  _soc_avs_cent_osc_thr_set
   2183  * Purpose:
   2184  *  Program hi/lo threshold for specified range of central osc.
   2185  *  Unique values can be specified for each osc.
   2186  * Parameters:
   2187  *  start_osc   - (IN)specifies first remote_osc
   2188  *  num_osc  - (IN)specifies number of remote_osc
   2189  *  sel_hi_thr - (IN)when true means program hi_threshold
   2190  *  regval - (IN)array of values to be written into threshold registers
   2191  * Returns:
   2192  *  SOC_E_xxx
   2193  */
   2194 STATIC int
   2195 _soc_avs_cent_osc_thr_set(int unit, int start_osc, int num_osc,
   2196         soc_avs_bool_t sel_hi_thr, const uint32 *regval)
   2197 {
   2198     int i, cached = 0, n;
   2199     soc_avs_control_t *avs;
   2200     soc_avs_info_t  *avs_info;
   2201 
   2202     avs = SOC_AVS_CONTROL(unit);
   2203     avs_info = SOC_AVS_INFO(unit);
   2204 
   2205     if (regval == NULL) {
   2206         return (SOC_E_PARAM);
   2207     }
   2208     if (avs_info->avs_flags &
   2209             SOC_AVS_INFO_F_RSOC_THRESHOLD_CACHE) {
   2210         if ((avs->cent_lo_thr_cache == NULL) ||
   2211             (avs->cent_hi_thr_cache == NULL)) {
   2212             cached = 0;
   2213         } else {
   2214             cached = 1;
   2215         }
   2216     }
   2217 
   2218     for (i = start_osc; i < start_osc + num_osc; i++) {
   2219         n = i - start_osc;
   2220         if (avs_info->avs_flags &
   2221             SOC_AVS_INFO_F_DO_NOT_ACCESS_XOSC) {
   2222             if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_CENTRAL, i)){
   2223                 continue;
   2224             }
   2225         }
   2226         if (sel_hi_thr == SOC_AVS_BOOL_TRUE) {
   2227             SOC_IF_ERROR_RETURN(
   2228                 WRITE_AVS_REG_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSCr(unit, i,
   2229                     regval[n]));
   2230             if (cached) {
   2231                 avs->cent_hi_thr_cache[i] = regval[n];
   2232             }
   2233         } else {
   2234             SOC_IF_ERROR_RETURN(
   2235                 WRITE_AVS_REG_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSCr(unit, i,
   2236                     regval[n]));
   2237             if (cached) {
   2238                 avs->cent_lo_thr_cache[i] = regval[n];
   2239             }
   2240         }
   2241     }
   2242     return SOC_E_NONE;
   2243 }
   2244 
   2245 #if AVS_LEGACY_THRESHOLD
   2246 /*
   2247  * Function:
   2248  *  _soc_avs_find_new_thr
   2249  * Purpose:
   2250  * Reads osc_counts, determines lowest_osc_count and programs osc_thresholds.
   2251  * Is a helper function for _soc_avs_set_new_thr.
   2252  * Parameters:
   2253  *  sel_hi_thr   - (IN)1 => hi_thr, 0 => lo_thr
   2254  *  write_rmt_osc_thr  - (IN)1 => write rmt_osc_thr
   2255  *  alloc_ptr - (OUT)points to area in mem to store osc_counts temporarily
   2256  *  rmt_osc_regval_h - (OUT)rmt_osc_regval_h
   2257  *  rmt_osc_regval_s - (OUT)rmt_osc_regval_s
   2258  * Returns:
   2259  *  SOC_E_xxx
   2260  */
   2261 STATIC int
   2262 _soc_avs_find_new_thr(int unit, soc_avs_bool_t sel_hi_thr,
   2263                       int write_rmt_osc_thr, uint32 *alloc_ptr,
   2264                       uint32 *rmt_osc_regval_h, uint32 *rmt_osc_regval_s)
   2265 {
   2266     soc_avs_info_t  *avs_info;
   2267     uint32 *rmt_osc_count_s = NULL, *rmt_osc_count_h = NULL,
   2268            *cent_osc_count = NULL, *cent_osc_thr = NULL;
   2269     uint32 lowest_count_s = SOC_AVS_ALL_ONES;
   2270     uint32 lowest_count_h = SOC_AVS_ALL_ONES;
   2271     int i;
   2272 
   2273     avs_info = SOC_AVS_INFO(unit);
   2274 
   2275     if ((alloc_ptr == NULL) || (rmt_osc_regval_h == NULL) ||
   2276             (rmt_osc_regval_s == NULL)) {
   2277         return (SOC_E_PARAM);
   2278     }
   2279 
   2280     /* Read osc_count for remote oscillators and find lowest */
   2281     rmt_osc_count_s = alloc_ptr;
   2282     rmt_osc_count_h = rmt_osc_count_s + avs_info->num_remotes;
   2283     SOC_AVS_FREE_IF_ERROR_RETURN(
   2284         _soc_avs_rmt_osc_count_get(unit,
   2285                                    avs_info->first_rmt, avs_info->num_remotes,
   2286                                    rmt_osc_count_h, rmt_osc_count_s),
   2287                                    alloc_ptr);
   2288     for (i = avs_info->first_rmt; i < avs_info->num_remotes; i++) {
   2289         if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   2290             continue;
   2291         }
   2292         if (rmt_osc_count_s[i] != 0) {
   2293             lowest_count_s = SOC_AVS_MIN(lowest_count_s, rmt_osc_count_s[i]);
   2294         }
   2295         if (rmt_osc_count_h[i] != 0) {
   2296             lowest_count_h = SOC_AVS_MIN(lowest_count_h, rmt_osc_count_h[i]);
   2297         }
   2298     }
   2299     /* Read osc_count for central oscillators and find lowest */
   2300     cent_osc_count = alloc_ptr;
   2301     SOC_IF_ERROR_RETURN(
   2302         _soc_avs_cent_osc_count_get(unit,
   2303                                     avs_info->first_cent,
   2304                                     avs_info->num_centrals, cent_osc_count));
   2305     for (i = 0; i < avs_info->num_centrals; i++) {
   2306         /* In 28nm , only oscillators 1&3 are SVT and HVT types */
   2307         /* So we can include only them in finding lowest oscillator count */
   2308         if (i != 1 && i != 3) {
   2309             continue; /*skip others*/
   2310         }
   2311         if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_CENTRAL, i)){
   2312             continue;
   2313         }
   2314         if (cent_osc_count[i] == 0) {
   2315             continue;
   2316         }
   2317         if (i == 1) {
   2318             lowest_count_s = SOC_AVS_MIN(lowest_count_s, cent_osc_count[i]);
   2319         }
   2320         if (i == 3) {
   2321             lowest_count_h = SOC_AVS_MIN(lowest_count_h, cent_osc_count[i]);
   2322         }
   2323     }
   2324     /* update thresholds for rmt_osc */
   2325     if (sel_hi_thr == SOC_AVS_BOOL_TRUE) {
   2326         soc_reg_field_set(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_H_THRESHOLDr,
   2327                           rmt_osc_regval_h, THRESH_HIf, lowest_count_h);
   2328         soc_reg_field_set(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_S_THRESHOLDr,
   2329                           rmt_osc_regval_s, THRESH_HIf, lowest_count_s);
   2330     } else {
   2331         soc_reg_field_set(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_H_THRESHOLDr,
   2332                           rmt_osc_regval_h, THRESH_LOf, lowest_count_h);
   2333         soc_reg_field_set(unit, AVS_REG_PMB_SLAVE_AVS_ROSC_S_THRESHOLDr,
   2334                           rmt_osc_regval_s, THRESH_LOf, lowest_count_s);
   2335     }
   2336 
   2337     cent_osc_thr = cent_osc_count;
   2338     for (i = avs_info->first_cent; i < avs_info->num_centrals; i++) {
   2339         /* Central #1 is SVT and #3 is HVT */
   2340         if (i == 1) {
   2341             cent_osc_thr[i] = lowest_count_s;
   2342         } else if (i == 3) {
   2343             cent_osc_thr[i] = lowest_count_h;
   2344         } else {
   2345             cent_osc_thr[i] = cent_osc_count[i];
   2346         }
   2347         if (sel_hi_thr == SOC_AVS_BOOL_TRUE) {
   2348             soc_reg_field_set(unit,
   2349                               AVS_REG_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSCr,
   2350                               cent_osc_count + i, THRESHOLDf, cent_osc_thr[i]);
   2351         } else {
   2352             soc_reg_field_set(unit,
   2353                               AVS_REG_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSCr,
   2354                               cent_osc_count + i, THRESHOLDf, cent_osc_thr[i]);
   2355         }
   2356     }
   2357     /* write thresholds for cent_osc */
   2358     SOC_IF_ERROR_RETURN(
   2359         _soc_avs_cent_osc_thr_set(unit, avs_info->first_cent,
   2360                                   avs_info->num_centrals, sel_hi_thr,
   2361                                   cent_osc_count));
   2362 
   2363     /* write thresholds for rmt_osc */
   2364     if (write_rmt_osc_thr) {
   2365         SOC_IF_ERROR_RETURN(
   2366             _soc_avs_rmt_osc_thr_set(unit,
   2367                                      avs_info->first_rmt, avs_info->num_remotes,
   2368                                      _W_OP_ALL,
   2369                                      *rmt_osc_regval_h, *rmt_osc_regval_s));
   2370     }
   2371 
   2372     return SOC_E_NONE;
   2373 }
   2374 #endif /* AVS_LEGACY_THRESHOLD */
   2375 
   2376 #define SOC_AVS_VINC_FOR_SET_NEW_THR_STEP (16)
   2377 
   2378 STATIC int
   2379 _soc_avs_set_new_thresholds(int unit)
   2380 {
   2381     soc_avs_control_t *avs;
   2382     soc_avs_info_t  *avs_info;
   2383     int32 vmarginl, vmarginh, slope_margin, intercept_margin;
   2384     uint32 reg, freq;
   2385     uint32 lower1, upper1, lower3, upper3;
   2386     int i;
   2387 
   2388     avs = SOC_AVS_CONTROL(unit);
   2389     avs_info = SOC_AVS_INFO(unit);
   2390     slope_margin = avs->slope_margin;
   2391     intercept_margin = avs->intercept_margin;
   2392     LOG_VERBOSE(BSL_LS_SOC_AVS,
   2393                 (BSL_META_U(unit,
   2394                             "slope_margin %d intercept margin %d\n"),
   2395                  slope_margin, intercept_margin));
   2396     LOG_VERBOSE(BSL_LS_SOC_AVS,
   2397                 (BSL_META_U(unit,
   2398                             "i, saved_voltage, vmarginl, vmarginh,"
   2399                             " cen_freq_thr, freq_l, reg_l, freq_h, reg_h ")));
   2400 
   2401     for (i = avs_info->first_cent; i < avs_info->num_centrals; i++) {
   2402         if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_CENTRAL, i)){
   2403             continue;
   2404         }
   2405         vmarginl = (slope_margin * avs->saved_voltage[i]) / SOC_AVS_S2 +
   2406                    intercept_margin;
   2407         /* high is 10mV higher than low */
   2408         vmarginh = vmarginl + avs->new_thr_inc;
   2409 
   2410         LOG_VERBOSE(BSL_LS_SOC_AVS,
   2411                     (BSL_META_U(unit, "%d, %d, %d, %d, %d "),
   2412                      i, avs->saved_voltage[i], vmarginl, vmarginh,
   2413                      avs->cen_freq_thr[i]));
   2414 
   2415         freq = avs->cen_freq_thr[i] +
   2416                (avs->cen_fth_slope[i] * vmarginl) / SOC_AVS_S2;
   2417         reg = _soc_avs_freq_to_reg(unit, freq);
   2418         SOC_IF_ERROR_RETURN(
   2419             _soc_avs_cent_osc_thr_set(unit, i, 1, SOC_AVS_BOOL_FALSE, &reg));
   2420 
   2421         LOG_VERBOSE(BSL_LS_SOC_AVS,
   2422                     (BSL_META_U(unit, "%d, %d, "), freq, reg));
   2423 
   2424         freq = avs->cen_freq_thr[i] +
   2425                (avs->cen_fth_slope[i] * vmarginh) / SOC_AVS_S2;
   2426         reg = _soc_avs_freq_to_reg(unit, freq);
   2427         SOC_IF_ERROR_RETURN(
   2428             _soc_avs_cent_osc_thr_set(unit, i, 1, SOC_AVS_BOOL_TRUE, &reg));
   2429 
   2430         LOG_VERBOSE(BSL_LS_SOC_AVS,
   2431                     (BSL_META_U(unit, "%d, %d \n"), freq, reg));
   2432     }
   2433 
   2434     /* All the remotes are same types as centrals 1 & 3 */
   2435     SOC_IF_ERROR_RETURN(
   2436         _soc_avs_cent_osc_thr_get(unit, 1, 1, &lower1, &upper1));
   2437     SOC_IF_ERROR_RETURN(
   2438         _soc_avs_cent_osc_thr_get(unit, 3, 1, &lower3, &upper3));
   2439 
   2440     LOG_VERBOSE(BSL_LS_SOC_AVS,
   2441                 (BSL_META_U(unit, "lower1 %d upper1 %d lower3 %d upper3 %d\n"),
   2442                  lower1, upper1, lower3, upper3));
   2443 
   2444     for (i = avs_info->first_rmt; i < avs_info->num_remotes; i++) {
   2445         if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   2446             continue;
   2447         }
   2448         SOC_IF_ERROR_RETURN(
   2449             _soc_avs_rmt_osc_thr_set(unit, i, 1, _W_OP_LO, lower3, lower1));
   2450         SOC_IF_ERROR_RETURN(
   2451             _soc_avs_rmt_osc_thr_set(unit, i, 1, _W_OP_HI, upper3, upper1));
   2452     }
   2453     avs->flags |= SOC_AVS_F_THRESHOLD_SET;
   2454     return SOC_E_NONE;
   2455 }
   2456 
   2457 #if AVS_LEGACY_THRESHOLD
   2458 /*
   2459  * Function:
   2460  *  _soc_avs_set_new_thr
   2461  * Purpose:
   2462  *  Finds lowest_count for cur_dac_code and sets lo_thr for all osc to
   2463  *  this value. Changes voltage to cur_dac_code+OFFSET, finds new lowest_count
   2464  *  and sets hi_thr for all osc to this value.
   2465  * Parameters:
   2466  *  vavs_sv   - (IN)Voltage at which lo_thr is determined.
   2467  * Returns:
   2468  *  SOC_E_xxx
   2469  */
   2470 STATIC int
   2471 _soc_avs_set_new_thr(int unit, uint32 vavs_sv)
   2472 {
   2473     uint32 current_voltage; /* current_dac; */
   2474     uint32 read_voltage;
   2475     soc_avs_bool_t sel_hi_thr, write_rmt_osc_thr;
   2476     uint32 rmt_osc_regval_h, rmt_osc_regval_s;
   2477     int alloc_size;
   2478     uint32 *alloc_ptr = NULL;
   2479     soc_avs_info_t *avs_info = SOC_AVS_INFO(unit);
   2480     soc_avs_control_t *avs = SOC_AVS_CONTROL(unit);
   2481 
   2482     if ((SOC_AVS_INFO(unit)->avs_flags & SOC_AVS_INFO_F_SET_THRESHOLDS) == 0) {
   2483         return (SOC_E_NONE);
   2484     }
   2485 
   2486     /* allocate memory */
   2487     alloc_size = 2 * SOC_AVS_MAX(avs_info->num_centrals, avs_info->num_remotes) *
   2488                  sizeof(uint32);
   2489     if ((alloc_ptr = (uint32 *)sal_alloc(alloc_size,
   2490                     "Storage for _soc_avs_set_new_thr")) == NULL) {
   2491         return (SOC_E_MEMORY);
   2492     }
   2493     /* Set the lo_thr with the smallest count found at current (low) voltage */
   2494     /* Find_and_write lo_thr for cent, find_only lo_thr for rmt */
   2495     rmt_osc_regval_h = 0, rmt_osc_regval_s = 0;
   2496 
   2497     /* get threshold low based on vavs + rw_delta */
   2498     current_voltage = vavs_sv + avs_info->rw_delta;
   2499     SOC_IF_ERROR_RETURN(soc_avs_voltage_set(unit, (uint32)current_voltage));
   2500 
   2501     if (LOG_CHECK(BSL_LS_SOC_AVS|BSL_VERBOSE)) {
   2502         SOC_AVS_FREE_IF_ERROR_RETURN(
   2503             soc_avs_voltage_get(unit, &read_voltage), alloc_ptr);
   2504     }
   2505 
   2506     SOC_AVS_FREE_IF_ERROR_RETURN(
   2507         _soc_avs_find_new_thr(unit, sel_hi_thr = SOC_AVS_BOOL_FALSE,
   2508                               write_rmt_osc_thr = FALSE, alloc_ptr,
   2509                               &rmt_osc_regval_h, &rmt_osc_regval_s),
   2510                               alloc_ptr);
   2511 
   2512     /* Now, raise the DAC (raise the voltage) to figure out the hi_thr value */
   2513     /* get threshold high based on vavs + rw_delta + new_thr_inc */
   2514     current_voltage += avs->new_thr_inc;
   2515 
   2516     LOG_INFO(BSL_LS_SOC_AVS,
   2517              (BSL_META_U(unit,
   2518                          "set voltage %d to set hi threshold\n"),
   2519               current_voltage));
   2520 
   2521     SOC_AVS_FREE_IF_ERROR_RETURN(
   2522         soc_avs_voltage_set(unit, current_voltage), alloc_ptr);
   2523     if (LOG_CHECK(BSL_LS_SOC_AVS|BSL_VERBOSE)) {
   2524         SOC_AVS_FREE_IF_ERROR_RETURN(
   2525             soc_avs_voltage_get(unit, &read_voltage), alloc_ptr);
   2526     }
   2527     /* Set the hi_thr with the smallest count found at higher voltage */
   2528     /* Find_and_write hi_thr for cent,
   2529      * find hi_thr for rmt, write hi_lo_thr for rmt */
   2530     SOC_AVS_FREE_IF_ERROR_RETURN(
   2531         _soc_avs_find_new_thr(unit, sel_hi_thr = SOC_AVS_BOOL_TRUE,
   2532                               write_rmt_osc_thr = TRUE, alloc_ptr,
   2533                               &rmt_osc_regval_h, &rmt_osc_regval_s),
   2534                               alloc_ptr);
   2535 
   2536     sal_free(alloc_ptr);
   2537 
   2538     avs->flags |= SOC_AVS_F_THRESHOLD_SET;
   2539     return (SOC_E_NONE);
   2540 }
   2541 #endif
   2542 
   2543 /*
   2544  * Function:
   2545  *  _soc_avs_start_main
   2546  * Purpose:
   2547  *  Runs initialize_oscs, find_final_voltage, set_new_thr.
   2548  * Parameters:
   2549  *
   2550  * Returns:
   2551  *  SOC_E_xxx
   2552  */
   2553 STATIC int
   2554 _soc_avs_start_main(int unit)
   2555 {
   2556     uint32 vpred = 0, vavs_sv = 0;
   2557 
   2558     SOC_IF_ERROR_RETURN(_soc_avs_initialize_oscs(unit));
   2559 
   2560     SOC_IF_ERROR_RETURN(_soc_avs_find_final_voltage(unit, &vpred, &vavs_sv));
   2561     if (vpred == 0) {
   2562         LOG_WARN(BSL_LS_SOC_AVS,
   2563                  (BSL_META_U(unit, "get the vpred=0\n")));
   2564         return (SOC_E_DISABLED);
   2565     }
   2566 
   2567 #if AVS_LEGACY_THRESHOLD
   2568     SOC_IF_ERROR_RETURN(_soc_avs_set_new_thr(unit, vavs_sv));
   2569 #endif
   2570     SOC_IF_ERROR_RETURN(_soc_avs_set_new_thresholds(unit));
   2571 
   2572     return (SOC_E_NONE);
   2573 }
   2574 
   2575 
   2576 /* This is the main entry point for AVS processing */
   2577 /* This is one-time routine that must be called during init.*/
   2578 int
   2579 soc_avs_start(int unit)
   2580 {
   2581     if (!soc_avs_inited(unit)) {
   2582         return SOC_E_INIT;
   2583     }
   2584     SOC_IF_ERROR_RETURN(_soc_avs_start_main(unit));
   2585     return (SOC_E_NONE);
   2586 }
   2587 
   2588 /* System VRM access function registeration */
   2589 int
   2590 soc_avs_vrm_access_func_register(int unit, soc_avs_vrm_access_t *vrm_access)
   2591 {
   2592     soc_avs_control_t *avs;
   2593 
   2594     soc_vrm_access_functions[unit] = vrm_access;
   2595     if (SOC_AVS_CONTROL(unit) != NULL) {
   2596         avs = SOC_AVS_CONTROL(unit);
   2597         avs->vrm_access = vrm_access;
   2598     }
   2599     return SOC_E_NONE;
   2600 }
   2601 
   2602 /*
   2603  * Default vrm info when vrm access functions are not specified.
   2604  * The default vrm should be pmbus compatiable device which driver is
   2605  * implemented in soc i2c device descriptor scheme.
   2606  */
   2607 static int
   2608 soc_avs_vrm_info_init(int unit, soc_avs_vrm_info_t *vrm_info)
   2609 {
   2610     int dev_id = 0;
   2611     int fd, rv;
   2612     i2c_driver_t *i2c_drv;
   2613 
   2614     if (vrm_info == NULL) {
   2615         return SOC_E_PARAM;
   2616     }
   2617 
   2618     if (!(vrm_info->profile.vrm_name)) {
   2619         return SOC_E_PARAM;
   2620     }
   2621     vrm_info->mux_id = -1;
   2622     vrm_info->vrm_id = -1;
   2623 
   2624     /* Access the device to check if it exists or not. */
   2625     if (vrm_info->profile.mux_name[0] != '\0') {
   2626         dev_id = soc_i2c_devopen(unit, vrm_info->profile.mux_name, 0, 0);
   2627         if (dev_id < 0) {
   2628             LOG_ERROR(BSL_LS_SOC_AVS,
   2629                       (BSL_META_U(unit, "Fail to open mux in VRM profile.\n")));
   2630             return SOC_E_FAIL;
   2631         }
   2632         vrm_info->mux_id = dev_id;
   2633     }
   2634     /* Enable mux when both mux device and its enable vlaue are specified */
   2635     if ((vrm_info->mux_id != -1) && (vrm_info->profile.mux_enable_value)) {
   2636         fd = vrm_info->mux_id;
   2637         i2c_drv = soc_i2c_device(unit, fd)->driver;
   2638         rv = i2c_drv->write(unit, vrm_info->mux_id, 0,
   2639                             &vrm_info->profile.mux_enable_value, 1);
   2640         if (SOC_FAILURE(rv)) {
   2641             LOG_ERROR(BSL_LS_SOC_AVS,
   2642                       (BSL_META_U(unit,
   2643                                   "Fail to enable mux in VRM profile.\n")));
   2644             return rv;
   2645         }
   2646     }
   2647 
   2648     if (vrm_info->profile.vrm_name[0] != '\0') {
   2649         dev_id = soc_i2c_devopen(unit, vrm_info->profile.vrm_name, 0, 0);
   2650         if (dev_id < 0) {
   2651             LOG_ERROR(BSL_LS_SOC_AVS,
   2652                       (BSL_META_U(unit, "Fail to open vrm in VRM profile.\n")));
   2653             return SOC_E_FAIL;
   2654         }
   2655         vrm_info->vrm_id = dev_id;
   2656     }
   2657 
   2658     return SOC_E_NONE;
   2659 }
   2660 
   2661 /* Specify the vrm as the default vrm */
   2662 int
   2663 soc_avs_vrm_profile_add(int unit, soc_avs_vrm_profile_t *vrm_profile)
   2664 {
   2665     soc_avs_vrm_info_t *vrm_info;
   2666 
   2667     if (SOC_AVS_CONTROL(unit) == NULL) {
   2668         return SOC_E_INIT;
   2669     }
   2670     /* Only allow one vrm profile, new one will replace the old one */
   2671     if (SOC_AVS_VRM_INFO(unit) == NULL) {
   2672         vrm_info = sal_alloc(sizeof(soc_avs_vrm_info_t), "avs vrm");
   2673         if (vrm_info == NULL) {
   2674             return SOC_E_MEMORY;
   2675         }
   2676         SOC_AVS_VRM_INFO(unit) = vrm_info;
   2677     } else {
   2678         LOG_WARN(BSL_LS_SOC_AVS,
   2679                  (BSL_META_U(unit, "VRM profile has been replaced \n")));
   2680     }
   2681 
   2682     sal_memcpy(&SOC_AVS_VRM_INFO(unit)->profile, vrm_profile,
   2683                sizeof(soc_avs_vrm_profile_t));
   2684 
   2685     return SOC_E_NONE;
   2686 }
   2687 
   2688 /*
   2689  * VRM initialization function
   2690  * If default vrm is not available or compatable with i2c pmbus driver,
   2691  * user has to register its vrm access functions.
   2692  */
   2693 int
   2694 soc_avs_vrm_init(int unit)
   2695 {
   2696     /* Check the custom registered access function */
   2697     if (SOC_AVS_VRM_ACCESS(unit) != NULL) {
   2698         if (SOC_AVS_VRM_ACCESS(unit)->vrm_init != NULL) {
   2699             return SOC_AVS_VRM_ACCESS(unit)->vrm_init(unit);
   2700         }
   2701     }
   2702     /* Try to use the pmbus vrm */
   2703     if (SOC_AVS_VRM_INFO(unit) != NULL) {
   2704         return soc_avs_vrm_info_init(unit, SOC_AVS_VRM_INFO(unit));
   2705     }
   2706     return SOC_E_UNAVAIL;
   2707 }
   2708 
   2709 int
   2710 soc_avs_vrm_deinit(int unit)
   2711 {
   2712     int rv;
   2713 
   2714     /* Check the custom registered access function */
   2715     if (SOC_AVS_VRM_ACCESS(unit) != NULL) {
   2716         if (SOC_AVS_VRM_ACCESS(unit)->vrm_deinit != NULL) {
   2717             rv = SOC_AVS_VRM_ACCESS(unit)->vrm_deinit(unit);
   2718             if (SOC_FAILURE(rv)) {
   2719                 return rv;
   2720             }
   2721         }
   2722     }
   2723     /* Try to use the pmbus vrm */
   2724     if (SOC_AVS_VRM_INFO(unit) != NULL) {
   2725         sal_free(SOC_AVS_VRM_INFO(unit));
   2726         SOC_AVS_VRM_INFO(unit) = NULL;
   2727     }
   2728     return SOC_E_NONE;
   2729 }
   2730 
   2731 /* Get the device openloop target voltage */
   2732 int
   2733 soc_avs_openloop_voltage_get(int unit, uint32 *voltage)
   2734 {
   2735     if ((SOC_AVS_FUNCTIONS(unit) != NULL) &&
   2736         (SOC_AVS_FUNCTIONS(unit)->openloop_voltage_get != NULL)) {
   2737         return SOC_AVS_FUNCTIONS(unit)->openloop_voltage_get(unit, voltage);
   2738     }
   2739     return SOC_E_UNAVAIL;
   2740 }
   2741 
   2742 int
   2743 soc_avs_openloop_main(int unit)
   2744 {
   2745     int rv;
   2746     uint32 voltage;
   2747 
   2748     if (SOC_AVS_CONTROL(unit) == NULL) {
   2749         return SOC_E_UNAVAIL;
   2750     }
   2751     if ((SOC_AVS_CONTROL(unit)->flags & SOC_AVS_F_VRM_INITED) == 0) {
   2752         rv = soc_avs_vrm_init(unit);
   2753         if (SOC_FAILURE(rv)) {
   2754             LOG_ERROR(BSL_LS_SOC_AVS,
   2755                       (BSL_META_U(unit, "Fail to init VRM !\n")));
   2756             return rv;
   2757         }
   2758         SOC_AVS_CONTROL(unit)->flags |= SOC_AVS_F_VRM_INITED;
   2759     }
   2760     rv = soc_avs_openloop_voltage_get(unit, &voltage);
   2761     if (SOC_FAILURE(rv)) {
   2762         return rv;
   2763     }
   2764     rv = soc_avs_voltage_set(unit, voltage);
   2765     if (SOC_FAILURE(rv)) {
   2766         return rv;
   2767     }
   2768     /* need to sleep a while to stabelize the voltage */
   2769     sal_usleep(SOC_AVS_OPENLOOP_DELAY);
   2770     return SOC_E_NONE;
   2771 }
   2772 
   2773 /*
   2774  * Function:
   2775  *  soc_avs_function_register
   2776  * Purpose:
   2777  *  avs_functions register function
   2778  * Parameters:
   2779  *
   2780  * Returns:
   2781  *  SOC_E_xxx
   2782  */
   2783 int
   2784 soc_avs_function_register(int unit, soc_avs_functions_t *avs_functions)
   2785 {
   2786     soc_avs_functions[unit] = avs_functions;
   2787 
   2788     /* Overwrite existed avs functions */
   2789     if (SOC_AVS_CONTROL(unit) != NULL) {
   2790         SOC_AVS_CONTROL(unit)->avs_functions = soc_avs_functions[unit];
   2791     }
   2792     return SOC_E_NONE;
   2793 }
   2794 
   2795 int
   2796 soc_avs_unregister(int unit)
   2797 {
   2798     soc_avs_functions[unit] = NULL;
   2799     return SOC_E_NONE;
   2800 }
   2801 
   2802 /*
   2803  * Function:
   2804  *  soc_avs_init
   2805  * Purpose:
   2806  *  software data structures allocation and initialization for avs module.
   2807  * Parameters:
   2808  *
   2809  * Returns:
   2810  *  SOC_E_xxx
   2811  */
   2812 int
   2813 soc_avs_init(int unit)
   2814 {
   2815     soc_avs_control_t *avs;
   2816     soc_avs_info_t  *avs_info;
   2817     int rv, i, track_step_size, new_thr_inc;
   2818     int vmin_avs;
   2819     int alloc_size;
   2820 
   2821     if (!soc_feature(unit, soc_feature_avs) &&
   2822         !soc_feature(unit, soc_feature_avs_openloop)) {
   2823         return SOC_E_UNAVAIL;
   2824     }
   2825 
   2826     if (SOC_AVS_CONTROL(unit) == NULL) {
   2827         SOC_AVS_CONTROL(unit) =
   2828             sal_alloc(sizeof(soc_avs_control_t), "avs_control");
   2829         if (SOC_AVS_CONTROL(unit) == NULL) {
   2830             return SOC_E_MEMORY;
   2831         }
   2832         sal_memset(SOC_AVS_CONTROL(unit), 0, sizeof(soc_avs_control_t));
   2833     }
   2834 
   2835     avs = SOC_AVS_CONTROL(unit);
   2836 
   2837     avs->avs_functions = soc_avs_functions[unit];
   2838     avs->vrm_access = soc_vrm_access_functions[unit];
   2839     if (soc_feature(unit, soc_feature_avs_openloop)) {
   2840         return SOC_E_NONE;
   2841     }
   2842 
   2843     /* avs_debug_xbmp, avs_debug_margin */
   2844     avs->avs_debug_xbmp = sal_alloc(sizeof(soc_avs_debug_xbmp_t), "avs_debug_xbmp");
   2845     if (avs->avs_debug_xbmp == NULL) {
   2846         sal_free(avs);
   2847         return SOC_E_MEMORY;
   2848     }
   2849     sal_memset(avs->avs_debug_xbmp, 0, sizeof(soc_avs_debug_xbmp_t));
   2850 
   2851     avs->avs_debug_margin =
   2852         sal_alloc(sizeof(soc_avs_debug_margin_t), "avs_debug_margin");
   2853     if (avs->avs_debug_margin == NULL) {
   2854         sal_free(avs->avs_debug_xbmp);
   2855         sal_free(avs);
   2856         return SOC_E_MEMORY;
   2857     }
   2858     sal_memset(avs->avs_debug_margin, 0, sizeof(soc_avs_debug_margin_t));
   2859 
   2860 
   2861     /* cen_freq_thr, rmt_freq_thr, cen_fth_slope */
   2862     avs->cen_freq_thr = _cent_freq_thr;
   2863     avs->rmt_freq_thr = _rmt_freq_thr;
   2864     avs->cen_fth_slope = _cent_fth_slope;
   2865 
   2866     avs->avs_info = sal_alloc(sizeof(soc_avs_info_t), "avs_info");
   2867     if (avs->avs_info == NULL) {
   2868         sal_free(avs->avs_debug_margin);
   2869         sal_free(avs->avs_debug_xbmp);
   2870         sal_free(avs);
   2871         return SOC_E_MEMORY;
   2872     }
   2873     sal_memset(avs->avs_info, 0, sizeof(soc_avs_info_t));
   2874 
   2875     avs_info = avs->avs_info;
   2876     /* general avs_info initialization */
   2877         /* default - disabled */
   2878     avs_info->num_centrals = 0;
   2879     avs_info->first_cent = 0;
   2880     for (i = 0; i < SOC_AVS_NUM_CENT_XBMP; i++) {
   2881         avs_info->cent_xbmp[i] = 0xFFFFFFFF;
   2882     }
   2883     avs_info->num_remotes = 0;
   2884     avs_info->first_rmt = 0;
   2885     for (i = 0; i < SOC_AVS_NUM_RMT_XBMP; i++) {
   2886         avs_info->rmt_xbmp[i] = 0xFFFFFFFF;
   2887     }
   2888     avs_info->vmin_avs = SOC_AVS_INT(SOC_AVS_DEFAULT_VMIN_AVS);
   2889     avs_info->vmax_avs = SOC_AVS_INT(SOC_AVS_DEFAULT_VMAX_AVS);
   2890     avs_info->vmargin_low  = SOC_AVS_INT(SOC_AVS_DEFAULT_VMARGIN_LOW);
   2891     avs_info->vmargin_high = SOC_AVS_INT(SOC_AVS_DEFAULT_VMARGIN_HIGH);
   2892 #ifdef BCM_SBUSDMA_SUPPORT
   2893     avs_info->cen_osc_reg = INVALIDr;
   2894     avs_info->rmt_osc_reg = INVALIDr;
   2895 #endif
   2896     if (SOC_AVS_FUNCTIONS(unit)->info_init == NULL) {
   2897         LOG_ERROR(BSL_LS_SOC_AVS,
   2898                   (BSL_META_U(unit, "no init functions registerd\n")));
   2899         sal_free(avs_info);
   2900         sal_free(avs->avs_debug_xbmp);
   2901         sal_free(avs);
   2902         return SOC_E_INTERNAL;
   2903     }
   2904     /* chip specific avs_info initialization */
   2905     rv = (SOC_AVS_FUNCTIONS(unit)->info_init)(unit, avs_info);
   2906     if (SOC_FAILURE(rv)) {
   2907         sal_free(avs->avs_debug_margin);
   2908         sal_free(avs->avs_debug_xbmp);
   2909         sal_free(avs_info);
   2910         sal_free(avs);
   2911         return rv;
   2912     }
   2913     /* avs_info checker */
   2914     if ((avs_info->num_centrals == 0) ||
   2915         (avs_info->num_centrals > 128) ||
   2916         (avs_info->num_remotes == 0) ||
   2917         (avs_info->num_remotes > 256)) {
   2918         sal_free(avs->avs_debug_margin);
   2919         sal_free(avs->avs_debug_xbmp);
   2920         sal_free(avs_info);
   2921         sal_free(avs);
   2922         return (SOC_E_PARAM);
   2923     }
   2924     /* overwrite the avs info from config */
   2925     vmin_avs = soc_property_get(unit, "avs_vmin", avs_info->vmin_avs);
   2926     avs_info->vmin_avs = vmin_avs;
   2927 
   2928     /* Create multex */
   2929     if ((avs->avsMutex = sal_mutex_create("AVS CONTROL")) == NULL) {
   2930         sal_free(avs->avs_debug_margin);
   2931         sal_free(avs->avs_debug_xbmp);
   2932         sal_free(avs_info);
   2933         sal_free(avs);
   2934         return (SOC_E_INTERNAL);
   2935     }
   2936     /* init avs track thread */
   2937     avs->avs_track_pid = SAL_THREAD_ERROR;
   2938     avs->avs_track_interval = 0;
   2939 
   2940 #ifdef BCM_SBUSDMA_SUPPORT
   2941     if (soc_feature(unit, soc_feature_sbusdma)) {
   2942         rv = soc_avs_sbusdma_desc_setup(unit);
   2943         if (rv) {
   2944             (void)soc_avs_sbusdma_desc_free(unit);
   2945             avs_info->avs_flags &= ~SOC_AVS_INFO_F_RSOC_COUNT_DMA;
   2946         }
   2947     }
   2948 #endif
   2949     alloc_size = avs_info->num_centrals * sizeof(uint32);
   2950     avs->cent_v1s_osc_cache = sal_alloc(alloc_size, "cent v1s ROSC cache");
   2951     if (avs->cent_v1s_osc_cache == NULL) {
   2952         sal_free(avs->avs_debug_margin);
   2953         sal_free(avs->avs_debug_xbmp);
   2954         sal_free(avs_info);
   2955         sal_free(avs);
   2956         return SOC_E_MEMORY;
   2957     }
   2958     sal_memset(avs->cent_v1s_osc_cache, 0, alloc_size);
   2959     alloc_size = avs_info->num_remotes * sizeof(uint32);
   2960     avs->rmt_v1s_h_osc_cache = sal_alloc(alloc_size, "remote v1s h ROSC cache");
   2961     if (avs->rmt_v1s_h_osc_cache == NULL) {
   2962         sal_free(avs->cent_v1s_osc_cache);
   2963         sal_free(avs->avs_debug_margin);
   2964         sal_free(avs->avs_debug_xbmp);
   2965         sal_free(avs_info);
   2966         sal_free(avs);
   2967         return SOC_E_MEMORY;
   2968     }
   2969     sal_memset(avs->rmt_v1s_h_osc_cache, 0, alloc_size);
   2970     avs->rmt_v1s_s_osc_cache = sal_alloc(alloc_size, "remote v1s s ROSC cache");
   2971     if (avs->rmt_v1s_s_osc_cache == NULL) {
   2972         sal_free(avs->cent_v1s_osc_cache);
   2973         sal_free(avs->rmt_v1s_h_osc_cache);
   2974         sal_free(avs->avs_debug_margin);
   2975         sal_free(avs->avs_debug_xbmp);
   2976         sal_free(avs_info);
   2977         sal_free(avs);
   2978         return SOC_E_MEMORY;
   2979     }
   2980     sal_memset(avs->rmt_v1s_s_osc_cache, 0, alloc_size);
   2981 
   2982     if (avs_info->avs_flags & SOC_AVS_INFO_F_RSOC_THRESHOLD_CACHE) {
   2983         alloc_size = avs_info->num_centrals * sizeof(uint32);
   2984         avs->cent_lo_thr_cache = sal_alloc(alloc_size, "cent ROSC lo thr cache");
   2985         if (avs->cent_lo_thr_cache == NULL) {
   2986             sal_free(avs->cent_v1s_osc_cache);
   2987             sal_free(avs->rmt_v1s_h_osc_cache);
   2988             sal_free(avs->rmt_v1s_s_osc_cache);
   2989             sal_free(avs->avs_debug_margin);
   2990             sal_free(avs->avs_debug_xbmp);
   2991             sal_free(avs_info);
   2992             sal_free(avs);
   2993             return SOC_E_MEMORY;
   2994         }
   2995         avs->cent_hi_thr_cache = sal_alloc(alloc_size, "cent ROSC hi thr cache");
   2996         if (avs->cent_hi_thr_cache == NULL) {
   2997             sal_free(avs->cent_v1s_osc_cache);
   2998             sal_free(avs->rmt_v1s_h_osc_cache);
   2999             sal_free(avs->rmt_v1s_s_osc_cache);
   3000             sal_free(avs->cent_lo_thr_cache);
   3001             sal_free(avs->avs_debug_margin);
   3002             sal_free(avs->avs_debug_xbmp);
   3003             sal_free(avs_info);
   3004             sal_free(avs);
   3005             return SOC_E_MEMORY;
   3006         }
   3007 
   3008         sal_memset(avs->cent_lo_thr_cache, 0, alloc_size);
   3009         sal_memset(avs->cent_hi_thr_cache, 0, alloc_size);
   3010 
   3011         alloc_size = avs_info->num_remotes * sizeof(uint32);
   3012         avs->rmt_h_thr_cache = sal_alloc(alloc_size, "rmt ROSC h thr cache");
   3013         if (avs->rmt_h_thr_cache == NULL) {
   3014             sal_free(avs->cent_v1s_osc_cache);
   3015             sal_free(avs->rmt_v1s_h_osc_cache);
   3016             sal_free(avs->rmt_v1s_s_osc_cache);
   3017             sal_free(avs->cent_hi_thr_cache);
   3018             sal_free(avs->cent_lo_thr_cache);
   3019             sal_free(avs->avs_debug_margin);
   3020             sal_free(avs->avs_debug_xbmp);
   3021             sal_free(avs_info);
   3022             sal_free(avs);
   3023             return SOC_E_MEMORY;
   3024         }
   3025         avs->rmt_s_thr_cache = sal_alloc(alloc_size, "rmt ROSC s thr cache");
   3026         if (avs->rmt_s_thr_cache == NULL) {
   3027             sal_free(avs->cent_v1s_osc_cache);
   3028             sal_free(avs->rmt_v1s_h_osc_cache);
   3029             sal_free(avs->rmt_v1s_s_osc_cache);
   3030             sal_free(avs->rmt_h_thr_cache);
   3031             sal_free(avs->cent_hi_thr_cache);
   3032             sal_free(avs->cent_lo_thr_cache);
   3033             sal_free(avs->avs_debug_margin);
   3034             sal_free(avs->avs_debug_xbmp);
   3035             sal_free(avs_info);
   3036             sal_free(avs);
   3037             return SOC_E_MEMORY;
   3038         }
   3039         sal_memset(avs->rmt_h_thr_cache, 0, alloc_size);
   3040         sal_memset(avs->rmt_s_thr_cache, 0, alloc_size);
   3041     }
   3042 
   3043     /* allocate saved_voltage */
   3044     alloc_size = avs_info->num_centrals * sizeof(uint32);
   3045     avs->saved_voltage = sal_alloc(alloc_size, "cent ROSC saved voltage");
   3046     if (avs->saved_voltage == NULL) {
   3047         sal_free(avs->cent_v1s_osc_cache);
   3048         sal_free(avs->rmt_v1s_h_osc_cache);
   3049         sal_free(avs->rmt_v1s_s_osc_cache);
   3050         sal_free(avs->rmt_s_thr_cache);
   3051         sal_free(avs->rmt_h_thr_cache);
   3052         sal_free(avs->cent_hi_thr_cache);
   3053         sal_free(avs->cent_lo_thr_cache);
   3054         sal_free(avs->avs_debug_margin);
   3055         sal_free(avs->avs_debug_xbmp);
   3056         sal_free(avs_info);
   3057         sal_free(avs);
   3058         return SOC_E_MEMORY;
   3059     }
   3060     sal_memset(avs->saved_voltage, 0, alloc_size);
   3061 
   3062     avs->flags |= SOC_AVS_F_INITED;
   3063 
   3064     /* track_inc_unit */
   3065     rv = soc_avs_ioctl(unit, SOC_AVS_CTRL_QUERY_TRACK_STEP_SIZE, &track_step_size, 1);
   3066 
   3067     if (SOC_FAILURE(rv)) {
   3068         /* default 3 mV*/
   3069         avs->track_step_size = 30;
   3070     } else {
   3071         avs->track_step_size = track_step_size;
   3072     }
   3073     /* overwrite the avs from config */
   3074     avs->track_step_size = soc_property_get(unit, "avs_track_step", avs->track_step_size);
   3075 
   3076     /* new_thr_inc_unit */
   3077     rv = soc_avs_ioctl(unit, SOC_AVS_CTRL_QUERY_NEW_THR_INC, &new_thr_inc, 1);
   3078 
   3079     if (SOC_FAILURE(rv)) {
   3080         /* default 10 mV */
   3081         avs->new_thr_inc = 100;
   3082     } else {
   3083         avs->new_thr_inc = new_thr_inc;
   3084     }
   3085     /* overwrite the avs info from config */
   3086     avs->new_thr_inc = soc_property_get(unit, "avs_thr_inc", avs->new_thr_inc);
   3087 
   3088     return SOC_E_NONE;
   3089 }
   3090 
   3091 /*
   3092  * Function:
   3093  *  soc_avs_deinit
   3094  * Purpose:
   3095  *  software data structures, resource de-initialization for avs module.
   3096  * Parameters:
   3097  *
   3098  * Returns:
   3099  *  SOC_E_xxx
   3100  */
   3101 int
   3102 soc_avs_deinit(int unit)
   3103 {
   3104     soc_avs_control_t *avs;
   3105 
   3106     avs = SOC_AVS_CONTROL(unit);
   3107     if (avs) {
   3108         if (SOC_AVS_FUNCTIONS(unit)->info_deinit) {
   3109             SOC_AVS_FUNCTIONS(unit)->info_deinit(unit);
   3110         }
   3111         SOC_AVS_FUNCTIONS(unit) = NULL;
   3112         (void)soc_avs_vrm_deinit(unit);
   3113         if (avs->avsMutex) {
   3114             sal_mutex_destroy(avs->avsMutex);
   3115             avs->avsMutex = NULL;
   3116         }
   3117         if (avs->avs_debug_margin) {
   3118             sal_free(avs->avs_debug_margin);
   3119         }
   3120         if (avs->avs_debug_xbmp) {
   3121             sal_free(avs->avs_debug_xbmp);
   3122         }
   3123         if (avs->avs_info) {
   3124             sal_free(avs->avs_info);
   3125         }
   3126 #ifdef BCM_SBUSDMA_SUPPORT
   3127         if (soc_feature(unit, soc_feature_sbusdma)) {
   3128             (void)soc_avs_sbusdma_desc_free(unit);
   3129         }
   3130 #endif
   3131         if(avs->rmt_s_thr_cache) {
   3132             sal_free(avs->rmt_s_thr_cache);
   3133         }
   3134         if(avs->rmt_h_thr_cache) {
   3135             sal_free(avs->rmt_h_thr_cache);
   3136         }
   3137         if(avs->cent_hi_thr_cache) {
   3138             sal_free(avs->cent_hi_thr_cache);
   3139         }
   3140         if(avs->cent_lo_thr_cache) {
   3141             sal_free(avs->cent_lo_thr_cache);
   3142         }
   3143         if(avs->cent_v1s_osc_cache) {
   3144             sal_free(avs->cent_v1s_osc_cache);
   3145         }
   3146         if(avs->rmt_v1s_h_osc_cache) {
   3147             sal_free(avs->rmt_v1s_h_osc_cache);
   3148         }
   3149         if(avs->rmt_v1s_s_osc_cache) {
   3150             sal_free(avs->rmt_v1s_s_osc_cache);
   3151         }
   3152         if(avs->saved_voltage) {
   3153             sal_free(avs->saved_voltage);
   3154         }
   3155         sal_free(avs);
   3156     }
   3157     SOC_AVS_CONTROL(unit) = NULL;
   3158 
   3159     return 0;
   3160 }
   3161 
   3162 /*
   3163  * Function:
   3164  *  soc_avs_debug_margin_set
   3165  * Purpose:
   3166  *  Mainly for CLI cmd usage to change the margin during the verification
   3167  *  If the custom margin value is set, algorithm will take this value instead
   3168  *  of chip initialized margin value.
   3169  * Parameters:
   3170  *
   3171  * Returns:
   3172  *  SOC_E_xxx
   3173  */
   3174 int
   3175 soc_avs_debug_margin_set(int unit, soc_avs_debug_margin_t *avs_debug_margin)
   3176 {
   3177     soc_avs_control_t *avs;
   3178 
   3179     if (!soc_avs_inited(unit)) {
   3180         return SOC_E_INIT;
   3181     }
   3182     avs = SOC_AVS_CONTROL(unit);
   3183 
   3184     SOC_AVS_LOCK(avs);
   3185     SOC_AVS_MARGIN(unit)->vmargin_low = avs_debug_margin->vmargin_low;
   3186     SOC_AVS_MARGIN(unit)->vmargin_high = avs_debug_margin->vmargin_high;
   3187     SOC_AVS_UNLOCK(avs);
   3188     return SOC_E_NONE;
   3189 }
   3190 
   3191 /*
   3192  * Function:
   3193  *  soc_avs_debug_margin_get
   3194  * Purpose:
   3195  *  Mainly for CLI cmd usage to get the customed margin during the verification
   3196  * Parameters:
   3197  *
   3198  * Returns:
   3199  *  SOC_E_xxx
   3200  */
   3201 int
   3202 soc_avs_debug_margin_get(int unit, soc_avs_debug_margin_t *avs_debug_margin)
   3203 {
   3204     soc_avs_control_t *avs;
   3205 
   3206     if (!soc_avs_inited(unit)) {
   3207         return SOC_E_INIT;
   3208     }
   3209     avs = SOC_AVS_CONTROL(unit);
   3210 
   3211     SOC_AVS_LOCK(avs);
   3212     avs_debug_margin->vmargin_low = SOC_AVS_MARGIN(unit)->vmargin_low;
   3213     avs_debug_margin->vmargin_high = SOC_AVS_MARGIN(unit)->vmargin_high;
   3214     SOC_AVS_UNLOCK(avs);
   3215     return SOC_E_NONE;
   3216 }
   3217 
   3218 /*
   3219  * Function:
   3220  *  soc_avs_xbmp_set
   3221  * Purpose:
   3222  *  Mainly for CLI cmd usage to config the osc exclusive bitmap
   3223  * Parameters:
   3224  *
   3225  * Returns:
   3226  *  SOC_E_xxx
   3227  */
   3228 int
   3229 soc_avs_xbmp_set(int unit, int type, int start_osc, int num_osc, int value)
   3230 {
   3231     soc_avs_control_t *avs;
   3232     int i;
   3233     if (!soc_avs_inited(unit)) {
   3234         return SOC_E_INIT;
   3235     }
   3236     avs = SOC_AVS_CONTROL(unit);
   3237 
   3238     SOC_AVS_LOCK(avs);
   3239     if (type == SOC_AVS_ROSC_TYPE_CENTRAL) {
   3240         for (i = start_osc; i < start_osc + num_osc; i++) {
   3241             if ((i >= 0) && (i / NUM_BITS_PER_XBMP < SOC_AVS_NUM_CENT_XBMP)) {
   3242                 if (value == 0) {
   3243                     SOC_AVS_XBMP(unit)->cent_xbmp[i / NUM_BITS_PER_XBMP] &= ~(0x1 <<
   3244                         (i % NUM_BITS_PER_XBMP));
   3245                 } else {
   3246                     SOC_AVS_XBMP(unit)->cent_xbmp[i / NUM_BITS_PER_XBMP] |= 0x1 <<
   3247                     (i % NUM_BITS_PER_XBMP);
   3248                 }
   3249             } else {
   3250                 SOC_AVS_UNLOCK(avs);
   3251                 return (SOC_E_FAIL);
   3252             }
   3253         }
   3254     }
   3255     if (type == SOC_AVS_ROSC_TYPE_REMOTE) {
   3256         for (i = start_osc; i < start_osc + num_osc; i++) {
   3257             if ((i >= 0) && (i / NUM_BITS_PER_XBMP < SOC_AVS_NUM_RMT_XBMP)) {
   3258                 if (value == 0) {
   3259                     SOC_AVS_XBMP(unit)->rmt_xbmp[i / NUM_BITS_PER_XBMP] &= ~(0x1 <<
   3260                             (i % NUM_BITS_PER_XBMP));
   3261                 } else {
   3262                     SOC_AVS_XBMP(unit)->rmt_xbmp[i / NUM_BITS_PER_XBMP] |=
   3263                         0x1 << (i % NUM_BITS_PER_XBMP);
   3264                 }
   3265             } else {
   3266                 SOC_AVS_UNLOCK(avs);
   3267                 return (SOC_E_FAIL);
   3268             }
   3269         }
   3270     }
   3271     SOC_AVS_UNLOCK(avs);
   3272     return SOC_E_NONE;
   3273 }
   3274 /*
   3275  * Function:
   3276  *  soc_avs_xbmp_get
   3277  * Purpose:
   3278  *  Mainly for CLI cmd usage to get the currently osc exclusive bitmap
   3279  *  which is the "OR" result of the customized value and chip initialized value
   3280  * Parameters:
   3281  *
   3282  * Returns:
   3283  *  SOC_E_xxx
   3284  */
   3285 int
   3286 soc_avs_xbmp_dump(int unit, int type)
   3287 {
   3288     int i;
   3289     if (!soc_avs_inited(unit)) {
   3290         return SOC_E_INIT;
   3291     }
   3292     if (type == SOC_AVS_ROSC_TYPE_REMOTE) {
   3293         for (i = 0; i < SOC_AVS_NUM_RMT_XBMP; i++) {
   3294             LOG_CLI((BSL_META_U(unit,
   3295                     "soc_avs_xbmp_dump: rmt_xbmp[%d] = 0x%08x\n"),
   3296                         i, (SOC_AVS_XBMP(unit)->rmt_xbmp[i] |
   3297                         SOC_AVS_INFO(unit)->rmt_xbmp[i])));
   3298         }
   3299     }
   3300     if (type == SOC_AVS_ROSC_TYPE_CENTRAL) {
   3301         for (i = 0; i < SOC_AVS_NUM_CENT_XBMP; i++) {
   3302             LOG_CLI((BSL_META_U(unit,
   3303                     "soc_avs_xbmp_dump: cent_xbmp[%d] = 0x%08x\n"),
   3304                     i, (SOC_AVS_XBMP(unit)->cent_xbmp[i] |
   3305                     SOC_AVS_INFO(unit)->cent_xbmp[i])));
   3306         }
   3307     }
   3308     return (SOC_E_NONE);
   3309 }
   3310 
   3311 /*
   3312  * Function:
   3313  *  _soc_avs_reset_sequencer
   3314  * Purpose:
   3315  *  Reset the sequencer and all of its calculations.
   3316  * Parameters:
   3317  *
   3318  * Returns:
   3319  *  SOC_E_xxx
   3320  */
   3321 STATIC int
   3322 _soc_avs_reset_sequencer(int unit)
   3323 {
   3324     uint32 regval, fieldval;
   3325     soc_reg_t reg;
   3326     soc_field_t field;
   3327     int i;
   3328     soc_avs_reg_info_t *osc_seq_reset_list;
   3329     soc_avs_info_t *avs_info;
   3330 
   3331     if(soc_avs_track_inited(unit)) {
   3332         return SOC_E_NONE;
   3333     }
   3334     avs_info = SOC_AVS_INFO(unit);
   3335 
   3336     SOC_AVS_IF_ERROR_NOT_UNAVAIL_RETURN(
   3337         soc_avs_ioctl(unit, SOC_AVS_CTRL_SEQUENCER_INIT, NULL, 0));
   3338 
   3339 
   3340     /* AVS_REG_HW_MNTR_SEQUENCER_INITr.SEQUENCER_INITf */
   3341     regval = 0;
   3342     reg = AVS_REG_HW_MNTR_SEQUENCER_INITr;
   3343     field = SEQUENCER_INITf;
   3344     soc_reg_field_set(unit, reg, &regval, field, 1);
   3345     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   3346     regval = 0;
   3347     soc_reg_field_set(unit, reg, &regval, field, 0);
   3348     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   3349 
   3350     SOC_AVS_IF_ERROR_NOT_UNAVAIL_RETURN(
   3351         soc_avs_ioctl(unit, SOC_AVS_CTRL_PVTMON_INIT, NULL, 0));
   3352 
   3353     /* AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr.M_INIT_PVT_MNTRf */
   3354     reg = AVS_REG_HW_MNTR_MEASUREMENTS_INIT_PVT_MNTRr;
   3355     field = M_INIT_PVT_MNTRf;
   3356     fieldval = _soc_avs_reg_field_all_ones(unit, reg, field);
   3357     regval = 0;
   3358     soc_reg_field_set(unit, reg, &regval, field, fieldval);
   3359     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   3360 
   3361    SOC_AVS_IF_ERROR_NOT_UNAVAIL_RETURN(
   3362         soc_avs_ioctl(unit, SOC_AVS_CTRL_OSC_MNTR_INIT, NULL, 0));
   3363 
   3364     /* reset cent and rmt OSCs measurement */
   3365     if (avs_info->osc_seq_reset_info) {
   3366         uint32 delay;
   3367         int rosc_count_mode;
   3368         int ref_clk_freq; /* in MHz*/
   3369         uint32 max_ref_clk_counter;
   3370 
   3371         osc_seq_reset_list = avs_info->osc_seq_reset_info;
   3372         for (i = 0; osc_seq_reset_list[i].reg_name != -1 ; i++) {
   3373             reg = osc_seq_reset_list[i].reg_name;
   3374             field = osc_seq_reset_list[i].reg_field;
   3375             regval = 0;
   3376             fieldval = _soc_avs_reg_field_all_ones(unit, reg, field);
   3377             soc_reg_field_set(unit, reg, &regval, field, fieldval);
   3378             SOC_IF_ERROR_RETURN(
   3379                 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   3380             regval = 0;
   3381             fieldval = 0;
   3382             soc_reg_field_set(unit, reg, &regval, field, fieldval);
   3383             SOC_IF_ERROR_RETURN(
   3384                 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   3385         }
   3386 
   3387         /* add delay to let all cent ROSC counts be valid*/
   3388         rosc_count_mode = avs_info->rosc_count_mode;
   3389         ref_clk_freq = avs_info->ref_clk_freq;
   3390         max_ref_clk_counter = (avs_info->measurement_time_control * 256U)
   3391                                + 255U;
   3392         /* delay in us */
   3393         delay = (max_ref_clk_counter * rosc_count_mode * avs_info->num_centrals)
   3394                  / ref_clk_freq;
   3395         /* delay in ms */
   3396         delay /= 1000;
   3397         /* delay with safe margin */
   3398         delay = delay * 2;
   3399         sal_msleep(delay);
   3400     }
   3401 
   3402    SOC_AVS_IF_ERROR_NOT_UNAVAIL_RETURN(
   3403         soc_avs_ioctl(unit, SOC_AVS_CTRL_HW_MNTR_SW_CONTROL, NULL, 0));
   3404 
   3405     /* Make sure we're not in take-over mode so sequencer will begin its
   3406      * measurements */
   3407     regval = 0;
   3408     reg = AVS_REG_HW_MNTR_SW_CONTROLSr;
   3409     soc_reg_field_set(unit, reg, &regval, SW_TAKEOVERf, 0);
   3410     soc_reg_field_set(unit, reg, &regval, SW_DO_MEASUREf, 0);
   3411     soc_reg_field_set(unit, reg, &regval, SW_SENSOR_IDXf, 0);
   3412     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   3413 
   3414     sal_msleep(SOC_AVS_SEQUENCER_DELAY);
   3415 
   3416     SOC_AVS_CONTROL(unit)->flags |= SOC_AVS_F_TRACK_INITED;
   3417     return (SOC_E_NONE);
   3418 }
   3419 
   3420 
   3421 /*
   3422  * Function:
   3423  *  _soc_avs_adjust_voltage
   3424  * Purpose:
   3425  *  If current voltage is within [Vmin_avs,Vmax_avs], last_set_voltage is
   3426  *  adjusted with adj_step. If current voltage is outside the range,
   3427  *  last_set_voltage is adjusted by adj_step in direction to bring back voltage
   3428  *  within the range (by ignoring sign of adj_step).
   3429  * Parameters:
   3430  *  adjustment_step - (IN)Positive, negative value to be added to
   3431  *                      last_set_voltage.
   3432  *  voltage_change_aborted - (OUT)TRUE if we could change voltage as requested.
   3433  * Returns:
   3434  *  SOC_E_xxx
   3435  */
   3436 STATIC int
   3437 _soc_avs_adjust_voltage(int unit, int adjustment_step, soc_avs_bool_t
   3438         *voltage_change_aborted)
   3439 {
   3440     uint32 last_set_voltage, new_set_voltage;
   3441     uint32 read_voltage;
   3442     int32 new_vmin_avs;
   3443     soc_avs_info_t *avs_info = SOC_AVS_INFO(unit);
   3444 
   3445     if (voltage_change_aborted == NULL) {
   3446         return (SOC_E_PARAM);
   3447     }
   3448     *voltage_change_aborted = SOC_AVS_BOOL_FALSE;
   3449     new_vmin_avs = avs_info->vmin_avs;
   3450 
   3451     last_set_voltage = _soc_last_set_voltage[unit];
   3452     SOC_AVS_ASSERT(last_set_voltage > 0);
   3453 
   3454     SOC_IF_ERROR_RETURN(soc_avs_voltage_get(unit, &read_voltage));
   3455 
   3456     /* Make sure we never violate the voltage max and min values */
   3457     /* Note that the adjustment step can be negative to adjust the other way */
   3458     if ((new_vmin_avs <= (int32)read_voltage) &&
   3459         ((int32)read_voltage <= avs_info->vmax_avs)) {
   3460         *voltage_change_aborted = SOC_AVS_BOOL_FALSE;
   3461         if (adjustment_step < 0) {
   3462             SOC_AVS_ASSERT(last_set_voltage > SOC_AVS_ABS(adjustment_step));
   3463         }
   3464         new_set_voltage = last_set_voltage + (uint32)adjustment_step;
   3465 
   3466         LOG_INFO(BSL_LS_SOC_AVS,
   3467                  (BSL_META_U(unit,
   3468                              "adjust step %d to voltage %d\n"),
   3469                   adjustment_step, new_set_voltage));
   3470 
   3471         SOC_IF_ERROR_RETURN(soc_avs_voltage_set(unit, new_set_voltage));
   3472 
   3473     } else {
   3474         *voltage_change_aborted = SOC_AVS_BOOL_TRUE;
   3475 
   3476         /* new algorithm says we shouldn't ALLOW the voltage to exceed its
   3477          * limits.
   3478          * So we know we're outside the safe voltage range -- bring it back */
   3479 
   3480         if ((int32)read_voltage > new_vmin_avs) {
   3481             SOC_AVS_ASSERT(last_set_voltage > SOC_AVS_ABS(adjustment_step));
   3482             new_set_voltage = last_set_voltage - SOC_AVS_ABS(adjustment_step);
   3483             LOG_WARN(BSL_LS_SOC_AVS,
   3484                      (BSL_META_U(unit,
   3485                                  "WARNING, read_voltage = %0d, is out of"
   3486                                  " limits, voltage will be decreased\n"),
   3487                       read_voltage));
   3488 
   3489         } else {
   3490             new_set_voltage = last_set_voltage + SOC_AVS_ABS(adjustment_step);
   3491             LOG_WARN(BSL_LS_SOC_AVS,
   3492                      (BSL_META_U(unit,
   3493                                  "WARNING, read_voltage = %0d, is out of"
   3494                                  " limits, voltage will be increased\n"),
   3495                       read_voltage));
   3496         }
   3497         SOC_IF_ERROR_RETURN(soc_avs_voltage_set(unit, new_set_voltage));
   3498     }
   3499     return (SOC_E_NONE);
   3500 }
   3501 #define SOC_AVS_TRACK_VINC_STEP  (2)
   3502     /* 2 step * 3 mV per step  */
   3503 #define SOC_AVS_TRACK_VDEC_STEP  (-1)
   3504     /* -1 step * 3 mV per step */
   3505 
   3506 /*
   3507  * Function:
   3508  *  _soc_avs_converge_process
   3509  * Purpose:
   3510  *  If any osc_count < lo_thr then increase the voltage.
   3511  *  Else if all osc_count are > hi_thr, then decrease the voltage.
   3512  * Parameters:
   3513  *  voltage_change_requested - (OUT)0,+1,-1 to indicated no change, inc, dec
   3514  *  voltage_change_aborted - (OUT)TRUE if we could change voltage as requested.
   3515  * Returns:
   3516  *  SOC_E_xxx
   3517  */
   3518 STATIC int
   3519 _soc_avs_converge_process(int unit, int *voltage_change_requested,
   3520         soc_avs_bool_t *voltage_change_aborted)
   3521 {
   3522     int i, alloc_size;
   3523     uint32 *posc_count = NULL, *posc_lo_thr = NULL, *posc_hi_thr = NULL;
   3524     uint32 *posc_count_h = NULL, *posc_count_s = NULL, *posc_lo_thr_h = NULL,
   3525            *posc_hi_thr_h = NULL, *posc_lo_thr_s = NULL, *posc_hi_thr_s = NULL;
   3526     soc_avs_bool_t inc_voltage = SOC_AVS_BOOL_FALSE,
   3527                    found_one_osc_below_hi_thr = SOC_AVS_BOOL_FALSE;
   3528     uint32 *alloc_ptr = NULL;
   3529     int inc_val, dec_val;
   3530     char *s = NULL, *s1 = NULL;
   3531 
   3532     soc_avs_info_t *avs_info = SOC_AVS_INFO(unit);
   3533     soc_avs_control_t *avs = SOC_AVS_CONTROL(unit);
   3534 
   3535     if ((avs->flags & SOC_AVS_F_THRESHOLD_SET) == 0) {
   3536         LOG_WARN(BSL_LS_SOC_AVS,
   3537                  (BSL_META_U(unit,
   3538                              "Threshold values are not set. "
   3539                              "Stop the _soc_avs_converge_process.\n")));
   3540         return (SOC_E_INTERNAL);
   3541     }
   3542 
   3543     if ((voltage_change_requested == NULL) ||
   3544         (voltage_change_aborted == NULL)) {
   3545         return (SOC_E_PARAM);
   3546     }
   3547     /* init outputs */
   3548     *voltage_change_aborted = SOC_AVS_BOOL_FALSE;
   3549     *voltage_change_requested = 0; /* no change */
   3550 
   3551     /* allocate memory */
   3552     alloc_size = 6 * SOC_AVS_MAX(avs_info->num_centrals, avs_info->num_remotes)
   3553                 * sizeof(uint32);
   3554     if ((alloc_ptr = (uint32 *)sal_alloc(alloc_size,
   3555                     "Storage for _soc_avs_converge_process")) == NULL) {
   3556         return (SOC_E_MEMORY);
   3557     }
   3558 
   3559     /* read all cent_osc counts, thresholds */
   3560     sal_memset(alloc_ptr, 0, alloc_size);
   3561     posc_count = alloc_ptr;
   3562     posc_hi_thr = posc_count + avs_info->num_centrals;
   3563     posc_lo_thr = posc_hi_thr + avs_info->num_centrals;
   3564 
   3565     SOC_AVS_FREE_IF_ERROR_RETURN(
   3566         _soc_avs_cent_osc_count_get(unit, avs_info->first_cent,
   3567                                     avs_info->num_centrals, posc_count),
   3568                                     alloc_ptr);
   3569 
   3570     SOC_AVS_FREE_IF_ERROR_RETURN(
   3571         _soc_avs_cent_osc_thr_get(unit, avs_info->first_cent,
   3572                                   avs_info->num_centrals, posc_lo_thr,
   3573                                   posc_hi_thr), alloc_ptr);
   3574     LOG_VERBOSE(BSL_LS_SOC_AVS,
   3575                 (BSL_META_U(unit,
   3576                             "index, osc_count, [lo_thr, hi_thr], +/-/ \n")));
   3577 
   3578     /* Process cent_osc counts, thresholds */
   3579     for (i = avs_info->first_cent; i < avs_info->num_centrals; i++) {
   3580         /* skip the items we are excluding */
   3581         if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_CENTRAL, i)){
   3582             continue;
   3583         }
   3584         if (posc_count[i] == 0) {
   3585             continue;
   3586         }
   3587         /* this should have already been handled by exclude list, but ... */
   3588         if (LOG_CHECK(BSL_LS_SOC_AVS|BSL_VERBOSE)) {
   3589             if (posc_count[i] < posc_lo_thr[i]) {
   3590                 s = "-";
   3591             } else if (posc_count[i] > posc_hi_thr[i]) {
   3592                 s = "+";
   3593             } else {
   3594                 s = " ";
   3595             }
   3596         }
   3597         LOG_VERBOSE(BSL_LS_SOC_AVS,
   3598                     (BSL_META_U(unit, "%d, %d, [%d, %d], %s\n"),
   3599                      i, posc_count[i], posc_lo_thr[i], posc_hi_thr[i], s));
   3600 
   3601         if ((posc_lo_thr[i] != 0) &&
   3602             (posc_count[i] < posc_lo_thr[i])) {
   3603             inc_voltage = SOC_AVS_BOOL_TRUE;
   3604         } else if ((posc_hi_thr[i] != 0) &&
   3605                    (posc_count[i] <= posc_hi_thr[i])) {
   3606             found_one_osc_below_hi_thr = SOC_AVS_BOOL_TRUE;
   3607         }
   3608     }
   3609 
   3610     /* read all rmt_osc counts, thresholds */
   3611     sal_memset(alloc_ptr, 0, alloc_size);
   3612     posc_count_h = alloc_ptr;
   3613     posc_count_s = posc_count_h + avs_info->num_remotes;
   3614     posc_hi_thr_h = posc_count_s + avs_info->num_remotes;
   3615     posc_lo_thr_h = posc_hi_thr_h + avs_info->num_remotes;
   3616     posc_hi_thr_s = posc_lo_thr_h + avs_info->num_remotes;
   3617     posc_lo_thr_s = posc_hi_thr_s + avs_info->num_remotes;
   3618 
   3619     SOC_AVS_FREE_IF_ERROR_RETURN(
   3620         _soc_avs_rmt_osc_count_get(unit, avs_info->first_rmt,
   3621                                    avs_info->num_remotes,
   3622                                    posc_count_h, posc_count_s), alloc_ptr);
   3623 
   3624     SOC_AVS_FREE_IF_ERROR_RETURN(
   3625         _soc_avs_rmt_osc_thr_get(unit, avs_info->first_rmt,
   3626                                  avs_info->num_remotes, posc_lo_thr_h,
   3627                                  posc_hi_thr_h, posc_lo_thr_s, posc_hi_thr_s),
   3628                                  alloc_ptr);
   3629     LOG_VERBOSE(BSL_LS_SOC_AVS,
   3630                 (BSL_META_U(unit,
   3631                             "index, osc_count_h , [lo_thr_h, hi_thr_h], "
   3632                             "osc_count_s, [lo_thr_s, hi_thr_s], +/-/ ,+/-/ \n")));
   3633 
   3634     /* Process remote_osc counts, thresholds */
   3635     for (i = avs_info->first_rmt; i < avs_info->num_remotes; i++) {
   3636         /* skip the items we are excluding */
   3637         if (_soc_avs_xbmp_check(unit, SOC_AVS_ROSC_TYPE_REMOTE, i)){
   3638             continue;
   3639         }
   3640 
   3641         /*if we didn't get a value then this is an unimplemented oscillator*/
   3642         /* this should have already been handled by exclude list */
   3643         if ((posc_count_h[i] == 0) || (posc_count_s[i] == 0)) {
   3644             continue;
   3645         }
   3646         if (LOG_CHECK(BSL_LS_SOC_AVS|BSL_VERBOSE)) {
   3647             if (posc_count_h[i] < posc_lo_thr_h[i]) {
   3648                 s = "-";
   3649             } else if (posc_count_h[i] > posc_hi_thr_h[i]) {
   3650                 s = "+";
   3651             } else {
   3652                 s = " ";
   3653             }
   3654             if (posc_count_s[i] < posc_lo_thr_s[i]) {
   3655                 s1 = "-";
   3656             } else if (posc_count_s[i] > posc_hi_thr_s[i]) {
   3657                 s1 = "+";
   3658             } else {
   3659                 s1 = " ";
   3660             }
   3661         }
   3662         LOG_VERBOSE(BSL_LS_SOC_AVS,
   3663                     (BSL_META_U(unit, "%d, %d, [%d, %d], %d, [%d, %d], %s, %s\n"),
   3664                      i, posc_count_h[i], posc_lo_thr_h[i], posc_hi_thr_h[i],
   3665                      posc_count_s[i], posc_lo_thr_s[i], posc_hi_thr_s[i],
   3666                      s, s1));
   3667 
   3668         if (((posc_lo_thr_s[i] != 0) &&
   3669              (posc_count_s[i] < posc_lo_thr_s[i])) ||
   3670             ((posc_lo_thr_h[i] != 0) &&
   3671              (posc_count_h[i] < posc_lo_thr_h[i]))) {
   3672             inc_voltage = SOC_AVS_BOOL_TRUE;
   3673 
   3674         } else if (((posc_hi_thr_s[i] != 0) &&
   3675                     (posc_count_s[i] <= posc_hi_thr_s[i])) ||
   3676                    ((posc_hi_thr_h[i] != 0) &&
   3677                     (posc_count_h[i] <= posc_hi_thr_h[i]))) {
   3678             found_one_osc_below_hi_thr = SOC_AVS_BOOL_TRUE;
   3679         }
   3680     }
   3681     if (inc_voltage == SOC_AVS_BOOL_TRUE) {
   3682         /* we raise the voltage by raising the DAC */
   3683         *voltage_change_requested = +1; /* inc */
   3684         inc_val = SOC_AVS_TRACK_VINC_STEP * avs->track_step_size;
   3685         SOC_AVS_FREE_IF_ERROR_RETURN(
   3686             _soc_avs_adjust_voltage(unit, inc_val, voltage_change_aborted),
   3687                                     alloc_ptr);
   3688     } else if (found_one_osc_below_hi_thr == SOC_AVS_BOOL_FALSE) {
   3689         /* we lower the voltage by lowering the DAC */
   3690         *voltage_change_requested = -1; /* dec */
   3691         dec_val = SOC_AVS_TRACK_VDEC_STEP * avs->track_step_size;
   3692         SOC_AVS_FREE_IF_ERROR_RETURN(
   3693             _soc_avs_adjust_voltage(unit, dec_val, voltage_change_aborted),
   3694                                     alloc_ptr);
   3695     }
   3696 
   3697     sal_free(alloc_ptr);
   3698     return (SOC_E_NONE);
   3699 }
   3700 /*
   3701  * Function:
   3702  *  soc_avs_track
   3703  * Purpose:
   3704  *  Reset sequencer and invoke _soc_avs_converge_process function.
   3705  *  This function will be called periodically when system is running.
   3706  */
   3707 int
   3708 soc_avs_track(int unit)
   3709 {
   3710     int voltage_change_requested;
   3711     soc_avs_bool_t voltage_change_aborted;
   3712 
   3713     if (!soc_avs_inited(unit)) {
   3714         return SOC_E_INIT;
   3715     }
   3716 
   3717     SOC_IF_ERROR_RETURN(_soc_avs_reset_sequencer(unit));
   3718 
   3719     SOC_IF_ERROR_RETURN(
   3720         _soc_avs_converge_process(unit,
   3721                                   &voltage_change_requested,
   3722                                   &voltage_change_aborted));
   3723 
   3724     LOG_INFO(BSL_LS_SOC_AVS,
   3725              (BSL_META_U(unit,
   3726                          "voltage_change_requested=%0d, "
   3727                          "voltage_change_aborted=%0d, last_set_voltage=%0d\n"),
   3728               voltage_change_requested, voltage_change_aborted,
   3729               _soc_last_set_voltage[unit]));
   3730 
   3731     return SOC_E_NONE;
   3732 }
   3733 void soc_avs_thread(void *unit_vp)
   3734 {
   3735     int unit = PTR_TO_INT(unit_vp);
   3736     soc_avs_control_t *avs = SOC_AVS_CONTROL(unit);
   3737     int rv = SOC_E_NONE;
   3738     int interval;
   3739 
   3740     while ((interval = avs->avs_track_interval) != 0) {
   3741 #ifdef SOC_AVS_DEBUG
   3742         sal_usecs_t     start_time;
   3743 #endif
   3744         LOG_VERBOSE(BSL_LS_SOC_AVS,
   3745                     (BSL_META_U(unit, "sleep %d\n"), interval));
   3746 
   3747         (void)sal_sem_take(avs->avs_track_notify, interval);
   3748 
   3749         if (avs->avs_track_interval == 0) {       /* Exit signaled */
   3750             break;
   3751         }
   3752 #ifdef SOC_AVS_DEBUG
   3753         start_time = sal_time_usecs();
   3754 #endif
   3755         rv = soc_avs_track(unit);
   3756 #ifdef SOC_AVS_DEBUG
   3757         LOG_VERBOSE(BSL_LS_SOC_AVS,
   3758                     (BSL_META_U(unit,
   3759                                 "Time taken for avs track: %d usec\n"),
   3760                      SAL_USECS_SUB(sal_time_usecs(), start_time)));
   3761 #endif
   3762         if (SOC_FAILURE(rv)) {
   3763             LOG_INFO(BSL_LS_SOC_AVS,
   3764                      (BSL_META_U(unit, "Fail to do avs_track\n")));
   3765         }
   3766 
   3767         if (!(avs->avs_track_interval)) {
   3768             break;
   3769         }
   3770     }
   3771     LOG_INFO(BSL_LS_SOC_AVS,
   3772              (BSL_META_U(unit,
   3773                          "exiting thread\n")));
   3774 
   3775     avs->avs_track_pid = SAL_THREAD_ERROR;
   3776     avs->avs_track_interval = 0;
   3777     sal_thread_exit(0);
   3778 }
   3779 
   3780 int
   3781 soc_avs_track_stop(int unit)
   3782 {
   3783     soc_avs_control_t *avs = SOC_AVS_CONTROL(unit);
   3784     soc_timeout_t       to;
   3785     sal_usecs_t     timeout;
   3786     int rv = SOC_E_NONE;
   3787 
   3788     if (!soc_avs_inited(unit)) {
   3789         return SOC_E_INIT;
   3790     }
   3791     LOG_INFO(BSL_LS_SOC_AVS,
   3792              (BSL_META_U(unit, "stop avs track")));
   3793     timeout = (1   * SECOND_USEC);
   3794     /* Stop thread if present */
   3795     if (avs->avs_track_interval != 0) {
   3796         avs->avs_track_interval = 0;
   3797         sal_sem_give(avs->avs_track_notify);
   3798         soc_timeout_init(&to, timeout, 0);
   3799          while ((avs->avs_track_pid) != SAL_THREAD_ERROR) {
   3800             if (soc_timeout_check(&to)) {
   3801                 LOG_ERROR(BSL_LS_SOC_AVS,
   3802                           (BSL_META_U(unit, "thread did not exit\n")));
   3803                 avs->avs_track_pid = SAL_THREAD_ERROR;
   3804                 rv = SOC_E_TIMEOUT;
   3805                 break;
   3806             }
   3807 
   3808             sal_usleep(10000);
   3809         }
   3810     }
   3811     if (NULL != avs->avs_track_notify) {
   3812         sal_sem_destroy(avs->avs_track_notify);
   3813         avs->avs_track_notify = NULL;
   3814     }
   3815     LOG_INFO(BSL_LS_SOC_AVS,
   3816              (BSL_META_U(unit, "thread stopped\n")));
   3817 
   3818     return (rv);
   3819 }
   3820 int
   3821 soc_avs_track_start(int unit, int interval)
   3822 {
   3823     soc_avs_control_t *avs = SOC_AVS_CONTROL(unit);
   3824     sal_sem_t           sem;
   3825 
   3826     if (!soc_avs_inited(unit)) {
   3827         return SOC_E_INIT;
   3828     }
   3829     LOG_INFO(BSL_LS_SOC_AVS,
   3830              (BSL_META_U(unit,
   3831                          "avs_track start with interval=%d\n"), interval));
   3832 
   3833     /* Stop if already running */
   3834     if (avs->avs_track_interval != 0) {
   3835         SOC_IF_ERROR_RETURN(soc_avs_track_stop(unit));
   3836     }
   3837 
   3838     if (interval == 0) {
   3839         return SOC_E_NONE;
   3840     }
   3841     if ((sem = avs->avs_track_notify) != NULL) {
   3842         avs->avs_track_notify = NULL;    /* Stop others from waking sem */
   3843         sal_sem_destroy(sem);           /* Then destroy it */
   3844     }
   3845 
   3846     avs->avs_track_notify = sal_sem_create("avs track notify",
   3847                                            sal_sem_BINARY, 0);
   3848 
   3849     sal_snprintf(avs->avs_track_name,
   3850                  sizeof(avs->avs_track_name),
   3851                  "bcmAVS.%d", unit);
   3852     /* Start the thread */
   3853     if (interval != 0) {
   3854         avs->avs_track_interval = interval;
   3855 
   3856         avs->avs_track_pid =
   3857             sal_thread_create(avs->avs_track_name,
   3858                               SAL_THREAD_STKSZ,
   3859                                             50,
   3860                               soc_avs_thread, INT_TO_PTR(unit));
   3861 
   3862         if (avs->avs_track_pid == SAL_THREAD_ERROR) {
   3863             avs->avs_track_interval = 0;
   3864             LOG_ERROR(BSL_LS_SOC_AVS,
   3865                       (BSL_META_U(unit, "thread create failed\n")));
   3866             return (SOC_E_INTERNAL);
   3867         }
   3868 
   3869         LOG_INFO(BSL_LS_SOC_AVS,
   3870                  (BSL_META_U(unit, "Created AVS thread\n")));
   3871     }
   3872     return SOC_E_NONE;
   3873 }
   3874 
   3875 int
   3876 soc_avs_info_dump(int unit)
   3877 {
   3878     soc_avs_control_t *avs = SOC_AVS_CONTROL(unit);
   3879     soc_avs_info_t *avs_info;
   3880     int i, xbmp_index;
   3881 
   3882     if (!soc_avs_inited(unit)) {
   3883         return SOC_E_INIT;
   3884     }
   3885     avs_info = SOC_AVS_INFO(unit);
   3886     LOG_CLI((BSL_META_U(unit,
   3887                         "Unit %d AVS Info Structure:\n"), unit));
   3888     LOG_CLI((BSL_META_U(unit,
   3889                         "\tnum_centrals = %d num_remotes = %d\n"),
   3890              avs_info->num_centrals, avs_info->num_remotes));
   3891     xbmp_index = (avs_info->num_centrals + NUM_BITS_PER_XBMP - 1)
   3892                  / NUM_BITS_PER_XBMP;
   3893     for (i = 0; i < xbmp_index; i++) {
   3894         LOG_CLI((BSL_META_U(unit,
   3895                             "\tcent_xbmp[%d] = 0x%08x\n"),
   3896                  i, avs_info->cent_xbmp[i]));
   3897     }
   3898     xbmp_index = (avs_info->num_remotes + NUM_BITS_PER_XBMP - 1)
   3899                  / NUM_BITS_PER_XBMP;
   3900     for (i = 0; i < xbmp_index; i++) {
   3901         LOG_CLI((BSL_META_U(unit,
   3902                             "\trmt_xbmp[%d] = 0x%08x\n"),
   3903                  i, avs_info->rmt_xbmp[i]));
   3904     }
   3905     LOG_CLI((BSL_META_U(unit,
   3906                         "\tvmin_avs = %d  vmax_avs = %d (in 0.1mV)\n"
   3907                         "\tvmargin_low = %d vmargin_high = %d (in 0.1mV)\n"
   3908                         "\tavs_flags = 0x%x \n"),
   3909              avs_info->vmin_avs, avs_info->vmax_avs,
   3910              avs_info->vmargin_low, avs_info->vmargin_high,
   3911              avs_info->avs_flags));
   3912     LOG_CLI((BSL_META_U(unit,
   3913                         "\tdebug_margin_low = %d debug_margin_high = %d (in 0.1mV)\n"
   3914                         "\tavs_thr_inc = %d avs_track_step = %d (in 0.1mV)\n"),
   3915              avs->avs_debug_margin->vmargin_low, avs->avs_debug_margin->vmargin_high,
   3916              avs->new_thr_inc, avs->track_step_size));
   3917     return SOC_E_NONE;
   3918 }
   3919 
   3920 #else /* INCLUDE_AVS */
   3921 
   3922 int _common_avs_c_not_empty;
   3923 
   3924 #endif /* INCLUDE_AVS */