ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val); if (ret < 0) return ret;
return !!(val & AIC32X4_PLLEN);
}
staticint clk_aic32x4_pll_get_muldiv(struct clk_aic32x4 *pll, struct clk_aic32x4_pll_muldiv *settings)
{ /* Change to use regmap_bulk_read? */ unsignedint val; int ret;
ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val); if (ret < 0) return ret;
settings->r = val & AIC32X4_PLL_R_MASK;
settings->p = (val & AIC32X4_PLL_P_MASK) >> AIC32X4_PLL_P_SHIFT;
ret = regmap_read(pll->regmap, AIC32X4_PLLJ, &val); if (ret < 0) return ret;
settings->j = val;
ret = regmap_read(pll->regmap, AIC32X4_PLLDMSB, &val); if (ret < 0) return ret;
settings->d = val << 8;
ret = regmap_read(pll->regmap, AIC32X4_PLLDLSB, &val); if (ret < 0) return ret;
settings->d |= val;
return 0;
}
staticint clk_aic32x4_pll_set_muldiv(struct clk_aic32x4 *pll, struct clk_aic32x4_pll_muldiv *settings)
{ int ret; /* Change to use regmap_bulk_write for some if not all? */
ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
AIC32X4_PLL_R_MASK, settings->r); if (ret < 0) return ret;
ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
AIC32X4_PLL_P_MASK,
settings->p << AIC32X4_PLL_P_SHIFT); if (ret < 0) return ret;
ret = regmap_write(pll->regmap, AIC32X4_PLLJ, settings->j); if (ret < 0) return ret;
ret = regmap_write(pll->regmap, AIC32X4_PLLDMSB, (settings->d >> 8)); if (ret < 0) return ret;
ret = regmap_write(pll->regmap, AIC32X4_PLLDLSB, (settings->d & 0xff)); if (ret < 0) return ret;
return 0;
}
staticunsignedlong clk_aic32x4_pll_calc_rate( struct clk_aic32x4_pll_muldiv *settings, unsignedlong parent_rate)
{
u64 rate; /* * We scale j by 10000 to account for the decimal part of P and divide * it back out later.
*/
rate = (u64) parent_rate * settings->r *
((settings->j * 10000) + settings->d);
/* * We scale this figure by 10000 so that we can get the decimal part * of the multiplier. This is because we can't do floating point * math in the kernel.
*/
multiplier = (u64) rate * settings->p * 10000;
do_div(multiplier, parent_rate);
/* * J can't be over 64, so R can scale this. * R can't be greater than 4.
*/
settings->r = ((u32) multiplier / 640000) + 1; if (settings->r > 4) return -1;
do_div(multiplier, settings->r);
/* * J can't be < 1.
*/ if (multiplier < 10000) return -1;
/* Figure out the integer part, J, and the fractional part, D. */
settings->j = (u32) multiplier / 10000;
settings->d = (u32) multiplier % 10000;
int aic32x4_register_clocks(struct device *dev, constchar *mclk_name)
{ int i;
/* * These lines are here to preserve the current functionality of * the driver with regard to the DT. These should eventually be set * by DT nodes so that the connections can be set up in configuration * rather than code.
*/
aic32x4_clkdesc_array[0].parent_names =
(constchar* []) { mclk_name, "bclk", "gpio", "din" };
aic32x4_clkdesc_array[1].parent_names =
(constchar *[]) { mclk_name, "bclk", "gpio", "pll" };
for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
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.