|
@@ -512,3 +512,104 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|
|
|
|
|
ret = omap3_noncore_dpll_program(clk, freqsel);
|
|
|
if (!ret)
|
|
|
+ new_parent = dd->clk_ref;
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * FIXME - this is all wrong. common code handles reparenting and
|
|
|
+ * migrating prepare/enable counts. dplls should be a multiplexer
|
|
|
+ * clock and this should be a set_parent operation so that all of that
|
|
|
+ * stuff is inherited for free
|
|
|
+ */
|
|
|
+
|
|
|
+ if (!ret)
|
|
|
+ __clk_reparent(hw->clk, new_parent);
|
|
|
+
|
|
|
+ clk_disable(dd->clk_ref);
|
|
|
+ __clk_unprepare(dd->clk_ref);
|
|
|
+ clk_disable(dd->clk_bypass);
|
|
|
+ __clk_unprepare(dd->clk_bypass);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* DPLL autoidle read/set code */
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap3_dpll_autoidle_read - read a DPLL's autoidle bits
|
|
|
+ * @clk: struct clk * of the DPLL to read
|
|
|
+ *
|
|
|
+ * Return the DPLL's autoidle bits, shifted down to bit 0. Returns
|
|
|
+ * -EINVAL if passed a null pointer or if the struct clk does not
|
|
|
+ * appear to refer to a DPLL.
|
|
|
+ */
|
|
|
+u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
|
|
|
+{
|
|
|
+ const struct dpll_data *dd;
|
|
|
+ u32 v;
|
|
|
+
|
|
|
+ if (!clk || !clk->dpll_data)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ dd = clk->dpll_data;
|
|
|
+
|
|
|
+ if (!dd->autoidle_reg)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ v = __raw_readl(dd->autoidle_reg);
|
|
|
+ v &= dd->autoidle_mask;
|
|
|
+ v >>= __ffs(dd->autoidle_mask);
|
|
|
+
|
|
|
+ return v;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap3_dpll_allow_idle - enable DPLL autoidle bits
|
|
|
+ * @clk: struct clk * of the DPLL to operate on
|
|
|
+ *
|
|
|
+ * Enable DPLL automatic idle control. This automatic idle mode
|
|
|
+ * switching takes effect only when the DPLL is locked, at least on
|
|
|
+ * OMAP3430. The DPLL will enter low-power stop when its downstream
|
|
|
+ * clocks are gated. No return value.
|
|
|
+ */
|
|
|
+void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
|
|
|
+{
|
|
|
+ const struct dpll_data *dd;
|
|
|
+ u32 v;
|
|
|
+
|
|
|
+ if (!clk || !clk->dpll_data)
|
|
|
+ return;
|
|
|
+
|
|
|
+ dd = clk->dpll_data;
|
|
|
+
|
|
|
+ if (!dd->autoidle_reg)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * REVISIT: CORE DPLL can optionally enter low-power bypass
|
|
|
+ * by writing 0x5 instead of 0x1. Add some mechanism to
|
|
|
+ * optionally enter this mode.
|
|
|
+ */
|
|
|
+ v = __raw_readl(dd->autoidle_reg);
|
|
|
+ v &= ~dd->autoidle_mask;
|
|
|
+ v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
|
|
|
+ __raw_writel(v, dd->autoidle_reg);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap3_dpll_deny_idle - prevent DPLL from automatically idling
|
|
|
+ * @clk: struct clk * of the DPLL to operate on
|
|
|
+ *
|
|
|
+ * Disable DPLL automatic idle control. No return value.
|
|
|
+ */
|
|
|
+void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
|
|
|
+{
|
|
|
+ const struct dpll_data *dd;
|
|
|
+ u32 v;
|
|
|
+
|
|
|
+ if (!clk || !clk->dpll_data)
|
|
|
+ return;
|
|
|
+
|
|
|
+ dd = clk->dpll_data;
|
|
|
+
|
|
|
+ if (!dd->autoidle_reg)
|