diff options
Diffstat (limited to 'target/linux/brcm63xx/patches-3.3/013-spi-bcm63xx-convert-to-the-pump-message-infrastructu.patch')
-rw-r--r-- | target/linux/brcm63xx/patches-3.3/013-spi-bcm63xx-convert-to-the-pump-message-infrastructu.patch | 289 |
1 files changed, 0 insertions, 289 deletions
diff --git a/target/linux/brcm63xx/patches-3.3/013-spi-bcm63xx-convert-to-the-pump-message-infrastructu.patch b/target/linux/brcm63xx/patches-3.3/013-spi-bcm63xx-convert-to-the-pump-message-infrastructu.patch deleted file mode 100644 index 7d4d951..0000000 --- a/target/linux/brcm63xx/patches-3.3/013-spi-bcm63xx-convert-to-the-pump-message-infrastructu.patch +++ /dev/null @@ -1,289 +0,0 @@ -From cde4384e1037c15e5dd04c68d19c75798b6281dd Mon Sep 17 00:00:00 2001 -From: Florian Fainelli <florian@openwrt.org> -Date: Fri, 20 Apr 2012 15:37:33 +0200 -Subject: [PATCH] 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 <tanguy.bouzeloc@efixo.com> -Signed-off-by: Florian Fainelli <florian@openwrt.org> -Signed-off-by: Grant Likely <grant.likely@secretlab.ca> ---- - drivers/spi/spi-bcm63xx.c | 149 +++++++++++++++++++++++++++------------------ - 1 file changed, 89 insertions(+), 60 deletions(-) - ---- 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 <florian@openwrt.org> -+ * Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org> - * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> - * - * This program is free software; you can redistribute it and/or -@@ -30,6 +30,8 @@ - #include <linux/spi/spi.h> - #include <linux/completion.h> - #include <linux/err.h> -+#include <linux/workqueue.h> -+#include <linux/pm_runtime.h> - - #include <bcm63xx_dev_spi.h> - -@@ -96,17 +98,12 @@ static const unsigned bcm63xx_spi_freq_t - { 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(st - 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(st - 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_ - 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(str - 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_ - 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; -+ -+ /* 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 ret; -+ return 0; - } - - /* This driver supports single master mode only. Hence -@@ -267,39 +319,15 @@ static irqreturn_t bcm63xx_spi_interrupt - 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(s - } - - 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(s - 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)); |