123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /*
- * omap_device implementation
- *
- * Copyright (C) 2009-2010 Nokia Corporation
- * Paul Walmsley, Kevin Hilman
- *
- * Developed in collaboration with (alphabetical order): Benoit
- * Cousson, Thara Gopinath, Tony Lindgren, Rajendra Nayak, Vikram
- * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard
- * Woodruff
- *
- * 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.
- *
- * This code provides a consistent interface for OMAP device drivers
- * to control power management and interconnect properties of their
- * devices.
- *
- * In the medium- to long-term, this code should either be
- * a) implemented via arch-specific pointers in platform_data
- * or
- * b) implemented as a proper omap_bus/omap_device in Linux, no more
- * platform_data func pointers
- *
- *
- * Guidelines for usage by driver authors:
- *
- * 1. These functions are intended to be used by device drivers via
- * function pointers in struct platform_data. As an example,
- * omap_device_enable() should be passed to the driver as
- *
- * struct foo_driver_platform_data {
- * ...
- * int (*device_enable)(struct platform_device *pdev);
- * ...
- * }
- *
- * Note that the generic "device_enable" name is used, rather than
- * "omap_device_enable". This is so other architectures can pass in their
- * own enable/disable functions here.
- *
- * This should be populated during device setup:
- *
- * ...
- * pdata->device_enable = omap_device_enable;
- * ...
- *
- * 2. Drivers should first check to ensure the function pointer is not null
- * before calling it, as in:
- *
- * if (pdata->device_enable)
- * pdata->device_enable(pdev);
- *
- * This allows other architectures that don't use similar device_enable()/
- * device_shutdown() functions to execute normally.
- *
- * ...
- *
- * Suggested usage by device drivers:
- *
- * During device initialization:
- * device_enable()
- *
- * During device idle:
- * (save remaining device context if necessary)
- * device_idle();
- *
- * During device resume:
- * device_enable();
- * (restore context if necessary)
- *
- * During device shutdown:
- * device_shutdown()
- * (device must be reinitialized at this point to use it again)
- *
- */
- #undef DEBUG
- #include <linux/kernel.h>
- #include <linux/export.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
- #include <linux/err.h>
- #include <linux/io.h>
- #include <linux/clk.h>
- #include <linux/clkdev.h>
- #include <linux/pm_runtime.h>
- #include <linux/of.h>
- #include <linux/notifier.h>
- #include "omap_device.h"
- #include "omap_hwmod.h"
- /* These parameters are passed to _omap_device_{de,}activate() */
- #define USE_WAKEUP_LAT 0
- #define IGNORE_WAKEUP_LAT 1
- static int omap_early_device_register(struct platform_device *pdev);
- static struct omap_device_pm_latency omap_default_latency[] = {
- {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- }
- };
- /* Private functions */
- /**
- * _omap_device_activate - increase device readiness
- * @od: struct omap_device *
- * @ignore_lat: increase to latency target (0) or full readiness (1)?
- *
- * Increase readiness of omap_device @od (thus decreasing device
- * wakeup latency, but consuming more power). If @ignore_lat is
- * IGNORE_WAKEUP_LAT, make the omap_device fully active. Otherwise,
- * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup
- * latency is greater than the requested maximum wakeup latency, step
- * backwards in the omap_device_pm_latency table to ensure the
- * device's maximum wakeup latency is less than or equal to the
- * requested maximum wakeup latency. Returns 0.
- */
- static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
- {
- struct timespec a, b, c;
- dev_dbg(&od->pdev->dev, "omap_device: activating\n");
- while (od->pm_lat_level > 0) {
- struct omap_device_pm_latency *odpl;
- unsigned long long act_lat = 0;
- od->pm_lat_level--;
- odpl = od->pm_lats + od->pm_lat_level;
- if (!ignore_lat &&
- (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit))
- break;
- read_persistent_clock(&a);
- /* XXX check return code */
- odpl->activate_func(od);
|