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
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
corgi_lcd.h
ds1305.h
dw_spi.h spi/dw_spi: enable platform specific chipselect. 2010-01-21 07:24:29 -07:00
eeprom.h
flash.h
Kbuild
l4f00242t03.h backlight: Add Epson L4F00242T03 LCD driver 2010-03-16 19:47:53 +00:00
libertas_spi.h
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
mmc_spi.h
orion_spi.h
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
spidev.h spi: new spi->mode bits 2009-06-30 18:56:00 -07:00
tdo24m.h
tle62x0.h
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