diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-03-15 15:08:11 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-05-29 19:48:19 -0400 |
commit | ebd4219f10fbe3938cd36443e240eb6076b811ab (patch) | |
tree | b5f33dcf501072d11a593962ef7b70b88db2b1cb /arch/arm/mm | |
parent | 99ca1772e52d8825172100a24e461a0ffe11e125 (diff) |
ARM: l2c: implement L2C-310 erratum 588369 as a method override
Implement L2C-310 erratum 588369 by overriding the invalidate range
and flush range methods in the outer_cache operations structure.
This allows us to sensibly contain the erratum code in one place
without affecting other locations/implemetations.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 6161232c8a85..79ff08db204d 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c | |||
@@ -522,6 +522,65 @@ static void l2c310_set_debug(unsigned long val) | |||
522 | writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); | 522 | writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); |
523 | } | 523 | } |
524 | 524 | ||
525 | static void l2c310_inv_range_erratum(unsigned long start, unsigned long end) | ||
526 | { | ||
527 | void __iomem *base = l2x0_base; | ||
528 | |||
529 | if ((start | end) & (CACHE_LINE_SIZE - 1)) { | ||
530 | unsigned long flags; | ||
531 | |||
532 | /* Erratum 588369 for both clean+invalidate operations */ | ||
533 | raw_spin_lock_irqsave(&l2x0_lock, flags); | ||
534 | l2c_set_debug(base, 0x03); | ||
535 | |||
536 | if (start & (CACHE_LINE_SIZE - 1)) { | ||
537 | start &= ~(CACHE_LINE_SIZE - 1); | ||
538 | writel_relaxed(start, base + L2X0_CLEAN_LINE_PA); | ||
539 | writel_relaxed(start, base + L2X0_INV_LINE_PA); | ||
540 | start += CACHE_LINE_SIZE; | ||
541 | } | ||
542 | |||
543 | if (end & (CACHE_LINE_SIZE - 1)) { | ||
544 | end &= ~(CACHE_LINE_SIZE - 1); | ||
545 | writel_relaxed(end, base + L2X0_CLEAN_LINE_PA); | ||
546 | writel_relaxed(end, base + L2X0_INV_LINE_PA); | ||
547 | } | ||
548 | |||
549 | l2c_set_debug(base, 0x00); | ||
550 | raw_spin_unlock_irqrestore(&l2x0_lock, flags); | ||
551 | } | ||
552 | |||
553 | __l2c210_op_pa_range(base + L2X0_INV_LINE_PA, start, end); | ||
554 | __l2c210_cache_sync(base); | ||
555 | } | ||
556 | |||
557 | static void l2c310_flush_range_erratum(unsigned long start, unsigned long end) | ||
558 | { | ||
559 | raw_spinlock_t *lock = &l2x0_lock; | ||
560 | unsigned long flags; | ||
561 | void __iomem *base = l2x0_base; | ||
562 | |||
563 | raw_spin_lock_irqsave(lock, flags); | ||
564 | while (start < end) { | ||
565 | unsigned long blk_end = start + min(end - start, 4096UL); | ||
566 | |||
567 | l2c_set_debug(base, 0x03); | ||
568 | while (start < blk_end) { | ||
569 | writel_relaxed(start, base + L2X0_CLEAN_LINE_PA); | ||
570 | writel_relaxed(start, base + L2X0_INV_LINE_PA); | ||
571 | start += CACHE_LINE_SIZE; | ||
572 | } | ||
573 | l2c_set_debug(base, 0x00); | ||
574 | |||
575 | if (blk_end < end) { | ||
576 | raw_spin_unlock_irqrestore(lock, flags); | ||
577 | raw_spin_lock_irqsave(lock, flags); | ||
578 | } | ||
579 | } | ||
580 | raw_spin_unlock_irqrestore(lock, flags); | ||
581 | __l2c210_cache_sync(base); | ||
582 | } | ||
583 | |||
525 | static void l2c310_flush_all_erratum(void) | 584 | static void l2c310_flush_all_erratum(void) |
526 | { | 585 | { |
527 | void __iomem *base = l2x0_base; | 586 | void __iomem *base = l2x0_base; |
@@ -600,9 +659,19 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, | |||
600 | const char *errata[4]; | 659 | const char *errata[4]; |
601 | unsigned n = 0; | 660 | unsigned n = 0; |
602 | 661 | ||
662 | /* For compatibility */ | ||
603 | if (revision <= L310_CACHE_ID_RTL_R3P0) | 663 | if (revision <= L310_CACHE_ID_RTL_R3P0) |
604 | fns->set_debug = l2c310_set_debug; | 664 | fns->set_debug = l2c310_set_debug; |
605 | 665 | ||
666 | if (IS_ENABLED(CONFIG_PL310_ERRATA_588369) && | ||
667 | revision < L310_CACHE_ID_RTL_R2P0 && | ||
668 | /* For bcm compatibility */ | ||
669 | fns->inv_range == l2x0_inv_range) { | ||
670 | fns->inv_range = l2c310_inv_range_erratum; | ||
671 | fns->flush_range = l2c310_flush_range_erratum; | ||
672 | errata[n++] = "588369"; | ||
673 | } | ||
674 | |||
606 | if (IS_ENABLED(CONFIG_PL310_ERRATA_727915) && | 675 | if (IS_ENABLED(CONFIG_PL310_ERRATA_727915) && |
607 | revision >= L310_CACHE_ID_RTL_R2P0 && | 676 | revision >= L310_CACHE_ID_RTL_R2P0 && |
608 | revision < L310_CACHE_ID_RTL_R3P1) { | 677 | revision < L310_CACHE_ID_RTL_R3P1) { |