Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi-gpio: allow operation without CS signal

Change spi-gpio so that it is possible to drive SPI communications over
GPIO without the need for a chipselect signal.

This is useful in very small setups where there's only one slave device
on the bus.

This patch does not affect existing setups.

I use this for a tiny communication channel between an embedded device and
a microcontroller. There are not enough GPIOs available for chipselect
and it's not needed anyway in this case.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Michael Buesch and committed by
Linus Torvalds
bfb9bcdb 8a0cecff

+19 -8
+13 -8
drivers/spi/spi_gpio.c
··· 178 178 if (is_active) 179 179 setsck(spi, spi->mode & SPI_CPOL); 180 180 181 - /* SPI is normally active-low */ 182 - gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); 181 + if (cs != SPI_GPIO_NO_CHIPSELECT) { 182 + /* SPI is normally active-low */ 183 + gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); 184 + } 183 185 } 184 186 185 187 static int spi_gpio_setup(struct spi_device *spi) ··· 193 191 return -EINVAL; 194 192 195 193 if (!spi->controller_state) { 196 - status = gpio_request(cs, dev_name(&spi->dev)); 197 - if (status) 198 - return status; 199 - status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); 194 + if (cs != SPI_GPIO_NO_CHIPSELECT) { 195 + status = gpio_request(cs, dev_name(&spi->dev)); 196 + if (status) 197 + return status; 198 + status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); 199 + } 200 200 } 201 201 if (!status) 202 202 status = spi_bitbang_setup(spi); 203 203 if (status) { 204 - if (!spi->controller_state) 204 + if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT) 205 205 gpio_free(cs); 206 206 } 207 207 return status; ··· 213 209 { 214 210 unsigned long cs = (unsigned long) spi->controller_data; 215 211 216 - gpio_free(cs); 212 + if (cs != SPI_GPIO_NO_CHIPSELECT) 213 + gpio_free(cs); 217 214 spi_bitbang_cleanup(spi); 218 215 } 219 216
+6
include/linux/spi/spi_gpio.h
··· 25 25 * ... 26 26 * }; 27 27 * 28 + * If chipselect is not used (there's only one device on the bus), assign 29 + * SPI_GPIO_NO_CHIPSELECT to the controller_data: 30 + * .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT; 31 + * 28 32 * If the bitbanged bus is later switched to a "native" controller, 29 33 * that platform_device and controller_data should be removed. 30 34 */ 35 + 36 + #define SPI_GPIO_NO_CHIPSELECT ((unsigned long)-1l) 31 37 32 38 /** 33 39 * struct spi_gpio_platform_data - parameter for bitbanged SPI master