Merge branch 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6
[pandora-kernel.git] / arch / arm / plat-omap / omap_device.c
index d2b1609..abe933c 100644 (file)
@@ -82,6 +82,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
 #define USE_WAKEUP_LAT                 0
 #define IGNORE_WAKEUP_LAT              1
 
-/*
- * OMAP_DEVICE_MAGIC: used to determine whether a struct omap_device
- * obtained via container_of() is in fact a struct omap_device
- */
-#define OMAP_DEVICE_MAGIC               0xf00dcafe
-
 /* Private functions */
 
 /**
@@ -243,6 +238,44 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
        return container_of(pdev, struct omap_device, pdev);
 }
 
+/**
+ * _add_optional_clock_alias - Add clock alias for hwmod optional clocks
+ * @od: struct omap_device *od
+ *
+ * For every optional clock present per hwmod per omap_device, this function
+ * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
+ * if an entry is already present in it with the form <dev-id=NULL, con-id=role>
+ *
+ * The function is called from inside omap_device_build_ss(), after
+ * omap_device_register.
+ *
+ * This allows drivers to get a pointer to its optional clocks based on its role
+ * by calling clk_get(<dev*>, <role>).
+ *
+ * No return value.
+ */
+static void _add_optional_clock_alias(struct omap_device *od,
+                                     struct omap_hwmod *oh)
+{
+       int i;
+
+       for (i = 0; i < oh->opt_clks_cnt; i++) {
+               struct omap_hwmod_opt_clk *oc;
+               int r;
+
+               oc = &oh->opt_clks[i];
+
+               if (!oc->_clk)
+                       continue;
+
+               r = clk_add_alias(oc->role, dev_name(&od->pdev.dev),
+                                 (char *)oc->clk, &od->pdev.dev);
+               if (r)
+                       pr_err("omap_device: %s: clk_add_alias for %s failed\n",
+                              dev_name(&od->pdev.dev), oc->role);
+       }
+}
+
 
 /* Public functions for use by core code */
 
@@ -257,12 +290,11 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
  */
 int omap_device_count_resources(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int c = 0;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               c += omap_hwmod_count_resources(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               c += omap_hwmod_count_resources(od->hwmods[i]);
 
        pr_debug("omap_device: %s: counted %d total resources across %d "
                 "hwmods\n", od->pdev.name, c, od->hwmods_cnt);
@@ -289,12 +321,11 @@ int omap_device_count_resources(struct omap_device *od)
  */
 int omap_device_fill_resources(struct omap_device *od, struct resource *res)
 {
-       struct omap_hwmod *oh;
        int c = 0;
        int i, r;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) {
-               r = omap_hwmod_fill_resources(oh, res);
+       for (i = 0; i < od->hwmods_cnt; i++) {
+               r = omap_hwmod_fill_resources(od->hwmods[i], res);
                res += r;
                c += r;
        }
@@ -414,15 +445,15 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
        od->pm_lats = pm_lats;
        od->pm_lats_cnt = pm_lats_cnt;
 
-       od->magic = OMAP_DEVICE_MAGIC;
-
        if (is_early_device)
                ret = omap_early_device_register(od);
        else
                ret = omap_device_register(od);
 
-       for (i = 0; i < oh_cnt; i++)
+       for (i = 0; i < oh_cnt; i++) {
                hwmods[i]->od = od;
+               _add_optional_clock_alias(od, hwmods[i]);
+       }
 
        if (ret)
                goto odbs_exit4;
@@ -473,6 +504,7 @@ int omap_device_register(struct omap_device *od)
 {
        pr_debug("omap_device: %s: registering\n", od->pdev.name);
 
+       od->pdev.dev.parent = &omap_device_parent;
        return platform_device_register(&od->pdev);
 }
 
@@ -566,7 +598,6 @@ int omap_device_shutdown(struct platform_device *pdev)
 {
        int ret, i;
        struct omap_device *od;
-       struct omap_hwmod *oh;
 
        od = _find_by_pdev(pdev);
 
@@ -579,8 +610,8 @@ int omap_device_shutdown(struct platform_device *pdev)
 
        ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_shutdown(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_shutdown(od->hwmods[i]);
 
        od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
 
@@ -626,18 +657,6 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
        return ret;
 }
 
-/**
- * omap_device_is_valid - Check if pointer is a valid omap_device
- * @od: struct omap_device *
- *
- * Return whether struct omap_device pointer @od points to a valid
- * omap_device.
- */
-bool omap_device_is_valid(struct omap_device *od)
-{
-       return (od && od->magic == OMAP_DEVICE_MAGIC);
-}
-
 /**
  * omap_device_get_pwrdm - return the powerdomain * associated with @od
  * @od: struct omap_device *
@@ -692,11 +711,10 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od)
  */
 int omap_device_enable_hwmods(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_enable(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_enable(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
@@ -710,11 +728,10 @@ int omap_device_enable_hwmods(struct omap_device *od)
  */
 int omap_device_idle_hwmods(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_idle(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_idle(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
@@ -729,11 +746,10 @@ int omap_device_idle_hwmods(struct omap_device *od)
  */
 int omap_device_disable_clocks(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_disable_clocks(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_disable_clocks(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
@@ -748,12 +764,22 @@ int omap_device_disable_clocks(struct omap_device *od)
  */
 int omap_device_enable_clocks(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_enable_clocks(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_enable_clocks(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
 }
+
+struct device omap_device_parent = {
+       .init_name      = "omap",
+       .parent         = &platform_bus,
+};
+
+static int __init omap_device_init(void)
+{
+       return device_register(&omap_device_parent);
+}
+core_initcall(omap_device_init);