1*152b0e47SKonstantin Porotchkin /* 2*152b0e47SKonstantin Porotchkin * Copyright (C) 2018 Marvell International Ltd. 3*152b0e47SKonstantin Porotchkin * 4*152b0e47SKonstantin Porotchkin * SPDX-License-Identifier: BSD-3-Clause 5*152b0e47SKonstantin Porotchkin * https://spdx.org/licenses 6*152b0e47SKonstantin Porotchkin */ 7*152b0e47SKonstantin Porotchkin 8*152b0e47SKonstantin Porotchkin /* LLC driver is the Last Level Cache (L3C) driver 9*152b0e47SKonstantin Porotchkin * for Marvell SoCs in AP806, AP807, and AP810 10*152b0e47SKonstantin Porotchkin */ 11*152b0e47SKonstantin Porotchkin 12*152b0e47SKonstantin Porotchkin #include <arch_helpers.h> 13*152b0e47SKonstantin Porotchkin #include <assert.h> 14*152b0e47SKonstantin Porotchkin #include <cache_llc.h> 15*152b0e47SKonstantin Porotchkin #include <ccu.h> 16*152b0e47SKonstantin Porotchkin #include <mmio.h> 17*152b0e47SKonstantin Porotchkin #include <mvebu_def.h> 18*152b0e47SKonstantin Porotchkin 19*152b0e47SKonstantin Porotchkin #define CCU_HTC_CR(ap_index) (MVEBU_CCU_BASE(ap_index) + 0x200) 20*152b0e47SKonstantin Porotchkin #define CCU_SET_POC_OFFSET 5 21*152b0e47SKonstantin Porotchkin 22*152b0e47SKonstantin Porotchkin extern void ca72_l2_enable_unique_clean(void); 23*152b0e47SKonstantin Porotchkin 24*152b0e47SKonstantin Porotchkin void llc_cache_sync(int ap_index) 25*152b0e47SKonstantin Porotchkin { 26*152b0e47SKonstantin Porotchkin mmio_write_32(LLC_SYNC(ap_index), 0); 27*152b0e47SKonstantin Porotchkin /* Atomic write, no need to wait */ 28*152b0e47SKonstantin Porotchkin } 29*152b0e47SKonstantin Porotchkin 30*152b0e47SKonstantin Porotchkin void llc_flush_all(int ap_index) 31*152b0e47SKonstantin Porotchkin { 32*152b0e47SKonstantin Porotchkin mmio_write_32(L2X0_CLEAN_INV_WAY(ap_index), LLC_WAY_MASK); 33*152b0e47SKonstantin Porotchkin llc_cache_sync(ap_index); 34*152b0e47SKonstantin Porotchkin } 35*152b0e47SKonstantin Porotchkin 36*152b0e47SKonstantin Porotchkin void llc_clean_all(int ap_index) 37*152b0e47SKonstantin Porotchkin { 38*152b0e47SKonstantin Porotchkin mmio_write_32(L2X0_CLEAN_WAY(ap_index), LLC_WAY_MASK); 39*152b0e47SKonstantin Porotchkin llc_cache_sync(ap_index); 40*152b0e47SKonstantin Porotchkin } 41*152b0e47SKonstantin Porotchkin 42*152b0e47SKonstantin Porotchkin void llc_inv_all(int ap_index) 43*152b0e47SKonstantin Porotchkin { 44*152b0e47SKonstantin Porotchkin mmio_write_32(L2X0_INV_WAY(ap_index), LLC_WAY_MASK); 45*152b0e47SKonstantin Porotchkin llc_cache_sync(ap_index); 46*152b0e47SKonstantin Porotchkin } 47*152b0e47SKonstantin Porotchkin 48*152b0e47SKonstantin Porotchkin void llc_disable(int ap_index) 49*152b0e47SKonstantin Porotchkin { 50*152b0e47SKonstantin Porotchkin llc_flush_all(ap_index); 51*152b0e47SKonstantin Porotchkin mmio_write_32(LLC_CTRL(ap_index), 0); 52*152b0e47SKonstantin Porotchkin dsbishst(); 53*152b0e47SKonstantin Porotchkin } 54*152b0e47SKonstantin Porotchkin 55*152b0e47SKonstantin Porotchkin void llc_enable(int ap_index, int excl_mode) 56*152b0e47SKonstantin Porotchkin { 57*152b0e47SKonstantin Porotchkin uint32_t val; 58*152b0e47SKonstantin Porotchkin 59*152b0e47SKonstantin Porotchkin dsbsy(); 60*152b0e47SKonstantin Porotchkin llc_inv_all(ap_index); 61*152b0e47SKonstantin Porotchkin dsbsy(); 62*152b0e47SKonstantin Porotchkin 63*152b0e47SKonstantin Porotchkin val = LLC_CTRL_EN; 64*152b0e47SKonstantin Porotchkin if (excl_mode) 65*152b0e47SKonstantin Porotchkin val |= LLC_EXCLUSIVE_EN; 66*152b0e47SKonstantin Porotchkin 67*152b0e47SKonstantin Porotchkin mmio_write_32(LLC_CTRL(ap_index), val); 68*152b0e47SKonstantin Porotchkin dsbsy(); 69*152b0e47SKonstantin Porotchkin } 70*152b0e47SKonstantin Porotchkin 71*152b0e47SKonstantin Porotchkin int llc_is_exclusive(int ap_index) 72*152b0e47SKonstantin Porotchkin { 73*152b0e47SKonstantin Porotchkin uint32_t reg; 74*152b0e47SKonstantin Porotchkin 75*152b0e47SKonstantin Porotchkin reg = mmio_read_32(LLC_CTRL(ap_index)); 76*152b0e47SKonstantin Porotchkin 77*152b0e47SKonstantin Porotchkin if ((reg & (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) == 78*152b0e47SKonstantin Porotchkin (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) 79*152b0e47SKonstantin Porotchkin return 1; 80*152b0e47SKonstantin Porotchkin 81*152b0e47SKonstantin Porotchkin return 0; 82*152b0e47SKonstantin Porotchkin } 83*152b0e47SKonstantin Porotchkin 84*152b0e47SKonstantin Porotchkin void llc_runtime_enable(int ap_index) 85*152b0e47SKonstantin Porotchkin { 86*152b0e47SKonstantin Porotchkin uint32_t reg; 87*152b0e47SKonstantin Porotchkin 88*152b0e47SKonstantin Porotchkin reg = mmio_read_32(LLC_CTRL(ap_index)); 89*152b0e47SKonstantin Porotchkin if (reg & LLC_CTRL_EN) 90*152b0e47SKonstantin Porotchkin return; 91*152b0e47SKonstantin Porotchkin 92*152b0e47SKonstantin Porotchkin INFO("Enabling LLC\n"); 93*152b0e47SKonstantin Porotchkin 94*152b0e47SKonstantin Porotchkin /* 95*152b0e47SKonstantin Porotchkin * Enable L2 UniqueClean evictions with data 96*152b0e47SKonstantin Porotchkin * Note: this configuration assumes that LLC is configured 97*152b0e47SKonstantin Porotchkin * in exclusive mode. 98*152b0e47SKonstantin Porotchkin * Later on in the code this assumption will be validated 99*152b0e47SKonstantin Porotchkin */ 100*152b0e47SKonstantin Porotchkin ca72_l2_enable_unique_clean(); 101*152b0e47SKonstantin Porotchkin llc_enable(ap_index, 1); 102*152b0e47SKonstantin Porotchkin 103*152b0e47SKonstantin Porotchkin /* Set point of coherency to DDR. 104*152b0e47SKonstantin Porotchkin * This is required by units which have SW cache coherency 105*152b0e47SKonstantin Porotchkin */ 106*152b0e47SKonstantin Porotchkin reg = mmio_read_32(CCU_HTC_CR(ap_index)); 107*152b0e47SKonstantin Porotchkin reg |= (0x1 << CCU_SET_POC_OFFSET); 108*152b0e47SKonstantin Porotchkin mmio_write_32(CCU_HTC_CR(ap_index), reg); 109*152b0e47SKonstantin Porotchkin } 110