]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'spi/for-next'
authorThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:37:27 +0000 (14:37 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:37:27 +0000 (14:37 +0200)
Conflicts:
drivers/spi/spi.c

1  2 
Documentation/driver-model/devres.txt
drivers/spi/spi-fsl-cpm.c
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi.c

index 3d9c2a766230a5d7d24164675a4bee3b4e67dd67,84ea8216cc7d81be6c6f00138be852a1571e46b2..5bdc8cb5fc2855047004cf673d735fa23c561fb8
@@@ -283,7 -283,6 +283,7 @@@ REGULATO
    devm_regulator_get()
    devm_regulator_put()
    devm_regulator_bulk_get()
 +  devm_regulator_register()
  
  CLOCK
    devm_clk_get()
@@@ -303,3 -302,6 +303,6 @@@ PH
  
  SLAVE DMA ENGINE
    devm_acpi_dma_controller_register()
+ SPI
+   devm_spi_register_master()
index bd5aaf42719ce0d735e02d62dfe1372558becaa0,58630edb8c21663d3d8d51b22a9b4fede8e5d252..54b06376f03c9e34b3d5863ffa814263455d904c
@@@ -20,7 -20,6 +20,7 @@@
  #include <linux/spi/spi.h>
  #include <linux/fsl_devices.h>
  #include <linux/dma-mapping.h>
 +#include <linux/of_address.h>
  #include <asm/cpm.h>
  #include <asm/qe.h>
  
@@@ -300,7 -299,7 +300,7 @@@ int fsl_spi_cpm_init(struct mpc8xxx_sp
  
                switch (mspi->subblock) {
                default:
-                       dev_warn(dev, "cell-index unspecified, assuming SPI1");
+                       dev_warn(dev, "cell-index unspecified, assuming SPI1\n");
                        /* fall through */
                case 0:
                        mspi->subblock = QE_CR_SUBBLOCK_SPI1;
index c1c936cf0ed4ec28f3f9ff7322805ebd6da6617b,43222d7532d16b66ff790d48e7b5eb85231a1051..aa40296f7d96c16101ae68c87e47e4fb2763fb45
@@@ -16,8 -16,6 +16,8 @@@
  #include <linux/fsl_devices.h>
  #include <linux/mm.h>
  #include <linux/of.h>
 +#include <linux/of_address.h>
 +#include <linux/of_irq.h>
  #include <linux/of_platform.h>
  #include <linux/interrupt.h>
  #include <linux/err.h>
@@@ -291,8 -289,8 +291,8 @@@ static void fsl_espi_do_trans(struct sp
                if ((first->bits_per_word != t->bits_per_word) ||
                        (first->speed_hz != t->speed_hz)) {
                        espi_trans->status = -EINVAL;
-                       dev_err(mspi->dev, "bits_per_word/speed_hz should be"
-                                       " same for the same SPI transfer\n");
+                       dev_err(mspi->dev,
+                               "bits_per_word/speed_hz should be same for the same SPI transfer\n");
                        return;
                }
  
index 8dcc1432f1f51fba2505bad2c6d5ab6690182faf,ee6e61cbf7f514caa5c5ebb212e0811426e8b408..58d5ee0e4443e24442cb4cbeb51b2e80ac637d3b
@@@ -20,7 -20,6 +20,7 @@@
  #include <linux/errno.h>
  #include <linux/interrupt.h>
  #include <linux/of_address.h>
 +#include <linux/of_irq.h>
  #include <linux/of_platform.h>
  #include <linux/completion.h>
  #include <linux/io.h>
@@@ -537,7 -536,7 +537,7 @@@ static int mpc512x_psc_spi_do_probe(str
        if (ret < 0)
                goto free_clock;
  
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(dev, master);
        if (ret < 0)
                goto free_clock;
  
@@@ -560,12 -559,10 +560,10 @@@ static int mpc512x_psc_spi_do_remove(st
        struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
  
-       spi_unregister_master(master);
        clk_disable_unprepare(mps->clk_mclk);
        free_irq(mps->irq, mps);
        if (mps->psc)
                iounmap(mps->psc);
-       spi_master_put(master);
  
        return 0;
  }
diff --combined drivers/spi/spi.c
index 740f9ddda227d55f15042e1e7a8d2cadb58aae71,8d05accf706c00fe3e0a156c8d3bde86ce47fcde..927998aa5e71e711177a3adbf7cfe94ed020a85b
@@@ -39,6 -39,9 +39,9 @@@
  #include <linux/ioport.h>
  #include <linux/acpi.h>
  
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/spi.h>
  static void spidev_release(struct device *dev)
  {
        struct spi_device       *spi = to_spi_device(dev);
@@@ -58,11 -61,13 +61,13 @@@ modalias_show(struct device *dev, struc
  
        return sprintf(buf, "%s%s\n", SPI_MODULE_PREFIX, spi->modalias);
  }
+ static DEVICE_ATTR_RO(modalias);
  
- static struct device_attribute spi_dev_attrs[] = {
-       __ATTR_RO(modalias),
-       __ATTR_NULL,
+ static struct attribute *spi_dev_attrs[] = {
+       &dev_attr_modalias.attr,
+       NULL,
  };
+ ATTRIBUTE_GROUPS(spi_dev);
  
  /* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
   * and the sysfs version makes coldplug work too.
@@@ -229,7 -234,7 +234,7 @@@ static const struct dev_pm_ops spi_pm 
  
  struct bus_type spi_bus_type = {
        .name           = "spi",
-       .dev_attrs      = spi_dev_attrs,
+       .dev_groups     = spi_dev_groups,
        .match          = spi_match_device,
        .uevent         = spi_uevent,
        .pm             = &spi_pm,
@@@ -240,27 -245,15 +245,27 @@@ EXPORT_SYMBOL_GPL(spi_bus_type)
  static int spi_drv_probe(struct device *dev)
  {
        const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
 +      struct spi_device               *spi = to_spi_device(dev);
 +      int ret;
 +
 +      acpi_dev_pm_attach(&spi->dev, true);
 +      ret = sdrv->probe(spi);
 +      if (ret)
 +              acpi_dev_pm_detach(&spi->dev, true);
  
 -      return sdrv->probe(to_spi_device(dev));
 +      return ret;
  }
  
  static int spi_drv_remove(struct device *dev)
  {
        const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
 +      struct spi_device               *spi = to_spi_device(dev);
 +      int ret;
 +
 +      ret = sdrv->remove(spi);
 +      acpi_dev_pm_detach(&spi->dev, true);
  
 -      return sdrv->remove(to_spi_device(dev));
 +      return ret;
  }
  
  static void spi_drv_shutdown(struct device *dev)
@@@ -335,7 -328,7 +340,7 @@@ struct spi_device *spi_alloc_device(str
        if (!spi_master_get(master))
                return NULL;
  
-       spi = kzalloc(sizeof *spi, GFP_KERNEL);
+       spi = kzalloc(sizeof(*spi), GFP_KERNEL);
        if (!spi) {
                dev_err(dev, "cannot alloc spi_device\n");
                spi_master_put(master);
@@@ -535,6 -528,95 +540,95 @@@ int spi_register_board_info(struct spi_
  
  /*-------------------------------------------------------------------------*/
  
+ static void spi_set_cs(struct spi_device *spi, bool enable)
+ {
+       if (spi->mode & SPI_CS_HIGH)
+               enable = !enable;
+       if (spi->cs_gpio >= 0)
+               gpio_set_value(spi->cs_gpio, !enable);
+       else if (spi->master->set_cs)
+               spi->master->set_cs(spi, !enable);
+ }
+ /*
+  * spi_transfer_one_message - Default implementation of transfer_one_message()
+  *
+  * This is a standard implementation of transfer_one_message() for
+  * drivers which impelment a transfer_one() operation.  It provides
+  * standard handling of delays and chip select management.
+  */
+ static int spi_transfer_one_message(struct spi_master *master,
+                                   struct spi_message *msg)
+ {
+       struct spi_transfer *xfer;
+       bool cur_cs = true;
+       bool keep_cs = false;
+       int ret = 0;
+       spi_set_cs(msg->spi, true);
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               trace_spi_transfer_start(msg, xfer);
+               INIT_COMPLETION(master->xfer_completion);
+               ret = master->transfer_one(master, msg->spi, xfer);
+               if (ret < 0) {
+                       dev_err(&msg->spi->dev,
+                               "SPI transfer failed: %d\n", ret);
+                       goto out;
+               }
+               if (ret > 0)
+                       wait_for_completion(&master->xfer_completion);
+               trace_spi_transfer_stop(msg, xfer);
+               if (msg->status != -EINPROGRESS)
+                       goto out;
+               if (xfer->delay_usecs)
+                       udelay(xfer->delay_usecs);
+               if (xfer->cs_change) {
+                       if (list_is_last(&xfer->transfer_list,
+                                        &msg->transfers)) {
+                               keep_cs = true;
+                       } else {
+                               cur_cs = !cur_cs;
+                               spi_set_cs(msg->spi, cur_cs);
+                       }
+               }
+               msg->actual_length += xfer->len;
+       }
+ out:
+       if (ret != 0 || !keep_cs)
+               spi_set_cs(msg->spi, false);
+       if (msg->status == -EINPROGRESS)
+               msg->status = ret;
+       spi_finalize_current_message(master);
+       return ret;
+ }
+ /**
+  * spi_finalize_current_transfer - report completion of a transfer
+  *
+  * Called by SPI drivers using the core transfer_one_message()
+  * implementation to notify it that the current interrupt driven
+  * transfer has finised and the next one may be scheduled.
+  */
+ void spi_finalize_current_transfer(struct spi_master *master)
+ {
+       complete(&master->xfer_completion);
+ }
+ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
  /**
   * spi_pump_messages - kthread work function which processes spi message queue
   * @work: pointer to kthread work struct contained in the master struct
@@@ -569,6 -651,7 +663,7 @@@ static void spi_pump_messages(struct kt
                        pm_runtime_mark_last_busy(master->dev.parent);
                        pm_runtime_put_autosuspend(master->dev.parent);
                }
+               trace_spi_master_idle(master);
                return;
        }
  
                }
        }
  
+       if (!was_busy)
+               trace_spi_master_busy(master);
        if (!was_busy && master->prepare_transfer_hardware) {
                ret = master->prepare_transfer_hardware(master);
                if (ret) {
                }
        }
  
+       trace_spi_message_start(master->cur_msg);
+       if (master->prepare_message) {
+               ret = master->prepare_message(master, master->cur_msg);
+               if (ret) {
+                       dev_err(&master->dev,
+                               "failed to prepare message: %d\n", ret);
+                       master->cur_msg->status = ret;
+                       spi_finalize_current_message(master);
+                       return;
+               }
+               master->cur_msg_prepared = true;
+       }
        ret = master->transfer_one_message(master, master->cur_msg);
        if (ret) {
                dev_err(&master->dev,
@@@ -690,6 -790,7 +802,7 @@@ void spi_finalize_current_message(struc
  {
        struct spi_message *mesg;
        unsigned long flags;
+       int ret;
  
        spin_lock_irqsave(&master->queue_lock, flags);
        mesg = master->cur_msg;
        queue_kthread_work(&master->kworker, &master->pump_messages);
        spin_unlock_irqrestore(&master->queue_lock, flags);
  
+       if (master->cur_msg_prepared && master->unprepare_message) {
+               ret = master->unprepare_message(master, mesg);
+               if (ret) {
+                       dev_err(&master->dev,
+                               "failed to unprepare message: %d\n", ret);
+               }
+       }
+       master->cur_msg_prepared = false;
        mesg->state = NULL;
        if (mesg->complete)
                mesg->complete(mesg->context);
+       trace_spi_message_done(mesg);
  }
  EXPORT_SYMBOL_GPL(spi_finalize_current_message);
  
@@@ -815,6 -927,8 +939,8 @@@ static int spi_master_initialize_queue(
  
        master->queued = true;
        master->transfer = spi_queued_transfer;
+       if (!master->transfer_one_message)
+               master->transfer_one_message = spi_transfer_one_message;
  
        /* Initialize and start queue */
        ret = spi_init_queue(master);
@@@ -850,10 -964,8 +976,8 @@@ static void of_register_spi_devices(str
  {
        struct spi_device *spi;
        struct device_node *nc;
-       const __be32 *prop;
-       char modalias[SPI_NAME_SIZE + 4];
        int rc;
-       int len;
+       u32 value;
  
        if (!master->dev.of_node)
                return;
                }
  
                /* Device address */
-               prop = of_get_property(nc, "reg", &len);
-               if (!prop || len < sizeof(*prop)) {
-                       dev_err(&master->dev, "%s has no 'reg' property\n",
-                               nc->full_name);
+               rc = of_property_read_u32(nc, "reg", &value);
+               if (rc) {
+                       dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
+                               nc->full_name, rc);
                        spi_dev_put(spi);
                        continue;
                }
-               spi->chip_select = be32_to_cpup(prop);
+               spi->chip_select = value;
  
                /* Mode (clock phase/polarity/etc.) */
                if (of_find_property(nc, "spi-cpha", NULL))
                        spi->mode |= SPI_3WIRE;
  
                /* Device DUAL/QUAD mode */
-               prop = of_get_property(nc, "spi-tx-bus-width", &len);
-               if (prop && len == sizeof(*prop)) {
-                       switch (be32_to_cpup(prop)) {
-                       case SPI_NBITS_SINGLE:
+               if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
+                       switch (value) {
+                       case 1:
                                break;
-                       case SPI_NBITS_DUAL:
+                       case 2:
                                spi->mode |= SPI_TX_DUAL;
                                break;
-                       case SPI_NBITS_QUAD:
+                       case 4:
                                spi->mode |= SPI_TX_QUAD;
                                break;
                        default:
                                dev_err(&master->dev,
                                        "spi-tx-bus-width %d not supported\n",
-                                       be32_to_cpup(prop));
+                                       value);
                                spi_dev_put(spi);
                                continue;
                        }
                }
  
-               prop = of_get_property(nc, "spi-rx-bus-width", &len);
-               if (prop && len == sizeof(*prop)) {
-                       switch (be32_to_cpup(prop)) {
-                       case SPI_NBITS_SINGLE:
+               if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) {
+                       switch (value) {
+                       case 1:
                                break;
-                       case SPI_NBITS_DUAL:
+                       case 2:
                                spi->mode |= SPI_RX_DUAL;
                                break;
-                       case SPI_NBITS_QUAD:
+                       case 4:
                                spi->mode |= SPI_RX_QUAD;
                                break;
                        default:
                                dev_err(&master->dev,
                                        "spi-rx-bus-width %d not supported\n",
-                                       be32_to_cpup(prop));
+                                       value);
                                spi_dev_put(spi);
                                continue;
                        }
                }
  
                /* Device speed */
-               prop = of_get_property(nc, "spi-max-frequency", &len);
-               if (!prop || len < sizeof(*prop)) {
-                       dev_err(&master->dev, "%s has no 'spi-max-frequency' property\n",
-                               nc->full_name);
+               rc = of_property_read_u32(nc, "spi-max-frequency", &value);
+               if (rc) {
+                       dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n",
+                               nc->full_name, rc);
                        spi_dev_put(spi);
                        continue;
                }
-               spi->max_speed_hz = be32_to_cpup(prop);
+               spi->max_speed_hz = value;
  
                /* IRQ */
                spi->irq = irq_of_parse_and_map(nc, 0);
                spi->dev.of_node = nc;
  
                /* Register the new device */
-               snprintf(modalias, sizeof(modalias), "%s%s", SPI_MODULE_PREFIX,
-                        spi->modalias);
-               request_module(modalias);
+               request_module("%s%s", SPI_MODULE_PREFIX, spi->modalias);
                rc = spi_add_device(spi);
                if (rc) {
                        dev_err(&master->dev, "spi_device register error %s\n",
@@@ -1037,10 -1145,8 +1157,10 @@@ static acpi_status acpi_spi_add_device(
                return AE_OK;
        }
  
-       strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias));
 +      adev->power.flags.ignore_parent = true;
+       strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias));
        if (spi_add_device(spi)) {
 +              adev->power.flags.ignore_parent = false;
                dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
                        dev_name(&adev->dev));
                spi_dev_put(spi);
@@@ -1111,7 -1217,7 +1231,7 @@@ struct spi_master *spi_alloc_master(str
        if (!dev)
                return NULL;
  
-       master = kzalloc(size + sizeof *master, GFP_KERNEL);
+       master = kzalloc(size + sizeof(*master), GFP_KERNEL);
        if (!master)
                return NULL;
  
@@@ -1136,7 -1242,7 +1256,7 @@@ static int of_spi_register_master(struc
                return 0;
  
        nb = of_gpio_named_count(np, "cs-gpios");
-       master->num_chipselect = max(nb, (int)master->num_chipselect);
+       master->num_chipselect = max_t(int, nb, master->num_chipselect);
  
        /* Return error only for an incorrectly formed cs-gpios property */
        if (nb == 0 || nb == -ENOENT)
@@@ -1223,6 -1329,7 +1343,7 @@@ int spi_register_master(struct spi_mast
        spin_lock_init(&master->bus_lock_spinlock);
        mutex_init(&master->bus_lock_mutex);
        master->bus_lock_flag = 0;
+       init_completion(&master->xfer_completion);
  
        /* register the device, then userspace will see it.
         * registration fails if the bus ID is in use.
@@@ -1259,6 -1366,41 +1380,41 @@@ done
  }
  EXPORT_SYMBOL_GPL(spi_register_master);
  
+ static void devm_spi_unregister(struct device *dev, void *res)
+ {
+       spi_unregister_master(*(struct spi_master **)res);
+ }
+ /**
+  * dev_spi_register_master - register managed SPI master controller
+  * @dev:    device managing SPI master
+  * @master: initialized master, originally from spi_alloc_master()
+  * Context: can sleep
+  *
+  * Register a SPI device as with spi_register_master() which will
+  * automatically be unregister
+  */
+ int devm_spi_register_master(struct device *dev, struct spi_master *master)
+ {
+       struct spi_master **ptr;
+       int ret;
+       ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+       ret = spi_register_master(master);
+       if (ret != 0) {
+               *ptr = master;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(devm_spi_register_master);
  static int __unregister(struct device *dev, void *null)
  {
        spi_unregister_device(to_spi_device(dev));
@@@ -1416,8 -1558,7 +1572,7 @@@ int spi_setup(struct spi_device *spi
        if (spi->master->setup)
                status = spi->master->setup(spi);
  
-       dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s"
-                               "%u bits/w, %u Hz max --> %d\n",
+       dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n",
                        (int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
                        (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
                        (spi->mode & SPI_LSB_FIRST) ? "lsb, " : "",
@@@ -1435,6 -1576,10 +1590,10 @@@ static int __spi_async(struct spi_devic
        struct spi_master *master = spi->master;
        struct spi_transfer *xfer;
  
+       message->spi = spi;
+       trace_spi_message_submit(message);
        if (list_empty(&message->transfers))
                return -EINVAL;
        if (!message->complete)
                }
        }
  
-       message->spi = spi;
        message->status = -EINPROGRESS;
        return master->transfer(spi, message);
  }
@@@ -1776,7 -1920,7 +1934,7 @@@ int spi_bus_unlock(struct spi_master *m
  EXPORT_SYMBOL_GPL(spi_bus_unlock);
  
  /* 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)
  
  static u8     *buf;
  
@@@ -1825,7 -1969,7 +1983,7 @@@ int spi_write_then_read(struct spi_devi
        }
  
        spi_message_init(&message);
-       memset(x, 0, sizeof x);
+       memset(x, 0, sizeof(x));
        if (n_tx) {
                x[0].len = n_tx;
                spi_message_add_tail(&x[0], &message);