Commit b171aa27 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6

* 'next-spi' of git://git.secretlab.ca/git/linux-2.6:
  spi/amba_pl022: Fix probe and remove hook section annotations.
  spi/mpc5121: change annotations for probe and remove functions
  spi/bitbang: reinitialize transfer parameters for every message
  spi/spi-gpio: add support for controllers without MISO or MOSI pin
  spi/bitbang: add support for SPI_MASTER_NO_{TX, RX} modes
  SPI100k: Fix 8-bit and RX-only transfers
  spi/mmc_spi: mmc_spi adaptations for SPI bus locking API
  spi/mmc_spi: SPI bus locking API, using mutex

Fix trivial conflict in drivers/spi/mpc512x_psc_spi.c due to 'struct
of_device' => 'struct platform_device' rename and __init/__exit to
__devinit/__devexit fix.
parents 11ac5524 b4225885
...@@ -182,7 +182,7 @@ mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len) ...@@ -182,7 +182,7 @@ mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len)
host->data_dma, sizeof(*host->data), host->data_dma, sizeof(*host->data),
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
status = spi_sync(host->spi, &host->readback); status = spi_sync_locked(host->spi, &host->readback);
if (host->dma_dev) if (host->dma_dev)
dma_sync_single_for_cpu(host->dma_dev, dma_sync_single_for_cpu(host->dma_dev,
...@@ -541,7 +541,7 @@ mmc_spi_command_send(struct mmc_spi_host *host, ...@@ -541,7 +541,7 @@ mmc_spi_command_send(struct mmc_spi_host *host,
host->data_dma, sizeof(*host->data), host->data_dma, sizeof(*host->data),
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
} }
status = spi_sync(host->spi, &host->m); status = spi_sync_locked(host->spi, &host->m);
if (host->dma_dev) if (host->dma_dev)
dma_sync_single_for_cpu(host->dma_dev, dma_sync_single_for_cpu(host->dma_dev,
...@@ -685,7 +685,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, ...@@ -685,7 +685,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
host->data_dma, sizeof(*scratch), host->data_dma, sizeof(*scratch),
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
status = spi_sync(spi, &host->m); status = spi_sync_locked(spi, &host->m);
if (status != 0) { if (status != 0) {
dev_dbg(&spi->dev, "write error (%d)\n", status); dev_dbg(&spi->dev, "write error (%d)\n", status);
...@@ -822,7 +822,7 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t, ...@@ -822,7 +822,7 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
} }
status = spi_sync(spi, &host->m); status = spi_sync_locked(spi, &host->m);
if (host->dma_dev) { if (host->dma_dev) {
dma_sync_single_for_cpu(host->dma_dev, dma_sync_single_for_cpu(host->dma_dev,
...@@ -1018,7 +1018,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, ...@@ -1018,7 +1018,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
host->data_dma, sizeof(*scratch), host->data_dma, sizeof(*scratch),
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
tmp = spi_sync(spi, &host->m); tmp = spi_sync_locked(spi, &host->m);
if (host->dma_dev) if (host->dma_dev)
dma_sync_single_for_cpu(host->dma_dev, dma_sync_single_for_cpu(host->dma_dev,
...@@ -1084,6 +1084,9 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -1084,6 +1084,9 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq)
} }
#endif #endif
/* request exclusive bus access */
spi_bus_lock(host->spi->master);
/* issue command; then optionally data and stop */ /* issue command; then optionally data and stop */
status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL); status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL);
if (status == 0 && mrq->data) { if (status == 0 && mrq->data) {
...@@ -1094,6 +1097,9 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -1094,6 +1097,9 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq)
mmc_cs_off(host); mmc_cs_off(host);
} }
/* release the bus */
spi_bus_unlock(host->spi->master);
mmc_request_done(host->mmc, mrq); mmc_request_done(host->mmc, mrq);
} }
...@@ -1290,23 +1296,6 @@ mmc_spi_detect_irq(int irq, void *mmc) ...@@ -1290,23 +1296,6 @@ mmc_spi_detect_irq(int irq, void *mmc)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
struct count_children {
unsigned n;
struct bus_type *bus;
};
static int maybe_count_child(struct device *dev, void *c)
{
struct count_children *ccp = c;
if (dev->bus == ccp->bus) {
if (ccp->n)
return -EBUSY;
ccp->n++;
}
return 0;
}
static int mmc_spi_probe(struct spi_device *spi) static int mmc_spi_probe(struct spi_device *spi)
{ {
void *ones; void *ones;
...@@ -1338,32 +1327,6 @@ static int mmc_spi_probe(struct spi_device *spi) ...@@ -1338,32 +1327,6 @@ static int mmc_spi_probe(struct spi_device *spi)
return status; return status;
} }
/* We can use the bus safely iff nobody else will interfere with us.
* Most commands consist of one SPI message to issue a command, then
* several more to collect its response, then possibly more for data
* transfer. Clocking access to other devices during that period will
* corrupt the command execution.
*
* Until we have software primitives which guarantee non-interference,
* we'll aim for a hardware-level guarantee.
*
* REVISIT we can't guarantee another device won't be added later...
*/
if (spi->master->num_chipselect > 1) {
struct count_children cc;
cc.n = 0;
cc.bus = spi->dev.bus;
status = device_for_each_child(spi->dev.parent, &cc,
maybe_count_child);
if (status < 0) {
dev_err(&spi->dev, "can't share SPI bus\n");
return status;
}
dev_warn(&spi->dev, "ASSUMING SPI bus stays unshared!\n");
}
/* We need a supply of ones to transmit. This is the only time /* We need a supply of ones to transmit. This is the only time
* the CPU touches these, so cache coherency isn't a concern. * the CPU touches these, so cache coherency isn't a concern.
* *
......
...@@ -1723,7 +1723,7 @@ static void pl022_cleanup(struct spi_device *spi) ...@@ -1723,7 +1723,7 @@ static void pl022_cleanup(struct spi_device *spi)
} }
static int __init static int __devinit
pl022_probe(struct amba_device *adev, struct amba_id *id) pl022_probe(struct amba_device *adev, struct amba_id *id)
{ {
struct device *dev = &adev->dev; struct device *dev = &adev->dev;
...@@ -1838,7 +1838,7 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) ...@@ -1838,7 +1838,7 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
return status; return status;
} }
static int __exit static int __devexit
pl022_remove(struct amba_device *adev) pl022_remove(struct amba_device *adev)
{ {
struct pl022 *pl022 = amba_get_drvdata(adev); struct pl022 *pl022 = amba_get_drvdata(adev);
...@@ -1970,7 +1970,7 @@ static struct amba_driver pl022_driver = { ...@@ -1970,7 +1970,7 @@ static struct amba_driver pl022_driver = {
}, },
.id_table = pl022_ids, .id_table = pl022_ids,
.probe = pl022_probe, .probe = pl022_probe,
.remove = __exit_p(pl022_remove), .remove = __devexit_p(pl022_remove),
.suspend = pl022_suspend, .suspend = pl022_suspend,
.resume = pl022_resume, .resume = pl022_resume,
}; };
......
...@@ -406,9 +406,9 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id) ...@@ -406,9 +406,9 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
} }
/* bus_num is used only for the case dev->platform_data == NULL */ /* bus_num is used only for the case dev->platform_data == NULL */
static int __init mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, static int __devinit mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
u32 size, unsigned int irq, u32 size, unsigned int irq,
s16 bus_num) s16 bus_num)
{ {
struct fsl_spi_platform_data *pdata = dev->platform_data; struct fsl_spi_platform_data *pdata = dev->platform_data;
struct mpc512x_psc_spi *mps; struct mpc512x_psc_spi *mps;
...@@ -492,7 +492,7 @@ static int __init mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, ...@@ -492,7 +492,7 @@ static int __init mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
return ret; return ret;
} }
static int __exit mpc512x_psc_spi_do_remove(struct device *dev) static int __devexit mpc512x_psc_spi_do_remove(struct device *dev)
{ {
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
...@@ -507,8 +507,8 @@ static int __exit mpc512x_psc_spi_do_remove(struct device *dev) ...@@ -507,8 +507,8 @@ static int __exit mpc512x_psc_spi_do_remove(struct device *dev)
return 0; return 0;
} }
static int __init mpc512x_psc_spi_of_probe(struct platform_device *op, static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op,
const struct of_device_id *match) const struct of_device_id *match)
{ {
const u32 *regaddr_p; const u32 *regaddr_p;
u64 regaddr64, size64; u64 regaddr64, size64;
...@@ -539,7 +539,7 @@ static int __init mpc512x_psc_spi_of_probe(struct platform_device *op, ...@@ -539,7 +539,7 @@ static int __init mpc512x_psc_spi_of_probe(struct platform_device *op,
irq_of_parse_and_map(op->dev.of_node, 0), id); irq_of_parse_and_map(op->dev.of_node, 0), id);
} }
static int __exit mpc512x_psc_spi_of_remove(struct platform_device *op) static int __devexit mpc512x_psc_spi_of_remove(struct platform_device *op)
{ {
return mpc512x_psc_spi_do_remove(&op->dev); return mpc512x_psc_spi_do_remove(&op->dev);
} }
...@@ -553,7 +553,7 @@ MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match); ...@@ -553,7 +553,7 @@ MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
static struct of_platform_driver mpc512x_psc_spi_of_driver = { static struct of_platform_driver mpc512x_psc_spi_of_driver = {
.probe = mpc512x_psc_spi_of_probe, .probe = mpc512x_psc_spi_of_probe,
.remove = __exit_p(mpc512x_psc_spi_of_remove), .remove = __devexit_p(mpc512x_psc_spi_of_remove),
.driver = { .driver = {
.name = "mpc512x-psc-spi", .name = "mpc512x-psc-spi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -141,7 +141,12 @@ static void spi100k_write_data(struct spi_master *master, int len, int data) ...@@ -141,7 +141,12 @@ static void spi100k_write_data(struct spi_master *master, int len, int data)
{ {
struct omap1_spi100k *spi100k = spi_master_get_devdata(master); struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
/* write 16-bit word */ /* write 16-bit word, shifting 8-bit data if necessary */
if (len <= 8) {
data <<= 8;
len = 16;
}
spi100k_enable_clock(master); spi100k_enable_clock(master);
writew( data , spi100k->base + SPI_TX_MSB); writew( data , spi100k->base + SPI_TX_MSB);
...@@ -162,6 +167,10 @@ static int spi100k_read_data(struct spi_master *master, int len) ...@@ -162,6 +167,10 @@ static int spi100k_read_data(struct spi_master *master, int len)
int dataH,dataL; int dataH,dataL;
struct omap1_spi100k *spi100k = spi_master_get_devdata(master); struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
/* Always do at least 16 bits */
if (len <= 8)
len = 16;
spi100k_enable_clock(master); spi100k_enable_clock(master);
writew(SPI_CTRL_SEN(0) | writew(SPI_CTRL_SEN(0) |
SPI_CTRL_WORD_SIZE(len) | SPI_CTRL_WORD_SIZE(len) |
...@@ -214,10 +223,6 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -214,10 +223,6 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
c = count; c = count;
word_len = cs->word_len; word_len = cs->word_len;
/* RX_ONLY mode needs dummy data in TX reg */
if (xfer->tx_buf == NULL)
spi100k_write_data(spi->master,word_len, 0);
if (word_len <= 8) { if (word_len <= 8) {
u8 *rx; u8 *rx;
const u8 *tx; const u8 *tx;
...@@ -227,9 +232,9 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -227,9 +232,9 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
do { do {
c-=1; c-=1;
if (xfer->tx_buf != NULL) if (xfer->tx_buf != NULL)
spi100k_write_data(spi->master,word_len, *tx); spi100k_write_data(spi->master, word_len, *tx++);
if (xfer->rx_buf != NULL) if (xfer->rx_buf != NULL)
*rx = spi100k_read_data(spi->master,word_len); *rx++ = spi100k_read_data(spi->master, word_len);
} while(c); } while(c);
} else if (word_len <= 16) { } else if (word_len <= 16) {
u16 *rx; u16 *rx;
...@@ -380,10 +385,6 @@ static void omap1_spi100k_work(struct work_struct *work) ...@@ -380,10 +385,6 @@ static void omap1_spi100k_work(struct work_struct *work)
if (t->len) { if (t->len) {
unsigned count; unsigned count;
/* RX_ONLY mode needs dummy data in TX reg */
if (t->tx_buf == NULL)
spi100k_write_data(spi->master, 8, 0);
count = omap1_spi100k_txrx_pio(spi, t); count = omap1_spi100k_txrx_pio(spi, t);
m->actual_length += count; m->actual_length += count;
......
...@@ -528,6 +528,10 @@ int spi_register_master(struct spi_master *master) ...@@ -528,6 +528,10 @@ int spi_register_master(struct spi_master *master)
dynamic = 1; dynamic = 1;
} }
spin_lock_init(&master->bus_lock_spinlock);
mutex_init(&master->bus_lock_mutex);
master->bus_lock_flag = 0;
/* register the device, then userspace will see it. /* register the device, then userspace will see it.
* registration fails if the bus ID is in use. * registration fails if the bus ID is in use.
*/ */
...@@ -670,6 +674,35 @@ int spi_setup(struct spi_device *spi) ...@@ -670,6 +674,35 @@ int spi_setup(struct spi_device *spi)
} }
EXPORT_SYMBOL_GPL(spi_setup); EXPORT_SYMBOL_GPL(spi_setup);
static int __spi_async(struct spi_device *spi, struct spi_message *message)
{
struct spi_master *master = spi->master;
/* Half-duplex links include original MicroWire, and ones with
* only one data pin like SPI_3WIRE (switches direction) or where
* either MOSI or MISO is missing. They can also be caused by
* software limitations.
*/
if ((master->flags & SPI_MASTER_HALF_DUPLEX)
|| (spi->mode & SPI_3WIRE)) {
struct spi_transfer *xfer;
unsigned flags = master->flags;
list_for_each_entry(xfer, &message->transfers, transfer_list) {
if (xfer->rx_buf && xfer->tx_buf)
return -EINVAL;
if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)
return -EINVAL;
if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
return -EINVAL;
}
}
message->spi = spi;
message->status = -EINPROGRESS;
return master->transfer(spi, message);
}
/** /**
* spi_async - asynchronous SPI transfer * spi_async - asynchronous SPI transfer
* @spi: device with which data will be exchanged * @spi: device with which data will be exchanged
...@@ -702,33 +735,68 @@ EXPORT_SYMBOL_GPL(spi_setup); ...@@ -702,33 +735,68 @@ EXPORT_SYMBOL_GPL(spi_setup);
int spi_async(struct spi_device *spi, struct spi_message *message) int spi_async(struct spi_device *spi, struct spi_message *message)
{ {
struct spi_master *master = spi->master; struct spi_master *master = spi->master;
int ret;
unsigned long flags;
/* Half-duplex links include original MicroWire, and ones with spin_lock_irqsave(&master->bus_lock_spinlock, flags);
* only one data pin like SPI_3WIRE (switches direction) or where
* either MOSI or MISO is missing. They can also be caused by
* software limitations.
*/
if ((master->flags & SPI_MASTER_HALF_DUPLEX)
|| (spi->mode & SPI_3WIRE)) {
struct spi_transfer *xfer;
unsigned flags = master->flags;
list_for_each_entry(xfer, &message->transfers, transfer_list) { if (master->bus_lock_flag)
if (xfer->rx_buf && xfer->tx_buf) ret = -EBUSY;
return -EINVAL; else
if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf) ret = __spi_async(spi, message);
return -EINVAL;
if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
return -EINVAL;
}
}
message->spi = spi; spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
message->status = -EINPROGRESS;
return master->transfer(spi, message); return ret;
} }
EXPORT_SYMBOL_GPL(spi_async); EXPORT_SYMBOL_GPL(spi_async);
/**
* spi_async_locked - version of spi_async with exclusive bus usage
* @spi: device with which data will be exchanged
* @message: describes the data transfers, including completion callback
* Context: any (irqs may be blocked, etc)
*
* This call may be used in_irq and other contexts which can't sleep,
* as well as from task contexts which can sleep.
*
* The completion callback is invoked in a context which can't sleep.
* Before that invocation, the value of message->status is undefined.
* When the callback is issued, message->status holds either zero (to
* indicate complete success) or a negative error code. After that
* callback returns, the driver which issued the transfer request may
* deallocate the associated memory; it's no longer in use by any SPI
* core or controller driver code.
*
* Note that although all messages to a spi_device are handled in
* FIFO order, messages may go to different devices in other orders.
* Some device might be higher priority, or have various "hard" access
* time requirements, for example.
*
* On detection of any fault during the transfer, processing of
* the entire message is aborted, and the device is deselected.
* Until returning from the associated message completion callback,
* no other spi_message queued to that device will be processed.
* (This rule applies equally to all the synchronous transfer calls,
* which are wrappers around this core asynchronous primitive.)
*/
int spi_async_locked(struct spi_device *spi, struct spi_message *message)
{
struct spi_master *master = spi->master;
int ret;
unsigned long flags;
spin_lock_irqsave(&master->bus_lock_spinlock, flags);
ret = __spi_async(spi, message);
spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(spi_async_locked);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -742,6 +810,32 @@ static void spi_complete(void *arg) ...@@ -742,6 +810,32 @@ static void spi_complete(void *arg)
complete(arg); complete(arg);
} }
static int __spi_sync(struct spi_device *spi, struct spi_message *message,
int bus_locked)
{
DECLARE_COMPLETION_ONSTACK(done);
int status;
struct spi_master *master = spi->master;
message->complete = spi_complete;
message->context = &done;
if (!bus_locked)
mutex_lock(&master->bus_lock_mutex);
status = spi_async_locked(spi, message);
if (!bus_locked)
mutex_unlock(&master->bus_lock_mutex);
if (status == 0) {
wait_for_completion(&done);
status = message->status;
}
message->context = NULL;
return status;
}
/** /**
* spi_sync - blocking/synchronous SPI data transfers * spi_sync - blocking/synchronous SPI data transfers
* @spi: device with which data will be exchanged * @spi: device with which data will be exchanged
...@@ -765,21 +859,86 @@ static void spi_complete(void *arg) ...@@ -765,21 +859,86 @@ static void spi_complete(void *arg)
*/ */
int spi_sync(struct spi_device *spi, struct spi_message *message) int spi_sync(struct spi_device *spi, struct spi_message *message)
{ {
DECLARE_COMPLETION_ONSTACK(done); return __spi_sync(spi, message, 0);
int status;
message->complete = spi_complete;
message->context = &done;
status = spi_async(spi, message);
if (status == 0) {
wait_for_completion(&done);
status = message->status;
}
message->context = NULL;
return status;
} }
EXPORT_SYMBOL_GPL(spi_sync); EXPORT_SYMBOL_GPL(spi_sync);
/**
* spi_sync_locked - version of spi_sync with exclusive bus usage
* @spi: device with which data will be exchanged
* @message: describes the data transfers
* Context: can sleep
*
* This call may only be used from a context that may sleep. The sleep
* is non-interruptible, and has no timeout. Low-overhead controller
* drivers may DMA directly into and out of the message buffers.
*
* This call should be used by drivers that require exclusive access to the
* SPI bus. It has to be preceeded by a spi_bus_lock call. The SPI bus must
* be released by a spi_bus_unlock call when the exclusive access is over.
*
* It returns zero on success, else a negative error code.
*/
int spi_sync_locked(struct spi_device *spi, struct spi_message *message)
{
return __spi_sync(spi, message, 1);
}
EXPORT_SYMBOL_GPL(spi_sync_locked);
/**
* spi_bus_lock - obtain a lock for exclusive SPI bus usage
* @master: SPI bus master that should be locked for exclusive bus access
* Context: can sleep
*
* This call may only be used from a context that may sleep. The sleep
* is non-interruptible, and has no timeout.
*
* This call should be used by drivers that require exclusive access to the
* SPI bus. The SPI bus must be released by a spi_bus_unlock call when the
* exclusive access is over. Data transfer must be done by spi_sync_locked
* and spi_async_locked calls when the SPI bus lock is held.
*
* It returns zero on success, else a negative error code.
*/
int spi_bus_lock(struct spi_master *master)
{
unsigned long flags;
mutex_lock(&master->bus_lock_mutex);
spin_lock_irqsave(&master->bus_lock_spinlock, flags);
master->bus_lock_flag = 1;
spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
/* mutex remains locked until spi_bus_unlock is called */
return 0;
}
EXPORT_SYMBOL_GPL(spi_bus_lock);
/**
* spi_bus_unlock - release the lock for exclusive SPI bus usage
* @master: SPI bus master that was locked for exclusive bus access
* Context: can sleep
*
* This call may only be used from a context that may sleep. The sleep
* is non-interruptible, and has no timeout.
*
* This call releases an SPI bus lock previously obtained by an spi_bus_lock
* call.
*
* It returns zero on success, else a negative error code.
*/
int spi_bus_unlock(struct spi_master *master)
{
master->bus_lock_flag = 0;
mutex_unlock(&master->bus_lock_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(spi_bus_unlock);
/* portable code must never pass more than 32 bytes */ /* portable code must never pass more than 32 bytes */
#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES) #define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
......
...@@ -259,7 +259,6 @@ static void bitbang_work(struct work_struct *work) ...@@ -259,7 +259,6 @@ static void bitbang_work(struct work_struct *work)
struct spi_bitbang *bitbang = struct spi_bitbang *bitbang =
container_of(work, struct spi_bitbang, work); container_of(work, struct spi_bitbang, work);
unsigned long flags; unsigned long flags;
int do_setup = -1;
int (*setup_transfer)(struct spi_device *, int (*setup_transfer)(struct spi_device *,
struct spi_transfer *); struct spi_transfer *);
...@@ -275,6 +274,7 @@ static void bitbang_work(struct work_struct *work) ...@@ -275,6 +274,7 @@ static void bitbang_work(struct work_struct *work)
unsigned tmp; unsigned tmp;
unsigned cs_change; unsigned cs_change;
int status; int status;
int do_setup = -1;
m = container_of(bitbang->queue.next, struct spi_message, m = container_of(bitbang->queue.next, struct spi_message,
queue); queue);
...@@ -307,6 +307,8 @@ static void bitbang_work(struct work_struct *work) ...@@ -307,6 +307,8 @@ static void bitbang_work(struct work_struct *work)
status = setup_transfer(spi, t); status = setup_transfer(spi, t);
if (status < 0) if (status < 0)
break; break;
if (do_setup == -1)
do_setup = 0;
} }
/* set up default clock polarity, and activate chip; /* set up default clock polarity, and activate chip;
...@@ -367,11 +369,6 @@ static void bitbang_work(struct work_struct *work) ...@@ -367,11 +369,6 @@ static void bitbang_work(struct work_struct *work)
m->status = status; m->status = status;
m->complete(m->context); m->complete(m->context);
/* restore speed and wordsize if it was overridden */
if (do_setup == 1)
setup_transfer(spi, NULL);
do_setup = 0;
/* normally deactivate chipselect ... unless no error and /* normally deactivate chipselect ... unless no error and
* cs_change has hinted that the next message will probably * cs_change has hinted that the next message will probably
* be for this chip too. * be for this chip too.
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
static inline u32 static inline u32
bitbang_txrx_be_cpha0(struct spi_device *spi, bitbang_txrx_be_cpha0(struct spi_device *spi,
unsigned nsecs, unsigned cpol, unsigned nsecs, unsigned cpol, unsigned flags,
u32 word, u8 bits) u32 word, u8 bits)
{ {
/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
...@@ -53,7 +53,8 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, ...@@ -53,7 +53,8 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
for (word <<= (32 - bits); likely(bits); bits--) { for (word <<= (32 - bits); likely(bits); bits--) {
/* setup MSB (to slave) on trailing edge */ /* setup MSB (to slave) on trailing edge */
setmosi(spi, word & (1 << 31)); if ((flags & SPI_MASTER_NO_TX) == 0)
setmosi(spi, word & (1 << 31));
spidelay(nsecs); /* T(setup) */ spidelay(nsecs); /* T(setup) */
setsck(spi, !cpol); setsck(spi, !cpol);
...@@ -61,7 +62,8 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, ...@@ -61,7 +62,8 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
/* sample MSB (from slave) on leading edge */ /* sample MSB (from slave) on leading edge */
word <<= 1; word <<= 1;
word |= getmiso(spi); if ((flags & SPI_MASTER_NO_RX) == 0)
word |= getmiso(spi);
setsck(spi, cpol); setsck(spi, cpol);
} }
return word; return word;
...@@ -69,7 +71,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, ...@@ -69,7 +71,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
static inline u32 static inline u32
bitbang_txrx_be_cpha1(struct spi_device *spi, bitbang_txrx_be_cpha1(struct spi_device *spi,
unsigned nsecs, unsigned cpol, unsigned nsecs, unsigned cpol, unsigned flags,
u32 word, u8 bits) u32 word, u8 bits)
{ {
/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
...@@ -79,7 +81,8 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, ...@@ -79,7 +81,8 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
/* setup MSB (to slave) on leading edge */ /* setup MSB (to slave) on leading edge */
setsck(spi, !cpol); setsck(spi, !cpol);
setmosi(spi, word & (1 << 31)); if ((flags & SPI_MASTER_NO_TX) == 0)
setmosi(spi, word & (1 << 31));
spidelay(nsecs); /* T(setup) */ spidelay(nsecs); /* T(setup) */
setsck(spi, cpol); setsck(spi, cpol);
...@@ -87,7 +90,8 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, ...@@ -87,7 +90,8 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
/* sample MSB (from slave) on trailing edge */ /* sample MSB (from slave) on trailing edge */
word <<= 1; word <<= 1;
word |= getmiso(spi); if ((flags & SPI_MASTER_NO_RX) == 0)
word |= getmiso(spi);
} }
return word; return word;
} }
...@@ -156,7 +156,7 @@ butterfly_txrx_word_mode0(struct spi_device *spi, ...@@ -156,7 +156,7 @@ butterfly_txrx_word_mode0(struct spi_device *spi,
unsigned nsecs, unsigned nsecs,
u32 word, u8 bits) u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
......
...@@ -146,25 +146,63 @@ static inline int getmiso(const struct spi_device *spi) ...@@ -146,25 +146,63 @@ static inline int getmiso(const struct spi_device *spi)
static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi, static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
} }
static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi, static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
} }
static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi, static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
} }
static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
}
/*
* These functions do not call setmosi or getmiso if respective flag
* (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to
* call when such pin is not present or defined in the controller.
* A separate set of callbacks is defined to get highest possible
* speed in the generic case (when both MISO and MOSI lines are
* available), as optimiser will remove the checks when argument is
* constant.
*/
static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits)
{
unsigned flags = spi->master->flags;
return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
}
static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits)
{
unsigned flags = spi->master->flags;
return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
}
static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits)
{
unsigned flags = spi->master->flags;
return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
}
static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits)
{
unsigned flags = spi->master->flags;
return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
...@@ -232,19 +270,30 @@ static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) ...@@ -232,19 +270,30 @@ static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
} }
static int __init static int __init
spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label,
u16 *res_flags)
{ {
int value; int value;
/* NOTE: SPI_*_GPIO symbols may reference "pdata" */ /* NOTE: SPI_*_GPIO symbols may reference "pdata" */
value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
if (value) value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
goto done; if (value)
goto done;
} else {
/* HW configuration without MOSI pin */
*res_flags |= SPI_MASTER_NO_TX;
}
value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
if (value) value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
goto free_mosi; if (value)
goto free_mosi;
} else {
/* HW configuration without MISO pin */
*res_flags |= SPI_MASTER_NO_RX;
}
value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
if (value) if (value)
...@@ -253,9 +302,11 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) ...@@ -253,9 +302,11 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label)
goto done; goto done;
free_miso: free_miso:
gpio_free(SPI_MISO_GPIO); if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
gpio_free(SPI_MISO_GPIO);
free_mosi: free_mosi:
gpio_free(SPI_MOSI_GPIO); if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
gpio_free(SPI_MOSI_GPIO);
done: done:
return value; return value;
} }
...@@ -266,6 +317,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) ...@@ -266,6 +317,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
struct spi_master *master; struct spi_master *master;
struct spi_gpio *spi_gpio; struct spi_gpio *spi_gpio;
struct spi_gpio_platform_data *pdata; struct spi_gpio_platform_data *pdata;
u16 master_flags = 0;
pdata = pdev->dev.platform_data; pdata = pdev->dev.platform_data;
#ifdef GENERIC_BITBANG #ifdef GENERIC_BITBANG
...@@ -273,7 +325,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) ...@@ -273,7 +325,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
#endif #endif
status = spi_gpio_request(pdata, dev_name(&pdev->dev)); status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
if (status < 0) if (status < 0)
return status; return status;
...@@ -289,6 +341,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) ...@@ -289,6 +341,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
if (pdata) if (pdata)
spi_gpio->pdata = *pdata; spi_gpio->pdata = *pdata;
master->flags = master_flags;
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->num_chipselect = SPI_N_CHIPSEL; master->num_chipselect = SPI_N_CHIPSEL;
master->setup = spi_gpio_setup; master->setup = spi_gpio_setup;
...@@ -296,10 +349,18 @@ static int __init spi_gpio_probe(struct platform_device *pdev) ...@@ -296,10 +349,18 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
spi_gpio->bitbang.master = spi_master_get(master); spi_gpio->bitbang.master = spi_master_get(master);
spi_gpio->bitbang.chipselect = spi_gpio_chipselect; spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) {
spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
} else {
spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
}
spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
spi_gpio->bitbang.flags = SPI_CS_HIGH; spi_gpio->bitbang.flags = SPI_CS_HIGH;
...@@ -307,8 +368,10 @@ static int __init spi_gpio_probe(struct platform_device *pdev) ...@@ -307,8 +368,10 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
if (status < 0) { if (status < 0) {
spi_master_put(spi_gpio->bitbang.master); spi_master_put(spi_gpio->bitbang.master);
gpio_free: gpio_free:
gpio_free(SPI_MISO_GPIO); if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
gpio_free(SPI_MOSI_GPIO); gpio_free(SPI_MISO_GPIO);
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
gpio_free(SPI_MOSI_GPIO);
gpio_free(SPI_SCK_GPIO); gpio_free(SPI_SCK_GPIO);
spi_master_put(master); spi_master_put(master);
} }
...@@ -331,8 +394,10 @@ static int __exit spi_gpio_remove(struct platform_device *pdev) ...@@ -331,8 +394,10 @@ static int __exit spi_gpio_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
gpio_free(SPI_MISO_GPIO); if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
gpio_free(SPI_MOSI_GPIO); gpio_free(SPI_MISO_GPIO);
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
gpio_free(SPI_MOSI_GPIO);
gpio_free(SPI_SCK_GPIO); gpio_free(SPI_SCK_GPIO);
return status; return status;
......
...@@ -191,7 +191,7 @@ static void lm70_chipselect(struct spi_device *spi, int value) ...@@ -191,7 +191,7 @@ static void lm70_chipselect(struct spi_device *spi, int value)
*/ */
static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits) static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
} }
static void spi_lm70llp_attach(struct parport *p) static void spi_lm70llp_attach(struct parport *p)
......
...@@ -64,25 +64,25 @@ static inline u32 getmiso(struct spi_device *dev) ...@@ -64,25 +64,25 @@ static inline u32 getmiso(struct spi_device *dev)
static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi, static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
} }
static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi, static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
} }
static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi, static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
} }
static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi, static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
} }
......
...@@ -83,25 +83,25 @@ static inline u32 getmiso(struct spi_device *dev) ...@@ -83,25 +83,25 @@ static inline u32 getmiso(struct spi_device *dev)
static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi, static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
} }
static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi, static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
} }
static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi, static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
} }
static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi, static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
} }
static void sh_sci_spi_chipselect(struct spi_device *dev, int value) static void sh_sci_spi_chipselect(struct spi_device *dev, int value)
......
...@@ -262,6 +262,13 @@ struct spi_master { ...@@ -262,6 +262,13 @@ struct spi_master {
#define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */ #define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */
#define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */
/* lock and mutex for SPI bus locking */
spinlock_t bus_lock_spinlock;
struct mutex bus_lock_mutex;
/* flag indicating that the SPI bus is locked for exclusive use */
bool bus_lock_flag;
/* Setup mode and clock, etc (spi driver may call many times). /* Setup mode and clock, etc (spi driver may call many times).
* *
* IMPORTANT: this may be called when transfers to another * IMPORTANT: this may be called when transfers to another
...@@ -542,6 +549,8 @@ static inline void spi_message_free(struct spi_message *m) ...@@ -542,6 +549,8 @@ static inline void spi_message_free(struct spi_message *m)
extern int spi_setup(struct spi_device *spi); extern int spi_setup(struct spi_device *spi);
extern int spi_async(struct spi_device *spi, struct spi_message *message); extern int spi_async(struct spi_device *spi, struct spi_message *message);
extern int spi_async_locked(struct spi_device *spi,
struct spi_message *message);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
...@@ -551,6 +560,9 @@ extern int spi_async(struct spi_device *spi, struct spi_message *message); ...@@ -551,6 +560,9 @@ extern int spi_async(struct spi_device *spi, struct spi_message *message);
*/ */
extern int spi_sync(struct spi_device *spi, struct spi_message *message); extern int spi_sync(struct spi_device *spi, struct spi_message *message);
extern int spi_sync_locked(struct spi_device *spi, struct spi_message *message);
extern int spi_bus_lock(struct spi_master *master);
extern int spi_bus_unlock(struct spi_master *master);
/** /**
* spi_write - SPI synchronous write * spi_write - SPI synchronous write
......
...@@ -29,11 +29,16 @@ ...@@ -29,11 +29,16 @@
* SPI_GPIO_NO_CHIPSELECT to the controller_data: * SPI_GPIO_NO_CHIPSELECT to the controller_data:
* .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT; * .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT;
* *
* If the MISO or MOSI pin is not available then it should be set to
* SPI_GPIO_NO_MISO or SPI_GPIO_NO_MOSI.
*
* If the bitbanged bus is later switched to a "native" controller, * If the bitbanged bus is later switched to a "native" controller,
* that platform_device and controller_data should be removed. * that platform_device and controller_data should be removed.
*/ */
#define SPI_GPIO_NO_CHIPSELECT ((unsigned long)-1l) #define SPI_GPIO_NO_CHIPSELECT ((unsigned long)-1l)
#define SPI_GPIO_NO_MISO ((unsigned long)-1l)
#define SPI_GPIO_NO_MOSI ((unsigned long)-1l)
/** /**
* struct spi_gpio_platform_data - parameter for bitbanged SPI master * struct spi_gpio_platform_data - parameter for bitbanged SPI master
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment