[kernel] Fix gpio_spi_old module for 2.6.35
[openwrt.git] / target / linux / xburst / patches-2.6.34 / 400-spi-gpio-3wire.patch
1 From 4cee37dd779deeb01f263995e8bd5e7b8457965b Mon Sep 17 00:00:00 2001
2 From: Lars-Peter Clausen <lars@metafoo.de>
3 Date: Sat, 24 Apr 2010 12:23:01 +0200
4 Subject: [PATCH] gpio spi 3wire
5
6 ---
7  drivers/spi/spi_bitbang.c       |    2 +
8  drivers/spi/spi_gpio.c          |   60 ++++++++++++++++++++++++++------------
9  include/linux/spi/spi_bitbang.h |    2 +
10  3 files changed, 45 insertions(+), 19 deletions(-)
11
12 diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
13 index 5265330..2bec91c 100644
14 --- a/drivers/spi/spi_bitbang.c
15 +++ b/drivers/spi/spi_bitbang.c
16 @@ -335,6 +335,8 @@ static void bitbang_work(struct work_struct *work)
17                                  */
18                                 if (!m->is_dma_mapped)
19                                         t->rx_dma = t->tx_dma = 0;
20 +                               if ((spi->mode & SPI_3WIRE) && bitbang->set_direction)
21 +                                       bitbang->set_direction(spi, t->tx_buf != NULL);
22                                 status = bitbang->txrx_bufs(spi, t);
23                         }
24                         if (status > 0)
25 diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c
26 index 26bd03e..ca769b8 100644
27 --- a/drivers/spi/spi_gpio.c
28 +++ b/drivers/spi/spi_gpio.c
29 @@ -45,6 +45,8 @@ struct spi_gpio {
30         struct spi_bitbang              bitbang;
31         struct spi_gpio_platform_data   pdata;
32         struct platform_device          *pdev;
33 +
34 +       int miso_pin;
35  };
36  
37  /*----------------------------------------------------------------------*/
38 @@ -88,19 +90,16 @@ struct spi_gpio {
39  
40  /*----------------------------------------------------------------------*/
41  
42 -static inline const struct spi_gpio_platform_data * __pure
43 -spi_to_pdata(const struct spi_device *spi)
44 +static inline const struct spi_gpio * __pure
45 +spi_to_spi_gpio(const struct spi_device *spi)
46  {
47         const struct spi_bitbang        *bang;
48 -       const struct spi_gpio           *spi_gpio;
49  
50         bang = spi_master_get_devdata(spi->master);
51 -       spi_gpio = container_of(bang, struct spi_gpio, bitbang);
52 -       return &spi_gpio->pdata;
53 +       return container_of(bang, struct spi_gpio, bitbang);
54  }
55  
56 -/* this is #defined to avoid unused-variable warnings when inlining */
57 -#define pdata          spi_to_pdata(spi)
58 +#define pdata &(spi_to_spi_gpio(spi)->pdata)
59  
60  static inline void setsck(const struct spi_device *spi, int is_on)
61  {
62 @@ -114,10 +113,9 @@ static inline void setmosi(const struct spi_device *spi, int is_on)
63  
64  static inline int getmiso(const struct spi_device *spi)
65  {
66 -       return !!gpio_get_value(SPI_MISO_GPIO);
67 +       return !!gpio_get_value(spi_to_spi_gpio(spi)->miso_pin);
68  }
69  
70 -#undef pdata
71  
72  /*
73   * NOTE:  this clocks "as fast as we can".  It "should" be a function of the
74 @@ -173,10 +171,16 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
75  static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
76  {
77         unsigned long cs = (unsigned long) spi->controller_data;
78 +       struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
79  
80         /* set initial clock polarity */
81 -       if (is_active)
82 +       if (is_active) {
83                 setsck(spi, spi->mode & SPI_CPOL);
84 +               if (spi->mode & SPI_3WIRE)
85 +                       spi_gpio->miso_pin = SPI_MOSI_GPIO;
86 +               else
87 +                       spi_gpio->miso_pin = SPI_MISO_GPIO;
88 +       }
89  
90         if (cs != SPI_GPIO_NO_CHIPSELECT) {
91                 /* SPI is normally active-low */
92 @@ -192,6 +196,9 @@ static int spi_gpio_setup(struct spi_device *spi)
93         if (spi->bits_per_word > 32)
94                 return -EINVAL;
95  
96 +       if (!(spi->mode & SPI_3WIRE) && !gpio_is_valid(SPI_MISO_GPIO))
97 +               return -EINVAL;
98 +
99         if (!spi->controller_state) {
100                 if (cs != SPI_GPIO_NO_CHIPSELECT) {
101                         status = gpio_request(cs, dev_name(&spi->dev));
102 @@ -209,6 +216,16 @@ static int spi_gpio_setup(struct spi_device *spi)
103         return status;
104  }
105  
106 +static void spi_gpio_set_direction(struct spi_device *spi, bool is_tx)
107 +{
108 +       if (is_tx)
109 +               gpio_direction_output(SPI_MISO_GPIO, 0);
110 +       else
111 +               gpio_direction_input(SPI_MISO_GPIO);
112 +}
113 +
114 +#undef pdata
115 +
116  static void spi_gpio_cleanup(struct spi_device *spi)
117  {
118         unsigned long   cs = (unsigned long) spi->controller_data;
119 @@ -243,18 +260,20 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label)
120         if (value)
121                 goto done;
122  
123 -       value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
124 +       value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
125         if (value)
126                 goto free_mosi;
127  
128 -       value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
129 -       if (value)
130 -               goto free_miso;
131 +       if (gpio_is_valid(SPI_MISO_GPIO)) {
132 +               value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
133 +               if (value)
134 +                       goto free_sck;
135 +       }
136  
137         goto done;
138  
139 -free_miso:
140 -       gpio_free(SPI_MISO_GPIO);
141 +free_sck:
142 +       gpio_free(SPI_SCK_GPIO);
143  free_mosi:
144         gpio_free(SPI_MOSI_GPIO);
145  done:
146 @@ -302,13 +321,15 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
147         spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
148         spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
149         spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
150 -       spi_gpio->bitbang.flags = SPI_CS_HIGH;
151 +       spi_gpio->bitbang.set_direction = spi_gpio_set_direction;
152 +       spi_gpio->bitbang.flags = SPI_CS_HIGH | SPI_3WIRE;
153  
154         status = spi_bitbang_start(&spi_gpio->bitbang);
155         if (status < 0) {
156                 spi_master_put(spi_gpio->bitbang.master);
157  gpio_free:
158 -               gpio_free(SPI_MISO_GPIO);
159 +               if (gpio_is_valid(SPI_MOSI_GPIO))
160 +                       gpio_free(SPI_MISO_GPIO);
161                 gpio_free(SPI_MOSI_GPIO);
162                 gpio_free(SPI_SCK_GPIO);
163                 spi_master_put(master);
164 @@ -332,7 +353,8 @@ static int __exit spi_gpio_remove(struct platform_device *pdev)
165  
166         platform_set_drvdata(pdev, NULL);
167  
168 -       gpio_free(SPI_MISO_GPIO);
169 +       if (gpio_is_valid(SPI_MISO_GPIO))
170 +               gpio_free(SPI_MISO_GPIO);
171         gpio_free(SPI_MOSI_GPIO);
172         gpio_free(SPI_SCK_GPIO);
173  
174 diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
175 index 3274c50..0a466c9 100644
176 --- a/include/linux/spi/spi_bitbang.h
177 +++ b/include/linux/spi/spi_bitbang.h
178 @@ -52,6 +52,8 @@ struct spi_bitbang {
179         u32     (*txrx_word[4])(struct spi_device *spi,
180                         unsigned nsecs,
181                         u32 word, u8 bits);
182 +
183 +       void (*set_direction)(struct spi_device *, bool is_tx);
184  };
185  
186  /* you can call these default bitbang->master methods from your custom
187 -- 
188 1.5.6.5
189