diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-05 13:04:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-05 13:04:41 -0400 |
commit | e0a77f26312a8b23b6040073c50b0c19b82ce8b4 (patch) | |
tree | 1edf0e5adcb876a20cb045c98b079cde5da3ce98 /drivers | |
parent | e24b0bfa2f0446ffaad2661040be23668133aef8 (diff) | |
parent | 1ad849aee5f53353ed88d9cd3d68a51b03a7d44f (diff) |
Merge tag 'spi-fix-v3.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc
Pull spi fixes from Mark Brown:
"A bunch of small driver fixes plus a fix for error handling in the
core - nothing too exciting overall."
* tag 'spi-fix-v3.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc:
spi/mpc512x-psc: optionally keep PSC SS asserted across xfer segmensts
spi: Unlock a spinlock before calling into the controller driver.
spi/s3c64xx: modified error interrupt handling and init
spi/bcm63xx: don't disable non enabled clocks in probe error path
spi/bcm63xx: Remove unused variable
spi: slink-tegra20: move runtime pm calls to transfer_one_message
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/spi-bcm63xx.c | 3 | ||||
-rw-r--r-- | drivers/spi/spi-mpc512x-psc.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-s3c64xx.c | 41 | ||||
-rw-r--r-- | drivers/spi/spi-tegra20-slink.c | 25 | ||||
-rw-r--r-- | drivers/spi/spi.c | 15 |
5 files changed, 42 insertions, 44 deletions
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 9578af782a77..d7df435d962e 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c | |||
@@ -152,7 +152,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi, | |||
152 | static int bcm63xx_spi_setup(struct spi_device *spi) | 152 | static int bcm63xx_spi_setup(struct spi_device *spi) |
153 | { | 153 | { |
154 | struct bcm63xx_spi *bs; | 154 | struct bcm63xx_spi *bs; |
155 | int ret; | ||
156 | 155 | ||
157 | bs = spi_master_get_devdata(spi->master); | 156 | bs = spi_master_get_devdata(spi->master); |
158 | 157 | ||
@@ -490,7 +489,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) | |||
490 | default: | 489 | default: |
491 | dev_err(dev, "unsupported MSG_CTL width: %d\n", | 490 | dev_err(dev, "unsupported MSG_CTL width: %d\n", |
492 | bs->msg_ctl_width); | 491 | bs->msg_ctl_width); |
493 | goto out_clk_disable; | 492 | goto out_err; |
494 | } | 493 | } |
495 | 494 | ||
496 | /* Initialize hardware */ | 495 | /* Initialize hardware */ |
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 89480b281d74..3e490ee7f275 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c | |||
@@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, | |||
164 | 164 | ||
165 | for (i = count; i > 0; i--) { | 165 | for (i = count; i > 0; i--) { |
166 | data = tx_buf ? *tx_buf++ : 0; | 166 | data = tx_buf ? *tx_buf++ : 0; |
167 | if (len == EOFBYTE) | 167 | if (len == EOFBYTE && t->cs_change) |
168 | setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); | 168 | setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); |
169 | out_8(&fifo->txdata_8, data); | 169 | out_8(&fifo->txdata_8, data); |
170 | len--; | 170 | len--; |
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index e862ab8853aa..4188b2faac5c 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c | |||
@@ -994,25 +994,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data) | |||
994 | { | 994 | { |
995 | struct s3c64xx_spi_driver_data *sdd = data; | 995 | struct s3c64xx_spi_driver_data *sdd = data; |
996 | struct spi_master *spi = sdd->master; | 996 | struct spi_master *spi = sdd->master; |
997 | unsigned int val; | 997 | unsigned int val, clr = 0; |
998 | 998 | ||
999 | val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR); | 999 | val = readl(sdd->regs + S3C64XX_SPI_STATUS); |
1000 | 1000 | ||
1001 | val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR | | 1001 | if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) { |
1002 | S3C64XX_SPI_PND_RX_UNDERRUN_CLR | | 1002 | clr = S3C64XX_SPI_PND_RX_OVERRUN_CLR; |
1003 | S3C64XX_SPI_PND_TX_OVERRUN_CLR | | ||
1004 | S3C64XX_SPI_PND_TX_UNDERRUN_CLR; | ||
1005 | |||
1006 | writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR); | ||
1007 | |||
1008 | if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR) | ||
1009 | dev_err(&spi->dev, "RX overrun\n"); | 1003 | dev_err(&spi->dev, "RX overrun\n"); |
1010 | if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR) | 1004 | } |
1005 | if (val & S3C64XX_SPI_ST_RX_UNDERRUN_ERR) { | ||
1006 | clr |= S3C64XX_SPI_PND_RX_UNDERRUN_CLR; | ||
1011 | dev_err(&spi->dev, "RX underrun\n"); | 1007 | dev_err(&spi->dev, "RX underrun\n"); |
1012 | if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR) | 1008 | } |
1009 | if (val & S3C64XX_SPI_ST_TX_OVERRUN_ERR) { | ||
1010 | clr |= S3C64XX_SPI_PND_TX_OVERRUN_CLR; | ||
1013 | dev_err(&spi->dev, "TX overrun\n"); | 1011 | dev_err(&spi->dev, "TX overrun\n"); |
1014 | if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR) | 1012 | } |
1013 | if (val & S3C64XX_SPI_ST_TX_UNDERRUN_ERR) { | ||
1014 | clr |= S3C64XX_SPI_PND_TX_UNDERRUN_CLR; | ||
1015 | dev_err(&spi->dev, "TX underrun\n"); | 1015 | dev_err(&spi->dev, "TX underrun\n"); |
1016 | } | ||
1017 | |||
1018 | /* Clear the pending irq by setting and then clearing it */ | ||
1019 | writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR); | ||
1020 | writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR); | ||
1016 | 1021 | ||
1017 | return IRQ_HANDLED; | 1022 | return IRQ_HANDLED; |
1018 | } | 1023 | } |
@@ -1036,9 +1041,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) | |||
1036 | writel(0, regs + S3C64XX_SPI_MODE_CFG); | 1041 | writel(0, regs + S3C64XX_SPI_MODE_CFG); |
1037 | writel(0, regs + S3C64XX_SPI_PACKET_CNT); | 1042 | writel(0, regs + S3C64XX_SPI_PACKET_CNT); |
1038 | 1043 | ||
1039 | /* Clear any irq pending bits */ | 1044 | /* Clear any irq pending bits, should set and clear the bits */ |
1040 | writel(readl(regs + S3C64XX_SPI_PENDING_CLR), | 1045 | val = S3C64XX_SPI_PND_RX_OVERRUN_CLR | |
1041 | regs + S3C64XX_SPI_PENDING_CLR); | 1046 | S3C64XX_SPI_PND_RX_UNDERRUN_CLR | |
1047 | S3C64XX_SPI_PND_TX_OVERRUN_CLR | | ||
1048 | S3C64XX_SPI_PND_TX_UNDERRUN_CLR; | ||
1049 | writel(val, regs + S3C64XX_SPI_PENDING_CLR); | ||
1050 | writel(0, regs + S3C64XX_SPI_PENDING_CLR); | ||
1042 | 1051 | ||
1043 | writel(0, regs + S3C64XX_SPI_SWAP_CFG); | 1052 | writel(0, regs + S3C64XX_SPI_SWAP_CFG); |
1044 | 1053 | ||
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index b8698b389ef3..a829563f4713 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c | |||
@@ -858,21 +858,6 @@ static int tegra_slink_setup(struct spi_device *spi) | |||
858 | return 0; | 858 | return 0; |
859 | } | 859 | } |
860 | 860 | ||
861 | static int tegra_slink_prepare_transfer(struct spi_master *master) | ||
862 | { | ||
863 | struct tegra_slink_data *tspi = spi_master_get_devdata(master); | ||
864 | |||
865 | return pm_runtime_get_sync(tspi->dev); | ||
866 | } | ||
867 | |||
868 | static int tegra_slink_unprepare_transfer(struct spi_master *master) | ||
869 | { | ||
870 | struct tegra_slink_data *tspi = spi_master_get_devdata(master); | ||
871 | |||
872 | pm_runtime_put(tspi->dev); | ||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static int tegra_slink_transfer_one_message(struct spi_master *master, | 861 | static int tegra_slink_transfer_one_message(struct spi_master *master, |
877 | struct spi_message *msg) | 862 | struct spi_message *msg) |
878 | { | 863 | { |
@@ -885,6 +870,12 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, | |||
885 | 870 | ||
886 | msg->status = 0; | 871 | msg->status = 0; |
887 | msg->actual_length = 0; | 872 | msg->actual_length = 0; |
873 | ret = pm_runtime_get_sync(tspi->dev); | ||
874 | if (ret < 0) { | ||
875 | dev_err(tspi->dev, "runtime get failed: %d\n", ret); | ||
876 | goto done; | ||
877 | } | ||
878 | |||
888 | single_xfer = list_is_singular(&msg->transfers); | 879 | single_xfer = list_is_singular(&msg->transfers); |
889 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 880 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
890 | INIT_COMPLETION(tspi->xfer_completion); | 881 | INIT_COMPLETION(tspi->xfer_completion); |
@@ -921,6 +912,8 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, | |||
921 | exit: | 912 | exit: |
922 | tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND); | 913 | tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND); |
923 | tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2); | 914 | tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2); |
915 | pm_runtime_put(tspi->dev); | ||
916 | done: | ||
924 | msg->status = ret; | 917 | msg->status = ret; |
925 | spi_finalize_current_message(master); | 918 | spi_finalize_current_message(master); |
926 | return ret; | 919 | return ret; |
@@ -1148,9 +1141,7 @@ static int tegra_slink_probe(struct platform_device *pdev) | |||
1148 | /* the spi->mode bits understood by this driver: */ | 1141 | /* the spi->mode bits understood by this driver: */ |
1149 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 1142 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
1150 | master->setup = tegra_slink_setup; | 1143 | master->setup = tegra_slink_setup; |
1151 | master->prepare_transfer_hardware = tegra_slink_prepare_transfer; | ||
1152 | master->transfer_one_message = tegra_slink_transfer_one_message; | 1144 | master->transfer_one_message = tegra_slink_transfer_one_message; |
1153 | master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer; | ||
1154 | master->num_chipselect = MAX_CHIP_SELECT; | 1145 | master->num_chipselect = MAX_CHIP_SELECT; |
1155 | master->bus_num = -1; | 1146 | master->bus_num = -1; |
1156 | 1147 | ||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5e073d897edb..004b10f184d4 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work) | |||
543 | /* Lock queue and check for queue work */ | 543 | /* Lock queue and check for queue work */ |
544 | spin_lock_irqsave(&master->queue_lock, flags); | 544 | spin_lock_irqsave(&master->queue_lock, flags); |
545 | if (list_empty(&master->queue) || !master->running) { | 545 | if (list_empty(&master->queue) || !master->running) { |
546 | if (master->busy && master->unprepare_transfer_hardware) { | 546 | if (!master->busy) { |
547 | ret = master->unprepare_transfer_hardware(master); | 547 | spin_unlock_irqrestore(&master->queue_lock, flags); |
548 | if (ret) { | 548 | return; |
549 | spin_unlock_irqrestore(&master->queue_lock, flags); | ||
550 | dev_err(&master->dev, | ||
551 | "failed to unprepare transfer hardware\n"); | ||
552 | return; | ||
553 | } | ||
554 | } | 549 | } |
555 | master->busy = false; | 550 | master->busy = false; |
556 | spin_unlock_irqrestore(&master->queue_lock, flags); | 551 | spin_unlock_irqrestore(&master->queue_lock, flags); |
552 | if (master->unprepare_transfer_hardware && | ||
553 | master->unprepare_transfer_hardware(master)) | ||
554 | dev_err(&master->dev, | ||
555 | "failed to unprepare transfer hardware\n"); | ||
557 | return; | 556 | return; |
558 | } | 557 | } |
559 | 558 | ||