diff options
author | Nicolas Ferre <nicolas.ferre@atmel.com> | 2013-04-03 01:58:36 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-23 14:30:19 -0400 |
commit | 8aad7924b5f55e330aebc1351525df9fa0056461 (patch) | |
tree | d9bee36fcab9bac4c6382cdc6feba6038ab25ffc /drivers/spi | |
parent | dfab30ee6184210ac3b91e3f70efaa47f14be4c4 (diff) |
spi/spi-atmel: add flag to controller data for lock operations
Will allow to drop the lock during DMA operations.
Replacing non-irqsave versions with irqsave versions of the lock
to make it correct in both pdc and dmaengine transfer mode
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
[wenyou.yang@atmel.com: submit the patch]
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Tested-by: Richard Genoud <richard.genoud@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-atmel.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 7e10bdb4a714..3625951e5df5 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c | |||
@@ -195,6 +195,7 @@ struct atmel_spi_caps { | |||
195 | */ | 195 | */ |
196 | struct atmel_spi { | 196 | struct atmel_spi { |
197 | spinlock_t lock; | 197 | spinlock_t lock; |
198 | unsigned long flags; | ||
198 | 199 | ||
199 | phys_addr_t phybase; | 200 | phys_addr_t phybase; |
200 | void __iomem *regs; | 201 | void __iomem *regs; |
@@ -333,6 +334,16 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) | |||
333 | gpio_set_value(asd->npcs_pin, !active); | 334 | gpio_set_value(asd->npcs_pin, !active); |
334 | } | 335 | } |
335 | 336 | ||
337 | static void atmel_spi_lock(struct atmel_spi *as) | ||
338 | { | ||
339 | spin_lock_irqsave(&as->lock, as->flags); | ||
340 | } | ||
341 | |||
342 | static void atmel_spi_unlock(struct atmel_spi *as) | ||
343 | { | ||
344 | spin_unlock_irqrestore(&as->lock, as->flags); | ||
345 | } | ||
346 | |||
336 | static inline int atmel_spi_xfer_is_last(struct spi_message *msg, | 347 | static inline int atmel_spi_xfer_is_last(struct spi_message *msg, |
337 | struct spi_transfer *xfer) | 348 | struct spi_transfer *xfer) |
338 | { | 349 | { |
@@ -569,9 +580,9 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as, | |||
569 | "xfer complete: %u bytes transferred\n", | 580 | "xfer complete: %u bytes transferred\n", |
570 | msg->actual_length); | 581 | msg->actual_length); |
571 | 582 | ||
572 | spin_unlock(&as->lock); | 583 | atmel_spi_unlock(as); |
573 | msg->complete(msg->context); | 584 | msg->complete(msg->context); |
574 | spin_lock(&as->lock); | 585 | atmel_spi_lock(as); |
575 | 586 | ||
576 | as->current_transfer = NULL; | 587 | as->current_transfer = NULL; |
577 | as->next_transfer = NULL; | 588 | as->next_transfer = NULL; |
@@ -594,7 +605,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
594 | u32 status, pending, imr; | 605 | u32 status, pending, imr; |
595 | int ret = IRQ_NONE; | 606 | int ret = IRQ_NONE; |
596 | 607 | ||
597 | spin_lock(&as->lock); | 608 | atmel_spi_lock(as); |
598 | 609 | ||
599 | xfer = as->current_transfer; | 610 | xfer = as->current_transfer; |
600 | msg = list_entry(as->queue.next, struct spi_message, queue); | 611 | msg = list_entry(as->queue.next, struct spi_message, queue); |
@@ -697,7 +708,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
697 | } | 708 | } |
698 | } | 709 | } |
699 | 710 | ||
700 | spin_unlock(&as->lock); | 711 | atmel_spi_unlock(as); |
701 | 712 | ||
702 | return ret; | 713 | return ret; |
703 | } | 714 | } |
@@ -802,13 +813,11 @@ static int atmel_spi_setup(struct spi_device *spi) | |||
802 | spi->controller_state = asd; | 813 | spi->controller_state = asd; |
803 | gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH)); | 814 | gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH)); |
804 | } else { | 815 | } else { |
805 | unsigned long flags; | 816 | atmel_spi_lock(as); |
806 | |||
807 | spin_lock_irqsave(&as->lock, flags); | ||
808 | if (as->stay == spi) | 817 | if (as->stay == spi) |
809 | as->stay = NULL; | 818 | as->stay = NULL; |
810 | cs_deactivate(as, spi); | 819 | cs_deactivate(as, spi); |
811 | spin_unlock_irqrestore(&as->lock, flags); | 820 | atmel_spi_unlock(as); |
812 | } | 821 | } |
813 | 822 | ||
814 | asd->csr = csr; | 823 | asd->csr = csr; |
@@ -827,7 +836,6 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) | |||
827 | { | 836 | { |
828 | struct atmel_spi *as; | 837 | struct atmel_spi *as; |
829 | struct spi_transfer *xfer; | 838 | struct spi_transfer *xfer; |
830 | unsigned long flags; | ||
831 | struct device *controller = spi->master->dev.parent; | 839 | struct device *controller = spi->master->dev.parent; |
832 | u8 bits; | 840 | u8 bits; |
833 | struct atmel_spi_device *asd; | 841 | struct atmel_spi_device *asd; |
@@ -892,11 +900,11 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) | |||
892 | msg->status = -EINPROGRESS; | 900 | msg->status = -EINPROGRESS; |
893 | msg->actual_length = 0; | 901 | msg->actual_length = 0; |
894 | 902 | ||
895 | spin_lock_irqsave(&as->lock, flags); | 903 | atmel_spi_lock(as); |
896 | list_add_tail(&msg->queue, &as->queue); | 904 | list_add_tail(&msg->queue, &as->queue); |
897 | if (!as->current_transfer) | 905 | if (!as->current_transfer) |
898 | atmel_spi_next_message(spi->master); | 906 | atmel_spi_next_message(spi->master); |
899 | spin_unlock_irqrestore(&as->lock, flags); | 907 | atmel_spi_unlock(as); |
900 | 908 | ||
901 | return 0; | 909 | return 0; |
902 | } | 910 | } |
@@ -906,17 +914,16 @@ static void atmel_spi_cleanup(struct spi_device *spi) | |||
906 | struct atmel_spi *as = spi_master_get_devdata(spi->master); | 914 | struct atmel_spi *as = spi_master_get_devdata(spi->master); |
907 | struct atmel_spi_device *asd = spi->controller_state; | 915 | struct atmel_spi_device *asd = spi->controller_state; |
908 | unsigned gpio = (unsigned) spi->controller_data; | 916 | unsigned gpio = (unsigned) spi->controller_data; |
909 | unsigned long flags; | ||
910 | 917 | ||
911 | if (!asd) | 918 | if (!asd) |
912 | return; | 919 | return; |
913 | 920 | ||
914 | spin_lock_irqsave(&as->lock, flags); | 921 | atmel_spi_lock(as); |
915 | if (as->stay == spi) { | 922 | if (as->stay == spi) { |
916 | as->stay = NULL; | 923 | as->stay = NULL; |
917 | cs_deactivate(as, spi); | 924 | cs_deactivate(as, spi); |
918 | } | 925 | } |
919 | spin_unlock_irqrestore(&as->lock, flags); | 926 | atmel_spi_unlock(as); |
920 | 927 | ||
921 | spi->controller_state = NULL; | 928 | spi->controller_state = NULL; |
922 | gpio_free(gpio); | 929 | gpio_free(gpio); |