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.
This commit is contained in:
Коммит
b171aa2770
|
@ -182,7 +182,7 @@ mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len)
|
|||
host->data_dma, sizeof(*host->data),
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
status = spi_sync(host->spi, &host->readback);
|
||||
status = spi_sync_locked(host->spi, &host->readback);
|
||||
|
||||
if (host->dma_dev)
|
||||
dma_sync_single_for_cpu(host->dma_dev,
|
||||
|
@ -541,7 +541,7 @@ mmc_spi_command_send(struct mmc_spi_host *host,
|
|||
host->data_dma, sizeof(*host->data),
|
||||
DMA_BIDIRECTIONAL);
|
||||
}
|
||||
status = spi_sync(host->spi, &host->m);
|
||||
status = spi_sync_locked(host->spi, &host->m);
|
||||
|
||||
if (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,
|
|||
host->data_dma, sizeof(*scratch),
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
status = spi_sync(spi, &host->m);
|
||||
status = spi_sync_locked(spi, &host->m);
|
||||
|
||||
if (status != 0) {
|
||||
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,
|
|||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
status = spi_sync(spi, &host->m);
|
||||
status = spi_sync_locked(spi, &host->m);
|
||||
|
||||
if (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,
|
|||
host->data_dma, sizeof(*scratch),
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
tmp = spi_sync(spi, &host->m);
|
||||
tmp = spi_sync_locked(spi, &host->m);
|
||||
|
||||
if (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)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* request exclusive bus access */
|
||||
spi_bus_lock(host->spi->master);
|
||||
|
||||
/* issue command; then optionally data and stop */
|
||||
status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL);
|
||||
if (status == 0 && mrq->data) {
|
||||
|
@ -1094,6 +1097,9 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
|||
mmc_cs_off(host);
|
||||
}
|
||||
|
||||
/* release the bus */
|
||||
spi_bus_unlock(host->spi->master);
|
||||
|
||||
mmc_request_done(host->mmc, mrq);
|
||||
}
|
||||
|
||||
|
@ -1290,23 +1296,6 @@ mmc_spi_detect_irq(int irq, void *mmc)
|
|||
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)
|
||||
{
|
||||
void *ones;
|
||||
|
@ -1338,32 +1327,6 @@ static int mmc_spi_probe(struct spi_device *spi)
|
|||
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
|
||||
* the CPU touches these, so cache coherency isn't a concern.
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
struct device *dev = &adev->dev;
|
||||
|
@ -1838,7 +1838,7 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
|
|||
return status;
|
||||
}
|
||||
|
||||
static int __exit
|
||||
static int __devexit
|
||||
pl022_remove(struct amba_device *adev)
|
||||
{
|
||||
struct pl022 *pl022 = amba_get_drvdata(adev);
|
||||
|
@ -1970,7 +1970,7 @@ static struct amba_driver pl022_driver = {
|
|||
},
|
||||
.id_table = pl022_ids,
|
||||
.probe = pl022_probe,
|
||||
.remove = __exit_p(pl022_remove),
|
||||
.remove = __devexit_p(pl022_remove),
|
||||
.suspend = pl022_suspend,
|
||||
.resume = pl022_resume,
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
static int __init mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
|
||||
u32 size, unsigned int irq,
|
||||
s16 bus_num)
|
||||
static int __devinit mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
|
||||
u32 size, unsigned int irq,
|
||||
s16 bus_num)
|
||||
{
|
||||
struct fsl_spi_platform_data *pdata = dev->platform_data;
|
||||
struct mpc512x_psc_spi *mps;
|
||||
|
@ -492,7 +492,7 @@ free_master:
|
|||
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 mpc512x_psc_spi *mps = spi_master_get_devdata(master);
|
||||
|
@ -507,8 +507,8 @@ static int __exit mpc512x_psc_spi_do_remove(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init mpc512x_psc_spi_of_probe(struct platform_device *op,
|
||||
const struct of_device_id *match)
|
||||
static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
const u32 *regaddr_p;
|
||||
u64 regaddr64, size64;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -553,7 +553,7 @@ MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
|
|||
|
||||
static struct of_platform_driver mpc512x_psc_spi_of_driver = {
|
||||
.probe = mpc512x_psc_spi_of_probe,
|
||||
.remove = __exit_p(mpc512x_psc_spi_of_remove),
|
||||
.remove = __devexit_p(mpc512x_psc_spi_of_remove),
|
||||
.driver = {
|
||||
.name = "mpc512x-psc-spi",
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
@ -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);
|
||||
|
||||
/* 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);
|
||||
writew( data , spi100k->base + SPI_TX_MSB);
|
||||
|
||||
|
@ -162,6 +167,10 @@ static int spi100k_read_data(struct spi_master *master, int len)
|
|||
int dataH,dataL;
|
||||
struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
|
||||
|
||||
/* Always do at least 16 bits */
|
||||
if (len <= 8)
|
||||
len = 16;
|
||||
|
||||
spi100k_enable_clock(master);
|
||||
writew(SPI_CTRL_SEN(0) |
|
||||
SPI_CTRL_WORD_SIZE(len) |
|
||||
|
@ -214,10 +223,6 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
|||
c = count;
|
||||
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) {
|
||||
u8 *rx;
|
||||
const u8 *tx;
|
||||
|
@ -227,9 +232,9 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
|||
do {
|
||||
c-=1;
|
||||
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)
|
||||
*rx = spi100k_read_data(spi->master,word_len);
|
||||
*rx++ = spi100k_read_data(spi->master, word_len);
|
||||
} while(c);
|
||||
} else if (word_len <= 16) {
|
||||
u16 *rx;
|
||||
|
@ -380,10 +385,6 @@ static void omap1_spi100k_work(struct work_struct *work)
|
|||
if (t->len) {
|
||||
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);
|
||||
m->actual_length += count;
|
||||
|
||||
|
|
|
@ -528,6 +528,10 @@ int spi_register_master(struct spi_master *master)
|
|||
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.
|
||||
* registration fails if the bus ID is in use.
|
||||
*/
|
||||
|
@ -670,6 +674,35 @@ int spi_setup(struct spi_device *spi)
|
|||
}
|
||||
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: device with which data will be exchanged
|
||||
|
@ -702,33 +735,68 @@ EXPORT_SYMBOL_GPL(spi_setup);
|
|||
int spi_async(struct spi_device *spi, struct spi_message *message)
|
||||
{
|
||||
struct spi_master *master = spi->master;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
/* 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;
|
||||
spin_lock_irqsave(&master->bus_lock_spinlock, 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;
|
||||
}
|
||||
}
|
||||
if (master->bus_lock_flag)
|
||||
ret = -EBUSY;
|
||||
else
|
||||
ret = __spi_async(spi, message);
|
||||
|
||||
message->spi = spi;
|
||||
message->status = -EINPROGRESS;
|
||||
return master->transfer(spi, message);
|
||||
spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
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)
|
|||
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: device with which data will be exchanged
|
||||
|
@ -765,21 +859,86 @@ static void spi_complete(void *arg)
|
|||
*/
|
||||
int spi_sync(struct spi_device *spi, struct spi_message *message)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(done);
|
||||
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;
|
||||
return __spi_sync(spi, message, 0);
|
||||
}
|
||||
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 */
|
||||
#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
|
||||
|
||||
|
|
|
@ -259,7 +259,6 @@ static void bitbang_work(struct work_struct *work)
|
|||
struct spi_bitbang *bitbang =
|
||||
container_of(work, struct spi_bitbang, work);
|
||||
unsigned long flags;
|
||||
int do_setup = -1;
|
||||
int (*setup_transfer)(struct spi_device *,
|
||||
struct spi_transfer *);
|
||||
|
||||
|
@ -275,6 +274,7 @@ static void bitbang_work(struct work_struct *work)
|
|||
unsigned tmp;
|
||||
unsigned cs_change;
|
||||
int status;
|
||||
int do_setup = -1;
|
||||
|
||||
m = container_of(bitbang->queue.next, struct spi_message,
|
||||
queue);
|
||||
|
@ -307,6 +307,8 @@ static void bitbang_work(struct work_struct *work)
|
|||
status = setup_transfer(spi, t);
|
||||
if (status < 0)
|
||||
break;
|
||||
if (do_setup == -1)
|
||||
do_setup = 0;
|
||||
}
|
||||
|
||||
/* set up default clock polarity, and activate chip;
|
||||
|
@ -367,11 +369,6 @@ static void bitbang_work(struct work_struct *work)
|
|||
m->status = status;
|
||||
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
|
||||
* cs_change has hinted that the next message will probably
|
||||
* be for this chip too.
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
static inline u32
|
||||
bitbang_txrx_be_cpha0(struct spi_device *spi,
|
||||
unsigned nsecs, unsigned cpol,
|
||||
unsigned nsecs, unsigned cpol, unsigned flags,
|
||||
u32 word, u8 bits)
|
||||
{
|
||||
/* 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,
|
|||
for (word <<= (32 - bits); likely(bits); bits--) {
|
||||
|
||||
/* 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) */
|
||||
|
||||
setsck(spi, !cpol);
|
||||
|
@ -61,7 +62,8 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
|
|||
|
||||
/* sample MSB (from slave) on leading edge */
|
||||
word <<= 1;
|
||||
word |= getmiso(spi);
|
||||
if ((flags & SPI_MASTER_NO_RX) == 0)
|
||||
word |= getmiso(spi);
|
||||
setsck(spi, cpol);
|
||||
}
|
||||
return word;
|
||||
|
@ -69,7 +71,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
|
|||
|
||||
static inline u32
|
||||
bitbang_txrx_be_cpha1(struct spi_device *spi,
|
||||
unsigned nsecs, unsigned cpol,
|
||||
unsigned nsecs, unsigned cpol, unsigned flags,
|
||||
u32 word, u8 bits)
|
||||
{
|
||||
/* 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,
|
|||
|
||||
/* setup MSB (to slave) on leading edge */
|
||||
setsck(spi, !cpol);
|
||||
setmosi(spi, word & (1 << 31));
|
||||
if ((flags & SPI_MASTER_NO_TX) == 0)
|
||||
setmosi(spi, word & (1 << 31));
|
||||
spidelay(nsecs); /* T(setup) */
|
||||
|
||||
setsck(spi, cpol);
|
||||
|
@ -87,7 +90,8 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
|
|||
|
||||
/* sample MSB (from slave) on trailing edge */
|
||||
word <<= 1;
|
||||
word |= getmiso(spi);
|
||||
if ((flags & SPI_MASTER_NO_RX) == 0)
|
||||
word |= getmiso(spi);
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ butterfly_txrx_word_mode0(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);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
|
@ -146,25 +146,63 @@ static inline int getmiso(const struct spi_device *spi)
|
|||
static u32 spi_gpio_txrx_word_mode0(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 u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
|
||||
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,
|
||||
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,
|
||||
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)
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
/* NOTE: SPI_*_GPIO symbols may reference "pdata" */
|
||||
|
||||
value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
|
||||
if (value)
|
||||
goto done;
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
|
||||
value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
|
||||
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 (value)
|
||||
goto free_mosi;
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
|
||||
value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
|
||||
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);
|
||||
if (value)
|
||||
|
@ -253,9 +302,11 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label)
|
|||
goto done;
|
||||
|
||||
free_miso:
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
free_mosi:
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
done:
|
||||
return value;
|
||||
}
|
||||
|
@ -266,6 +317,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
|
|||
struct spi_master *master;
|
||||
struct spi_gpio *spi_gpio;
|
||||
struct spi_gpio_platform_data *pdata;
|
||||
u16 master_flags = 0;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
#ifdef GENERIC_BITBANG
|
||||
|
@ -273,7 +325,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
#endif
|
||||
|
||||
status = spi_gpio_request(pdata, dev_name(&pdev->dev));
|
||||
status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
|
@ -289,6 +341,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
|
|||
if (pdata)
|
||||
spi_gpio->pdata = *pdata;
|
||||
|
||||
master->flags = master_flags;
|
||||
master->bus_num = pdev->id;
|
||||
master->num_chipselect = SPI_N_CHIPSEL;
|
||||
master->setup = spi_gpio_setup;
|
||||
|
@ -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.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;
|
||||
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;
|
||||
|
||||
if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) {
|
||||
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;
|
||||
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.flags = SPI_CS_HIGH;
|
||||
|
||||
|
@ -307,8 +368,10 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
|
|||
if (status < 0) {
|
||||
spi_master_put(spi_gpio->bitbang.master);
|
||||
gpio_free:
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
gpio_free(SPI_SCK_GPIO);
|
||||
spi_master_put(master);
|
||||
}
|
||||
|
@ -331,8 +394,10 @@ static int __exit spi_gpio_remove(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
gpio_free(SPI_SCK_GPIO);
|
||||
|
||||
return status;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -64,25 +64,25 @@ static inline u32 getmiso(struct spi_device *dev)
|
|||
static u32 s3c2410_spigpio_txrx_mode0(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 u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi,
|
||||
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,
|
||||
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,
|
||||
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)
|
|||
static u32 sh_sci_spi_txrx_mode0(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 u32 sh_sci_spi_txrx_mode1(struct spi_device *spi,
|
||||
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,
|
||||
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,
|
||||
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)
|
||||
|
|
|
@ -262,6 +262,13 @@ struct spi_master {
|
|||
#define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */
|
||||
#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).
|
||||
*
|
||||
* IMPORTANT: this may be called when transfers to another
|
||||
|
@ -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_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);
|
|||
*/
|
||||
|
||||
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
|
||||
|
|
|
@ -29,11 +29,16 @@
|
|||
* SPI_GPIO_NO_CHIPSELECT to the controller_data:
|
||||
* .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,
|
||||
* that platform_device and controller_data should be removed.
|
||||
*/
|
||||
|
||||
#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
|
||||
|
|
Загрузка…
Ссылка в новой задаче