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
Unified · Split
| @@ -152,7 +152,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi, · 151 unmodified lines | ||
| 152 | 152 | static int bcm63xx_spi_setup(struct spi_device *spi) |
| 153 | 153 | { |
| 154 | 154 | struct bcm63xx_spi *bs; |
| 155 | − int ret; | |
| 156 | 155 | |
| 157 | 156 | bs = spi_master_get_devdata(spi->master); |
| 158 | 157 | |
| @@ -490,7 +489,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) · 331 unmodified lines | ||
| 490 | 489 | default: |
| 491 | 490 | dev_err(dev, "unsupported MSG_CTL width: %d\n", |
| 492 | 491 | bs->msg_ctl_width); |
| 493 | − goto out_clk_disable; | |
| 492 | + goto out_err; | |
| 494 | 493 | } |
| 495 | 494 | |
| 496 | 495 | /* Initialize hardware */ |
| @@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, · 163 unmodified lines | ||
| 164 | 164 | |
| 165 | 165 | for (i = count; i > 0; i--) { |
| 166 | 166 | data = tx_buf ? *tx_buf++ : 0; |
| 167 | − if (len == EOFBYTE) | |
| 167 | + if (len == EOFBYTE && t->cs_change) | |
| 168 | 168 | setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); |
| 169 | 169 | out_8(&fifo->txdata_8, data); |
| 170 | 170 | len--; |
| @@ -994,25 +994,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data) · 993 unmodified lines | ||
| 994 | 994 | { |
| 995 | 995 | struct s3c64xx_spi_driver_data *sdd = data; |
| 996 | 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 | | |
| 1002 | − S3C64XX_SPI_PND_RX_UNDERRUN_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) | |
| 1001 | + if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) { | |
| 1002 | + clr = S3C64XX_SPI_PND_RX_OVERRUN_CLR; | |
| 1009 | 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 | 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 | 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 | 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 | 1022 | return IRQ_HANDLED; |
| 1018 | 1023 | } |
| @@ -1036,9 +1041,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) · 17 unmodified lines | ||
| 1036 | 1041 | writel(0, regs + S3C64XX_SPI_MODE_CFG); |
| 1037 | 1042 | writel(0, regs + S3C64XX_SPI_PACKET_CNT); |
| 1038 | 1043 | |
| 1039 | − /* Clear any irq pending bits */ | |
| 1040 | − writel(readl(regs + S3C64XX_SPI_PENDING_CLR), | |
| 1041 | − regs + S3C64XX_SPI_PENDING_CLR); | |
| 1044 | + /* Clear any irq pending bits, should set and clear the bits */ | |
| 1045 | + val = S3C64XX_SPI_PND_RX_OVERRUN_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 | 1052 | writel(0, regs + S3C64XX_SPI_SWAP_CFG); |
| 1044 | 1053 | |
| @@ -858,21 +858,6 @@ static int tegra_slink_setup(struct spi_device *spi) · 857 unmodified lines | ||
| 858 | 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 | 861 | static int tegra_slink_transfer_one_message(struct spi_master *master, |
| 877 | 862 | struct spi_message *msg) |
| 878 | 863 | { |
| @@ -885,6 +870,12 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, · 6 unmodified lines | ||
| 885 | 870 | |
| 886 | 871 | msg->status = 0; |
| 887 | 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 | 879 | single_xfer = list_is_singular(&msg->transfers); |
| 889 | 880 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
| 890 | 881 | INIT_COMPLETION(tspi->xfer_completion); |
| @@ -921,6 +912,8 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, · 30 unmodified lines | ||
| 921 | 912 | exit: |
| 922 | 913 | tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND); |
| 923 | 914 | tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2); |
| 915 | + pm_runtime_put(tspi->dev); | |
| 916 | +done: | |
| 924 | 917 | msg->status = ret; |
| 925 | 918 | spi_finalize_current_message(master); |
| 926 | 919 | return ret; |
| @@ -1148,9 +1141,7 @@ static int tegra_slink_probe(struct platform_device *pdev) · 221 unmodified lines | ||
| 1148 | 1141 | /* the spi->mode bits understood by this driver: */ |
| 1149 | 1142 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
| 1150 | 1143 | master->setup = tegra_slink_setup; |
| 1151 | − master->prepare_transfer_hardware = tegra_slink_prepare_transfer; | |
| 1152 | 1144 | master->transfer_one_message = tegra_slink_transfer_one_message; |
| 1153 | − master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer; | |
| 1154 | 1145 | master->num_chipselect = MAX_CHIP_SELECT; |
| 1155 | 1146 | master->bus_num = -1; |
| 1156 | 1147 | |
| @@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work) · 542 unmodified lines | ||
| 543 | 543 | /* Lock queue and check for queue work */ |
| 544 | 544 | spin_lock_irqsave(&master->queue_lock, flags); |
| 545 | 545 | if (list_empty(&master->queue) || !master->running) { |
| 546 | − if (master->busy && master->unprepare_transfer_hardware) { | |
| 547 | − ret = master->unprepare_transfer_hardware(master); | |
| 548 | − if (ret) { | |
| 549 | − spin_unlock_irqrestore(&master->queue_lock, flags); | |
| 550 | − dev_err(&master->dev, | |
| 551 | − "failed to unprepare transfer hardware\n"); | |
| 552 | − return; | |
| 553 | − } | |
| 546 | + if (!master->busy) { | |
| 547 | + spin_unlock_irqrestore(&master->queue_lock, flags); | |
| 548 | + return; | |
| 554 | 549 | } |
| 555 | 550 | master->busy = false; |
| 556 | 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 | 556 | return; |
| 558 | 557 | } |
| 559 | 558 | |