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 } 112*5a40d70fSKonstantin Porotchkin 113*5a40d70fSKonstantin Porotchkin #if LLC_SRAM 114*5a40d70fSKonstantin Porotchkin void llc_sram_enable(int ap_index) 115*5a40d70fSKonstantin Porotchkin { 116*5a40d70fSKonstantin Porotchkin uint32_t tc, way; 117*5a40d70fSKonstantin Porotchkin uint32_t way_addr; 118*5a40d70fSKonstantin Porotchkin 119*5a40d70fSKonstantin Porotchkin /* Lockdown all available ways for all traffic classes */ 120*5a40d70fSKonstantin Porotchkin for (tc = 0; tc < LLC_TC_NUM; tc++) 121*5a40d70fSKonstantin Porotchkin mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_WAY_MASK); 122*5a40d70fSKonstantin Porotchkin 123*5a40d70fSKonstantin Porotchkin /* Clear the high bits of SRAM address */ 124*5a40d70fSKonstantin Porotchkin mmio_write_32(LLC_BANKED_MNT_AHR(ap_index), 0); 125*5a40d70fSKonstantin Porotchkin 126*5a40d70fSKonstantin Porotchkin way_addr = PLAT_MARVELL_TRUSTED_RAM_BASE; 127*5a40d70fSKonstantin Porotchkin for (way = 0; way < LLC_WAYS; way++) { 128*5a40d70fSKonstantin Porotchkin /* Trigger allocation block command */ 129*5a40d70fSKonstantin Porotchkin mmio_write_32(LLC_BLK_ALOC(ap_index), 130*5a40d70fSKonstantin Porotchkin LLC_BLK_ALOC_BASE_ADDR(way_addr) | 131*5a40d70fSKonstantin Porotchkin LLC_BLK_ALOC_WAY_DATA_CLR | 132*5a40d70fSKonstantin Porotchkin LLC_BLK_ALOC_WAY_ID(way)); 133*5a40d70fSKonstantin Porotchkin way_addr += LLC_WAY_SIZE; 134*5a40d70fSKonstantin Porotchkin } 135*5a40d70fSKonstantin Porotchkin llc_enable(ap_index, 1); 136*5a40d70fSKonstantin Porotchkin } 137*5a40d70fSKonstantin Porotchkin 138*5a40d70fSKonstantin Porotchkin void llc_sram_disable(int ap_index) 139*5a40d70fSKonstantin Porotchkin { 140*5a40d70fSKonstantin Porotchkin uint32_t tc; 141*5a40d70fSKonstantin Porotchkin 142*5a40d70fSKonstantin Porotchkin /* Disable the line lockings */ 143*5a40d70fSKonstantin Porotchkin for (tc = 0; tc < LLC_TC_NUM; tc++) 144*5a40d70fSKonstantin Porotchkin mmio_write_32(LLC_TCN_LOCK(ap_index, tc), 0); 145*5a40d70fSKonstantin Porotchkin 146*5a40d70fSKonstantin Porotchkin /* Invalidate all ways */ 147*5a40d70fSKonstantin Porotchkin llc_inv_all(ap_index); 148*5a40d70fSKonstantin Porotchkin } 149*5a40d70fSKonstantin Porotchkin #endif /* LLC_SRAM */ 150