Register the omapdevs early in the boot process. Also provide functions for other code (primarily the OMAP PM layer at the moment) to look up an omapdev given a platform_device name and id. Signed-off-by: Paul Walmsley <paul@xxxxxxxxx> --- arch/arm/mach-omap2/Makefile | 2 arch/arm/mach-omap2/io.c | 3 arch/arm/mach-omap2/omapdev.c | 177 +++++++++++++++++++++++++++++ arch/arm/plat-omap/include/mach/omapdev.h | 7 + 4 files changed, 188 insertions(+), 1 deletions(-) create mode 100644 arch/arm/mach-omap2/omapdev.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 33de217..25a4791 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -5,7 +5,7 @@ # Common support obj-y := irq.o id.o io.o sdrc.o control.o prcm.o clock.o mux.o \ devices.o serial.o gpmc.o timer-gp.o powerdomain.o \ - clockdomain.o + clockdomain.o omapdev.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 05d4f2d..1829c1b 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -29,6 +29,8 @@ #include <mach/sdrc.h> #include <mach/gpmc.h> +#include "omapdev-common.h" + #include "clock.h" #include <mach/powerdomain.h> @@ -202,6 +204,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sp) omap_pm_if_early_init(); pwrdm_init(powerdomains_omap); clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps); + omapdev_init(omapdevs); omap2_clk_init(); omap_pm_if_init(NULL, NULL); omap2_sdrc_init(sp); diff --git a/arch/arm/mach-omap2/omapdev.c b/arch/arm/mach-omap2/omapdev.c new file mode 100644 index 0000000..1488681 --- /dev/null +++ b/arch/arm/mach-omap2/omapdev.c @@ -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; +} + diff --git a/arch/arm/plat-omap/include/mach/omapdev.h b/arch/arm/plat-omap/include/mach/omapdev.h index ef91f00..4b379bc 100644 --- a/arch/arm/plat-omap/include/mach/omapdev.h +++ b/arch/arm/plat-omap/include/mach/omapdev.h @@ -15,6 +15,7 @@ #include <linux/types.h> #include <linux/list.h> +#include <linux/platform_device.h> #include <mach/cpu.h> #include <mach/powerdomain.h> @@ -47,5 +48,11 @@ struct omapdev { }; +void omapdev_init(struct omapdev **odev_list); + +struct powerdomain *omapdev_get_pwrdm(struct omapdev *odev); + +struct omapdev *omapdev_find_pdev(struct platform_device *pdev); + #endif -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html