diff options
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 165 |
1 files changed, 114 insertions, 51 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0e45c296d3d2..8d80fceca6a4 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -46,6 +46,7 @@ static DEFINE_MUTEX(core_lock); | |||
46 | static DEFINE_IDR(i2c_adapter_idr); | 46 | static DEFINE_IDR(i2c_adapter_idr); |
47 | static LIST_HEAD(userspace_devices); | 47 | static LIST_HEAD(userspace_devices); |
48 | 48 | ||
49 | static struct device_type i2c_client_type; | ||
49 | static int i2c_check_addr(struct i2c_adapter *adapter, int addr); | 50 | static int i2c_check_addr(struct i2c_adapter *adapter, int addr); |
50 | static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); | 51 | static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); |
51 | 52 | ||
@@ -64,9 +65,13 @@ static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, | |||
64 | 65 | ||
65 | static int i2c_device_match(struct device *dev, struct device_driver *drv) | 66 | static int i2c_device_match(struct device *dev, struct device_driver *drv) |
66 | { | 67 | { |
67 | struct i2c_client *client = to_i2c_client(dev); | 68 | struct i2c_client *client = i2c_verify_client(dev); |
68 | struct i2c_driver *driver = to_i2c_driver(drv); | 69 | struct i2c_driver *driver; |
70 | |||
71 | if (!client) | ||
72 | return 0; | ||
69 | 73 | ||
74 | driver = to_i2c_driver(drv); | ||
70 | /* match on an id table if there is one */ | 75 | /* match on an id table if there is one */ |
71 | if (driver->id_table) | 76 | if (driver->id_table) |
72 | return i2c_match_id(driver->id_table, client) != NULL; | 77 | return i2c_match_id(driver->id_table, client) != NULL; |
@@ -94,10 +99,14 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
94 | 99 | ||
95 | static int i2c_device_probe(struct device *dev) | 100 | static int i2c_device_probe(struct device *dev) |
96 | { | 101 | { |
97 | struct i2c_client *client = to_i2c_client(dev); | 102 | struct i2c_client *client = i2c_verify_client(dev); |
98 | struct i2c_driver *driver = to_i2c_driver(dev->driver); | 103 | struct i2c_driver *driver; |
99 | int status; | 104 | int status; |
100 | 105 | ||
106 | if (!client) | ||
107 | return 0; | ||
108 | |||
109 | driver = to_i2c_driver(dev->driver); | ||
101 | if (!driver->probe || !driver->id_table) | 110 | if (!driver->probe || !driver->id_table) |
102 | return -ENODEV; | 111 | return -ENODEV; |
103 | client->driver = driver; | 112 | client->driver = driver; |
@@ -114,11 +123,11 @@ static int i2c_device_probe(struct device *dev) | |||
114 | 123 | ||
115 | static int i2c_device_remove(struct device *dev) | 124 | static int i2c_device_remove(struct device *dev) |
116 | { | 125 | { |
117 | struct i2c_client *client = to_i2c_client(dev); | 126 | struct i2c_client *client = i2c_verify_client(dev); |
118 | struct i2c_driver *driver; | 127 | struct i2c_driver *driver; |
119 | int status; | 128 | int status; |
120 | 129 | ||
121 | if (!dev->driver) | 130 | if (!client || !dev->driver) |
122 | return 0; | 131 | return 0; |
123 | 132 | ||
124 | driver = to_i2c_driver(dev->driver); | 133 | driver = to_i2c_driver(dev->driver); |
@@ -136,37 +145,40 @@ static int i2c_device_remove(struct device *dev) | |||
136 | 145 | ||
137 | static void i2c_device_shutdown(struct device *dev) | 146 | static void i2c_device_shutdown(struct device *dev) |
138 | { | 147 | { |
148 | struct i2c_client *client = i2c_verify_client(dev); | ||
139 | struct i2c_driver *driver; | 149 | struct i2c_driver *driver; |
140 | 150 | ||
141 | if (!dev->driver) | 151 | if (!client || !dev->driver) |
142 | return; | 152 | return; |
143 | driver = to_i2c_driver(dev->driver); | 153 | driver = to_i2c_driver(dev->driver); |
144 | if (driver->shutdown) | 154 | if (driver->shutdown) |
145 | driver->shutdown(to_i2c_client(dev)); | 155 | driver->shutdown(client); |
146 | } | 156 | } |
147 | 157 | ||
148 | static int i2c_device_suspend(struct device *dev, pm_message_t mesg) | 158 | static int i2c_device_suspend(struct device *dev, pm_message_t mesg) |
149 | { | 159 | { |
160 | struct i2c_client *client = i2c_verify_client(dev); | ||
150 | struct i2c_driver *driver; | 161 | struct i2c_driver *driver; |
151 | 162 | ||
152 | if (!dev->driver) | 163 | if (!client || !dev->driver) |
153 | return 0; | 164 | return 0; |
154 | driver = to_i2c_driver(dev->driver); | 165 | driver = to_i2c_driver(dev->driver); |
155 | if (!driver->suspend) | 166 | if (!driver->suspend) |
156 | return 0; | 167 | return 0; |
157 | return driver->suspend(to_i2c_client(dev), mesg); | 168 | return driver->suspend(client, mesg); |
158 | } | 169 | } |
159 | 170 | ||
160 | static int i2c_device_resume(struct device *dev) | 171 | static int i2c_device_resume(struct device *dev) |
161 | { | 172 | { |
173 | struct i2c_client *client = i2c_verify_client(dev); | ||
162 | struct i2c_driver *driver; | 174 | struct i2c_driver *driver; |
163 | 175 | ||
164 | if (!dev->driver) | 176 | if (!client || !dev->driver) |
165 | return 0; | 177 | return 0; |
166 | driver = to_i2c_driver(dev->driver); | 178 | driver = to_i2c_driver(dev->driver); |
167 | if (!driver->resume) | 179 | if (!driver->resume) |
168 | return 0; | 180 | return 0; |
169 | return driver->resume(to_i2c_client(dev)); | 181 | return driver->resume(client); |
170 | } | 182 | } |
171 | 183 | ||
172 | static void i2c_client_dev_release(struct device *dev) | 184 | static void i2c_client_dev_release(struct device *dev) |
@@ -175,10 +187,10 @@ static void i2c_client_dev_release(struct device *dev) | |||
175 | } | 187 | } |
176 | 188 | ||
177 | static ssize_t | 189 | static ssize_t |
178 | show_client_name(struct device *dev, struct device_attribute *attr, char *buf) | 190 | show_name(struct device *dev, struct device_attribute *attr, char *buf) |
179 | { | 191 | { |
180 | struct i2c_client *client = to_i2c_client(dev); | 192 | return sprintf(buf, "%s\n", dev->type == &i2c_client_type ? |
181 | return sprintf(buf, "%s\n", client->name); | 193 | to_i2c_client(dev)->name : to_i2c_adapter(dev)->name); |
182 | } | 194 | } |
183 | 195 | ||
184 | static ssize_t | 196 | static ssize_t |
@@ -188,18 +200,28 @@ show_modalias(struct device *dev, struct device_attribute *attr, char *buf) | |||
188 | return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); | 200 | return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); |
189 | } | 201 | } |
190 | 202 | ||
191 | static struct device_attribute i2c_dev_attrs[] = { | 203 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
192 | __ATTR(name, S_IRUGO, show_client_name, NULL), | 204 | static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); |
205 | |||
206 | static struct attribute *i2c_dev_attrs[] = { | ||
207 | &dev_attr_name.attr, | ||
193 | /* modalias helps coldplug: modprobe $(cat .../modalias) */ | 208 | /* modalias helps coldplug: modprobe $(cat .../modalias) */ |
194 | __ATTR(modalias, S_IRUGO, show_modalias, NULL), | 209 | &dev_attr_modalias.attr, |
195 | { }, | 210 | NULL |
211 | }; | ||
212 | |||
213 | static struct attribute_group i2c_dev_attr_group = { | ||
214 | .attrs = i2c_dev_attrs, | ||
215 | }; | ||
216 | |||
217 | static const struct attribute_group *i2c_dev_attr_groups[] = { | ||
218 | &i2c_dev_attr_group, | ||
219 | NULL | ||
196 | }; | 220 | }; |
197 | 221 | ||
198 | struct bus_type i2c_bus_type = { | 222 | struct bus_type i2c_bus_type = { |
199 | .name = "i2c", | 223 | .name = "i2c", |
200 | .dev_attrs = i2c_dev_attrs, | ||
201 | .match = i2c_device_match, | 224 | .match = i2c_device_match, |
202 | .uevent = i2c_device_uevent, | ||
203 | .probe = i2c_device_probe, | 225 | .probe = i2c_device_probe, |
204 | .remove = i2c_device_remove, | 226 | .remove = i2c_device_remove, |
205 | .shutdown = i2c_device_shutdown, | 227 | .shutdown = i2c_device_shutdown, |
@@ -208,6 +230,12 @@ struct bus_type i2c_bus_type = { | |||
208 | }; | 230 | }; |
209 | EXPORT_SYMBOL_GPL(i2c_bus_type); | 231 | EXPORT_SYMBOL_GPL(i2c_bus_type); |
210 | 232 | ||
233 | static struct device_type i2c_client_type = { | ||
234 | .groups = i2c_dev_attr_groups, | ||
235 | .uevent = i2c_device_uevent, | ||
236 | .release = i2c_client_dev_release, | ||
237 | }; | ||
238 | |||
211 | 239 | ||
212 | /** | 240 | /** |
213 | * i2c_verify_client - return parameter as i2c_client, or NULL | 241 | * i2c_verify_client - return parameter as i2c_client, or NULL |
@@ -220,7 +248,7 @@ EXPORT_SYMBOL_GPL(i2c_bus_type); | |||
220 | */ | 248 | */ |
221 | struct i2c_client *i2c_verify_client(struct device *dev) | 249 | struct i2c_client *i2c_verify_client(struct device *dev) |
222 | { | 250 | { |
223 | return (dev->bus == &i2c_bus_type) | 251 | return (dev->type == &i2c_client_type) |
224 | ? to_i2c_client(dev) | 252 | ? to_i2c_client(dev) |
225 | : NULL; | 253 | : NULL; |
226 | } | 254 | } |
@@ -273,7 +301,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) | |||
273 | 301 | ||
274 | client->dev.parent = &client->adapter->dev; | 302 | client->dev.parent = &client->adapter->dev; |
275 | client->dev.bus = &i2c_bus_type; | 303 | client->dev.bus = &i2c_bus_type; |
276 | client->dev.release = i2c_client_dev_release; | 304 | client->dev.type = &i2c_client_type; |
277 | 305 | ||
278 | dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), | 306 | dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), |
279 | client->addr); | 307 | client->addr); |
@@ -368,13 +396,6 @@ static void i2c_adapter_dev_release(struct device *dev) | |||
368 | complete(&adap->dev_released); | 396 | complete(&adap->dev_released); |
369 | } | 397 | } |
370 | 398 | ||
371 | static ssize_t | ||
372 | show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
373 | { | ||
374 | struct i2c_adapter *adap = to_i2c_adapter(dev); | ||
375 | return sprintf(buf, "%s\n", adap->name); | ||
376 | } | ||
377 | |||
378 | /* | 399 | /* |
379 | * Let users instantiate I2C devices through sysfs. This can be used when | 400 | * Let users instantiate I2C devices through sysfs. This can be used when |
380 | * platform initialization code doesn't contain the proper data for | 401 | * platform initialization code doesn't contain the proper data for |
@@ -493,19 +514,34 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, | |||
493 | return res; | 514 | return res; |
494 | } | 515 | } |
495 | 516 | ||
496 | static struct device_attribute i2c_adapter_attrs[] = { | 517 | static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device); |
497 | __ATTR(name, S_IRUGO, show_adapter_name, NULL), | 518 | static DEVICE_ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device); |
498 | __ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device), | 519 | |
499 | __ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device), | 520 | static struct attribute *i2c_adapter_attrs[] = { |
500 | { }, | 521 | &dev_attr_name.attr, |
522 | &dev_attr_new_device.attr, | ||
523 | &dev_attr_delete_device.attr, | ||
524 | NULL | ||
501 | }; | 525 | }; |
502 | 526 | ||
503 | static struct class i2c_adapter_class = { | 527 | static struct attribute_group i2c_adapter_attr_group = { |
504 | .owner = THIS_MODULE, | 528 | .attrs = i2c_adapter_attrs, |
505 | .name = "i2c-adapter", | ||
506 | .dev_attrs = i2c_adapter_attrs, | ||
507 | }; | 529 | }; |
508 | 530 | ||
531 | static const struct attribute_group *i2c_adapter_attr_groups[] = { | ||
532 | &i2c_adapter_attr_group, | ||
533 | NULL | ||
534 | }; | ||
535 | |||
536 | static struct device_type i2c_adapter_type = { | ||
537 | .groups = i2c_adapter_attr_groups, | ||
538 | .release = i2c_adapter_dev_release, | ||
539 | }; | ||
540 | |||
541 | #ifdef CONFIG_I2C_COMPAT | ||
542 | static struct class_compat *i2c_adapter_compat_class; | ||
543 | #endif | ||
544 | |||
509 | static void i2c_scan_static_board_info(struct i2c_adapter *adapter) | 545 | static void i2c_scan_static_board_info(struct i2c_adapter *adapter) |
510 | { | 546 | { |
511 | struct i2c_devinfo *devinfo; | 547 | struct i2c_devinfo *devinfo; |
@@ -555,14 +591,22 @@ static int i2c_register_adapter(struct i2c_adapter *adap) | |||
555 | adap->timeout = HZ; | 591 | adap->timeout = HZ; |
556 | 592 | ||
557 | dev_set_name(&adap->dev, "i2c-%d", adap->nr); | 593 | dev_set_name(&adap->dev, "i2c-%d", adap->nr); |
558 | adap->dev.release = &i2c_adapter_dev_release; | 594 | adap->dev.bus = &i2c_bus_type; |
559 | adap->dev.class = &i2c_adapter_class; | 595 | adap->dev.type = &i2c_adapter_type; |
560 | res = device_register(&adap->dev); | 596 | res = device_register(&adap->dev); |
561 | if (res) | 597 | if (res) |
562 | goto out_list; | 598 | goto out_list; |
563 | 599 | ||
564 | dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); | 600 | dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); |
565 | 601 | ||
602 | #ifdef CONFIG_I2C_COMPAT | ||
603 | res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev, | ||
604 | adap->dev.parent); | ||
605 | if (res) | ||
606 | dev_warn(&adap->dev, | ||
607 | "Failed to create compatibility class link\n"); | ||
608 | #endif | ||
609 | |||
566 | /* create pre-declared device nodes */ | 610 | /* create pre-declared device nodes */ |
567 | if (adap->nr < __i2c_first_dynamic_bus_num) | 611 | if (adap->nr < __i2c_first_dynamic_bus_num) |
568 | i2c_scan_static_board_info(adap); | 612 | i2c_scan_static_board_info(adap); |
@@ -741,6 +785,11 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
741 | checking the returned value. */ | 785 | checking the returned value. */ |
742 | res = device_for_each_child(&adap->dev, NULL, __unregister_client); | 786 | res = device_for_each_child(&adap->dev, NULL, __unregister_client); |
743 | 787 | ||
788 | #ifdef CONFIG_I2C_COMPAT | ||
789 | class_compat_remove_link(i2c_adapter_compat_class, &adap->dev, | ||
790 | adap->dev.parent); | ||
791 | #endif | ||
792 | |||
744 | /* clean up the sysfs representation */ | 793 | /* clean up the sysfs representation */ |
745 | init_completion(&adap->dev_released); | 794 | init_completion(&adap->dev_released); |
746 | device_unregister(&adap->dev); | 795 | device_unregister(&adap->dev); |
@@ -768,9 +817,13 @@ EXPORT_SYMBOL(i2c_del_adapter); | |||
768 | 817 | ||
769 | static int __attach_adapter(struct device *dev, void *data) | 818 | static int __attach_adapter(struct device *dev, void *data) |
770 | { | 819 | { |
771 | struct i2c_adapter *adapter = to_i2c_adapter(dev); | 820 | struct i2c_adapter *adapter; |
772 | struct i2c_driver *driver = data; | 821 | struct i2c_driver *driver = data; |
773 | 822 | ||
823 | if (dev->type != &i2c_adapter_type) | ||
824 | return 0; | ||
825 | adapter = to_i2c_adapter(dev); | ||
826 | |||
774 | i2c_detect(adapter, driver); | 827 | i2c_detect(adapter, driver); |
775 | 828 | ||
776 | /* Legacy drivers scan i2c busses directly */ | 829 | /* Legacy drivers scan i2c busses directly */ |
@@ -809,8 +862,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
809 | INIT_LIST_HEAD(&driver->clients); | 862 | INIT_LIST_HEAD(&driver->clients); |
810 | /* Walk the adapters that are already present */ | 863 | /* Walk the adapters that are already present */ |
811 | mutex_lock(&core_lock); | 864 | mutex_lock(&core_lock); |
812 | class_for_each_device(&i2c_adapter_class, NULL, driver, | 865 | bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter); |
813 | __attach_adapter); | ||
814 | mutex_unlock(&core_lock); | 866 | mutex_unlock(&core_lock); |
815 | 867 | ||
816 | return 0; | 868 | return 0; |
@@ -819,10 +871,14 @@ EXPORT_SYMBOL(i2c_register_driver); | |||
819 | 871 | ||
820 | static int __detach_adapter(struct device *dev, void *data) | 872 | static int __detach_adapter(struct device *dev, void *data) |
821 | { | 873 | { |
822 | struct i2c_adapter *adapter = to_i2c_adapter(dev); | 874 | struct i2c_adapter *adapter; |
823 | struct i2c_driver *driver = data; | 875 | struct i2c_driver *driver = data; |
824 | struct i2c_client *client, *_n; | 876 | struct i2c_client *client, *_n; |
825 | 877 | ||
878 | if (dev->type != &i2c_adapter_type) | ||
879 | return 0; | ||
880 | adapter = to_i2c_adapter(dev); | ||
881 | |||
826 | /* Remove the devices we created ourselves as the result of hardware | 882 | /* Remove the devices we created ourselves as the result of hardware |
827 | * probing (using a driver's detect method) */ | 883 | * probing (using a driver's detect method) */ |
828 | list_for_each_entry_safe(client, _n, &driver->clients, detected) { | 884 | list_for_each_entry_safe(client, _n, &driver->clients, detected) { |
@@ -850,8 +906,7 @@ static int __detach_adapter(struct device *dev, void *data) | |||
850 | void i2c_del_driver(struct i2c_driver *driver) | 906 | void i2c_del_driver(struct i2c_driver *driver) |
851 | { | 907 | { |
852 | mutex_lock(&core_lock); | 908 | mutex_lock(&core_lock); |
853 | class_for_each_device(&i2c_adapter_class, NULL, driver, | 909 | bus_for_each_dev(&i2c_bus_type, NULL, driver, __detach_adapter); |
854 | __detach_adapter); | ||
855 | mutex_unlock(&core_lock); | 910 | mutex_unlock(&core_lock); |
856 | 911 | ||
857 | driver_unregister(&driver->driver); | 912 | driver_unregister(&driver->driver); |
@@ -940,17 +995,23 @@ static int __init i2c_init(void) | |||
940 | retval = bus_register(&i2c_bus_type); | 995 | retval = bus_register(&i2c_bus_type); |
941 | if (retval) | 996 | if (retval) |
942 | return retval; | 997 | return retval; |
943 | retval = class_register(&i2c_adapter_class); | 998 | #ifdef CONFIG_I2C_COMPAT |
944 | if (retval) | 999 | i2c_adapter_compat_class = class_compat_register("i2c-adapter"); |
1000 | if (!i2c_adapter_compat_class) { | ||
1001 | retval = -ENOMEM; | ||
945 | goto bus_err; | 1002 | goto bus_err; |
1003 | } | ||
1004 | #endif | ||
946 | retval = i2c_add_driver(&dummy_driver); | 1005 | retval = i2c_add_driver(&dummy_driver); |
947 | if (retval) | 1006 | if (retval) |
948 | goto class_err; | 1007 | goto class_err; |
949 | return 0; | 1008 | return 0; |
950 | 1009 | ||
951 | class_err: | 1010 | class_err: |
952 | class_unregister(&i2c_adapter_class); | 1011 | #ifdef CONFIG_I2C_COMPAT |
1012 | class_compat_unregister(i2c_adapter_compat_class); | ||
953 | bus_err: | 1013 | bus_err: |
1014 | #endif | ||
954 | bus_unregister(&i2c_bus_type); | 1015 | bus_unregister(&i2c_bus_type); |
955 | return retval; | 1016 | return retval; |
956 | } | 1017 | } |
@@ -958,7 +1019,9 @@ bus_err: | |||
958 | static void __exit i2c_exit(void) | 1019 | static void __exit i2c_exit(void) |
959 | { | 1020 | { |
960 | i2c_del_driver(&dummy_driver); | 1021 | i2c_del_driver(&dummy_driver); |
961 | class_unregister(&i2c_adapter_class); | 1022 | #ifdef CONFIG_I2C_COMPAT |
1023 | class_compat_unregister(i2c_adapter_compat_class); | ||
1024 | #endif | ||
962 | bus_unregister(&i2c_bus_type); | 1025 | bus_unregister(&i2c_bus_type); |
963 | } | 1026 | } |
964 | 1027 | ||