Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: l2c: trial at enabling some Cortex-A9 optimisations

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

+78 -3
+8
arch/arm/include/asm/hardware/cache-l2x0.h
··· 134 134 135 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 145 #define L2X0_CTRL_EN 1 138 146 139 147 #define L2X0_WAY_SIZE_SHIFT 3
+70 -3
arch/arm/mm/cache-l2x0.c
··· 16 16 * along with this program; if not, write to the Free Software 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 + #include <linux/cpu.h> 19 20 #include <linux/err.h> 20 21 #include <linux/init.h> 22 + #include <linux/smp.h> 21 23 #include <linux/spinlock.h> 22 24 #include <linux/io.h> 23 25 #include <linux/of.h> 24 26 #include <linux/of_address.h> 25 27 26 28 #include <asm/cacheflush.h> 29 + #include <asm/cp15.h> 27 30 #include <asm/cputype.h> 28 31 #include <asm/hardware/cache-l2x0.h> 29 32 #include "cache-tauros3.h" ··· 642 639 L310_POWER_CTRL); 643 640 644 641 l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); 642 + 643 + /* Re-enable full-line-of-zeros for Cortex-A9 */ 644 + if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO) 645 + set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); 645 646 } 647 + } 648 + 649 + static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, void *data) 650 + { 651 + switch (act & ~CPU_TASKS_FROZEN) { 652 + case CPU_STARTING: 653 + set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); 654 + break; 655 + case CPU_DYING: 656 + set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1))); 657 + break; 658 + } 659 + return NOTIFY_OK; 646 660 } 647 661 648 662 static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) ··· 675 655 pr_warn("L2C-310 early BRESP only supported with Cortex-A9\n"); 676 656 aux &= ~L310_AUX_CTRL_EARLY_BRESP; 677 657 } 658 + } 659 + 660 + if (cortex_a9) { 661 + u32 aux_cur = readl_relaxed(base + L2X0_AUX_CTRL); 662 + u32 acr = get_auxcr(); 663 + 664 + pr_debug("Cortex-A9 ACR=0x%08x\n", acr); 665 + 666 + if (acr & BIT(3) && !(aux_cur & L310_AUX_CTRL_FULL_LINE_ZERO)) 667 + pr_err("L2C-310: full line of zeros enabled in Cortex-A9 but not L2C-310 - invalid\n"); 668 + 669 + if (aux & L310_AUX_CTRL_FULL_LINE_ZERO && !(acr & BIT(3))) 670 + pr_err("L2C-310: enabling full line of zeros but not enabled in Cortex-A9\n"); 671 + 672 + if (!(aux & L310_AUX_CTRL_FULL_LINE_ZERO) && !outer_cache.write_sec) { 673 + aux |= L310_AUX_CTRL_FULL_LINE_ZERO; 674 + pr_info("L2C-310 full line of zeros enabled for Cortex-A9\n"); 675 + } 676 + } else if (aux & (L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP)) { 677 + pr_err("L2C-310: disabling Cortex-A9 specific feature bits\n"); 678 + aux &= ~(L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP); 679 + } 680 + 681 + if (aux & (L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH)) { 682 + u32 prefetch = readl_relaxed(base + L310_PREFETCH_CTRL); 683 + 684 + pr_info("L2C-310 %s%s prefetch enabled, offset %u lines\n", 685 + aux & L310_AUX_CTRL_INSTR_PREFETCH ? "I" : "", 686 + aux & L310_AUX_CTRL_DATA_PREFETCH ? "D" : "", 687 + 1 + (prefetch & L310_PREFETCH_CTRL_OFFSET_MASK)); 678 688 } 679 689 680 690 /* r3p0 or later has power control register */ ··· 727 677 aux |= L310_AUX_CTRL_NS_LOCKDOWN; 728 678 729 679 l2c_enable(base, aux, num_lock); 680 + 681 + if (aux & L310_AUX_CTRL_FULL_LINE_ZERO) { 682 + set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); 683 + cpu_notifier(l2c310_cpu_enable_flz, 0); 684 + } 730 685 } 731 686 732 687 static void __init l2c310_fixup(void __iomem *base, u32 cache_id, ··· 787 732 } 788 733 } 789 734 735 + static void l2c310_disable(void) 736 + { 737 + /* 738 + * If full-line-of-zeros is enabled, we must first disable it in the 739 + * Cortex-A9 auxiliary control register before disabling the L2 cache. 740 + */ 741 + if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO) 742 + set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1))); 743 + 744 + l2c_disable(); 745 + } 746 + 790 747 static const struct l2c_init_data l2c310_init_fns __initconst = { 791 748 .type = "L2C-310", 792 749 .way_size_0 = SZ_8K, ··· 811 744 .clean_range = l2c210_clean_range, 812 745 .flush_range = l2c210_flush_range, 813 746 .flush_all = l2c210_flush_all, 814 - .disable = l2c_disable, 747 + .disable = l2c310_disable, 815 748 .sync = l2c210_sync, 816 749 .resume = l2c310_resume, 817 750 }, ··· 1062 995 .clean_range = l2c210_clean_range, 1063 996 .flush_range = l2c210_flush_range, 1064 997 .flush_all = l2c210_flush_all, 1065 - .disable = l2c_disable, 998 + .disable = l2c310_disable, 1066 999 .sync = l2c210_sync, 1067 1000 .resume = l2c310_resume, 1068 1001 }, ··· 1409 1342 .clean_range = bcm_clean_range, 1410 1343 .flush_range = bcm_flush_range, 1411 1344 .flush_all = l2c210_flush_all, 1412 - .disable = l2c_disable, 1345 + .disable = l2c310_disable, 1413 1346 .sync = l2c210_sync, 1414 1347 .resume = l2c310_resume, 1415 1348 },