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

Commit 8e326471 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull spi updates from Mark Brown:
 "Quite a quiet release for SPI, there are no changes at all to the core
  and not that many changes to drivers. Highlights of those driver
  changes include:

   - SH MSIOF support for GPIO chip selects contributed by Geert
     Uytterhoeven.

   - Full duplex support for a3700 contributed by Maxime Chevallier.

   - Support for DMA transfers on Atmel devices that require a bounce
     buffer contributed by Radu Pirea"

* tag 'spi-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (31 commits)
  spi: dw: Remove unused members from struct chip_data
  spi: orion: Fix a resource leak if the optional "axi" clk is deferred
  spi: a3700: Remove endianness swapping for full-duplex transfers
  spi: a3700: Remove endianness swapping functions when accessing FIFOs
  spi: a3700: Add full-duplex support
  spi: a3700: Allow to enable or disable FIFO mode
  spi: a3700: Set frequency limits at startup
  spi: a3700: Clear DATA_OUT when performing a read
  spi: orion: Fix clock resource by adding an optional bus clock
  spi: s3c64xx: add SPDX identifier
  spi: imx: do not access registers while clocks disabled
  spi: atmel: Implements transfers with bounce buffer
  spi: sh-msiof: Fix timeout failures for TX-only DMA transfers
  spi: spi-fsl-dspi: account for const type of of_device_id.data
  spi: bcm53xx: simplify reading SPI data
  spi: sirf: account for const type of of_device_id.data
  spi: pxa2xx: Use gpiod_put() not gpiod_free()
  spi: pxa2xx: avoid redundant gpio_to_desc(desc_to_gpio()) round-trip
  spi: sh-msiof: Document hardware limitations related to chip selects
  spi: sh-msiof: Implement cs-gpios configuration
  ...
parents 0bae60fc 35a8f1a9
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -36,7 +36,21 @@ Required properties:

Optional properties:
- clocks               : Must contain a reference to the functional clock.
- num-cs               : Total number of chip-selects (default is 1)
- num-cs               : Total number of chip selects (default is 1).
			 Up to 3 native chip selects are supported:
			   0: MSIOF_SYNC
			   1: MSIOF_SS1
			   2: MSIOF_SS2
			 Hardware limitations related to chip selects:
			   - Native chip selects are always deasserted in
			     between transfers that are part of the same
			     message.  Use cs-gpios to work around this.
			   - All slaves using native chip selects must use the
			     same spi-cs-high configuration.  Use cs-gpios to
			     work around this.
			   - When using GPIO chip selects, at least one native
			     chip select must be left unused, as it will be
			     driven anyway.
- dmas                 : Must contain a list of two references to DMA
			 specifiers, one for transmission, and one for
			 reception.
+3 −1
Original line number Diff line number Diff line
@@ -27,7 +27,9 @@ The Meson SPICC is generic SPI controller for general purpose Full-Duplex
communications with dedicated 16 words RX/TX PIO FIFOs.

Required properties:
 - compatible: should be "amlogic,meson-gx-spicc" on Amlogic GX SoCs.
 - compatible: should be:
	"amlogic,meson-gx-spicc" on Amlogic GX and compatible SoCs.
	"amlogic,meson-axg-spicc" on Amlogic AXG and compatible SoCs
 - reg: physical base address and length of the controller registers
 - interrupts: The interrupt specifier
 - clock-names: Must contain "core"
+9 −0
Original line number Diff line number Diff line
@@ -18,8 +18,17 @@ Required properties:
	The eight register sets following the control registers refer to
	chip-select lines 0 through 7 respectively.
- cell-index : Which of multiple SPI controllers is this.
- clocks : pointers to the reference clocks for this device, the first
	   one is the one used for the clock on the spi bus, the
	   second one is optional and is the clock used for the
	   functional part of the controller

Optional properties:
- interrupts : Is currently not used.
- clock-names : names of used clocks, mandatory if the second clock is
		used, the name must be "core", and "axi" (the latter
		is only for Armada 7K/8K).


Example:
       spi@10600 {
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ Xilinx SPI controller Device Tree Bindings
-------------------------------------------------

Required properties:
- compatible		: Should be "xlnx,xps-spi-2.00.a" or "xlnx,xps-spi-2.00.b"
- compatible		: Should be "xlnx,xps-spi-2.00.a", "xlnx,xps-spi-2.00.b" or "xlnx,axi-quad-spi-1.00.a"
- reg			: Physical base address and size of SPI registers map.
- interrupts		: Property with a value describing the interrupt
			  number.
+92 −18
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@

#define DRIVER_NAME			"armada_3700_spi"

#define A3700_SPI_MAX_SPEED_HZ		100000000
#define A3700_SPI_MAX_PRESCALE		30
#define A3700_SPI_TIMEOUT		10

/* SPI Register Offest */
@@ -184,12 +186,15 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
	return 0;
}

static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi)
static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi, bool enable)
{
	u32 val;

	val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG);
	if (enable)
		val |= A3700_SPI_FIFO_MODE;
	else
		val &= ~A3700_SPI_FIFO_MODE;
	spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val);
}

@@ -297,7 +302,7 @@ static int a3700_spi_init(struct a3700_spi *a3700_spi)
		a3700_spi_deactivate_cs(a3700_spi, i);

	/* Enable FIFO mode */
	a3700_spi_fifo_mode_set(a3700_spi);
	a3700_spi_fifo_mode_set(a3700_spi, true);

	/* Set SPI mode */
	a3700_spi_mode_set(a3700_spi, master->mode_bits);
@@ -416,15 +421,20 @@ static void a3700_spi_transfer_setup(struct spi_device *spi,
				     struct spi_transfer *xfer)
{
	struct a3700_spi *a3700_spi;
	unsigned int byte_len;

	a3700_spi = spi_master_get_devdata(spi->master);

	a3700_spi_clock_set(a3700_spi, xfer->speed_hz);

	byte_len = xfer->bits_per_word >> 3;
	/* Use 4 bytes long transfers. Each transfer method has its way to deal
	 * with the remaining bytes for non 4-bytes aligned transfers.
	 */
	a3700_spi_bytelen_set(a3700_spi, 4);

	a3700_spi_fifo_thres_set(a3700_spi, byte_len);
	/* Initialize the working buffers */
	a3700_spi->tx_buf  = xfer->tx_buf;
	a3700_spi->rx_buf  = xfer->rx_buf;
	a3700_spi->buf_len = xfer->len;
}

static void a3700_spi_set_cs(struct spi_device *spi, bool enable)
@@ -491,7 +501,7 @@ static int a3700_spi_fifo_write(struct a3700_spi *a3700_spi)
	u32 val;

	while (!a3700_is_wfifo_full(a3700_spi) && a3700_spi->buf_len) {
		val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf);
		val = *(u32 *)a3700_spi->tx_buf;
		spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val);
		a3700_spi->buf_len -= 4;
		a3700_spi->tx_buf += 4;
@@ -514,9 +524,8 @@ static int a3700_spi_fifo_read(struct a3700_spi *a3700_spi)
	while (!a3700_is_rfifo_empty(a3700_spi) && a3700_spi->buf_len) {
		val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG);
		if (a3700_spi->buf_len >= 4) {
			u32 data = le32_to_cpu(val);

			memcpy(a3700_spi->rx_buf, &data, 4);
			memcpy(a3700_spi->rx_buf, &val, 4);

			a3700_spi->buf_len -= 4;
			a3700_spi->rx_buf += 4;
@@ -579,27 +588,26 @@ static int a3700_spi_prepare_message(struct spi_master *master,
	if (ret)
		return ret;

	a3700_spi_bytelen_set(a3700_spi, 4);

	a3700_spi_mode_set(a3700_spi, spi->mode);

	return 0;
}

static int a3700_spi_transfer_one(struct spi_master *master,
static int a3700_spi_transfer_one_fifo(struct spi_master *master,
				  struct spi_device *spi,
				  struct spi_transfer *xfer)
{
	struct a3700_spi *a3700_spi = spi_master_get_devdata(master);
	int ret = 0, timeout = A3700_SPI_TIMEOUT;
	unsigned int nbits = 0;
	unsigned int nbits = 0, byte_len;
	u32 val;

	a3700_spi_transfer_setup(spi, xfer);
	/* Make sure we use FIFO mode */
	a3700_spi_fifo_mode_set(a3700_spi, true);

	a3700_spi->tx_buf  = xfer->tx_buf;
	a3700_spi->rx_buf  = xfer->rx_buf;
	a3700_spi->buf_len = xfer->len;
	/* Configure FIFO thresholds */
	byte_len = xfer->bits_per_word >> 3;
	a3700_spi_fifo_thres_set(a3700_spi, byte_len);

	if (xfer->tx_buf)
		nbits = xfer->tx_nbits;
@@ -615,6 +623,11 @@ static int a3700_spi_transfer_one(struct spi_master *master,
	a3700_spi_header_set(a3700_spi);

	if (xfer->rx_buf) {
		/* Clear WFIFO, since it's last 2 bytes are shifted out during
		 * a read operation
		 */
		spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, 0);

		/* Set read data length */
		spireg_write(a3700_spi, A3700_SPI_IF_DIN_CNT_REG,
			     a3700_spi->buf_len);
@@ -729,6 +742,63 @@ static int a3700_spi_transfer_one(struct spi_master *master,
	return ret;
}

static int a3700_spi_transfer_one_full_duplex(struct spi_master *master,
				  struct spi_device *spi,
				  struct spi_transfer *xfer)
{
	struct a3700_spi *a3700_spi = spi_master_get_devdata(master);
	u32 val;

	/* Disable FIFO mode */
	a3700_spi_fifo_mode_set(a3700_spi, false);

	while (a3700_spi->buf_len) {

		/* When we have less than 4 bytes to transfer, switch to 1 byte
		 * mode. This is reset after each transfer
		 */
		if (a3700_spi->buf_len < 4)
			a3700_spi_bytelen_set(a3700_spi, 1);

		if (a3700_spi->byte_len == 1)
			val = *a3700_spi->tx_buf;
		else
			val = *(u32 *)a3700_spi->tx_buf;

		spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val);

		/* Wait for all the data to be shifted in / out */
		while (!(spireg_read(a3700_spi, A3700_SPI_IF_CTRL_REG) &
				A3700_SPI_XFER_DONE))
			cpu_relax();

		val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG);

		memcpy(a3700_spi->rx_buf, &val, a3700_spi->byte_len);

		a3700_spi->buf_len -= a3700_spi->byte_len;
		a3700_spi->tx_buf += a3700_spi->byte_len;
		a3700_spi->rx_buf += a3700_spi->byte_len;

	}

	spi_finalize_current_transfer(master);

	return 0;
}

static int a3700_spi_transfer_one(struct spi_master *master,
				  struct spi_device *spi,
				  struct spi_transfer *xfer)
{
	a3700_spi_transfer_setup(spi, xfer);

	if (xfer->tx_buf && xfer->rx_buf)
		return a3700_spi_transfer_one_full_duplex(master, spi, xfer);

	return a3700_spi_transfer_one_fifo(master, spi, xfer);
}

static int a3700_spi_unprepare_message(struct spi_master *master,
				       struct spi_message *message)
{
@@ -778,7 +848,6 @@ static int a3700_spi_probe(struct platform_device *pdev)
	master->transfer_one = a3700_spi_transfer_one;
	master->unprepare_message = a3700_spi_unprepare_message;
	master->set_cs = a3700_spi_set_cs;
	master->flags = SPI_MASTER_HALF_DUPLEX;
	master->mode_bits |= (SPI_RX_DUAL | SPI_TX_DUAL |
			      SPI_RX_QUAD | SPI_TX_QUAD);

@@ -818,6 +887,11 @@ static int a3700_spi_probe(struct platform_device *pdev)
		goto error;
	}

	master->max_speed_hz = min_t(unsigned long, A3700_SPI_MAX_SPEED_HZ,
					clk_get_rate(spi->clk));
	master->min_speed_hz = DIV_ROUND_UP(clk_get_rate(spi->clk),
						A3700_SPI_MAX_PRESCALE);

	ret = a3700_spi_init(spi);
	if (ret)
		goto error_clk;
Loading