1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "mmu500.h"
9
10 #include <mod_synquacer_system.h>
11
12 #include <fwk_log.h>
13
14 #include <inttypes.h>
15
SMMU_setup_PMU(MMU500_Type_t * SMMU)16 void SMMU_setup_PMU(MMU500_Type_t *SMMU)
17 {
18 volatile uint32_t *pmu_regs;
19 int page_size;
20
21 page_size = ((SMMU->GR0.IDR1 & SMMU_IDR1_PAGESIZE) == 0) ? 0x1000 : 0x10000;
22
23 pmu_regs = (volatile uint32_t *)(((uint32_t)SMMU) + 3 * page_size);
24
25 pmu_regs[0x0400 / 4] =
26 0x00000010U; /* PMEVTYPER0: P=U=NSP=NSU=0, EVENT=0x0010(access) */
27 pmu_regs[0x0404 / 4] =
28 0x00000011U; /* PMEVTYPER1: P=U=NSP=NSU=0, EVENT=0x0011(read) */
29 pmu_regs[0x0408 / 4] =
30 0x00000012U; /* PMEVTYPER2: P=U=NSP=NSU=0, EVENT=0x0012(write) */
31 pmu_regs[0x0c00 / 4] =
32 0x00000007U; /* PMCNTENSET0: enable counter #0, #1, #2 */
33 pmu_regs[0x0800 / 4] = 0x00000800U; /* PMCGCR0: enable=1, global_basis */
34 pmu_regs[0x0e04 / 4] = 0x00000003U; /* PMCR: enable=1, reset=1 */
35
36 FWK_LOG_INFO(
37 "[MMU500] setup PMU for MMU-500@0x%08" PRIx32
38 ". page_size=%d. 0x%08" PRIx32 "(access), 0x%08" PRIx32
39 "(read), 0x%08" PRIx32 "(write).",
40 (uint32_t)SMMU,
41 page_size,
42 (uint32_t)&pmu_regs[0],
43 (uint32_t)&pmu_regs[1],
44 (uint32_t)&pmu_regs[2]);
45 }
46
SMMU_s_init(MMU500_Type_t * SMMU,uint32_t num_context,const MMU500_ContextInfo_t * context_info,enum mmu500_granule granule)47 int32_t SMMU_s_init(
48 MMU500_Type_t *SMMU,
49 uint32_t num_context,
50 const MMU500_ContextInfo_t *context_info,
51 enum mmu500_granule granule)
52 {
53 uint32_t temp;
54 uint32_t i;
55
56 SMMU->GR0.ACR |=
57 SMMU_ACR_S2CRB_TLBEN | SMMU_ACR_MMUDISB_TLBEN | SMMU_ACR_SMTNMB_TLBEN;
58
59 if ((num_context > (SMMU->GR0.IDR1 & SMMU_IDR1_NUMCB)) ||
60 (num_context > (SMMU->GR0.IDR0 & SMMU_IDR0_NUMSMRG))) {
61 /* num_context too large */
62 return -1;
63 }
64
65 /* Use all context banks for secure access */
66 temp = SMMU->GR0.SCR1;
67 temp &= ~(SMMU_SCR1_NSNUMCBO | SMMU_SCR1_NSNUMSMRGO);
68 SMMU->GR0.SCR1 = temp | (0 << SMMU_SCR1_NSNUMCBO_OFFSET) |
69 (0 << SMMU_SCR1_NSNUMSMRGO_OFFSET) | SMMU_SCR1_SPMEN;
70
71 SMMU->GR0.CR0 =
72 (SMMU_CR0_SMCFCFG | SMMU_CR0_USFCFG | SMMU_CR0_STALLD |
73 SMMU_CR0_GCFGFIE | SMMU_CR0_GCFGFRE | SMMU_CR0_GFIE | SMMU_CR0_GFRE);
74
75 for (i = 0; i < num_context; i++) {
76 SMMU->GR0.S2CR[i] = SMMU_S2CRn_TYPE_CONTEXT | i;
77 SMMU->GR0.SMR[i] = SMMU_SMRn_VALID |
78 (context_info[i].stream_match_mask << 16) |
79 context_info[i].stream_match_id;
80 SMMU_ns_cb_stage1_init(SMMU, i, context_info[i].base_addr, granule);
81 }
82
83 SMMU_setup_PMU(SMMU);
84
85 return 0;
86 }
87
SMMU_ns_cb_stage1_init(MMU500_Type_t * SMMU,uint32_t cb,uint64_t base_addr,enum mmu500_granule granule)88 void SMMU_ns_cb_stage1_init(
89 MMU500_Type_t *SMMU,
90 uint32_t cb,
91 uint64_t base_addr,
92 enum mmu500_granule granule)
93 {
94 uint64_t temp;
95
96 SMMU->GR1.CBAR[cb] = SMMU_CBAR_TYPE_STAGE1 | SMMU_CBAR_MEM_NORMAL;
97 SMMU->GR1.CBA2R[cb] = SMMU_CBA2R_VA64;
98
99 SMMU->TCB[cb].CB_TCR =
100 (SMMU_TCR_EPD1 | SMMU_TCR_SH0_OUTER | SMMU_TCR_ORGN0_WBWA |
101 SMMU_TCR_IRGN0_WBWA | SMMU_TCR_T0SZ_256TB);
102
103 switch (granule) {
104 case MMU500_GRANULE_4KB:
105 SMMU->TCB[cb].CB_TCR |= SMMU_TCR_TG0_4KB;
106 break;
107 case MMU500_GRANULE_16KB:
108 SMMU->TCB[cb].CB_TCR |= SMMU_TCR_TG0_16KB;
109 break;
110 case MMU500_GRANULE_64KB:
111 SMMU->TCB[cb].CB_TCR |= SMMU_TCR_TG0_64KB;
112 break;
113 }
114
115 SMMU->TCB[cb].CB_TCR2 = SMMU_TCR2_SEP_47 | SMMU_TCR2_PASIZE_48;
116 SMMU->TCB[cb].CB_TTBR0 =
117 (((uint64_t)0) << SMMU_TTBRn_ASID_OFFSET) | ((uint64_t)base_addr);
118
119 /*
120 * AttrIndx[2:0]: setting
121 * 2'b000: 0xFF=Outer write-back,non-transient normal memory,
122 * read-write/Inner write-back.non-transient normal
123 * memory,read-write 2'b001: 0x00=Device-nGnRnE 2'b010-111: (not used)
124 */
125 temp = 0x00000000000000ffLLU;
126 SMMU->TCB[cb].CB_MAIR0 = (uint32_t)temp;
127 SMMU->TCB[cb].CB_MAIR1 = (uint32_t)(temp >> 32);
128
129 SMMU->TCB[cb].CB_FSR = 0xffffffff;
130
131 SMMU->TCB[cb].CB_SCTLR =
132 (SMMU_SCTLR_MEM_NORMAL | SMMU_SCTLR_UWXN | SMMU_SCTLR_CFIE |
133 SMMU_SCTLR_CFRE | SMMU_SCTLR_M);
134 }
135
SMMU_s_disable(MMU500_Type_t * SMMU,uint32_t num_context)136 void SMMU_s_disable(MMU500_Type_t *SMMU, uint32_t num_context)
137 {
138 uint32_t i;
139
140 if ((num_context > (SMMU->GR0.IDR1 & SMMU_IDR1_NUMCB)) ||
141 (num_context > (SMMU->GR0.IDR0 & SMMU_IDR0_NUMSMRG))) {
142 /* num_context too large */
143 return;
144 }
145
146 SMMU->GR0.ACR &= ~(
147 SMMU_ACR_S2CRB_TLBEN | SMMU_ACR_MMUDISB_TLBEN | SMMU_ACR_SMTNMB_TLBEN);
148
149 for (i = 0; i < num_context; i++)
150 SMMU->TCB[i].CB_SCTLR &= ~(SMMU_SCTLR_M);
151 }
152