Merge remote-tracking branches 'spi/topic/delay', 'spi/topic/dw', 'spi/topic/fsl...
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / drivers / spi / spi.c
index 5787b723b593f79bb5e55f3b68abcb2f19d4b5cb..656dd3e3220c5062b43b5a162a078f245f90630c 100644 (file)
@@ -697,10 +697,15 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
        if (spi->mode & SPI_CS_HIGH)
                enable = !enable;
 
-       if (gpio_is_valid(spi->cs_gpio))
+       if (gpio_is_valid(spi->cs_gpio)) {
                gpio_set_value(spi->cs_gpio, !enable);
-       else if (spi->master->set_cs)
+               /* Some SPI masters need both GPIO CS & slave_select */
+               if ((spi->master->flags & SPI_MASTER_GPIO_SS) &&
+                   spi->master->set_cs)
+                       spi->master->set_cs(spi, !enable);
+       } else if (spi->master->set_cs) {
                spi->master->set_cs(spi, !enable);
+       }
 }
 
 #ifdef CONFIG_HAS_DMA
@@ -720,6 +725,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
        int desc_len;
        int sgs;
        struct page *vm_page;
+       struct scatterlist *sg;
        void *sg_buf;
        size_t min;
        int i, ret;
@@ -738,6 +744,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
        if (ret != 0)
                return ret;
 
+       sg = &sgt->sgl[0];
        for (i = 0; i < sgs; i++) {
 
                if (vmalloced_buf || kmap_buf) {
@@ -751,16 +758,17 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
                                sg_free_table(sgt);
                                return -ENOMEM;
                        }
-                       sg_set_page(&sgt->sgl[i], vm_page,
+                       sg_set_page(sg, vm_page,
                                    min, offset_in_page(buf));
                } else {
                        min = min_t(size_t, len, desc_len);
                        sg_buf = buf;
-                       sg_set_buf(&sgt->sgl[i], sg_buf, min);
+                       sg_set_buf(sg, sg_buf, min);
                }
 
                buf += min;
                len -= min;
+               sg = sg_next(sg);
        }
 
        ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
@@ -1034,8 +1042,14 @@ static int spi_transfer_one_message(struct spi_master *master,
                if (msg->status != -EINPROGRESS)
                        goto out;
 
-               if (xfer->delay_usecs)
-                       udelay(xfer->delay_usecs);
+               if (xfer->delay_usecs) {
+                       u16 us = xfer->delay_usecs;
+
+                       if (us <= 10)
+                               udelay(us);
+                       else
+                               usleep_range(us, us + DIV_ROUND_UP(us, 10));
+               }
 
                if (xfer->cs_change) {
                        if (list_is_last(&xfer->transfer_list,
@@ -1618,9 +1632,11 @@ static void of_register_spi_devices(struct spi_master *master)
                if (of_node_test_and_set_flag(nc, OF_POPULATED))
                        continue;
                spi = of_register_spi_device(master, nc);
-               if (IS_ERR(spi))
+               if (IS_ERR(spi)) {
                        dev_warn(&master->dev, "Failed to create SPI device for %s\n",
                                nc->full_name);
+                       of_node_clear_flag(nc, OF_POPULATED);
+               }
        }
 }
 #else
@@ -3131,6 +3147,7 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action,
                if (IS_ERR(spi)) {
                        pr_err("%s: failed to create for '%s'\n",
                                        __func__, rd->dn->full_name);
+                       of_node_clear_flag(rd->dn, OF_POPULATED);
                        return notifier_from_errno(PTR_ERR(spi));
                }
                break;