diff options
Diffstat (limited to 'target/linux/xburst/patches-2.6.34/400-spi-gpio-3wire.patch')
-rw-r--r-- | target/linux/xburst/patches-2.6.34/400-spi-gpio-3wire.patch | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/target/linux/xburst/patches-2.6.34/400-spi-gpio-3wire.patch b/target/linux/xburst/patches-2.6.34/400-spi-gpio-3wire.patch new file mode 100644 index 0000000000..90ed1cdb01 --- /dev/null +++ b/target/linux/xburst/patches-2.6.34/400-spi-gpio-3wire.patch @@ -0,0 +1,189 @@ +From 4cee37dd779deeb01f263995e8bd5e7b8457965b 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(-) + +diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c +index 5265330..2bec91c 100644 +--- a/drivers/spi/spi_bitbang.c ++++ b/drivers/spi/spi_bitbang.c +@@ -335,6 +335,8 @@ static void bitbang_work(struct work_struct *work) + */ + 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) +diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c +index 26bd03e..ca769b8 100644 +--- a/drivers/spi/spi_gpio.c ++++ b/drivers/spi/spi_gpio.c +@@ -45,6 +45,8 @@ struct spi_gpio { + struct spi_bitbang bitbang; + struct spi_gpio_platform_data pdata; + struct platform_device *pdev; ++ ++ int miso_pin; + }; + + /*----------------------------------------------------------------------*/ +@@ -88,19 +90,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) + { +@@ -114,10 +113,9 @@ static inline void setmosi(const struct spi_device *spi, int is_on) + + 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: this clocks "as fast as we can". It "should" be a function of the +@@ -173,10 +171,16 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, + 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 */ +@@ -192,6 +196,9 @@ static int spi_gpio_setup(struct spi_device *spi) + 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)); +@@ -209,6 +216,16 @@ static int spi_gpio_setup(struct spi_device *spi) + 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; +@@ -243,18 +260,20 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) + 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: +@@ -302,13 +321,15 @@ static int __init spi_gpio_probe(struct platform_device *pdev) + 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); +@@ -332,7 +353,8 @@ static int __exit spi_gpio_remove(struct platform_device *pdev) + + 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); + +diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h +index 3274c50..0a466c9 100644 +--- a/include/linux/spi/spi_bitbang.h ++++ b/include/linux/spi/spi_bitbang.h +@@ -52,6 +52,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 +-- +1.5.6.5 + |