diff options
Diffstat (limited to 'drivers/spi')
34 files changed, 432 insertions, 628 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 52e2900d9d8..a1fd73df541 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -88,7 +88,7 @@ config SPI_BFIN_SPORT config SPI_AU1550 tristate "Au1550/Au12x0 SPI Controller" - depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL + depends on MIPS_ALCHEMY && EXPERIMENTAL select SPI_BITBANG help If you say yes to this option, support will be included for the diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index 4813a63ce6f..881c1967741 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -320,18 +320,7 @@ static struct platform_driver altera_spi_driver = { .of_match_table = altera_spi_match, }, }; - -static int __init altera_spi_init(void) -{ - return platform_driver_register(&altera_spi_driver); -} -module_init(altera_spi_init); - -static void __exit altera_spi_exit(void) -{ - platform_driver_unregister(&altera_spi_driver); -} -module_exit(altera_spi_exit); +module_platform_driver(altera_spi_driver); MODULE_DESCRIPTION("Altera SPI driver"); MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 03019bf5a5e..024b48aed5c 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -273,18 +273,7 @@ static struct platform_driver ath79_spi_driver = { .owner = THIS_MODULE, }, }; - -static __init int ath79_spi_init(void) -{ - return platform_driver_register(&ath79_spi_driver); -} -module_init(ath79_spi_init); - -static __exit void ath79_spi_exit(void) -{ - platform_driver_unregister(&ath79_spi_driver); -} -module_exit(ath79_spi_exit); +module_platform_driver(ath79_spi_driver); MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR913X"); MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 82dee9a6c0d..79665e2e6ec 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -22,7 +22,7 @@ #include <asm/io.h> #include <mach/board.h> -#include <mach/gpio.h> +#include <asm/gpio.h> #include <mach/cpu.h> /* SPI register offsets */ @@ -1074,18 +1074,7 @@ static struct platform_driver atmel_spi_driver = { .resume = atmel_spi_resume, .remove = __exit_p(atmel_spi_remove), }; - -static int __init atmel_spi_init(void) -{ - return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe); -} -module_init(atmel_spi_init); - -static void __exit atmel_spi_exit(void) -{ - platform_driver_unregister(&atmel_spi_driver); -} -module_exit(atmel_spi_exit); +module_platform_driver(atmel_spi_driver); MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver"); MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index e557ff617b1..248a2cc671a 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -938,15 +938,4 @@ static struct platform_driver bfin_sport_spi_driver = { .suspend = bfin_sport_spi_suspend, .resume = bfin_sport_spi_resume, }; - -static int __init bfin_sport_spi_init(void) -{ - return platform_driver_register(&bfin_sport_spi_driver); -} -module_init(bfin_sport_spi_init); - -static void __exit bfin_sport_spi_exit(void) -{ - platform_driver_unregister(&bfin_sport_spi_driver); -} -module_exit(bfin_sport_spi_exit); +module_platform_driver(bfin_sport_spi_driver); diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index b8d25f2b703..3b83ff8b1e2 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -1098,7 +1098,7 @@ static int bfin_spi_setup(struct spi_device *spi) if (chip->pio_interrupt && !drv_data->irq_requested) { ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler, - IRQF_DISABLED, "BFIN_SPI", drv_data); + 0, "BFIN_SPI", drv_data); if (ret) { dev_err(&spi->dev, "Unable to register spi IRQ\n"); goto error; diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index ae2cd1c1fda..6eee64a5d24 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -487,7 +487,7 @@ static int __devinit mcfqspi_probe(struct platform_device *pdev) goto fail2; } - status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, IRQF_DISABLED, + status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, 0, pdev->name, mcfqspi); if (status) { dev_dbg(&pdev->dev, "request_irq failed\n"); @@ -621,20 +621,10 @@ static struct platform_driver mcfqspi_driver = { .driver.name = DRIVER_NAME, .driver.owner = THIS_MODULE, .driver.pm = MCFQSPI_DEV_PM_OPS, + .probe = mcfqspi_probe, .remove = __devexit_p(mcfqspi_remove), }; - -static int __init mcfqspi_init(void) -{ - return platform_driver_probe(&mcfqspi_driver, mcfqspi_probe); -} -module_init(mcfqspi_init); - -static void __exit mcfqspi_exit(void) -{ - platform_driver_unregister(&mcfqspi_driver); -} -module_exit(mcfqspi_exit); +module_platform_driver(mcfqspi_driver); MODULE_AUTHOR("Steven King <sfking@fdwdc.com>"); MODULE_DESCRIPTION("Coldfire QSPI Controller Driver"); diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 1f0ed8005c9..31bfba805cf 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -799,7 +799,7 @@ rx_dma_failed: * It will invoke spi_bitbang_start to create work queue so that client driver * can register transfer method to work queue. */ -static int davinci_spi_probe(struct platform_device *pdev) +static int __devinit davinci_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct davinci_spi *dspi; @@ -984,7 +984,7 @@ err: * It will also call spi_bitbang_stop to destroy the work queue which was * created by spi_bitbang_start. */ -static int __exit davinci_spi_remove(struct platform_device *pdev) +static int __devexit davinci_spi_remove(struct platform_device *pdev) { struct davinci_spi *dspi; struct spi_master *master; @@ -1011,20 +1011,10 @@ static struct platform_driver davinci_spi_driver = { .name = "spi_davinci", .owner = THIS_MODULE, }, - .remove = __exit_p(davinci_spi_remove), + .probe = davinci_spi_probe, + .remove = __devexit_p(davinci_spi_remove), }; - -static int __init davinci_spi_init(void) -{ - return platform_driver_probe(&davinci_spi_driver, davinci_spi_probe); -} -module_init(davinci_spi_init); - -static void __exit davinci_spi_exit(void) -{ - platform_driver_unregister(&davinci_spi_driver); -} -module_exit(davinci_spi_exit); +module_platform_driver(davinci_spi_driver); MODULE_DESCRIPTION("TI DaVinci SPI Master Controller Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index 130e55537db..e743a45ee92 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -116,13 +116,13 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) /* 1. setup DMA related registers */ if (cs_change) { spi_enable_chip(dws, 0); - dw_writew(dws, dmardlr, 0xf); - dw_writew(dws, dmatdlr, 0x10); + dw_writew(dws, DW_SPI_DMARDLR, 0xf); + dw_writew(dws, DW_SPI_DMATDLR, 0x10); if (dws->tx_dma) dma_ctrl |= 0x2; if (dws->rx_dma) dma_ctrl |= 0x1; - dw_writew(dws, dmacr, dma_ctrl); + dw_writew(dws, DW_SPI_DMACR, dma_ctrl); spi_enable_chip(dws, 1); } @@ -200,7 +200,8 @@ static struct dw_spi_dma_ops mid_dma_ops = { int dw_spi_mid_init(struct dw_spi *dws) { - u32 *clk_reg, clk_cdiv; + void __iomem *clk_reg; + u32 clk_cdiv; clk_reg = ioremap_nocache(MRST_CLK_SPI0_REG, 16); if (!clk_reg) diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 34eb66501db..fac399c3022 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -127,24 +127,14 @@ static int __devexit dw_spi_mmio_remove(struct platform_device *pdev) } static struct platform_driver dw_spi_mmio_driver = { + .probe = dw_spi_mmio_probe, .remove = __devexit_p(dw_spi_mmio_remove), .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, }, }; - -static int __init dw_spi_mmio_init(void) -{ - return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe); -} -module_init(dw_spi_mmio_init); - -static void __exit dw_spi_mmio_exit(void) -{ - platform_driver_unregister(&dw_spi_mmio_driver); -} -module_exit(dw_spi_mmio_exit); +module_platform_driver(dw_spi_mmio_driver); MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>"); MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core"); diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 857cd30b44b..296d94f4cf7 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -88,35 +88,35 @@ static ssize_t spi_show_regs(struct file *file, char __user *user_buf, len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, "=================================\n"); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "CTRL0: \t\t0x%08x\n", dw_readl(dws, ctrl0)); + "CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "CTRL1: \t\t0x%08x\n", dw_readl(dws, ctrl1)); + "CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "SSIENR: \t0x%08x\n", dw_readl(dws, ssienr)); + "SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "SER: \t\t0x%08x\n", dw_readl(dws, ser)); + "SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "BAUDR: \t\t0x%08x\n", dw_readl(dws, baudr)); + "BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "TXFTLR: \t0x%08x\n", dw_readl(dws, txfltr)); + "TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "RXFTLR: \t0x%08x\n", dw_readl(dws, rxfltr)); + "RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "TXFLR: \t\t0x%08x\n", dw_readl(dws, txflr)); + "TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "RXFLR: \t\t0x%08x\n", dw_readl(dws, rxflr)); + "RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "SR: \t\t0x%08x\n", dw_readl(dws, sr)); + "SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "IMR: \t\t0x%08x\n", dw_readl(dws, imr)); + "IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "ISR: \t\t0x%08x\n", dw_readl(dws, isr)); + "ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "DMACR: \t\t0x%08x\n", dw_readl(dws, dmacr)); + "DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "DMATDLR: \t0x%08x\n", dw_readl(dws, dmatdlr)); + "DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, - "DMARDLR: \t0x%08x\n", dw_readl(dws, dmardlr)); + "DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, "=================================\n"); @@ -166,7 +166,7 @@ static inline u32 tx_max(struct dw_spi *dws) u32 tx_left, tx_room, rxtx_gap; tx_left = (dws->tx_end - dws->tx) / dws->n_bytes; - tx_room = dws->fifo_len - dw_readw(dws, txflr); + tx_room = dws->fifo_len - dw_readw(dws, DW_SPI_TXFLR); /* * Another concern is about the tx/rx mismatch, we @@ -187,7 +187,7 @@ static inline u32 rx_max(struct dw_spi *dws) { u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes; - return min(rx_left, (u32)dw_readw(dws, rxflr)); + return min(rx_left, (u32)dw_readw(dws, DW_SPI_RXFLR)); } static void dw_writer(struct dw_spi *dws) @@ -203,7 +203,7 @@ static void dw_writer(struct dw_spi *dws) else txw = *(u16 *)(dws->tx); } - dw_writew(dws, dr, txw); + dw_writew(dws, DW_SPI_DR, txw); dws->tx += dws->n_bytes; } } @@ -214,7 +214,7 @@ static void dw_reader(struct dw_spi *dws) u16 rxw; while (max--) { - rxw = dw_readw(dws, dr); + rxw = dw_readw(dws, DW_SPI_DR); /* Care rx only if the transfer's original "rx" is not null */ if (dws->rx_end - dws->len) { if (dws->n_bytes == 1) @@ -322,13 +322,13 @@ EXPORT_SYMBOL_GPL(dw_spi_xfer_done); static irqreturn_t interrupt_transfer(struct dw_spi *dws) { - u16 irq_status = dw_readw(dws, isr); + u16 irq_status = dw_readw(dws, DW_SPI_ISR); /* Error handling */ if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { - dw_readw(dws, txoicr); - dw_readw(dws, rxoicr); - dw_readw(dws, rxuicr); + dw_readw(dws, DW_SPI_TXOICR); + dw_readw(dws, DW_SPI_RXOICR); + dw_readw(dws, DW_SPI_RXUICR); int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun"); return IRQ_HANDLED; } @@ -352,7 +352,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) static irqreturn_t dw_spi_irq(int irq, void *dev_id) { struct dw_spi *dws = dev_id; - u16 irq_status = dw_readw(dws, isr) & 0x3f; + u16 irq_status = dw_readw(dws, DW_SPI_ISR) & 0x3f; if (!irq_status) return IRQ_NONE; @@ -520,11 +520,11 @@ static void pump_transfers(unsigned long data) * 2. clk_div is changed * 3. control value changes */ - if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div || imask) { + if (dw_readw(dws, DW_SPI_CTRL0) != cr0 || cs_change || clk_div || imask) { spi_enable_chip(dws, 0); - if (dw_readw(dws, ctrl0) != cr0) - dw_writew(dws, ctrl0, cr0); + if (dw_readw(dws, DW_SPI_CTRL0) != cr0) + dw_writew(dws, DW_SPI_CTRL0, cr0); spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); spi_chip_sel(dws, spi->chip_select); @@ -534,7 +534,7 @@ static void pump_transfers(unsigned long data) if (imask) spi_umask_intr(dws, imask); if (txint_level) - dw_writew(dws, txfltr, txint_level); + dw_writew(dws, DW_SPI_TXFLTR, txint_level); spi_enable_chip(dws, 1); if (cs_change) @@ -790,13 +790,13 @@ static void spi_hw_init(struct dw_spi *dws) if (!dws->fifo_len) { u32 fifo; for (fifo = 2; fifo <= 257; fifo++) { - dw_writew(dws, txfltr, fifo); - if (fifo != dw_readw(dws, txfltr)) + dw_writew(dws, DW_SPI_TXFLTR, fifo); + if (fifo != dw_readw(dws, DW_SPI_TXFLTR)) break; } dws->fifo_len = (fifo == 257) ? 0 : fifo; - dw_writew(dws, txfltr, 0); + dw_writew(dws, DW_SPI_TXFLTR, 0); } } diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 8b7b07bf6c3..9c57c078031 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -4,6 +4,33 @@ #include <linux/io.h> #include <linux/scatterlist.h> +/* Register offsets */ +#define DW_SPI_CTRL0 0x00 +#define DW_SPI_CTRL1 0x04 +#define DW_SPI_SSIENR 0x08 +#define DW_SPI_MWCR 0x0c +#define DW_SPI_SER 0x10 +#define DW_SPI_BAUDR 0x14 +#define DW_SPI_TXFLTR 0x18 +#define DW_SPI_RXFLTR 0x1c +#define DW_SPI_TXFLR 0x20 +#define DW_SPI_RXFLR 0x24 +#define DW_SPI_SR 0x28 +#define DW_SPI_IMR 0x2c +#define DW_SPI_ISR 0x30 +#define DW_SPI_RISR 0x34 +#define DW_SPI_TXOICR 0x38 +#define DW_SPI_RXOICR 0x3c +#define DW_SPI_RXUICR 0x40 +#define DW_SPI_MSTICR 0x44 +#define DW_SPI_ICR 0x48 +#define DW_SPI_DMACR 0x4c +#define DW_SPI_DMATDLR 0x50 +#define DW_SPI_DMARDLR 0x54 +#define DW_SPI_IDR 0x58 +#define DW_SPI_VERSION 0x5c +#define DW_SPI_DR 0x60 + /* Bit fields in CTRLR0 */ #define SPI_DFS_OFFSET 0 @@ -55,35 +82,6 @@ enum dw_ssi_type { SSI_NS_MICROWIRE, }; -struct dw_spi_reg { - u32 ctrl0; - u32 ctrl1; - u32 ssienr; - u32 mwcr; - u32 ser; - u32 baudr; - u32 txfltr; - u32 rxfltr; - u32 txflr; - u32 rxflr; - u32 sr; - u32 imr; - u32 isr; - u32 risr; - u32 txoicr; - u32 rxoicr; - u32 rxuicr; - u32 msticr; - u32 icr; - u32 dmacr; - u32 dmatdlr; - u32 dmardlr; - u32 idr; - u32 version; - u32 dr; /* Currently oper as 32 bits, - though only low 16 bits matters */ -} __packed; - struct dw_spi; struct dw_spi_dma_ops { int (*dma_init)(struct dw_spi *dws); @@ -161,23 +159,34 @@ struct dw_spi { #endif }; -#define dw_readl(dw, name) \ - __raw_readl(&(((struct dw_spi_reg *)dw->regs)->name)) -#define dw_writel(dw, name, val) \ - __raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name)) -#define dw_readw(dw, name) \ - __raw_readw(&(((struct dw_spi_reg *)dw->regs)->name)) -#define dw_writew(dw, name, val) \ - __raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name)) +static inline u32 dw_readl(struct dw_spi *dws, u32 offset) +{ + return __raw_readl(dws->regs + offset); +} + +static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val) +{ + __raw_writel(val, dws->regs + offset); +} + +static inline u16 dw_readw(struct dw_spi *dws, u32 offset) +{ + return __raw_readw(dws->regs + offset); +} + +static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val) +{ + __raw_writew(val, dws->regs + offset); +} static inline void spi_enable_chip(struct dw_spi *dws, int enable) { - dw_writel(dws, ssienr, (enable ? 1 : 0)); + dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0)); } static inline void spi_set_clk(struct dw_spi *dws, u16 div) { - dw_writel(dws, baudr, div); + dw_writel(dws, DW_SPI_BAUDR, div); } static inline void spi_chip_sel(struct dw_spi *dws, u16 cs) @@ -188,7 +197,7 @@ static inline void spi_chip_sel(struct dw_spi *dws, u16 cs) if (dws->cs_control) dws->cs_control(1); - dw_writel(dws, ser, 1 << cs); + dw_writel(dws, DW_SPI_SER, 1 << cs); } /* Disable IRQ bits */ @@ -196,8 +205,8 @@ static inline void spi_mask_intr(struct dw_spi *dws, u32 mask) { u32 new_mask; - new_mask = dw_readl(dws, imr) & ~mask; - dw_writel(dws, imr, new_mask); + new_mask = dw_readl(dws, DW_SPI_IMR) & ~mask; + dw_writel(dws, DW_SPI_IMR, new_mask); } /* Enable IRQ bits */ @@ -205,8 +214,8 @@ static inline void spi_umask_intr(struct dw_spi *dws, u32 mask) { u32 new_mask; - new_mask = dw_readl(dws, imr) | mask; - dw_writel(dws, imr, new_mask); + new_mask = dw_readl(dws, DW_SPI_IMR) | mask; + dw_writel(dws, DW_SPI_IMR, new_mask); } /* diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 1cf645479bf..0a282e5fcc9 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -24,6 +24,7 @@ #include <linux/dmaengine.h> #include <linux/bitops.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <linux/platform_device.h> #include <linux/workqueue.h> #include <linux/sched.h> @@ -1025,7 +1026,7 @@ static void ep93xx_spi_release_dma(struct ep93xx_spi *espi) free_page((unsigned long)espi->zeropage); } -static int __init ep93xx_spi_probe(struct platform_device *pdev) +static int __devinit ep93xx_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct ep93xx_spi_info *info; @@ -1150,7 +1151,7 @@ fail_release_master: return error; } -static int __exit ep93xx_spi_remove(struct platform_device *pdev) +static int __devexit ep93xx_spi_remove(struct platform_device *pdev) { struct spi_master *master = platform_get_drvdata(pdev); struct ep93xx_spi *espi = spi_master_get_devdata(master); @@ -1196,20 +1197,10 @@ static struct platform_driver ep93xx_spi_driver = { .name = "ep93xx-spi", .owner = THIS_MODULE, }, - .remove = __exit_p(ep93xx_spi_remove), + .probe = ep93xx_spi_probe, + .remove = __devexit_p(ep93xx_spi_remove), }; - -static int __init ep93xx_spi_init(void) -{ - return platform_driver_probe(&ep93xx_spi_driver, ep93xx_spi_probe); -} -module_init(ep93xx_spi_init); - -static void __exit ep93xx_spi_exit(void) -{ - platform_driver_unregister(&ep93xx_spi_driver); -} -module_exit(ep93xx_spi_exit); +module_platform_driver(ep93xx_spi_driver); MODULE_DESCRIPTION("EP93xx SPI Controller driver"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>"); diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 54e499d5f92..d770f03705c 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -744,18 +744,7 @@ static struct platform_driver fsl_espi_driver = { .probe = of_fsl_espi_probe, .remove = __devexit_p(of_fsl_espi_remove), }; - -static int __init fsl_espi_init(void) -{ - return platform_driver_register(&fsl_espi_driver); -} -module_init(fsl_espi_init); - -static void __exit fsl_espi_exit(void) -{ - platform_driver_unregister(&fsl_espi_driver); -} -module_exit(fsl_espi_exit); +module_platform_driver(fsl_espi_driver); MODULE_AUTHOR("Mingkai Hu"); MODULE_DESCRIPTION("Enhanced Freescale SPI Driver"); diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 0e88ab74549..635ff08b377 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -311,7 +311,7 @@ done: return value; } -static int __init spi_gpio_probe(struct platform_device *pdev) +static int __devinit spi_gpio_probe(struct platform_device *pdev) { int status; struct spi_master *master; @@ -379,7 +379,7 @@ gpio_free: return status; } -static int __exit spi_gpio_remove(struct platform_device *pdev) +static int __devexit spi_gpio_remove(struct platform_device *pdev) { struct spi_gpio *spi_gpio; struct spi_gpio_platform_data *pdata; @@ -408,21 +408,10 @@ MODULE_ALIAS("platform:" DRIVER_NAME); static struct platform_driver spi_gpio_driver = { .driver.name = DRIVER_NAME, .driver.owner = THIS_MODULE, - .remove = __exit_p(spi_gpio_remove), + .probe = spi_gpio_probe, + .remove = __devexit_p(spi_gpio_remove), }; - -static int __init spi_gpio_init(void) -{ - return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe); -} -module_init(spi_gpio_init); - -static void __exit spi_gpio_exit(void) -{ - platform_driver_unregister(&spi_gpio_driver); -} -module_exit(spi_gpio_exit); - +module_platform_driver(spi_gpio_driver); MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO "); MODULE_AUTHOR("David Brownell"); diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index fa594d604ac..c6e697f5e00 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -929,19 +929,7 @@ static struct platform_driver spi_imx_driver = { .probe = spi_imx_probe, .remove = __devexit_p(spi_imx_remove), }; - -static int __init spi_imx_init(void) -{ - return platform_driver_register(&spi_imx_driver); -} - -static void __exit spi_imx_exit(void) -{ - platform_driver_unregister(&spi_imx_driver); -} - -module_init(spi_imx_init); -module_exit(spi_imx_exit); +module_platform_driver(spi_imx_driver); MODULE_DESCRIPTION("SPI Master Controller driver"); MODULE_AUTHOR("Sascha Hauer, Pengutronix"); diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 6a5b4238fb6..4c63f772780 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -559,18 +559,7 @@ static struct platform_driver mpc512x_psc_spi_of_driver = { .of_match_table = mpc512x_psc_spi_of_match, }, }; - -static int __init mpc512x_psc_spi_init(void) -{ - return platform_driver_register(&mpc512x_psc_spi_of_driver); -} -module_init(mpc512x_psc_spi_init); - -static void __exit mpc512x_psc_spi_exit(void) -{ - platform_driver_unregister(&mpc512x_psc_spi_of_driver); -} -module_exit(mpc512x_psc_spi_exit); +module_platform_driver(mpc512x_psc_spi_of_driver); MODULE_AUTHOR("John Rigby"); MODULE_DESCRIPTION("MPC512x PSC SPI Driver"); diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index e30baf0852a..66047156d90 100644 --- a/drivers/spi/spi-mpc52xx-psc.c +++ b/drivers/spi/spi-mpc52xx-psc.c @@ -511,18 +511,7 @@ static struct platform_driver mpc52xx_psc_spi_of_driver = { .of_match_table = mpc52xx_psc_spi_of_match, }, }; - -static int __init mpc52xx_psc_spi_init(void) -{ - return platform_driver_register(&mpc52xx_psc_spi_of_driver); -} -module_init(mpc52xx_psc_spi_init); - -static void __exit mpc52xx_psc_spi_exit(void) -{ - platform_driver_unregister(&mpc52xx_psc_spi_of_driver); -} -module_exit(mpc52xx_psc_spi_exit); +module_platform_driver(mpc52xx_psc_spi_of_driver); MODULE_AUTHOR("Dragos Carp"); MODULE_DESCRIPTION("MPC52xx PSC SPI Driver"); diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c index 015a974bed7..57633d96345 100644 --- a/drivers/spi/spi-mpc52xx.c +++ b/drivers/spi/spi-mpc52xx.c @@ -564,16 +564,4 @@ static struct platform_driver mpc52xx_spi_of_driver = { .probe = mpc52xx_spi_probe, .remove = __devexit_p(mpc52xx_spi_remove), }; - -static int __init mpc52xx_spi_init(void) -{ - return platform_driver_register(&mpc52xx_spi_of_driver); -} -module_init(mpc52xx_spi_init); - -static void __exit mpc52xx_spi_exit(void) -{ - platform_driver_unregister(&mpc52xx_spi_of_driver); -} -module_exit(mpc52xx_spi_exit); - +module_platform_driver(mpc52xx_spi_of_driver); diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index c0a6ce81f9c..e763254741c 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -484,19 +484,7 @@ static struct platform_driver nuc900_spi_driver = { .owner = THIS_MODULE, }, }; - -static int __init nuc900_spi_init(void) -{ - return platform_driver_register(&nuc900_spi_driver); -} - -static void __exit nuc900_spi_exit(void) -{ - platform_driver_unregister(&nuc900_spi_driver); -} - -module_init(nuc900_spi_init); -module_exit(nuc900_spi_exit); +module_platform_driver(nuc900_spi_driver); MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); MODULE_DESCRIPTION("nuc900 spi driver!"); diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index f1bde66cea1..897274e8715 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -406,18 +406,7 @@ static struct platform_driver tiny_spi_driver = { .of_match_table = tiny_spi_match, }, }; - -static int __init tiny_spi_init(void) -{ - return platform_driver_register(&tiny_spi_driver); -} -module_init(tiny_spi_init); - -static void __exit tiny_spi_exit(void) -{ - platform_driver_unregister(&tiny_spi_driver); -} -module_exit(tiny_spi_exit); +module_platform_driver(tiny_spi_driver); MODULE_DESCRIPTION("OpenCores tiny SPI driver"); MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index fde3a2d4f12..322be7aea8b 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1116,15 +1116,16 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) status = -ENODEV; goto err1; } + + r->start += pdata->regs_offset; + r->end += pdata->regs_offset; + mcspi->phys = r->start; if (!request_mem_region(r->start, resource_size(r), dev_name(&pdev->dev))) { status = -EBUSY; goto err1; } - r->start += pdata->regs_offset; - r->end += pdata->regs_offset; - mcspi->phys = r->start; mcspi->base = ioremap(r->start, resource_size(r)); if (!mcspi->base) { dev_dbg(&pdev->dev, "can't ioremap MCSPI\n"); diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 730b4a37b82..f103e470cb6 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -113,7 +113,6 @@ #define SSP_CR0_MASK_CSS_ST (0x1FUL << 16) #define SSP_CR0_MASK_FRF_ST (0x3UL << 21) - /* * SSP Control Register 0 - SSP_CR1 */ @@ -283,7 +282,6 @@ #define SPI_POLLING_TIMEOUT 1000 - /* * The type of reading going on on this chip */ @@ -515,9 +513,6 @@ static void giveback(struct pl022 *pl022) if (msg->complete) msg->complete(msg->context); /* This message is completed, so let's turn off the clocks & power */ - clk_disable(pl022->clk); - amba_pclk_disable(pl022->adev); - amba_vcore_disable(pl022->adev); pm_runtime_put(&pl022->adev->dev); } @@ -752,7 +747,6 @@ static void readwriter(struct pl022 *pl022) */ } - /** * next_transfer - Move to the Next transfer in the current spi message * @pl022: SSP driver private data structure @@ -1019,14 +1013,14 @@ static int configure_dma(struct pl022 *pl022) dmaengine_slave_config(txchan, &tx_conf); /* Create sglists for the transfers */ - pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1; + pages = DIV_ROUND_UP(pl022->cur_transfer->len, PAGE_SIZE); dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages); - ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL); + ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_ATOMIC); if (ret) goto err_alloc_rx_sg; - ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL); + ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_ATOMIC); if (ret) goto err_alloc_tx_sg; @@ -1534,8 +1528,7 @@ static void pump_messages(struct work_struct *work) /* Initial message state */ pl022->cur_msg->state = STATE_START; pl022->cur_transfer = list_entry(pl022->cur_msg->transfers.next, - struct spi_transfer, - transfer_list); + struct spi_transfer, transfer_list); /* Setup the SPI using the per chip configuration */ pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); @@ -1545,9 +1538,6 @@ static void pump_messages(struct work_struct *work) * (poll/interrupt/DMA) */ pm_runtime_get_sync(&pl022->adev->dev); - amba_vcore_enable(pl022->adev); - amba_pclk_enable(pl022->adev); - clk_enable(pl022->clk); restore_state(pl022); flush(pl022); @@ -1557,7 +1547,6 @@ static void pump_messages(struct work_struct *work) do_interrupt_dma_transfer(pl022); } - static int __init init_queue(struct pl022 *pl022) { INIT_LIST_HEAD(&pl022->queue); @@ -1566,8 +1555,8 @@ static int __init init_queue(struct pl022 *pl022) pl022->running = false; pl022->busy = false; - tasklet_init(&pl022->pump_transfers, - pump_transfers, (unsigned long)pl022); + tasklet_init(&pl022->pump_transfers, pump_transfers, + (unsigned long)pl022); INIT_WORK(&pl022->pump_messages, pump_messages); pl022->workqueue = create_singlethread_workqueue( @@ -1578,7 +1567,6 @@ static int __init init_queue(struct pl022 *pl022) return 0; } - static int start_queue(struct pl022 *pl022) { unsigned long flags; @@ -1601,7 +1589,6 @@ static int start_queue(struct pl022 *pl022) return 0; } - static int stop_queue(struct pl022 *pl022) { unsigned long flags; @@ -1797,71 +1784,70 @@ static int pl022_transfer(struct spi_device *spi, struct spi_message *msg) return 0; } -static int calculate_effective_freq(struct pl022 *pl022, - int freq, - struct ssp_clock_params *clk_freq) +static inline u32 spi_rate(u32 rate, u16 cpsdvsr, u16 scr) +{ + return rate / (cpsdvsr * (1 + scr)); +} + +static int calculate_effective_freq(struct pl022 *pl022, int freq, struct + ssp_clock_params * clk_freq) { /* Lets calculate the frequency parameters */ - u16 cpsdvsr = 2; - u16 scr = 0; - bool freq_found = false; - u32 rate; - u32 max_tclk; - u32 min_tclk; + u16 cpsdvsr = CPSDVR_MIN, scr = SCR_MIN; + u32 rate, max_tclk, min_tclk, best_freq = 0, best_cpsdvsr = 0, + best_scr = 0, tmp, found = 0; rate = clk_get_rate(pl022->clk); /* cpsdvscr = 2 & scr 0 */ - max_tclk = (rate / (CPSDVR_MIN * (1 + SCR_MIN))); + max_tclk = spi_rate(rate, CPSDVR_MIN, SCR_MIN); /* cpsdvsr = 254 & scr = 255 */ - min_tclk = (rate / (CPSDVR_MAX * (1 + SCR_MAX))); - - if ((freq <= max_tclk) && (freq >= min_tclk)) { - while (cpsdvsr <= CPSDVR_MAX && !freq_found) { - while (scr <= SCR_MAX && !freq_found) { - if ((rate / - (cpsdvsr * (1 + scr))) > freq) - scr += 1; - else { - /* - * This bool is made true when - * effective frequency >= - * target frequency is found - */ - freq_found = true; - if ((rate / - (cpsdvsr * (1 + scr))) != freq) { - if (scr == SCR_MIN) { - cpsdvsr -= 2; - scr = SCR_MAX; - } else - scr -= 1; - } - } - } - if (!freq_found) { - cpsdvsr += 2; - scr = SCR_MIN; - } - } - if (cpsdvsr != 0) { - dev_dbg(&pl022->adev->dev, - "SSP Effective Frequency is %u\n", - (rate / (cpsdvsr * (1 + scr)))); - clk_freq->cpsdvsr = (u8) (cpsdvsr & 0xFF); - clk_freq->scr = (u8) (scr & 0xFF); - dev_dbg(&pl022->adev->dev, - "SSP cpsdvsr = %d, scr = %d\n", - clk_freq->cpsdvsr, clk_freq->scr); - } - } else { + min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX); + + if (!((freq <= max_tclk) && (freq >= min_tclk))) { dev_err(&pl022->adev->dev, "controller data is incorrect: out of range frequency"); return -EINVAL; } + + /* + * best_freq will give closest possible available rate (<= requested + * freq) for all values of scr & cpsdvsr. + */ + while ((cpsdvsr <= CPSDVR_MAX) && !found) { + while (scr <= SCR_MAX) { + tmp = spi_rate(rate, cpsdvsr, scr); + + if (tmp > freq) + scr++; + /* + * If found exact value, update and break. + * If found more closer value, update and continue. + */ + else if ((tmp == freq) || (tmp > best_freq)) { + best_freq = tmp; + best_cpsdvsr = cpsdvsr; + best_scr = scr; + + if (tmp == freq) + break; + } + scr++; + } + cpsdvsr += 2; + scr = SCR_MIN; + } + + clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF); + clk_freq->scr = (u8) (best_scr & 0xFF); + dev_dbg(&pl022->adev->dev, + "SSP Target Frequency is: %u, Effective Frequency is %u\n", + freq, best_freq); + dev_dbg(&pl022->adev->dev, "SSP cpsdvsr = %d, scr = %d\n", + clk_freq->cpsdvsr, clk_freq->scr); + return 0; } - /* * A piece of default chip info unless the platform * supplies it. @@ -1879,7 +1865,6 @@ static const struct pl022_config_chip pl022_default_chip_info = { .cs_control = null_cs_control, }; - /** * pl022_setup - setup function registered to SPI master framework * @spi: spi device which is requesting setup @@ -1956,7 +1941,6 @@ static int pl022_setup(struct spi_device *spi) goto err_config_params; } - status = verify_controller_parameters(pl022, chip_info); if (status) { dev_err(&spi->dev, "controller data is incorrect"); @@ -2096,7 +2080,8 @@ static int pl022_setup(struct spi_device *spi) } SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1); SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2); - SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3); + SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, + 3); /* Save controller_state */ spi_set_ctldata(spi, chip); @@ -2122,7 +2107,6 @@ static void pl022_cleanup(struct spi_device *spi) kfree(chip); } - static int __devinit pl022_probe(struct amba_device *adev, const struct amba_id *id) { @@ -2186,8 +2170,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) } printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", adev->res.start, pl022->virtbase); - pm_runtime_enable(dev); - pm_runtime_resume(dev); pl022->clk = clk_get(&adev->dev, NULL); if (IS_ERR(pl022->clk)) { @@ -2196,6 +2178,12 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) goto err_no_clk; } + status = clk_prepare(pl022->clk); + if (status) { + dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n"); + goto err_clk_prep; + } + /* Disable SSP */ writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); @@ -2235,22 +2223,22 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) goto err_spi_register; } dev_dbg(dev, "probe succeeded\n"); - /* - * Disable the silicon block pclk and any voltage domain and just - * power it up and clock it when it's needed - */ - amba_pclk_disable(adev); - amba_vcore_disable(adev); + + /* let runtime pm put suspend */ + pm_runtime_put(dev); return 0; err_spi_register: err_start_queue: err_init_queue: destroy_queue(pl022); - pl022_dma_remove(pl022); + if (platform_info->enable_dma) + pl022_dma_remove(pl022); + free_irq(adev->irq[0], pl022); - pm_runtime_disable(&adev->dev); err_no_irq: + clk_unprepare(pl022->clk); + err_clk_prep: clk_put(pl022->clk); err_no_clk: iounmap(pl022->virtbase); @@ -2271,13 +2259,22 @@ pl022_remove(struct amba_device *adev) if (!pl022) return 0; + /* + * undo pm_runtime_put() in probe. I assume that we're not + * accessing the primecell here. + */ + pm_runtime_get_noresume(&adev->dev); + /* Remove the queue */ if (destroy_queue(pl022) != 0) dev_err(&adev->dev, "queue remove failed\n"); load_ssp_default_config(pl022); - pl022_dma_remove(pl022); + if (pl022->master_info->enable_dma) + pl022_dma_remove(pl022); + free_irq(adev->irq[0], pl022); clk_disable(pl022->clk); + clk_unprepare(pl022->clk); clk_put(pl022->clk); iounmap(pl022->virtbase); amba_release_regions(adev); @@ -2288,46 +2285,70 @@ pl022_remove(struct amba_device *adev) return 0; } -#ifdef CONFIG_PM -static int pl022_suspend(struct amba_device *adev, pm_message_t state) +#ifdef CONFIG_SUSPEND +static int pl022_suspend(struct device *dev) { - struct pl022 *pl022 = amba_get_drvdata(adev); + struct pl022 *pl022 = dev_get_drvdata(dev); int status = 0; status = stop_queue(pl022); if (status) { - dev_warn(&adev->dev, "suspend cannot stop queue\n"); + dev_warn(dev, "suspend cannot stop queue\n"); return status; } - amba_vcore_enable(adev); - amba_pclk_enable(adev); + amba_vcore_enable(pl022->adev); + amba_pclk_enable(pl022->adev); load_ssp_default_config(pl022); - amba_pclk_disable(adev); - amba_vcore_disable(adev); - dev_dbg(&adev->dev, "suspended\n"); + amba_pclk_disable(pl022->adev); + amba_vcore_disable(pl022->adev); + dev_dbg(dev, "suspended\n"); return 0; } -static int pl022_resume(struct amba_device *adev) +static int pl022_resume(struct device *dev) { - struct pl022 *pl022 = amba_get_drvdata(adev); + struct pl022 *pl022 = dev_get_drvdata(dev); int status = 0; /* Start the queue running */ status = start_queue(pl022); if (status) - dev_err(&adev->dev, "problem starting queue (%d)\n", status); + dev_err(dev, "problem starting queue (%d)\n", status); else - dev_dbg(&adev->dev, "resumed\n"); + dev_dbg(dev, "resumed\n"); return status; } -#else -#define pl022_suspend NULL -#define pl022_resume NULL #endif /* CONFIG_PM */ +#ifdef CONFIG_PM_RUNTIME +static int pl022_runtime_suspend(struct device *dev) +{ + struct pl022 *pl022 = dev_get_drvdata(dev); + + clk_disable(pl022->clk); + amba_vcore_disable(pl022->adev); + + return 0; +} + +static int pl022_runtime_resume(struct device *dev) +{ + struct pl022 *pl022 = dev_get_drvdata(dev); + + amba_vcore_enable(pl022->adev); + clk_enable(pl022->clk); + + return 0; +} +#endif + +static const struct dev_pm_ops pl022_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume) + SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL) +}; + static struct vendor_data vendor_arm = { .fifodepth = 8, .max_bpw = 16, @@ -2337,7 +2358,6 @@ static struct vendor_data vendor_arm = { .loopback = true, }; - static struct vendor_data vendor_st = { .fifodepth = 32, .max_bpw = 32, @@ -2392,9 +2412,9 @@ static struct amba_id pl022_ids[] = { * and 32 locations deep TX/RX FIFO but no extended * CR0/CR1 register */ - .id = 0x00080023, - .mask = 0xffffffff, - .data = &vendor_st_pl023, + .id = 0x00080023, + .mask = 0xffffffff, + .data = &vendor_st_pl023, }, { .id = 0x10080023, @@ -2407,27 +2427,23 @@ static struct amba_id pl022_ids[] = { static struct amba_driver pl022_driver = { .drv = { .name = "ssp-pl022", + .pm = &pl022_dev_pm_ops, }, .id_table = pl022_ids, .probe = pl022_probe, .remove = __devexit_p(pl022_remove), - .suspend = pl022_suspend, - .resume = pl022_resume, }; - static int __init pl022_init(void) { return amba_driver_register(&pl022_driver); } - subsys_initcall(pl022_init); static void __exit pl022_exit(void) { amba_driver_unregister(&pl022_driver); } - module_exit(pl022_exit); MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index b267fd901e5..98ec53285fc 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -514,7 +514,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op) /* Request IRQ */ hw->irqnum = irq_of_parse_and_map(np, 0); ret = request_irq(hw->irqnum, spi_ppc4xx_int, - IRQF_DISABLED, "spi_ppc4xx_of", (void *)hw); + 0, "spi_ppc4xx_of", (void *)hw); if (ret) { dev_err(dev, "unable to allocate interrupt\n"); goto free_gpios; @@ -594,18 +594,7 @@ static struct platform_driver spi_ppc4xx_of_driver = { .of_match_table = spi_ppc4xx_of_match, }, }; - -static int __init spi_ppc4xx_init(void) -{ - return platform_driver_register(&spi_ppc4xx_of_driver); -} -module_init(spi_ppc4xx_init); - -static void __exit spi_ppc4xx_exit(void) -{ - platform_driver_unregister(&spi_ppc4xx_of_driver); -} -module_exit(spi_ppc4xx_exit); +module_platform_driver(spi_ppc4xx_of_driver); MODULE_AUTHOR("Gary Jennejohn & Stefan Roese"); MODULE_DESCRIPTION("Simple PPC4xx SPI Driver"); diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index 1996ac57ef9..b857a3e7af9 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -505,7 +505,7 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw) } } -static int __init s3c24xx_spi_probe(struct platform_device *pdev) +static int __devinit s3c24xx_spi_probe(struct platform_device *pdev) { struct s3c2410_spi_info *pdata; struct s3c24xx_spi *hw; @@ -661,7 +661,7 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) return err; } -static int __exit s3c24xx_spi_remove(struct platform_device *dev) +static int __devexit s3c24xx_spi_remove(struct platform_device *dev) { struct s3c24xx_spi *hw = platform_get_drvdata(dev); @@ -719,26 +719,15 @@ static const struct dev_pm_ops s3c24xx_spi_pmops = { MODULE_ALIAS("platform:s3c2410-spi"); static struct platform_driver s3c24xx_spi_driver = { - .remove = __exit_p(s3c24xx_spi_remove), + .probe = s3c24xx_spi_probe, + .remove = __devexit_p(s3c24xx_spi_remove), .driver = { .name = "s3c2410-spi", .owner = THIS_MODULE, .pm = S3C24XX_SPI_PMOPS, }, }; - -static int __init s3c24xx_spi_init(void) -{ - return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe); -} - -static void __exit s3c24xx_spi_exit(void) -{ - platform_driver_unregister(&s3c24xx_spi_driver); -} - -module_init(s3c24xx_spi_init); -module_exit(s3c24xx_spi_exit); +module_platform_driver(s3c24xx_spi_driver); MODULE_DESCRIPTION("S3C24XX SPI Driver"); MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 595dacc7645..019a7163572 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -131,6 +131,12 @@ #define RXBUSY (1<<2) #define TXBUSY (1<<3) +struct s3c64xx_spi_dma_data { + unsigned ch; + enum dma_data_direction direction; + enum dma_ch dmach; +}; + /** * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver. * @clk: Pointer to the spi clock. @@ -164,13 +170,14 @@ struct s3c64xx_spi_driver_data { struct work_struct work; struct list_head queue; spinlock_t lock; - enum dma_ch rx_dmach; - enum dma_ch tx_dmach; unsigned long sfr_start; struct completion xfer_completion; unsigned state; unsigned cur_mode, cur_bpw; unsigned cur_speed; + struct s3c64xx_spi_dma_data rx_dma; + struct s3c64xx_spi_dma_data tx_dma; + struct samsung_dma_ops *ops; }; static struct s3c2410_dma_client s3c64xx_spi_dma_client = { @@ -226,6 +233,78 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) writel(val, regs + S3C64XX_SPI_CH_CFG); } +static void s3c64xx_spi_dmacb(void *data) +{ + struct s3c64xx_spi_driver_data *sdd; + struct s3c64xx_spi_dma_data *dma = data; + unsigned long flags; + + if (dma->direction == DMA_FROM_DEVICE) + sdd = container_of(data, + struct s3c64xx_spi_driver_data, rx_dma); + else + sdd = container_of(data, + struct s3c64xx_spi_driver_data, tx_dma); + + spin_lock_irqsave(&sdd->lock, flags); + + if (dma->direction == DMA_FROM_DEVICE) { + sdd->state &= ~RXBUSY; + if (!(sdd->state & TXBUSY)) + complete(&sdd->xfer_completion); + } else { + sdd->state &= ~TXBUSY; + if (!(sdd->state & RXBUSY)) + complete(&sdd->xfer_completion); + } + + spin_unlock_irqrestore(&sdd->lock, flags); +} + +static void prepare_dma(struct s3c64xx_spi_dma_data *dma, + unsigned len, dma_addr_t buf) +{ + struct s3c64xx_spi_driver_data *sdd; + struct samsung_dma_prep_info info; + + if (dma->direction == DMA_FROM_DEVICE) + sdd = container_of((void *)dma, + struct s3c64xx_spi_driver_data, rx_dma); + else + sdd = container_of((void *)dma, + struct s3c64xx_spi_driver_data, tx_dma); + + info.cap = DMA_SLAVE; + info.len = len; + info.fp = s3c64xx_spi_dmacb; + info.fp_param = dma; + info.direction = dma->direction; + info.buf = buf; + + sdd->ops->prepare(dma->ch, &info); + sdd->ops->trigger(dma->ch); +} + +static int acquire_dma(struct s3c64xx_spi_driver_data *sdd) +{ + struct samsung_dma_info info; + + sdd->ops = samsung_dma_get_ops(); + + info.cap = DMA_SLAVE; + info.client = &s3c64xx_spi_dma_client; + info.width = sdd->cur_bpw / 8; + + info.direction = sdd->rx_dma.direction; + info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA; + sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info); + info.direction = sdd->tx_dma.direction; + info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA; + sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info); + + return 1; +} + static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, struct spi_device *spi, struct spi_transfer *xfer, int dma_mode) @@ -258,10 +337,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, chcfg |= S3C64XX_SPI_CH_TXCH_ON; if (dma_mode) { modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; - s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8); - s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd, - xfer->tx_dma, xfer->len); - s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START); + prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma); } else { switch (sdd->cur_bpw) { case 32: @@ -293,10 +369,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) | S3C64XX_SPI_PACKET_CNT_EN, regs + S3C64XX_SPI_PACKET_CNT); - s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8); - s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd, - xfer->rx_dma, xfer->len); - s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START); + prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma); } } @@ -482,46 +555,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) } } -static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, - int size, enum s3c2410_dma_buffresult res) -{ - struct s3c64xx_spi_driver_data *sdd = buf_id; - unsigned long flags; - - spin_lock_irqsave(&sdd->lock, flags); - - if (res == S3C2410_RES_OK) - sdd->state &= ~RXBUSY; - else - dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size); - - /* If the other done */ - if (!(sdd->state & TXBUSY)) - complete(&sdd->xfer_completion); - - spin_unlock_irqrestore(&sdd->lock, flags); -} - -static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, - int size, enum s3c2410_dma_buffresult res) -{ - struct s3c64xx_spi_driver_data *sdd = buf_id; - unsigned long flags; - - spin_lock_irqsave(&sdd->lock, flags); - - if (res == S3C2410_RES_OK) - sdd->state &= ~TXBUSY; - else - dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size); - - /* If the other done */ - if (!(sdd->state & RXBUSY)) - complete(&sdd->xfer_completion); - - spin_unlock_irqrestore(&sdd->lock, flags); -} - #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32) static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, @@ -696,12 +729,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd, if (use_dma) { if (xfer->tx_buf != NULL && (sdd->state & TXBUSY)) - s3c2410_dma_ctrl(sdd->tx_dmach, - S3C2410_DMAOP_FLUSH); + sdd->ops->stop(sdd->tx_dma.ch); if (xfer->rx_buf != NULL && (sdd->state & RXBUSY)) - s3c2410_dma_ctrl(sdd->rx_dmach, - S3C2410_DMAOP_FLUSH); + sdd->ops->stop(sdd->rx_dma.ch); } goto out; @@ -739,30 +770,6 @@ out: msg->complete(msg->context); } -static int acquire_dma(struct s3c64xx_spi_driver_data *sdd) -{ - if (s3c2410_dma_request(sdd->rx_dmach, - &s3c64xx_spi_dma_client, NULL) < 0) { - dev_err(&sdd->pdev->dev, "cannot get RxDMA\n"); - return 0; - } - s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb); - s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW, - sdd->sfr_start + S3C64XX_SPI_RX_DATA); - - if (s3c2410_dma_request(sdd->tx_dmach, - &s3c64xx_spi_dma_client, NULL) < 0) { - dev_err(&sdd->pdev->dev, "cannot get TxDMA\n"); - s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client); - return 0; - } - s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb); - s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM, - sdd->sfr_start + S3C64XX_SPI_TX_DATA); - - return 1; -} - static void s3c64xx_spi_work(struct work_struct *work) { struct s3c64xx_spi_driver_data *sdd = container_of(work, @@ -799,8 +806,8 @@ static void s3c64xx_spi_work(struct work_struct *work) spin_unlock_irqrestore(&sdd->lock, flags); /* Free DMA channels */ - s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client); - s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client); + sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client); + sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client); } static int s3c64xx_spi_transfer(struct spi_device *spi, @@ -1017,8 +1024,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) sdd->cntrlr_info = sci; sdd->pdev = pdev; sdd->sfr_start = mem_res->start; - sdd->tx_dmach = dmatx_res->start; - sdd->rx_dmach = dmarx_res->start; + sdd->tx_dma.dmach = dmatx_res->start; + sdd->tx_dma.direction = DMA_TO_DEVICE; + sdd->rx_dma.dmach = dmarx_res->start; + sdd->rx_dma.direction = DMA_FROM_DEVICE; sdd->cur_bpw = 8; @@ -1106,7 +1115,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) pdev->id, master->num_chipselect); dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n", mem_res->end, mem_res->start, - sdd->rx_dmach, sdd->tx_dmach); + sdd->rx_dma.dmach, sdd->tx_dma.dmach); return 0; diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index e00d94b2225..0f4834ae28c 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -635,7 +635,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) goto err2; } - ret = request_irq(i, sh_msiof_spi_irq, IRQF_DISABLED, + ret = request_irq(i, sh_msiof_spi_irq, 0, dev_name(&pdev->dev), p); if (ret) { dev_err(&pdev->dev, "unable to request irq\n"); @@ -730,18 +730,7 @@ static struct platform_driver sh_msiof_spi_drv = { .pm = &sh_msiof_spi_dev_pm_ops, }, }; - -static int __init sh_msiof_spi_init(void) -{ - return platform_driver_register(&sh_msiof_spi_drv); -} -module_init(sh_msiof_spi_init); - -static void __exit sh_msiof_spi_exit(void) -{ - platform_driver_unregister(&sh_msiof_spi_drv); -} -module_exit(sh_msiof_spi_exit); +module_platform_driver(sh_msiof_spi_drv); MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver"); MODULE_AUTHOR("Magnus Damm"); diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c index e7779c09f6e..8844bc34278 100644 --- a/drivers/spi/spi-sh-sci.c +++ b/drivers/spi/spi-sh-sci.c @@ -186,18 +186,7 @@ static struct platform_driver sh_sci_spi_drv = { .owner = THIS_MODULE, }, }; - -static int __init sh_sci_spi_init(void) -{ - return platform_driver_register(&sh_sci_spi_drv); -} -module_init(sh_sci_spi_init); - -static void __exit sh_sci_spi_exit(void) -{ - platform_driver_unregister(&sh_sci_spi_drv); -} -module_exit(sh_sci_spi_exit); +module_platform_driver(sh_sci_spi_drv); MODULE_DESCRIPTION("SH SCI SPI Driver"); MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c index 9eedd71ad89..70c8af9f7cc 100644 --- a/drivers/spi/spi-sh.c +++ b/drivers/spi/spi-sh.c @@ -484,7 +484,7 @@ static int __devinit spi_sh_probe(struct platform_device *pdev) goto error2; } - ret = request_irq(irq, spi_sh_irq, IRQF_DISABLED, "spi_sh", ss); + ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss); if (ret < 0) { dev_err(&pdev->dev, "request_irq error\n"); goto error3; @@ -524,18 +524,7 @@ static struct platform_driver spi_sh_driver = { .owner = THIS_MODULE, }, }; - -static int __init spi_sh_init(void) -{ - return platform_driver_register(&spi_sh_driver); -} -module_init(spi_sh_init); - -static void __exit spi_sh_exit(void) -{ - platform_driver_unregister(&spi_sh_driver); -} -module_exit(spi_sh_exit); +module_platform_driver(spi_sh_driver); MODULE_DESCRIPTION("SH SPI bus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-stmp.c b/drivers/spi/spi-stmp.c index fadff76eb7e..58e38528532 100644 --- a/drivers/spi/spi-stmp.c +++ b/drivers/spi/spi-stmp.c @@ -659,19 +659,8 @@ static struct platform_driver stmp_spi_driver = { .suspend = stmp_spi_suspend, .resume = stmp_spi_resume, }; +module_platform_driver(stmp_spi_driver); -static int __init stmp_spi_init(void) -{ - return platform_driver_register(&stmp_spi_driver); -} - -static void __exit stmp_spi_exit(void) -{ - platform_driver_unregister(&stmp_spi_driver); -} - -module_init(stmp_spi_init); -module_exit(stmp_spi_exit); module_param(pio, int, S_IRUGO); module_param(clock, int, S_IRUGO); MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>"); diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c index a5a6302dc8e..ae6d78a3e91 100644 --- a/drivers/spi/spi-tegra.c +++ b/drivers/spi/spi-tegra.c @@ -18,6 +18,7 @@ */ #include <linux/kernel.h> +#include <linux/module.h> #include <linux/init.h> #include <linux/err.h> #include <linux/platform_device.h> @@ -464,7 +465,7 @@ static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m) return 0; } -static int __init spi_tegra_probe(struct platform_device *pdev) +static int __devinit spi_tegra_probe(struct platform_device *pdev) { struct spi_master *master; struct spi_tegra_data *tspi; @@ -612,19 +613,9 @@ static struct platform_driver spi_tegra_driver = { .owner = THIS_MODULE, .of_match_table = spi_tegra_of_match_table, }, + .probe = spi_tegra_probe, .remove = __devexit_p(spi_tegra_remove), }; - -static int __init spi_tegra_init(void) -{ - return platform_driver_probe(&spi_tegra_driver, spi_tegra_probe); -} -module_init(spi_tegra_init); - -static void __exit spi_tegra_exit(void) -{ - platform_driver_unregister(&spi_tegra_driver); -} -module_exit(spi_tegra_exit); +module_platform_driver(spi_tegra_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-ti-ssp.c b/drivers/spi/spi-ti-ssp.c index ee22795c797..7963c60063d 100644 --- a/drivers/spi/spi-ti-ssp.c +++ b/drivers/spi/spi-ti-ssp.c @@ -383,18 +383,7 @@ static struct platform_driver ti_ssp_spi_driver = { .owner = THIS_MODULE, }, }; - -static int __init ti_ssp_spi_init(void) -{ - return platform_driver_register(&ti_ssp_spi_driver); -} -module_init(ti_ssp_spi_init); - -static void __exit ti_ssp_spi_exit(void) -{ - platform_driver_unregister(&ti_ssp_spi_driver); -} -module_exit(ti_ssp_spi_exit); +module_platform_driver(ti_ssp_spi_driver); MODULE_DESCRIPTION("SSP SPI Master"); MODULE_AUTHOR("Cyril Chemparathy"); diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 1d23f383186..6a80749391d 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -50,6 +50,8 @@ #define PCH_RX_THOLD 7 #define PCH_RX_THOLD_MAX 15 +#define PCH_TX_THOLD 2 + #define PCH_MAX_BAUDRATE 5000000 #define PCH_MAX_FIFO_DEPTH 16 @@ -58,6 +60,7 @@ #define PCH_SLEEP_TIME 10 #define SSN_LOW 0x02U +#define SSN_HIGH 0x03U #define SSN_NO_CONTROL 0x00U #define PCH_MAX_CS 0xFF #define PCI_DEVICE_ID_GE_SPI 0x8816 @@ -316,16 +319,19 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val, /* if transfer complete interrupt */ if (reg_spsr_val & SPSR_FI_BIT) { - if (tx_index < bpw_len) + if ((tx_index == bpw_len) && (rx_index == tx_index)) { + /* disable interrupts */ + pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL); + + /* transfer is completed; + inform pch_spi_process_messages */ + data->transfer_complete = true; + data->transfer_active = false; + wake_up(&data->wait); + } else { dev_err(&data->master->dev, "%s : Transfer is not completed", __func__); - /* disable interrupts */ - pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL); - - /* transfer is completed;inform pch_spi_process_messages */ - data->transfer_complete = true; - data->transfer_active = false; - wake_up(&data->wait); + } } } @@ -348,16 +354,26 @@ static irqreturn_t pch_spi_handler(int irq, void *dev_id) "%s returning due to suspend\n", __func__); return IRQ_NONE; } - if (data->use_dma) - return IRQ_NONE; io_remap_addr = data->io_remap_addr; spsr = io_remap_addr + PCH_SPSR; reg_spsr_val = ioread32(spsr); - if (reg_spsr_val & SPSR_ORF_BIT) - dev_err(&board_dat->pdev->dev, "%s Over run error", __func__); + if (reg_spsr_val & SPSR_ORF_BIT) { + dev_err(&board_dat->pdev->dev, "%s Over run error\n", __func__); + if (data->current_msg->complete != 0) { + data->transfer_complete = true; + data->current_msg->status = -EIO; + data->current_msg->complete(data->current_msg->context); + data->bcurrent_msg_processing = false; + data->current_msg = NULL; + data->cur_trans = NULL; + } + } + + if (data->use_dma) + return IRQ_NONE; /* Check if the interrupt is for SPI device */ if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) { @@ -756,10 +772,6 @@ static void pch_spi_set_ir(struct pch_spi_data *data) wait_event_interruptible(data->wait, data->transfer_complete); - pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL); - dev_dbg(&data->master->dev, - "%s:no more control over SSN-writing 0 to SSNXCR.", __func__); - /* clear all interrupts */ pch_spi_writereg(data->master, PCH_SPSR, pch_spi_readreg(data->master, PCH_SPSR)); @@ -815,10 +827,11 @@ static void pch_spi_copy_rx_data_for_dma(struct pch_spi_data *data, int bpw) } } -static void pch_spi_start_transfer(struct pch_spi_data *data) +static int pch_spi_start_transfer(struct pch_spi_data *data) { struct pch_spi_dma_ctrl *dma; unsigned long flags; + int rtn; dma = &data->dma; @@ -833,19 +846,23 @@ static void pch_spi_start_transfer(struct pch_spi_data *data) initiating the transfer. */ dev_dbg(&data->master->dev, "%s:waiting for transfer to get over\n", __func__); - wait_event_interruptible(data->wait, data->transfer_complete); + rtn = wait_event_interruptible_timeout(data->wait, + data->transfer_complete, + msecs_to_jiffies(2 * HZ)); dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent, DMA_FROM_DEVICE); + + dma_sync_sg_for_cpu(&data->master->dev, dma->sg_tx_p, dma->nent, + DMA_FROM_DEVICE); + memset(data->dma.tx_buf_virt, 0, PAGE_SIZE); + async_tx_ack(dma->desc_rx); async_tx_ack(dma->desc_tx); kfree(dma->sg_tx_p); kfree(dma->sg_rx_p); spin_lock_irqsave(&data->lock, flags); - pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL); - dev_dbg(&data->master->dev, - "%s:no more control over SSN-writing 0 to SSNXCR.", __func__); /* clear fifo threshold, disable interrupts, disable SPI transfer */ pch_spi_setclr_reg(data->master, PCH_SPCR, 0, @@ -858,6 +875,8 @@ static void pch_spi_start_transfer(struct pch_spi_data *data) pch_spi_clear_fifo(data->master); spin_unlock_irqrestore(&data->lock, flags); + + return rtn; } static void pch_dma_rx_complete(void *arg) @@ -1023,8 +1042,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) /* set receive fifo threshold and transmit fifo threshold */ pch_spi_setclr_reg(data->master, PCH_SPCR, ((size - 1) << SPCR_RFIC_FIELD) | - ((PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE) << - SPCR_TFIC_FIELD), + (PCH_TX_THOLD << SPCR_TFIC_FIELD), MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS); spin_unlock_irqrestore(&data->lock, flags); @@ -1035,13 +1053,20 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) /* offset, length setting */ sg = dma->sg_rx_p; for (i = 0; i < num; i++, sg++) { - if (i == 0) { - sg->offset = 0; + if (i == (num - 2)) { + sg->offset = size * i; + sg->offset = sg->offset * (*bpw / 8); sg_set_page(sg, virt_to_page(dma->rx_buf_virt), rem, sg->offset); sg_dma_len(sg) = rem; + } else if (i == (num - 1)) { + sg->offset = size * (i - 1) + rem; + sg->offset = sg->offset * (*bpw / 8); + sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size, + sg->offset); + sg_dma_len(sg) = size; } else { - sg->offset = rem + size * (i - 1); + sg->offset = size * i; sg->offset = sg->offset * (*bpw / 8); sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size, sg->offset); @@ -1065,6 +1090,16 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) dma->desc_rx = desc_rx; /* TX */ + if (data->bpw_len > PCH_DMA_TRANS_SIZE) { + num = data->bpw_len / PCH_DMA_TRANS_SIZE; + size = PCH_DMA_TRANS_SIZE; + rem = 16; + } else { + num = 1; + size = data->bpw_len; + rem = data->bpw_len; + } + dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */ /* offset, length setting */ @@ -1162,6 +1197,7 @@ static void pch_spi_process_messages(struct work_struct *pwork) if (data->use_dma) pch_spi_request_dma(data, data->current_msg->spi->bits_per_word); + pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL); do { /* If we are already processing a message get the next transfer structure from the message otherwise retrieve @@ -1184,7 +1220,8 @@ static void pch_spi_process_messages(struct work_struct *pwork) if (data->use_dma) { pch_spi_handle_dma(data, &bpw); - pch_spi_start_transfer(data); + if (!pch_spi_start_transfer(data)) + goto out; pch_spi_copy_rx_data_for_dma(data, bpw); } else { pch_spi_set_tx(data, &bpw); @@ -1222,6 +1259,8 @@ static void pch_spi_process_messages(struct work_struct *pwork) } while (data->cur_trans != NULL); +out: + pch_spi_writereg(data->master, PCH_SSNXCR, SSN_HIGH); if (data->use_dma) pch_spi_release_dma(data); } diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 4d2c75df886..4c5a663b9fa 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -538,18 +538,7 @@ static struct platform_driver xilinx_spi_driver = { .of_match_table = xilinx_spi_of_match, }, }; - -static int __init xilinx_spi_pltfm_init(void) -{ - return platform_driver_register(&xilinx_spi_driver); -} -module_init(xilinx_spi_pltfm_init); - -static void __exit xilinx_spi_pltfm_exit(void) -{ - platform_driver_unregister(&xilinx_spi_driver); -} -module_exit(xilinx_spi_pltfm_exit); +module_platform_driver(xilinx_spi_driver); MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); MODULE_DESCRIPTION("Xilinx SPI driver"); |