if (cr0 & CPG_PLLxCR0_SSMODE_FM) {
ni = div64_ul(rate, prate); if (ni < 1) {
ni = 1;
nf = 0;
} else {
ni = min(ni, 256U);
nf = div64_ul((u64)(rate - prate * ni) << 24,
parent_rate);
}
} else {
ni = DIV_ROUND_CLOSEST_ULL(rate, prate);
ni = clamp(ni, 1U, 256U);
}
if (readl(pll_clk->pllcr0_reg) & CPG_PLLxCR0_KICK) return -EBUSY;
cpg_reg_modify(pll_clk->pllcr0_reg, CPG_PLLxCR0_NI8,
FIELD_PREP(CPG_PLLxCR0_NI8, ni - 1)); if (cr0 & CPG_PLLxCR0_SSMODE_FM)
cpg_reg_modify(pll_clk->pllcr1_reg, CPG_PLLxCR1_NF25,
FIELD_PREP(CPG_PLLxCR1_NF25, nf));
/* * Set KICK bit in PLLxCR0 to update hardware setting and wait for * clock change completion.
*/
cpg_reg_modify(pll_clk->pllcr0_reg, 0, CPG_PLLxCR0_KICK);
/* * Note: There is no HW information about the worst case latency. * * Using experimental measurements, it seems that no more than * ~45 µs are needed, independently of the CPU rate. * Since this value might be dependent on external xtal rate, pll * rate or even the other emulation clocks rate, use 1000 as a * "super" safe value.
*/ return readl_poll_timeout(pll_clk->pllecr_reg, val,
val & pll_clk->pllecr_pllst_mask, 0, 1000);
}
/* * Set KICK bit in FRQCRB to update hardware setting and wait for * clock change completion.
*/
cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
/* * Note: There is no HW information about the worst case latency. * * Using experimental measurements, it seems that no more than * ~10 iterations are needed, independently of the CPU rate. * Since this value might be dependent on external xtal rate, pll1 * rate or even the other emulation clocks rate, use 1000 as a * "super" safe value.
*/ for (i = 1000; i; i--) { if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK)) return 0;
parent = clks[core->parent & 0xffff]; /* some types use high bits */ if (IS_ERR(parent)) return ERR_CAST(parent);
switch (core->type) { case CLK_TYPE_GEN4_MAIN:
div = cpg_pll_config->extal_div; break;
case CLK_TYPE_GEN4_PLL1:
mult = cpg_pll_config->pll1_mult;
div = cpg_pll_config->pll1_div; break;
case CLK_TYPE_GEN4_PLL5:
mult = cpg_pll_config->pll5_mult;
div = cpg_pll_config->pll5_div; break;
case CLK_TYPE_GEN4_PLL2X_3X:
value = readl(base + core->offset);
mult = (FIELD_GET(CPG_PLLxCR_STC, value) + 1) * 2; break;
case CLK_TYPE_GEN4_PLL_F8_25: return cpg_pll_clk_register(core->name, __clk_get_name(parent),
base, core->offset,
&cpg_pll_f8_25_clk_ops);
case CLK_TYPE_GEN4_PLL_V8_25: return cpg_pll_clk_register(core->name, __clk_get_name(parent),
base, core->offset,
&cpg_pll_v8_25_clk_ops);
case CLK_TYPE_GEN4_PLL_V9_24: /* Variable fractional 9.24 is not yet supported, using fixed */
fallthrough; case CLK_TYPE_GEN4_PLL_F9_24: return cpg_pll_clk_register(core->name, __clk_get_name(parent),
base, core->offset,
&cpg_pll_f9_24_clk_ops);
case CLK_TYPE_GEN4_Z: return cpg_z_clk_register(core->name, __clk_get_name(parent),
base, core->div, core->offset);
case CLK_TYPE_GEN4_SDSRC:
value = readl(base + CPG_SD0CKCR1);
div = FIELD_GET(CPG_SD0CKCR1_SDSRC_SEL, value) + 4; break;
case CLK_TYPE_GEN4_SDH: return cpg_sdh_clk_register(core->name, base + core->offset,
__clk_get_name(parent), notifiers);
case CLK_TYPE_GEN4_SD: return cpg_sd_clk_register(core->name, base + core->offset,
__clk_get_name(parent));
case CLK_TYPE_GEN4_MDSEL: /* * Clock selectable between two parents and two fixed dividers * using a mode pin
*/ if (cpg_mode & BIT(core->offset)) {
div = core->div & 0xffff;
} else {
parent = clks[core->parent >> 16]; if (IS_ERR(parent)) return ERR_CAST(parent);
div = core->div >> 16;
}
mult = 1; break;
case CLK_TYPE_GEN4_OSC: /* * Clock combining OSC EXTAL predivider and a fixed divider
*/
div = cpg_pll_config->osc_prediv * core->div; break;
case CLK_TYPE_GEN4_RPCSRC: return clk_register_divider_table(NULL, core->name,
__clk_get_name(parent), 0,
base + CPG_RPCCKCR, 3, 2, 0,
cpg_rpcsrc_div_table,
&cpg_lock);
case CLK_TYPE_GEN4_RPC: return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
__clk_get_name(parent), notifiers);
case CLK_TYPE_GEN4_RPCD2: return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
__clk_get_name(parent));
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.