]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/spi/spi-davinci.c
Merge remote-tracking branches 'spi/topic/davinci', 'spi/topic/doc', 'spi/topic/dw...
[karo-tx-linux.git] / drivers / spi / spi-davinci.c
index 276a3884fb3c1d43c928b0b975b8d7aa67f6be58..63700ab7bd9ff6687d03d7f900f1ddbc98a69d27 100644 (file)
@@ -65,6 +65,7 @@
 
 /* SPIDAT1 (upper 16 bit defines) */
 #define SPIDAT1_CSHOLD_MASK    BIT(12)
+#define SPIDAT1_WDEL           BIT(10)
 
 /* SPIGCR1 */
 #define SPIGCR1_CLKMOD_MASK    BIT(1)
@@ -167,8 +168,10 @@ static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *dspi)
 static u32 davinci_spi_tx_buf_u8(struct davinci_spi *dspi)
 {
        u32 data = 0;
+
        if (dspi->tx) {
                const u8 *tx = dspi->tx;
+
                data = *tx++;
                dspi->tx = tx;
        }
@@ -178,8 +181,10 @@ static u32 davinci_spi_tx_buf_u8(struct davinci_spi *dspi)
 static u32 davinci_spi_tx_buf_u16(struct davinci_spi *dspi)
 {
        u32 data = 0;
+
        if (dspi->tx) {
                const u16 *tx = dspi->tx;
+
                data = *tx++;
                dspi->tx = tx;
        }
@@ -209,6 +214,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
 {
        struct davinci_spi *dspi;
        struct davinci_spi_platform_data *pdata;
+       struct davinci_spi_config *spicfg = spi->controller_data;
        u8 chip_sel = spi->chip_select;
        u16 spidat1 = CS_DEFAULT;
        bool gpio_chipsel = false;
@@ -223,6 +229,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
                gpio = spi->cs_gpio;
        }
 
+       /* program delay transfers if tx_delay is non zero */
+       if (spicfg->wdelay)
+               spidat1 |= SPIDAT1_WDEL;
+
        /*
         * Board specific chip select logic decides the polarity and cs
         * line for the controller
@@ -237,9 +247,9 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
                        spidat1 |= SPIDAT1_CSHOLD_MASK;
                        spidat1 &= ~(0x1 << chip_sel);
                }
-
-               iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
        }
+
+       iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
 }
 
 /**
@@ -285,7 +295,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
        int prescale;
 
        dspi = spi_master_get_devdata(spi->master);
-       spicfg = (struct davinci_spi_config *)spi->controller_data;
+       spicfg = spi->controller_data;
        if (!spicfg)
                spicfg = &davinci_spi_default_cfg;
 
@@ -332,6 +342,14 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
        if (!(spi->mode & SPI_CPHA))
                spifmt |= SPIFMT_PHASE_MASK;
 
+       /*
+       * Assume wdelay is used only on SPI peripherals that has this field
+       * in SPIFMTn register and when it's configured from board file or DT.
+       */
+       if (spicfg->wdelay)
+               spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
+                               & SPIFMT_WDELAY_MASK);
+
        /*
         * Version 1 hardware supports two basic SPI modes:
         *  - Standard SPI mode uses 4 pins, with chipselect
@@ -349,9 +367,6 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
 
                u32 delay = 0;
 
-               spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
-                                                       & SPIFMT_WDELAY_MASK);
-
                if (spicfg->odd_parity)
                        spifmt |= SPIFMT_ODD_PARITY_MASK;
 
@@ -383,6 +398,26 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
        return 0;
 }
 
+static int davinci_spi_of_setup(struct spi_device *spi)
+{
+       struct davinci_spi_config *spicfg = spi->controller_data;
+       struct device_node *np = spi->dev.of_node;
+       u32 prop;
+
+       if (spicfg == NULL && np) {
+               spicfg = kzalloc(sizeof(*spicfg), GFP_KERNEL);
+               if (!spicfg)
+                       return -ENOMEM;
+               *spicfg = davinci_spi_default_cfg;
+               /* override with dt configured values */
+               if (!of_property_read_u32(np, "ti,spi-wdelay", &prop))
+                       spicfg->wdelay = (u8)prop;
+               spi->controller_data = spicfg;
+       }
+
+       return 0;
+}
+
 /**
  * davinci_spi_setup - This functions will set default transfer method
  * @spi: spi device on which data transfer to be done
@@ -397,36 +432,33 @@ static int davinci_spi_setup(struct spi_device *spi)
        struct spi_master *master = spi->master;
        struct device_node *np = spi->dev.of_node;
        bool internal_cs = true;
-       unsigned long flags = GPIOF_DIR_OUT;
 
        dspi = spi_master_get_devdata(spi->master);
        pdata = &dspi->pdata;
 
-       flags |= (spi->mode & SPI_CS_HIGH) ? GPIOF_INIT_LOW : GPIOF_INIT_HIGH;
-
        if (!(spi->mode & SPI_NO_CS)) {
                if (np && (master->cs_gpios != NULL) && (spi->cs_gpio >= 0)) {
-                       retval = gpio_request_one(spi->cs_gpio,
-                                                 flags, dev_name(&spi->dev));
+                       retval = gpio_direction_output(
+                                     spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
                        internal_cs = false;
                } else if (pdata->chip_sel &&
                           spi->chip_select < pdata->num_chipselect &&
                           pdata->chip_sel[spi->chip_select] != SPI_INTERN_CS) {
                        spi->cs_gpio = pdata->chip_sel[spi->chip_select];
-                       retval = gpio_request_one(spi->cs_gpio,
-                                                 flags, dev_name(&spi->dev));
+                       retval = gpio_direction_output(
+                                     spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
                        internal_cs = false;
                }
-       }
 
-       if (retval) {
-               dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
-                       spi->cs_gpio, retval);
-               return retval;
-       }
+               if (retval) {
+                       dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
+                               spi->cs_gpio, retval);
+                       return retval;
+               }
 
-       if (internal_cs)
-               set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
+               if (internal_cs)
+                       set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
+       }
 
        if (spi->mode & SPI_READY)
                set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);
@@ -436,13 +468,16 @@ static int davinci_spi_setup(struct spi_device *spi)
        else
                clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
 
-       return retval;
+       return davinci_spi_of_setup(spi);
 }
 
 static void davinci_spi_cleanup(struct spi_device *spi)
 {
-       if (spi->cs_gpio >= 0)
-               gpio_free(spi->cs_gpio);
+       struct davinci_spi_config *spicfg = spi->controller_data;
+
+       spi->controller_data = NULL;
+       if (spi->dev.of_node)
+               kfree(spicfg);
 }
 
 static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
@@ -967,6 +1002,27 @@ static int davinci_spi_probe(struct platform_device *pdev)
        if (dspi->version == SPI_VERSION_2)
                dspi->bitbang.flags |= SPI_READY;
 
+       if (pdev->dev.of_node) {
+               int i;
+
+               for (i = 0; i < pdata->num_chipselect; i++) {
+                       int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
+                                                       "cs-gpios", i);
+
+                       if (cs_gpio == -EPROBE_DEFER) {
+                               ret = cs_gpio;
+                               goto free_clk;
+                       }
+
+                       if (gpio_is_valid(cs_gpio)) {
+                               ret = devm_gpio_request(&pdev->dev, cs_gpio,
+                                                       dev_name(&pdev->dev));
+                               if (ret)
+                                       goto free_clk;
+                       }
+               }
+       }
+
        r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
        if (r)
                dma_rx_chan = r->start;
@@ -985,8 +1041,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
                        goto free_clk;
 
                dev_info(&pdev->dev, "DMA: supported\n");
-               dev_info(&pdev->dev, "DMA: RX channel: %pa, TX channel: %pa, "
-                               "event queue: %d\n", &dma_rx_chan, &dma_tx_chan,
+               dev_info(&pdev->dev, "DMA: RX channel: %pa, TX channel: %pa, event queue: %d\n",
+                               &dma_rx_chan, &dma_tx_chan,
                                pdata->dma_event_q);
        }