summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-03 12:31:39 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-03 12:31:39 -0700
commitd25e436c4b68db2895185b24ad1f22499c2f87b0 (patch)
treedd66245410513f09d2439ef0b34cf1d131696bed /drivers
parenta90f0e9ebb88ba7b0efea4e7d9defc0c2b96f712 (diff)
parent282ec0ea65dab88fda51b5b9b649958ae42f4ac0 (diff)
downloadlinux-d25e436c4b68db2895185b24ad1f22499c2f87b0.tar.gz
linux-d25e436c4b68db2895185b24ad1f22499c2f87b0.tar.bz2
linux-d25e436c4b68db2895185b24ad1f22499c2f87b0.zip
Merge tag 'spi-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown: "There's quite a lot of small driver specific fixes and enhancements in this release but the main activity has been around the loopback and spidev test drivers which is good to see as it should hopefully help improve the quality of all the drivers as people start to make use of the new code: - Additional tests in the loopback test driver for vmalloc() compatibility and around delays together with fixes for existing tests. - Support for testing continuous data transfer for use in soak testing. - Device property support for board info platforms. - Support for registering empty sets of devices via board info (useful when writing code to enumerate hardware automatically)" * tag 'spi-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (52 commits) spi: cadence: Allow for GPIO pins to be used as chipselects spi-imx: Implements handling of the SPI_READY mode flag. spi: tegra: fix spelling mistake: "trasfer" -> "transfer" spi: spi-ti-qspi: Use bounce buffer if read buffer is not DMA'ble spi: Add can_dma like interface for spi_flash_read spi: dw: Disable clock after unregistering the host spi: double time out tolerance spi: atmel: add deepest PM support to SAMA5D2 spi: atmel: factorize reusable code for SPI controller init spi: orion: add LSB support spi: pl022: don't use uninitialized variable spi: loopback-test: fix spelling mistake: "minimam" -> "minimum" spi: dynamycally allocated message initialization spi: spi-ti-qspi: Remove unused dma_dev variable spi: omap2-mcspi: poll OMAP2_MCSPI_CHSTAT_RXS for PIO transfer spi: spi-ti-qspi: Use dma_engine wrapper for dma memcpy call spi: spidev_test: add option to continuously transfer data spi: loopback-test: fix potential integer overflow on multiple spi: sun6i: update max transfer size reported spi: pl022: Document property values ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/acpi_apd.c1
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/spi-atmel.c44
-rw-r--r--drivers/spi/spi-bcm63xx-hsspi.c35
-rw-r--r--drivers/spi/spi-bcm63xx.c51
-rw-r--r--drivers/spi/spi-cadence.c65
-rw-r--r--drivers/spi/spi-davinci.c95
-rw-r--r--drivers/spi/spi-dw-mmio.c2
-rw-r--r--drivers/spi/spi-fsl-dspi.c3
-rw-r--r--drivers/spi/spi-fsl-spi.c3
-rw-r--r--drivers/spi/spi-imx.c20
-rw-r--r--drivers/spi/spi-lantiq-ssc.c438
-rw-r--r--drivers/spi/spi-loopback-test.c154
-rw-r--r--drivers/spi/spi-omap2-mcspi.c9
-rw-r--r--drivers/spi/spi-orion.c11
-rw-r--r--drivers/spi/spi-pl022.c2
-rw-r--r--drivers/spi/spi-sc18is602.c24
-rw-r--r--drivers/spi/spi-sun6i.c94
-rw-r--r--drivers/spi/spi-tegra114.c2
-rw-r--r--drivers/spi/spi-tegra20-sflash.c2
-rw-r--r--drivers/spi/spi-tegra20-slink.c2
-rw-r--r--drivers/spi/spi-test.h21
-rw-r--r--drivers/spi/spi-ti-qspi.c70
-rw-r--r--drivers/spi/spi-xlp.c1
-rw-r--r--drivers/spi/spi.c38
-rw-r--r--drivers/spi/spidev.c1
26 files changed, 790 insertions, 400 deletions
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 26696b693e63..17a1eb14847a 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -169,6 +169,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
#ifdef CONFIG_ARM64
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
{ "BRCM900D", APD_ADDR(vulcan_spi_desc) },
+ { "CAV900D", APD_ADDR(vulcan_spi_desc) },
#endif
{ }
};
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 25ae7f2e44b5..1761c9004fc1 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -715,7 +715,7 @@ config SPI_XILINX
config SPI_XLP
tristate "Netlogic XLP SPI controller driver"
- depends on CPU_XLP || ARCH_VULCAN || COMPILE_TEST
+ depends on CPU_XLP || ARCH_THUNDER2 || COMPILE_TEST
help
Enable support for the SPI controller on the Netlogic XLP SoCs.
Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX, XLP9XX
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 0e7712bac3b6..1eb83c9613d5 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -1464,6 +1464,25 @@ static int atmel_spi_gpio_cs(struct platform_device *pdev)
return 0;
}
+static void atmel_spi_init(struct atmel_spi *as)
+{
+ spi_writel(as, CR, SPI_BIT(SWRST));
+ spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
+ if (as->caps.has_wdrbt) {
+ spi_writel(as, MR, SPI_BIT(WDRBT) | SPI_BIT(MODFDIS)
+ | SPI_BIT(MSTR));
+ } else {
+ spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
+ }
+
+ if (as->use_pdc)
+ spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+ spi_writel(as, CR, SPI_BIT(SPIEN));
+
+ if (as->fifo_size)
+ spi_writel(as, CR, SPI_BIT(FIFOEN));
+}
+
static int atmel_spi_probe(struct platform_device *pdev)
{
struct resource *regs;
@@ -1572,26 +1591,14 @@ static int atmel_spi_probe(struct platform_device *pdev)
as->spi_clk = clk_get_rate(clk);
- spi_writel(as, CR, SPI_BIT(SWRST));
- spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
- if (as->caps.has_wdrbt) {
- spi_writel(as, MR, SPI_BIT(WDRBT) | SPI_BIT(MODFDIS)
- | SPI_BIT(MSTR));
- } else {
- spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
- }
-
- if (as->use_pdc)
- spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
- spi_writel(as, CR, SPI_BIT(SPIEN));
-
as->fifo_size = 0;
if (!of_property_read_u32(pdev->dev.of_node, "atmel,fifo-size",
&as->fifo_size)) {
dev_info(&pdev->dev, "Using FIFO (%u data)\n", as->fifo_size);
- spi_writel(as, CR, SPI_BIT(FIFOEN));
}
+ atmel_spi_init(as);
+
pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
@@ -1695,8 +1702,17 @@ static int atmel_spi_suspend(struct device *dev)
static int atmel_spi_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
+ struct atmel_spi *as = spi_master_get_devdata(master);
int ret;
+ ret = clk_prepare_enable(as->clk);
+ if (ret)
+ return ret;
+
+ atmel_spi_init(as);
+
+ clk_disable_unprepare(as->clk);
+
if (!pm_runtime_suspended(dev)) {
ret = atmel_spi_runtime_resume(dev);
if (ret)
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index 55789f7cda92..5514cd02e93a 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/spi/spi.h>
#include <linux/mutex.h>
+#include <linux/of.h>
#define HSSPI_GLOBAL_CTRL_REG 0x0
#define GLOBAL_CTRL_CS_POLARITY_SHIFT 0
@@ -91,6 +92,7 @@
#define HSSPI_MAX_SYNC_CLOCK 30000000
+#define HSSPI_SPI_MAX_CS 8
#define HSSPI_BUS_NUM 1 /* 0 is legacy SPI */
struct bcm63xx_hsspi {
@@ -332,7 +334,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct clk *clk;
int irq, ret;
- u32 reg, rate;
+ u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -351,8 +353,16 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
return PTR_ERR(clk);
rate = clk_get_rate(clk);
- if (!rate)
- return -EINVAL;
+ if (!rate) {
+ struct clk *pll_clk = devm_clk_get(dev, "pll");
+
+ if (IS_ERR(pll_clk))
+ return PTR_ERR(pll_clk);
+
+ rate = clk_get_rate(pll_clk);
+ if (!rate)
+ return -EINVAL;
+ }
ret = clk_prepare_enable(clk);
if (ret)
@@ -374,8 +384,17 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
mutex_init(&bs->bus_mutex);
init_completion(&bs->done);
- master->bus_num = HSSPI_BUS_NUM;
- master->num_chipselect = 8;
+ master->dev.of_node = dev->of_node;
+ if (!dev->of_node)
+ master->bus_num = HSSPI_BUS_NUM;
+
+ of_property_read_u32(dev->of_node, "num-cs", &num_cs);
+ if (num_cs > 8) {
+ dev_warn(dev, "unsupported number of cs (%i), reducing to 8\n",
+ num_cs);
+ num_cs = HSSPI_SPI_MAX_CS;
+ }
+ master->num_chipselect = num_cs;
master->setup = bcm63xx_hsspi_setup;
master->transfer_one_message = bcm63xx_hsspi_transfer_one;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
@@ -461,10 +480,16 @@ static int bcm63xx_hsspi_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(bcm63xx_hsspi_pm_ops, bcm63xx_hsspi_suspend,
bcm63xx_hsspi_resume);
+static const struct of_device_id bcm63xx_hsspi_of_match[] = {
+ { .compatible = "brcm,bcm6328-hsspi", },
+ { },
+};
+
static struct platform_driver bcm63xx_hsspi_driver = {
.driver = {
.name = "bcm63xx-hsspi",
.pm = &bcm63xx_hsspi_pm_ops,
+ .of_match_table = bcm63xx_hsspi_of_match,
},
.probe = bcm63xx_hsspi_probe,
.remove = bcm63xx_hsspi_remove,
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index fee747030ee6..247f71b02235 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -26,6 +26,7 @@
#include <linux/completion.h>
#include <linux/err.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
/* BCM 6338/6348 SPI core */
#define SPI_6348_RSET_SIZE 64
@@ -428,6 +429,13 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static size_t bcm63xx_spi_max_length(struct spi_device *spi)
+{
+ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
+
+ return bs->fifo_size;
+}
+
static const unsigned long bcm6348_spi_reg_offsets[] = {
[SPI_CMD] = SPI_6348_CMD,
[SPI_INT_STATUS] = SPI_6348_INT_STATUS,
@@ -477,21 +485,48 @@ static const struct platform_device_id bcm63xx_spi_dev_match[] = {
},
};
+static const struct of_device_id bcm63xx_spi_of_match[] = {
+ { .compatible = "brcm,bcm6348-spi", .data = &bcm6348_spi_reg_offsets },
+ { .compatible = "brcm,bcm6358-spi", .data = &bcm6358_spi_reg_offsets },
+ { },
+};
+
static int bcm63xx_spi_probe(struct platform_device *pdev)
{
struct resource *r;
const unsigned long *bcm63xx_spireg;
struct device *dev = &pdev->dev;
- int irq;
+ int irq, bus_num;
struct spi_master *master;
struct clk *clk;
struct bcm63xx_spi *bs;
int ret;
+ u32 num_cs = BCM63XX_SPI_MAX_CS;
- if (!pdev->id_entry->driver_data)
- return -EINVAL;
+ if (dev->of_node) {
+ const struct of_device_id *match;
+
+ match = of_match_node(bcm63xx_spi_of_match, dev->of_node);
+ if (!match)
+ return -EINVAL;
+ bcm63xx_spireg = match->data;
+
+ of_property_read_u32(dev->of_node, "num-cs", &num_cs);
+ if (num_cs > BCM63XX_SPI_MAX_CS) {
+ dev_warn(dev, "unsupported number of cs (%i), reducing to 8\n",
+ num_cs);
+ num_cs = BCM63XX_SPI_MAX_CS;
+ }
- bcm63xx_spireg = (const unsigned long *)pdev->id_entry->driver_data;
+ bus_num = -1;
+ } else if (pdev->id_entry->driver_data) {
+ const struct platform_device_id *match = pdev->id_entry;
+
+ bcm63xx_spireg = (const unsigned long *)match->driver_data;
+ bus_num = BCM63XX_SPI_BUS_NUM;
+ } else {
+ return -EINVAL;
+ }
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -536,11 +571,14 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
goto out_err;
}
- master->bus_num = BCM63XX_SPI_BUS_NUM;
- master->num_chipselect = BCM63XX_SPI_MAX_CS;
+ master->dev.of_node = dev->of_node;
+ master->bus_num = bus_num;
+ master->num_chipselect = num_cs;
master->transfer_one_message = bcm63xx_spi_transfer_one;
master->mode_bits = MODEBITS;
master->bits_per_word_mask = SPI_BPW_MASK(8);
+ master->max_transfer_size = bcm63xx_spi_max_length;
+ master->max_message_size = bcm63xx_spi_max_length;
master->auto_runtime_pm = true;
bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
@@ -624,6 +662,7 @@ static struct platform_driver bcm63xx_spi_driver = {
.driver = {
.name = "bcm63xx-spi",
.pm = &bcm63xx_spi_pm_ops,
+ .of_match_table = bcm63xx_spi_of_match,
},
.id_table = bcm63xx_spi_dev_match,
.probe = bcm63xx_spi_probe,
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index 1c57ce64abba..f0b5c7b91f37 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -13,6 +13,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -127,6 +128,10 @@ struct cdns_spi {
u32 is_decoded_cs;
};
+struct cdns_spi_device_data {
+ bool gpio_requested;
+};
+
/* Macros for the SPI controller read/write */
static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset)
{
@@ -456,6 +461,64 @@ static int cdns_unprepare_transfer_hardware(struct spi_master *master)
return 0;
}
+static int cdns_spi_setup(struct spi_device *spi)
+{
+
+ int ret = -EINVAL;
+ struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi);
+
+ /* this is a pin managed by the controller, leave it alone */
+ if (spi->cs_gpio == -ENOENT)
+ return 0;
+
+ /* this seems to be the first time we're here */
+ if (!cdns_spi_data) {
+ cdns_spi_data = kzalloc(sizeof(*cdns_spi_data), GFP_KERNEL);
+ if (!cdns_spi_data)
+ return -ENOMEM;
+ cdns_spi_data->gpio_requested = false;
+ spi_set_ctldata(spi, cdns_spi_data);
+ }
+
+ /* if we haven't done so, grab the gpio */
+ if (!cdns_spi_data->gpio_requested && gpio_is_valid(spi->cs_gpio)) {
+ ret = gpio_request_one(spi->cs_gpio,
+ (spi->mode & SPI_CS_HIGH) ?
+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
+ dev_name(&spi->dev));
+ if (ret)
+ dev_err(&spi->dev, "can't request chipselect gpio %d\n",
+ spi->cs_gpio);
+ else
+ cdns_spi_data->gpio_requested = true;
+ } else {
+ if (gpio_is_valid(spi->cs_gpio)) {
+ int mode = ((spi->mode & SPI_CS_HIGH) ?
+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH);
+
+ ret = gpio_direction_output(spi->cs_gpio, mode);
+ if (ret)
+ dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n",
+ spi->cs_gpio, ret);
+ }
+ }
+
+ return ret;
+}
+
+static void cdns_spi_cleanup(struct spi_device *spi)
+{
+ struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi);
+
+ if (cdns_spi_data) {
+ if (cdns_spi_data->gpio_requested)
+ gpio_free(spi->cs_gpio);
+ kfree(cdns_spi_data);
+ spi_set_ctldata(spi, NULL);
+ }
+
+}
+
/**
* cdns_spi_probe - Probe method for the SPI driver
* @pdev: Pointer to the platform_device structure
@@ -555,6 +618,8 @@ static int cdns_spi_probe(struct platform_device *pdev)
master->transfer_one = cdns_transfer_one;
master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
master->set_cs = cdns_spi_chipselect;
+ master->setup = cdns_spi_setup;
+ master->cleanup = cdns_spi_cleanup;
master->auto_runtime_pm = true;
master->mode_bits = SPI_CPOL | SPI_CPHA;
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 02fb96797ac8..595acdcfc7d0 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -109,6 +109,8 @@
#define SPIDEF 0x4c
#define SPIFMT0 0x50
+#define DMA_MIN_BYTES 16
+
/* SPI Controller driver's private data. */
struct davinci_spi {
struct spi_bitbang bitbang;
@@ -389,6 +391,7 @@ static int davinci_spi_of_setup(struct spi_device *spi)
{
struct davinci_spi_config *spicfg = spi->controller_data;
struct device_node *np = spi->dev.of_node;
+ struct davinci_spi *dspi = spi_master_get_devdata(spi->master);
u32 prop;
if (spicfg == NULL && np) {
@@ -400,6 +403,9 @@ static int davinci_spi_of_setup(struct spi_device *spi)
if (!of_property_read_u32(np, "ti,spi-wdelay", &prop))
spicfg->wdelay = (u8)prop;
spi->controller_data = spicfg;
+
+ if (dspi->dma_rx && dspi->dma_tx)
+ spicfg->io_type = SPI_IO_TYPE_DMA;
}
return 0;
@@ -467,6 +473,22 @@ static void davinci_spi_cleanup(struct spi_device *spi)
kfree(spicfg);
}
+static bool davinci_spi_can_dma(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *xfer)
+{
+ struct davinci_spi_config *spicfg = spi->controller_data;
+ bool can_dma = false;
+
+ if (spicfg)
+ can_dma = (spicfg->io_type == SPI_IO_TYPE_DMA) &&
+ (xfer->len >= DMA_MIN_BYTES) &&
+ !is_vmalloc_addr(xfer->rx_buf) &&
+ !is_vmalloc_addr(xfer->tx_buf);
+
+ return can_dma;
+}
+
static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
{
struct device *sdev = dspi->bitbang.master->dev.parent;
@@ -581,8 +603,6 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
struct davinci_spi_config *spicfg;
struct davinci_spi_platform_data *pdata;
unsigned uninitialized_var(rx_buf_count);
- void *dummy_buf = NULL;
- struct scatterlist sg_rx, sg_tx;
dspi = spi_master_get_devdata(spi->master);
pdata = &dspi->pdata;
@@ -605,10 +625,9 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
reinit_completion(&dspi->done);
- if (spicfg->io_type == SPI_IO_TYPE_INTR)
- set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
-
- if (spicfg->io_type != SPI_IO_TYPE_DMA) {
+ if (!davinci_spi_can_dma(spi->master, spi, t)) {
+ if (spicfg->io_type != SPI_IO_TYPE_POLL)
+ set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
/* start the transfer */
dspi->wcount--;
tx_data = dspi->get_tx(dspi);
@@ -630,51 +649,28 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
};
struct dma_async_tx_descriptor *rxdesc;
struct dma_async_tx_descriptor *txdesc;
- void *buf;
-
- dummy_buf = kzalloc(t->len, GFP_KERNEL);
- if (!dummy_buf)
- goto err_alloc_dummy_buf;
dmaengine_slave_config(dspi->dma_rx, &dma_rx_conf);
dmaengine_slave_config(dspi->dma_tx, &dma_tx_conf);
- sg_init_table(&sg_rx, 1);
- if (!t->rx_buf)
- buf = dummy_buf;
- else
- buf = t->rx_buf;
- t->rx_dma = dma_map_single(&spi->dev, buf,
- t->len, DMA_FROM_DEVICE);
- if (dma_mapping_error(&spi->dev, !t->rx_dma)) {
- ret = -EFAULT;
- goto err_rx_map;
- }
- sg_dma_address(&sg_rx) = t->rx_dma;
- sg_dma_len(&sg_rx) = t->len;
-
- sg_init_table(&sg_tx, 1);
- if (!t->tx_buf)
- buf = dummy_buf;
- else
- buf = (void *)t->tx_buf;
- t->tx_dma = dma_map_single(&spi->dev, buf,
- t->len, DMA_TO_DEVICE);
- if (dma_mapping_error(&spi->dev, t->tx_dma)) {
- ret = -EFAULT;
- goto err_tx_map;
- }
- sg_dma_address(&sg_tx) = t->tx_dma;
- sg_dma_len(&sg_tx) = t->len;
-
rxdesc = dmaengine_prep_slave_sg(dspi->dma_rx,
- &sg_rx, 1, DMA_DEV_TO_MEM,
+ t->rx_sg.sgl, t->rx_sg.nents, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!rxdesc)
goto err_desc;
+ if (!t->tx_buf) {
+ /* To avoid errors when doing rx-only transfers with
+ * many SG entries (> 20), use the rx buffer as the
+ * dummy tx buffer so that dma reloads are done at the
+ * same time for rx and tx.
+ */
+ t->tx_sg.sgl = t->rx_sg.sgl;
+ t->tx_sg.nents = t->rx_sg.nents;
+ }
+
txdesc = dmaengine_prep_slave_sg(dspi->dma_tx,
- &sg_tx, 1, DMA_MEM_TO_DEV,
+ t->tx_sg.sgl, t->tx_sg.nents, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!txdesc)
goto err_desc;
@@ -710,16 +706,9 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
}
clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL);
- if (spicfg->io_type == SPI_IO_TYPE_DMA) {
+ if (davinci_spi_can_dma(spi->master, spi, t))
clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
- dma_unmap_single(&spi->dev, t->rx_dma,
- t->len, DMA_FROM_DEVICE);
- dma_unmap_single(&spi->dev, t->tx_dma,
- t->len, DMA_TO_DEVICE);
- kfree(dummy_buf);
- }
-
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
@@ -742,12 +731,6 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
return t->len;
err_desc:
- dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE);
-err_tx_map:
- dma_unmap_single(&spi->dev, t->rx_dma, t->len, DMA_FROM_DEVICE);
-err_rx_map:
- kfree(dummy_buf);
-err_alloc_dummy_buf:
return ret;
}
@@ -988,8 +971,10 @@ static int davinci_spi_probe(struct platform_device *pdev)
master->bus_num = pdev->id;
master->num_chipselect = pdata->num_chipselect;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16);
+ master->flags = SPI_MASTER_MUST_RX;
master->setup = davinci_spi_setup;
master->cleanup = davinci_spi_cleanup;
+ master->can_dma = davinci_spi_can_dma;
dspi->bitbang.chipselect = davinci_spi_chipselect;
dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 447497e9124c..d25cc4037e23 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -115,8 +115,8 @@ static int dw_spi_mmio_remove(struct platform_device *pdev)
{
struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
- clk_disable_unprepare(dwsmmio->clk);
dw_spi_remove_host(&dwsmmio->dws);
+ clk_disable_unprepare(dwsmmio->clk);
return 0;
}
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 14c8e7ce1913..15201645bdc4 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1002,7 +1002,8 @@ static int dspi_probe(struct platform_device *pdev)
if (IS_ERR(dspi->regmap)) {
dev_err(&pdev->dev, "failed to init regmap: %ld\n",
PTR_ERR(dspi->regmap));
- return PTR_ERR(dspi->regmap);
+ ret = PTR_ERR(dspi->regmap);
+ goto out_master_put;
}
dspi_init(dspi);
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 0fc3452652ae..8f2e97857e8b 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -814,7 +814,7 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
struct device_node *np = ofdev->dev.of_node;
struct spi_master *master;
struct resource mem;
- int irq, type;
+ int irq = 0, type;
int ret = -ENOMEM;
ret = of_mpc8xxx_spi_probe(ofdev);
@@ -847,6 +847,7 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
return 0;
err:
+ irq_dispose_mapping(irq);
if (type == TYPE_FSL)
of_fsl_spi_free_chipselects(dev);
return ret;
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 9a7c62f471dc..b402530a7a9a 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -95,6 +95,7 @@ struct spi_imx_data {
unsigned int spi_bus_clk;
unsigned int bytes_per_word;
+ unsigned int spi_drctl;
unsigned int count;
void (*tx)(struct spi_imx_data *);
@@ -246,6 +247,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
#define MX51_ECSPI_CTRL_XCH (1 << 2)
#define MX51_ECSPI_CTRL_SMC (1 << 3)
#define MX51_ECSPI_CTRL_MODE_MASK (0xf << 4)
+#define MX51_ECSPI_CTRL_DRCTL(drctl) ((drctl) << 16)
#define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8
#define MX51_ECSPI_CTRL_PREDIV_OFFSET 12
#define MX51_ECSPI_CTRL_CS(cs) ((cs) << 18)
@@ -355,6 +357,12 @@ static int mx51_ecspi_config(struct spi_device *spi,
*/
ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
+ /*
+ * Enable SPI_RDY handling (falling edge/level triggered).
+ */
+ if (spi->mode & SPI_READY)
+ ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl);
+
/* set clock speed */
ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk);
spi_imx->spi_bus_clk = clk;
@@ -1173,7 +1181,7 @@ static int spi_imx_probe(struct platform_device *pdev)
struct spi_master *master;
struct spi_imx_data *spi_imx;
struct resource *res;
- int i, ret, irq;
+ int i, ret, irq, spi_drctl;
if (!np && !mxc_platform_info) {
dev_err(&pdev->dev, "can't get the platform data\n");
@@ -1181,6 +1189,12 @@ static int spi_imx_probe(struct platform_device *pdev)
}
master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
+ ret = of_property_read_u32(np, "fsl,spi-rdy-drctl", &spi_drctl);
+ if ((ret < 0) || (spi_drctl >= 0x3)) {
+ /* '11' is reserved */
+ spi_drctl = 0;
+ }
+
if (!master)
return -ENOMEM;
@@ -1216,7 +1230,9 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx))
- spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
+ spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
+
+ spi_imx->spi_drctl = spi_drctl;
init_completion(&spi_imx->xfer_done);
diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c
index 8a626f7fccea..d5976615d924 100644
--- a/drivers/spi/spi-lantiq-ssc.c
+++ b/drivers/spi/spi-lantiq-ssc.c
@@ -26,136 +26,140 @@
#include <lantiq_soc.h>
#endif
-#define SPI_RX_IRQ_NAME "spi_rx"
-#define SPI_TX_IRQ_NAME "spi_tx"
-#define SPI_ERR_IRQ_NAME "spi_err"
-#define SPI_FRM_IRQ_NAME "spi_frm"
-
-#define SPI_CLC 0x00
-#define SPI_PISEL 0x04
-#define SPI_ID 0x08
-#define SPI_CON 0x10
-#define SPI_STAT 0x14
-#define SPI_WHBSTATE 0x18
-#define SPI_TB 0x20
-#define SPI_RB 0x24
-#define SPI_RXFCON 0x30
-#define SPI_TXFCON 0x34
-#define SPI_FSTAT 0x38
-#define SPI_BRT 0x40
-#define SPI_BRSTAT 0x44
-#define SPI_SFCON 0x60
-#define SPI_SFSTAT 0x64
-#define SPI_GPOCON 0x70
-#define SPI_GPOSTAT 0x74
-#define SPI_FPGO 0x78
-#define SPI_RXREQ 0x80
-#define SPI_RXCNT 0x84
-#define SPI_DMACON 0xec
-#define SPI_IRNEN 0xf4
-#define SPI_IRNICR 0xf8
-#define SPI_IRNCR 0xfc
-
-#define SPI_CLC_SMC_S 16 /* Clock divider for sleep mode */
-#define SPI_CLC_SMC_M (0xFF << SPI_CLC_SMC_S)
-#define SPI_CLC_RMC_S 8 /* Clock divider for normal run mode */
-#define SPI_CLC_RMC_M (0xFF << SPI_CLC_RMC_S)
-#define SPI_CLC_DISS BIT(1) /* Disable status bit */
-#define SPI_CLC_DISR BIT(0) /* Disable request bit */
-
-#define SPI_ID_TXFS_S 24 /* Implemented TX FIFO size */
-#define SPI_ID_TXFS_M (0x3F << SPI_ID_TXFS_S)
-#define SPI_ID_RXFS_S 16 /* Implemented RX FIFO size */
-#define SPI_ID_RXFS_M (0x3F << SPI_ID_RXFS_S)
-#define SPI_ID_MOD_S 8 /* Module ID */
-#define SPI_ID_MOD_M (0xff << SPI_ID_MOD_S)
-#define SPI_ID_CFG_S 5 /* DMA interface support */
-#define SPI_ID_CFG_M (1 << SPI_ID_CFG_S)
-#define SPI_ID_REV_M 0x1F /* Hardware revision number */
-
-#define SPI_CON_BM_S 16 /* Data width selection */
-#define SPI_CON_BM_M (0x1F << SPI_CON_BM_S)
-#define SPI_CON_EM BIT(24) /* Echo mode */
-#define SPI_CON_IDLE BIT(23) /* Idle bit value */
-#define SPI_CON_ENBV BIT(22) /* Enable byte valid control */
-#define SPI_CON_RUEN BIT(12) /* Receive underflow error enable */
-#define SPI_CON_TUEN BIT(11) /* Transmit underflow error enable */
-#define SPI_CON_AEN BIT(10) /* Abort error enable */
-#define SPI_CON_REN BIT(9) /* Receive overflow error enable */
-#define SPI_CON_TEN BIT(8) /* Transmit overflow error enable */
-#define SPI_CON_LB BIT(7) /* Loopback control */
-#define SPI_CON_PO BIT(6) /* Clock polarity control */
-#define SPI_CON_PH BIT(5) /* Clock phase control */
-#define SPI_CON_HB BIT(4) /* Heading control */
-#define SPI_CON_RXOFF BIT(1) /* Switch receiver off */
-#define SPI_CON_TXOFF BIT(0) /* Switch transmitter off */
-
-#define SPI_STAT_RXBV_S 28
-#define SPI_STAT_RXBV_M (0x7 << SPI_STAT_RXBV_S)
-#define SPI_STAT_BSY BIT(13) /* Busy flag */
-#define SPI_STAT_RUE BIT(12) /* Receive underflow error flag */
-#define SPI_STAT_TUE BIT(11) /* Transmit underflow error flag */
-#define SPI_STAT_AE BIT(10) /* Abort error flag */
-#define SPI_STAT_RE BIT(9) /* Receive error flag */
-#define SPI_STAT_TE BIT(8) /* Transmit error flag */
-#define SPI_STAT_ME BIT(7) /* Mode error flag */
-#define SPI_STAT_MS BIT(1) /* Master/slave select bit */
-#define SPI_STAT_EN BIT(0) /* Enable bit */
-#define SPI_STAT_ERRORS (SPI_STAT_ME | SPI_STAT_TE | SPI_STAT_RE | \
- SPI_STAT_AE | SPI_STAT_TUE | SPI_STAT_RUE)
-
-#define SPI_WHBSTATE_SETTUE BIT(15) /* Set transmit underflow error flag */
-#define SPI_WHBSTATE_SETAE BIT(1