1152b0e47SKonstantin Porotchkin /* 2152b0e47SKonstantin Porotchkin * Copyright (C) 2018 Marvell International Ltd. 3152b0e47SKonstantin Porotchkin * 4152b0e47SKonstantin Porotchkin * SPDX-License-Identifier: BSD-3-Clause 5152b0e47SKonstantin Porotchkin * https://spdx.org/licenses 6152b0e47SKonstantin Porotchkin */ 7152b0e47SKonstantin Porotchkin 8152b0e47SKonstantin Porotchkin /* LLC driver is the Last Level Cache (L3C) driver 9152b0e47SKonstantin Porotchkin * for Marvell SoCs in AP806, AP807, and AP810 10152b0e47SKonstantin Porotchkin */ 11152b0e47SKonstantin Porotchkin 12152b0e47SKonstantin Porotchkin #include <assert.h> 1309d40e0eSAntonio Nino Diaz 1409d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1509d40e0eSAntonio Nino Diaz #include <drivers/marvell/cache_llc.h> 1609d40e0eSAntonio Nino Diaz #include <drivers/marvell/ccu.h> 1709d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 1809d40e0eSAntonio Nino Diaz 19152b0e47SKonstantin Porotchkin #include <mvebu_def.h> 20152b0e47SKonstantin Porotchkin 21152b0e47SKonstantin Porotchkin #define CCU_HTC_CR(ap_index) (MVEBU_CCU_BASE(ap_index) + 0x200) 22152b0e47SKonstantin Porotchkin #define CCU_SET_POC_OFFSET 5 23152b0e47SKonstantin Porotchkin 24152b0e47SKonstantin Porotchkin extern void ca72_l2_enable_unique_clean(void); 25152b0e47SKonstantin Porotchkin 26152b0e47SKonstantin Porotchkin void llc_cache_sync(int ap_index) 27152b0e47SKonstantin Porotchkin { 28152b0e47SKonstantin Porotchkin mmio_write_32(LLC_SYNC(ap_index), 0); 29152b0e47SKonstantin Porotchkin /* Atomic write, no need to wait */ 30152b0e47SKonstantin Porotchkin } 31152b0e47SKonstantin Porotchkin 32152b0e47SKonstantin Porotchkin void llc_flush_all(int ap_index) 33152b0e47SKonstantin Porotchkin { 34772aa5baSKonstantin Porotchkin mmio_write_32(LLC_CLEAN_INV_WAY(ap_index), LLC_ALL_WAYS_MASK); 35152b0e47SKonstantin Porotchkin llc_cache_sync(ap_index); 36152b0e47SKonstantin Porotchkin } 37152b0e47SKonstantin Porotchkin 38152b0e47SKonstantin Porotchkin void llc_clean_all(int ap_index) 39152b0e47SKonstantin Porotchkin { 40772aa5baSKonstantin Porotchkin mmio_write_32(LLC_CLEAN_WAY(ap_index), LLC_ALL_WAYS_MASK); 41152b0e47SKonstantin Porotchkin llc_cache_sync(ap_index); 42152b0e47SKonstantin Porotchkin } 43152b0e47SKonstantin Porotchkin 44152b0e47SKonstantin Porotchkin void llc_inv_all(int ap_index) 45152b0e47SKonstantin Porotchkin { 46772aa5baSKonstantin Porotchkin mmio_write_32(LLC_INV_WAY(ap_index), LLC_ALL_WAYS_MASK); 47152b0e47SKonstantin Porotchkin llc_cache_sync(ap_index); 48152b0e47SKonstantin Porotchkin } 49152b0e47SKonstantin Porotchkin 50152b0e47SKonstantin Porotchkin void llc_disable(int ap_index) 51152b0e47SKonstantin Porotchkin { 52152b0e47SKonstantin Porotchkin llc_flush_all(ap_index); 53152b0e47SKonstantin Porotchkin mmio_write_32(LLC_CTRL(ap_index), 0); 54152b0e47SKonstantin Porotchkin dsbishst(); 55152b0e47SKonstantin Porotchkin } 56152b0e47SKonstantin Porotchkin 57152b0e47SKonstantin Porotchkin void llc_enable(int ap_index, int excl_mode) 58152b0e47SKonstantin Porotchkin { 59152b0e47SKonstantin Porotchkin uint32_t val; 60152b0e47SKonstantin Porotchkin 61152b0e47SKonstantin Porotchkin dsbsy(); 62152b0e47SKonstantin Porotchkin llc_inv_all(ap_index); 63152b0e47SKonstantin Porotchkin dsbsy(); 64152b0e47SKonstantin Porotchkin 65152b0e47SKonstantin Porotchkin val = LLC_CTRL_EN; 66152b0e47SKonstantin Porotchkin if (excl_mode) 67152b0e47SKonstantin Porotchkin val |= LLC_EXCLUSIVE_EN; 68152b0e47SKonstantin Porotchkin 69152b0e47SKonstantin Porotchkin mmio_write_32(LLC_CTRL(ap_index), val); 70152b0e47SKonstantin Porotchkin dsbsy(); 71152b0e47SKonstantin Porotchkin } 72152b0e47SKonstantin Porotchkin 73152b0e47SKonstantin Porotchkin int llc_is_exclusive(int ap_index) 74152b0e47SKonstantin Porotchkin { 75152b0e47SKonstantin Porotchkin uint32_t reg; 76152b0e47SKonstantin Porotchkin 77152b0e47SKonstantin Porotchkin reg = mmio_read_32(LLC_CTRL(ap_index)); 78152b0e47SKonstantin Porotchkin 79152b0e47SKonstantin Porotchkin if ((reg & (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) == 80152b0e47SKonstantin Porotchkin (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) 81152b0e47SKonstantin Porotchkin return 1; 82152b0e47SKonstantin Porotchkin 83152b0e47SKonstantin Porotchkin return 0; 84152b0e47SKonstantin Porotchkin } 85152b0e47SKonstantin Porotchkin 86152b0e47SKonstantin Porotchkin void llc_runtime_enable(int ap_index) 87152b0e47SKonstantin Porotchkin { 88152b0e47SKonstantin Porotchkin uint32_t reg; 89152b0e47SKonstantin Porotchkin 90152b0e47SKonstantin Porotchkin reg = mmio_read_32(LLC_CTRL(ap_index)); 91152b0e47SKonstantin Porotchkin if (reg & LLC_CTRL_EN) 92152b0e47SKonstantin Porotchkin return; 93152b0e47SKonstantin Porotchkin 94152b0e47SKonstantin Porotchkin INFO("Enabling LLC\n"); 95152b0e47SKonstantin Porotchkin 96152b0e47SKonstantin Porotchkin /* 97152b0e47SKonstantin Porotchkin * Enable L2 UniqueClean evictions with data 98152b0e47SKonstantin Porotchkin * Note: this configuration assumes that LLC is configured 99152b0e47SKonstantin Porotchkin * in exclusive mode. 100152b0e47SKonstantin Porotchkin * Later on in the code this assumption will be validated 101152b0e47SKonstantin Porotchkin */ 102152b0e47SKonstantin Porotchkin ca72_l2_enable_unique_clean(); 103152b0e47SKonstantin Porotchkin llc_enable(ap_index, 1); 104152b0e47SKonstantin Porotchkin 105152b0e47SKonstantin Porotchkin /* Set point of coherency to DDR. 106152b0e47SKonstantin Porotchkin * This is required by units which have SW cache coherency 107152b0e47SKonstantin Porotchkin */ 108152b0e47SKonstantin Porotchkin reg = mmio_read_32(CCU_HTC_CR(ap_index)); 109152b0e47SKonstantin Porotchkin reg |= (0x1 << CCU_SET_POC_OFFSET); 110152b0e47SKonstantin Porotchkin mmio_write_32(CCU_HTC_CR(ap_index), reg); 111152b0e47SKonstantin Porotchkin } 1125a40d70fSKonstantin Porotchkin 1135a40d70fSKonstantin Porotchkin #if LLC_SRAM 114*506ff4c0SKonstantin Porotchkin int llc_sram_enable(int ap_index, int size) 1155a40d70fSKonstantin Porotchkin { 116*506ff4c0SKonstantin Porotchkin uint32_t tc, way, ways_to_allocate; 1175a40d70fSKonstantin Porotchkin uint32_t way_addr; 1185a40d70fSKonstantin Porotchkin 119*506ff4c0SKonstantin Porotchkin if ((size <= 0) || (size > LLC_SIZE) || (size % LLC_WAY_SIZE)) 120*506ff4c0SKonstantin Porotchkin return -1; 121*506ff4c0SKonstantin Porotchkin 122*506ff4c0SKonstantin Porotchkin llc_enable(ap_index, 1); 123*506ff4c0SKonstantin Porotchkin llc_inv_all(ap_index); 124*506ff4c0SKonstantin Porotchkin 125*506ff4c0SKonstantin Porotchkin ways_to_allocate = size / LLC_WAY_SIZE; 126*506ff4c0SKonstantin Porotchkin 1275a40d70fSKonstantin Porotchkin /* Lockdown all available ways for all traffic classes */ 1285a40d70fSKonstantin Porotchkin for (tc = 0; tc < LLC_TC_NUM; tc++) 129*506ff4c0SKonstantin Porotchkin mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_ALL_WAYS_MASK); 1305a40d70fSKonstantin Porotchkin 1315a40d70fSKonstantin Porotchkin /* Clear the high bits of SRAM address */ 1325a40d70fSKonstantin Porotchkin mmio_write_32(LLC_BANKED_MNT_AHR(ap_index), 0); 1335a40d70fSKonstantin Porotchkin 1345a40d70fSKonstantin Porotchkin way_addr = PLAT_MARVELL_TRUSTED_RAM_BASE; 135*506ff4c0SKonstantin Porotchkin for (way = 0; way < ways_to_allocate; way++) { 1365a40d70fSKonstantin Porotchkin /* Trigger allocation block command */ 1375a40d70fSKonstantin Porotchkin mmio_write_32(LLC_BLK_ALOC(ap_index), 1385a40d70fSKonstantin Porotchkin LLC_BLK_ALOC_BASE_ADDR(way_addr) | 139*506ff4c0SKonstantin Porotchkin LLC_BLK_ALOC_WAY_DATA_SET | 1405a40d70fSKonstantin Porotchkin LLC_BLK_ALOC_WAY_ID(way)); 1415a40d70fSKonstantin Porotchkin way_addr += LLC_WAY_SIZE; 1425a40d70fSKonstantin Porotchkin } 143*506ff4c0SKonstantin Porotchkin return 0; 1445a40d70fSKonstantin Porotchkin } 1455a40d70fSKonstantin Porotchkin 1465a40d70fSKonstantin Porotchkin void llc_sram_disable(int ap_index) 1475a40d70fSKonstantin Porotchkin { 1485a40d70fSKonstantin Porotchkin uint32_t tc; 1495a40d70fSKonstantin Porotchkin 1505a40d70fSKonstantin Porotchkin /* Disable the line lockings */ 1515a40d70fSKonstantin Porotchkin for (tc = 0; tc < LLC_TC_NUM; tc++) 1525a40d70fSKonstantin Porotchkin mmio_write_32(LLC_TCN_LOCK(ap_index, tc), 0); 1535a40d70fSKonstantin Porotchkin 1545a40d70fSKonstantin Porotchkin /* Invalidate all ways */ 1555a40d70fSKonstantin Porotchkin llc_inv_all(ap_index); 1565a40d70fSKonstantin Porotchkin } 157*506ff4c0SKonstantin Porotchkin 158*506ff4c0SKonstantin Porotchkin int llc_sram_test(int ap_index, int size, char *msg) 159*506ff4c0SKonstantin Porotchkin { 160*506ff4c0SKonstantin Porotchkin uintptr_t addr, end_addr; 161*506ff4c0SKonstantin Porotchkin uint32_t data = 0; 162*506ff4c0SKonstantin Porotchkin 163*506ff4c0SKonstantin Porotchkin if ((size <= 0) || (size > LLC_SIZE)) 164*506ff4c0SKonstantin Porotchkin return -1; 165*506ff4c0SKonstantin Porotchkin 166*506ff4c0SKonstantin Porotchkin INFO("=== LLC SRAM WRITE test %s\n", msg); 167*506ff4c0SKonstantin Porotchkin for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE, 168*506ff4c0SKonstantin Porotchkin end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size; 169*506ff4c0SKonstantin Porotchkin addr < end_addr; addr += 4) { 170*506ff4c0SKonstantin Porotchkin mmio_write_32(addr, addr); 171*506ff4c0SKonstantin Porotchkin } 172*506ff4c0SKonstantin Porotchkin INFO("=== LLC SRAM WRITE test %s PASSED\n", msg); 173*506ff4c0SKonstantin Porotchkin INFO("=== LLC SRAM READ test %s\n", msg); 174*506ff4c0SKonstantin Porotchkin for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE, 175*506ff4c0SKonstantin Porotchkin end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size; 176*506ff4c0SKonstantin Porotchkin addr < end_addr; addr += 4) { 177*506ff4c0SKonstantin Porotchkin data = mmio_read_32(addr); 178*506ff4c0SKonstantin Porotchkin if (data != addr) { 179*506ff4c0SKonstantin Porotchkin INFO("=== LLC SRAM READ test %s FAILED @ 0x%08lx)\n", 180*506ff4c0SKonstantin Porotchkin msg, addr); 181*506ff4c0SKonstantin Porotchkin return -1; 182*506ff4c0SKonstantin Porotchkin } 183*506ff4c0SKonstantin Porotchkin } 184*506ff4c0SKonstantin Porotchkin INFO("=== LLC SRAM READ test %s PASSED (last read = 0x%08x)\n", 185*506ff4c0SKonstantin Porotchkin msg, data); 186*506ff4c0SKonstantin Porotchkin return 0; 187*506ff4c0SKonstantin Porotchkin } 188*506ff4c0SKonstantin Porotchkin 1895a40d70fSKonstantin Porotchkin #endif /* LLC_SRAM */ 190