diff options
Diffstat (limited to 'drivers/i2c/i2c-core.c')
| -rw-r--r-- | drivers/i2c/i2c-core.c | 162 |
1 files changed, 14 insertions, 148 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e9eae57a2b50..210cf4874cb7 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
| @@ -102,7 +102,7 @@ static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) | |||
| 102 | struct acpi_resource_i2c_serialbus *sb; | 102 | struct acpi_resource_i2c_serialbus *sb; |
| 103 | 103 | ||
| 104 | sb = &ares->data.i2c_serial_bus; | 104 | sb = &ares->data.i2c_serial_bus; |
| 105 | if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { | 105 | if (!info->addr && sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { |
| 106 | info->addr = sb->slave_address; | 106 | info->addr = sb->slave_address; |
| 107 | if (sb->access_mode == ACPI_I2C_10BIT_MODE) | 107 | if (sb->access_mode == ACPI_I2C_10BIT_MODE) |
| 108 | info->flags |= I2C_CLIENT_TEN; | 108 | info->flags |= I2C_CLIENT_TEN; |
| @@ -698,101 +698,6 @@ static void i2c_device_shutdown(struct device *dev) | |||
| 698 | driver->shutdown(client); | 698 | driver->shutdown(client); |
| 699 | } | 699 | } |
| 700 | 700 | ||
| 701 | #ifdef CONFIG_PM_SLEEP | ||
| 702 | static int i2c_legacy_suspend(struct device *dev, pm_message_t mesg) | ||
| 703 | { | ||
| 704 | struct i2c_client *client = i2c_verify_client(dev); | ||
| 705 | struct i2c_driver *driver; | ||
| 706 | |||
| 707 | if (!client || !dev->driver) | ||
| 708 | return 0; | ||
| 709 | driver = to_i2c_driver(dev->driver); | ||
| 710 | if (!driver->suspend) | ||
| 711 | return 0; | ||
| 712 | return driver->suspend(client, mesg); | ||
| 713 | } | ||
| 714 | |||
| 715 | static int i2c_legacy_resume(struct device *dev) | ||
| 716 | { | ||
| 717 | struct i2c_client *client = i2c_verify_client(dev); | ||
| 718 | struct i2c_driver *driver; | ||
| 719 | |||
| 720 | if (!client || !dev->driver) | ||
| 721 | return 0; | ||
| 722 | driver = to_i2c_driver(dev->driver); | ||
| 723 | if (!driver->resume) | ||
| 724 | return 0; | ||
| 725 | return driver->resume(client); | ||
| 726 | } | ||
| 727 | |||
| 728 | static int i2c_device_pm_suspend(struct device *dev) | ||
| 729 | { | ||
| 730 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 731 | |||
| 732 | if (pm) | ||
| 733 | return pm_generic_suspend(dev); | ||
| 734 | else | ||
| 735 | return i2c_legacy_suspend(dev, PMSG_SUSPEND); | ||
| 736 | } | ||
| 737 | |||
| 738 | static int i2c_device_pm_resume(struct device *dev) | ||
| 739 | { | ||
| 740 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 741 | |||
| 742 | if (pm) | ||
| 743 | return pm_generic_resume(dev); | ||
| 744 | else | ||
| 745 | return i2c_legacy_resume(dev); | ||
| 746 | } | ||
| 747 | |||
| 748 | static int i2c_device_pm_freeze(struct device *dev) | ||
| 749 | { | ||
| 750 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 751 | |||
| 752 | if (pm) | ||
| 753 | return pm_generic_freeze(dev); | ||
| 754 | else | ||
| 755 | return i2c_legacy_suspend(dev, PMSG_FREEZE); | ||
| 756 | } | ||
| 757 | |||
| 758 | static int i2c_device_pm_thaw(struct device *dev) | ||
| 759 | { | ||
| 760 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 761 | |||
| 762 | if (pm) | ||
| 763 | return pm_generic_thaw(dev); | ||
| 764 | else | ||
| 765 | return i2c_legacy_resume(dev); | ||
| 766 | } | ||
| 767 | |||
| 768 | static int i2c_device_pm_poweroff(struct device *dev) | ||
| 769 | { | ||
| 770 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 771 | |||
| 772 | if (pm) | ||
| 773 | return pm_generic_poweroff(dev); | ||
| 774 | else | ||
| 775 | return i2c_legacy_suspend(dev, PMSG_HIBERNATE); | ||
| 776 | } | ||
| 777 | |||
| 778 | static int i2c_device_pm_restore(struct device *dev) | ||
| 779 | { | ||
| 780 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 781 | |||
| 782 | if (pm) | ||
| 783 | return pm_generic_restore(dev); | ||
| 784 | else | ||
| 785 | return i2c_legacy_resume(dev); | ||
| 786 | } | ||
| 787 | #else /* !CONFIG_PM_SLEEP */ | ||
| 788 | #define i2c_device_pm_suspend NULL | ||
| 789 | #define i2c_device_pm_resume NULL | ||
| 790 | #define i2c_device_pm_freeze NULL | ||
| 791 | #define i2c_device_pm_thaw NULL | ||
| 792 | #define i2c_device_pm_poweroff NULL | ||
| 793 | #define i2c_device_pm_restore NULL | ||
| 794 | #endif /* !CONFIG_PM_SLEEP */ | ||
| 795 | |||
| 796 | static void i2c_client_dev_release(struct device *dev) | 701 | static void i2c_client_dev_release(struct device *dev) |
| 797 | { | 702 | { |
| 798 | kfree(to_i2c_client(dev)); | 703 | kfree(to_i2c_client(dev)); |
| @@ -804,6 +709,7 @@ show_name(struct device *dev, struct device_attribute *attr, char *buf) | |||
| 804 | return sprintf(buf, "%s\n", dev->type == &i2c_client_type ? | 709 | return sprintf(buf, "%s\n", dev->type == &i2c_client_type ? |
| 805 | to_i2c_client(dev)->name : to_i2c_adapter(dev)->name); | 710 | to_i2c_client(dev)->name : to_i2c_adapter(dev)->name); |
| 806 | } | 711 | } |
| 712 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
| 807 | 713 | ||
| 808 | static ssize_t | 714 | static ssize_t |
| 809 | show_modalias(struct device *dev, struct device_attribute *attr, char *buf) | 715 | show_modalias(struct device *dev, struct device_attribute *attr, char *buf) |
| @@ -817,8 +723,6 @@ show_modalias(struct device *dev, struct device_attribute *attr, char *buf) | |||
| 817 | 723 | ||
| 818 | return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); | 724 | return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); |
| 819 | } | 725 | } |
| 820 | |||
| 821 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
| 822 | static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); | 726 | static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); |
| 823 | 727 | ||
| 824 | static struct attribute *i2c_dev_attrs[] = { | 728 | static struct attribute *i2c_dev_attrs[] = { |
| @@ -827,29 +731,7 @@ static struct attribute *i2c_dev_attrs[] = { | |||
| 827 | &dev_attr_modalias.attr, | 731 | &dev_attr_modalias.attr, |
| 828 | NULL | 732 | NULL |
| 829 | }; | 733 | }; |
| 830 | 734 | ATTRIBUTE_GROUPS(i2c_dev); | |
| 831 | static struct attribute_group i2c_dev_attr_group = { | ||
| 832 | .attrs = i2c_dev_attrs, | ||
| 833 | }; | ||
| 834 | |||
| 835 | static const struct attribute_group *i2c_dev_attr_groups[] = { | ||
| 836 | &i2c_dev_attr_group, | ||
| 837 | NULL | ||
| 838 | }; | ||
| 839 | |||
| 840 | static const struct dev_pm_ops i2c_device_pm_ops = { | ||
| 841 | .suspend = i2c_device_pm_suspend, | ||
| 842 | .resume = i2c_device_pm_resume, | ||
| 843 | .freeze = i2c_device_pm_freeze, | ||
| 844 | .thaw = i2c_device_pm_thaw, | ||
| 845 | .poweroff = i2c_device_pm_poweroff, | ||
| 846 | .restore = i2c_device_pm_restore, | ||
| 847 | SET_RUNTIME_PM_OPS( | ||
| 848 | pm_generic_runtime_suspend, | ||
| 849 | pm_generic_runtime_resume, | ||
| 850 | NULL | ||
| 851 | ) | ||
| 852 | }; | ||
| 853 | 735 | ||
| 854 | struct bus_type i2c_bus_type = { | 736 | struct bus_type i2c_bus_type = { |
| 855 | .name = "i2c", | 737 | .name = "i2c", |
| @@ -857,12 +739,11 @@ struct bus_type i2c_bus_type = { | |||
| 857 | .probe = i2c_device_probe, | 739 | .probe = i2c_device_probe, |
| 858 | .remove = i2c_device_remove, | 740 | .remove = i2c_device_remove, |
| 859 | .shutdown = i2c_device_shutdown, | 741 | .shutdown = i2c_device_shutdown, |
| 860 | .pm = &i2c_device_pm_ops, | ||
| 861 | }; | 742 | }; |
| 862 | EXPORT_SYMBOL_GPL(i2c_bus_type); | 743 | EXPORT_SYMBOL_GPL(i2c_bus_type); |
| 863 | 744 | ||
| 864 | static struct device_type i2c_client_type = { | 745 | static struct device_type i2c_client_type = { |
| 865 | .groups = i2c_dev_attr_groups, | 746 | .groups = i2c_dev_groups, |
| 866 | .uevent = i2c_device_uevent, | 747 | .uevent = i2c_device_uevent, |
| 867 | .release = i2c_client_dev_release, | 748 | .release = i2c_client_dev_release, |
| 868 | }; | 749 | }; |
| @@ -1261,6 +1142,7 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, | |||
| 1261 | 1142 | ||
| 1262 | return count; | 1143 | return count; |
| 1263 | } | 1144 | } |
| 1145 | static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device); | ||
| 1264 | 1146 | ||
| 1265 | /* | 1147 | /* |
| 1266 | * And of course let the users delete the devices they instantiated, if | 1148 | * And of course let the users delete the devices they instantiated, if |
| @@ -1315,8 +1197,6 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, | |||
| 1315 | "delete_device"); | 1197 | "delete_device"); |
| 1316 | return res; | 1198 | return res; |
| 1317 | } | 1199 | } |
| 1318 | |||
| 1319 | static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device); | ||
| 1320 | static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL, | 1200 | static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL, |
| 1321 | i2c_sysfs_delete_device); | 1201 | i2c_sysfs_delete_device); |
| 1322 | 1202 | ||
| @@ -1326,18 +1206,10 @@ static struct attribute *i2c_adapter_attrs[] = { | |||
| 1326 | &dev_attr_delete_device.attr, | 1206 | &dev_attr_delete_device.attr, |
| 1327 | NULL | 1207 | NULL |
| 1328 | }; | 1208 | }; |
| 1329 | 1209 | ATTRIBUTE_GROUPS(i2c_adapter); | |
| 1330 | static struct attribute_group i2c_adapter_attr_group = { | ||
| 1331 | .attrs = i2c_adapter_attrs, | ||
| 1332 | }; | ||
| 1333 | |||
| 1334 | static const struct attribute_group *i2c_adapter_attr_groups[] = { | ||
| 1335 | &i2c_adapter_attr_group, | ||
| 1336 | NULL | ||
| 1337 | }; | ||
| 1338 | 1210 | ||
| 1339 | struct device_type i2c_adapter_type = { | 1211 | struct device_type i2c_adapter_type = { |
| 1340 | .groups = i2c_adapter_attr_groups, | 1212 | .groups = i2c_adapter_groups, |
| 1341 | .release = i2c_adapter_dev_release, | 1213 | .release = i2c_adapter_dev_release, |
| 1342 | }; | 1214 | }; |
| 1343 | EXPORT_SYMBOL_GPL(i2c_adapter_type); | 1215 | EXPORT_SYMBOL_GPL(i2c_adapter_type); |
| @@ -1419,8 +1291,6 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, | |||
| 1419 | if (of_get_property(node, "wakeup-source", NULL)) | 1291 | if (of_get_property(node, "wakeup-source", NULL)) |
| 1420 | info.flags |= I2C_CLIENT_WAKE; | 1292 | info.flags |= I2C_CLIENT_WAKE; |
| 1421 | 1293 | ||
| 1422 | request_module("%s%s", I2C_MODULE_PREFIX, info.type); | ||
| 1423 | |||
| 1424 | result = i2c_new_device(adap, &info); | 1294 | result = i2c_new_device(adap, &info); |
| 1425 | if (result == NULL) { | 1295 | if (result == NULL) { |
| 1426 | dev_err(&adap->dev, "of_i2c: Failure registering %s\n", | 1296 | dev_err(&adap->dev, "of_i2c: Failure registering %s\n", |
| @@ -1796,11 +1666,15 @@ void i2c_del_adapter(struct i2c_adapter *adap) | |||
| 1796 | /* device name is gone after device_unregister */ | 1666 | /* device name is gone after device_unregister */ |
| 1797 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); | 1667 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); |
| 1798 | 1668 | ||
| 1799 | /* clean up the sysfs representation */ | 1669 | /* wait until all references to the device are gone |
| 1670 | * | ||
| 1671 | * FIXME: This is old code and should ideally be replaced by an | ||
| 1672 | * alternative which results in decoupling the lifetime of the struct | ||
| 1673 | * device from the i2c_adapter, like spi or netdev do. Any solution | ||
| 1674 | * should be throughly tested with DEBUG_KOBJECT_RELEASE enabled! | ||
| 1675 | */ | ||
| 1800 | init_completion(&adap->dev_released); | 1676 | init_completion(&adap->dev_released); |
| 1801 | device_unregister(&adap->dev); | 1677 | device_unregister(&adap->dev); |
| 1802 | |||
| 1803 | /* wait for sysfs to drop all references */ | ||
| 1804 | wait_for_completion(&adap->dev_released); | 1678 | wait_for_completion(&adap->dev_released); |
| 1805 | 1679 | ||
| 1806 | /* free bus id */ | 1680 | /* free bus id */ |
| @@ -1859,14 +1733,6 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
| 1859 | if (res) | 1733 | if (res) |
| 1860 | return res; | 1734 | return res; |
| 1861 | 1735 | ||
| 1862 | /* Drivers should switch to dev_pm_ops instead. */ | ||
| 1863 | if (driver->suspend) | ||
| 1864 | pr_warn("i2c-core: driver [%s] using legacy suspend method\n", | ||
| 1865 | driver->driver.name); | ||
| 1866 | if (driver->resume) | ||
| 1867 | pr_warn("i2c-core: driver [%s] using legacy resume method\n", | ||
| 1868 | driver->driver.name); | ||
| 1869 | |||
| 1870 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); | 1736 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); |
| 1871 | 1737 | ||
| 1872 | INIT_LIST_HEAD(&driver->clients); | 1738 | INIT_LIST_HEAD(&driver->clients); |
