]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/spi/spi.c
Merge remote-tracking branches 'spi/topic/overlay', 'spi/topic/pxa2xx', 'spi/topic...
[linux.git] / drivers / spi / spi.c
index e2415be209d5a77e9224add30db37d65244fabda..2ae1588babd688d769a92cc3d05c16b9f146a4bf 100644 (file)
@@ -84,8 +84,7 @@ static ssize_t spi_device_##field##_show(struct device *dev,          \
                                         struct device_attribute *attr, \
                                        char *buf)                      \
 {                                                                      \
-       struct spi_device *spi = container_of(dev,                      \
-                                             struct spi_device, dev);  \
+       struct spi_device *spi = to_spi_device(dev);                    \
        return spi_statistics_##field##_show(&spi->statistics, buf);    \
 }                                                                      \
 static struct device_attribute dev_attr_spi_device_##field = {         \
@@ -376,6 +375,7 @@ static void spi_drv_shutdown(struct device *dev)
 
 /**
  * __spi_register_driver - register a SPI driver
+ * @owner: owner module of the driver to register
  * @sdrv: the driver to register
  * Context: can sleep
  *
@@ -604,6 +604,24 @@ struct spi_device *spi_new_device(struct spi_master *master,
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
+/**
+ * spi_unregister_device - unregister a single SPI device
+ * @spi: spi_device to unregister
+ *
+ * Start making the passed SPI device vanish. Normally this would be handled
+ * by spi_unregister_master().
+ */
+void spi_unregister_device(struct spi_device *spi)
+{
+       if (!spi)
+               return;
+
+       if (spi->dev.of_node)
+               of_node_clear_flag(spi->dev.of_node, OF_POPULATED);
+       device_unregister(&spi->dev);
+}
+EXPORT_SYMBOL_GPL(spi_unregister_device);
+
 static void spi_match_master_to_boardinfo(struct spi_master *master,
                                struct spi_board_info *bi)
 {
@@ -1547,6 +1565,8 @@ static void of_register_spi_devices(struct spi_master *master)
                return;
 
        for_each_available_child_of_node(master->dev.of_node, nc) {
+               if (of_node_test_and_set_flag(nc, OF_POPULATED))
+                       continue;
                spi = of_register_spi_device(master, nc);
                if (IS_ERR(spi))
                        dev_warn(&master->dev, "Failed to create SPI device for %s\n",
@@ -1704,7 +1724,7 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
        master->bus_num = -1;
        master->num_chipselect = 1;
        master->dev.class = &spi_master_class;
-       master->dev.parent = get_device(dev);
+       master->dev.parent = dev;
        spi_master_set_devdata(master, &master[1]);
 
        return master;
@@ -2130,6 +2150,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
         * Set transfer tx_nbits and rx_nbits as single transfer default
         * (SPI_NBITS_SINGLE) if it is not set for this transfer.
         */
+       message->frame_length = 0;
        list_for_each_entry(xfer, &message->transfers, transfer_list) {
                message->frame_length += xfer->len;
                if (!xfer->bits_per_word)
@@ -2631,6 +2652,11 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action,
                if (master == NULL)
                        return NOTIFY_OK;       /* not for us */
 
+               if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) {
+                       put_device(&master->dev);
+                       return NOTIFY_OK;
+               }
+
                spi = of_register_spi_device(master, rd->dn);
                put_device(&master->dev);
 
@@ -2642,6 +2668,10 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action,
                break;
 
        case OF_RECONFIG_CHANGE_REMOVE:
+               /* already depopulated? */
+               if (!of_node_check_flag(rd->dn, OF_POPULATED))
+                       return NOTIFY_OK;
+
                /* find our device by node */
                spi = of_find_spi_device_by_node(rd->dn);
                if (spi == NULL)