[PATCH 04/10] ARM: OMAP: omap_device: register to the per-device PM QoS framework
Rajendra Nayak
rnayak at ti.com
Wed Jun 20 06:41:24 EDT 2012
On Thursday 14 June 2012 08:35 PM, Jean Pihet wrote:
> Implement the devices wake-up latency constraints using the global
> device PM QoS notification handler which applies the constraints to the
> underlying layer by calling the corresponding function at hwmod level.
>
> Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using wake-up
> latency constraints on MPU, CORE and PER.
>
> Signed-off-by: Jean Pihet<j-pihet at ti.com>
> Reviewed-by: Kevin Hilman<khilman at ti.com>
> [paul at pwsan.com: modified to work with omap_devices with large numbers of
> hwmods; moved code to mach-omap2/omap_device.c; added documentation; use
> notifier return codes]
> Signed-off-by: Paul Walmsley<paul at pwsan.com>
> ---
> arch/arm/plat-omap/omap_device.c | 81 +++++++++++++++++++++++++++++++++++++-
> 1 files changed, 80 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
> index c490240..241705b 100644
> --- a/arch/arm/plat-omap/omap_device.c
> +++ b/arch/arm/plat-omap/omap_device.c
> @@ -3,6 +3,7 @@
> * omap_device implementation
> *
> * Copyright (C) 2009-2010 Nokia Corporation
> + * Copyright (C) 2011 Texas Instruments, Inc.
2012?
> * Paul Walmsley, Kevin Hilman
> *
> * Developed in collaboration with (alphabetical order): Benoit
> @@ -89,6 +90,7 @@
> #include<linux/pm_runtime.h>
> #include<linux/of.h>
> #include<linux/notifier.h>
> +#include<linux/pm_qos.h>
>
> #include<plat/omap_device.h>
> #include<plat/omap_hwmod.h>
> @@ -401,6 +403,72 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
> return NOTIFY_DONE;
> }
>
> +/**
> + * _omap_device_pm_qos_handler - interface to the per-device PM QoS framework
> + * @nb: pointer to omap_device_pm_qos_nb (not used)
> + * @new_value: new maximum wakeup latency constraint for @req->dev (in us)
> + * @req: struct dev_pm_qos_request * passed by the Linux PM QoS code
> + *
> + * Called by the Linux core device PM QoS code to alter the maximum
> + * wakeup latency constraint on a device. If the underlying device is
> + * an omap_device, then this code will pass the constraint on to the
> + * underlying hwmods. Returns -EINVAL if this code can't handle the
> + * constraint for some reason, or passes along the return code from the
> + * hwmod wakeup latency constraint functions.
> + */
> +static int _omap_device_pm_qos_handler(struct notifier_block *nb,
> + unsigned long new_value,
> + void *req)
> +{
> + struct omap_device *od;
> + struct omap_hwmod *oh;
> + struct platform_device *pdev;
> + struct dev_pm_qos_request *dev_pm_qos_req = req;
> + int ret = NOTIFY_OK;
> + int r, i;
> +
> + pr_debug("OMAP PM constraints: req at 0x%p, new_value=%lu\n",
> + req, new_value);
> +
> + /* Look for the platform device for the constraint target device */
> + pdev = to_platform_device(dev_pm_qos_req->dev);
> +
> + /* Try to catch non platform devices */
> + if (pdev->name == NULL) {
Is this a safe way to catch non platform devices?
regards,
Rajendra
> + pr_err("%s: Error: platform device for device %s not valid\n",
> + __func__, dev_name(dev_pm_qos_req->dev));
> + return NOTIFY_DONE;
> + }
> +
> + /* Find the associated omap_device for dev */
> + od = to_omap_device(pdev);
> + if (od == NULL) {
> + pr_err("%s: Error: no omap_device for device %s\n",
> + __func__, dev_name(dev_pm_qos_req->dev));
> + return NOTIFY_DONE;
> + }
> +
> + pr_debug("OMAP PM constraints: req at 0x%p, dev=0x%p, new_value=%lu\n",
> + req, dev_pm_qos_req->dev, new_value);
> +
> + for (i = 0; i< od->hwmods_cnt; i++) {
> + oh = od->hwmods[i];
> + if (new_value == PM_QOS_DEV_LAT_DEFAULT_VALUE)
> + r = omap_hwmod_remove_wakeuplat_constraint(
> + oh,
> + dev_pm_qos_req);
> + else
> + r = omap_hwmod_set_wakeuplat_constraint(
> + oh,
> + dev_pm_qos_req,
> + new_value);
> +
> + if (!r)
> + ret = NOTIFY_BAD;
> + }
> +
> + return ret;
> +}
>
> /* Public functions for use by core code */
>
> @@ -1115,13 +1183,24 @@ int omap_device_enable_clocks(struct omap_device *od)
> return 0;
> }
>
> +static struct notifier_block omap_device_pm_qos_nb = {
> + .notifier_call = _omap_device_pm_qos_handler,
> +};
> +
> static struct notifier_block platform_nb = {
> .notifier_call = _omap_device_notifier_call,
> };
>
> static int __init omap_device_init(void)
> {
> + int ret;
> +
> bus_register_notifier(&platform_bus_type,&platform_nb);
> - return 0;
> +
> + ret = dev_pm_qos_add_global_notifier(&omap_device_pm_qos_nb);
> + if (ret)
> + pr_err("omap_device: cannot add global notifier for dev PM QoS\n");
> +
> + return ret;
> }
> core_initcall(omap_device_init);
More information about the linux-arm-kernel
mailing list