From 3d3522604a5557e80fdcab61c54bd04eaf15b525 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Tue, 19 Feb 2013 22:44:57 +0100 Subject: spi/atmel: fix speed_hz check in atmel_spi_transfer() atmel_spi_transfer() would check speed_hz and fail if the speed was changed in the transfer. After commit "spi: make sure all transfer has proper speed set" this would happen on all transfers. Change speed_hz check to only fail if a lower speed than max is requested. Signed-off-by: Joachim Eastwood Acked-by: Nicolas Ferre Signed-off-by: Grant Likely diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 656d137..80f5867 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -847,8 +847,8 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) } /* FIXME implement these protocol options!! */ - if (xfer->speed_hz) { - dev_dbg(&spi->dev, "no protocol options yet\n"); + if (xfer->speed_hz < spi->max_speed_hz) { + dev_dbg(&spi->dev, "can't change speed in transfer\n"); return -ENOPROTOOPT; } -- cgit v0.10.2 From 446411e18b2cb17d153e45f634a3c9a79ada3ac2 Mon Sep 17 00:00:00 2001 From: Andreas Larsson Date: Wed, 13 Feb 2013 14:20:25 +0100 Subject: spi: Initialize cs_gpio and cs_gpios with -ENOENT The return value from of_get_named_gpio is -ENOENT when the given index matches a hole in the "cs-gpios" property phandle list. However, the default value of cs_gpio in struct spi_device and entries of cs_gpios in struct spi_master is -EINVAL, which is documented to indicate that a GPIO line should not be used for the given spi_device. This sets the default value of cs_gpio in struct spi_device and entries of cs_gpios in struct spi_master to -ENOENT. Thus, -ENOENT is the only value used to indicate that no GPIO line should be used. Signed-off-by: Andreas Larsson Signed-off-by: Grant Likely diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 004b10f..bcca66c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -334,7 +334,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master) spi->dev.parent = &master->dev; spi->dev.bus = &spi_bus_type; spi->dev.release = spidev_release; - spi->cs_gpio = -EINVAL; + spi->cs_gpio = -ENOENT; device_initialize(&spi->dev); return spi; } @@ -1079,7 +1079,7 @@ static int of_spi_register_master(struct spi_master *master) return -ENOMEM; for (i = 0; i < master->num_chipselect; i++) - cs[i] = -EINVAL; + cs[i] = -ENOENT; for (i = 0; i < nb; i++) cs[i] = of_get_named_gpio(np, "cs-gpios", i); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 38c2b92..c395f32 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -57,7 +57,7 @@ extern struct bus_type spi_bus_type; * @modalias: Name of the driver to use with this device, or an alias * for that name. This appears in the sysfs "modalias" attribute * 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) * * A @spi_device is used to interchange data between an SPI slave @@ -261,7 +261,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * queue so the subsystem notifies the driver that it may relax the * hardware by issuing this call * @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). * * Each SPI master controller can communicate with one or more @spi_device -- cgit v0.10.2 From 8ec5d84ef51cc64ed02bb9bf0e43a652178252c1 Mon Sep 17 00:00:00 2001 From: Andreas Larsson Date: Wed, 13 Feb 2013 14:23:24 +0100 Subject: spi: Return error from of_spi_register_master on bad "cs-gpios" property This makes sure that an error is returned on an incorrectly formed "cs-gpios" property, but reports success when the "cs-gpios" property is well formed or missing. When holes in the cs-gpios property phandle list is used to indicate that some other form of chipselect is to be used it is important that failure to read a broken "cs-gpios" property does not silently fail leading to the spi controller to use an unintended chipselect. Signed-off-by: Andreas Larsson Signed-off-by: Grant Likely diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index bcca66c..3738e7c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1067,8 +1067,11 @@ static int of_spi_register_master(struct spi_master *master) nb = of_gpio_named_count(np, "cs-gpios"); 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; + else if (nb < 0) + return nb; cs = devm_kzalloc(&master->dev, sizeof(int) * master->num_chipselect, -- cgit v0.10.2 From 0d2d0cc5216db678070efc911ef47f4cb53b4aad Mon Sep 17 00:00:00 2001 From: "Manjunathappa, Prakash" Date: Mon, 25 Feb 2013 16:14:07 +0530 Subject: spi/davinci: fix module build error Fix below module build error: CC [M] drivers/spi/spi-davinci.o drivers/spi/spi-davinci.c:774:1: error: '__mod_of_device_table' aliased to undefined symbol 'davini_spi_of_match' drivers/spi/spi-davinci.c:774:1: error: '__mod_of_device_table' aliased to undefined symbol 'davini_spi_of_match' make[2]: *** [drivers/spi/spi-davinci.o] Error 1 make[1]: *** [drivers/spi] Error 2 make[1]: *** Waiting for unfinished jobs.... make: *** [drivers] Error 2 Signed-off-by: Manjunathappa, Prakash Acked-by: Sekhar Nori Signed-off-by: Grant Likely diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 8234d22..6287c83 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -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 -- cgit v0.10.2 From f557c98b168a2860bfc7dedf4b4e3bafb59dc267 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Thu, 2 May 2013 19:25:11 +0800 Subject: spi/spi-atmel: BUG: fix doesn' support 16 bits transfers using PIO Fix using PIO transfer mode only support 8 bits transfer, doesn't support 16 bits. Signed-off-by: Richard Genoud [wenyou.yang@atmel.com: submit the patch] Signed-off-by: Wenyou Yang Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 787bd2c..d8cb7da 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -526,13 +526,17 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master, } if (xfer->tx_buf) - spi_writel(as, TDR, *(u8 *)(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)); else spi_writel(as, TDR, 0); dev_dbg(master->dev.parent, - " start pio xfer %p: len %u tx %p rx %p\n", - xfer, xfer->len, xfer->tx_buf, xfer->rx_buf); + " start pio xfer %p: len %u tx %p rx %p bitpw %d\n", + xfer, xfer->len, xfer->tx_buf, xfer->rx_buf, + xfer->bits_per_word); /* Enable relevant interrupts */ 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 *rxp; + u16 *txp16; + u16 *rxp16; unsigned long xfer_pos = xfer->len - as->current_remaining_bytes; if (xfer->rx_buf) { - rxp = ((u8 *)xfer->rx_buf) + xfer_pos; - *rxp = spi_readl(as, RDR); + 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 = spi_readl(as, RDR); + } } else { spi_readl(as, RDR); } - - as->current_remaining_bytes--; + 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--; + } if (as->current_remaining_bytes) { if (xfer->tx_buf) { - txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1; - spi_writel(as, TDR, *txp); + 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; + spi_writel(as, TDR, *txp); + } } else { spi_writel(as, TDR, 0); } @@ -1378,6 +1400,13 @@ 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!! */ if (xfer->speed_hz) { dev_dbg(&spi->dev, "no protocol options yet\n"); -- cgit v0.10.2