Merge tag 'stable/for-linus-3.9-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / spi / spi-s3c64xx.c
index e862ab8..4188b2f 100644 (file)
@@ -994,25 +994,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
 {
        struct s3c64xx_spi_driver_data *sdd = data;
        struct spi_master *spi = sdd->master;
-       unsigned int val;
+       unsigned int val, clr = 0;
 
-       val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR);
+       val = readl(sdd->regs + S3C64XX_SPI_STATUS);
 
-       val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR |
-               S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
-               S3C64XX_SPI_PND_TX_OVERRUN_CLR |
-               S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
-
-       writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR);
-
-       if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR)
+       if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) {
+               clr = S3C64XX_SPI_PND_RX_OVERRUN_CLR;
                dev_err(&spi->dev, "RX overrun\n");
-       if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR)
+       }
+       if (val & S3C64XX_SPI_ST_RX_UNDERRUN_ERR) {
+               clr |= S3C64XX_SPI_PND_RX_UNDERRUN_CLR;
                dev_err(&spi->dev, "RX underrun\n");
-       if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR)
+       }
+       if (val & S3C64XX_SPI_ST_TX_OVERRUN_ERR) {
+               clr |= S3C64XX_SPI_PND_TX_OVERRUN_CLR;
                dev_err(&spi->dev, "TX overrun\n");
-       if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR)
+       }
+       if (val & S3C64XX_SPI_ST_TX_UNDERRUN_ERR) {
+               clr |= S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
                dev_err(&spi->dev, "TX underrun\n");
+       }
+
+       /* Clear the pending irq by setting and then clearing it */
+       writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR);
+       writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR);
 
        return IRQ_HANDLED;
 }
@@ -1036,9 +1041,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
        writel(0, regs + S3C64XX_SPI_MODE_CFG);
        writel(0, regs + S3C64XX_SPI_PACKET_CNT);
 
-       /* Clear any irq pending bits */
-       writel(readl(regs + S3C64XX_SPI_PENDING_CLR),
-                               regs + S3C64XX_SPI_PENDING_CLR);
+       /* Clear any irq pending bits, should set and clear the bits */
+       val = S3C64XX_SPI_PND_RX_OVERRUN_CLR |
+               S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
+               S3C64XX_SPI_PND_TX_OVERRUN_CLR |
+               S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
+       writel(val, regs + S3C64XX_SPI_PENDING_CLR);
+       writel(0, regs + S3C64XX_SPI_PENDING_CLR);
 
        writel(0, regs + S3C64XX_SPI_SWAP_CFG);