1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017 - 2020, Broadcom 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <arch_helpers.h> 8*91f16700Schasinglulu #include <common/debug.h> 9*91f16700Schasinglulu #include <drivers/delay_timer.h> 10*91f16700Schasinglulu #include <lib/mmio.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <iommu.h> 13*91f16700Schasinglulu #include <platform_def.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #define SMMU_BASE 0x64000000 16*91f16700Schasinglulu #define ARM_SMMU_MAX_NUM_CNTXT_BANK 64 17*91f16700Schasinglulu #define SMMU_CTX_BANK_IDX_SECURE_CRMU 63 18*91f16700Schasinglulu #define ARM_SMMU_NUM_SECURE_MASTER 1 19*91f16700Schasinglulu #define ARM_SMMU_NSNUMCBO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \ 20*91f16700Schasinglulu ARM_SMMU_NUM_SECURE_MASTER) 21*91f16700Schasinglulu #define ARM_SMMU_NSNUMSMRGO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \ 22*91f16700Schasinglulu ARM_SMMU_NUM_SECURE_MASTER) 23*91f16700Schasinglulu /* Reserved Banks. */ 24*91f16700Schasinglulu #define SMMU_CTX_BANK_IDX (SMMU_CTX_BANK_IDX_SECURE_CRMU - \ 25*91f16700Schasinglulu ARM_SMMU_NUM_SECURE_MASTER) 26*91f16700Schasinglulu #define NUM_OF_SMRS 1 27*91f16700Schasinglulu 28*91f16700Schasinglulu #define STG1_WITH_STG2_BYPASS 1 29*91f16700Schasinglulu #define ARM_LPAE_PGTBL_PHYS_CRMU 0x880000000 30*91f16700Schasinglulu #define ARM_LPAE_PGTBL_PHYS 0x880200000 31*91f16700Schasinglulu #define ARM_LPAE_PGTBL_PTE_CNT 512 32*91f16700Schasinglulu #define ARM_LPAE_PTE_L1_BLOCK_SIZE 0x40000000 33*91f16700Schasinglulu #define ARM_LPAE_PTE_L1_ADDR_MASK 0x0000FFFFC0000000UL 34*91f16700Schasinglulu #define ARM_LPAE_PTE_TABLE 0x2UL 35*91f16700Schasinglulu #define ARM_LPAE_PTE_VALID 0x1UL 36*91f16700Schasinglulu #define ARM_LPAE_PTE_ATTRINDX 2 37*91f16700Schasinglulu #define ARM_LPAE_PTE_NS 5 38*91f16700Schasinglulu #define ARM_LPAE_PTE_AP 6 39*91f16700Schasinglulu #define ARM_LPAE_PTE_AP_EL1_RW 0x0 40*91f16700Schasinglulu #define ARM_LPAE_PTE_AP_EL0_RW 0x1 41*91f16700Schasinglulu #define ARM_LPAE_PTE_SH 8 42*91f16700Schasinglulu #define ARM_LPAE_PTE_SH_NON 0x0 43*91f16700Schasinglulu #define ARM_LPAE_PTE_SH_OUTER 0x2 44*91f16700Schasinglulu #define ARM_LPAE_PTE_SH_INNER 0x3 45*91f16700Schasinglulu #define ARM_LPAE_PTE_AF 10 46*91f16700Schasinglulu #define ARM_SMMU_RES_SIZE 0x80000 47*91f16700Schasinglulu 48*91f16700Schasinglulu #define ARM_LPAE_PTE_NSTABLE 0x8000000000000000UL 49*91f16700Schasinglulu #define ARM_LPAE_PTE_L1_INDEX_SHIFT 30 50*91f16700Schasinglulu #define ARM_LPAE_PTE_L1_INDEX_MASK 0x1ff 51*91f16700Schasinglulu #define ARM_LPAE_PTE_L0_INDEX_SHIFT 39 52*91f16700Schasinglulu #define ARM_LPAE_PTE_L0_INDEX_MASK 0x1ff 53*91f16700Schasinglulu #define ARM_LPAE_PTE_TABLE_MASK ~(0xfffUL) 54*91f16700Schasinglulu /* Configuration registers */ 55*91f16700Schasinglulu #define ARM_SMMU_GR0_sCR0 0x0 56*91f16700Schasinglulu #define sCR0_CLIENTPD (1 << 0) 57*91f16700Schasinglulu #define sCR0_GFRE (1 << 1) 58*91f16700Schasinglulu #define sCR0_GFIE (1 << 2) 59*91f16700Schasinglulu #define sCR0_GCFGFRE (1 << 4) 60*91f16700Schasinglulu #define sCR0_GCFGFIE (1 << 5) 61*91f16700Schasinglulu #define sCR0_USFCFG (1 << 10) 62*91f16700Schasinglulu #define sCR0_VMIDPNE (1 << 11) 63*91f16700Schasinglulu #define sCR0_PTM (1 << 12) 64*91f16700Schasinglulu #define sCR0_FB (1 << 13) 65*91f16700Schasinglulu #define sCR0_VMID16EN (1 << 31) 66*91f16700Schasinglulu #define sCR0_BSU_SHIFT 14 67*91f16700Schasinglulu #define sCR0_BSU_MASK 0x3 68*91f16700Schasinglulu #define ARM_SMMU_SMMU_SCR1 0x4 69*91f16700Schasinglulu #define SCR1_NSNUMCBO_MASK 0xFF 70*91f16700Schasinglulu #define SCR1_NSNUMCBO_SHIFT 0x0 71*91f16700Schasinglulu #define SCR1_NSNUMSMRGO_MASK 0xFF00 72*91f16700Schasinglulu #define SCR1_NSNUMSMRGO_SHIFT 0x8 73*91f16700Schasinglulu 74*91f16700Schasinglulu /* Identification registers */ 75*91f16700Schasinglulu #define ARM_SMMU_GR0_ID0 0x20 76*91f16700Schasinglulu #define ARM_SMMU_GR0_ID1 0x24 77*91f16700Schasinglulu #define ARM_SMMU_GR0_ID2 0x28 78*91f16700Schasinglulu #define ARM_SMMU_GR0_ID3 0x2c 79*91f16700Schasinglulu #define ARM_SMMU_GR0_ID4 0x30 80*91f16700Schasinglulu #define ARM_SMMU_GR0_ID5 0x34 81*91f16700Schasinglulu #define ARM_SMMU_GR0_ID6 0x38 82*91f16700Schasinglulu #define ARM_SMMU_GR0_ID7 0x3c 83*91f16700Schasinglulu #define ARM_SMMU_GR0_sGFSR 0x48 84*91f16700Schasinglulu #define ARM_SMMU_GR0_sGFSYNR0 0x50 85*91f16700Schasinglulu #define ARM_SMMU_GR0_sGFSYNR1 0x54 86*91f16700Schasinglulu #define ARM_SMMU_GR0_sGFSYNR2 0x58 87*91f16700Schasinglulu 88*91f16700Schasinglulu #define ID1_PAGESIZE (1U << 31) 89*91f16700Schasinglulu #define ID1_NUMPAGENDXB_SHIFT 28 90*91f16700Schasinglulu #define ID1_NUMPAGENDXB_MASK 7 91*91f16700Schasinglulu #define ID1_NUMS2CB_SHIFT 16 92*91f16700Schasinglulu #define ID1_NUMS2CB_MASK 0xff 93*91f16700Schasinglulu #define ID1_NUMCB_SHIFT 0 94*91f16700Schasinglulu #define ID1_NUMCB_MASK 0xff 95*91f16700Schasinglulu 96*91f16700Schasinglulu /* SMMU global address space */ 97*91f16700Schasinglulu #define ARM_SMMU_GR0(smmu) ((smmu)->base) 98*91f16700Schasinglulu #define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift)) 99*91f16700Schasinglulu 100*91f16700Schasinglulu /* Stream mapping registers */ 101*91f16700Schasinglulu #define ARM_SMMU_GR0_SMR(n) (0x800 + (n << 2)) 102*91f16700Schasinglulu #define SMR_VALID (1U << 31) 103*91f16700Schasinglulu #define SMR_MASK_SHIFT 16 104*91f16700Schasinglulu #define SMR_ID_SHIFT 0 105*91f16700Schasinglulu 106*91f16700Schasinglulu #define ARM_SMMU_GR0_S2CR(n) (0xc00 + (n << 2)) 107*91f16700Schasinglulu #define S2CR_CBNDX_SHIFT 0 108*91f16700Schasinglulu #define S2CR_CBNDX_MASK 0xff 109*91f16700Schasinglulu #define S2CR_TYPE_SHIFT 16 110*91f16700Schasinglulu #define S2CR_TYPE_MASK 0x3 111*91f16700Schasinglulu 112*91f16700Schasinglulu #define ARM_SMMU_GR1_CBA2R(n) (0x800 + (n << 2)) 113*91f16700Schasinglulu #define CBA2R_RW64_32BIT (0 << 0) 114*91f16700Schasinglulu #define CBA2R_RW64_64BIT (1 << 0) 115*91f16700Schasinglulu #define CBA2R_VMID_SHIFT 16 116*91f16700Schasinglulu #define CBA2R_VMID_MASK 0xffff 117*91f16700Schasinglulu 118*91f16700Schasinglulu #define ARM_SMMU_GR1_CBAR(n) (0x0 + (n << 2)) 119*91f16700Schasinglulu #define CBAR_VMID_SHIFT 0 120*91f16700Schasinglulu #define CBAR_VMID_MASK 0xff 121*91f16700Schasinglulu #define CBAR_S1_BPSHCFG_SHIFT 8 122*91f16700Schasinglulu #define CBAR_S1_BPSHCFG_MASK 3 123*91f16700Schasinglulu #define CBAR_S1_BPSHCFG_NSH 3 124*91f16700Schasinglulu #define CBAR_S1_MEMATTR_SHIFT 12 125*91f16700Schasinglulu #define CBAR_S1_MEMATTR_MASK 0xf 126*91f16700Schasinglulu #define CBAR_S1_MEMATTR_WB 0xf 127*91f16700Schasinglulu #define CBAR_TYPE_SHIFT 16 128*91f16700Schasinglulu #define CBAR_TYPE_MASK 0x3 129*91f16700Schasinglulu #define CBAR_TYPE_S2_TRANS (0 << CBAR_TYPE_SHIFT) 130*91f16700Schasinglulu #define CBAR_TYPE_S1_TRANS_S2_BYPASS (1 << CBAR_TYPE_SHIFT) 131*91f16700Schasinglulu #define CBAR_TYPE_S1_TRANS_S2_FAULT (2 << CBAR_TYPE_SHIFT) 132*91f16700Schasinglulu #define CBAR_TYPE_S1_TRANS_S2_TRANS (3 << CBAR_TYPE_SHIFT) 133*91f16700Schasinglulu #define CBAR_IRPTNDX_SHIFT 24 134*91f16700Schasinglulu #define CBAR_IRPTNDX_MASK 0xff 135*91f16700Schasinglulu 136*91f16700Schasinglulu /* Translation context bank */ 137*91f16700Schasinglulu #define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size >> 1)) 138*91f16700Schasinglulu #define ARM_SMMU_CB(smmu, n) ((n) * (1 << (smmu)->pgshift)) 139*91f16700Schasinglulu 140*91f16700Schasinglulu #define ARM_SMMU_CB_SCTLR 0x0 141*91f16700Schasinglulu #define ARM_SMMU_CB_ACTLR 0x4 142*91f16700Schasinglulu #define ARM_SMMU_CB_RESUME 0x8 143*91f16700Schasinglulu #define ARM_SMMU_CB_TTBCR2 0x10 144*91f16700Schasinglulu #define ARM_SMMU_CB_TTBR0 0x20 145*91f16700Schasinglulu #define ARM_SMMU_CB_TTBR1 0x28 146*91f16700Schasinglulu #define ARM_SMMU_CB_TTBCR 0x30 147*91f16700Schasinglulu #define ARM_SMMU_CB_CONTEXTIDR 0x34 148*91f16700Schasinglulu #define ARM_SMMU_CB_S1_MAIR0 0x38 149*91f16700Schasinglulu #define ARM_SMMU_CB_S1_MAIR1 0x3c 150*91f16700Schasinglulu #define ARM_SMMU_CB_PAR 0x50 151*91f16700Schasinglulu #define ARM_SMMU_CB_FSR 0x58 152*91f16700Schasinglulu #define ARM_SMMU_CB_FAR 0x60 153*91f16700Schasinglulu #define ARM_SMMU_CB_FSYNR0 0x68 154*91f16700Schasinglulu #define ARM_SMMU_CB_S1_TLBIVA 0x600 155*91f16700Schasinglulu #define ARM_SMMU_CB_S1_TLBIASID 0x610 156*91f16700Schasinglulu #define ARM_SMMU_CB_S1_TLBIVAL 0x620 157*91f16700Schasinglulu #define ARM_SMMU_CB_S2_TLBIIPAS2 0x630 158*91f16700Schasinglulu #define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638 159*91f16700Schasinglulu #define ARM_SMMU_CB_ATS1PR 0x800 160*91f16700Schasinglulu #define ARM_SMMU_CB_ATSR 0x8f0 161*91f16700Schasinglulu 162*91f16700Schasinglulu #define SCTLR_S1_ASIDPNE (1 << 12) 163*91f16700Schasinglulu #define SCTLR_CFCFG (1 << 7) 164*91f16700Schasinglulu #define SCTLR_CFIE (1 << 6) 165*91f16700Schasinglulu #define SCTLR_CFRE (1 << 5) 166*91f16700Schasinglulu #define SCTLR_E (1 << 4) 167*91f16700Schasinglulu #define SCTLR_AFE (1 << 2) 168*91f16700Schasinglulu #define SCTLR_TRE (1 << 1) 169*91f16700Schasinglulu #define SCTLR_M (1 << 0) 170*91f16700Schasinglulu 171*91f16700Schasinglulu /* ARM LPAE configuration. */ 172*91f16700Schasinglulu /**************************************************************/ 173*91f16700Schasinglulu /* Register bits */ 174*91f16700Schasinglulu #define ARM_32_LPAE_TCR_EAE (1 << 31) 175*91f16700Schasinglulu #define ARM_64_LPAE_S2_TCR_RES1 (1 << 31) 176*91f16700Schasinglulu 177*91f16700Schasinglulu #define ARM_LPAE_TCR_EPD1 (1 << 23) 178*91f16700Schasinglulu 179*91f16700Schasinglulu #define ARM_LPAE_TCR_TG0_4K (0 << 14) 180*91f16700Schasinglulu #define ARM_LPAE_TCR_TG0_64K (1 << 14) 181*91f16700Schasinglulu #define ARM_LPAE_TCR_TG0_16K (2 << 14) 182*91f16700Schasinglulu 183*91f16700Schasinglulu #define ARM_LPAE_TCR_SH0_SHIFT 12 184*91f16700Schasinglulu #define ARM_LPAE_TCR_SH0_MASK 0x3 185*91f16700Schasinglulu #define ARM_LPAE_TCR_SH_NS 0 186*91f16700Schasinglulu #define ARM_LPAE_TCR_SH_OS 2 187*91f16700Schasinglulu #define ARM_LPAE_TCR_SH_IS 3 188*91f16700Schasinglulu 189*91f16700Schasinglulu #define ARM_LPAE_TCR_ORGN0_SHIFT 10 190*91f16700Schasinglulu #define ARM_LPAE_TCR_IRGN0_SHIFT 8 191*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_MASK 0x3 192*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_NC 0 193*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_WBWA 1 194*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_WT 2 195*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_WB 3 196*91f16700Schasinglulu 197*91f16700Schasinglulu #define ARM_LPAE_TCR_SL0_SHIFT 6 198*91f16700Schasinglulu #define ARM_LPAE_TCR_SL0_MASK 0x3 199*91f16700Schasinglulu 200*91f16700Schasinglulu #define ARM_LPAE_TCR_T0SZ_SHIFT 0 201*91f16700Schasinglulu #define ARM_LPAE_TCR_SZ_MASK 0xf 202*91f16700Schasinglulu 203*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_SHIFT 16 204*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_MASK 0x7 205*91f16700Schasinglulu 206*91f16700Schasinglulu #define ARM_LPAE_TCR_IPS_SHIFT 32 207*91f16700Schasinglulu #define ARM_LPAE_TCR_IPS_MASK 0x7 208*91f16700Schasinglulu 209*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_32_BIT 0x0ULL 210*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_36_BIT 0x1ULL 211*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_40_BIT 0x2ULL 212*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_42_BIT 0x3ULL 213*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_44_BIT 0x4ULL 214*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_48_BIT 0x5ULL 215*91f16700Schasinglulu 216*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_SHIFT(n) ((n) << 3) 217*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_MASK 0xff 218*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_DEVICE 0x04 219*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_NC 0x44 220*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_WBRWA 0xff 221*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_IDX_NC 0 222*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_IDX_CACHE 1 223*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_IDX_DEV 2 224*91f16700Schasinglulu 225*91f16700Schasinglulu #define TTBRn_ASID_SHIFT 48 226*91f16700Schasinglulu #define TTBCR2_SEP_SHIFT 15 227*91f16700Schasinglulu #define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT) 228*91f16700Schasinglulu #define TTBCR2_AS (1 << 4) 229*91f16700Schasinglulu #define TTBCR_T0SZ(ia_bits) (64 - (ia_bits)) 230*91f16700Schasinglulu 231*91f16700Schasinglulu #define S2CR_PRIVCFG_SHIFT 24 232*91f16700Schasinglulu #define S2CR_PRIVCFG_MASK 0x3 233*91f16700Schasinglulu 234*91f16700Schasinglulu /**************************************************************/ 235*91f16700Schasinglulu 236*91f16700Schasinglulu uint16_t paxc_stream_ids[] = { 0x2000 }; 237*91f16700Schasinglulu 238*91f16700Schasinglulu uint16_t paxc_stream_ids_mask[] = { 0x1fff }; 239*91f16700Schasinglulu uint16_t crmu_stream_ids[] = { CRMU_STREAM_ID }; 240*91f16700Schasinglulu uint16_t crmu_stream_ids_mask[] = { 0x0 }; 241*91f16700Schasinglulu 242*91f16700Schasinglulu enum arm_smmu_s2cr_type { 243*91f16700Schasinglulu S2CR_TYPE_TRANS, 244*91f16700Schasinglulu S2CR_TYPE_BYPASS, 245*91f16700Schasinglulu S2CR_TYPE_FAULT, 246*91f16700Schasinglulu }; 247*91f16700Schasinglulu 248*91f16700Schasinglulu enum arm_smmu_s2cr_privcfg { 249*91f16700Schasinglulu S2CR_PRIVCFG_DEFAULT, 250*91f16700Schasinglulu S2CR_PRIVCFG_DIPAN, 251*91f16700Schasinglulu S2CR_PRIVCFG_UNPRIV, 252*91f16700Schasinglulu S2CR_PRIVCFG_PRIV, 253*91f16700Schasinglulu }; 254*91f16700Schasinglulu 255*91f16700Schasinglulu struct arm_smmu_smr { 256*91f16700Schasinglulu uint16_t mask; 257*91f16700Schasinglulu uint16_t id; 258*91f16700Schasinglulu uint32_t valid; 259*91f16700Schasinglulu }; 260*91f16700Schasinglulu 261*91f16700Schasinglulu struct arm_smmu_s2cr { 262*91f16700Schasinglulu int count; 263*91f16700Schasinglulu enum arm_smmu_s2cr_type type; 264*91f16700Schasinglulu enum arm_smmu_s2cr_privcfg privcfg; 265*91f16700Schasinglulu uint8_t cbndx; 266*91f16700Schasinglulu }; 267*91f16700Schasinglulu 268*91f16700Schasinglulu struct arm_smmu_cfg { 269*91f16700Schasinglulu uint8_t cbndx; 270*91f16700Schasinglulu uint8_t irptndx; 271*91f16700Schasinglulu uint32_t cbar; 272*91f16700Schasinglulu }; 273*91f16700Schasinglulu 274*91f16700Schasinglulu struct arm_smmu_device { 275*91f16700Schasinglulu uint8_t *base; 276*91f16700Schasinglulu uint32_t streams; 277*91f16700Schasinglulu unsigned long size; 278*91f16700Schasinglulu unsigned long pgshift; 279*91f16700Schasinglulu unsigned long va_size; 280*91f16700Schasinglulu unsigned long ipa_size; 281*91f16700Schasinglulu unsigned long pa_size; 282*91f16700Schasinglulu struct arm_smmu_smr smr[NUM_OF_SMRS]; 283*91f16700Schasinglulu struct arm_smmu_s2cr s2cr[NUM_OF_SMRS]; 284*91f16700Schasinglulu struct arm_smmu_cfg cfg[NUM_OF_SMRS]; 285*91f16700Schasinglulu uint16_t *stream_ids; 286*91f16700Schasinglulu uint16_t *stream_ids_mask; 287*91f16700Schasinglulu }; 288*91f16700Schasinglulu 289*91f16700Schasinglulu void arm_smmu_enable_secure_client_port(void) 290*91f16700Schasinglulu { 291*91f16700Schasinglulu uintptr_t smmu_base = SMMU_BASE; 292*91f16700Schasinglulu 293*91f16700Schasinglulu mmio_clrbits_32(smmu_base, sCR0_CLIENTPD); 294*91f16700Schasinglulu } 295*91f16700Schasinglulu 296*91f16700Schasinglulu void arm_smmu_reserve_secure_cntxt(void) 297*91f16700Schasinglulu { 298*91f16700Schasinglulu uintptr_t smmu_base = SMMU_BASE; 299*91f16700Schasinglulu 300*91f16700Schasinglulu mmio_clrsetbits_32(smmu_base + ARM_SMMU_SMMU_SCR1, 301*91f16700Schasinglulu (SCR1_NSNUMSMRGO_MASK | SCR1_NSNUMCBO_MASK), 302*91f16700Schasinglulu ((ARM_SMMU_NSNUMCBO << SCR1_NSNUMCBO_SHIFT) | 303*91f16700Schasinglulu (ARM_SMMU_NSNUMSMRGO << SCR1_NSNUMSMRGO_SHIFT))); 304*91f16700Schasinglulu } 305*91f16700Schasinglulu 306*91f16700Schasinglulu static void arm_smmu_smr_cfg(struct arm_smmu_device *smmu, uint32_t index) 307*91f16700Schasinglulu { 308*91f16700Schasinglulu uint32_t idx = smmu->cfg[index].cbndx; 309*91f16700Schasinglulu struct arm_smmu_smr *smr = &smmu->smr[index]; 310*91f16700Schasinglulu uint32_t reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT; 311*91f16700Schasinglulu 312*91f16700Schasinglulu if (smr->valid) 313*91f16700Schasinglulu reg |= SMR_VALID; 314*91f16700Schasinglulu 315*91f16700Schasinglulu mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) + 316*91f16700Schasinglulu ARM_SMMU_GR0_SMR(idx)), reg); 317*91f16700Schasinglulu } 318*91f16700Schasinglulu 319*91f16700Schasinglulu static void arm_smmu_s2cr_cfg(struct arm_smmu_device *smmu, uint32_t index) 320*91f16700Schasinglulu { 321*91f16700Schasinglulu uint32_t idx = smmu->cfg[index].cbndx; 322*91f16700Schasinglulu struct arm_smmu_s2cr *s2cr = &smmu->s2cr[index]; 323*91f16700Schasinglulu 324*91f16700Schasinglulu uint32_t reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT | 325*91f16700Schasinglulu (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT | 326*91f16700Schasinglulu (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT; 327*91f16700Schasinglulu 328*91f16700Schasinglulu mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) + 329*91f16700Schasinglulu ARM_SMMU_GR0_S2CR(idx)), reg); 330*91f16700Schasinglulu } 331*91f16700Schasinglulu 332*91f16700Schasinglulu static void smmu_set_pgtbl(struct arm_smmu_device *smmu, 333*91f16700Schasinglulu enum iommu_domain dom, 334*91f16700Schasinglulu uint64_t *pg_table_base) 335*91f16700Schasinglulu { 336*91f16700Schasinglulu int i, l0_index, l1_index; 337*91f16700Schasinglulu uint64_t addr, *pte, *l0_base, *l1_base; 338*91f16700Schasinglulu uint64_t addr_space_limit; 339*91f16700Schasinglulu 340*91f16700Schasinglulu if (dom == PCIE_PAXC) { 341*91f16700Schasinglulu addr_space_limit = 0xffffffffff; 342*91f16700Schasinglulu } else if (dom == DOMAIN_CRMU) { 343*91f16700Schasinglulu addr_space_limit = 0xffffffff; 344*91f16700Schasinglulu } else { 345*91f16700Schasinglulu ERROR("dom is not supported\n"); 346*91f16700Schasinglulu return; 347*91f16700Schasinglulu } 348*91f16700Schasinglulu 349*91f16700Schasinglulu l0_base = pg_table_base; 350*91f16700Schasinglulu /* clear L0 descriptors. */ 351*91f16700Schasinglulu for (i = 0; i < ARM_LPAE_PGTBL_PTE_CNT; i++) 352*91f16700Schasinglulu l0_base[i] = 0x0; 353*91f16700Schasinglulu 354*91f16700Schasinglulu addr = 0x0; 355*91f16700Schasinglulu while (addr < addr_space_limit) { 356*91f16700Schasinglulu /* find L0 pte */ 357*91f16700Schasinglulu l0_index = ((addr >> ARM_LPAE_PTE_L0_INDEX_SHIFT) & 358*91f16700Schasinglulu ARM_LPAE_PTE_L0_INDEX_MASK); 359*91f16700Schasinglulu l1_base = l0_base + ((l0_index + 1) * ARM_LPAE_PGTBL_PTE_CNT); 360*91f16700Schasinglulu 361*91f16700Schasinglulu /* setup L0 pte if required */ 362*91f16700Schasinglulu pte = l0_base + l0_index; 363*91f16700Schasinglulu if (*pte == 0x0) { 364*91f16700Schasinglulu *pte |= ((uint64_t)l1_base & ARM_LPAE_PTE_TABLE_MASK); 365*91f16700Schasinglulu if (dom == PCIE_PAXC) 366*91f16700Schasinglulu *pte |= ARM_LPAE_PTE_NSTABLE; 367*91f16700Schasinglulu *pte |= ARM_LPAE_PTE_TABLE; 368*91f16700Schasinglulu *pte |= ARM_LPAE_PTE_VALID; 369*91f16700Schasinglulu } 370*91f16700Schasinglulu 371*91f16700Schasinglulu /* find L1 pte */ 372*91f16700Schasinglulu l1_index = ((addr >> ARM_LPAE_PTE_L1_INDEX_SHIFT) & 373*91f16700Schasinglulu ARM_LPAE_PTE_L1_INDEX_MASK); 374*91f16700Schasinglulu pte = l1_base + l1_index; 375*91f16700Schasinglulu 376*91f16700Schasinglulu /* setup L1 pte */ 377*91f16700Schasinglulu *pte = 0x0; 378*91f16700Schasinglulu *pte |= (addr & ARM_LPAE_PTE_L1_ADDR_MASK); 379*91f16700Schasinglulu if (addr < 0x80000000) { 380*91f16700Schasinglulu *pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV << 381*91f16700Schasinglulu ARM_LPAE_PTE_ATTRINDX); 382*91f16700Schasinglulu if (dom == PCIE_PAXC) 383*91f16700Schasinglulu *pte |= (1 << ARM_LPAE_PTE_NS); 384*91f16700Schasinglulu } else { 385*91f16700Schasinglulu *pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE << 386*91f16700Schasinglulu ARM_LPAE_PTE_ATTRINDX); 387*91f16700Schasinglulu *pte |= (1 << ARM_LPAE_PTE_NS); 388*91f16700Schasinglulu } 389*91f16700Schasinglulu *pte |= (ARM_LPAE_PTE_AP_EL0_RW << ARM_LPAE_PTE_AP); 390*91f16700Schasinglulu *pte |= (ARM_LPAE_PTE_SH_INNER << ARM_LPAE_PTE_SH); 391*91f16700Schasinglulu *pte |= (1 << ARM_LPAE_PTE_AF); 392*91f16700Schasinglulu *pte |= ARM_LPAE_PTE_VALID; 393*91f16700Schasinglulu 394*91f16700Schasinglulu addr += ARM_LPAE_PTE_L1_BLOCK_SIZE; 395*91f16700Schasinglulu } 396*91f16700Schasinglulu } 397*91f16700Schasinglulu 398*91f16700Schasinglulu void arm_smmu_create_identity_map(enum iommu_domain dom) 399*91f16700Schasinglulu { 400*91f16700Schasinglulu struct arm_smmu_device iommu; 401*91f16700Schasinglulu struct arm_smmu_device *smmu = &iommu; 402*91f16700Schasinglulu uint32_t reg, reg2; 403*91f16700Schasinglulu unsigned long long reg64; 404*91f16700Schasinglulu uint32_t idx; 405*91f16700Schasinglulu uint16_t asid; 406*91f16700Schasinglulu unsigned int context_bank_index; 407*91f16700Schasinglulu unsigned long long pg_table_base; 408*91f16700Schasinglulu 409*91f16700Schasinglulu smmu->base = (uint8_t *) SMMU_BASE; 410*91f16700Schasinglulu reg = mmio_read_32((uintptr_t) (ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_ID1)); 411*91f16700Schasinglulu smmu->pgshift = (reg & ID1_PAGESIZE) ? 16 : 12; 412*91f16700Schasinglulu smmu->size = ARM_SMMU_RES_SIZE; 413*91f16700Schasinglulu smmu->stream_ids = NULL; 414*91f16700Schasinglulu 415*91f16700Schasinglulu switch (dom) { 416*91f16700Schasinglulu case PCIE_PAXC: 417*91f16700Schasinglulu smmu->stream_ids = &paxc_stream_ids[0]; 418*91f16700Schasinglulu smmu->stream_ids_mask = &paxc_stream_ids_mask[0]; 419*91f16700Schasinglulu smmu->streams = ARRAY_SIZE(paxc_stream_ids); 420*91f16700Schasinglulu context_bank_index = SMMU_CTX_BANK_IDX; 421*91f16700Schasinglulu pg_table_base = ARM_LPAE_PGTBL_PHYS; 422*91f16700Schasinglulu break; 423*91f16700Schasinglulu case DOMAIN_CRMU: 424*91f16700Schasinglulu smmu->stream_ids = &crmu_stream_ids[0]; 425*91f16700Schasinglulu smmu->stream_ids_mask = &crmu_stream_ids_mask[0]; 426*91f16700Schasinglulu smmu->streams = ARRAY_SIZE(crmu_stream_ids); 427*91f16700Schasinglulu context_bank_index = SMMU_CTX_BANK_IDX_SECURE_CRMU; 428*91f16700Schasinglulu pg_table_base = ARM_LPAE_PGTBL_PHYS_CRMU; 429*91f16700Schasinglulu break; 430*91f16700Schasinglulu default: 431*91f16700Schasinglulu ERROR("domain not supported\n"); 432*91f16700Schasinglulu return; 433*91f16700Schasinglulu } 434*91f16700Schasinglulu 435*91f16700Schasinglulu if (smmu->streams > NUM_OF_SMRS) { 436*91f16700Schasinglulu INFO("can not support more than %d sids\n", NUM_OF_SMRS); 437*91f16700Schasinglulu return; 438*91f16700Schasinglulu } 439*91f16700Schasinglulu 440*91f16700Schasinglulu /* set up iommu dev. */ 441*91f16700Schasinglulu for (idx = 0; idx < smmu->streams; idx++) { 442*91f16700Schasinglulu /* S2CR. */ 443*91f16700Schasinglulu smmu->s2cr[idx].type = S2CR_TYPE_TRANS; 444*91f16700Schasinglulu smmu->s2cr[idx].privcfg = S2CR_PRIVCFG_DEFAULT; 445*91f16700Schasinglulu smmu->s2cr[idx].cbndx = context_bank_index; 446*91f16700Schasinglulu smmu->cfg[idx].cbndx = context_bank_index; 447*91f16700Schasinglulu smmu->cfg[idx].cbar = STG1_WITH_STG2_BYPASS << CBAR_TYPE_SHIFT; 448*91f16700Schasinglulu arm_smmu_s2cr_cfg(smmu, idx); 449*91f16700Schasinglulu 450*91f16700Schasinglulu /* SMR. */ 451*91f16700Schasinglulu smmu->smr[idx].mask = smmu->stream_ids_mask[idx]; 452*91f16700Schasinglulu smmu->smr[idx].id = smmu->stream_ids[idx]; 453*91f16700Schasinglulu smmu->smr[idx].valid = 1; 454*91f16700Schasinglulu arm_smmu_smr_cfg(smmu, idx); 455*91f16700Schasinglulu 456*91f16700Schasinglulu /* CBA2R. 64-bit Translation */ 457*91f16700Schasinglulu mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) + 458*91f16700Schasinglulu ARM_SMMU_GR1_CBA2R(smmu->cfg[idx].cbndx)), 459*91f16700Schasinglulu 0x1); 460*91f16700Schasinglulu /* CBAR.*/ 461*91f16700Schasinglulu reg = smmu->cfg[idx].cbar; 462*91f16700Schasinglulu reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) | 463*91f16700Schasinglulu (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); 464*91f16700Schasinglulu 465*91f16700Schasinglulu mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) + 466*91f16700Schasinglulu ARM_SMMU_GR1_CBAR(smmu->cfg[idx].cbndx)), 467*91f16700Schasinglulu reg); 468*91f16700Schasinglulu 469*91f16700Schasinglulu /* TTBCR. */ 470*91f16700Schasinglulu reg64 = (ARM_LPAE_TCR_SH_IS << ARM_LPAE_TCR_SH0_SHIFT) | 471*91f16700Schasinglulu (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) | 472*91f16700Schasinglulu (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT); 473*91f16700Schasinglulu reg64 |= ARM_LPAE_TCR_TG0_4K; 474*91f16700Schasinglulu reg64 |= (ARM_LPAE_TCR_PS_40_BIT << ARM_LPAE_TCR_IPS_SHIFT); 475*91f16700Schasinglulu /* ias 40 bits.*/ 476*91f16700Schasinglulu reg64 |= TTBCR_T0SZ(40) << ARM_LPAE_TCR_T0SZ_SHIFT; 477*91f16700Schasinglulu /* Disable speculative walks through TTBR1 */ 478*91f16700Schasinglulu reg64 |= ARM_LPAE_TCR_EPD1; 479*91f16700Schasinglulu reg = (uint32_t) reg64; 480*91f16700Schasinglulu reg2 = (uint32_t) (reg64 >> 32); 481*91f16700Schasinglulu reg2 |= TTBCR2_SEP_UPSTREAM; 482*91f16700Schasinglulu reg2 |= TTBCR2_AS; 483*91f16700Schasinglulu 484*91f16700Schasinglulu mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + 485*91f16700Schasinglulu ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + 486*91f16700Schasinglulu ARM_SMMU_CB_TTBCR2), reg2); 487*91f16700Schasinglulu 488*91f16700Schasinglulu mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + 489*91f16700Schasinglulu ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + 490*91f16700Schasinglulu ARM_SMMU_CB_TTBCR), reg); 491*91f16700Schasinglulu 492*91f16700Schasinglulu /* TTBR0. */ 493*91f16700Schasinglulu asid = smmu->cfg[idx].cbndx; 494*91f16700Schasinglulu reg64 = pg_table_base; 495*91f16700Schasinglulu reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT; 496*91f16700Schasinglulu 497*91f16700Schasinglulu mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + 498*91f16700Schasinglulu ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + 499*91f16700Schasinglulu ARM_SMMU_CB_TTBR0), reg64); 500*91f16700Schasinglulu /* TTBR1. */ 501*91f16700Schasinglulu reg64 = 0; 502*91f16700Schasinglulu reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT; 503*91f16700Schasinglulu 504*91f16700Schasinglulu mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + 505*91f16700Schasinglulu ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + 506*91f16700Schasinglulu ARM_SMMU_CB_TTBR1), reg64); 507*91f16700Schasinglulu /* MAIR. */ 508*91f16700Schasinglulu reg = (ARM_LPAE_MAIR_ATTR_NC 509*91f16700Schasinglulu << ARM_LPAE_MAIR_ATTR_SHIFT 510*91f16700Schasinglulu (ARM_LPAE_MAIR_ATTR_IDX_NC)) | 511*91f16700Schasinglulu (ARM_LPAE_MAIR_ATTR_WBRWA << 512*91f16700Schasinglulu ARM_LPAE_MAIR_ATTR_SHIFT 513*91f16700Schasinglulu (ARM_LPAE_MAIR_ATTR_IDX_CACHE)) | 514*91f16700Schasinglulu (ARM_LPAE_MAIR_ATTR_DEVICE << 515*91f16700Schasinglulu ARM_LPAE_MAIR_ATTR_SHIFT 516*91f16700Schasinglulu (ARM_LPAE_MAIR_ATTR_IDX_DEV)); 517*91f16700Schasinglulu 518*91f16700Schasinglulu mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + 519*91f16700Schasinglulu ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + 520*91f16700Schasinglulu ARM_SMMU_CB_S1_MAIR0), reg); 521*91f16700Schasinglulu 522*91f16700Schasinglulu /* MAIR1. */ 523*91f16700Schasinglulu reg = 0; 524*91f16700Schasinglulu mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + 525*91f16700Schasinglulu ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + 526*91f16700Schasinglulu ARM_SMMU_CB_S1_MAIR1), reg); 527*91f16700Schasinglulu /* SCTLR. */ 528*91f16700Schasinglulu reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | SCTLR_M; 529*91f16700Schasinglulu /* stage 1.*/ 530*91f16700Schasinglulu reg |= SCTLR_S1_ASIDPNE; 531*91f16700Schasinglulu mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + 532*91f16700Schasinglulu ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + 533*91f16700Schasinglulu ARM_SMMU_CB_SCTLR), reg); 534*91f16700Schasinglulu } 535*91f16700Schasinglulu smmu_set_pgtbl(smmu, dom, (uint64_t *)pg_table_base); 536*91f16700Schasinglulu } 537