diff options
Diffstat (limited to 'arch/arm/plat-omap/omap_device.c')
-rw-r--r-- | arch/arm/plat-omap/omap_device.c | 87 |
1 files changed, 77 insertions, 10 deletions
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index abe933cd8f0..a37b8eb65b7 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -83,9 +83,11 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/clkdev.h> #include <plat/omap_device.h> #include <plat/omap_hwmod.h> +#include <plat/clock.h> /* These parameters are passed to _omap_device_{de,}activate() */ #define USE_WAKEUP_LAT 0 @@ -239,12 +241,12 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev) } /** - * _add_optional_clock_alias - Add clock alias for hwmod optional clocks + * _add_optional_clock_clkdev - Add clkdev entry 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> + * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role> + * if it does not exist already. * * The function is called from inside omap_device_build_ss(), after * omap_device_register. @@ -254,25 +256,39 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev) * * No return value. */ -static void _add_optional_clock_alias(struct omap_device *od, +static void _add_optional_clock_clkdev(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; + struct clk *r; + struct clk_lookup *l; 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", + r = clk_get_sys(dev_name(&od->pdev.dev), oc->role); + if (!IS_ERR(r)) + continue; /* clkdev entry exists */ + + r = omap_clk_get_by_name((char *)oc->clk); + if (IS_ERR(r)) { + pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n", + dev_name(&od->pdev.dev), oc->clk); + continue; + } + + l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev)); + if (!l) { + pr_err("omap_device: %s: clkdev_alloc for %s failed\n", dev_name(&od->pdev.dev), oc->role); + return; + } + clkdev_add(l); } } @@ -280,6 +296,34 @@ static void _add_optional_clock_alias(struct omap_device *od, /* Public functions for use by core code */ /** + * omap_device_get_context_loss_count - get lost context count + * @od: struct omap_device * + * + * Using the primary hwmod, query the context loss count for this + * device. + * + * Callers should consider context for this device lost any time this + * function returns a value different than the value the caller got + * the last time it called this function. + * + * If any hwmods exist for the omap_device assoiated with @pdev, + * return the context loss counter for that hwmod, otherwise return + * zero. + */ +u32 omap_device_get_context_loss_count(struct platform_device *pdev) +{ + struct omap_device *od; + u32 ret = 0; + + od = _find_by_pdev(pdev); + + if (od->hwmods_cnt) + ret = omap_hwmod_get_context_loss_count(od->hwmods[0]); + + return ret; +} + +/** * omap_device_count_resources - count number of struct resource entries needed * @od: struct omap_device * * @@ -452,7 +496,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, for (i = 0; i < oh_cnt; i++) { hwmods[i]->od = od; - _add_optional_clock_alias(od, hwmods[i]); + _add_optional_clock_clkdev(od, hwmods[i]); } if (ret) @@ -492,6 +536,28 @@ int omap_early_device_register(struct omap_device *od) return 0; } +static int _od_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return omap_device_idle(pdev); +} + +static int _od_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return omap_device_enable(pdev); +} + +static struct dev_power_domain omap_device_power_domain = { + .ops = { + .runtime_suspend = _od_runtime_suspend, + .runtime_resume = _od_runtime_resume, + USE_PLATFORM_PM_SLEEP_OPS + } +}; + /** * omap_device_register - register an omap_device with one omap_hwmod * @od: struct omap_device * to register @@ -505,6 +571,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; + od->pdev.dev.pwr_domain = &omap_device_power_domain; return platform_device_register(&od->pdev); } |