/** * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate * @clk: DPLL output struct clk * * Using parent clock DPLL data, look up DPLL state. If locked, set our * rate to the dpll_clk * 2; otherwise, just use dpll_clk. */ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, unsigned long parent_rate) { const struct dpll_data *dd; unsigned long rate; u32 v; struct clk_hw_omap *pclk = NULL; if (!parent_rate) return 0; pclk = omap3_find_clkoutx2_dpll(hw); if (!pclk) return 0; dd = pclk->dpll_data; WARN_ON(!dd->enable_mask); v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask; v >>= __ffs(dd->enable_mask); if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE)) rate = parent_rate; else rate = parent_rate * 2; return rate; }
long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { const struct dpll_data *dd; u32 v; struct clk_hw_omap *pclk = NULL; if (!*prate) return 0; pclk = omap3_find_clkoutx2_dpll(hw); if (!pclk) return 0; dd = pclk->dpll_data; /* TYPE J does not have a clkoutx2 */ if (dd->flags & DPLL_J_TYPE) { *prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate); return *prate; } WARN_ON(!dd->enable_mask); v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask; v >>= __ffs(dd->enable_mask); /* If in bypass, the rate is fixed to the bypass rate*/ if (v != OMAP3XXX_EN_DPLL_LOCKED) return *prate; if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) { unsigned long best_parent; best_parent = (rate / 2); *prate = __clk_round_rate(__clk_get_parent(hw->clk), best_parent); } return *prate * 2; }