|
@@ -150,3 +150,110 @@ static void _autodep_lookup(struct clkdm_autodep *autodep)
|
|
|
pr_err("clockdomain: autodeps: clockdomain %s does not exist\n",
|
|
|
autodep->clkdm.name);
|
|
|
clkdm = ERR_PTR(-ENOENT);
|
|
|
+ }
|
|
|
+ autodep->clkdm.ptr = clkdm;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
|
|
|
+ * @clkdm: struct clockdomain *
|
|
|
+ *
|
|
|
+ * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
|
|
|
+ * in hardware-supervised mode. Meant to be called from clock framework
|
|
|
+ * when a clock inside clockdomain 'clkdm' is enabled. No return value.
|
|
|
+ *
|
|
|
+ * XXX autodeps are deprecated and should be removed at the earliest
|
|
|
+ * opportunity
|
|
|
+ */
|
|
|
+void _clkdm_add_autodeps(struct clockdomain *clkdm)
|
|
|
+{
|
|
|
+ struct clkdm_autodep *autodep;
|
|
|
+
|
|
|
+ if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
|
|
|
+ if (IS_ERR(autodep->clkdm.ptr))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n",
|
|
|
+ clkdm->name, autodep->clkdm.ptr->name);
|
|
|
+
|
|
|
+ clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr);
|
|
|
+ clkdm_add_wkdep(clkdm, autodep->clkdm.ptr);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm
|
|
|
+ * @clkdm: struct clockdomain *
|
|
|
+ *
|
|
|
+ * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
|
|
|
+ * in hardware-supervised mode. Meant to be called from clock framework
|
|
|
+ * when a clock inside clockdomain 'clkdm' is disabled. No return value.
|
|
|
+ *
|
|
|
+ * XXX autodeps are deprecated and should be removed at the earliest
|
|
|
+ * opportunity
|
|
|
+ */
|
|
|
+void _clkdm_del_autodeps(struct clockdomain *clkdm)
|
|
|
+{
|
|
|
+ struct clkdm_autodep *autodep;
|
|
|
+
|
|
|
+ if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
|
|
|
+ if (IS_ERR(autodep->clkdm.ptr))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n",
|
|
|
+ clkdm->name, autodep->clkdm.ptr->name);
|
|
|
+
|
|
|
+ clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr);
|
|
|
+ clkdm_del_wkdep(clkdm, autodep->clkdm.ptr);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
|
|
|
+ * @clkdm: clockdomain that we are resolving dependencies for
|
|
|
+ * @clkdm_deps: ptr to array of struct clkdm_deps to resolve
|
|
|
+ *
|
|
|
+ * Iterates through @clkdm_deps, looking up the struct clockdomain named by
|
|
|
+ * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep.
|
|
|
+ * No return value.
|
|
|
+ */
|
|
|
+static void _resolve_clkdm_deps(struct clockdomain *clkdm,
|
|
|
+ struct clkdm_dep *clkdm_deps)
|
|
|
+{
|
|
|
+ struct clkdm_dep *cd;
|
|
|
+
|
|
|
+ for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
|
|
|
+ if (cd->clkdm)
|
|
|
+ continue;
|
|
|
+ cd->clkdm = _clkdm_lookup(cd->clkdm_name);
|
|
|
+
|
|
|
+ WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen",
|
|
|
+ clkdm->name, cd->clkdm_name);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* Public functions */
|
|
|
+
|
|
|
+/**
|
|
|
+ * clkdm_register_platform_funcs - register clockdomain implementation fns
|
|
|
+ * @co: func pointers for arch specific implementations
|
|
|
+ *
|
|
|
+ * Register the list of function pointers used to implement the
|
|
|
+ * clockdomain functions on different OMAP SoCs. Should be called
|
|
|
+ * before any other clkdm_register*() function. Returns -EINVAL if
|
|
|
+ * @co is null, -EEXIST if platform functions have already been
|
|
|
+ * registered, or 0 upon success.
|
|
|
+ */
|
|
|
+int clkdm_register_platform_funcs(struct clkdm_ops *co)
|
|
|
+{
|
|
|
+ if (!co)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (arch_clkdm)
|
|
|
+ return -EEXIST;
|