diff options
| -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); |
