cache.c 3.9 KB

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