spi: Fixes for v3.9
A bunch of small driver fixes plus a fix for error handling in the core - nothing too exciting overall. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJRXt12AAoJELSic+t+oim9PNIP/RPojoOyrzSr2knNwgFHtxo7 rcQqxq/Z0Ah6B/BKZ5qomzIaUPzLoKGM2ND4KhCJjBrXY3PR6hJQK6b4M2ocXbpK whC5lt36M9/3b/eLGH9lIfKGXPKT+n2qfvbALdlxWYTcLbeoiMfakwcGhZngihEq H96x7+xOuBheF8dx46+zG10uUm0lP3hpELzXKqHi/K173FEfgIeq9iELzfTiQbIw tdXUl7jrUwifvBlUx3/tRM334K4pAGeq+hLtftxvX/qFBqNIZ6bO3ZguZLaPNgXd NvQ1AtsArf2KmL+/093Zesz+b7fqfLEjsBqecWjhT7UWEs1y8qmmTBNM6cgAOzyg OZnFzZ8fl3G9YuLgktAFr1pWT9T43B/ZFbQ4NQzkxVOh1QvOz1Xkx9JS0hCigVBu pen6n5L2OWzxcGsDiB38b4HSCzLgNt4QtsXCtQZaDKUJ6Q8pmsCWClyPfqJwbEWR 5QNW/8x2BCuQMSa4aKvPhjw9bIfOhOYX/+JQezHdS/pu6nwAGHHM5Yohtjn9/hm/ 6hXniAzctT6rbk4ZDr5ux1CBxyBzjcTAL0tdiqFglAYcXwRNpzqm714jKN57yH6p YXD3V2aRF7h7honDJqav18M9opuIo4rNg0lBCreA+5FJ+MmQHLIU/DvfO6qUV2/0 XO540x4NdS1PMAX02P1h =eqgv -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
e0a77f2631
@ -152,7 +152,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
|
||||
static int bcm63xx_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct bcm63xx_spi *bs;
|
||||
int ret;
|
||||
|
||||
bs = spi_master_get_devdata(spi->master);
|
||||
|
||||
@ -490,7 +489,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
||||
default:
|
||||
dev_err(dev, "unsupported MSG_CTL width: %d\n",
|
||||
bs->msg_ctl_width);
|
||||
goto out_clk_disable;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* Initialize hardware */
|
||||
|
@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
|
||||
|
||||
for (i = count; i > 0; i--) {
|
||||
data = tx_buf ? *tx_buf++ : 0;
|
||||
if (len == EOFBYTE)
|
||||
if (len == EOFBYTE && t->cs_change)
|
||||
setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
|
||||
out_8(&fifo->txdata_8, data);
|
||||
len--;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -858,21 +858,6 @@ static int tegra_slink_setup(struct spi_device *spi)
|
||||
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,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
@ -885,6 +870,12 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
|
||||
|
||||
msg->status = 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);
|
||||
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
|
||||
INIT_COMPLETION(tspi->xfer_completion);
|
||||
@ -921,6 +912,8 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
|
||||
exit:
|
||||
tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
|
||||
tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
|
||||
pm_runtime_put(tspi->dev);
|
||||
done:
|
||||
msg->status = ret;
|
||||
spi_finalize_current_message(master);
|
||||
return ret;
|
||||
@ -1148,9 +1141,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
|
||||
/* the spi->mode bits understood by this driver: */
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
master->setup = tegra_slink_setup;
|
||||
master->prepare_transfer_hardware = tegra_slink_prepare_transfer;
|
||||
master->transfer_one_message = tegra_slink_transfer_one_message;
|
||||
master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer;
|
||||
master->num_chipselect = MAX_CHIP_SELECT;
|
||||
master->bus_num = -1;
|
||||
|
||||
|
@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work)
|
||||
/* Lock queue and check for queue work */
|
||||
spin_lock_irqsave(&master->queue_lock, flags);
|
||||
if (list_empty(&master->queue) || !master->running) {
|
||||
if (master->busy && master->unprepare_transfer_hardware) {
|
||||
ret = master->unprepare_transfer_hardware(master);
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&master->queue_lock, flags);
|
||||
dev_err(&master->dev,
|
||||
"failed to unprepare transfer hardware\n");
|
||||
return;
|
||||
}
|
||||
if (!master->busy) {
|
||||
spin_unlock_irqrestore(&master->queue_lock, flags);
|
||||
return;
|
||||
}
|
||||
master->busy = false;
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user