Commit e0a77f26 authored by Linus Torvalds's avatar Linus Torvalds

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
parents e24b0bfa 1ad849ae
...@@ -152,7 +152,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi, ...@@ -152,7 +152,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
static int bcm63xx_spi_setup(struct spi_device *spi) static int bcm63xx_spi_setup(struct spi_device *spi)
{ {
struct bcm63xx_spi *bs; struct bcm63xx_spi *bs;
int ret;
bs = spi_master_get_devdata(spi->master); bs = spi_master_get_devdata(spi->master);
...@@ -490,7 +489,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) ...@@ -490,7 +489,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
default: default:
dev_err(dev, "unsupported MSG_CTL width: %d\n", dev_err(dev, "unsupported MSG_CTL width: %d\n",
bs->msg_ctl_width); bs->msg_ctl_width);
goto out_clk_disable; goto out_err;
} }
/* Initialize hardware */ /* Initialize hardware */
......
...@@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, ...@@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
for (i = count; i > 0; i--) { for (i = count; i > 0; i--) {
data = tx_buf ? *tx_buf++ : 0; data = tx_buf ? *tx_buf++ : 0;
if (len == EOFBYTE) if (len == EOFBYTE && t->cs_change)
setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
out_8(&fifo->txdata_8, data); out_8(&fifo->txdata_8, data);
len--; len--;
......
...@@ -994,25 +994,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data) ...@@ -994,25 +994,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
{ {
struct s3c64xx_spi_driver_data *sdd = data; struct s3c64xx_spi_driver_data *sdd = data;
struct spi_master *spi = sdd->master; 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 | if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) {
S3C64XX_SPI_PND_RX_UNDERRUN_CLR | clr = S3C64XX_SPI_PND_RX_OVERRUN_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)
dev_err(&spi->dev, "RX overrun\n"); 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"); 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"); 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"); 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; return IRQ_HANDLED;
} }
...@@ -1036,9 +1041,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) ...@@ -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_MODE_CFG);
writel(0, regs + S3C64XX_SPI_PACKET_CNT); writel(0, regs + S3C64XX_SPI_PACKET_CNT);
/* Clear any irq pending bits */ /* Clear any irq pending bits, should set and clear the bits */
writel(readl(regs + S3C64XX_SPI_PENDING_CLR), val = S3C64XX_SPI_PND_RX_OVERRUN_CLR |
regs + S3C64XX_SPI_PENDING_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); writel(0, regs + S3C64XX_SPI_SWAP_CFG);
......
...@@ -858,21 +858,6 @@ static int tegra_slink_setup(struct spi_device *spi) ...@@ -858,21 +858,6 @@ static int tegra_slink_setup(struct spi_device *spi)
return 0; return 0;
} }
static int tegra_slink_prepare_transfer(struct spi_master *master)
{
struct tegra_slink_data *tspi = spi_master_get_devdata(master);
return pm_runtime_get_sync(tspi->dev);
}
static int tegra_slink_unprepare_transfer(struct spi_master *master)
{
struct tegra_slink_data *tspi = spi_master_get_devdata(master);
pm_runtime_put(tspi->dev);
return 0;
}
static int tegra_slink_transfer_one_message(struct spi_master *master, static int tegra_slink_transfer_one_message(struct spi_master *master,
struct spi_message *msg) struct spi_message *msg)
{ {
...@@ -885,6 +870,12 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, ...@@ -885,6 +870,12 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
msg->status = 0; msg->status = 0;
msg->actual_length = 0; msg->actual_length = 0;
ret = pm_runtime_get_sync(tspi->dev);
if (ret < 0) {
dev_err(tspi->dev, "runtime get failed: %d\n", ret);
goto done;
}
single_xfer = list_is_singular(&msg->transfers); single_xfer = list_is_singular(&msg->transfers);
list_for_each_entry(xfer, &msg->transfers, transfer_list) { list_for_each_entry(xfer, &msg->transfers, transfer_list) {
INIT_COMPLETION(tspi->xfer_completion); INIT_COMPLETION(tspi->xfer_completion);
...@@ -921,6 +912,8 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, ...@@ -921,6 +912,8 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
exit: exit:
tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND); tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2); tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
pm_runtime_put(tspi->dev);
done:
msg->status = ret; msg->status = ret;
spi_finalize_current_message(master); spi_finalize_current_message(master);
return ret; return ret;
...@@ -1148,9 +1141,7 @@ static int tegra_slink_probe(struct platform_device *pdev) ...@@ -1148,9 +1141,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
/* the spi->mode bits understood by this driver: */ /* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->setup = tegra_slink_setup; master->setup = tegra_slink_setup;
master->prepare_transfer_hardware = tegra_slink_prepare_transfer;
master->transfer_one_message = tegra_slink_transfer_one_message; master->transfer_one_message = tegra_slink_transfer_one_message;
master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer;
master->num_chipselect = MAX_CHIP_SELECT; master->num_chipselect = MAX_CHIP_SELECT;
master->bus_num = -1; master->bus_num = -1;
......
...@@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work) ...@@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work)
/* Lock queue and check for queue work */ /* Lock queue and check for queue work */
spin_lock_irqsave(&master->queue_lock, flags); spin_lock_irqsave(&master->queue_lock, flags);
if (list_empty(&master->queue) || !master->running) { if (list_empty(&master->queue) || !master->running) {
if (master->busy && master->unprepare_transfer_hardware) { if (!master->busy) {
ret = master->unprepare_transfer_hardware(master); spin_unlock_irqrestore(&master->queue_lock, flags);
if (ret) { return;
spin_unlock_irqrestore(&master->queue_lock, flags);
dev_err(&master->dev,
"failed to unprepare transfer hardware\n");
return;
}
} }
master->busy = false; master->busy = false;
spin_unlock_irqrestore(&master->queue_lock, flags); spin_unlock_irqrestore(&master->queue_lock, flags);
if (master->unprepare_transfer_hardware &&
master->unprepare_transfer_hardware(master))
dev_err(&master->dev,
"failed to unprepare transfer hardware\n");
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment