diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-03-18 17:40:01 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-05-29 19:50:41 -0400 |
commit | 8ef418c7178fa611d84e187bacb967880f6f5b69 (patch) | |
tree | c09538d68dd96ea3d6e99dc0e926dc3b3aaf1133 /arch/arm/mm/cache-l2x0.c | |
parent | 560be6136b3605ebbb8bd04b49b175c809d4e953 (diff) |
ARM: l2c: trial at enabling some Cortex-A9 optimisations
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/cache-l2x0.c')
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 73 |
1 files changed, 70 insertions, 3 deletions
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index e99a0ffd22d1..efc5cabf70e0 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c | |||
@@ -16,14 +16,17 @@ | |||
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | #include <linux/cpu.h> | ||
19 | #include <linux/err.h> | 20 | #include <linux/err.h> |
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/smp.h> | ||
21 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
22 | #include <linux/io.h> | 24 | #include <linux/io.h> |
23 | #include <linux/of.h> | 25 | #include <linux/of.h> |
24 | #include <linux/of_address.h> | 26 | #include <linux/of_address.h> |
25 | 27 | ||
26 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
29 | #include <asm/cp15.h> | ||
27 | #include <asm/cputype.h> | 30 | #include <asm/cputype.h> |
28 | #include <asm/hardware/cache-l2x0.h> | 31 | #include <asm/hardware/cache-l2x0.h> |
29 | #include "cache-tauros3.h" | 32 | #include "cache-tauros3.h" |
@@ -639,7 +642,24 @@ static void l2c310_resume(void) | |||
639 | L310_POWER_CTRL); | 642 | L310_POWER_CTRL); |
640 | 643 | ||
641 | l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); | 644 | l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); |
645 | |||
646 | /* Re-enable full-line-of-zeros for Cortex-A9 */ | ||
647 | if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO) | ||
648 | set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); | ||
649 | } | ||
650 | } | ||
651 | |||
652 | static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, void *data) | ||
653 | { | ||
654 | switch (act & ~CPU_TASKS_FROZEN) { | ||
655 | case CPU_STARTING: | ||
656 | set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); | ||
657 | break; | ||
658 | case CPU_DYING: | ||
659 | set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1))); | ||
660 | break; | ||
642 | } | 661 | } |
662 | return NOTIFY_OK; | ||
643 | } | 663 | } |
644 | 664 | ||
645 | static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) | 665 | static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) |
@@ -657,6 +677,36 @@ static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) | |||
657 | } | 677 | } |
658 | } | 678 | } |
659 | 679 | ||
680 | if (cortex_a9) { | ||
681 | u32 aux_cur = readl_relaxed(base + L2X0_AUX_CTRL); | ||
682 | u32 acr = get_auxcr(); | ||
683 | |||
684 | pr_debug("Cortex-A9 ACR=0x%08x\n", acr); | ||
685 | |||
686 | if (acr & BIT(3) && !(aux_cur & L310_AUX_CTRL_FULL_LINE_ZERO)) | ||
687 | pr_err("L2C-310: full line of zeros enabled in Cortex-A9 but not L2C-310 - invalid\n"); | ||
688 | |||
689 | if (aux & L310_AUX_CTRL_FULL_LINE_ZERO && !(acr & BIT(3))) | ||
690 | pr_err("L2C-310: enabling full line of zeros but not enabled in Cortex-A9\n"); | ||
691 | |||
692 | if (!(aux & L310_AUX_CTRL_FULL_LINE_ZERO) && !outer_cache.write_sec) { | ||
693 | aux |= L310_AUX_CTRL_FULL_LINE_ZERO; | ||
694 | pr_info("L2C-310 full line of zeros enabled for Cortex-A9\n"); | ||
695 | } | ||
696 | } else if (aux & (L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP)) { | ||
697 | pr_err("L2C-310: disabling Cortex-A9 specific feature bits\n"); | ||
698 | aux &= ~(L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP); | ||
699 | } | ||
700 | |||
701 | if (aux & (L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH)) { | ||
702 | u32 prefetch = readl_relaxed(base + L310_PREFETCH_CTRL); | ||
703 | |||
704 | pr_info("L2C-310 %s%s prefetch enabled, offset %u lines\n", | ||
705 | aux & L310_AUX_CTRL_INSTR_PREFETCH ? "I" : "", | ||
706 | aux & L310_AUX_CTRL_DATA_PREFETCH ? "D" : "", | ||
707 | 1 + (prefetch & L310_PREFETCH_CTRL_OFFSET_MASK)); | ||
708 | } | ||
709 | |||
660 | /* r3p0 or later has power control register */ | 710 | /* r3p0 or later has power control register */ |
661 | if (rev >= L310_CACHE_ID_RTL_R3P0) { | 711 | if (rev >= L310_CACHE_ID_RTL_R3P0) { |
662 | u32 power_ctrl; | 712 | u32 power_ctrl; |
@@ -677,6 +727,11 @@ static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) | |||
677 | aux |= L310_AUX_CTRL_NS_LOCKDOWN; | 727 | aux |= L310_AUX_CTRL_NS_LOCKDOWN; |
678 | 728 | ||
679 | l2c_enable(base, aux, num_lock); | 729 | l2c_enable(base, aux, num_lock); |
730 | |||
731 | if (aux & L310_AUX_CTRL_FULL_LINE_ZERO) { | ||
732 | set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); | ||
733 | cpu_notifier(l2c310_cpu_enable_flz, 0); | ||
734 | } | ||
680 | } | 735 | } |
681 | 736 | ||
682 | static void __init l2c310_fixup(void __iomem *base, u32 cache_id, | 737 | static void __init l2c310_fixup(void __iomem *base, u32 cache_id, |
@@ -732,6 +787,18 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, | |||
732 | } | 787 | } |
733 | } | 788 | } |
734 | 789 | ||
790 | static void l2c310_disable(void) | ||
791 | { | ||
792 | /* | ||
793 | * If full-line-of-zeros is enabled, we must first disable it in the | ||
794 | * Cortex-A9 auxiliary control register before disabling the L2 cache. | ||
795 | */ | ||
796 | if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO) | ||
797 | set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1))); | ||
798 | |||
799 | l2c_disable(); | ||
800 | } | ||
801 | |||
735 | static const struct l2c_init_data l2c310_init_fns __initconst = { | 802 | static const struct l2c_init_data l2c310_init_fns __initconst = { |
736 | .type = "L2C-310", | 803 | .type = "L2C-310", |
737 | .way_size_0 = SZ_8K, | 804 | .way_size_0 = SZ_8K, |
@@ -744,7 +811,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { | |||
744 | .clean_range = l2c210_clean_range, | 811 | .clean_range = l2c210_clean_range, |
745 | .flush_range = l2c210_flush_range, | 812 | .flush_range = l2c210_flush_range, |
746 | .flush_all = l2c210_flush_all, | 813 | .flush_all = l2c210_flush_all, |
747 | .disable = l2c_disable, | 814 | .disable = l2c310_disable, |
748 | .sync = l2c210_sync, | 815 | .sync = l2c210_sync, |
749 | .resume = l2c310_resume, | 816 | .resume = l2c310_resume, |
750 | }, | 817 | }, |
@@ -995,7 +1062,7 @@ static const struct l2c_init_data of_l2c310_data __initconst = { | |||
995 | .clean_range = l2c210_clean_range, | 1062 | .clean_range = l2c210_clean_range, |
996 | .flush_range = l2c210_flush_range, | 1063 | .flush_range = l2c210_flush_range, |
997 | .flush_all = l2c210_flush_all, | 1064 | .flush_all = l2c210_flush_all, |
998 | .disable = l2c_disable, | 1065 | .disable = l2c310_disable, |
999 | .sync = l2c210_sync, | 1066 | .sync = l2c210_sync, |
1000 | .resume = l2c310_resume, | 1067 | .resume = l2c310_resume, |
1001 | }, | 1068 | }, |
@@ -1342,7 +1409,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { | |||
1342 | .clean_range = bcm_clean_range, | 1409 | .clean_range = bcm_clean_range, |
1343 | .flush_range = bcm_flush_range, | 1410 | .flush_range = bcm_flush_range, |
1344 | .flush_all = l2c210_flush_all, | 1411 | .flush_all = l2c210_flush_all, |
1345 | .disable = l2c_disable, | 1412 | .disable = l2c310_disable, |
1346 | .sync = l2c210_sync, | 1413 | .sync = l2c210_sync, |
1347 | .resume = l2c310_resume, | 1414 | .resume = l2c310_resume, |
1348 | }, | 1415 | }, |