/* * Determine the mdiv (post divider) based on the frequency ID being used. * There are 4 sources that can be used to derive the output clock rate: * - 25 MHz Crystal * - System clock * - PLL channel 0 (slow clock) * - PLL channel 1 (fast clock)
*/ staticint __get_mdiv(struct iproc_arm_pll *pll)
{ unsignedint fid; int mdiv;
u32 val;
fid = __get_fid(pll);
switch (fid) { case ARM_PLL_FID_CRYSTAL_CLK: case ARM_PLL_FID_SYS_CLK:
mdiv = 1; break;
case ARM_PLL_FID_CH0_SLOW_CLK:
val = readl(pll->base + IPROC_CLK_PLLARMC_OFFSET);
mdiv = val & IPROC_CLK_PLLARMC_MDIV_MASK; if (mdiv == 0)
mdiv = 256; break;
case ARM_PLL_FID_CH1_FAST_CLK:
val = readl(pll->base + IPROC_CLK_PLLARMCTL5_OFFSET);
mdiv = val & IPROC_CLK_PLLARMCTL5_H_MDIV_MASK; if (mdiv == 0)
mdiv = 256; break;
val = readl(pll->base + IPROC_CLK_PLLARM_OFFSET_OFFSET); if (val & (1 << IPROC_CLK_PLLARM_SW_CTL_SHIFT)) { /* * offset mode is active. Read the ndiv from the PLLARM OFFSET * register
*/
ndiv_int = (val >> IPROC_CLK_PLLARM_NDIV_INT_OFFSET_SHIFT) &
IPROC_CLK_PLLARM_NDIV_INT_OFFSET_MASK; if (ndiv_int == 0)
ndiv_int = 256;
ndiv_frac = val & IPROC_CLK_PLLARM_NDIV_FRAC_OFFSET_MASK;
} else { /* offset mode not active */
val = readl(pll->base + IPROC_CLK_PLLARMA_OFFSET);
ndiv_int = (val >> IPROC_CLK_PLLARMA_NDIV_INT_SHIFT) &
IPROC_CLK_PLLARMA_NDIV_INT_MASK; if (ndiv_int == 0)
ndiv_int = 1024;
val = readl(pll->base + IPROC_CLK_PLLARMB_OFFSET);
ndiv_frac = val & IPROC_CLK_PLLARMB_NDIV_FRAC_MASK;
}
ndiv = (ndiv_int << 20) | ndiv_frac;
return ndiv;
}
/* * The output frequency of the ARM PLL is calculated based on the ARM PLL * divider values: * pdiv = ARM PLL pre-divider * ndiv = ARM PLL multiplier * mdiv = ARM PLL post divider * * The frequency is calculated by: * ((ndiv * parent clock rate) / pdiv) / mdiv
*/ staticunsignedlong iproc_arm_pll_recalc_rate(struct clk_hw *hw, unsignedlong parent_rate)
{ struct iproc_arm_pll *pll = to_iproc_arm_pll(hw);
u32 val; int mdiv;
u64 ndiv; unsignedint pdiv;
/* in bypass mode, use parent rate */
val = readl(pll->base + IPROC_CLK_PLLARMC_OFFSET); if (val & (1 << IPROC_CLK_PLLARMC_BYPCLK_EN_SHIFT)) {
pll->rate = parent_rate; return pll->rate;
}
/* PLL needs to be locked */
val = readl(pll->base + IPROC_CLK_PLLARMA_OFFSET); if (!(val & (1 << IPROC_CLK_PLLARMA_LOCK_SHIFT))) {
pll->rate = 0; return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.