From 4870c2170d91f33a1a90bd5b1d7c5534332f30f2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 28 Jun 2013 11:43:34 -0700 Subject: [PATCH 01/11] spi: spi-ep93xx: always handle transfer specific settings __spi_async(), which starts every SPI message transfer, initializes the bits_per_word and max speed for every transfer in the message. Since the conditional test in ep93xx_spi_process_transfer() will always succeed just remove it and always call ep93xx_spi_chip_setup() to configure the hardware for each transfer in the message. Remove the redundant ep93xx_spi_chp_setup() in ep93xx_spi_process_transfer() which just initializes the hardware to the "default" based on the SPI device. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 45 ++++++++++------------------------------ 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index cad30b8a1d71..11e2b999cce2 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -708,39 +708,21 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, struct spi_transfer *t) { struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi); + int err; msg->state = t; - /* - * Handle any transfer specific settings if needed. We use - * temporary chip settings here and restore original later when - * the transfer is finished. - */ - if (t->speed_hz || t->bits_per_word) { - struct ep93xx_spi_chip tmp_chip = *chip; - - if (t->speed_hz) { - int err; - - err = ep93xx_spi_calc_divisors(espi, &tmp_chip, - t->speed_hz); - if (err) { - dev_err(&espi->pdev->dev, - "failed to adjust speed\n"); - msg->status = err; - return; - } - } - - if (t->bits_per_word) - tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word); - - /* - * Set up temporary new hw settings for this transfer. - */ - ep93xx_spi_chip_setup(espi, &tmp_chip); + err = ep93xx_spi_calc_divisors(espi, chip, t->speed_hz); + if (err) { + dev_err(&espi->pdev->dev, "failed to adjust speed\n"); + msg->status = err; + return; } + chip->dss = bits_per_word_to_dss(t->bits_per_word); + + ep93xx_spi_chip_setup(espi, chip); + espi->rx = 0; espi->tx = 0; @@ -783,9 +765,6 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, ep93xx_spi_cs_control(msg->spi, true); } } - - if (t->speed_hz || t->bits_per_word) - ep93xx_spi_chip_setup(espi, chip); } /* @@ -838,10 +817,8 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi, espi->fifo_level = 0; /* - * Update SPI controller registers according to spi device and assert - * the chipselect. + * Assert the chipselect. */ - ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi)); ep93xx_spi_cs_control(msg->spi, true); list_for_each_entry(t, &msg->transfers, transfer_list) { From 8d7586bda032748ceec44416fa32a711a62e4954 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:06:26 -0700 Subject: [PATCH 02/11] spi: spi-ep93xx: use read,write instead of __raw_* variants The memory resource used by this driver is ioremap()'d and the normal read,write calls can be used instead of the __raw_* variants. Also, remove the inline tag on the helper functions and let the compiler decide if they are inlined. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 11e2b999cce2..d7eccfc40ac9 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -158,28 +158,26 @@ struct ep93xx_spi_chip { /* converts bits per word to CR0.DSS value */ #define bits_per_word_to_dss(bpw) ((bpw) - 1) -static inline void -ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value) +static void ep93xx_spi_write_u8(const struct ep93xx_spi *espi, + u16 reg, u8 value) { - __raw_writeb(value, espi->regs_base + reg); + writeb(value, espi->regs_base + reg); } -static inline u8 -ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg) +static u8 ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg) { - return __raw_readb(spi->regs_base + reg); + return readb(spi->regs_base + reg); } -static inline void -ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value) +static void ep93xx_spi_write_u16(const struct ep93xx_spi *espi, + u16 reg, u16 value) { - __raw_writew(value, espi->regs_base + reg); + writew(value, espi->regs_base + reg); } -static inline u16 -ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg) +static u16 ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg) { - return __raw_readw(spi->regs_base + reg); + return readw(spi->regs_base + reg); } static int ep93xx_spi_enable(const struct ep93xx_spi *espi) From 701c3587ee38ed53719187b0f1b059e113ac534f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:07:01 -0700 Subject: [PATCH 03/11] spi: spi-ep93xx: remove bits_per_word() helper Check t->bits_per_word directly and remove the inline helper function. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d7eccfc40ac9..d5e64201cdd3 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -429,17 +429,9 @@ static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, ep93xx_spi_write_u16(espi, SSPCR0, cr0); } -static inline int bits_per_word(const struct ep93xx_spi *espi) -{ - struct spi_message *msg = espi->current_msg; - struct spi_transfer *t = msg->state; - - return t->bits_per_word; -} - static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) { - if (bits_per_word(espi) > 8) { + if (t->bits_per_word > 8) { u16 tx_val = 0; if (t->tx_buf) @@ -458,7 +450,7 @@ static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t) { - if (bits_per_word(espi) > 8) { + if (t->bits_per_word > 8) { u16 rx_val; rx_val = ep93xx_spi_read_u16(espi, SSPDR); @@ -544,7 +536,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir) size_t len = t->len; int i, ret, nents; - if (bits_per_word(espi) > 8) + if (t->bits_per_word > 8) buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; else buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; From 48a7776e981fdf780728e45de4ae4f2b522c9c4d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:07:53 -0700 Subject: [PATCH 04/11] spi: spi-ep93xx: get platform resources early in (*probe) Get the platform resources early in the (*probe) to minimize the number of goto's in the error path. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d5e64201cdd3..c2660c24c0ab 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -991,6 +991,18 @@ static int ep93xx_spi_probe(struct platform_device *pdev) info = pdev->dev.platform_data; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get irq resources\n"); + return -EBUSY; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "unable to get iomem resource\n"); + return -ENODEV; + } + master = spi_alloc_master(&pdev->dev, sizeof(*espi)); if (!master) { dev_err(&pdev->dev, "failed to allocate spi master\n"); @@ -1027,20 +1039,6 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi->min_rate = clk_get_rate(espi->clk) / (254 * 256); espi->pdev = pdev; - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - error = -EBUSY; - dev_err(&pdev->dev, "failed to get irq resources\n"); - goto fail_put_clock; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "unable to get iomem resource\n"); - error = -ENODEV; - goto fail_put_clock; - } - espi->sspdr_phys = res->start + SSPDR; espi->regs_base = devm_ioremap_resource(&pdev->dev, res); From b2d185edbac9c40adb1d390ad966e6900992e69d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:08:59 -0700 Subject: [PATCH 05/11] spi: spi-ep93xx: remove dev_err() for kzalloc() failure The kzalloc() failure will have already output a message. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index c2660c24c0ab..7a44163ace50 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -1004,10 +1004,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev) } master = spi_alloc_master(&pdev->dev, sizeof(*espi)); - if (!master) { - dev_err(&pdev->dev, "failed to allocate spi master\n"); + if (!master) return -ENOMEM; - } master->setup = ep93xx_spi_setup; master->transfer = ep93xx_spi_transfer; From d9b65dfd44fdade5c0fde5f7b8a0f267e99f990d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:09:29 -0700 Subject: [PATCH 06/11] spi: spi-ep93xx: remove 'dss' from per chip private data This value is only needed to set the bits per word for each transfer of a message. There is no reason to set the value in ep93xx_spi_enable() because ep93xx_spi_process_transfer() sets it again for each transfer. Just pass the t->bits_per_word directly to ep93xx_spi_chip_setup() in ep93xx_spi_process_transfer() and remove 'dss' from the per chip private data. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 7a44163ace50..8d562526abe5 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -139,7 +139,6 @@ struct ep93xx_spi { * @rate: max rate in hz this chip supports * @div_cpsr: cpsr (pre-scaler) divider * @div_scr: scr divider - * @dss: bits per word (4 - 16 bits) * @ops: private chip operations * * This structure is used to store hardware register specific settings for each @@ -151,7 +150,6 @@ struct ep93xx_spi_chip { unsigned long rate; u8 div_cpsr; u8 div_scr; - u8 dss; struct ep93xx_spi_chip_ops *ops; }; @@ -329,8 +327,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) chip->rate = spi->max_speed_hz; } - chip->dss = bits_per_word_to_dss(spi->bits_per_word); - ep93xx_spi_cs_control(spi, false); return 0; } @@ -407,22 +403,25 @@ static void ep93xx_spi_cleanup(struct spi_device *spi) * ep93xx_spi_chip_setup() - configures hardware according to given @chip * @espi: ep93xx SPI controller struct * @chip: chip specific settings + * @bits_per_word: transfer bits_per_word * * This function sets up the actual hardware registers with settings given in * @chip. Note that no validation is done so make sure that callers validate * settings before calling this. */ static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, - const struct ep93xx_spi_chip *chip) + const struct ep93xx_spi_chip *chip, + u8 bits_per_word) { + u8 dss = bits_per_word_to_dss(bits_per_word); u16 cr0; cr0 = chip->div_scr << SSPCR0_SCR_SHIFT; cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; - cr0 |= chip->dss; + cr0 |= dss; dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", - chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss); + chip->spi->mode, chip->div_cpsr, chip->div_scr, dss); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr); @@ -709,9 +708,7 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, return; } - chip->dss = bits_per_word_to_dss(t->bits_per_word); - - ep93xx_spi_chip_setup(espi, chip); + ep93xx_spi_chip_setup(espi, chip, t->bits_per_word); espi->rx = 0; espi->tx = 0; From e6eb8d9bb7b9c144ae63a5e97a686dd8a3377443 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:08:21 -0700 Subject: [PATCH 07/11] spi: spi-ep93xx: use devm_clk_get() Use devm_clk_get() so that the clk_put() happens automatically when the last reference to this driver is dropped. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 8d562526abe5..cc2a2405bd1d 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -1016,7 +1016,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi = spi_master_get_devdata(master); - espi->clk = clk_get(&pdev->dev, NULL); + espi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(espi->clk)) { dev_err(&pdev->dev, "unable to get spi clock\n"); error = PTR_ERR(espi->clk); @@ -1039,14 +1039,14 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi->regs_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(espi->regs_base)) { error = PTR_ERR(espi->regs_base); - goto fail_put_clock; + goto fail_release_master; } error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt, 0, "ep93xx-spi", espi); if (error) { dev_err(&pdev->dev, "failed to request irq\n"); - goto fail_put_clock; + goto fail_release_master; } if (info->use_dma && ep93xx_spi_setup_dma(espi)) @@ -1080,8 +1080,6 @@ fail_free_queue: destroy_workqueue(espi->wq); fail_free_dma: ep93xx_spi_release_dma(espi); -fail_put_clock: - clk_put(espi->clk); fail_release_master: spi_master_put(master); @@ -1117,7 +1115,6 @@ static int ep93xx_spi_remove(struct platform_device *pdev) spin_unlock_irq(&espi->lock); ep93xx_spi_release_dma(espi); - clk_put(espi->clk); spi_unregister_master(master); return 0; From 22c1b69ea833de84a9505135303ff443e62b3b15 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:10:00 -0700 Subject: [PATCH 08/11] spi: spi-ep93xx: don't bother calculating the divisors in ep93xx_spi_setup() The divisors needed to generate the SPI clock are calculated per transfer based on the t->speed_hz. There is no reason to calculate them in ep93xx_spi_setup(). Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index cc2a2405bd1d..6cdfc4036b75 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -136,7 +136,6 @@ struct ep93xx_spi { /** * struct ep93xx_spi_chip - SPI device hardware settings * @spi: back pointer to the SPI device - * @rate: max rate in hz this chip supports * @div_cpsr: cpsr (pre-scaler) divider * @div_scr: scr divider * @ops: private chip operations @@ -147,7 +146,6 @@ struct ep93xx_spi { */ struct ep93xx_spi_chip { const struct spi_device *spi; - unsigned long rate; u8 div_cpsr; u8 div_scr; struct ep93xx_spi_chip_ops *ops; @@ -315,18 +313,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) spi_set_ctldata(spi, chip); } - if (spi->max_speed_hz != chip->rate) { - int err; - - err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz); - if (err != 0) { - spi_set_ctldata(spi, NULL); - kfree(chip); - return err; - } - chip->rate = spi->max_speed_hz; - } - ep93xx_spi_cs_control(spi, false); return 0; } From f7ef1da9e22ce390333645fc0ea70ff279eecd55 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:10:29 -0700 Subject: [PATCH 09/11] spi: spi-ep93xx: move the clock divider calcs into ep93xx_spi_chip_setup() The divider values stored in the per chip data are only used to set the registers in the hardware to generate the desired SPI clock. Since these are calculated per transfer based on the t->speed_hz there is no reason keep them in the per chip data. Move the ep93xx_spi_calc_divisors() call into ep93xx_spi_chip_setup() and return the dividers thru pointers. Remove the divider values from the per chip data structure. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 57 ++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 6cdfc4036b75..2e64806b40af 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -136,18 +136,10 @@ struct ep93xx_spi { /** * struct ep93xx_spi_chip - SPI device hardware settings * @spi: back pointer to the SPI device - * @div_cpsr: cpsr (pre-scaler) divider - * @div_scr: scr divider * @ops: private chip operations - * - * This structure is used to store hardware register specific settings for each - * SPI device. Settings are written to hardware by function - * ep93xx_spi_chip_setup(). */ struct ep93xx_spi_chip { const struct spi_device *spi; - u8 div_cpsr; - u8 div_scr; struct ep93xx_spi_chip_ops *ops; }; @@ -224,17 +216,13 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi) /** * ep93xx_spi_calc_divisors() - calculates SPI clock divisors * @espi: ep93xx SPI controller struct - * @chip: divisors are calculated for this chip * @rate: desired SPI output clock rate - * - * Function calculates cpsr (clock pre-scaler) and scr divisors based on - * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If, - * for some reason, divisors cannot be calculated nothing is stored and - * %-EINVAL is returned. + * @div_cpsr: pointer to return the cpsr (pre-scaler) divider + * @div_scr: pointer to return the scr divider */ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, - struct ep93xx_spi_chip *chip, - unsigned long rate) + unsigned long rate, + u8 *div_cpsr, u8 *div_scr) { unsigned long spi_clk_rate = clk_get_rate(espi->clk); int cpsr, scr; @@ -257,8 +245,8 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, for (cpsr = 2; cpsr <= 254; cpsr += 2) { for (scr = 0; scr <= 255; scr++) { if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) { - chip->div_scr = (u8)scr; - chip->div_cpsr = (u8)cpsr; + *div_scr = (u8)scr; + *div_cpsr = (u8)cpsr; return 0; } } @@ -389,29 +377,35 @@ static void ep93xx_spi_cleanup(struct spi_device *spi) * ep93xx_spi_chip_setup() - configures hardware according to given @chip * @espi: ep93xx SPI controller struct * @chip: chip specific settings + * @speed_hz: transfer speed * @bits_per_word: transfer bits_per_word - * - * This function sets up the actual hardware registers with settings given in - * @chip. Note that no validation is done so make sure that callers validate - * settings before calling this. */ -static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, - const struct ep93xx_spi_chip *chip, - u8 bits_per_word) +static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, + const struct ep93xx_spi_chip *chip, + u32 speed_hz, u8 bits_per_word) { u8 dss = bits_per_word_to_dss(bits_per_word); + u8 div_cpsr = 0; + u8 div_scr = 0; u16 cr0; + int err; - cr0 = chip->div_scr << SSPCR0_SCR_SHIFT; + err = ep93xx_spi_calc_divisors(espi, speed_hz, &div_cpsr, &div_scr); + if (err) + return err; + + cr0 = div_scr << SSPCR0_SCR_SHIFT; cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; cr0 |= dss; dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", - chip->spi->mode, chip->div_cpsr, chip->div_scr, dss); + chip->spi->mode, div_cpsr, div_scr, dss); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); - ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr); + ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr); ep93xx_spi_write_u16(espi, SSPCR0, cr0); + + return 0; } static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) @@ -687,15 +681,14 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, msg->state = t; - err = ep93xx_spi_calc_divisors(espi, chip, t->speed_hz); + err = ep93xx_spi_chip_setup(espi, chip, t->speed_hz, t->bits_per_word); if (err) { - dev_err(&espi->pdev->dev, "failed to adjust speed\n"); + dev_err(&espi->pdev->dev, + "failed to setup chip for transfer\n"); msg->status = err; return; } - ep93xx_spi_chip_setup(espi, chip, t->bits_per_word); - espi->rx = 0; espi->tx = 0; From 84ddb3c1df021c69a40af30e3e30cc7429a5d659 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 8 Jul 2013 09:12:37 -0700 Subject: [PATCH 10/11] spi: spi-ep93xx: convert to the queued driver infrastructure The SPI core provides infrastructure for standard message queueing. Use that instead of handling it in the driver. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 165 +++++---------------------------------- 1 file changed, 19 insertions(+), 146 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 2e64806b40af..4c9a50ce4f6c 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -70,19 +69,13 @@ /** * struct ep93xx_spi - EP93xx SPI controller structure - * @lock: spinlock that protects concurrent accesses to fields @running, - * @current_msg and @msg_queue * @pdev: pointer to platform device * @clk: clock for the controller * @regs_base: pointer to ioremap()'d registers * @sspdr_phys: physical address of the SSPDR register * @min_rate: minimum clock rate (in Hz) supported by the controller * @max_rate: maximum clock rate (in Hz) supported by the controller - * @running: is the queue running - * @wq: workqueue used by the driver - * @msg_work: work that is queued for the driver * @wait: wait here until given transfer is completed - * @msg_queue: queue for the messages * @current_msg: message that is currently processed (or %NULL if none) * @tx: current byte in transfer to transmit * @rx: current byte in transfer to receive @@ -96,30 +89,15 @@ * @tx_sgt: sg table for TX transfers * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by * the client - * - * This structure holds EP93xx SPI controller specific information. When - * @running is %true, driver accepts transfer requests from protocol drivers. - * @current_msg is used to hold pointer to the message that is currently - * processed. If @current_msg is %NULL, it means that no processing is going - * on. - * - * Most of the fields are only written once and they can be accessed without - * taking the @lock. Fields that are accessed concurrently are: @current_msg, - * @running, and @msg_queue. */ struct ep93xx_spi { - spinlock_t lock; const struct platform_device *pdev; struct clk *clk; void __iomem *regs_base; unsigned long sspdr_phys; unsigned long min_rate; unsigned long max_rate; - bool running; - struct workqueue_struct *wq; - struct work_struct msg_work; struct completion wait; - struct list_head msg_queue; struct spi_message *current_msg; size_t tx; size_t rx; @@ -230,7 +208,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, /* * Make sure that max value is between values supported by the * controller. Note that minimum value is already checked in - * ep93xx_spi_transfer(). + * ep93xx_spi_transfer_one_message(). */ rate = clamp(rate, espi->min_rate, espi->max_rate); @@ -305,54 +283,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) return 0; } -/** - * ep93xx_spi_transfer() - queue message to be transferred - * @spi: target SPI device - * @msg: message to be transferred - * - * This function is called by SPI device drivers when they are going to transfer - * a new message. It simply puts the message in the queue and schedules - * workqueue to perform the actual transfer later on. - * - * Returns %0 on success and negative error in case of failure. - */ -static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) -{ - struct ep93xx_spi *espi = spi_master_get_devdata(spi->master); - struct spi_transfer *t; - unsigned long flags; - - if (!msg || !msg->complete) - return -EINVAL; - - /* first validate each transfer */ - list_for_each_entry(t, &msg->transfers, transfer_list) { - if (t->speed_hz && t->speed_hz < espi->min_rate) - return -EINVAL; - } - - /* - * Now that we own the message, let's initialize it so that it is - * suitable for us. We use @msg->status to signal whether there was - * error in transfer and @msg->state is used to hold pointer to the - * current transfer (or %NULL if no active current transfer). - */ - msg->state = NULL; - msg->status = 0; - msg->actual_length = 0; - - spin_lock_irqsave(&espi->lock, flags); - if (!espi->running) { - spin_unlock_irqrestore(&espi->lock, flags); - return -ESHUTDOWN; - } - list_add_tail(&msg->queue, &espi->msg_queue); - queue_work(espi->wq, &espi->msg_work); - spin_unlock_irqrestore(&espi->lock, flags); - - return 0; -} - /** * ep93xx_spi_cleanup() - cleans up master controller specific state * @spi: SPI device to cleanup @@ -801,50 +731,29 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi, ep93xx_spi_disable(espi); } -#define work_to_espi(work) (container_of((work), struct ep93xx_spi, msg_work)) - -/** - * ep93xx_spi_work() - EP93xx SPI workqueue worker function - * @work: work struct - * - * Workqueue worker function. This function is called when there are new - * SPI messages to be processed. Message is taken out from the queue and then - * passed to ep93xx_spi_process_message(). - * - * After message is transferred, protocol driver is notified by calling - * @msg->complete(). In case of error, @msg->status is set to negative error - * number, otherwise it contains zero (and @msg->actual_length is updated). - */ -static void ep93xx_spi_work(struct work_struct *work) +static int ep93xx_spi_transfer_one_message(struct spi_master *master, + struct spi_message *msg) { - struct ep93xx_spi *espi = work_to_espi(work); - struct spi_message *msg; + struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct spi_transfer *t; - spin_lock_irq(&espi->lock); - if (!espi->running || espi->current_msg || - list_empty(&espi->msg_queue)) { - spin_unlock_irq(&espi->lock); - return; + /* first validate each transfer */ + list_for_each_entry(t, &msg->transfers, transfer_list) { + if (t->speed_hz < espi->min_rate) + return -EINVAL; } - msg = list_first_entry(&espi->msg_queue, struct spi_message, queue); - list_del_init(&msg->queue); + + msg->state = NULL; + msg->status = 0; + msg->actual_length = 0; + espi->current_msg = msg; - spin_unlock_irq(&espi->lock); - ep93xx_spi_process_message(espi, msg); - - /* - * Update the current message and re-schedule ourselves if there are - * more messages in the queue. - */ - spin_lock_irq(&espi->lock); espi->current_msg = NULL; - if (espi->running && !list_empty(&espi->msg_queue)) - queue_work(espi->wq, &espi->msg_work); - spin_unlock_irq(&espi->lock); - /* notify the protocol driver that we are done with this message */ - msg->complete(msg->context); + spi_finalize_current_message(master); + + return 0; } static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id) @@ -984,7 +893,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) return -ENOMEM; master->setup = ep93xx_spi_setup; - master->transfer = ep93xx_spi_transfer; + master->transfer_one_message = ep93xx_spi_transfer_one_message; master->cleanup = ep93xx_spi_cleanup; master->bus_num = pdev->id; master->num_chipselect = info->num_chipselect; @@ -1002,7 +911,6 @@ static int ep93xx_spi_probe(struct platform_device *pdev) goto fail_release_master; } - spin_lock_init(&espi->lock); init_completion(&espi->wait); /* @@ -1031,23 +939,13 @@ static int ep93xx_spi_probe(struct platform_device *pdev) if (info->use_dma && ep93xx_spi_setup_dma(espi)) dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n"); - 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); - INIT_LIST_HEAD(&espi->msg_queue); - espi->running = true; - /* make sure that the hardware is disabled */ ep93xx_spi_write_u8(espi, SSPCR1, 0); error = spi_register_master(master); if (error) { dev_err(&pdev->dev, "failed to register SPI master\n"); - goto fail_free_queue; + goto fail_free_dma; } dev_info(&pdev->dev, "EP93xx SPI Controller at 0x%08lx irq %d\n", @@ -1055,8 +953,6 @@ static int ep93xx_spi_probe(struct platform_device *pdev) return 0; -fail_free_queue: - destroy_workqueue(espi->wq); fail_free_dma: ep93xx_spi_release_dma(espi); fail_release_master: @@ -1070,29 +966,6 @@ static int ep93xx_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct ep93xx_spi *espi = spi_master_get_devdata(master); - spin_lock_irq(&espi->lock); - espi->running = false; - spin_unlock_irq(&espi->lock); - - destroy_workqueue(espi->wq); - - /* - * Complete remaining messages with %-ESHUTDOWN status. - */ - spin_lock_irq(&espi->lock); - while (!list_empty(&espi->msg_queue)) { - struct spi_message *msg; - - msg = list_first_entry(&espi->msg_queue, - struct spi_message, queue); - list_del_init(&msg->queue); - msg->status = -ESHUTDOWN; - spin_unlock_irq(&espi->lock); - msg->complete(msg->context); - spin_lock_irq(&espi->lock); - } - spin_unlock_irq(&espi->lock); - ep93xx_spi_release_dma(espi); spi_unregister_master(master); From 6a3fc31f35025a583499c0d3b1c6fc5dcf6e48ec Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Tue, 30 Jul 2013 19:35:36 +0200 Subject: [PATCH 11/11] spi/ep93xx: Fix format specifier warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the following sparse warning by changing the the format specifier for size_t to %zu. drivers/spi/spi-ep93xx.c:512:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘size_t’ [-Wformat] Signed-off-by: Emil Goode Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 4c9a50ce4f6c..31611f7d7be9 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -509,7 +509,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir) } if (WARN_ON(len)) { - dev_warn(&espi->pdev->dev, "len = %d expected 0!", len); + dev_warn(&espi->pdev->dev, "len = %zu expected 0!", len); return ERR_PTR(-EINVAL); }