diff options
author | Bob Liu <lliubbo@gmail.com> | 2011-01-11 11:19:07 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-02-15 15:56:58 -0500 |
commit | 4d676fc5c39a677aa72148debd47029d8d8f0634 (patch) | |
tree | 5f2e97edbf7870a5cdb789faffde7ebeca25648e /drivers/spi | |
parent | b214b7bbffca8ac6a6f1dad46408f7a9d4219098 (diff) |
spi/bfin_spi: support for multiples of 8bits with hardware CS
We can do multiples of 8bit transfers when using the hardware CS and a
little bit of magic, so make it work.
Signed-off-by: Bob Liu <lliubbo@gmail.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi_bfin5xx.c | 103 |
1 files changed, 71 insertions, 32 deletions
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 3f223511127b..e8d68b79e98f 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c | |||
@@ -425,6 +425,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) | |||
425 | struct bfin_spi_slave_data *chip = drv_data->cur_chip; | 425 | struct bfin_spi_slave_data *chip = drv_data->cur_chip; |
426 | struct spi_message *msg = drv_data->cur_msg; | 426 | struct spi_message *msg = drv_data->cur_msg; |
427 | int n_bytes = drv_data->n_bytes; | 427 | int n_bytes = drv_data->n_bytes; |
428 | int loop = 0; | ||
428 | 429 | ||
429 | /* wait until transfer finished. */ | 430 | /* wait until transfer finished. */ |
430 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 431 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
@@ -435,10 +436,15 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) | |||
435 | /* last read */ | 436 | /* last read */ |
436 | if (drv_data->rx) { | 437 | if (drv_data->rx) { |
437 | dev_dbg(&drv_data->pdev->dev, "last read\n"); | 438 | dev_dbg(&drv_data->pdev->dev, "last read\n"); |
438 | if (n_bytes == 2) | 439 | if (n_bytes % 2) { |
439 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | 440 | u16 *buf = (u16 *)drv_data->rx; |
440 | else if (n_bytes == 1) | 441 | for (loop = 0; loop < n_bytes / 2; loop++) |
441 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | 442 | *buf++ = read_RDBR(drv_data); |
443 | } else { | ||
444 | u8 *buf = (u8 *)drv_data->rx; | ||
445 | for (loop = 0; loop < n_bytes; loop++) | ||
446 | *buf++ = read_RDBR(drv_data); | ||
447 | } | ||
442 | drv_data->rx += n_bytes; | 448 | drv_data->rx += n_bytes; |
443 | } | 449 | } |
444 | 450 | ||
@@ -458,29 +464,53 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) | |||
458 | if (drv_data->rx && drv_data->tx) { | 464 | if (drv_data->rx && drv_data->tx) { |
459 | /* duplex */ | 465 | /* duplex */ |
460 | dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n"); | 466 | dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n"); |
461 | if (drv_data->n_bytes == 2) { | 467 | if (n_bytes % 2) { |
462 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | 468 | u16 *buf = (u16 *)drv_data->rx; |
463 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 469 | u16 *buf2 = (u16 *)drv_data->tx; |
464 | } else if (drv_data->n_bytes == 1) { | 470 | for (loop = 0; loop < n_bytes / 2; loop++) { |
465 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | 471 | *buf++ = read_RDBR(drv_data); |
466 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 472 | write_TDBR(drv_data, *buf2++); |
473 | } | ||
474 | } else { | ||
475 | u8 *buf = (u8 *)drv_data->rx; | ||
476 | u8 *buf2 = (u8 *)drv_data->tx; | ||
477 | for (loop = 0; loop < n_bytes; loop++) { | ||
478 | *buf++ = read_RDBR(drv_data); | ||
479 | write_TDBR(drv_data, *buf2++); | ||
480 | } | ||
467 | } | 481 | } |
468 | } else if (drv_data->rx) { | 482 | } else if (drv_data->rx) { |
469 | /* read */ | 483 | /* read */ |
470 | dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n"); | 484 | dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n"); |
471 | if (drv_data->n_bytes == 2) | 485 | if (n_bytes % 2) { |
472 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | 486 | u16 *buf = (u16 *)drv_data->rx; |
473 | else if (drv_data->n_bytes == 1) | 487 | for (loop = 0; loop < n_bytes / 2; loop++) { |
474 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | 488 | *buf++ = read_RDBR(drv_data); |
475 | write_TDBR(drv_data, chip->idle_tx_val); | 489 | write_TDBR(drv_data, chip->idle_tx_val); |
490 | } | ||
491 | } else { | ||
492 | u8 *buf = (u8 *)drv_data->rx; | ||
493 | for (loop = 0; loop < n_bytes; loop++) { | ||
494 | *buf++ = read_RDBR(drv_data); | ||
495 | write_TDBR(drv_data, chip->idle_tx_val); | ||
496 | } | ||
497 | } | ||
476 | } else if (drv_data->tx) { | 498 | } else if (drv_data->tx) { |
477 | /* write */ | 499 | /* write */ |
478 | dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n"); | 500 | dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n"); |
479 | bfin_spi_dummy_read(drv_data); | 501 | if (n_bytes % 2) { |
480 | if (drv_data->n_bytes == 2) | 502 | u16 *buf = (u16 *)drv_data->tx; |
481 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 503 | for (loop = 0; loop < n_bytes / 2; loop++) { |
482 | else if (drv_data->n_bytes == 1) | 504 | read_RDBR(drv_data); |
483 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 505 | write_TDBR(drv_data, *buf++); |
506 | } | ||
507 | } else { | ||
508 | u8 *buf = (u8 *)drv_data->tx; | ||
509 | for (loop = 0; loop < n_bytes; loop++) { | ||
510 | read_RDBR(drv_data); | ||
511 | write_TDBR(drv_data, *buf++); | ||
512 | } | ||
513 | } | ||
484 | } | 514 | } |
485 | 515 | ||
486 | if (drv_data->tx) | 516 | if (drv_data->tx) |
@@ -651,16 +681,16 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
651 | 681 | ||
652 | /* Bits per word setup */ | 682 | /* Bits per word setup */ |
653 | bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; | 683 | bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; |
654 | if (bits_per_word == 8) { | 684 | if ((bits_per_word > 0) && (bits_per_word % 16 == 0)) { |
655 | drv_data->n_bytes = 1; | 685 | drv_data->n_bytes = bits_per_word/8; |
656 | drv_data->len = transfer->len; | ||
657 | cr_width = 0; | ||
658 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; | ||
659 | } else if (bits_per_word == 16) { | ||
660 | drv_data->n_bytes = 2; | ||
661 | drv_data->len = (transfer->len) >> 1; | 686 | drv_data->len = (transfer->len) >> 1; |
662 | cr_width = BIT_CTL_WORDSIZE; | 687 | cr_width = BIT_CTL_WORDSIZE; |
663 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; | 688 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; |
689 | } else if ((bits_per_word > 0) && (bits_per_word % 8 == 0)) { | ||
690 | drv_data->n_bytes = bits_per_word/8; | ||
691 | drv_data->len = transfer->len; | ||
692 | cr_width = 0; | ||
693 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; | ||
664 | } else { | 694 | } else { |
665 | dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n"); | 695 | dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n"); |
666 | message->status = -EINVAL; | 696 | message->status = -EINVAL; |
@@ -815,10 +845,19 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
815 | if (drv_data->tx == NULL) | 845 | if (drv_data->tx == NULL) |
816 | write_TDBR(drv_data, chip->idle_tx_val); | 846 | write_TDBR(drv_data, chip->idle_tx_val); |
817 | else { | 847 | else { |
818 | if (bits_per_word == 8) | 848 | int loop; |
819 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 849 | if (bits_per_word % 16 == 0) { |
820 | else | 850 | u16 *buf = (u16 *)drv_data->tx; |
821 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 851 | for (loop = 0; loop < bits_per_word / 16; |
852 | loop++) { | ||
853 | write_TDBR(drv_data, *buf++); | ||
854 | } | ||
855 | } else if (bits_per_word % 8 == 0) { | ||
856 | u8 *buf = (u8 *)drv_data->tx; | ||
857 | for (loop = 0; loop < bits_per_word / 8; loop++) | ||
858 | write_TDBR(drv_data, *buf++); | ||
859 | } | ||
860 | |||
822 | drv_data->tx += drv_data->n_bytes; | 861 | drv_data->tx += drv_data->n_bytes; |
823 | } | 862 | } |
824 | 863 | ||
@@ -1031,7 +1070,7 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
1031 | chip->ctl_reg &= bfin_ctl_reg; | 1070 | chip->ctl_reg &= bfin_ctl_reg; |
1032 | } | 1071 | } |
1033 | 1072 | ||
1034 | if (spi->bits_per_word != 8 && spi->bits_per_word != 16) { | 1073 | if (spi->bits_per_word % 8) { |
1035 | dev_err(&spi->dev, "%d bits_per_word is not supported\n", | 1074 | dev_err(&spi->dev, "%d bits_per_word is not supported\n", |
1036 | spi->bits_per_word); | 1075 | spi->bits_per_word); |
1037 | goto error; | 1076 | goto error; |