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 register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); 27 28 void arm_cl2_config(vaddr_t pl310_base) 29 { 30 uint32_t val = 0; 31 uint32_t id = 0; 32 33 /* Disable PL310 */ 34 io_write32(pl310_base + PL310_CTRL, 0); 35 36 io_write32(pl310_base + PL310_TAG_RAM_CTRL, PL310_TAG_RAM_CTRL_INIT); 37 io_write32(pl310_base + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT); 38 io_write32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); 39 /* 40 * The L2 cache controller(PL310) version on the i.MX6D/Q 41 * is r3p1-50rel0 42 * The L2 cache controller(PL310) version on the 43 * i.MX6DL/SOLO/SL/SX/DQP is r3p2. 44 * 45 * According to ARM PL310 errata: 752271 46 * ID: 752271: Double linefill feature can cause data corruption 47 * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 48 * Workaround: The only workaround to this erratum is to disable the 49 * double linefill feature. This is the default behavior. 50 */ 51 val = PL310_PREFETCH_CTRL_INIT; 52 53 id = io_read32(pl310_base + PL310_CACHE_ID); 54 55 if (((id & PL310_CACHE_ID_PART_MASK) == PL310_CACHE_ID_PART_L310) && 56 ((id & PL310_CACHE_ID_RTL_MASK) < PL310_CACHE_ID_RTL_R3P2)) 57 val &= ~PL310_PREFETCH_DOUBLE_LINEFILL; 58 59 io_write32(pl310_base + PL310_PREFETCH_CTRL, val); 60 61 io_write32(pl310_base + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); 62 63 /* invalidate all cache ways */ 64 arm_cl2_invbyway(pl310_base); 65 } 66 67 void arm_cl2_enable(vaddr_t pl310_base) 68 { 69 uint32_t val __maybe_unused; 70 71 /* Enable PL310 ctrl -> only set lsb bit */ 72 io_write32(pl310_base + PL310_CTRL, 1); 73 74 #ifndef CFG_PL310_SIP_PROTOCOL 75 /* if L2 FLZW enable, enable in L1 */ 76 val = io_read32(pl310_base + PL310_AUX_CTRL); 77 if (val & PL310_AUX_CTRL_FLZW) 78 write_actlr(read_actlr() | ACTLR_CA9_WFLZ); 79 #endif 80 } 81 82 vaddr_t pl310_base(void) 83 { 84 return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_SEC, 1); 85 } 86 87 vaddr_t pl310_nsbase(void) 88 { 89 return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_NSEC, 1); 90 } 91 92 #ifdef CFG_PL310_SIP_PROTOCOL 93 uint32_t pl310_enable(void) 94 { 95 vaddr_t base = pl310_base(); 96 97 arm_cl2_config(base); 98 arm_cl2_enable(base); 99 return OPTEE_SMC_RETURN_OK; 100 } 101 102 uint32_t pl310_disable(void) 103 { 104 EMSG("not implemented"); 105 return OPTEE_SMC_RETURN_ENOTAVAIL; 106 } 107 108 uint32_t pl310_enable_writeback(void) 109 { 110 vaddr_t base = pl310_base(); 111 112 io_write32(base + PL310_DEBUG_CTRL, 0); 113 return OPTEE_SMC_RETURN_OK; 114 } 115 116 uint32_t pl310_disable_writeback(void) 117 { 118 vaddr_t base = pl310_base(); 119 uint32_t val = PL310_DEBUG_CTRL_DISABLE_WRITEBACK | 120 PL310_DEBUG_CTRL_DISABLE_LINEFILL; 121 122 io_write32(base + PL310_DEBUG_CTRL, val); 123 return OPTEE_SMC_RETURN_OK; 124 } 125 126 uint32_t pl310_enable_wflz(void) 127 { 128 write_actlr(read_actlr() | ACTLR_CA9_WFLZ); 129 return OPTEE_SMC_RETURN_OK; 130 } 131 #endif 132