1 /* 2 * Copyright (C) 2018 Marvell International Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * https://spdx.org/licenses 6 */ 7 8 /* LLC driver is the Last Level Cache (L3C) driver 9 * for Marvell SoCs in AP806, AP807, and AP810 10 */ 11 12 #include <assert.h> 13 14 #include <arch_helpers.h> 15 #include <drivers/marvell/cache_llc.h> 16 #include <drivers/marvell/ccu.h> 17 #include <lib/mmio.h> 18 19 #include <mvebu_def.h> 20 21 #define CCU_HTC_CR(ap_index) (MVEBU_CCU_BASE(ap_index) + 0x200) 22 #define CCU_SET_POC_OFFSET 5 23 24 extern void ca72_l2_enable_unique_clean(void); 25 26 void llc_cache_sync(int ap_index) 27 { 28 mmio_write_32(LLC_SYNC(ap_index), 0); 29 /* Atomic write, no need to wait */ 30 } 31 32 void llc_flush_all(int ap_index) 33 { 34 mmio_write_32(LLC_CLEAN_INV_WAY(ap_index), LLC_ALL_WAYS_MASK); 35 llc_cache_sync(ap_index); 36 } 37 38 void llc_clean_all(int ap_index) 39 { 40 mmio_write_32(LLC_CLEAN_WAY(ap_index), LLC_ALL_WAYS_MASK); 41 llc_cache_sync(ap_index); 42 } 43 44 void llc_inv_all(int ap_index) 45 { 46 mmio_write_32(LLC_INV_WAY(ap_index), LLC_ALL_WAYS_MASK); 47 llc_cache_sync(ap_index); 48 } 49 50 void llc_disable(int ap_index) 51 { 52 llc_flush_all(ap_index); 53 mmio_write_32(LLC_CTRL(ap_index), 0); 54 dsbishst(); 55 } 56 57 void llc_enable(int ap_index, int excl_mode) 58 { 59 uint32_t val; 60 61 dsbsy(); 62 llc_inv_all(ap_index); 63 dsbsy(); 64 65 val = LLC_CTRL_EN; 66 if (excl_mode) 67 val |= LLC_EXCLUSIVE_EN; 68 69 mmio_write_32(LLC_CTRL(ap_index), val); 70 dsbsy(); 71 } 72 73 int llc_is_exclusive(int ap_index) 74 { 75 uint32_t reg; 76 77 reg = mmio_read_32(LLC_CTRL(ap_index)); 78 79 if ((reg & (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) == 80 (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) 81 return 1; 82 83 return 0; 84 } 85 86 void llc_runtime_enable(int ap_index) 87 { 88 uint32_t reg; 89 90 reg = mmio_read_32(LLC_CTRL(ap_index)); 91 if (reg & LLC_CTRL_EN) 92 return; 93 94 INFO("Enabling LLC\n"); 95 96 /* 97 * Enable L2 UniqueClean evictions with data 98 * Note: this configuration assumes that LLC is configured 99 * in exclusive mode. 100 * Later on in the code this assumption will be validated 101 */ 102 ca72_l2_enable_unique_clean(); 103 llc_enable(ap_index, 1); 104 105 /* Set point of coherency to DDR. 106 * This is required by units which have SW cache coherency 107 */ 108 reg = mmio_read_32(CCU_HTC_CR(ap_index)); 109 reg |= (0x1 << CCU_SET_POC_OFFSET); 110 mmio_write_32(CCU_HTC_CR(ap_index), reg); 111 } 112 113 #if LLC_SRAM 114 int llc_sram_enable(int ap_index, int size) 115 { 116 uint32_t tc, way, ways_to_allocate; 117 uint32_t way_addr; 118 119 if ((size <= 0) || (size > LLC_SIZE) || (size % LLC_WAY_SIZE)) 120 return -1; 121 122 llc_enable(ap_index, 1); 123 llc_inv_all(ap_index); 124 125 ways_to_allocate = size / LLC_WAY_SIZE; 126 127 /* Lockdown all available ways for all traffic classes */ 128 for (tc = 0; tc < LLC_TC_NUM; tc++) 129 mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_ALL_WAYS_MASK); 130 131 /* Clear the high bits of SRAM address */ 132 mmio_write_32(LLC_BANKED_MNT_AHR(ap_index), 0); 133 134 way_addr = PLAT_MARVELL_TRUSTED_RAM_BASE; 135 for (way = 0; way < ways_to_allocate; way++) { 136 /* Trigger allocation block command */ 137 mmio_write_32(LLC_BLK_ALOC(ap_index), 138 LLC_BLK_ALOC_BASE_ADDR(way_addr) | 139 LLC_BLK_ALOC_WAY_DATA_SET | 140 LLC_BLK_ALOC_WAY_ID(way)); 141 way_addr += LLC_WAY_SIZE; 142 } 143 return 0; 144 } 145 146 void llc_sram_disable(int ap_index) 147 { 148 uint32_t tc; 149 150 /* Disable the line lockings */ 151 for (tc = 0; tc < LLC_TC_NUM; tc++) 152 mmio_write_32(LLC_TCN_LOCK(ap_index, tc), 0); 153 154 /* Invalidate all ways */ 155 llc_inv_all(ap_index); 156 } 157 158 int llc_sram_test(int ap_index, int size, char *msg) 159 { 160 uintptr_t addr, end_addr; 161 uint32_t data = 0; 162 163 if ((size <= 0) || (size > LLC_SIZE)) 164 return -1; 165 166 INFO("=== LLC SRAM WRITE test %s\n", msg); 167 for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE, 168 end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size; 169 addr < end_addr; addr += 4) { 170 mmio_write_32(addr, addr); 171 } 172 INFO("=== LLC SRAM WRITE test %s PASSED\n", msg); 173 INFO("=== LLC SRAM READ test %s\n", msg); 174 for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE, 175 end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size; 176 addr < end_addr; addr += 4) { 177 data = mmio_read_32(addr); 178 if (data != addr) { 179 INFO("=== LLC SRAM READ test %s FAILED @ 0x%08lx)\n", 180 msg, addr); 181 return -1; 182 } 183 } 184 INFO("=== LLC SRAM READ test %s PASSED (last read = 0x%08x)\n", 185 msg, data); 186 return 0; 187 } 188 189 #endif /* LLC_SRAM */ 190