xref: /optee_os/core/arch/arm/plat-imx/imx_pl310.c (revision 52676ba07e05458570a9dd3506937466a7af2038)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2dd2561c4SPeng Fan /*
3dd2561c4SPeng Fan  * Copyright (C) 2016 Freescale Semiconductor, Inc.
4dd2561c4SPeng Fan  *
5dd2561c4SPeng Fan  * Peng Fan <peng.fan@nxp.com>
6dd2561c4SPeng Fan  */
743852166SPeng Fan 
8dd2561c4SPeng Fan #include <arm32.h>
9dd2561c4SPeng Fan #include <io.h>
1065401337SJens Wiklander #include <kernel/boot.h>
11dd2561c4SPeng Fan #include <kernel/tz_ssvce_def.h>
12dd2561c4SPeng Fan #include <kernel/tz_ssvce_pl310.h>
13ea850f1fSMathieu Briand #include <mm/core_memprot.h>
14ea850f1fSMathieu Briand #include <mm/core_mmu.h>
158d5160deSJordan Rhee #include <sm/optee_smc.h>
16dd2561c4SPeng Fan #include <platform_config.h>
17dd2561c4SPeng Fan #include <stdint.h>
188d5160deSJordan Rhee #include "imx_pl310.h"
198d5160deSJordan Rhee 
208d5160deSJordan Rhee #define PL310_AUX_CTRL_FLZW			BIT(0)
218d5160deSJordan Rhee #define PL310_DEBUG_CTRL_DISABLE_WRITEBACK	BIT(1)
228d5160deSJordan Rhee #define PL310_DEBUG_CTRL_DISABLE_LINEFILL	BIT(0)
237e785722SClement Faure #define PL310_PREFETCH_DOUBLE_LINEFILL		BIT(30)
24dd2561c4SPeng Fan 
25a5e82dc7SJerome Forissier register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE);
26*52676ba0SClement Faure register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PL310_BASE, CORE_MMU_PGDIR_SIZE);
27ea850f1fSMathieu Briand 
arm_cl2_config(vaddr_t pl310_base)28dd2561c4SPeng Fan void arm_cl2_config(vaddr_t pl310_base)
29dd2561c4SPeng Fan {
307e785722SClement Faure 	uint32_t val = 0;
317e785722SClement Faure 	uint32_t id = 0;
327e785722SClement Faure 
33dd2561c4SPeng Fan 	/* Disable PL310 */
34c9df313bSEtienne Carriere 	io_write32(pl310_base + PL310_CTRL, 0);
35dd2561c4SPeng Fan 
36c9df313bSEtienne Carriere 	io_write32(pl310_base + PL310_TAG_RAM_CTRL, PL310_TAG_RAM_CTRL_INIT);
37c9df313bSEtienne Carriere 	io_write32(pl310_base + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT);
38c9df313bSEtienne Carriere 	io_write32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT);
397e785722SClement Faure 	/*
407e785722SClement Faure 	 * The L2 cache controller(PL310) version on the i.MX6D/Q
417e785722SClement Faure 	 * is r3p1-50rel0
427e785722SClement Faure 	 * The L2 cache controller(PL310) version on the
437e785722SClement Faure 	 * i.MX6DL/SOLO/SL/SX/DQP is r3p2.
447e785722SClement Faure 	 *
457e785722SClement Faure 	 * According to ARM PL310 errata: 752271
467e785722SClement Faure 	 * ID: 752271: Double linefill feature can cause data corruption
477e785722SClement Faure 	 * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2
487e785722SClement Faure 	 * Workaround: The only workaround to this erratum is to disable the
497e785722SClement Faure 	 * double linefill feature. This is the default behavior.
507e785722SClement Faure 	 */
517e785722SClement Faure 	val = PL310_PREFETCH_CTRL_INIT;
527e785722SClement Faure 
537e785722SClement Faure 	id = io_read32(pl310_base + PL310_CACHE_ID);
547e785722SClement Faure 
557e785722SClement Faure 	if (((id & PL310_CACHE_ID_PART_MASK) == PL310_CACHE_ID_PART_L310) &&
567e785722SClement Faure 	    ((id & PL310_CACHE_ID_RTL_MASK) < PL310_CACHE_ID_RTL_R3P2))
577e785722SClement Faure 		val &= ~PL310_PREFETCH_DOUBLE_LINEFILL;
587e785722SClement Faure 
597e785722SClement Faure 	io_write32(pl310_base + PL310_PREFETCH_CTRL, val);
607e785722SClement Faure 
61c9df313bSEtienne Carriere 	io_write32(pl310_base + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT);
62dd2561c4SPeng Fan 
63dd2561c4SPeng Fan 	/* invalidate all cache ways */
64dd2561c4SPeng Fan 	arm_cl2_invbyway(pl310_base);
65dd2561c4SPeng Fan }
66dd2561c4SPeng Fan 
arm_cl2_enable(vaddr_t pl310_base)67dd2561c4SPeng Fan void arm_cl2_enable(vaddr_t pl310_base)
68dd2561c4SPeng Fan {
698d5160deSJordan Rhee 	uint32_t val __maybe_unused;
70dd2561c4SPeng Fan 
71dd2561c4SPeng Fan 	/* Enable PL310 ctrl -> only set lsb bit */
72c9df313bSEtienne Carriere 	io_write32(pl310_base + PL310_CTRL, 1);
73dd2561c4SPeng Fan 
748d5160deSJordan Rhee #ifndef CFG_PL310_SIP_PROTOCOL
75dd2561c4SPeng Fan 	/* if L2 FLZW enable, enable in L1 */
76c9df313bSEtienne Carriere 	val = io_read32(pl310_base + PL310_AUX_CTRL);
778d5160deSJordan Rhee 	if (val & PL310_AUX_CTRL_FLZW)
788d5160deSJordan Rhee 		write_actlr(read_actlr() | ACTLR_CA9_WFLZ);
798d5160deSJordan Rhee #endif
80dd2561c4SPeng Fan }
81ea850f1fSMathieu Briand 
pl310_base(void)82ea850f1fSMathieu Briand vaddr_t pl310_base(void)
83ea850f1fSMathieu Briand {
84c2e4eb43SAnton Rybakov 	return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_SEC, 1);
85ea850f1fSMathieu Briand }
86ea850f1fSMathieu Briand 
pl310_nsbase(void)87*52676ba0SClement Faure vaddr_t pl310_nsbase(void)
88*52676ba0SClement Faure {
89*52676ba0SClement Faure 	return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_NSEC, 1);
90*52676ba0SClement Faure }
91*52676ba0SClement Faure 
928d5160deSJordan Rhee #ifdef CFG_PL310_SIP_PROTOCOL
pl310_enable(void)938d5160deSJordan Rhee uint32_t pl310_enable(void)
948d5160deSJordan Rhee {
958d5160deSJordan Rhee 	vaddr_t base = pl310_base();
968d5160deSJordan Rhee 
978d5160deSJordan Rhee 	arm_cl2_config(base);
988d5160deSJordan Rhee 	arm_cl2_enable(base);
998d5160deSJordan Rhee 	return OPTEE_SMC_RETURN_OK;
1008d5160deSJordan Rhee }
1018d5160deSJordan Rhee 
pl310_disable(void)1028d5160deSJordan Rhee uint32_t pl310_disable(void)
1038d5160deSJordan Rhee {
1048d5160deSJordan Rhee 	EMSG("not implemented");
1058d5160deSJordan Rhee 	return OPTEE_SMC_RETURN_ENOTAVAIL;
1068d5160deSJordan Rhee }
1078d5160deSJordan Rhee 
pl310_enable_writeback(void)1088d5160deSJordan Rhee uint32_t pl310_enable_writeback(void)
1098d5160deSJordan Rhee {
1108d5160deSJordan Rhee 	vaddr_t base = pl310_base();
1118d5160deSJordan Rhee 
112c9df313bSEtienne Carriere 	io_write32(base + PL310_DEBUG_CTRL, 0);
1138d5160deSJordan Rhee 	return OPTEE_SMC_RETURN_OK;
1148d5160deSJordan Rhee }
1158d5160deSJordan Rhee 
pl310_disable_writeback(void)1168d5160deSJordan Rhee uint32_t pl310_disable_writeback(void)
1178d5160deSJordan Rhee {
1188d5160deSJordan Rhee 	vaddr_t base = pl310_base();
1198d5160deSJordan Rhee 	uint32_t val = PL310_DEBUG_CTRL_DISABLE_WRITEBACK |
1208d5160deSJordan Rhee 		       PL310_DEBUG_CTRL_DISABLE_LINEFILL;
1218d5160deSJordan Rhee 
122c9df313bSEtienne Carriere 	io_write32(base + PL310_DEBUG_CTRL, val);
1238d5160deSJordan Rhee 	return OPTEE_SMC_RETURN_OK;
1248d5160deSJordan Rhee }
1258d5160deSJordan Rhee 
pl310_enable_wflz(void)1268d5160deSJordan Rhee uint32_t pl310_enable_wflz(void)
1278d5160deSJordan Rhee {
1288d5160deSJordan Rhee 	write_actlr(read_actlr() | ACTLR_CA9_WFLZ);
1298d5160deSJordan Rhee 	return OPTEE_SMC_RETURN_OK;
1308d5160deSJordan Rhee }
1318d5160deSJordan Rhee #endif
132