From d558c4733759e077cf449246983a5d1fe97fc434 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Mar 2013 11:51:19 +0530 Subject: spi: slink-tegra20: move runtime pm calls to transfer_one_message The prepare_transfer_hardware() is called in atomic context and calling synchronous runtime pm calls can create scheduling deadlock. Therefore, in place of calling runtime PM calls from prepare/unprepare message transfer, calling this in transfer_one_message(). Signed-off-by: Laxman Dewangan Tested-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-slink.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index b8698b389ef..a829563f471 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -858,21 +858,6 @@ static int tegra_slink_setup(struct spi_device *spi) return 0; } -static int tegra_slink_prepare_transfer(struct spi_master *master) -{ - struct tegra_slink_data *tspi = spi_master_get_devdata(master); - - return pm_runtime_get_sync(tspi->dev); -} - -static int tegra_slink_unprepare_transfer(struct spi_master *master) -{ - struct tegra_slink_data *tspi = spi_master_get_devdata(master); - - pm_runtime_put(tspi->dev); - return 0; -} - static int tegra_slink_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -885,6 +870,12 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, msg->status = 0; msg->actual_length = 0; + ret = pm_runtime_get_sync(tspi->dev); + if (ret < 0) { + dev_err(tspi->dev, "runtime get failed: %d\n", ret); + goto done; + } + single_xfer = list_is_singular(&msg->transfers); list_for_each_entry(xfer, &msg->transfers, transfer_list) { INIT_COMPLETION(tspi->xfer_completion); @@ -921,6 +912,8 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, exit: tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND); tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2); + pm_runtime_put(tspi->dev); +done: msg->status = ret; spi_finalize_current_message(master); return ret; @@ -1148,9 +1141,7 @@ static int tegra_slink_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->setup = tegra_slink_setup; - master->prepare_transfer_hardware = tegra_slink_prepare_transfer; master->transfer_one_message = tegra_slink_transfer_one_message; - master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer; master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; -- cgit v1.2.3 From 4a25b680b1e84cf97c740c8005e2c6655d6cfa7f Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Tue, 12 Mar 2013 00:13:36 +0100 Subject: spi/bcm63xx: Remove unused variable This fixes the following warning: drivers/spi/spi-bcm63xx.c: In function 'bcm63xx_spi_setup': drivers/spi/spi-bcm63xx.c:157:6: warning: unused variable 'ret' Signed-off-by: Kevin Cernekee Acked-by: Florian Fainelli Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 9578af782a7..0415a32cce3 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -152,7 +152,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi, static int bcm63xx_spi_setup(struct spi_device *spi) { struct bcm63xx_spi *bs; - int ret; bs = spi_master_get_devdata(spi->master); -- cgit v1.2.3 From b435ff212e91bddc2d12e6638a4d846d5f60daa6 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Tue, 12 Mar 2013 00:13:37 +0100 Subject: spi/bcm63xx: don't disable non enabled clocks in probe error path When msg_ctl_width is set to an invalid value we try to disable the clock despite it never being enabled. Fix it by jumping to the correct label. Signed-off-by: Jonas Gorski Acked-by: Florian Fainelli Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 0415a32cce3..d7df435d962 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -489,7 +489,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) default: dev_err(dev, "unsupported MSG_CTL width: %d\n", bs->msg_ctl_width); - goto out_clk_disable; + goto out_err; } /* Initialize hardware */ -- cgit v1.2.3 From 6c43a519610a5e11af5be707ad88391ce86129ba Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 20 Mar 2013 09:45:22 +0100 Subject: drivers/Kconfig: add several missing GENERIC_HARDIRQS dependencies With this patch an allmodconfig finally builds on s390 again. Fixes these build errors: ERROR: "devm_request_threaded_irq" [drivers/spi/spi-altera.ko] undefined! ERROR: "devm_request_threaded_irq" [drivers/media/platform/sh_veu.ko] undefined! ERROR: "devm_request_threaded_irq" [drivers/dma/dw_dmac.ko] undefined! Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/spi/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/spi') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f80eee74a31..2be0de920d6 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -55,6 +55,7 @@ comment "SPI Master Controller Drivers" config SPI_ALTERA tristate "Altera SPI Controller" + depends on GENERIC_HARDIRQS select SPI_BITBANG help This is the driver for the Altera SPI Controller. @@ -310,7 +311,7 @@ config SPI_PXA2XX_DMA config SPI_PXA2XX tristate "PXA2xx SSP SPI master" - depends on ARCH_PXA || PCI || ACPI + depends on (ARCH_PXA || PCI || ACPI) && GENERIC_HARDIRQS select PXA_SSP if ARCH_PXA help This enables using a PXA2xx or Sodaville SSP port as a SPI master -- cgit v1.2.3 From 375981f2e14868be16cafbffd34a4f16a6ee01c6 Mon Sep 17 00:00:00 2001 From: Girish K S Date: Wed, 13 Mar 2013 12:13:30 +0530 Subject: spi/s3c64xx: modified error interrupt handling and init The status of the interrupt is available in the status register, so reading the clear pending register and writing back the same value will not actually clear the pending interrupts. This patch modifies the interrupt handler to read the status register and clear the corresponding pending bit in the clear pending register. Modified the hwInit function to clear all the pending interrupts. Signed-off-by: Girish K S Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-s3c64xx.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index e862ab8853a..4188b2faac5 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -994,25 +994,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data) { struct s3c64xx_spi_driver_data *sdd = data; struct spi_master *spi = sdd->master; - unsigned int val; + unsigned int val, clr = 0; - val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR); + val = readl(sdd->regs + S3C64XX_SPI_STATUS); - val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR | - S3C64XX_SPI_PND_RX_UNDERRUN_CLR | - S3C64XX_SPI_PND_TX_OVERRUN_CLR | - S3C64XX_SPI_PND_TX_UNDERRUN_CLR; - - writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR); - - if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR) + if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) { + clr = S3C64XX_SPI_PND_RX_OVERRUN_CLR; dev_err(&spi->dev, "RX overrun\n"); - if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR) + } + if (val & S3C64XX_SPI_ST_RX_UNDERRUN_ERR) { + clr |= S3C64XX_SPI_PND_RX_UNDERRUN_CLR; dev_err(&spi->dev, "RX underrun\n"); - if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR) + } + if (val & S3C64XX_SPI_ST_TX_OVERRUN_ERR) { + clr |= S3C64XX_SPI_PND_TX_OVERRUN_CLR; dev_err(&spi->dev, "TX overrun\n"); - if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR) + } + if (val & S3C64XX_SPI_ST_TX_UNDERRUN_ERR) { + clr |= S3C64XX_SPI_PND_TX_UNDERRUN_CLR; dev_err(&spi->dev, "TX underrun\n"); + } + + /* Clear the pending irq by setting and then clearing it */ + writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR); + writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR); return IRQ_HANDLED; } @@ -1036,9 +1041,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) writel(0, regs + S3C64XX_SPI_MODE_CFG); writel(0, regs + S3C64XX_SPI_PACKET_CNT); - /* Clear any irq pending bits */ - writel(readl(regs + S3C64XX_SPI_PENDING_CLR), - regs + S3C64XX_SPI_PENDING_CLR); + /* Clear any irq pending bits, should set and clear the bits */ + val = S3C64XX_SPI_PND_RX_OVERRUN_CLR | + S3C64XX_SPI_PND_RX_UNDERRUN_CLR | + S3C64XX_SPI_PND_TX_OVERRUN_CLR | + S3C64XX_SPI_PND_TX_UNDERRUN_CLR; + writel(val, regs + S3C64XX_SPI_PENDING_CLR); + writel(0, regs + S3C64XX_SPI_PENDING_CLR); writel(0, regs + S3C64XX_SPI_SWAP_CFG); -- cgit v1.2.3 From b0b36b861e434ee1c1a64cb39259e262f79af62e Mon Sep 17 00:00:00 2001 From: Bryan Freed Date: Wed, 13 Mar 2013 11:17:40 -0700 Subject: spi: Unlock a spinlock before calling into the controller driver. spi_pump_messages() calls into a controller driver with unprepare_transfer_hardware() which is documented as "This may sleep". As in the prepare_transfer_hardware() call below, we should release the queue_lock spinlock before making the call. Rework the logic a bit to hold queue_lock to protect the 'busy' flag, then release it to call unprepare_transfer_hardware(). Signed-off-by: Bryan Freed Reviewed-by: Doug Anderson Signed-off-by: Doug Anderson Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index f996c600eb8..5b96250b062 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work) /* Lock queue and check for queue work */ spin_lock_irqsave(&master->queue_lock, flags); if (list_empty(&master->queue) || !master->running) { - if (master->busy && master->unprepare_transfer_hardware) { - ret = master->unprepare_transfer_hardware(master); - if (ret) { - spin_unlock_irqrestore(&master->queue_lock, flags); - dev_err(&master->dev, - "failed to unprepare transfer hardware\n"); - return; - } + if (!master->busy) { + spin_unlock_irqrestore(&master->queue_lock, flags); + return; } master->busy = false; spin_unlock_irqrestore(&master->queue_lock, flags); + if (master->unprepare_transfer_hardware && + master->unprepare_transfer_hardware(master)) + dev_err(&master->dev, + "failed to unprepare transfer hardware\n"); return; } -- cgit v1.2.3 From 1ad849aee5f53353ed88d9cd3d68a51b03a7d44f Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Wed, 13 Mar 2013 14:57:43 +0100 Subject: spi/mpc512x-psc: optionally keep PSC SS asserted across xfer segmensts Some SPI slave devices require asserted chip select signal across multiple transfer segments of an SPI message. Currently the driver always de-asserts the internal SS signal for every single transfer segment of the message and ignores the 'cs_change' flag of the transfer description. Disable the internal chip select (SS) only if this is needed and indicated by the 'cs_change' flag. Without this change, each partial transfer of a surrounding multi-part SPI transaction might erroneously change the SS signal, which might prevent slaves from answering the request that was sent in a previous transfer segment because the transaction could be considered aborted (SS was de-asserted before reading the response). Reported-by: Gerhard Sittig Signed-off-by: Anatolij Gustschin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-mpc512x-psc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 89480b281d7..3e490ee7f27 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, for (i = count; i > 0; i--) { data = tx_buf ? *tx_buf++ : 0; - if (len == EOFBYTE) + if (len == EOFBYTE && t->cs_change) setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); out_8(&fifo->txdata_8, data); len--; -- cgit v1.2.3 From 29896178cff0cd6e4ee78edc26158cc197a6b504 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 1 Apr 2013 00:21:08 +0000 Subject: ACPI / SPI: Use parent's ACPI_HANDLE() in acpi_register_spi_devices() The ACPI handle of struct spi_master's dev member should not be set, because this causes that struct spi_master to be associated with the ACPI device node corresponding to its parent as the second "physical_device", which is incorrect (this happens during the registration of struct spi_master). Consequently, acpi_register_spi_devices() should use the ACPI handle of the parent of the struct spi_master it is called for rather than that struct spi_master's ACPI handle (which should be NULL). Make that happen and modify the spi-pxa2xx driver, which currently is the only driver for ACPI-enumerated SPI controller chips, not to set the ACPI handle for the struct spi_master it creates. Signed-off-by: Rafael J. Wysocki Acked-by: Mika Westerberg Acked-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 1 - drivers/spi/spi.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 90b27a3508a..810413883c7 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1168,7 +1168,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) master->dev.parent = &pdev->dev; master->dev.of_node = pdev->dev.of_node; - ACPI_HANDLE_SET(&master->dev, ACPI_HANDLE(&pdev->dev)); /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index f996c600eb8..5e073d897ed 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -984,7 +984,7 @@ static void acpi_register_spi_devices(struct spi_master *master) acpi_status status; acpi_handle handle; - handle = ACPI_HANDLE(&master->dev); + handle = ACPI_HANDLE(master->dev.parent); if (!handle) return; -- cgit v1.2.3