tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: I2C device drivers in NetBSD


I recently wrote an i2c driver for the arm platform and did something similar. 
I used the presence of the I2C_F_POLL flag to perform a synchronous transfer 
and used the absence of it (instead of adding a new flag) to indicate an 
asynchronous transfer. 

In the case of the async transfer, I setup a structure in the softc structure 
to define the parameters of the transfer, kicked it off and allowed the 
interrupt handler to conduct the transfer. When complete the interrupt handler 
signaled a condition variable. The exec function that initiated the transfer 
performed a timed wait on the same condition variable.

Hope this helps.


On Aug 3, 2011, at 3:38 PM, Peter Tworek wrote:

> Hi,
> For the past month I've been working on porting NetBSD to Openmoko GTA02
> phone. The port is mostly based on existing s3c2xx0 platform already
> supported by NetBSD. One of the sub-components of S3C2440 SOC not
> supported by the existing port is iic controller. GTA02 has at least 3
> components attached to this bus so it's a rather critical to have a
> working iic bus. Writing a driver for the controller is not a very
> complicated thing to do, I actually have it working already, but there
> are a couple of issues I have encountered.
> When reading trough the sources of some existing iic bus drivers I've
> noticed that all of them transfer the data synchronously. In most cases
> data is being written to the transmitter, start condition is generated,
> some loop is entered in which the driver actively waits for hardware
> event indicating either acknowledge or transmit failure. The loop
> usually has a limited number of iterations to handle transmit timeouts.
> This whole scheme seems fine if you consider most of the i2c device
> drivers NetBSD currently supports (eproms, rtcs). One of the components
> of GTA02 is a slightly more complicated piece of silicon - NXP/Philips
> PCF50633 [1]. Servicing this device in some circumstances might require
> several i2c transactions per second. For such workloads it's probably
> better idea to use interrupt based transfers. The question is how to
> implement support for such transfers using current iic driver interface?
> My current approach uses standard NetBSD iic interface (iic_acquire_bus,
> iic_exec, iic_release_bus). The only difference is that I've added
> additional flag I2C_F_INTR. When I2C_F_POLL is set the driver works in a
> way described above. When I2C_F_POLL is set the underlying driver:
> 1. Populates a work queue with simple operations describing iic
> transactions that have to be performed.
> 2. Acquires a spin mutex (IPL SERIAL priority, same as interrupt handler
> for the driver).
> 3. Initiates the transfer by filling tx register with slave address,
> enabling interrupts and generating start condition.
> 4. Starts waiting on a condition variable, cv_timedwait (mutex from step 2).
> Now all work is being done by the interrupt handler. Single run of this
> handler retrieves new task from the work queue (step 1), sets up the
> hardware to perform it and exits. The hardware is set in a way which
> triggers another interrupt when transfer has been finished or an error
> occurred. After all the tasks have been performed the interrupt handler
> disables interrupts, signals the condition variable and exits. Then it's
> just a matter of retrieving the results of all the iic transactions
> performed and returning them to the caller of iic_exec.
> This scheme works, but:
> 1. I'm not exactly sure if condition variable is the best
> synchronization mechanism for this particular use case. I don't know all
> the facilities NetBSD has to offer (I'm pretty new to NetBSD kernel
> programming). Is there something else that would be better for this
> particular job?
> 2. Condition variables (according to manual pages) put some constrains
> on where they can be used. Those will obviously also apply to iic_exec
> calls with with I2C_F_INTR flag. I feel that at least some of those
> constrains already apply to iic_exec interface. (I wouldn't call it from
> any interrupt handler for example). The question is if it puts any new
> constrains on the iic_exec?
> 3. Right now to indicate that the driver can sleep/use interrupt based
> transfers I use I2C_F_INTR flag. The question is if a new flag is
> necessary? I2C_F_POLL is used to tell the driver not to sleep, but
> actively wait for the transfer to finish. When not specified we could
> treat it as an indication that interrupt based transfer is
> allowed/desired. Should a new flag be added?
> /ptw
> [1]

Home | Main Index | Thread Index | Old Index