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