diff options
author | Shimoda, Yoshihiro <yoshihiro.shimoda.uh@renesas.com> | 2012-04-20 01:50:36 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2012-05-20 00:37:16 -0400 |
commit | a3633fe7aa7022e2e9b2b799a0cbf3d6944d8ba5 (patch) | |
tree | acd8bfc00d867708e90b8e28e84de5617c9c7ac4 /drivers/spi/spi-rspi.c | |
parent | d195f7bebc14ece71bf11d09f1726ee6f6b4f4b9 (diff) |
spi/rspi: add dmaengine support
This patch adds dmaengine supporting using sh_dma driver. The module
receives data by DMAC, it also needs TX DMAC to generate SPI's clocks.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi/spi-rspi.c')
-rw-r--r-- | drivers/spi/spi-rspi.c | 320 |
1 files changed, 314 insertions, 6 deletions
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 354f170eab95..4894bde4bbff 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c | |||
@@ -31,7 +31,11 @@ | |||
31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/clk.h> | 33 | #include <linux/clk.h> |
34 | #include <linux/dmaengine.h> | ||
35 | #include <linux/dma-mapping.h> | ||
36 | #include <linux/sh_dma.h> | ||
34 | #include <linux/spi/spi.h> | 37 | #include <linux/spi/spi.h> |
38 | #include <linux/spi/rspi.h> | ||
35 | 39 | ||
36 | #define RSPI_SPCR 0x00 | 40 | #define RSPI_SPCR 0x00 |
37 | #define RSPI_SSLP 0x01 | 41 | #define RSPI_SSLP 0x01 |
@@ -141,6 +145,16 @@ struct rspi_data { | |||
141 | spinlock_t lock; | 145 | spinlock_t lock; |
142 | struct clk *clk; | 146 | struct clk *clk; |
143 | unsigned char spsr; | 147 | unsigned char spsr; |
148 | |||
149 | /* for dmaengine */ | ||
150 | struct sh_dmae_slave dma_tx; | ||
151 | struct sh_dmae_slave dma_rx; | ||
152 | struct dma_chan *chan_tx; | ||
153 | struct dma_chan *chan_rx; | ||
154 | int irq; | ||
155 | |||
156 | unsigned dma_width_16bit:1; | ||
157 | unsigned dma_callbacked:1; | ||
144 | }; | 158 | }; |
145 | 159 | ||
146 | static void rspi_write8(struct rspi_data *rspi, u8 data, u16 offset) | 160 | static void rspi_write8(struct rspi_data *rspi, u8 data, u16 offset) |
@@ -265,11 +279,125 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, | |||
265 | return 0; | 279 | return 0; |
266 | } | 280 | } |
267 | 281 | ||
268 | static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, | 282 | static void rspi_dma_complete(void *arg) |
269 | struct spi_transfer *t) | 283 | { |
284 | struct rspi_data *rspi = arg; | ||
285 | |||
286 | rspi->dma_callbacked = 1; | ||
287 | wake_up_interruptible(&rspi->wait); | ||
288 | } | ||
289 | |||
290 | static int rspi_dma_map_sg(struct scatterlist *sg, void *buf, unsigned len, | ||
291 | struct dma_chan *chan, | ||
292 | enum dma_transfer_direction dir) | ||
293 | { | ||
294 | sg_init_table(sg, 1); | ||
295 | sg_set_buf(sg, buf, len); | ||
296 | sg_dma_len(sg) = len; | ||
297 | return dma_map_sg(chan->device->dev, sg, 1, dir); | ||
298 | } | ||
299 | |||
300 | static void rspi_dma_unmap_sg(struct scatterlist *sg, struct dma_chan *chan, | ||
301 | enum dma_transfer_direction dir) | ||
302 | { | ||
303 | dma_unmap_sg(chan->device->dev, sg, 1, dir); | ||
304 | } | ||
305 | |||
306 | static void rspi_memory_to_8bit(void *buf, const void *data, unsigned len) | ||
307 | { | ||
308 | u16 *dst = buf; | ||
309 | const u8 *src = data; | ||
310 | |||
311 | while (len) { | ||
312 | *dst++ = (u16)(*src++); | ||
313 | len--; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len) | ||
318 | { | ||
319 | u8 *dst = buf; | ||
320 | const u16 *src = data; | ||
321 | |||
322 | while (len) { | ||
323 | *dst++ = (u8)*src++; | ||
324 | len--; | ||
325 | } | ||
326 | } | ||
327 | |||
328 | static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t) | ||
329 | { | ||
330 | struct scatterlist sg; | ||
331 | void *buf = NULL; | ||
332 | struct dma_async_tx_descriptor *desc; | ||
333 | unsigned len; | ||
334 | int ret = 0; | ||
335 | |||
336 | if (rspi->dma_width_16bit) { | ||
337 | /* | ||
338 | * If DMAC bus width is 16-bit, the driver allocates a dummy | ||
339 | * buffer. And, the driver converts original data into the | ||
340 | * DMAC data as the following format: | ||
341 | * original data: 1st byte, 2nd byte ... | ||
342 | * DMAC data: 1st byte, dummy, 2nd byte, dummy ... | ||
343 | */ | ||
344 | len = t->len * 2; | ||
345 | buf = kmalloc(len, GFP_KERNEL); | ||
346 | if (!buf) | ||
347 | return -ENOMEM; | ||
348 | rspi_memory_to_8bit(buf, t->tx_buf, t->len); | ||
349 | } else { | ||
350 | len = t->len; | ||
351 | buf = (void *)t->tx_buf; | ||
352 | } | ||
353 | |||
354 | if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) { | ||
355 | ret = -EFAULT; | ||
356 | goto end_nomap; | ||
357 | } | ||
358 | desc = dmaengine_prep_slave_sg(rspi->chan_tx, &sg, 1, DMA_TO_DEVICE, | ||
359 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
360 | if (!desc) { | ||
361 | ret = -EIO; | ||
362 | goto end; | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be | ||
367 | * called. So, this driver disables the IRQ while DMA transfer. | ||
368 | */ | ||
369 | disable_irq(rspi->irq); | ||
370 | |||
371 | rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR); | ||
372 | rspi_enable_irq(rspi, SPCR_SPTIE); | ||
373 | rspi->dma_callbacked = 0; | ||
374 | |||
375 | desc->callback = rspi_dma_complete; | ||
376 | desc->callback_param = rspi; | ||
377 | dmaengine_submit(desc); | ||
378 | dma_async_issue_pending(rspi->chan_tx); | ||
379 | |||
380 | ret = wait_event_interruptible_timeout(rspi->wait, | ||
381 | rspi->dma_callbacked, HZ); | ||
382 | if (ret > 0 && rspi->dma_callbacked) | ||
383 | ret = 0; | ||
384 | else if (!ret) | ||
385 | ret = -ETIMEDOUT; | ||
386 | rspi_disable_irq(rspi, SPCR_SPTIE); | ||
387 | |||
388 | enable_irq(rspi->irq); | ||
389 | |||
390 | end: | ||
391 | rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE); | ||
392 | end_nomap: | ||
393 | if (rspi->dma_width_16bit) | ||
394 | kfree(buf); | ||
395 | |||
396 | return ret; | ||
397 | } | ||
398 | |||
399 | static void rspi_receive_init(struct rspi_data *rspi) | ||
270 | { | 400 | { |
271 | int remain = t->len; | ||
272 | u8 *data; | ||
273 | unsigned char spsr; | 401 | unsigned char spsr; |
274 | 402 | ||
275 | spsr = rspi_read8(rspi, RSPI_SPSR); | 403 | spsr = rspi_read8(rspi, RSPI_SPSR); |
@@ -278,6 +406,15 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, | |||
278 | if (spsr & SPSR_OVRF) | 406 | if (spsr & SPSR_OVRF) |
279 | rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF, | 407 | rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF, |
280 | RSPI_SPCR); | 408 | RSPI_SPCR); |
409 | } | ||
410 | |||
411 | static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, | ||
412 | struct spi_transfer *t) | ||
413 | { | ||
414 | int remain = t->len; | ||
415 | u8 *data; | ||
416 | |||
417 | rspi_receive_init(rspi); | ||
281 | 418 | ||
282 | data = (u8 *)t->rx_buf; | 419 | data = (u8 *)t->rx_buf; |
283 | while (remain > 0) { | 420 | while (remain > 0) { |
@@ -307,6 +444,120 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, | |||
307 | return 0; | 444 | return 0; |
308 | } | 445 | } |
309 | 446 | ||
447 | static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) | ||
448 | { | ||
449 | struct scatterlist sg, sg_dummy; | ||
450 | void *dummy = NULL, *rx_buf = NULL; | ||
451 | struct dma_async_tx_descriptor *desc, *desc_dummy; | ||
452 | unsigned len; | ||
453 | int ret = 0; | ||
454 | |||
455 | if (rspi->dma_width_16bit) { | ||
456 | /* | ||
457 | * If DMAC bus width is 16-bit, the driver allocates a dummy | ||
458 | * buffer. And, finally the driver converts the DMAC data into | ||
459 | * actual data as the following format: | ||
460 | * DMAC data: 1st byte, dummy, 2nd byte, dummy ... | ||
461 | * actual data: 1st byte, 2nd byte ... | ||
462 | */ | ||
463 | len = t->len * 2; | ||
464 | rx_buf = kmalloc(len, GFP_KERNEL); | ||
465 | if (!rx_buf) | ||
466 | return -ENOMEM; | ||
467 | } else { | ||
468 | len = t->len; | ||
469 | rx_buf = t->rx_buf; | ||
470 | } | ||
471 | |||
472 | /* prepare dummy transfer to generate SPI clocks */ | ||
473 | dummy = kzalloc(len, GFP_KERNEL); | ||
474 | if (!dummy) { | ||
475 | ret = -ENOMEM; | ||
476 | goto end_nomap; | ||
477 | } | ||
478 | if (!rspi_dma_map_sg(&sg_dummy, dummy, len, rspi->chan_tx, | ||
479 | DMA_TO_DEVICE)) { | ||
480 | ret = -EFAULT; | ||
481 | goto end_nomap; | ||
482 | } | ||
483 | desc_dummy = dmaengine_prep_slave_sg(rspi->chan_tx, &sg_dummy, 1, | ||
484 | DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
485 | if (!desc_dummy) { | ||
486 | ret = -EIO; | ||
487 | goto end_dummy_mapped; | ||
488 | } | ||
489 | |||
490 | /* prepare receive transfer */ | ||
491 | if (!rspi_dma_map_sg(&sg, rx_buf, len, rspi->chan_rx, | ||
492 | DMA_FROM_DEVICE)) { | ||
493 | ret = -EFAULT; | ||
494 | goto end_dummy_mapped; | ||
495 | |||
496 | } | ||
497 | desc = dmaengine_prep_slave_sg(rspi->chan_rx, &sg, 1, DMA_FROM_DEVICE, | ||
498 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
499 | if (!desc) { | ||
500 | ret = -EIO; | ||
501 | goto end; | ||
502 | } | ||
503 | |||
504 | rspi_receive_init(rspi); | ||
505 | |||
506 | /* | ||
507 | * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be | ||
508 | * called. So, this driver disables the IRQ while DMA transfer. | ||
509 | */ | ||
510 | disable_irq(rspi->irq); | ||
511 | |||
512 | rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR); | ||
513 | rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE); | ||
514 | rspi->dma_callbacked = 0; | ||
515 | |||
516 | desc->callback = rspi_dma_complete; | ||
517 | desc->callback_param = rspi; | ||
518 | dmaengine_submit(desc); | ||
519 | dma_async_issue_pending(rspi->chan_rx); | ||
520 | |||
521 | desc_dummy->callback = NULL; /* No callback */ | ||
522 | dmaengine_submit(desc_dummy); | ||
523 | dma_async_issue_pending(rspi->chan_tx); | ||
524 | |||
525 | ret = wait_event_interruptible_timeout(rspi->wait, | ||
526 | rspi->dma_callbacked, HZ); | ||
527 | if (ret > 0 && rspi->dma_callbacked) | ||
528 | ret = 0; | ||
529 | else if (!ret) | ||
530 | ret = -ETIMEDOUT; | ||
531 | rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE); | ||
532 | |||
533 | enable_irq(rspi->irq); | ||
534 | |||
535 | end: | ||
536 | rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE); | ||
537 | end_dummy_mapped: | ||
538 | rspi_dma_unmap_sg(&sg_dummy, rspi->chan_tx, DMA_TO_DEVICE); | ||
539 | end_nomap: | ||
540 | if (rspi->dma_width_16bit) { | ||
541 | if (!ret) | ||
542 | rspi_memory_from_8bit(t->rx_buf, rx_buf, t->len); | ||
543 | kfree(rx_buf); | ||
544 | } | ||
545 | kfree(dummy); | ||
546 | |||
547 | return ret; | ||
548 | } | ||
549 | |||
550 | static int rspi_is_dma(struct rspi_data *rspi, struct spi_transfer *t) | ||
551 | { | ||
552 | if (t->tx_buf && rspi->chan_tx) | ||
553 | return 1; | ||
554 | /* If the module receives data by DMAC, it also needs TX DMAC */ | ||
555 | if (t->rx_buf && rspi->chan_tx && rspi->chan_rx) | ||
556 | return 1; | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
310 | static void rspi_work(struct work_struct *work) | 561 | static void rspi_work(struct work_struct *work) |
311 | { | 562 | { |
312 | struct rspi_data *rspi = container_of(work, struct rspi_data, ws); | 563 | struct rspi_data *rspi = container_of(work, struct rspi_data, ws); |
@@ -325,12 +576,18 @@ static void rspi_work(struct work_struct *work) | |||
325 | 576 | ||
326 | list_for_each_entry(t, &mesg->transfers, transfer_list) { | 577 | list_for_each_entry(t, &mesg->transfers, transfer_list) { |
327 | if (t->tx_buf) { | 578 | if (t->tx_buf) { |
328 | ret = rspi_send_pio(rspi, mesg, t); | 579 | if (rspi_is_dma(rspi, t)) |
580 | ret = rspi_send_dma(rspi, t); | ||
581 | else | ||
582 | ret = rspi_send_pio(rspi, mesg, t); | ||
329 | if (ret < 0) | 583 | if (ret < 0) |
330 | goto error; | 584 | goto error; |
331 | } | 585 | } |
332 | if (t->rx_buf) { | 586 | if (t->rx_buf) { |
333 | ret = rspi_receive_pio(rspi, mesg, t); | 587 | if (rspi_is_dma(rspi, t)) |
588 | ret = rspi_receive_dma(rspi, t); | ||
589 | else | ||
590 | ret = rspi_receive_pio(rspi, mesg, t); | ||
334 | if (ret < 0) | 591 | if (ret < 0) |
335 | goto error; | 592 | goto error; |
336 | } | 593 | } |
@@ -406,11 +663,58 @@ static irqreturn_t rspi_irq(int irq, void *_sr) | |||
406 | return ret; | 663 | return ret; |
407 | } | 664 | } |
408 | 665 | ||
666 | static bool rspi_filter(struct dma_chan *chan, void *filter_param) | ||
667 | { | ||
668 | chan->private = filter_param; | ||
669 | return true; | ||
670 | } | ||
671 | |||
672 | static void __devinit rspi_request_dma(struct rspi_data *rspi, | ||
673 | struct platform_device *pdev) | ||
674 | { | ||
675 | struct rspi_plat_data *rspi_pd = pdev->dev.platform_data; | ||
676 | dma_cap_mask_t mask; | ||
677 | |||
678 | if (!rspi_pd) | ||
679 | return; | ||
680 | |||
681 | rspi->dma_width_16bit = rspi_pd->dma_width_16bit; | ||
682 | |||
683 | /* If the module receives data by DMAC, it also needs TX DMAC */ | ||
684 | if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) { | ||
685 | dma_cap_zero(mask); | ||
686 | dma_cap_set(DMA_SLAVE, mask); | ||
687 | rspi->dma_rx.slave_id = rspi_pd->dma_rx_id; | ||
688 | rspi->chan_rx = dma_request_channel(mask, rspi_filter, | ||
689 | &rspi->dma_rx); | ||
690 | if (rspi->chan_rx) | ||
691 | dev_info(&pdev->dev, "Use DMA when rx.\n"); | ||
692 | } | ||
693 | if (rspi_pd->dma_tx_id) { | ||
694 | dma_cap_zero(mask); | ||
695 | dma_cap_set(DMA_SLAVE, mask); | ||
696 | rspi->dma_tx.slave_id = rspi_pd->dma_tx_id; | ||
697 | rspi->chan_tx = dma_request_channel(mask, rspi_filter, | ||
698 | &rspi->dma_tx); | ||
699 | if (rspi->chan_tx) | ||
700 | dev_info(&pdev->dev, "Use DMA when tx\n"); | ||
701 | } | ||
702 | } | ||
703 | |||
704 | static void __devexit rspi_release_dma(struct rspi_data *rspi) | ||
705 | { | ||
706 | if (rspi->chan_tx) | ||
707 | dma_release_channel(rspi->chan_tx); | ||
708 | if (rspi->chan_rx) | ||
709 | dma_release_channel(rspi->chan_rx); | ||
710 | } | ||
711 | |||
409 | static int __devexit rspi_remove(struct platform_device *pdev) | 712 | static int __devexit rspi_remove(struct platform_device *pdev) |
410 | { | 713 | { |
411 | struct rspi_data *rspi = dev_get_drvdata(&pdev->dev); | 714 | struct rspi_data *rspi = dev_get_drvdata(&pdev->dev); |
412 | 715 | ||
413 | spi_unregister_master(rspi->master); | 716 | spi_unregister_master(rspi->master); |
717 | rspi_release_dma(rspi); | ||
414 | free_irq(platform_get_irq(pdev, 0), rspi); | 718 | free_irq(platform_get_irq(pdev, 0), rspi); |
415 | clk_put(rspi->clk); | 719 | clk_put(rspi->clk); |
416 | iounmap(rspi->addr); | 720 | iounmap(rspi->addr); |
@@ -483,6 +787,9 @@ static int __devinit rspi_probe(struct platform_device *pdev) | |||
483 | goto error3; | 787 | goto error3; |
484 | } | 788 | } |
485 | 789 | ||
790 | rspi->irq = irq; | ||
791 | rspi_request_dma(rspi, pdev); | ||
792 | |||
486 | ret = spi_register_master(master); | 793 | ret = spi_register_master(master); |
487 | if (ret < 0) { | 794 | if (ret < 0) { |
488 | dev_err(&pdev->dev, "spi_register_master error.\n"); | 795 | dev_err(&pdev->dev, "spi_register_master error.\n"); |
@@ -494,6 +801,7 @@ static int __devinit rspi_probe(struct platform_device *pdev) | |||
494 | return 0; | 801 | return 0; |
495 | 802 | ||
496 | error4: | 803 | error4: |
804 | rspi_release_dma(rspi); | ||
497 | free_irq(irq, rspi); | 805 | free_irq(irq, rspi); |
498 | error3: | 806 | error3: |
499 | clk_put(rspi->clk); | 807 | clk_put(rspi->clk); |