From 7d0771970c51e736758525dd71fb82dd036b823a Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 17 Jun 2009 16:26:03 -0700 Subject: spi: move common spi_setup() functionality into core Start moving some spi_setup() functionality into the SPI core from the various spi_master controller drivers: - Make that function stop being an inline; - Move two common idioms from drivers into that new function: * Default bits_per_word to 8 if that field isn't set * Issue a standardized dev_dbg() message This is a net minor source code shrink, and supports enhancments found in some follow-up patches. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/omap2_mcspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/spi/omap2_mcspi.c') diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index d6d0c5d241ce..b4f3b753d0f4 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -619,9 +619,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) return -EINVAL; } - if (spi->bits_per_word == 0) - spi->bits_per_word = 8; - else if (spi->bits_per_word < 4 || spi->bits_per_word > 32) { + if (spi->bits_per_word < 4 || spi->bits_per_word > 32) { dev_dbg(&spi->dev, "setup: unsupported %d bit words\n", spi->bits_per_word); return -EINVAL; -- cgit v1.2.3 From e7db06b5d5afcef15c4c3e61c3a7441ed7ad1407 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 17 Jun 2009 16:26:04 -0700 Subject: spi: move more spi_setup() functionality into core Move some common spi_setup() error checks into the SPI framework from the spi_master controller drivers: - Add a new "mode_bits" field to spi_master - Use that in spi_setup to validate the spi->mode value being requested. Setting this new field is now mandatory for any controller supporting more than vanilla SPI_MODE_0. - Update all spi_master drivers to: * Initialize that field * Remove current spi_setup() checks using that value. This is a net minor code shrink. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/atmel_spi.c | 12 +++--------- drivers/spi/au1550_spi.c | 12 +++--------- drivers/spi/mpc52xx_psc_spi.c | 12 +++--------- drivers/spi/omap2_mcspi.c | 12 +++--------- drivers/spi/omap_uwire.c | 12 +++--------- drivers/spi/orion_spi.c | 9 +++------ drivers/spi/pxa2xx_spi.c | 12 +++--------- drivers/spi/spi.c | 11 +++++++++++ drivers/spi/spi_bfin5xx.c | 9 +++------ drivers/spi/spi_bitbang.c | 9 +++------ drivers/spi/spi_imx.c | 12 +++--------- drivers/spi/spi_mpc83xx.c | 14 ++++---------- drivers/spi/spi_s3c24xx.c | 12 +++--------- drivers/spi/spi_txx9.c | 9 +++------ drivers/spi/xilinx_spi.c | 12 +++--------- include/linux/spi/spi.h | 3 +++ 16 files changed, 57 insertions(+), 115 deletions(-) (limited to 'drivers/spi/omap2_mcspi.c') diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 9f9ff3af72d7..f5b3fdbb1e27 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -530,9 +530,6 @@ atmel_spi_interrupt(int irq, void *dev_id) return ret; } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) - static int atmel_spi_setup(struct spi_device *spi) { struct atmel_spi *as; @@ -562,12 +559,6 @@ static int atmel_spi_setup(struct spi_device *spi) return -EINVAL; } - if (spi->mode & ~MODEBITS) { - dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode & ~MODEBITS); - return -EINVAL; - } - /* see notes above re chipselect */ if (!atmel_spi_is_v2() && spi->chip_select == 0 @@ -773,6 +764,9 @@ static int __init atmel_spi_probe(struct platform_device *pdev) if (!master) goto out_free; + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->bus_num = pdev->id; master->num_chipselect = 4; master->setup = atmel_spi_setup; diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c index 6a407e60f05b..76cbc1a66598 100644 --- a/drivers/spi/au1550_spi.c +++ b/drivers/spi/au1550_spi.c @@ -284,9 +284,6 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) return 0; } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST) - static int au1550_spi_setup(struct spi_device *spi) { struct au1550_spi *hw = spi_master_get_devdata(spi->master); @@ -297,12 +294,6 @@ static int au1550_spi_setup(struct spi_device *spi) return -EINVAL; } - if (spi->mode & ~MODEBITS) { - dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode & ~MODEBITS); - return -EINVAL; - } - if (spi->max_speed_hz == 0) spi->max_speed_hz = hw->freq_max; if (spi->max_speed_hz > hw->freq_max @@ -779,6 +770,9 @@ static int __init au1550_spi_probe(struct platform_device *pdev) goto err_nomem; } + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + hw = spi_master_get_devdata(master); hw->master = spi_master_get(master); diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 68c77a911595..bdae9f908978 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c @@ -261,9 +261,6 @@ static void mpc52xx_psc_spi_work(struct work_struct *work) spin_unlock_irq(&mps->lock); } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST) - static int mpc52xx_psc_spi_setup(struct spi_device *spi) { struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); @@ -273,12 +270,6 @@ static int mpc52xx_psc_spi_setup(struct spi_device *spi) if (spi->bits_per_word%8) return -EINVAL; - if (spi->mode & ~MODEBITS) { - dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode & ~MODEBITS); - return -EINVAL; - } - if (!cs) { cs = kzalloc(sizeof *cs, GFP_KERNEL); if (!cs) @@ -385,6 +376,9 @@ static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, dev_set_drvdata(dev, master); mps = spi_master_get_devdata(master); + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + mps->irq = irq; if (pdata == NULL) { dev_warn(dev, "probe called without platform data, no " diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index b4f3b753d0f4..eee4b6e0af2c 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -603,9 +603,6 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) return 0; } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) - static int omap2_mcspi_setup(struct spi_device *spi) { int ret; @@ -613,12 +610,6 @@ static int omap2_mcspi_setup(struct spi_device *spi) struct omap2_mcspi_dma *mcspi_dma; struct omap2_mcspi_cs *cs = spi->controller_state; - if (spi->mode & ~MODEBITS) { - dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode & ~MODEBITS); - return -EINVAL; - } - if (spi->bits_per_word < 4 || spi->bits_per_word > 32) { dev_dbg(&spi->dev, "setup: unsupported %d bit words\n", spi->bits_per_word); @@ -982,6 +973,9 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) return -ENOMEM; } + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + if (pdev->id != -1) master->bus_num = pdev->id; diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c index 747d29be45d5..aa90ddb37066 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/omap_uwire.c @@ -447,19 +447,10 @@ done: return status; } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) - static int uwire_setup(struct spi_device *spi) { struct uwire_state *ust = spi->controller_state; - if (spi->mode & ~MODEBITS) { - dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode & ~MODEBITS); - return -EINVAL; - } - if (ust == NULL) { ust = kzalloc(sizeof(*ust), GFP_KERNEL); if (ust == NULL) @@ -520,6 +511,9 @@ static int __init uwire_probe(struct platform_device *pdev) uwire_write_reg(UWIRE_SR3, 1); + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->bus_num = 2; /* "official" */ master->num_chipselect = 4; master->setup = uwire_setup; diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c index 6d5e33bb4b4a..3aea50da7b29 100644 --- a/drivers/spi/orion_spi.c +++ b/drivers/spi/orion_spi.c @@ -358,12 +358,6 @@ static int orion_spi_setup(struct spi_device *spi) orion_spi = spi_master_get_devdata(spi->master); - if (spi->mode) { - dev_err(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode); - return -EINVAL; - } - /* Fix ac timing if required. */ if (orion_spi->spi_info->enable_clock_fix) orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG, @@ -473,6 +467,9 @@ static int __init orion_spi_probe(struct platform_device *pdev) if (pdev->id != -1) master->bus_num = pdev->id; + /* we support only mode 0, and no options */ + master->mode_bits = 0; + master->setup = orion_spi_setup; master->transfer = orion_spi_transfer; master->num_chipselect = ORION_NUM_CHIPSELECTS; diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index c7365e0b22dd..9c311dc4771d 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1185,9 +1185,6 @@ static int transfer(struct spi_device *spi, struct spi_message *msg) return 0; } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA) - static int setup_cs(struct spi_device *spi, struct chip_data *chip, struct pxa2xx_spi_chip *chip_info) { @@ -1252,12 +1249,6 @@ static int setup(struct spi_device *spi) return -EINVAL; } - if (spi->mode & ~MODEBITS) { - dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode & ~MODEBITS); - return -EINVAL; - } - /* Only alloc on first setup */ chip = spi_get_ctldata(spi); if (!chip) { @@ -1493,6 +1484,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) drv_data->pdev = pdev; drv_data->ssp = ssp; + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA; + master->bus_num = pdev->id; master->num_chipselect = platform_info->num_chipselect; master->dma_alignment = DMA_ALIGNMENT; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 0276bc37e255..a525a3a848c1 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -607,8 +607,19 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master); */ int spi_setup(struct spi_device *spi) { + unsigned bad_bits; int status; + /* help drivers fail *cleanly* when they need options + * that aren't supported with their current master + */ + bad_bits = spi->mode & ~spi->master->mode_bits; + if (bad_bits) { + dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", + bad_bits); + return -EINVAL; + } + if (!spi->bits_per_word) spi->bits_per_word = 8; diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index d54058a903be..73e24ef5a2f9 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -1010,12 +1010,6 @@ static int bfin_spi_setup(struct spi_device *spi) struct driver_data *drv_data = spi_master_get_devdata(spi->master); int ret; - /* Abort device setup if requested features are not supported */ - if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) { - dev_err(&spi->dev, "requested mode not fully supported\n"); - return -EINVAL; - } - if (spi->bits_per_word != 8 && spi->bits_per_word != 16) return -EINVAL; @@ -1283,6 +1277,9 @@ static int __init bfin_spi_probe(struct platform_device *pdev) drv_data->pdev = pdev; drv_data->pin_req = platform_info->pin_req; + /* the spi->mode bits supported by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + master->bus_num = pdev->id; master->num_chipselect = platform_info->num_chipselect; master->cleanup = bfin_spi_cleanup; diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 855b0b06e625..2a5abc08e857 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -188,12 +188,6 @@ int spi_bitbang_setup(struct spi_device *spi) bitbang = spi_master_get_devdata(spi->master); - /* Bitbangers can support SPI_CS_HIGH, SPI_3WIRE, and so on; - * add those to master->flags, and provide the other support. - */ - if ((spi->mode & ~(SPI_CPOL|SPI_CPHA|bitbang->flags)) != 0) - return -EINVAL; - if (!cs) { cs = kzalloc(sizeof *cs, GFP_KERNEL); if (!cs) @@ -452,6 +446,9 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) spin_lock_init(&bitbang->lock); INIT_LIST_HEAD(&bitbang->queue); + if (!bitbang->master->mode_bits) + bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; + if (!bitbang->master->transfer) bitbang->master->transfer = spi_bitbang_transfer; if (!bitbang->txrx_bufs) { diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 26d5ef06dbd9..c195e45f7f35 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -1171,9 +1171,6 @@ msg_rejected: return -EINVAL; } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) - /* On first setup bad values must free chip_data memory since will cause spi_new_device to fail. Bad value setup from protocol driver are simply not applied and notified to the calling driver. */ @@ -1186,12 +1183,6 @@ static int setup(struct spi_device *spi) u32 tmp; int status = 0; - if (spi->mode & ~MODEBITS) { - dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode & ~MODEBITS); - return -EINVAL; - } - /* Get controller data */ chip_info = spi->controller_data; @@ -1478,6 +1469,9 @@ static int __init spi_imx_probe(struct platform_device *pdev) drv_data->master_info = platform_info; drv_data->pdev = pdev; + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->bus_num = pdev->id; master->num_chipselect = platform_info->num_chipselect; master->dma_alignment = DMA_ALIGNMENT; diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index 0926a3e293e0..ce61be98e06d 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c @@ -419,10 +419,6 @@ static void mpc83xx_spi_work(struct work_struct *work) spin_unlock_irq(&mpc83xx_spi->lock); } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ - | SPI_LSB_FIRST | SPI_LOOP) - static int mpc83xx_spi_setup(struct spi_device *spi) { struct mpc83xx_spi *mpc83xx_spi; @@ -430,12 +426,6 @@ static int mpc83xx_spi_setup(struct spi_device *spi) u32 hw_mode; struct spi_mpc83xx_cs *cs = spi->controller_state; - if (spi->mode & ~MODEBITS) { - dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode & ~MODEBITS); - return -EINVAL; - } - if (!spi->max_speed_hz) return -EINVAL; @@ -562,6 +552,10 @@ mpc83xx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) dev_set_drvdata(dev, master); + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH + | SPI_LSB_FIRST | SPI_LOOP; + master->setup = mpc83xx_spi_setup; master->transfer = mpc83xx_spi_transfer; master->cleanup = mpc83xx_spi_cleanup; diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 18a4c7f54380..e0d44af4745a 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c @@ -146,19 +146,10 @@ static int s3c24xx_spi_setupxfer(struct spi_device *spi, return 0; } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) - static int s3c24xx_spi_setup(struct spi_device *spi) { int ret; - if (spi->mode & ~MODEBITS) { - dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", - spi->mode & ~MODEBITS); - return -EINVAL; - } - ret = s3c24xx_spi_setupxfer(spi, NULL); if (ret < 0) { dev_err(&spi->dev, "setupxfer returned %d\n", ret); @@ -283,6 +274,9 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) /* setup the master state. */ + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->num_chipselect = hw->pdata->num_cs; master->bus_num = pdata->bus_num; diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c index 8e36b2153d9a..96057de133ad 100644 --- a/drivers/spi/spi_txx9.c +++ b/drivers/spi/spi_txx9.c @@ -110,17 +110,11 @@ static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c, ndelay(cs_delay); /* CS Setup Time / CS Recovery Time */ } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CS_HIGH|SPI_CPOL|SPI_CPHA) - static int txx9spi_setup(struct spi_device *spi) { struct txx9spi *c = spi_master_get_devdata(spi->master); u8 bits_per_word; - if (spi->mode & ~MODEBITS) - return -EINVAL; - if (!spi->max_speed_hz || spi->max_speed_hz > c->max_speed_hz || spi->max_speed_hz < c->min_speed_hz) @@ -414,6 +408,9 @@ static int __init txx9spi_probe(struct platform_device *dev) (unsigned long long)res->start, irq, (c->baseclk + 500000) / 1000000); + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA; + master->bus_num = dev->id; master->setup = txx9spi_setup; master->transfer = txx9spi_transfer; diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 2d7e6b81fb4a..46b8c5c2f45e 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -158,9 +158,6 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi, return 0; } -/* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA) - static int xilinx_spi_setup(struct spi_device *spi) { struct spi_bitbang *bitbang; @@ -170,12 +167,6 @@ static int xilinx_spi_setup(struct spi_device *spi) xspi = spi_master_get_devdata(spi->master); bitbang = &xspi->bitbang; - if (spi->mode & ~MODEBITS) { - dev_err(&spi->dev, "%s, unsupported mode bits %x\n", - __func__, spi->mode & ~MODEBITS); - return -EINVAL; - } - retval = xilinx_spi_setup_transfer(spi, NULL); if (retval < 0) return retval; @@ -327,6 +318,9 @@ static int __init xilinx_spi_of_probe(struct of_device *ofdev, goto put_master; } + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA; + xspi = spi_master_get_devdata(master); xspi->bitbang.master = spi_master_get(master); xspi->bitbang.chipselect = xilinx_spi_chipselect; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 0db5d64fc5e8..9c4cd27f4685 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -245,6 +245,9 @@ struct spi_master { */ u16 dma_alignment; + /* spi_device.mode flags understood by this controller driver */ + u16 mode_bits; + /* Setup mode and clock, etc (spi driver may call many times). * * IMPORTANT: this may be called when transfers to another -- cgit v1.2.3 From ddb22195cb3dc5175ba3aac5e957d0e34cd2ee73 Mon Sep 17 00:00:00 2001 From: Jouni Hogander Date: Wed, 29 Jul 2009 15:02:11 -0700 Subject: spi: omap2_mcspi supports wake events Currently mcspi wake-ups are not enabled. This might cause cases where OMAP is not waking up on mcspi events. Signed-off-by: Jouni Hogander Signed-off-by: Tony Lindgren Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/omap2_mcspi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/spi/omap2_mcspi.c') diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index eee4b6e0af2c..2b64091b0f1f 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -59,6 +59,8 @@ /* per-register bitmasks: */ +#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3) +#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP (1 << 2) #define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE (1 << 0) #define OMAP2_MCSPI_SYSCONFIG_SOFTRESET (1 << 1) @@ -90,6 +92,7 @@ #define OMAP2_MCSPI_CHCTRL_EN (1 << 0) +#define OMAP2_MCSPI_WAKEUPENABLE_WKEN (1 << 0) /* We have 2 DMA channels per CS, one for RX and one for TX */ struct omap2_mcspi_dma { @@ -873,8 +876,12 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi) } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE)); mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, - /* (3 << 8) | (2 << 3) | */ - OMAP2_MCSPI_SYSCONFIG_AUTOIDLE); + OMAP2_MCSPI_SYSCONFIG_AUTOIDLE | + OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP | + OMAP2_MCSPI_SYSCONFIG_SMARTIDLE); + + mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, + OMAP2_MCSPI_WAKEUPENABLE_WKEN); omap2_mcspi_set_master_mode(master); -- cgit v1.2.3 From 57c5c28dbc835c67a9c23912bab56b7f165e7715 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Wed, 29 Jul 2009 15:02:12 -0700 Subject: spi: omap2_mcspi rxdma bugfix When data is read through DMA, the last element must be read separately through the RX register. It cannot be transferred by the DMA. For further details see e.g. OMAP35x TRM (table 19-16). Without the fix the driver causes extra clocks to be clocked to the bus after DMA RX operations. This can cause interesting behaviour with some devices. Signed-off-by: Juuso Oikarinen Signed-off-by: Eero Nurkkala [aaro.koskinen@nokia.com: Simplified the patch while keeping the idea.] Signed-off-by: Aaro Koskinen Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/omap2_mcspi.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/spi/omap2_mcspi.c') diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 2b64091b0f1f..9b80ad36dbba 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -272,7 +272,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) if (rx != NULL) { omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel, - data_type, element_count, 1, + data_type, element_count - 1, 1, OMAP_DMA_SYNC_ELEMENT, mcspi_dma->dma_rx_sync_dev, 1); @@ -303,6 +303,25 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) if (rx != NULL) { wait_for_completion(&mcspi_dma->dma_rx_completion); dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE); + omap2_mcspi_set_enable(spi, 0); + if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) + & OMAP2_MCSPI_CHSTAT_RXS)) { + u32 w; + + w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); + if (word_len <= 8) + ((u8 *)xfer->rx_buf)[element_count - 1] = w; + else if (word_len <= 16) + ((u16 *)xfer->rx_buf)[element_count - 1] = w; + else /* word_len <= 32 */ + ((u32 *)xfer->rx_buf)[element_count - 1] = w; + } else { + dev_err(&spi->dev, "DMA RX last word empty"); + count -= (word_len <= 8) ? 1 : + (word_len <= 16) ? 2 : + /* word_len <= 32 */ 4; + } + omap2_mcspi_set_enable(spi, 1); } return count; } -- cgit v1.2.3