From 8fec6f74a62c4e3d6897bc91f2eb08dfbadfe6da Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 10 Sep 2013 17:06:26 +0530 Subject: spi: atmel: Fix incorrect error path 'irq' was not released when clk_prepare_enable failed. Fix it. Signed-off-by: Sachin Kamat Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index fd7cc566095a..d4ac60b4a56e 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1583,7 +1583,7 @@ static int atmel_spi_probe(struct platform_device *pdev) /* Initialize the hardware */ ret = clk_prepare_enable(clk); if (ret) - goto out_unmap_regs; + goto out_free_irq; spi_writel(as, CR, SPI_BIT(SWRST)); spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ if (as->caps.has_wdrbt) { @@ -1614,6 +1614,7 @@ out_free_dma: spi_writel(as, CR, SPI_BIT(SWRST)); spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ clk_disable_unprepare(clk); +out_free_irq: free_irq(irq, master); out_unmap_regs: iounmap(as->regs); -- cgit v1.2.3 From ec60dd37e1d907d0524fa4c5806ecf24b16ea712 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 17:54:12 +0900 Subject: spi: atmel: convert from legacy pm ops to dev_pm_ops Instead of using legacy suspend/resume methods, using newer dev_pm_ops structure allows better control over power management. Also, duplicated 'return' is removed from atmel_spi_resume(). Signed-off-by: Jingoo Han Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index fd7cc566095a..3daf754f96f8 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1675,29 +1675,30 @@ static int atmel_spi_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM - -static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int atmel_spi_suspend(struct device *dev) { - struct spi_master *master = platform_get_drvdata(pdev); + struct spi_master *master = dev_get_drvdata(dev); struct atmel_spi *as = spi_master_get_devdata(master); clk_disable_unprepare(as->clk); return 0; } -static int atmel_spi_resume(struct platform_device *pdev) +static int atmel_spi_resume(struct device *dev) { - struct spi_master *master = platform_get_drvdata(pdev); + struct spi_master *master = dev_get_drvdata(dev); struct atmel_spi *as = spi_master_get_devdata(master); - return clk_prepare_enable(as->clk); + clk_prepare_enable(as->clk); return 0; } +static SIMPLE_DEV_PM_OPS(atmel_spi_pm_ops, atmel_spi_suspend, atmel_spi_resume); + +#define ATMEL_SPI_PM_OPS (&atmel_spi_pm_ops) #else -#define atmel_spi_suspend NULL -#define atmel_spi_resume NULL +#define ATMEL_SPI_PM_OPS NULL #endif #if defined(CONFIG_OF) @@ -1713,10 +1714,9 @@ static struct platform_driver atmel_spi_driver = { .driver = { .name = "atmel_spi", .owner = THIS_MODULE, + .pm = ATMEL_SPI_PM_OPS, .of_match_table = of_match_ptr(atmel_spi_dt_ids), }, - .suspend = atmel_spi_suspend, - .resume = atmel_spi_resume, .probe = atmel_spi_probe, .remove = atmel_spi_remove, }; -- cgit v1.2.3 From a536d7654338a06356afd0363e6adf51a02cb08b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 10 Sep 2013 17:06:27 +0530 Subject: spi: atmel: Silence checkpatch errors Fixes the following types of checkpatch errors and warning: ERROR: space required after that ',' (ctx:VxV) WARNING: sizeof *as should be sizeof(*as) Signed-off-by: Sachin Kamat Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 3daf754f96f8..6478a9713038 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -170,18 +170,18 @@ /* Bit manipulation macros */ #define SPI_BIT(name) \ (1 << SPI_##name##_OFFSET) -#define SPI_BF(name,value) \ +#define SPI_BF(name, value) \ (((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET) -#define SPI_BFEXT(name,value) \ +#define SPI_BFEXT(name, value) \ (((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1)) -#define SPI_BFINS(name,value,old) \ - ( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \ - | SPI_BF(name,value)) +#define SPI_BFINS(name, value, old) \ + (((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \ + | SPI_BF(name, value)) /* Register access macros */ -#define spi_readl(port,reg) \ +#define spi_readl(port, reg) \ __raw_readl((port)->regs + SPI_##reg) -#define spi_writel(port,reg,value) \ +#define spi_writel(port, reg, value) \ __raw_writel((value), (port)->regs + SPI_##reg) /* use PIO for small transfers, avoiding DMA setup/teardown overhead and @@ -1516,7 +1516,7 @@ static int atmel_spi_probe(struct platform_device *pdev) /* setup spi core then atmel-specific driver state */ ret = -ENOMEM; - master = spi_alloc_master(&pdev->dev, sizeof *as); + master = spi_alloc_master(&pdev->dev, sizeof(*as)); if (!master) goto out_free; -- cgit v1.2.3 From fbbfd68bc00d7bf431042b2e92cc4e540b827f67 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 17:55:32 +0900 Subject: spi: bfin5xx: convert from legacy pm ops to dev_pm_ops Instead of using legacy suspend/resume methods, using newer dev_pm_ops structure allows better control over power management. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-bfin5xx.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 45bdf73d6868..1e2894315bb0 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -1410,10 +1410,10 @@ static int bfin_spi_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int bfin_spi_suspend(struct device *dev) { - struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev); + struct bfin_spi_master_data *drv_data = dev_get_drvdata(dev); int status = 0; status = bfin_spi_stop_queue(drv_data); @@ -1432,9 +1432,9 @@ static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int bfin_spi_resume(struct platform_device *pdev) +static int bfin_spi_resume(struct device *dev) { - struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev); + struct bfin_spi_master_data *drv_data = dev_get_drvdata(dev); int status = 0; bfin_write(&drv_data->regs->ctl, drv_data->ctrl_reg); @@ -1443,25 +1443,27 @@ static int bfin_spi_resume(struct platform_device *pdev) /* Start the queue running */ status = bfin_spi_start_queue(drv_data); if (status != 0) { - dev_err(&pdev->dev, "problem starting queue (%d)\n", status); + dev_err(dev, "problem starting queue (%d)\n", status); return status; } return 0; } + +static SIMPLE_DEV_PM_OPS(bfin_spi_pm_ops, bfin_spi_suspend, bfin_spi_resume); + +#define BFIN_SPI_PM_OPS (&bfin_spi_pm_ops) #else -#define bfin_spi_suspend NULL -#define bfin_spi_resume NULL -#endif /* CONFIG_PM */ +#define BFIN_SPI_PM_OPS NULL +#endif MODULE_ALIAS("platform:bfin-spi"); static struct platform_driver bfin_spi_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .pm = BFIN_SPI_PM_OPS, }, - .suspend = bfin_spi_suspend, - .resume = bfin_spi_resume, .remove = bfin_spi_remove, }; -- cgit v1.2.3 From 673d6e1767ee06496f0f94e5087c817003983ffd Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 17:56:17 +0900 Subject: spi: bfin-sport: convert from legacy pm ops to dev_pm_ops Instead of using legacy suspend/resume methods, using newer dev_pm_ops structure allows better control over power management. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-bfin-sport.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index 91921b5f5817..6c81a5978eca 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -879,11 +879,10 @@ static int bfin_sport_spi_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int -bfin_sport_spi_suspend(struct platform_device *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int bfin_sport_spi_suspend(struct device *dev) { - struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev); + struct bfin_sport_spi_master_data *drv_data = dev_get_drvdata(dev); int status; status = bfin_sport_spi_stop_queue(drv_data); @@ -896,10 +895,9 @@ bfin_sport_spi_suspend(struct platform_device *pdev, pm_message_t state) return status; } -static int -bfin_sport_spi_resume(struct platform_device *pdev) +static int bfin_sport_spi_resume(struct device *dev) { - struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev); + struct bfin_sport_spi_master_data *drv_data = dev_get_drvdata(dev); int status; /* Enable the SPI interface */ @@ -912,19 +910,22 @@ bfin_sport_spi_resume(struct platform_device *pdev) return status; } + +static SIMPLE_DEV_PM_OPS(bfin_sport_spi_pm_ops, bfin_sport_spi_suspend, + bfin_sport_spi_resume); + +#define BFIN_SPORT_SPI_PM_OPS (&bfin_sport_spi_pm_ops) #else -# define bfin_sport_spi_suspend NULL -# define bfin_sport_spi_resume NULL +#define BFIN_SPORT_SPI_PM_OPS NULL #endif static struct platform_driver bfin_sport_spi_driver = { .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, + .name = DRV_NAME, + .owner = THIS_MODULE, + .pm = BFIN_SPORT_SPI_PM_OPS, }, .probe = bfin_sport_spi_probe, .remove = bfin_sport_spi_remove, - .suspend = bfin_sport_spi_suspend, - .resume = bfin_sport_spi_resume, }; module_platform_driver(bfin_sport_spi_driver); -- cgit v1.2.3 From 32ea3944436ca9e73677f9d844289780f255d45a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 11 Sep 2013 16:05:04 +0530 Subject: spi: spi-davinci: Fix variable type 'prescale' contains the return value of davinci_spi_get_prescale() which is a signed integer. Convert 'prescale' to integer to silence the following warning: drivers/spi/spi-davinci.c:318 davinci_spi_setup_transfer() warn: unsigned 'prescale' is never less than zero. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-davinci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 8fbfe2483ffd..8a04f1e05db2 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -279,7 +279,8 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, struct davinci_spi *dspi; struct davinci_spi_config *spicfg; u8 bits_per_word = 0; - u32 hz = 0, spifmt = 0, prescale = 0; + u32 hz = 0, spifmt = 0; + int prescale; dspi = spi_master_get_devdata(spi->master); spicfg = (struct davinci_spi_config *)spi->controller_data; -- cgit v1.2.3 From 1e0d191f62c779cdd6953db2541b6b92969ce1bb Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 2 Sep 2013 11:54:20 +0200 Subject: spi: designware: delete premature free_irq Free_irq is not needed if there has been no request_irq. Free_irq is removed from both the probe and remove functions. The correct request_irq and free_irq appear to be in the add_host and remove_host functions in spi-dw.c. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e; @@ *e = platform_get_irq(...); ... when != request_irq(e,...) *free_irq(e,...) // Signed-off-by: Julia Lawall Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mmio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 4aa8be865cc0..168c620947f4 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -74,7 +74,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) dwsmmio->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dwsmmio->clk)) { ret = PTR_ERR(dwsmmio->clk); - goto err_irq; + goto err_unmap; } clk_enable(dwsmmio->clk); @@ -94,8 +94,6 @@ err_clk: clk_disable(dwsmmio->clk); clk_put(dwsmmio->clk); dwsmmio->clk = NULL; -err_irq: - free_irq(dws->irq, dws); err_unmap: iounmap(dws->regs); err_release_reg: @@ -115,7 +113,6 @@ static int dw_spi_mmio_remove(struct platform_device *pdev) clk_put(dwsmmio->clk); dwsmmio->clk = NULL; - free_irq(dwsmmio->dws.irq, &dwsmmio->dws); dw_spi_remove_host(&dwsmmio->dws); iounmap(dwsmmio->dws.regs); kfree(dwsmmio); -- cgit v1.2.3 From 7cce62f3aa956a4ce170e53c98cc195b74aba4b4 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Sep 2013 18:54:31 +0900 Subject: spi: dw-pci: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-dw-pci.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 6055c8d9fdd7..6a708620816a 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -109,7 +109,6 @@ static void spi_pci_remove(struct pci_dev *pdev) { struct dw_spi_pci *dwpci = pci_get_drvdata(pdev); - pci_set_drvdata(pdev, NULL); dw_spi_remove_host(&dwpci->dws); iounmap(dwpci->dws.regs); pci_release_region(pdev, 0); -- cgit v1.2.3 From 91a92e12baf3c8cc2e353b3a70ddca9f9a59cf02 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Sep 2013 18:55:20 +0900 Subject: spi: spidev: remove unnecessary spi_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spidev.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index ca5bcfe874d0..c53556a1899a 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -629,7 +629,6 @@ static int spidev_remove(struct spi_device *spi) /* make sure ops on existing fds can abort cleanly */ spin_lock_irq(&spidev->spi_lock); spidev->spi = NULL; - spi_set_drvdata(spi, NULL); spin_unlock_irq(&spidev->spi_lock); /* prevent new opens */ -- cgit v1.2.3 From 2ef3599d8181afcbd347226faba75991f9e008fc Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 5 Sep 2013 15:51:21 +0900 Subject: spi: fsl-dspi: add missing __iomem annotation Added missing __iomem annotation in order to fix the following sparse warnings: drivers/spi/spi-fsl-dspi.c:140:16: warning: incorrect type in argument 1 (different address spaces) drivers/spi/spi-fsl-dspi.c:140:16: expected void const volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:140:16: got void * drivers/spi/spi-fsl-dspi.c:143:9: warning: incorrect type in argument 2 (different address spaces) drivers/spi/spi-fsl-dspi.c:143:9: expected void volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:143:9: got void * drivers/spi/spi-fsl-dspi.c:132:18: warning: incorrect type in argument 1 (different address spaces) drivers/spi/spi-fsl-dspi.c:132:18: expected void const volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:132:18: got void * drivers/spi/spi-fsl-dspi.c:241:17: warning: incorrect type in argument 2 (different address spaces) drivers/spi/spi-fsl-dspi.c:241:17: expected void volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:241:17: got void * drivers/spi/spi-fsl-dspi.c:132:18: warning: incorrect type in argument 1 (different address spaces) drivers/spi/spi-fsl-dspi.c:132:18: expected void const volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:132:18: got void * drivers/spi/spi-fsl-dspi.c:259:29: warning: incorrect type in argument 1 (different address spaces) drivers/spi/spi-fsl-dspi.c:259:29: expected void const volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:259:29: got void * drivers/spi/spi-fsl-dspi.c:266:29: warning: incorrect type in argument 1 (different address spaces) drivers/spi/spi-fsl-dspi.c:266:29: expected void const volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:266:29: got void * drivers/spi/spi-fsl-dspi.c:298:9: warning: incorrect type in argument 2 (different address spaces) drivers/spi/spi-fsl-dspi.c:298:9: expected void volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:298:9: got void * drivers/spi/spi-fsl-dspi.c:299:9: warning: incorrect type in argument 2 (different address spaces) drivers/spi/spi-fsl-dspi.c:299:9: expected void volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:299:9: got void * drivers/spi/spi-fsl-dspi.c:300:9: warning: incorrect type in argument 2 (different address spaces) drivers/spi/spi-fsl-dspi.c:300:9: expected void volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:300:9: got void * drivers/spi/spi-fsl-dspi.c:303:17: warning: incorrect type in argument 2 (different address spaces) drivers/spi/spi-fsl-dspi.c:303:17: expected void volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:303:17: got void * drivers/spi/spi-fsl-dspi.c:318:21: warning: incorrect type in argument 1 (different address spaces) drivers/spi/spi-fsl-dspi.c:318:21: expected void const volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:318:21: got void * drivers/spi/spi-fsl-dspi.c:327:9: warning: incorrect type in argument 2 (different address spaces) drivers/spi/spi-fsl-dspi.c:327:9: expected void volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:327:9: got void * drivers/spi/spi-fsl-dspi.c:386:9: warning: incorrect type in argument 2 (different address spaces) drivers/spi/spi-fsl-dspi.c:386:9: expected void volatile [noderef] *addr drivers/spi/spi-fsl-dspi.c:386:9: got void * drivers/spi/spi-fsl-dspi.c:485:20: warning: incorrect type in assignment (different address spaces) drivers/spi/spi-fsl-dspi.c:485:20: expected void *base drivers/spi/spi-fsl-dspi.c:485:20: got void [noderef] * Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6cd07d13ecab..735d4f51016c 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -108,7 +108,7 @@ struct fsl_dspi { struct spi_bitbang bitbang; struct platform_device *pdev; - void *base; + void __iomem *base; int irq; struct clk *clk; -- cgit v1.2.3 From b444d1dfe296433a93d6b814d924e0ab99ad7e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Sep 2013 10:46:33 +0200 Subject: spi: fsl-dspi: several minor improvements and fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - improve dependencies using COMPILE_TEST - fix a typo - drop platform_set_drvdata(pdev, NULL) in error path of probe - make MODULE_LICENSE match the header Signed-off-by: Uwe Kleine-König Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 1 + drivers/spi/spi-fsl-dspi.c | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b9c53cc40e1f..c463d364b3dd 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -264,6 +264,7 @@ config SPI_FSL_SPI config SPI_FSL_DSPI tristate "Freescale DSPI controller" select SPI_BITBANG + depends on SOC_VF610 || COMPILE_TEST help This enables support for the Freescale DSPI controller in master mode. VF610 platform uses the controller. diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 735d4f51016c..dc3d4eb0531c 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -165,7 +165,7 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, } } - pr_warn("Can not find valid buad rate,speed_hz is %d,clkrate is %ld\ + pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\ ,we use the max prescaler value.\n", speed_hz, clkrate); *pbr = ARRAY_SIZE(pbr_tbl) - 1; *br = ARRAY_SIZE(brs) - 1; @@ -526,7 +526,6 @@ out_clk_put: clk_disable_unprepare(dspi->clk); out_master_put: spi_master_put(master); - platform_set_drvdata(pdev, NULL); return ret; } @@ -553,5 +552,5 @@ static struct platform_driver fsl_dspi_driver = { module_platform_driver(fsl_dspi_driver); MODULE_DESCRIPTION("Freescale DSPI Controller Driver"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRIVER_NAME); -- cgit v1.2.3 From 6e99897ba0cdeb83e91738683000aeed6a079cae Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 2 Sep 2013 11:56:21 +0530 Subject: spi: pl022: Remove redundant break 'break' immediately after return has no effect. Signed-off-by: Sachin Kamat Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 9c511a954d21..1ff2d8e78f51 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1619,7 +1619,6 @@ static int verify_controller_parameters(struct pl022 *pl022, dev_err(&pl022->adev->dev, "RX FIFO Trigger Level is configured incorrectly\n"); return -EINVAL; - break; } switch (chip_info->tx_lev_trig) { case SSP_TX_1_OR_MORE_EMPTY_LOC: @@ -1645,7 +1644,6 @@ static int verify_controller_parameters(struct pl022 *pl022, dev_err(&pl022->adev->dev, "TX FIFO Trigger Level is configured incorrectly\n"); return -EINVAL; - break; } if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) { if ((chip_info->ctrl_len < SSP_BITS_4) -- cgit v1.2.3 From 4ebfee9118599dece86429270be1bcbb3099f237 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Sep 2013 18:53:36 +0900 Subject: spi: pl022: remove unnecessary amba_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 1ff2d8e78f51..c13d523f1f48 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2286,7 +2286,6 @@ pl022_remove(struct amba_device *adev) amba_release_regions(adev); tasklet_disable(&pl022->pump_transfers); spi_unregister_master(pl022->master); - amba_set_drvdata(adev, NULL); return 0; } -- cgit v1.2.3 From 5ce0ba88650f2606244a761d92e2b725f4ab3583 Mon Sep 17 00:00:00 2001 From: Hiep Cao Minh Date: Tue, 3 Sep 2013 13:10:26 +0900 Subject: spi: rcar: add Renesas QSPI support on RSPI The R8A7790 has QSPI module which is very similar to RSPI. This patch adds into RSPI module together to supports QSPI module. Signed-off-by: Hiep Cao Minh Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- drivers/spi/spi-rspi.c | 183 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 143 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b9c53cc40e1f..738facf90597 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -369,7 +369,7 @@ config SPI_PXA2XX_PCI config SPI_RSPI tristate "Renesas RSPI controller" - depends on SUPERH && SH_DMAE_BASE + depends on (SUPERH || ARCH_SHMOBILE) && SH_DMAE_BASE help SPI driver for Renesas RSPI blocks. diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 8719206a03a0..4c8dbac11b42 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -59,6 +59,14 @@ #define RSPI_SPCMD6 0x1c #define RSPI_SPCMD7 0x1e +/*qspi only */ +#define QSPI_SPBFCR 0x18 +#define QSPI_SPBDCR 0x1a +#define QSPI_SPBMUL0 0x1c +#define QSPI_SPBMUL1 0x20 +#define QSPI_SPBMUL2 0x24 +#define QSPI_SPBMUL3 0x28 + /* SPCR */ #define SPCR_SPRIE 0x80 #define SPCR_SPE 0x40 @@ -126,6 +134,8 @@ #define SPCMD_LSBF 0x1000 #define SPCMD_SPB_MASK 0x0f00 #define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK) +#define SPCMD_SPB_8BIT 0x0000 /* qspi only */ +#define SPCMD_SPB_16BIT 0x0100 #define SPCMD_SPB_20BIT 0x0000 #define SPCMD_SPB_24BIT 0x0100 #define SPCMD_SPB_32BIT 0x0200 @@ -135,6 +145,10 @@ #define SPCMD_CPOL 0x0002 #define SPCMD_CPHA 0x0001 +/* SPBFCR */ +#define SPBFCR_TXRST 0x80 /* qspi only */ +#define SPBFCR_RXRST 0x40 /* qspi only */ + struct rspi_data { void __iomem *addr; u32 max_speed_hz; @@ -145,6 +159,7 @@ struct rspi_data { spinlock_t lock; struct clk *clk; unsigned char spsr; + const struct spi_ops *ops; /* for dmaengine */ struct dma_chan *chan_tx; @@ -165,6 +180,11 @@ static void rspi_write16(struct rspi_data *rspi, u16 data, u16 offset) iowrite16(data, rspi->addr + offset); } +static void rspi_write32(struct rspi_data *rspi, u32 data, u16 offset) +{ + iowrite32(data, rspi->addr + offset); +} + static u8 rspi_read8(struct rspi_data *rspi, u16 offset) { return ioread8(rspi->addr + offset); @@ -175,17 +195,98 @@ static u16 rspi_read16(struct rspi_data *rspi, u16 offset) return ioread16(rspi->addr + offset); } -static unsigned char rspi_calc_spbr(struct rspi_data *rspi) +/* optional functions */ +struct spi_ops { + int (*set_config_register)(struct rspi_data *rspi, int access_size); +}; + +/* + * functions for RSPI + */ +static int rspi_set_config_register(struct rspi_data *rspi, int access_size) { - int tmp; - unsigned char spbr; + int spbr; + + /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ + rspi_write8(rspi, 0x00, RSPI_SPPCR); - tmp = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; - spbr = clamp(tmp, 0, 255); + /* Sets transfer bit rate */ + spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; + rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); + + /* Sets number of frames to be used: 1 frame */ + rspi_write8(rspi, 0x00, RSPI_SPDCR); - return spbr; + /* Sets RSPCK, SSL, next-access delay value */ + rspi_write8(rspi, 0x00, RSPI_SPCKD); + rspi_write8(rspi, 0x00, RSPI_SSLND); + rspi_write8(rspi, 0x00, RSPI_SPND); + + /* Sets parity, interrupt mask */ + rspi_write8(rspi, 0x00, RSPI_SPCR2); + + /* Sets SPCMD */ + rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP, + RSPI_SPCMD0); + + /* Sets RSPI mode */ + rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); + + return 0; } +/* + * functions for QSPI + */ +static int qspi_set_config_register(struct rspi_data *rspi, int access_size) +{ + u16 spcmd; + int spbr; + + /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ + rspi_write8(rspi, 0x00, RSPI_SPPCR); + + /* Sets transfer bit rate */ + spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz); + rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); + + /* Sets number of frames to be used: 1 frame */ + rspi_write8(rspi, 0x00, RSPI_SPDCR); + + /* Sets RSPCK, SSL, next-access delay value */ + rspi_write8(rspi, 0x00, RSPI_SPCKD); + rspi_write8(rspi, 0x00, RSPI_SSLND); + rspi_write8(rspi, 0x00, RSPI_SPND); + + /* Data Length Setting */ + if (access_size == 8) + spcmd = SPCMD_SPB_8BIT; + else if (access_size == 16) + spcmd = SPCMD_SPB_16BIT; + else if (access_size == 32) + spcmd = SPCMD_SPB_32BIT; + + spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN; + + /* Resets transfer data length */ + rspi_write32(rspi, 0, QSPI_SPBMUL0); + + /* Resets transmit and receive buffer */ + rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); + /* Sets buffer to allow normal operation */ + rspi_write8(rspi, 0x00, QSPI_SPBFCR); + + /* Sets SPCMD */ + rspi_write16(rspi, spcmd, RSPI_SPCMD0); + + /* Enables SPI function in a master mode */ + rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR); + + return 0; +} + +#define set_config_register(spi, n) spi->ops->set_config_register(spi, n) + static void rspi_enable_irq(struct rspi_data *rspi, u8 enable) { rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); @@ -220,35 +321,6 @@ static void rspi_negate_ssl(struct rspi_data *rspi) rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); } -static int rspi_set_config_register(struct rspi_data *rspi, int access_size) -{ - /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ - rspi_write8(rspi, 0x00, RSPI_SPPCR); - - /* Sets transfer bit rate */ - rspi_write8(rspi, rspi_calc_spbr(rspi), RSPI_SPBR); - - /* Sets number of frames to be used: 1 frame */ - rspi_write8(rspi, 0x00, RSPI_SPDCR); - - /* Sets RSPCK, SSL, next-access delay value */ - rspi_write8(rspi, 0x00, RSPI_SPCKD); - rspi_write8(rspi, 0x00, RSPI_SSLND); - rspi_write8(rspi, 0x00, RSPI_SPND); - - /* Sets parity, interrupt mask */ - rspi_write8(rspi, 0x00, RSPI_SPCR2); - - /* Sets SPCMD */ - rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP, - RSPI_SPCMD0); - - /* Sets RSPI mode */ - rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); - - return 0; -} - static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, struct spi_transfer *t) { @@ -616,7 +688,7 @@ static int rspi_setup(struct spi_device *spi) spi->bits_per_word = 8; rspi->max_speed_hz = spi->max_speed_hz; - rspi_set_config_register(rspi, 8); + set_config_register(rspi, 8); return 0; } @@ -745,7 +817,16 @@ static int rspi_probe(struct platform_device *pdev) struct rspi_data *rspi; int ret, irq; char clk_name[16]; - + struct rspi_plat_data *rspi_pd = pdev->dev.platform_data; + const struct spi_ops *ops; + const struct platform_device_id *id_entry = pdev->id_entry; + + ops = (struct spi_ops *)id_entry->driver_data; + /* ops parameter check */ + if (!ops->set_config_register) { + dev_err(&pdev->dev, "there is no set_config_register\n"); + return -ENODEV; + } /* get base addr */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (unlikely(res == NULL)) { @@ -767,7 +848,7 @@ static int rspi_probe(struct platform_device *pdev) rspi = spi_master_get_devdata(master); platform_set_drvdata(pdev, rspi); - + rspi->ops = ops; rspi->master = master; rspi->addr = ioremap(res->start, resource_size(res)); if (rspi->addr == NULL) { @@ -776,7 +857,7 @@ static int rspi_probe(struct platform_device *pdev) goto error1; } - snprintf(clk_name, sizeof(clk_name), "rspi%d", pdev->id); + snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id); rspi->clk = clk_get(&pdev->dev, clk_name); if (IS_ERR(rspi->clk)) { dev_err(&pdev->dev, "cannot get clock\n"); @@ -790,7 +871,10 @@ static int rspi_probe(struct platform_device *pdev) INIT_WORK(&rspi->ws, rspi_work); init_waitqueue_head(&rspi->wait); - master->num_chipselect = 2; + master->num_chipselect = rspi_pd->num_chipselect; + if (!master->num_chipselect) + master->num_chipselect = 2; /* default */ + master->bus_num = pdev->id; master->setup = rspi_setup; master->transfer = rspi_transfer; @@ -832,11 +916,28 @@ error1: return ret; } +static struct spi_ops rspi_ops = { + .set_config_register = rspi_set_config_register, +}; + +static struct spi_ops qspi_ops = { + .set_config_register = qspi_set_config_register, +}; + +static struct platform_device_id spi_driver_ids[] = { + { "rspi", (kernel_ulong_t)&rspi_ops }, + { "qspi", (kernel_ulong_t)&qspi_ops }, + {}, +}; + +MODULE_DEVICE_TABLE(platform, spi_driver_ids); + static struct platform_driver rspi_driver = { .probe = rspi_probe, .remove = rspi_remove, + .id_table = spi_driver_ids, .driver = { - .name = "rspi", + .name = "renesas_spi", .owner = THIS_MODULE, }, }; -- cgit v1.2.3 From cfeb33127bfd5c248c8633715d75c04186d8fca9 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 10 Sep 2013 11:20:13 +0530 Subject: spi: spi-s3c24xx: Staticize s3c24xx_spi_tryfiq 's3c24xx_spi_tryfiq' is used only in this file. Make it static. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-s3c24xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index ce318d95a6ee..d39589dba5c1 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -280,7 +280,7 @@ static inline u32 ack_bit(unsigned int irq) * so the caller does not need to do anything more than start the transfer * as normal, since the IRQ will have been re-routed to the FIQ handler. */ -void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw) +static void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw) { struct pt_regs regs; enum spi_fiq_mode mode; -- cgit v1.2.3 From 50c959fc3366693174cdf3f1c82d0c01bbee926f Mon Sep 17 00:00:00 2001 From: Lukasz Czerwinski Date: Mon, 9 Sep 2013 16:09:25 +0200 Subject: spi: spi-s3c64xx: Use module_platform_driver() subsys_init_call() initializes driver too early. It's preventing to move DMA channel allocation at the begining (driver probe). This patch reduces and simplifies initalization code by using module_platform_driver() macro. It's also efficiently delaying driver startup. Signed-off-by: Lukasz Czerwinski Signed-off-by: Kyungmin Park Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 512b8893893b..20dd71237d3b 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1633,22 +1633,13 @@ static struct platform_driver s3c64xx_spi_driver = { .pm = &s3c64xx_spi_pm, .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), }, + .probe = s3c64xx_spi_probe, .remove = s3c64xx_spi_remove, .id_table = s3c64xx_spi_driver_ids, }; MODULE_ALIAS("platform:s3c64xx-spi"); -static int __init s3c64xx_spi_init(void) -{ - return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); -} -subsys_initcall(s3c64xx_spi_init); - -static void __exit s3c64xx_spi_exit(void) -{ - platform_driver_unregister(&s3c64xx_spi_driver); -} -module_exit(s3c64xx_spi_exit); +module_platform_driver(s3c64xx_spi_driver); MODULE_AUTHOR("Jaswinder Singh "); MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); -- cgit v1.2.3 From e91d2352bb6ebd061b362b3c632ec517ac0c23b1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 30 Aug 2013 11:00:23 +0800 Subject: spi: tegra: Use DIV_ROUND_UP instead of open coded This also makes the intention more clear. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 2 +- drivers/spi/spi-tegra20-sflash.c | 2 +- drivers/spi/spi-tegra20-slink.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 145dd435483b..946ff7377352 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -267,7 +267,7 @@ static unsigned tegra_spi_calculate_curr_xfer_param( unsigned max_len; unsigned total_fifo_words; - tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1; + tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8); if (bits_per_word == 8 || bits_per_word == 16) { tspi->is_packed = 1; diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 1d814dc6e000..64c9cf511175 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -173,7 +173,7 @@ static unsigned tegra_sflash_calculate_curr_xfer_param( unsigned remain_len = t->len - tsd->cur_pos; unsigned max_word; - tsd->bytes_per_word = (t->bits_per_word - 1) / 8 + 1; + tsd->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8); max_word = remain_len / tsd->bytes_per_word; if (max_word > SPI_FIFO_DEPTH) max_word = SPI_FIFO_DEPTH; diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index c70353672a23..231b84523d37 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -283,7 +283,7 @@ static unsigned tegra_slink_calculate_curr_xfer_param( unsigned total_fifo_words; bits_per_word = t->bits_per_word; - tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1; + tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8); if (bits_per_word == 8 || bits_per_word == 16) { tspi->is_packed = 1; -- cgit v1.2.3 From 666d5b4c742ba666eb68b467d777b7862f362ae5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 31 Aug 2013 18:50:52 +0100 Subject: spi: core: Add devm_spi_register_master() Help simplify the cleanup code for SPI master drivers by providing a managed master registration function, ensuring that the master is automatically unregistered whenever the device is unbound. Signed-off-by: Mark Brown --- drivers/spi/spi.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9e039c60c068..a586ceb111fc 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1245,6 +1245,41 @@ done: } EXPORT_SYMBOL_GPL(spi_register_master); +static void devm_spi_unregister(struct device *dev, void *res) +{ + spi_unregister_master(*(struct spi_master **)res); +} + +/** + * dev_spi_register_master - register managed SPI master controller + * @dev: device managing SPI master + * @master: initialized master, originally from spi_alloc_master() + * Context: can sleep + * + * Register a SPI device as with spi_register_master() which will + * automatically be unregister + */ +int devm_spi_register_master(struct device *dev, struct spi_master *master) +{ + struct spi_master **ptr; + int ret; + + ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = spi_register_master(master); + if (ret != 0) { + *ptr = master; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_spi_register_master); + static int __unregister(struct device *dev, void *null) { spi_unregister_device(to_spi_device(dev)); -- cgit v1.2.3 From 94c69f765f1b4a658d96905ec59928e3e3e07e6a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Sep 2013 15:43:41 +0800 Subject: spi: bitbang: Let spi_bitbang_start() take a reference to master Many drivers that use bitbang library have a leak on probe error paths. This is because once a spi_master_get() call succeeds, we need an additional spi_master_put() call to free the memory. Fix this issue by moving the code taking a reference to master to spi_bitbang_start(), so spi_bitbang_start() will take a reference to master on success. With this change, the caller is responsible for calling spi_bitbang_stop() to decrement the reference and spi_master_put() as counterpart of spi_alloc_master() to prevent a memory leak. So now we have below patten for drivers using bitbang library: probe: spi_alloc_master -> Init reference count to 1 spi_bitbang_start -> Increment reference count remove: spi_bitbang_stop -> Decrement reference count spi_master_put -> Decrement reference count (reference count reaches 0) Fixup all users accordingly. Signed-off-by: Axel Lin Suggested-by: Uwe Kleine-Koenig Acked-by: Uwe Kleine-Koenig Signed-off-by: Mark Brown --- drivers/spi/spi-altera.c | 2 +- drivers/spi/spi-ath79.c | 2 +- drivers/spi/spi-au1550.c | 2 +- drivers/spi/spi-bitbang.c | 12 +++++++++++- drivers/spi/spi-butterfly.c | 2 +- drivers/spi/spi-davinci.c | 10 ++++------ drivers/spi/spi-efm32.c | 2 +- drivers/spi/spi-fsl-dspi.c | 2 +- drivers/spi/spi-gpio.c | 5 ++--- drivers/spi/spi-imx.c | 2 +- drivers/spi/spi-lm70llp.c | 2 +- drivers/spi/spi-nuc900.c | 3 +-- drivers/spi/spi-oc-tiny.c | 2 +- drivers/spi/spi-ppc4xx.c | 3 ++- drivers/spi/spi-s3c24xx.c | 2 +- drivers/spi/spi-sh-sci.c | 2 +- drivers/spi/spi-sirf.c | 2 +- drivers/spi/spi-xilinx.c | 2 +- 18 files changed, 33 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index 9a64c3fee218..595b62cb545d 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -219,7 +219,7 @@ static int altera_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hw); /* setup the state for the bitbang driver */ - hw->bitbang.master = spi_master_get(master); + hw->bitbang.master = master; if (!hw->bitbang.master) return err; hw->bitbang.chipselect = altera_spi_chipsel; diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 37bad952ab38..821bf7ac218d 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -231,7 +231,7 @@ static int ath79_spi_probe(struct platform_device *pdev) master->num_chipselect = pdata->num_chipselect; } - sp->bitbang.master = spi_master_get(master); + sp->bitbang.master = master; sp->bitbang.chipselect = ath79_spi_chipselect; sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; sp->bitbang.setup_transfer = spi_bitbang_setup_transfer; diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 1d00d9b397dd..e06400a3a719 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -775,7 +775,7 @@ static int au1550_spi_probe(struct platform_device *pdev) hw = spi_master_get_devdata(master); - hw->master = spi_master_get(master); + hw->master = master; hw->pdata = dev_get_platdata(&pdev->dev); hw->dev = &pdev->dev; diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 8c11355dec23..0056623dfc6b 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -414,10 +414,16 @@ static int spi_bitbang_unprepare_hardware(struct spi_master *spi) * This routine registers the spi_master, which will process requests in a * dedicated task, keeping IRQs unblocked most of the time. To stop * processing those requests, call spi_bitbang_stop(). + * + * On success, this routine will take a reference to master. The caller is + * responsible for calling spi_bitbang_stop() to decrement the reference and + * spi_master_put() as counterpart of spi_alloc_master() to prevent a memory + * leak. */ int spi_bitbang_start(struct spi_bitbang *bitbang) { struct spi_master *master = bitbang->master; + int ret; if (!master || !bitbang->chipselect) return -EINVAL; @@ -449,7 +455,11 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) /* driver may get busy before register() returns, especially * if someone registered boardinfo for devices */ - return spi_register_master(master); + ret = spi_register_master(spi_master_get(master)); + if (ret) + spi_master_put(master); + + return 0; } EXPORT_SYMBOL_GPL(spi_bitbang_start); diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index 5ed08e537433..b1ecea2d76b3 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -225,7 +225,7 @@ static void butterfly_attach(struct parport *p) master->bus_num = 42; master->num_chipselect = 2; - pp->bitbang.master = spi_master_get(master); + pp->bitbang.master = master; pp->bitbang.chipselect = butterfly_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 8fbfe2483ffd..af2bb73d0168 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -916,7 +916,7 @@ static int davinci_spi_probe(struct platform_device *pdev) if (ret) goto unmap_io; - dspi->bitbang.master = spi_master_get(master); + dspi->bitbang.master = master; if (dspi->bitbang.master == NULL) { ret = -ENODEV; goto irq_free; @@ -925,7 +925,7 @@ static int davinci_spi_probe(struct platform_device *pdev) dspi->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dspi->clk)) { ret = -ENODEV; - goto put_master; + goto irq_free; } clk_prepare_enable(dspi->clk); @@ -1015,8 +1015,6 @@ free_dma: free_clk: clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); -put_master: - spi_master_put(master); irq_free: free_irq(dspi->irq, dspi); unmap_io: @@ -1024,7 +1022,7 @@ unmap_io: release_region: release_mem_region(dspi->pbase, resource_size(r)); free_master: - kfree(master); + spi_master_put(master); err: return ret; } @@ -1051,11 +1049,11 @@ static int davinci_spi_remove(struct platform_device *pdev) clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); - spi_master_put(master); free_irq(dspi->irq, dspi); iounmap(dspi->base); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(dspi->pbase, resource_size(r)); + spi_master_put(master); return 0; } diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index 7d84418a01d8..d428a40778c1 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -347,7 +347,7 @@ static int efm32_spi_probe(struct platform_device *pdev) ddata = spi_master_get_devdata(master); - ddata->bitbang.master = spi_master_get(master); + ddata->bitbang.master = master; ddata->bitbang.chipselect = efm32_spi_chipselect; ddata->bitbang.setup_transfer = efm32_spi_setup_transfer; ddata->bitbang.txrx_bufs = efm32_spi_txrx_bufs; diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6cd07d13ecab..d338b6722255 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -450,7 +450,7 @@ static int dspi_probe(struct platform_device *pdev) dspi = spi_master_get_devdata(master); dspi->pdev = pdev; - dspi->bitbang.master = spi_master_get(master); + dspi->bitbang.master = master; dspi->bitbang.chipselect = dspi_chipselect; dspi->bitbang.setup_transfer = dspi_setup_transfer; dspi->bitbang.txrx_bufs = dspi_txrx_transfer; diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 68b69fec13a9..14c01b44ca7a 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -467,7 +467,7 @@ static int spi_gpio_probe(struct platform_device *pdev) } #endif - spi_gpio->bitbang.master = spi_master_get(master); + spi_gpio->bitbang.master = master; spi_gpio->bitbang.chipselect = spi_gpio_chipselect; if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) { @@ -486,7 +486,6 @@ static int spi_gpio_probe(struct platform_device *pdev) status = spi_bitbang_start(&spi_gpio->bitbang); if (status < 0) { - spi_master_put(spi_gpio->bitbang.master); gpio_free: if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) gpio_free(SPI_MISO_GPIO); @@ -510,13 +509,13 @@ static int spi_gpio_remove(struct platform_device *pdev) /* stop() unregisters child devices too */ status = spi_bitbang_stop(&spi_gpio->bitbang); - spi_master_put(spi_gpio->bitbang.master); if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) gpio_free(SPI_MISO_GPIO); if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) gpio_free(SPI_MOSI_GPIO); gpio_free(SPI_SCK_GPIO); + spi_master_put(spi_gpio->bitbang.master); return status; } diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 15323d8bd9cf..02d9f468b2b6 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -786,7 +786,7 @@ static int spi_imx_probe(struct platform_device *pdev) master->num_chipselect = num_cs; spi_imx = spi_master_get_devdata(master); - spi_imx->bitbang.master = spi_master_get(master); + spi_imx->bitbang.master = master; for (i = 0; i < master->num_chipselect; i++) { int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index 0759b5db9883..41c5765be746 100644 --- a/drivers/spi/spi-lm70llp.c +++ b/drivers/spi/spi-lm70llp.c @@ -222,7 +222,7 @@ static void spi_lm70llp_attach(struct parport *p) /* * SPI and bitbang hookup. */ - pp->bitbang.master = spi_master_get(master); + pp->bitbang.master = master; pp->bitbang.chipselect = lm70_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx; pp->bitbang.flags = SPI_3WIRE; diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index 47a68b43bcd5..e0c32bc69ee2 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -349,7 +349,7 @@ static int nuc900_spi_probe(struct platform_device *pdev) } hw = spi_master_get_devdata(master); - hw->master = spi_master_get(master); + hw->master = master; hw->pdata = dev_get_platdata(&pdev->dev); hw->dev = &pdev->dev; @@ -435,7 +435,6 @@ err_iomap: kfree(hw->ioarea); err_pdata: spi_master_put(hw->master); - err_nomem: return err; } diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index 333cb1badcd7..91c668596202 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -306,7 +306,7 @@ static int tiny_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hw); /* setup the state for the bitbang driver */ - hw->bitbang.master = spi_master_get(master); + hw->bitbang.master = master; if (!hw->bitbang.master) return err; hw->bitbang.setup_transfer = tiny_spi_setup_transfer; diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 0ee53c25ba58..c57740bb70d3 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -396,7 +396,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) master->dev.of_node = np; platform_set_drvdata(op, master); hw = spi_master_get_devdata(master); - hw->master = spi_master_get(master); + hw->master = master; hw->dev = dev; init_completion(&hw->done); @@ -558,6 +558,7 @@ static int spi_ppc4xx_of_remove(struct platform_device *op) free_irq(hw->irqnum, hw); iounmap(hw->regs); free_gpios(hw); + spi_master_put(master); return 0; } diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index ce318d95a6ee..c9cfdfaf7523 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -524,7 +524,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) hw = spi_master_get_devdata(master); memset(hw, 0, sizeof(struct s3c24xx_spi)); - hw->master = spi_master_get(master); + hw->master = master; hw->pdata = pdata = dev_get_platdata(&pdev->dev); hw->dev = &pdev->dev; diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c index 8eefeb6007df..38eb24df796c 100644 --- a/drivers/spi/spi-sh-sci.c +++ b/drivers/spi/spi-sh-sci.c @@ -133,7 +133,7 @@ static int sh_sci_spi_probe(struct platform_device *dev) sp->info = dev_get_platdata(&dev->dev); /* setup spi bitbang adaptor */ - sp->bitbang.master = spi_master_get(master); + sp->bitbang.master = master; sp->bitbang.master->bus_num = sp->info->bus_num; sp->bitbang.master->num_chipselect = sp->info->num_chipselect; sp->bitbang.chipselect = sh_sci_spi_chipselect; diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index a1f21b747733..592b4aff651f 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -632,7 +632,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) if (ret) goto free_master; - sspi->bitbang.master = spi_master_get(master); + sspi->bitbang.master = master; sspi->bitbang.chipselect = spi_sirfsoc_chipselect; sspi->bitbang.setup_transfer = spi_sirfsoc_setup_transfer; sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer; diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 0bf1b2c457a1..ec3a83f52ea2 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -372,7 +372,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) master->mode_bits = SPI_CPOL | SPI_CPHA; xspi = spi_master_get_devdata(master); - xspi->bitbang.master = spi_master_get(master); + xspi->bitbang.master = master; xspi->bitbang.chipselect = xilinx_spi_chipselect; xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; -- cgit v1.2.3 From 9191546f69ddefe66e46bbe9ba8d1872bc226553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Sep 2013 09:51:30 +0200 Subject: spi: efm32: add spi_bitbang_stop to device remove callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This call is needed to cleanup the resources requested by spi_bitbang_start in the probe callback. Noticed-by: Axel Lin Signed-off-by: Uwe Kleine-König Signed-off-by: Mark Brown --- drivers/spi/spi-efm32.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index d428a40778c1..18659fc6bef2 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -478,6 +478,8 @@ static int efm32_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct efm32_spi_ddata *ddata = spi_master_get_devdata(master); + spi_bitbang_stop(&ddata->bitbang); + efm32_spi_write32(ddata, 0, REG_IEN); free_irq(ddata->txirq, ddata); -- cgit v1.2.3 From 91800f0e90050a4db4c77e940796f501e02af8be Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 31 Aug 2013 18:55:53 +0100 Subject: spi/s3c64xx: Use managed registration Also improve the error reporting on failure and remove a duplicate put. This provides a small code saving. Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 20dd71237d3b..8bed27a4108c 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1428,9 +1428,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, sdd->regs + S3C64XX_SPI_INT_EN); - if (spi_register_master(master)) { - dev_err(&pdev->dev, "cannot register SPI master\n"); - ret = -EBUSY; + ret = devm_spi_register_master(&pdev->dev, master); + if (ret != 0) { + dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret); goto err3; } @@ -1461,16 +1461,12 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); - spi_unregister_master(master); - writel(0, sdd->regs + S3C64XX_SPI_INT_EN); clk_disable_unprepare(sdd->src_clk); clk_disable_unprepare(sdd->clk); - spi_master_put(master); - return 0; } -- cgit v1.2.3 From a3b924df8fa9083d2291efc2d1dca93609953718 Mon Sep 17 00:00:00 2001 From: Mateusz Krawczuk Date: Mon, 23 Sep 2013 11:45:45 +0200 Subject: spi: s3c64xx: Add missing compatibles Add compatibles for s3c6410, s5pc100 and s5pc110/s5pv210 boards. Signed-off-by: Mateusz Krawczuk Signed-off-by: Kyungmin Park Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 8bed27a4108c..84cc6ac801fe 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1612,6 +1612,18 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = { }; static const struct of_device_id s3c64xx_spi_dt_match[] = { + { .compatible = "samsung,s3c2443-spi", + .data = (void *)&s3c2443_spi_port_config, + }, + { .compatible = "samsung,s3c6410-spi", + .data = (void *)&s3c6410_spi_port_config, + }, + { .compatible = "samsung,s5pc100-spi", + .data = (void *)&s5pc100_spi_port_config, + }, + { .compatible = "samsung,s5pv210-spi", + .data = (void *)&s5pv210_spi_port_config, + }, { .compatible = "samsung,exynos4210-spi", .data = (void *)&exynos4_spi_port_config, }, -- cgit v1.2.3 From 57841439b62e3ddb5ee50e765aa50330dde612d0 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 20 Sep 2013 18:39:18 +0800 Subject: spi: efm32: Don't call kfree() after spi_master_put() Calling kfree() to clean up the memory obtained from spi_alloc_master() is wrong as this is done in spi_master_release() when spi_master->dev's refcount reaches zero. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/spi/spi-efm32.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index 7d84418a01d8..5b3117f69507 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -467,7 +467,6 @@ err_disable_clk: clk_disable_unprepare(ddata->clk); err: spi_master_put(master); - kfree(master); } return ret; @@ -484,7 +483,6 @@ static int efm32_spi_remove(struct platform_device *pdev) free_irq(ddata->rxirq, ddata); clk_disable_unprepare(ddata->clk); spi_master_put(master); - kfree(master); return 0; } -- cgit v1.2.3 From 9553821ead2b6e813a8b3a5360e20e28bfabc177 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 24 Sep 2013 10:54:51 +0300 Subject: spi: spi-topcliff-pch: fix a pci_iomap() check If pci_iomap() returns NULL, adding "PCH_ADDRESS_SIZE * plat_dev->id" can make it non-NULL which breaks the error handling. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- drivers/spi/spi-topcliff-pch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index eaeeed51bbbf..777c40452bd1 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1410,13 +1410,13 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev) /* baseaddress + address offset) */ data->io_base_addr = pci_resource_start(board_dat->pdev, 1) + PCH_ADDRESS_SIZE * plat_dev->id; - data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0) + - PCH_ADDRESS_SIZE * plat_dev->id; + data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0); if (!data->io_remap_addr) { dev_err(&plat_dev->dev, "%s pci_iomap failed\n", __func__); ret = -ENOMEM; goto err_pci_iomap; } + data->io_remap_addr += PCH_ADDRESS_SIZE * plat_dev->id; dev_dbg(&plat_dev->dev, "[ch%d] remap_addr=%p\n", plat_dev->id, data->io_remap_addr); -- cgit v1.2.3 From 247263dba208fab08c7f49900a9c79adaae1176e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:23:00 +0900 Subject: spi: bcm2835: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove a duplicate put. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 52c81481c5c7..4c332143a310 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -358,7 +358,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) bcm2835_wr(bs, BCM2835_SPI_CS, BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); - err = spi_register_master(master); + err = devm_spi_register_master(&pdev->dev, master); if (err) { dev_err(&pdev->dev, "could not register SPI master: %d\n", err); goto out_free_irq; @@ -381,14 +381,12 @@ static int bcm2835_spi_remove(struct platform_device *pdev) struct bcm2835_spi *bs = spi_master_get_devdata(master); free_irq(bs->irq, master); - spi_unregister_master(master); /* Clear FIFOs, and disable the HW block */ bcm2835_wr(bs, BCM2835_SPI_CS, BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); clk_disable_unprepare(bs->clk); - spi_master_put(master); return 0; } -- cgit v1.2.3 From bca76931b934ad323c56d9aab7a74139306d18bf Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:24:57 +0900 Subject: spi: bcm63xx: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove a duplicate put. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 536b0e363826..80d56b214eb5 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -412,7 +412,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); /* register and we are done */ - ret = spi_register_master(master); + ret = devm_spi_register_master(dev, master); if (ret) { dev_err(dev, "spi register failed\n"); goto out_clk_disable; @@ -438,8 +438,6 @@ static int bcm63xx_spi_remove(struct platform_device *pdev) struct spi_master *master = spi_master_get(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); @@ -447,8 +445,6 @@ static int bcm63xx_spi_remove(struct platform_device *pdev) clk_disable_unprepare(bs->clk); clk_put(bs->clk); - spi_master_put(master); - return 0; } -- cgit v1.2.3 From 6221df6d88b847da0803b2ced7826f005e62c837 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:26:30 +0900 Subject: spi: bfin-v3: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Scott Jiang Signed-off-by: Mark Brown --- drivers/spi/spi-bfin-v3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c index f4bf81347d68..8f8598834b30 100644 --- a/drivers/spi/spi-bfin-v3.c +++ b/drivers/spi/spi-bfin-v3.c @@ -867,7 +867,7 @@ static int bfin_spi_probe(struct platform_device *pdev) tasklet_init(&drv_data->pump_transfers, bfin_spi_pump_transfers, (unsigned long)drv_data); /* register with the SPI framework */ - ret = spi_register_master(master); + ret = devm_spi_register_master(dev, master); if (ret) { dev_err(dev, "can not register spi master\n"); goto err_free_peripheral; @@ -898,7 +898,6 @@ static int bfin_spi_remove(struct platform_device *pdev) free_dma(drv_data->rx_dma); free_dma(drv_data->tx_dma); - spi_unregister_master(drv_data->master); return 0; } -- cgit v1.2.3 From c493fc4bbd4f27b1a8a141648df866c386441b70 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:27:48 +0900 Subject: spi: clps711x: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-clps711x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index b597a92565dc..f2b1a1c33907 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -230,7 +230,7 @@ static int spi_clps711x_probe(struct platform_device *pdev) goto clk_out; } - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (!ret) { dev_info(&pdev->dev, "SPI bus driver initialized. Master clock %u Hz\n", @@ -261,8 +261,6 @@ static int spi_clps711x_remove(struct platform_device *pdev) if (gpio_is_valid(hw->chipselect[i])) gpio_free(hw->chipselect[i]); - spi_unregister_master(master); - return 0; } -- cgit v1.2.3 From 434eaf3b231125c73450bbc6ebe2396b9b63aa2f Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:30:41 +0900 Subject: spi: ep93xx: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d22c00a227b6..486fb6deab05 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -942,7 +942,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) /* make sure that the hardware is disabled */ ep93xx_spi_write_u8(espi, SSPCR1, 0); - error = spi_register_master(master); + error = devm_spi_register_master(&pdev->dev, master); if (error) { dev_err(&pdev->dev, "failed to register SPI master\n"); goto fail_free_dma; @@ -968,7 +968,6 @@ static int ep93xx_spi_remove(struct platform_device *pdev) ep93xx_spi_release_dma(espi); - spi_unregister_master(master); return 0; } -- cgit v1.2.3 From eaa24297846bcdd98cefd52937ed88046a121ebc Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:31:50 +0900 Subject: spi: mpc512x: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove a duplicate put. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-mpc512x-psc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index dbc5e999a1f5..b4426dd8a0c3 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -534,7 +534,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, if (ret < 0) goto free_clock; - ret = spi_register_master(master); + ret = devm_spi_register_master(dev, master); if (ret < 0) goto free_clock; @@ -557,12 +557,10 @@ static int mpc512x_psc_spi_do_remove(struct device *dev) struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); - spi_unregister_master(master); clk_disable_unprepare(mps->clk_mclk); free_irq(mps->irq, mps); if (mps->psc) iounmap(mps->psc); - spi_master_put(master); return 0; } -- cgit v1.2.3 From 33e195acf2682627d9f4d9fb9c30a5dd5323bc5c Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:32:56 +0900 Subject: spi: mxs: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove a duplicate put. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index de7b1141b90f..312c7f99c4a7 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -571,7 +571,7 @@ static int mxs_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (ret) { dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret); goto out_disable_clk; @@ -598,10 +598,8 @@ static int mxs_spi_remove(struct platform_device *pdev) spi = spi_master_get_devdata(master); ssp = &spi->ssp; - spi_unregister_master(master); clk_disable_unprepare(ssp->clk); dma_release_channel(ssp->dmach); - spi_master_put(master); return 0; } -- cgit v1.2.3 From 22ad2d8df77d1e88996d0e8f1c04db65f235a778 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:34:24 +0900 Subject: spi: octeon: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-octeon.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-octeon.c b/drivers/spi/spi-octeon.c index 5f28ddbe4f7e..67249a48b391 100644 --- a/drivers/spi/spi-octeon.c +++ b/drivers/spi/spi-octeon.c @@ -272,7 +272,7 @@ static int octeon_spi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_MASK(8); master->dev.of_node = pdev->dev.of_node; - err = spi_register_master(master); + err = devm_spi_register_master(&pdev->dev, master); if (err) { dev_err(&pdev->dev, "register master failed: %d\n", err); goto fail; @@ -292,8 +292,6 @@ static int octeon_spi_remove(struct platform_device *pdev) struct octeon_spi *p = spi_master_get_devdata(master); u64 register_base = p->register_base; - spi_unregister_master(master); - /* Clear the CSENA* and put everything in a known state. */ cvmx_write_csr(register_base + OCTEON_SPI_CFG, 0); -- cgit v1.2.3 From 5c4c5c7be116b0cce2e71173158060afac4144d0 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:37:23 +0900 Subject: spi: omap-100k: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 69ecf05757dd..b6ed82beb01d 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -457,7 +457,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev) goto err; } - status = spi_register_master(master); + status = devm_spi_register_master(&pdev->dev, master); if (status < 0) goto err; @@ -485,8 +485,6 @@ static int omap1_spi100k_remove(struct platform_device *pdev) r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi_unregister_master(master); - return 0; } -- cgit v1.2.3 From b95e02b748ce3674a81d5796b5ee398cbccc92df Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:40:29 +0900 Subject: spi: omap2-mcspi: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index ed4af4708d9a..2f7fd35a9ac8 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1407,7 +1407,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) if (status < 0) goto disable_pm; - status = spi_register_master(master); + status = devm_spi_register_master(&pdev->dev, master); if (status < 0) goto disable_pm; @@ -1435,7 +1435,6 @@ static int omap2_mcspi_remove(struct platform_device *pdev) pm_runtime_put_sync(mcspi->dev); pm_runtime_disable(&pdev->dev); - spi_unregister_master(master); kfree(dma_channels); return 0; -- cgit v1.2.3 From 4bd3d8e36b5571db8874ea95ba2b95de1192e387 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:43:09 +0900 Subject: spi: orion: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Jason Cooper Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 1d1d321d90c4..d96d67869d7b 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -457,7 +457,7 @@ static int orion_spi_probe(struct platform_device *pdev) goto out_rel_clk; master->dev.of_node = pdev->dev.of_node; - status = spi_register_master(master); + status = devm_spi_register_master(&pdev->dev, master); if (status < 0) goto out_rel_clk; @@ -483,8 +483,6 @@ static int orion_spi_remove(struct platform_device *pdev) clk_disable_unprepare(spi->clk); clk_put(spi->clk); - spi_unregister_master(master); - return 0; } -- cgit v1.2.3 From 35794a77168b739bbc758b6c5b11c78572188d77 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:44:59 +0900 Subject: spi: pl022: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index c13d523f1f48..5e3011094eb6 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2225,7 +2225,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) /* Register with the SPI framework */ amba_set_drvdata(adev, pl022); - status = spi_register_master(master); + status = devm_spi_register_master(&adev->dev, master); if (status != 0) { dev_err(&adev->dev, "probe - problem registering spi master\n"); @@ -2285,7 +2285,6 @@ pl022_remove(struct amba_device *adev) clk_unprepare(pl022->clk); amba_release_regions(adev); tasklet_disable(&pl022->pump_transfers); - spi_unregister_master(pl022->master); return 0; } -- cgit v1.2.3 From a807fcd090d6e778717d0954fc6a58a72ee16ba0 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:46:55 +0900 Subject: spi: pxa2xx: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 2eb06ee0b326..669306aa6c29 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1196,7 +1196,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) /* Register with the SPI framework */ platform_set_drvdata(pdev, drv_data); - status = spi_register_master(master); + status = devm_spi_register_master(&pdev->dev, master); if (status != 0) { dev_err(&pdev->dev, "problem registering spi master\n"); goto out_error_clock_enabled; @@ -1248,9 +1248,6 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) /* Release SSP */ pxa_ssp_free(ssp); - /* Disconnect from the SPI framework */ - spi_unregister_master(drv_data->master); - return 0; } -- cgit v1.2.3 From 1c43f2ae1ee3b04f7466e31a59b19b7fa5fe4fc2 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:47:59 +0900 Subject: spi: sh-hspi: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Kuninori Morimoto Signed-off-by: Mark Brown --- drivers/spi/spi-sh-hspi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 0b68cb592fa4..97e913d225f3 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -303,7 +303,7 @@ static int hspi_probe(struct platform_device *pdev) master->mode_bits = SPI_CPOL | SPI_CPHA; master->auto_runtime_pm = true; master->transfer_one_message = hspi_transfer_one_message; - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "spi_register_master error.\n"); goto error1; @@ -328,7 +328,6 @@ static int hspi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); clk_put(hspi->clk); - spi_unregister_master(hspi->master); return 0; } -- cgit v1.2.3 From 5c8096439600de88a7ceded70cc86b817d4a548e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:49:24 +0900 Subject: spi: tegra114: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 145dd435483b..bb3a19f2ed39 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1115,7 +1115,7 @@ static int tegra_spi_probe(struct platform_device *pdev) pm_runtime_put(&pdev->dev); master->dev.of_node = pdev->dev.of_node; - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "can not register to master err %d\n", ret); goto exit_pm_disable; @@ -1142,7 +1142,6 @@ static int tegra_spi_remove(struct platform_device *pdev) struct tegra_spi_data *tspi = spi_master_get_devdata(master); free_irq(tspi->irq, tspi); - spi_unregister_master(master); if (tspi->tx_dma_chan) tegra_spi_deinit_dma_param(tspi, false); -- cgit v1.2.3 From f12f7318c44aa5ea1672f9a356de02a8739b6892 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:50:25 +0900 Subject: spi: tegra20-sflash: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-sflash.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 1d814dc6e000..a68d7797a8ec 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -529,7 +529,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) pm_runtime_put(&pdev->dev); master->dev.of_node = pdev->dev.of_node; - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "can not register to master err %d\n", ret); goto exit_pm_disable; @@ -553,7 +553,6 @@ static int tegra_sflash_remove(struct platform_device *pdev) struct tegra_sflash_data *tsd = spi_master_get_devdata(master); free_irq(tsd->irq, tsd); - spi_unregister_master(master); pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) -- cgit v1.2.3 From 716db5d64f5f9bd6600cd4f85c2986d34cd7f60e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:51:32 +0900 Subject: spi: tegra20-slink: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-slink.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index c70353672a23..829283e785d9 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1164,7 +1164,7 @@ static int tegra_slink_probe(struct platform_device *pdev) pm_runtime_put(&pdev->dev); master->dev.of_node = pdev->dev.of_node; - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "can not register to master err %d\n", ret); goto exit_pm_disable; @@ -1191,7 +1191,6 @@ static int tegra_slink_remove(struct platform_device *pdev) struct tegra_slink_data *tspi = spi_master_get_devdata(master); free_irq(tspi->irq, tspi); - spi_unregister_master(master); if (tspi->tx_dma_chan) tegra_slink_deinit_dma_param(tspi, false); -- cgit v1.2.3 From 7388c03bac1b4466864945233abf3ca8ba1cb061 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:52:37 +0900 Subject: spi: ti-qspi: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove unnecessary remove(). Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index e12d962a289f..4e2109d9853d 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -532,7 +532,7 @@ static int ti_qspi_probe(struct platform_device *pdev) if (!of_property_read_u32(np, "spi-max-frequency", &max_freq)) qspi->spi_max_frequency = max_freq; - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (ret) goto free_master; @@ -543,22 +543,12 @@ free_master: return ret; } -static int ti_qspi_remove(struct platform_device *pdev) -{ - struct ti_qspi *qspi = platform_get_drvdata(pdev); - - spi_unregister_master(qspi->master); - - return 0; -} - static const struct dev_pm_ops ti_qspi_pm_ops = { .runtime_resume = ti_qspi_runtime_resume, }; static struct platform_driver ti_qspi_driver = { .probe = ti_qspi_probe, - .remove = ti_qspi_remove, .driver = { .name = "ti,dra7xxx-qspi", .owner = THIS_MODULE, -- cgit v1.2.3 From 2fe7e4add3e53df7c1b97e32076f8390dd81c6b3 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 24 Sep 2013 13:53:37 +0900 Subject: spi: txx9: use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove a duplicate put. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-txx9.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index 7c6d15766c72..69eb88627d40 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -406,7 +406,7 @@ static int txx9spi_probe(struct platform_device *dev) master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */ master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); - ret = spi_register_master(master); + ret = devm_spi_register_master(&dev->dev, master); if (ret) goto exit; return 0; @@ -428,11 +428,9 @@ static int txx9spi_remove(struct platform_device *dev) struct spi_master *master = spi_master_get(platform_get_drvdata(dev)); struct txx9spi *c = spi_master_get_devdata(master); - spi_unregister_master(master); destroy_workqueue(c->workqueue); clk_disable(c->clk); clk_put(c->clk); - spi_master_put(master); return 0; } -- cgit v1.2.3 From 7d5f880b46f222ff83a76fd36b01f5a59bf32122 Mon Sep 17 00:00:00 2001 From: Mateusz Krawczuk Date: Tue, 24 Sep 2013 18:07:46 +0200 Subject: spi: s3c64xx: Allow build on all Samsung platforms Replace all symbols by simple dependency PLAT_SAMSUNG. Signed-off-by: Mateusz Krawczuk Signed-off-by: Kyungmin Park Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b9c53cc40e1f..d92d6690d615 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -393,7 +393,7 @@ config SPI_S3C24XX_FIQ config SPI_S3C64XX tristate "Samsung S3C64XX series type SPI" - depends on (ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS) + depends on PLAT_SAMSUNG select S3C64XX_DMA if ARCH_S3C64XX help SPI driver for Samsung S3C64XX and newer SoCs. -- cgit v1.2.3 From 633795b992ebae2a78890c0cfa5c17058eb93817 Mon Sep 17 00:00:00 2001 From: Sourav Poddar Date: Tue, 24 Sep 2013 20:41:23 +0530 Subject: spi/qspi: Add dual/quad read mode bit. Add dual/quad read mode bit flag for the master controller. These check will be used in the spi framework to determine whether the master controller can do dual/quad read respectively. Signed-off-by: Sourav Poddar Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index e12d962a289f..7a45c3e665f8 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -472,7 +472,7 @@ static int ti_qspi_probe(struct platform_device *pdev) if (!master) return -ENOMEM; - master->mode_bits = SPI_CPOL | SPI_CPHA; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD; master->bus_num = -1; master->flags = SPI_MASTER_HALF_DUPLEX; -- cgit v1.2.3 From f4fade12d506e14867a2b0a5e2f7aaf227297d8b Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 26 Sep 2013 13:01:43 -0400 Subject: spi/tegra114: Correct support for cs_change The tegra114 driver wasn't currently handling the cs_change functionality. cs_change is meant to invert the decisions of whether or not to deactivate CS after each transfer. Without cs_change, after every transfer (other than the last in the message) the normal behavior is to leave CS active. For the last transfer, normally CS is deactivated when the transfer is complete. With cs_change set on a transfer (other than last one) CS would be deactivated and the next transfer would need to activate it again. If cs_change was set on the last tranfer in a message, then CS would be left active when the message compeleted. Also, this builds in logic so that if a different device tries to start a transfer while CS is active from a different device, it will abort the previous transfer and start a new one for the new device. This splits tegra_spi_start_transfer_one into 2 functions, the new one being tegra_spi_setup_transfer_one. The setup function is safe to call on all transfers, sets up for the transfer, and handles the special case of the first transfer in a message. In this special case, it needs to know whether or not it needs to activate CS. This work was based on the spi-atmel driver. Signed-off-by: Rhyland Klein Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 85 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 145dd435483b..64ca86c806e5 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -182,6 +182,7 @@ struct tegra_spi_data { u32 cur_speed; struct spi_device *cur_spi; + struct spi_device *cs_control; unsigned cur_pos; unsigned cur_len; unsigned words_per_32bit; @@ -676,15 +677,12 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi, dma_release_channel(dma_chan); } -static int tegra_spi_start_transfer_one(struct spi_device *spi, - struct spi_transfer *t, bool is_first_of_msg, - bool is_single_xfer) +static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi, + struct spi_transfer *t, bool is_first_of_msg) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); u32 speed = t->speed_hz; u8 bits_per_word = t->bits_per_word; - unsigned total_fifo_words; - int ret; unsigned long command1; int req_mode; @@ -698,7 +696,6 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, tspi->cur_rx_pos = 0; tspi->cur_tx_pos = 0; tspi->curr_xfer = t; - total_fifo_words = tegra_spi_calculate_curr_xfer_param(spi, tspi, t); if (is_first_of_msg) { tegra_spi_clear_status(tspi); @@ -717,7 +714,12 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, else if (req_mode == SPI_MODE_3) command1 |= SPI_CONTROL_MODE_3; - tegra_spi_writel(tspi, command1, SPI_COMMAND1); + if (tspi->cs_control) { + if (tspi->cs_control != spi) + tegra_spi_writel(tspi, command1, SPI_COMMAND1); + tspi->cs_control = NULL; + } else + tegra_spi_writel(tspi, command1, SPI_COMMAND1); command1 |= SPI_CS_SW_HW; if (spi->mode & SPI_CS_HIGH) @@ -732,6 +734,18 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, command1 |= SPI_BIT_LENGTH(bits_per_word - 1); } + return command1; +} + +static int tegra_spi_start_transfer_one(struct spi_device *spi, + struct spi_transfer *t, unsigned long command1) +{ + struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); + unsigned total_fifo_words; + int ret; + + total_fifo_words = tegra_spi_calculate_curr_xfer_param(spi, tspi, t); + if (tspi->is_packed) command1 |= SPI_PACKED; @@ -803,29 +817,50 @@ static int tegra_spi_setup(struct spi_device *spi) return 0; } +static void tegra_spi_transfer_delay(int delay) +{ + if (!delay) + return; + + if (delay >= 1000) + mdelay(delay / 1000); + + udelay(delay % 1000); +} + static int tegra_spi_transfer_one_message(struct spi_master *master, struct spi_message *msg) { bool is_first_msg = true; - int single_xfer; struct tegra_spi_data *tspi = spi_master_get_devdata(master); struct spi_transfer *xfer; struct spi_device *spi = msg->spi; int ret; + bool skip = false; msg->status = 0; msg->actual_length = 0; - single_xfer = list_is_singular(&msg->transfers); list_for_each_entry(xfer, &msg->transfers, transfer_list) { + unsigned long cmd1; + INIT_COMPLETION(tspi->xfer_completion); - ret = tegra_spi_start_transfer_one(spi, xfer, - is_first_msg, single_xfer); + + cmd1 = tegra_spi_setup_transfer_one(spi, xfer, is_first_msg); + + if (!xfer->len) { + ret = 0; + skip = true; + goto complete_xfer; + } + + ret = tegra_spi_start_transfer_one(spi, xfer, cmd1); if (ret < 0) { dev_err(tspi->dev, "spi can not start transfer, err %d\n", ret); - goto exit; + goto complete_xfer; } + is_first_msg = false; ret = wait_for_completion_timeout(&tspi->xfer_completion, SPI_DMA_TIMEOUT); @@ -833,24 +868,40 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, dev_err(tspi->dev, "spi trasfer timeout, err %d\n", ret); ret = -EIO; - goto exit; + goto complete_xfer; } if (tspi->tx_status || tspi->rx_status) { dev_err(tspi->dev, "Error in Transfer\n"); ret = -EIO; - goto exit; + goto complete_xfer; } msg->actual_length += xfer->len; - if (xfer->cs_change && xfer->delay_usecs) { + +complete_xfer: + if (ret < 0 || skip) { tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); - udelay(xfer->delay_usecs); + tegra_spi_transfer_delay(xfer->delay_usecs); + goto exit; + } else if (msg->transfers.prev == &xfer->transfer_list) { + /* This is the last transfer in message */ + if (xfer->cs_change) + tspi->cs_control = spi; + else { + tegra_spi_writel(tspi, tspi->def_command1_reg, + SPI_COMMAND1); + tegra_spi_transfer_delay(xfer->delay_usecs); + } + } else if (xfer->cs_change) { + tegra_spi_writel(tspi, tspi->def_command1_reg, + SPI_COMMAND1); + tegra_spi_transfer_delay(xfer->delay_usecs); } + } ret = 0; exit: - tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); msg->status = ret; spi_finalize_current_message(master); return ret; -- cgit v1.2.3 From 70fac17cec347c4013cb8f380c6fe6554a13d884 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sat, 31 Aug 2013 20:24:14 +0200 Subject: spi: simplify call to request_module() request_module() can handle format strings on its own, no need to create the full module name ourself. Signed-off-by: Mathias Krause Signed-off-by: Mark Brown --- drivers/spi/spi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9e039c60c068..74a526ce8c04 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -839,7 +839,6 @@ static void of_register_spi_devices(struct spi_master *master) struct spi_device *spi; struct device_node *nc; const __be32 *prop; - char modalias[SPI_NAME_SIZE + 4]; int rc; int len; @@ -944,9 +943,7 @@ static void of_register_spi_devices(struct spi_master *master) spi->dev.of_node = nc; /* Register the new device */ - snprintf(modalias, sizeof(modalias), "%s%s", SPI_MODULE_PREFIX, - spi->modalias); - request_module(modalias); + request_module("%s%s", SPI_MODULE_PREFIX, spi->modalias); rc = spi_add_device(spi); if (rc) { dev_err(&master->dev, "spi_device register error %s\n", -- cgit v1.2.3 From 89da4293a7bb29ac42b7dd2c2573c8a5ebb0b6c7 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Fri, 27 Sep 2013 05:37:25 -0700 Subject: spi: Use of_property_read_u32 Instead of getting the raw property, checking the length, and doing endian conversion each time, use the OF function of_property_read_u32() that does all that. Error messages are slightly improved with error codes from of_property_read_u32() for different ways the property may be invalid (missing, too short, etc.) Signed-off-by: Trent Piepho Signed-off-by: Mark Brown --- drivers/spi/spi.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 74a526ce8c04..1cd491f79422 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -838,9 +838,8 @@ static void of_register_spi_devices(struct spi_master *master) { struct spi_device *spi; struct device_node *nc; - const __be32 *prop; int rc; - int len; + u32 value; if (!master->dev.of_node) return; @@ -865,14 +864,14 @@ static void of_register_spi_devices(struct spi_master *master) } /* Device address */ - prop = of_get_property(nc, "reg", &len); - if (!prop || len < sizeof(*prop)) { - dev_err(&master->dev, "%s has no 'reg' property\n", - nc->full_name); + rc = of_property_read_u32(nc, "reg", &value); + if (rc) { + dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n", + nc->full_name, rc); spi_dev_put(spi); continue; } - spi->chip_select = be32_to_cpup(prop); + spi->chip_select = value; /* Mode (clock phase/polarity/etc.) */ if (of_find_property(nc, "spi-cpha", NULL)) @@ -885,55 +884,53 @@ static void of_register_spi_devices(struct spi_master *master) spi->mode |= SPI_3WIRE; /* Device DUAL/QUAD mode */ - prop = of_get_property(nc, "spi-tx-bus-width", &len); - if (prop && len == sizeof(*prop)) { - switch (be32_to_cpup(prop)) { - case SPI_NBITS_SINGLE: + if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) { + switch (value) { + case 1: break; - case SPI_NBITS_DUAL: + case 2: spi->mode |= SPI_TX_DUAL; break; - case SPI_NBITS_QUAD: + case 4: spi->mode |= SPI_TX_QUAD; break; default: dev_err(&master->dev, "spi-tx-bus-width %d not supported\n", - be32_to_cpup(prop)); + value); spi_dev_put(spi); continue; } } - prop = of_get_property(nc, "spi-rx-bus-width", &len); - if (prop && len == sizeof(*prop)) { - switch (be32_to_cpup(prop)) { - case SPI_NBITS_SINGLE: + if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) { + switch (value) { + case 1: break; - case SPI_NBITS_DUAL: + case 2: spi->mode |= SPI_RX_DUAL; break; - case SPI_NBITS_QUAD: + case 4: spi->mode |= SPI_RX_QUAD; break; default: dev_err(&master->dev, "spi-rx-bus-width %d not supported\n", - be32_to_cpup(prop)); + value); spi_dev_put(spi); continue; } } /* Device speed */ - prop = of_get_property(nc, "spi-max-frequency", &len); - if (!prop || len < sizeof(*prop)) { - dev_err(&master->dev, "%s has no 'spi-max-frequency' property\n", - nc->full_name); + rc = of_property_read_u32(nc, "spi-max-frequency", &value); + if (rc) { + dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n", + nc->full_name, rc); spi_dev_put(spi); continue; } - spi->max_speed_hz = be32_to_cpup(prop); + spi->max_speed_hz = value; /* IRQ */ spi->irq = irq_of_parse_and_map(nc, 0); -- cgit v1.2.3 From 67651b29ef15e5ef9897ed8cb9072222c4cf3432 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 27 Sep 2013 20:10:26 +0100 Subject: spi/s3c64xx: Flush FIFOs prior to cleaning up transfer Ensure that the FIFOs are fully drained before we deassert /CS or do any delays that have been requested in order to ensure that the behaviour visible on the bus matches that which was requested by the caller. Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 229c6b994be3..2e267ce9dc19 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -960,6 +960,8 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, goto out; } + flush_fifo(sdd); + if (xfer->delay_usecs) udelay(xfer->delay_usecs); @@ -972,8 +974,6 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, } msg->actual_length += xfer->len; - - flush_fifo(sdd); } out: -- cgit v1.2.3 From 8b06d5b8576d1df4122fa9ca40578ec7f094cb3e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 27 Sep 2013 18:44:53 +0100 Subject: spi/s3c64xx: Check that clock enables succeed on runtime resume Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 2e267ce9dc19..dd5ed13436e5 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1524,9 +1524,17 @@ static int s3c64xx_spi_runtime_resume(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + int ret; - clk_prepare_enable(sdd->src_clk); - clk_prepare_enable(sdd->clk); + ret = clk_prepare_enable(sdd->src_clk); + if (ret != 0) + return ret; + + ret = clk_prepare_enable(sdd->clk); + if (ret != 0) { + clk_disable_unprepare(sdd->src_clk); + return ret; + } return 0; } -- cgit v1.2.3 From 64d930ac116db25db814f76c31bfd4a7ea428f74 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 27 Sep 2013 18:45:23 +0100 Subject: spi/s3c64xx: Remove unused gpios field from driver data Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index dd5ed13436e5..7f960db66763 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -205,7 +205,6 @@ struct s3c64xx_spi_driver_data { #endif struct s3c64xx_spi_port_config *port_conf; unsigned int port_id; - unsigned long gpios[4]; bool cs_gpio; }; -- cgit v1.2.3 From dd97e26849c16f484191f056b6e080cc30ebe98b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 27 Sep 2013 18:58:55 +0100 Subject: spi/s3c64xx: Use core cs_gpio field Rather than using the driver custom platform data to store the chip select GPIO use the cs_gpio field provided by the SPI core, supporting future refectoring. Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 7f960db66763..43caeee8641a 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -558,22 +558,18 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, struct spi_device *spi) { - struct s3c64xx_spi_csinfo *cs; - if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */ if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ /* Deselect the last toggled device */ - cs = sdd->tgl_spi->controller_data; - if (sdd->cs_gpio) - gpio_set_value(cs->line, + if (spi->cs_gpio >= 0) + gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); } sdd->tgl_spi = NULL; } - cs = spi->controller_data; - if (sdd->cs_gpio) - gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); + if (spi->cs_gpio >= 0) + gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 1 : 0); /* Start the signals */ writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); @@ -701,13 +697,11 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, struct spi_device *spi) { - struct s3c64xx_spi_csinfo *cs = spi->controller_data; - if (sdd->tgl_spi == spi) sdd->tgl_spi = NULL; - if (sdd->cs_gpio) - gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); + if (spi->cs_gpio >= 0) + gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); /* Quiese the signals */ writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); @@ -1070,6 +1064,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi) cs->line, err); goto err_gpio_req; } + + spi->cs_gpio = cs->line; } spi_set_ctldata(spi, cs); @@ -1139,8 +1135,8 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi) struct s3c64xx_spi_driver_data *sdd; sdd = spi_master_get_devdata(spi->master); - if (cs && sdd->cs_gpio) { - gpio_free(cs->line); + if (spi->cs_gpio) { + gpio_free(spi->cs_gpio); if (spi->dev.of_node) kfree(cs); } -- cgit v1.2.3 From 8c09daa1c963e2ab58029520dd2f3d54184d7258 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 27 Sep 2013 19:56:31 +0100 Subject: spi/s3c64xx: Factor transfer start out of enable/disable_cs() The hardware level /CS handling is tied to the start of the data path so is rolled into the same function as we use to manipulate GPIO /CS. In order to support factoring out the /CS handling into the core separate the two and explicitly start transfers separately to the /CS handling. Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 43caeee8641a..2ab96fb28d22 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -570,9 +570,6 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, if (spi->cs_gpio >= 0) gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 1 : 0); - - /* Start the signals */ - writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); } static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, @@ -702,9 +699,6 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, if (spi->cs_gpio >= 0) gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); - - /* Quiese the signals */ - writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); } static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) @@ -930,6 +924,9 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, /* Slave Select */ enable_cs(sdd, spi); + /* Start the signals */ + writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); + spin_unlock_irqrestore(&sdd->lock, flags); status = wait_for_xfer(sdd, xfer, use_dma); @@ -970,10 +967,14 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, } out: - if (!cs_toggle || status) + if (!cs_toggle || status) { + /* Quiese the signals */ + writel(S3C64XX_SPI_SLAVE_SIG_INACT, + sdd->regs + S3C64XX_SPI_SLAVE_SEL); disable_cs(sdd, spi); - else + } else { sdd->tgl_spi = spi; + } s3c64xx_spi_unmap_mssg(sdd, msg); @@ -1112,11 +1113,13 @@ static int s3c64xx_spi_setup(struct spi_device *spi) } pm_runtime_put(&sdd->pdev->dev); + writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); disable_cs(sdd, spi); return 0; setup_exit: /* setup() returns with device de-selected */ + writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); disable_cs(sdd, spi); gpio_free(cs->line); -- cgit v1.2.3 From 0f5a751ace250097d3ad7835df7d376f21f44509 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 27 Sep 2013 20:38:01 +0100 Subject: spi/s3c64xx: Enable GPIO /CS prior to starting hardware To help with bisection of future refactoring to share more of the code for handling a spi_message pull the enabling of GPIO based /CS prior to all the hardware setup for starting a transfer. Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 2ab96fb28d22..e6312322f66a 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -906,6 +906,9 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, s3c64xx_spi_config(sdd); } + /* Slave Select */ + enable_cs(sdd, spi); + /* Polling method for xfers not bigger than FIFO capacity */ use_dma = 0; if (!is_polling(sdd) && @@ -921,9 +924,6 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, enable_datapath(sdd, spi, xfer, use_dma); - /* Slave Select */ - enable_cs(sdd, spi); - /* Start the signals */ writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); -- cgit v1.2.3 From 600ba98bff438510dc81fc1ba9048420479bbded Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 27 Sep 2013 16:34:28 +0200 Subject: hwmon: (adt7310) Use spi_w8r16be() instead spi_w8r16() Using spi_w8r16be() instead of spi_w8r16() in this driver makes a code a bit shorter and cleaner. Signed-off-by: Lars-Peter Clausen Acked-by: Guenter Roeck Signed-off-by: Mark Brown --- drivers/hwmon/adt7310.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c index da5f0789fb97..5994cf68e0a4 100644 --- a/drivers/hwmon/adt7310.c +++ b/drivers/hwmon/adt7310.c @@ -42,13 +42,8 @@ static const u8 adt7310_reg_table[] = { static int adt7310_spi_read_word(struct device *dev, u8 reg) { struct spi_device *spi = to_spi_device(dev); - int ret; - ret = spi_w8r16(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ); - if (ret < 0) - return ret; - - return be16_to_cpu((__force __be16)ret); + return spi_w8r16be(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ); } static int adt7310_spi_write_word(struct device *dev, u8 reg, u16 data) -- cgit v1.2.3 From 235907422548aae38d03a545f20fceb728b70ddd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 27 Sep 2013 16:34:29 +0200 Subject: staging:iio:ade7753/ade7754/ade7759: Use spi_w8r16be() instead of spi_w8r16() Using spi_w8r16be() will do the conversion of the result from big endian to native endian in the helper function. This makes the code a bit smaller and also keeps sparse happy. Fixes the following sparse warnings: drivers/staging/iio/meter/ade7753.c:97:29: warning: incorrect type in argument 1 (different base types) drivers/staging/iio/meter/ade7753.c:97:29: expected restricted __be16 const [usertype] *p drivers/staging/iio/meter/ade7753.c:97:29: got unsigned short [usertype] *val drivers/staging/iio/meter/ade7754.c:97:29: warning: incorrect type in argument 1 (different base types) drivers/staging/iio/meter/ade7754.c:97:29: expected restricted __be16 const [usertype] *p drivers/staging/iio/meter/ade7754.c:97:29: got unsigned short [usertype] *val drivers/staging/iio/meter/ade7759.c:97:29: warning: incorrect type in argument 1 (different base types) drivers/staging/iio/meter/ade7759.c:97:29: expected restricted __be16 const [usertype] *p drivers/staging/iio/meter/ade7759.c:97:29: got unsigned short [usertype] *val Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Mark Brown --- drivers/staging/iio/meter/ade7753.c | 3 +-- drivers/staging/iio/meter/ade7754.c | 3 +-- drivers/staging/iio/meter/ade7759.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 74025fbae679..abfc8bd1794d 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -86,7 +86,7 @@ static int ade7753_spi_read_reg_16(struct device *dev, struct ade7753_state *st = iio_priv(indio_dev); ssize_t ret; - ret = spi_w8r16(st->us, ADE7753_READ_REG(reg_address)); + ret = spi_w8r16be(st->us, ADE7753_READ_REG(reg_address)); if (ret < 0) { dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -94,7 +94,6 @@ static int ade7753_spi_read_reg_16(struct device *dev, } *val = ret; - *val = be16_to_cpup(val); return 0; } diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index f649ebe55a04..3d1c02cd6538 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -86,7 +86,7 @@ static int ade7754_spi_read_reg_16(struct device *dev, struct ade7754_state *st = iio_priv(indio_dev); int ret; - ret = spi_w8r16(st->us, ADE7754_READ_REG(reg_address)); + ret = spi_w8r16be(st->us, ADE7754_READ_REG(reg_address)); if (ret < 0) { dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -94,7 +94,6 @@ static int ade7754_spi_read_reg_16(struct device *dev, } *val = ret; - *val = be16_to_cpup(val); return 0; } diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index d214ac4932cb..7467e51fd424 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -86,7 +86,7 @@ static int ade7759_spi_read_reg_16(struct device *dev, struct ade7759_state *st = iio_priv(indio_dev); int ret; - ret = spi_w8r16(st->us, ADE7759_READ_REG(reg_address)); + ret = spi_w8r16be(st->us, ADE7759_READ_REG(reg_address)); if (ret < 0) { dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -94,7 +94,6 @@ static int ade7759_spi_read_reg_16(struct device *dev, } *val = ret; - *val = be16_to_cpup(val); return 0; } -- cgit v1.2.3 From c70837908dc1b63298125e1b80064c4639d92fd2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Sep 2013 15:32:53 +0530 Subject: spi: clps711x: Remove redundant label Remove empty label. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-clps711x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 5655acf55bfe..1a786834c16d 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -227,7 +227,7 @@ static int spi_clps711x_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Can't request IRQ\n"); clk_put(hw->spi_clk); - goto clk_out; + goto err_out; } ret = spi_register_master(master); @@ -240,7 +240,6 @@ static int spi_clps711x_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to register master\n"); -clk_out: err_out: while (--i >= 0) if (gpio_is_valid(hw->chipselect[i])) -- cgit v1.2.3 From 3b3a80019ff194e86e740ec2f013a8915efd1ccf Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 2 Oct 2013 16:45:25 +0200 Subject: spi: ti-qspi: one only one interrupt handler The here used irq and threaded irq handler is a complete non-sense. After the status register is read and the source disabled it schedules a thread (the irq thread) to read the status from the variable, invoke complete() and then renable the interrupt. Again: schedule a thread which invokes _only_ complete(). This patch removes this non-sense and we remain with one handler which invokes complete() if needed. The device remove path should now disable the interupts. This has been compile time tested. Signed-off-by: Sebastian Andrzej Siewior Tested-by: Sourav Poddar Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 7a45c3e665f8..a61aeb9bb823 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -41,9 +41,6 @@ struct ti_qspi_regs { struct ti_qspi { struct completion transfer_complete; - /* IRQ synchronization */ - spinlock_t lock; - /* list synchronization */ struct mutex list_lock; @@ -57,7 +54,6 @@ struct ti_qspi { u32 spi_max_frequency; u32 cmd; u32 dc; - u32 stat; }; #define QSPI_PID (0x0) @@ -397,13 +393,12 @@ static irqreturn_t ti_qspi_isr(int irq, void *dev_id) { struct ti_qspi *qspi = dev_id; u16 int_stat; + u32 stat; irqreturn_t ret = IRQ_HANDLED; - spin_lock(&qspi->lock); - int_stat = ti_qspi_read(qspi, QSPI_INTR_STATUS_ENABLED_CLEAR); - qspi->stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG); + stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG); if (!int_stat) { dev_dbg(qspi->dev, "No IRQ triggered\n"); @@ -411,35 +406,14 @@ static irqreturn_t ti_qspi_isr(int irq, void *dev_id) goto out; } - ret = IRQ_WAKE_THREAD; - - ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG); ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_STATUS_ENABLED_CLEAR); - + if (stat & WC) + complete(&qspi->transfer_complete); out: - spin_unlock(&qspi->lock); - return ret; } -static irqreturn_t ti_qspi_threaded_isr(int this_irq, void *dev_id) -{ - struct ti_qspi *qspi = dev_id; - unsigned long flags; - - spin_lock_irqsave(&qspi->lock, flags); - - if (qspi->stat & WC) - complete(&qspi->transfer_complete); - - spin_unlock_irqrestore(&qspi->lock, flags); - - ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG); - - return IRQ_HANDLED; -} - static int ti_qspi_runtime_resume(struct device *dev) { struct ti_qspi *qspi; @@ -499,7 +473,6 @@ static int ti_qspi_probe(struct platform_device *pdev) return irq; } - spin_lock_init(&qspi->lock); mutex_init(&qspi->list_lock); qspi->base = devm_ioremap_resource(&pdev->dev, r); @@ -508,8 +481,7 @@ static int ti_qspi_probe(struct platform_device *pdev) goto free_master; } - ret = devm_request_threaded_irq(&pdev->dev, irq, ti_qspi_isr, - ti_qspi_threaded_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, ti_qspi_isr, 0, dev_name(&pdev->dev), qspi); if (ret < 0) { dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", @@ -547,6 +519,7 @@ static int ti_qspi_remove(struct platform_device *pdev) { struct ti_qspi *qspi = platform_get_drvdata(pdev); + ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG); spi_unregister_master(qspi->master); return 0; -- cgit v1.2.3 From 702a4879ec337463f858c8ab467482cce260bf18 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Sep 2013 15:43:41 +0800 Subject: spi: bitbang: Let spi_bitbang_start() take a reference to master Many drivers that use bitbang library have a leak on probe error paths. This is because once a spi_master_get() call succeeds, we need an additional spi_master_put() call to free the memory. Fix this issue by moving the code taking a reference to master to spi_bitbang_start(), so spi_bitbang_start() will take a reference to master on success. With this change, the caller is responsible for calling spi_bitbang_stop() to decrement the reference and spi_master_put() as counterpart of spi_alloc_master() to prevent a memory leak. So now we have below patten for drivers using bitbang library: probe: spi_alloc_master -> Init reference count to 1 spi_bitbang_start -> Increment reference count remove: spi_bitbang_stop -> Decrement reference count spi_master_put -> Decrement reference count (reference count reaches 0) Fixup all users accordingly. Signed-off-by: Axel Lin Suggested-by: Uwe Kleine-Koenig Acked-by: Uwe Kleine-Koenig Signed-off-by: Mark Brown --- drivers/spi/spi-altera.c | 2 +- drivers/spi/spi-ath79.c | 2 +- drivers/spi/spi-au1550.c | 2 +- drivers/spi/spi-bitbang.c | 12 +++++++++++- drivers/spi/spi-butterfly.c | 2 +- drivers/spi/spi-davinci.c | 10 ++++------ drivers/spi/spi-efm32.c | 2 +- drivers/spi/spi-fsl-dspi.c | 2 +- drivers/spi/spi-gpio.c | 5 ++--- drivers/spi/spi-imx.c | 2 +- drivers/spi/spi-lm70llp.c | 2 +- drivers/spi/spi-nuc900.c | 3 +-- drivers/spi/spi-oc-tiny.c | 2 +- drivers/spi/spi-ppc4xx.c | 3 ++- drivers/spi/spi-s3c24xx.c | 2 +- drivers/spi/spi-sh-sci.c | 2 +- drivers/spi/spi-sirf.c | 2 +- drivers/spi/spi-xilinx.c | 2 +- 18 files changed, 33 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index 9a64c3fee218..595b62cb545d 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -219,7 +219,7 @@ static int altera_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hw); /* setup the state for the bitbang driver */ - hw->bitbang.master = spi_master_get(master); + hw->bitbang.master = master; if (!hw->bitbang.master) return err; hw->bitbang.chipselect = altera_spi_chipsel; diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 37bad952ab38..821bf7ac218d 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -231,7 +231,7 @@ static int ath79_spi_probe(struct platform_device *pdev) master->num_chipselect = pdata->num_chipselect; } - sp->bitbang.master = spi_master_get(master); + sp->bitbang.master = master; sp->bitbang.chipselect = ath79_spi_chipselect; sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; sp->bitbang.setup_transfer = spi_bitbang_setup_transfer; diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 1d00d9b397dd..e06400a3a719 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -775,7 +775,7 @@ static int au1550_spi_probe(struct platform_device *pdev) hw = spi_master_get_devdata(master); - hw->master = spi_master_get(master); + hw->master = master; hw->pdata = dev_get_platdata(&pdev->dev); hw->dev = &pdev->dev; diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 8c11355dec23..0056623dfc6b 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -414,10 +414,16 @@ static int spi_bitbang_unprepare_hardware(struct spi_master *spi) * This routine registers the spi_master, which will process requests in a * dedicated task, keeping IRQs unblocked most of the time. To stop * processing those requests, call spi_bitbang_stop(). + * + * On success, this routine will take a reference to master. The caller is + * responsible for calling spi_bitbang_stop() to decrement the reference and + * spi_master_put() as counterpart of spi_alloc_master() to prevent a memory + * leak. */ int spi_bitbang_start(struct spi_bitbang *bitbang) { struct spi_master *master = bitbang->master; + int ret; if (!master || !bitbang->chipselect) return -EINVAL; @@ -449,7 +455,11 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) /* driver may get busy before register() returns, especially * if someone registered boardinfo for devices */ - return spi_register_master(master); + ret = spi_register_master(spi_master_get(master)); + if (ret) + spi_master_put(master); + + return 0; } EXPORT_SYMBOL_GPL(spi_bitbang_start); diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index 5ed08e537433..b1ecea2d76b3 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -225,7 +225,7 @@ static void butterfly_attach(struct parport *p) master->bus_num = 42; master->num_chipselect = 2; - pp->bitbang.master = spi_master_get(master); + pp->bitbang.master = master; pp->bitbang.chipselect = butterfly_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 8fbfe2483ffd..af2bb73d0168 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -916,7 +916,7 @@ static int davinci_spi_probe(struct platform_device *pdev) if (ret) goto unmap_io; - dspi->bitbang.master = spi_master_get(master); + dspi->bitbang.master = master; if (dspi->bitbang.master == NULL) { ret = -ENODEV; goto irq_free; @@ -925,7 +925,7 @@ static int davinci_spi_probe(struct platform_device *pdev) dspi->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dspi->clk)) { ret = -ENODEV; - goto put_master; + goto irq_free; } clk_prepare_enable(dspi->clk); @@ -1015,8 +1015,6 @@ free_dma: free_clk: clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); -put_master: - spi_master_put(master); irq_free: free_irq(dspi->irq, dspi); unmap_io: @@ -1024,7 +1022,7 @@ unmap_io: release_region: release_mem_region(dspi->pbase, resource_size(r)); free_master: - kfree(master); + spi_master_put(master); err: return ret; } @@ -1051,11 +1049,11 @@ static int davinci_spi_remove(struct platform_device *pdev) clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); - spi_master_put(master); free_irq(dspi->irq, dspi); iounmap(dspi->base); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(dspi->pbase, resource_size(r)); + spi_master_put(master); return 0; } diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index 7d84418a01d8..d428a40778c1 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -347,7 +347,7 @@ static int efm32_spi_probe(struct platform_device *pdev) ddata = spi_master_get_devdata(master); - ddata->bitbang.master = spi_master_get(master); + ddata->bitbang.master = master; ddata->bitbang.chipselect = efm32_spi_chipselect; ddata->bitbang.setup_transfer = efm32_spi_setup_transfer; ddata->bitbang.txrx_bufs = efm32_spi_txrx_bufs; diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6cd07d13ecab..d338b6722255 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -450,7 +450,7 @@ static int dspi_probe(struct platform_device *pdev) dspi = spi_master_get_devdata(master); dspi->pdev = pdev; - dspi->bitbang.master = spi_master_get(master); + dspi->bitbang.master = master; dspi->bitbang.chipselect = dspi_chipselect; dspi->bitbang.setup_transfer = dspi_setup_transfer; dspi->bitbang.txrx_bufs = dspi_txrx_transfer; diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 68b69fec13a9..14c01b44ca7a 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -467,7 +467,7 @@ static int spi_gpio_probe(struct platform_device *pdev) } #endif - spi_gpio->bitbang.master = spi_master_get(master); + spi_gpio->bitbang.master = master; spi_gpio->bitbang.chipselect = spi_gpio_chipselect; if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) { @@ -486,7 +486,6 @@ static int spi_gpio_probe(struct platform_device *pdev) status = spi_bitbang_start(&spi_gpio->bitbang); if (status < 0) { - spi_master_put(spi_gpio->bitbang.master); gpio_free: if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) gpio_free(SPI_MISO_GPIO); @@ -510,13 +509,13 @@ static int spi_gpio_remove(struct platform_device *pdev) /* stop() unregisters child devices too */ status = spi_bitbang_stop(&spi_gpio->bitbang); - spi_master_put(spi_gpio->bitbang.master); if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) gpio_free(SPI_MISO_GPIO); if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) gpio_free(SPI_MOSI_GPIO); gpio_free(SPI_SCK_GPIO); + spi_master_put(spi_gpio->bitbang.master); return status; } diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 15323d8bd9cf..02d9f468b2b6 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -786,7 +786,7 @@ static int spi_imx_probe(struct platform_device *pdev) master->num_chipselect = num_cs; spi_imx = spi_master_get_devdata(master); - spi_imx->bitbang.master = spi_master_get(master); + spi_imx->bitbang.master = master; for (i = 0; i < master->num_chipselect; i++) { int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index 0759b5db9883..41c5765be746 100644 --- a/drivers/spi/spi-lm70llp.c +++ b/drivers/spi/spi-lm70llp.c @@ -222,7 +222,7 @@ static void spi_lm70llp_attach(struct parport *p) /* * SPI and bitbang hookup. */ - pp->bitbang.master = spi_master_get(master); + pp->bitbang.master = master; pp->bitbang.chipselect = lm70_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx; pp->bitbang.flags = SPI_3WIRE; diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index 47a68b43bcd5..e0c32bc69ee2 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -349,7 +349,7 @@ static int nuc900_spi_probe(struct platform_device *pdev) } hw = spi_master_get_devdata(master); - hw->master = spi_master_get(master); + hw->master = master; hw->pdata = dev_get_platdata(&pdev->dev); hw->dev = &pdev->dev; @@ -435,7 +435,6 @@ err_iomap: kfree(hw->ioarea); err_pdata: spi_master_put(hw->master); - err_nomem: return err; } diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index 333cb1badcd7..91c668596202 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -306,7 +306,7 @@ static int tiny_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hw); /* setup the state for the bitbang driver */ - hw->bitbang.master = spi_master_get(master); + hw->bitbang.master = master; if (!hw->bitbang.master) return err; hw->bitbang.setup_transfer = tiny_spi_setup_transfer; diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 0ee53c25ba58..c57740bb70d3 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -396,7 +396,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) master->dev.of_node = np; platform_set_drvdata(op, master); hw = spi_master_get_devdata(master); - hw->master = spi_master_get(master); + hw->master = master; hw->dev = dev; init_completion(&hw->done); @@ -558,6 +558,7 @@ static int spi_ppc4xx_of_remove(struct platform_device *op) free_irq(hw->irqnum, hw); iounmap(hw->regs); free_gpios(hw); + spi_master_put(master); return 0; } diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index ce318d95a6ee..c9cfdfaf7523 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -524,7 +524,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) hw = spi_master_get_devdata(master); memset(hw, 0, sizeof(struct s3c24xx_spi)); - hw->master = spi_master_get(master); + hw->master = master; hw->pdata = pdata = dev_get_platdata(&pdev->dev); hw->dev = &pdev->dev; diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c index 8eefeb6007df..38eb24df796c 100644 --- a/drivers/spi/spi-sh-sci.c +++ b/drivers/spi/spi-sh-sci.c @@ -133,7 +133,7 @@ static int sh_sci_spi_probe(struct platform_device *dev) sp->info = dev_get_platdata(&dev->dev); /* setup spi bitbang adaptor */ - sp->bitbang.master = spi_master_get(master); + sp->bitbang.master = master; sp->bitbang.master->bus_num = sp->info->bus_num; sp->bitbang.master->num_chipselect = sp->info->num_chipselect; sp->bitbang.chipselect = sh_sci_spi_chipselect; diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index a1f21b747733..592b4aff651f 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -632,7 +632,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) if (ret) goto free_master; - sspi->bitbang.master = spi_master_get(master); + sspi->bitbang.master = master; sspi->bitbang.chipselect = spi_sirfsoc_chipselect; sspi->bitbang.setup_transfer = spi_sirfsoc_setup_transfer; sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer; diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 0bf1b2c457a1..ec3a83f52ea2 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -372,7 +372,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) master->mode_bits = SPI_CPOL | SPI_CPHA; xspi = spi_master_get_devdata(master); - xspi->bitbang.master = spi_master_get(master); + xspi->bitbang.master = master; xspi->bitbang.chipselect = xilinx_spi_chipselect; xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; -- cgit v1.2.3 From e6f7563b7354c2eb26d89b8622b3582a4c6510d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Sep 2013 09:51:30 +0200 Subject: spi: efm32: add spi_bitbang_stop to device remove callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This call is needed to cleanup the resources requested by spi_bitbang_start in the probe callback. Noticed-by: Axel Lin Signed-off-by: Uwe Kleine-König Signed-off-by: Mark Brown --- drivers/spi/spi-efm32.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index 34ef44c77e8e..5ce61e5f9770 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -477,6 +477,8 @@ static int efm32_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct efm32_spi_ddata *ddata = spi_master_get_devdata(master); + spi_bitbang_stop(&ddata->bitbang); + efm32_spi_write32(ddata, 0, REG_IEN); free_irq(ddata->txirq, ddata); -- cgit v1.2.3 From fb30a1819a4315091cb731403ebf74ff1a490f43 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Oct 2013 16:39:22 +0100 Subject: spi/tegra20-slink: Remove unused is_single_xfer check Currently transfer_one_message() checks to see if the message consists of a single spi_transfer and tells _start_transfer_one() but it just ignores this. Don't bother. Signed-off-by: Mark Brown Acked-by: Laxman Dewangan --- drivers/spi/spi-tegra20-slink.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index c70353672a23..36d4e663db9b 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -707,8 +707,7 @@ static void tegra_slink_deinit_dma_param(struct tegra_slink_data *tspi, } static int tegra_slink_start_transfer_one(struct spi_device *spi, - struct spi_transfer *t, bool is_first_of_msg, - bool is_single_xfer) + struct spi_transfer *t, bool is_first_of_msg) { struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master); u32 speed; @@ -828,7 +827,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, struct spi_message *msg) { bool is_first_msg = true; - int single_xfer; struct tegra_slink_data *tspi = spi_master_get_devdata(master); struct spi_transfer *xfer; struct spi_device *spi = msg->spi; @@ -837,11 +835,9 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, msg->status = 0; msg->actual_length = 0; - single_xfer = list_is_singular(&msg->transfers); list_for_each_entry(xfer, &msg->transfers, transfer_list) { INIT_COMPLETION(tspi->xfer_completion); - ret = tegra_slink_start_transfer_one(spi, xfer, - is_first_msg, single_xfer); + ret = tegra_slink_start_transfer_one(spi, xfer, is_first_msg); if (ret < 0) { dev_err(tspi->dev, "spi can not start transfer, err %d\n", ret); -- cgit v1.2.3 From 56ec1978ff07380bbdc0a942c8779ec9fd9e02ee Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 7 Oct 2013 19:33:53 +0100 Subject: spi: Provide trace points for message processing Provide tracepoints for the lifecycle of a message from submission to completion and for the active time for masters to help with performance analysis of SPI I/O. Signed-off-by: Mark Brown --- drivers/spi/spi.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9e039c60c068..8bef0c9a7233 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -39,6 +39,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include + static void spidev_release(struct device *dev) { struct spi_device *spi = to_spi_device(dev); @@ -557,6 +560,7 @@ static void spi_pump_messages(struct kthread_work *work) pm_runtime_mark_last_busy(master->dev.parent); pm_runtime_put_autosuspend(master->dev.parent); } + trace_spi_master_idle(master); return; } @@ -585,6 +589,9 @@ static void spi_pump_messages(struct kthread_work *work) } } + if (!was_busy) + trace_spi_master_busy(master); + if (!was_busy && master->prepare_transfer_hardware) { ret = master->prepare_transfer_hardware(master); if (ret) { @@ -597,6 +604,8 @@ static void spi_pump_messages(struct kthread_work *work) } } + trace_spi_message_start(master->cur_msg); + ret = master->transfer_one_message(master, master->cur_msg); if (ret) { dev_err(&master->dev, @@ -689,6 +698,8 @@ void spi_finalize_current_message(struct spi_master *master) mesg->state = NULL; if (mesg->complete) mesg->complete(mesg->context); + + trace_spi_message_done(mesg); } EXPORT_SYMBOL_GPL(spi_finalize_current_message); @@ -1421,6 +1432,10 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) struct spi_master *master = spi->master; struct spi_transfer *xfer; + message->spi = spi; + + trace_spi_message_submit(message); + if (list_empty(&message->transfers)) return -EINVAL; if (!message->complete) @@ -1520,7 +1535,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) } } - message->spi = spi; message->status = -EINPROGRESS; return master->transfer(spi, message); } -- cgit v1.2.3 From ebd805cc14bec607e74795b7933570f240508cb4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 27 Sep 2013 19:56:31 +0100 Subject: spi/s3c64xx: Factor transfer start out of enable/disable_cs() The hardware level /CS handling is tied to the start of the data path so is rolled into the same function as we use to manipulate GPIO /CS. In order to support factoring out the /CS handling into the core separate the two and explicitly start transfers separately to the /CS handling. Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index e6312322f66a..8e732a1b8a9b 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -927,6 +927,9 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, /* Start the signals */ writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); + /* Start the signals */ + writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); + spin_unlock_irqrestore(&sdd->lock, flags); status = wait_for_xfer(sdd, xfer, use_dma); -- cgit v1.2.3 From aa7da564cab718d04c77e3a3c73926473e7a94f7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Oct 2013 18:27:38 -0700 Subject: spi: convert bus code to use dev_groups The dev_attrs field of struct bus_type is going away soon, dev_groups should be used instead. This converts the spi bus code to use the correct field. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Mark Brown --- drivers/spi/spi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 1cd491f79422..7f8057f3433a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -58,11 +58,13 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf) return sprintf(buf, "%s%s\n", SPI_MODULE_PREFIX, spi->modalias); } +static DEVICE_ATTR_RO(modalias); -static struct device_attribute spi_dev_attrs[] = { - __ATTR_RO(modalias), - __ATTR_NULL, +static struct attribute *spi_dev_attrs[] = { + &dev_attr_modalias.attr, + NULL, }; +ATTRIBUTE_GROUPS(spi_dev); /* modalias support makes "modprobe $MODALIAS" new-style hotplug work, * and the sysfs version makes coldplug work too. @@ -229,7 +231,7 @@ static const struct dev_pm_ops spi_pm = { struct bus_type spi_bus_type = { .name = "spi", - .dev_attrs = spi_dev_attrs, + .dev_groups = spi_dev_groups, .match = spi_match_device, .uevent = spi_uevent, .pm = &spi_pm, -- cgit v1.2.3 From 75dab1bfbbaa54c4e8cdca0f46b4ed65492559c6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 8 Oct 2013 22:35:37 +0200 Subject: spi: spi-au1550: replace platform_driver_probe to support deferred probing Subsystems like pinctrl and gpio rightfully make use of deferred probing at core level. Now, deferred drivers won't be retried if they don't have a .probe function specified in the driver struct. Fix this driver to have that, so the devices it supports won't get lost in a deferred probe. Signed-off-by: Wolfram Sang Signed-off-by: Mark Brown --- drivers/spi/spi-au1550.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 1d00d9b397dd..313dd49b541d 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -985,6 +985,7 @@ static int au1550_spi_remove(struct platform_device *pdev) MODULE_ALIAS("platform:au1550-spi"); static struct platform_driver au1550_spi_drv = { + .probe = au1550_spi_probe, .remove = au1550_spi_remove, .driver = { .name = "au1550-spi", @@ -1004,7 +1005,7 @@ static int __init au1550_spi_init(void) printk(KERN_ERR "au1550-spi: cannot add memory" "dbdma device\n"); } - return platform_driver_probe(&au1550_spi_drv, au1550_spi_probe); + return platform_driver_register(&au1550_spi_drv); } module_init(au1550_spi_init); -- cgit v1.2.3 From 6a009e8d886be476d7e6ea978c27c9517c449d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 8 Oct 2013 20:49:59 +0200 Subject: spi: efm32: drop unused struct and fix size check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The variable efm32_spi_pdata_default origins from an earlier revision of the patch introducing the driver, its use was dropped because of review comments but I forgot to also drop the variable itself. Signed-off-by: Uwe Kleine-König Signed-off-by: Mark Brown --- drivers/spi/spi-efm32.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index 5ce61e5f9770..d4d3cc534792 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -280,10 +280,6 @@ static irqreturn_t efm32_spi_txirq(int irq, void *data) return IRQ_HANDLED; } -static const struct efm32_spi_pdata efm32_spi_pdata_default = { - .location = 1, -}; - static u32 efm32_spi_get_configured_location(struct efm32_spi_ddata *ddata) { u32 reg = efm32_spi_read32(ddata, REG_ROUTE); @@ -387,7 +383,7 @@ static int efm32_spi_probe(struct platform_device *pdev) goto err; } - if (resource_size(res) < 60) { + if (resource_size(res) < 0x60) { ret = -EINVAL; dev_err(&pdev->dev, "memory resource too small\n"); goto err; -- cgit v1.2.3 From db9371b853e7cebce93f0775215ef297b8d0bf93 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 8 Oct 2013 22:35:38 +0200 Subject: spi: spi-bfin5xx: replace platform_driver_probe to support deferred probing Subsystems like pinctrl and gpio rightfully make use of deferred probing at core level. Now, deferred drivers won't be retried if they don't have a .probe function specified in the driver struct. Fix this driver to have that, so the devices it supports won't get lost in a deferred probe. Signed-off-by: Wolfram Sang Signed-off-by: Mark Brown --- drivers/spi/spi-bfin5xx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 1e2894315bb0..5284f158d4e6 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -1464,12 +1464,13 @@ static struct platform_driver bfin_spi_driver = { .owner = THIS_MODULE, .pm = BFIN_SPI_PM_OPS, }, + .probe = bfin_spi_probe, .remove = bfin_spi_remove, }; static int __init bfin_spi_init(void) { - return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe); + return platform_driver_register(&bfin_spi_driver); } subsys_initcall(bfin_spi_init); -- cgit v1.2.3 From 93e9c900102aa2e9b10ec4758b441c8b6e53daf3 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 8 Oct 2013 22:35:39 +0200 Subject: spi: spi-omap-uwire: replace platform_driver_probe to support deferred probing Subsystems like pinctrl and gpio rightfully make use of deferred probing at core level. Now, deferred drivers won't be retried if they don't have a .probe function specified in the driver struct. Fix this driver to have that, so the devices it supports won't get lost in a deferred probe. Signed-off-by: Wolfram Sang Signed-off-by: Mark Brown --- drivers/spi/spi-omap-uwire.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c index a6a8f0961750..9313fd3b413d 100644 --- a/drivers/spi/spi-omap-uwire.c +++ b/drivers/spi/spi-omap-uwire.c @@ -557,7 +557,8 @@ static struct platform_driver uwire_driver = { .name = "omap_uwire", .owner = THIS_MODULE, }, - .remove = uwire_remove, + .probe = uwire_probe, + .remove = uwire_remove, // suspend ... unuse ck // resume ... use ck }; @@ -579,7 +580,7 @@ static int __init omap_uwire_init(void) omap_writel(val | 0x00AAA000, OMAP7XX_IO_CONF_9); } - return platform_driver_probe(&uwire_driver, uwire_probe); + return platform_driver_register(&uwire_driver); } static void __exit omap_uwire_exit(void) -- cgit v1.2.3 From 1d82d0c2682ec88a84aaae40c830bddf6ab09482 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 8 Oct 2013 22:35:41 +0200 Subject: spi: spi-txx9: replace platform_driver_probe to support deferred probing Subsystems like pinctrl and gpio rightfully make use of deferred probing at core level. Now, deferred drivers won't be retried if they don't have a .probe function specified in the driver struct. Fix this driver to have that, so the devices it supports won't get lost in a deferred probe. Signed-off-by: Wolfram Sang Signed-off-by: Mark Brown --- drivers/spi/spi-txx9.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index 7c6d15766c72..c67a1b866f4f 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -440,6 +440,7 @@ static int txx9spi_remove(struct platform_device *dev) MODULE_ALIAS("platform:spi_txx9"); static struct platform_driver txx9spi_driver = { + .probe = txx9spi_probe, .remove = txx9spi_remove, .driver = { .name = "spi_txx9", @@ -449,7 +450,7 @@ static struct platform_driver txx9spi_driver = { static int __init txx9spi_init(void) { - return platform_driver_probe(&txx9spi_driver, txx9spi_probe); + return platform_driver_register(&txx9spi_driver); } subsys_initcall(txx9spi_init); -- cgit v1.2.3 From 5db542ed85b5e88346675f672dbd2eefa52005f4 Mon Sep 17 00:00:00 2001 From: Illia Smyrnov Date: Wed, 9 Oct 2013 15:05:08 +0300 Subject: spi: omap2-mcspi: Fix FIFO support for transmit-and-receive mode This patch fixes MCSPI FIFO buffer support when transmit-and-receive (full duplex) mode is used. In this mode FIFO can be used for RX or for TX or for both directions. If FIFO used for both directions the buffer is split into two 32-byte buffers - one for each direction. Also for full duplex mode both AEL and AFL need to be set in CHCONF0 register. Signed-off-by: Illia Smyrnov Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index ed4af4708d9a..32dca0c55358 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -276,7 +276,7 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi, struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi *mcspi; unsigned int wcnt; - int fifo_depth, bytes_per_word; + int max_fifo_depth, fifo_depth, bytes_per_word; u32 chconf, xferlevel; mcspi = spi_master_get_devdata(master); @@ -287,7 +287,12 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi, if (t->len % bytes_per_word != 0) goto disable_fifo; - fifo_depth = gcd(t->len, OMAP2_MCSPI_MAX_FIFODEPTH); + if (t->rx_buf != NULL && t->tx_buf != NULL) + max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH / 2; + else + max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH; + + fifo_depth = gcd(t->len, max_fifo_depth); if (fifo_depth < 2 || fifo_depth % bytes_per_word != 0) goto disable_fifo; @@ -299,7 +304,8 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi, if (t->rx_buf != NULL) { chconf |= OMAP2_MCSPI_CHCONF_FFER; xferlevel |= (fifo_depth - 1) << 8; - } else { + } + if (t->tx_buf != NULL) { chconf |= OMAP2_MCSPI_CHCONF_FFET; xferlevel |= fifo_depth - 1; } -- cgit v1.2.3 From cb52c673f8adc4a1cba7b645ff5375b57dae21fa Mon Sep 17 00:00:00 2001 From: Hiep Cao Minh Date: Thu, 10 Oct 2013 17:14:03 +0900 Subject: spi/rspi: Fix 8bit data access, clear buffer The R8A7790 has QSPI module which added into RSPI together. The transmit or receive data should be read from or written to with the longword-, word-, or byte-access width. Modify word- access to byte-access. In 16-bit data register, QSPI send or receive datas access from high 8-bit while RSPI send or receive datas access from low 8-bit on single mode. Modify to reset transmit-receive buffer data and reading dummy after data are transmited. RSPI has a TXMD bit on control register(SPCR) to set transmit-only mode when transmit data or Full-duplex synchronous mode when receive data. In QSPI the TXMD bit is not supported, so after transmit data, dummy should be read and before transmit or receive data the bufer register should be reset. This driver is the implementation of send and receive pio only, DMA is not supported at this time. Without this patch, it will occur error when transmit and receive Signed-off-by: Hiep Cao Minh Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 4c8dbac11b42..58449ad4ad0d 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -198,6 +198,11 @@ static u16 rspi_read16(struct rspi_data *rspi, u16 offset) /* optional functions */ struct spi_ops { int (*set_config_register)(struct rspi_data *rspi, int access_size); + int (*send_pio)(struct rspi_data *rspi, struct spi_message *mesg, + struct spi_transfer *t); + int (*receive_pio)(struct rspi_data *rspi, struct spi_message *mesg, + struct spi_transfer *t); + }; /* @@ -349,6 +354,43 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, return 0; } +static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, + struct spi_transfer *t) +{ + int remain = t->len; + u8 *data; + + rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR); + rspi_write8(rspi, 0x00, QSPI_SPBFCR); + + data = (u8 *)t->tx_buf; + while (remain > 0) { + + if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) { + dev_err(&rspi->master->dev, + "%s: tx empty timeout\n", __func__); + return -ETIMEDOUT; + } + rspi_write8(rspi, *data++, RSPI_SPDR); + + if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) { + dev_err(&rspi->master->dev, + "%s: receive timeout\n", __func__); + return -ETIMEDOUT; + } + rspi_read8(rspi, RSPI_SPDR); + + remain--; + } + + /* Waiting for the last transmition */ + rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); + + return 0; +} + +#define send_pio(spi, mesg, t) spi->ops->send_pio(spi, mesg, t) + static void rspi_dma_complete(void *arg) { struct rspi_data *rspi = arg; @@ -514,6 +556,51 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, return 0; } +static void qspi_receive_init(struct rspi_data *rspi) +{ + unsigned char spsr; + + spsr = rspi_read8(rspi, RSPI_SPSR); + if (spsr & SPSR_SPRF) + rspi_read8(rspi, RSPI_SPDR); /* dummy read */ + rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); + rspi_write8(rspi, 0x00, QSPI_SPBFCR); +} + +static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, + struct spi_transfer *t) +{ + int remain = t->len; + u8 *data; + + qspi_receive_init(rspi); + + data = (u8 *)t->rx_buf; + while (remain > 0) { + + if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) { + dev_err(&rspi->master->dev, + "%s: tx empty timeout\n", __func__); + return -ETIMEDOUT; + } + /* dummy write for generate clock */ + rspi_write8(rspi, 0x00, RSPI_SPDR); + + if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) { + dev_err(&rspi->master->dev, + "%s: receive timeout\n", __func__); + return -ETIMEDOUT; + } + /* SPDR allows 8, 16 or 32-bit access */ + *data++ = rspi_read8(rspi, RSPI_SPDR); + remain--; + } + + return 0; +} + +#define receive_pio(spi, mesg, t) spi->ops->receive_pio(spi, mesg, t) + static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) { struct scatterlist sg, sg_dummy; @@ -653,7 +740,7 @@ static void rspi_work(struct work_struct *work) if (rspi_is_dma(rspi, t)) ret = rspi_send_dma(rspi, t); else - ret = rspi_send_pio(rspi, mesg, t); + ret = send_pio(rspi, mesg, t); if (ret < 0) goto error; } @@ -661,7 +748,7 @@ static void rspi_work(struct work_struct *work) if (rspi_is_dma(rspi, t)) ret = rspi_receive_dma(rspi, t); else - ret = rspi_receive_pio(rspi, mesg, t); + ret = receive_pio(rspi, mesg, t); if (ret < 0) goto error; } @@ -918,10 +1005,14 @@ error1: static struct spi_ops rspi_ops = { .set_config_register = rspi_set_config_register, + .send_pio = rspi_send_pio, + .receive_pio = rspi_receive_pio, }; static struct spi_ops qspi_ops = { .set_config_register = qspi_set_config_register, + .send_pio = qspi_send_pio, + .receive_pio = qspi_receive_pio, }; static struct platform_device_id spi_driver_ids[] = { -- cgit v1.2.3 From cf9eb39c6f7b42fdf9aa6f1af28780b2522a847a Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 10 Oct 2013 17:19:17 +0300 Subject: spi: Fix modalias for ACPI enumerated SPI devices There is a minor fault about ACPI enumerated SPI devices with their modalias attribute. Now modalias is set by device instance not by hardware ID. For example "spi:INTABCD:00", "spi:INTABCD:01" etc. This means each device instance gets different modalias which does match with generated modules.alias. Currently this is not problem as matching can happen also with "acpi:INTABCD" modalias. Fix this by using ACPI hardware ID. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9e039c60c068..e57e9acd75cb 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1025,7 +1025,7 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level, return AE_OK; } - strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias)); + strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias)); if (spi_add_device(spi)) { dev_err(&master->dev, "failed to add SPI device %s from ACPI\n", dev_name(&adev->dev)); -- cgit v1.2.3 From 2841a5fc375e9c573d10b82db30fa8a4cc25301c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 5 Oct 2013 00:23:12 +0100 Subject: spi: Provide per-message prepare and unprepare operations Many SPI drivers perform setup and tear down on every message, usually doing things like DMA mapping the message. Provide hooks for them to use to provide such operations. This is of limited value for drivers that implement transfer_one_message() but will be of much greater utility with future factoring out of standard implementations of that function. Signed-off-by: Mark Brown --- drivers/spi/spi.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8bef0c9a7233..8a30c6b66a64 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -606,6 +606,18 @@ static void spi_pump_messages(struct kthread_work *work) trace_spi_message_start(master->cur_msg); + if (master->prepare_message) { + ret = master->prepare_message(master, master->cur_msg); + if (ret) { + dev_err(&master->dev, + "failed to prepare message: %d\n", ret); + master->cur_msg->status = ret; + spi_finalize_current_message(master); + return; + } + master->cur_msg_prepared = true; + } + ret = master->transfer_one_message(master, master->cur_msg); if (ret) { dev_err(&master->dev, @@ -687,6 +699,7 @@ void spi_finalize_current_message(struct spi_master *master) { struct spi_message *mesg; unsigned long flags; + int ret; spin_lock_irqsave(&master->queue_lock, flags); mesg = master->cur_msg; @@ -695,6 +708,15 @@ void spi_finalize_current_message(struct spi_master *master) queue_kthread_work(&master->kworker, &master->pump_messages); spin_unlock_irqrestore(&master->queue_lock, flags); + if (master->cur_msg_prepared && master->unprepare_message) { + ret = master->unprepare_message(master, mesg); + if (ret) { + dev_err(&master->dev, + "failed to unprepare message: %d\n", ret); + } + } + master->cur_msg_prepared = false; + mesg->state = NULL; if (mesg->complete) mesg->complete(mesg->context); -- cgit v1.2.3 From 6bb9c0e34185717f5b0df4ad468476f64f0d73fb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 5 Oct 2013 00:42:58 +0100 Subject: spi/s3c64xx: Use prepare_message() and unprepare_message() This is of very little value in itself but will be useful once the loop iterating over the transfers is also factored out into the core. Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 512b8893893b..27b744be982e 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -862,16 +862,12 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, } } -static int s3c64xx_spi_transfer_one_message(struct spi_master *master, - struct spi_message *msg) +static int s3c64xx_spi_prepare_message(struct spi_master *master, + struct spi_message *msg) { struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); struct spi_device *spi = msg->spi; struct s3c64xx_spi_csinfo *cs = spi->controller_data; - struct spi_transfer *xfer; - int status = 0, cs_toggle = 0; - u32 speed; - u8 bpw; /* If Master's(controller) state differs from that needed by Slave */ if (sdd->cur_speed != spi->max_speed_hz @@ -887,13 +883,25 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, if (s3c64xx_spi_map_mssg(sdd, msg)) { dev_err(&spi->dev, "Xfer: Unable to map message buffers!\n"); - status = -ENOMEM; - goto out; + return -ENOMEM; } /* Configure feedback delay */ writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK); + return 0; +} + +static int s3c64xx_spi_transfer_one_message(struct spi_master *master, + struct spi_message *msg) +{ + struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct spi_device *spi = msg->spi; + struct spi_transfer *xfer; + int status = 0, cs_toggle = 0; + u32 speed; + u8 bpw; + list_for_each_entry(xfer, &msg->transfers, transfer_list) { unsigned long flags; @@ -991,6 +999,16 @@ out: return 0; } +static int s3c64xx_spi_unprepare_message(struct spi_master *master, + struct spi_message *msg) +{ + struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + + s3c64xx_spi_unmap_mssg(sdd, msg); + + return 0; +} + static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( struct spi_device *spi) { @@ -1359,7 +1377,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) master->setup = s3c64xx_spi_setup; master->cleanup = s3c64xx_spi_cleanup; master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; + master->prepare_message = s3c64xx_spi_prepare_message; master->transfer_one_message = s3c64xx_spi_transfer_one_message; + master->unprepare_message = s3c64xx_spi_unprepare_message; master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; master->num_chipselect = sci->num_cs; master->dma_alignment = 8; -- cgit v1.2.3 From b158935f70b9c156903338053216dd0adf7ce31c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 5 Oct 2013 11:50:40 +0100 Subject: spi: Provide common spi_message processing loop The loops which SPI controller drivers use to process the list of transfers in a spi_message are typically very similar and have some error prone areas such as the handling of /CS. Help simplify drivers by factoring this code out into the core - if drivers provide a transfer_one() function instead of a transfer_one_message() function the core will handle processing at the message level. /CS can be controlled by either setting cs_gpio or providing a set_cs function. If this is not possible for hardware reasons then both can be omitted and the driver should continue to implement manual /CS handling. This is a first step in refactoring and it is expected that there will be further enhancements, for example factoring out of the mapping of transfers for DMA and the initiation and completion of interrupt driven transfers. Signed-off-by: Mark Brown --- drivers/spi/spi.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8a30c6b66a64..85c18d8a86b3 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -526,6 +526,95 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) /*-------------------------------------------------------------------------*/ +static void spi_set_cs(struct spi_device *spi, bool enable) +{ + if (spi->mode & SPI_CS_HIGH) + enable = !enable; + + if (spi->cs_gpio >= 0) + gpio_set_value(spi->cs_gpio, !enable); + else if (spi->master->set_cs) + spi->master->set_cs(spi, !enable); +} + +/* + * spi_transfer_one_message - Default implementation of transfer_one_message() + * + * This is a standard implementation of transfer_one_message() for + * drivers which impelment a transfer_one() operation. It provides + * standard handling of delays and chip select management. + */ +static int spi_transfer_one_message(struct spi_master *master, + struct spi_message *msg) +{ + struct spi_transfer *xfer; + bool cur_cs = true; + bool keep_cs = false; + int ret = 0; + + spi_set_cs(msg->spi, true); + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + trace_spi_transfer_start(msg, xfer); + + INIT_COMPLETION(master->xfer_completion); + + ret = master->transfer_one(master, msg->spi, xfer); + if (ret < 0) { + dev_err(&msg->spi->dev, + "SPI transfer failed: %d\n", ret); + goto out; + } + + if (ret > 0) + wait_for_completion(&master->xfer_completion); + + trace_spi_transfer_stop(msg, xfer); + + if (msg->status != -EINPROGRESS) + goto out; + + if (xfer->delay_usecs) + udelay(xfer->delay_usecs); + + if (xfer->cs_change) { + if (list_is_last(&xfer->transfer_list, + &msg->transfers)) { + keep_cs = true; + } else { + cur_cs = !cur_cs; + spi_set_cs(msg->spi, cur_cs); + } + } + + msg->actual_length += xfer->len; + } + +out: + if (ret != 0 || !keep_cs) + spi_set_cs(msg->spi, false); + + if (msg->status == -EINPROGRESS) + msg->status = ret; + + spi_finalize_current_message(master); + + return ret; +} + +/** + * spi_finalize_current_transfer - report completion of a transfer + * + * Called by SPI drivers using the core transfer_one_message() + * implementation to notify it that the current interrupt driven + * transfer has finised and the next one may be scheduled. + */ +void spi_finalize_current_transfer(struct spi_master *master) +{ + complete(&master->xfer_completion); +} +EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); + /** * spi_pump_messages - kthread work function which processes spi message queue * @work: pointer to kthread work struct contained in the master struct @@ -836,6 +925,8 @@ static int spi_master_initialize_queue(struct spi_master *master) master->queued = true; master->transfer = spi_queued_transfer; + if (!master->transfer_one_message) + master->transfer_one_message = spi_transfer_one_message; /* Initialize and start queue */ ret = spi_init_queue(master); @@ -1242,6 +1333,7 @@ int spi_register_master(struct spi_master *master) spin_lock_init(&master->bus_lock_spinlock); mutex_init(&master->bus_lock_mutex); master->bus_lock_flag = 0; + init_completion(&master->xfer_completion); /* register the device, then userspace will see it. * registration fails if the bus ID is in use. -- cgit v1.2.3 From 0732a9d2a1551e3be5fd8a3ea680deb3d9e56193 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 5 Oct 2013 11:51:14 +0100 Subject: spi/s3c64xx: Use core message handling Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 152 +++++++++++++++++----------------------------- 1 file changed, 56 insertions(+), 96 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index c7b36c06ef40..25eb352d6a42 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -879,121 +879,81 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master, return 0; } -static int s3c64xx_spi_transfer_one_message(struct spi_master *master, - struct spi_message *msg) +static int s3c64xx_spi_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) { struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); - struct spi_device *spi = msg->spi; - struct spi_transfer *xfer; - int status = 0, cs_toggle = 0; + int status; u32 speed; u8 bpw; + unsigned long flags; + int use_dma; - list_for_each_entry(xfer, &msg->transfers, transfer_list) { - - unsigned long flags; - int use_dma; - - INIT_COMPLETION(sdd->xfer_completion); - - /* Only BPW and Speed may change across transfers */ - bpw = xfer->bits_per_word; - speed = xfer->speed_hz ? : spi->max_speed_hz; - - if (xfer->len % (bpw / 8)) { - dev_err(&spi->dev, - "Xfer length(%u) not a multiple of word size(%u)\n", - xfer->len, bpw / 8); - status = -EIO; - goto out; - } - - if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { - sdd->cur_bpw = bpw; - sdd->cur_speed = speed; - s3c64xx_spi_config(sdd); - } - - /* Slave Select */ - enable_cs(sdd, spi); - - /* Polling method for xfers not bigger than FIFO capacity */ - use_dma = 0; - if (!is_polling(sdd) && - (sdd->rx_dma.ch && sdd->tx_dma.ch && - (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1)))) - use_dma = 1; - - spin_lock_irqsave(&sdd->lock, flags); + INIT_COMPLETION(sdd->xfer_completion); - /* Pending only which is to be done */ - sdd->state &= ~RXBUSY; - sdd->state &= ~TXBUSY; + /* Only BPW and Speed may change across transfers */ + bpw = xfer->bits_per_word; + speed = xfer->speed_hz ? : spi->max_speed_hz; - enable_datapath(sdd, spi, xfer, use_dma); - - /* Start the signals */ - writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); + if (xfer->len % (bpw / 8)) { + dev_err(&spi->dev, + "Xfer length(%u) not a multiple of word size(%u)\n", + xfer->len, bpw / 8); + return -EIO; + } - /* Start the signals */ - writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); + if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { + sdd->cur_bpw = bpw; + sdd->cur_speed = speed; + s3c64xx_spi_config(sdd); + } - spin_unlock_irqrestore(&sdd->lock, flags); + /* Polling method for xfers not bigger than FIFO capacity */ + use_dma = 0; + if (!is_polling(sdd) && + (sdd->rx_dma.ch && sdd->tx_dma.ch && + (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1)))) + use_dma = 1; - status = wait_for_xfer(sdd, xfer, use_dma); + spin_lock_irqsave(&sdd->lock, flags); - if (status) { - dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n", - xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, - (sdd->state & RXBUSY) ? 'f' : 'p', - (sdd->state & TXBUSY) ? 'f' : 'p', - xfer->len); + /* Pending only which is to be done */ + sdd->state &= ~RXBUSY; + sdd->state &= ~TXBUSY; - if (use_dma) { - if (xfer->tx_buf != NULL - && (sdd->state & TXBUSY)) - s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma); - if (xfer->rx_buf != NULL - && (sdd->state & RXBUSY)) - s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma); - } + enable_datapath(sdd, spi, xfer, use_dma); - goto out; - } + /* Start the signals */ + writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); - flush_fifo(sdd); + /* Start the signals */ + writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); - if (xfer->delay_usecs) - udelay(xfer->delay_usecs); + spin_unlock_irqrestore(&sdd->lock, flags); - if (xfer->cs_change) { - /* Hint that the next mssg is gonna be - for the same device */ - if (list_is_last(&xfer->transfer_list, - &msg->transfers)) - cs_toggle = 1; + status = wait_for_xfer(sdd, xfer, use_dma); + + if (status) { + dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n", + xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, + (sdd->state & RXBUSY) ? 'f' : 'p', + (sdd->state & TXBUSY) ? 'f' : 'p', + xfer->len); + + if (use_dma) { + if (xfer->tx_buf != NULL + && (sdd->state & TXBUSY)) + s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma); + if (xfer->rx_buf != NULL + && (sdd->state & RXBUSY)) + s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma); } - - msg->actual_length += xfer->len; - } - -out: - if (!cs_toggle || status) { - /* Quiese the signals */ - writel(S3C64XX_SPI_SLAVE_SIG_INACT, - sdd->regs + S3C64XX_SPI_SLAVE_SEL); - disable_cs(sdd, spi); } else { - sdd->tgl_spi = spi; + flush_fifo(sdd); } - s3c64xx_spi_unmap_mssg(sdd, msg); - - msg->status = status; - - spi_finalize_current_message(master); - - return 0; + return status; } static int s3c64xx_spi_unprepare_message(struct spi_master *master, @@ -1379,7 +1339,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) master->cleanup = s3c64xx_spi_cleanup; master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; master->prepare_message = s3c64xx_spi_prepare_message; - master->transfer_one_message = s3c64xx_spi_transfer_one_message; + master->transfer_one = s3c64xx_spi_transfer_one; master->unprepare_message = s3c64xx_spi_unprepare_message; master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; master->num_chipselect = sci->num_cs; -- cgit v1.2.3 From 2c067509a1e3540613ef597c5dc6bd1f47d539cb Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 11 Oct 2013 18:29:58 +0900 Subject: spi: pl022: Use dev_info() instead of printk() Change raw printk() call to dev_info() to provide a better message to userspace so it can properly identify the device. Signed-off-by: Jingoo Han Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index c13d523f1f48..6e77c938a6ae 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2173,8 +2173,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) status = -ENOMEM; goto err_no_ioremap; } - printk(KERN_INFO "pl022: mapped registers from %pa to %p\n", - &adev->res.start, pl022->virtbase); + dev_info(&adev->dev, "mapped registers from %pa to %p\n", + &adev->res.start, pl022->virtbase); pl022->clk = devm_clk_get(&adev->dev, NULL); if (IS_ERR(pl022->clk)) { -- cgit v1.2.3 From e0045ebf3be4a7461a42b7f87c1c094ac7e4db78 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 11 Oct 2013 18:31:41 +0900 Subject: spi: dw-pci: Use dev_info() instead of printk() Change raw printk() call to dev_info() to provide a better message to userspace so it can properly identify the device. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-dw-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 6a708620816a..66fa9955ea14 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -40,7 +40,7 @@ static int spi_pci_probe(struct pci_dev *pdev, int pci_bar = 0; int ret; - printk(KERN_INFO "DW: found PCI SPI controller(ID: %04x:%04x)\n", + dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n", pdev->vendor, pdev->device); ret = pci_enable_device(pdev); -- cgit v1.2.3 From 5fe5f05e2202414a8b9015e9aedf19e08f6fe832 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 10:31:51 +0900 Subject: spi: Fix checkpatch issue Fix the following checkpatch error and warnings. ERROR: space required after that ',' (ctx:VxV) WARNING: quoted string split across lines WARNING: max() should probably be max_t(int, nb, master->num_chipselect) WARNING: sizeof *spi should be sizeof(*spi) WARNING: sizeof *master should be sizeof(*master) WARNING: sizeof x should be sizeof(x) Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7f8057f3433a..956b26c2b737 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -325,7 +325,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master) if (!spi_master_get(master)) return NULL; - spi = kzalloc(sizeof *spi, GFP_KERNEL); + spi = kzalloc(sizeof(*spi), GFP_KERNEL); if (!spi) { dev_err(dev, "cannot alloc spi_device\n"); spi_master_put(master); @@ -1093,7 +1093,7 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size) if (!dev) return NULL; - master = kzalloc(size + sizeof *master, GFP_KERNEL); + master = kzalloc(size + sizeof(*master), GFP_KERNEL); if (!master) return NULL; @@ -1118,7 +1118,7 @@ static int of_spi_register_master(struct spi_master *master) return 0; nb = of_gpio_named_count(np, "cs-gpios"); - master->num_chipselect = max(nb, (int)master->num_chipselect); + master->num_chipselect = max_t(int, nb, master->num_chipselect); /* Return error only for an incorrectly formed cs-gpios property */ if (nb == 0 || nb == -ENOENT) @@ -1398,8 +1398,7 @@ int spi_setup(struct spi_device *spi) if (spi->master->setup) status = spi->master->setup(spi); - dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s" - "%u bits/w, %u Hz max --> %d\n", + dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n", (int) (spi->mode & (SPI_CPOL | SPI_CPHA)), (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "", (spi->mode & SPI_LSB_FIRST) ? "lsb, " : "", @@ -1758,7 +1757,7 @@ int spi_bus_unlock(struct spi_master *master) EXPORT_SYMBOL_GPL(spi_bus_unlock); /* portable code must never pass more than 32 bytes */ -#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES) +#define SPI_BUFSIZ max(32, SMP_CACHE_BYTES) static u8 *buf; @@ -1807,7 +1806,7 @@ int spi_write_then_read(struct spi_device *spi, } spi_message_init(&message); - memset(x, 0, sizeof x); + memset(x, 0, sizeof(x)); if (n_tx) { x[0].len = n_tx; spi_message_add_tail(&x[0], &message); -- cgit v1.2.3 From 01b9e0418689951c6ae4ba3b221bc42f49eb6407 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 10:32:48 +0900 Subject: spi: atmel: Fix checkpatch issue Fix the following checkpatch warning. WARNING: quoted string split across lines Signed-off-by: Jingoo Han Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 6478a9713038..a828222c3e4e 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1401,8 +1401,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) asd = spi->controller_state; bits = (asd->csr >> 4) & 0xf; if (bits != xfer->bits_per_word - 8) { - dev_dbg(&spi->dev, "you can't yet change " - "bits_per_word in transfers\n"); + dev_dbg(&spi->dev, "you can't yet change bits_per_word in transfers\n"); return -ENOPROTOOPT; } } -- cgit v1.2.3 From cff93c58f7a99b3bf2fc3b343a1b6ca0546120da Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 10:33:38 +0900 Subject: spi: bitbang: Fix checkpatch issue Fix the following checkpatch warnings WARNING: sizeof *cs should be sizeof(*cs) WARNING: please, no space before tabs WARNING: space prohibited between function name and open parenthesis '(' WARNING: line over 80 characters Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 0056623dfc6b..bd222f6b677d 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -191,7 +191,7 @@ int spi_bitbang_setup(struct spi_device *spi) bitbang = spi_master_get_devdata(spi->master); if (!cs) { - cs = kzalloc(sizeof *cs, GFP_KERNEL); + cs = kzalloc(sizeof(*cs), GFP_KERNEL); if (!cs) return -ENOMEM; spi->controller_state = cs; @@ -258,7 +258,7 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) static int spi_bitbang_prepare_hardware(struct spi_master *spi) { - struct spi_bitbang *bitbang; + struct spi_bitbang *bitbang; unsigned long flags; bitbang = spi_master_get_devdata(spi); @@ -273,7 +273,7 @@ static int spi_bitbang_prepare_hardware(struct spi_master *spi) static int spi_bitbang_transfer_one(struct spi_master *master, struct spi_message *m) { - struct spi_bitbang *bitbang; + struct spi_bitbang *bitbang; unsigned nsecs; struct spi_transfer *t = NULL; unsigned cs_change; @@ -292,7 +292,7 @@ static int spi_bitbang_transfer_one(struct spi_master *master, cs_change = 1; status = 0; - list_for_each_entry (t, &m->transfers, transfer_list) { + list_for_each_entry(t, &m->transfers, transfer_list) { /* override speed or wordsize? */ if (t->speed_hz || t->bits_per_word) @@ -349,7 +349,8 @@ static int spi_bitbang_transfer_one(struct spi_master *master, if (t->delay_usecs) udelay(t->delay_usecs); - if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) { + if (cs_change && + !list_is_last(&t->transfer_list, &m->transfers)) { /* sometimes a short mid-message deselect of the chip * may be needed to terminate a mode or command */ @@ -378,7 +379,7 @@ static int spi_bitbang_transfer_one(struct spi_master *master, static int spi_bitbang_unprepare_hardware(struct spi_master *spi) { - struct spi_bitbang *bitbang; + struct spi_bitbang *bitbang; unsigned long flags; bitbang = spi_master_get_devdata(spi); -- cgit v1.2.3 From ac8ed236a9765c8b0689ff97eaca071211d9e22b Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 10:34:24 +0900 Subject: spi: butterfly: Fix checkpatch issue Fix the following checkpatch errors and warnings. ERROR: space required before the open brace '{' ERROR: space required after that close brace '}' ERROR: space required before the open parenthesis '(' ERROR: do not use C99 // comments WARNING: sizeof *pp should be sizeof(*pp) Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-butterfly.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index 5ed08e537433..75b1860cb25e 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -147,8 +147,8 @@ static void butterfly_chipselect(struct spi_device *spi, int value) /* we only needed to implement one mode here, and choose SPI_MODE_0 */ -#define spidelay(X) do{}while(0) -//#define spidelay ndelay +#define spidelay(X) do { } while (0) +/* #define spidelay ndelay */ #include "spi-bitbang-txrx.h" @@ -171,15 +171,15 @@ static struct mtd_partition partitions[] = { { /* sector 0 = 8 pages * 264 bytes/page (1 block) * sector 1 = 248 pages * 264 bytes/page */ - .name = "bookkeeping", // 66 KB + .name = "bookkeeping", /* 66 KB */ .offset = 0, .size = (8 + 248) * 264, -// .mask_flags = MTD_WRITEABLE, + /* .mask_flags = MTD_WRITEABLE, */ }, { /* sector 2 = 256 pages * 264 bytes/page * sectors 3-5 = 512 pages * 264 bytes/page */ - .name = "filesystem", // 462 KB + .name = "filesystem", /* 462 KB */ .offset = MTDPART_OFS_APPEND, .size = MTDPART_SIZ_FULL, } }; @@ -209,7 +209,7 @@ static void butterfly_attach(struct parport *p) * and no way to be selective about what it binds to. */ - master = spi_alloc_master(dev, sizeof *pp); + master = spi_alloc_master(dev, sizeof(*pp)); if (!master) { status = -ENOMEM; goto done; @@ -289,7 +289,6 @@ static void butterfly_attach(struct parport *p) pr_debug("%s: dataflash at %s\n", p->name, dev_name(&pp->dataflash->dev)); - // dev_info(_what?_, ...) pr_info("%s: AVR Butterfly\n", p->name); butterfly = pp; return; -- cgit v1.2.3 From 3fed8068fbad01b044c40c4df24bb97e853813ff Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 10:35:08 +0900 Subject: spi: orion: Fix checkpatch issue Fix the following checkpatch warnings. WARNING: quoted string split across lines WARNING: sizeof *spi should be sizeof(*spi) Signed-off-by: Jingoo Han Acked-by: Jason Cooper Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 1d1d321d90c4..c6caed3c4625 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -84,8 +84,8 @@ static int orion_spi_set_transfer_size(struct orion_spi *orion_spi, int size) orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG, ORION_SPI_IF_8_16_BIT_MODE); } else { - pr_debug("Bad bits per word value %d (only 8 or 16 are " - "allowed).\n", size); + pr_debug("Bad bits per word value %d (only 8 or 16 are allowed).\n", + size); return -EINVAL; } @@ -407,7 +407,7 @@ static int orion_spi_probe(struct platform_device *pdev) const u32 *iprop; int size; - master = spi_alloc_master(&pdev->dev, sizeof *spi); + master = spi_alloc_master(&pdev->dev, sizeof(*spi)); if (master == NULL) { dev_dbg(&pdev->dev, "master allocation failed\n"); return -ENOMEM; -- cgit v1.2.3 From a29c8ae7187aee902d37d7677255de726614e43e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 10:35:42 +0900 Subject: spi: sh-hspi: Fix checkpatch issue Fix the following checkpatch warning. WARNING: space prohibited before semicolon Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-sh-hspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index e488a90a98b8..b9e7b5e61528 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -137,7 +137,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi, rate /= 16; /* CLKCx calculation */ - rate /= (((idiv_clk & 0x1F) + 1) * 2) ; + rate /= (((idiv_clk & 0x1F) + 1) * 2); /* save best settings */ tmp = abs(target_rate - rate); -- cgit v1.2.3 From 3cb7b407ce84e5756076f64bf4341cc101955966 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 10:36:10 +0900 Subject: spi: tegra20-slink: Fix checkpatch issue Fix the following checkpatch warning. WARNING: space prohibited before semicolon Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-slink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 36d4e663db9b..d1d2bff01301 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -278,7 +278,7 @@ static unsigned tegra_slink_calculate_curr_xfer_param( { unsigned remain_len = t->len - tspi->cur_pos; unsigned max_word; - unsigned bits_per_word ; + unsigned bits_per_word; unsigned max_len; unsigned total_fifo_words; -- cgit v1.2.3 From 256fbf36d159f286011667ad84c378452d5fc1bf Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 10:36:31 +0900 Subject: spi: txx9: Fix checkpatch issue Fix the following checkpatch warnings. WARNING: space prohibited between function name and open parenthesis '(' Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-txx9.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index 7c6d15766c72..017139bdec99 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -177,7 +177,7 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m) | 0x08, TXx9_SPCR0); - list_for_each_entry (t, &m->transfers, transfer_list) { + list_for_each_entry(t, &m->transfers, transfer_list) { const void *txbuf = t->tx_buf; void *rxbuf = t->rx_buf; u32 data; @@ -308,7 +308,7 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m) m->actual_length = 0; /* check each transfer's parameters */ - list_for_each_entry (t, &m->transfers, transfer_list) { + list_for_each_entry(t, &m->transfers, transfer_list) { u32 speed_hz = t->speed_hz ? : spi->max_speed_hz; u8 bits_per_word = t->bits_per_word; -- cgit v1.2.3 From 95c63cfba777bf2154565abbdc61ea970aaa632c Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 10:36:54 +0900 Subject: spi: spidev: Fix checkpatch issue Fix the following checkpatch warnings. WARNING: Use #include instead of WARNING: braces {} are not necessary for any arm of this statement Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spidev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index c53556a1899a..d7c6e36021e8 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -37,7 +37,7 @@ #include #include -#include +#include /* @@ -206,9 +206,9 @@ spidev_write(struct file *filp, const char __user *buf, mutex_lock(&spidev->buf_lock); missing = copy_from_user(spidev->buffer, buf, count); - if (missing == 0) { + if (missing == 0) status = spidev_sync_write(spidev, count); - } else + else status = -EFAULT; mutex_unlock(&spidev->buf_lock); -- cgit v1.2.3 From 05209f457069e595ce0262a9032cbade05398571 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 12 Oct 2013 15:15:31 +0800 Subject: spi: fsl-dspi: add missing clk_disable_unprepare() in dspi_remove() clock source is prepared and enabled by clk_prepare_enable() in probe function, but no disable or unprepare in remove. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index dc3d4eb0531c..3c26fb297cf1 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -536,6 +536,7 @@ static int dspi_remove(struct platform_device *pdev) /* Disconnect from the SPI framework */ spi_bitbang_stop(&dspi->bitbang); + clk_disable_unprepare(dspi->clk); spi_master_put(dspi->bitbang.master); return 0; -- cgit v1.2.3 From ecc77773d3b5344394d0a126ab06fe51dac419b8 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 11 Oct 2013 17:21:53 +0530 Subject: spi: gpio: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/spi/spi-gpio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 68b69fec13a9..22ef6e1f9e9d 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From a1829d2b76ae70e8f15fcf60aba5b703d46d66d9 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 11 Oct 2013 13:53:59 +0300 Subject: spi: Add missing newline to dev_ prints in drivers Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-bfin-sport.c | 2 +- drivers/spi/spi-bfin5xx.c | 4 ++-- drivers/spi/spi-ep93xx.c | 4 ++-- drivers/spi/spi-fsl-cpm.c | 2 +- drivers/spi/spi-omap2-mcspi.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index 91921b5f5817..7b2cda0747d5 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -592,7 +592,7 @@ bfin_sport_spi_setup(struct spi_device *spi) */ if (chip_info->ctl_reg || chip_info->enable_dma) { ret = -EINVAL; - dev_err(&spi->dev, "don't set ctl_reg/enable_dma fields"); + dev_err(&spi->dev, "don't set ctl_reg/enable_dma fields\n"); goto error; } chip->cs_chg_udelay = chip_info->cs_chg_udelay; diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 45bdf73d6868..18b892e7455a 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -524,7 +524,7 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id) timeout = jiffies + HZ; while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF)) if (!time_before(jiffies, timeout)) { - dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF"); + dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF\n"); break; } else cpu_relax(); @@ -1052,7 +1052,7 @@ static int bfin_spi_setup(struct spi_device *spi) if (!(spi->mode & SPI_CPHA)) dev_warn(&spi->dev, "Warning: SPI CPHA not set:" " Slave Select not under software control!\n" - " See Documentation/blackfin/bfin-spi-notes.txt"); + " See Documentation/blackfin/bfin-spi-notes.txt\n"); chip->flag = (1 << spi->chip_select) << 8; } else diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d22c00a227b6..b57a341d3e1c 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -330,7 +330,7 @@ static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", chip->spi->mode, div_cpsr, div_scr, dss); - dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); + dev_dbg(&espi->pdev->dev, "setup: cr0 %#x\n", cr0); ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr); ep93xx_spi_write_u16(espi, SSPCR0, cr0); @@ -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 = %zu expected 0!", len); + dev_warn(&espi->pdev->dev, "len = %zu expected 0!\n", len); return ERR_PTR(-EINVAL); } diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c index 07971e3fe58b..58630edb8c21 100644 --- a/drivers/spi/spi-fsl-cpm.c +++ b/drivers/spi/spi-fsl-cpm.c @@ -299,7 +299,7 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) switch (mspi->subblock) { default: - dev_warn(dev, "cell-index unspecified, assuming SPI1"); + dev_warn(dev, "cell-index unspecified, assuming SPI1\n"); /* fall through */ case 0: mspi->subblock = QE_CR_SUBBLOCK_SPI1; diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index ed4af4708d9a..15d32042a7db 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -498,7 +498,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, ((u32 *)xfer->rx_buf)[elements++] = w; } else { int bytes_per_word = mcspi_bytes_per_word(word_len); - dev_err(&spi->dev, "DMA RX penultimate word empty"); + dev_err(&spi->dev, "DMA RX penultimate word empty\n"); count -= (bytes_per_word << 1); omap2_mcspi_set_enable(spi, 1); return count; @@ -516,7 +516,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, else /* word_len <= 32 */ ((u32 *)xfer->rx_buf)[elements] = w; } else { - dev_err(&spi->dev, "DMA RX last word empty"); + dev_err(&spi->dev, "DMA RX last word empty\n"); count -= mcspi_bytes_per_word(word_len); } omap2_mcspi_set_enable(spi, 1); -- cgit v1.2.3 From f6bd03a746271f298aa5bfb6e049b245757efaed Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 11 Oct 2013 13:54:00 +0300 Subject: spi: Don't break user-visible strings to multiple source lines in drivers User-visible strings are more difficult to grep from sources if they are separated to multiple source lines. This is worse than over 80 columns long line code style violation. Fix this by making those to single-line strings or by breaking them between variables. While at there, convert if (printk_ratelimit()) dev_warn() to use dev_warn_ratelimited in spi-pxa2xx.c. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 4 ++-- drivers/spi/spi-bfin5xx.c | 19 ++++++++++--------- drivers/spi/spi-dw.c | 4 ++-- drivers/spi/spi-fsl-espi.c | 4 ++-- drivers/spi/spi-mpc52xx-psc.c | 4 ++-- drivers/spi/spi-pxa2xx.c | 36 ++++++++++++++++-------------------- drivers/spi/spi-topcliff-pch.c | 13 +++++++------ 7 files changed, 41 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index d4ac60b4a56e..fb61f59661d1 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1401,8 +1401,8 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) asd = spi->controller_state; bits = (asd->csr >> 4) & 0xf; if (bits != xfer->bits_per_word - 8) { - dev_dbg(&spi->dev, "you can't yet change " - "bits_per_word in transfers\n"); + dev_dbg(&spi->dev, + "you can't yet change bits_per_word in transfers\n"); return -ENOPROTOOPT; } } diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 18b892e7455a..b70a2bd9324d 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -913,8 +913,9 @@ static void bfin_spi_pump_messages(struct work_struct *work) drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, struct spi_transfer, transfer_list); - dev_dbg(&drv_data->pdev->dev, "got a message to pump, " - "state is set to: baud %d, flag 0x%x, ctl 0x%x\n", + dev_dbg(&drv_data->pdev->dev, + "got a message to pump, state is set to: baud " + "%d, flag 0x%x, ctl 0x%x\n", drv_data->cur_chip->baud, drv_data->cur_chip->flag, drv_data->cur_chip->ctl_reg); @@ -1013,8 +1014,8 @@ static int bfin_spi_setup(struct spi_device *spi) * but let's assume (for now) they do. */ if (chip_info->ctl_reg & ~bfin_ctl_reg) { - dev_err(&spi->dev, "do not set bits in ctl_reg " - "that the SPI framework manages\n"); + dev_err(&spi->dev, + "do not set bits in ctl_reg that the SPI framework manages\n"); goto error; } chip->enable_dma = chip_info->enable_dma != 0 @@ -1050,17 +1051,17 @@ static int bfin_spi_setup(struct spi_device *spi) chip->chip_select_num = spi->chip_select; if (chip->chip_select_num < MAX_CTRL_CS) { if (!(spi->mode & SPI_CPHA)) - dev_warn(&spi->dev, "Warning: SPI CPHA not set:" - " Slave Select not under software control!\n" - " See Documentation/blackfin/bfin-spi-notes.txt\n"); + dev_warn(&spi->dev, + "Warning: SPI CPHA not set: Slave Select not under software control!\n" + "See Documentation/blackfin/bfin-spi-notes.txt\n"); chip->flag = (1 << spi->chip_select) << 8; } else chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS; if (chip->enable_dma && chip->pio_interrupt) { - dev_err(&spi->dev, "enable_dma is set, " - "do not set pio_interrupt\n"); + dev_err(&spi->dev, + "enable_dma is set, do not set pio_interrupt\n"); goto error; } /* diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 79c958e49f61..b897c4adb39d 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -870,8 +870,8 @@ void dw_spi_remove_host(struct dw_spi *dws) /* Remove the queue */ status = destroy_queue(dws); if (status != 0) - dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not " - "complete, message memory not freed\n"); + dev_err(&dws->master->dev, + "dw_spi_remove: workqueue will not complete, message memory not freed\n"); if (dws->dma_ops && dws->dma_ops->dma_exit) dws->dma_ops->dma_exit(dws); diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index b8f1103fe28e..43222d7532d1 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -289,8 +289,8 @@ static void fsl_espi_do_trans(struct spi_message *m, if ((first->bits_per_word != t->bits_per_word) || (first->speed_hz != t->speed_hz)) { espi_trans->status = -EINVAL; - dev_err(mspi->dev, "bits_per_word/speed_hz should be" - " same for the same SPI transfer\n"); + dev_err(mspi->dev, + "bits_per_word/speed_hz should be same for the same SPI transfer\n"); return; } diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index 6e925dc34396..00ba910ab302 100644 --- a/drivers/spi/spi-mpc52xx-psc.c +++ b/drivers/spi/spi-mpc52xx-psc.c @@ -383,8 +383,8 @@ static int mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, mps->irq = irq; if (pdata == NULL) { - dev_warn(dev, "probe called without platform data, no " - "cs_control function will be called\n"); + dev_warn(dev, + "probe called without platform data, no cs_control function will be called\n"); mps->cs_control = NULL; mps->sysclk = 0; master->bus_num = bus_num; diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index c1a50674c1e3..64e1682c39b1 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -573,8 +573,8 @@ static irqreturn_t ssp_int(int irq, void *dev_id) write_SSTO(0, reg); write_SSSR_CS(drv_data, drv_data->clear_sr); - dev_err(&drv_data->pdev->dev, "bad message state " - "in interrupt handler\n"); + dev_err(&drv_data->pdev->dev, + "bad message state in interrupt handler\n"); /* Never fail */ return IRQ_HANDLED; @@ -651,8 +651,8 @@ static void pump_transfers(unsigned long data) if (message->is_dma_mapped || transfer->rx_dma || transfer->tx_dma) { dev_err(&drv_data->pdev->dev, - "pump_transfers: mapped transfer length " - "of %u is greater than %d\n", + "pump_transfers: mapped transfer length of " + "%u is greater than %d\n", transfer->len, MAX_DMA_LEN); message->status = -EINVAL; giveback(drv_data); @@ -660,11 +660,10 @@ static void pump_transfers(unsigned long data) } /* warn ... we force this to PIO mode */ - if (printk_ratelimit()) - dev_warn(&message->spi->dev, "pump_transfers: " - "DMA disabled for transfer length %ld " - "greater than %d\n", - (long)drv_data->len, MAX_DMA_LEN); + dev_warn_ratelimited(&message->spi->dev, + "pump_transfers: DMA disabled for transfer length %ld " + "greater than %d\n", + (long)drv_data->len, MAX_DMA_LEN); } /* Setup the transfer state based on the type of transfer */ @@ -726,11 +725,8 @@ static void pump_transfers(unsigned long data) message->spi, bits, &dma_burst, &dma_thresh)) - if (printk_ratelimit()) - dev_warn(&message->spi->dev, - "pump_transfers: " - "DMA burst size reduced to " - "match bits_per_word\n"); + dev_warn_ratelimited(&message->spi->dev, + "pump_transfers: DMA burst size reduced to match bits_per_word\n"); } cr0 = clk_div @@ -854,8 +850,8 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip, if (gpio_is_valid(chip_info->gpio_cs)) { err = gpio_request(chip_info->gpio_cs, "SPI_CS"); if (err) { - dev_err(&spi->dev, "failed to request chip select " - "GPIO%d\n", chip_info->gpio_cs); + dev_err(&spi->dev, "failed to request chip select GPIO%d\n", + chip_info->gpio_cs); return err; } @@ -899,8 +895,8 @@ static int setup(struct spi_device *spi) if (drv_data->ssp_type == CE4100_SSP) { if (spi->chip_select > 4) { - dev_err(&spi->dev, "failed setup: " - "cs number must not be > 4.\n"); + dev_err(&spi->dev, + "failed setup: cs number must not be > 4.\n"); kfree(chip); return -EINVAL; } @@ -956,8 +952,8 @@ static int setup(struct spi_device *spi) spi->bits_per_word, &chip->dma_burst_size, &chip->dma_threshold)) { - dev_warn(&spi->dev, "in setup: DMA burst size reduced " - "to match bits_per_word\n"); + dev_warn(&spi->dev, + "in setup: DMA burst size reduced to match bits_per_word\n"); } } diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index eaeeed51bbbf..14843efaaf3a 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -506,8 +506,8 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg) goto err_out; } - dev_dbg(&pspi->dev, "%s Transfer List not empty. " - "Transfer Speed is set.\n", __func__); + dev_dbg(&pspi->dev, + "%s Transfer List not empty. Transfer Speed is set.\n", __func__); spin_lock_irqsave(&data->lock, flags); /* validate Tx/Rx buffers and Transfer length */ @@ -526,8 +526,9 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg) goto err_return_spinlock; } - dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length" - " valid\n", __func__); + dev_dbg(&pspi->dev, + "%s Tx/Rx buffer valid. Transfer length valid\n", + __func__); /* if baud rate has been specified validate the same */ if (transfer->speed_hz > PCH_MAX_BAUDRATE) @@ -1181,8 +1182,8 @@ static void pch_spi_process_messages(struct work_struct *pwork) spin_lock(&data->lock); /* check if suspend has been initiated;if yes flush queue */ if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) { - dev_dbg(&data->master->dev, "%s suspend/remove initiated," - "flushing queue\n", __func__); + dev_dbg(&data->master->dev, + "%s suspend/remove initiated, flushing queue\n", __func__); list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) { pmsg->status = -EIO; -- cgit v1.2.3 From 31407478a7b56187f9912eb6882a3c623365319f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 16 Oct 2013 13:22:35 +0100 Subject: spi/atmel: Convert to devm_ioremap_resource() This simplifies error handling. Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index ce4953f74423..118a938776bd 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1546,7 +1546,7 @@ static int atmel_spi_probe(struct platform_device *pdev) INIT_LIST_HEAD(&as->queue); as->pdev = pdev; - as->regs = ioremap(regs->start, resource_size(regs)); + as->regs = devm_ioremap_resource(&pdev->dev, regs); if (!as->regs) goto out_free_buffer; as->phybase = regs->start; @@ -1617,7 +1617,6 @@ out_free_dma: out_free_irq: free_irq(irq, master); out_unmap_regs: - iounmap(as->regs); out_free_buffer: if (!as->use_pdc) tasklet_kill(&as->tasklet); @@ -1669,7 +1668,6 @@ static int atmel_spi_remove(struct platform_device *pdev) clk_disable_unprepare(as->clk); clk_put(as->clk); free_irq(as->irq, master); - iounmap(as->regs); spi_unregister_master(master); -- cgit v1.2.3 From 63fc184cde2d771affc2e7885c05a2792bae9f86 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 5 Oct 2013 12:23:38 +0100 Subject: spi/tegra20-slink: Crude refactoring to use core message parsing This is a half done conversion with minimal code reorganisation provided for bisection purposes. A further patch will move the first transfer preparation into tegra_slink_prepare_message(). The cs_change and udelay handling is removed, these should be implemented by the framework and in any case are buggy - the two fields should not be related and the cs_change handling appears to at best only work the first time it's used in a message. Signed-off-by: Mark Brown Tested-by: Stephen Warren --- drivers/spi/spi-tegra20-slink.c | 88 +++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index d1d2bff01301..3576fcb3f79b 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -196,6 +196,7 @@ struct tegra_slink_data { u32 rx_status; u32 status_reg; bool is_packed; + bool is_first_msg; unsigned long packed_size; u32 command_reg; @@ -823,55 +824,56 @@ static int tegra_slink_setup(struct spi_device *spi) return 0; } -static int tegra_slink_transfer_one_message(struct spi_master *master, - struct spi_message *msg) +static int tegra_slink_prepare_message(struct spi_master *master, + struct spi_message *msg) { - bool is_first_msg = true; struct tegra_slink_data *tspi = spi_master_get_devdata(master); - struct spi_transfer *xfer; - struct spi_device *spi = msg->spi; - int ret; - msg->status = 0; - msg->actual_length = 0; + tspi->is_first_msg = true; - list_for_each_entry(xfer, &msg->transfers, transfer_list) { - INIT_COMPLETION(tspi->xfer_completion); - ret = tegra_slink_start_transfer_one(spi, xfer, is_first_msg); - if (ret < 0) { - dev_err(tspi->dev, - "spi can not start transfer, err %d\n", ret); - goto exit; - } - is_first_msg = false; - ret = wait_for_completion_timeout(&tspi->xfer_completion, - SLINK_DMA_TIMEOUT); - if (WARN_ON(ret == 0)) { - dev_err(tspi->dev, - "spi trasfer timeout, err %d\n", ret); - ret = -EIO; - goto exit; - } + return 0; +} - if (tspi->tx_status || tspi->rx_status) { - dev_err(tspi->dev, "Error in Transfer\n"); - ret = -EIO; - goto exit; - } - msg->actual_length += xfer->len; - if (xfer->cs_change && xfer->delay_usecs) { - tegra_slink_writel(tspi, tspi->def_command_reg, - SLINK_COMMAND); - udelay(xfer->delay_usecs); - } +static int tegra_slink_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct tegra_slink_data *tspi = spi_master_get_devdata(master); + int ret; + + INIT_COMPLETION(tspi->xfer_completion); + ret = tegra_slink_start_transfer_one(spi, xfer, tspi->is_first_msg); + if (ret < 0) { + dev_err(tspi->dev, + "spi can not start transfer, err %d\n", ret); + return ret; } - ret = 0; -exit: + tspi->is_first_msg = false; + ret = wait_for_completion_timeout(&tspi->xfer_completion, + SLINK_DMA_TIMEOUT); + if (WARN_ON(ret == 0)) { + dev_err(tspi->dev, + "spi trasfer timeout, err %d\n", ret); + return -EIO; + } + + if (tspi->tx_status) + return tspi->tx_status; + if (tspi->rx_status) + return tspi->rx_status; + + return 0; +} + +static int tegra_slink_unprepare_message(struct spi_master *master, + struct spi_message *msg) +{ + struct tegra_slink_data *tspi = spi_master_get_devdata(master); + tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND); tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2); - msg->status = ret; - spi_finalize_current_message(master); - return ret; + + return 0; } static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi) @@ -1074,7 +1076,9 @@ 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->transfer_one_message = tegra_slink_transfer_one_message; + master->prepare_message = tegra_slink_prepare_message; + master->transfer_one = tegra_slink_transfer_one; + master->unprepare_message = tegra_slink_unprepare_message; master->auto_runtime_pm = true; master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; -- cgit v1.2.3 From f178e3dec700d5f47cc9a282dd098a2a7422d6c7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 5 Oct 2013 12:30:42 +0100 Subject: spi/tegra20-slink: Move first transfer preparation to prepare_message This is more idiomatic for the factored out message processing and gives a small simplification of the code since we always set the per-transfer parameters in the same fashion. Signed-off-by: Mark Brown Tested-by: Stephen Warren --- drivers/spi/spi-tegra20-slink.c | 55 +++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 3576fcb3f79b..14292c53c030 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -196,7 +196,6 @@ struct tegra_slink_data { u32 rx_status; u32 status_reg; bool is_packed; - bool is_first_msg; unsigned long packed_size; u32 command_reg; @@ -708,7 +707,7 @@ static void tegra_slink_deinit_dma_param(struct tegra_slink_data *tspi, } static int tegra_slink_start_transfer_one(struct spi_device *spi, - struct spi_transfer *t, bool is_first_of_msg) + struct spi_transfer *t) { struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master); u32 speed; @@ -732,32 +731,12 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, tspi->curr_xfer = t; total_fifo_words = tegra_slink_calculate_curr_xfer_param(spi, tspi, t); - if (is_first_of_msg) { - tegra_slink_clear_status(tspi); + command = tspi->command_reg; + command &= ~SLINK_BIT_LENGTH(~0); + command |= SLINK_BIT_LENGTH(bits_per_word - 1); - command = tspi->def_command_reg; - command |= SLINK_BIT_LENGTH(bits_per_word - 1); - command |= SLINK_CS_SW | SLINK_CS_VALUE; - - command2 = tspi->def_command2_reg; - command2 |= SLINK_SS_EN_CS(spi->chip_select); - - command &= ~SLINK_MODES; - if (spi->mode & SPI_CPHA) - command |= SLINK_CK_SDA; - - if (spi->mode & SPI_CPOL) - command |= SLINK_IDLE_SCLK_DRIVE_HIGH; - else - command |= SLINK_IDLE_SCLK_DRIVE_LOW; - } else { - command = tspi->command_reg; - command &= ~SLINK_BIT_LENGTH(~0); - command |= SLINK_BIT_LENGTH(bits_per_word - 1); - - command2 = tspi->command2_reg; - command2 &= ~(SLINK_RXEN | SLINK_TXEN); - } + command2 = tspi->command2_reg; + command2 &= ~(SLINK_RXEN | SLINK_TXEN); tegra_slink_writel(tspi, command, SLINK_COMMAND); tspi->command_reg = command; @@ -828,8 +807,24 @@ static int tegra_slink_prepare_message(struct spi_master *master, struct spi_message *msg) { struct tegra_slink_data *tspi = spi_master_get_devdata(master); + struct spi_device *spi = msg->spi; - tspi->is_first_msg = true; + tegra_slink_clear_status(tspi); + + tspi->command_reg = tspi->def_command_reg; + tspi->command_reg |= SLINK_CS_SW | SLINK_CS_VALUE; + + tspi->command2_reg = tspi->def_command2_reg; + tspi->command2_reg |= SLINK_SS_EN_CS(spi->chip_select); + + tspi->command_reg &= ~SLINK_MODES; + if (spi->mode & SPI_CPHA) + tspi->command_reg |= SLINK_CK_SDA; + + if (spi->mode & SPI_CPOL) + tspi->command_reg |= SLINK_IDLE_SCLK_DRIVE_HIGH; + else + tspi->command_reg |= SLINK_IDLE_SCLK_DRIVE_LOW; return 0; } @@ -842,13 +837,13 @@ static int tegra_slink_transfer_one(struct spi_master *master, int ret; INIT_COMPLETION(tspi->xfer_completion); - ret = tegra_slink_start_transfer_one(spi, xfer, tspi->is_first_msg); + ret = tegra_slink_start_transfer_one(spi, xfer); if (ret < 0) { dev_err(tspi->dev, "spi can not start transfer, err %d\n", ret); return ret; } - tspi->is_first_msg = false; + ret = wait_for_completion_timeout(&tspi->xfer_completion, SLINK_DMA_TIMEOUT); if (WARN_ON(ret == 0)) { -- cgit v1.2.3 From 383382501193dc70fb92393eb585a39f9d39b378 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 17 Oct 2013 18:06:46 +0200 Subject: spi/s3c64xx: Add missing pm_runtime_set_active() call in probe() Mark device as PM runtime active during initialization to reflect actual device power/clocks state. This reduces the enable count for SPI bus controller gate clock so it can be disabled when the bus controller is not used. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index a80376dc3a10..05fab71c1c45 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1428,6 +1428,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, sdd->regs + S3C64XX_SPI_INT_EN); + pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); if (spi_register_master(master)) { -- cgit v1.2.3 From 7b8f7eef1afcb834d701f369dbd2e18b03fd7647 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 17 Oct 2013 14:45:41 +0200 Subject: spi/s3c64xx: Add missing pm_runtime_put on setup fail pm_runtime_put() wasn't called if clock rate could not be set up in s3c64xx_spi_setup() leading to invalid count of device pm_runtime usage. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 05fab71c1c45..ae07c3afe956 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1121,6 +1121,7 @@ static int s3c64xx_spi_setup(struct spi_device *spi) return 0; setup_exit: + pm_runtime_put(&sdd->pdev->dev); /* setup() returns with device de-selected */ disable_cs(sdd, spi); -- cgit v1.2.3 From 58f46e41c1925236a1c34873caa5d1247f846005 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:14:25 -0700 Subject: spi: spi-mxs: Always set LOCK_CS There are two bits which control the CS line in the CTRL0 register: LOCK_CS and IGNORE_CRC. The latter would be better named DEASSERT_CS in SPI mode. LOCK_CS keeps CS asserted though the entire transfer. This should always be set. The DMA code will always set it, explicitly on the first segment of the first transfer, and then implicitly on all the rest by never clearing the bit from the value read from the ctrl0 register. The PIO code will explicitly set it for the first transfer, leave it set for intermediate transfers, and then clear it for the final transfer. It should not clear it. The only reason to not set LOCK_CS would be to attempt an altered protocol where CS pulses between each word. Though don't get your hopes up if you want to do this, as the hardware doesn't appear to do this in any sane manner. It appears to be related to the hardware FIFO fill level. The code can be simplified by just setting LOCK_CS once and then not needing to deal with it at all in the PIO and DMA transfer functions. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index de7b1141b90f..e6172aedf859 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -79,6 +79,8 @@ static int mxs_spi_setup_transfer(struct spi_device *dev, mxs_ssp_set_clk_rate(ssp, hz); + writel(BM_SSP_CTRL0_LOCK_CS, + ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BF_SSP_CTRL1_SSP_MODE(BV_SSP_CTRL1_SSP_MODE__SPI) | BF_SSP_CTRL1_WORD_LENGTH (BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) | @@ -147,8 +149,6 @@ static inline void mxs_spi_enable(struct mxs_spi *spi) { struct mxs_ssp *ssp = &spi->ssp; - writel(BM_SSP_CTRL0_LOCK_CS, - ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); } @@ -157,8 +157,6 @@ static inline void mxs_spi_disable(struct mxs_spi *spi) { struct mxs_ssp *ssp = &spi->ssp; - writel(BM_SSP_CTRL0_LOCK_CS, - ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); } @@ -232,8 +230,6 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT; ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); - if (*first) - ctrl0 |= BM_SSP_CTRL0_LOCK_CS; if (!write) ctrl0 |= BM_SSP_CTRL0_READ; -- cgit v1.2.3 From f5bc7384dc4e9bf3bcf976ef0c1ac9704fa1ad43 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:14:32 -0700 Subject: spi: spi-mxs: Remove mxs_spi_enable and mxs_spi_disable These functions consist of nothing but one single writel call and are only called once. And the names really aren't accurate or clear, since they don't enable or disble SPI. Rather they set the bit that controls the state of CS at the end of transfer. It easier to follow the code to just set this bit with a writel() along with all the other bits being set in the same function. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index e6172aedf859..991ee01731b2 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -145,22 +145,6 @@ static void mxs_spi_set_cs(struct mxs_spi *spi, unsigned cs) writel(select, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); } -static inline void mxs_spi_enable(struct mxs_spi *spi) -{ - struct mxs_ssp *ssp = &spi->ssp; - - writel(BM_SSP_CTRL0_IGNORE_CRC, - ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); -} - -static inline void mxs_spi_disable(struct mxs_spi *spi) -{ - struct mxs_ssp *ssp = &spi->ssp; - - writel(BM_SSP_CTRL0_IGNORE_CRC, - ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); -} - static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set) { const unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT); @@ -335,13 +319,15 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, struct mxs_ssp *ssp = &spi->ssp; if (*first) - mxs_spi_enable(spi); + writel(BM_SSP_CTRL0_IGNORE_CRC, + ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); mxs_spi_set_cs(spi, cs); while (len--) { if (*last && len == 0) - mxs_spi_disable(spi); + writel(BM_SSP_CTRL0_IGNORE_CRC, + ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); if (ssp->devid == IMX23_SSP) { writel(BM_SSP_CTRL0_XFER_COUNT, -- cgit v1.2.3 From 75e73fa24882fb76e8ef89226893728ed0f78870 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:14:39 -0700 Subject: spi: spi-mxs: Always clear INGORE_CRC, to keep CS asserted INGORE_CRC, better named DEASSERT_CS, should be cleared on all tranfers except the last. So instead of only clearing it on the first transfer, we can just always clear it. It will set on the last transfer. This removes the only use of the "first" flag in the transfer functions, so that flag can be then be removed. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 991ee01731b2..e2a9cc21dff1 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -318,9 +318,8 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, { struct mxs_ssp *ssp = &spi->ssp; - if (*first) - writel(BM_SSP_CTRL0_IGNORE_CRC, - ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); + writel(BM_SSP_CTRL0_IGNORE_CRC, + ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); mxs_spi_set_cs(spi, cs); -- cgit v1.2.3 From 28cad125881cb10172895774d4c3a04e748bf6bf Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:14:50 -0700 Subject: spi: spi-mxs: Change flag arguments in txrx functions to bit flags There are three flag arguments to the PIO and DMA txrx functions. Two are passed as pointers to integers, even though they are input only and not modified, which makes no sense to do. The third is passed as an integer. The compiler must use an argument register or stack variable for each flag this way. Using bitflags in a single flag argument is more efficient and produces smaller code, since all the flags can fit in a single register. And all the flag arguments get cumbersome, especially when more are added for things like GPIO chipselects. The "first" flag is never used, so can just be deleted. The "last" flag is renamed to DEASSERT_CS, since that's really what it does. The spi_transfer cs_change flag means that CS might be de-asserted on a transfer which is not last and not de-assert on the last transfer, so it is not which transfer is the last we need to know but rather the transfers after which CS should be de-asserted. This also extends the driver to not ignore cs_change when setting the DEASSERT_CS nee "last" flag. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 55 +++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index e2a9cc21dff1..090930aa7205 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -57,6 +57,13 @@ #define SG_MAXLEN 0xff00 +/* + * Flags for txrx functions. More efficient that using an argument register for + * each one. + */ +#define TXRX_WRITE (1<<0) /* This is a write */ +#define TXRX_DEASSERT_CS (1<<1) /* De-assert CS at end of txrx */ + struct mxs_spi { struct mxs_ssp ssp; struct completion c; @@ -184,7 +191,7 @@ static irqreturn_t mxs_ssp_irq_handler(int irq, void *dev_id) static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, unsigned char *buf, int len, - int *first, int *last, int write) + unsigned int flags) { struct mxs_ssp *ssp = &spi->ssp; struct dma_async_tx_descriptor *desc = NULL; @@ -214,15 +221,19 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT; ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); - if (!write) + if (!(flags & TXRX_WRITE)) ctrl0 |= BM_SSP_CTRL0_READ; /* Queue the DMA data transfer. */ for (sg_count = 0; sg_count < sgs; sg_count++) { + /* Prepare the transfer descriptor. */ min = min(len, desc_len); - /* Prepare the transfer descriptor. */ - if ((sg_count + 1 == sgs) && *last) + /* + * De-assert CS on last segment if flag is set (i.e., no more + * transfers will follow) + */ + if ((sg_count + 1 == sgs) && (flags & TXRX_DEASSERT_CS)) ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC; if (ssp->devid == IMX23_SSP) { @@ -247,7 +258,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, sg_init_one(&dma_xfer[sg_count].sg, sg_buf, min); ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1, - write ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + (flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); len -= min; buf += min; @@ -267,7 +278,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, desc = dmaengine_prep_slave_sg(ssp->dmach, &dma_xfer[sg_count].sg, 1, - write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, + (flags & TXRX_WRITE) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { @@ -304,7 +315,7 @@ err_vmalloc: while (--sg_count >= 0) { err_mapped: dma_unmap_sg(ssp->dev, &dma_xfer[sg_count].sg, 1, - write ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + (flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); } kfree(dma_xfer); @@ -314,7 +325,7 @@ err_mapped: static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, unsigned char *buf, int len, - int *first, int *last, int write) + unsigned int flags) { struct mxs_ssp *ssp = &spi->ssp; @@ -324,7 +335,7 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, mxs_spi_set_cs(spi, cs); while (len--) { - if (*last && len == 0) + if (len == 0 && (flags & TXRX_DEASSERT_CS)) writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); @@ -337,7 +348,7 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, writel(1, ssp->base + HW_SSP_XFER_SIZE); } - if (write) + if (flags & TXRX_WRITE) writel(BM_SSP_CTRL0_READ, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); else @@ -350,13 +361,13 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 1)) return -ETIMEDOUT; - if (write) + if (flags & TXRX_WRITE) writel(*buf, ssp->base + HW_SSP_DATA(ssp)); writel(BM_SSP_CTRL0_DATA_XFER, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); - if (!write) { + if (!(flags & TXRX_WRITE)) { if (mxs_ssp_wait(spi, HW_SSP_STATUS(ssp), BM_SSP_STATUS_FIFO_EMPTY, 0)) return -ETIMEDOUT; @@ -381,13 +392,11 @@ static int mxs_spi_transfer_one(struct spi_master *master, { struct mxs_spi *spi = spi_master_get_devdata(master); struct mxs_ssp *ssp = &spi->ssp; - int first, last; struct spi_transfer *t, *tmp_t; + unsigned int flag; int status = 0; int cs; - first = last = 0; - cs = m->spi->chip_select; list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) { @@ -396,10 +405,9 @@ static int mxs_spi_transfer_one(struct spi_master *master, if (status) break; - if (&t->transfer_list == m->transfers.next) - first = 1; - if (&t->transfer_list == m->transfers.prev) - last = 1; + /* De-assert on last transfer, inverted by cs_change flag */ + flag = (&t->transfer_list == m->transfers.prev) ^ t->cs_change ? + TXRX_DEASSERT_CS : 0; if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) { dev_err(ssp->dev, "Cannot send and receive simultaneously\n"); @@ -424,11 +432,11 @@ static int mxs_spi_transfer_one(struct spi_master *master, if (t->tx_buf) status = mxs_spi_txrx_pio(spi, cs, (void *)t->tx_buf, - t->len, &first, &last, 1); + t->len, flag | TXRX_WRITE); if (t->rx_buf) status = mxs_spi_txrx_pio(spi, cs, t->rx_buf, t->len, - &first, &last, 0); + flag); } else { writel(BM_SSP_CTRL1_DMA_ENABLE, ssp->base + HW_SSP_CTRL1(ssp) + @@ -437,11 +445,11 @@ static int mxs_spi_transfer_one(struct spi_master *master, if (t->tx_buf) status = mxs_spi_txrx_dma(spi, cs, (void *)t->tx_buf, t->len, - &first, &last, 1); + flag | TXRX_WRITE); if (t->rx_buf) status = mxs_spi_txrx_dma(spi, cs, t->rx_buf, t->len, - &first, &last, 0); + flag); } if (status) { @@ -450,7 +458,6 @@ static int mxs_spi_transfer_one(struct spi_master *master, } m->actual_length += t->len; - first = last = 0; } m->status = status; -- cgit v1.2.3 From df23286e57ceefe427d7ff925193283a8fafe9f3 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:14:57 -0700 Subject: spi: spi-mxs: Fix extra CS pulses and read mode in multi-transfer messages There are two bits which control the CS line in the CTRL0 register: LOCK_CS and IGNORE_CRC. The latter would be better named DEASSERT_CS in SPI mode. Setting DEASSERT_CS causes CS to be de-asserted at the end of the transfer. It should normally be set only for the final segment of the final transfer. The DMA code explicitly sets it in this case, but because it never clears the bit from the ctrl0 register, it will remain set for all transfers in subsequent messages. This results in a CS pulse between transfers. There is a similar problem with the read mode bit never being cleared in DMA mode. This patch fixes DEASSERT_CS and READ being left on in DMA mode. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 090930aa7205..68ea5078a9cf 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -218,7 +218,8 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, INIT_COMPLETION(spi->c); ctrl0 = readl(ssp->base + HW_SSP_CTRL0); - ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT; + ctrl0 &= ~(BM_SSP_CTRL0_XFER_COUNT | BM_SSP_CTRL0_IGNORE_CRC | + BM_SSP_CTRL0_READ); ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); if (!(flags & TXRX_WRITE)) -- cgit v1.2.3 From 0b782f70b51b9e611a69b9d4533b44d66b2e3e75 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:15:04 -0700 Subject: spi: spi-mxs: Fix chip select control bits in DMA mode In DMA mode the chip select control bits would be ORed into the CTRL0 register without first clearing the bits. This means that after addressing slave 1, the CTRL0 bit to address slave 1 would be still be set when addressing slave 0, resulting in slave 1 continuing to be addressed. The message handling function would pass the CS value to the txrx function, which would re-program the bits on each transfer in the message. The selected CS does not change during a message so this is inefficient. It also means there are two different sets of code for selecting the CS, one for PIO that worked and one for DMA that didn't. Change the code to set the CS bits in the message handling function once. Now the DMA and PIO txrx functions don't need to care about CS at all. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 68ea5078a9cf..a9a273e20fd2 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -140,18 +140,6 @@ static uint32_t mxs_spi_cs_to_reg(unsigned cs) return select; } -static void mxs_spi_set_cs(struct mxs_spi *spi, unsigned cs) -{ - const uint32_t mask = - BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ; - uint32_t select; - struct mxs_ssp *ssp = &spi->ssp; - - writel(mask, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); - select = mxs_spi_cs_to_reg(cs); - writel(select, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); -} - static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set) { const unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT); @@ -189,7 +177,7 @@ static irqreturn_t mxs_ssp_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, +static int mxs_spi_txrx_dma(struct mxs_spi *spi, unsigned char *buf, int len, unsigned int flags) { @@ -217,10 +205,11 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, INIT_COMPLETION(spi->c); + /* Chip select was already programmed into CTRL0 */ ctrl0 = readl(ssp->base + HW_SSP_CTRL0); ctrl0 &= ~(BM_SSP_CTRL0_XFER_COUNT | BM_SSP_CTRL0_IGNORE_CRC | BM_SSP_CTRL0_READ); - ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); + ctrl0 |= BM_SSP_CTRL0_DATA_XFER; if (!(flags & TXRX_WRITE)) ctrl0 |= BM_SSP_CTRL0_READ; @@ -324,7 +313,7 @@ err_mapped: return ret; } -static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, +static int mxs_spi_txrx_pio(struct mxs_spi *spi, unsigned char *buf, int len, unsigned int flags) { @@ -333,8 +322,6 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); - mxs_spi_set_cs(spi, cs); - while (len--) { if (len == 0 && (flags & TXRX_DEASSERT_CS)) writel(BM_SSP_CTRL0_IGNORE_CRC, @@ -396,9 +383,12 @@ static int mxs_spi_transfer_one(struct spi_master *master, struct spi_transfer *t, *tmp_t; unsigned int flag; int status = 0; - int cs; - cs = m->spi->chip_select; + /* Program CS register bits here, it will be used for all transfers. */ + writel(BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ, + ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); + writel(mxs_spi_cs_to_reg(m->spi->chip_select), + ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) { @@ -431,11 +421,11 @@ static int mxs_spi_transfer_one(struct spi_master *master, STMP_OFFSET_REG_CLR); if (t->tx_buf) - status = mxs_spi_txrx_pio(spi, cs, + status = mxs_spi_txrx_pio(spi, (void *)t->tx_buf, t->len, flag | TXRX_WRITE); if (t->rx_buf) - status = mxs_spi_txrx_pio(spi, cs, + status = mxs_spi_txrx_pio(spi, t->rx_buf, t->len, flag); } else { @@ -444,11 +434,11 @@ static int mxs_spi_transfer_one(struct spi_master *master, STMP_OFFSET_REG_SET); if (t->tx_buf) - status = mxs_spi_txrx_dma(spi, cs, + status = mxs_spi_txrx_dma(spi, (void *)t->tx_buf, t->len, flag | TXRX_WRITE); if (t->rx_buf) - status = mxs_spi_txrx_dma(spi, cs, + status = mxs_spi_txrx_dma(spi, t->rx_buf, t->len, flag); } -- cgit v1.2.3 From 210f65fedf1d26d0a1d604fa82425018f7ad6090 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:15:11 -0700 Subject: spi: spi-mxs: Remove full duplex check, spi core already does it Because the driver sets the SPI_MASTER_HALF_DUPLEX flag, the spi core will check transfers to insure they are not full duplex. It's not necessary to check that in the spi-mxs driver as well. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index a9a273e20fd2..de7387ef25b8 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -399,12 +399,6 @@ static int mxs_spi_transfer_one(struct spi_master *master, /* De-assert on last transfer, inverted by cs_change flag */ flag = (&t->transfer_list == m->transfers.prev) ^ t->cs_change ? TXRX_DEASSERT_CS : 0; - if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) { - dev_err(ssp->dev, - "Cannot send and receive simultaneously\n"); - status = -EINVAL; - break; - } /* * Small blocks can be transfered via PIO. -- cgit v1.2.3 From 1a33073fcf11e70447b704c0228e28099e6ab39d Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:15:18 -0700 Subject: spi: spi-mxs: Remove bogus setting of ssp clk rate field The ssp struct has a clock rate field, to provide the actual value, in Hz, of the SSP output clock (the rate of SSP_SCK) after mxs_ssp_set_clk_rate() is called. It is set by mxs_ssp_set_clk_rate(), for SSP using drivers (like SPI and MMC) to *read* if they want to know the actual clock rate. The SPI driver isn't supposed to *write* to it. For some reason the spi-mxs driver decides to write to this field on init, and sets it to the value of the SSP input clock (clk_sspN, from the MXS clocking block) in kHz. It shouldn't be setting the value, and certainly shouldn't be setting it with the wrong clock in the wrong units. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index de7387ef25b8..8cb5d8b6f042 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -536,7 +536,6 @@ static int mxs_spi_probe(struct platform_device *pdev) goto out_dma_release; clk_set_rate(ssp->clk, clk_freq); - ssp->clk_rate = clk_get_rate(ssp->clk) / 1000; ret = stmp_reset_block(ssp->base); if (ret) -- cgit v1.2.3 From 9c97e3421fa0aeec131689008181f8ee1dac5e99 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:15:25 -0700 Subject: spi: spi-mxs: Fix race in setup method Despite many warnings in the SPI documentation and code, the spi-mxs driver sets shared chip registers in the ->setup method. This method can be called when transfers are in progress on other slaves controlled by the master. Setting registers or any other shared state will corrupt those transfers. So fix mxs_spi_setup() to not call mxs_spi_setup_transfer(). mxs_spi_setup_transfer() is already called for each transfer when they are actually performed in mxs_spi_transfer_one(), so the call in mxs_spi_setup() isn't necessary to setup anything. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 8cb5d8b6f042..e9cbdb6b1309 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -103,21 +103,13 @@ static int mxs_spi_setup_transfer(struct spi_device *dev, static int mxs_spi_setup(struct spi_device *dev) { - int err = 0; - if (!dev->bits_per_word) dev->bits_per_word = 8; if (dev->mode & ~(SPI_CPOL | SPI_CPHA)) return -EINVAL; - err = mxs_spi_setup_transfer(dev, NULL); - if (err) { - dev_err(&dev->dev, - "Failed to setup transfer, error = %d\n", err); - } - - return err; + return 0; } static uint32_t mxs_spi_cs_to_reg(unsigned cs) -- cgit v1.2.3 From d426eadb1ef166b472b09a223c30d3104fde2586 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:15:33 -0700 Subject: spi: spi-mxs: Remove check of spi mode bits The spi core already checks for a slave setting mode bits that we didn't list as supported when the master was registered. There is no need to do it again in the master driver. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index e9cbdb6b1309..23cc41273dd3 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -106,9 +106,6 @@ static int mxs_spi_setup(struct spi_device *dev) if (!dev->bits_per_word) dev->bits_per_word = 8; - if (dev->mode & ~(SPI_CPOL | SPI_CPHA)) - return -EINVAL; - return 0; } -- cgit v1.2.3 From aa9e0c6feb3e06463b45b0d9734a2cdbf95c4431 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:15:40 -0700 Subject: spi: spi-mxs: Clean up setup_transfer function It can't be called with a NULL transfer anymore so it can be simplified to not check for that. Fix indention of line-wrapped code to Linux standard. The transfer pointer can be const. It's not necessary to check if the spi_transfer's speed_hz is zero, as the spi core also fills it in from the spi_device. However, the spi core does not check if spi_device's speed is zero so we have to do that still. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 23cc41273dd3..9e6101a38e85 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -70,17 +70,14 @@ struct mxs_spi { }; static int mxs_spi_setup_transfer(struct spi_device *dev, - struct spi_transfer *t) + const struct spi_transfer *t) { struct mxs_spi *spi = spi_master_get_devdata(dev->master); struct mxs_ssp *ssp = &spi->ssp; - uint32_t hz = 0; + const unsigned int hz = min(dev->max_speed_hz, t->speed_hz); - hz = dev->max_speed_hz; - if (t && t->speed_hz) - hz = min(hz, t->speed_hz); if (hz == 0) { - dev_err(&dev->dev, "Cannot continue with zero clock\n"); + dev_err(&dev->dev, "SPI clock rate of zero not allowed\n"); return -EINVAL; } @@ -88,12 +85,12 @@ static int mxs_spi_setup_transfer(struct spi_device *dev, writel(BM_SSP_CTRL0_LOCK_CS, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); + writel(BF_SSP_CTRL1_SSP_MODE(BV_SSP_CTRL1_SSP_MODE__SPI) | - BF_SSP_CTRL1_WORD_LENGTH - (BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) | - ((dev->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) | - ((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0), - ssp->base + HW_SSP_CTRL1(ssp)); + BF_SSP_CTRL1_WORD_LENGTH(BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) | + ((dev->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) | + ((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0), + ssp->base + HW_SSP_CTRL1(ssp)); writel(0x0, ssp->base + HW_SSP_CMD0); writel(0x0, ssp->base + HW_SSP_CMD1); -- cgit v1.2.3 From a560943ead2cbded93c30c9b04886f3c743d7f00 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:15:47 -0700 Subject: spi: spi-mxs: Don't set clock for each xfer mxs_spi_setup_transfer() would set the SSP SCK rate every time it was called, which is before every transfer. It is uncommon for the SCK rate to change between transfers (or at all of that matter) and this causes many unnecessary reprogrammings of the clock registers. Code changed to only set the rate when it changes. This significantly speeds up short SPI messages, especially messages made up of many transfers, as the calculation of the clock divisors is rather costly. On an iMX287, using spidev with messages that consist of 511 transfers of 4 bytes each at an SCK of 48 MHz, the effective transfer rate more than doubles from about 290 KB/sec to 600 KB/sec! Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 9e6101a38e85..759de701f050 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -67,6 +67,7 @@ struct mxs_spi { struct mxs_ssp ssp; struct completion c; + unsigned int sck; /* Rate requested (vs actual) */ }; static int mxs_spi_setup_transfer(struct spi_device *dev, @@ -81,7 +82,19 @@ static int mxs_spi_setup_transfer(struct spi_device *dev, return -EINVAL; } - mxs_ssp_set_clk_rate(ssp, hz); + if (hz != spi->sck) { + mxs_ssp_set_clk_rate(ssp, hz); + /* + * Save requested rate, hz, rather than the actual rate, + * ssp->clk_rate. Otherwise we would set the rate every trasfer + * when the actual rate is not quite the same as requested rate. + */ + spi->sck = hz; + /* + * Perhaps we should return an error if the actual clock is + * nowhere close to what was requested? + */ + } writel(BM_SSP_CTRL0_LOCK_CS, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); -- cgit v1.2.3 From 42e182f86222dee2679c19fb1ab5006354a3be62 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 1 Oct 2013 13:15:54 -0700 Subject: spi: spi-mxs: Use u32 instead of uint32_t It's consistent with all the other spi drivers that way. Signed-off-by: Trent Piepho Cc: Marek Vasut Cc: Fabio Estevam Cc: Shawn Guo Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 759de701f050..2a819f7b0241 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -119,9 +119,9 @@ static int mxs_spi_setup(struct spi_device *dev) return 0; } -static uint32_t mxs_spi_cs_to_reg(unsigned cs) +static u32 mxs_spi_cs_to_reg(unsigned cs) { - uint32_t select = 0; + u32 select = 0; /* * i.MX28 Datasheet: 17.10.1: HW_SSP_CTRL0 @@ -143,7 +143,7 @@ static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set) { const unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT); struct mxs_ssp *ssp = &spi->ssp; - uint32_t reg; + u32 reg; do { reg = readl_relaxed(ssp->base + offset); @@ -187,11 +187,11 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, const int sgs = DIV_ROUND_UP(len, desc_len); int sg_count; int min, ret; - uint32_t ctrl0; + u32 ctrl0; struct page *vm_page; void *sg_buf; struct { - uint32_t pio[4]; + u32 pio[4]; struct scatterlist sg; } *dma_xfer; -- cgit v1.2.3 From 347de6bab4bd0166115a5c90491a05bf9df508ee Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 21 Oct 2013 15:42:49 +0200 Subject: spi/s3c64xx: Do not ignore return value of spi_master_resume/suspend During PM resume and suspend do not ignore the return value of spi_master_suspend() or spi_master_resume(). Instead pass it further. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 8e732a1b8a9b..435406b48fda 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1477,7 +1477,9 @@ static int s3c64xx_spi_suspend(struct device *dev) struct spi_master *master = dev_get_drvdata(dev); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); - spi_master_suspend(master); + int ret = spi_master_suspend(master); + if (ret) + return ret; /* Disable the clock */ clk_disable_unprepare(sdd->src_clk); @@ -1503,9 +1505,7 @@ static int s3c64xx_spi_resume(struct device *dev) s3c64xx_spi_hwinit(sdd, sdd->port_id); - spi_master_resume(master); - - return 0; + return spi_master_resume(master); } #endif /* CONFIG_PM_SLEEP */ -- cgit v1.2.3 From 9d7fd21acb2094d38d8560b0b3c91fa31efa6a71 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 21 Oct 2013 15:42:50 +0200 Subject: spi/s3c64xx: Fix doubled clock disable on suspend Fix doubled clock disable and unprepare during PM suspend which triggered the warnings: WARNING: at drivers/clk/clk.c:800 clk_disable+0x18/0x24() Modules linked in: CPU: 0 PID: 1745 Comm: sh Not tainted 3.10.14-01211-ge2549bb-dirty #62 [] (unwind_backtrace+0x0/0x138) from [] (show_stack+0x10/0x14) [] (show_stack+0x10/0x14) from [] (warn_slowpath_common+0x4c/0x68) [] (warn_slowpath_common+0x4c/0x68) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (clk_disable+0x18/0x24) [] (clk_disable+0x18/0x24) from [] (s3c64xx_spi_suspend+0x28/0x54) [] (s3c64xx_spi_suspend+0x28/0x54) from [] (platform_pm_suspend+0x2c/0x5c) [] (platform_pm_suspend+0x2c/0x5c) from [] (dpm_run_callback+0x44/0x7c) [] (dpm_run_callback+0x44/0x7c) from [] (__device_suspend+0x108/0x300) [] (__device_suspend+0x108/0x300) from [] (dpm_suspend+0x54/0x208) [] (dpm_suspend+0x54/0x208) from [] (suspend_devices_and_enter+0x98/0x458) [] (suspend_devices_and_enter+0x98/0x458) from [] (pm_suspend+0x1c4/0x25c) [] (pm_suspend+0x1c4/0x25c) from [] (state_store+0x6c/0xbc) [] (state_store+0x6c/0xbc) from [] (kobj_attr_store+0x14/0x20) [] (kobj_attr_store+0x14/0x20) from [] (sysfs_write_file+0xfc/0x164) [] (sysfs_write_file+0xfc/0x164) from [] (vfs_write+0xbc/0x1bc) [] (vfs_write+0xbc/0x1bc) from [] (SyS_write+0x40/0x68) [] (SyS_write+0x40/0x68) from [] (ret_fast_syscall+0x0/0x3c) The clocks may be already disabled before suspending. Check PM runtime suspend status and disable clocks only if device is not suspended. During resume do not enable the clocks if device is runtime suspended. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 435406b48fda..1dbdcc7b9ea7 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1481,9 +1481,10 @@ static int s3c64xx_spi_suspend(struct device *dev) if (ret) return ret; - /* Disable the clock */ - clk_disable_unprepare(sdd->src_clk); - clk_disable_unprepare(sdd->clk); + if (!pm_runtime_suspended(dev)) { + clk_disable_unprepare(sdd->clk); + clk_disable_unprepare(sdd->src_clk); + } sdd->cur_speed = 0; /* Output Clock is stopped */ @@ -1499,9 +1500,10 @@ static int s3c64xx_spi_resume(struct device *dev) if (sci->cfg_gpio) sci->cfg_gpio(); - /* Enable the clock */ - clk_prepare_enable(sdd->src_clk); - clk_prepare_enable(sdd->clk); + if (!pm_runtime_suspended(dev)) { + clk_prepare_enable(sdd->src_clk); + clk_prepare_enable(sdd->clk); + } s3c64xx_spi_hwinit(sdd, sdd->port_id); -- cgit v1.2.3 From 9e556dcc55774c9a1032f32baa0e5cfafede8b70 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 23 Oct 2013 16:31:50 +0800 Subject: spi: spi-imx: only enable the clocks when we start to transfer a message Current code keeps the clocks enabled all the time, it wastes the power when there is no operaiton on the spi controller. In order to save the power, this patch adds the two hooks: spi_imx_prepare_message: enable the clocks for this message spi_imx_unprepare_message: disable the clocks. This patch also disables the clocks in the end of the probe. Signed-off-by: Huang Shijie Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 15323d8bd9cf..cc9defe7a7f2 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -749,6 +749,35 @@ static void spi_imx_cleanup(struct spi_device *spi) { } +static int +spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg) +{ + struct spi_imx_data *spi_imx = spi_master_get_devdata(master); + int ret; + + ret = clk_enable(spi_imx->clk_per); + if (ret) + return ret; + + ret = clk_enable(spi_imx->clk_ipg); + if (ret) { + clk_disable(spi_imx->clk_per); + return ret; + } + + return 0; +} + +static int +spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg) +{ + struct spi_imx_data *spi_imx = spi_master_get_devdata(master); + + clk_disable(spi_imx->clk_ipg); + clk_disable(spi_imx->clk_per); + return 0; +} + static int spi_imx_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -810,6 +839,8 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx->bitbang.txrx_bufs = spi_imx_transfer; spi_imx->bitbang.master->setup = spi_imx_setup; spi_imx->bitbang.master->cleanup = spi_imx_cleanup; + spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message; + spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; init_completion(&spi_imx->xfer_done); @@ -872,6 +903,8 @@ static int spi_imx_probe(struct platform_device *pdev) dev_info(&pdev->dev, "probed\n"); + clk_disable(spi_imx->clk_ipg); + clk_disable(spi_imx->clk_per); return ret; out_clk_put: -- cgit v1.2.3 From 543c954d6807ad0682c37846b7b9c423cd941415 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 21 Oct 2013 11:12:02 +0800 Subject: spi: atmel: fix return value check in atmel_spi_probe() In case of error, the function devm_ioremap_resource() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Signed-off-by: Wei Yongjun Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 118a938776bd..273db0beb2b8 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1547,8 +1547,10 @@ static int atmel_spi_probe(struct platform_device *pdev) as->pdev = pdev; as->regs = devm_ioremap_resource(&pdev->dev, regs); - if (!as->regs) + if (IS_ERR(as->regs)) { + ret = PTR_ERR(as->regs); goto out_free_buffer; + } as->phybase = regs->start; as->irq = irq; as->clk = clk; -- cgit v1.2.3 From e5f7825cda366809153701e8bb89123bd973be00 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 24 Oct 2013 21:53:29 -0700 Subject: spi/hspi: add device tree support Support for loading the Renesas HSPI driver via devicetree. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- drivers/spi/spi-sh-hspi.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index b9e7b5e61528..8a147d92f9eb 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -303,6 +303,7 @@ static int hspi_probe(struct platform_device *pdev) master->setup = hspi_setup; master->cleanup = hspi_cleanup; master->mode_bits = SPI_CPOL | SPI_CPHA; + master->dev.of_node = pdev->dev.of_node; master->auto_runtime_pm = true; master->transfer_one_message = hspi_transfer_one_message; ret = spi_register_master(master); @@ -333,12 +334,19 @@ static int hspi_remove(struct platform_device *pdev) return 0; } +static struct of_device_id hspi_of_match[] = { + { .compatible = "renesas,hspi", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, hspi_of_match); + static struct platform_driver hspi_driver = { .probe = hspi_probe, .remove = hspi_remove, .driver = { .name = "sh-hspi", .owner = THIS_MODULE, + .of_match_table = hspi_of_match, }, }; module_platform_driver(hspi_driver); -- cgit v1.2.3