/* * On some HW, N is set to zero on init. This value is invalid as * it would result in a division by zero. The rate can't be * calculated in this case
*/ if (n == 0) return 0;
/* * The rate provided by the setting is not an exact match, let's * try to improve the result using the fractional parameter
*/
frac = __pll_params_with_frac(req->rate, req->best_parent_rate, m, n, pll);
req->rate = __pll_params_to_rate(req->best_parent_rate, m, n, frac, pll);
/* * Keep the clock running, which was already initialized and enabled * from the bootloader stage, to avoid any glitches.
*/ if ((pll->flags & CLK_MESON_PLL_NOINIT_ENABLED) &&
meson_clk_pll_is_enabled(hw)) return 0;
if (pll->init_count) { if (MESON_PARM_APPLICABLE(&pll->rst))
meson_parm_write(clk->map, &pll->rst, 1);
/* do nothing if the PLL is already enabled */ if (clk_hw_is_enabled(hw)) return 0;
/* Make sure the pll is in reset */ if (MESON_PARM_APPLICABLE(&pll->rst))
meson_parm_write(clk->map, &pll->rst, 1);
/* Enable the pll */
meson_parm_write(clk->map, &pll->en, 1);
/* Take the pll out reset */ if (MESON_PARM_APPLICABLE(&pll->rst))
meson_parm_write(clk->map, &pll->rst, 0);
/* * Compared with the previous SoCs, self-adaption current module * is newly added for A1, keep the new power-on sequence to enable the * PLL. The sequence is: * 1. enable the pll, delay for 10us * 2. enable the pll self-adaption current module, delay for 40us * 3. enable the lock detect module
*/ if (MESON_PARM_APPLICABLE(&pll->current_en)) {
udelay(10);
meson_parm_write(clk->map, &pll->current_en, 1);
udelay(40);
}
if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
meson_parm_write(clk->map, &pll->l_detect, 1);
meson_parm_write(clk->map, &pll->l_detect, 0);
}
if (MESON_PARM_APPLICABLE(&pll->frac)) {
frac = __pll_params_with_frac(rate, parent_rate, m, n, pll);
meson_parm_write(clk->map, &pll->frac, frac);
}
/* If the pll is stopped, bail out now */ if (!enabled) return 0;
ret = meson_clk_pll_enable(hw); if (ret) {
pr_warn("%s: pll %s didn't lock, trying to set old rate %lu\n",
__func__, clk_hw_get_name(hw), old_rate); /* * FIXME: Do we really need/want this HACK ? * It looks unsafe. what happens if the clock gets into a * broken state and we can't lock back on the old_rate ? Looks * like an infinite recursion is possible
*/
meson_clk_pll_set_rate(hw, old_rate, parent_rate);
}
return ret;
}
/* * The Meson G12A PCIE PLL is fined tuned to deliver a very precise * 100MHz reference clock for the PCIe Analog PHY, and thus requires * a strict register sequence to enable the PLL. * To simplify, re-use the _init() op to enable the PLL and keep * the other ops except set_rate since the rate is fixed.
*/ conststruct clk_ops meson_clk_pcie_pll_ops = {
.init = clk_regmap_init,
.recalc_rate = meson_clk_pll_recalc_rate,
.determine_rate = meson_clk_pll_determine_rate,
.is_enabled = meson_clk_pll_is_enabled,
.enable = meson_clk_pcie_pll_enable,
.disable = meson_clk_pll_disable
};
EXPORT_SYMBOL_NS_GPL(meson_clk_pcie_pll_ops, "CLK_MESON");
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.