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

Commit 24b414d5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull spi fixes from Mark Brown:
 "A few driver specific fixes, the biggest one being a fix for the newly
  added Qualcomm SPI controller driver to make it not use its internal
  chip select due to hardware bugs, replacing it with GPIOs"

* tag 'spi-v3.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: qup: Remove chip select function
  spi: qup: Fix order of spi_register_master
  spi: sh-sci: fix use-after-free in sh_sci_spi_remove()
  spi/pxa2xx: fix incorrect SW mode chipselect setting for BayTrail LPSS SPI
parents 4194976b 7216a418
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -23,6 +23,12 @@ Optional properties:
- spi-max-frequency: Specifies maximum SPI clock frequency,
                     Units - Hz. Definition as per
                     Documentation/devicetree/bindings/spi/spi-bus.txt
- num-cs:	total number of chipselects
- cs-gpios:	should specify GPIOs used for chipselects.
		The gpios will be referred to as reg = <index> in the SPI child
		nodes.  If unspecified, a single SPI device without a chip
		select can be used.


SPI slave nodes must be children of the SPI master node and can contain
properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
+6 −2
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
	 */
	orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);

	/* Test SPI_CS_CONTROL_SW_MODE bit enabling */
	value = orig | SPI_CS_CONTROL_SW_MODE;
	writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
	value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
@@ -126,10 +127,13 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
		goto detection_done;
	}

	value &= ~SPI_CS_CONTROL_SW_MODE;
	orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);

	/* Test SPI_CS_CONTROL_SW_MODE bit disabling */
	value = orig & ~SPI_CS_CONTROL_SW_MODE;
	writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
	value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
	if (value != orig) {
	if (value != (orig & ~SPI_CS_CONTROL_SW_MODE)) {
		offset = 0x800;
		goto detection_done;
	}
+13 −31
Original line number Diff line number Diff line
@@ -424,31 +424,6 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
	return 0;
}

static void spi_qup_set_cs(struct spi_device *spi, bool enable)
{
	struct spi_qup *controller = spi_master_get_devdata(spi->master);

	u32 iocontol, mask;

	iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL);

	/* Disable auto CS toggle and use manual */
	iocontol &= ~SPI_IO_C_MX_CS_MODE;
	iocontol |= SPI_IO_C_FORCE_CS;

	iocontol &= ~SPI_IO_C_CS_SELECT_MASK;
	iocontol |= SPI_IO_C_CS_SELECT(spi->chip_select);

	mask = SPI_IO_C_CS_N_POLARITY_0 << spi->chip_select;

	if (enable)
		iocontol |= mask;
	else
		iocontol &= ~mask;

	writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL);
}

static int spi_qup_transfer_one(struct spi_master *master,
			      struct spi_device *spi,
			      struct spi_transfer *xfer)
@@ -571,12 +546,16 @@ static int spi_qup_probe(struct platform_device *pdev)
		return -ENOMEM;
	}

	/* use num-cs unless not present or out of range */
	if (of_property_read_u16(dev->of_node, "num-cs",
			&master->num_chipselect) ||
			(master->num_chipselect > SPI_NUM_CHIPSELECTS))
		master->num_chipselect = SPI_NUM_CHIPSELECTS;

	master->bus_num = pdev->id;
	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
	master->num_chipselect = SPI_NUM_CHIPSELECTS;
	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
	master->max_speed_hz = max_freq;
	master->set_cs = spi_qup_set_cs;
	master->transfer_one = spi_qup_transfer_one;
	master->dev.of_node = pdev->dev.of_node;
	master->auto_runtime_pm = true;
@@ -640,16 +619,19 @@ static int spi_qup_probe(struct platform_device *pdev)
	if (ret)
		goto error;

	ret = devm_spi_register_master(dev, master);
	if (ret)
		goto error;

	pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
	pm_runtime_use_autosuspend(dev);
	pm_runtime_set_active(dev);
	pm_runtime_enable(dev);

	ret = devm_spi_register_master(dev, master);
	if (ret)
		goto disable_pm;

	return 0;

disable_pm:
	pm_runtime_disable(&pdev->dev);
error:
	clk_disable_unprepare(cclk);
	clk_disable_unprepare(iclk);
+2 −2
Original line number Diff line number Diff line
@@ -175,9 +175,9 @@ static int sh_sci_spi_remove(struct platform_device *dev)
{
	struct sh_sci_spi *sp = platform_get_drvdata(dev);

	iounmap(sp->membase);
	setbits(sp, PIN_INIT, 0);
	spi_bitbang_stop(&sp->bitbang);
	setbits(sp, PIN_INIT, 0);
	iounmap(sp->membase);
	spi_master_put(sp->bitbang.master);
	return 0;
}