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