From 9232b9b1b57dc5c01f435433e70e26c122bf4e44 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 20 Mar 2012 16:10:09 +0530 Subject: spi/davinci: Fix DMA API usage in davinci The driver uses NULL for dma_unmap_single instead of the struct device that the API expects. Signed-off-by: Shubhrajyoti D Tested-by: Akshay Shankarmurthy Signed-off-by: Grant Likely --- drivers/spi/spi-davinci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 31bfba805cf4..9b2901feaf78 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -653,7 +653,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n", rx_buf_count); if (t->tx_buf) - dma_unmap_single(NULL, t->tx_dma, t->len, + dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE); return -ENOMEM; } @@ -692,10 +692,10 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) if (spicfg->io_type == SPI_IO_TYPE_DMA) { if (t->tx_buf) - dma_unmap_single(NULL, t->tx_dma, t->len, + dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE); - dma_unmap_single(NULL, t->rx_dma, rx_buf_count, + dma_unmap_single(&spi->dev, t->rx_dma, rx_buf_count, DMA_FROM_DEVICE); clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN); -- cgit v1.2.3 From 5039a86973cd35bdb2f64d28ee12f13fe2bb5a4c Mon Sep 17 00:00:00 2001 From: Kenth Eriksson Date: Fri, 30 Mar 2012 17:05:30 +0200 Subject: spi/mpc83xx: fix NULL pdata dereference bug Commit 178db7d3, "spi: Fix device unregistration when unregistering the bus master", changed device initialization to be children of the bus master, not children of the bus masters parent device. The pdata pointer used in fsl_spi_chipselect must updated to reflect the changed initialization. Signed-off-by: Kenth Eriksson Acked-by: Joakim Tjernlund Signed-off-by: Grant Likely --- drivers/spi/spi-fsl-spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 24cacff57786..5f748c0d96bd 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -139,10 +139,12 @@ static void fsl_spi_change_mode(struct spi_device *spi) static void fsl_spi_chipselect(struct spi_device *spi, int value) { struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); - struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data; + struct fsl_spi_platform_data *pdata; bool pol = spi->mode & SPI_CS_HIGH; struct spi_mpc8xxx_cs *cs = spi->controller_state; + pdata = spi->dev.parent->parent->platform_data; + if (value == BITBANG_CS_INACTIVE) { if (pdata->cs_control) pdata->cs_control(spi, !pol); -- cgit v1.2.3 From cc4d22ae541ccd989ef163c46a38afde131e1644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 29 Mar 2012 21:54:18 +0200 Subject: spi/imx: mark base member in spi_imx_data as __iomem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes 36 sparse warnings like: drivers/spi/spi-imx.c:143:1: warning: incorrect type in argument 1 (different address spaces) drivers/spi/spi-imx.c:143:1: expected void const volatile [noderef] * drivers/spi/spi-imx.c:143:1: got void * Signed-off-by: Uwe Kleine-König Signed-off-by: Grant Likely --- drivers/spi/spi-imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 31054e3de4c1..373f4fff9358 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -83,7 +83,7 @@ struct spi_imx_data { struct spi_bitbang bitbang; struct completion xfer_done; - void *base; + void __iomem *base; int irq; struct clk *clk; unsigned long spi_clk; -- cgit v1.2.3 From 39ec0d38141b198f94fd19c2bb10fd7c616510d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Tue, 3 Apr 2012 15:03:44 +0200 Subject: spi/imx: prevent NULL pointer dereference in spi_imx_probe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When no platform_data is present and either 'spi-num-chipselects' is not defined in the DT or 'cs-gpios' has less entries than 'spi-num-chipselects' specifies, the NULL platform_data pointer is being dereferenced. Signed-off-by: Lothar Waßmann Signed-off-by: Grant Likely --- drivers/spi/spi-imx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 373f4fff9358..570f22053be8 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -766,8 +766,12 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) } ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs); - if (ret < 0) - num_cs = mxc_platform_info->num_chipselect; + if (ret < 0) { + if (mxc_platform_info) + num_cs = mxc_platform_info->num_chipselect; + else + return ret; + } master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data) + sizeof(int) * num_cs); @@ -784,7 +788,7 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) for (i = 0; i < master->num_chipselect; i++) { int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); - if (cs_gpio < 0) + if (cs_gpio < 0 && mxc_platform_info) cs_gpio = mxc_platform_info->chipselect[i]; spi_imx->chipselect[i] = cs_gpio; -- cgit v1.2.3 From 1e45860f541497d73162305d48b638d9b87e1ae3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Apr 2012 13:11:50 +0100 Subject: ARM: 7366/3: amba: Remove AMBA level regulator support The AMBA bus regulator support is being used to model on/off switches for power domains which isn't terribly idiomatic for modern kernels with the generic power domain code and creates integration problems on platforms which don't use regulators for their power domains as it's hard to tell the difference between a regulator that is needed but failed to be provided and one that isn't supposed to be there (though DT does make that easier). Platforms that wish to use the regulator API to manage their power domains can indirect via the power domain interface. This feature is only used with the vape supply of the db8500 PRCMU driver which supplies the UARTs and MMC controllers, none of which have support for managing vcore at runtime in mainline (only pl022 SPI controller does). Update that supply to have an always_on constraint until the power domain support for the system is updated so that it is enabled for these users, this is likely to have no impact on practical systems as probably at least one of these devices will be active and cause AMBA to hold the supply on anyway. Signed-off-by: Mark Brown Acked-by: Linus Walleij Tested-by: Shawn Guo Signed-off-by: Russell King --- drivers/spi/spi-pl022.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 96f0da66b185..09c925aaf320 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2195,7 +2195,6 @@ static int pl022_runtime_suspend(struct device *dev) struct pl022 *pl022 = dev_get_drvdata(dev); clk_disable(pl022->clk); - amba_vcore_disable(pl022->adev); return 0; } @@ -2204,7 +2203,6 @@ static int pl022_runtime_resume(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); - amba_vcore_enable(pl022->adev); clk_enable(pl022->clk); return 0; -- cgit v1.2.3 From eb798c641a34ae9cee9fcacfbe5dd40bd7777607 Mon Sep 17 00:00:00 2001 From: Vinit Shenoy Date: Tue, 17 Apr 2012 12:40:13 +0530 Subject: spi/pl022: Fix range checking for bits per word pl022 ssp controller supports word lengths from 4 to 16 (or 32) bits. Currently implemented checks were incorrect. It has following check if (pl022->vendor->max_bpw >= 32) which must be checking for <=. Also error print message is incorrect, that prints "range is from 1 to 16". Fix both these issues. Signed-off-by: Vinit Shenoy Acked-by: Linus Walleij Signed-off-by: Grant Likely --- drivers/spi/spi-pl022.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 09c925aaf320..1ead49dbebce 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1823,9 +1823,12 @@ static int pl022_setup(struct spi_device *spi) } else chip->cs_control = chip_info->cs_control; - if (bits <= 3) { - /* PL022 doesn't support less than 4-bits */ + /* Check bits per word with vendor specific range */ + if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) { status = -ENOTSUPP; + dev_err(&spi->dev, "illegal data size for this controller!\n"); + dev_err(&spi->dev, "This controller can only handle 4 <= n <= %d bit words\n", + pl022->vendor->max_bpw); goto err_config_params; } else if (bits <= 8) { dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n"); @@ -1838,20 +1841,10 @@ static int pl022_setup(struct spi_device *spi) chip->read = READING_U16; chip->write = WRITING_U16; } else { - if (pl022->vendor->max_bpw >= 32) { - dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n"); - chip->n_bytes = 4; - chip->read = READING_U32; - chip->write = WRITING_U32; - } else { - dev_err(&spi->dev, - "illegal data size for this controller!\n"); - dev_err(&spi->dev, - "a standard pl022 can only handle " - "1 <= n <= 16 bit words\n"); - status = -ENOTSUPP; - goto err_config_params; - } + dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n"); + chip->n_bytes = 4; + chip->read = READING_U32; + chip->write = WRITING_U32; } /* Now Initialize all register settings required for this chip */ -- cgit v1.2.3 From 5eb806a3a68920a9f373f18b03fa14852047e62b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 19 Apr 2012 14:44:21 +0530 Subject: spi/pl022: Fix calculate_effective_freq() calculate_effective_freq() was still not optimized and there were cases when it returned without error and with values of cpsr and scr as zero. Also, the variable named found is not used well. This patch targets to optimize and correct this routine. Tested for SPEAr. Signed-off-by: Viresh Kumar Tested-by: Vinit Kamalaksha Shenoy Acked-by: Linus Walleij Signed-off-by: Grant Likely --- drivers/spi/spi-pl022.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 1ead49dbebce..8aa44e7adaef 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1681,26 +1681,37 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct while (scr <= SCR_MAX) { tmp = spi_rate(rate, cpsdvsr, scr); - if (tmp > freq) + if (tmp > freq) { + /* we need lower freq */ scr++; + continue; + } + /* - * If found exact value, update and break. - * If found more closer value, update and continue. + * If found exact value, mark found and break. + * If found more closer value, update and break. */ - else if ((tmp == freq) || (tmp > best_freq)) { + if (tmp > best_freq) { best_freq = tmp; best_cpsdvsr = cpsdvsr; best_scr = scr; if (tmp == freq) - break; + found = 1; } - scr++; + /* + * increased scr will give lower rates, which are not + * required + */ + break; } cpsdvsr += 2; scr = SCR_MIN; } + WARN(!best_freq, "pl022: Matching cpsdvsr and scr not found for %d Hz rate \n", + freq); + clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF); clk_freq->scr = (u8) (best_scr & 0xFF); dev_dbg(&pl022->adev->dev, -- cgit v1.2.3 From d4b9b578cba7231c1fbafbe901a2e8f38654e056 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 17 Apr 2012 18:46:36 -0700 Subject: spi/spi-ep93xx.c: use dma_transfer_direction instead of dma_data_direction A new enum indicating the dma channel direction was introduced by: commit 49920bc66984a512f4bcc7735a61642cd0e4d6f2 dmaengine: add new enum dma_transfer_direction The following commit changed spi-ep93xx to use the new enum: commit a485df4b4404379786c4bdd258bc528b2617449d spi, serial: move to dma_transfer_direction In doing so a sparse warning was introduced: warning: mixing different enum types int enum dma_data_direction versus int enum dma_transfer_direction This is produced because the 'dir' passed in ep93xx_spi_dma_prepare is an enum dma_data_direction and is being used to set the dma_slave_config 'direction' which is now an enum dma_transfer_direction. Fix this by converting spi-ep93xx to use the new enum type in all places. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Acked-by: Vinod Koul Signed-off-by: Grant Likely --- drivers/spi/spi-ep93xx.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 6db2887852d6..e8055073e84d 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -545,13 +545,12 @@ static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi) * in case of failure. */ static struct dma_async_tx_descriptor * -ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) +ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir) { struct spi_transfer *t = espi->current_msg->state; struct dma_async_tx_descriptor *txd; enum dma_slave_buswidth buswidth; struct dma_slave_config conf; - enum dma_transfer_direction slave_dirn; struct scatterlist *sg; struct sg_table *sgt; struct dma_chan *chan; @@ -567,14 +566,13 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) memset(&conf, 0, sizeof(conf)); conf.direction = dir; - if (dir == DMA_FROM_DEVICE) { + if (dir == DMA_DEV_TO_MEM) { chan = espi->dma_rx; buf = t->rx_buf; sgt = &espi->rx_sgt; conf.src_addr = espi->sspdr_phys; conf.src_addr_width = buswidth; - slave_dirn = DMA_DEV_TO_MEM; } else { chan = espi->dma_tx; buf = t->tx_buf; @@ -582,7 +580,6 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) conf.dst_addr = espi->sspdr_phys; conf.dst_addr_width = buswidth; - slave_dirn = DMA_MEM_TO_DEV; } ret = dmaengine_slave_config(chan, &conf); @@ -633,8 +630,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) if (!nents) return ERR_PTR(-ENOMEM); - txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, - slave_dirn, DMA_CTRL_ACK); + txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, dir, DMA_CTRL_ACK); if (!txd) { dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir); return ERR_PTR(-ENOMEM); @@ -651,12 +647,12 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) * unmapped. */ static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi, - enum dma_data_direction dir) + enum dma_transfer_direction dir) { struct dma_chan *chan; struct sg_table *sgt; - if (dir == DMA_FROM_DEVICE) { + if (dir == DMA_DEV_TO_MEM) { chan = espi->dma_rx; sgt = &espi->rx_sgt; } else { @@ -677,16 +673,16 @@ static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi) struct spi_message *msg = espi->current_msg; struct dma_async_tx_descriptor *rxd, *txd; - rxd = ep93xx_spi_dma_prepare(espi, DMA_FROM_DEVICE); + rxd = ep93xx_spi_dma_prepare(espi, DMA_DEV_TO_MEM); if (IS_ERR(rxd)) { dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd)); msg->status = PTR_ERR(rxd); return; } - txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE); + txd = ep93xx_spi_dma_prepare(espi, DMA_MEM_TO_DEV); if (IS_ERR(txd)) { - ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE); + ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM); dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd)); msg->status = PTR_ERR(txd); return; @@ -705,8 +701,8 @@ static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi) wait_for_completion(&espi->wait); - ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE); - ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE); + ep93xx_spi_dma_finish(espi, DMA_MEM_TO_DEV); + ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM); } /** -- cgit v1.2.3 From cde4384e1037c15e5dd04c68d19c75798b6281dd Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 20 Apr 2012 15:37:33 +0200 Subject: spi/bcm63xx: convert to the pump message infrastructure This patch converts the bcm63xx SPI driver to use the SPI infrastructure pump message queue. Since we were previously sleeping in the SPI driver's transfer() function (which is not allowed) this is now fixed as well. To complete that conversion a certain number of changes have been made: - the transfer len is split into multiple hardware transfers in case its size is bigger than the hardware FIFO size - the FIFO refill is no longer done in the interrupt context, which was a bad idea leading to quick interrupt handler re-entrancy Tested-by: Tanguy Bouzeloc Signed-off-by: Florian Fainelli Signed-off-by: Grant Likely --- drivers/spi/spi-bcm63xx.c | 149 +++++++++++++++++++++++++++------------------- 1 file changed, 89 insertions(+), 60 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index f01b2648452e..63b0028a8bd3 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -1,7 +1,7 @@ /* * Broadcom BCM63xx SPI controller support * - * Copyright (C) 2009-2011 Florian Fainelli + * Copyright (C) 2009-2012 Florian Fainelli * Copyright (C) 2010 Tanguy Bouzeloc * * This program is free software; you can redistribute it and/or @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include @@ -96,17 +98,12 @@ static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = { { 391000, SPI_CLK_0_391MHZ } }; -static int bcm63xx_spi_setup_transfer(struct spi_device *spi, - struct spi_transfer *t) +static int bcm63xx_spi_check_transfer(struct spi_device *spi, + struct spi_transfer *t) { - struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); u8 bits_per_word; - u8 clk_cfg, reg; - u32 hz; - int i; bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; - hz = (t) ? t->speed_hz : spi->max_speed_hz; if (bits_per_word != 8) { dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", __func__, bits_per_word); @@ -119,6 +116,19 @@ static int bcm63xx_spi_setup_transfer(struct spi_device *spi, return -EINVAL; } + return 0; +} + +static void bcm63xx_spi_setup_transfer(struct spi_device *spi, + struct spi_transfer *t) +{ + struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); + u32 hz; + u8 clk_cfg, reg; + int i; + + hz = (t) ? t->speed_hz : spi->max_speed_hz; + /* Find the closest clock configuration */ for (i = 0; i < SPI_CLK_MASK; i++) { if (hz <= bcm63xx_spi_freq_table[i][0]) { @@ -139,8 +149,6 @@ static int bcm63xx_spi_setup_transfer(struct spi_device *spi, bcm_spi_writeb(bs, reg, SPI_CLK_CFG); dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n", clk_cfg, hz); - - return 0; } /* the spi->mode bits understood by this driver: */ @@ -165,7 +173,7 @@ static int bcm63xx_spi_setup(struct spi_device *spi) return -EINVAL; } - ret = bcm63xx_spi_setup_transfer(spi, NULL); + ret = bcm63xx_spi_check_transfer(spi, NULL); if (ret < 0) { dev_err(&spi->dev, "setup: unsupported mode bits %x\n", spi->mode & ~MODEBITS); @@ -190,28 +198,29 @@ static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs) bs->remaining_bytes -= size; } -static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) +static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi, + struct spi_transfer *t) { struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); u16 msg_ctl; u16 cmd; + /* Disable the CMD_DONE interrupt */ + bcm_spi_writeb(bs, 0, SPI_INT_MASK); + dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", t->tx_buf, t->rx_buf, t->len); /* Transmitter is inhibited */ bs->tx_ptr = t->tx_buf; bs->rx_ptr = t->rx_buf; - init_completion(&bs->done); if (t->tx_buf) { bs->remaining_bytes = t->len; bcm63xx_spi_fill_tx_fifo(bs); } - /* Enable the command done interrupt which - * we use to determine completion of a command */ - bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); + init_completion(&bs->done); /* Fill in the Message control register */ msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT); @@ -230,33 +239,76 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT); bcm_spi_writew(bs, cmd, SPI_CMD); - wait_for_completion(&bs->done); - /* Disable the CMD_DONE interrupt */ - bcm_spi_writeb(bs, 0, SPI_INT_MASK); + /* Enable the CMD_DONE interrupt */ + bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); return t->len - bs->remaining_bytes; } -static int bcm63xx_transfer(struct spi_device *spi, struct spi_message *m) +static int bcm63xx_spi_prepare_transfer(struct spi_master *master) { - struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); - struct spi_transfer *t; - int ret = 0; + struct bcm63xx_spi *bs = spi_master_get_devdata(master); - if (unlikely(list_empty(&m->transfers))) - return -EINVAL; + pm_runtime_get_sync(&bs->pdev->dev); - if (bs->stopping) - return -ESHUTDOWN; + return 0; +} + +static int bcm63xx_spi_unprepare_transfer(struct spi_master *master) +{ + struct bcm63xx_spi *bs = spi_master_get_devdata(master); + + pm_runtime_put(&bs->pdev->dev); + + return 0; +} + +static int bcm63xx_spi_transfer_one(struct spi_master *master, + struct spi_message *m) +{ + struct bcm63xx_spi *bs = spi_master_get_devdata(master); + struct spi_transfer *t; + struct spi_device *spi = m->spi; + int status = 0; + unsigned int timeout = 0; list_for_each_entry(t, &m->transfers, transfer_list) { - ret += bcm63xx_txrx_bufs(spi, t); - } + unsigned int len = t->len; + u8 rx_tail; - m->complete(m->context); + status = bcm63xx_spi_check_transfer(spi, t); + if (status < 0) + goto exit; - return ret; + /* configure adapter for a new transfer */ + bcm63xx_spi_setup_transfer(spi, t); + + while (len) { + /* send the data */ + len -= bcm63xx_txrx_bufs(spi, t); + + timeout = wait_for_completion_timeout(&bs->done, HZ); + if (!timeout) { + status = -ETIMEDOUT; + goto exit; + } + + /* read out all data */ + rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL); + + /* Read out all the data */ + if (rx_tail) + memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail); + } + + m->actual_length += t->len; + } +exit: + m->status = status; + spi_finalize_current_message(master); + + return 0; } /* This driver supports single master mode only. Hence @@ -267,39 +319,15 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id) struct spi_master *master = (struct spi_master *)dev_id; struct bcm63xx_spi *bs = spi_master_get_devdata(master); u8 intr; - u16 cmd; /* Read interupts and clear them immediately */ intr = bcm_spi_readb(bs, SPI_INT_STATUS); bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); bcm_spi_writeb(bs, 0, SPI_INT_MASK); - /* A tansfer completed */ - if (intr & SPI_INTR_CMD_DONE) { - u8 rx_tail; - - rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL); - - /* Read out all the data */ - if (rx_tail) - memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail); - - /* See if there is more data to send */ - if (bs->remaining_bytes > 0) { - bcm63xx_spi_fill_tx_fifo(bs); - - /* Start the transfer */ - bcm_spi_writew(bs, SPI_HD_W << SPI_MSG_TYPE_SHIFT, - SPI_MSG_CTL); - cmd = bcm_spi_readw(bs, SPI_CMD); - cmd |= SPI_CMD_START_IMMEDIATE; - cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); - bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); - bcm_spi_writew(bs, cmd, SPI_CMD); - } else { - complete(&bs->done); - } - } + /* A transfer completed */ + if (intr & SPI_INTR_CMD_DONE) + complete(&bs->done); return IRQ_HANDLED; } @@ -345,7 +373,6 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev) } bs = spi_master_get_devdata(master); - init_completion(&bs->done); platform_set_drvdata(pdev, master); bs->pdev = pdev; @@ -379,7 +406,9 @@ static int __devinit 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->transfer = bcm63xx_transfer; + master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer; + master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer; + master->transfer_one_message = bcm63xx_spi_transfer_one; bs->speed_hz = pdata->speed_hz; bs->stopping = 0; bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); -- cgit v1.2.3 From 1e41dc0ee2f3807328db95e4f87ff1333245190f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 20 Apr 2012 15:37:34 +0200 Subject: spi/bcm63xx: don't use the stopping state We do not need to use a flag to indicate if the master driver is stopping it is sufficient to perform spi master unregistering in the platform driver's remove function. Signed-off-by: Florian Fainelli Signed-off-by: Grant Likely --- drivers/spi/spi-bcm63xx.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 63b0028a8bd3..80e5ed34e0d9 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -39,8 +39,6 @@ #define DRV_VER "0.1.2" struct bcm63xx_spi { - spinlock_t lock; - int stopping; struct completion done; void __iomem *regs; @@ -161,9 +159,6 @@ static int bcm63xx_spi_setup(struct spi_device *spi) bs = spi_master_get_devdata(spi->master); - if (bs->stopping) - return -ESHUTDOWN; - if (!spi->bits_per_word) spi->bits_per_word = 8; @@ -410,10 +405,8 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev) master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer; master->transfer_one_message = bcm63xx_spi_transfer_one; bs->speed_hz = pdata->speed_hz; - bs->stopping = 0; bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA)); - spin_lock_init(&bs->lock); /* Initialize hardware */ clk_enable(bs->clk); @@ -447,18 +440,16 @@ static int __devexit bcm63xx_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct bcm63xx_spi *bs = spi_master_get_devdata(master); + spi_unregister_master(master); + /* reset spi block */ bcm_spi_writeb(bs, 0, SPI_INT_MASK); - spin_lock(&bs->lock); - bs->stopping = 1; /* HW shutdown */ clk_disable(bs->clk); clk_put(bs->clk); - spin_unlock(&bs->lock); platform_set_drvdata(pdev, 0); - spi_unregister_master(master); return 0; } -- cgit v1.2.3 From 88a3a255a510ed193bf0cc35424761c3c9247586 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 20 Apr 2012 15:37:35 +0200 Subject: spi/bcm63xx: set master driver mode_bits. We were not properly advertising the MODE bits supported by this driver, fix that. Signed-off-by: Florian Fainelli Signed-off-by: Grant Likely --- drivers/spi/spi-bcm63xx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 80e5ed34e0d9..7491971139a6 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -404,6 +404,7 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev) 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; bs->speed_hz = pdata->speed_hz; bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA)); -- cgit v1.2.3 From ea505bc99f77f3f9db02bb965bd59ac5db063f60 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 19 Apr 2012 11:48:15 +0530 Subject: spi/pl022: Allow request for higher frequency than maximum possible Currently, if we request for frequency greater than maximum possible, spi driver returns error. For example, if the spi block src frequency is 333/4 MHz, i.e. 83.33.. MHz, maximum frequency programmable would be src/2. Which would come around 41.6... It is difficult to pass frequency in these figures. We normally try to program in round figures, like 42 MHz and it should get programmed to <= requested_frequency, i.e. 41.6... For this to happen, we must not return error even if requested freq is higher than max possible. But should program it to max possible. Reported-by: Vinit Kamalaksha Shenoy Signed-off-by: Viresh Kumar Acked-by: Linus Walleij Signed-off-by: Grant Likely --- drivers/spi/spi-pl022.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 8aa44e7adaef..400ae2121a2a 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1667,9 +1667,15 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct /* cpsdvsr = 254 & scr = 255 */ min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX); - if (!((freq <= max_tclk) && (freq >= min_tclk))) { + if (freq > max_tclk) + dev_warn(&pl022->adev->dev, + "Max speed that can be programmed is %d Hz, you requested %d\n", + max_tclk, freq); + + if (freq < min_tclk) { dev_err(&pl022->adev->dev, - "controller data is incorrect: out of range frequency"); + "Requested frequency: %d Hz is less than minimum possible %d Hz\n", + freq, min_tclk); return -EINVAL; } -- cgit v1.2.3 From 22ac3e82e1d3e5cad92538fe4ab51906cb220444 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Mon, 23 Apr 2012 18:18:08 -0400 Subject: spi/bfin5xx: rename config macro name for bfin5xx spi controller driver This controller is only for blackfin 5xx soc, so rename it to BFIN5XX Signed-off-by: Scott Jiang Signed-off-by: Grant Likely --- drivers/spi/Kconfig | 2 +- drivers/spi/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3ed748355b98..00c024039c97 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -74,7 +74,7 @@ config SPI_ATMEL This selects a driver for the Atmel SPI Controller, present on many AT32 (AVR32) and AT91 (ARM) chips. -config SPI_BFIN +config SPI_BFIN5XX tristate "SPI controller driver for ADI Blackfin5xx" depends on BLACKFIN help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index a1d48e0ba3dc..9d75d2198ff5 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o obj-$(CONFIG_SPI_ATH79) += spi-ath79.o obj-$(CONFIG_SPI_AU1550) += spi-au1550.o obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o -obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o +obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o -- cgit v1.2.3 From 488e1a9de27f0a299fc185f0b5c67246a3f0c6c9 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Mon, 23 Apr 2012 18:18:09 -0400 Subject: spi/spi-bfin-sport: move word length setup to transfer handler Each transfer may have its own bits per word. Signed-off-by: Scott Jiang Signed-off-by: Grant Likely --- drivers/spi/spi-bfin-sport.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index 248a2cc671a9..bfd90474c7e2 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -252,19 +252,15 @@ static void bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data) { struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip; - unsigned int bits = (drv_data->ops == &bfin_sport_transfer_ops_u8 ? 7 : 15); bfin_sport_spi_disable(drv_data); dev_dbg(drv_data->dev, "restoring spi ctl state\n"); bfin_write(&drv_data->regs->tcr1, chip->ctl_reg); - bfin_write(&drv_data->regs->tcr2, bits); bfin_write(&drv_data->regs->tclkdiv, chip->baud); - bfin_write(&drv_data->regs->tfsdiv, bits); SSYNC(); bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS)); - bfin_write(&drv_data->regs->rcr2, bits); SSYNC(); bfin_sport_spi_cs_active(chip); @@ -425,6 +421,9 @@ bfin_sport_spi_pump_transfers(unsigned long data) drv_data->ops = &bfin_sport_transfer_ops_u8; else drv_data->ops = &bfin_sport_transfer_ops_u16; + bfin_write(&drv_data->regs->tcr2, bits_per_word - 1); + bfin_write(&drv_data->regs->tfsdiv, bits_per_word - 1); + bfin_write(&drv_data->regs->rcr2, bits_per_word - 1); drv_data->state = RUNNING_STATE; -- cgit v1.2.3 From 7666fd8b02af87a8b672b00d47e56d77f709127e Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Mon, 23 Apr 2012 18:18:10 -0400 Subject: spi/bfin_spi: drop bits_per_word from client data No other SPI controller has this field, and SPI clients should be setting this up in their own drivers. So drop it from the Blackfin controller to keep people from using it. Signed-off-by: Mike Frysinger Signed-off-by: Scott Jiang Signed-off-by: Grant Likely --- drivers/spi/spi-bfin5xx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 3b83ff8b1e2b..c0cdcb7c8135 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -1026,7 +1026,6 @@ static int bfin_spi_setup(struct spi_device *spi) chip->cs_chg_udelay = chip_info->cs_chg_udelay; chip->idle_tx_val = chip_info->idle_tx_val; chip->pio_interrupt = chip_info->pio_interrupt; - spi->bits_per_word = chip_info->bits_per_word; } else { /* force a default base state */ chip->ctl_reg &= bfin_ctl_reg; -- cgit v1.2.3 From 8d9d2a4b6ca0013b62a438808d22bdd615abcd00 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Mon, 23 Apr 2012 18:18:11 -0400 Subject: spi/spi_bfin_sport: drop bits_per_word from client data Since the member was dropped from the common Blackfin header, we need to stop using it in the SPORT driver too. Signed-off-by: Mike Frysinger Signed-off-by: Scott Jiang Signed-off-by: Grant Likely --- drivers/spi/spi-bfin-sport.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index bfd90474c7e2..1fe51198a622 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -416,11 +416,12 @@ bfin_sport_spi_pump_transfers(unsigned long data) drv_data->cs_change = transfer->cs_change; /* Bits per word setup */ - bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; - if (bits_per_word == 8) - drv_data->ops = &bfin_sport_transfer_ops_u8; - else + bits_per_word = transfer->bits_per_word ? : + message->spi->bits_per_word ? : 8; + if (bits_per_word % 16 == 0) drv_data->ops = &bfin_sport_transfer_ops_u16; + else + drv_data->ops = &bfin_sport_transfer_ops_u8; bfin_write(&drv_data->regs->tcr2, bits_per_word - 1); bfin_write(&drv_data->regs->tfsdiv, bits_per_word - 1); bfin_write(&drv_data->regs->rcr2, bits_per_word - 1); @@ -597,11 +598,12 @@ bfin_sport_spi_setup(struct spi_device *spi) } chip->cs_chg_udelay = chip_info->cs_chg_udelay; chip->idle_tx_val = chip_info->idle_tx_val; - spi->bits_per_word = chip_info->bits_per_word; } } - if (spi->bits_per_word != 8 && spi->bits_per_word != 16) { + 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; } -- cgit v1.2.3 From 128465ca7c0775609b1c24f66cd6bddac5f59c9b Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Mon, 23 Apr 2012 18:18:12 -0400 Subject: spi/spi-bfin5xx: fix reversed if condition in interrupt mode This condition is used to determine 8 bits or 16 and 32 bits transfer. Obviously it is reversed. Signed-off-by: Scott Jiang Signed-off-by: Grant Likely --- drivers/spi/spi-bfin5xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index c0cdcb7c8135..432d0190e6ba 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -396,7 +396,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) /* last read */ if (drv_data->rx) { dev_dbg(&drv_data->pdev->dev, "last read\n"); - if (n_bytes % 2) { + if (!(n_bytes % 2)) { u16 *buf = (u16 *)drv_data->rx; for (loop = 0; loop < n_bytes / 2; loop++) *buf++ = bfin_read(&drv_data->regs->rdbr); @@ -424,7 +424,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) if (drv_data->rx && drv_data->tx) { /* duplex */ dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n"); - if (n_bytes % 2) { + if (!(n_bytes % 2)) { u16 *buf = (u16 *)drv_data->rx; u16 *buf2 = (u16 *)drv_data->tx; for (loop = 0; loop < n_bytes / 2; loop++) { @@ -442,7 +442,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) } else if (drv_data->rx) { /* read */ dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n"); - if (n_bytes % 2) { + if (!(n_bytes % 2)) { u16 *buf = (u16 *)drv_data->rx; for (loop = 0; loop < n_bytes / 2; loop++) { *buf++ = bfin_read(&drv_data->regs->rdbr); @@ -458,7 +458,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) } else if (drv_data->tx) { /* write */ dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n"); - if (n_bytes % 2) { + if (!(n_bytes % 2)) { u16 *buf = (u16 *)drv_data->tx; for (loop = 0; loop < n_bytes / 2; loop++) { bfin_read(&drv_data->regs->rdbr); -- cgit v1.2.3 From 2431a8154634027ce3915200699f26fb3725a1f2 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Mon, 23 Apr 2012 18:18:13 -0400 Subject: spi/spi-bfin5xx: Fix flush of last bit after each spi transfer This patch ensures that the last bit of a transfer gets correctly flushed out of the register. Signed-off-by: Scott Jiang Signed-off-by: Grant Likely --- drivers/spi/spi-bfin5xx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 432d0190e6ba..9bb4d4af8547 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -587,6 +587,7 @@ static void bfin_spi_pump_transfers(unsigned long data) if (message->state == DONE_STATE) { dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n"); message->status = 0; + bfin_spi_flush(drv_data); bfin_spi_giveback(drv_data); return; } @@ -870,8 +871,10 @@ static void bfin_spi_pump_transfers(unsigned long data) message->actual_length += drv_data->len_in_bytes; /* Move to next transfer of this msg */ message->state = bfin_spi_next_transfer(drv_data); - if (drv_data->cs_change) + if (drv_data->cs_change && message->state != DONE_STATE) { + bfin_spi_flush(drv_data); bfin_spi_cs_deactive(drv_data, chip); + } } /* Schedule next transfer tasklet */ -- cgit v1.2.3