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

Commit 1f638766 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull spi updates from Mark Brown:
 "A few driver specific fixes plus improved error handling in the
  generic DT GPIO chipselect handling - not exciting but useful."

* tag 'spi-v3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi/spi-atmel: BUG: fix doesn' support 16 bits transfers using PIO
  spi/davinci: fix module build error
  spi: Return error from of_spi_register_master on bad "cs-gpios" property
  spi: Initialize cs_gpio and cs_gpios with -ENOENT
  spi/atmel: fix speed_hz check in atmel_spi_transfer()
parents fea0f9ff 88b0357d
Loading
Loading
Loading
Loading
+40 −11
Original line number Original line Diff line number Diff line
@@ -526,13 +526,17 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master,
	}
	}


	if (xfer->tx_buf)
	if (xfer->tx_buf)
		if (xfer->bits_per_word > 8)
			spi_writel(as, TDR, *(u16 *)(xfer->tx_buf));
		else
			spi_writel(as, TDR, *(u8 *)(xfer->tx_buf));
			spi_writel(as, TDR, *(u8 *)(xfer->tx_buf));
	else
	else
		spi_writel(as, TDR, 0);
		spi_writel(as, TDR, 0);


	dev_dbg(master->dev.parent,
	dev_dbg(master->dev.parent,
		"  start pio xfer %p: len %u tx %p rx %p\n",
		"  start pio xfer %p: len %u tx %p rx %p bitpw %d\n",
		xfer, xfer->len, xfer->tx_buf, xfer->rx_buf);
		xfer, xfer->len, xfer->tx_buf, xfer->rx_buf,
		xfer->bits_per_word);


	/* Enable relevant interrupts */
	/* Enable relevant interrupts */
	spi_writel(as, IER, SPI_BIT(RDRF) | SPI_BIT(OVRES));
	spi_writel(as, IER, SPI_BIT(RDRF) | SPI_BIT(OVRES));
@@ -950,21 +954,39 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
{
{
	u8		*txp;
	u8		*txp;
	u8		*rxp;
	u8		*rxp;
	u16		*txp16;
	u16		*rxp16;
	unsigned long	xfer_pos = xfer->len - as->current_remaining_bytes;
	unsigned long	xfer_pos = xfer->len - as->current_remaining_bytes;


	if (xfer->rx_buf) {
	if (xfer->rx_buf) {
		if (xfer->bits_per_word > 8) {
			rxp16 = (u16 *)(((u8 *)xfer->rx_buf) + xfer_pos);
			*rxp16 = spi_readl(as, RDR);
		} else {
			rxp = ((u8 *)xfer->rx_buf) + xfer_pos;
			rxp = ((u8 *)xfer->rx_buf) + xfer_pos;
			*rxp = spi_readl(as, RDR);
			*rxp = spi_readl(as, RDR);
		}
	} else {
	} else {
		spi_readl(as, RDR);
		spi_readl(as, RDR);
	}
	}

	if (xfer->bits_per_word > 8) {
		as->current_remaining_bytes -= 2;
		if (as->current_remaining_bytes < 0)
			as->current_remaining_bytes = 0;
	} else {
		as->current_remaining_bytes--;
		as->current_remaining_bytes--;
	}


	if (as->current_remaining_bytes) {
	if (as->current_remaining_bytes) {
		if (xfer->tx_buf) {
		if (xfer->tx_buf) {
			if (xfer->bits_per_word > 8) {
				txp16 = (u16 *)(((u8 *)xfer->tx_buf)
							+ xfer_pos + 2);
				spi_writel(as, TDR, *txp16);
			} else {
				txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1;
				txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1;
				spi_writel(as, TDR, *txp);
				spi_writel(as, TDR, *txp);
			}
		} else {
		} else {
			spi_writel(as, TDR, 0);
			spi_writel(as, TDR, 0);
		}
		}
@@ -1378,9 +1400,16 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
			}
			}
		}
		}


		if (xfer->bits_per_word > 8) {
			if (xfer->len % 2) {
				dev_dbg(&spi->dev, "buffer len should be 16 bits aligned\n");
				return -EINVAL;
			}
		}

		/* FIXME implement these protocol options!! */
		/* FIXME implement these protocol options!! */
		if (xfer->speed_hz) {
		if (xfer->speed_hz < spi->max_speed_hz) {
			dev_dbg(&spi->dev, "no protocol options yet\n");
			dev_dbg(&spi->dev, "can't change speed in transfer\n");
			return -ENOPROTOOPT;
			return -ENOPROTOOPT;
		}
		}


+1 −1
Original line number Original line Diff line number Diff line
@@ -784,7 +784,7 @@ static const struct of_device_id davinci_spi_of_match[] = {
	},
	},
	{ },
	{ },
};
};
MODULE_DEVICE_TABLE(of, davini_spi_of_match);
MODULE_DEVICE_TABLE(of, davinci_spi_of_match);


/**
/**
 * spi_davinci_get_pdata - Get platform data from DTS binding
 * spi_davinci_get_pdata - Get platform data from DTS binding
+6 −3
Original line number Original line Diff line number Diff line
@@ -334,7 +334,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
	spi->dev.parent = &master->dev;
	spi->dev.parent = &master->dev;
	spi->dev.bus = &spi_bus_type;
	spi->dev.bus = &spi_bus_type;
	spi->dev.release = spidev_release;
	spi->dev.release = spidev_release;
	spi->cs_gpio = -EINVAL;
	spi->cs_gpio = -ENOENT;
	device_initialize(&spi->dev);
	device_initialize(&spi->dev);
	return spi;
	return spi;
}
}
@@ -1067,8 +1067,11 @@ static int of_spi_register_master(struct spi_master *master)
	nb = of_gpio_named_count(np, "cs-gpios");
	nb = of_gpio_named_count(np, "cs-gpios");
	master->num_chipselect = max(nb, (int)master->num_chipselect);
	master->num_chipselect = max(nb, (int)master->num_chipselect);


	if (nb < 1)
	/* Return error only for an incorrectly formed cs-gpios property */
	if (nb == 0 || nb == -ENOENT)
		return 0;
		return 0;
	else if (nb < 0)
		return nb;


	cs = devm_kzalloc(&master->dev,
	cs = devm_kzalloc(&master->dev,
			  sizeof(int) * master->num_chipselect,
			  sizeof(int) * master->num_chipselect,
@@ -1079,7 +1082,7 @@ static int of_spi_register_master(struct spi_master *master)
		return -ENOMEM;
		return -ENOMEM;


	for (i = 0; i < master->num_chipselect; i++)
	for (i = 0; i < master->num_chipselect; i++)
		cs[i] = -EINVAL;
		cs[i] = -ENOENT;


	for (i = 0; i < nb; i++)
	for (i = 0; i < nb; i++)
		cs[i] = of_get_named_gpio(np, "cs-gpios", i);
		cs[i] = of_get_named_gpio(np, "cs-gpios", i);
+2 −2
Original line number Original line Diff line number Diff line
@@ -57,7 +57,7 @@ extern struct bus_type spi_bus_type;
 * @modalias: Name of the driver to use with this device, or an alias
 * @modalias: Name of the driver to use with this device, or an alias
 *	for that name.  This appears in the sysfs "modalias" attribute
 *	for that name.  This appears in the sysfs "modalias" attribute
 *	for driver coldplugging, and in uevents used for hotplugging
 *	for driver coldplugging, and in uevents used for hotplugging
 * @cs_gpio: gpio number of the chipselect line (optional, -EINVAL when
 * @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when
 *	when not using a GPIO line)
 *	when not using a GPIO line)
 *
 *
 * A @spi_device is used to interchange data between an SPI slave
 * A @spi_device is used to interchange data between an SPI slave
@@ -266,7 +266,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
 *	queue so the subsystem notifies the driver that it may relax the
 *	queue so the subsystem notifies the driver that it may relax the
 *	hardware by issuing this call
 *	hardware by issuing this call
 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
 *	number. Any individual value may be -EINVAL for CS lines that
 *	number. Any individual value may be -ENOENT for CS lines that
 *	are not GPIOs (driven by the SPI controller itself).
 *	are not GPIOs (driven by the SPI controller itself).
 *
 *
 * Each SPI master controller can communicate with one or more @spi_device
 * Each SPI master controller can communicate with one or more @spi_device