1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2016 Freescale Semiconductor, Inc. 4 * 5 * Peng Fan <peng.fan@nxp.com> 6 */ 7 8 #include <arm32.h> 9 #include <io.h> 10 #include <kernel/boot.h> 11 #include <kernel/tz_ssvce_def.h> 12 #include <kernel/tz_ssvce_pl310.h> 13 #include <mm/core_memprot.h> 14 #include <mm/core_mmu.h> 15 #include <sm/optee_smc.h> 16 #include <platform_config.h> 17 #include <stdint.h> 18 #include "imx_pl310.h" 19 20 #define PL310_AUX_CTRL_FLZW BIT(0) 21 #define PL310_DEBUG_CTRL_DISABLE_WRITEBACK BIT(1) 22 #define PL310_DEBUG_CTRL_DISABLE_LINEFILL BIT(0) 23 #define PL310_PREFETCH_DOUBLE_LINEFILL BIT(30) 24 25 register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); 26 27 void arm_cl2_config(vaddr_t pl310_base) 28 { 29 uint32_t val = 0; 30 uint32_t id = 0; 31 32 /* Disable PL310 */ 33 io_write32(pl310_base + PL310_CTRL, 0); 34 35 io_write32(pl310_base + PL310_TAG_RAM_CTRL, PL310_TAG_RAM_CTRL_INIT); 36 io_write32(pl310_base + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT); 37 io_write32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); 38 /* 39 * The L2 cache controller(PL310) version on the i.MX6D/Q 40 * is r3p1-50rel0 41 * The L2 cache controller(PL310) version on the 42 * i.MX6DL/SOLO/SL/SX/DQP is r3p2. 43 * 44 * According to ARM PL310 errata: 752271 45 * ID: 752271: Double linefill feature can cause data corruption 46 * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 47 * Workaround: The only workaround to this erratum is to disable the 48 * double linefill feature. This is the default behavior. 49 */ 50 val = PL310_PREFETCH_CTRL_INIT; 51 52 id = io_read32(pl310_base + PL310_CACHE_ID); 53 54 if (((id & PL310_CACHE_ID_PART_MASK) == PL310_CACHE_ID_PART_L310) && 55 ((id & PL310_CACHE_ID_RTL_MASK) < PL310_CACHE_ID_RTL_R3P2)) 56 val &= ~PL310_PREFETCH_DOUBLE_LINEFILL; 57 58 io_write32(pl310_base + PL310_PREFETCH_CTRL, val); 59 60 io_write32(pl310_base + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); 61 62 /* invalidate all cache ways */ 63 arm_cl2_invbyway(pl310_base); 64 } 65 66 void arm_cl2_enable(vaddr_t pl310_base) 67 { 68 uint32_t val __maybe_unused; 69 70 /* Enable PL310 ctrl -> only set lsb bit */ 71 io_write32(pl310_base + PL310_CTRL, 1); 72 73 #ifndef CFG_PL310_SIP_PROTOCOL 74 /* if L2 FLZW enable, enable in L1 */ 75 val = io_read32(pl310_base + PL310_AUX_CTRL); 76 if (val & PL310_AUX_CTRL_FLZW) 77 write_actlr(read_actlr() | ACTLR_CA9_WFLZ); 78 #endif 79 } 80 81 vaddr_t pl310_base(void) 82 { 83 return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_SEC, 1); 84 } 85 86 #ifdef CFG_PL310_SIP_PROTOCOL 87 uint32_t pl310_enable(void) 88 { 89 vaddr_t base = pl310_base(); 90 91 arm_cl2_config(base); 92 arm_cl2_enable(base); 93 return OPTEE_SMC_RETURN_OK; 94 } 95 96 uint32_t pl310_disable(void) 97 { 98 EMSG("not implemented"); 99 return OPTEE_SMC_RETURN_ENOTAVAIL; 100 } 101 102 uint32_t pl310_enable_writeback(void) 103 { 104 vaddr_t base = pl310_base(); 105 106 io_write32(base + PL310_DEBUG_CTRL, 0); 107 return OPTEE_SMC_RETURN_OK; 108 } 109 110 uint32_t pl310_disable_writeback(void) 111 { 112 vaddr_t base = pl310_base(); 113 uint32_t val = PL310_DEBUG_CTRL_DISABLE_WRITEBACK | 114 PL310_DEBUG_CTRL_DISABLE_LINEFILL; 115 116 io_write32(base + PL310_DEBUG_CTRL, val); 117 return OPTEE_SMC_RETURN_OK; 118 } 119 120 uint32_t pl310_enable_wflz(void) 121 { 122 write_actlr(read_actlr() | ACTLR_CA9_WFLZ); 123 return OPTEE_SMC_RETURN_OK; 124 } 125 #endif 126