kernel-fxtec-pro1x/include/linux/spi
Ernst Schwab cf32b71e98 spi/mmc_spi: SPI bus locking API, using mutex
SPI bus locking API to allow exclusive access to the SPI bus, especially, but
not limited to, for the mmc_spi driver.

Coded according to an outline from Grant Likely; here is his
specification (accidentally swapped function names corrected):

It requires 3 things to be added to struct spi_master.
- 1 Mutex
- 1 spin lock
- 1 flag.

The mutex protects spi_sync, and provides sleeping "for free"
The spinlock protects the atomic spi_async call.
The flag is set when the lock is obtained, and checked while holding
the spinlock in spi_async().  If the flag is checked, then spi_async()
must fail immediately.

The current runtime API looks like this:
spi_async(struct spi_device*, struct spi_message*);
spi_sync(struct spi_device*, struct spi_message*);

The API needs to be extended to this:
spi_async(struct spi_device*, struct spi_message*)
spi_sync(struct spi_device*, struct spi_message*)
spi_bus_lock(struct spi_master*)  /* although struct spi_device* might
be easier */
spi_bus_unlock(struct spi_master*)
spi_async_locked(struct spi_device*, struct spi_message*)
spi_sync_locked(struct spi_device*, struct spi_message*)

Drivers can only call the last two if they already hold the spi_master_lock().

spi_bus_lock() obtains the mutex, obtains the spin lock, sets the
flag, and releases the spin lock before returning.  It doesn't even
need to sleep while waiting for "in-flight" spi_transactions to
complete because its purpose is to guarantee no additional
transactions are added.  It does not guarantee that the bus is idle.

spi_bus_unlock() clears the flag and releases the mutex, which will
wake up any waiters.

The difference between spi_async() and spi_async_locked() is that the
locked version bypasses the check of the lock flag.  Both versions
need to obtain the spinlock.

The difference between spi_sync() and spi_sync_locked() is that
spi_sync() must hold the mutex while enqueuing a new transfer.
spi_sync_locked() doesn't because the mutex is already held.  Note
however that spi_sync must *not* continue to hold the mutex while
waiting for the transfer to complete, otherwise only one transfer
could be queued up at a time!

Almost no code needs to be written.  The current spi_async() and
spi_sync() can probably be renamed to __spi_async() and __spi_sync()
so that spi_async(), spi_sync(), spi_async_locked() and
spi_sync_locked() can just become wrappers around the common code.

spi_sync() is protected by a mutex because it can sleep
spi_async() needs to be protected with a flag and a spinlock because
it can be called atomically and must not sleep

Signed-off-by: Ernst Schwab <eschwab@online.de>
[grant.likely@secretlab.ca: use spin_lock_irqsave()]
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Matt Fleming <matt@console-pimps.org>
Tested-by: Antonio Ospite <ospite@studenti.unina.it>
2010-06-28 17:49:29 -07:00
..
ad7877.h blackfin architecture 2007-05-07 12:12:58 -07:00
ad7879.h Input: ad7879 - support auxiliary GPIOs via gpiolib 2010-01-19 00:31:51 -08:00
ads7846.h Input: ads7846 - add wakeup support 2010-03-11 00:02:43 -08:00
at73c213.h [ALSA] ALSA sound driver for the AT73C213 DAC using Atmel SSC driver 2007-10-16 15:57:50 +02:00
corgi_lcd.h [ARM] corgi_lcd: use GPIO API for BACKLIGHT_ON and BACKLIGHT_CONT 2008-09-25 09:38:14 +01:00
ds1305.h rtc: ds1305/ds1306 driver 2008-07-24 10:47:33 -07:00
dw_spi.h spi/dw_spi: enable platform specific chipselect. 2010-01-21 07:24:29 -07:00
eeprom.h memory_accessor: implement the new memory_accessor interfaces for SPI EEPROMs 2009-04-02 19:04:50 -07:00
flash.h [PATCH] spi: M25 series SPI flash 2006-01-13 16:29:55 -08:00
Kbuild /dev/spidevB.C interface 2007-05-08 11:15:15 -07:00
l4f00242t03.h backlight: Add Epson L4F00242T03 LCD driver 2010-03-16 19:47:53 +00:00
libertas_spi.h net/libertas: remove GPIO-CS handling in SPI interface code 2009-06-10 13:27:50 -04:00
lms283gf05.h backlight: spi driver for LMS283GF05 LCD 2009-09-07 15:08:06 +01:00
max7301.h gpio: add driver for MAX7300 I2C GPIO extender 2010-03-06 11:26:48 -08:00
mc33880.h gpio: add MC33880 driver 2009-09-23 07:39:46 -07:00
mcp23s08.h gpio: mcp23s08 handles multiple chips per chipselect 2008-07-25 10:53:30 -07:00
mmc_spi.h mmc_spi: Add support for OpenFirmware bindings 2008-12-31 19:01:55 +01:00
orion_spi.h orion_spi: handle 88F6183 erratum 2008-10-16 11:21:38 -07:00
sh_msiof.h spi: SuperH MSIOF SPI Master driver V2 2009-12-13 00:48:27 -07:00
spi.h spi/mmc_spi: SPI bus locking API, using mutex 2010-06-28 17:49:29 -07:00
spi_bitbang.h spi: move bitbang txrx utility functions to private header 2010-05-25 00:23:17 -06:00
spi_gpio.h spi-gpio: allow operation without CS signal 2009-04-02 19:04:51 -07:00
spidev.h spi: new spi->mode bits 2009-06-30 18:56:00 -07:00
tdo24m.h backlight: add support for Toppoly TDO35S series to tdo24m lcd driver 2009-01-08 20:11:07 +00:00
tle62x0.h SPI: tle620x power switch driver 2007-07-17 10:23:05 -07:00
wl12xx.h wl1251: add support for dedicated IRQ line 2010-04-16 15:47:14 -04:00
xilinx_spi.h xilinx_spi: add support for the DS570 IP. 2009-12-08 18:48:14 -07:00