aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorBob Liu <lliubbo@gmail.com>2011-01-11 11:19:07 -0500
committerGrant Likely <grant.likely@secretlab.ca>2011-02-15 15:56:58 -0500
commit4d676fc5c39a677aa72148debd47029d8d8f0634 (patch)
tree5f2e97edbf7870a5cdb789faffde7ebeca25648e /drivers/spi
parentb214b7bbffca8ac6a6f1dad46408f7a9d4219098 (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.c103
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;