summaryrefslogtreecommitdiff
path: root/target/linux/xburst/patches-2.6.35/400-spi-gpio-3wire.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/xburst/patches-2.6.35/400-spi-gpio-3wire.patch')
-rw-r--r--target/linux/xburst/patches-2.6.35/400-spi-gpio-3wire.patch180
1 files changed, 180 insertions, 0 deletions
diff --git a/target/linux/xburst/patches-2.6.35/400-spi-gpio-3wire.patch b/target/linux/xburst/patches-2.6.35/400-spi-gpio-3wire.patch
new file mode 100644
index 0000000..d60a851
--- /dev/null
+++ b/target/linux/xburst/patches-2.6.35/400-spi-gpio-3wire.patch
@@ -0,0 +1,180 @@
+From 62b6a295d39417293adcc81dc36b7edc56546814 Mon Sep 17 00:00:00 2001
+From: Lars-Peter Clausen <lars@metafoo.de>
+Date: Sat, 24 Apr 2010 12:23:01 +0200
+Subject: [PATCH] gpio spi 3wire
+
+---
+ drivers/spi/spi_bitbang.c | 2 +
+ drivers/spi/spi_gpio.c | 60 ++++++++++++++++++++++++++------------
+ include/linux/spi/spi_bitbang.h | 2 +
+ 3 files changed, 45 insertions(+), 19 deletions(-)
+
+--- a/drivers/spi/spi_bitbang.c
++++ b/drivers/spi/spi_bitbang.c
+@@ -335,6 +335,8 @@ static void bitbang_work(struct work_str
+ */
+ if (!m->is_dma_mapped)
+ t->rx_dma = t->tx_dma = 0;
++ if ((spi->mode & SPI_3WIRE) && bitbang->set_direction)
++ bitbang->set_direction(spi, t->tx_buf != NULL);
+ status = bitbang->txrx_bufs(spi, t);
+ }
+ if (status > 0)
+--- a/drivers/spi/spi_gpio.c
++++ b/drivers/spi/spi_gpio.c
+@@ -46,6 +46,8 @@ struct spi_gpio {
+ struct spi_bitbang bitbang;
+ struct spi_gpio_platform_data pdata;
+ struct platform_device *pdev;
++
++ int miso_pin;
+ };
+
+ /*----------------------------------------------------------------------*/
+@@ -91,19 +93,16 @@ struct spi_gpio {
+
+ /*----------------------------------------------------------------------*/
+
+-static inline const struct spi_gpio_platform_data * __pure
+-spi_to_pdata(const struct spi_device *spi)
++static inline const struct spi_gpio * __pure
++spi_to_spi_gpio(const struct spi_device *spi)
+ {
+ const struct spi_bitbang *bang;
+- const struct spi_gpio *spi_gpio;
+
+ bang = spi_master_get_devdata(spi->master);
+- spi_gpio = container_of(bang, struct spi_gpio, bitbang);
+- return &spi_gpio->pdata;
++ return container_of(bang, struct spi_gpio, bitbang);
+ }
+
+-/* this is #defined to avoid unused-variable warnings when inlining */
+-#define pdata spi_to_pdata(spi)
++#define pdata &(spi_to_spi_gpio(spi)->pdata)
+
+ static inline void setsck(const struct spi_device *spi, int is_on)
+ {
+@@ -117,10 +116,9 @@ static inline void setmosi(const struct
+
+ static inline int getmiso(const struct spi_device *spi)
+ {
+- return !!gpio_get_value(SPI_MISO_GPIO);
++ return !!gpio_get_value(spi_to_spi_gpio(spi)->miso_pin);
+ }
+
+-#undef pdata
+
+ /*
+ * NOTE: to clock "as fast as we can", set spi_device.max_speed_hz
+@@ -183,10 +181,16 @@ static u32 spi_gpio_txrx_word_mode3(stru
+ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
+ {
+ unsigned long cs = (unsigned long) spi->controller_data;
++ struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
+
+ /* set initial clock polarity */
+- if (is_active)
++ if (is_active) {
+ setsck(spi, spi->mode & SPI_CPOL);
++ if (spi->mode & SPI_3WIRE)
++ spi_gpio->miso_pin = SPI_MOSI_GPIO;
++ else
++ spi_gpio->miso_pin = SPI_MISO_GPIO;
++ }
+
+ if (cs != SPI_GPIO_NO_CHIPSELECT) {
+ /* SPI is normally active-low */
+@@ -202,6 +206,9 @@ static int spi_gpio_setup(struct spi_dev
+ if (spi->bits_per_word > 32)
+ return -EINVAL;
+
++ if (!(spi->mode & SPI_3WIRE) && !gpio_is_valid(SPI_MISO_GPIO))
++ return -EINVAL;
++
+ if (!spi->controller_state) {
+ if (cs != SPI_GPIO_NO_CHIPSELECT) {
+ status = gpio_request(cs, dev_name(&spi->dev));
+@@ -219,6 +226,16 @@ static int spi_gpio_setup(struct spi_dev
+ return status;
+ }
+
++static void spi_gpio_set_direction(struct spi_device *spi, bool is_tx)
++{
++ if (is_tx)
++ gpio_direction_output(SPI_MISO_GPIO, 0);
++ else
++ gpio_direction_input(SPI_MISO_GPIO);
++}
++
++#undef pdata
++
+ static void spi_gpio_cleanup(struct spi_device *spi)
+ {
+ unsigned long cs = (unsigned long) spi->controller_data;
+@@ -253,18 +270,20 @@ spi_gpio_request(struct spi_gpio_platfor
+ if (value)
+ goto done;
+
+- value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
++ value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
+ if (value)
+ goto free_mosi;
+
+- value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
+- if (value)
+- goto free_miso;
++ if (gpio_is_valid(SPI_MISO_GPIO)) {
++ value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
++ if (value)
++ goto free_sck;
++ }
+
+ goto done;
+
+-free_miso:
+- gpio_free(SPI_MISO_GPIO);
++free_sck:
++ gpio_free(SPI_SCK_GPIO);
+ free_mosi:
+ gpio_free(SPI_MOSI_GPIO);
+ done:
+@@ -312,13 +331,15 @@ static int __devinit spi_gpio_probe(stru
+ spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
+ spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
+ spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
+- spi_gpio->bitbang.flags = SPI_CS_HIGH;
++ spi_gpio->bitbang.set_direction = spi_gpio_set_direction;
++ spi_gpio->bitbang.flags = SPI_CS_HIGH | SPI_3WIRE;
+
+ status = spi_bitbang_start(&spi_gpio->bitbang);
+ if (status < 0) {
+ spi_master_put(spi_gpio->bitbang.master);
+ gpio_free:
+- gpio_free(SPI_MISO_GPIO);
++ if (gpio_is_valid(SPI_MOSI_GPIO))
++ gpio_free(SPI_MISO_GPIO);
+ gpio_free(SPI_MOSI_GPIO);
+ gpio_free(SPI_SCK_GPIO);
+ spi_master_put(master);
+@@ -342,7 +363,8 @@ static int __devexit spi_gpio_remove(str
+
+ platform_set_drvdata(pdev, NULL);
+
+- gpio_free(SPI_MISO_GPIO);
++ if (gpio_is_valid(SPI_MISO_GPIO))
++ gpio_free(SPI_MISO_GPIO);
+ gpio_free(SPI_MOSI_GPIO);
+ gpio_free(SPI_SCK_GPIO);
+
+--- a/include/linux/spi/spi_bitbang.h
++++ b/include/linux/spi/spi_bitbang.h
+@@ -34,6 +34,8 @@ struct spi_bitbang {
+ u32 (*txrx_word[4])(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits);
++
++ void (*set_direction)(struct spi_device *, bool is_tx);
+ };
+
+ /* you can call these default bitbang->master methods from your custom