From 6dc81f6fc0eaf0714bc6e959f8769705f41fd708 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 13 May 2013 13:45:09 +0300 Subject: [PATCH 01/42] spi/pxa2xx: fix compile warning in pxa2xx_spi_acpi_get_pdata() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit cbfd6a21b6f (spi/pxa2xx: Convert to devm_ioremap_resource()) converted the driver to use devm_ioremap_resource(). However it causes following warning to be emitted: drivers/spi/spi-pxa2xx.c: In function ‘pxa2xx_spi_acpi_get_pdata’: drivers/spi/spi-pxa2xx.c:1094:3: warning: return makes pointer from integer without a cast [enabled by default] Fix this by returning NULL as it was done previously (error printing is already done by devm_ioremap_resource()). Signed-off-by: Mika Westerberg Cc: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index f5d84d6f8222..e5d782332ca5 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1091,7 +1091,7 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ssp->phys_base = res->start; ssp->mmio_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(ssp->mmio_base)) - return PTR_ERR(ssp->mmio_base); + return NULL; ssp->clk = devm_clk_get(&pdev->dev, NULL); ssp->irq = platform_get_irq(pdev, 0); From cddb339badb03dd96a5272195eec17e7899df154 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 13 May 2013 13:45:10 +0300 Subject: [PATCH 02/42] spi/pxa2xx: convert to dma_request_slave_channel_compat() Now that we have these nice DMA API helper functions we can take advantage of those instead of open-coding the channel/request line extraction from ACPI. Use the _compat version which still allows passing the channel/request line from platform data. Signed-off-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-dma.c | 11 ++++++----- drivers/spi/spi-pxa2xx.c | 34 ++-------------------------------- 2 files changed, 8 insertions(+), 37 deletions(-) diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index c735c5a008a2..f4cb744bf23f 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -327,22 +327,23 @@ void pxa2xx_spi_dma_start(struct driver_data *drv_data) int pxa2xx_spi_dma_setup(struct driver_data *drv_data) { struct pxa2xx_spi_master *pdata = drv_data->master_info; + struct device *dev = &drv_data->pdev->dev; dma_cap_mask_t mask; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - drv_data->dummy = devm_kzalloc(&drv_data->pdev->dev, SZ_2K, GFP_KERNEL); + drv_data->dummy = devm_kzalloc(dev, SZ_2K, GFP_KERNEL); if (!drv_data->dummy) return -ENOMEM; - drv_data->tx_chan = dma_request_channel(mask, pxa2xx_spi_dma_filter, - pdata); + drv_data->tx_chan = dma_request_slave_channel_compat(mask, + pxa2xx_spi_dma_filter, pdata, dev, "tx"); if (!drv_data->tx_chan) return -ENODEV; - drv_data->rx_chan = dma_request_channel(mask, pxa2xx_spi_dma_filter, - pdata); + drv_data->rx_chan = dma_request_slave_channel_compat(mask, + pxa2xx_spi_dma_filter, pdata, dev, "rx"); if (!drv_data->rx_chan) { dma_release_channel(drv_data->tx_chan); drv_data->tx_chan = NULL; diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index e5d782332ca5..d20b31ae96d3 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1040,32 +1040,10 @@ static void cleanup(struct spi_device *spi) } #ifdef CONFIG_ACPI -static int pxa2xx_spi_acpi_add_dma(struct acpi_resource *res, void *data) -{ - struct pxa2xx_spi_master *pdata = data; - - if (res->type == ACPI_RESOURCE_TYPE_FIXED_DMA) { - const struct acpi_resource_fixed_dma *dma; - - dma = &res->data.fixed_dma; - if (pdata->tx_slave_id < 0) { - pdata->tx_slave_id = dma->request_lines; - pdata->tx_chan_id = dma->channels; - } else if (pdata->rx_slave_id < 0) { - pdata->rx_slave_id = dma->request_lines; - pdata->rx_chan_id = dma->channels; - } - } - - /* Tell the ACPI core to skip this resource */ - return 1; -} - static struct pxa2xx_spi_master * pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) { struct pxa2xx_spi_master *pdata; - struct list_head resource_list; struct acpi_device *adev; struct ssp_device *ssp; struct resource *res; @@ -1103,15 +1081,7 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ssp->port_id = devid; pdata->num_chipselect = 1; - pdata->rx_slave_id = -1; - pdata->tx_slave_id = -1; - - INIT_LIST_HEAD(&resource_list); - acpi_dev_get_resources(adev, &resource_list, pxa2xx_spi_acpi_add_dma, - pdata); - acpi_dev_free_resource_list(&resource_list); - - pdata->enable_dma = pdata->rx_slave_id >= 0 && pdata->tx_slave_id >= 0; + pdata->enable_dma = true; return pdata; } @@ -1214,7 +1184,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) if (platform_info->enable_dma) { status = pxa2xx_spi_dma_setup(drv_data); if (status) { - dev_warn(dev, "failed to setup DMA, using PIO\n"); + dev_dbg(dev, "no DMA channels available, using PIO\n"); platform_info->enable_dma = false; } } From 4b30f2a1218220c295b01af6f219ab0477064a74 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 13 May 2013 13:45:11 +0300 Subject: [PATCH 03/42] spi/pxa2xx: add Intel BayTrail ACPI ID Intel BayTrail has one general purpose SPI controller that is compatible with Intel Low Power Subsystem SPI. The controller is enumerated from ACPI namespace with ACPI ID 80860F0E. Signed-off-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index d20b31ae96d3..f66995353e70 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1089,6 +1089,7 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) static struct acpi_device_id pxa2xx_spi_acpi_match[] = { { "INT33C0", 0 }, { "INT33C1", 0 }, + { "80860F0E", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); From 89e8773075bae055090db518bf2085c0d40ca9d5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 3 May 2013 16:27:12 +0900 Subject: [PATCH 04/42] spi: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Grant Likely Signed-off-by: Mark Brown --- drivers/spi/spi-altera.c | 2 -- drivers/spi/spi-ath79.c | 2 -- drivers/spi/spi-au1550.c | 2 -- drivers/spi/spi-bcm63xx.c | 3 --- drivers/spi/spi-bfin-sport.c | 3 --- drivers/spi/spi-bfin5xx.c | 3 --- drivers/spi/spi-clps711x.c | 2 -- drivers/spi/spi-coldfire-qspi.c | 1 - drivers/spi/spi-dw-mmio.c | 2 -- drivers/spi/spi-ep93xx.c | 2 -- drivers/spi/spi-gpio.c | 2 -- drivers/spi/spi-imx.c | 3 --- drivers/spi/spi-oc-tiny.c | 2 -- drivers/spi/spi-pxa2xx.c | 3 --- drivers/spi/spi-s3c64xx.c | 2 -- 15 files changed, 34 deletions(-) diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index a537f8dffc09..81b9adb6e766 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -285,7 +285,6 @@ static int altera_spi_probe(struct platform_device *pdev) exit_busy: err = -EBUSY; exit: - platform_set_drvdata(pdev, NULL); spi_master_put(master); return err; } @@ -296,7 +295,6 @@ static int altera_spi_remove(struct platform_device *dev) struct spi_master *master = hw->bitbang.master; spi_bitbang_stop(&hw->bitbang); - platform_set_drvdata(dev, NULL); spi_master_put(master); return 0; } diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index e504b7636058..6f6d45548050 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -287,7 +287,6 @@ err_clk_put: err_unmap: iounmap(sp->base); err_put_master: - platform_set_drvdata(pdev, NULL); spi_master_put(sp->bitbang.master); return ret; @@ -302,7 +301,6 @@ static int ath79_spi_remove(struct platform_device *pdev) clk_disable(sp->clk); clk_put(sp->clk); iounmap(sp->base); - platform_set_drvdata(pdev, NULL); spi_master_put(sp->bitbang.master); return 0; diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 44dd34b6ad09..39560f45ba1d 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -987,8 +987,6 @@ static int au1550_spi_remove(struct platform_device *pdev) au1xxx_dbdma_chan_free(hw->dma_tx_ch); } - platform_set_drvdata(pdev, NULL); - spi_master_put(hw->master); return 0; } diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index a4ec5f4ec817..099d0839bbd4 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -469,7 +469,6 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) out_clk_disable: clk_disable_unprepare(clk); out_err: - platform_set_drvdata(pdev, NULL); spi_master_put(master); out_clk: clk_put(clk); @@ -491,8 +490,6 @@ static int bcm63xx_spi_remove(struct platform_device *pdev) clk_disable_unprepare(bs->clk); clk_put(bs->clk); - platform_set_drvdata(pdev, 0); - spi_master_put(master); return 0; diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index 39b0d1711b4e..6d04c80559bb 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -882,9 +882,6 @@ static int bfin_sport_spi_remove(struct platform_device *pdev) peripheral_free_list(drv_data->pin_req); - /* Prevent double remove */ - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 317f564c899c..68ca4449e36f 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -1418,9 +1418,6 @@ static int bfin_spi_remove(struct platform_device *pdev) peripheral_free_list(drv_data->pin_req); - /* Prevent double remove */ - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index a11cbf02691a..6859a0294c51 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -254,7 +254,6 @@ err_out: if (gpio_is_valid(hw->chipselect[i])) gpio_free(hw->chipselect[i]); - platform_set_drvdata(pdev, NULL); spi_master_put(master); kfree(master); @@ -274,7 +273,6 @@ static int spi_clps711x_remove(struct platform_device *pdev) gpio_free(hw->chipselect[i]); devm_clk_put(&pdev->dev, hw->spi_clk); - platform_set_drvdata(pdev, NULL); spi_unregister_master(master); kfree(master); diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 7b5cc9e4e94d..3f1766003e68 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -524,7 +524,6 @@ static int mcfqspi_remove(struct platform_device *pdev) /* disable the hardware (set the baud rate to 0) */ mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR); - platform_set_drvdata(pdev, NULL); mcfqspi_cs_teardown(mcfqspi); clk_disable(mcfqspi->clk); clk_put(mcfqspi->clk); diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 4a6d5c9057a4..4aa8be865cc0 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -111,8 +111,6 @@ static int dw_spi_mmio_remove(struct platform_device *pdev) struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev); struct resource *mem; - platform_set_drvdata(pdev, NULL); - clk_disable(dwsmmio->clk); clk_put(dwsmmio->clk); dwsmmio->clk = NULL; diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d7bac60253c9..8d4f2a6aab90 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -1132,7 +1132,6 @@ fail_put_clock: clk_put(espi->clk); fail_release_master: spi_master_put(master); - platform_set_drvdata(pdev, NULL); return error; } @@ -1167,7 +1166,6 @@ static int ep93xx_spi_remove(struct platform_device *pdev) ep93xx_spi_release_dma(espi); clk_put(espi->clk); - platform_set_drvdata(pdev, NULL); spi_unregister_master(master); return 0; diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 0021fc4c45bc..9672c7b87889 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -514,8 +514,6 @@ static int spi_gpio_remove(struct platform_device *pdev) status = spi_bitbang_stop(&spi_gpio->bitbang); spi_master_put(spi_gpio->bitbang.master); - platform_set_drvdata(pdev, NULL); - if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) gpio_free(SPI_MISO_GPIO); if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 0befeeb522f4..f4d7cacbab3b 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -902,7 +902,6 @@ out_gpio_free: } spi_master_put(master); kfree(master); - platform_set_drvdata(pdev, NULL); return ret; } @@ -929,8 +928,6 @@ static int spi_imx_remove(struct platform_device *pdev) release_mem_region(res->start, resource_size(res)); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index e60a776ed2d4..58deb79d046b 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -368,7 +368,6 @@ exit_gpio: exit_busy: err = -EBUSY; exit: - platform_set_drvdata(pdev, NULL); spi_master_put(master); return err; } @@ -382,7 +381,6 @@ static int tiny_spi_remove(struct platform_device *pdev) spi_bitbang_stop(&hw->bitbang); for (i = 0; i < hw->gpio_cs_count; i++) gpio_free(hw->gpio_cs[i]); - platform_set_drvdata(pdev, NULL); spi_master_put(master); return 0; } diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index f5d84d6f8222..5a7fa2cd1efe 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1299,9 +1299,6 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) /* Disconnect from the SPI framework */ spi_unregister_master(drv_data->master); - /* Prevent double remove */ - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 5000586cb98d..5f3759d9b8f9 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1399,7 +1399,6 @@ err3: err2: clk_disable_unprepare(sdd->clk); err0: - platform_set_drvdata(pdev, NULL); spi_master_put(master); return ret; @@ -1420,7 +1419,6 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) clk_disable_unprepare(sdd->clk); - platform_set_drvdata(pdev, NULL); spi_master_put(master); return 0; From 2d6e75e894f355109d1f256cfdcfca9aafa90b9a Mon Sep 17 00:00:00 2001 From: Laurent Navet Date: Thu, 2 May 2013 14:13:30 +0200 Subject: [PATCH 05/42] spi: bmc2835: use devm_ioremap_resource() Replace a call to deprecated devm_request_and_ioremap by devm_ioremap_resource. Found with coccicheck and this semantic patch: scripts/coccinelle/api/devm_request_and_ioremap.cocci. Signed-off-by: Laurent Navet Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 89c0b5033114..a4185e492321 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -331,10 +331,9 @@ static int bcm2835_spi_probe(struct platform_device *pdev) goto out_master_put; } - bs->regs = devm_request_and_ioremap(&pdev->dev, res); - if (!bs->regs) { - dev_err(&pdev->dev, "could not request/map memory region\n"); - err = -ENODEV; + bs->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(bs->regs)) { + err = PTR_ERR(bs->regs); goto out_master_put; } From e9b3db6608a159f18bc4bf9657e4aeba24354ea1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 6 May 2013 15:05:55 -0300 Subject: [PATCH 06/42] spi: spi-imx: Let device core handle pinctrl Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for handling pinctrl. So remove devm_pinctrl_get_select_default() from the driver. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 0befeeb522f4..9821ef1deb6f 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -37,7 +37,6 @@ #include #include #include -#include #include @@ -760,7 +759,6 @@ static int spi_imx_probe(struct platform_device *pdev) struct spi_master *master; struct spi_imx_data *spi_imx; struct resource *res; - struct pinctrl *pinctrl; int i, ret, num_cs; if (!np && !mxc_platform_info) { @@ -848,12 +846,6 @@ static int spi_imx_probe(struct platform_device *pdev) goto out_iounmap; } - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); - goto out_free_irq; - } - spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(spi_imx->clk_ipg)) { ret = PTR_ERR(spi_imx->clk_ipg); From 0514dd76ea556859d398aaff725817e1c97579ea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 6 May 2013 20:32:09 +0100 Subject: [PATCH 07/42] spi/omap2: Let device core handle pinctrl Since commit ab78029 (drivers/pinctrl: grab default handles from device core) we can rely on device core for handling pinctrl so remove devm_pinctrl_get_select_default() from the driver. Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 86d2158946bb..000922abcb87 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -38,7 +38,6 @@ #include #include #include -#include #include @@ -1186,7 +1185,6 @@ static int omap2_mcspi_probe(struct platform_device *pdev) static int bus_num = 1; struct device_node *node = pdev->dev.of_node; const struct of_device_id *match; - struct pinctrl *pinctrl; master = spi_alloc_master(&pdev->dev, sizeof *mcspi); if (master == NULL) { @@ -1284,11 +1282,6 @@ static int omap2_mcspi_probe(struct platform_device *pdev) if (status < 0) goto dma_chnl_free; - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, - "pins are not configured from the driver\n"); - pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); pm_runtime_enable(&pdev->dev); From de1f9f270ea7fb7af37e1b62580e27b15273d63d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 6 May 2013 20:29:58 +0100 Subject: [PATCH 08/42] spi/sirf: Let device core handle pinctrl Since commit ab78029 (drivers/pinctrl: grab default handles from device core) we can rely on device core for handling pinctrl so remove devm_pinctrl_get_select_default() from the driver. Signed-off-by: Mark Brown Acked-by: Barry Song --- drivers/spi/spi-sirf.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 0808cd56bf8d..ac2ea8a1bd65 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -19,7 +19,6 @@ #include #include #include -#include #define DRIVER_NAME "sirfsoc_spi" @@ -127,7 +126,6 @@ struct sirfsoc_spi { void __iomem *base; u32 ctrl_freq; /* SPI controller clock speed */ struct clk *clk; - struct pinctrl *p; /* rx & tx bufs from the spi_transfer */ const void *tx; @@ -558,15 +556,10 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) master->bus_num = pdev->id; sspi->bitbang.master->dev.of_node = pdev->dev.of_node; - sspi->p = pinctrl_get_select_default(&pdev->dev); - ret = IS_ERR(sspi->p); - if (ret) - goto free_master; - sspi->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(sspi->clk)) { ret = -EINVAL; - goto free_pin; + goto free_master; } clk_prepare_enable(sspi->clk); sspi->ctrl_freq = clk_get_rate(sspi->clk); @@ -594,8 +587,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) free_clk: clk_disable_unprepare(sspi->clk); clk_put(sspi->clk); -free_pin: - pinctrl_put(sspi->p); free_master: spi_master_put(master); err_cs: @@ -618,7 +609,6 @@ static int spi_sirfsoc_remove(struct platform_device *pdev) } clk_disable_unprepare(sspi->clk); clk_put(sspi->clk); - pinctrl_put(sspi->p); spi_master_put(master); return 0; } From 86db3b04fe386caa98bb4be00408f082b60a74b0 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 6 May 2013 15:05:56 -0300 Subject: [PATCH 09/42] spi: spi-mxs: Let device core handle pinctrl Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for handling pinctrl. So remove devm_pinctrl_get_select_default() from the driver. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 84982768cd10..88fe1cfcbc65 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -506,7 +505,6 @@ static int mxs_spi_probe(struct platform_device *pdev) struct mxs_spi *spi; struct mxs_ssp *ssp; struct resource *iores; - struct pinctrl *pinctrl; struct clk *clk; void __iomem *base; int devid, clk_freq; @@ -528,10 +526,6 @@ static int mxs_spi_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - return PTR_ERR(pinctrl); - clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); From 27474d268c20a0e62f71065a043c08f5adb2419d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 16 May 2013 12:08:56 +0800 Subject: [PATCH 10/42] spi: ep93xx: fix error return code in ep93xx_spi_probe() Fix to return -ENOMEM in the workqueue create error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d7bac60253c9..5c63e1323160 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -1104,6 +1104,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi->wq = create_singlethread_workqueue("ep93xx_spid"); if (!espi->wq) { dev_err(&pdev->dev, "unable to create workqueue\n"); + error = -ENOMEM; goto fail_free_dma; } INIT_WORK(&espi->msg_work, ep93xx_spi_work); From 4a577f5275e948f96ea1a9bbce5d994ec6db618b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 16 May 2013 13:11:32 +0800 Subject: [PATCH 11/42] spi: coldfire-qspi: fix error return code in mcfqspi_probe() If pdev->dev.platform_data is not set, mcfqspi_probe() will return 0 and release all the resources, in this case, we should return a error code instead of 0. This patch fix to return -ENOENT in this case and move the check for pdev->dev.platform_data to the begin of this function. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 7b5cc9e4e94d..f99943bf3519 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -408,6 +408,12 @@ static int mcfqspi_probe(struct platform_device *pdev) struct mcfqspi_platform_data *pdata; int status; + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_dbg(&pdev->dev, "platform data is missing\n"); + return -ENOENT; + } + master = spi_alloc_master(&pdev->dev, sizeof(*mcfqspi)); if (master == NULL) { dev_dbg(&pdev->dev, "spi_alloc_master failed\n"); @@ -458,11 +464,6 @@ static int mcfqspi_probe(struct platform_device *pdev) } clk_enable(mcfqspi->clk); - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_dbg(&pdev->dev, "platform data is missing\n"); - goto fail4; - } master->bus_num = pdata->bus_num; master->num_chipselect = pdata->num_chipselect; From 237ce4665c12376391ddb148509204652f6ab758 Mon Sep 17 00:00:00 2001 From: Qipan Li Date: Sat, 18 May 2013 19:46:06 +0800 Subject: [PATCH 12/42] spi: sirf: fix the issue while transferring more than 256 words currently, spi irq handler only does rx processing and fetching data from rx fifo when "FRM_END" irq happens. FRM_END indicates one transfer completes. if rx size is less than 256, it works well. but the problem is that spi rx fifo size is only 256 bytes, then if data size of one frame is more than 256, before FRM_END comes, rx fifo will be filled with RXFIFO_OFLOW overflow interrupt, it will make us lose some data due to fifo overflow. Explicitly we need do fetch work from device rx fifo in irq handler not only in "FRM_END" irq but also in "THD_REACH" irq. THD_REACH means rx fifo has come to its threshold and will come to overflow if we don't take data from it in time. In this patch, we fix this issue. we take data from rx fifo when either FRM_END or RX_THD_REACH irq comes, we put data into tx fifo when either TX_FIFO_EMPTY or TX_THD_REACH irq comes. Signed-off-by: Qipan Li Signed-off-by: Zhiwu Song Signed-off-by: Barry Song Signed-off-by: Mark Brown --- drivers/spi/spi-sirf.c | 43 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index ac2ea8a1bd65..e00b437fa2a2 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -140,9 +140,6 @@ struct sirfsoc_spi { unsigned int left_tx_cnt; unsigned int left_rx_cnt; - /* tasklet to push tx msg into FIFO */ - struct tasklet_struct tasklet_tx; - int chipselect[0]; }; @@ -234,17 +231,6 @@ static void spi_sirfsoc_tx_word_u32(struct sirfsoc_spi *sspi) sspi->left_tx_cnt--; } -static void spi_sirfsoc_tasklet_tx(unsigned long arg) -{ - struct sirfsoc_spi *sspi = (struct sirfsoc_spi *)arg; - - /* Fill Tx FIFO while there are left words to be transmitted */ - while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) & - SIRFSOC_SPI_FIFO_FULL)) && - sspi->left_tx_cnt) - sspi->tx_word(sspi); -} - static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) { struct sirfsoc_spi *sspi = dev_id; @@ -259,25 +245,25 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); } - if (spi_stat & SIRFSOC_SPI_FRM_END) { + if (spi_stat & (SIRFSOC_SPI_FRM_END + | SIRFSOC_SPI_RXFIFO_THD_REACH)) while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS) & SIRFSOC_SPI_FIFO_EMPTY)) && sspi->left_rx_cnt) sspi->rx_word(sspi); - /* Received all words */ - if ((sspi->left_rx_cnt == 0) && (sspi->left_tx_cnt == 0)) { - complete(&sspi->done); - writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); - } + if (spi_stat & (SIRFSOC_SPI_FIFO_EMPTY + | SIRFSOC_SPI_TXFIFO_THD_REACH)) + while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) + & SIRFSOC_SPI_FIFO_FULL)) && + sspi->left_tx_cnt) + sspi->tx_word(sspi); + + /* Received all words */ + if ((sspi->left_rx_cnt == 0) && (sspi->left_tx_cnt == 0)) { + complete(&sspi->done); + writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); } - - if (spi_stat & SIRFSOC_SPI_RXFIFO_THD_REACH || - spi_stat & SIRFSOC_SPI_TXFIFO_THD_REACH || - spi_stat & SIRFSOC_SPI_RX_FIFO_FULL || - spi_stat & SIRFSOC_SPI_TXFIFO_EMPTY) - tasklet_schedule(&sspi->tasklet_tx); - return IRQ_HANDLED; } @@ -566,9 +552,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) init_completion(&sspi->done); - tasklet_init(&sspi->tasklet_tx, spi_sirfsoc_tasklet_tx, - (unsigned long)sspi); - writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP); writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP); writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP); From 2922a8de996956893bb98e4aa91be9774c958336 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 21 May 2013 20:36:34 -0600 Subject: [PATCH 13/42] spi: introduce macros to set bits_per_word_mask Introduce two macros to make setting up spi_master.bits_per_word_mask easier, and avoid mistakes like writing BIT(n) instead of BIT(n - 1). SPI_BPW_MASK is for a single supported value of bits_per_word_mask. SPI_BPW_RANGE_MASK represents a contiguous set of bit lengths. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6ff26c8db7b9..173725622252 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -308,6 +308,8 @@ struct spi_master { /* bitmask of supported bits_per_word for transfers */ u32 bits_per_word_mask; +#define SPI_BPW_MASK(bits) BIT((bits) - 1) +#define SPI_BPW_RANGE_MASK(min, max) ((BIT(max) - 1) - (BIT(min) - 1)) /* other constraints relevant to this driver */ u16 flags; From 24b5a82cf5709a4bc577f42fdaa61b23a7f58f08 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 May 2013 19:20:40 +0900 Subject: [PATCH 14/42] spi: use platform_{get,set}_drvdata() Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-davinci.c | 4 ++-- drivers/spi/spi-fsl-spi.c | 2 +- drivers/spi/spi-mpc52xx-psc.c | 2 +- drivers/spi/spi-mpc52xx.c | 4 ++-- drivers/spi/spi-omap-100k.c | 4 ++-- drivers/spi/spi-omap-uwire.c | 4 ++-- drivers/spi/spi-omap2-mcspi.c | 4 ++-- drivers/spi/spi-orion.c | 4 ++-- drivers/spi/spi-ppc4xx.c | 6 ++---- drivers/spi/spi-rspi.c | 4 ++-- drivers/spi/spi-sh-hspi.c | 4 ++-- drivers/spi/spi-sh.c | 4 ++-- drivers/spi/spi-tegra114.c | 4 ++-- drivers/spi/spi-tegra20-sflash.c | 4 ++-- drivers/spi/spi-tegra20-slink.c | 4 ++-- 15 files changed, 28 insertions(+), 30 deletions(-) diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 50b13c9b1ab6..968e36416cfa 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -865,7 +865,7 @@ static int davinci_spi_probe(struct platform_device *pdev) goto err; } - dev_set_drvdata(&pdev->dev, master); + platform_set_drvdata(pdev, master); dspi = spi_master_get_devdata(master); if (dspi == NULL) { @@ -1044,7 +1044,7 @@ static int davinci_spi_remove(struct platform_device *pdev) struct spi_master *master; struct resource *r; - master = dev_get_drvdata(&pdev->dev); + master = platform_get_drvdata(pdev); dspi = spi_master_get_devdata(master); spi_bitbang_stop(&dspi->bitbang); diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 14e202ee7036..41e89c3e3edc 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -853,7 +853,7 @@ err: static int of_fsl_spi_remove(struct platform_device *ofdev) { - struct spi_master *master = dev_get_drvdata(&ofdev->dev); + struct spi_master *master = platform_get_drvdata(ofdev); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); int ret; diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index 291120b37dbb..fed0571d4dec 100644 --- a/drivers/spi/spi-mpc52xx-psc.c +++ b/drivers/spi/spi-mpc52xx-psc.c @@ -481,7 +481,7 @@ static int mpc52xx_psc_spi_of_probe(struct platform_device *op) static int mpc52xx_psc_spi_of_remove(struct platform_device *op) { - struct spi_master *master = spi_master_get(dev_get_drvdata(&op->dev)); + struct spi_master *master = spi_master_get(platform_get_drvdata(op)); struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master); flush_workqueue(mps->workqueue); diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c index 29f77056eedc..7c675fe83101 100644 --- a/drivers/spi/spi-mpc52xx.c +++ b/drivers/spi/spi-mpc52xx.c @@ -438,7 +438,7 @@ static int mpc52xx_spi_probe(struct platform_device *op) master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; master->dev.of_node = op->dev.of_node; - dev_set_drvdata(&op->dev, master); + platform_set_drvdata(op, master); ms = spi_master_get_devdata(master); ms->master = master; @@ -529,7 +529,7 @@ static int mpc52xx_spi_probe(struct platform_device *op) static int mpc52xx_spi_remove(struct platform_device *op) { - struct spi_master *master = spi_master_get(dev_get_drvdata(&op->dev)); + struct spi_master *master = spi_master_get(platform_get_drvdata(op)); struct mpc52xx_spi *ms = spi_master_get_devdata(master); int i; diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 78d29a18dcc4..9236764861a9 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -510,7 +510,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev) master->num_chipselect = 2; master->mode_bits = MODEBITS; - dev_set_drvdata(&pdev->dev, master); + platform_set_drvdata(pdev, master); spi100k = spi_master_get_devdata(master); spi100k->master = master; @@ -569,7 +569,7 @@ static int omap1_spi100k_remove(struct platform_device *pdev) unsigned long flags; int status = 0; - master = dev_get_drvdata(&pdev->dev); + master = platform_get_drvdata(pdev); spi100k = spi_master_get_devdata(master); spin_lock_irqsave(&spi100k->lock, flags); diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c index 102b233b50c4..a6a8f0961750 100644 --- a/drivers/spi/spi-omap-uwire.c +++ b/drivers/spi/spi-omap-uwire.c @@ -495,7 +495,7 @@ static int uwire_probe(struct platform_device *pdev) return -ENOMEM; } - dev_set_drvdata(&pdev->dev, uwire); + platform_set_drvdata(pdev, uwire); uwire->ck = clk_get(&pdev->dev, "fck"); if (IS_ERR(uwire->ck)) { @@ -538,7 +538,7 @@ static int uwire_probe(struct platform_device *pdev) static int uwire_remove(struct platform_device *pdev) { - struct uwire_spi *uwire = dev_get_drvdata(&pdev->dev); + struct uwire_spi *uwire = platform_get_drvdata(pdev); int status; // FIXME remove all child devices, somewhere ... diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 86d2158946bb..1a75aefd1504 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1204,7 +1204,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) master->cleanup = omap2_mcspi_cleanup; master->dev.of_node = node; - dev_set_drvdata(&pdev->dev, master); + platform_set_drvdata(pdev, master); mcspi = spi_master_get_devdata(master); mcspi->master = master; @@ -1318,7 +1318,7 @@ static int omap2_mcspi_remove(struct platform_device *pdev) struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *dma_channels; - master = dev_get_drvdata(&pdev->dev); + master = platform_get_drvdata(pdev); mcspi = spi_master_get_devdata(master); dma_channels = mcspi->dma_channels; diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 66a5f82cf138..5d90bebaa0fa 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -428,7 +428,7 @@ static int orion_spi_probe(struct platform_device *pdev) master->transfer_one_message = orion_spi_transfer_one_message; master->num_chipselect = ORION_NUM_CHIPSELECTS; - dev_set_drvdata(&pdev->dev, master); + platform_set_drvdata(pdev, master); spi = spi_master_get_devdata(master); spi->master = master; @@ -485,7 +485,7 @@ static int orion_spi_remove(struct platform_device *pdev) struct resource *r; struct orion_spi *spi; - master = dev_get_drvdata(&pdev->dev); + master = platform_get_drvdata(pdev); spi = spi_master_get_devdata(master); clk_disable_unprepare(spi->clk); diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 357f183a4fb7..8548e574749d 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -406,7 +406,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) if (master == NULL) return -ENOMEM; master->dev.of_node = np; - dev_set_drvdata(dev, master); + platform_set_drvdata(op, master); hw = spi_master_get_devdata(master); hw->master = spi_master_get(master); hw->dev = dev; @@ -553,7 +553,6 @@ request_mem_error: free_gpios: free_gpios(hw); free_master: - dev_set_drvdata(dev, NULL); spi_master_put(master); dev_err(dev, "initialization failed\n"); @@ -562,11 +561,10 @@ free_master: static int spi_ppc4xx_of_remove(struct platform_device *op) { - struct spi_master *master = dev_get_drvdata(&op->dev); + struct spi_master *master = platform_get_drvdata(op); struct ppc4xx_spi *hw = spi_master_get_devdata(master); spi_bitbang_stop(&hw->bitbang); - dev_set_drvdata(&op->dev, NULL); release_mem_region(hw->mapbase, hw->mapsize); free_irq(hw->irqnum, hw); iounmap(hw->regs); diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 902f2fb902db..b44a6ac3cec9 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -719,7 +719,7 @@ static void rspi_release_dma(struct rspi_data *rspi) static int rspi_remove(struct platform_device *pdev) { - struct rspi_data *rspi = dev_get_drvdata(&pdev->dev); + struct rspi_data *rspi = platform_get_drvdata(pdev); spi_unregister_master(rspi->master); rspi_release_dma(rspi); @@ -759,7 +759,7 @@ static int rspi_probe(struct platform_device *pdev) } rspi = spi_master_get_devdata(master); - dev_set_drvdata(&pdev->dev, rspi); + platform_set_drvdata(pdev, rspi); rspi->master = master; rspi->addr = ioremap(res->start, resource_size(res)); diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 60cfae51c713..d3a62b9cfff3 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -297,7 +297,7 @@ static int hspi_probe(struct platform_device *pdev) } hspi = spi_master_get_devdata(master); - dev_set_drvdata(&pdev->dev, hspi); + platform_set_drvdata(pdev, hspi); /* init hspi */ hspi->master = master; @@ -341,7 +341,7 @@ static int hspi_probe(struct platform_device *pdev) static int hspi_remove(struct platform_device *pdev) { - struct hspi_priv *hspi = dev_get_drvdata(&pdev->dev); + struct hspi_priv *hspi = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c index 3c3600a994bd..c120a70094f2 100644 --- a/drivers/spi/spi-sh.c +++ b/drivers/spi/spi-sh.c @@ -434,7 +434,7 @@ static irqreturn_t spi_sh_irq(int irq, void *_ss) static int spi_sh_remove(struct platform_device *pdev) { - struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev); + struct spi_sh_data *ss = platform_get_drvdata(pdev); spi_unregister_master(ss->master); destroy_workqueue(ss->workqueue); @@ -471,7 +471,7 @@ static int spi_sh_probe(struct platform_device *pdev) } ss = spi_master_get_devdata(master); - dev_set_drvdata(&pdev->dev, ss); + platform_set_drvdata(pdev, ss); switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { case IORESOURCE_MEM_8BIT: diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 598eb45e8008..e8f542ab8935 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1041,7 +1041,7 @@ static int tegra_spi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "master allocation failed\n"); return -ENOMEM; } - dev_set_drvdata(&pdev->dev, master); + platform_set_drvdata(pdev, master); tspi = spi_master_get_devdata(master); /* Parse DT */ @@ -1152,7 +1152,7 @@ exit_free_master: static int tegra_spi_remove(struct platform_device *pdev) { - struct spi_master *master = dev_get_drvdata(&pdev->dev); + struct spi_master *master = platform_get_drvdata(pdev); struct tegra_spi_data *tspi = spi_master_get_devdata(master); free_irq(tspi->irq, tspi); diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 09df8e22dba0..c1d5d95e70ea 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -480,7 +480,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; - dev_set_drvdata(&pdev->dev, master); + platform_set_drvdata(pdev, master); tsd = spi_master_get_devdata(master); tsd->master = master; tsd->dev = &pdev->dev; @@ -555,7 +555,7 @@ exit_free_master: static int tegra_sflash_remove(struct platform_device *pdev) { - struct spi_master *master = dev_get_drvdata(&pdev->dev); + struct spi_master *master = platform_get_drvdata(pdev); struct tegra_sflash_data *tsd = spi_master_get_devdata(master); free_irq(tsd->irq, tsd); diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 3faf88d003de..80490cc11ce5 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1089,7 +1089,7 @@ static int tegra_slink_probe(struct platform_device *pdev) master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; - dev_set_drvdata(&pdev->dev, master); + platform_set_drvdata(pdev, master); tspi = spi_master_get_devdata(master); tspi->master = master; tspi->dev = &pdev->dev; @@ -1193,7 +1193,7 @@ exit_free_master: static int tegra_slink_remove(struct platform_device *pdev) { - struct spi_master *master = dev_get_drvdata(&pdev->dev); + struct spi_master *master = platform_get_drvdata(pdev); struct tegra_slink_data *tspi = spi_master_get_devdata(master); free_irq(tspi->irq, tspi); From 5b547a75405184d54d148132b9e4600516c49c6e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 23 May 2013 20:54:37 +0200 Subject: [PATCH 15/42] spi: pl022: use DMA by default when probing from DT In the past we controlled the selection of DMA for a certain host by a boolean switch in the platform data. Currently there is no way to enable DMA on a PL022 probed from the device tree. Let's default to trying to obtain DMA channels in the DT case, and then we can always fail (and thus fall back to PIO mode). Signed-off-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 371cc66f1a0e..3b246543282f 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2083,6 +2083,7 @@ pl022_platform_data_dt_get(struct device *dev) } pd->bus_id = -1; + pd->enable_dma = 1; of_property_read_u32(np, "num-cs", &tmp); pd->num_chipselect = tmp; of_property_read_u32(np, "pl022,autosuspend-delay", From 24778be20f87d5aadb19624fc768b3159fa43efc Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 21 May 2013 20:36:35 -0600 Subject: [PATCH 16/42] spi: convert drivers to use bits_per_word_mask Fill in the recently added spi_master.bits_per_word_mask field in as many drivers as possible. Make related cleanups, such as removing any redundant error-checking, or empty setup callbacks. Signed-off-by: Stephen Warren Acked-by: H Hartley Sweeten Signed-off-by: Mark Brown --- drivers/spi/spi-altera.c | 12 ------------ drivers/spi/spi-ath79.c | 4 +--- drivers/spi/spi-atmel.c | 9 +-------- drivers/spi/spi-au1550.c | 12 +----------- drivers/spi/spi-bcm63xx.c | 20 +------------------- drivers/spi/spi-bfin-sport.c | 10 ++-------- drivers/spi/spi-bfin5xx.c | 21 +++++---------------- drivers/spi/spi-clps711x.c | 7 +------ drivers/spi/spi-coldfire-qspi.c | 11 ++--------- drivers/spi/spi-davinci.c | 8 ++++---- drivers/spi/spi-dw.c | 26 ++++---------------------- drivers/spi/spi-ep93xx.c | 11 +---------- drivers/spi/spi-fsl-espi.c | 9 ++------- drivers/spi/spi-gpio.c | 4 +--- drivers/spi/spi-imx.c | 6 +++--- drivers/spi/spi-mxs.c | 7 +------ drivers/spi/spi-nuc900.c | 13 ------------- drivers/spi/spi-omap-100k.c | 12 ++---------- drivers/spi/spi-omap2-mcspi.c | 13 ++----------- drivers/spi/spi-ppc4xx.c | 13 +------------ drivers/spi/spi-pxa2xx.c | 20 ++------------------ drivers/spi/spi-s3c64xx.c | 3 ++- drivers/spi/spi-sirf.c | 6 ++---- drivers/spi/spi-ti-ssp.c | 16 +--------------- drivers/spi/spi-topcliff-pch.c | 17 +---------------- drivers/spi/spi-txx9.c | 8 +------- drivers/spi/spi-xcomm.c | 12 ++---------- drivers/spi/spi-xilinx.c | 16 ---------------- 28 files changed, 46 insertions(+), 280 deletions(-) diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index a537f8dffc09..6b7096e0ad68 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -103,16 +103,6 @@ static void altera_spi_chipsel(struct spi_device *spi, int value) } } -static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) -{ - return 0; -} - -static int altera_spi_setup(struct spi_device *spi) -{ - return 0; -} - static inline unsigned int hw_txbyte(struct altera_spi *hw, int count) { if (hw->tx) { @@ -231,7 +221,6 @@ static int altera_spi_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->num_chipselect = 16; master->mode_bits = SPI_CS_HIGH; - master->setup = altera_spi_setup; hw = spi_master_get_devdata(master); platform_set_drvdata(pdev, hw); @@ -240,7 +229,6 @@ static int altera_spi_probe(struct platform_device *pdev) hw->bitbang.master = spi_master_get(master); if (!hw->bitbang.master) return err; - hw->bitbang.setup_transfer = altera_spi_setupxfer; hw->bitbang.chipselect = altera_spi_chipsel; hw->bitbang.txrx_bufs = altera_spi_txrx; diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index e504b7636058..5e2d52ce387f 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -155,9 +155,6 @@ static int ath79_spi_setup(struct spi_device *spi) { int status = 0; - if (spi->bits_per_word > 32) - return -EINVAL; - if (!spi->controller_state) { status = ath79_spi_setup_cs(spi); if (status) @@ -226,6 +223,7 @@ static int ath79_spi_probe(struct platform_device *pdev) pdata = pdev->dev.platform_data; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->setup = ath79_spi_setup; master->cleanup = ath79_spi_cleanup; if (pdata) { diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 380387a47b1d..31cfc8711547 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1268,13 +1268,6 @@ static int atmel_spi_setup(struct spi_device *spi) return -EINVAL; } - if (bits < 8 || bits > 16) { - dev_dbg(&spi->dev, - "setup: invalid bits_per_word %u (8 to 16)\n", - bits); - return -EINVAL; - } - /* see notes above re chipselect */ if (!atmel_spi_is_v2(as) && spi->chip_select == 0 @@ -1515,7 +1508,7 @@ static int atmel_spi_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); master->dev.of_node = pdev->dev.of_node; master->bus_num = pdev->id; master->num_chipselect = master->dev.of_node ? 0 : 4; diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 44dd34b6ad09..d736fa942020 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -248,11 +248,6 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) hz = t->speed_hz; } - if (bpw < 4 || bpw > 24) { - dev_err(&spi->dev, "setupxfer: invalid bits_per_word=%d\n", - bpw); - return -EINVAL; - } if (hz > spi->max_speed_hz || hz > hw->freq_max || hz < hw->freq_min) { dev_err(&spi->dev, "setupxfer: clock rate=%d out of range\n", hz); @@ -296,12 +291,6 @@ static int au1550_spi_setup(struct spi_device *spi) { struct au1550_spi *hw = spi_master_get_devdata(spi->master); - if (spi->bits_per_word < 4 || spi->bits_per_word > 24) { - dev_err(&spi->dev, "setup: invalid bits_per_word=%d\n", - spi->bits_per_word); - return -EINVAL; - } - if (spi->max_speed_hz == 0) spi->max_speed_hz = hw->freq_max; if (spi->max_speed_hz > hw->freq_max @@ -782,6 +771,7 @@ static int au1550_spi_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 24); hw = spi_master_get_devdata(master); diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index a4ec5f4ec817..270f09c071fb 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -124,17 +124,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi, /* the spi->mode bits understood by this driver: */ #define MODEBITS (SPI_CPOL | SPI_CPHA) -static int bcm63xx_spi_setup(struct spi_device *spi) -{ - if (spi->bits_per_word != 8) { - dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", - __func__, spi->bits_per_word); - return -EINVAL; - } - - return 0; -} - static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, unsigned int num_transfers) { @@ -277,13 +266,6 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master, * full-duplex transfers. */ list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->bits_per_word != 8) { - dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", - __func__, t->bits_per_word); - status = -EINVAL; - goto exit; - } - if (!first) first = t; @@ -430,11 +412,11 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) master->bus_num = pdata->bus_num; master->num_chipselect = pdata->num_chipselect; - master->setup = bcm63xx_spi_setup; master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer; master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer; master->transfer_one_message = bcm63xx_spi_transfer_one; master->mode_bits = MODEBITS; + master->bits_per_word_mask = SPI_BPW_MASK(8); bs->msg_type_shift = pdata->msg_type_shift; bs->msg_ctl_width = pdata->msg_ctl_width; bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index 39b0d1711b4e..e4a858ad6ef6 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -417,7 +417,7 @@ bfin_sport_spi_pump_transfers(unsigned long data) /* Bits per word setup */ bits_per_word = transfer->bits_per_word; - if (bits_per_word % 16 == 0) + if (bits_per_word == 16) drv_data->ops = &bfin_sport_transfer_ops_u16; else drv_data->ops = &bfin_sport_transfer_ops_u8; @@ -600,13 +600,6 @@ bfin_sport_spi_setup(struct spi_device *spi) } } - if (spi->bits_per_word % 8) { - dev_err(&spi->dev, "%d bits_per_word is not supported\n", - spi->bits_per_word); - ret = -EINVAL; - goto error; - } - /* translate common spi framework into our register * following configure contents are same for tx and rx. */ @@ -778,6 +771,7 @@ static int bfin_sport_spi_probe(struct platform_device *pdev) drv_data->pin_req = platform_info->pin_req; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->bus_num = pdev->id; master->num_chipselect = platform_info->num_chipselect; master->cleanup = bfin_sport_spi_cleanup; diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 317f564c899c..e35c19cff9ca 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -643,21 +643,16 @@ static void bfin_spi_pump_transfers(unsigned long data) /* Bits per word setup */ bits_per_word = transfer->bits_per_word; - if (bits_per_word % 16 == 0) { + if (bits_per_word == 16) { drv_data->n_bytes = bits_per_word/8; drv_data->len = (transfer->len) >> 1; cr_width = BIT_CTL_WORDSIZE; drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; - } else if (bits_per_word % 8 == 0) { + } else if (bits_per_word == 8) { drv_data->n_bytes = bits_per_word/8; drv_data->len = transfer->len; cr_width = 0; drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; - } else { - dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n"); - message->status = -EINVAL; - bfin_spi_giveback(drv_data); - return; } cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE); cr |= cr_width; @@ -808,13 +803,13 @@ static void bfin_spi_pump_transfers(unsigned long data) bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val); else { int loop; - if (bits_per_word % 16 == 0) { + if (bits_per_word == 16) { u16 *buf = (u16 *)drv_data->tx; for (loop = 0; loop < bits_per_word / 16; loop++) { bfin_write(&drv_data->regs->tdbr, *buf++); } - } else if (bits_per_word % 8 == 0) { + } else if (bits_per_word == 8) { u8 *buf = (u8 *)drv_data->tx; for (loop = 0; loop < bits_per_word / 8; loop++) bfin_write(&drv_data->regs->tdbr, *buf++); @@ -1033,12 +1028,6 @@ static int bfin_spi_setup(struct spi_device *spi) chip->ctl_reg &= bfin_ctl_reg; } - if (spi->bits_per_word % 8) { - dev_err(&spi->dev, "%d bits_per_word is not supported\n", - spi->bits_per_word); - goto error; - } - /* translate common spi framework into our register */ if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) { dev_err(&spi->dev, "unsupported spi modes detected\n"); @@ -1299,7 +1288,7 @@ static int bfin_spi_probe(struct platform_device *pdev) /* the spi->mode bits supported by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; - + master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->bus_num = pdev->id; master->num_chipselect = platform_info->num_chipselect; master->cleanup = bfin_spi_cleanup; diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index a11cbf02691a..e322b5bf9910 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -42,12 +42,6 @@ static int spi_clps711x_setup(struct spi_device *spi) { struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master); - if (spi->bits_per_word != 8) { - dev_err(&spi->dev, "Unsupported master bus width %i\n", - spi->bits_per_word); - return -EINVAL; - } - /* We are expect that SPI-device is not selected */ gpio_direction_output(hw->chipselect[spi->chip_select], !(spi->mode & SPI_CS_HIGH)); @@ -190,6 +184,7 @@ static int spi_clps711x_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->mode_bits = SPI_CPHA | SPI_CS_HIGH; + master->bits_per_word_mask = SPI_BPW_MASK(8); master->num_chipselect = pdata->num_chipselect; master->setup = spi_clps711x_setup; master->transfer_one_message = spi_clps711x_transfer_one_message; diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 7b5cc9e4e94d..9a7db9d1b4ca 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -312,10 +312,7 @@ static int mcfqspi_transfer_one_message(struct spi_master *master, bool cs_high = spi->mode & SPI_CS_HIGH; u16 qmr = MCFQSPI_QMR_MSTR; - if (t->bits_per_word) - qmr |= t->bits_per_word << 10; - else - qmr |= spi->bits_per_word << 10; + qmr |= t->bits_per_word << 10; if (spi->mode & SPI_CPHA) qmr |= MCFQSPI_QMR_CPHA; if (spi->mode & SPI_CPOL) @@ -377,11 +374,6 @@ static int mcfqspi_unprepare_transfer_hw(struct spi_master *master) static int mcfqspi_setup(struct spi_device *spi) { - if ((spi->bits_per_word < 8) || (spi->bits_per_word > 16)) { - dev_dbg(&spi->dev, "%d bits per word is not supported\n", - spi->bits_per_word); - return -EINVAL; - } if (spi->chip_select >= spi->master->num_chipselect) { dev_dbg(&spi->dev, "%d chip select is out of range\n", spi->chip_select); @@ -477,6 +469,7 @@ static int mcfqspi_probe(struct platform_device *pdev) mcfqspi->dev = &pdev->dev; master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); master->setup = mcfqspi_setup; master->transfer_one_message = mcfqspi_transfer_one_message; master->prepare_transfer_hardware = mcfqspi_prepare_transfer_hw; diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 50b13c9b1ab6..b141ef221b14 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -299,16 +299,15 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, * Assign function pointer to appropriate transfer method * 8bit, 16bit or 32bit transfer */ - if (bits_per_word <= 8 && bits_per_word >= 2) { + if (bits_per_word <= 8) { dspi->get_rx = davinci_spi_rx_buf_u8; dspi->get_tx = davinci_spi_tx_buf_u8; dspi->bytes_per_word[spi->chip_select] = 1; - } else if (bits_per_word <= 16 && bits_per_word >= 2) { + } else { dspi->get_rx = davinci_spi_rx_buf_u16; dspi->get_tx = davinci_spi_tx_buf_u16; dspi->bytes_per_word[spi->chip_select] = 2; - } else - return -EINVAL; + } if (!hz) hz = spi->max_speed_hz; @@ -933,6 +932,7 @@ static int davinci_spi_probe(struct platform_device *pdev) master->dev.of_node = pdev->dev.of_node; master->bus_num = pdev->id; master->num_chipselect = pdata->num_chipselect; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); master->setup = davinci_spi_setup; dspi->bitbang.chipselect = davinci_spi_chipselect; diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index c1abc06899e7..79c958e49f61 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -457,19 +457,7 @@ static void pump_transfers(unsigned long data) } if (transfer->bits_per_word) { bits = transfer->bits_per_word; - - switch (bits) { - case 8: - case 16: - dws->n_bytes = dws->dma_width = bits >> 3; - break; - default: - printk(KERN_ERR "MRST SPI0: unsupported bits:" - "%db\n", bits); - message->status = -EIO; - goto early_exit; - } - + dws->n_bytes = dws->dma_width = bits >> 3; cr0 = (bits - 1) | (chip->type << SPI_FRF_OFFSET) | (spi->mode << SPI_MODE_OFFSET) @@ -629,9 +617,6 @@ static int dw_spi_setup(struct spi_device *spi) struct dw_spi_chip *chip_info = NULL; struct chip_data *chip; - if (spi->bits_per_word != 8 && spi->bits_per_word != 16) - return -EINVAL; - /* Only alloc on first setup */ chip = spi_get_ctldata(spi); if (!chip) { @@ -660,16 +645,12 @@ static int dw_spi_setup(struct spi_device *spi) chip->enable_dma = chip_info->enable_dma; } - if (spi->bits_per_word <= 8) { + if (spi->bits_per_word == 8) { chip->n_bytes = 1; chip->dma_width = 1; - } else if (spi->bits_per_word <= 16) { + } else if (spi->bits_per_word == 16) { chip->n_bytes = 2; chip->dma_width = 2; - } else { - /* Never take >16b case for MRST SPIC */ - dev_err(&spi->dev, "invalid wordsize\n"); - return -EINVAL; } chip->bits_per_word = spi->bits_per_word; @@ -824,6 +805,7 @@ int dw_spi_add_host(struct dw_spi *dws) } master->mode_bits = SPI_CPOL | SPI_CPHA; + master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->bus_num = dws->bus_num; master->num_chipselect = dws->num_cs; master->cleanup = dw_spi_cleanup; diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d7bac60253c9..f1b14977abdf 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -296,12 +296,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) struct ep93xx_spi *espi = spi_master_get_devdata(spi->master); struct ep93xx_spi_chip *chip; - if (spi->bits_per_word < 4 || spi->bits_per_word > 16) { - dev_err(&espi->pdev->dev, "invalid bits per word %d\n", - spi->bits_per_word); - return -EINVAL; - } - chip = spi_get_ctldata(spi); if (!chip) { dev_dbg(&espi->pdev->dev, "initial setup for %s\n", @@ -365,10 +359,6 @@ static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) /* first validate each transfer */ list_for_each_entry(t, &msg->transfers, transfer_list) { - if (t->bits_per_word) { - if (t->bits_per_word < 4 || t->bits_per_word > 16) - return -EINVAL; - } if (t->speed_hz && t->speed_hz < espi->min_rate) return -EINVAL; } @@ -1046,6 +1036,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->num_chipselect = info->num_chipselect; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); platform_set_drvdata(pdev, master); diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 24610ca8955d..0ef05f198f22 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -144,10 +144,6 @@ static int fsl_espi_setup_transfer(struct spi_device *spi, if (!bits_per_word) bits_per_word = spi->bits_per_word; - /* Make sure its a bit width we support [4..16] */ - if ((bits_per_word < 4) || (bits_per_word > 16)) - return -EINVAL; - if (!hz) hz = spi->max_speed_hz; @@ -157,12 +153,10 @@ static int fsl_espi_setup_transfer(struct spi_device *spi, cs->get_tx = mpc8xxx_spi_tx_buf_u32; if (bits_per_word <= 8) { cs->rx_shift = 8 - bits_per_word; - } else if (bits_per_word <= 16) { + } else cs->rx_shift = 16 - bits_per_word; if (spi->mode & SPI_LSB_FIRST) cs->get_tx = fsl_espi_tx_buf_lsb; - } else { - return -EINVAL; } mpc8xxx_spi->rx_shift = cs->rx_shift; @@ -609,6 +603,7 @@ static struct spi_master * fsl_espi_probe(struct device *dev, if (ret) goto err_probe; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); master->setup = fsl_espi_setup; mpc8xxx_spi = spi_master_get_devdata(master); diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 0021fc4c45bc..a7801a889ff9 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -239,9 +239,6 @@ static int spi_gpio_setup(struct spi_device *spi) struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); struct device_node *np = spi->master->dev.of_node; - if (spi->bits_per_word > 32) - return -EINVAL; - if (np) { /* * In DT environments, the CS GPIOs have already been @@ -446,6 +443,7 @@ static int spi_gpio_probe(struct platform_device *pdev) if (pdata) spi_gpio->pdata = *pdata; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->flags = master_flags; master->bus_num = pdev->id; master->num_chipselect = SPI_N_CHIPSEL; diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 0befeeb522f4..cb88eeb74cc4 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -698,11 +698,10 @@ static int spi_imx_setupxfer(struct spi_device *spi, } else if (config.bpw <= 16) { spi_imx->rx = spi_imx_buf_rx_u16; spi_imx->tx = spi_imx_buf_tx_u16; - } else if (config.bpw <= 32) { + } spi_imx->rx = spi_imx_buf_rx_u32; spi_imx->tx = spi_imx_buf_tx_u32; - } else - BUG(); + } spi_imx->devtype_data->config(spi_imx, &config); @@ -783,6 +782,7 @@ static int spi_imx_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->bus_num = pdev->id; master->num_chipselect = num_cs; diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 84982768cd10..62b7e8ee1163 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -75,12 +75,6 @@ static int mxs_spi_setup_transfer(struct spi_device *dev, if (t && t->bits_per_word) bits_per_word = t->bits_per_word; - if (bits_per_word != 8) { - dev_err(&dev->dev, "%s, unsupported bits_per_word=%d\n", - __func__, bits_per_word); - return -EINVAL; - } - hz = dev->max_speed_hz; if (t && t->speed_hz) hz = min(hz, t->speed_hz); @@ -548,6 +542,7 @@ static int mxs_spi_probe(struct platform_device *pdev) master->transfer_one_message = mxs_spi_transfer_one; master->setup = mxs_spi_setup; + master->bits_per_word_mask = SPI_BPW_MASK(8); master->mode_bits = SPI_CPOL | SPI_CPHA; master->num_chipselect = 3; master->dev.of_node = np; diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index b3f9ec83ef73..94efa2c6298e 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -174,17 +174,6 @@ static void nuc900_spi_gobusy(struct nuc900_spi *hw) spin_unlock_irqrestore(&hw->lock, flags); } -static int nuc900_spi_setupxfer(struct spi_device *spi, - struct spi_transfer *t) -{ - return 0; -} - -static int nuc900_spi_setup(struct spi_device *spi) -{ - return 0; -} - static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count) { return hw->tx ? hw->tx[count] : 0; @@ -377,10 +366,8 @@ static int nuc900_spi_probe(struct platform_device *pdev) master->num_chipselect = hw->pdata->num_cs; master->bus_num = hw->pdata->bus_num; hw->bitbang.master = hw->master; - hw->bitbang.setup_transfer = nuc900_spi_setupxfer; hw->bitbang.chipselect = nuc900_spi_chipsel; hw->bitbang.txrx_bufs = nuc900_spi_txrx; - hw->bitbang.master->setup = nuc900_spi_setup; hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (hw->res == NULL) { diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 78d29a18dcc4..9137fcc4f99b 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -298,12 +298,6 @@ static int omap1_spi100k_setup(struct spi_device *spi) struct omap1_spi100k *spi100k; struct omap1_spi100k_cs *cs = spi->controller_state; - if (spi->bits_per_word < 4 || spi->bits_per_word > 32) { - dev_dbg(&spi->dev, "setup: unsupported %d bit words\n", - spi->bits_per_word); - return -EINVAL; - } - spi100k = spi_master_get_devdata(spi->master); if (!cs) { @@ -451,10 +445,7 @@ static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) unsigned len = t->len; if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ - || (len && !(rx_buf || tx_buf)) - || (t->bits_per_word && - ( t->bits_per_word < 4 - || t->bits_per_word > 32))) { + || (len && !(rx_buf || tx_buf))) { dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", t->speed_hz, len, @@ -509,6 +500,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev) master->cleanup = NULL; master->num_chipselect = 2; master->mode_bits = MODEBITS; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); dev_set_drvdata(&pdev->dev, master); diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 86d2158946bb..6246fb455774 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -857,12 +857,6 @@ static int omap2_mcspi_setup(struct spi_device *spi) struct omap2_mcspi_dma *mcspi_dma; struct omap2_mcspi_cs *cs = spi->controller_state; - if (spi->bits_per_word < 4 || spi->bits_per_word > 32) { - dev_dbg(&spi->dev, "setup: unsupported %d bit words\n", - spi->bits_per_word); - return -EINVAL; - } - mcspi_dma = &mcspi->dma_channels[spi->chip_select]; if (!cs) { @@ -1072,10 +1066,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, unsigned len = t->len; if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ - || (len && !(rx_buf || tx_buf)) - || (t->bits_per_word && - ( t->bits_per_word < 4 - || t->bits_per_word > 32))) { + || (len && !(rx_buf || tx_buf))) { dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", t->speed_hz, len, @@ -1196,7 +1187,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->setup = omap2_mcspi_setup; master->prepare_transfer_hardware = omap2_prepare_transfer; master->unprepare_transfer_hardware = omap2_unprepare_transfer; diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 357f183a4fb7..01df34bed2d0 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -190,12 +190,6 @@ static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t) speed = min(t->speed_hz, spi->max_speed_hz); } - if (bits_per_word != 8) { - dev_err(&spi->dev, "invalid bits-per-word (%d)\n", - bits_per_word); - return -EINVAL; - } - if (!speed || (speed > spi->max_speed_hz)) { dev_err(&spi->dev, "invalid speed_hz (%d)\n", speed); return -EINVAL; @@ -229,12 +223,6 @@ static int spi_ppc4xx_setup(struct spi_device *spi) { struct spi_ppc4xx_cs *cs = spi->controller_state; - if (spi->bits_per_word != 8) { - dev_err(&spi->dev, "invalid bits-per-word (%d)\n", - spi->bits_per_word); - return -EINVAL; - } - if (!spi->max_speed_hz) { dev_err(&spi->dev, "invalid max_speed_hz (must be non-zero)\n"); return -EINVAL; @@ -465,6 +453,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) bbp->use_dma = 0; bbp->master->setup = spi_ppc4xx_setup; bbp->master->cleanup = spi_ppc4xx_cleanup; + bbp->master->bits_per_word_mask = SPI_BPW_MASK(8); /* the spi->mode bits understood by this driver: */ bbp->master->mode_bits = diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index f5d84d6f8222..7de2ca1c4ee3 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -881,21 +881,6 @@ static int setup(struct spi_device *spi) rx_thres = RX_THRESH_DFLT; } - if (!pxa25x_ssp_comp(drv_data) - && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) { - dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " - "b/w not 4-32 for type non-PXA25x_SSP\n", - drv_data->ssp_type, spi->bits_per_word); - return -EINVAL; - } else if (pxa25x_ssp_comp(drv_data) - && (spi->bits_per_word < 4 - || spi->bits_per_word > 16)) { - dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " - "b/w not 4-16 for type PXA25x_SSP\n", - drv_data->ssp_type, spi->bits_per_word); - return -EINVAL; - } - /* Only alloc on first setup */ chip = spi_get_ctldata(spi); if (!chip) { @@ -1011,9 +996,6 @@ static int setup(struct spi_device *spi) chip->n_bytes = 4; chip->read = u32_reader; chip->write = u32_writer; - } else { - dev_err(&spi->dev, "invalid wordsize\n"); - return -ENODEV; } chip->bits_per_word = spi->bits_per_word; @@ -1190,11 +1172,13 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) drv_data->ioaddr = ssp->mmio_base; drv_data->ssdr_physical = ssp->phys_base + SSDR; if (pxa25x_ssp_comp(drv_data)) { + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; drv_data->dma_cr1 = 0; drv_data->clear_sr = SSSR_ROR; drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR; } else { + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE; drv_data->dma_cr1 = DEFAULT_DMA_CR1; drv_data->clear_sr = SSSR_ROR | SSSR_TINT; diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 5000586cb98d..39a3824ec3d7 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1314,7 +1314,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; master->num_chipselect = sci->num_cs; master->dma_alignment = 8; - master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1); + master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | + SPI_BPW_MASK(8); /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 0808cd56bf8d..77497be042a8 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -425,10 +425,6 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | SIRFSOC_SPI_FIFO_WIDTH_DWORD; break; - default: - dev_err(&spi->dev, "Bits per word %d not supported\n", - bits_per_word); - return -EINVAL; } if (!(spi->mode & SPI_CS_HIGH)) @@ -556,6 +552,8 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer; sspi->bitbang.master->setup = spi_sirfsoc_setup; master->bus_num = pdev->id; + master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) | + SPI_BPW_MASK(16) | SPI_BPW_MASK(32); sspi->bitbang.master->dev.of_node = pdev->dev.of_node; sspi->p = pinctrl_get_select_default(&pdev->dev); diff --git a/drivers/spi/spi-ti-ssp.c b/drivers/spi/spi-ti-ssp.c index 46992cab65f1..10606fcc6efc 100644 --- a/drivers/spi/spi-ti-ssp.c +++ b/drivers/spi/spi-ti-ssp.c @@ -237,14 +237,6 @@ static void ti_ssp_spi_work(struct work_struct *work) spin_unlock(&hw->lock); } -static int ti_ssp_spi_setup(struct spi_device *spi) -{ - if (spi->bits_per_word > 32) - return -EINVAL; - - return 0; -} - static int ti_ssp_spi_transfer(struct spi_device *spi, struct spi_message *m) { struct ti_ssp_spi *hw; @@ -269,12 +261,6 @@ static int ti_ssp_spi_transfer(struct spi_device *spi, struct spi_message *m) dev_err(&spi->dev, "invalid xfer, full duplex\n"); return -EINVAL; } - - if (t->bits_per_word > 32) { - dev_err(&spi->dev, "invalid xfer width %d\n", - t->bits_per_word); - return -EINVAL; - } } spin_lock(&hw->lock); @@ -337,8 +323,8 @@ static int ti_ssp_spi_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->num_chipselect = pdata->num_cs; master->mode_bits = MODE_BITS; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->flags = SPI_MASTER_HALF_DUPLEX; - master->setup = ti_ssp_spi_setup; master->transfer = ti_ssp_spi_transfer; error = spi_register_master(master); diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 35f60bd252dd..15cb39b0549e 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -472,11 +472,6 @@ static int pch_spi_setup(struct spi_device *pspi) dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__); } - if ((pspi->bits_per_word != 8) && (pspi->bits_per_word != 16)) { - dev_err(&pspi->dev, "%s Invalid bits per word\n", __func__); - return -EINVAL; - } - /* Check baud rate setting */ /* if baud rate of chip is greater than max we can support,return error */ @@ -537,17 +532,6 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg) /* if baud rate has been specified validate the same */ if (transfer->speed_hz > PCH_MAX_BAUDRATE) transfer->speed_hz = PCH_MAX_BAUDRATE; - - /* if bits per word has been specified validate the same */ - if (transfer->bits_per_word) { - if ((transfer->bits_per_word != 8) - && (transfer->bits_per_word != 16)) { - retval = -EINVAL; - dev_err(&pspi->dev, - "%s Invalid bits per word\n", __func__); - goto err_return_spinlock; - } - } } spin_unlock_irqrestore(&data->lock, flags); @@ -1442,6 +1426,7 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev) master->setup = pch_spi_setup; master->transfer = pch_spi_transfer; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); data->board_dat = board_dat; data->plat_dev = plat_dev; diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index adb853047926..cefd9568f098 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -116,17 +116,12 @@ static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c, static int txx9spi_setup(struct spi_device *spi) { struct txx9spi *c = spi_master_get_devdata(spi->master); - u8 bits_per_word; if (!spi->max_speed_hz || spi->max_speed_hz > c->max_speed_hz || spi->max_speed_hz < c->min_speed_hz) return -EINVAL; - bits_per_word = spi->bits_per_word; - if (bits_per_word != 8 && bits_per_word != 16) - return -EINVAL; - if (gpio_direction_output(spi->chip_select, !(spi->mode & SPI_CS_HIGH))) { dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n"); @@ -319,8 +314,6 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m) if (!t->tx_buf && !t->rx_buf && t->len) return -EINVAL; - if (bits_per_word != 8 && bits_per_word != 16) - return -EINVAL; if (t->len & ((bits_per_word >> 3) - 1)) return -EINVAL; if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz) @@ -411,6 +404,7 @@ static int txx9spi_probe(struct platform_device *dev) master->setup = txx9spi_setup; master->transfer = txx9spi_transfer; master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */ + master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); ret = spi_register_master(master); if (ret) diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c index 4d3ec8b9f479..4258c712ad3c 100644 --- a/drivers/spi/spi-xcomm.c +++ b/drivers/spi/spi-xcomm.c @@ -76,7 +76,7 @@ static int spi_xcomm_setup_transfer(struct spi_xcomm *spi_xcomm, { unsigned int speed; - if ((t->bits_per_word && t->bits_per_word != 8) || t->len > 62) + if (t->len > 62) return -EINVAL; speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz; @@ -209,14 +209,6 @@ static int spi_xcomm_transfer_one(struct spi_master *master, return status; } -static int spi_xcomm_setup(struct spi_device *spi) -{ - if (spi->bits_per_word != 8) - return -EINVAL; - - return 0; -} - static int spi_xcomm_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -233,8 +225,8 @@ static int spi_xcomm_probe(struct i2c_client *i2c, master->num_chipselect = 16; master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_3WIRE; + master->bits_per_word_mask = SPI_BPW_MASK(8); master->flags = SPI_MASTER_HALF_DUPLEX; - master->setup = spi_xcomm_setup; master->transfer_one_message = spi_xcomm_transfer_one; master->dev.of_node = i2c->dev.of_node; i2c_set_clientdata(i2c, master); diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index e1d769607425..f321bf95d7c3 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -232,21 +232,6 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi, return 0; } -static int xilinx_spi_setup(struct spi_device *spi) -{ - /* always return 0, we can not check the number of bits. - * There are cases when SPI setup is called before any driver is - * there, in that case the SPI core defaults to 8 bits, which we - * do not support in some cases. But if we return an error, the - * SPI device would not be registered and no driver can get hold of it - * When the driver is there, it will call SPI setup again with the - * correct number of bits per transfer. - * If a driver setups with the wrong bit number, it will fail when - * it tries to do a transfer - */ - return 0; -} - static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi) { u8 sr; @@ -377,7 +362,6 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, xspi->bitbang.chipselect = xilinx_spi_chipselect; xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; - xspi->bitbang.master->setup = xilinx_spi_setup; init_completion(&xspi->done); if (!request_mem_region(mem->start, resource_size(mem), From 6051426fd0538eac4e28c55a08e4f4fb1c709b65 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 30 May 2013 13:38:09 +0530 Subject: [PATCH 17/42] spi: spi-imx: Fix compilation error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix compilation error due to a typo introduced by commit 24778be20f ("spi: convert drivers to use bits_per_word_mask"). Without this patch we get the following build errors: drivers/spi/spi-imx.c: In function ‘spi_imx_setupxfer’: drivers/spi/spi-imx.c:703:2: warning: no return statement in function returning non-void [-Wreturn-type] drivers/spi/spi-imx.c: At top level: drivers/spi/spi-imx.c:705:9: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘->’ token drivers/spi/spi-imx.c:707:2: error: expected identifier or ‘(’ before ‘return’ drivers/spi/spi-imx.c:708:1: error: expected identifier or ‘(’ before ‘}’ token Signed-off-by: Sachin Kamat Cc: Stephen Warren Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index cb88eeb74cc4..982667383dd5 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -698,7 +698,7 @@ static int spi_imx_setupxfer(struct spi_device *spi, } else if (config.bpw <= 16) { spi_imx->rx = spi_imx_buf_rx_u16; spi_imx->tx = spi_imx_buf_tx_u16; - } + } else { spi_imx->rx = spi_imx_buf_rx_u32; spi_imx->tx = spi_imx_buf_tx_u32; } From 4dd9572abc224019a042b662fb0eececca283cb9 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 30 May 2013 09:59:39 -0600 Subject: [PATCH 18/42] spi: fix undefined behaviour in SPI_BPW_RANGE_MASK The parameters to SPI_BPW_RANGE_MASK() are in the range 1..32. If 32 is used as a parameter, part of the expression is "1 << 32". Since 32 is >= the size of the type in use, such a shift is undefined behaviour. Add macro SPI_BIT_MASK to Implement a special case and thus avoid undefined behaviour. Use this new macro rather than BIT() when implementing SPI_BPW_RANGE_MASK(). This fixes build warnings such as: drivers/spi/spi-gpio.c:446:2: warning: left shift count >= width of type [enabled by default] SPI_BPW_MASK() already avoids this, since its parameter is also in range 1..32, yet it only shifts by up to one less than the input parameter. Reported-by: Fengguang Wu Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 173725622252..3e9479134d9d 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -309,7 +309,8 @@ struct spi_master { /* bitmask of supported bits_per_word for transfers */ u32 bits_per_word_mask; #define SPI_BPW_MASK(bits) BIT((bits) - 1) -#define SPI_BPW_RANGE_MASK(min, max) ((BIT(max) - 1) - (BIT(min) - 1)) +#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0UL : (BIT(bits) - 1)) +#define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min)) /* other constraints relevant to this driver */ u16 flags; From eca8960a8e0f48dc62c1063bcc33a626455d766e Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 30 May 2013 09:59:40 -0600 Subject: [PATCH 19/42] spi: fix incorrect handling of min param in SPI_BPW_RANGE_MASK SPI_BPW_RANGE_MASK is intended to work by calculating two masks; one representing support for all bits up-to-and-including the "max" supported value, and one representing support for all bits up-to-but-not-including the "min" supported value, and then taking the difference between the two, resulting in a mask representing support for all bits between (inclusive) the min and max values. However, the second mask ended up representing all bits up-to-and- including rather up-to-but-not-including. Fix this bug. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 3e9479134d9d..28e440be1c07 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -310,7 +310,7 @@ struct spi_master { u32 bits_per_word_mask; #define SPI_BPW_MASK(bits) BIT((bits) - 1) #define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0UL : (BIT(bits) - 1)) -#define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min)) +#define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min - 1)) /* other constraints relevant to this driver */ u16 flags; From 51faed692b6a76870b53415307be54b39b5d4016 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 30 May 2013 09:59:41 -0600 Subject: [PATCH 20/42] spi: fix build break in spi-fsl-espi.c Fix a build error introduced by 24778be "spi: convert drivers to use bits_per_word_mask": drivers/spi/spi-fsl-espi.c:162:13: error: expected '=', ',', ';', 'asm' or '__attribute__' before '->' token Reported-by: Fengguang Wu Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 0ef05f198f22..6a74d7848d93 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -153,7 +153,7 @@ static int fsl_espi_setup_transfer(struct spi_device *spi, cs->get_tx = mpc8xxx_spi_tx_buf_u32; if (bits_per_word <= 8) { cs->rx_shift = 8 - bits_per_word; - } else + } else { cs->rx_shift = 16 - bits_per_word; if (spi->mode & SPI_LSB_FIRST) cs->get_tx = fsl_espi_tx_buf_lsb; From 8471090479df5aa0a439c1dd673c3d4904ea7c1d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 May 2013 13:29:07 +0530 Subject: [PATCH 21/42] spi: spi-s3c24xx: Remove redundant platform_set_drvdata() Setting platform data to NULL is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-s3c24xx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index 02d64603fcc5..68910b310152 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -667,8 +667,6 @@ static int s3c24xx_spi_remove(struct platform_device *dev) { struct s3c24xx_spi *hw = platform_get_drvdata(dev); - platform_set_drvdata(dev, NULL); - spi_bitbang_stop(&hw->bitbang); clk_disable(hw->clk); From 69a01719012735f931cd1ed6aa0ac63e2a237c99 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 May 2013 13:29:08 +0530 Subject: [PATCH 22/42] spi: spi-txx9: Remove redundant platform_set_drvdata() Setting platform data to NULL is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-txx9.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index adb853047926..4f2eecf1603b 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -425,7 +425,6 @@ exit: clk_disable(c->clk); clk_put(c->clk); } - platform_set_drvdata(dev, NULL); spi_master_put(master); return ret; } @@ -436,7 +435,6 @@ static int txx9spi_remove(struct platform_device *dev) struct txx9spi *c = spi_master_get_devdata(master); spi_unregister_master(master); - platform_set_drvdata(dev, NULL); destroy_workqueue(c->workqueue); clk_disable(c->clk); clk_put(c->clk); From 804ae4380d1e76f5d81272b8a3b765f5e02fe46e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 3 Jun 2013 15:24:53 +0200 Subject: [PATCH 23/42] spi: sirf: avoid uninitialized-use warning 24778be20 "spi: convert drivers to use bits_per_word_mask" removed the "default" statement in the spi_sirfsoc_setup_transfer switch, causing a new warning: drivers/spi/spi-sirf.c: In function 'spi_sirfsoc_setup_transfer': arch/arm/include/asm/io.h:90:2: warning: 'rxfifo_ctrl' may be used uninitialized in this function [-Wmaybe-uninitialized] asm volatile("str %1, %0" ^ drivers/spi/spi-sirf.c:364:19: note: 'rxfifo_ctrl' was declared here u32 txfifo_ctrl, rxfifo_ctrl; ^ The compiler has correctly identified that this case may happen, but since we know that things are horribly broken if bits_per_word is ever something other than the values we tested, calling BUG() is an appropriate action and tells the compiler that execution will not continue afterwards. Signed-off-by: Arnd Bergmann Cc: Stephen Warren Cc: Mark Brown Signed-off-by: Mark Brown --- drivers/spi/spi-sirf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 77497be042a8..e262736f9163 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -425,6 +425,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | SIRFSOC_SPI_FIFO_WIDTH_DWORD; break; + default: + BUG(); } if (!(spi->mode & SPI_CS_HIGH)) From 2f767a9f6b9d06a7e6a7b9b2ce0b6f0888ea15fa Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Fri, 31 May 2013 17:01:59 +0200 Subject: [PATCH 24/42] spi: atmel: convert to dma_request_slave_channel_compat() Use generic DMA DT helper. Platforms booting with or without DT populated are both supported. Based on Ludovic Desroches patchset "ARM: at91: move to generic DMA device tree binding" Signed-off-by: Richard Genoud Acked-by: Ludovic Desroches Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 42 ++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 380387a47b1d..ceda43c91142 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -424,10 +424,15 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as, return err; } -static bool filter(struct dma_chan *chan, void *slave) +static bool filter(struct dma_chan *chan, void *pdata) { - struct at_dma_slave *sl = slave; + struct atmel_spi_dma *sl_pdata = pdata; + struct at_dma_slave *sl; + if (!sl_pdata) + return false; + + sl = &sl_pdata->dma_slave; if (sl->dma_dev == chan->device->dev) { chan->private = sl; return true; @@ -438,24 +443,31 @@ static bool filter(struct dma_chan *chan, void *slave) static int atmel_spi_configure_dma(struct atmel_spi *as) { - struct at_dma_slave *sdata = &as->dma.dma_slave; struct dma_slave_config slave_config; + struct device *dev = &as->pdev->dev; int err; - if (sdata && sdata->dma_dev) { - dma_cap_mask_t mask; + dma_cap_mask_t mask; + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); - /* Try to grab two DMA channels */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - as->dma.chan_tx = dma_request_channel(mask, filter, sdata); - if (as->dma.chan_tx) - as->dma.chan_rx = - dma_request_channel(mask, filter, sdata); + as->dma.chan_tx = dma_request_slave_channel_compat(mask, filter, + &as->dma, + dev, "tx"); + if (!as->dma.chan_tx) { + dev_err(dev, + "DMA TX channel not available, SPI unable to use DMA\n"); + err = -EBUSY; + goto error; } - if (!as->dma.chan_rx || !as->dma.chan_tx) { - dev_err(&as->pdev->dev, - "DMA channel not available, SPI unable to use DMA\n"); + + as->dma.chan_rx = dma_request_slave_channel_compat(mask, filter, + &as->dma, + dev, "rx"); + + if (!as->dma.chan_rx) { + dev_err(dev, + "DMA RX channel not available, SPI unable to use DMA\n"); err = -EBUSY; goto error; } From c36e93a0bdc7df31543a6950454dbd26b56c9015 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Mon, 3 Jun 2013 14:03:49 +0200 Subject: [PATCH 25/42] spi: mpc512x: minor prep before feature change mechanical edits before changing functionality, to reduce diffs - rename variables to later tell remaining TX and RX apart - use size_t for the current TX and RX length (for better compatibility with the min() macro) - remove unused members from the master data (sysclk, eofbyte) - silence a checkpatch warning (braces around single statement) Signed-off-by: Gerhard Sittig Signed-off-by: Mark Brown --- drivers/spi/spi-mpc512x-psc.c | 43 ++++++++++++++++------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index dfddf336912d..759a937d5fa7 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -33,7 +33,6 @@ struct mpc512x_psc_spi { void (*cs_control)(struct spi_device *spi, bool on); - u32 sysclk; /* driver internal data */ struct mpc52xx_psc __iomem *psc; @@ -42,7 +41,6 @@ struct mpc512x_psc_spi { u8 bits_per_word; u8 busy; u32 mclk; - u8 eofbyte; struct workqueue_struct *workqueue; struct work_struct work; @@ -50,7 +48,7 @@ struct mpc512x_psc_spi { struct list_head queue; spinlock_t lock; /* Message queue lock */ - struct completion done; + struct completion txisrdone; }; /* controller state */ @@ -138,7 +136,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); struct mpc52xx_psc __iomem *psc = mps->psc; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; - size_t len = t->len; + size_t tx_len = t->len; u8 *tx_buf = (u8 *)t->tx_buf; u8 *rx_buf = (u8 *)t->rx_buf; @@ -152,58 +150,57 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, /* enable transmiter/receiver */ out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - while (len) { - int count; + while (tx_len) { + size_t txcount; int i; u8 data; size_t fifosz; - int rxcount; + size_t rxcount; /* * The number of bytes that can be sent at a time * depends on the fifo size. */ fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz)); - count = min(fifosz, len); + txcount = min(fifosz, tx_len); - for (i = count; i > 0; i--) { + for (i = txcount; i > 0; i--) { data = tx_buf ? *tx_buf++ : 0; - if (len == EOFBYTE && t->cs_change) + if (tx_len == EOFBYTE && t->cs_change) setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); out_8(&fifo->txdata_8, data); - len--; + tx_len--; } - INIT_COMPLETION(mps->done); + INIT_COMPLETION(mps->txisrdone); /* interrupt on tx fifo empty */ out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY); - wait_for_completion(&mps->done); + wait_for_completion(&mps->txisrdone); mdelay(1); - /* rx fifo should have count bytes in it */ + /* rx fifo should have txcount bytes in it */ rxcount = in_be32(&fifo->rxcnt); - if (rxcount != count) + if (rxcount != txcount) mdelay(1); rxcount = in_be32(&fifo->rxcnt); - if (rxcount != count) { + if (rxcount != txcount) { dev_warn(&spi->dev, "expected %d bytes in rx fifo " - "but got %d\n", count, rxcount); + "but got %d\n", txcount, rxcount); } - rxcount = min(rxcount, count); + rxcount = min(rxcount, txcount); for (i = rxcount; i > 0; i--) { data = in_8(&fifo->rxdata_8); if (rx_buf) *rx_buf++ = data; } - while (in_be32(&fifo->rxcnt)) { + while (in_be32(&fifo->rxcnt)) in_8(&fifo->rxdata_8); - } } /* disable transmiter/receiver and fifo interrupt */ out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); @@ -412,7 +409,7 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id) in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) { out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); out_be32(&fifo->tximr, 0); - complete(&mps->done); + complete(&mps->txisrdone); return IRQ_HANDLED; } return IRQ_NONE; @@ -444,11 +441,9 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, if (pdata == NULL) { mps->cs_control = mpc512x_spi_cs_control; - mps->sysclk = 0; master->bus_num = bus_num; } else { mps->cs_control = pdata->cs_control; - mps->sysclk = pdata->sysclk; master->bus_num = pdata->bus_num; master->num_chipselect = pdata->max_chipselect; } @@ -479,7 +474,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, goto free_irq; spin_lock_init(&mps->lock); - init_completion(&mps->done); + init_completion(&mps->txisrdone); INIT_WORK(&mps->work, mpc512x_psc_spi_work); INIT_LIST_HEAD(&mps->queue); From 5df24ea63d1eb1b3b0556817bdaf378c19f196ea Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Mon, 3 Jun 2013 14:03:50 +0200 Subject: [PATCH 26/42] spi: mpc512x: improve throughput in the RX/TX func change the MPC512x SPI controller's transmission routine to increase throughput: allow the RX byte counter to "lag behind" the TX byte counter while iterating over the transfer's data, only wait for the remaining RX bytes at the very end of the transfer this approach eliminates delays in the milliseconds range, transfer times for e.g. 16MB of SPI flash data dropped from 31s to 9s, correct operation was tested by continuously transferring and comparing data from an SPI flash (more than 200GB in some 45 hours) background information on the motivation: one might assume that all the RX data should have been received when the TX data was sent, given the fact that we are the SPI master and provide all of the clock, but in practise there's a difference the ISR is triggered when the TX FIFO became empty, while transmission of the last item still occurs (from the TX hold and shift registers), sampling RX data on the opposite clock edge compared to the TX data adds another delay (half a bit period), and RX data needs to propagate from the reception buffer to the RX FIFO depending on the specific SoC implementation to cut it short: a difference between TX and RX byte counters during transmission is not just acceptable but should be considered the regular case, only the very end of the transfer needs to make sure that all of the RX data was received before deasserting the chip select and telling the caller that transmission has completed Signed-off-by: Gerhard Sittig Signed-off-by: Mark Brown --- drivers/spi/spi-mpc512x-psc.c | 137 ++++++++++++++++++++++++++-------- 1 file changed, 105 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 759a937d5fa7..53c7899a8aba 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -137,6 +137,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, struct mpc52xx_psc __iomem *psc = mps->psc; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; size_t tx_len = t->len; + size_t rx_len = t->len; u8 *tx_buf = (u8 *)t->tx_buf; u8 *rx_buf = (u8 *)t->rx_buf; @@ -150,57 +151,129 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, /* enable transmiter/receiver */ out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - while (tx_len) { + while (rx_len || tx_len) { size_t txcount; - int i; u8 data; size_t fifosz; size_t rxcount; + int rxtries; /* - * The number of bytes that can be sent at a time - * depends on the fifo size. + * send the TX bytes in as large a chunk as possible + * but neither exceed the TX nor the RX FIFOs */ fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz)); txcount = min(fifosz, tx_len); + fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->rxsz)); + fifosz -= in_be32(&fifo->rxcnt) + 1; + txcount = min(fifosz, txcount); + if (txcount) { - for (i = txcount; i > 0; i--) { - data = tx_buf ? *tx_buf++ : 0; - if (tx_len == EOFBYTE && t->cs_change) - setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); - out_8(&fifo->txdata_8, data); - tx_len--; + /* fill the TX FIFO */ + while (txcount-- > 0) { + data = tx_buf ? *tx_buf++ : 0; + if (tx_len == EOFBYTE && t->cs_change) + setbits32(&fifo->txcmd, + MPC512x_PSC_FIFO_EOF); + out_8(&fifo->txdata_8, data); + tx_len--; + } + + /* have the ISR trigger when the TX FIFO is empty */ + INIT_COMPLETION(mps->txisrdone); + out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); + out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY); + wait_for_completion(&mps->txisrdone); } - INIT_COMPLETION(mps->txisrdone); + /* + * consume as much RX data as the FIFO holds, while we + * iterate over the transfer's TX data length + * + * only insist in draining all the remaining RX bytes + * when the TX bytes were exhausted (that's at the very + * end of this transfer, not when still iterating over + * the transfer's chunks) + */ + rxtries = 50; + do { - /* interrupt on tx fifo empty */ - out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); - out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY); + /* + * grab whatever was in the FIFO when we started + * looking, don't bother fetching what was added to + * the FIFO while we read from it -- we'll return + * here eventually and prefer sending out remaining + * TX data + */ + fifosz = in_be32(&fifo->rxcnt); + rxcount = min(fifosz, rx_len); + while (rxcount-- > 0) { + data = in_8(&fifo->rxdata_8); + if (rx_buf) + *rx_buf++ = data; + rx_len--; + } - wait_for_completion(&mps->txisrdone); + /* + * come back later if there still is TX data to send, + * bail out of the RX drain loop if all of the TX data + * was sent and all of the RX data was received (i.e. + * when the transmission has completed) + */ + if (tx_len) + break; + if (!rx_len) + break; - mdelay(1); + /* + * TX data transmission has completed while RX data + * is still pending -- that's a transient situation + * which depends on wire speed and specific + * hardware implementation details (buffering) yet + * should resolve very quickly + * + * just yield for a moment to not hog the CPU for + * too long when running SPI at low speed + * + * the timeout range is rather arbitrary and tries + * to balance throughput against system load; the + * chosen values result in a minimal timeout of 50 + * times 10us and thus work at speeds as low as + * some 20kbps, while the maximum timeout at the + * transfer's end could be 5ms _if_ nothing else + * ticks in the system _and_ RX data still wasn't + * received, which only occurs in situations that + * are exceptional; removing the unpredictability + * of the timeout either decreases throughput + * (longer timeouts), or puts more load on the + * system (fixed short timeouts) or requires the + * use of a timeout API instead of a counter and an + * unknown inner delay + */ + usleep_range(10, 100); - /* rx fifo should have txcount bytes in it */ - rxcount = in_be32(&fifo->rxcnt); - if (rxcount != txcount) - mdelay(1); - - rxcount = in_be32(&fifo->rxcnt); - if (rxcount != txcount) { - dev_warn(&spi->dev, "expected %d bytes in rx fifo " - "but got %d\n", txcount, rxcount); + } while (--rxtries > 0); + if (!tx_len && rx_len && !rxtries) { + /* + * not enough RX bytes even after several retries + * and the resulting rather long timeout? + */ + rxcount = in_be32(&fifo->rxcnt); + dev_warn(&spi->dev, + "short xfer, missing %zd RX bytes, FIFO level %zd\n", + rx_len, rxcount); } - rxcount = min(rxcount, txcount); - for (i = rxcount; i > 0; i--) { - data = in_8(&fifo->rxdata_8); - if (rx_buf) - *rx_buf++ = data; + /* + * drain and drop RX data which "should not be there" in + * the first place, for undisturbed transmission this turns + * into a NOP (except for the FIFO level fetch) + */ + if (!tx_len && !rx_len) { + while (in_be32(&fifo->rxcnt)) + in_8(&fifo->rxdata_8); } - while (in_be32(&fifo->rxcnt)) - in_8(&fifo->rxdata_8); + } /* disable transmiter/receiver and fifo interrupt */ out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); From 85085898ab0fefc6e181d3b495dc34034dda2fee Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Mon, 3 Jun 2013 14:03:51 +0200 Subject: [PATCH 27/42] spi: mpc512x: use the SPI subsystem's message queue the SPI subsystem recently grew support to queue messages before handing them to the SPI master, and erroneously emitted deprecation warnings when the SPI master's driver did not use the common logic (in fact the master might queue messages, but implement the queue in the master driver's source) [ 0.823015] mpc512x-psc-spi 80011400.psc: master is unqueued, this is deprecated [ 0.854913] mpc512x-psc-spi 80011500.psc: master is unqueued, this is deprecated this change makes the MPC512x PSC SPI driver use the SPI subsystem's support to queue SPI messages and removes the master driver's private code for the queue support Signed-off-by: Gerhard Sittig Signed-off-by: Mark Brown --- drivers/spi/spi-mpc512x-psc.c | 185 ++++++++++++++-------------------- 1 file changed, 74 insertions(+), 111 deletions(-) diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 53c7899a8aba..29fce6af5145 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -39,15 +38,8 @@ struct mpc512x_psc_spi { struct mpc512x_psc_fifo __iomem *fifo; unsigned int irq; u8 bits_per_word; - u8 busy; u32 mclk; - struct workqueue_struct *workqueue; - struct work_struct work; - - struct list_head queue; - spinlock_t lock; /* Message queue lock */ - struct completion txisrdone; }; @@ -134,7 +126,6 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, struct spi_transfer *t) { struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); - struct mpc52xx_psc __iomem *psc = mps->psc; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; size_t tx_len = t->len; size_t rx_len = t->len; @@ -144,13 +135,6 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, if (!tx_buf && !rx_buf && t->len) return -EINVAL; - /* Zero MR2 */ - in_8(&psc->mode); - out_8(&psc->mode, 0x0); - - /* enable transmiter/receiver */ - out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - while (rx_len || tx_len) { size_t txcount; u8 data; @@ -275,76 +259,90 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, } } - /* disable transmiter/receiver and fifo interrupt */ - out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); - out_be32(&fifo->tximr, 0); return 0; } -static void mpc512x_psc_spi_work(struct work_struct *work) +static int mpc512x_psc_spi_msg_xfer(struct spi_master *master, + struct spi_message *m) { - struct mpc512x_psc_spi *mps = container_of(work, - struct mpc512x_psc_spi, - work); + struct spi_device *spi; + unsigned cs_change; + int status; + struct spi_transfer *t; - spin_lock_irq(&mps->lock); - mps->busy = 1; - while (!list_empty(&mps->queue)) { - struct spi_message *m; - struct spi_device *spi; - struct spi_transfer *t = NULL; - unsigned cs_change; - int status; - - m = container_of(mps->queue.next, struct spi_message, queue); - list_del_init(&m->queue); - spin_unlock_irq(&mps->lock); - - spi = m->spi; - cs_change = 1; - status = 0; - list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->bits_per_word || t->speed_hz) { - status = mpc512x_psc_spi_transfer_setup(spi, t); - if (status < 0) - break; - } - - if (cs_change) - mpc512x_psc_spi_activate_cs(spi); - cs_change = t->cs_change; - - status = mpc512x_psc_spi_transfer_rxtx(spi, t); - if (status) + spi = m->spi; + cs_change = 1; + status = 0; + list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->bits_per_word || t->speed_hz) { + status = mpc512x_psc_spi_transfer_setup(spi, t); + if (status < 0) break; - m->actual_length += t->len; - - if (t->delay_usecs) - udelay(t->delay_usecs); - - if (cs_change) - mpc512x_psc_spi_deactivate_cs(spi); } - m->status = status; - m->complete(m->context); + if (cs_change) + mpc512x_psc_spi_activate_cs(spi); + cs_change = t->cs_change; - if (status || !cs_change) + status = mpc512x_psc_spi_transfer_rxtx(spi, t); + if (status) + break; + m->actual_length += t->len; + + if (t->delay_usecs) + udelay(t->delay_usecs); + + if (cs_change) mpc512x_psc_spi_deactivate_cs(spi); - - mpc512x_psc_spi_transfer_setup(spi, NULL); - - spin_lock_irq(&mps->lock); } - mps->busy = 0; - spin_unlock_irq(&mps->lock); + + m->status = status; + m->complete(m->context); + + if (status || !cs_change) + mpc512x_psc_spi_deactivate_cs(spi); + + mpc512x_psc_spi_transfer_setup(spi, NULL); + + spi_finalize_current_message(master); + return status; +} + +static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master) +{ + struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); + struct mpc52xx_psc __iomem *psc = mps->psc; + + dev_dbg(&master->dev, "%s()\n", __func__); + + /* Zero MR2 */ + in_8(&psc->mode); + out_8(&psc->mode, 0x0); + + /* enable transmitter/receiver */ + out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); + + return 0; +} + +static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master) +{ + struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); + struct mpc52xx_psc __iomem *psc = mps->psc; + struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; + + dev_dbg(&master->dev, "%s()\n", __func__); + + /* disable transmitter/receiver and fifo interrupt */ + out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); + out_be32(&fifo->tximr, 0); + + return 0; } static int mpc512x_psc_spi_setup(struct spi_device *spi) { - struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); struct mpc512x_psc_spi_cs *cs = spi->controller_state; - unsigned long flags; int ret; if (spi->bits_per_word % 8) @@ -373,28 +371,6 @@ static int mpc512x_psc_spi_setup(struct spi_device *spi) cs->bits_per_word = spi->bits_per_word; cs->speed_hz = spi->max_speed_hz; - spin_lock_irqsave(&mps->lock, flags); - if (!mps->busy) - mpc512x_psc_spi_deactivate_cs(spi); - spin_unlock_irqrestore(&mps->lock, flags); - - return 0; -} - -static int mpc512x_psc_spi_transfer(struct spi_device *spi, - struct spi_message *m) -{ - struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); - unsigned long flags; - - m->actual_length = 0; - m->status = -EINPROGRESS; - - spin_lock_irqsave(&mps->lock, flags); - list_add_tail(&m->queue, &mps->queue); - queue_work(mps->workqueue, &mps->work); - spin_unlock_irqrestore(&mps->lock, flags); - return 0; } @@ -477,7 +453,7 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id) struct mpc512x_psc_spi *mps = (struct mpc512x_psc_spi *)dev_id; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; - /* clear interrupt and wake up the work queue */ + /* clear interrupt and wake up the rx/tx routine */ if (in_be32(&fifo->txisr) & in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) { out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); @@ -523,7 +499,9 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; master->setup = mpc512x_psc_spi_setup; - master->transfer = mpc512x_psc_spi_transfer; + master->prepare_transfer_hardware = mpc512x_psc_spi_prep_xfer_hw; + master->transfer_one_message = mpc512x_psc_spi_msg_xfer; + master->unprepare_transfer_hardware = mpc512x_psc_spi_unprep_xfer_hw; master->cleanup = mpc512x_psc_spi_cleanup; master->dev.of_node = dev->of_node; @@ -541,31 +519,18 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, "mpc512x-psc-spi", mps); if (ret) goto free_master; + init_completion(&mps->txisrdone); ret = mpc512x_psc_spi_port_config(master, mps); if (ret < 0) goto free_irq; - spin_lock_init(&mps->lock); - init_completion(&mps->txisrdone); - INIT_WORK(&mps->work, mpc512x_psc_spi_work); - INIT_LIST_HEAD(&mps->queue); - - mps->workqueue = - create_singlethread_workqueue(dev_name(master->dev.parent)); - if (mps->workqueue == NULL) { - ret = -EBUSY; - goto free_irq; - } - ret = spi_register_master(master); if (ret < 0) - goto unreg_master; + goto free_irq; return ret; -unreg_master: - destroy_workqueue(mps->workqueue); free_irq: free_irq(mps->irq, mps); free_master: @@ -581,8 +546,6 @@ static int mpc512x_psc_spi_do_remove(struct device *dev) struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); - flush_workqueue(mps->workqueue); - destroy_workqueue(mps->workqueue); spi_unregister_master(master); free_irq(mps->irq, mps); if (mps->psc) From 082339bc63cccf8ea49b1f3cf4ee39ce00742849 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 4 Jun 2013 16:02:36 +0200 Subject: [PATCH 28/42] spi: spi-xilinx: Add run run-time endian detection Do not load endian value from platform data and rather autodetect it. Signed-off-by: Michal Simek Signed-off-by: Mark Brown --- drivers/mfd/timberdale.c | 1 - drivers/spi/spi-xilinx.c | 29 +++++++++++++++++++++-------- include/linux/spi/xilinx_spi.h | 1 - 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index 59e0ee247e86..0c1fcbc23d04 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -145,7 +145,6 @@ static struct spi_board_info timberdale_spi_8bit_board_info[] = { static struct xspi_platform_data timberdale_xspi_platform_data = { .num_chipselect = 3, - .little_endian = true, /* bits per word and devices will be filled in runtime depending * on the HW config */ diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index e1d769607425..bb6ae4ee7dea 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -30,6 +30,7 @@ */ #define XSPI_CR_OFFSET 0x60 /* Control Register */ +#define XSPI_CR_LOOP 0x01 #define XSPI_CR_ENABLE 0x02 #define XSPI_CR_MASTER_MODE 0x04 #define XSPI_CR_CPOL 0x08 @@ -359,11 +360,12 @@ static const struct of_device_id xilinx_spi_of_match[] = { MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, - u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word) + u32 irq, s16 bus_num, int num_cs, int bits_per_word) { struct spi_master *master; struct xilinx_spi *xspi; int ret; + u32 tmp; master = spi_alloc_master(dev, sizeof(struct xilinx_spi)); if (!master) @@ -396,13 +398,25 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, xspi->mem = *mem; xspi->irq = irq; - if (little_endian) { - xspi->read_fn = xspi_read32; - xspi->write_fn = xspi_write32; - } else { + + /* + * Detect endianess on the IP via loop bit in CR. Detection + * must be done before reset is sent because incorrect reset + * value generates error interrupt. + * Setup little endian helper functions first and try to use them + * and check if bit was correctly setup or not. + */ + xspi->read_fn = xspi_read32; + xspi->write_fn = xspi_write32; + + xspi->write_fn(XSPI_CR_LOOP, xspi->regs + XSPI_CR_OFFSET); + tmp = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); + tmp &= XSPI_CR_LOOP; + if (tmp != XSPI_CR_LOOP) { xspi->read_fn = xspi_read32_be; xspi->write_fn = xspi_write32_be; } + xspi->bits_per_word = bits_per_word; if (xspi->bits_per_word == 8) { xspi->tx_fn = xspi_tx8; @@ -466,14 +480,13 @@ static int xilinx_spi_probe(struct platform_device *dev) { struct xspi_platform_data *pdata; struct resource *r; - int irq, num_cs = 0, little_endian = 0, bits_per_word = 8; + int irq, num_cs = 0, bits_per_word = 8; struct spi_master *master; u8 i; pdata = dev->dev.platform_data; if (pdata) { num_cs = pdata->num_chipselect; - little_endian = pdata->little_endian; bits_per_word = pdata->bits_per_word; } @@ -505,7 +518,7 @@ static int xilinx_spi_probe(struct platform_device *dev) return -ENXIO; master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs, - little_endian, bits_per_word); + bits_per_word); if (!master) return -ENODEV; diff --git a/include/linux/spi/xilinx_spi.h b/include/linux/spi/xilinx_spi.h index 6f17278810b0..333ecdfee0d9 100644 --- a/include/linux/spi/xilinx_spi.h +++ b/include/linux/spi/xilinx_spi.h @@ -11,7 +11,6 @@ */ struct xspi_platform_data { u16 num_chipselect; - bool little_endian; u8 bits_per_word; struct spi_board_info *devices; u8 num_devices; From 913b19660e166e718d419cccd753c3990881f17c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 May 2013 17:17:49 +0530 Subject: [PATCH 29/42] spi: spi-xilinx: Remove redundant platform_set_drvdata() Setting platform data to NULL is not necessary. Also fixes the following sparse warning: drivers/spi/spi-xilinx.c:508:35: warning: Using plain integer as NULL pointer Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index bb6ae4ee7dea..b07b004cea13 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -534,7 +534,6 @@ static int xilinx_spi_probe(struct platform_device *dev) static int xilinx_spi_remove(struct platform_device *dev) { xilinx_spi_deinit(platform_get_drvdata(dev)); - platform_set_drvdata(dev, 0); return 0; } From f5d8ee3f15dd71837ca672c3743b1bca5a0c013a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 May 2013 17:17:48 +0530 Subject: [PATCH 30/42] spi: spi-topcliff-pch: Fix sparse warnings Fixes the following type of warnings: drivers/spi/spi-topcliff-pch.c:370:52: warning: Using plain integer as NULL pointer Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-topcliff-pch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 35f60bd252dd..0c8071a618c5 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -367,7 +367,7 @@ static irqreturn_t pch_spi_handler(int irq, void *dev_id) if (reg_spsr_val & SPSR_ORF_BIT) { dev_err(&board_dat->pdev->dev, "%s Over run error\n", __func__); - if (data->current_msg->complete != 0) { + if (data->current_msg->complete) { data->transfer_complete = true; data->current_msg->status = -EIO; data->current_msg->complete(data->current_msg->context); @@ -659,7 +659,7 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw) list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) { pmsg->status = -ENOMEM; - if (pmsg->complete != 0) + if (pmsg->complete) pmsg->complete(pmsg->context); /* delete from queue */ @@ -709,7 +709,7 @@ static void pch_spi_nomore_transfer(struct pch_spi_data *data) * [To the spi core..indicating end of transfer] */ data->current_msg->status = 0; - if (data->current_msg->complete != 0) { + if (data->current_msg->complete) { dev_dbg(&data->master->dev, "%s:Invoking callback of SPI core\n", __func__); data->current_msg->complete(data->current_msg->context); @@ -1202,7 +1202,7 @@ static void pch_spi_process_messages(struct work_struct *pwork) list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) { pmsg->status = -EIO; - if (pmsg->complete != 0) { + if (pmsg->complete) { spin_unlock(&data->lock); pmsg->complete(pmsg->context); spin_lock(&data->lock); From d08643237382bb0107a2d03b4e1986852414aa85 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 May 2013 17:17:47 +0530 Subject: [PATCH 31/42] spi: spi-fsl-lib: Make mpc8xxx_spi_work static 'mpc8xxx_spi_work' is used only in this file. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c index a91db0e57b23..e947f2d1b2f5 100644 --- a/drivers/spi/spi-fsl-lib.c +++ b/drivers/spi/spi-fsl-lib.c @@ -61,7 +61,7 @@ struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata) return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata); } -void mpc8xxx_spi_work(struct work_struct *work) +static void mpc8xxx_spi_work(struct work_struct *work) { struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi, work); From 26cb3bb14950ee017f311f3bf1ae82f95ee0be64 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 May 2013 13:29:06 +0530 Subject: [PATCH 32/42] spi: spi-nuc900: Remove redundant platform_set_drvdata() Setting platform data to NULL is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-nuc900.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index b3f9ec83ef73..150d85453c27 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -459,8 +459,6 @@ static int nuc900_spi_remove(struct platform_device *dev) free_irq(hw->irq, hw); - platform_set_drvdata(dev, NULL); - spi_bitbang_stop(&hw->bitbang); clk_disable(hw->clk); From e33d085d11e54bc9fb07b2555cd104d8e7b3089b Mon Sep 17 00:00:00 2001 From: "dan.carpenter@oracle.com" Date: Sun, 9 Jun 2013 16:07:28 +0300 Subject: [PATCH 33/42] spi: spi-xilinx: cleanup a check in xilinx_spi_txrx_bufs() '!' has higher precedence than comparisons so the original condition is equivalent to "if (xspi->remaining_bytes == 0)". This makes the static checkers complain. xspi->remaining_bytes is signed and from looking at the code briefly, I think it might be able to go negative. I suspect that going negative may cause a bug, but I don't have the hardware and can't test. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 34d18dcfa0db..109a535b639c 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -315,7 +315,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) } /* See if there is more data to send */ - if (!xspi->remaining_bytes > 0) + if (xspi->remaining_bytes <= 0) break; } From 56cd5c1578135120d73a7054140855728f8cca36 Mon Sep 17 00:00:00 2001 From: Illia Smyrnov Date: Fri, 14 Jun 2013 19:12:07 +0300 Subject: [PATCH 34/42] spi: omap2-mcspi: Move bytes per word calculation to the function Introduce mcspi_bytes_per_word function as replacement for the next code fragment: int c = (word_len <= 8) ? 1 : (word_len <= 16) ? 2 : /* word_len <= 32 */ 4; This code used 2 times in current driver code and will be used 2 times in the next FIFO buffer support patch. Replace it with inline function with clear name to improve code legibility. Signed-off-by: Illia Smyrnov Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 000922abcb87..5a93a0df551f 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -186,6 +186,16 @@ static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val) mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); } +static inline int mcspi_bytes_per_word(int word_len) +{ + if (word_len <= 8) + return 1; + else if (word_len <= 16) + return 2; + else /* word_len <= 32 */ + return 4; +} + static void omap2_mcspi_set_dma_req(const struct spi_device *spi, int is_read, int enable) { @@ -432,10 +442,9 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, else /* word_len <= 32 */ ((u32 *)xfer->rx_buf)[elements++] = w; } else { + int bytes_per_word = mcspi_bytes_per_word(word_len); dev_err(&spi->dev, "DMA RX penultimate word empty"); - count -= (word_len <= 8) ? 2 : - (word_len <= 16) ? 4 : - /* word_len <= 32 */ 8; + count -= (bytes_per_word << 1); omap2_mcspi_set_enable(spi, 1); return count; } @@ -453,9 +462,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, ((u32 *)xfer->rx_buf)[elements] = w; } else { dev_err(&spi->dev, "DMA RX last word empty"); - count -= (word_len <= 8) ? 1 : - (word_len <= 16) ? 2 : - /* word_len <= 32 */ 4; + count -= mcspi_bytes_per_word(word_len); } omap2_mcspi_set_enable(spi, 1); return count; From d33f473dcd8e69321f001ba330d648f475b504c9 Mon Sep 17 00:00:00 2001 From: Illia Smyrnov Date: Mon, 17 Jun 2013 16:31:06 +0300 Subject: [PATCH 35/42] spi: omap2-mcspi: Add FIFO buffer support The MCSPI controller has a built-in FIFO buffer to unload the DMA or interrupt handler and improve data throughput. This patch adds FIFO buffer support for SPI transfers in DMA mode. For SPI transfers in DMA mode, the largest possible FIFO buffer size will be calculated and set up. The FIFO won't be used for the SPI transfers in DMA mode if: calculated FIFO buffer size is less then 2 bytes or the FIFO buffer size isn't multiple of the SPI word length. Signed-off-by: Illia Smyrnov Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 147 ++++++++++++++++++++++++++++++---- 1 file changed, 130 insertions(+), 17 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 5a93a0df551f..6802806d1f18 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -38,12 +38,15 @@ #include #include #include +#include #include #include #define OMAP2_MCSPI_MAX_FREQ 48000000 +#define OMAP2_MCSPI_MAX_FIFODEPTH 64 +#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF #define SPI_AUTOSUSPEND_TIMEOUT 2000 #define OMAP2_MCSPI_REVISION 0x00 @@ -53,6 +56,7 @@ #define OMAP2_MCSPI_WAKEUPENABLE 0x20 #define OMAP2_MCSPI_SYST 0x24 #define OMAP2_MCSPI_MODULCTRL 0x28 +#define OMAP2_MCSPI_XFERLEVEL 0x7c /* per-channel banks, 0x14 bytes each, first is: */ #define OMAP2_MCSPI_CHCONF0 0x2c @@ -62,6 +66,7 @@ #define OMAP2_MCSPI_RX0 0x3c /* per-register bitmasks: */ +#define OMAP2_MCSPI_IRQSTATUS_EOW BIT(17) #define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0) #define OMAP2_MCSPI_MODULCTRL_MS BIT(2) @@ -82,10 +87,13 @@ #define OMAP2_MCSPI_CHCONF_IS BIT(18) #define OMAP2_MCSPI_CHCONF_TURBO BIT(19) #define OMAP2_MCSPI_CHCONF_FORCE BIT(20) +#define OMAP2_MCSPI_CHCONF_FFET BIT(27) +#define OMAP2_MCSPI_CHCONF_FFER BIT(28) #define OMAP2_MCSPI_CHSTAT_RXS BIT(0) #define OMAP2_MCSPI_CHSTAT_TXS BIT(1) #define OMAP2_MCSPI_CHSTAT_EOT BIT(2) +#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3) #define OMAP2_MCSPI_CHCTRL_EN BIT(0) @@ -128,6 +136,7 @@ struct omap2_mcspi { struct omap2_mcspi_dma *dma_channels; struct device *dev; struct omap2_mcspi_regs ctx; + int fifo_depth; unsigned int pin_dir:1; }; @@ -257,6 +266,58 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master) ctx->modulctrl = l; } +static void omap2_mcspi_set_fifo(const struct spi_device *spi, + struct spi_transfer *t, int enable) +{ + struct spi_master *master = spi->master; + struct omap2_mcspi_cs *cs = spi->controller_state; + struct omap2_mcspi *mcspi; + unsigned int wcnt; + int fifo_depth, bytes_per_word; + u32 chconf, xferlevel; + + mcspi = spi_master_get_devdata(master); + + chconf = mcspi_cached_chconf0(spi); + if (enable) { + bytes_per_word = mcspi_bytes_per_word(cs->word_len); + if (t->len % bytes_per_word != 0) + goto disable_fifo; + + fifo_depth = gcd(t->len, OMAP2_MCSPI_MAX_FIFODEPTH); + if (fifo_depth < 2 || fifo_depth % bytes_per_word != 0) + goto disable_fifo; + + wcnt = t->len / bytes_per_word; + if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT) + goto disable_fifo; + + xferlevel = wcnt << 16; + if (t->rx_buf != NULL) { + chconf |= OMAP2_MCSPI_CHCONF_FFER; + xferlevel |= (fifo_depth - 1) << 8; + } else { + chconf |= OMAP2_MCSPI_CHCONF_FFET; + xferlevel |= fifo_depth - 1; + } + + mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, xferlevel); + mcspi_write_chconf0(spi, chconf); + mcspi->fifo_depth = fifo_depth; + + return; + } + +disable_fifo: + if (t->rx_buf != NULL) + chconf &= ~OMAP2_MCSPI_CHCONF_FFER; + else + chconf &= ~OMAP2_MCSPI_CHCONF_FFET; + + mcspi_write_chconf0(spi, chconf); + mcspi->fifo_depth = 0; +} + static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) { struct spi_master *spi_cntrl = mcspi->master; @@ -373,7 +434,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, { struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *mcspi_dma; - unsigned int count; + unsigned int count, dma_count; u32 l; int elements = 0; int word_len, element_count; @@ -381,6 +442,11 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; count = xfer->len; + dma_count = xfer->len; + + if (mcspi->fifo_depth == 0) + dma_count -= es; + word_len = cs->word_len; l = mcspi_cached_chconf0(spi); @@ -394,16 +460,15 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, if (mcspi_dma->dma_rx) { struct dma_async_tx_descriptor *tx; struct scatterlist sg; - size_t len = xfer->len - es; dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); - if (l & OMAP2_MCSPI_CHCONF_TURBO) - len -= es; + if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0) + dma_count -= es; sg_init_table(&sg, 1); sg_dma_address(&sg) = xfer->rx_dma; - sg_dma_len(&sg) = len; + sg_dma_len(&sg) = dma_count; tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | @@ -423,6 +488,10 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, wait_for_completion(&mcspi_dma->dma_rx_completion); dma_unmap_single(mcspi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE); + + if (mcspi->fifo_depth > 0) + return count; + omap2_mcspi_set_enable(spi, 0); elements = element_count - 1; @@ -481,7 +550,10 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) struct dma_slave_config cfg; enum dma_slave_buswidth width; unsigned es; + u32 burst; void __iomem *chstat_reg; + void __iomem *irqstat_reg; + int wait_res; mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; @@ -499,19 +571,27 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) es = 4; } + count = xfer->len; + burst = 1; + + if (mcspi->fifo_depth > 0) { + if (count > mcspi->fifo_depth) + burst = mcspi->fifo_depth / es; + else + burst = count / es; + } + memset(&cfg, 0, sizeof(cfg)); cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0; cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; cfg.src_addr_width = width; cfg.dst_addr_width = width; - cfg.src_maxburst = 1; - cfg.dst_maxburst = 1; + cfg.src_maxburst = burst; + cfg.dst_maxburst = burst; rx = xfer->rx_buf; tx = xfer->tx_buf; - count = xfer->len; - if (tx != NULL) omap2_mcspi_tx_dma(spi, xfer, cfg); @@ -519,18 +599,38 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) count = omap2_mcspi_rx_dma(spi, xfer, cfg, es); if (tx != NULL) { - chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; wait_for_completion(&mcspi_dma->dma_tx_completion); dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE); + if (mcspi->fifo_depth > 0) { + irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS; + + if (mcspi_wait_for_reg_bit(irqstat_reg, + OMAP2_MCSPI_IRQSTATUS_EOW) < 0) + dev_err(&spi->dev, "EOW timed out\n"); + + mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS, + OMAP2_MCSPI_IRQSTATUS_EOW); + } + /* for TX_ONLY mode, be sure all words have shifted out */ if (rx == NULL) { - if (mcspi_wait_for_reg_bit(chstat_reg, - OMAP2_MCSPI_CHSTAT_TXS) < 0) - dev_err(&spi->dev, "TXS timed out\n"); - else if (mcspi_wait_for_reg_bit(chstat_reg, - OMAP2_MCSPI_CHSTAT_EOT) < 0) + chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; + if (mcspi->fifo_depth > 0) { + wait_res = mcspi_wait_for_reg_bit(chstat_reg, + OMAP2_MCSPI_CHSTAT_TXFFE); + if (wait_res < 0) + dev_err(&spi->dev, "TXFFE timed out\n"); + } else { + wait_res = mcspi_wait_for_reg_bit(chstat_reg, + OMAP2_MCSPI_CHSTAT_TXS); + if (wait_res < 0) + dev_err(&spi->dev, "TXS timed out\n"); + } + if (wait_res >= 0 && + (mcspi_wait_for_reg_bit(chstat_reg, + OMAP2_MCSPI_CHSTAT_EOT) < 0)) dev_err(&spi->dev, "EOT timed out\n"); } } @@ -957,7 +1057,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) cs = spi->controller_state; cd = spi->controller_data; - omap2_mcspi_set_enable(spi, 1); + omap2_mcspi_set_enable(spi, 0); list_for_each_entry(t, &m->transfers, transfer_list) { if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { status = -EINVAL; @@ -1005,6 +1105,12 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) if (t->len) { unsigned count; + if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && + (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)) + omap2_mcspi_set_fifo(spi, t, 1); + + omap2_mcspi_set_enable(spi, 1); + /* RX_ONLY mode needs dummy data in TX reg */ if (t->tx_buf == NULL) __raw_writel(0, cs->base @@ -1031,6 +1137,11 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) omap2_mcspi_force_cs(spi, 0); cs_active = 0; } + + omap2_mcspi_set_enable(spi, 0); + + if (mcspi->fifo_depth > 0) + omap2_mcspi_set_fifo(spi, t, 0); } /* Restore defaults if they were overriden */ if (par_override) { @@ -1051,8 +1162,10 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) omap2_mcspi_set_enable(spi, 0); - m->status = status; + if (mcspi->fifo_depth > 0 && t) + omap2_mcspi_set_fifo(spi, t, 0); + m->status = status; } static int omap2_mcspi_transfer_one_message(struct spi_master *master, From 7e9955567eadb83642be55e6ae5853412dd48d14 Mon Sep 17 00:00:00 2001 From: Girish K S Date: Mon, 20 May 2013 12:21:32 +0530 Subject: [PATCH 36/42] spi: s3c64xx: added support for polling mode The 64xx spi driver supports partial polling mode. Only the last chunk of the transfer length is transferred or recieved in polling mode. Some SoC's that adopt this controller might not have have dma interface. This patch adds support for complete polling mode and gives flexibity for the user to select poll/dma mode. Signed-off-by: Girish K S Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 153 ++++++++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 49 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 5000586cb98d..0a806924b906 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -39,6 +39,7 @@ #endif #define MAX_SPI_PORTS 3 +#define S3C64XX_SPI_QUIRK_POLL (1 << 0) /* Registers and bit-fields */ @@ -130,6 +131,7 @@ #define S3C64XX_SPI_TRAILCNT S3C64XX_SPI_MAX_TRAILCNT #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) +#define is_polling(x) (x->port_conf->quirks & S3C64XX_SPI_QUIRK_POLL) #define RXBUSY (1<<2) #define TXBUSY (1<<3) @@ -158,6 +160,7 @@ struct s3c64xx_spi_port_config { int fifo_lvl_mask[MAX_SPI_PORTS]; int rx_lvl_offset; int tx_st_done; + int quirks; bool high_speed; bool clk_from_cmu; }; @@ -344,8 +347,12 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) { struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi); - /* Acquire DMA channels */ - while (!acquire_dma(sdd)) + /* + * If DMA resource was not available during + * probe, no need to continue with dma requests + * else Acquire DMA channels + */ + while (!is_polling(sdd) && !acquire_dma(sdd)) usleep_range(10000, 11000); pm_runtime_get_sync(&sdd->pdev->dev); @@ -358,9 +365,12 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi); /* Free DMA channels */ - sdd->ops->release((enum dma_ch)sdd->rx_dma.ch, &s3c64xx_spi_dma_client); - sdd->ops->release((enum dma_ch)sdd->tx_dma.ch, &s3c64xx_spi_dma_client); - + if (!is_polling(sdd)) { + sdd->ops->release((enum dma_ch)sdd->rx_dma.ch, + &s3c64xx_spi_dma_client); + sdd->ops->release((enum dma_ch)sdd->tx_dma.ch, + &s3c64xx_spi_dma_client); + } pm_runtime_put(&sdd->pdev->dev); return 0; @@ -464,8 +474,10 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi); /* Free DMA channels */ - dma_release_channel(sdd->rx_dma.ch); - dma_release_channel(sdd->tx_dma.ch); + if (!is_polling(sdd)) { + dma_release_channel(sdd->rx_dma.ch); + dma_release_channel(sdd->tx_dma.ch); + } pm_runtime_put(&sdd->pdev->dev); return 0; @@ -566,6 +578,30 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, cs = spi->controller_data; gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); + + /* Start the signals */ + writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); +} + +static u32 wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, + int timeout_ms) +{ + void __iomem *regs = sdd->regs; + unsigned long val = 1; + u32 status; + + /* max fifo depth available */ + u32 max_fifo = (FIFO_LVL_MASK(sdd) >> 1) + 1; + + if (timeout_ms) + val = msecs_to_loops(timeout_ms); + + do { + status = readl(regs + S3C64XX_SPI_STATUS); + } while (RX_FIFO_LVL(status, sdd) < max_fifo && --val); + + /* return the actual received data length */ + return RX_FIFO_LVL(status, sdd); } static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, @@ -590,20 +626,19 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, } while (RX_FIFO_LVL(status, sdd) < xfer->len && --val); } - if (!val) - return -EIO; - if (dma_mode) { u32 status; /* + * If the previous xfer was completed within timeout, then + * proceed further else return -EIO. * DmaTx returns after simply writing data in the FIFO, * w/o waiting for real transmission on the bus to finish. * DmaRx returns only after Dma read data from FIFO which * needs bus transmission to finish, so we don't worry if * Xfer involved Rx(with or without Tx). */ - if (xfer->rx_buf == NULL) { + if (val && !xfer->rx_buf) { val = msecs_to_loops(10); status = readl(regs + S3C64XX_SPI_STATUS); while ((TX_FIFO_LVL(status, sdd) @@ -613,30 +648,53 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, status = readl(regs + S3C64XX_SPI_STATUS); } - if (!val) - return -EIO; } + + /* If timed out while checking rx/tx status return error */ + if (!val) + return -EIO; } else { + int loops; + u32 cpy_len; + u8 *buf; + /* If it was only Tx */ - if (xfer->rx_buf == NULL) { + if (!xfer->rx_buf) { sdd->state &= ~TXBUSY; return 0; } - switch (sdd->cur_bpw) { - case 32: - ioread32_rep(regs + S3C64XX_SPI_RX_DATA, - xfer->rx_buf, xfer->len / 4); - break; - case 16: - ioread16_rep(regs + S3C64XX_SPI_RX_DATA, - xfer->rx_buf, xfer->len / 2); - break; - default: - ioread8_rep(regs + S3C64XX_SPI_RX_DATA, - xfer->rx_buf, xfer->len); - break; - } + /* + * If the receive length is bigger than the controller fifo + * size, calculate the loops and read the fifo as many times. + * loops = length / max fifo size (calculated by using the + * fifo mask). + * For any size less than the fifo size the below code is + * executed atleast once. + */ + loops = xfer->len / ((FIFO_LVL_MASK(sdd) >> 1) + 1); + buf = xfer->rx_buf; + do { + /* wait for data to be received in the fifo */ + cpy_len = wait_for_timeout(sdd, (loops ? ms : 0)); + + switch (sdd->cur_bpw) { + case 32: + ioread32_rep(regs + S3C64XX_SPI_RX_DATA, + buf, cpy_len / 4); + break; + case 16: + ioread16_rep(regs + S3C64XX_SPI_RX_DATA, + buf, cpy_len / 2); + break; + default: + ioread8_rep(regs + S3C64XX_SPI_RX_DATA, + buf, cpy_len); + break; + } + + buf = buf + cpy_len; + } while (loops--); sdd->state &= ~RXBUSY; } @@ -652,6 +710,9 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, sdd->tgl_spi = NULL; gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); + + /* Quiese the signals */ + writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); } static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) @@ -733,7 +794,7 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, struct device *dev = &sdd->pdev->dev; struct spi_transfer *xfer; - if (msg->is_dma_mapped) + if (is_polling(sdd) || msg->is_dma_mapped) return 0; /* First mark all xfer unmapped */ @@ -782,7 +843,7 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, struct device *dev = &sdd->pdev->dev; struct spi_transfer *xfer; - if (msg->is_dma_mapped) + if (is_polling(sdd) || msg->is_dma_mapped) return; list_for_each_entry(xfer, &msg->transfers, transfer_list) { @@ -861,8 +922,9 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, /* Polling method for xfers not bigger than FIFO capacity */ use_dma = 0; - if (sdd->rx_dma.ch && sdd->tx_dma.ch && - (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1))) + if (!is_polling(sdd) && + (sdd->rx_dma.ch && sdd->tx_dma.ch && + (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1)))) use_dma = 1; spin_lock_irqsave(&sdd->lock, flags); @@ -876,17 +938,10 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, /* Slave Select */ enable_cs(sdd, spi); - /* Start the signals */ - writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); - spin_unlock_irqrestore(&sdd->lock, flags); status = wait_for_xfer(sdd, xfer, use_dma); - /* Quiese the signals */ - writel(S3C64XX_SPI_SLAVE_SIG_INACT, - sdd->regs + S3C64XX_SPI_SLAVE_SEL); - if (status) { dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n", xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, @@ -1287,19 +1342,19 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) if (!sdd->pdev->dev.of_node) { res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (!res) { - dev_err(&pdev->dev, "Unable to get SPI tx dma " - "resource\n"); - return -ENXIO; - } - sdd->tx_dma.dmach = res->start; + dev_warn(&pdev->dev, "Unable to get SPI tx dma " + "resource. Switching to poll mode\n"); + sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL; + } else + sdd->tx_dma.dmach = res->start; res = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (!res) { - dev_err(&pdev->dev, "Unable to get SPI rx dma " - "resource\n"); - return -ENXIO; - } - sdd->rx_dma.dmach = res->start; + dev_warn(&pdev->dev, "Unable to get SPI rx dma " + "resource. Switching to poll mode\n"); + sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL; + } else + sdd->rx_dma.dmach = res->start; } sdd->tx_dma.direction = DMA_MEM_TO_DEV; From 796170733e50405e3039eacdf5cfb2f08f3eb9ba Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 19 Jun 2013 19:12:39 +0100 Subject: [PATCH 37/42] spi/s3c64xx: Make wait_for_timeout() function name less generic Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 0a806924b906..70b221355400 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -583,7 +583,7 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); } -static u32 wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, +static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, int timeout_ms) { void __iomem *regs = sdd->regs; @@ -676,7 +676,8 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, buf = xfer->rx_buf; do { /* wait for data to be received in the fifo */ - cpy_len = wait_for_timeout(sdd, (loops ? ms : 0)); + cpy_len = s3c64xx_spi_wait_for_timeout(sdd, + (loops ? ms : 0)); switch (sdd->cur_bpw) { case 32: From 74f3aaad21660c91ea13136ea8c41f5183e421fd Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Sat, 22 Jun 2013 23:07:38 +0530 Subject: [PATCH 38/42] spi: omap2-mcspi: convert to dma_request_slave_channel_compat() Convert dmaengine channel requests to use dma_request_slave_channel_compat(). This supports the DT case of platforms requiring channel selection from either the OMAP DMA or the EDMA engine. AM33xx only boots from DT and is the only user implementing EDMA so in the !DT case we can default to the OMAP DMA filter. Signed-off-by: Matt Porter Acked-by: Mark Brown Signed-off-by: Joel A Fernandes Signed-off-by: Sourav Poddar Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 64 ++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 6802806d1f18..bb9afc3f043b 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -109,6 +109,9 @@ struct omap2_mcspi_dma { struct completion dma_tx_completion; struct completion dma_rx_completion; + + char dma_rx_ch_name[14]; + char dma_tx_ch_name[14]; }; /* use PIO for small transfers, avoiding DMA setup/teardown overhead and @@ -936,12 +939,20 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); sig = mcspi_dma->dma_rx_sync_dev; - mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + + mcspi_dma->dma_rx = + dma_request_slave_channel_compat(mask, omap_dma_filter_fn, + &sig, &master->dev, + mcspi_dma->dma_rx_ch_name); if (!mcspi_dma->dma_rx) goto no_dma; sig = mcspi_dma->dma_tx_sync_dev; - mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + mcspi_dma->dma_tx = + dma_request_slave_channel_compat(mask, omap_dma_filter_fn, + &sig, &master->dev, + mcspi_dma->dma_tx_ch_name); + if (!mcspi_dma->dma_tx) { dma_release_channel(mcspi_dma->dma_rx); mcspi_dma->dma_rx = NULL; @@ -1374,29 +1385,42 @@ static int omap2_mcspi_probe(struct platform_device *pdev) goto free_master; for (i = 0; i < master->num_chipselect; i++) { - char dma_ch_name[14]; + char *dma_rx_ch_name = mcspi->dma_channels[i].dma_rx_ch_name; + char *dma_tx_ch_name = mcspi->dma_channels[i].dma_tx_ch_name; struct resource *dma_res; - sprintf(dma_ch_name, "rx%d", i); - dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, - dma_ch_name); - if (!dma_res) { - dev_dbg(&pdev->dev, "cannot get DMA RX channel\n"); - status = -ENODEV; - break; - } + sprintf(dma_rx_ch_name, "rx%d", i); + if (!pdev->dev.of_node) { + dma_res = + platform_get_resource_byname(pdev, + IORESOURCE_DMA, + dma_rx_ch_name); + if (!dma_res) { + dev_dbg(&pdev->dev, + "cannot get DMA RX channel\n"); + status = -ENODEV; + break; + } - mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start; - sprintf(dma_ch_name, "tx%d", i); - dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, - dma_ch_name); - if (!dma_res) { - dev_dbg(&pdev->dev, "cannot get DMA TX channel\n"); - status = -ENODEV; - break; + mcspi->dma_channels[i].dma_rx_sync_dev = + dma_res->start; } + sprintf(dma_tx_ch_name, "tx%d", i); + if (!pdev->dev.of_node) { + dma_res = + platform_get_resource_byname(pdev, + IORESOURCE_DMA, + dma_tx_ch_name); + if (!dma_res) { + dev_dbg(&pdev->dev, + "cannot get DMA TX channel\n"); + status = -ENODEV; + break; + } - mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start; + mcspi->dma_channels[i].dma_tx_sync_dev = + dma_res->start; + } } if (status < 0) From 0b9e49e6704b81fd991827b0b60a0a6d56d06921 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 24 Jun 2013 17:31:59 +0530 Subject: [PATCH 39/42] spi: omap2-mcspi: add generic DMA request support to the DT binding The binding definition is based on the generic DMA request binding Signed-off-by: Matt Porter Signed-off-by: Joel A Fernandes Signed-off-by: Sourav Poddar Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/omap-spi.txt | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/spi/omap-spi.txt b/Documentation/devicetree/bindings/spi/omap-spi.txt index 938809c6829b..4c85c4c69584 100644 --- a/Documentation/devicetree/bindings/spi/omap-spi.txt +++ b/Documentation/devicetree/bindings/spi/omap-spi.txt @@ -10,7 +10,18 @@ Required properties: input. The default is D0 as input and D1 as output. -Example: +Optional properties: +- dmas: List of DMA specifiers with the controller specific format + as described in the generic DMA client binding. A tx and rx + specifier is required for each chip select. +- dma-names: List of DMA request names. These strings correspond + 1:1 with the DMA specifiers listed in dmas. The string naming + is to be "rxN" and "txN" for RX and TX requests, + respectively, where N equals the chip select number. + +Examples: + +[hwmod populated DMA resources] mcspi1: mcspi@1 { #address-cells = <1>; @@ -20,3 +31,17 @@ mcspi1: mcspi@1 { ti,spi-num-cs = <4>; }; +[generic DMA request binding] + +mcspi1: mcspi@1 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ti,omap4-mcspi"; + ti,hwmods = "mcspi1"; + ti,spi-num-cs = <2>; + dmas = <&edma 42 + &edma 43 + &edma 44 + &edma 45>; + dma-names = "tx0", "rx0", "tx1", "rx1"; +}; From 3146beec21b64f4551fcf0ac148381d54dc41b1b Mon Sep 17 00:00:00 2001 From: Girish K S Date: Fri, 21 Jun 2013 11:26:12 +0530 Subject: [PATCH 40/42] spi: s3c64xx: Added provision for dedicated cs pin The existing driver supports gpio based /cs signal. For controller's that have one device per controller, the slave device's /cs signal might be internally controlled by the chip select bit of slave select register. They are not externally asserted/deasserted using gpio pin. This patch adds support for controllers with dedicated /cs pin. if "cs-gpio" property doesnt exist in a spi dts node, the controller would treat the /cs pin as dedicated. Signed-off-by: Girish K S Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 70b221355400..067f442de2d4 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -208,6 +208,7 @@ struct s3c64xx_spi_driver_data { struct s3c64xx_spi_port_config *port_conf; unsigned int port_id; unsigned long gpios[4]; + bool cs_gpio; }; static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) @@ -570,14 +571,16 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ /* Deselect the last toggled device */ cs = sdd->tgl_spi->controller_data; - gpio_set_value(cs->line, - spi->mode & SPI_CS_HIGH ? 0 : 1); + if (sdd->cs_gpio) + gpio_set_value(cs->line, + spi->mode & SPI_CS_HIGH ? 0 : 1); } sdd->tgl_spi = NULL; } cs = spi->controller_data; - gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); + if (sdd->cs_gpio) + gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); /* Start the signals */ writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); @@ -710,7 +713,8 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, if (sdd->tgl_spi == spi) sdd->tgl_spi = NULL; - gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); + if (sdd->cs_gpio) + gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); /* Quiese the signals */ writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); @@ -998,8 +1002,10 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( { struct s3c64xx_spi_csinfo *cs; struct device_node *slave_np, *data_np = NULL; + struct s3c64xx_spi_driver_data *sdd; u32 fb_delay = 0; + sdd = spi_master_get_devdata(spi->master); slave_np = spi->dev.of_node; if (!slave_np) { dev_err(&spi->dev, "device node not found\n"); @@ -1019,7 +1025,10 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( return ERR_PTR(-ENOMEM); } - cs->line = of_get_named_gpio(data_np, "cs-gpio", 0); + /* The CS line is asserted/deasserted by the gpio pin */ + if (sdd->cs_gpio) + cs->line = of_get_named_gpio(data_np, "cs-gpio", 0); + if (!gpio_is_valid(cs->line)) { dev_err(&spi->dev, "chip select gpio is not specified or invalid\n"); kfree(cs); @@ -1059,7 +1068,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi) return -ENODEV; } - if (!spi_get_ctldata(spi)) { + /* Request gpio only if cs line is asserted by gpio pins */ + if (sdd->cs_gpio) { err = gpio_request_one(cs->line, GPIOF_OUT_INIT_HIGH, dev_name(&spi->dev)); if (err) { @@ -1068,9 +1078,11 @@ static int s3c64xx_spi_setup(struct spi_device *spi) cs->line, err); goto err_gpio_req; } - spi_set_ctldata(spi, cs); } + if (!spi_get_ctldata(spi)) + spi_set_ctldata(spi, cs); + sci = sdd->cntrlr_info; spin_lock_irqsave(&sdd->lock, flags); @@ -1148,8 +1160,10 @@ err_gpio_req: static void s3c64xx_spi_cleanup(struct spi_device *spi) { struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi); + struct s3c64xx_spi_driver_data *sdd; - if (cs) { + sdd = spi_master_get_devdata(spi->master); + if (cs && sdd->cs_gpio) { gpio_free(cs->line); if (spi->dev.of_node) kfree(cs); @@ -1326,7 +1340,11 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->cntrlr_info = sci; sdd->pdev = pdev; sdd->sfr_start = mem_res->start; + sdd->cs_gpio = true; if (pdev->dev.of_node) { + if (!of_find_property(pdev->dev.of_node, "cs-gpio", NULL)) + sdd->cs_gpio = false; + ret = of_alias_get_id(pdev->dev.of_node, "spi"); if (ret < 0) { dev_err(&pdev->dev, "failed to get alias id, errno %d\n", From bff82038ca3e2976ad0b51d32c7a8c9ed31065f7 Mon Sep 17 00:00:00 2001 From: Girish K S Date: Fri, 21 Jun 2013 11:26:13 +0530 Subject: [PATCH 41/42] spi: s3c64xx: Added support for exynos5440 spi This patch adds support for the exynos5440 spi controller. The integration of the spi IP in exynos5440 is different from other SoC's. The I/O pins are no more configured via gpio, they have dedicated pins. Signed-off-by: Girish K S Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 067f442de2d4..d170cc0d81a0 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1609,6 +1609,15 @@ static struct s3c64xx_spi_port_config exynos4_spi_port_config = { .clk_from_cmu = true, }; +static struct s3c64xx_spi_port_config exynos5440_spi_port_config = { + .fifo_lvl_mask = { 0x1ff }, + .rx_lvl_offset = 15, + .tx_st_done = 25, + .high_speed = true, + .clk_from_cmu = true, + .quirks = S3C64XX_SPI_QUIRK_POLL, +}; + static struct platform_device_id s3c64xx_spi_driver_ids[] = { { .name = "s3c2443-spi", @@ -1637,6 +1646,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = { { .compatible = "samsung,exynos4210-spi", .data = (void *)&exynos4_spi_port_config, }, + { .compatible = "samsung,exynos5440-spi", + .data = (void *)&exynos5440_spi_port_config, + }, { }, }; MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match); From cd469106c3aa2303d928c20a35cac5d669f816f7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 26 Jun 2013 16:09:48 +0100 Subject: [PATCH 42/42] spi/s3c64xx: Rely on the compiler eliminating the OF ID table This should work with modern compilers, isn't that much of an issue if it goes wrong and it ensures that the DT-only hardware variants don't leave unreferenced parameters structures lying around. Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index d170cc0d81a0..ecc0f06d71ef 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1641,7 +1641,6 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = { { }, }; -#ifdef CONFIG_OF static const struct of_device_id s3c64xx_spi_dt_match[] = { { .compatible = "samsung,exynos4210-spi", .data = (void *)&exynos4_spi_port_config, @@ -1652,7 +1651,6 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = { { }, }; MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match); -#endif /* CONFIG_OF */ static struct platform_driver s3c64xx_spi_driver = { .driver = {