aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi_gpio.c
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2010-06-30 16:27:37 -0400
committerGrant Likely <grant.likely@secretlab.ca>2010-07-04 00:45:44 -0400
commit3c8e1a84fd6b984a7bce8816db2e3defc57bbfe4 (patch)
tree52761ad5f2229d0b176ca36b7107a0ec43e1168f /drivers/spi/spi_gpio.c
parent04bb2a031cf95b34b7432dd47b318a932a895b4c (diff)
spi/spi-gpio: add support for controllers without MISO or MOSI pin
There are some boards that do not strictly follow SPI standard and use only 3 wires (SCLK, MOSI or MISO, SS) for connecting some simple auxiliary chips and controls them with GPIO based 'spi controller'. In this configuration the MISO or MOSI line is missing (it is not required if the chip does not transfer any data back to host or host only reads data from chip). This patch adds support for such non-standard configuration in GPIO-based SPI controller. It has been tested in configuration without MISO pin. Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi/spi_gpio.c')
-rw-r--r--drivers/spi/spi_gpio.c101
1 files changed, 83 insertions, 18 deletions
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c
index 82b480cc963..e24a63498ac 100644
--- a/drivers/spi/spi_gpio.c
+++ b/drivers/spi/spi_gpio.c
@@ -167,6 +167,44 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
167 return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); 167 return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
168} 168}
169 169
170/*
171 * These functions do not call setmosi or getmiso if respective flag
172 * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to
173 * call when such pin is not present or defined in the controller.
174 * A separate set of callbacks is defined to get highest possible
175 * speed in the generic case (when both MISO and MOSI lines are
176 * available), as optimiser will remove the checks when argument is
177 * constant.
178 */
179
180static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
181 unsigned nsecs, u32 word, u8 bits)
182{
183 unsigned flags = spi->master->flags;
184 return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
185}
186
187static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
188 unsigned nsecs, u32 word, u8 bits)
189{
190 unsigned flags = spi->master->flags;
191 return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
192}
193
194static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
195 unsigned nsecs, u32 word, u8 bits)
196{
197 unsigned flags = spi->master->flags;
198 return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
199}
200
201static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
202 unsigned nsecs, u32 word, u8 bits)
203{
204 unsigned flags = spi->master->flags;
205 return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
206}
207
170/*----------------------------------------------------------------------*/ 208/*----------------------------------------------------------------------*/
171 209
172static void spi_gpio_chipselect(struct spi_device *spi, int is_active) 210static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
@@ -232,19 +270,30 @@ static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
232} 270}
233 271
234static int __init 272static int __init
235spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) 273spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label,
274 u16 *res_flags)
236{ 275{
237 int value; 276 int value;
238 277
239 /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ 278 /* NOTE: SPI_*_GPIO symbols may reference "pdata" */
240 279
241 value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); 280 if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
242 if (value) 281 value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
243 goto done; 282 if (value)
283 goto done;
284 } else {
285 /* HW configuration without MOSI pin */
286 *res_flags |= SPI_MASTER_NO_TX;
287 }
244 288
245 value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); 289 if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
246 if (value) 290 value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
247 goto free_mosi; 291 if (value)
292 goto free_mosi;
293 } else {
294 /* HW configuration without MISO pin */
295 *res_flags |= SPI_MASTER_NO_RX;
296 }
248 297
249 value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); 298 value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
250 if (value) 299 if (value)
@@ -253,9 +302,11 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label)
253 goto done; 302 goto done;
254 303
255free_miso: 304free_miso:
256 gpio_free(SPI_MISO_GPIO); 305 if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
306 gpio_free(SPI_MISO_GPIO);
257free_mosi: 307free_mosi:
258 gpio_free(SPI_MOSI_GPIO); 308 if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
309 gpio_free(SPI_MOSI_GPIO);
259done: 310done:
260 return value; 311 return value;
261} 312}
@@ -266,6 +317,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
266 struct spi_master *master; 317 struct spi_master *master;
267 struct spi_gpio *spi_gpio; 318 struct spi_gpio *spi_gpio;
268 struct spi_gpio_platform_data *pdata; 319 struct spi_gpio_platform_data *pdata;
320 u16 master_flags = 0;
269 321
270 pdata = pdev->dev.platform_data; 322 pdata = pdev->dev.platform_data;
271#ifdef GENERIC_BITBANG 323#ifdef GENERIC_BITBANG
@@ -273,7 +325,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
273 return -ENODEV; 325 return -ENODEV;
274#endif 326#endif
275 327
276 status = spi_gpio_request(pdata, dev_name(&pdev->dev)); 328 status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
277 if (status < 0) 329 if (status < 0)
278 return status; 330 return status;
279 331
@@ -289,6 +341,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
289 if (pdata) 341 if (pdata)
290 spi_gpio->pdata = *pdata; 342 spi_gpio->pdata = *pdata;
291 343
344 master->flags = master_flags;
292 master->bus_num = pdev->id; 345 master->bus_num = pdev->id;
293 master->num_chipselect = SPI_N_CHIPSEL; 346 master->num_chipselect = SPI_N_CHIPSEL;
294 master->setup = spi_gpio_setup; 347 master->setup = spi_gpio_setup;
@@ -296,10 +349,18 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
296 349
297 spi_gpio->bitbang.master = spi_master_get(master); 350 spi_gpio->bitbang.master = spi_master_get(master);
298 spi_gpio->bitbang.chipselect = spi_gpio_chipselect; 351 spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
299 spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; 352
300 spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; 353 if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) {
301 spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; 354 spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
302 spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; 355 spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
356 spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
357 spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
358 } else {
359 spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
360 spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
361 spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
362 spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
363 }
303 spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; 364 spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
304 spi_gpio->bitbang.flags = SPI_CS_HIGH; 365 spi_gpio->bitbang.flags = SPI_CS_HIGH;
305 366
@@ -307,8 +368,10 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
307 if (status < 0) { 368 if (status < 0) {
308 spi_master_put(spi_gpio->bitbang.master); 369 spi_master_put(spi_gpio->bitbang.master);
309gpio_free: 370gpio_free:
310 gpio_free(SPI_MISO_GPIO); 371 if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
311 gpio_free(SPI_MOSI_GPIO); 372 gpio_free(SPI_MISO_GPIO);
373 if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
374 gpio_free(SPI_MOSI_GPIO);
312 gpio_free(SPI_SCK_GPIO); 375 gpio_free(SPI_SCK_GPIO);
313 spi_master_put(master); 376 spi_master_put(master);
314 } 377 }
@@ -331,8 +394,10 @@ static int __exit spi_gpio_remove(struct platform_device *pdev)
331 394
332 platform_set_drvdata(pdev, NULL); 395 platform_set_drvdata(pdev, NULL);
333 396
334 gpio_free(SPI_MISO_GPIO); 397 if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
335 gpio_free(SPI_MOSI_GPIO); 398 gpio_free(SPI_MISO_GPIO);
399 if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
400 gpio_free(SPI_MOSI_GPIO);
336 gpio_free(SPI_SCK_GPIO); 401 gpio_free(SPI_SCK_GPIO);
337 402
338 return status; 403 return status;