#include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
+#include <linux/completion.h>
#include <asm/uaccess.h>
static DEFINE_MUTEX(core_lists);
static DEFINE_IDR(i2c_adapter_idr);
+
+/* ------------------------------------------------------------------------- */
+
/* match always succeeds, as we want the probe() to tell if we really accept this match */
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
return 1;
}
-static int i2c_bus_suspend(struct device * dev, pm_message_t state)
+static int i2c_device_probe(struct device *dev)
{
- int rc = 0;
+ return -ENODEV;
+}
- if (dev->driver && dev->driver->suspend)
- rc = dev->driver->suspend(dev, state);
- return rc;
+static int i2c_device_remove(struct device *dev)
+{
+ return 0;
}
-static int i2c_bus_resume(struct device * dev)
+static void i2c_device_shutdown(struct device *dev)
{
- int rc = 0;
-
- if (dev->driver && dev->driver->resume)
- rc = dev->driver->resume(dev);
- return rc;
+ struct i2c_driver *driver;
+
+ if (!dev->driver)
+ return;
+ driver = to_i2c_driver(dev->driver);
+ if (driver->shutdown)
+ driver->shutdown(to_i2c_client(dev));
}
-static int i2c_device_probe(struct device *dev)
+static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
{
- return -ENODEV;
+ struct i2c_driver *driver;
+
+ if (!dev->driver)
+ return 0;
+ driver = to_i2c_driver(dev->driver);
+ if (!driver->suspend)
+ return 0;
+ return driver->suspend(to_i2c_client(dev), mesg);
}
-static int i2c_device_remove(struct device *dev)
+static int i2c_device_resume(struct device * dev)
{
- return 0;
+ struct i2c_driver *driver;
+
+ if (!dev->driver)
+ return 0;
+ driver = to_i2c_driver(dev->driver);
+ if (!driver->resume)
+ return 0;
+ return driver->resume(to_i2c_client(dev));
}
struct bus_type i2c_bus_type = {
- .name = "i2c",
- .match = i2c_device_match,
- .probe = i2c_device_probe,
- .remove = i2c_device_remove,
- .suspend = i2c_bus_suspend,
- .resume = i2c_bus_resume,
+ .name = "i2c",
+ .match = i2c_device_match,
+ .probe = i2c_device_probe,
+ .remove = i2c_device_remove,
+ .shutdown = i2c_device_shutdown,
+ .suspend = i2c_device_suspend,
+ .resume = i2c_device_resume,
};
+/* ------------------------------------------------------------------------- */
+
void i2c_adapter_dev_release(struct device *dev)
{
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
/* I2C bus adapters -- one roots each I2C or SMBUS segment */
-static void i2c_adapter_class_dev_release(struct class_device *dev)
-{
- struct i2c_adapter *adap = class_dev_to_i2c_adapter(dev);
- complete(&adap->class_dev_released);
-}
-
-static ssize_t i2c_adapter_show_name(struct class_device *cdev, char *buf)
-{
- struct i2c_adapter *adap = class_dev_to_i2c_adapter(cdev);
- return sprintf(buf, "%s\n", adap->name);
-}
-
-static struct class_device_attribute i2c_adapter_attrs[] = {
- __ATTR(name, S_IRUGO, i2c_adapter_show_name, NULL),
- { },
-};
-
struct class i2c_adapter_class = {
.owner = THIS_MODULE,
.name = "i2c-adapter",
- .class_dev_attrs = i2c_adapter_attrs,
- .release = &i2c_adapter_class_dev_release,
};
static ssize_t show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
*/
if (adap->dev.parent == NULL) {
adap->dev.parent = &platform_bus;
- printk(KERN_WARNING "**WARNING** I2C adapter driver [%s] "
- "forgot to specify physical device; fix it!\n",
- adap->name);
+ pr_debug("I2C adapter driver [%s] forgot to specify "
+ "physical device\n", adap->name);
}
sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
adap->dev.driver = &i2c_adapter_driver;
adap->dev.release = &i2c_adapter_dev_release;
+ adap->dev.class = &i2c_adapter_class;
res = device_register(&adap->dev);
if (res)
goto out_list;
if (res)
goto out_unregister;
- /* Add this adapter to the i2c_adapter class */
- memset(&adap->class_dev, 0x00, sizeof(struct class_device));
- adap->class_dev.dev = &adap->dev;
- adap->class_dev.class = &i2c_adapter_class;
- strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
- res = class_device_register(&adap->class_dev);
- if (res)
- goto out_remove_name;
-
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
/* inform drivers of new adapters */
mutex_unlock(&core_lists);
return res;
-out_remove_name:
- device_remove_file(&adap->dev, &dev_attr_name);
out_unregister:
init_completion(&adap->dev_released); /* Needed? */
device_unregister(&adap->dev);
/* clean up the sysfs representation */
init_completion(&adap->dev_released);
- init_completion(&adap->class_dev_released);
- class_device_unregister(&adap->class_dev);
device_remove_file(&adap->dev, &dev_attr_name);
device_unregister(&adap->dev);
list_del(&adap->list);
/* wait for sysfs to drop all references */
wait_for_completion(&adap->dev_released);
- wait_for_completion(&adap->class_dev_released);
/* free dynamically allocated bus id */
idr_remove(&i2c_adapter_idr, adap->nr);