|
@@ -257,43 +257,113 @@ static void _resolve_clkdm_deps(struct clockdomain *clkdm,
|
|
|
/* Public functions */
|
|
|
|
|
|
/**
|
|
|
- * clkdm_init - set up the clockdomain layer
|
|
|
- * @clkdms: optional pointer to an array of clockdomains to register
|
|
|
- * @init_autodeps: optional pointer to an array of autodeps to register
|
|
|
- * @custom_funcs: func pointers for arch specific implementations
|
|
|
- *
|
|
|
- * Set up internal state. If a pointer to an array of clockdomains
|
|
|
- * @clkdms was supplied, loop through the list of clockdomains,
|
|
|
- * register all that are available on the current platform. Similarly,
|
|
|
- * if a pointer to an array of clockdomain autodependencies
|
|
|
- * @init_autodeps was provided, register those. No return value.
|
|
|
+ * 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;
|
|
|
+
|
|
|
+ arch_clkdm = co;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * clkdm_register_clkdms - register SoC clockdomains
|
|
|
+ * @cs: pointer to an array of struct clockdomain to register
|
|
|
+ *
|
|
|
+ * Register the clockdomains available on a particular OMAP SoC. Must
|
|
|
+ * be called after clkdm_register_platform_funcs(). May be called
|
|
|
+ * multiple times. Returns -EACCES if called before
|
|
|
+ * clkdm_register_platform_funcs(); -EINVAL if the argument @cs is
|
|
|
+ * null; or 0 upon success.
|
|
|
*/
|
|
|
-void clkdm_init(struct clockdomain **clkdms,
|
|
|
- struct clkdm_autodep *init_autodeps,
|
|
|
- struct clkdm_ops *custom_funcs)
|
|
|
+int clkdm_register_clkdms(struct clockdomain **cs)
|
|
|
{
|
|
|
struct clockdomain **c = NULL;
|
|
|
- struct clockdomain *clkdm;
|
|
|
- struct clkdm_autodep *autodep = NULL;
|
|
|
|
|
|
- if (!custom_funcs)
|
|
|
- WARN(1, "No custom clkdm functions registered\n");
|
|
|
- else
|
|
|
- arch_clkdm = custom_funcs;
|
|
|
+ if (!arch_clkdm)
|
|
|
+ return -EACCES;
|
|
|
+
|
|
|
+ if (!cs)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ for (c = cs; *c; c++)
|
|
|
+ _clkdm_register(*c);
|
|
|
|
|
|
- if (clkdms)
|
|
|
- for (c = clkdms; *c; c++)
|
|
|
- _clkdm_register(*c);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * clkdm_register_autodeps - register autodeps (if required)
|
|
|
+ * @ia: pointer to a static array of struct clkdm_autodep to register
|
|
|
+ *
|
|
|
+ * Register clockdomain "automatic dependencies." These are
|
|
|
+ * clockdomain wakeup and sleep dependencies that are automatically
|
|
|
+ * added whenever the first clock inside a clockdomain is enabled, and
|
|
|
+ * removed whenever the last clock inside a clockdomain is disabled.
|
|
|
+ * These are currently only used on OMAP3 devices, and are deprecated,
|
|
|
+ * since they waste energy. However, until the OMAP2/3 IP block
|
|
|
+ * enable/disable sequence can be converted to match the OMAP4
|
|
|
+ * sequence, they are needed.
|
|
|
+ *
|
|
|
+ * Must be called only after all of the SoC clockdomains are
|
|
|
+ * registered, since the function will resolve autodep clockdomain
|
|
|
+ * names into clockdomain pointers.
|
|
|
+ *
|
|
|
+ * The struct clkdm_autodep @ia array must be static, as this function
|
|
|
+ * does not copy the array elements.
|
|
|
+ *
|
|
|
+ * Returns -EACCES if called before any clockdomains have been
|
|
|
+ * registered, -EINVAL if called with a null @ia argument, -EEXIST if
|
|
|
+ * autodeps have already been registered, or 0 upon success.
|
|
|
+ */
|
|
|
+int clkdm_register_autodeps(struct clkdm_autodep *ia)
|
|
|
+{
|
|
|
+ struct clkdm_autodep *a = NULL;
|
|
|
+
|
|
|
+ if (list_empty(&clkdm_list))
|
|
|
+ return -EACCES;
|
|
|
+
|
|
|
+ if (!ia)
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
- autodeps = init_autodeps;
|
|
|
if (autodeps)
|
|
|
- for (autodep = autodeps; autodep->clkdm.ptr; autodep++)
|
|
|
- _autodep_lookup(autodep);
|
|
|
+ return -EEXIST;
|
|
|
+
|
|
|
+ autodeps = ia;
|
|
|
+ for (a = autodeps; a->clkdm.ptr; a++)
|
|
|
+ _autodep_lookup(a);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * clkdm_complete_init - set up the clockdomain layer
|
|
|
+ *
|
|
|
+ * Put all clockdomains into software-supervised mode; PM code should
|
|
|
+ * later enable hardware-supervised mode as appropriate. Must be
|
|
|
+ * called after clkdm_register_clkdms(). Returns -EACCES if called
|
|
|
+ * before clkdm_register_clkdms(), or 0 upon success.
|
|
|
+ */
|
|
|
+int clkdm_complete_init(void)
|
|
|
+{
|
|
|
+ struct clockdomain *clkdm;
|
|
|
+
|
|
|
+ if (list_empty(&clkdm_list))
|
|
|
+ return -EACCES;
|
|
|
|
|
|
- /*
|
|
|
- * Put all clockdomains into software-supervised mode; PM code
|
|
|
- * should later enable hardware-supervised mode as appropriate
|
|
|
- */
|
|
|
list_for_each_entry(clkdm, &clkdm_list, node) {
|
|
|
if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
|
|
|
clkdm_wakeup(clkdm);
|
|
@@ -306,6 +376,8 @@ void clkdm_init(struct clockdomain **clkdms,
|
|
|
_resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
|
|
|
clkdm_clear_all_sleepdeps(clkdm);
|
|
|
}
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|