Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0a77f26 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -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 */
+1 −1
Original line number Diff line number Diff line
@@ -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--;
+25 −16
Original line number Diff line number Diff line
@@ -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);

+8 −17
Original line number Diff line number Diff line
@@ -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;

+7 −8
Original line number Diff line number Diff line
@@ -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) {
		if (!master->busy) {
			spin_unlock_irqrestore(&master->queue_lock, flags);
				dev_err(&master->dev,
					"failed to unprepare transfer hardware\n");
			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;
	}