aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2014-03-18 17:40:01 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-05-29 19:50:41 -0400
commit8ef418c7178fa611d84e187bacb967880f6f5b69 (patch)
treec09538d68dd96ea3d6e99dc0e926dc3b3aaf1133 /arch
parent560be6136b3605ebbb8bd04b49b175c809d4e953 (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')
-rw-r--r--arch/arm/include/asm/hardware/cache-l2x0.h8
-rw-r--r--arch/arm/mm/cache-l2x0.c73
2 files changed, 78 insertions, 3 deletions
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index 84bbd31b8910..3a5ec1c25659 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -134,6 +134,14 @@
134 134
135#define L310_ADDR_FILTER_EN 1 135#define L310_ADDR_FILTER_EN 1
136 136
137#define L310_PREFETCH_CTRL_OFFSET_MASK 0x1f
138#define L310_PREFETCH_CTRL_DBL_LINEFILL_INCR BIT(23)
139#define L310_PREFETCH_CTRL_PREFETCH_DROP BIT(24)
140#define L310_PREFETCH_CTRL_DBL_LINEFILL_WRAP BIT(27)
141#define L310_PREFETCH_CTRL_DATA_PREFETCH BIT(28)
142#define L310_PREFETCH_CTRL_INSTR_PREFETCH BIT(29)
143#define L310_PREFETCH_CTRL_DBL_LINEFILL BIT(30)
144
137#define L2X0_CTRL_EN 1 145#define L2X0_CTRL_EN 1
138 146
139#define L2X0_WAY_SIZE_SHIFT 3 147#define L2X0_WAY_SIZE_SHIFT 3
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
652static 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
645static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) 665static 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
682static void __init l2c310_fixup(void __iomem *base, u32 cache_id, 737static 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
790static 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
735static const struct l2c_init_data l2c310_init_fns __initconst = { 802static 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 },