diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-12 15:01:39 +0900 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-12 15:01:39 +0900 |
commit | f095ca6b31cfd20e6e7e0338ed8548d8a4374287 (patch) | |
tree | 1305b11e76affa8e9738b0e236ac2881d7057ce2 | |
parent | c6d65bf246fbba6e9042a35aba050d2a92f39505 (diff) | |
parent | 82f85cf98f0eb60093e8b3d606711c2d49538478 (diff) | |
download | op-kernel-dev-f095ca6b31cfd20e6e7e0338ed8548d8a4374287.zip op-kernel-dev-f095ca6b31cfd20e6e7e0338ed8548d8a4374287.tar.gz |
Merge tag 'spi-v3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"As well as the usual driver updates and cleanups there's a few
improvements to the core here:
- The start of some improvements to factor out more of the SPI
message loop into the core. Right now this is just simplifying the
code a bit but hopefully next time around we'll also have managed
to roll out some noticable performance improvements which drivers
can take advantage of.
- Support for loading modules for ACPI enumerated SPI devices.
- Managed registration for SPI controllers.
- Helper for another common I/O pattern"
* tag 'spi-v3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (116 commits)
spi/hspi: add device tree support
spi: atmel: fix return value check in atmel_spi_probe()
spi: spi-imx: only enable the clocks when we start to transfer a message
spi/s3c64xx: Fix doubled clock disable on suspend
spi/s3c64xx: Do not ignore return value of spi_master_resume/suspend
spi: spi-mxs: Use u32 instead of uint32_t
spi: spi-mxs: Don't set clock for each xfer
spi: spi-mxs: Clean up setup_transfer function
spi: spi-mxs: Remove check of spi mode bits
spi: spi-mxs: Fix race in setup method
spi: spi-mxs: Remove bogus setting of ssp clk rate field
spi: spi-mxs: Remove full duplex check, spi core already does it
spi: spi-mxs: Fix chip select control bits in DMA mode
spi: spi-mxs: Fix extra CS pulses and read mode in multi-transfer messages
spi: spi-mxs: Change flag arguments in txrx functions to bit flags
spi: spi-mxs: Always clear INGORE_CRC, to keep CS asserted
spi: spi-mxs: Remove mxs_spi_enable and mxs_spi_disable
spi: spi-mxs: Always set LOCK_CS
spi/s3c64xx: Add missing pm_runtime_put on setup fail
spi/s3c64xx: Add missing pm_runtime_set_active() call in probe()
...
62 files changed, 1267 insertions, 701 deletions
diff --git a/Documentation/devicetree/bindings/spi/sh-hspi.txt b/Documentation/devicetree/bindings/spi/sh-hspi.txt new file mode 100644 index 0000000..30b57b1 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/sh-hspi.txt @@ -0,0 +1,7 @@ +Renesas HSPI. + +Required properties: +- compatible : "renesas,hspi" +- reg : Offset and length of the register set for the device +- interrupts : interrupt line used by HSPI + diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 3d9c2a7..5bdc8cb 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -303,3 +303,6 @@ PHY SLAVE DMA ENGINE devm_acpi_dma_controller_register() + +SPI + devm_spi_register_master() diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c index da5f078..5994cf6 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) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b9c53cc..eb1f1ef 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. @@ -369,7 +370,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. @@ -393,7 +394,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. diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index 9a64c3f..595b62c 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 37bad95..821bf7a 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-atmel.c b/drivers/spi/spi-atmel.c index d4ac60b..273db0b 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 @@ -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; } } @@ -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; @@ -1546,9 +1546,11 @@ 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)); - if (!as->regs) + as->regs = devm_ioremap_resource(&pdev->dev, 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; @@ -1617,7 +1619,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,36 +1670,36 @@ 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); 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) @@ -1714,10 +1715,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, }; diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 1d00d9b3..c4141c9 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; @@ -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); diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 52c8148..4c332143 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; } diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 536b0e3..80d56b2 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; } diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index 91921b5..38941e5 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; @@ -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); diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c index f4bf813..8f85988 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; } diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 45bdf73..f0f195a 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(); @@ -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"); + 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; } /* @@ -1410,10 +1411,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 +1433,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,31 +1444,34 @@ 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, + .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); diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 8c11355..bd222f6 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); @@ -414,10 +415,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 +456,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 5ed08e5..8081f96 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; @@ -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; @@ -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; diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 6416798..e2a5a42 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -226,10 +226,10 @@ static int spi_clps711x_probe(struct platform_device *pdev) dev_name(&pdev->dev), hw); if (ret) { dev_err(&pdev->dev, "Can't request IRQ\n"); - goto clk_out; + goto err_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", @@ -239,7 +239,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])) @@ -260,8 +259,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; } diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 8fbfe24..dd72445 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; @@ -916,7 +917,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 +926,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 +1016,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 +1023,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 +1050,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-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 4aa8be8..168c620 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); diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 6055c8d..66fa995 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); @@ -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); diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 79c958e..b897c4ad 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-efm32.c b/drivers/spi/spi-efm32.c index 7d84418..d4d3cc5 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); @@ -347,7 +343,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; @@ -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; @@ -467,7 +463,6 @@ err_disable_clk: clk_disable_unprepare(ddata->clk); err: spi_master_put(master); - kfree(master); } return ret; @@ -478,13 +473,14 @@ 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); free_irq(ddata->rxirq, ddata); clk_disable_unprepare(ddata->clk); spi_master_put(master); - kfree(master); return 0; } diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d22c00a..1bfaed6 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); } @@ -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; } diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c index 07971e3..58630ed 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-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 4e44575..8641b03 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; @@ -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; @@ -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; @@ -520,7 +520,6 @@ out_clk_put: clk_disable_unprepare(dspi->clk); out_master_put: spi_master_put(master); - platform_set_drvdata(pdev, NULL); return ret; } @@ -531,6 +530,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; @@ -547,5 +547,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); diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index b8f1103..43222d7 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-gpio.c b/drivers/spi/spi-gpio.c index 68b69fe..3fb09f9 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -22,6 +22,7 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/gpio.h> +#include <linux/of.h> #include <linux/of_device.h> #include <linux/of_gpio.h> @@ -467,7 +468,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 +487,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 +510,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 15323d8..b80f2f7 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; @@ -786,7 +815,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); @@ -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: diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index 0759b5d..41c5765 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-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 6adf4e3..ee6e61c 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -536,7 +536,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; @@ -559,12 +559,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; } diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index 6e925dc..00ba910 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-mxs.c b/drivers/spi/spi-mxs.c index de7b114..de33305 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -57,34 +57,53 @@ #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; + unsigned int sck; /* Rate requested (vs actual) */ }; 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; } - 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); 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); @@ -94,26 +113,15 @@ 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) +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 @@ -131,43 +139,11 @@ 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 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); -} - -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); -} - 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); @@ -200,9 +176,9 @@ 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, - int *first, int *last, int write) + unsigned int flags) { struct mxs_ssp *ssp = &spi->ssp; struct dma_async_tx_descriptor *desc = NULL; @@ -211,11 +187,11 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, 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; @@ -228,21 +204,25 @@ 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; - ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); + ctrl0 &= ~(BM_SSP_CTRL0_XFER_COUNT | BM_SSP_CTRL0_IGNORE_CRC | + BM_SSP_CTRL0_READ); + ctrl0 |= BM_SSP_CTRL0_DATA_XFER; - if (*first) - ctrl0 |= BM_SSP_CTRL0_LOCK_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) { @@ -267,7 +247,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; @@ -287,7 +267,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) { @@ -324,7 +304,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); @@ -332,20 +312,19 @@ 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, - int *first, int *last, int write) + unsigned int flags) { struct mxs_ssp *ssp = &spi->ssp; - if (*first) - mxs_spi_enable(spi); - - mxs_spi_set_cs(spi, cs); + writel(BM_SSP_CTRL0_IGNORE_CRC, + ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); while (len--) { - if (*last && len == 0) - mxs_spi_disable(spi); + if (len == 0 && (flags & TXRX_DEASSERT_CS)) + 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, @@ -356,7 +335,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 @@ -369,13 +348,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; @@ -400,14 +379,15 @@ 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; + /* 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) { @@ -415,16 +395,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; - 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; - } + /* De-assert on last transfer, inverted by cs_change flag */ + flag = (&t->transfer_list == m->transfers.prev) ^ t->cs_change ? + TXRX_DEASSERT_CS : 0; /* * Small blocks can be transfered via PIO. @@ -441,26 +414,26 @@ 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, &first, &last, 1); + 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, - &first, &last, 0); + flag); } else { writel(BM_SSP_CTRL1_DMA_ENABLE, ssp->base + HW_SSP_CTRL1(ssp) + 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, - &first, &last, 1); + 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, - &first, &last, 0); + flag); } if (status) { @@ -469,7 +442,6 @@ static int mxs_spi_transfer_one(struct spi_master *master, } m->actual_length += t->len; - first = last = 0; } m->status = status; @@ -563,7 +535,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) @@ -571,7 +542,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 +569,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; } diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index 47a68b4..e0c32bc 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 333cb1b..91c6685 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-octeon.c b/drivers/spi/spi-octeon.c index 5f28ddb..67249a4 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); diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 69ecf05..b6ed82b 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; } diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c index a6a8f09..9313fd3 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) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index ed4af47..443df39 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; } @@ -498,7 +504,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 +522,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); @@ -1407,7 +1413,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 +1441,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; diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 1d1d321..744841e 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; @@ -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; } diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 9c511a9..2789b45 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) @@ -2175,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)) { @@ -2227,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"); @@ -2287,8 +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); - amba_set_drvdata(adev, NULL); return 0; } diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 0ee53c2..c57740bb7 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-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index c1a5067..cb0e1f1 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"); } } @@ -1205,7 +1201,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; @@ -1257,9 +1253,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; } diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 8719206..58449ad4 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,103 @@ 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); + 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); + +}; + +/* + * functions for RSPI + */ +static int rspi_set_config_register(struct rspi_data *rspi, int access_size) +{ + 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) - 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); + + /* 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) { - int tmp; - unsigned char spbr; + 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); - tmp = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; - spbr = clamp(tmp, 0, 255); + /* Enables SPI function in a master mode */ + rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR); - return spbr; + 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,54 +326,60 @@ 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) +static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, + struct spi_transfer *t) { - /* 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); + int remain = t->len; + u8 *data; - /* 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 = (u8 *)t->tx_buf; + while (remain > 0) { + rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, + RSPI_SPCR); - /* Sets parity, interrupt mask */ - rspi_write8(rspi, 0x00, RSPI_SPCR2); + if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) { + dev_err(&rspi->master->dev, + "%s: tx empty timeout\n", __func__); + return -ETIMEDOUT; + } - /* Sets SPCMD */ - rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP, - RSPI_SPCMD0); + rspi_write16(rspi, *data, RSPI_SPDR); + data++; + remain--; + } - /* Sets RSPI mode */ - rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); + /* Waiting for the last transmition */ + rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); return 0; } -static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, +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) { - rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, - RSPI_SPCR); 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); - rspi_write16(rspi, *data, RSPI_SPDR); - data++; remain--; } @@ -277,6 +389,8 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, 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; @@ -442,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; @@ -581,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; } @@ -589,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; } @@ -616,7 +775,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 +904,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 +935,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 +944,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 +958,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 +1003,32 @@ error1: return ret; } +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[] = { + { "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, }, }; diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index ce318d9..0dc32a1 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; @@ -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-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index a80376d..9e2020d 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; }; @@ -559,25 +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); - - /* Start the signals */ - writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); + if (spi->cs_gpio >= 0) + gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 1 : 0); } static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, @@ -702,16 +694,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); - - /* Quiese the signals */ - writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); + if (spi->cs_gpio >= 0) + gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); } static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) @@ -862,16 +849,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,106 +870,98 @@ 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); - 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; - } + return 0; +} - if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { - sdd->cur_bpw = bpw; - sdd->cur_speed = speed; - s3c64xx_spi_config(sdd); - } +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); + int status; + u32 speed; + u8 bpw; + unsigned long flags; + int use_dma; - /* 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; + INIT_COMPLETION(sdd->xfer_completion); - spin_lock_irqsave(&sdd->lock, flags); + /* Only BPW and Speed may change across transfers */ + bpw = xfer->bits_per_word; + speed = xfer->speed_hz ? : spi->max_speed_hz; - /* Pending only which is to be done */ - sdd->state &= ~RXBUSY; - sdd->state &= ~TXBUSY; + 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; + } - enable_datapath(sdd, spi, xfer, use_dma); + 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_unlock_irqrestore(&sdd->lock, flags); + spin_lock_irqsave(&sdd->lock, flags); - status = wait_for_xfer(sdd, xfer, use_dma); + /* Pending only which is to be done */ + sdd->state &= ~RXBUSY; + sdd->state &= ~TXBUSY; - 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); + enable_datapath(sdd, spi, xfer, use_dma); - 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); - } + /* Start the signals */ + writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); - goto out; - } + /* 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; - + } else { flush_fifo(sdd); } -out: - if (!cs_toggle || status) - disable_cs(sdd, spi); - else - sdd->tgl_spi = spi; - - s3c64xx_spi_unmap_mssg(sdd, msg); + return status; +} - msg->status = status; +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); - spi_finalize_current_message(master); + s3c64xx_spi_unmap_mssg(sdd, msg); return 0; } @@ -1071,6 +1046,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); @@ -1117,11 +1094,14 @@ 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: + pm_runtime_put(&sdd->pdev->dev); /* 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); @@ -1140,8 +1120,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); } @@ -1359,7 +1339,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->transfer_one_message = s3c64xx_spi_transfer_one_message; + master->prepare_message = s3c64xx_spi_prepare_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; master->dma_alignment = 8; @@ -1428,11 +1410,12 @@ 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)) { - 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 +1444,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; } @@ -1480,11 +1459,14 @@ 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); - 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 */ @@ -1500,15 +1482,14 @@ 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); - spi_master_resume(master); - - return 0; + return spi_master_resume(master); } #endif /* CONFIG_PM_SLEEP */ @@ -1528,9 +1509,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; } @@ -1616,6 +1605,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, }, @@ -1633,22 +1634,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 <jassi.brar@samsung.com>"); MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index e488a90..292567a 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); @@ -303,9 +303,10 @@ 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); + ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "spi_register_master error.\n"); goto error1; @@ -328,17 +329,23 @@ static int hspi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); clk_put(hspi->clk); - spi_unregister_master(hspi->master); 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); diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c index 8eefeb6..38eb24d 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 a1f21b7..592b4af 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-tegra114.c b/drivers/spi/spi-tegra114.c index 145dd43..9146bb3 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; @@ -267,7 +268,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; @@ -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; @@ -1115,7 +1166,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 +1193,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); diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 1d814dc..79be8ce 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; @@ -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)) diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index c703536..af0a678 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -278,12 +278,12 @@ 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; 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; @@ -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) { 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; @@ -824,58 +803,72 @@ 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; - int single_xfer; 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; + tegra_slink_clear_status(tspi); - 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); - 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; - } + tspi->command_reg = tspi->def_command_reg; + tspi->command_reg |= SLINK_CS_SW | SLINK_CS_VALUE; - 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); - } + 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; +} + +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); + if (ret < 0) { + dev_err(tspi->dev, + "spi can not start transfer, err %d\n", ret); + return ret; } - ret = 0; -exit: + + 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) @@ -1078,7 +1071,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; @@ -1164,7 +1159,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 +1186,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); diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index e12d962..0b71270 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; @@ -472,7 +446,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; @@ -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", @@ -532,7 +504,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; @@ -547,7 +519,7 @@ static int ti_qspi_remove(struct platform_device *pdev) { struct ti_qspi *qspi = platform_get_drvdata(pdev); - spi_unregister_master(qspi->master); + ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG); return 0; } @@ -558,7 +530,7 @@ static const struct dev_pm_ops ti_qspi_pm_ops = { static struct platform_driver ti_qspi_driver = { .probe = ti_qspi_probe, - .remove = ti_qspi_remove, + .remove = ti_qspi_remove, .driver = { .name = "ti,dra7xxx-qspi", .owner = THIS_MODULE, diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index eaeeed5..4461313 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; @@ -1410,13 +1411,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); diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index 7c6d157..637cce2 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; @@ -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; } @@ -440,6 +438,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 +448,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); diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 0bf1b2c..ec3a83f 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; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9e039c6..8d05acc 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -39,6 +39,9 @@ #include <linux/ioport.h> #include <linux/acpi.h> +#define CREATE_TRACE_POINTS +#include <trace/events/spi.h> + static void spidev_release(struct device *dev) { struct spi_device *spi = to_spi_device(dev); @@ -58,11 +61,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 +234,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, @@ -323,7 +328,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); @@ -523,6 +528,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 @@ -557,6 +651,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 +680,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 +695,20 @@ 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, @@ -678,6 +790,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; @@ -686,9 +799,20 @@ 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); + + trace_spi_message_done(mesg); } EXPORT_SYMBOL_GPL(spi_finalize_current_message); @@ -803,6 +927,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); @@ -838,10 +964,8 @@ 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; + u32 value; if (!master->dev.of_node) return; @@ -866,14 +990,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)) @@ -886,55 +1010,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); @@ -944,9 +1066,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", @@ -1025,7 +1145,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)); @@ -1097,7 +1217,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; @@ -1122,7 +1242,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) @@ -1209,6 +1329,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. @@ -1245,6 +1366,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)); @@ -1402,8 +1558,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, " : "", @@ -1421,6 +1576,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 +1679,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) } } - message->spi = spi; message->status = -EINPROGRESS; return master->transfer(spi, message); } @@ -1762,7 +1920,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; @@ -1811,7 +1969,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); diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index ca5bcfe..d7c6e36 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -37,7 +37,7 @@ #include <linux/spi/spi.h> #include <linux/spi/spidev.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> /* @@ -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); @@ -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 */ diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 6200335..00492ca 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 2e046f6..e0aa13a 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 145f896..ea0c9de 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; } diff --git a/include/linux/spi/rspi.h b/include/linux/spi/rspi.h index 900f0e3..a25bd6f 100644 --- a/include/linux/spi/rspi.h +++ b/include/linux/spi/rspi.h @@ -26,6 +26,8 @@ struct rspi_plat_data { unsigned int dma_rx_id; unsigned dma_width_16bit:1; /* DMAC read/write width = 16-bit */ + + u16 num_chipselect; }; #endif diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 887116d..8c62ba7 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -23,6 +23,7 @@ #include <linux/mod_devicetable.h> #include <linux/slab.h> #include <linux/kthread.h> +#include <linux/completion.h> /* * INTERFACES between SPI master-side drivers and SPI infrastructure. @@ -150,8 +151,7 @@ static inline void *spi_get_drvdata(struct spi_device *spi) } struct spi_message; - - +struct spi_transfer; /** * struct spi_driver - Host side "protocol" driver @@ -257,6 +257,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @queue_lock: spinlock to syncronise access to message queue * @queue: message queue * @cur_msg: the currently in-flight message + * @cur_msg_prepared: spi_prepare_message was called for the currently + * in-flight message + * @xfer_completion: used by core tranfer_one_message() * @busy: message pump is busy * @running: message pump is running * @rt: whether this queue is set to run as a realtime task @@ -274,6 +277,16 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @unprepare_transfer_hardware: there are currently no more messages on the * queue so the subsystem notifies the driver that it may relax the * hardware by issuing this call + * @set_cs: assert or deassert chip select, true to assert. May be called + * from interrupt context. + * @prepare_message: set up the controller to transfer a single message, + * for example doing DMA mapping. Called from threaded + * context. + * @transfer_one: transfer a single spi_transfer. When the + * driver is finished with this transfer it must call + * spi_finalize_current_transfer() so the subsystem can issue + * the next transfer + * @unprepare_message: undo any work done by prepare_message(). * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * number. Any individual value may be -ENOENT for CS lines that * are not GPIOs (driven by the SPI controller itself). @@ -388,11 +401,25 @@ struct spi_master { bool running; bool rt; bool auto_runtime_pm; + bool cur_msg_prepared; + struct completion xfer_completion; int (*prepare_transfer_hardware)(struct spi_master *master); int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg); int (*unprepare_transfer_hardware)(struct spi_master *master); + int (*prepare_message)(struct spi_master *master, + struct spi_message *message); + int (*unprepare_message)(struct spi_master *master, + struct spi_message *message); + + /* + * These hooks are for drivers that use a generic implementation + * of transfer_one_message() provied by the core. + */ + void (*set_cs)(struct spi_device *spi, bool enable); + int (*transfer_one)(struct spi_master *master, struct spi_device *spi, + struct spi_transfer *transfer); /* gpio chip select */ int *cs_gpios; @@ -428,12 +455,15 @@ extern int spi_master_resume(struct spi_master *master); /* Calls the driver make to interact with the message queue */ extern struct spi_message *spi_get_next_queued_message(struct spi_master *master); extern void spi_finalize_current_message(struct spi_master *master); +extern void spi_finalize_current_transfer(struct spi_master *master); /* the spi driver core manages memory for the spi_master classdev */ extern struct spi_master * spi_alloc_master(struct device *host, unsigned size); extern int spi_register_master(struct spi_master *master); +extern int devm_spi_register_master(struct device *dev, + struct spi_master *master); extern void spi_unregister_master(struct spi_master *master); extern struct spi_master *spi_busnum_to_master(u16 busnum); @@ -823,6 +853,33 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd) return (status < 0) ? status : result; } +/** + * spi_w8r16be - SPI synchronous 8 bit write followed by 16 bit big-endian read + * @spi: device with which data will be exchanged + * @cmd: command to be written before data is read back + * Context: can sleep + * + * This returns the (unsigned) sixteen bit number returned by the device in cpu + * endianness, or else a negative error code. Callable only from contexts that + * can sleep. + * + * This function is similar to spi_w8r16, with the exception that it will + * convert the read 16 bit data word from big-endian to native endianness. + * + */ +static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) + +{ + ssize_t status; + __be16 result; + + status = spi_write_then_read(spi, &cmd, 1, &result, 2); + if (status < 0) + return status; + + return be16_to_cpu(result); +} + /*---------------------------------------------------------------------------*/ /* diff --git a/include/trace/events/spi.h b/include/trace/events/spi.h new file mode 100644 index 0000000..7e02c98 --- /dev/null +++ b/include/trace/events/spi.h @@ -0,0 +1,156 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM spi + +#if !defined(_TRACE_SPI_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SPI_H + +#include <linux/ktime.h> +#include <linux/tracepoint.h> + +DECLARE_EVENT_CLASS(spi_master, + + TP_PROTO(struct spi_master *master), + + TP_ARGS(master), + + TP_STRUCT__entry( + __field( int, bus_num ) + ), + + TP_fast_assign( + __entry->bus_num = master->bus_num; + ), + + TP_printk("spi%d", (int)__entry->bus_num) + +); + +DEFINE_EVENT(spi_master, spi_master_idle, + + TP_PROTO(struct spi_master *master), + + TP_ARGS(master) + +); + +DEFINE_EVENT(spi_master, spi_master_busy, + + TP_PROTO(struct spi_master *master), + + TP_ARGS(master) + +); + +DECLARE_EVENT_CLASS(spi_message, + + TP_PROTO(struct spi_message *msg), + + TP_ARGS(msg), + + TP_STRUCT__entry( + __field( int, bus_num ) + __field( int, chip_select ) + __field( struct spi_message *, msg ) + ), + + TP_fast_assign( + __entry->bus_num = msg->spi->master->bus_num; + __entry->chip_select = msg->spi->chip_select; + __entry->msg = msg; + ), + + TP_printk("spi%d.%d %p", (int)__entry->bus_num, + (int)__entry->chip_select, + (struct spi_message *)__entry->msg) +); + +DEFINE_EVENT(spi_message, spi_message_submit, + + TP_PROTO(struct spi_message *msg), + + TP_ARGS(msg) + +); + +DEFINE_EVENT(spi_message, spi_message_start, + + TP_PROTO(struct spi_message *msg), + + TP_ARGS(msg) + +); + +TRACE_EVENT(spi_message_done, + + TP_PROTO(struct spi_message *msg), + + TP_ARGS(msg), + + TP_STRUCT__entry( + __field( int, bus_num ) + __field( int, chip_select ) + __field( struct spi_message *, msg ) + __field( unsigned, frame ) + __field( unsigned, actual ) + ), + + TP_fast_assign( + __entry->bus_num = msg->spi->master->bus_num; + __entry->chip_select = msg->spi->chip_select; + __entry->msg = msg; + __entry->frame = msg->frame_length; + __entry->actual = msg->actual_length; + ), + + TP_printk("spi%d.%d %p len=%u/%u", (int)__entry->bus_num, + (int)__entry->chip_select, + (struct spi_message *)__entry->msg, + (unsigned)__entry->actual, (unsigned)__entry->frame) +); + +DECLARE_EVENT_CLASS(spi_transfer, + + TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer), + + TP_ARGS(msg, xfer), + + TP_STRUCT__entry( + __field( int, bus_num ) + __field( int, chip_select ) + __field( struct spi_transfer *, xfer ) + __field( int, len ) + ), + + TP_fast_assign( + __entry->bus_num = msg->spi->master->bus_num; + __entry->chip_select = msg->spi->chip_select; + __entry->xfer = xfer; + __entry->len = xfer->len; + ), + + TP_printk("spi%d.%d %p len=%d", (int)__entry->bus_num, + (int)__entry->chip_select, + (struct spi_message *)__entry->xfer, + (int)__entry->len) +); + +DEFINE_EVENT(spi_transfer, spi_transfer_start, + + TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer), + + TP_ARGS(msg, xfer) + +); + +DEFINE_EVENT(spi_transfer, spi_transfer_stop, + + TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer), + + TP_ARGS(msg, xfer) + +); + +#endif /* _TRACE_POWER_H */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> |