Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 14 Aug 2010 18:54:09 +0000 (11:54 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 14 Aug 2010 18:54:09 +0000 (11:54 -0700)
* '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.

1  2 
drivers/mmc/host/mmc_spi.c
drivers/spi/mpc512x_psc_spi.c
drivers/spi/spi.c

index 1145ea0792e6b32f86973a92c5f15e9cc8ea2e83,dfc290dd43a3a1d035f68c81e05ac4127950963b..62a35822003ef5b0383c1c97ddaaaf05c1c7a479
@@@ -182,7 -182,7 +182,7 @@@ mmc_spi_readbytes(struct mmc_spi_host *
                                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 +541,7 @@@ mmc_spi_command_send(struct mmc_spi_hos
                                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 +685,7 @@@ mmc_spi_writeblock(struct mmc_spi_host 
                                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 +822,7 @@@ mmc_spi_readblock(struct mmc_spi_host *
                                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 +1018,7 @@@ mmc_spi_data_do(struct mmc_spi_host *ho
                                        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 +1084,9 @@@ static void mmc_spi_request(struct mmc_
        }
  #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) {
                        mmc_cs_off(host);
        }
  
+       /* release the bus */
+       spi_bus_unlock(host->spi->master);
        mmc_request_done(host->mmc, mrq);
  }
  
@@@ -1290,23 -1296,6 +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;
                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.
         *
@@@ -1533,21 -1496,12 +1496,21 @@@ static int __devexit mmc_spi_remove(str
        return 0;
  }
  
 +#if defined(CONFIG_OF)
 +static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
 +      { .compatible = "mmc-spi-slot", },
 +      {},
 +};
 +#endif
  
  static struct spi_driver mmc_spi_driver = {
        .driver = {
                .name =         "mmc_spi",
                .bus =          &spi_bus_type,
                .owner =        THIS_MODULE,
 +#if defined(CONFIG_OF)
 +              .of_match_table = mmc_spi_of_match_table,
 +#endif
        },
        .probe =        mmc_spi_probe,
        .remove =       __devexit_p(mmc_spi_remove),
index cddbfceb324f6ccbef716395ddbf2190e3538435,c8d69fc393abeeec82d4d98a6cf1b30f7008a8e5..77d9e7ee8b27b6502d39dcc1b08aaa827b8fd96b
@@@ -19,7 -19,6 +19,7 @@@
  #include <linux/init.h>
  #include <linux/errno.h>
  #include <linux/interrupt.h>
 +#include <linux/of_address.h>
  #include <linux/of_platform.h>
  #include <linux/workqueue.h>
  #include <linux/completion.h>
@@@ -406,9 -405,9 +406,9 @@@ static irqreturn_t mpc512x_psc_spi_isr(
  }
  
  /* 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;
        master->setup = mpc512x_psc_spi_setup;
        master->transfer = mpc512x_psc_spi_transfer;
        master->cleanup = mpc512x_psc_spi_cleanup;
 +      master->dev.of_node = dev->of_node;
  
        tempp = ioremap(regaddr, size);
        if (!tempp) {
@@@ -492,7 -490,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);
        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 of_device *op,
++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;
                                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 of_device *op)
++static int __devexit mpc512x_psc_spi_of_remove(struct platform_device *op)
  {
        return mpc512x_psc_spi_do_remove(&op->dev);
  }
@@@ -553,7 -551,7 +553,7 @@@ MODULE_DEVICE_TABLE(of, mpc512x_psc_spi
  
  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,
diff --combined drivers/spi/spi.c
index 1bb1b88780cefc4cd69e88e15d4e1f5413c55d1e,fdde7061ef586695891f956cfb929f5f5e08dfdd..a9e5c79ae52a04a43aebabeacfc2d3cc29e03e77
@@@ -26,7 -26,6 +26,7 @@@
  #include <linux/slab.h>
  #include <linux/mod_devicetable.h>
  #include <linux/spi/spi.h>
 +#include <linux/of_spi.h>
  
  
  /* SPI bustype and spi_master class are registered after board init code
@@@ -528,6 -527,10 +528,10 @@@ int spi_register_master(struct spi_mast
                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.
         */
        /* populate children from any spi device tables */
        scan_boardinfo(master);
        status = 0;
 +
 +      /* Register devices from the device tree */
 +      of_register_spi_devices(master);
  done:
        return status;
  }
@@@ -670,6 -670,35 +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
  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 -806,32 +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
   */
  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)