1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2015 Freescale Semiconductor, Inc. 4 */ 5 6#include <common.h> 7#include <cpu_func.h> 8#include <asm/armv7.h> 9#include <asm/cache.h> 10#include <asm/pl310.h> 11#include <asm/io.h> 12#include <asm/mach-imx/sys_proto.h> 13 14void enable_ca7_smp(void) 15{ 16 u32 val; 17 18 /* Read MIDR */ 19 asm volatile ("mrc p15, 0, %0, c0, c0, 0\n\t" : "=r"(val)); 20 val = (val >> 4); 21 val &= 0xf; 22 23 /* Only set the SMP for Cortex A7 */ 24 if (val == 0x7) { 25 /* Read auxiliary control register */ 26 asm volatile ("mrc p15, 0, %0, c1, c0, 1\n\t" : "=r"(val)); 27 28 if (val & (1 << 6)) 29 return; 30 31 /* Enable SMP */ 32 val |= (1 << 6); 33 34 /* Write auxiliary control register */ 35 asm volatile ("mcr p15, 0, %0, c1, c0, 1\n\t" : : "r"(val)); 36 37 DSB; 38 ISB; 39 } 40} 41 42#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) 43void enable_caches(void) 44{ 45#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) 46 enum dcache_option option = DCACHE_WRITETHROUGH; 47#else 48 enum dcache_option option = DCACHE_WRITEBACK; 49#endif 50 /* Avoid random hang when download by usb */ 51 invalidate_dcache_all(); 52 53 /* Set ACTLR.SMP bit for Cortex-A7 */ 54 enable_ca7_smp(); 55 56 /* Enable D-cache. I-cache is already enabled in start.S */ 57 dcache_enable(); 58 59 /* Enable caching on OCRAM and ROM */ 60 mmu_set_region_dcache_behaviour(ROMCP_ARB_BASE_ADDR, 61 ROMCP_ARB_END_ADDR, 62 option); 63 mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, 64 IRAM_SIZE, 65 option); 66} 67#else 68void enable_caches(void) 69{ 70 /* 71 * Set ACTLR.SMP bit for Cortex-A7, even if the caches are 72 * disabled by u-boot 73 */ 74 enable_ca7_smp(); 75 76 puts("WARNING: Caches not enabled\n"); 77} 78#endif 79 80#ifndef CONFIG_SYS_L2CACHE_OFF 81#ifdef CONFIG_SYS_L2_PL310 82#define IOMUXC_GPR11_L2CACHE_AS_OCRAM 0x00000002 83void v7_outer_cache_enable(void) 84{ 85 struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE; 86 struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; 87 unsigned int val, cache_id; 88 89 90 /* 91 * Must disable the L2 before changing the latency parameters 92 * and auxiliary control register. 93 */ 94 clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); 95 96 /* 97 * Set bit 22 in the auxiliary control register. If this bit 98 * is cleared, PL310 treats Normal Shared Non-cacheable 99 * accesses as Cacheable no-allocate. 100 */ 101 setbits_le32(&pl310->pl310_aux_ctrl, L310_SHARED_ATT_OVERRIDE_ENABLE); 102 103 if (is_mx6sl() || is_mx6sll()) { 104 val = readl(&iomux->gpr[11]); 105 if (val & IOMUXC_GPR11_L2CACHE_AS_OCRAM) { 106 /* L2 cache configured as OCRAM, reset it */ 107 val &= ~IOMUXC_GPR11_L2CACHE_AS_OCRAM; 108 writel(val, &iomux->gpr[11]); 109 } 110 } 111 112 writel(0x132, &pl310->pl310_tag_latency_ctrl); 113 writel(0x132, &pl310->pl310_data_latency_ctrl); 114 115 val = readl(&pl310->pl310_prefetch_ctrl); 116 117 /* Turn on the L2 I/D prefetch, double linefill */ 118 /* Set prefetch offset with any value except 23 as per errata 765569 */ 119 val |= 0x7000000f; 120 121 /* 122 * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0 123 * The L2 cache controller(PL310) version on the i.MX6DL/SOLO/SL/SX/DQP 124 * is r3p2. 125 * But according to ARM PL310 errata: 752271 126 * ID: 752271: Double linefill feature can cause data corruption 127 * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 128 * Workaround: The only workaround to this erratum is to disable the 129 * double linefill feature. This is the default behavior. 130 */ 131 cache_id = readl(&pl310->pl310_cache_id); 132 if (((cache_id & L2X0_CACHE_ID_PART_MASK) == L2X0_CACHE_ID_PART_L310) 133 && ((cache_id & L2X0_CACHE_ID_RTL_MASK) < L2X0_CACHE_ID_RTL_R3P2)) 134 val &= ~(1 << 30); 135 writel(val, &pl310->pl310_prefetch_ctrl); 136 137 val = readl(&pl310->pl310_power_ctrl); 138 val |= L2X0_DYNAMIC_CLK_GATING_EN; 139 val |= L2X0_STNDBY_MODE_EN; 140 writel(val, &pl310->pl310_power_ctrl); 141 142 setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); 143} 144 145void v7_outer_cache_disable(void) 146{ 147 struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE; 148 149 clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); 150} 151#endif /* !CONFIG_SYS_L2_PL310 */ 152#endif /* !CONFIG_SYS_L2CACHE_OFF */ 153