@@ -261,6 +261,7 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
static int really_probe(struct device *dev, struct device_driver *drv)
{
+ struct device_asset *asset;
int ret = 0;
atomic_inc(&probe_count);
@@ -275,6 +276,23 @@ static int really_probe(struct device *dev, struct device_driver *drv)
goto probe_failed;
}
+ asset = dev->assets;
+ while (asset && asset->pre_probe) {
+ dev_info(dev, "Enabling pre-probe asset %s\n", asset->name);
+ ret = asset->pre_probe(dev, asset);
+ if (ret) {
+ dev_err(dev, "Error Enabling pre-probe asset %s\n",
+ asset->name);
+ if (asset != dev->assets)
+ do {
+ asset--;
+ asset->post_remove(dev, asset);
+ } while (asset != dev->assets);
+ goto probe_failed;
+ }
+ asset++;
+ }
+
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
@@ -478,6 +496,7 @@ EXPORT_SYMBOL_GPL(driver_attach);
static void __device_release_driver(struct device *dev)
{
struct device_driver *drv;
+ struct device_asset *asset;
drv = dev->driver;
if (drv) {
@@ -496,6 +515,23 @@ static void __device_release_driver(struct device *dev)
dev->bus->remove(dev);
else if (drv->remove)
drv->remove(dev);
+
+ asset = dev->assets;
+ if (asset) {
+ /* remove in reverse order */
+ while (asset->pre_probe)
+ asset++;
+
+ if (asset != dev->assets)
+ do {
+ asset--;
+ dev_info(dev,
+ "Disabling post-remove asset %s\n",
+ asset->name);
+ asset->post_remove(dev, asset);
+ } while (asset != dev->assets);
+ }
+
devres_release_all(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
@@ -577,6 +577,26 @@ struct device_dma_parameters {
};
/**
+ * struct device_asset - a prerequisite for this device's probing
+ * @name: Name of the regulator, clock, etc. Optional.
+ * @asset: Pointer to the regulator, clock, etc. If no name is given,
+ * this can be set before device probe, otherwise the pre_probe
+ * handler will dereference the name and store a pointer here
+ * @data: Optional configuration data the asset may need
+ * @pre_probe: Called before this device this is associated with gets
+ * probed.
+ * @post_remove: Called after this device instance gets removed.
+ */
+
+struct device_asset {
+ const char *name;
+ void *asset;
+ void *data;
+ int (*pre_probe)(struct device *device, struct device_asset *asset);
+ void (*post_remove)(struct device *device, struct device_asset *asset);
+};
+
+/**
* struct device - The basic device structure
* @parent: The device's "parent" device, the device to which it is attached.
* In most cases, a parent device is some sort of bus or host
@@ -600,6 +620,9 @@ struct device_dma_parameters {
* variants, which GPIO pins act in what additional roles, and so
* on. This shrinks the "Board Support Packages" (BSPs) and
* minimizes board-specific #ifdefs in drivers.
+ * @assets: Pointer to a NULL-pre_probe terminated array of named or
+ * pointed-to objects that should be enabled for this device
+ * just before probe and disabled after removal
* @power: For device power management.
* See Documentation/power/devices.txt for details.
* @pm_domain: Provide callbacks that are executed during system suspend,
@@ -653,6 +676,8 @@ struct device {
device */
void *platform_data; /* Platform specific data, device
core doesn't touch it */
+ struct device_asset *assets; /* optional assets enabled before probe
+ * and disabled after removal */
struct dev_pm_info power;
struct dev_pm_domain *pm_domain;
This patch adds support for a new struct device member "assets" which may point to an array of struct assets. The array is terminated by one with a NULL pre_probe callback. These assets consist of named (in .name) or anonymous object pointers (.data) operated on by specified callbacks. A void * is provided to give configuration data or pointer if needed. Before device probe, any assets associated with the device have their pre_probe() callback called, which will typically "enable" them, and after device removal the post_remove() callback is called which will typically disable them. Signed-off-by: Andy Green <andy.green@linaro.org> --- drivers/base/dd.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/device.h | 25 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html