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

merlin16_pll_config.c (7690B)


      1 /**********************************************************************************
      2  **********************************************************************************
      3  *  File Name     :  merlin16_pll_config.c                                        *
      4  *  Created On    :  14/07/2013                                                   *
      5  *  Created By    :  Kiran Divakar                                                *
      6  *  Description   :  Merlin16 PLL Configuration API                               *
      7  *  Revision      :    *
      8  *                                                                                *
      9  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
     10  * 
     11  * Copyright 2007-2019 Broadcom Inc. All rights reserved.                                                          *
     12  *  No portions of this material may be reproduced in any form without            *
     13  *  the written permission of:                                                    *
     14  *      Broadcom Corporation                                                      *
     15  *      5300 California Avenue                                                    *
     16  *      Irvine, CA  92617                                                         *
     17  *                                                                                *
     18  *  All information contained in this document is Broadcom Corporation            *
     19  *  company private proprietary, and trade secret.                                *
     20  */
     21 
     22 /** @file merlin16_pll_config.c
     23  * Merlin16 PLL Configuration
     24  */
     25 
     26 
     27 #include "merlin16_config.h"
     28 #include "merlin16_functions.h"
     29 #include "merlin16_internal.h"
     30 #include "merlin16_internal_error.h"
     31 #include "merlin16_select_defns.h"
     32 
     33 #define _ndiv_frac_l(x) ((x)&0xF)
     34 #define _ndiv_frac_h(x) ((x)>>4)
     35 
     36 #define _ndiv_frac_decode(l_, h_) (((l_) & 0xF) | (((h_) & 0x3FFF) << 4))
     37 
     38 static const uint8_t pll_fraction_width = 18;
     39 
     40 err_code_t merlin16_INTERNAL_configure_pll(srds_access_t *sa__,
     41                                          enum merlin16_pll_refclk_enum refclk,
     42                                          enum merlin16_pll_div_enum div,
     43                                          uint32_t vco_freq_khz,
     44                                          enum merlin16_pll_option_enum pll_option) {
     45     uint32_t refclk_freq_hz;
     46 
     47     EFUN(merlin16_INTERNAL_resolve_pll_parameters(refclk, &refclk_freq_hz, &div, &vco_freq_khz, MERLIN16_PLL_OPTION_NONE));
     48 
     49     /* Use this to restore defaults if reprogramming the PLL under dp-reset (typically Auto-Neg FW) - Need this for DUAL_PLL (see F16) */
     50     /* EFUN(wrc_ams_pll_i_ndiv_int(0x42));                   */
     51     /* EFUN(wrc_ams_pll_i_ndiv_frac_h(_ndiv_frac_h(0x0)));   */
     52     /* EFUN(wrc_ams_pll_i_ndiv_frac_l(_ndiv_frac_l(0x0)));   */
     53     /* EFUN(wrc_ams_pll_i_pll_frac_mode(0x2));               */
     54 
     55     {
     56         uint8_t reset_state;
     57         /* Use core_s_rstb to re-initialize all registers to default before calling this function. */
     58         ESTM(reset_state = rdc_core_dp_reset_state());
     59 
     60         if(reset_state < 7) {
     61             EFUN_PRINTF(("ERROR: merlin16_configure_pll(..) called without core_dp_s_rstb=0\n"));
     62             return (_error(ERR_CODE_CORE_DP_NOT_RESET));
     63         }
     64     }
     65 
     66     /* Clear PLL powerdown */
     67     EFUN(wrc_ams_pll_pwrdn(0));
     68 
     69     EFUN(wrc_ams_pll_i_ndiv_int(SRDS_INTERNAL_GET_PLL_DIV_INTEGER(div)));
     70     {
     71         const uint32_t pll_fraction_num = SRDS_INTERNAL_GET_PLL_DIV_FRACTION_NUM(div, pll_fraction_width);
     72         const uint8_t  frac_mode_en = (pll_fraction_num != 0);
     73         EFUN(wrc_ams_pll_i_ndiv_frac_h   (_ndiv_frac_h(pll_fraction_num)));
     74         EFUN(wrc_ams_pll_i_ndiv_frac_l   (_ndiv_frac_l(pll_fraction_num)));
     75         EFUN(wrc_ams_pll_sel_fp3cap      ((frac_mode_en) ? 0xF : 0x0));
     76         EFUN(wrc_ams_pll_i_pfd_offset    ((frac_mode_en) ? 0x2 : 0x0));
     77         EFUN(wrc_ams_pll_i_ndiv_dither_en((frac_mode_en && (refclk != MERLIN16_PLL_REFCLK_50MHZ)) ? 0x1 : 0x0));
     78         EFUN(wrc_ams_pll_en_8p5g         ((vco_freq_khz <= 9375000) ? 0x1 : 0x0)); /* pll_ctrl<36> */
     79         EFUN(wrc_ams_pll_en_8p5g_vco     ((vco_freq_khz <= 9375000) ? 0x1 : 0x0)); /* pll_ctrl<21> */
     80         EFUN(wrc_ams_pll_en_hcur_vco     (0x1));  /* pll_ctrl<31> */
     81         EFUN(wrc_ams_pll_refclk_in_bias  (0x3F)); /* pll_ctrl<159:154> */
     82         EFUN(wrc_ams_pll_vco_hkvco       ((vco_freq_khz <= 9375000) ? 0x1 : 0x0)); /* pll_ctrl<71>, now called VCO_HKVCO */
     83 
     84         /* Handle refclk PLL options */
     85         if (pll_option == MERLIN16_PLL_OPTION_REFCLK_DIV2_EN) {
     86             EFUN(wrc_ams_pll_refclk_div2_frc_val(1));
     87             EFUN(wrc_ams_pll_refclk_div_frc(1));
     88         } else if (pll_option == MERLIN16_PLL_OPTION_REFCLK_DIV4_EN) {
     89             EFUN(wrc_ams_pll_refclk_div4_frc_val(1));
     90             EFUN(wrc_ams_pll_refclk_div_frc(1));
     91         }
     92 
     93         /* pll_ctrl<19:16> */
     94         if (refclk == MERLIN16_PLL_REFCLK_161P1328125MHZ)
     95             if (vco_freq_khz < 9375000)         EFUN(wrc_ams_pll_curr_sel(0x3));
     96             else                                EFUN(wrc_ams_pll_curr_sel(0x5));
     97         else if (frac_mode_en)                  EFUN(wrc_ams_pll_curr_sel(0x3));
     98         else                                    EFUN(wrc_ams_pll_curr_sel(0xD));
     99                 
    100         
    101 
    102         /* pll_ctrl<11:9> */
    103         if (refclk == MERLIN16_PLL_REFCLK_161P1328125MHZ)
    104             if (vco_freq_khz < 9375000)         EFUN(wrc_ams_pll_rpar(0x2));
    105             else                                EFUN(wrc_ams_pll_rpar(0x3));
    106         else if (refclk == MERLIN16_PLL_REFCLK_156P25MHZ)
    107             if (vco_freq_khz > 12000000)        EFUN(wrc_ams_pll_rpar(0x5));
    108             else if (frac_mode_en)              EFUN(wrc_ams_pll_rpar(0x2));
    109             else                                EFUN(wrc_ams_pll_rpar(0x4));
    110         else if (refclk == MERLIN16_PLL_REFCLK_125MHZ)
    111             if (frac_mode_en)                   EFUN(wrc_ams_pll_rpar(0x2));
    112             else if (vco_freq_khz < 9375000)    EFUN(wrc_ams_pll_rpar(0x3));
    113             else                                EFUN(wrc_ams_pll_rpar(0x4));
    114         else if (refclk == MERLIN16_PLL_REFCLK_50MHZ)
    115             if (frac_mode_en)                   EFUN(wrc_ams_pll_rpar(0x1));
    116             else if (vco_freq_khz < 8500000)    EFUN(wrc_ams_pll_rpar(0x1));
    117             else if (vco_freq_khz < 9375000)    EFUN(wrc_ams_pll_rpar(0x2));
    118             else                                EFUN(wrc_ams_pll_rpar(0x3));
    119         else                                    EFUN(wrc_ams_pll_rpar(0x2));
    120 
    121     }
    122 
    123     EFUN(wrc_ams_pll_i_pll_frac_mode(0x2));
    124 
    125     /* Toggling PLL mmd reset */
    126     EFUN(wrc_ams_pll_mmd_resetb(0x0));
    127     EFUN(wrc_ams_pll_mmd_resetb(0x1));
    128 
    129     /* NOTE: Might have to add some optimized PLL control bus settings post-DVT (See 28nm merlin_pll_config.c) */
    130 
    131     /* Update core variables with the VCO rate. */
    132     {
    133         struct merlin16_uc_core_config_st core_config;
    134         EFUN(merlin16_get_uc_core_config(sa__, &core_config));
    135         core_config.vco_rate_in_Mhz = (vco_freq_khz + 500) / 1000;
    136         core_config.field.vco_rate = MHZ_TO_VCO_RATE(core_config.vco_rate_in_Mhz);
    137         EFUN(merlin16_INTERNAL_set_uc_core_config(sa__, core_config));
    138     }
    139 
    140     return (ERR_CODE_NONE);
    141 
    142 } /* merlin16_configure_pll */
    143 
    144 err_code_t merlin16_INTERNAL_read_pll_div(srds_access_t *sa__, uint32_t *div) {
    145     uint16_t ndiv_int;
    146     uint32_t ndiv_frac;
    147     ESTM(ndiv_int = rdc_ams_pll_i_ndiv_int());
    148     ESTM(ndiv_frac = _ndiv_frac_decode(rdc_ams_pll_i_ndiv_frac_l(), rdc_ams_pll_i_ndiv_frac_h()));
    149     *div = SRDS_INTERNAL_COMPOSE_PLL_DIV(ndiv_int, ndiv_frac, pll_fraction_width);
    150     return (ERR_CODE_NONE);
    151 }
    152