--- a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/spi-gpio.h @@ -21,7 +21,8 @@ struct s3c2410_spigpio_info { int num_chipselect; int bus_num; - void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs); + int non_blocking_transfer; + void (*chip_select)(struct s3c2410_spigpio_info *spi, int csid, int cs); }; --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -264,6 +264,123 @@ static int spi_bitbang_bufs(struct spi_d * Drivers can provide word-at-a-time i/o primitives, or provide * transfer-at-a-time ones to leverage dma or fifo hardware. */ + +/* Synchronous non blocking transfer */ +int +spi_bitbang_transfer_sync(struct spi_device *spi, struct spi_message *m) +{ + struct spi_bitbang *bitbang = spi_master_get_devdata(spi->master); + struct spi_transfer *t; + unsigned long flags; + int cs_change = 1; + int status; + int nsecs; + int (*setup_transfer)(struct spi_device *, struct spi_transfer *); + + /* FIXME this is made-up ... the correct value is known to + * word-at-a-time bitbang code, and presumably chipselect() + * should enforce these requirements too? + */ + nsecs = 100; + cs_change = 1; + status = 0; + setup_transfer = NULL; + + local_irq_save(flags); + list_for_each_entry (t, &m->transfers, transfer_list) { + /* override or restore speed and wordsize */ + if (t->speed_hz || t->bits_per_word) { + setup_transfer = bitbang->setup_transfer; + if (!setup_transfer) { + status = -ENOPROTOOPT; + break; + } + } + if (setup_transfer) { + status = setup_transfer(spi, t); + if (status < 0) + break; + } + + /* set up default clock polarity, and activate chip; + * this implicitly updates clock and spi modes as + * previously recorded for this device via setup(). + * (and also deselects any other chip that might be + * selected ...) + */ + + if (cs_change) { + bitbang->chipselect(spi, BITBANG_CS_ACTIVE); + ndelay(nsecs); + } + + cs_change = t->cs_change; + if (!t->tx_buf && !t->rx_buf && t->len) { + status = -EINVAL; + break; + } + + /* transfer data. the lower level code handles any + * new dma mappings it needs. our caller always gave + * us dma-safe buffers. + */ + if (t->len) { + /* REVISIT dma API still needs a designated + * DMA_ADDR_INVALID; ~0 might be better. + */ + if (!m->is_dma_mapped) + t->rx_dma = t->tx_dma = 0; + status = bitbang->txrx_bufs(spi, t); + } + + if (status > 0) + m->actual_length += status; + if (status != t->len) { + /* always report some kind of error */ + if (status >= 0) + status = -EREMOTEIO; + break; + } + status = 0; + /* protocol tweaks before next transfer */ + if (t->delay_usecs) + udelay(t->delay_usecs); + if (!cs_change) + continue; + if (t->transfer_list.next == &m->transfers) + break; + /* sometimes a short mid-message deselect of the chip + * may be needed to terminate a mode or command + */ + ndelay(nsecs); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(nsecs); + } + + m->status = status; + if (m->complete) + m->complete(m->context); + + /* restore speed and wordsize */ + if (setup_transfer) + setup_transfer(spi, NULL); + + /* normally deactivate chipselect ... unless no error and + * cs_change has hinted that the next message will probably + * be for this chip too. + */ + if (!(status == 0 && cs_change)) { + ndelay(nsecs); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(nsecs); + } + + local_irq_restore(flags); + + return status; +} +EXPORT_SYMBOL_GPL(spi_bitbang_transfer_sync); + static void bitbang_work(struct work_struct *work) { struct spi_bitbang *bitbang = @@ -274,120 +391,13 @@ static void bitbang_work(struct work_str bitbang->busy = 1; while (!list_empty(&bitbang->queue)) { struct spi_message *m; - struct spi_device *spi; - unsigned nsecs; - struct spi_transfer *t = NULL; - unsigned tmp; - unsigned cs_change; - int status; - int (*setup_transfer)(struct spi_device *, - struct spi_transfer *); m = container_of(bitbang->queue.next, struct spi_message, queue); list_del_init(&m->queue); - spin_unlock_irqrestore(&bitbang->lock, flags); - - /* FIXME this is made-up ... the correct value is known to - * word-at-a-time bitbang code, and presumably chipselect() - * should enforce these requirements too? - */ - nsecs = 100; - - spi = m->spi; - tmp = 0; - cs_change = 1; - status = 0; - setup_transfer = NULL; - - list_for_each_entry (t, &m->transfers, transfer_list) { - - /* override or restore speed and wordsize */ - if (t->speed_hz || t->bits_per_word) { - setup_transfer = bitbang->setup_transfer; - if (!setup_transfer) { - status = -ENOPROTOOPT; - break; - } - } - if (setup_transfer) { - status = setup_transfer(spi, t); - if (status < 0) - break; - } - - /* set up default clock polarity, and activate chip; - * this implicitly updates clock and spi modes as - * previously recorded for this device via setup(). - * (and also deselects any other chip that might be - * selected ...) - */ - if (cs_change) { - bitbang->chipselect(spi, BITBANG_CS_ACTIVE); - ndelay(nsecs); - } - cs_change = t->cs_change; - if (!t->tx_buf && !t->rx_buf && t->len) { - status = -EINVAL; - break; - } - - /* transfer data. the lower level code handles any - * new dma mappings it needs. our caller always gave - * us dma-safe buffers. - */ - if (t->len) { - /* REVISIT dma API still needs a designated - * DMA_ADDR_INVALID; ~0 might be better. - */ - if (!m->is_dma_mapped) - t->rx_dma = t->tx_dma = 0; - status = bitbang->txrx_bufs(spi, t); - } - if (status > 0) - m->actual_length += status; - if (status != t->len) { - /* always report some kind of error */ - if (status >= 0) - status = -EREMOTEIO; - break; - } - status = 0; - - /* protocol tweaks before next transfer */ - if (t->delay_usecs) - udelay(t->delay_usecs); - - if (!cs_change) - continue; - if (t->transfer_list.next == &m->transfers) - break; - - /* sometimes a short mid-message deselect of the chip - * may be needed to terminate a mode or command - */ - ndelay(nsecs); - bitbang->chipselect(spi, BITBANG_CS_INACTIVE); - ndelay(nsecs); - } - - m->status = status; - m->complete(m->context); - - /* restore speed and wordsize */ - if (setup_transfer) - setup_transfer(spi, NULL); - - /* normally deactivate chipselect ... unless no error and - * cs_change has hinted that the next message will probably - * be for this chip too. - */ - if (!(status == 0 && cs_change)) { - ndelay(nsecs); - bitbang->chipselect(spi, BITBANG_CS_INACTIVE); - ndelay(nsecs); - } + spin_unlock_irqrestore(&bitbang->lock, flags); + spi_bitbang_transfer_sync(m->spi, m); spin_lock_irqsave(&bitbang->lock, flags); } bitbang->busy = 0; @@ -459,6 +469,9 @@ int spi_bitbang_start(struct spi_bitbang if (!bitbang->master->transfer) bitbang->master->transfer = spi_bitbang_transfer; + if (!bitbang->master->transfer_sync && bitbang->non_blocking_transfer) + bitbang->master->transfer_sync = spi_bitbang_transfer_sync; + if (!bitbang->txrx_bufs) { bitbang->use_dma = 0; bitbang->txrx_bufs = spi_bitbang_bufs; --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c @@ -91,7 +91,7 @@ static void s3c2410_spigpio_chipselect(s struct s3c2410_spigpio *sg = spidev_to_sg(dev); if (sg->info && sg->info->chip_select) - (sg->info->chip_select)(sg->info, value); + (sg->info->chip_select)(sg->info, dev->chip_select, value); } static int s3c2410_spigpio_probe(struct platform_device *dev) @@ -112,14 +112,17 @@ static int s3c2410_spigpio_probe(struct platform_set_drvdata(dev, sp); - /* copy in the plkatform data */ + /* copy in the platform data */ info = sp->info = dev->dev.platform_data; + master->num_chipselect = info->num_chipselect; + /* setup spi bitbang adaptor */ sp->bitbang.master = spi_master_get(master); sp->bitbang.master->bus_num = info->bus_num; sp->bitbang.master->num_chipselect = info->num_chipselect; sp->bitbang.chipselect = s3c2410_spigpio_chipselect; + sp->bitbang.non_blocking_transfer = info->non_blocking_transfer; sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0; sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1; --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -129,6 +129,8 @@ struct mmc_request { struct mmc_host; struct mmc_card; +extern void mmc_flush_scheduled_work(void); + extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *); extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -25,5 +25,9 @@ #define SDIO_VENDOR_ID_MARVELL 0x02df #define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103 +#define SDIO_DEVICE_ID_MARVELL_88W8688 0x9104 +#define SDIO_VENDOR_ID_ATHEROS 0x0271 +#define SDIO_DEVICE_ID_ATHEROS_AR6001 0x0100 +#define SDIO_DEVICE_ID_ATHEROS_AR6002 0x0200 #endif --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -31,6 +31,9 @@ struct spi_bitbang { u8 use_dma; u8 flags; /* extra spi->mode support */ + /* Support for synchronous non blocking transfers */ + int non_blocking_transfer; + struct spi_master *master; /* setup_transfer() changes clock and/or wordsize to match settings @@ -62,6 +65,8 @@ extern void spi_bitbang_cleanup(struct s extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m); extern int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t); +extern int spi_bitbang_transfer_sync(struct spi_device *spi, + struct spi_message *m); /* start or stop queue processing */ extern int spi_bitbang_start(struct spi_bitbang *spi); --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -204,7 +204,6 @@ static inline void spi_unregister_driver * SPI slaves, and are numbered from zero to num_chipselects. * each slave has a chipselect signal, but it's common that not * every chipselect is connected to a slave. - * @dma_alignment: SPI controller constraint on DMA buffers alignment. * @setup: updates the device mode and clocking records used by a * device's SPI controller; protocol code may call this. This * must fail if an unrecognized or unsupported mode is requested. @@ -240,17 +239,7 @@ struct spi_master { */ u16 num_chipselect; - /* some SPI controllers pose alignment requirements on DMAable - * buffers; let protocol drivers know about these requirements. - */ - u16 dma_alignment; - - /* Setup mode and clock, etc (spi driver may call many times). - * - * IMPORTANT: this may be called when transfers to another - * device are active. DO NOT UPDATE SHARED REGISTERS in ways - * which could break those transfers. - */ + /* setup mode and clock, etc (spi driver may call many times) */ int (*setup)(struct spi_device *spi); /* bidirectional bulk transfers @@ -275,6 +264,13 @@ struct spi_master { int (*transfer)(struct spi_device *spi, struct spi_message *mesg); + /* + * Synchronous non blocking transfer function. Should guarantee + * data availability when it returns + */ + int (*transfer_sync)(struct spi_device *spi, + struct spi_message *mesg); + /* called on release() to free memory provided by spi_master */ void (*cleanup)(struct spi_device *spi); }; @@ -584,6 +580,29 @@ spi_async(struct spi_device *spi, struct return spi->master->transfer(spi, message); } +/** + * spi_non_blocking_transfer - Synchronous, non blocking transfer + * @spi: device with which data will be exchanged + * @message: describes the data transfers with optional completion handlers + * Context: any (irqs may be blocked, etc) + * + * Data is guaranteed to be written or read when this function returns. + * + * Note : This may not be supported by all spi masters. + */ + +static inline int +spi_non_blocking_transfer(struct spi_device *spi, struct spi_message *message) +{ + if (unlikely(!spi->master->transfer_sync)) { + dev_err(&spi->master->dev, + "non-blocking transfers not supported\n"); + return -EIO; + } + + return spi->master->transfer_sync(spi, message); +} + /*---------------------------------------------------------------------------*/ /* All these synchronous SPI transfer routines are utilities layered