val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift;
val &= divider->mask;
div = _get_div(divider, val); if (!div) {
WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
clk_hw_get_name(hw)); return parent_rate;
}
return DIV_ROUND_UP(parent_rate, div);
}
/* * The reverse of DIV_ROUND_UP: The maximum number which * divided by m is r
*/ #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
/* * The maximum divider we can use without overflowing * unsigned long in rate * i below
*/
maxdiv = min(ULONG_MAX / rate, maxdiv);
for (i = 1; i <= maxdiv; i++) { if (!_is_valid_div(divider, i)) continue; if (rate * i == parent_rate_saved) { /* * It's the most ideal case if the requested rate can be * divided from parent clock without needing to change * parent rate, so return the divider immediately.
*/
*best_parent_rate = parent_rate_saved; return i;
}
parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
MULT_ROUND_UP(rate, i));
now = DIV_ROUND_UP(parent_rate, i); if (now <= rate && now > best) {
bestdiv = i;
best = now;
*best_parent_rate = parent_rate;
}
}
if (div > divider->max)
div = divider->max; if (div < divider->min)
div = divider->min;
value = _get_val(divider, div);
val = ti_clk_ll_ops->clk_readl(÷r->reg);
val &= ~(divider->mask << divider->shift);
val |= value << divider->shift;
ti_clk_ll_ops->clk_writel(val, ÷r->reg);
ti_clk_latch(÷r->reg, divider->latch);
return 0;
}
/** * clk_divider_save_context - Save the divider value * @hw: pointer struct clk_hw * * Save the divider value
*/ staticint clk_divider_save_context(struct clk_hw *hw)
{ struct clk_omap_divider *divider = to_clk_omap_divider(hw);
u32 val;
val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift;
divider->context = val & divider->mask;
return 0;
}
/** * clk_divider_restore_context - restore the saved the divider value * @hw: pointer struct clk_hw * * Restore the saved the divider value
*/ staticvoid clk_divider_restore_context(struct clk_hw *hw)
{ struct clk_omap_divider *divider = to_clk_omap_divider(hw);
u32 val;
val = ti_clk_ll_ops->clk_readl(÷r->reg);
val &= ~(divider->mask << divider->shift);
val |= divider->context << divider->shift;
ti_clk_ll_ops->clk_writel(val, ÷r->reg);
}
/* Determine required size for divider table */ for (i = 0; i < num_div; i++) {
of_property_read_u32_index(node, "ti,dividers", i, &val); if (val)
valid_div++;
}
if (!valid_div) {
pr_err("no valid dividers for %pOFn table\n", node); return -EINVAL;
}
for (i = 0; i < num_div; i++) {
of_property_read_u32_index(node, "ti,dividers", i, &val); if (val) {
table[valid_div].div = val;
table[valid_div].val = i;
valid_div++;
}
}
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.