[i2c] [patch 2.6.19-rc6 9/11] i2c driver "new style" binding

David Brownell david-b at pacbell.net
Mon Nov 27 23:40:10 CET 2006


> It doesn't.  I got v2.6.19-rc6 out of git, applied the above patch, and 
> applied the patchset, and it still fails on patch 9.  Where is 
> i2c_do_add_adapter() supposed to come from? 

I see what happened ... that's version 0 of this patch, not the current
version; it didn't even include the Signed-Off-By line.

That sometimes happens when keeping older versions around.  On the
other hand, it's better than what happens when you _don't_ have the
around, and have to recover ... ;)

This version should work properly ... it's the one I'm running right
now on an x86_64 and ARM (OMAP OSK).

- Dave

=======================	CUT HERE
Kick in standard driver model probe mechanisms, by adding "new style"
I2C enumeration that works without SMBUS_QUICK support from controllers,
and devices.

 - Provide a new call, i2c_register_adapter(), to register an adapter
   using a specific I2C bus number.  Since I2C devices are identified
   as pairs { bus number, device address }, this is needed to ensure
   that the right bus number is used.

 - Define "struct i2c_board_info", used to declare I2C devices along
   with previously missing information like what IRQ they issue, and
   a pointer to be stored in platform_data.  An I2C_BOARD_INFO() macro
   packages the mandatory information.

 - Provide a new call, i2c_register_board_info(), letting board-specific
   arch_initcall() level code declare the board info for I2C devices that
   are hooked up with staticallly defined I2C bus numbers (like those
   from most system-on-chip processors).

 - When an adapter is registered, consult that static registered board
   information and use it to create device nodes that can be bound to
   "new style" drivers using probe().

 - Provide a pair of calls, i2c_new_device() and i2c_unregister_device(),
   to support more dynamic declaration of that board info.  For example,
   a PCI card with an embedded adapter, with a config eeprom and a few
   other i2c devices, could use this to declare those i2c devices.

 - All that new stuff has kerneldoc.  (Too bad the rest of I2C doesn't!)

 - Move some init_completion() calls earlier, to where they belong.

With this patch, "new style" drivers and configuration are working, and
systems that don't support SMBUS_QUICK can work.  Plus, two longstanding
omissions in the I2C stack are resolved:  drivers no longer need to add
board-specific code to handle either (a) irqs issued by i2c chips, or
(b) board-specific configuration, such as which chip variant is used.

Signed-off-by: David Brownell <dbrownell at users.sourceforge.net>

---
Includes some bugfixes (those IDR calls are strange!) and, per Greg's
suggestion, a macro for board init.

 drivers/i2c/i2c-core.c |  388 ++++++++++++++++++++++++++++++++++++-------------
 include/linux/i2c.h    |   61 +++++++
 2 files changed, 353 insertions(+), 96 deletions(-)

Index: g26/include/linux/i2c.h
===================================================================
--- g26.orig/include/linux/i2c.h	2006-11-25 14:12:33.000000000 -0800
+++ g26/include/linux/i2c.h	2006-11-25 14:12:33.000000000 -0800
@@ -163,6 +163,7 @@ struct i2c_client {
 	int usage_count;		/* How many accesses currently  */
 					/* to the client		*/
 	struct device dev;		/* the device structure		*/
+	int irq;			/* irq issued by device (or -1) */
 	struct list_head list;
 	char name[I2C_NAME_SIZE];
 	struct completion released;
@@ -184,6 +185,65 @@ static inline void i2c_set_clientdata (s
 	dev_set_drvdata (&dev->dev, data);
 }
 
+/**
+ * struct i2c_board_info - template for device creation
+ * @driver: identifies the driver to be bound to the device
+ * @dev_addr: stored in i2c_client.addr
+ * @bus_num: usually matches i2c_client.adapter->nr
+ * @platform_data: stored in i2c_client.dev.platform_data
+ * @irq: stored in i2c_client.irq
+
+ * I2C doesn't actually support hardware probing, although controllers and
+ * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
+ * a device at a given address.  Drivers commonly need more information than
+ * that, such as chip configuration, associated IRQ, and more.
+ *
+ * i2c_board_info is used to build tables of information listing I2C devices
+ * that are present.  This information is used to grow the driver model tree
+ * for "new style" I2C drivers.  For mainboards this is done statically using
+ * i2c_register_board_info(), where @bus_num represents an adapter that isn't
+ * yet available.  For add-on boards, i2c_new_device() does this dynamically
+ * with the adapter already known.
+ */
+struct i2c_board_info {
+	char		driver[KOBJ_NAME_LEN];
+	short		bus_num;
+	unsigned short	dev_addr;
+	void		*platform_data;
+	int		irq;
+};
+
+/**
+ * I2C_BOARD_INFO - macro used to list an i2c device and its driver
+ * @driver_name: identifies the driver to use with the device
+ * @busnum: numbers the bus to which the device is connected; ignored
+ *	when i2c_new_device() explicitly idenfies that bus.
+ * @devaddr: the device's address on the bus.
+ *
+ * This macro initializes mandatory fields of a struct i2c_board_info,
+ * declaring what has been provided on a particular board.  Optional
+ * fields (such as the associated irq, or device-specific platform_data)
+ * are provided using conventional syntax.
+ */
+#define I2C_BOARD_INFO(driver_name,busnum,devaddr) \
+	.driver = driver_name, .bus_num = busnum, .dev_addr = devaddr
+
+
+/* Add-on boards should register/unregister their devices; e.g. a board
+ * with integrated I2C, a config eeprom, sensors, and a codec that's
+ * used in conjunction with the primary hardware.
+ */
+extern struct i2c_client *
+i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
+
+extern void i2c_unregister_device(struct i2c_client *);
+
+/* Mainboard arch_initcall() code should register all its I2C devices.
+ * This is done at arch_initcall time; add-on boards do use other calls.
+ */
+extern int
+i2c_register_board_info(struct i2c_board_info const *info, unsigned n);
+
 /*
  * The following structs are for those who like to implement new bus drivers:
  * i2c_algorithm is the interface to a class of hardware solutions which can
@@ -295,6 +355,7 @@ struct i2c_client_address_data {
  */
 extern int i2c_add_adapter(struct i2c_adapter *);
 extern int i2c_del_adapter(struct i2c_adapter *);
+extern int i2c_register_adapter(struct i2c_adapter *);
 
 extern int i2c_register_driver(struct module *, struct i2c_driver *);
 extern int i2c_del_driver(struct i2c_driver *);
Index: g26/drivers/i2c/i2c-core.c
===================================================================
--- g26.orig/drivers/i2c/i2c-core.c	2006-11-25 14:12:33.000000000 -0800
+++ g26/drivers/i2c/i2c-core.c	2006-11-25 14:47:26.000000000 -0800
@@ -155,35 +155,6 @@ struct bus_type i2c_bus_type = {
 
 /* ------------------------------------------------------------------------- */
 
-/* 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 show_adapter_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 adapter_attrs[] = {
-	__ATTR(name, S_IRUGO, show_adapter_name, NULL),
-	{ },
-};
-
-struct class i2c_adapter_class = {
-	.name =			"i2c-adapter",
-	.owner =		THIS_MODULE,
-	.class_dev_attrs =	adapter_attrs,
-	.release =		&i2c_adapter_class_dev_release,
-};
-
-/* ------------------------------------------------------------------------- */
-
-
 static void i2c_client_release(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -196,15 +167,7 @@ static ssize_t show_client_name(struct d
 	return sprintf(buf, "%s\n", client->name);
 }
 
-/*
- * We can't use the DEVICE_ATTR() macro here as we want the same filename for a
- * different type of a device.  So beware if the DEVICE_ATTR() macro ever
- * changes, this definition will also have to change.
- */
-static struct device_attribute dev_attr_client_name = {
-	.attr	= {.name = "name", .mode = S_IRUGO, .owner = THIS_MODULE },
-	.show	= &show_client_name,
-};
+DEVICE_ATTR(name, S_IRUGO, show_client_name, NULL);
 
 /* modalias helps with coldplug:  modprobe $(cat /sys/devices/.../modalias)
  * it's a convention across all Linux devices.
@@ -212,7 +175,7 @@ static struct device_attribute dev_attr_
 DEVICE_ATTR(modalias, S_IRUGO, show_client_name, NULL);
 
 static /*const*/ struct attribute *i2c_dev_attrs[] = {
-	&dev_attr_client_name.attr,
+	&dev_attr_name.attr,
 	&dev_attr_modalias.attr,
 	NULL,
 };
@@ -222,7 +185,53 @@ static const struct attribute_group i2c_
 };
 
 
-static void i2c_unregister_device(struct i2c_client *client)
+/**
+ * i2c_new_device - instantiate an i2c device for use with new style driver
+ * @adap: the adapter managing the device
+ * @info: describes one I2C device
+ *
+ * Create a device to work with a new style i2c driver, where binding is
+ * handled by driver model probe()/remove() methods.
+ *
+ * This returns the new i2c client, which may be saved for later use with
+ * i2c_unregister_device(), or NULL to indicate an error.
+ */
+struct i2c_client *
+i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
+{
+	struct i2c_client	*client;
+	int			status;
+
+	client = kzalloc(sizeof *client, SLAB_KERNEL);
+	if (!client)
+		return NULL;
+
+	client->adapter = adap;
+
+	strlcpy(client->name, info->driver, sizeof client->name);
+	client->dev.platform_data = info->platform_data;
+	client->addr = info->dev_addr;
+	client->irq = info->irq;
+
+	/* a new style driver may be bound to this device when we
+	 * return from this function, or any later moment (e.g. maybe
+	 * it hotplugged).
+	 */
+	status = i2c_attach_client(client);
+	if (status < 0) {
+		kfree(client);
+		client = NULL;
+	}
+	return client;
+}
+EXPORT_SYMBOL_GPL(i2c_new_device);
+
+
+/**
+ * i2c_unregister_device - reverse effect of i2c_new_device()
+ * @client: value returned from i2c_new_device()
+ */
+void i2c_unregister_device(struct i2c_client *client)
 {
 	struct i2c_adapter	*adap = client->adapter;
 	struct i2c_driver	*driver = client->driver;
@@ -247,75 +256,148 @@ static void i2c_unregister_device(struct
 	/* now remove the device, and free its memory */
 	status = i2c_detach_client(client);
 	if (status < 0)
-		dev_err(&adap->dev, "detach failed (%d) for client [%s] "
+		dev_err(adap->class_dev.dev,
+			"detach failed (%d) for client [%s] "
 			"at address 0x%02x\n",
 			status, client->name, client->addr);
 	else
 		put_device(&client->dev);
 
 }
+EXPORT_SYMBOL_GPL(i2c_unregister_device);
 
+static int first_dynamic_bus_num = 0;
 
-/* ------------------------------------------------------------------------- */
 
-/*
- * i2c_add_adapter is called from within the algorithm layer,
- * when a new hw adapter registers. A new device is register to be
- * available for clients.
+#ifdef	CONFIG_I2C	/* modules can't register static board_info */
+
+struct boardinfo {
+	struct list_head	list;
+	unsigned		n_board_info;
+	struct i2c_board_info	board_info[0];
+};
+
+static LIST_HEAD(board_list);
+static DECLARE_MUTEX(board_lock);
+
+
+/**
+ * i2c_register_board_info - statically declare I2C devices
+ * @info: vector of i2c device descriptors
+ * @len: how many descriptors in the vector
+ *
+ * Systems with the I2C core statically configured can declare tables of board
+ * info as they initialize.  This should be done in board-specific init code
+ * near arch_initcall() time, or equivalent, before any I2C adapter drivers are
+ * registered.  For example, mainboard init code could define several devices,
+ * as could the init code for each daughterboard in a board stack.
+ *
+ * The I2C devices will be created later, after the adapter for the relevant bus
+ * has been registered.  After that moment, standard driver model tools are used
+ * to bind "new style" I2C drivers to the devices.
+ *
+ * The board info passed can safely be __initdata, but be careful of embedded
+ * pointers (for platform_data, functions, etc) since that won't be copied.
  */
+int __init
+i2c_register_board_info(struct i2c_board_info const *info, unsigned len)
+{
+	struct boardinfo	*bi;
+	int			i;
 
-int i2c_add_adapter(struct i2c_adapter *adap)
+	bi = kmalloc(sizeof(*bi) + len * sizeof *info, GFP_KERNEL);
+	if (!bi)
+		return -ENOMEM;
+	bi->n_board_info = len;
+	memcpy(bi->board_info, info, len * sizeof *info);
+
+	/* assign dynamic bus numbers after the last static one */
+	for (i = 0; i < len; i++, info++) {
+		if (info->bus_num >= first_dynamic_bus_num)
+			first_dynamic_bus_num = info->bus_num + 1;
+	}
+
+	down(&board_lock);
+	list_add_tail(&bi->list, &board_list);
+	up(&board_lock);
+	return 0;
+}
+
+static void scan_static_board_info(struct i2c_adapter *adap)
 {
-	struct device *dev = adap->class_dev.dev;
-	int id, res = 0;
-	struct list_head   *item;
-	struct i2c_driver  *driver;
+	struct boardinfo	*bi;
 
-	mutex_lock(&core_lists);
+	down(&board_lock);
+	list_for_each_entry(bi, &board_list, list) {
+		struct i2c_board_info	*chip = bi->board_info;
+		unsigned		n;
 
-	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) {
-		res = -ENOMEM;
-		goto out_unlock;
+		for (n = bi->n_board_info; n > 0; n--, chip++) {
+			if (chip->bus_num != adap->nr)
+				continue;
+			(void) i2c_new_device(adap, chip);
+		}
 	}
+	up(&board_lock);
+}
+
+#else	/* i2c core is modular */
+static inline void scan_static_board_info(struct i2c_adapter *adap) {}
+#endif
+
+
+/* ------------------------------------------------------------------------- */
+
+/* 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 show_adapter_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 adapter_attrs[] = {
+	__ATTR(name, S_IRUGO, show_adapter_name, NULL),
+	{ },
+};
+
+struct class i2c_adapter_class = {
+	.name =			"i2c-adapter",
+	.owner =		THIS_MODULE,
+	.class_dev_attrs =	adapter_attrs,
+	.release =		&i2c_adapter_class_dev_release,
+};
 
-	res = idr_get_new(&i2c_adapter_idr, adap, &id);
-	if (res < 0) {
-		if (res == -EAGAIN)
-			res = -ENOMEM;
-		goto out_unlock;
-	}
 
-	adap->nr =  id & MAX_ID_MASK;
+static int __i2c_register_adapter(struct i2c_adapter *adap)
+{
+	struct device		*dev = adap->class_dev.dev;
+	int			res = 0;
+	struct list_head	*item;
+	struct i2c_driver	*driver;
+
+	if (!dev)
+		return -ENODEV;
+
+	init_completion(&adap->dev_released);
+	init_completion(&adap->class_dev_released);
 	mutex_init(&adap->bus_lock);
 	mutex_init(&adap->clist_lock);
-	list_add_tail(&adap->list,&adapters);
 	INIT_LIST_HEAD(&adap->clients);
 
-	/* Caller must have zero-initialized adap->class_dev, then
-	 * initialized adap->class_dev.dev as the real device so we
-	 * can properly add this adapter to the i2c_adapter class.
-	 *
-	 * As a **TEMPORARY migration aid** we create a platform
-	 * device for drivers that don't yet use the driver model.
-	 * Expect this to vanish by January 2008.
-	 */
-	if (!dev) {
-		printk(KERN_WARNING "I2C bus '%s' has no device; "
-			"convert it to the driver model\n",
-			adap->name);
-		adap->legacy_hack = platform_device_register_simple(
-			"legacy_i2c_adapter", adap->nr, NULL, 0);
-		if (adap->legacy_hack) {
-			dev = &adap->legacy_hack->dev;
-			adap->class_dev.dev = dev;
-		} else {
-			res = -ENODEV;
-			goto out_unlock;
-		}
-	}
-
 	sprintf(adap->class_dev.class_id, "i2c-%d", adap->nr);
 	adap->class_dev.class = &i2c_adapter_class;
+
+	mutex_lock(&core_lists);
+
+	list_add_tail(&adap->list,&adapters);
+
 	res = class_device_register(&adap->class_dev);
 	if (res)
 		goto out_list;
@@ -323,7 +405,11 @@ int i2c_add_adapter(struct i2c_adapter *
 	dev_dbg(dev, "adapter %s [%s] registered\n",
 			adap->class_dev.class_id, adap->name);
 
-	/* inform drivers of new adapters */
+	/* create devices for new style drivers */
+	if (adap->nr < first_dynamic_bus_num)
+		scan_static_board_info(adap);
+
+	/* let legacy drivers scan this bus for devices */
 	list_for_each(item,&drivers) {
 		driver = list_entry(item, struct i2c_driver, list);
 		if (driver->attach_adapter)
@@ -343,6 +429,114 @@ out_list:
 }
 
 
+/**
+ * i2c_add_adapter - declare i2c adapter, use dynamic bus number
+ * @adap: the adapter to add (with adap->class_dev.dev initialized)
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * doesn't matter.  Examples: for I2C adapters dynamically added by
+ * USB links or PCI plugin cards.
+ *
+ * Note that there is temporary support for legacy "non driver model"
+ * adapters, without a device initialized for the class device.  This
+ * will be removed in the future.
+ *
+ * When this returns zero, a new bus number was allocated and stored
+ * in adap->nr, and the specified adapter became available for clients.
+ * Otherwise, a negative errno value is returned.
+ */
+int i2c_add_adapter(struct i2c_adapter *adap)
+{
+	int	id, res = 0;
+
+retry:
+	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+		return -ENOMEM;
+
+	mutex_lock(&core_lists);
+	/* "above" here means "above or equal to", sigh */
+	res = idr_get_new_above(&i2c_adapter_idr, adap,
+				first_dynamic_bus_num, &id);
+	adap->nr = id;
+	mutex_unlock(&core_lists);
+	if (res < 0) {
+		if (res == -EAGAIN)
+			goto retry;
+		return res;
+	}
+
+	/* As a **TEMPORARY migration aid** we create a platform
+	 * device for drivers that don't yet use the driver model.
+	 * Expect this to vanish by sometime in 2008.
+	 */
+	if (!adap->class_dev.dev) {
+		printk(KERN_WARNING "I2C bus '%s' has no device; "
+			"convert it to the driver model\n",
+			adap->name);
+		adap->legacy_hack = platform_device_register_simple(
+			"legacy_i2c_adapter", adap->nr, NULL, 0);
+		if (adap->legacy_hack)
+			adap->class_dev.dev = &adap->legacy_hack->dev;
+		else {
+			mutex_lock(&core_lists);
+			idr_remove(&i2c_adapter_idr, adap->nr);
+			mutex_unlock(&core_lists);
+			return -ENODEV;
+		}
+	}
+
+	if (res == 0)
+		res = __i2c_register_adapter(adap);
+	return res;
+}
+EXPORT_SYMBOL_GPL(i2c_add_adapter);
+
+/**
+ * i2c_register_adapter - declare i2c adapter, use static bus number
+ * @adap: the adapter to register (with adap->nr and adap->class_dev.dev
+ *	initialized)
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * matters.  Example: for I2C adapters from system-on-chip CPUs, or
+ * otherwise built in to the system's mainboard, and where i2c_board_info
+ * is used to properly configure I2C devices..
+ *
+ * When this returns zero, the specified adapter became available for
+ * clients using the bus number provided in adap->nr.  Otherwise, a
+ * negative errno value is returned.
+ */
+int i2c_register_adapter(struct i2c_adapter *adap)
+{
+	int	id;
+	int	status;
+
+	if (adap->nr & ~MAX_ID_MASK)
+		return -EINVAL;
+
+retry:
+	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+		return -ENOMEM;
+
+	mutex_lock(&core_lists);
+	/* "above" here means "above or equal to", sigh;
+	 * we need the "equal to" result to force the result
+	 */
+	status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
+	if (status == 0 && id != adap->nr) {
+		status = -EBUSY;
+		idr_remove(&i2c_adapter_idr, id);
+	}
+	mutex_unlock(&core_lists);
+	if (status == -EAGAIN)
+		goto retry;
+
+	if (status == 0)
+		status = __i2c_register_adapter(adap);
+	return status;
+}
+EXPORT_SYMBOL_GPL(i2c_register_adapter);
+
+
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
 	struct device *dev = adap->class_dev.dev;
@@ -399,8 +593,6 @@ int i2c_del_adapter(struct i2c_adapter *
 	}
 
 	/* clean up the sysfs representation */
-	init_completion(&adap->dev_released);
-	init_completion(&adap->class_dev_released);
 	class_device_unregister(&adap->class_dev);
 	list_del(&adap->list);
 
@@ -408,7 +600,7 @@ int i2c_del_adapter(struct i2c_adapter *
 	wait_for_completion(&adap->dev_released);
 	wait_for_completion(&adap->class_dev_released);
 
-	/* free dynamically allocated bus id */
+	/* free bus id */
 	idr_remove(&i2c_adapter_idr, adap->nr);
 
 	dev_dbg(dev, "adapter %s [%s] unregistered\n",
@@ -418,6 +610,7 @@ int i2c_del_adapter(struct i2c_adapter *
 	mutex_unlock(&core_lists);
 	return res;
 }
+EXPORT_SYMBOL(i2c_del_adapter);
 
 
 /* ------------------------------------------------------------------------- */
@@ -441,7 +634,10 @@ int i2c_register_driver(struct module *o
 		}
 	}
 
-	/* add the driver to the list of i2c drivers in the driver core */
+	/* add the driver to the list of i2c drivers in the driver core;
+	 * new style drivers will be probed existing but unbound devices
+	 * when this returns.
+	 */
 	driver->driver.owner = owner;
 	driver->driver.bus = &i2c_bus_type;
 
@@ -567,10 +763,13 @@ int i2c_attach_client(struct i2c_client 
 	client->usage_count = 0;
 
 	client->dev.parent = adapter->class_dev.dev;
-	client->dev.driver = &client->driver->driver;
+	if (client->driver)
+		client->dev.driver = &client->driver->driver;
 	client->dev.bus = &i2c_bus_type;
 	client->dev.release = &i2c_client_release;
 
+	init_completion(&client->released);
+
 	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
 		"%d-%04x", i2c_adapter_id(adapter), client->addr);
 	res = device_register(&client->dev);
@@ -594,7 +793,6 @@ int i2c_attach_client(struct i2c_client 
 	return 0;
 
 out_unregister:
-	init_completion(&client->released); /* Needed? */
 	device_unregister(&client->dev);
 	wait_for_completion(&client->released);
 out_list:
@@ -630,7 +828,6 @@ int i2c_detach_client(struct i2c_client 
 
 	mutex_lock(&adapter->clist_lock);
 	list_del(&client->list);
-	init_completion(&client->released);
 	sysfs_remove_group(&client->dev.kobj, &i2c_dev_attr_group);
 	device_unregister(&client->dev);
 	mutex_unlock(&adapter->clist_lock);
@@ -737,6 +934,7 @@ int i2c_transfer(struct i2c_adapter * ad
 
 	if (adap->algo->master_xfer) {
 #ifdef DEBUG
+if(0)
 		for (ret = 0; ret < num; ret++) {
 			dev_dbg(dev, "master_xfer[%d] %c, addr=0x%02x, "
 				"len=%d\n", ret, msgs[ret].flags & I2C_M_RD ?
@@ -1313,8 +1511,6 @@ s32 i2c_smbus_xfer(struct i2c_adapter * 
 EXPORT_SYMBOL_GPL(i2c_adapter_class);
 EXPORT_SYMBOL_GPL(i2c_bus_type);
 
-EXPORT_SYMBOL(i2c_add_adapter);
-EXPORT_SYMBOL(i2c_del_adapter);
 EXPORT_SYMBOL(i2c_del_driver);
 EXPORT_SYMBOL(i2c_attach_client);
 EXPORT_SYMBOL(i2c_detach_client);





More information about the i2c mailing list