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:
@@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
#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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
|||||||
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 = {
|
|||||||
},
|
},
|
||||||
.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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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 @@ free_master:
|
|||||||
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)
|
|||||||
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,
|
|||||||
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);
|
|||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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);
|
|||||||
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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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 {
|
|||||||
#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)
|
|||||||
|
|
||||||
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);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
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 @@
|
|||||||
* 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
|
||||||
|
Reference in New Issue
Block a user