xref: /openbmc/linux/drivers/i2c/i2c-dev.c (revision b97d6790d03b763eca08847a9a5869a4291b9f9a)
1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds     i2c-dev.c - i2c-bus driver, char device interface
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds     Copyright (C) 1995-97 Simon G. Vogl
61da177e4SLinus Torvalds     Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
71da177e4SLinus Torvalds     Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds */
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds /* Note that this is a complete rewrite of Simon Vogl's i2c-dev module.
121da177e4SLinus Torvalds    But I have used so much of his original code and ideas that it seems
131da177e4SLinus Torvalds    only fair to recognize him as co-author -- Frodo */
141da177e4SLinus Torvalds 
151da177e4SLinus Torvalds /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
161da177e4SLinus Torvalds 
17295e0e7bSAndy Shevchenko #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
18295e0e7bSAndy Shevchenko 
19d6760b14SErico Nunes #include <linux/cdev.h>
20f01adfabSWolfram Sang #include <linux/compat.h>
219ea3e941SJean Delvare #include <linux/device.h>
221da177e4SLinus Torvalds #include <linux/fs.h>
231da177e4SLinus Torvalds #include <linux/i2c-dev.h>
24a8766073SWolfram Sang #include <linux/i2c.h>
25a8766073SWolfram Sang #include <linux/init.h>
26cd97f39bSJean Delvare #include <linux/jiffies.h>
27a8766073SWolfram Sang #include <linux/kernel.h>
28a8766073SWolfram Sang #include <linux/list.h>
29a8766073SWolfram Sang #include <linux/module.h>
30a8766073SWolfram Sang #include <linux/notifier.h>
31a8766073SWolfram Sang #include <linux/slab.h>
32ae5624fcSFarid Hammane #include <linux/uaccess.h>
331da177e4SLinus Torvalds 
34907135aaSDavid Brownell /*
35907135aaSDavid Brownell  * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
36907135aaSDavid Brownell  * slave (i2c_client) with which messages will be exchanged.  It's coupled
37907135aaSDavid Brownell  * with a character special file which is accessed by user mode drivers.
38907135aaSDavid Brownell  *
39907135aaSDavid Brownell  * The list of i2c_dev structures is parallel to the i2c_adapter lists
409ea3e941SJean Delvare  * maintained by the driver model, and is updated using bus notifications.
41907135aaSDavid Brownell  */
421da177e4SLinus Torvalds struct i2c_dev {
43f3b3aadbSJean Delvare 	struct list_head list;
441da177e4SLinus Torvalds 	struct i2c_adapter *adap;
451413ef63SKevin Hao 	struct device dev;
46d6760b14SErico Nunes 	struct cdev cdev;
471da177e4SLinus Torvalds };
481da177e4SLinus Torvalds 
498a6d508aSChengguang Xu #define I2C_MINORS	(MINORMASK + 1)
50f3b3aadbSJean Delvare static LIST_HEAD(i2c_dev_list);
51f3b3aadbSJean Delvare static DEFINE_SPINLOCK(i2c_dev_list_lock);
521da177e4SLinus Torvalds 
i2c_dev_get_by_minor(unsigned index)531da177e4SLinus Torvalds static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
541da177e4SLinus Torvalds {
551da177e4SLinus Torvalds 	struct i2c_dev *i2c_dev;
561da177e4SLinus Torvalds 
57f3b3aadbSJean Delvare 	spin_lock(&i2c_dev_list_lock);
58f3b3aadbSJean Delvare 	list_for_each_entry(i2c_dev, &i2c_dev_list, list) {
59f3b3aadbSJean Delvare 		if (i2c_dev->adap->nr == index)
60f3b3aadbSJean Delvare 			goto found;
61f3b3aadbSJean Delvare 	}
62f3b3aadbSJean Delvare 	i2c_dev = NULL;
63f3b3aadbSJean Delvare found:
64f3b3aadbSJean Delvare 	spin_unlock(&i2c_dev_list_lock);
651da177e4SLinus Torvalds 	return i2c_dev;
661da177e4SLinus Torvalds }
671da177e4SLinus Torvalds 
get_free_i2c_dev(struct i2c_adapter * adap)681da177e4SLinus Torvalds static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
691da177e4SLinus Torvalds {
701da177e4SLinus Torvalds 	struct i2c_dev *i2c_dev;
711da177e4SLinus Torvalds 
72f3b3aadbSJean Delvare 	if (adap->nr >= I2C_MINORS) {
73295e0e7bSAndy Shevchenko 		pr_err("Out of device minors (%d)\n", adap->nr);
74f3b3aadbSJean Delvare 		return ERR_PTR(-ENODEV);
75f3b3aadbSJean Delvare 	}
76f3b3aadbSJean Delvare 
775263ebb5SDeepak Saxena 	i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
781da177e4SLinus Torvalds 	if (!i2c_dev)
791da177e4SLinus Torvalds 		return ERR_PTR(-ENOMEM);
809455e4c9SJean Delvare 	i2c_dev->adap = adap;
81f3b3aadbSJean Delvare 
82f3b3aadbSJean Delvare 	spin_lock(&i2c_dev_list_lock);
83f3b3aadbSJean Delvare 	list_add_tail(&i2c_dev->list, &i2c_dev_list);
84f3b3aadbSJean Delvare 	spin_unlock(&i2c_dev_list_lock);
851da177e4SLinus Torvalds 	return i2c_dev;
861da177e4SLinus Torvalds }
871da177e4SLinus Torvalds 
put_i2c_dev(struct i2c_dev * i2c_dev,bool del_cdev)881413ef63SKevin Hao static void put_i2c_dev(struct i2c_dev *i2c_dev, bool del_cdev)
891da177e4SLinus Torvalds {
90f3b3aadbSJean Delvare 	spin_lock(&i2c_dev_list_lock);
91f3b3aadbSJean Delvare 	list_del(&i2c_dev->list);
92f3b3aadbSJean Delvare 	spin_unlock(&i2c_dev_list_lock);
931413ef63SKevin Hao 	if (del_cdev)
941413ef63SKevin Hao 		cdev_device_del(&i2c_dev->cdev, &i2c_dev->dev);
951413ef63SKevin Hao 	put_device(&i2c_dev->dev);
961da177e4SLinus Torvalds }
971da177e4SLinus Torvalds 
name_show(struct device * dev,struct device_attribute * attr,char * buf)9845f176aeSGuenter Roeck static ssize_t name_show(struct device *dev,
99ac11d060SGreg Kroah-Hartman 			 struct device_attribute *attr, char *buf)
1001da177e4SLinus Torvalds {
101ac11d060SGreg Kroah-Hartman 	struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(dev->devt));
10279472132SGreg Kroah-Hartman 
10379472132SGreg Kroah-Hartman 	if (!i2c_dev)
10479472132SGreg Kroah-Hartman 		return -ENODEV;
105b18f32d9SAndy Shevchenko 	return sysfs_emit(buf, "%s\n", i2c_dev->adap->name);
1061da177e4SLinus Torvalds }
10745f176aeSGuenter Roeck static DEVICE_ATTR_RO(name);
10845f176aeSGuenter Roeck 
10945f176aeSGuenter Roeck static struct attribute *i2c_attrs[] = {
11045f176aeSGuenter Roeck 	&dev_attr_name.attr,
11145f176aeSGuenter Roeck 	NULL,
11245f176aeSGuenter Roeck };
11345f176aeSGuenter Roeck ATTRIBUTE_GROUPS(i2c);
1141da177e4SLinus Torvalds 
115907135aaSDavid Brownell /* ------------------------------------------------------------------------- */
116907135aaSDavid Brownell 
117907135aaSDavid Brownell /*
118907135aaSDavid Brownell  * After opening an instance of this character special file, a file
119907135aaSDavid Brownell  * descriptor starts out associated only with an i2c_adapter (and bus).
120907135aaSDavid Brownell  *
121907135aaSDavid Brownell  * Using the I2C_RDWR ioctl(), you can then *immediately* issue i2c_msg
122907135aaSDavid Brownell  * traffic to any devices on the bus used by that adapter.  That's because
123907135aaSDavid Brownell  * the i2c_msg vectors embed all the addressing information they need, and
124907135aaSDavid Brownell  * are submitted directly to an i2c_adapter.  However, SMBus-only adapters
125907135aaSDavid Brownell  * don't support that interface.
126907135aaSDavid Brownell  *
127907135aaSDavid Brownell  * To use read()/write() system calls on that file descriptor, or to use
128907135aaSDavid Brownell  * SMBus interfaces (and work with SMBus-only hosts!), you must first issue
129907135aaSDavid Brownell  * an I2C_SLAVE (or I2C_SLAVE_FORCE) ioctl.  That configures an anonymous
130907135aaSDavid Brownell  * (never registered) i2c_client so it holds the addressing information
131907135aaSDavid Brownell  * needed by those system calls and by this SMBus interface.
132907135aaSDavid Brownell  */
133907135aaSDavid Brownell 
i2cdev_read(struct file * file,char __user * buf,size_t count,loff_t * offset)1341da177e4SLinus Torvalds static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,
1351da177e4SLinus Torvalds 		loff_t *offset)
1361da177e4SLinus Torvalds {
1371da177e4SLinus Torvalds 	char *tmp;
1381da177e4SLinus Torvalds 	int ret;
1391da177e4SLinus Torvalds 
1400be16c30SH Hartley Sweeten 	struct i2c_client *client = file->private_data;
1411da177e4SLinus Torvalds 
1421da177e4SLinus Torvalds 	if (count > 8192)
1431da177e4SLinus Torvalds 		count = 8192;
1441da177e4SLinus Torvalds 
14586ff25edSGreg Kroah-Hartman 	tmp = kzalloc(count, GFP_KERNEL);
1461da177e4SLinus Torvalds 	if (tmp == NULL)
1471da177e4SLinus Torvalds 		return -ENOMEM;
1481da177e4SLinus Torvalds 
149295e0e7bSAndy Shevchenko 	pr_debug("i2c-%d reading %zu bytes.\n", iminor(file_inode(file)), count);
1501da177e4SLinus Torvalds 
1511da177e4SLinus Torvalds 	ret = i2c_master_recv(client, tmp, count);
1521da177e4SLinus Torvalds 	if (ret >= 0)
15386ff25edSGreg Kroah-Hartman 		if (copy_to_user(buf, tmp, ret))
15486ff25edSGreg Kroah-Hartman 			ret = -EFAULT;
1551da177e4SLinus Torvalds 	kfree(tmp);
1561da177e4SLinus Torvalds 	return ret;
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds 
i2cdev_write(struct file * file,const char __user * buf,size_t count,loff_t * offset)159ae5624fcSFarid Hammane static ssize_t i2cdev_write(struct file *file, const char __user *buf,
160ae5624fcSFarid Hammane 		size_t count, loff_t *offset)
1611da177e4SLinus Torvalds {
1621da177e4SLinus Torvalds 	int ret;
1631da177e4SLinus Torvalds 	char *tmp;
1640be16c30SH Hartley Sweeten 	struct i2c_client *client = file->private_data;
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds 	if (count > 8192)
1671da177e4SLinus Torvalds 		count = 8192;
1681da177e4SLinus Torvalds 
169f1c2e33cSJulia Lawall 	tmp = memdup_user(buf, count);
170f1c2e33cSJulia Lawall 	if (IS_ERR(tmp))
171f1c2e33cSJulia Lawall 		return PTR_ERR(tmp);
1721da177e4SLinus Torvalds 
173295e0e7bSAndy Shevchenko 	pr_debug("i2c-%d writing %zu bytes.\n", iminor(file_inode(file)), count);
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds 	ret = i2c_master_send(client, tmp, count);
1761da177e4SLinus Torvalds 	kfree(tmp);
1771da177e4SLinus Torvalds 	return ret;
1781da177e4SLinus Torvalds }
1791da177e4SLinus Torvalds 
i2cdev_check(struct device * dev,void * addrp)1809b766b81SDavid Brownell static int i2cdev_check(struct device *dev, void *addrp)
1819b766b81SDavid Brownell {
1829b766b81SDavid Brownell 	struct i2c_client *client = i2c_verify_client(dev);
1839b766b81SDavid Brownell 
1849b766b81SDavid Brownell 	if (!client || client->addr != *(unsigned int *)addrp)
1859b766b81SDavid Brownell 		return 0;
1869b766b81SDavid Brownell 
1879b766b81SDavid Brownell 	return dev->driver ? -EBUSY : 0;
1889b766b81SDavid Brownell }
1899b766b81SDavid Brownell 
1900826374bSMichael Lawnick /* walk up mux tree */
i2cdev_check_mux_parents(struct i2c_adapter * adapter,int addr)1910826374bSMichael Lawnick static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr)
1920826374bSMichael Lawnick {
19397cc4d49SJean Delvare 	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
1940826374bSMichael Lawnick 	int result;
1950826374bSMichael Lawnick 
1960826374bSMichael Lawnick 	result = device_for_each_child(&adapter->dev, &addr, i2cdev_check);
19797cc4d49SJean Delvare 	if (!result && parent)
19897cc4d49SJean Delvare 		result = i2cdev_check_mux_parents(parent, addr);
1990826374bSMichael Lawnick 
2000826374bSMichael Lawnick 	return result;
2010826374bSMichael Lawnick }
2020826374bSMichael Lawnick 
2030826374bSMichael Lawnick /* recurse down mux tree */
i2cdev_check_mux_children(struct device * dev,void * addrp)2040826374bSMichael Lawnick static int i2cdev_check_mux_children(struct device *dev, void *addrp)
2050826374bSMichael Lawnick {
2060826374bSMichael Lawnick 	int result;
2070826374bSMichael Lawnick 
2080826374bSMichael Lawnick 	if (dev->type == &i2c_adapter_type)
2090826374bSMichael Lawnick 		result = device_for_each_child(dev, addrp,
2100826374bSMichael Lawnick 						i2cdev_check_mux_children);
2110826374bSMichael Lawnick 	else
2120826374bSMichael Lawnick 		result = i2cdev_check(dev, addrp);
2130826374bSMichael Lawnick 
2140826374bSMichael Lawnick 	return result;
2150826374bSMichael Lawnick }
2160826374bSMichael Lawnick 
217bd4217d8SJean Delvare /* This address checking function differs from the one in i2c-core
218bd4217d8SJean Delvare    in that it considers an address with a registered device, but no
2199b766b81SDavid Brownell    driver bound to it, as NOT busy. */
i2cdev_check_addr(struct i2c_adapter * adapter,unsigned int addr)220bd4217d8SJean Delvare static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
221bd4217d8SJean Delvare {
22297cc4d49SJean Delvare 	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
2230826374bSMichael Lawnick 	int result = 0;
2240826374bSMichael Lawnick 
22597cc4d49SJean Delvare 	if (parent)
22697cc4d49SJean Delvare 		result = i2cdev_check_mux_parents(parent, addr);
2270826374bSMichael Lawnick 
2280826374bSMichael Lawnick 	if (!result)
2290826374bSMichael Lawnick 		result = device_for_each_child(&adapter->dev, &addr,
2300826374bSMichael Lawnick 						i2cdev_check_mux_children);
2310826374bSMichael Lawnick 
2320826374bSMichael Lawnick 	return result;
233bd4217d8SJean Delvare }
234bd4217d8SJean Delvare 
i2cdev_ioctl_rdwr(struct i2c_client * client,unsigned nmsgs,struct i2c_msg * msgs)235c57d3e7aSJean Delvare static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
2367d5cb456SAl Viro 		unsigned nmsgs, struct i2c_msg *msgs)
237dba7997aSJean Delvare {
238dba7997aSJean Delvare 	u8 __user **data_ptrs;
239dba7997aSJean Delvare 	int i, res;
240dba7997aSJean Delvare 
2416da2ec56SKees Cook 	data_ptrs = kmalloc_array(nmsgs, sizeof(u8 __user *), GFP_KERNEL);
242dba7997aSJean Delvare 	if (data_ptrs == NULL) {
2437d5cb456SAl Viro 		kfree(msgs);
244dba7997aSJean Delvare 		return -ENOMEM;
245dba7997aSJean Delvare 	}
246dba7997aSJean Delvare 
247dba7997aSJean Delvare 	res = 0;
2487d5cb456SAl Viro 	for (i = 0; i < nmsgs; i++) {
249838bfa60SJean Delvare 		/* Limit the size of the message to a sane amount */
2507d5cb456SAl Viro 		if (msgs[i].len > 8192) {
251dba7997aSJean Delvare 			res = -EINVAL;
252dba7997aSJean Delvare 			break;
253dba7997aSJean Delvare 		}
254838bfa60SJean Delvare 
2557d5cb456SAl Viro 		data_ptrs[i] = (u8 __user *)msgs[i].buf;
2567d5cb456SAl Viro 		msgs[i].buf = memdup_user(data_ptrs[i], msgs[i].len);
2577d5cb456SAl Viro 		if (IS_ERR(msgs[i].buf)) {
2587d5cb456SAl Viro 			res = PTR_ERR(msgs[i].buf);
259dba7997aSJean Delvare 			break;
260dba7997aSJean Delvare 		}
261978336d4SWolfram Sang 		/* memdup_user allocates with GFP_KERNEL, so DMA is ok */
262978336d4SWolfram Sang 		msgs[i].flags |= I2C_M_DMA_SAFE;
263838bfa60SJean Delvare 
264838bfa60SJean Delvare 		/*
265838bfa60SJean Delvare 		 * If the message length is received from the slave (similar
266838bfa60SJean Delvare 		 * to SMBus block read), we must ensure that the buffer will
267838bfa60SJean Delvare 		 * be large enough to cope with a message length of
268838bfa60SJean Delvare 		 * I2C_SMBUS_BLOCK_MAX as this is the maximum underlying bus
269838bfa60SJean Delvare 		 * drivers allow. The first byte in the buffer must be
270838bfa60SJean Delvare 		 * pre-filled with the number of extra bytes, which must be
271838bfa60SJean Delvare 		 * at least one to hold the message length, but can be
272838bfa60SJean Delvare 		 * greater (for example to account for a checksum byte at
273838bfa60SJean Delvare 		 * the end of the message.)
274838bfa60SJean Delvare 		 */
2757d5cb456SAl Viro 		if (msgs[i].flags & I2C_M_RECV_LEN) {
2767d5cb456SAl Viro 			if (!(msgs[i].flags & I2C_M_RD) ||
27723a27722SAlexander Popov 			    msgs[i].len < 1 || msgs[i].buf[0] < 1 ||
2787d5cb456SAl Viro 			    msgs[i].len < msgs[i].buf[0] +
279838bfa60SJean Delvare 					     I2C_SMBUS_BLOCK_MAX) {
280a0692f0eSYingjoe Chen 				i++;
281838bfa60SJean Delvare 				res = -EINVAL;
282838bfa60SJean Delvare 				break;
283838bfa60SJean Delvare 			}
284838bfa60SJean Delvare 
2857d5cb456SAl Viro 			msgs[i].len = msgs[i].buf[0];
286838bfa60SJean Delvare 		}
287dba7997aSJean Delvare 	}
288dba7997aSJean Delvare 	if (res < 0) {
289dba7997aSJean Delvare 		int j;
290dba7997aSJean Delvare 		for (j = 0; j < i; ++j)
2917d5cb456SAl Viro 			kfree(msgs[j].buf);
292dba7997aSJean Delvare 		kfree(data_ptrs);
2937d5cb456SAl Viro 		kfree(msgs);
294dba7997aSJean Delvare 		return res;
295dba7997aSJean Delvare 	}
296dba7997aSJean Delvare 
2977d5cb456SAl Viro 	res = i2c_transfer(client->adapter, msgs, nmsgs);
298dba7997aSJean Delvare 	while (i-- > 0) {
2997d5cb456SAl Viro 		if (res >= 0 && (msgs[i].flags & I2C_M_RD)) {
3007d5cb456SAl Viro 			if (copy_to_user(data_ptrs[i], msgs[i].buf,
3017d5cb456SAl Viro 					 msgs[i].len))
302dba7997aSJean Delvare 				res = -EFAULT;
303dba7997aSJean Delvare 		}
3047d5cb456SAl Viro 		kfree(msgs[i].buf);
305dba7997aSJean Delvare 	}
306dba7997aSJean Delvare 	kfree(data_ptrs);
3077d5cb456SAl Viro 	kfree(msgs);
308dba7997aSJean Delvare 	return res;
309dba7997aSJean Delvare }
310dba7997aSJean Delvare 
i2cdev_ioctl_smbus(struct i2c_client * client,u8 read_write,u8 command,u32 size,union i2c_smbus_data __user * data)311dba7997aSJean Delvare static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
3127d5cb456SAl Viro 		u8 read_write, u8 command, u32 size,
3137d5cb456SAl Viro 		union i2c_smbus_data __user *data)
314dba7997aSJean Delvare {
31530f939feSVlad Tsyrklevich 	union i2c_smbus_data temp = {};
316dba7997aSJean Delvare 	int datasize, res;
317dba7997aSJean Delvare 
3187d5cb456SAl Viro 	if ((size != I2C_SMBUS_BYTE) &&
3197d5cb456SAl Viro 	    (size != I2C_SMBUS_QUICK) &&
3207d5cb456SAl Viro 	    (size != I2C_SMBUS_BYTE_DATA) &&
3217d5cb456SAl Viro 	    (size != I2C_SMBUS_WORD_DATA) &&
3227d5cb456SAl Viro 	    (size != I2C_SMBUS_PROC_CALL) &&
3237d5cb456SAl Viro 	    (size != I2C_SMBUS_BLOCK_DATA) &&
3247d5cb456SAl Viro 	    (size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
3257d5cb456SAl Viro 	    (size != I2C_SMBUS_I2C_BLOCK_DATA) &&
3267d5cb456SAl Viro 	    (size != I2C_SMBUS_BLOCK_PROC_CALL)) {
327dba7997aSJean Delvare 		dev_dbg(&client->adapter->dev,
328dba7997aSJean Delvare 			"size out of range (%x) in ioctl I2C_SMBUS.\n",
3297d5cb456SAl Viro 			size);
330dba7997aSJean Delvare 		return -EINVAL;
331dba7997aSJean Delvare 	}
332dba7997aSJean Delvare 	/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
333dba7997aSJean Delvare 	   so the check is valid if size==I2C_SMBUS_QUICK too. */
3347d5cb456SAl Viro 	if ((read_write != I2C_SMBUS_READ) &&
3357d5cb456SAl Viro 	    (read_write != I2C_SMBUS_WRITE)) {
336dba7997aSJean Delvare 		dev_dbg(&client->adapter->dev,
337dba7997aSJean Delvare 			"read_write out of range (%x) in ioctl I2C_SMBUS.\n",
3387d5cb456SAl Viro 			read_write);
339dba7997aSJean Delvare 		return -EINVAL;
340dba7997aSJean Delvare 	}
341dba7997aSJean Delvare 
342dba7997aSJean Delvare 	/* Note that command values are always valid! */
343dba7997aSJean Delvare 
3447d5cb456SAl Viro 	if ((size == I2C_SMBUS_QUICK) ||
3457d5cb456SAl Viro 	    ((size == I2C_SMBUS_BYTE) &&
3467d5cb456SAl Viro 	    (read_write == I2C_SMBUS_WRITE)))
347dba7997aSJean Delvare 		/* These are special: we do not use data */
348dba7997aSJean Delvare 		return i2c_smbus_xfer(client->adapter, client->addr,
3497d5cb456SAl Viro 				      client->flags, read_write,
3507d5cb456SAl Viro 				      command, size, NULL);
351dba7997aSJean Delvare 
3527d5cb456SAl Viro 	if (data == NULL) {
353dba7997aSJean Delvare 		dev_dbg(&client->adapter->dev,
354dba7997aSJean Delvare 			"data is NULL pointer in ioctl I2C_SMBUS.\n");
355dba7997aSJean Delvare 		return -EINVAL;
356dba7997aSJean Delvare 	}
357dba7997aSJean Delvare 
3587d5cb456SAl Viro 	if ((size == I2C_SMBUS_BYTE_DATA) ||
3597d5cb456SAl Viro 	    (size == I2C_SMBUS_BYTE))
3607d5cb456SAl Viro 		datasize = sizeof(data->byte);
3617d5cb456SAl Viro 	else if ((size == I2C_SMBUS_WORD_DATA) ||
3627d5cb456SAl Viro 		 (size == I2C_SMBUS_PROC_CALL))
3637d5cb456SAl Viro 		datasize = sizeof(data->word);
364dba7997aSJean Delvare 	else /* size == smbus block, i2c block, or block proc. call */
3657d5cb456SAl Viro 		datasize = sizeof(data->block);
366dba7997aSJean Delvare 
3677d5cb456SAl Viro 	if ((size == I2C_SMBUS_PROC_CALL) ||
3687d5cb456SAl Viro 	    (size == I2C_SMBUS_BLOCK_PROC_CALL) ||
3697d5cb456SAl Viro 	    (size == I2C_SMBUS_I2C_BLOCK_DATA) ||
3707d5cb456SAl Viro 	    (read_write == I2C_SMBUS_WRITE)) {
3717d5cb456SAl Viro 		if (copy_from_user(&temp, data, datasize))
372dba7997aSJean Delvare 			return -EFAULT;
373dba7997aSJean Delvare 	}
3747d5cb456SAl Viro 	if (size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
375dba7997aSJean Delvare 		/* Convert old I2C block commands to the new
376dba7997aSJean Delvare 		   convention. This preserves binary compatibility. */
3777d5cb456SAl Viro 		size = I2C_SMBUS_I2C_BLOCK_DATA;
3787d5cb456SAl Viro 		if (read_write == I2C_SMBUS_READ)
379dba7997aSJean Delvare 			temp.block[0] = I2C_SMBUS_BLOCK_MAX;
380dba7997aSJean Delvare 	}
381dba7997aSJean Delvare 	res = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
3827d5cb456SAl Viro 	      read_write, command, size, &temp);
3837d5cb456SAl Viro 	if (!res && ((size == I2C_SMBUS_PROC_CALL) ||
3847d5cb456SAl Viro 		     (size == I2C_SMBUS_BLOCK_PROC_CALL) ||
3857d5cb456SAl Viro 		     (read_write == I2C_SMBUS_READ))) {
3867d5cb456SAl Viro 		if (copy_to_user(data, &temp, datasize))
387dba7997aSJean Delvare 			return -EFAULT;
388dba7997aSJean Delvare 	}
389dba7997aSJean Delvare 	return res;
390dba7997aSJean Delvare }
391dba7997aSJean Delvare 
i2cdev_ioctl(struct file * file,unsigned int cmd,unsigned long arg)39277e38bffSAlan Cox static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3931da177e4SLinus Torvalds {
3940be16c30SH Hartley Sweeten 	struct i2c_client *client = file->private_data;
3951da177e4SLinus Torvalds 	unsigned long funcs;
3961da177e4SLinus Torvalds 
397e8aafcb2SJean Delvare 	dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
398e8aafcb2SJean Delvare 		cmd, arg);
3991da177e4SLinus Torvalds 
4001da177e4SLinus Torvalds 	switch (cmd) {
4011da177e4SLinus Torvalds 	case I2C_SLAVE:
4021da177e4SLinus Torvalds 	case I2C_SLAVE_FORCE:
4031da177e4SLinus Torvalds 		if ((arg > 0x3ff) ||
4041da177e4SLinus Torvalds 		    (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
4051da177e4SLinus Torvalds 			return -EINVAL;
406bd4217d8SJean Delvare 		if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))
4071da177e4SLinus Torvalds 			return -EBUSY;
408bd4217d8SJean Delvare 		/* REVISIT: address could become busy later */
4091da177e4SLinus Torvalds 		client->addr = arg;
4101da177e4SLinus Torvalds 		return 0;
4111da177e4SLinus Torvalds 	case I2C_TENBIT:
4121da177e4SLinus Torvalds 		if (arg)
4131da177e4SLinus Torvalds 			client->flags |= I2C_M_TEN;
4141da177e4SLinus Torvalds 		else
4151da177e4SLinus Torvalds 			client->flags &= ~I2C_M_TEN;
4161da177e4SLinus Torvalds 		return 0;
4171da177e4SLinus Torvalds 	case I2C_PEC:
4189e685c84SJean Delvare 		/*
4199e685c84SJean Delvare 		 * Setting the PEC flag here won't affect kernel drivers,
4209e685c84SJean Delvare 		 * which will be using the i2c_client node registered with
4219e685c84SJean Delvare 		 * the driver model core.  Likewise, when that client has
4229e685c84SJean Delvare 		 * the PEC flag already set, the i2c-dev driver won't see
4239e685c84SJean Delvare 		 * (or use) this setting.
4249e685c84SJean Delvare 		 */
4251da177e4SLinus Torvalds 		if (arg)
4261da177e4SLinus Torvalds 			client->flags |= I2C_CLIENT_PEC;
4271da177e4SLinus Torvalds 		else
4281da177e4SLinus Torvalds 			client->flags &= ~I2C_CLIENT_PEC;
4291da177e4SLinus Torvalds 		return 0;
4301da177e4SLinus Torvalds 	case I2C_FUNCS:
4311da177e4SLinus Torvalds 		funcs = i2c_get_functionality(client->adapter);
4322c003e8eSJean Delvare 		return put_user(funcs, (unsigned long __user *)arg);
4331da177e4SLinus Torvalds 
4347d5cb456SAl Viro 	case I2C_RDWR: {
4357d5cb456SAl Viro 		struct i2c_rdwr_ioctl_data rdwr_arg;
4367d5cb456SAl Viro 		struct i2c_msg *rdwr_pa;
4371da177e4SLinus Torvalds 
4387d5cb456SAl Viro 		if (copy_from_user(&rdwr_arg,
4397d5cb456SAl Viro 				   (struct i2c_rdwr_ioctl_data __user *)arg,
4407d5cb456SAl Viro 				   sizeof(rdwr_arg)))
4417d5cb456SAl Viro 			return -EFAULT;
4421da177e4SLinus Torvalds 
44371581562SWolfram Sang 		if (!rdwr_arg.msgs || rdwr_arg.nmsgs == 0)
44471581562SWolfram Sang 			return -EINVAL;
44571581562SWolfram Sang 
44671581562SWolfram Sang 		/*
44771581562SWolfram Sang 		 * Put an arbitrary limit on the number of messages that can
44871581562SWolfram Sang 		 * be sent at once
44971581562SWolfram Sang 		 */
4507d5cb456SAl Viro 		if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
4517d5cb456SAl Viro 			return -EINVAL;
4527d5cb456SAl Viro 
453*bef76b85SPhilipp Stanner 		rdwr_pa = memdup_array_user(rdwr_arg.msgs,
454*bef76b85SPhilipp Stanner 					    rdwr_arg.nmsgs, sizeof(struct i2c_msg));
4557d5cb456SAl Viro 		if (IS_ERR(rdwr_pa))
4567d5cb456SAl Viro 			return PTR_ERR(rdwr_pa);
4577d5cb456SAl Viro 
4587d5cb456SAl Viro 		return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
4597d5cb456SAl Viro 	}
4607d5cb456SAl Viro 
4617d5cb456SAl Viro 	case I2C_SMBUS: {
4627d5cb456SAl Viro 		struct i2c_smbus_ioctl_data data_arg;
4637d5cb456SAl Viro 		if (copy_from_user(&data_arg,
4647d5cb456SAl Viro 				   (struct i2c_smbus_ioctl_data __user *) arg,
4657d5cb456SAl Viro 				   sizeof(struct i2c_smbus_ioctl_data)))
4667d5cb456SAl Viro 			return -EFAULT;
4677d5cb456SAl Viro 		return i2cdev_ioctl_smbus(client, data_arg.read_write,
4687d5cb456SAl Viro 					  data_arg.command,
4697d5cb456SAl Viro 					  data_arg.size,
4707d5cb456SAl Viro 					  data_arg.data);
4717d5cb456SAl Viro 	}
47253be7959SDavid Brownell 	case I2C_RETRIES:
4736ebec961SYi Zeng 		if (arg > INT_MAX)
4746ebec961SYi Zeng 			return -EINVAL;
4756ebec961SYi Zeng 
47653be7959SDavid Brownell 		client->adapter->retries = arg;
47753be7959SDavid Brownell 		break;
47853be7959SDavid Brownell 	case I2C_TIMEOUT:
4796ebec961SYi Zeng 		if (arg > INT_MAX)
4806ebec961SYi Zeng 			return -EINVAL;
4816ebec961SYi Zeng 
482cd97f39bSJean Delvare 		/* For historical reasons, user-space sets the timeout
483cd97f39bSJean Delvare 		 * value in units of 10 ms.
484cd97f39bSJean Delvare 		 */
485cd97f39bSJean Delvare 		client->adapter->timeout = msecs_to_jiffies(arg * 10);
48653be7959SDavid Brownell 		break;
4871da177e4SLinus Torvalds 	default:
48853be7959SDavid Brownell 		/* NOTE:  returning a fault code here could cause trouble
48953be7959SDavid Brownell 		 * in buggy userspace code.  Some old kernel bugs returned
49053be7959SDavid Brownell 		 * zero in this case, and userspace code might accidentally
49153be7959SDavid Brownell 		 * have depended on that bug.
49253be7959SDavid Brownell 		 */
49353be7959SDavid Brownell 		return -ENOTTY;
4941da177e4SLinus Torvalds 	}
4951da177e4SLinus Torvalds 	return 0;
4961da177e4SLinus Torvalds }
4971da177e4SLinus Torvalds 
4987d5cb456SAl Viro #ifdef CONFIG_COMPAT
4997d5cb456SAl Viro 
5007d5cb456SAl Viro struct i2c_smbus_ioctl_data32 {
5017d5cb456SAl Viro 	u8 read_write;
5027d5cb456SAl Viro 	u8 command;
5037d5cb456SAl Viro 	u32 size;
5047d5cb456SAl Viro 	compat_caddr_t data; /* union i2c_smbus_data *data */
5057d5cb456SAl Viro };
5067d5cb456SAl Viro 
5077d5cb456SAl Viro struct i2c_msg32 {
5087d5cb456SAl Viro 	u16 addr;
5097d5cb456SAl Viro 	u16 flags;
5107d5cb456SAl Viro 	u16 len;
5117d5cb456SAl Viro 	compat_caddr_t buf;
5127d5cb456SAl Viro };
5137d5cb456SAl Viro 
5147d5cb456SAl Viro struct i2c_rdwr_ioctl_data32 {
5157d5cb456SAl Viro 	compat_caddr_t msgs; /* struct i2c_msg __user *msgs */
5167d5cb456SAl Viro 	u32 nmsgs;
5177d5cb456SAl Viro };
5187d5cb456SAl Viro 
compat_i2cdev_ioctl(struct file * file,unsigned int cmd,unsigned long arg)5197d5cb456SAl Viro static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
5207d5cb456SAl Viro {
5217d5cb456SAl Viro 	struct i2c_client *client = file->private_data;
5227d5cb456SAl Viro 	unsigned long funcs;
5237d5cb456SAl Viro 	switch (cmd) {
5247d5cb456SAl Viro 	case I2C_FUNCS:
5257d5cb456SAl Viro 		funcs = i2c_get_functionality(client->adapter);
5267d5cb456SAl Viro 		return put_user(funcs, (compat_ulong_t __user *)arg);
5277d5cb456SAl Viro 	case I2C_RDWR: {
5287d5cb456SAl Viro 		struct i2c_rdwr_ioctl_data32 rdwr_arg;
5293265a7e6SAndreas Hecht 		struct i2c_msg32 __user *p;
5307d5cb456SAl Viro 		struct i2c_msg *rdwr_pa;
5317d5cb456SAl Viro 		int i;
5327d5cb456SAl Viro 
5337d5cb456SAl Viro 		if (copy_from_user(&rdwr_arg,
5347d5cb456SAl Viro 				   (struct i2c_rdwr_ioctl_data32 __user *)arg,
5357d5cb456SAl Viro 				   sizeof(rdwr_arg)))
5367d5cb456SAl Viro 			return -EFAULT;
5377d5cb456SAl Viro 
538bb436283SPavel Skripkin 		if (!rdwr_arg.msgs || rdwr_arg.nmsgs == 0)
539bb436283SPavel Skripkin 			return -EINVAL;
540bb436283SPavel Skripkin 
5417d5cb456SAl Viro 		if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
5427d5cb456SAl Viro 			return -EINVAL;
5437d5cb456SAl Viro 
5447d5cb456SAl Viro 		rdwr_pa = kmalloc_array(rdwr_arg.nmsgs, sizeof(struct i2c_msg),
5457d5cb456SAl Viro 				      GFP_KERNEL);
5467d5cb456SAl Viro 		if (!rdwr_pa)
5477d5cb456SAl Viro 			return -ENOMEM;
5487d5cb456SAl Viro 
5497d5cb456SAl Viro 		p = compat_ptr(rdwr_arg.msgs);
5507d5cb456SAl Viro 		for (i = 0; i < rdwr_arg.nmsgs; i++) {
5517d5cb456SAl Viro 			struct i2c_msg32 umsg;
5527d5cb456SAl Viro 			if (copy_from_user(&umsg, p + i, sizeof(umsg))) {
5537d5cb456SAl Viro 				kfree(rdwr_pa);
5547d5cb456SAl Viro 				return -EFAULT;
5557d5cb456SAl Viro 			}
5567d5cb456SAl Viro 			rdwr_pa[i] = (struct i2c_msg) {
5577d5cb456SAl Viro 				.addr = umsg.addr,
5587d5cb456SAl Viro 				.flags = umsg.flags,
5597d5cb456SAl Viro 				.len = umsg.len,
560aef80e2fSAndy Shevchenko 				.buf = (__force __u8 *)compat_ptr(umsg.buf),
5617d5cb456SAl Viro 			};
5627d5cb456SAl Viro 		}
5637d5cb456SAl Viro 
5647d5cb456SAl Viro 		return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
5657d5cb456SAl Viro 	}
5667d5cb456SAl Viro 	case I2C_SMBUS: {
5677d5cb456SAl Viro 		struct i2c_smbus_ioctl_data32	data32;
5687d5cb456SAl Viro 		if (copy_from_user(&data32,
5697d5cb456SAl Viro 				   (void __user *) arg,
5707d5cb456SAl Viro 				   sizeof(data32)))
5717d5cb456SAl Viro 			return -EFAULT;
5727d5cb456SAl Viro 		return i2cdev_ioctl_smbus(client, data32.read_write,
5737d5cb456SAl Viro 					  data32.command,
5747d5cb456SAl Viro 					  data32.size,
5757d5cb456SAl Viro 					  compat_ptr(data32.data));
5767d5cb456SAl Viro 	}
5777d5cb456SAl Viro 	default:
5787d5cb456SAl Viro 		return i2cdev_ioctl(file, cmd, arg);
5797d5cb456SAl Viro 	}
5807d5cb456SAl Viro }
5817d5cb456SAl Viro #else
5827d5cb456SAl Viro #define compat_i2cdev_ioctl NULL
5837d5cb456SAl Viro #endif
5847d5cb456SAl Viro 
i2cdev_open(struct inode * inode,struct file * file)5851da177e4SLinus Torvalds static int i2cdev_open(struct inode *inode, struct file *file)
5861da177e4SLinus Torvalds {
5871da177e4SLinus Torvalds 	unsigned int minor = iminor(inode);
5881da177e4SLinus Torvalds 	struct i2c_client *client;
5891da177e4SLinus Torvalds 	struct i2c_adapter *adap;
5901da177e4SLinus Torvalds 
5915136ed4fSviresh kumar 	adap = i2c_get_adapter(minor);
5929669f541SVincent Sanders 	if (!adap)
5939669f541SVincent Sanders 		return -ENODEV;
5941da177e4SLinus Torvalds 
595907135aaSDavid Brownell 	/* This creates an anonymous i2c_client, which may later be
596907135aaSDavid Brownell 	 * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.
597907135aaSDavid Brownell 	 *
598907135aaSDavid Brownell 	 * This client is ** NEVER REGISTERED ** with the driver model
599907135aaSDavid Brownell 	 * or I2C core code!!  It just holds private copies of addressing
600907135aaSDavid Brownell 	 * information and maybe a PEC flag.
601907135aaSDavid Brownell 	 */
60222f76e74SJean Delvare 	client = kzalloc(sizeof(*client), GFP_KERNEL);
6031da177e4SLinus Torvalds 	if (!client) {
6041da177e4SLinus Torvalds 		i2c_put_adapter(adap);
6059669f541SVincent Sanders 		return -ENOMEM;
6061da177e4SLinus Torvalds 	}
60722f76e74SJean Delvare 	snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
6081da177e4SLinus Torvalds 
6091da177e4SLinus Torvalds 	client->adapter = adap;
6101da177e4SLinus Torvalds 	file->private_data = client;
6111da177e4SLinus Torvalds 
6129669f541SVincent Sanders 	return 0;
6131da177e4SLinus Torvalds }
6141da177e4SLinus Torvalds 
i2cdev_release(struct inode * inode,struct file * file)6151da177e4SLinus Torvalds static int i2cdev_release(struct inode *inode, struct file *file)
6161da177e4SLinus Torvalds {
6171da177e4SLinus Torvalds 	struct i2c_client *client = file->private_data;
6181da177e4SLinus Torvalds 
6191da177e4SLinus Torvalds 	i2c_put_adapter(client->adapter);
6201da177e4SLinus Torvalds 	kfree(client);
6211da177e4SLinus Torvalds 	file->private_data = NULL;
6221da177e4SLinus Torvalds 
6231da177e4SLinus Torvalds 	return 0;
6241da177e4SLinus Torvalds }
6251da177e4SLinus Torvalds 
6262b8693c0SArjan van de Ven static const struct file_operations i2cdev_fops = {
6271da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
6281da177e4SLinus Torvalds 	.llseek		= no_llseek,
6291da177e4SLinus Torvalds 	.read		= i2cdev_read,
6301da177e4SLinus Torvalds 	.write		= i2cdev_write,
63177e38bffSAlan Cox 	.unlocked_ioctl	= i2cdev_ioctl,
6327d5cb456SAl Viro 	.compat_ioctl	= compat_i2cdev_ioctl,
6331da177e4SLinus Torvalds 	.open		= i2cdev_open,
6341da177e4SLinus Torvalds 	.release	= i2cdev_release,
6351da177e4SLinus Torvalds };
6361da177e4SLinus Torvalds 
637907135aaSDavid Brownell /* ------------------------------------------------------------------------- */
638907135aaSDavid Brownell 
63979472132SGreg Kroah-Hartman static struct class *i2c_dev_class;
6401da177e4SLinus Torvalds 
i2cdev_dev_release(struct device * dev)6411413ef63SKevin Hao static void i2cdev_dev_release(struct device *dev)
6421413ef63SKevin Hao {
6431413ef63SKevin Hao 	struct i2c_dev *i2c_dev;
6441413ef63SKevin Hao 
6451413ef63SKevin Hao 	i2c_dev = container_of(dev, struct i2c_dev, dev);
6461413ef63SKevin Hao 	kfree(i2c_dev);
6471413ef63SKevin Hao }
6481413ef63SKevin Hao 
i2cdev_attach_adapter(struct device * dev)6499e5f81f9SGeert Uytterhoeven static int i2cdev_attach_adapter(struct device *dev)
6501da177e4SLinus Torvalds {
6519ea3e941SJean Delvare 	struct i2c_adapter *adap;
6521da177e4SLinus Torvalds 	struct i2c_dev *i2c_dev;
653defcb46eSJean Delvare 	int res;
6541da177e4SLinus Torvalds 
6559ea3e941SJean Delvare 	if (dev->type != &i2c_adapter_type)
656cddf70d0SBartosz Golaszewski 		return NOTIFY_DONE;
6579ea3e941SJean Delvare 	adap = to_i2c_adapter(dev);
6589ea3e941SJean Delvare 
6591da177e4SLinus Torvalds 	i2c_dev = get_free_i2c_dev(adap);
6601da177e4SLinus Torvalds 	if (IS_ERR(i2c_dev))
661cddf70d0SBartosz Golaszewski 		return NOTIFY_DONE;
6621da177e4SLinus Torvalds 
663d6760b14SErico Nunes 	cdev_init(&i2c_dev->cdev, &i2cdev_fops);
664d6760b14SErico Nunes 	i2c_dev->cdev.owner = THIS_MODULE;
665d6760b14SErico Nunes 
6661413ef63SKevin Hao 	device_initialize(&i2c_dev->dev);
6671413ef63SKevin Hao 	i2c_dev->dev.devt = MKDEV(I2C_MAJOR, adap->nr);
6681413ef63SKevin Hao 	i2c_dev->dev.class = i2c_dev_class;
6691413ef63SKevin Hao 	i2c_dev->dev.parent = &adap->dev;
6701413ef63SKevin Hao 	i2c_dev->dev.release = i2cdev_dev_release;
671993eb48fSAndy Shevchenko 
672993eb48fSAndy Shevchenko 	res = dev_set_name(&i2c_dev->dev, "i2c-%d", adap->nr);
673993eb48fSAndy Shevchenko 	if (res)
674993eb48fSAndy Shevchenko 		goto err_put_i2c_dev;
6751413ef63SKevin Hao 
6761413ef63SKevin Hao 	res = cdev_device_add(&i2c_dev->cdev, &i2c_dev->dev);
677993eb48fSAndy Shevchenko 	if (res)
678993eb48fSAndy Shevchenko 		goto err_put_i2c_dev;
679b32d20dcSJean Delvare 
680295e0e7bSAndy Shevchenko 	pr_debug("adapter [%s] registered as minor %d\n", adap->name, adap->nr);
681cddf70d0SBartosz Golaszewski 	return NOTIFY_OK;
682993eb48fSAndy Shevchenko 
683993eb48fSAndy Shevchenko err_put_i2c_dev:
684993eb48fSAndy Shevchenko 	put_i2c_dev(i2c_dev, false);
685cddf70d0SBartosz Golaszewski 	return NOTIFY_DONE;
6861da177e4SLinus Torvalds }
6871da177e4SLinus Torvalds 
i2cdev_detach_adapter(struct device * dev)6889e5f81f9SGeert Uytterhoeven static int i2cdev_detach_adapter(struct device *dev)
6891da177e4SLinus Torvalds {
6909ea3e941SJean Delvare 	struct i2c_adapter *adap;
6911da177e4SLinus Torvalds 	struct i2c_dev *i2c_dev;
6921da177e4SLinus Torvalds 
6939ea3e941SJean Delvare 	if (dev->type != &i2c_adapter_type)
694cddf70d0SBartosz Golaszewski 		return NOTIFY_DONE;
6959ea3e941SJean Delvare 	adap = to_i2c_adapter(dev);
6969ea3e941SJean Delvare 
6979455e4c9SJean Delvare 	i2c_dev = i2c_dev_get_by_minor(adap->nr);
698b32d20dcSJean Delvare 	if (!i2c_dev) /* attach_adapter must have failed */
699cddf70d0SBartosz Golaszewski 		return NOTIFY_DONE;
7001da177e4SLinus Torvalds 
7011413ef63SKevin Hao 	put_i2c_dev(i2c_dev, true);
7021da177e4SLinus Torvalds 
703295e0e7bSAndy Shevchenko 	pr_debug("adapter [%s] unregistered\n", adap->name);
704cddf70d0SBartosz Golaszewski 	return NOTIFY_OK;
7051da177e4SLinus Torvalds }
7061da177e4SLinus Torvalds 
i2cdev_notifier_call(struct notifier_block * nb,unsigned long action,void * data)707eff245c8SShubhrajyoti D static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
7089ea3e941SJean Delvare 			 void *data)
7099ea3e941SJean Delvare {
7109ea3e941SJean Delvare 	struct device *dev = data;
7119ea3e941SJean Delvare 
7129ea3e941SJean Delvare 	switch (action) {
7139ea3e941SJean Delvare 	case BUS_NOTIFY_ADD_DEVICE:
7149e5f81f9SGeert Uytterhoeven 		return i2cdev_attach_adapter(dev);
7159ea3e941SJean Delvare 	case BUS_NOTIFY_DEL_DEVICE:
7169e5f81f9SGeert Uytterhoeven 		return i2cdev_detach_adapter(dev);
7179ea3e941SJean Delvare 	}
7189ea3e941SJean Delvare 
719cddf70d0SBartosz Golaszewski 	return NOTIFY_DONE;
7209ea3e941SJean Delvare }
7219ea3e941SJean Delvare 
7229ea3e941SJean Delvare static struct notifier_block i2cdev_notifier = {
7239ea3e941SJean Delvare 	.notifier_call = i2cdev_notifier_call,
7241da177e4SLinus Torvalds };
7251da177e4SLinus Torvalds 
726907135aaSDavid Brownell /* ------------------------------------------------------------------------- */
727907135aaSDavid Brownell 
i2c_dev_attach_adapter(struct device * dev,void * dummy)7289e5f81f9SGeert Uytterhoeven static int __init i2c_dev_attach_adapter(struct device *dev, void *dummy)
7299e5f81f9SGeert Uytterhoeven {
7309e5f81f9SGeert Uytterhoeven 	i2cdev_attach_adapter(dev);
7319e5f81f9SGeert Uytterhoeven 	return 0;
7329e5f81f9SGeert Uytterhoeven }
7339e5f81f9SGeert Uytterhoeven 
i2c_dev_detach_adapter(struct device * dev,void * dummy)7349e5f81f9SGeert Uytterhoeven static int __exit i2c_dev_detach_adapter(struct device *dev, void *dummy)
7359e5f81f9SGeert Uytterhoeven {
7369e5f81f9SGeert Uytterhoeven 	i2cdev_detach_adapter(dev);
7379e5f81f9SGeert Uytterhoeven 	return 0;
7389e5f81f9SGeert Uytterhoeven }
7399e5f81f9SGeert Uytterhoeven 
740907135aaSDavid Brownell /*
741907135aaSDavid Brownell  * module load/unload record keeping
742907135aaSDavid Brownell  */
743907135aaSDavid Brownell 
i2c_dev_init(void)7441da177e4SLinus Torvalds static int __init i2c_dev_init(void)
7451da177e4SLinus Torvalds {
7461da177e4SLinus Torvalds 	int res;
7471da177e4SLinus Torvalds 
748295e0e7bSAndy Shevchenko 	pr_info("i2c /dev entries driver\n");
7491da177e4SLinus Torvalds 
750d6760b14SErico Nunes 	res = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, "i2c");
7511da177e4SLinus Torvalds 	if (res)
7521da177e4SLinus Torvalds 		goto out;
7531da177e4SLinus Torvalds 
7541aaba11dSGreg Kroah-Hartman 	i2c_dev_class = class_create("i2c-dev");
755e74783ecSSven Wegener 	if (IS_ERR(i2c_dev_class)) {
756e74783ecSSven Wegener 		res = PTR_ERR(i2c_dev_class);
7571da177e4SLinus Torvalds 		goto out_unreg_chrdev;
758e74783ecSSven Wegener 	}
75945f176aeSGuenter Roeck 	i2c_dev_class->dev_groups = i2c_groups;
7601da177e4SLinus Torvalds 
7619ea3e941SJean Delvare 	/* Keep track of adapters which will be added or removed later */
7629ea3e941SJean Delvare 	res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
7631da177e4SLinus Torvalds 	if (res)
7641da177e4SLinus Torvalds 		goto out_unreg_class;
7651da177e4SLinus Torvalds 
7669ea3e941SJean Delvare 	/* Bind to already existing adapters right away */
7679e5f81f9SGeert Uytterhoeven 	i2c_for_each_dev(NULL, i2c_dev_attach_adapter);
7689ea3e941SJean Delvare 
7691da177e4SLinus Torvalds 	return 0;
7701da177e4SLinus Torvalds 
7711da177e4SLinus Torvalds out_unreg_class:
77279472132SGreg Kroah-Hartman 	class_destroy(i2c_dev_class);
7731da177e4SLinus Torvalds out_unreg_chrdev:
774d6760b14SErico Nunes 	unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
7751da177e4SLinus Torvalds out:
776295e0e7bSAndy Shevchenko 	pr_err("Driver Initialisation failed\n");
7771da177e4SLinus Torvalds 	return res;
7781da177e4SLinus Torvalds }
7791da177e4SLinus Torvalds 
i2c_dev_exit(void)7801da177e4SLinus Torvalds static void __exit i2c_dev_exit(void)
7811da177e4SLinus Torvalds {
7829ea3e941SJean Delvare 	bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
7839e5f81f9SGeert Uytterhoeven 	i2c_for_each_dev(NULL, i2c_dev_detach_adapter);
78479472132SGreg Kroah-Hartman 	class_destroy(i2c_dev_class);
785d6760b14SErico Nunes 	unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
7861da177e4SLinus Torvalds }
7871da177e4SLinus Torvalds 
788f80531c8SJarkko Nikula MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
789f80531c8SJarkko Nikula MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
7901da177e4SLinus Torvalds MODULE_DESCRIPTION("I2C /dev entries driver");
7911da177e4SLinus Torvalds MODULE_LICENSE("GPL");
7921da177e4SLinus Torvalds 
7931da177e4SLinus Torvalds module_init(i2c_dev_init);
7941da177e4SLinus Torvalds module_exit(i2c_dev_exit);
795