1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021-2022, Arm Limited. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <stdbool.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #include <lib/mpmm/mpmm.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <plat/common/platform.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu #if ENABLE_MPMM_FCONF 15*91f16700Schasinglulu # include <lib/fconf/fconf.h> 16*91f16700Schasinglulu # include <lib/fconf/fconf_mpmm_getter.h> 17*91f16700Schasinglulu #endif 18*91f16700Schasinglulu 19*91f16700Schasinglulu static uint64_t read_cpuppmcr_el3_mpmmpinctl(void) 20*91f16700Schasinglulu { 21*91f16700Schasinglulu return (read_cpuppmcr_el3() >> CPUPPMCR_EL3_MPMMPINCTL_SHIFT) & 22*91f16700Schasinglulu CPUPPMCR_EL3_MPMMPINCTL_MASK; 23*91f16700Schasinglulu } 24*91f16700Schasinglulu 25*91f16700Schasinglulu static void write_cpumpmmcr_el3_mpmm_en(uint64_t mpmm_en) 26*91f16700Schasinglulu { 27*91f16700Schasinglulu uint64_t value = read_cpumpmmcr_el3(); 28*91f16700Schasinglulu 29*91f16700Schasinglulu value &= ~(CPUMPMMCR_EL3_MPMM_EN_MASK << CPUMPMMCR_EL3_MPMM_EN_SHIFT); 30*91f16700Schasinglulu value |= (mpmm_en & CPUMPMMCR_EL3_MPMM_EN_MASK) << 31*91f16700Schasinglulu CPUMPMMCR_EL3_MPMM_EN_SHIFT; 32*91f16700Schasinglulu 33*91f16700Schasinglulu write_cpumpmmcr_el3(value); 34*91f16700Schasinglulu } 35*91f16700Schasinglulu 36*91f16700Schasinglulu static bool mpmm_supported(void) 37*91f16700Schasinglulu { 38*91f16700Schasinglulu bool supported = false; 39*91f16700Schasinglulu const struct mpmm_topology *topology; 40*91f16700Schasinglulu 41*91f16700Schasinglulu #if ENABLE_MPMM_FCONF 42*91f16700Schasinglulu topology = FCONF_GET_PROPERTY(mpmm, config, topology); 43*91f16700Schasinglulu #else 44*91f16700Schasinglulu topology = plat_mpmm_topology(); 45*91f16700Schasinglulu #endif /* ENABLE_MPMM_FCONF */ 46*91f16700Schasinglulu 47*91f16700Schasinglulu /* 48*91f16700Schasinglulu * For the current core firstly try to find out if the platform 49*91f16700Schasinglulu * configuration has claimed support for MPMM, then make sure that MPMM 50*91f16700Schasinglulu * is controllable through the system registers. 51*91f16700Schasinglulu */ 52*91f16700Schasinglulu 53*91f16700Schasinglulu if (topology != NULL) { 54*91f16700Schasinglulu unsigned int core_pos = plat_my_core_pos(); 55*91f16700Schasinglulu 56*91f16700Schasinglulu supported = topology->cores[core_pos].supported && 57*91f16700Schasinglulu (read_cpuppmcr_el3_mpmmpinctl() == 0U); 58*91f16700Schasinglulu } else { 59*91f16700Schasinglulu ERROR("MPMM: failed to generate MPMM topology\n"); 60*91f16700Schasinglulu } 61*91f16700Schasinglulu 62*91f16700Schasinglulu return supported; 63*91f16700Schasinglulu } 64*91f16700Schasinglulu 65*91f16700Schasinglulu /* Defaults to false */ 66*91f16700Schasinglulu static bool mpmm_disable_for_errata; 67*91f16700Schasinglulu 68*91f16700Schasinglulu void mpmm_enable(void) 69*91f16700Schasinglulu { 70*91f16700Schasinglulu if (mpmm_supported()) { 71*91f16700Schasinglulu if (mpmm_disable_for_errata) { 72*91f16700Schasinglulu WARN("MPMM: disabled by errata workaround\n"); 73*91f16700Schasinglulu return; 74*91f16700Schasinglulu } 75*91f16700Schasinglulu write_cpumpmmcr_el3_mpmm_en(1U); 76*91f16700Schasinglulu } 77*91f16700Schasinglulu } 78*91f16700Schasinglulu 79*91f16700Schasinglulu /* 80*91f16700Schasinglulu * This function is called from assembly code very early in BL31 so it must be 81*91f16700Schasinglulu * small and simple. 82*91f16700Schasinglulu */ 83*91f16700Schasinglulu void mpmm_errata_disable(void) 84*91f16700Schasinglulu { 85*91f16700Schasinglulu mpmm_disable_for_errata = true; 86*91f16700Schasinglulu } 87