#include "base.h"
+#define to_platform_driver(drv) (container_of((drv), struct platform_driver, driver))
+
struct device platform_bus = {
.bus_id = "platform",
};
+EXPORT_SYMBOL_GPL(platform_bus);
/**
* platform_get_resource - get a resource for a device
}
return NULL;
}
+EXPORT_SYMBOL_GPL(platform_get_resource);
/**
* platform_get_irq - get an IRQ for a device
{
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
- return r ? r->start : 0;
+ return r ? r->start : -ENXIO;
}
+EXPORT_SYMBOL_GPL(platform_get_irq);
/**
* platform_get_resource_byname - get a resource for a device by name
}
return NULL;
}
+EXPORT_SYMBOL_GPL(platform_get_resource_byname);
/**
* platform_get_irq - get an IRQ for a device
{
struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
- return r ? r->start : 0;
+ return r ? r->start : -ENXIO;
}
+EXPORT_SYMBOL_GPL(platform_get_irq_byname);
/**
* platform_add_devices - add a numbers of platform devices
return ret;
}
+EXPORT_SYMBOL_GPL(platform_add_devices);
struct platform_object {
struct platform_device pdev;
pa->pdev.dev.release = platform_device_release;
}
- return pa ? &pa->pdev : NULL;
+ return pa ? &pa->pdev : NULL;
}
EXPORT_SYMBOL_GPL(platform_device_alloc);
p = &ioport_resource;
}
- if (p && request_resource(p, r)) {
+ if (p && insert_resource(p, r)) {
printk(KERN_ERR
"%s: failed to claim resource %d\n",
pdev->dev.bus_id, i);
pr_debug("Registering platform device '%s'. Parent at %s\n",
pdev->dev.bus_id, pdev->dev.parent->bus_id);
- ret = device_register(&pdev->dev);
+ ret = device_add(&pdev->dev);
if (ret == 0)
return ret;
EXPORT_SYMBOL_GPL(platform_device_add);
/**
- * platform_device_register - add a platform-level device
- * @pdev: platform device we're adding
- *
- */
-int platform_device_register(struct platform_device * pdev)
-{
- device_initialize(&pdev->dev);
- return platform_device_add(pdev);
-}
-
-/**
- * platform_device_unregister - remove a platform-level device
+ * platform_device_del - remove a platform-level device
* @pdev: platform device we're removing
*
* Note that this function will also release all memory- and port-based
* resources owned by the device (@dev->resource).
*/
-void platform_device_unregister(struct platform_device * pdev)
+void platform_device_del(struct platform_device *pdev)
{
int i;
release_resource(r);
}
- device_unregister(&pdev->dev);
+ device_del(&pdev->dev);
}
}
+EXPORT_SYMBOL_GPL(platform_device_del);
+
+/**
+ * platform_device_register - add a platform-level device
+ * @pdev: platform device we're adding
+ *
+ */
+int platform_device_register(struct platform_device * pdev)
+{
+ device_initialize(&pdev->dev);
+ return platform_device_add(pdev);
+}
+EXPORT_SYMBOL_GPL(platform_device_register);
+
+/**
+ * platform_device_unregister - unregister a platform-level device
+ * @pdev: platform device we're unregistering
+ *
+ * Unregistration is done in 2 steps. First we release all resources
+ * and remove it from the subsystem, then we drop reference count by
+ * calling platform_device_put().
+ */
+void platform_device_unregister(struct platform_device * pdev)
+{
+ platform_device_del(pdev);
+ platform_device_put(pdev);
+}
+EXPORT_SYMBOL_GPL(platform_device_unregister);
/**
* platform_device_register_simple
platform_device_put(pdev);
return ERR_PTR(retval);
}
+EXPORT_SYMBOL_GPL(platform_device_register_simple);
+
+static int platform_drv_probe(struct device *_dev)
+{
+ struct platform_driver *drv = to_platform_driver(_dev->driver);
+ struct platform_device *dev = to_platform_device(_dev);
+
+ return drv->probe(dev);
+}
+
+static int platform_drv_remove(struct device *_dev)
+{
+ struct platform_driver *drv = to_platform_driver(_dev->driver);
+ struct platform_device *dev = to_platform_device(_dev);
+
+ return drv->remove(dev);
+}
+
+static void platform_drv_shutdown(struct device *_dev)
+{
+ struct platform_driver *drv = to_platform_driver(_dev->driver);
+ struct platform_device *dev = to_platform_device(_dev);
+
+ drv->shutdown(dev);
+}
+
+static int platform_drv_suspend(struct device *_dev, pm_message_t state)
+{
+ struct platform_driver *drv = to_platform_driver(_dev->driver);
+ struct platform_device *dev = to_platform_device(_dev);
+
+ return drv->suspend(dev, state);
+}
+
+static int platform_drv_resume(struct device *_dev)
+{
+ struct platform_driver *drv = to_platform_driver(_dev->driver);
+ struct platform_device *dev = to_platform_device(_dev);
+
+ return drv->resume(dev);
+}
+
+/**
+ * platform_driver_register
+ * @drv: platform driver structure
+ */
+int platform_driver_register(struct platform_driver *drv)
+{
+ drv->driver.bus = &platform_bus_type;
+ if (drv->probe)
+ drv->driver.probe = platform_drv_probe;
+ if (drv->remove)
+ drv->driver.remove = platform_drv_remove;
+ if (drv->shutdown)
+ drv->driver.shutdown = platform_drv_shutdown;
+ if (drv->suspend)
+ drv->driver.suspend = platform_drv_suspend;
+ if (drv->resume)
+ drv->driver.resume = platform_drv_resume;
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(platform_driver_register);
+
+/**
+ * platform_driver_unregister
+ * @drv: platform driver structure
+ */
+void platform_driver_unregister(struct platform_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(platform_driver_unregister);
+
+
+/* modalias support enables more hands-off userspace setup:
+ * (a) environment variable lets new-style hotplug events work once system is
+ * fully running: "modprobe $MODALIAS"
+ * (b) sysfs attribute lets new-style coldplug recover from hotplug events
+ * mishandled before system is fully running: "modprobe $(cat modalias)"
+ */
+static ssize_t
+modalias_show(struct device *dev, struct device_attribute *a, char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ int len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->name);
+
+ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute platform_dev_attrs[] = {
+ __ATTR_RO(modalias),
+ __ATTR_NULL,
+};
+
+static int platform_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ envp[0] = buffer;
+ snprintf(buffer, buffer_size, "MODALIAS=%s", pdev->name);
+ return 0;
+}
/**
struct bus_type platform_bus_type = {
.name = "platform",
+ .dev_attrs = platform_dev_attrs,
.match = platform_match,
+ .uevent = platform_uevent,
.suspend = platform_suspend,
.resume = platform_resume,
};
+EXPORT_SYMBOL_GPL(platform_bus_type);
int __init platform_bus_init(void)
{
}
EXPORT_SYMBOL_GPL(dma_get_required_mask);
#endif
-
-EXPORT_SYMBOL_GPL(platform_bus);
-EXPORT_SYMBOL_GPL(platform_bus_type);
-EXPORT_SYMBOL_GPL(platform_add_devices);
-EXPORT_SYMBOL_GPL(platform_device_register);
-EXPORT_SYMBOL_GPL(platform_device_register_simple);
-EXPORT_SYMBOL_GPL(platform_device_unregister);
-EXPORT_SYMBOL_GPL(platform_get_irq);
-EXPORT_SYMBOL_GPL(platform_get_resource);
-EXPORT_SYMBOL_GPL(platform_get_irq_byname);
-EXPORT_SYMBOL_GPL(platform_get_resource_byname);