[i2c] [patch/rfc 2.6.19-rc6 1/3] I2C "new style" driver model type binding

Jean Delvare khali at linux-fr.org
Fri Nov 17 16:37:30 CET 2006


Hi David,

Thanks for working on this, this is very much appreciated.

On Thu, 16 Nov 2006 11:24:35 -0800, David Brownell wrote:
> I2C infrastructure updates to support enumeration according to the standard
> driver model.  Nothing yet _uses_ it to create I2C devices.
> 
> Terminology being adopted:  "legacy" drivers create devices (i2c_client)
> themselves, while "new style" ones follow the driver model (the i2c_client
> is handed to the probe routine).  It's an either/or thing; the two models
> don't mix, and drivers that try won't even be registered.
> 
>  - Update i2c_device_match() to handle new style driver binding by comparing
>    client and driver names (like platform and SPI busses).

This won't work in the general case, as i2c chip drivers can support up
to 8 different chip types. So we need to either list all supported
types in the driver and lookup that list in i2c_device_match(), or
instanciate the i2c chips by {driver name, type number} pair rather
than chip name. The former sounds more flexible. And isn't exactly what
device_id tables are meant for?

>  - Add bus uevent() method, for hotplug support.
> 
>  - Add device modalias attribute, for coldplug support; switch over to use
>    attribute groups ("name" and "modalias", contents are the same).

Why duplicate it if it's the same?

> 
>  - Add driver probe() method.  Update i2c_device_probe() to use it with
>    new style drivers.
>    
>  - Add driver remove() method.  Update i2c_device_remove() to use it with
>    new style drivers.  Call that from i2c_del_adapter() as needed.  Also
>    update i2c_del_adapter() to handle the new case of cleaning up I2C
>    devices without (new style) drivers.
> 
>  - Rename i2c_bus_{suspend,resume}() to reflect their per-device nature.
> 
>  - Update Documentation/i2c accordingly

Note that once again, these are quite a few changes for a single patch.
I'd appreciate smaller patches, they are easier to review and test.

> 
> The hotplug/coldplug support will be the only externally visible change.
> That will be an overall NOP since the I2C stack currently doesn't create
> clients/devices except as part of binding them to legacy drivers, where
> the driver must already be loaded.
> 
> NOTE:  earlier proposals adding probe() methods used a different signature,
> since they didn't address the huge gap between the "legacy" I2C model (where
> drivers create device nodes) and the driver model (they don't).

This is the reason why these proposals were dismissed. I like your
approach better.

> 
> -----
>  Documentation/i2c/smbus-protocol  |    9 +-
>  Documentation/i2c/summary         |   30 +++++---
>  Documentation/i2c/writing-clients |   68 ++++++++++++++----
>  drivers/i2c/i2c-core.c            |  142 +++++++++++++++++++++++++++++++-------
>  include/linux/i2c.h               |   11 ++
>  5 files changed, 207 insertions(+), 53 deletions(-)
> 
> Index: o26/include/linux/i2c.h
> ===================================================================
> --- o26.orig/include/linux/i2c.h	2006-11-16 09:44:40.000000000 -0800
> +++ o26/include/linux/i2c.h	2006-11-16 11:04:35.000000000 -0800
> @@ -114,7 +114,7 @@ struct i2c_driver {
>  	 * can be used by the driver to test if the bus meets its conditions
>  	 * & seek for the presence of the chip(s) it supports. If found, it
>  	 * registers the client(s) that are on the bus to the i2c admin. via
> -	 * i2c_attach_client.
> +	 * i2c_attach_client.  (LEGACY I2C DRIVERS ONLY)
>  	 */
>  	int (*attach_adapter)(struct i2c_adapter *);
>  	int (*detach_adapter)(struct i2c_adapter *);
> @@ -122,10 +122,17 @@ struct i2c_driver {
>  	/* tells the driver that a client is about to be deleted & gives it
>  	 * the chance to remove its private data. Also, if the client struct
>  	 * has been dynamically allocated by the driver in the function above,
> -	 * it must be freed here.
> +	 * it must be freed here.  (LEGACY I2C DRIVERS ONLY)
>  	 */
>  	int (*detach_client)(struct i2c_client *);
>  
> +	/* Standard driver model interfaces, for "new style" i2c drivers.
> +	 * With the driver model, device enumeration is NEVER done by drivers;
> +	 * it's done by infrastructure.  (NEW STYLE DRIVERS ONLY)
> +	 */
> +	int (*probe)(struct i2c_client *);
> +	int (*remove)(struct i2c_client *);
> +
>  	/* driver model interfaces that don't relate to enumeration  */
>  	void (*shutdown)(struct i2c_client *);
>  	int (*suspend)(struct i2c_client *, pm_message_t mesg);
> Index: o26/drivers/i2c/i2c-core.c
> ===================================================================
> --- o26.orig/drivers/i2c/i2c-core.c	2006-11-16 09:44:40.000000000 -0800
> +++ o26/drivers/i2c/i2c-core.c	2006-11-16 11:04:35.000000000 -0800
> @@ -44,13 +44,46 @@ static DEFINE_IDR(i2c_adapter_idr);
>  
>  static int i2c_device_match(struct device *dev, struct device_driver *drv)
>  {
> -	/* (for now) bypass driver model probing entirely; drivers
> -	 * scan each i2c adapter/bus themselves.
> +	struct i2c_client	*client = to_i2c_client(dev);
> +	struct i2c_driver	*driver = to_i2c_driver(drv);

BTW, did I mention how much I dislike this coding style?

> +
> +	/* legacy i2c drivers bypass driver model probing entirely;
> +	 * drivers scan each i2c adapter/bus themselves.
> +	 */
> +	if (!driver->probe)
> +		return 0;
> +
> +	/* new style drivers use the same driver matching policy as
> +	 * platform devices or SPI:  compare device and driver names.
>  	 */
> +	return strcmp(client->name, drv->name) == 0;
> +}
> +
> +#ifdef	CONFIG_HOTPLUG
> +
> +/* uevent helps with hotplug: modprobe $(MODALIAS) */
> +static int i2c_device_uevent(struct device *dev, char **envp, int num_envp,
> +		      char *buffer, int buffer_size)
> +{
> +	struct i2c_client	*client = to_i2c_client(dev);
> +	int			i = 0, length = 0;
> +
> +	if (!dev)
> +		return -ENODEV;
> +
> +	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
> +			"MODALIAS=%s", client->name))
> +		return -ENOMEM;
> +	envp[i] = NULL;
>  	return 0;
>  }

I'm not familiar with uevent, can you please explain what this function
is for and when it will be called?

> -static int i2c_bus_suspend(struct device * dev, pm_message_t mesg)
> +#else
> +#define i2c_device_uevent	NULL
> +#endif	/* CONFIG_HOTPLUG */
> +
> +
> +static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
>  {
>  	struct i2c_driver	*driver = to_i2c_driver(dev->driver);
>  
> @@ -59,7 +92,7 @@ static int i2c_bus_suspend(struct device
>  	return driver->suspend(to_i2c_client(dev), mesg);
>  }
>  
> -static int i2c_bus_resume(struct device * dev)
> +static int i2c_device_resume(struct device * dev)
>  {
>  	struct i2c_driver	*driver = to_i2c_driver(dev->driver);
>  
> @@ -70,12 +103,23 @@ static int i2c_bus_resume(struct device 
>  
>  static int i2c_device_probe(struct device *dev)
>  {
> -	return -ENODEV;
> +	struct i2c_driver	*driver = to_i2c_driver(dev->driver);
> +
> +	if (!dev->driver || !driver->probe)
> +		return -ENODEV;
> +	return driver->probe(to_i2c_client(dev));
>  }
>  
>  static int i2c_device_remove(struct device *dev)
>  {
> -	return 0;
> +	struct i2c_driver	*driver = to_i2c_driver(dev->driver);
> +	int			status;
> +
> +	if (!dev->driver || !driver->resume)

I assume that's a typo and you really meant ->remove?

> +		return 0;
> +	status = driver->remove(to_i2c_client(dev));
> +	dev->driver = NULL;
> +	return status;
>  }
>  
>  static void i2c_device_shutdown(struct device *dev)
> @@ -90,11 +134,12 @@ static void i2c_device_shutdown(struct d
>  struct bus_type i2c_bus_type = {
>  	.name =		"i2c",
>  	.match =	i2c_device_match,
> +	.uevent =	i2c_device_uevent,
>  	.probe =	i2c_device_probe,
>  	.remove =	i2c_device_remove,
>  	.shutdown =	i2c_device_shutdown,
> -	.suspend =      i2c_bus_suspend,
> -	.resume =       i2c_bus_resume,
> +	.suspend =      i2c_device_suspend,
> +	.resume =       i2c_device_resume,
>  };
>  
>  /* ------------------------------------------------------------------------- */
> @@ -147,9 +192,9 @@ 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
> +/*
> + * We can't use the DEVICE_ATTR() macro here; we used the same name for
> + * an i2c adapter attribute (above).  So if the DEVICE_ATTR() macro ever
>   * changes, this definition will also have to change.
>   */
>  static struct device_attribute dev_attr_client_name = {

This change doesn't belong to this patch. BTW, it looks to me like this
issue could be solved by using the __ATTR macro, then the comment would
no longer be needed. Something like:

Use the __ATTR macro where possible.

Signed-off-by: Jean Delvare <khali at linux-fr.org>
---
 drivers/i2c/i2c-core.c |   11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

--- linux-2.6.19-rc6.orig/drivers/i2c/i2c-core.c	2006-11-17 11:46:17.000000000 +0100
+++ linux-2.6.19-rc6/drivers/i2c/i2c-core.c	2006-11-17 15:46:11.000000000 +0100
@@ -128,14 +128,11 @@
 }
 
 /* 
- * 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.
+ * We can't use the DEVICE_ATTR() macro here, as we used the same name for
+ * an i2c adapter attribute (above).
  */
-static struct device_attribute dev_attr_client_name = {
-	.attr	= {.name = "name", .mode = S_IRUGO, .owner = THIS_MODULE },
-	.show	= &show_client_name,
-};
+static struct device_attribute dev_attr_client_name =
+	__ATTR(name, S_IRUGO, &show_client_name, NULL);
 
 
 /* ---------------------------------------------------

> @@ -157,6 +202,18 @@ static struct device_attribute dev_attr_
>  	.show	= &show_client_name,
>  };
>  
> +/* modalias helps with coldplug:  modprobe $(cat /sys/devices/.../modalias) */
> +DEVICE_ATTR(modalias, S_IRUGO, show_client_name, NULL);
> +
> +static const struct attribute *i2c_dev_attrs[] = {
> +	&dev_attr_client_name.attr,
> +	&dev_attr_modalias.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group i2c_dev_attr_group = {
> +	.attrs = (struct attribute **)i2c_dev_attrs,

Don't declare the struct attribute array const, and you won't have to
cast. The struct attribute_group itself, on the other hand, can be
declared const.

> +};
>  
>  /* ---------------------------------------------------
>   * registering functions
> @@ -228,7 +285,7 @@ int i2c_add_adapter(struct i2c_adapter *
>  
>  	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
>  
> -	/* let drivers scan this bus for matching devices */
> +	/* let legacy drivers scan this bus for matching devices */
>  	res = bus_for_each_drv(&i2c_bus_type, NULL, adap,
>  			i2c_do_add_adapter);
>  
> @@ -285,7 +342,7 @@ int i2c_del_adapter(struct i2c_adapter *
>  		goto out_unlock;
>  	}
>  
> -	/* (maybe) tell drivers about this removal */
> +	/* (maybe) tell legacy drivers about this removal */

Why "maybe", BTW?

>  	res = bus_for_each_drv(&i2c_bus_type, NULL, adap,
>  			i2c_do_del_adapter);
>  	if (res)
> @@ -300,10 +357,32 @@ int i2c_del_adapter(struct i2c_adapter *
>  		client = list_entry(item, struct i2c_client, list);
>  		driver = client->driver;
>  
> +		/* new style driver */
> +		if (driver->remove) {
> +			if ((res = i2c_device_remove(&client->dev)) < 0) {
> +				dev_err(&client->dev, "remove failed (%d)\n",
> +					res);
> +				goto out_unlock;
> +			}
> +			driver = NULL;
> +		}
> +
> +		/* device from config tables */
> +		if (!driver) {
> +			if ((res = i2c_detach_client(client)) < 0)
> +				goto detach_failed;
> +			continue;
> +		}
> +
> +		/* legacy drivers create clients themselves */
>  		if ((res = driver->detach_client(client))) {
> -			dev_err(&adap->dev, "detach_client failed for client "
> -				"[%s] at address 0x%02x\n", client->name,
> -				client->addr);
> +detach_failed:
> +			dev_err(&adap->dev, "detach failed (%d) "
> +					"for client [%s] "
> +					"at address 0x%02x\n",
> +					res,
> +					client->name,
> +					client->addr);

Please don't overindent your code, it hurts readability. There's no
reason to use a double tab here, one is enough.

>  			goto out_unlock;
>  		}
>  	}
> @@ -343,18 +422,32 @@ int i2c_register_driver(struct module *o
>  	struct i2c_adapter *adapter;
>  	int res;
>  
> -	/* add the driver to the list of i2c drivers in the driver core */
> +	/* new style driver methods can't mix with legacy ones */
> +	if (driver->probe || driver->remove) {
> +		if (driver->attach_adapter
> +				|| driver->detach_adapter
> +				|| driver->detach_client) {

Ditto. You should align on the opening parenthesis as is done in the
rest of this file.

> +			pr_debug("i2c-core: driver [%s] is confused\n",
> +					driver->driver.name);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	/* add the driver to the list of i2c drivers in the driver core;
> +	 * on error, or for new style drivers, we're already done.
> +	 */
>  	driver->driver.owner = owner;
>  	driver->driver.bus = &i2c_bus_type;
>  
>  	res = driver_register(&driver->driver);
> -	if (res)
> +	pr_debug("i2c-core: register driver %s --> %d\n",
> +			driver->driver.name, res);
> +
> +	if (res || driver->probe)
>  		return res;
>  
>  	mutex_lock(&core_lists);
>  
> -	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
> -
>  	/* scan current busses for matching devices */
>  	if (driver->attach_adapter) {
>  		list_for_each(item,&adapters) {
> @@ -373,7 +466,6 @@ int i2c_del_driver(struct i2c_driver *dr
>  	struct list_head   *item1, *item2, *_n;
>  	struct i2c_client  *client;
>  	struct i2c_adapter *adap;
> -	
>  	int res = 0;
>  
>  	mutex_lock(&core_lists);
> @@ -453,14 +545,14 @@ int i2c_attach_client(struct i2c_client 
>  		goto out_unlock;
>  	}
>  	list_add_tail(&client->list,&adapter->clients);
> -	
> +
>  	client->usage_count = 0;
>  
>  	client->dev.parent = &client->adapter->dev;
>  	client->dev.driver = &client->driver->driver;
>  	client->dev.bus = &i2c_bus_type;
>  	client->dev.release = &i2c_client_release;
> -	
> +
>  	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
>  		"%d-%04x", i2c_adapter_id(adapter), client->addr);
>  	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",

These whitespace changes also belong to a separate patch. (In fact, you
might as well send me a preliminary patch killing all trailing
white-space from the main i2c files, if it helps you keep your text
editor happy.)

> @@ -468,7 +560,7 @@ int i2c_attach_client(struct i2c_client 
>  	res = device_register(&client->dev);
>  	if (res)
>  		goto out_list;
> -	res = device_create_file(&client->dev, &dev_attr_client_name);
> +	res = sysfs_create_group(&client->dev.kobj, &i2c_dev_attr_group);
>  	if (res)
>  		goto out_unregister;
>  	mutex_unlock(&adapter->clist_lock);
> @@ -521,7 +613,7 @@ int i2c_detach_client(struct i2c_client 
>  	mutex_lock(&adapter->clist_lock);
>  	list_del(&client->list);
>  	init_completion(&client->released);
> -	device_remove_file(&client->dev, &dev_attr_client_name);
> +	sysfs_remove_group(&client->dev.kobj, &i2c_dev_attr_group);
>  	device_unregister(&client->dev);
>  	mutex_unlock(&adapter->clist_lock);
>  	wait_for_completion(&client->released);
> Index: o26/Documentation/i2c/writing-clients
> ===================================================================
> --- o26.orig/Documentation/i2c/writing-clients	2006-11-16 11:04:35.000000000 -0800
> +++ o26/Documentation/i2c/writing-clients	2006-11-16 11:04:57.000000000 -0800
> @@ -1,5 +1,5 @@
>  This is a small guide for those who want to write kernel drivers for I2C
> -or SMBus devices.
> +or SMBus devices, using Linux as the protocol host.

I don't really understand what you mean here.

>  
>  To set up a driver, you need to do several things. Some are optional, and
>  some things can be done slightly or completely different. Use this as a
> @@ -29,8 +29,16 @@ static struct i2c_driver foo_driver = {
>  	.driver = {
>  		.name	= "foo",
>  	},
> +
> +	/* iff driver uses driver model ("new style") binding model: */
> +	.probe		= foo_probe,
> +	.remove		= foo_remove,
> +
> +	/* else, driver uses "legacy" binding model: */
>  	.attach_adapter	= foo_attach_adapter,
>  	.detach_client	= foo_detach_client,
> +
> +	/* these may be used regardless of the driver binding model */
>  	.shutdown	= foo_shutdown,	/* optional */
>  	.suspend	= foo_suspend,	/* optional */
>  	.resume		= foo_resume,	/* optional */
> @@ -140,7 +148,45 @@ Writing is done the same way.
>  
>  Probing and attaching
>  =====================

In the rest of this file, we left a blank line after each header,
please do the same.

> +The Linux I2C stack was originally written to support access to hardware
> +monitoring chips on PC motherboards, and thus it embeds some assumptions
> +that are more appropriate to SMBUS (and PCs) than to I2C.  One of these

s/SMBUS/SMBus/ (everywhere)

> +assumptions is that bus adapter drivers support the SMBUS_QUICK primitive
> +to probe device presence.  Another is that devices and their drivers can
> +be sufficiently configured using only such probe primitives.
> +
> +As Linux and its I2C stack became more widely used in embedded systems,
> +those assumptions became more problematic.  Drivers for I2C devices that

Not only embedded systems are affected, the v4l-dvb people keep
complaining about it as well.

> +issue interrupts need more (and different) configuration information, as
> +do drivers which can support more than one chip variant, or which need
> +board-specific information to be operate correctly.

Many i2c hardware monitoring drivers support more than one chip
variant, so that fact isn't relevant. What matters is whether the
variants can be identified just by probing, or not.

> +
> +Accordingly, the I2C stack now has two models for associating I2C devices
> +to drivers:  the original "legacy" model, and a newer one that's fully
> +compatible with the Linux 2.6 driver model.  These models do not mix,
> +since the "legacy" model requires drivers to create "i2c_client" device
> +objects after SMBUS style probing, while the Linux driver model expects
> +drivers to be given such device objects in their probe() routines.
> +
> +
> +New Style (Driver Model) Binding Model
> +--------------------------------------
> +System infrastructure, typically board-specific initialization code,
> +defines what I2C devices exist.  For example, they may provide a table
> +with device descriptors, which is later used to create i2c_client objects
> +for each I2C device and associate them with board-specific configuration
> +information about IRQs, chip type, and so on.
> +
> +I2C device drivers using this binding model work just like any other
> +kind of driver in Linux:  they provide a probe() method to bind to
> +those devices, and a remove() to unbind.

s/remove()/remove() method/

> +
> +	int	foo_probe(struct i2c_client *client);
> +	int	foo_remove(struct i2c_client *client);

Please use a space instad of tab between int and foo.

> +
>  
> +Legacy Driver Binding Model
> +---------------------------
>  Most i2c devices can be present on several i2c addresses; for some this
>  is determined in hardware (by soldering some chip pins to Vcc or Ground),
>  for others this can be changed in software (by writing to specific client
> @@ -162,9 +208,8 @@ NOTE: If you want to write a `sensors' d
>  
>  
>  
> -Probing classes
> ----------------
> -
> +Probing classes (Legacy model)
> +------------------------------
>  All parameters are given as lists of unsigned 16-bit integers. Lists are
>  terminated by I2C_CLIENT_END.
>  The following lists are used internally:
> @@ -210,9 +255,8 @@ Note that you *have* to call the defined
>  without any prefix!
>  
>  
> -Attaching to an adapter
> ------------------------
> -
> +Attaching to an adapter (Legacy model)
> +--------------------------------------
>  Whenever a new adapter is inserted, or for all adapters if the driver is
>  being registered, the callback attach_adapter() is called. Now is the
>  time to determine what devices are present on the adapter, and to register
> @@ -237,9 +281,8 @@ them (unless a `force' parameter was use
>  are already in use (by some other registered client) are skipped.
>  
>  
> -The detect client function
> ---------------------------
> -
> +The detect client function (Legacy model)
> +-----------------------------------------
>  The detect client function is called by i2c_probe. The `kind' parameter
>  contains -1 for a probed detection, 0 for a forced detection, or a positive
>  number for a forced detection with a chip type forced.
> @@ -427,9 +470,8 @@ For now, you can ignore the `flags' para
>    }
>  
>  
> -Removing the client
> -===================
> -
> +Removing the client (Legacy model)
> +==================================
>  The detach_client call back function is called when a client should be
>  removed. It may actually fail, but only when panicking. This code is
>  much simpler than the attachment code, fortunately!
> Index: o26/Documentation/i2c/summary
> ===================================================================
> --- o26.orig/Documentation/i2c/summary	2006-11-16 11:04:35.000000000 -0800
> +++ o26/Documentation/i2c/summary	2006-11-16 11:04:57.000000000 -0800
> @@ -4,17 +4,22 @@ I2C and SMBus
>  =============
>  
>  I2C (pronounce: I squared C) is a protocol developed by Philips. It is a 
> -slow two-wire protocol (10-400 kHz), but it suffices for many types of 
> -devices.
> +slow two-wire protocol (up to 400 kHz), with a high speed extension (MBits),

3.4 Mbit/s, actually. It's a bit strange to mix Hz and bit/s though.

> +which provides an inexpensive (two pins!) bus for connecting many types of
> +devices with infrequent or low bandwidth communications requirements.  It
> +is widely used with embedded systems.
> +
> +SMBus (System Management Bus) is based on the I2C protocol, and is mostly
> +a subset of I2C protocols and signaling.  Many I2C devices will work on an
> +SMBUS, but some SMBUS protocols are I2C-incompatible.  Modern PC mainboards

Oh, really? Which ones?

> +rely on SMBUS.  The most common devices connected through SMBUS are RAM
> +modules with I2C EEPROMs holding RAM chip data, and hardware monitors.

"hardware monitoring chips" sounds better, methinks.

> +
> +Because the SMBus is mostly a subset of the generalized I2C bus, we can
> +use its protocols on many I2C systems.  However, there are systems that don't
> +meet both SMBUS and I2C electrical constraints; and others which can't
> +implement all the SMBUS protocol messages.
>  
> -SMBus (System Management Bus) is a subset of the I2C protocol. Many
> -modern mainboards have a System Management Bus. There are a lot of 
> -devices which can be connected to a SMBus; the most notable are modern 
> -memory chips with EEPROM memories and chips for hardware monitoring.
> -
> -Because the SMBus is just a special case of the generalized I2C bus, we
> -can simulate the SMBus protocol on plain I2C busses. The reverse is
> -regretfully impossible.
>  
>  
>  Terminology
> @@ -29,6 +34,7 @@ When we talk about I2C, we use the follo
>  An Algorithm driver contains general code that can be used for a whole class
>  of I2C adapters. Each specific adapter driver depends on one algorithm
>  driver.
> +
>  A Driver driver (yes, this sounds ridiculous, sorry) contains the general
>  code to access some type of device. Each detected device gets its own
>  data in the Client structure. Usually, Driver and Client are more closely
> @@ -40,6 +46,10 @@ a separate Adapter and Algorithm driver)
>  in this package. See the lm_sensors project http://www.lm-sensors.nu
>  for device drivers.
>  
> +At this time, Linux only operates I2C (or SMBUS) in host mode; you can't
> +use these APIs to make a Linux system behave as a device, either to speak
> +a custom protocol or to emulate some other device.

"host mode" doesn't belong to the I2C naming convention, you'd rather
speak of "master" and "slave" roles. The Linux system operates as a
master.

> +
>  
>  Included Bus Drivers
>  ====================
> Index: o26/Documentation/i2c/smbus-protocol
> ===================================================================
> --- o26.orig/Documentation/i2c/smbus-protocol	2006-11-16 11:04:35.000000000 -0800
> +++ o26/Documentation/i2c/smbus-protocol	2006-11-16 11:04:57.000000000 -0800
> @@ -6,12 +6,15 @@ Certain protocol features which are not 
>  this package are briefly described at the end of this document.
>  
>  Some adapters understand only the SMBus (System Management Bus) protocol,
> -which is a subset from the I2C protocol. Fortunately, many devices use
> -only the same subset, which makes it possible to put them on an SMBus.
> +which largely overlaps the I2C protocol.  SMBUS has some mechanisms that
> +I2C doesn't, like SMBUS_QUICK; and vice versa.  The electrical constraints

I don't see anything in the I2C specification which would make the
SMBus Quick command invalid. It's a standard I2C transaction. What
makes you think otherwise?

> +are also different.  Fortunately, many I2C devices use a subset of the I2C
> +protocols and signaling which is SMBus-compatible.
> +
>  If you write a driver for some I2C device, please try to use the SMBus
>  commands if at all possible (if the device uses only that subset of the
>  I2C protocol). This makes it possible to use the device driver on both
> -SMBus adapters and I2C adapters (the SMBus command set is automatically
> +SMBus adapters and I2C adapters (most SMBus commands are automatically
>  translated to I2C on I2C adapters, but plain I2C commands can not be
>  handled at all on most pure SMBus adapters).

Thanks,
-- 
Jean Delvare



More information about the i2c mailing list