| 1 | /* |
| 2 | * ARM SMMUv3 support - Common API |
| 3 | * |
| 4 | * Copyright (C) 2014-2016 Broadcom Corporation |
| 5 | * Copyright (c) 2017 Red Hat, Inc. |
| 6 | * Written by Prem Mallappa, Eric Auger |
| 7 | * |
| 8 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 9 | */ |
| 10 | |
| 11 | #ifndef HW_ARM_SMMUV3_COMMON_H |
| 12 | #define HW_ARM_SMMUV3_COMMON_H |
| 13 | |
| 14 | #include "hw/core/registerfields.h" |
| 15 | |
| 16 | /* Configuration Data */ |
| 17 | |
| 18 | /* STE Level 1 Descriptor */ |
| 19 | typedef struct STEDesc { |
| 20 | uint32_t word[2]; |
| 21 | } STEDesc; |
| 22 | |
| 23 | /* CD Level 1 Descriptor */ |
| 24 | typedef struct CDDesc { |
| 25 | uint32_t word[2]; |
| 26 | } CDDesc; |
| 27 | |
| 28 | /* Stream Table Entry(STE) */ |
| 29 | typedef struct STE { |
| 30 | uint32_t word[16]; |
| 31 | } STE; |
| 32 | |
| 33 | /* Context Descriptor(CD) */ |
| 34 | typedef struct CD { |
| 35 | uint32_t word[16]; |
| 36 | } CD; |
| 37 | |
| 38 | /* STE fields */ |
| 39 | |
| 40 | REG32(STE_0, 0) |
| 41 | FIELD(STE_0, VALID, 0, 1) |
| 42 | FIELD(STE_0, CONFIG, 1, 3) |
| 43 | FIELD(STE_0, S1FMT, 4, 2) |
| 44 | FIELD(STE_0, CTXPTR_LO, 6, 26) |
| 45 | REG32(STE_1, 4) |
| 46 | FIELD(STE_1, CTXPTR_HI, 0, 24) |
| 47 | FIELD(STE_1, S1CDMAX, 27, 5) |
| 48 | REG32(STE_2, 8) |
| 49 | FIELD(STE_2, S1STALLD, 27, 1) |
| 50 | FIELD(STE_2, EATS, 28, 2) |
| 51 | FIELD(STE_2, STRW, 30, 2) |
| 52 | REG32(STE_4, 16) |
| 53 | FIELD(STE_4, S2VMID, 0, 16) |
| 54 | REG32(STE_5, 20) |
| 55 | FIELD(STE_5, S2T0SZ, 0, 6) |
| 56 | FIELD(STE_5, S2SL0, 6, 2) |
| 57 | FIELD(STE_5, S2TG, 14, 2) |
| 58 | FIELD(STE_5, S2PS, 16, 3) |
| 59 | FIELD(STE_5, S2AA64, 19, 1) |
| 60 | FIELD(STE_5, S2ENDI, 20, 1) |
| 61 | FIELD(STE_5, S2AFFD, 21, 1) |
| 62 | FIELD(STE_5, S2HD, 23, 1) |
| 63 | FIELD(STE_5, S2HA, 24, 1) |
| 64 | FIELD(STE_5, S2S, 25, 1) |
| 65 | FIELD(STE_5, S2R, 26, 1) |
| 66 | REG32(STE_6, 24) |
| 67 | FIELD(STE_6, S2TTB_LO, 4, 28) |
| 68 | REG32(STE_7, 28) |
| 69 | FIELD(STE_7, S2TTB_HI, 0, 20) |
| 70 | |
| 71 | /* Get STE fields */ |
| 72 | #define STE_VALID(x) FIELD_EX32((x)->word[0], STE_0, VALID) |
| 73 | #define STE_CONFIG(x) FIELD_EX32((x)->word[0], STE_0, CONFIG) |
| 74 | #define STE_S1FMT(x) FIELD_EX32((x)->word[0], STE_0, S1FMT) |
| 75 | #define STE_CTXPTR(x) \ |
| 76 | (((uint64_t)FIELD_EX32((x)->word[0], STE_0, CTXPTR_LO) << 6) | \ |
| 77 | ((uint64_t)FIELD_EX32((x)->word[1], STE_1, CTXPTR_HI) << 32)) |
| 78 | #define STE_S1CDMAX(x) FIELD_EX32((x)->word[1], STE_1, S1CDMAX) |
| 79 | #define STE_S1STALLD(x) FIELD_EX32((x)->word[2], STE_2, S1STALLD) |
| 80 | #define STE_EATS(x) FIELD_EX32((x)->word[2], STE_2, EATS) |
| 81 | #define STE_STRW(x) FIELD_EX32((x)->word[2], STE_2, STRW) |
| 82 | #define STE_S2VMID(x) FIELD_EX32((x)->word[4], STE_4, S2VMID) |
| 83 | #define STE_S2T0SZ(x) FIELD_EX32((x)->word[5], STE_5, S2T0SZ) |
| 84 | #define STE_S2SL0(x) FIELD_EX32((x)->word[5], STE_5, S2SL0) |
| 85 | #define STE_S2TG(x) FIELD_EX32((x)->word[5], STE_5, S2TG) |
| 86 | #define STE_S2PS(x) FIELD_EX32((x)->word[5], STE_5, S2PS) |
| 87 | #define STE_S2AA64(x) FIELD_EX32((x)->word[5], STE_5, S2AA64) |
| 88 | #define STE_S2ENDI(x) FIELD_EX32((x)->word[5], STE_5, S2ENDI) |
| 89 | #define STE_S2AFFD(x) FIELD_EX32((x)->word[5], STE_5, S2AFFD) |
| 90 | #define STE_S2HD(x) FIELD_EX32((x)->word[5], STE_5, S2HD) |
| 91 | #define STE_S2HA(x) FIELD_EX32((x)->word[5], STE_5, S2HA) |
| 92 | #define STE_S2S(x) FIELD_EX32((x)->word[5], STE_5, S2S) |
| 93 | #define STE_S2R(x) FIELD_EX32((x)->word[5], STE_5, S2R) |
| 94 | #define STE_S2TTB(x) \ |
| 95 | (((uint64_t)FIELD_EX32((x)->word[6], STE_6, S2TTB_LO) << 4) | \ |
| 96 | ((uint64_t)FIELD_EX32((x)->word[7], STE_7, S2TTB_HI) << 32)) |
| 97 | |
| 98 | #define STE_CFG_S1_ENABLED(config) (config & 0x1) |
| 99 | #define STE_CFG_S2_ENABLED(config) (config & 0x2) |
| 100 | #define STE_CFG_ABORT(config) (!(config & 0x4)) |
| 101 | #define STE_CFG_BYPASS(config) (config == 0x4) |
| 102 | #define STE_CFG_S1_TRANSLATE(config) (config == 0x5) |
| 103 | |
| 104 | #define SMMU_STE_VALID (1ULL << 0) |
| 105 | #define SMMU_STE_CFG_BYPASS (1ULL << 3) |
| 106 | |
| 107 | #define STE0_V MAKE_64BIT_MASK(0, 1) |
| 108 | #define STE0_CONFIG MAKE_64BIT_MASK(1, 3) |
| 109 | #define STE0_S1FMT MAKE_64BIT_MASK(4, 2) |
| 110 | #define STE0_CTXPTR MAKE_64BIT_MASK(6, 50) |
| 111 | #define STE0_S1CDMAX MAKE_64BIT_MASK(59, 5) |
| 112 | #define STE0_MASK (STE0_S1CDMAX | STE0_CTXPTR | STE0_S1FMT | STE0_CONFIG | \ |
| 113 | STE0_V) |
| 114 | |
| 115 | #define STE1_S1DSS MAKE_64BIT_MASK(0, 2) |
| 116 | #define STE1_S1CIR MAKE_64BIT_MASK(2, 2) |
| 117 | #define STE1_S1COR MAKE_64BIT_MASK(4, 2) |
| 118 | #define STE1_S1CSH MAKE_64BIT_MASK(6, 2) |
| 119 | #define STE1_S1STALLD MAKE_64BIT_MASK(27, 1) |
| 120 | #define STE1_EATS MAKE_64BIT_MASK(28, 2) |
| 121 | #define STE1_MASK (STE1_EATS | STE1_S1STALLD | STE1_S1CSH | STE1_S1COR | \ |
| 122 | STE1_S1CIR | STE1_S1DSS) |
| 123 | |
| 124 | /* Update STE fields */ |
| 125 | #define STE_SET_VALID(ste, v) \ |
| 126 | ((ste)->word[0] = FIELD_DP32((ste)->word[0], STE_0, VALID, (v))) |
| 127 | #define STE_SET_CONFIG(ste, v) \ |
| 128 | ((ste)->word[0] = FIELD_DP32((ste)->word[0], STE_0, CONFIG, (v))) |
| 129 | |
| 130 | #define STE_SET_CTXPTR(ste, v) do { \ |
| 131 | (ste)->word[0] = FIELD_DP32((ste)->word[0], STE_0, CTXPTR_LO, (v) >> 6); \ |
| 132 | (ste)->word[1] = FIELD_DP32((ste)->word[1], STE_1, CTXPTR_HI, (v) >> 32); \ |
| 133 | } while (0) |
| 134 | #define STE_SET_S2T0SZ(ste, v) \ |
| 135 | ((ste)->word[5] = FIELD_DP32((ste)->word[5], STE_5, S2T0SZ, (v))) |
| 136 | #define STE_SET_S2SL0(ste, v) \ |
| 137 | ((ste)->word[5] = FIELD_DP32((ste)->word[5], STE_5, S2SL0, (v))) |
| 138 | #define STE_SET_S2TG(ste, v) \ |
| 139 | ((ste)->word[5] = FIELD_DP32((ste)->word[5], STE_5, S2TG, (v))) |
| 140 | #define STE_SET_S2PS(ste, v) \ |
| 141 | ((ste)->word[5] = FIELD_DP32((ste)->word[5], STE_5, S2PS, (v))) |
| 142 | #define STE_SET_S2AA64(ste, v) \ |
| 143 | ((ste)->word[5] = FIELD_DP32((ste)->word[5], STE_5, S2AA64, (v))) |
| 144 | #define STE_SET_S2ENDI(ste, v) \ |
| 145 | ((ste)->word[5] = FIELD_DP32((ste)->word[5], STE_5, S2ENDI, (v))) |
| 146 | #define STE_SET_S2AFFD(ste, v) \ |
| 147 | ((ste)->word[5] = FIELD_DP32((ste)->word[5], STE_5, S2AFFD, (v))) |
| 148 | #define STE_SET_S2S(ste, v) \ |
| 149 | ((ste)->word[5] = FIELD_DP32((ste)->word[5], STE_5, S2S, (v))) |
| 150 | #define STE_SET_S2TTB(ste, v) do { \ |
| 151 | (ste)->word[6] = FIELD_DP32((ste)->word[6], STE_6, S2TTB_LO, (v) >> 4); \ |
| 152 | (ste)->word[7] = FIELD_DP32((ste)->word[7], STE_7, S2TTB_HI, (v) >> 32); \ |
| 153 | } while (0) |
| 154 | |
| 155 | /* CD fields */ |
| 156 | |
| 157 | REG32(CD_0, 0) |
| 158 | FIELD(CD_0, TSZ0, 0, 6) |
| 159 | FIELD(CD_0, TG0, 6, 2) |
| 160 | FIELD(CD_0, EPD0, 14, 1) |
| 161 | FIELD(CD_0, ENDI, 15, 1) |
| 162 | FIELD(CD_0, TSZ1, 16, 6) |
| 163 | FIELD(CD_0, TG1, 22, 2) |
| 164 | FIELD(CD_0, EPD1, 30, 1) |
| 165 | FIELD(CD_0, VALID, 31, 1) |
| 166 | REG32(CD_1, 4) |
| 167 | FIELD(CD_1, IPS, 0, 3) |
| 168 | FIELD(CD_1, AFFD, 3, 1) |
| 169 | FIELD(CD_1, TBI, 6, 2) |
| 170 | FIELD(CD_1, AARCH64, 9, 1) |
| 171 | FIELD(CD_1, HD, 10, 1) |
| 172 | FIELD(CD_1, HA, 11, 1) |
| 173 | FIELD(CD_1, S, 12, 1) |
| 174 | FIELD(CD_1, R, 13, 1) |
| 175 | FIELD(CD_1, A, 14, 1) |
| 176 | FIELD(CD_1, ASID, 16, 16) |
| 177 | REG32(CD_2, 8) |
| 178 | FIELD(CD_2, NSCFG0, 0, 1) |
| 179 | FIELD(CD_2, HAD0, 1, 1) |
| 180 | FIELD(CD_2, TTB0_LO, 4, 28) |
| 181 | REG32(CD_3, 12) |
| 182 | FIELD(CD_3, TTB0_HI, 0, 20) |
| 183 | REG32(CD_4, 16) |
| 184 | FIELD(CD_4, NSCFG1, 0, 1) |
| 185 | FIELD(CD_4, HAD1, 1, 1) |
| 186 | FIELD(CD_4, TTB1_LO, 4, 28) |
| 187 | REG32(CD_5, 20) |
| 188 | FIELD(CD_5, TTB1_HI, 0, 20) |
| 189 | |
| 190 | /* Get CD fields */ |
| 191 | #define CD_TSZ(x, sel) ((sel) ? \ |
| 192 | FIELD_EX32((x)->word[0], CD_0, TSZ1) : \ |
| 193 | FIELD_EX32((x)->word[0], CD_0, TSZ0)) |
| 194 | #define CD_TG(x, sel) ((sel) ? \ |
| 195 | FIELD_EX32((x)->word[0], CD_0, TG1) : \ |
| 196 | FIELD_EX32((x)->word[0], CD_0, TG0)) |
| 197 | #define CD_EPD(x, sel) ((sel) ? \ |
| 198 | FIELD_EX32((x)->word[0], CD_0, EPD1) : \ |
| 199 | FIELD_EX32((x)->word[0], CD_0, EPD0)) |
| 200 | #define CD_ENDI(x) FIELD_EX32((x)->word[0], CD_0, ENDI) |
| 201 | #define CD_VALID(x) FIELD_EX32((x)->word[0], CD_0, VALID) |
| 202 | #define CD_IPS(x) FIELD_EX32((x)->word[1], CD_1, IPS) |
| 203 | #define CD_AFFD(x) FIELD_EX32((x)->word[1], CD_1, AFFD) |
| 204 | #define CD_TBI(x) FIELD_EX32((x)->word[1], CD_1, TBI) |
| 205 | #define CD_AARCH64(x) FIELD_EX32((x)->word[1], CD_1, AARCH64) |
| 206 | #define CD_HD(x) FIELD_EX32((x)->word[1], CD_1, HD) |
| 207 | #define CD_HA(x) FIELD_EX32((x)->word[1], CD_1, HA) |
| 208 | #define CD_S(x) FIELD_EX32((x)->word[1], CD_1, S) |
| 209 | #define CD_R(x) FIELD_EX32((x)->word[1], CD_1, R) |
| 210 | #define CD_A(x) FIELD_EX32((x)->word[1], CD_1, A) |
| 211 | #define CD_ASID(x) FIELD_EX32((x)->word[1], CD_1, ASID) |
| 212 | #define CD_NSCFG(x, sel) ((sel) ? \ |
| 213 | FIELD_EX32((x)->word[4], CD_4, NSCFG1) : \ |
| 214 | FIELD_EX32((x)->word[2], CD_2, NSCFG0)) |
| 215 | #define CD_HAD(x, sel) ((sel) ? \ |
| 216 | FIELD_EX32((x)->word[4], CD_4, HAD1) : \ |
| 217 | FIELD_EX32((x)->word[2], CD_2, HAD0)) |
| 218 | #define CD_TTB(x, sel) \ |
| 219 | ((sel) ? (((uint64_t)FIELD_EX32((x)->word[5], CD_5, TTB1_HI) << 32) | \ |
| 220 | ((uint64_t)FIELD_EX32((x)->word[4], CD_4, TTB1_LO) << 4)) : \ |
| 221 | (((uint64_t)FIELD_EX32((x)->word[3], CD_3, TTB0_HI) << 32) | \ |
| 222 | ((uint64_t)FIELD_EX32((x)->word[2], CD_2, TTB0_LO) << 4))) |
| 223 | |
| 224 | /* Update CD fields */ |
| 225 | #define CD_SET_VALID(cd, v) \ |
| 226 | ((cd)->word[0] = FIELD_DP32((cd)->word[0], CD_0, VALID, (v))) |
| 227 | #define CD_SET_ASID(cd, v) \ |
| 228 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, ASID, (v))) |
| 229 | #define CD_SET_TTB(cd, sel, v) do { \ |
| 230 | if (sel) { \ |
| 231 | (cd)->word[4] = FIELD_DP32((cd)->word[4], CD_4, TTB1_LO, (v) >> 4); \ |
| 232 | (cd)->word[5] = FIELD_DP32((cd)->word[5], CD_5, TTB1_HI, (v) >> 32); \ |
| 233 | } else { \ |
| 234 | (cd)->word[2] = FIELD_DP32((cd)->word[2], CD_2, TTB0_LO, (v) >> 4); \ |
| 235 | (cd)->word[3] = FIELD_DP32((cd)->word[3], CD_3, TTB0_HI, (v) >> 32); \ |
| 236 | } \ |
| 237 | } while (0) |
| 238 | |
| 239 | #define CD_SET_TSZ(cd, sel, v) \ |
| 240 | ((cd)->word[0] = (sel) ? FIELD_DP32((cd)->word[0], CD_0, TSZ1, (v)) : \ |
| 241 | FIELD_DP32((cd)->word[0], CD_0, TSZ0, (v))) |
| 242 | #define CD_SET_TG(cd, sel, v) \ |
| 243 | ((cd)->word[0] = (sel) ? FIELD_DP32((cd)->word[0], CD_0, TG1, (v)) : \ |
| 244 | FIELD_DP32((cd)->word[0], CD_0, TG0, (v))) |
| 245 | #define CD_SET_EPD(cd, sel, v) \ |
| 246 | ((cd)->word[0] = (sel) ? FIELD_DP32((cd)->word[0], CD_0, EPD1, (v)) : \ |
| 247 | FIELD_DP32((cd)->word[0], CD_0, EPD0, (v))) |
| 248 | #define CD_SET_ENDI(cd, v) \ |
| 249 | ((cd)->word[0] = FIELD_DP32((cd)->word[0], CD_0, ENDI, (v))) |
| 250 | #define CD_SET_IPS(cd, v) \ |
| 251 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, IPS, (v))) |
| 252 | #define CD_SET_AFFD(cd, v) \ |
| 253 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, AFFD, (v))) |
| 254 | #define CD_SET_TBI(cd, v) \ |
| 255 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, TBI, (v))) |
| 256 | #define CD_SET_HD(cd, v) \ |
| 257 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, HD, (v))) |
| 258 | #define CD_SET_HA(cd, v) \ |
| 259 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, HA, (v))) |
| 260 | #define CD_SET_S(cd, v) \ |
| 261 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, S, (v))) |
| 262 | #define CD_SET_R(cd, v) \ |
| 263 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, R, (v))) |
| 264 | #define CD_SET_A(cd, v) \ |
| 265 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, A, (v))) |
| 266 | #define CD_SET_AARCH64(cd, v) \ |
| 267 | ((cd)->word[1] = FIELD_DP32((cd)->word[1], CD_1, AARCH64, (v))) |
| 268 | #define CD_SET_NSCFG(cd, sel, v) \ |
| 269 | ((sel) ? ((cd)->word[4] = FIELD_DP32((cd)->word[4], CD_4, NSCFG1, (v))) : \ |
| 270 | ((cd)->word[2] = FIELD_DP32((cd)->word[2], CD_2, NSCFG0, (v)))) |
| 271 | |
| 272 | /* MMIO Registers */ |
| 273 | |
| 274 | REG32(IDR0, 0x0) |
| 275 | FIELD(IDR0, S2P, 0 , 1) |
| 276 | FIELD(IDR0, S1P, 1 , 1) |
| 277 | FIELD(IDR0, TTF, 2 , 2) |
| 278 | FIELD(IDR0, COHACC, 4 , 1) |
| 279 | FIELD(IDR0, BTM, 5 , 1) |
| 280 | FIELD(IDR0, HTTU, 6 , 2) |
| 281 | FIELD(IDR0, DORMHINT, 8 , 1) |
| 282 | FIELD(IDR0, HYP, 9 , 1) |
| 283 | FIELD(IDR0, ATS, 10, 1) |
| 284 | FIELD(IDR0, NS1ATS, 11, 1) |
| 285 | FIELD(IDR0, ASID16, 12, 1) |
| 286 | FIELD(IDR0, MSI, 13, 1) |
| 287 | FIELD(IDR0, SEV, 14, 1) |
| 288 | FIELD(IDR0, ATOS, 15, 1) |
| 289 | FIELD(IDR0, PRI, 16, 1) |
| 290 | FIELD(IDR0, VMW, 17, 1) |
| 291 | FIELD(IDR0, VMID16, 18, 1) |
| 292 | FIELD(IDR0, CD2L, 19, 1) |
| 293 | FIELD(IDR0, VATOS, 20, 1) |
| 294 | FIELD(IDR0, TTENDIAN, 21, 2) |
| 295 | FIELD(IDR0, ATSRECERR, 23, 1) |
| 296 | FIELD(IDR0, STALL_MODEL, 24, 2) |
| 297 | FIELD(IDR0, TERM_MODEL, 26, 1) |
| 298 | FIELD(IDR0, STLEVEL, 27, 2) |
| 299 | FIELD(IDR0, RME_IMPL, 30, 1) |
| 300 | |
| 301 | REG32(IDR1, 0x4) |
| 302 | FIELD(IDR1, SIDSIZE, 0 , 6) |
| 303 | FIELD(IDR1, SSIDSIZE, 6 , 5) |
| 304 | FIELD(IDR1, PRIQS, 11, 5) |
| 305 | FIELD(IDR1, EVENTQS, 16, 5) |
| 306 | FIELD(IDR1, CMDQS, 21, 5) |
| 307 | FIELD(IDR1, ATTR_PERMS_OVR, 26, 1) |
| 308 | FIELD(IDR1, ATTR_TYPES_OVR, 27, 1) |
| 309 | FIELD(IDR1, REL, 28, 1) |
| 310 | FIELD(IDR1, QUEUES_PRESET, 29, 1) |
| 311 | FIELD(IDR1, TABLES_PRESET, 30, 1) |
| 312 | FIELD(IDR1, ECMDQ, 31, 1) |
| 313 | |
| 314 | #define SMMU_IDR1_SIDSIZE 16 |
| 315 | #define SMMU_CMDQS 19 |
| 316 | #define SMMU_EVENTQS 19 |
| 317 | |
| 318 | REG32(IDR2, 0x8) |
| 319 | FIELD(IDR2, BA_VATOS, 0, 10) |
| 320 | |
| 321 | REG32(IDR3, 0xc) |
| 322 | FIELD(IDR3, HAD, 2, 1); |
| 323 | FIELD(IDR3, PBHA, 3, 1); |
| 324 | FIELD(IDR3, XNX, 4, 1); |
| 325 | FIELD(IDR3, PPS, 5, 1); |
| 326 | FIELD(IDR3, MPAM, 7, 1); |
| 327 | FIELD(IDR3, FWB, 8, 1); |
| 328 | FIELD(IDR3, STT, 9, 1); |
| 329 | FIELD(IDR3, RIL, 10, 1); |
| 330 | FIELD(IDR3, BBML, 11, 2); |
| 331 | FIELD(IDR3, E0PD, 13, 1); |
| 332 | FIELD(IDR3, PTWNNC, 14, 1); |
| 333 | FIELD(IDR3, DPT, 15, 1); |
| 334 | |
| 335 | REG32(IDR4, 0x10) |
| 336 | |
| 337 | REG32(IDR5, 0x14) |
| 338 | FIELD(IDR5, OAS, 0, 3); |
| 339 | FIELD(IDR5, GRAN4K, 4, 1); |
| 340 | FIELD(IDR5, GRAN16K, 5, 1); |
| 341 | FIELD(IDR5, GRAN64K, 6, 1); |
| 342 | FIELD(IDR5, VAX, 10, 2); |
| 343 | FIELD(IDR5, STALL_MAX, 16, 16); |
| 344 | |
| 345 | #define SMMU_IDR5_OAS_44 4 |
| 346 | #define SMMU_IDR5_OAS_48 5 |
| 347 | |
| 348 | REG32(IIDR, 0x18) |
| 349 | REG32(AIDR, 0x1c) |
| 350 | REG32(CR0, 0x20) |
| 351 | FIELD(CR0, SMMUEN, 0, 1) |
| 352 | FIELD(CR0, EVENTQEN, 2, 1) |
| 353 | FIELD(CR0, CMDQEN, 3, 1) |
| 354 | |
| 355 | #define SMMU_CR0_RESERVED 0xFFFFFA20 |
| 356 | |
| 357 | REG32(CR0ACK, 0x24) |
| 358 | REG32(CR1, 0x28) |
| 359 | REG32(CR2, 0x2c) |
| 360 | REG32(STATUSR, 0x40) |
| 361 | REG32(GBPA, 0x44) |
| 362 | FIELD(GBPA, ABORT, 20, 1) |
| 363 | FIELD(GBPA, UPDATE, 31, 1) |
| 364 | |
| 365 | /* Use incoming. */ |
| 366 | #define SMMU_GBPA_RESET_VAL 0x1000 |
| 367 | |
| 368 | REG32(IRQ_CTRL, 0x50) |
| 369 | FIELD(IRQ_CTRL, GERROR_IRQEN, 0, 1) |
| 370 | FIELD(IRQ_CTRL, PRI_IRQEN, 1, 1) |
| 371 | FIELD(IRQ_CTRL, EVENTQ_IRQEN, 2, 1) |
| 372 | |
| 373 | REG32(IRQ_CTRL_ACK, 0x54) |
| 374 | REG32(GERROR, 0x60) |
| 375 | FIELD(GERROR, CMDQ_ERR, 0, 1) |
| 376 | FIELD(GERROR, EVENTQ_ABT_ERR, 2, 1) |
| 377 | FIELD(GERROR, PRIQ_ABT_ERR, 3, 1) |
| 378 | FIELD(GERROR, MSI_CMDQ_ABT_ERR, 4, 1) |
| 379 | FIELD(GERROR, MSI_EVENTQ_ABT_ERR, 5, 1) |
| 380 | FIELD(GERROR, MSI_PRIQ_ABT_ERR, 6, 1) |
| 381 | FIELD(GERROR, MSI_GERROR_ABT_ERR, 7, 1) |
| 382 | FIELD(GERROR, MSI_SFM_ERR, 8, 1) |
| 383 | |
| 384 | REG32(GERRORN, 0x64) |
| 385 | |
| 386 | #define A_GERROR_IRQ_CFG0 0x68 /* 64b */ |
| 387 | REG32(GERROR_IRQ_CFG1, 0x70) |
| 388 | REG32(GERROR_IRQ_CFG2, 0x74) |
| 389 | |
| 390 | #define A_STRTAB_BASE 0x80 /* 64b */ |
| 391 | |
| 392 | #define SMMU_BASE_ADDR_MASK 0xfffffffffffc0 |
| 393 | |
| 394 | REG32(STRTAB_BASE_CFG, 0x88) |
| 395 | FIELD(STRTAB_BASE_CFG, FMT, 16, 2) |
| 396 | FIELD(STRTAB_BASE_CFG, SPLIT, 6 , 5) |
| 397 | FIELD(STRTAB_BASE_CFG, LOG2SIZE, 0 , 6) |
| 398 | |
| 399 | #define A_CMDQ_BASE 0x90 /* 64b */ |
| 400 | REG32(CMDQ_PROD, 0x98) |
| 401 | REG32(CMDQ_CONS, 0x9c) |
| 402 | FIELD(CMDQ_CONS, ERR, 24, 7) |
| 403 | |
| 404 | #define A_EVENTQ_BASE 0xa0 /* 64b */ |
| 405 | REG32(EVENTQ_PROD, 0xa8) |
| 406 | REG32(EVENTQ_CONS, 0xac) |
| 407 | |
| 408 | #define A_EVENTQ_IRQ_CFG0 0xb0 /* 64b */ |
| 409 | REG32(EVENTQ_IRQ_CFG1, 0xb8) |
| 410 | REG32(EVENTQ_IRQ_CFG2, 0xbc) |
| 411 | |
| 412 | #define A_IDREGS 0xfd0 |
| 413 | |
| 414 | /* Commands */ |
| 415 | |
| 416 | typedef enum SMMUCommandType { |
| 417 | SMMU_CMD_NONE = 0x00, |
| 418 | SMMU_CMD_PREFETCH_CONFIG , |
| 419 | SMMU_CMD_PREFETCH_ADDR, |
| 420 | SMMU_CMD_CFGI_STE, |
| 421 | SMMU_CMD_CFGI_STE_RANGE, |
| 422 | SMMU_CMD_CFGI_CD, |
| 423 | SMMU_CMD_CFGI_CD_ALL, |
| 424 | SMMU_CMD_CFGI_ALL, |
| 425 | SMMU_CMD_TLBI_NH_ALL = 0x10, |
| 426 | SMMU_CMD_TLBI_NH_ASID, |
| 427 | SMMU_CMD_TLBI_NH_VA, |
| 428 | SMMU_CMD_TLBI_NH_VAA, |
| 429 | SMMU_CMD_TLBI_EL3_ALL = 0x18, |
| 430 | SMMU_CMD_TLBI_EL3_VA = 0x1a, |
| 431 | SMMU_CMD_TLBI_EL2_ALL = 0x20, |
| 432 | SMMU_CMD_TLBI_EL2_ASID, |
| 433 | SMMU_CMD_TLBI_EL2_VA, |
| 434 | SMMU_CMD_TLBI_EL2_VAA, |
| 435 | SMMU_CMD_TLBI_S12_VMALL = 0x28, |
| 436 | SMMU_CMD_TLBI_S2_IPA = 0x2a, |
| 437 | SMMU_CMD_TLBI_NSNH_ALL = 0x30, |
| 438 | SMMU_CMD_ATC_INV = 0x40, |
| 439 | SMMU_CMD_PRI_RESP, |
| 440 | SMMU_CMD_RESUME = 0x44, |
| 441 | SMMU_CMD_STALL_TERM, |
| 442 | SMMU_CMD_SYNC, |
| 443 | } SMMUCommandType; |
| 444 | |
| 445 | #endif /* HW_ARM_SMMUV3_COMMON_H */ |