Subject: New i2c framework
To: None <tech-kern@netbsd.org>
From: Jason Thorpe <thorpej@wasabisystems.com>
List: tech-kern
Date: 07/26/2003 22:45:07
Folks...

Wasabi Systems would like to contribute a new i2c framework to the 
NetBSD source tree.  It attempts to address the concerns people have 
had with previous proposals.  This new code has been used successfully 
by Wasabi Systems on a variety of platforms with a pretty wide variety 
of i2c interface controllers, examples being:

	* Dumb bit-bang controllers (the mode we currently use
	  on the IBM 405GP's i2c interface).

	* A few styles of automated controllers that give you control
	  over sending start/stop conditions on the i2c bus (Intel
	  XScale IOP and Marvell Discovery).

	* An automated controller that is too smart for its own good,
	  giving software no control over start/stop conditions (on a
	  chip that has not been publicly announced yet).

This framework was initially designed and implemented by Steve 
Woodford.  It was later modified by me to support bit-bang and 
overly-automated controllers.

Two of the major concerns the last time an i2c framework was proposed 
here, and my solutions to them:

	Q. What about SMBus?  Many i2c controllers are really SMBus
	   controllers that are automated.

	A. This is a lot like the "too smart" automated controller
	   listed above.  The three SMBus operations can be described
	   like so:

		1. SMBus "write byte".  Equivalent i2c:
			- START write
			- send 1 byte [command]
			- send 1 byte [data] with STOP

		2. SMBus "read byte"
			- START write
			- send 1 byte [command]
			- REPEATED START read
			- read 1 byte [data] with STOP

		3. SMBus "receive byte"
			- START read
			- read 1 byte [data] with STOP

	   All of these operations can be expressed in the new API.
	   For convenience, there are functions that provide these
	   primitives, implementing them in terms of the more general
	   i2c API.  Drivers for automated SMBus controllers need
	   only ensure that the request that is presented to them is
	   one that the controller can perform.

	Q. What about queueing of transfers in the face of code that
	   needs to do i2c operations in interrupt context?

	A. First of all, there are no queued transfers in this new API.
	   When a client wants to access the i2c bus, it must "acquire"
	   it.  There are still some issues about "polling" clients
	   and how they lock the bus for themselves, but I don't consider
	   that a show-stopper at this time.  I have some ideas on how
	   to fix it, but would like to get this code out there.  Thankfully
	   I have not encountered code that needs to talk to the i2c in
	   in interrupt context yet.

i2c interface drivers present themselves to the framework using an 
i2c_tag_t.  The API that clients use is a function called iic_exec():

	int iic_exec(i2c_tag_t tag, i2c_op_t op, i2c_addr_t addr,
		const void *cmd, size_t cmdlen, void *buf, size_t buflen,
		int flags);

i2c_op_t is an enum type describing the type of operation to be 
performed:

	- I2C_OP_READ (no stop condition at the end)
	- I2C_OP_READ_WITH_STOP (stop condition at the end)
	- I2C_OP_WRITE (no stop condition at the end)
	- I2C_OP_WRITE_WITH_STOP (stop condition at the end)

flags is either 0 or I2C_F_POLL (the latter indicating that sleeping is 
not allowed).

Those four operations are implemented in therms of the following 5 
primitives provided by the controller driver:

	- ic_send_start -- set a START condition on the i2c bus
	  [This is not actually used by the middle-end at this time.]
	- ic_send_stop -- set a STOP condition on the i2c bus
	- ic_initiate_xfer -- set a START condition (which may be
	  a REPEATED START) and send the i2c device address onto
	  the i2c bus
	- ic_read_byte -- read a byte from the i2c bus
	- ic_write_byte -- write a byte to the i2c bus

In the event an automated controller does not provide sufficient 
operation granularity, it can elect to provide an ic_exec entry point 
which will be used instead.  SMBus controllers are likely candidates 
for using this entry point.

There is a big-bang module that implements the i2c wire protocol for 
dumb controllers.  In such cases, the controller merely needs to 
provide callbacks which set the state of the pins as specified by the 
bit-bang module.

I have converted the "tl" driver to use the new i2c framework, and have 
also converted the acorn26 and acorn32 ports (the latter because they 
had an "iic" device node whose name clashed with the new one).  
Unfortunately, I cannot test these 3 things -- I'm relying on other 
people to do this for me.

The new code is at:

	ftp://ftp.netbsd.org/pub/misc/thorpej/i2c.shar

		New contents of the sys/dev/i2c directory.

	ftp://ftp.netbsd.org/pub/misc/thorpej/i2c.patch

		Patch that glues it in, and adjusts the "tl" driver
		and the acorn26 and acorn32 ports.

I'd like to get this code checked in soon (mostly because if I don't, 
I'll run out of time to worry about getting it merged in).  I think it 
will be useful to folks, and it (or something like it) will be required 
by some new ports that are currently being worked on.  So, please test 
out those three previously mentioned things, look over the code, and 
tell me what you think.  :-)

         -- Jason R. Thorpe <thorpej@wasabisystems.com>