@ -808,56 +808,87 @@ static int stm32mp1_clk_get_parent(struct stm32mp1_clk_priv *priv,
return - EINVAL ;
}
static ulong stm32mp1_read_pll_freq ( struct stm32mp1_clk_priv * priv ,
int pll_id , int div _id )
static ulong pll_get_fref_ck ( struct stm32mp1_clk_priv * priv ,
int pll_id )
{
const struct stm32mp1_clk_pll * pll = priv - > data - > pll ;
int divm , divn , divy , src ;
ulong refclk , dfout ;
u32 selr , cfgr1 , cfgr2 , fracr ;
debug ( " %s(%d, %d) \n " , __func__ , pll_id , div_id ) ;
if ( div_id > _DIV_NB )
return 0 ;
u32 selr ;
int src ;
ulong refclk ;
/* Get current refclk */
selr = readl ( priv - > base + pll [ pll_id ] . rckxselr ) ;
src = selr & RCC_SELR_SRC_MASK ;
refclk = stm32mp1_clk_get_fixed ( priv , pll [ pll_id ] . refclk [ src ] ) ;
debug ( " PLL%d : selr=%x refclk = %d kHz \n " ,
pll_id , selr , ( u32 ) ( refclk / 1000 ) ) ;
return refclk ;
}
/*
* pll_get_fvco ( ) : return the VCO or ( VCO / 2 ) frequency for the requested PLL
* - PLL1 & PLL2 = > return VCO / 2 with Fpll_y_ck = FVCO / 2 * ( DIVy + 1 )
* - PLL3 & PLL4 = > return VCO with Fpll_y_ck = FVCO / ( DIVy + 1 )
* = > in all the case Fpll_y_ck = pll_get_fvco ( ) / ( DIVy + 1 )
*/
static ulong pll_get_fvco ( struct stm32mp1_clk_priv * priv ,
int pll_id )
{
const struct stm32mp1_clk_pll * pll = priv - > data - > pll ;
int divm , divn ;
ulong refclk , fvco ;
u32 cfgr1 , fracr ;
cfgr1 = readl ( priv - > base + pll [ pll_id ] . pllxcfgr1 ) ;
cfgr2 = readl ( priv - > base + pll [ pll_id ] . pllxcfgr2 ) ;
fracr = readl ( priv - > base + pll [ pll_id ] . pllxfracr ) ;
debug ( " PLL%d : selr=%x cfgr1=%x cfgr2=%x fracr=%x \n " ,
pll_id , selr , cfgr1 , cfgr2 , fracr ) ;
divm = ( cfgr1 & ( RCC_PLLNCFGR1_DIVM_MASK ) ) > > RCC_PLLNCFGR1_DIVM_SHIFT ;
divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK ;
divy = ( cfgr2 > > RCC_PLLNCFGR2_SHIFT ( div_id ) ) & RCC_PLLNCFGR2_DIVX_MASK ;
debug ( " DIVN=%d DIVM=%d DIVY=%d \n " , divn , divm , divy ) ;
debug ( " PLL%d : cfgr1=%x fracr=%x DIVN=%d DIVM=%d \n " ,
pll_id , cfgr1 , fracr , divn , divm ) ;
src = selr & RCC_SELR_SRC_MASK ;
refclk = stm32mp1_clk_get_fixed ( priv , pll [ pll_id ] . refclk [ src ] ) ;
refclk = pll_get_fref_ck ( priv , pll_id ) ;
debug ( " refclk = %d kHz \n " , ( u32 ) ( refclk / 1000 ) ) ;
/*
* For : PLL1 & PLL2 = > VCO is * 2 but ck_pll_y is also / 2
* So same final result than PLL2 et 4
* with FRACV :
* Fck_pll_y = Fck_ref * ( ( DIVN + 1 ) + FRACV / 2 ^ 13 )
* / ( DIVM + 1 ) * ( DIVy + 1 )
/* with FRACV :
* Fvco = Fck_ref * ( ( DIVN + 1 ) + FRACV / 2 ^ 13 ) / ( DIVM + 1 )
* without FRACV
* Fck_pll_y = Fck_ref * ( ( DIVN + 1 ) / ( DIVM + 1 ) * ( DIVy + 1 )
* Fvco = Fck_ref * ( ( DIVN + 1 ) / ( DIVM + 1 )
*/
if ( fracr & RCC_PLLNFRACR_FRACLE ) {
u32 fracv = ( fracr & RCC_PLLNFRACR_FRACV_MASK )
> > RCC_PLLNFRACR_FRACV_SHIFT ;
d fout = ( ulong ) lldiv ( ( unsigned long long ) refclk *
fvc o = ( ulong ) lldiv ( ( unsigned long long ) refclk *
( ( ( divn + 1 ) < < 13 ) + fracv ) ,
( ( unsigned long long ) ( divm + 1 ) *
( divy + 1 ) ) < < 13 ) ;
( ( unsigned long long ) ( divm + 1 ) ) < < 13 ) ;
} else {
d fout = ( ulong ) ( refclk * ( divn + 1 ) / ( divm + 1 ) * ( divy + 1 ) ) ;
fvc o = ( ulong ) ( refclk * ( divn + 1 ) / ( divm + 1 ) ) ;
}
debug ( " PLL%d : %s = %ld \n " , pll_id , __func__ , fvco ) ;
return fvco ;
}
static ulong stm32mp1_read_pll_freq ( struct stm32mp1_clk_priv * priv ,
int pll_id , int div_id )
{
const struct stm32mp1_clk_pll * pll = priv - > data - > pll ;
int divy ;
ulong dfout ;
u32 cfgr2 ;
debug ( " %s(%d, %d) \n " , __func__ , pll_id , div_id ) ;
if ( div_id > = _DIV_NB )
return 0 ;
cfgr2 = readl ( priv - > base + pll [ pll_id ] . pllxcfgr2 ) ;
divy = ( cfgr2 > > RCC_PLLNCFGR2_SHIFT ( div_id ) ) & RCC_PLLNCFGR2_DIVX_MASK ;
debug ( " PLL%d : cfgr2=%x DIVY=%d \n " , pll_id , cfgr2 , divy ) ;
dfout = pll_get_fvco ( priv , pll_id ) / ( divy + 1 ) ;
debug ( " => dfout = %d kHz \n " , ( u32 ) ( dfout / 1000 ) ) ;
return dfout ;