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