|
@@ -414,3 +414,101 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
|
|
|
r = clkdm_clk_enable(clk->clkdm, hw->clk);
|
|
|
if (r) {
|
|
|
WARN(1,
|
|
|
+ "%s: could not enable %s's clockdomain %s: %d\n",
|
|
|
+ __func__, __clk_get_name(hw->clk),
|
|
|
+ clk->clkdm->name, r);
|
|
|
+ return r;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ parent = __clk_get_parent(hw->clk);
|
|
|
+
|
|
|
+ if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
|
|
|
+ WARN_ON(parent != dd->clk_bypass);
|
|
|
+ r = _omap3_noncore_dpll_bypass(clk);
|
|
|
+ } else {
|
|
|
+ WARN_ON(parent != dd->clk_ref);
|
|
|
+ r = _omap3_noncore_dpll_lock(clk);
|
|
|
+ }
|
|
|
+
|
|
|
+ return r;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap3_noncore_dpll_disable - instruct a DPLL to enter low-power stop
|
|
|
+ * @clk: pointer to a DPLL struct clk
|
|
|
+ *
|
|
|
+ * Instructs a non-CORE DPLL to enter low-power stop. This function is
|
|
|
+ * intended for use in struct clkops. No return value.
|
|
|
+ */
|
|
|
+void omap3_noncore_dpll_disable(struct clk_hw *hw)
|
|
|
+{
|
|
|
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
|
|
+
|
|
|
+ _omap3_noncore_dpll_stop(clk);
|
|
|
+ if (clk->clkdm)
|
|
|
+ clkdm_clk_disable(clk->clkdm, hw->clk);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* Non-CORE DPLL rate set code */
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap3_noncore_dpll_set_rate - set non-core DPLL rate
|
|
|
+ * @clk: struct clk * of DPLL to set
|
|
|
+ * @rate: rounded target rate
|
|
|
+ *
|
|
|
+ * Set the DPLL CLKOUT to the target rate. If the DPLL can enter
|
|
|
+ * low-power bypass, and the target rate is the bypass source clock
|
|
|
+ * rate, then configure the DPLL for bypass. Otherwise, round the
|
|
|
+ * target rate if it hasn't been done already, then program and lock
|
|
|
+ * the DPLL. Returns -EINVAL upon error, or 0 upon success.
|
|
|
+ */
|
|
|
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|
|
+ unsigned long parent_rate)
|
|
|
+{
|
|
|
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
|
|
+ struct clk *new_parent = NULL;
|
|
|
+ u16 freqsel = 0;
|
|
|
+ struct dpll_data *dd;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!hw || !rate)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ dd = clk->dpll_data;
|
|
|
+ if (!dd)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ __clk_prepare(dd->clk_bypass);
|
|
|
+ clk_enable(dd->clk_bypass);
|
|
|
+ __clk_prepare(dd->clk_ref);
|
|
|
+ clk_enable(dd->clk_ref);
|
|
|
+
|
|
|
+ if (__clk_get_rate(dd->clk_bypass) == rate &&
|
|
|
+ (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
|
|
|
+ pr_debug("%s: %s: set rate: entering bypass.\n",
|
|
|
+ __func__, __clk_get_name(hw->clk));
|
|
|
+
|
|
|
+ ret = _omap3_noncore_dpll_bypass(clk);
|
|
|
+ if (!ret)
|
|
|
+ new_parent = dd->clk_bypass;
|
|
|
+ } else {
|
|
|
+ if (dd->last_rounded_rate != rate)
|
|
|
+ rate = __clk_round_rate(hw->clk, rate);
|
|
|
+
|
|
|
+ if (dd->last_rounded_rate == 0)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ /* No freqsel on OMAP4 and OMAP3630 */
|
|
|
+ if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
|
|
|
+ freqsel = _omap3_dpll_compute_freqsel(clk,
|
|
|
+ dd->last_rounded_n);
|
|
|
+ WARN_ON(!freqsel);
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_debug("%s: %s: set rate: locking rate to %lu.\n",
|
|
|
+ __func__, __clk_get_name(hw->clk), rate);
|
|
|
+
|
|
|
+ ret = omap3_noncore_dpll_program(clk, freqsel);
|
|
|
+ if (!ret)
|