diff options
Diffstat (limited to 'drivers/spi')
28 files changed, 479 insertions, 237 deletions
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index 5e7314ac51e..a537f8dffc0 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -134,7 +134,7 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t) hw->tx = t->tx_buf; hw->rx = t->rx_buf; hw->count = 0; - hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8; + hw->bytes_per_word = t->bits_per_word / 8; hw->len = t->len / hw->bytes_per_word; if (hw->irq >= 0) { diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 9a5d7791c5f..e504b763605 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -24,17 +24,24 @@ #include <linux/spi/spi_bitbang.h> #include <linux/bitops.h> #include <linux/gpio.h> +#include <linux/clk.h> +#include <linux/err.h> #include <asm/mach-ath79/ar71xx_regs.h> #include <asm/mach-ath79/ath79_spi_platform.h> #define DRV_NAME "ath79-spi" +#define ATH79_SPI_RRW_DELAY_FACTOR 12000 +#define MHZ (1000 * 1000) + struct ath79_spi { struct spi_bitbang bitbang; u32 ioc_base; u32 reg_ctrl; void __iomem *base; + struct clk *clk; + unsigned rrw_delay; }; static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg) @@ -52,6 +59,12 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi) return spi_master_get_devdata(spi->master); } +static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs) +{ + if (nsecs > sp->rrw_delay) + ndelay(nsecs - sp->rrw_delay); +} + static void ath79_spi_chipselect(struct spi_device *spi, int is_active) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); @@ -83,15 +96,8 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active) } -static int ath79_spi_setup_cs(struct spi_device *spi) +static void ath79_spi_enable(struct ath79_spi *sp) { - struct ath79_spi *sp = ath79_spidev_to_sp(spi); - struct ath79_spi_controller_data *cdata; - - cdata = spi->controller_data; - if (spi->chip_select && !cdata) - return -EINVAL; - /* enable GPIO mode */ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); @@ -101,44 +107,48 @@ static int ath79_spi_setup_cs(struct spi_device *spi) /* TODO: setup speed? */ ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); +} - if (spi->chip_select) { - int status = 0; +static void ath79_spi_disable(struct ath79_spi *sp) +{ + /* restore CTRL register */ + ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl); + /* disable GPIO mode */ + ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); +} - status = gpio_request(cdata->gpio, dev_name(&spi->dev)); - if (status) - return status; +static int ath79_spi_setup_cs(struct spi_device *spi) +{ + struct ath79_spi_controller_data *cdata; + int status; - status = gpio_direction_output(cdata->gpio, - spi->mode & SPI_CS_HIGH); - if (status) { - gpio_free(cdata->gpio); - return status; - } - } else { + cdata = spi->controller_data; + if (spi->chip_select && !cdata) + return -EINVAL; + + status = 0; + if (spi->chip_select) { + unsigned long flags; + + flags = GPIOF_DIR_OUT; if (spi->mode & SPI_CS_HIGH) - sp->ioc_base |= AR71XX_SPI_IOC_CS0; + flags |= GPIOF_INIT_HIGH; else - sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); + flags |= GPIOF_INIT_LOW; + + status = gpio_request_one(cdata->gpio, flags, + dev_name(&spi->dev)); } - return 0; + return status; } static void ath79_spi_cleanup_cs(struct spi_device *spi) { - struct ath79_spi *sp = ath79_spidev_to_sp(spi); - if (spi->chip_select) { struct ath79_spi_controller_data *cdata = spi->controller_data; gpio_free(cdata->gpio); } - - /* restore CTRL register */ - ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl); - /* disable GPIO mode */ - ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); } static int ath79_spi_setup(struct spi_device *spi) @@ -184,7 +194,11 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs, /* setup MSB (to slave) on trailing edge */ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out); + ath79_spi_delay(sp, nsecs); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK); + ath79_spi_delay(sp, nsecs); + if (bits == 1) + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out); word <<= 1; } @@ -198,6 +212,7 @@ static int ath79_spi_probe(struct platform_device *pdev) struct ath79_spi *sp; struct ath79_spi_platform_data *pdata; struct resource *r; + unsigned long rate; int ret; master = spi_alloc_master(&pdev->dev, sizeof(*sp)); @@ -236,12 +251,39 @@ static int ath79_spi_probe(struct platform_device *pdev) goto err_put_master; } + sp->clk = clk_get(&pdev->dev, "ahb"); + if (IS_ERR(sp->clk)) { + ret = PTR_ERR(sp->clk); + goto err_unmap; + } + + ret = clk_enable(sp->clk); + if (ret) + goto err_clk_put; + + rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ); + if (!rate) { + ret = -EINVAL; + goto err_clk_disable; + } + + sp->rrw_delay = ATH79_SPI_RRW_DELAY_FACTOR / rate; + dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n", + sp->rrw_delay); + + ath79_spi_enable(sp); ret = spi_bitbang_start(&sp->bitbang); if (ret) - goto err_unmap; + goto err_disable; return 0; +err_disable: + ath79_spi_disable(sp); +err_clk_disable: + clk_disable(sp->clk); +err_clk_put: + clk_put(sp->clk); err_unmap: iounmap(sp->base); err_put_master: @@ -256,6 +298,9 @@ static int ath79_spi_remove(struct platform_device *pdev) struct ath79_spi *sp = platform_get_drvdata(pdev); spi_bitbang_stop(&sp->bitbang); + ath79_spi_disable(sp); + clk_disable(sp->clk); + clk_put(sp->clk); iounmap(sp->base); platform_set_drvdata(pdev, NULL); spi_master_put(sp->bitbang.master); @@ -263,9 +308,15 @@ static int ath79_spi_remove(struct platform_device *pdev) return 0; } +static void ath79_spi_shutdown(struct platform_device *pdev) +{ + ath79_spi_remove(pdev); +} + static struct platform_driver ath79_spi_driver = { .probe = ath79_spi_probe, .remove = ath79_spi_remove, + .shutdown = ath79_spi_shutdown, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index ab34497bcfe..656d137db25 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1088,7 +1088,7 @@ static struct platform_driver atmel_spi_driver = { .suspend = atmel_spi_suspend, .resume = atmel_spi_resume, .probe = atmel_spi_probe, - .remove = __exit_p(atmel_spi_remove), + .remove = atmel_spi_remove, }; module_platform_driver(atmel_spi_driver); diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 4de66d1cfe5..44dd34b6ad0 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -717,7 +717,7 @@ static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw) } } -static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw) +static void au1550_spi_setup_psc_as_spi(struct au1550_spi *hw) { u32 stat, cfg; @@ -766,7 +766,7 @@ static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw) } -static int __init au1550_spi_probe(struct platform_device *pdev) +static int au1550_spi_probe(struct platform_device *pdev) { struct au1550_spi *hw; struct spi_master *master; @@ -968,7 +968,7 @@ err_nomem: return err; } -static int __exit au1550_spi_remove(struct platform_device *pdev) +static int au1550_spi_remove(struct platform_device *pdev) { struct au1550_spi *hw = platform_get_drvdata(pdev); @@ -997,7 +997,7 @@ static int __exit au1550_spi_remove(struct platform_device *pdev) MODULE_ALIAS("platform:au1550-spi"); static struct platform_driver au1550_spi_drv = { - .remove = __exit_p(au1550_spi_remove), + .remove = au1550_spi_remove, .driver = { .name = "au1550-spi", .owner = THIS_MODULE, diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index f44ab550853..9578af782a7 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -37,6 +37,8 @@ #define PFX KBUILD_MODNAME +#define BCM63XX_SPI_MAX_PREPEND 15 + struct bcm63xx_spi { struct completion done; @@ -49,16 +51,10 @@ struct bcm63xx_spi { unsigned int msg_type_shift; unsigned int msg_ctl_width; - /* Data buffers */ - const unsigned char *tx_ptr; - unsigned char *rx_ptr; - /* data iomem */ u8 __iomem *tx_io; const u8 __iomem *rx_io; - int remaining_bytes; - struct clk *clk; struct platform_device *pdev; }; @@ -175,24 +171,17 @@ static int bcm63xx_spi_setup(struct spi_device *spi) return 0; } -/* Fill the TX FIFO with as many bytes as possible */ -static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs) -{ - u8 size; - - /* Fill the Tx FIFO with as many bytes as possible */ - size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes : - bs->fifo_size; - memcpy_toio(bs->tx_io, bs->tx_ptr, size); - bs->remaining_bytes -= size; -} - -static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi, - struct spi_transfer *t) +static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, + unsigned int num_transfers) { struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); u16 msg_ctl; u16 cmd; + u8 rx_tail; + unsigned int i, timeout = 0, prepend_len = 0, len = 0; + struct spi_transfer *t = first; + bool do_rx = false; + bool do_tx = false; /* Disable the CMD_DONE interrupt */ bcm_spi_writeb(bs, 0, SPI_INT_MASK); @@ -200,25 +189,45 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi, dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", t->tx_buf, t->rx_buf, t->len); - /* Transmitter is inhibited */ - bs->tx_ptr = t->tx_buf; - bs->rx_ptr = t->rx_buf; + if (num_transfers > 1 && t->tx_buf && t->len <= BCM63XX_SPI_MAX_PREPEND) + prepend_len = t->len; - if (t->tx_buf) { - bs->remaining_bytes = t->len; - bcm63xx_spi_fill_tx_fifo(bs); + /* prepare the buffer */ + for (i = 0; i < num_transfers; i++) { + if (t->tx_buf) { + do_tx = true; + memcpy_toio(bs->tx_io + len, t->tx_buf, t->len); + + /* don't prepend more than one tx */ + if (t != first) + prepend_len = 0; + } + + if (t->rx_buf) { + do_rx = true; + /* prepend is half-duplex write only */ + if (t == first) + prepend_len = 0; + } + + len += t->len; + + t = list_entry(t->transfer_list.next, struct spi_transfer, + transfer_list); } + len -= prepend_len; + init_completion(&bs->done); /* Fill in the Message control register */ - msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT); + msg_ctl = (len << SPI_BYTE_CNT_SHIFT); - if (t->rx_buf && t->tx_buf) + if (do_rx && do_tx && prepend_len == 0) msg_ctl |= (SPI_FD_RW << bs->msg_type_shift); - else if (t->rx_buf) + else if (do_rx) msg_ctl |= (SPI_HD_R << bs->msg_type_shift); - else if (t->tx_buf) + else if (do_tx) msg_ctl |= (SPI_HD_W << bs->msg_type_shift); switch (bs->msg_ctl_width) { @@ -232,14 +241,41 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi, /* Issue the transfer */ cmd = SPI_CMD_START_IMMEDIATE; - cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); + cmd |= (prepend_len << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT); bcm_spi_writew(bs, cmd, SPI_CMD); /* Enable the CMD_DONE interrupt */ bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); - return t->len - bs->remaining_bytes; + timeout = wait_for_completion_timeout(&bs->done, HZ); + if (!timeout) + return -ETIMEDOUT; + + /* read out all data */ + rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL); + + if (do_rx && rx_tail != len) + return -EIO; + + if (!rx_tail) + return 0; + + len = 0; + t = first; + /* Read out all the data */ + for (i = 0; i < num_transfers; i++) { + if (t->rx_buf) + memcpy_fromio(t->rx_buf, bs->rx_io + len, t->len); + + if (t != first || prepend_len == 0) + len += t->len; + + t = list_entry(t->transfer_list.next, struct spi_transfer, + transfer_list); + } + + return 0; } static int bcm63xx_spi_prepare_transfer(struct spi_master *master) @@ -264,41 +300,76 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master, struct spi_message *m) { struct bcm63xx_spi *bs = spi_master_get_devdata(master); - struct spi_transfer *t; + struct spi_transfer *t, *first = NULL; struct spi_device *spi = m->spi; int status = 0; - unsigned int timeout = 0; - + unsigned int n_transfers = 0, total_len = 0; + bool can_use_prepend = false; + + /* + * This SPI controller does not support keeping CS active after a + * transfer. + * Work around this by merging as many transfers we can into one big + * full-duplex transfers. + */ list_for_each_entry(t, &m->transfers, transfer_list) { - unsigned int len = t->len; - u8 rx_tail; - status = bcm63xx_spi_check_transfer(spi, t); if (status < 0) goto exit; - /* configure adapter for a new transfer */ - bcm63xx_spi_setup_transfer(spi, t); + if (!first) + first = t; + + n_transfers++; + total_len += t->len; + + if (n_transfers == 2 && !first->rx_buf && !t->tx_buf && + first->len <= BCM63XX_SPI_MAX_PREPEND) + can_use_prepend = true; + else if (can_use_prepend && t->tx_buf) + can_use_prepend = false; + + /* we can only transfer one fifo worth of data */ + if ((can_use_prepend && + total_len > (bs->fifo_size + BCM63XX_SPI_MAX_PREPEND)) || + (!can_use_prepend && total_len > bs->fifo_size)) { + dev_err(&spi->dev, "unable to do transfers larger than FIFO size (%i > %i)\n", + total_len, bs->fifo_size); + status = -EINVAL; + goto exit; + } + + /* all combined transfers have to have the same speed */ + if (t->speed_hz != first->speed_hz) { + dev_err(&spi->dev, "unable to change speed between transfers\n"); + status = -EINVAL; + goto exit; + } - while (len) { - /* send the data */ - len -= bcm63xx_txrx_bufs(spi, t); + /* CS will be deasserted directly after transfer */ + if (t->delay_usecs) { + dev_err(&spi->dev, "unable to keep CS asserted after transfer\n"); + status = -EINVAL; + goto exit; + } + + if (t->cs_change || + list_is_last(&t->transfer_list, &m->transfers)) { + /* configure adapter for a new transfer */ + bcm63xx_spi_setup_transfer(spi, first); - timeout = wait_for_completion_timeout(&bs->done, HZ); - if (!timeout) { - status = -ETIMEDOUT; + /* send the data */ + status = bcm63xx_txrx_bufs(spi, first, n_transfers); + if (status) goto exit; - } - /* read out all data */ - rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL); + m->actual_length += total_len; - /* Read out all the data */ - if (rx_tail) - memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail); + first = NULL; + n_transfers = 0; + total_len = 0; + can_use_prepend = false; } - - m->actual_length += t->len; } exit: m->status = status; diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index ac7ffca7ba4..39b0d1711b4 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -416,8 +416,7 @@ bfin_sport_spi_pump_transfers(unsigned long data) drv_data->cs_change = transfer->cs_change; /* Bits per word setup */ - bits_per_word = transfer->bits_per_word ? : - message->spi->bits_per_word ? : 8; + bits_per_word = transfer->bits_per_word; if (bits_per_word % 16 == 0) drv_data->ops = &bfin_sport_transfer_ops_u16; else diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 0429d833f75..317f564c899 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -642,8 +642,7 @@ static void bfin_spi_pump_transfers(unsigned long data) drv_data->cs_change = transfer->cs_change; /* Bits per word setup */ - bits_per_word = transfer->bits_per_word ? : - message->spi->bits_per_word ? : 8; + bits_per_word = transfer->bits_per_word; if (bits_per_word % 16 == 0) { drv_data->n_bytes = bits_per_word/8; drv_data->len = (transfer->len) >> 1; @@ -1274,7 +1273,7 @@ static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data) return 0; } -static int __init bfin_spi_probe(struct platform_device *pdev) +static int bfin_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct bfin5xx_spi_master *platform_info; diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 328c4dcd3d5..a63d7da3bfe 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -69,7 +69,7 @@ static unsigned bitbang_txrx_8( unsigned ns, struct spi_transfer *t ) { - unsigned bits = t->bits_per_word ? : spi->bits_per_word; + unsigned bits = t->bits_per_word; unsigned count = t->len; const u8 *tx = t->tx_buf; u8 *rx = t->rx_buf; @@ -95,7 +95,7 @@ static unsigned bitbang_txrx_16( unsigned ns, struct spi_transfer *t ) { - unsigned bits = t->bits_per_word ? : spi->bits_per_word; + unsigned bits = t->bits_per_word; unsigned count = t->len; const u16 *tx = t->tx_buf; u16 *rx = t->rx_buf; @@ -121,7 +121,7 @@ static unsigned bitbang_txrx_32( unsigned ns, struct spi_transfer *t ) { - unsigned bits = t->bits_per_word ? : spi->bits_per_word; + unsigned bits = t->bits_per_word; unsigned count = t->len; const u32 *tx = t->tx_buf; u32 *rx = t->rx_buf; diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 1366c4620d5..a11cbf02691 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -68,7 +68,7 @@ static int spi_clps711x_setup_xfer(struct spi_device *spi, struct spi_transfer *xfer) { u32 speed = xfer->speed_hz ? : spi->max_speed_hz; - u8 bpw = xfer->bits_per_word ? : spi->bits_per_word; + u8 bpw = xfer->bits_per_word; struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master); if (bpw != 8) { diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 58466b810da..7b5cc9e4e94 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -329,8 +329,7 @@ static int mcfqspi_transfer_one_message(struct spi_master *master, mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high); mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE); - if ((t->bits_per_word ? t->bits_per_word : - spi->bits_per_word) == 8) + if (t->bits_per_word == 8) mcfqspi_transfer_msg8(mcfqspi, t->len, t->tx_buf, t->rx_buf); else diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 13661e129d9..8234d225972 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -28,6 +28,8 @@ #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/edma.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> #include <linux/slab.h> @@ -135,7 +137,7 @@ struct davinci_spi { int dma_rx_chnum; int dma_tx_chnum; - struct davinci_spi_platform_data *pdata; + struct davinci_spi_platform_data pdata; void (*get_rx)(u32 rx_data, struct davinci_spi *); u32 (*get_tx)(struct davinci_spi *); @@ -213,7 +215,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) bool gpio_chipsel = false; dspi = spi_master_get_devdata(spi->master); - pdata = dspi->pdata; + pdata = &dspi->pdata; if (pdata->chip_sel && chip_sel < pdata->num_chipselect && pdata->chip_sel[chip_sel] != SPI_INTERN_CS) @@ -392,7 +394,7 @@ static int davinci_spi_setup(struct spi_device *spi) struct davinci_spi_platform_data *pdata; dspi = spi_master_get_devdata(spi->master); - pdata = dspi->pdata; + pdata = &dspi->pdata; /* if bits per word length is zero then set it default 8 */ if (!spi->bits_per_word) @@ -534,7 +536,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) struct scatterlist sg_rx, sg_tx; dspi = spi_master_get_devdata(spi->master); - pdata = dspi->pdata; + pdata = &dspi->pdata; spicfg = (struct davinci_spi_config *)spi->controller_data; if (!spicfg) spicfg = &davinci_spi_default_cfg; @@ -700,6 +702,19 @@ err_alloc_dummy_buf: } /** + * dummy_thread_fn - dummy thread function + * @irq: IRQ number for this SPI Master + * @context_data: structure for SPI Master controller davinci_spi + * + * This is to satisfy the request_threaded_irq() API so that the irq + * handler is called in interrupt context. + */ +static irqreturn_t dummy_thread_fn(s32 irq, void *data) +{ + return IRQ_HANDLED; +} + +/** * davinci_spi_irq - Interrupt handler for SPI Master Controller * @irq: IRQ number for this SPI Master * @context_data: structure for SPI Master controller davinci_spi @@ -758,6 +773,70 @@ rx_dma_failed: return r; } +#if defined(CONFIG_OF) +static const struct of_device_id davinci_spi_of_match[] = { + { + .compatible = "ti,dm644x-spi", + }, + { + .compatible = "ti,da8xx-spi", + .data = (void *)SPI_VERSION_2, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, davini_spi_of_match); + +/** + * spi_davinci_get_pdata - Get platform data from DTS binding + * @pdev: ptr to platform data + * @dspi: ptr to driver data + * + * Parses and populates pdata in dspi from device tree bindings. + * + * NOTE: Not all platform data params are supported currently. + */ +static int spi_davinci_get_pdata(struct platform_device *pdev, + struct davinci_spi *dspi) +{ + struct device_node *node = pdev->dev.of_node; + struct davinci_spi_platform_data *pdata; + unsigned int num_cs, intr_line = 0; + const struct of_device_id *match; + + pdata = &dspi->pdata; + + pdata->version = SPI_VERSION_1; + match = of_match_device(of_match_ptr(davinci_spi_of_match), + &pdev->dev); + if (!match) + return -ENODEV; + + /* match data has the SPI version number for SPI_VERSION_2 */ + if (match->data == (void *)SPI_VERSION_2) + pdata->version = SPI_VERSION_2; + + /* + * default num_cs is 1 and all chipsel are internal to the chip + * indicated by chip_sel being NULL. GPIO based CS is not + * supported yet in DT bindings. + */ + num_cs = 1; + of_property_read_u32(node, "num-cs", &num_cs); + pdata->num_chipselect = num_cs; + of_property_read_u32(node, "ti,davinci-spi-intr-line", &intr_line); + pdata->intr_line = intr_line; + return 0; +} +#else +#define davinci_spi_of_match NULL +static struct davinci_spi_platform_data + *spi_davinci_get_pdata(struct platform_device *pdev, + struct davinci_spi *dspi) +{ + return -ENODEV; +} +#endif + /** * davinci_spi_probe - probe function for SPI Master Controller * @pdev: platform_device structure which contains plateform specific data @@ -780,12 +859,6 @@ static int davinci_spi_probe(struct platform_device *pdev) int i = 0, ret = 0; u32 spipc0; - pdata = pdev->dev.platform_data; - if (pdata == NULL) { - ret = -ENODEV; - goto err; - } - master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi)); if (master == NULL) { ret = -ENOMEM; @@ -800,6 +873,19 @@ static int davinci_spi_probe(struct platform_device *pdev) goto free_master; } + if (pdev->dev.platform_data) { + pdata = pdev->dev.platform_data; + dspi->pdata = *pdata; + } else { + /* update dspi pdata with that from the DT */ + ret = spi_davinci_get_pdata(pdev, dspi); + if (ret < 0) + goto free_master; + } + + /* pdata in dspi is now updated and point pdata to that */ + pdata = &dspi->pdata; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (r == NULL) { ret = -ENOENT; @@ -807,7 +893,6 @@ static int davinci_spi_probe(struct platform_device *pdev) } dspi->pbase = r->start; - dspi->pdata = pdata; mem = request_mem_region(r->start, resource_size(r), pdev->name); if (mem == NULL) { @@ -827,8 +912,8 @@ static int davinci_spi_probe(struct platform_device *pdev) goto unmap_io; } - ret = request_irq(dspi->irq, davinci_spi_irq, 0, dev_name(&pdev->dev), - dspi); + ret = request_threaded_irq(dspi->irq, davinci_spi_irq, dummy_thread_fn, + 0, dev_name(&pdev->dev), dspi); if (ret) goto unmap_io; @@ -843,8 +928,9 @@ static int davinci_spi_probe(struct platform_device *pdev) ret = -ENODEV; goto put_master; } - clk_enable(dspi->clk); + clk_prepare_enable(dspi->clk); + master->dev.of_node = pdev->dev.of_node; master->bus_num = pdev->id; master->num_chipselect = pdata->num_chipselect; master->setup = davinci_spi_setup; @@ -927,7 +1013,7 @@ free_dma: dma_release_channel(dspi->dma_rx); dma_release_channel(dspi->dma_tx); free_clk: - clk_disable(dspi->clk); + clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); put_master: spi_master_put(master); @@ -963,7 +1049,7 @@ static int davinci_spi_remove(struct platform_device *pdev) spi_bitbang_stop(&dspi->bitbang); - clk_disable(dspi->clk); + clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); spi_master_put(master); free_irq(dspi->irq, dspi); @@ -978,6 +1064,7 @@ static struct platform_driver davinci_spi_driver = { .driver = { .name = "spi_davinci", .owner = THIS_MODULE, + .of_match_table = davinci_spi_of_match, }, .probe = davinci_spi_probe, .remove = davinci_spi_remove, diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index acb1e1935c5..aecbff16ad6 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -446,7 +446,7 @@ static inline int bits_per_word(const struct ep93xx_spi *espi) struct spi_message *msg = espi->current_msg; struct spi_transfer *t = msg->state; - return t->bits_per_word ? t->bits_per_word : msg->spi->bits_per_word; + return t->bits_per_word; } static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c index 6a6f62ec284..c7a74f0ef89 100644 --- a/drivers/spi/spi-falcon.c +++ b/drivers/spi/spi-falcon.c @@ -398,7 +398,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master, } m->status = ret; - m->complete(m->context); + spi_finalize_current_message(master); return 0; } @@ -423,6 +423,7 @@ static int falcon_sflash_probe(struct platform_device *pdev) master->mode_bits = SPI_MODE_3; master->num_chipselect = 1; + master->flags = SPI_MASTER_HALF_DUPLEX; master->bus_num = -1; master->setup = falcon_sflash_setup; master->prepare_transfer_hardware = falcon_sflash_prepare_xfer; diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 904913290aa..0befeeb522f 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -949,3 +949,4 @@ module_platform_driver(spi_imx_driver); MODULE_DESCRIPTION("SPI Master Controller driver"); MODULE_AUTHOR("Sascha Hauer, Pengutronix"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index cb3a3106bd4..89480b281d7 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -438,6 +438,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, master->num_chipselect = pdata->max_chipselect; } + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; master->setup = mpc512x_psc_spi_setup; master->transfer = mpc512x_psc_spi_transfer; master->cleanup = mpc512x_psc_spi_cleanup; @@ -522,17 +523,11 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *op) regaddr64 = of_translate_address(op->dev.of_node, regaddr_p); /* get PSC id (0..11, used by port_config) */ - if (op->dev.platform_data == NULL) { - const u32 *psc_nump; - - psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL); - if (!psc_nump || *psc_nump > 11) { - dev_err(&op->dev, "mpc512x_psc_spi: Device node %s " - "has invalid cell-index property\n", - op->dev.of_node->full_name); - return -EINVAL; - } - id = *psc_nump; + id = of_alias_get_id(op->dev.of_node, "spi"); + if (id < 0) { + dev_err(&op->dev, "no alias id for %s\n", + op->dev.of_node->full_name); + return id; } return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64, diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index a3ede249d05..e3d8b3197d2 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -241,6 +241,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, INIT_COMPLETION(spi->c); ctrl0 = readl(ssp->base + HW_SSP_CTRL0); + ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT; ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); if (*first) @@ -256,8 +257,10 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, if ((sg_count + 1 == sgs) && *last) ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC; - if (ssp->devid == IMX23_SSP) + if (ssp->devid == IMX23_SSP) { + ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT; ctrl0 |= min; + } dma_xfer[sg_count].pio[0] = ctrl0; dma_xfer[sg_count].pio[3] = min; diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 3aef7fa7d5b..78d29a18dcc 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -481,7 +481,7 @@ static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) return 0; } -static int __init omap1_spi100k_reset(struct omap1_spi100k *spi100k) +static int omap1_spi100k_reset(struct omap1_spi100k *spi100k) { return 0; } @@ -560,7 +560,7 @@ err1: return status; } -static int __exit omap1_spi100k_remove(struct platform_device *pdev) +static int omap1_spi100k_remove(struct platform_device *pdev) { struct spi_master *master; struct omap1_spi100k *spi100k; @@ -604,7 +604,7 @@ static struct platform_driver omap1_spi100k_driver = { .name = "omap1_spi100k", .owner = THIS_MODULE, }, - .remove = __exit_p(omap1_spi100k_remove), + .remove = omap1_spi100k_remove, }; diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c index 0a94d9dc9c3..102b233b50c 100644 --- a/drivers/spi/spi-omap-uwire.c +++ b/drivers/spi/spi-omap-uwire.c @@ -476,7 +476,7 @@ static void uwire_off(struct uwire_spi *uwire) spi_master_put(uwire->bitbang.master); } -static int __init uwire_probe(struct platform_device *pdev) +static int uwire_probe(struct platform_device *pdev) { struct spi_master *master; struct uwire_spi *uwire; @@ -536,7 +536,7 @@ static int __init uwire_probe(struct platform_device *pdev) return status; } -static int __exit uwire_remove(struct platform_device *pdev) +static int uwire_remove(struct platform_device *pdev) { struct uwire_spi *uwire = dev_get_drvdata(&pdev->dev); int status; @@ -557,7 +557,7 @@ static struct platform_driver uwire_driver = { .name = "omap_uwire", .owner = THIS_MODULE, }, - .remove = __exit_p(uwire_remove), + .remove = uwire_remove, // suspend ... unuse ck // resume ... use ck }; diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 12789fcfa98..69945b014c9 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -298,10 +298,10 @@ static void omap2_mcspi_rx_callback(void *data) struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; - complete(&mcspi_dma->dma_rx_completion); - /* We must disable the DMA RX request */ omap2_mcspi_set_dma_req(spi, 1, 0); + + complete(&mcspi_dma->dma_rx_completion); } static void omap2_mcspi_tx_callback(void *data) @@ -310,10 +310,10 @@ static void omap2_mcspi_tx_callback(void *data) struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; - complete(&mcspi_dma->dma_tx_completion); - /* We must disable the DMA TX request */ omap2_mcspi_set_dma_req(spi, 0, 0); + + complete(&mcspi_dma->dma_tx_completion); } static void omap2_mcspi_tx_dma(struct spi_device *spi, diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index b7e718254b1..66a5f82cf13 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -366,7 +366,7 @@ msg_done: return 0; } -static int __init orion_spi_reset(struct orion_spi *orion_spi) +static int orion_spi_reset(struct orion_spi *orion_spi) { /* Verify that the CS is deasserted */ orion_spi_set_cs(orion_spi, 0); @@ -396,7 +396,7 @@ static int orion_spi_setup(struct spi_device *spi) return 0; } -static int __init orion_spi_probe(struct platform_device *pdev) +static int orion_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct orion_spi *spi; @@ -479,7 +479,7 @@ out: } -static int __exit orion_spi_remove(struct platform_device *pdev) +static int orion_spi_remove(struct platform_device *pdev) { struct spi_master *master; struct resource *r; @@ -513,20 +513,11 @@ static struct platform_driver orion_spi_driver = { .owner = THIS_MODULE, .of_match_table = of_match_ptr(orion_spi_of_match_table), }, - .remove = __exit_p(orion_spi_remove), + .probe = orion_spi_probe, + .remove = orion_spi_remove, }; -static int __init orion_spi_init(void) -{ - return platform_driver_probe(&orion_spi_driver, orion_spi_probe); -} -module_init(orion_spi_init); - -static void __exit orion_spi_exit(void) -{ - platform_driver_unregister(&orion_spi_driver); -} -module_exit(orion_spi_exit); +module_platform_driver(orion_spi_driver); MODULE_DESCRIPTION("Orion SPI driver"); MODULE_AUTHOR("Shadi Ammouri <shadi@marvell.com>"); diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 7a85f22b647..424b333fab1 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -389,7 +389,7 @@ static void free_gpios(struct ppc4xx_spi *hw) /* * platform_device layer stuff... */ -static int __init spi_ppc4xx_of_probe(struct platform_device *op) +static int spi_ppc4xx_of_probe(struct platform_device *op) { struct ppc4xx_spi *hw; struct spi_master *master; @@ -560,7 +560,7 @@ free_master: return ret; } -static int __exit spi_ppc4xx_of_remove(struct platform_device *op) +static int spi_ppc4xx_of_remove(struct platform_device *op) { struct spi_master *master = dev_get_drvdata(&op->dev); struct ppc4xx_spi *hw = spi_master_get_devdata(master); @@ -583,7 +583,7 @@ MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match); static struct platform_driver spi_ppc4xx_of_driver = { .probe = spi_ppc4xx_of_probe, - .remove = __exit_p(spi_ppc4xx_of_remove), + .remove = spi_ppc4xx_of_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 6495352bcc1..8f492ed317c 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -62,7 +62,7 @@ #define S3C64XX_SPI_CLKSEL_SRCMSK (3<<9) #define S3C64XX_SPI_CLKSEL_SRCSHFT 9 #define S3C64XX_SPI_ENCLK_ENABLE (1<<8) -#define S3C64XX_SPI_PSR_MASK 0xff +#define S3C64XX_SPI_PSR_MASK 0xff #define S3C64XX_SPI_MODE_CH_TSZ_BYTE (0<<29) #define S3C64XX_SPI_MODE_CH_TSZ_HALFWORD (1<<29) @@ -697,7 +697,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, INIT_COMPLETION(sdd->xfer_completion); /* Only BPW and Speed may change across transfers */ - bpw = xfer->bits_per_word ? : spi->bits_per_word; + bpw = xfer->bits_per_word; speed = xfer->speed_hz ? : spi->max_speed_hz; if (xfer->len % (bpw / 8)) { @@ -743,8 +743,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, sdd->regs + S3C64XX_SPI_SLAVE_SEL); if (status) { - dev_err(&spi->dev, "I/O Error: " - "rx-%d tx-%d res:rx-%c tx-%c len-%d\n", + 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', @@ -799,7 +798,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) /* Acquire DMA channels */ while (!acquire_dma(sdd)) - msleep(10); + usleep_range(10000, 11000); pm_runtime_get_sync(&sdd->pdev->dev); @@ -841,16 +840,14 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( cs = kzalloc(sizeof(*cs), GFP_KERNEL); if (!cs) { - dev_err(&spi->dev, "could not allocate memory for controller" - " data\n"); + dev_err(&spi->dev, "could not allocate memory for controller data\n"); of_node_put(data_np); return ERR_PTR(-ENOMEM); } cs->line = of_get_named_gpio(data_np, "cs-gpio", 0); if (!gpio_is_valid(cs->line)) { - dev_err(&spi->dev, "chip select gpio is not specified or " - "invalid\n"); + dev_err(&spi->dev, "chip select gpio is not specified or invalid\n"); kfree(cs); of_node_put(data_np); return ERR_PTR(-EINVAL); @@ -1078,8 +1075,8 @@ static int s3c64xx_spi_get_dmares( if (!sdd->pdev->dev.of_node) { res = platform_get_resource(pdev, IORESOURCE_DMA, tx ? 0 : 1); if (!res) { - dev_err(&pdev->dev, "Unable to get SPI-%s dma " - "resource\n", chan_str); + dev_err(&pdev->dev, "Unable to get SPI-%s dma resource\n", + chan_str); return -ENXIO; } dma_data->dmach = res->start; @@ -1135,8 +1132,7 @@ static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd) gpio_free(sdd->gpios[idx]); } -static struct s3c64xx_spi_info * s3c64xx_spi_parse_dt( - struct device *dev) +static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev) { struct s3c64xx_spi_info *sci; u32 temp; @@ -1148,16 +1144,14 @@ static struct s3c64xx_spi_info * s3c64xx_spi_parse_dt( } if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) { - dev_warn(dev, "spi bus clock parent not specified, using " - "clock at index 0 as parent\n"); + dev_warn(dev, "spi bus clock parent not specified, using clock at index 0 as parent\n"); sci->src_clk_nr = 0; } else { sci->src_clk_nr = temp; } if (of_property_read_u32(dev->of_node, "num-cs", &temp)) { - dev_warn(dev, "number of chip select lines not specified, " - "assuming 1 chip select line\n"); + dev_warn(dev, "number of chip select lines not specified, assuming 1 chip select line\n"); sci->num_cs = 1; } else { sci->num_cs = temp; @@ -1197,7 +1191,7 @@ static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( platform_get_device_id(pdev)->driver_data; } -static int __init s3c64xx_spi_probe(struct platform_device *pdev) +static int s3c64xx_spi_probe(struct platform_device *pdev) { struct resource *mem_res; struct s3c64xx_spi_driver_data *sdd; @@ -1247,8 +1241,8 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) if (pdev->dev.of_node) { ret = of_alias_get_id(pdev->dev.of_node, "spi"); if (ret < 0) { - dev_err(&pdev->dev, "failed to get alias id, " - "errno %d\n", ret); + dev_err(&pdev->dev, "failed to get alias id, errno %d\n", + ret); goto err0; } sdd->port_id = ret; @@ -1282,7 +1276,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) if (sdd->regs == NULL) { dev_err(&pdev->dev, "Unable to remap IO\n"); ret = -ENXIO; - goto err1; + goto err0; } if (!sci->cfg_gpio && pdev->dev.of_node) { @@ -1291,36 +1285,36 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) } else if (sci->cfg_gpio == NULL || sci->cfg_gpio()) { dev_err(&pdev->dev, "Unable to config gpio\n"); ret = -EBUSY; - goto err2; + goto err0; } /* Setup clocks */ - sdd->clk = clk_get(&pdev->dev, "spi"); + sdd->clk = devm_clk_get(&pdev->dev, "spi"); if (IS_ERR(sdd->clk)) { dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n"); ret = PTR_ERR(sdd->clk); - goto err3; + goto err1; } if (clk_prepare_enable(sdd->clk)) { dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n"); ret = -EBUSY; - goto err4; + goto err1; } sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr); - sdd->src_clk = clk_get(&pdev->dev, clk_name); + sdd->src_clk = devm_clk_get(&pdev->dev, clk_name); if (IS_ERR(sdd->src_clk)) { dev_err(&pdev->dev, "Unable to acquire clock '%s'\n", clk_name); ret = PTR_ERR(sdd->src_clk); - goto err5; + goto err2; } if (clk_prepare_enable(sdd->src_clk)) { dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name); ret = -EBUSY; - goto err6; + goto err2; } /* Setup Deufult Mode */ @@ -1330,11 +1324,12 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) init_completion(&sdd->xfer_completion); INIT_LIST_HEAD(&sdd->queue); - ret = request_irq(irq, s3c64xx_spi_irq, 0, "spi-s3c64xx", sdd); + ret = devm_request_irq(&pdev->dev, irq, s3c64xx_spi_irq, 0, + "spi-s3c64xx", sdd); if (ret != 0) { dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n", irq, ret); - goto err7; + goto err3; } writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN | @@ -1344,11 +1339,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) if (spi_register_master(master)) { dev_err(&pdev->dev, "cannot register SPI master\n"); ret = -EBUSY; - goto err8; + goto err3; } - dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d " - "with %d Slaves attached\n", + dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n", sdd->port_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, @@ -1358,21 +1352,13 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) return 0; -err8: - free_irq(irq, sdd); -err7: +err3: clk_disable_unprepare(sdd->src_clk); -err6: - clk_put(sdd->src_clk); -err5: +err2: clk_disable_unprepare(sdd->clk); -err4: - clk_put(sdd->clk); -err3: +err1: if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node) s3c64xx_spi_dt_gpio_free(sdd); -err2: -err1: err0: platform_set_drvdata(pdev, NULL); spi_master_put(master); @@ -1391,13 +1377,9 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) writel(0, sdd->regs + S3C64XX_SPI_INT_EN); - free_irq(platform_get_irq(pdev, 0), sdd); - clk_disable_unprepare(sdd->src_clk); - clk_put(sdd->src_clk); clk_disable_unprepare(sdd->clk); - clk_put(sdd->clk); if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node) s3c64xx_spi_dt_gpio_free(sdd); diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 96358d0eabb..8b40d0884f8 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -592,6 +593,37 @@ static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs, return 0; } +#ifdef CONFIG_OF +static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) +{ + struct sh_msiof_spi_info *info; + struct device_node *np = dev->of_node; + u32 num_cs = 0; + + info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL); + if (!info) { + dev_err(dev, "failed to allocate setup data\n"); + return NULL; + } + + /* Parse the MSIOF properties */ + of_property_read_u32(np, "num-cs", &num_cs); + of_property_read_u32(np, "renesas,tx-fifo-size", + &info->tx_fifo_override); + of_property_read_u32(np, "renesas,rx-fifo-size", + &info->rx_fifo_override); + + info->num_chipselect = num_cs; + + return info; +} +#else +static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) +{ + return NULL; +} +#endif + static int sh_msiof_spi_probe(struct platform_device *pdev) { struct resource *r; @@ -610,7 +642,17 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) p = spi_master_get_devdata(master); platform_set_drvdata(pdev, p); - p->info = pdev->dev.platform_data; + if (pdev->dev.of_node) + p->info = sh_msiof_spi_parse_dt(&pdev->dev); + else + p->info = pdev->dev.platform_data; + + if (!p->info) { + dev_err(&pdev->dev, "failed to obtain device info\n"); + ret = -ENXIO; + goto err1; + } + init_completion(&p->done); p->clk = clk_get(&pdev->dev, NULL); @@ -715,6 +757,17 @@ static int sh_msiof_spi_runtime_nop(struct device *dev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id sh_msiof_match[] = { + { .compatible = "renesas,sh-msiof", }, + { .compatible = "renesas,sh-mobile-msiof", }, + {}, +}; +MODULE_DEVICE_TABLE(of, sh_msiof_match); +#else +#define sh_msiof_match NULL +#endif + static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = { .runtime_suspend = sh_msiof_spi_runtime_nop, .runtime_resume = sh_msiof_spi_runtime_nop, @@ -727,6 +780,7 @@ static struct platform_driver sh_msiof_spi_drv = { .name = "spi_sh_msiof", .owner = THIS_MODULE, .pm = &sh_msiof_spi_dev_pm_ops, + .of_match_table = sh_msiof_match, }, }; module_platform_driver(sh_msiof_spi_drv); diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index e0f43a512e8..6a5626d146b 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -382,8 +382,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) sspi = spi_master_get_devdata(spi->master); - bits_per_word = t && t->bits_per_word ? t->bits_per_word : - spi->bits_per_word; + bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz; /* Enable IO mode for RX, TX */ @@ -570,7 +569,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ret = -EINVAL; goto free_pin; } - clk_enable(sspi->clk); + clk_prepare_enable(sspi->clk); sspi->ctrl_freq = clk_get_rate(sspi->clk); init_completion(&sspi->done); @@ -594,7 +593,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) return 0; free_clk: - clk_disable(sspi->clk); + clk_disable_unprepare(sspi->clk); clk_put(sspi->clk); free_pin: pinctrl_put(sspi->p); @@ -618,7 +617,7 @@ static int spi_sirfsoc_remove(struct platform_device *pdev) if (sspi->chipselect[i] > 0) gpio_free(sspi->chipselect[i]); } - clk_disable(sspi->clk); + clk_disable_unprepare(sspi->clk); clk_put(sspi->clk); pinctrl_put(sspi->p); spi_master_put(master); @@ -659,6 +658,7 @@ static const struct dev_pm_ops spi_sirfsoc_pm_ops = { static const struct of_device_id spi_sirfsoc_of_match[] = { { .compatible = "sirf,prima2-spi", }, + { .compatible = "sirf,marco-spi", }, {} }; MODULE_DEVICE_TABLE(of, sirfsoc_spi_of_match); diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 448a8cc71df..9a42c158e24 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -269,9 +269,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi, u32 speed; unsigned long command; - speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz; - if (!speed) - speed = tsd->spi_max_frequency; + speed = t->speed_hz; if (speed != tsd->cur_speed) { clk_set_rate(tsd->clk, speed); tsd->cur_speed = speed; @@ -319,6 +317,15 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi, return tegra_sflash_start_cpu_based_transfer(tsd, t); } +static int tegra_sflash_setup(struct spi_device *spi) +{ + struct tegra_sflash_data *tsd = spi_master_get_devdata(spi->master); + + /* Set speed to the spi max fequency if spi device has not set */ + spi->max_speed_hz = spi->max_speed_hz ? : tsd->spi_max_frequency; + return 0; +} + static int tegra_sflash_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -492,6 +499,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA; + master->setup = tegra_sflash_setup; master->transfer_one_message = tegra_sflash_transfer_one_message; master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 651167f2e0a..8d51db8dea6 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -284,8 +284,7 @@ static unsigned tegra_slink_calculate_curr_xfer_param( unsigned max_len; unsigned total_fifo_words; - bits_per_word = t->bits_per_word ? t->bits_per_word : - spi->bits_per_word; + bits_per_word = t->bits_per_word; tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1; if (bits_per_word == 8 || bits_per_word == 16) { @@ -378,8 +377,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf( } else { unsigned int bits_per_word; - bits_per_word = t->bits_per_word ? t->bits_per_word : - tspi->cur_spi->bits_per_word; + bits_per_word = t->bits_per_word; for (count = 0; count < rx_full_count; count++) { x = tegra_slink_readl(tspi, SLINK_RX_FIFO); for (i = 0; (i < tspi->bytes_per_word); i++) @@ -444,8 +442,7 @@ static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf( unsigned int x; unsigned int rx_mask, bits_per_word; - bits_per_word = t->bits_per_word ? t->bits_per_word : - tspi->cur_spi->bits_per_word; + bits_per_word = t->bits_per_word; rx_mask = (1 << bits_per_word) - 1; for (count = 0; count < tspi->curr_dma_words; count++) { x = tspi->rx_dma_buf[count]; @@ -728,9 +725,7 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, unsigned long command2; bits_per_word = t->bits_per_word; - speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz; - if (!speed) - speed = tspi->spi_max_frequency; + speed = t->speed_hz; if (speed != tspi->cur_speed) { clk_set_rate(tspi->clk, speed * 4); tspi->cur_speed = speed; @@ -841,6 +836,8 @@ static int tegra_slink_setup(struct spi_device *spi) BUG_ON(spi->chip_select >= MAX_CHIP_SELECT); + /* Set speed to the spi max fequency if spi device has not set */ + spi->max_speed_hz = spi->max_speed_hz ? : tspi->spi_max_frequency; ret = pm_runtime_get_sync(tspi->dev); if (ret < 0) { dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret); diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index d5a3cbb646c..adb85304792 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -189,9 +189,8 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m) unsigned int len = t->len; unsigned int wsize; u32 speed_hz = t->speed_hz ? : spi->max_speed_hz; - u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word; + u8 bits_per_word = t->bits_per_word; - bits_per_word = bits_per_word ? : 8; wsize = bits_per_word >> 3; /* in bytes */ if (prev_speed_hz != speed_hz @@ -316,9 +315,8 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m) /* check each transfer's parameters */ 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 ? : spi->bits_per_word; + u8 bits_per_word = t->bits_per_word; - bits_per_word = bits_per_word ? : 8; if (!t->tx_buf && !t->rx_buf && t->len) return -EINVAL; if (bits_per_word != 8 && bits_per_word != 16) @@ -337,7 +335,7 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m) return 0; } -static int __init txx9spi_probe(struct platform_device *dev) +static int txx9spi_probe(struct platform_device *dev) { struct spi_master *master; struct txx9spi *c; @@ -432,7 +430,7 @@ exit: return ret; } -static int __exit txx9spi_remove(struct platform_device *dev) +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); @@ -450,7 +448,7 @@ static int __exit txx9spi_remove(struct platform_device *dev) MODULE_ALIAS("platform:spi_txx9"); static struct platform_driver txx9spi_driver = { - .remove = __exit_p(txx9spi_remove), + .remove = txx9spi_remove, .driver = { .name = "spi_txx9", .owner = THIS_MODULE, diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 19ee901577d..d1e0a316826 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1135,6 +1135,9 @@ int spi_register_master(struct spi_master *master) if (master->num_chipselect == 0) return -EINVAL; + if ((master->bus_num < 0) && master->dev.of_node) + master->bus_num = of_alias_get_id(master->dev.of_node, "spi"); + /* convention: dynamically assigned bus IDs count down from the max */ if (master->bus_num < 0) { /* FIXME switch to an IDR based scheme, something like @@ -1366,12 +1369,14 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) } /** - * Set transfer bits_per_word as spi device default if it is not - * set for this transfer. + * Set transfer bits_per_word and max speed as spi device default if + * it is not set for this transfer. */ list_for_each_entry(xfer, &message->transfers, transfer_list) { if (!xfer->bits_per_word) xfer->bits_per_word = spi->bits_per_word; + if (!xfer->speed_hz) + xfer->speed_hz = spi->max_speed_hz; } message->spi = spi; @@ -1656,7 +1661,8 @@ int spi_write_then_read(struct spi_device *spi, * using the pre-allocated buffer or the transfer is too large. */ if ((n_tx + n_rx) > SPI_BUFSIZ || !mutex_trylock(&lock)) { - local_buf = kmalloc(max((unsigned)SPI_BUFSIZ, n_tx + n_rx), GFP_KERNEL); + local_buf = kmalloc(max((unsigned)SPI_BUFSIZ, n_tx + n_rx), + GFP_KERNEL | GFP_DMA); if (!local_buf) return -ENOMEM; } else { |