tools/qemu: fix FreeBSD compile issue
[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
This page took 0.050402 seconds and 5 git commands to generate.