package/cyassl: update to version 1.6.5
[openwrt.git] / target / linux / brcm63xx / patches-2.6.35 / 121-spi-gpio-norxtx-support.patch
1 From 3c8e1a84fd6b984a7bce8816db2e3defc57bbfe4 Mon Sep 17 00:00:00 2001
2 From: Marek Szyprowski <m.szyprowski@samsung.com>
3 Date: Wed, 30 Jun 2010 14:27:37 -0600
4 Subject: [PATCH] spi/spi-gpio: add support for controllers without MISO or MOSI pin
5
6 There are some boards that do not strictly follow SPI standard and use
7 only 3 wires (SCLK, MOSI or MISO, SS) for connecting some simple auxiliary
8 chips and controls them with GPIO based 'spi controller'. In this
9 configuration the MISO or MOSI line is missing (it is not required if the
10 chip does not transfer any data back to host or host only reads data from
11 chip).
12
13 This patch adds support for such non-standard configuration in GPIO-based
14 SPI controller. It has been tested in configuration without MISO pin.
15
16 Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com>
17 Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
18 Acked-by: David Brownell <dbrownell@users.sourceforge.net>
19 Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
20 ---
21  drivers/spi/spi_gpio.c       |  101 ++++++++++++++++++++++++++++++++++-------
22  include/linux/spi/spi_gpio.h |    5 ++
23  2 files changed, 88 insertions(+), 18 deletions(-)
24
25 --- a/drivers/spi/spi_gpio.c
26 +++ b/drivers/spi/spi_gpio.c
27 @@ -178,6 +178,44 @@ static u32 spi_gpio_txrx_word_mode3(stru
28         return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
29  }
30  
31 +/*
32 + * These functions do not call setmosi or getmiso if respective flag
33 + * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to
34 + * call when such pin is not present or defined in the controller.
35 + * A separate set of callbacks is defined to get highest possible
36 + * speed in the generic case (when both MISO and MOSI lines are
37 + * available), as optimiser will remove the checks when argument is
38 + * constant.
39 + */
40 +
41 +static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
42 +               unsigned nsecs, u32 word, u8 bits)
43 +{
44 +       unsigned flags = spi->master->flags;
45 +       return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
46 +}
47 +
48 +static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
49 +               unsigned nsecs, u32 word, u8 bits)
50 +{
51 +       unsigned flags = spi->master->flags;
52 +       return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
53 +}
54 +
55 +static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
56 +               unsigned nsecs, u32 word, u8 bits)
57 +{
58 +       unsigned flags = spi->master->flags;
59 +       return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
60 +}
61 +
62 +static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
63 +               unsigned nsecs, u32 word, u8 bits)
64 +{
65 +       unsigned flags = spi->master->flags;
66 +       return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
67 +}
68 +
69  /*----------------------------------------------------------------------*/
70  
71  static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
72 @@ -243,19 +281,30 @@ static int __devinit spi_gpio_alloc(unsi
73  }
74  
75  static int __devinit
76 -spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label)
77 +spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label,
78 +       u16 *res_flags)
79  {
80         int value;
81  
82         /* NOTE:  SPI_*_GPIO symbols may reference "pdata" */
83  
84 -       value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
85 -       if (value)
86 -               goto done;
87 -
88 -       value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
89 -       if (value)
90 -               goto free_mosi;
91 +       if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
92 +               value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
93 +               if (value)
94 +                       goto done;
95 +       } else {
96 +               /* HW configuration without MOSI pin */
97 +               *res_flags |= SPI_MASTER_NO_TX;
98 +       }
99 +
100 +       if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
101 +               value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
102 +               if (value)
103 +                       goto free_mosi;
104 +       } else {
105 +               /* HW configuration without MISO pin */
106 +               *res_flags |= SPI_MASTER_NO_RX;
107 +       }
108  
109         value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
110         if (value)
111 @@ -264,9 +313,11 @@ spi_gpio_request(struct spi_gpio_platfor
112         goto done;
113  
114  free_miso:
115 -       gpio_free(SPI_MISO_GPIO);
116 +       if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
117 +               gpio_free(SPI_MISO_GPIO);
118  free_mosi:
119 -       gpio_free(SPI_MOSI_GPIO);
120 +       if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
121 +               gpio_free(SPI_MOSI_GPIO);
122  done:
123         return value;
124  }
125 @@ -277,6 +328,7 @@ static int __devinit spi_gpio_probe(stru
126         struct spi_master               *master;
127         struct spi_gpio                 *spi_gpio;
128         struct spi_gpio_platform_data   *pdata;
129 +       u16 master_flags = 0;
130  
131         pdata = pdev->dev.platform_data;
132  #ifdef GENERIC_BITBANG
133 @@ -284,7 +336,7 @@ static int __devinit spi_gpio_probe(stru
134                 return -ENODEV;
135  #endif
136  
137 -       status = spi_gpio_request(pdata, dev_name(&pdev->dev));
138 +       status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
139         if (status < 0)
140                 return status;
141  
142 @@ -300,6 +352,7 @@ static int __devinit spi_gpio_probe(stru
143         if (pdata)
144                 spi_gpio->pdata = *pdata;
145  
146 +       master->flags = master_flags;
147         master->bus_num = pdev->id;
148         master->num_chipselect = SPI_N_CHIPSEL;
149         master->setup = spi_gpio_setup;
150 @@ -307,10 +360,18 @@ static int __devinit spi_gpio_probe(stru
151  
152         spi_gpio->bitbang.master = spi_master_get(master);
153         spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
154 -       spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
155 -       spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
156 -       spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
157 -       spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
158 +
159 +       if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) {
160 +               spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
161 +               spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
162 +               spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
163 +               spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
164 +       } else {
165 +               spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
166 +               spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
167 +               spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
168 +               spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
169 +       }
170         spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
171         spi_gpio->bitbang.flags = SPI_CS_HIGH;
172  
173 @@ -318,8 +379,10 @@ static int __devinit spi_gpio_probe(stru
174         if (status < 0) {
175                 spi_master_put(spi_gpio->bitbang.master);
176  gpio_free:
177 -               gpio_free(SPI_MISO_GPIO);
178 -               gpio_free(SPI_MOSI_GPIO);
179 +               if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
180 +                       gpio_free(SPI_MISO_GPIO);
181 +               if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
182 +                       gpio_free(SPI_MOSI_GPIO);
183                 gpio_free(SPI_SCK_GPIO);
184                 spi_master_put(master);
185         }
186 @@ -342,8 +405,10 @@ static int __devexit spi_gpio_remove(str
187  
188         platform_set_drvdata(pdev, NULL);
189  
190 -       gpio_free(SPI_MISO_GPIO);
191 -       gpio_free(SPI_MOSI_GPIO);
192 +       if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
193 +               gpio_free(SPI_MISO_GPIO);
194 +       if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
195 +               gpio_free(SPI_MOSI_GPIO);
196         gpio_free(SPI_SCK_GPIO);
197  
198         return status;
199 --- a/include/linux/spi/spi_gpio.h
200 +++ b/include/linux/spi/spi_gpio.h
201 @@ -29,11 +29,16 @@
202   * SPI_GPIO_NO_CHIPSELECT to the controller_data:
203   *             .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT;
204   *
205 + * If the MISO or MOSI pin is not available then it should be set to
206 + * SPI_GPIO_NO_MISO or SPI_GPIO_NO_MOSI.
207 + *
208   * If the bitbanged bus is later switched to a "native" controller,
209   * that platform_device and controller_data should be removed.
210   */
211  
212  #define SPI_GPIO_NO_CHIPSELECT         ((unsigned long)-1l)
213 +#define SPI_GPIO_NO_MISO               ((unsigned long)-1l)
214 +#define SPI_GPIO_NO_MOSI               ((unsigned long)-1l)
215  
216  /**
217   * struct spi_gpio_platform_data - parameter for bitbanged SPI master