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> 13*09d40e0eSAntonio Nino Diaz 14*09d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 15*09d40e0eSAntonio Nino Diaz #include <drivers/marvell/cache_llc.h> 16*09d40e0eSAntonio Nino Diaz #include <drivers/marvell/ccu.h> 17*09d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 18*09d40e0eSAntonio 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 { 34152b0e47SKonstantin Porotchkin mmio_write_32(L2X0_CLEAN_INV_WAY(ap_index), LLC_WAY_MASK); 35152b0e47SKonstantin Porotchkin llc_cache_sync(ap_index); 36152b0e47SKonstantin Porotchkin } 37152b0e47SKonstantin Porotchkin 38152b0e47SKonstantin Porotchkin void llc_clean_all(int ap_index) 39152b0e47SKonstantin Porotchkin { 40152b0e47SKonstantin Porotchkin mmio_write_32(L2X0_CLEAN_WAY(ap_index), LLC_WAY_MASK); 41152b0e47SKonstantin Porotchkin llc_cache_sync(ap_index); 42152b0e47SKonstantin Porotchkin } 43152b0e47SKonstantin Porotchkin 44152b0e47SKonstantin Porotchkin void llc_inv_all(int ap_index) 45152b0e47SKonstantin Porotchkin { 46152b0e47SKonstantin Porotchkin mmio_write_32(L2X0_INV_WAY(ap_index), LLC_WAY_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