aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/i2c-dev.c')
-rw-r--r--drivers/i2c/i2c-dev.c73
1 files changed, 45 insertions, 28 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 5f3a52d517c3..c90ce50b619f 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -28,6 +28,8 @@
28 28
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/device.h>
32#include <linux/notifier.h>
31#include <linux/fs.h> 33#include <linux/fs.h>
32#include <linux/slab.h> 34#include <linux/slab.h>
33#include <linux/init.h> 35#include <linux/init.h>
@@ -37,16 +39,13 @@
37#include <linux/jiffies.h> 39#include <linux/jiffies.h>
38#include <linux/uaccess.h> 40#include <linux/uaccess.h>
39 41
40static struct i2c_driver i2cdev_driver;
41
42/* 42/*
43 * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a 43 * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
44 * slave (i2c_client) with which messages will be exchanged. It's coupled 44 * slave (i2c_client) with which messages will be exchanged. It's coupled
45 * with a character special file which is accessed by user mode drivers. 45 * with a character special file which is accessed by user mode drivers.
46 * 46 *
47 * The list of i2c_dev structures is parallel to the i2c_adapter lists 47 * The list of i2c_dev structures is parallel to the i2c_adapter lists
48 * maintained by the driver model, and is updated using notifications 48 * maintained by the driver model, and is updated using bus notifications.
49 * delivered to the i2cdev_driver.
50 */ 49 */
51struct i2c_dev { 50struct i2c_dev {
52 struct list_head list; 51 struct list_head list;
@@ -192,13 +191,12 @@ static int i2cdev_check(struct device *dev, void *addrp)
192/* walk up mux tree */ 191/* walk up mux tree */
193static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr) 192static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr)
194{ 193{
194 struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
195 int result; 195 int result;
196 196
197 result = device_for_each_child(&adapter->dev, &addr, i2cdev_check); 197 result = device_for_each_child(&adapter->dev, &addr, i2cdev_check);
198 198 if (!result && parent)
199 if (!result && i2c_parent_is_i2c_adapter(adapter)) 199 result = i2cdev_check_mux_parents(parent, addr);
200 result = i2cdev_check_mux_parents(
201 to_i2c_adapter(adapter->dev.parent), addr);
202 200
203 return result; 201 return result;
204} 202}
@@ -222,11 +220,11 @@ static int i2cdev_check_mux_children(struct device *dev, void *addrp)
222 driver bound to it, as NOT busy. */ 220 driver bound to it, as NOT busy. */
223static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) 221static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
224{ 222{
223 struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
225 int result = 0; 224 int result = 0;
226 225
227 if (i2c_parent_is_i2c_adapter(adapter)) 226 if (parent)
228 result = i2cdev_check_mux_parents( 227 result = i2cdev_check_mux_parents(parent, addr);
229 to_i2c_adapter(adapter->dev.parent), addr);
230 228
231 if (!result) 229 if (!result)
232 result = device_for_each_child(&adapter->dev, &addr, 230 result = device_for_each_child(&adapter->dev, &addr,
@@ -492,7 +490,6 @@ static int i2cdev_open(struct inode *inode, struct file *file)
492 return -ENOMEM; 490 return -ENOMEM;
493 } 491 }
494 snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr); 492 snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
495 client->driver = &i2cdev_driver;
496 493
497 client->adapter = adap; 494 client->adapter = adap;
498 file->private_data = client; 495 file->private_data = client;
@@ -523,19 +520,18 @@ static const struct file_operations i2cdev_fops = {
523 520
524/* ------------------------------------------------------------------------- */ 521/* ------------------------------------------------------------------------- */
525 522
526/*
527 * The legacy "i2cdev_driver" is used primarily to get notifications when
528 * I2C adapters are added or removed, so that each one gets an i2c_dev
529 * and is thus made available to userspace driver code.
530 */
531
532static struct class *i2c_dev_class; 523static struct class *i2c_dev_class;
533 524
534static int i2cdev_attach_adapter(struct i2c_adapter *adap) 525static int i2cdev_attach_adapter(struct device *dev, void *dummy)
535{ 526{
527 struct i2c_adapter *adap;
536 struct i2c_dev *i2c_dev; 528 struct i2c_dev *i2c_dev;
537 int res; 529 int res;
538 530
531 if (dev->type != &i2c_adapter_type)
532 return 0;
533 adap = to_i2c_adapter(dev);
534
539 i2c_dev = get_free_i2c_dev(adap); 535 i2c_dev = get_free_i2c_dev(adap);
540 if (IS_ERR(i2c_dev)) 536 if (IS_ERR(i2c_dev))
541 return PTR_ERR(i2c_dev); 537 return PTR_ERR(i2c_dev);
@@ -562,10 +558,15 @@ error:
562 return res; 558 return res;
563} 559}
564 560
565static int i2cdev_detach_adapter(struct i2c_adapter *adap) 561static int i2cdev_detach_adapter(struct device *dev, void *dummy)
566{ 562{
563 struct i2c_adapter *adap;
567 struct i2c_dev *i2c_dev; 564 struct i2c_dev *i2c_dev;
568 565
566 if (dev->type != &i2c_adapter_type)
567 return 0;
568 adap = to_i2c_adapter(dev);
569
569 i2c_dev = i2c_dev_get_by_minor(adap->nr); 570 i2c_dev = i2c_dev_get_by_minor(adap->nr);
570 if (!i2c_dev) /* attach_adapter must have failed */ 571 if (!i2c_dev) /* attach_adapter must have failed */
571 return 0; 572 return 0;
@@ -578,12 +579,23 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
578 return 0; 579 return 0;
579} 580}
580 581
581static struct i2c_driver i2cdev_driver = { 582int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
582 .driver = { 583 void *data)
583 .name = "dev_driver", 584{
584 }, 585 struct device *dev = data;
585 .attach_adapter = i2cdev_attach_adapter, 586
586 .detach_adapter = i2cdev_detach_adapter, 587 switch (action) {
588 case BUS_NOTIFY_ADD_DEVICE:
589 return i2cdev_attach_adapter(dev, NULL);
590 case BUS_NOTIFY_DEL_DEVICE:
591 return i2cdev_detach_adapter(dev, NULL);
592 }
593
594 return 0;
595}
596
597static struct notifier_block i2cdev_notifier = {
598 .notifier_call = i2cdev_notifier_call,
587}; 599};
588 600
589/* ------------------------------------------------------------------------- */ 601/* ------------------------------------------------------------------------- */
@@ -608,10 +620,14 @@ static int __init i2c_dev_init(void)
608 goto out_unreg_chrdev; 620 goto out_unreg_chrdev;
609 } 621 }
610 622
611 res = i2c_add_driver(&i2cdev_driver); 623 /* Keep track of adapters which will be added or removed later */
624 res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
612 if (res) 625 if (res)
613 goto out_unreg_class; 626 goto out_unreg_class;
614 627
628 /* Bind to already existing adapters right away */
629 i2c_for_each_dev(NULL, i2cdev_attach_adapter);
630
615 return 0; 631 return 0;
616 632
617out_unreg_class: 633out_unreg_class:
@@ -625,7 +641,8 @@ out:
625 641
626static void __exit i2c_dev_exit(void) 642static void __exit i2c_dev_exit(void)
627{ 643{
628 i2c_del_driver(&i2cdev_driver); 644 bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
645 i2c_for_each_dev(NULL, i2cdev_detach_adapter);
629 class_destroy(i2c_dev_class); 646 class_destroy(i2c_dev_class);
630 unregister_chrdev(I2C_MAJOR, "i2c"); 647 unregister_chrdev(I2C_MAJOR, "i2c");
631} 648}