[xburst] Add 2.6.37 support
[openwrt.git] / target / linux / xburst / patches-2.6.35 / 400-spi-gpio-3wire.patch
1 From 62b6a295d39417293adcc81dc36b7edc56546814 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 --- a/drivers/spi/spi_bitbang.c
13 +++ b/drivers/spi/spi_bitbang.c
14 @@ -335,6 +335,8 @@ static void bitbang_work(struct work_str
15                                  */
16                                 if (!m->is_dma_mapped)
17                                         t->rx_dma = t->tx_dma = 0;
18 +                               if ((spi->mode & SPI_3WIRE) && bitbang->set_direction)
19 +                                       bitbang->set_direction(spi, t->tx_buf != NULL);
20                                 status = bitbang->txrx_bufs(spi, t);
21                         }
22                         if (status > 0)
23 --- a/drivers/spi/spi_gpio.c
24 +++ b/drivers/spi/spi_gpio.c
25 @@ -46,6 +46,8 @@ struct spi_gpio {
26         struct spi_bitbang              bitbang;
27         struct spi_gpio_platform_data   pdata;
28         struct platform_device          *pdev;
29 +
30 +       int miso_pin;
31  };
32  
33  /*----------------------------------------------------------------------*/
34 @@ -91,19 +93,16 @@ struct spi_gpio {
35  
36  /*----------------------------------------------------------------------*/
37  
38 -static inline const struct spi_gpio_platform_data * __pure
39 -spi_to_pdata(const struct spi_device *spi)
40 +static inline const struct spi_gpio * __pure
41 +spi_to_spi_gpio(const struct spi_device *spi)
42  {
43         const struct spi_bitbang        *bang;
44 -       const struct spi_gpio           *spi_gpio;
45  
46         bang = spi_master_get_devdata(spi->master);
47 -       spi_gpio = container_of(bang, struct spi_gpio, bitbang);
48 -       return &spi_gpio->pdata;
49 +       return container_of(bang, struct spi_gpio, bitbang);
50  }
51  
52 -/* this is #defined to avoid unused-variable warnings when inlining */
53 -#define pdata          spi_to_pdata(spi)
54 +#define pdata &(spi_to_spi_gpio(spi)->pdata)
55  
56  static inline void setsck(const struct spi_device *spi, int is_on)
57  {
58 @@ -117,10 +116,9 @@ static inline void setmosi(const struct 
59  
60  static inline int getmiso(const struct spi_device *spi)
61  {
62 -       return !!gpio_get_value(SPI_MISO_GPIO);
63 +       return !!gpio_get_value(spi_to_spi_gpio(spi)->miso_pin);
64  }
65  
66 -#undef pdata
67  
68  /*
69   * NOTE:  to clock "as fast as we can", set spi_device.max_speed_hz
70 @@ -183,10 +181,16 @@ static u32 spi_gpio_txrx_word_mode3(stru
71  static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
72  {
73         unsigned long cs = (unsigned long) spi->controller_data;
74 +       struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
75  
76         /* set initial clock polarity */
77 -       if (is_active)
78 +       if (is_active) {
79                 setsck(spi, spi->mode & SPI_CPOL);
80 +               if (spi->mode & SPI_3WIRE)
81 +                       spi_gpio->miso_pin = SPI_MOSI_GPIO;
82 +               else
83 +                       spi_gpio->miso_pin = SPI_MISO_GPIO;
84 +       }
85  
86         if (cs != SPI_GPIO_NO_CHIPSELECT) {
87                 /* SPI is normally active-low */
88 @@ -202,6 +206,9 @@ static int spi_gpio_setup(struct spi_dev
89         if (spi->bits_per_word > 32)
90                 return -EINVAL;
91  
92 +       if (!(spi->mode & SPI_3WIRE) && !gpio_is_valid(SPI_MISO_GPIO))
93 +               return -EINVAL;
94 +
95         if (!spi->controller_state) {
96                 if (cs != SPI_GPIO_NO_CHIPSELECT) {
97                         status = gpio_request(cs, dev_name(&spi->dev));
98 @@ -219,6 +226,16 @@ static int spi_gpio_setup(struct spi_dev
99         return status;
100  }
101  
102 +static void spi_gpio_set_direction(struct spi_device *spi, bool is_tx)
103 +{
104 +       if (is_tx)
105 +               gpio_direction_output(SPI_MISO_GPIO, 0);
106 +       else
107 +               gpio_direction_input(SPI_MISO_GPIO);
108 +}
109 +
110 +#undef pdata
111 +
112  static void spi_gpio_cleanup(struct spi_device *spi)
113  {
114         unsigned long   cs = (unsigned long) spi->controller_data;
115 @@ -253,18 +270,20 @@ spi_gpio_request(struct spi_gpio_platfor
116         if (value)
117                 goto done;
118  
119 -       value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
120 +       value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
121         if (value)
122                 goto free_mosi;
123  
124 -       value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
125 -       if (value)
126 -               goto free_miso;
127 +       if (gpio_is_valid(SPI_MISO_GPIO)) {
128 +               value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
129 +               if (value)
130 +                       goto free_sck;
131 +       }
132  
133         goto done;
134  
135 -free_miso:
136 -       gpio_free(SPI_MISO_GPIO);
137 +free_sck:
138 +       gpio_free(SPI_SCK_GPIO);
139  free_mosi:
140         gpio_free(SPI_MOSI_GPIO);
141  done:
142 @@ -312,13 +331,15 @@ static int __devinit spi_gpio_probe(stru
143         spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
144         spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
145         spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
146 -       spi_gpio->bitbang.flags = SPI_CS_HIGH;
147 +       spi_gpio->bitbang.set_direction = spi_gpio_set_direction;
148 +       spi_gpio->bitbang.flags = SPI_CS_HIGH | SPI_3WIRE;
149  
150         status = spi_bitbang_start(&spi_gpio->bitbang);
151         if (status < 0) {
152                 spi_master_put(spi_gpio->bitbang.master);
153  gpio_free:
154 -               gpio_free(SPI_MISO_GPIO);
155 +               if (gpio_is_valid(SPI_MOSI_GPIO))
156 +                       gpio_free(SPI_MISO_GPIO);
157                 gpio_free(SPI_MOSI_GPIO);
158                 gpio_free(SPI_SCK_GPIO);
159                 spi_master_put(master);
160 @@ -342,7 +363,8 @@ static int __devexit spi_gpio_remove(str
161  
162         platform_set_drvdata(pdev, NULL);
163  
164 -       gpio_free(SPI_MISO_GPIO);
165 +       if (gpio_is_valid(SPI_MISO_GPIO))
166 +               gpio_free(SPI_MISO_GPIO);
167         gpio_free(SPI_MOSI_GPIO);
168         gpio_free(SPI_SCK_GPIO);
169  
170 --- a/include/linux/spi/spi_bitbang.h
171 +++ b/include/linux/spi/spi_bitbang.h
172 @@ -34,6 +34,8 @@ struct spi_bitbang {
173         u32     (*txrx_word[4])(struct spi_device *spi,
174                         unsigned nsecs,
175                         u32 word, u8 bits);
176 +
177 +       void (*set_direction)(struct spi_device *, bool is_tx);
178  };
179  
180  /* you can call these default bitbang->master methods from your custom