Maemo patchset 20101501+0m5
[h-e-n] / arch / arm / mach-omap2 / omapdev.c
diff --git a/arch/arm/mach-omap2/omapdev.c b/arch/arm/mach-omap2/omapdev.c
new file mode 100644 (file)
index 0000000..1488681
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * omapdev device registration and handling code
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <mach/cpu.h>
+#include <mach/powerdomain.h>
+#include <mach/omapdev.h>
+
+/* odev_list contains all registered struct omapdevs */
+static LIST_HEAD(odev_list);
+
+
+/* Private functions */
+
+/*
+ * _omapdev_lookup - look up an OMAP module pointer by its name
+ * @name: name of the OMAP module to look up
+ *
+ * Finds a registered OMAP module by its name, returning a pointer to
+ * it. Returns a pointer to the struct omapdev if found, or NULL
+ * otherwise.
+ */
+static struct omapdev *_omapdev_lookup(const char *name)
+{
+       struct omapdev *odev, *temp_odev;
+
+       if (!name)
+               return NULL;
+
+       odev = NULL;
+
+       list_for_each_entry(temp_odev, &odev_list, node) {
+               if (!strcmp(name, temp_odev->name)) {
+                       odev = temp_odev;
+                       break;
+               }
+       }
+
+       return odev;
+}
+
+/*
+ * _omapdev_register - register an OMAP module
+ * @odev: struct omapdev * to register
+ *
+ * Adds a OMAP module to the internal OMAP module list.  Returns
+ * -EINVAL if given a null pointer, -EEXIST if a OMAP module is
+ * already registered by the provided name, or 0 upon success.
+ */
+static int _omapdev_register(struct omapdev *odev)
+{
+       struct powerdomain *pwrdm;
+
+       if (!odev)
+               return -EINVAL;
+
+       if (!omap_chip_is(odev->omap_chip))
+               return -EINVAL;
+
+       if (_omapdev_lookup(odev->name))
+               return -EEXIST;
+
+       pwrdm = pwrdm_lookup(odev->pwrdm.name);
+       if (!pwrdm) {
+               pr_debug("omapdev: cannot register %s: bad powerdomain\n",
+                        odev->name);
+               return -EINVAL;
+       }
+       odev->pwrdm.ptr = pwrdm;
+
+       list_add(&odev->node, &odev_list);
+
+       pr_debug("omapdev: registered %s\n", odev->name);
+
+       return 0;
+}
+
+
+
+/* Public functions */
+
+
+/**
+ * omapdev_init - set up the OMAP module layer
+ * @odevs: ptr to a array of omapdev ptrs to register
+ *
+ * Loop through the list of OMAP modules, registering them all.  No
+ * return value.
+ */
+void omapdev_init(struct omapdev **odevs)
+{
+       struct omapdev **d = NULL;
+
+       if (!list_empty(&odev_list)) {
+               pr_debug("omapdev: init already called\n");
+               return;
+       }
+
+       for (d = odevs; *d; d++) {
+               int v;
+
+               if (!omap_chip_is((*d)->omap_chip))
+                       continue;
+
+               v = _omapdev_register(*d);
+               if (ERR_PTR(v))
+                       pr_err("omapdev: could not register %s\n",
+                              (*d)->name);
+       }
+}
+
+
+/**
+ * omapdev_get_pwrdm - return pwrdm pointer associated with the device
+ * @omapdev: omapdev *
+ *
+ */
+struct powerdomain *omapdev_get_pwrdm(struct omapdev *odev)
+{
+       if (!odev)
+               return NULL;
+
+       return odev->pwrdm.ptr;
+}
+
+
+/**
+ * omapdev_find_pdev - look up an OMAP module by platform_device
+ * @pdev_name: platform_device name to find
+ * @pdev_id: platform_device id to find
+ *
+ * Finds a registered OMAP module by the platform_device name and ID
+ * that is associated with it in the omapdev structure. If multiple
+ * records exist, simply returns the 'first' record that it finds -
+ * this is probably not optimal behavior, but should work for current
+ * purposes.  Returns a pointer to the struct omapdev if found, or
+ * NULL otherwise.
+ */
+struct omapdev *omapdev_find_pdev(struct platform_device *pdev)
+{
+       struct omapdev *odev, *temp_odev;
+
+       if (!pdev)
+               return NULL;
+
+       odev = NULL;
+
+       list_for_each_entry(temp_odev, &odev_list, node) {
+               if (temp_odev->pdev_name &&
+                   !strcmp(pdev->name, temp_odev->pdev_name) &&
+                   pdev->id == temp_odev->pdev_id) {
+                       odev = temp_odev;
+                       break;
+               }
+       }
+
+       return odev;
+}
+