Merge remote-tracking branches 'spi/topic/cadence', 'spi/topic/dt', 'spi/topic/ep93xx...
[muen/linux.git] / drivers / spi / spi.c
index 4fcbb0aa71d361e4e5e50600a2d14a7722e22034..cf8ee5e48f73659cae5471157b288f9e88669f64 100644 (file)
 #include <linux/ioport.h>
 #include <linux/acpi.h>
 #include <linux/highmem.h>
+#include <linux/idr.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/spi.h>
+#define SPI_DYN_FIRST_BUS_NUM 0
+
+static DEFINE_IDR(spi_master_idr);
 
 static void spidev_release(struct device *dev)
 {
@@ -321,8 +325,7 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
        if (rc != -ENODEV)
                return rc;
 
-       add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias);
-       return 0;
+       return add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias);
 }
 
 struct bus_type spi_bus_type = {
@@ -421,6 +424,7 @@ static LIST_HEAD(spi_controller_list);
 /*
  * Used to protect add/del opertion for board_info list and
  * spi_controller list, and their matching process
+ * also used to protect object of type struct idr
  */
 static DEFINE_MUTEX(board_lock);
 
@@ -1533,15 +1537,15 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
        int rc;
 
        /* Mode (clock phase/polarity/etc.) */
-       if (of_find_property(nc, "spi-cpha", NULL))
+       if (of_property_read_bool(nc, "spi-cpha"))
                spi->mode |= SPI_CPHA;
-       if (of_find_property(nc, "spi-cpol", NULL))
+       if (of_property_read_bool(nc, "spi-cpol"))
                spi->mode |= SPI_CPOL;
-       if (of_find_property(nc, "spi-cs-high", NULL))
+       if (of_property_read_bool(nc, "spi-cs-high"))
                spi->mode |= SPI_CS_HIGH;
-       if (of_find_property(nc, "spi-3wire", NULL))
+       if (of_property_read_bool(nc, "spi-3wire"))
                spi->mode |= SPI_3WIRE;
-       if (of_find_property(nc, "spi-lsb-first", NULL))
+       if (of_property_read_bool(nc, "spi-lsb-first"))
                spi->mode |= SPI_LSB_FIRST;
 
        /* Device DUAL/QUAD mode */
@@ -1583,8 +1587,8 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
 
        if (spi_controller_is_slave(ctlr)) {
                if (strcmp(nc->name, "slave")) {
-                       dev_err(&ctlr->dev, "%s is not called 'slave'\n",
-                               nc->full_name);
+                       dev_err(&ctlr->dev, "%pOF is not called 'slave'\n",
+                               nc);
                        return -EINVAL;
                }
                return 0;
@@ -1593,8 +1597,8 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
        /* Device address */
        rc = of_property_read_u32(nc, "reg", &value);
        if (rc) {
-               dev_err(&ctlr->dev, "%s has no valid 'reg' property (%d)\n",
-                       nc->full_name, rc);
+               dev_err(&ctlr->dev, "%pOF has no valid 'reg' property (%d)\n",
+                       nc, rc);
                return rc;
        }
        spi->chip_select = value;
@@ -1603,8 +1607,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
        rc = of_property_read_u32(nc, "spi-max-frequency", &value);
        if (rc) {
                dev_err(&ctlr->dev,
-                       "%s has no valid 'spi-max-frequency' property (%d)\n",
-                       nc->full_name, rc);
+                       "%pOF has no valid 'spi-max-frequency' property (%d)\n", nc, rc);
                return rc;
        }
        spi->max_speed_hz = value;
@@ -1621,8 +1624,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
        /* Alloc an spi_device */
        spi = spi_alloc_device(ctlr);
        if (!spi) {
-               dev_err(&ctlr->dev, "spi_device alloc error for %s\n",
-                       nc->full_name);
+               dev_err(&ctlr->dev, "spi_device alloc error for %pOF\n", nc);
                rc = -ENOMEM;
                goto err_out;
        }
@@ -1631,8 +1633,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
        rc = of_modalias_node(nc, spi->modalias,
                                sizeof(spi->modalias));
        if (rc < 0) {
-               dev_err(&ctlr->dev, "cannot find modalias for %s\n",
-                       nc->full_name);
+               dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc);
                goto err_out;
        }
 
@@ -1647,8 +1648,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
        /* Register the new device */
        rc = spi_add_device(spi);
        if (rc) {
-               dev_err(&ctlr->dev, "spi_device register error %s\n",
-                       nc->full_name);
+               dev_err(&ctlr->dev, "spi_device register error %pOF\n", nc);
                goto err_of_node_put;
        }
 
@@ -1682,8 +1682,7 @@ static void of_register_spi_devices(struct spi_controller *ctlr)
                spi = of_register_spi_device(ctlr, nc);
                if (IS_ERR(spi)) {
                        dev_warn(&ctlr->dev,
-                                "Failed to create SPI device for %s\n",
-                                nc->full_name);
+                                "Failed to create SPI device for %pOF\n", nc);
                        of_node_clear_flag(nc, OF_POPULATED);
                }
        }
@@ -2052,11 +2051,10 @@ static int of_spi_register_master(struct spi_controller *ctlr)
  */
 int spi_register_controller(struct spi_controller *ctlr)
 {
-       static atomic_t         dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
        struct device           *dev = ctlr->dev.parent;
        struct boardinfo        *bi;
        int                     status = -ENODEV;
-       int                     dynamic = 0;
+       int                     id;
 
        if (!dev)
                return -ENODEV;
@@ -2072,19 +2070,28 @@ int spi_register_controller(struct spi_controller *ctlr)
         */
        if (ctlr->num_chipselect == 0)
                return -EINVAL;
-
-       if ((ctlr->bus_num < 0) && ctlr->dev.of_node)
-               ctlr->bus_num = of_alias_get_id(ctlr->dev.of_node, "spi");
-
-       /* convention:  dynamically assigned bus IDs count down from the max */
+       /* allocate dynamic bus number using Linux idr */
+       if ((ctlr->bus_num < 0) && ctlr->dev.of_node) {
+               id = of_alias_get_id(ctlr->dev.of_node, "spi");
+               if (id >= 0) {
+                       ctlr->bus_num = id;
+                       mutex_lock(&board_lock);
+                       id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
+                                      ctlr->bus_num + 1, GFP_KERNEL);
+                       mutex_unlock(&board_lock);
+                       if (WARN(id < 0, "couldn't get idr"))
+                               return id == -ENOSPC ? -EBUSY : id;
+               }
+       }
        if (ctlr->bus_num < 0) {
-               /* FIXME switch to an IDR based scheme, something like
-                * I2C now uses, so we can't run out of "dynamic" IDs
-                */
-               ctlr->bus_num = atomic_dec_return(&dyn_bus_id);
-               dynamic = 1;
+               mutex_lock(&board_lock);
+               id = idr_alloc(&spi_master_idr, ctlr, SPI_DYN_FIRST_BUS_NUM, 0,
+                              GFP_KERNEL);
+               mutex_unlock(&board_lock);
+               if (WARN(id < 0, "couldn't get idr"))
+                       return id;
+               ctlr->bus_num = id;
        }
-
        INIT_LIST_HEAD(&ctlr->queue);
        spin_lock_init(&ctlr->queue_lock);
        spin_lock_init(&ctlr->bus_lock_spinlock);
@@ -2100,11 +2107,16 @@ int spi_register_controller(struct spi_controller *ctlr)
         */
        dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num);
        status = device_add(&ctlr->dev);
-       if (status < 0)
+       if (status < 0) {
+               /* free bus id */
+               mutex_lock(&board_lock);
+               idr_remove(&spi_master_idr, ctlr->bus_num);
+               mutex_unlock(&board_lock);
                goto done;
-       dev_dbg(dev, "registered %s %s%s\n",
+       }
+       dev_dbg(dev, "registered %s %s\n",
                        spi_controller_is_slave(ctlr) ? "slave" : "master",
-                       dev_name(&ctlr->dev), dynamic ? " (dynamic)" : "");
+                       dev_name(&ctlr->dev));
 
        /* If we're using a queued driver, start the queue */
        if (ctlr->transfer)
@@ -2113,6 +2125,10 @@ int spi_register_controller(struct spi_controller *ctlr)
                status = spi_controller_initialize_queue(ctlr);
                if (status) {
                        device_del(&ctlr->dev);
+                       /* free bus id */
+                       mutex_lock(&board_lock);
+                       idr_remove(&spi_master_idr, ctlr->bus_num);
+                       mutex_unlock(&board_lock);
                        goto done;
                }
        }
@@ -2191,19 +2207,33 @@ static int __unregister(struct device *dev, void *null)
  */
 void spi_unregister_controller(struct spi_controller *ctlr)
 {
+       struct spi_controller *found;
        int dummy;
 
+       /* First make sure that this controller was ever added */
+       mutex_lock(&board_lock);
+       found = idr_find(&spi_master_idr, ctlr->bus_num);
+       mutex_unlock(&board_lock);
+       if (found != ctlr) {
+               dev_dbg(&ctlr->dev,
+                       "attempting to delete unregistered controller [%s]\n",
+                       dev_name(&ctlr->dev));
+               return;
+       }
        if (ctlr->queued) {
                if (spi_destroy_queue(ctlr))
                        dev_err(&ctlr->dev, "queue remove failed\n");
        }
-
        mutex_lock(&board_lock);
        list_del(&ctlr->list);
        mutex_unlock(&board_lock);
 
        dummy = device_for_each_child(&ctlr->dev, NULL, __unregister);
        device_unregister(&ctlr->dev);
+       /* free bus id */
+       mutex_lock(&board_lock);
+       idr_remove(&spi_master_idr, ctlr->bus_num);
+       mutex_unlock(&board_lock);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_controller);
 
@@ -3311,8 +3341,8 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action,
                put_device(&ctlr->dev);
 
                if (IS_ERR(spi)) {
-                       pr_err("%s: failed to create for '%s'\n",
-                                       __func__, rd->dn->full_name);
+                       pr_err("%s: failed to create for '%pOF'\n",
+                                       __func__, rd->dn);
                        of_node_clear_flag(rd->dn, OF_POPULATED);
                        return notifier_from_errno(PTR_ERR(spi));
                }