xref: /arm-trusted-firmware/lib/mpmm/mpmm.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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