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