Peter, 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. Frank 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] http://people.openmoko.org/tony_tu/GTA02/datasheet/PMU/PCF50633DS_02.pdf
