| /* |
| * Copyright (c) 2021-2022, Arm Limited. All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include <stdbool.h> |
| |
| #include <common/debug.h> |
| #include <lib/mpmm/mpmm.h> |
| |
| #include <plat/common/platform.h> |
| |
| #if ENABLE_MPMM_FCONF |
| # include <lib/fconf/fconf.h> |
| # include <lib/fconf/fconf_mpmm_getter.h> |
| #endif |
| |
| static uint64_t read_cpuppmcr_el3_mpmmpinctl(void) |
| { |
| return (read_cpuppmcr_el3() >> CPUPPMCR_EL3_MPMMPINCTL_SHIFT) & |
| CPUPPMCR_EL3_MPMMPINCTL_MASK; |
| } |
| |
| static void write_cpumpmmcr_el3_mpmm_en(uint64_t mpmm_en) |
| { |
| uint64_t value = read_cpumpmmcr_el3(); |
| |
| value &= ~(CPUMPMMCR_EL3_MPMM_EN_MASK << CPUMPMMCR_EL3_MPMM_EN_SHIFT); |
| value |= (mpmm_en & CPUMPMMCR_EL3_MPMM_EN_MASK) << |
| CPUMPMMCR_EL3_MPMM_EN_SHIFT; |
| |
| write_cpumpmmcr_el3(value); |
| } |
| |
| static bool mpmm_supported(void) |
| { |
| bool supported = false; |
| const struct mpmm_topology *topology; |
| |
| #if ENABLE_MPMM_FCONF |
| topology = FCONF_GET_PROPERTY(mpmm, config, topology); |
| #else |
| topology = plat_mpmm_topology(); |
| #endif /* ENABLE_MPMM_FCONF */ |
| |
| /* |
| * For the current core firstly try to find out if the platform |
| * configuration has claimed support for MPMM, then make sure that MPMM |
| * is controllable through the system registers. |
| */ |
| |
| if (topology != NULL) { |
| unsigned int core_pos = plat_my_core_pos(); |
| |
| supported = topology->cores[core_pos].supported && |
| (read_cpuppmcr_el3_mpmmpinctl() == 0U); |
| } else { |
| ERROR("MPMM: failed to generate MPMM topology\n"); |
| } |
| |
| return supported; |
| } |
| |
| /* Defaults to false */ |
| static bool mpmm_disable_for_errata; |
| |
| void mpmm_enable(void) |
| { |
| if (mpmm_supported()) { |
| if (mpmm_disable_for_errata) { |
| WARN("MPMM: disabled by errata workaround\n"); |
| return; |
| } |
| write_cpumpmmcr_el3_mpmm_en(1U); |
| } |
| } |
| |
| /* |
| * This function is called from assembly code very early in BL31 so it must be |
| * small and simple. |
| */ |
| void mpmm_errata_disable(void) |
| { |
| mpmm_disable_for_errata = true; |
| } |