diff options
Diffstat (limited to 'drivers/spi/amba-pl022.c')
-rw-r--r-- | drivers/spi/amba-pl022.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index ff5bbb9c43c9..9aeb68113100 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
@@ -363,6 +363,7 @@ struct pl022 { | |||
363 | void *rx_end; | 363 | void *rx_end; |
364 | enum ssp_reading read; | 364 | enum ssp_reading read; |
365 | enum ssp_writing write; | 365 | enum ssp_writing write; |
366 | u32 exp_fifo_level; | ||
366 | }; | 367 | }; |
367 | 368 | ||
368 | /** | 369 | /** |
@@ -501,6 +502,9 @@ static int flush(struct pl022 *pl022) | |||
501 | while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) | 502 | while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) |
502 | readw(SSP_DR(pl022->virtbase)); | 503 | readw(SSP_DR(pl022->virtbase)); |
503 | } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--); | 504 | } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--); |
505 | |||
506 | pl022->exp_fifo_level = 0; | ||
507 | |||
504 | return limit; | 508 | return limit; |
505 | } | 509 | } |
506 | 510 | ||
@@ -583,10 +587,9 @@ static void readwriter(struct pl022 *pl022) | |||
583 | * errons in 8bit wide transfers on ARM variants (just 8 words | 587 | * errons in 8bit wide transfers on ARM variants (just 8 words |
584 | * FIFO, means only 8x8 = 64 bits in FIFO) at least. | 588 | * FIFO, means only 8x8 = 64 bits in FIFO) at least. |
585 | * | 589 | * |
586 | * FIXME: currently we have no logic to account for this. | 590 | * To prevent this issue, the TX FIFO is only filled to the |
587 | * perhaps there is even something broken in HW regarding | 591 | * unused RX FIFO fill length, regardless of what the TX |
588 | * 8bit transfers (it doesn't fail on 16bit) so this needs | 592 | * FIFO status flag indicates. |
589 | * more investigation... | ||
590 | */ | 593 | */ |
591 | dev_dbg(&pl022->adev->dev, | 594 | dev_dbg(&pl022->adev->dev, |
592 | "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n", | 595 | "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n", |
@@ -613,11 +616,12 @@ static void readwriter(struct pl022 *pl022) | |||
613 | break; | 616 | break; |
614 | } | 617 | } |
615 | pl022->rx += (pl022->cur_chip->n_bytes); | 618 | pl022->rx += (pl022->cur_chip->n_bytes); |
619 | pl022->exp_fifo_level--; | ||
616 | } | 620 | } |
617 | /* | 621 | /* |
618 | * Write as much as you can, while keeping an eye on the RX FIFO! | 622 | * Write as much as possible up to the RX FIFO size |
619 | */ | 623 | */ |
620 | while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF) | 624 | while ((pl022->exp_fifo_level < pl022->vendor->fifodepth) |
621 | && (pl022->tx < pl022->tx_end)) { | 625 | && (pl022->tx < pl022->tx_end)) { |
622 | switch (pl022->write) { | 626 | switch (pl022->write) { |
623 | case WRITING_NULL: | 627 | case WRITING_NULL: |
@@ -634,6 +638,7 @@ static void readwriter(struct pl022 *pl022) | |||
634 | break; | 638 | break; |
635 | } | 639 | } |
636 | pl022->tx += (pl022->cur_chip->n_bytes); | 640 | pl022->tx += (pl022->cur_chip->n_bytes); |
641 | pl022->exp_fifo_level++; | ||
637 | /* | 642 | /* |
638 | * This inner reader takes care of things appearing in the RX | 643 | * This inner reader takes care of things appearing in the RX |
639 | * FIFO as we're transmitting. This will happen a lot since the | 644 | * FIFO as we're transmitting. This will happen a lot since the |
@@ -660,6 +665,7 @@ static void readwriter(struct pl022 *pl022) | |||
660 | break; | 665 | break; |
661 | } | 666 | } |
662 | pl022->rx += (pl022->cur_chip->n_bytes); | 667 | pl022->rx += (pl022->cur_chip->n_bytes); |
668 | pl022->exp_fifo_level--; | ||
663 | } | 669 | } |
664 | } | 670 | } |
665 | /* | 671 | /* |