|
@@ -686,3 +686,141 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
|
|
|
|
|
|
if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)
|
|
|
return 0;
|
|
|
+
|
|
|
+ return clkdm_add_sleepdep(clkdm, init_clkdm);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _del_initiator_dep: allow @oh to smart-idle even if @init_oh is active
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Allow the hardware module @oh to enter idle while the hardare
|
|
|
+ * module initiator @init_oh is active. Useful when a module will not
|
|
|
+ * be accessed by a particular initiator (e.g., if a module will not
|
|
|
+ * be accessed by the IVA, there should be no sleepdep between the IVA
|
|
|
+ * initiator and the module). Only applies to modules in smart-idle
|
|
|
+ * mode. If the clockdomain is marked as not needing autodeps, return
|
|
|
+ * 0 without doing anything. Returns -EINVAL upon error or passes
|
|
|
+ * along clkdm_del_sleepdep() value upon success.
|
|
|
+ */
|
|
|
+static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
|
|
|
+{
|
|
|
+ struct clockdomain *clkdm, *init_clkdm;
|
|
|
+
|
|
|
+ clkdm = _get_clkdm(oh);
|
|
|
+ init_clkdm = _get_clkdm(init_oh);
|
|
|
+
|
|
|
+ if (!clkdm || !init_clkdm)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return clkdm_del_sleepdep(clkdm, init_clkdm);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _init_main_clk - get a struct clk * for the the hwmod's main functional clk
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Called from _init_clocks(). Populates the @oh _clk (main
|
|
|
+ * functional clock pointer) if a main_clk is present. Returns 0 on
|
|
|
+ * success or -EINVAL on error.
|
|
|
+ */
|
|
|
+static int _init_main_clk(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!oh->main_clk)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ oh->_clk = clk_get(NULL, oh->main_clk);
|
|
|
+ if (IS_ERR(oh->_clk)) {
|
|
|
+ pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n",
|
|
|
+ oh->name, oh->main_clk);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * HACK: This needs a re-visit once clk_prepare() is implemented
|
|
|
+ * to do something meaningful. Today its just a no-op.
|
|
|
+ * If clk_prepare() is used at some point to do things like
|
|
|
+ * voltage scaling etc, then this would have to be moved to
|
|
|
+ * some point where subsystems like i2c and pmic become
|
|
|
+ * available.
|
|
|
+ */
|
|
|
+ clk_prepare(oh->_clk);
|
|
|
+
|
|
|
+ if (!_get_clkdm(oh))
|
|
|
+ pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n",
|
|
|
+ oh->name, oh->main_clk);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _init_interface_clks - get a struct clk * for the the hwmod's interface clks
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Called from _init_clocks(). Populates the @oh OCP slave interface
|
|
|
+ * clock pointers. Returns 0 on success or -EINVAL on error.
|
|
|
+ */
|
|
|
+static int _init_interface_clks(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ struct omap_hwmod_ocp_if *os;
|
|
|
+ struct list_head *p;
|
|
|
+ struct clk *c;
|
|
|
+ int i = 0;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ p = oh->slave_ports.next;
|
|
|
+
|
|
|
+ while (i < oh->slaves_cnt) {
|
|
|
+ os = _fetch_next_ocp_if(&p, &i);
|
|
|
+ if (!os->clk)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ c = clk_get(NULL, os->clk);
|
|
|
+ if (IS_ERR(c)) {
|
|
|
+ pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
|
|
|
+ oh->name, os->clk);
|
|
|
+ ret = -EINVAL;
|
|
|
+ }
|
|
|
+ os->_clk = c;
|
|
|
+ /*
|
|
|
+ * HACK: This needs a re-visit once clk_prepare() is implemented
|
|
|
+ * to do something meaningful. Today its just a no-op.
|
|
|
+ * If clk_prepare() is used at some point to do things like
|
|
|
+ * voltage scaling etc, then this would have to be moved to
|
|
|
+ * some point where subsystems like i2c and pmic become
|
|
|
+ * available.
|
|
|
+ */
|
|
|
+ clk_prepare(os->_clk);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _init_opt_clk - get a struct clk * for the the hwmod's optional clocks
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Called from _init_clocks(). Populates the @oh omap_hwmod_opt_clk
|
|
|
+ * clock pointers. Returns 0 on success or -EINVAL on error.
|
|
|
+ */
|
|
|
+static int _init_opt_clks(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ struct omap_hwmod_opt_clk *oc;
|
|
|
+ struct clk *c;
|
|
|
+ int i;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
|
|
|
+ c = clk_get(NULL, oc->clk);
|
|
|
+ if (IS_ERR(c)) {
|
|
|
+ pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
|
|
|
+ oh->name, oc->clk);
|
|
|
+ ret = -EINVAL;
|
|
|
+ }
|
|
|
+ oc->_clk = c;
|
|
|
+ /*
|
|
|
+ * HACK: This needs a re-visit once clk_prepare() is implemented
|