diff options
-rw-r--r-- | drivers/spi/spi-bitbang.c | 261 | ||||
-rw-r--r-- | include/linux/spi/spi_bitbang.h | 5 |
2 files changed, 115 insertions, 151 deletions
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index a63d7da3bfe2..a89178dc8498 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c | |||
@@ -255,150 +255,142 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
255 | * Drivers can provide word-at-a-time i/o primitives, or provide | 255 | * Drivers can provide word-at-a-time i/o primitives, or provide |
256 | * transfer-at-a-time ones to leverage dma or fifo hardware. | 256 | * transfer-at-a-time ones to leverage dma or fifo hardware. |
257 | */ | 257 | */ |
258 | static void bitbang_work(struct work_struct *work) | 258 | |
259 | static int spi_bitbang_prepare_hardware(struct spi_master *spi) | ||
259 | { | 260 | { |
260 | struct spi_bitbang *bitbang = | 261 | struct spi_bitbang *bitbang; |
261 | container_of(work, struct spi_bitbang, work); | ||
262 | unsigned long flags; | 262 | unsigned long flags; |
263 | struct spi_message *m, *_m; | 263 | |
264 | bitbang = spi_master_get_devdata(spi); | ||
264 | 265 | ||
265 | spin_lock_irqsave(&bitbang->lock, flags); | 266 | spin_lock_irqsave(&bitbang->lock, flags); |
266 | bitbang->busy = 1; | 267 | bitbang->busy = 1; |
267 | list_for_each_entry_safe(m, _m, &bitbang->queue, queue) { | 268 | spin_unlock_irqrestore(&bitbang->lock, flags); |
268 | struct spi_device *spi; | ||
269 | unsigned nsecs; | ||
270 | struct spi_transfer *t = NULL; | ||
271 | unsigned tmp; | ||
272 | unsigned cs_change; | ||
273 | int status; | ||
274 | int do_setup = -1; | ||
275 | |||
276 | list_del(&m->queue); | ||
277 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
278 | |||
279 | /* FIXME this is made-up ... the correct value is known to | ||
280 | * word-at-a-time bitbang code, and presumably chipselect() | ||
281 | * should enforce these requirements too? | ||
282 | */ | ||
283 | nsecs = 100; | ||
284 | 269 | ||
285 | spi = m->spi; | 270 | return 0; |
286 | tmp = 0; | 271 | } |
287 | cs_change = 1; | ||
288 | status = 0; | ||
289 | 272 | ||
290 | list_for_each_entry (t, &m->transfers, transfer_list) { | 273 | static int spi_bitbang_transfer_one(struct spi_master *master, |
291 | 274 | struct spi_message *m) | |
292 | /* override speed or wordsize? */ | 275 | { |
293 | if (t->speed_hz || t->bits_per_word) | 276 | struct spi_bitbang *bitbang; |
294 | do_setup = 1; | 277 | unsigned nsecs; |
295 | 278 | struct spi_transfer *t = NULL; | |
296 | /* init (-1) or override (1) transfer params */ | 279 | unsigned tmp; |
297 | if (do_setup != 0) { | 280 | unsigned cs_change; |
298 | status = bitbang->setup_transfer(spi, t); | 281 | int status; |
299 | if (status < 0) | 282 | int do_setup = -1; |
300 | break; | 283 | struct spi_device *spi = m->spi; |
301 | if (do_setup == -1) | 284 | |
302 | do_setup = 0; | 285 | bitbang = spi_master_get_devdata(master); |
303 | } | 286 | |
304 | 287 | /* FIXME this is made-up ... the correct value is known to | |
305 | /* set up default clock polarity, and activate chip; | 288 | * word-at-a-time bitbang code, and presumably chipselect() |
306 | * this implicitly updates clock and spi modes as | 289 | * should enforce these requirements too? |
307 | * previously recorded for this device via setup(). | 290 | */ |
308 | * (and also deselects any other chip that might be | 291 | nsecs = 100; |
309 | * selected ...) | ||
310 | */ | ||
311 | if (cs_change) { | ||
312 | bitbang->chipselect(spi, BITBANG_CS_ACTIVE); | ||
313 | ndelay(nsecs); | ||
314 | } | ||
315 | cs_change = t->cs_change; | ||
316 | if (!t->tx_buf && !t->rx_buf && t->len) { | ||
317 | status = -EINVAL; | ||
318 | break; | ||
319 | } | ||
320 | 292 | ||
321 | /* transfer data. the lower level code handles any | 293 | tmp = 0; |
322 | * new dma mappings it needs. our caller always gave | 294 | cs_change = 1; |
323 | * us dma-safe buffers. | 295 | status = 0; |
324 | */ | 296 | |
325 | if (t->len) { | 297 | list_for_each_entry (t, &m->transfers, transfer_list) { |
326 | /* REVISIT dma API still needs a designated | 298 | |
327 | * DMA_ADDR_INVALID; ~0 might be better. | 299 | /* override speed or wordsize? */ |
328 | */ | 300 | if (t->speed_hz || t->bits_per_word) |
329 | if (!m->is_dma_mapped) | 301 | do_setup = 1; |
330 | t->rx_dma = t->tx_dma = 0; | 302 | |
331 | status = bitbang->txrx_bufs(spi, t); | 303 | /* init (-1) or override (1) transfer params */ |
332 | } | 304 | if (do_setup != 0) { |
333 | if (status > 0) | 305 | status = bitbang->setup_transfer(spi, t); |
334 | m->actual_length += status; | 306 | if (status < 0) |
335 | if (status != t->len) { | ||
336 | /* always report some kind of error */ | ||
337 | if (status >= 0) | ||
338 | status = -EREMOTEIO; | ||
339 | break; | 307 | break; |
340 | } | 308 | if (do_setup == -1) |
341 | status = 0; | 309 | do_setup = 0; |
342 | |||
343 | /* protocol tweaks before next transfer */ | ||
344 | if (t->delay_usecs) | ||
345 | udelay(t->delay_usecs); | ||
346 | |||
347 | if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) { | ||
348 | /* sometimes a short mid-message deselect of the chip | ||
349 | * may be needed to terminate a mode or command | ||
350 | */ | ||
351 | ndelay(nsecs); | ||
352 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
353 | ndelay(nsecs); | ||
354 | } | ||
355 | } | 310 | } |
356 | 311 | ||
357 | m->status = status; | 312 | /* set up default clock polarity, and activate chip; |
358 | m->complete(m->context); | 313 | * this implicitly updates clock and spi modes as |
314 | * previously recorded for this device via setup(). | ||
315 | * (and also deselects any other chip that might be | ||
316 | * selected ...) | ||
317 | */ | ||
318 | if (cs_change) { | ||
319 | bitbang->chipselect(spi, BITBANG_CS_ACTIVE); | ||
320 | ndelay(nsecs); | ||
321 | } | ||
322 | cs_change = t->cs_change; | ||
323 | if (!t->tx_buf && !t->rx_buf && t->len) { | ||
324 | status = -EINVAL; | ||
325 | break; | ||
326 | } | ||
359 | 327 | ||
360 | /* normally deactivate chipselect ... unless no error and | 328 | /* transfer data. the lower level code handles any |
361 | * cs_change has hinted that the next message will probably | 329 | * new dma mappings it needs. our caller always gave |
362 | * be for this chip too. | 330 | * us dma-safe buffers. |
363 | */ | 331 | */ |
364 | if (!(status == 0 && cs_change)) { | 332 | if (t->len) { |
333 | /* REVISIT dma API still needs a designated | ||
334 | * DMA_ADDR_INVALID; ~0 might be better. | ||
335 | */ | ||
336 | if (!m->is_dma_mapped) | ||
337 | t->rx_dma = t->tx_dma = 0; | ||
338 | status = bitbang->txrx_bufs(spi, t); | ||
339 | } | ||
340 | if (status > 0) | ||
341 | m->actual_length += status; | ||
342 | if (status != t->len) { | ||
343 | /* always report some kind of error */ | ||
344 | if (status >= 0) | ||
345 | status = -EREMOTEIO; | ||
346 | break; | ||
347 | } | ||
348 | status = 0; | ||
349 | |||
350 | /* protocol tweaks before next transfer */ | ||
351 | if (t->delay_usecs) | ||
352 | udelay(t->delay_usecs); | ||
353 | |||
354 | if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) { | ||
355 | /* sometimes a short mid-message deselect of the chip | ||
356 | * may be needed to terminate a mode or command | ||
357 | */ | ||
365 | ndelay(nsecs); | 358 | ndelay(nsecs); |
366 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | 359 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); |
367 | ndelay(nsecs); | 360 | ndelay(nsecs); |
368 | } | 361 | } |
362 | } | ||
363 | |||
364 | m->status = status; | ||
369 | 365 | ||
370 | spin_lock_irqsave(&bitbang->lock, flags); | 366 | /* normally deactivate chipselect ... unless no error and |
367 | * cs_change has hinted that the next message will probably | ||
368 | * be for this chip too. | ||
369 | */ | ||
370 | if (!(status == 0 && cs_change)) { | ||
371 | ndelay(nsecs); | ||
372 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
373 | ndelay(nsecs); | ||
371 | } | 374 | } |
372 | bitbang->busy = 0; | 375 | |
373 | spin_unlock_irqrestore(&bitbang->lock, flags); | 376 | spi_finalize_current_message(master); |
377 | |||
378 | return status; | ||
374 | } | 379 | } |
375 | 380 | ||
376 | /** | 381 | static int spi_bitbang_unprepare_hardware(struct spi_master *spi) |
377 | * spi_bitbang_transfer - default submit to transfer queue | ||
378 | */ | ||
379 | int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) | ||
380 | { | 382 | { |
381 | struct spi_bitbang *bitbang; | 383 | struct spi_bitbang *bitbang; |
382 | unsigned long flags; | 384 | unsigned long flags; |
383 | int status = 0; | ||
384 | 385 | ||
385 | m->actual_length = 0; | 386 | bitbang = spi_master_get_devdata(spi); |
386 | m->status = -EINPROGRESS; | ||
387 | |||
388 | bitbang = spi_master_get_devdata(spi->master); | ||
389 | 387 | ||
390 | spin_lock_irqsave(&bitbang->lock, flags); | 388 | spin_lock_irqsave(&bitbang->lock, flags); |
391 | if (!spi->max_speed_hz) | 389 | bitbang->busy = 0; |
392 | status = -ENETDOWN; | ||
393 | else { | ||
394 | list_add_tail(&m->queue, &bitbang->queue); | ||
395 | queue_work(bitbang->workqueue, &bitbang->work); | ||
396 | } | ||
397 | spin_unlock_irqrestore(&bitbang->lock, flags); | 390 | spin_unlock_irqrestore(&bitbang->lock, flags); |
398 | 391 | ||
399 | return status; | 392 | return 0; |
400 | } | 393 | } |
401 | EXPORT_SYMBOL_GPL(spi_bitbang_transfer); | ||
402 | 394 | ||
403 | /*----------------------------------------------------------------------*/ | 395 | /*----------------------------------------------------------------------*/ |
404 | 396 | ||
@@ -428,20 +420,22 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer); | |||
428 | int spi_bitbang_start(struct spi_bitbang *bitbang) | 420 | int spi_bitbang_start(struct spi_bitbang *bitbang) |
429 | { | 421 | { |
430 | struct spi_master *master = bitbang->master; | 422 | struct spi_master *master = bitbang->master; |
431 | int status; | ||
432 | 423 | ||
433 | if (!master || !bitbang->chipselect) | 424 | if (!master || !bitbang->chipselect) |
434 | return -EINVAL; | 425 | return -EINVAL; |
435 | 426 | ||
436 | INIT_WORK(&bitbang->work, bitbang_work); | ||
437 | spin_lock_init(&bitbang->lock); | 427 | spin_lock_init(&bitbang->lock); |
438 | INIT_LIST_HEAD(&bitbang->queue); | ||
439 | 428 | ||
440 | if (!master->mode_bits) | 429 | if (!master->mode_bits) |
441 | master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; | 430 | master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; |
442 | 431 | ||
443 | if (!master->transfer) | 432 | if (master->transfer || master->transfer_one_message) |
444 | master->transfer = spi_bitbang_transfer; | 433 | return -EINVAL; |
434 | |||
435 | master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; | ||
436 | master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; | ||
437 | master->transfer_one_message = spi_bitbang_transfer_one; | ||
438 | |||
445 | if (!bitbang->txrx_bufs) { | 439 | if (!bitbang->txrx_bufs) { |
446 | bitbang->use_dma = 0; | 440 | bitbang->use_dma = 0; |
447 | bitbang->txrx_bufs = spi_bitbang_bufs; | 441 | bitbang->txrx_bufs = spi_bitbang_bufs; |
@@ -454,32 +448,11 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) | |||
454 | } | 448 | } |
455 | } else if (!master->setup) | 449 | } else if (!master->setup) |
456 | return -EINVAL; | 450 | return -EINVAL; |
457 | if (master->transfer == spi_bitbang_transfer && | ||
458 | !bitbang->setup_transfer) | ||
459 | return -EINVAL; | ||
460 | |||
461 | /* this task is the only thing to touch the SPI bits */ | ||
462 | bitbang->busy = 0; | ||
463 | bitbang->workqueue = create_singlethread_workqueue( | ||
464 | dev_name(master->dev.parent)); | ||
465 | if (bitbang->workqueue == NULL) { | ||
466 | status = -EBUSY; | ||
467 | goto err1; | ||
468 | } | ||
469 | 451 | ||
470 | /* driver may get busy before register() returns, especially | 452 | /* driver may get busy before register() returns, especially |
471 | * if someone registered boardinfo for devices | 453 | * if someone registered boardinfo for devices |
472 | */ | 454 | */ |
473 | status = spi_register_master(master); | 455 | return spi_register_master(master); |
474 | if (status < 0) | ||
475 | goto err2; | ||
476 | |||
477 | return status; | ||
478 | |||
479 | err2: | ||
480 | destroy_workqueue(bitbang->workqueue); | ||
481 | err1: | ||
482 | return status; | ||
483 | } | 456 | } |
484 | EXPORT_SYMBOL_GPL(spi_bitbang_start); | 457 | EXPORT_SYMBOL_GPL(spi_bitbang_start); |
485 | 458 | ||
@@ -490,10 +463,6 @@ int spi_bitbang_stop(struct spi_bitbang *bitbang) | |||
490 | { | 463 | { |
491 | spi_unregister_master(bitbang->master); | 464 | spi_unregister_master(bitbang->master); |
492 | 465 | ||
493 | WARN_ON(!list_empty(&bitbang->queue)); | ||
494 | |||
495 | destroy_workqueue(bitbang->workqueue); | ||
496 | |||
497 | return 0; | 466 | return 0; |
498 | } | 467 | } |
499 | EXPORT_SYMBOL_GPL(spi_bitbang_stop); | 468 | EXPORT_SYMBOL_GPL(spi_bitbang_stop); |
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index f987a2bee16a..daebaba886aa 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h | |||
@@ -4,11 +4,7 @@ | |||
4 | #include <linux/workqueue.h> | 4 | #include <linux/workqueue.h> |
5 | 5 | ||
6 | struct spi_bitbang { | 6 | struct spi_bitbang { |
7 | struct workqueue_struct *workqueue; | ||
8 | struct work_struct work; | ||
9 | |||
10 | spinlock_t lock; | 7 | spinlock_t lock; |
11 | struct list_head queue; | ||
12 | u8 busy; | 8 | u8 busy; |
13 | u8 use_dma; | 9 | u8 use_dma; |
14 | u8 flags; /* extra spi->mode support */ | 10 | u8 flags; /* extra spi->mode support */ |
@@ -41,7 +37,6 @@ struct spi_bitbang { | |||
41 | */ | 37 | */ |
42 | extern int spi_bitbang_setup(struct spi_device *spi); | 38 | extern int spi_bitbang_setup(struct spi_device *spi); |
43 | extern void spi_bitbang_cleanup(struct spi_device *spi); | 39 | extern void spi_bitbang_cleanup(struct spi_device *spi); |
44 | extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m); | ||
45 | extern int spi_bitbang_setup_transfer(struct spi_device *spi, | 40 | extern int spi_bitbang_setup_transfer(struct spi_device *spi, |
46 | struct spi_transfer *t); | 41 | struct spi_transfer *t); |
47 | 42 | ||