| /* |
| * Copyright (c) 2017 - 2020, Broadcom |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include <arch_helpers.h> |
| #include <common/debug.h> |
| #include <drivers/delay_timer.h> |
| #include <lib/mmio.h> |
| |
| #include <iommu.h> |
| #include <platform_def.h> |
| |
| #define SMMU_BASE 0x64000000 |
| #define ARM_SMMU_MAX_NUM_CNTXT_BANK 64 |
| #define SMMU_CTX_BANK_IDX_SECURE_CRMU 63 |
| #define ARM_SMMU_NUM_SECURE_MASTER 1 |
| #define ARM_SMMU_NSNUMCBO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \ |
| ARM_SMMU_NUM_SECURE_MASTER) |
| #define ARM_SMMU_NSNUMSMRGO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \ |
| ARM_SMMU_NUM_SECURE_MASTER) |
| /* Reserved Banks. */ |
| #define SMMU_CTX_BANK_IDX (SMMU_CTX_BANK_IDX_SECURE_CRMU - \ |
| ARM_SMMU_NUM_SECURE_MASTER) |
| #define NUM_OF_SMRS 1 |
| |
| #define STG1_WITH_STG2_BYPASS 1 |
| #define ARM_LPAE_PGTBL_PHYS_CRMU 0x880000000 |
| #define ARM_LPAE_PGTBL_PHYS 0x880200000 |
| #define ARM_LPAE_PGTBL_PTE_CNT 512 |
| #define ARM_LPAE_PTE_L1_BLOCK_SIZE 0x40000000 |
| #define ARM_LPAE_PTE_L1_ADDR_MASK 0x0000FFFFC0000000UL |
| #define ARM_LPAE_PTE_TABLE 0x2UL |
| #define ARM_LPAE_PTE_VALID 0x1UL |
| #define ARM_LPAE_PTE_ATTRINDX 2 |
| #define ARM_LPAE_PTE_NS 5 |
| #define ARM_LPAE_PTE_AP 6 |
| #define ARM_LPAE_PTE_AP_EL1_RW 0x0 |
| #define ARM_LPAE_PTE_AP_EL0_RW 0x1 |
| #define ARM_LPAE_PTE_SH 8 |
| #define ARM_LPAE_PTE_SH_NON 0x0 |
| #define ARM_LPAE_PTE_SH_OUTER 0x2 |
| #define ARM_LPAE_PTE_SH_INNER 0x3 |
| #define ARM_LPAE_PTE_AF 10 |
| #define ARM_SMMU_RES_SIZE 0x80000 |
| |
| #define ARM_LPAE_PTE_NSTABLE 0x8000000000000000UL |
| #define ARM_LPAE_PTE_L1_INDEX_SHIFT 30 |
| #define ARM_LPAE_PTE_L1_INDEX_MASK 0x1ff |
| #define ARM_LPAE_PTE_L0_INDEX_SHIFT 39 |
| #define ARM_LPAE_PTE_L0_INDEX_MASK 0x1ff |
| #define ARM_LPAE_PTE_TABLE_MASK ~(0xfffUL) |
| /* Configuration registers */ |
| #define ARM_SMMU_GR0_sCR0 0x0 |
| #define sCR0_CLIENTPD (1 << 0) |
| #define sCR0_GFRE (1 << 1) |
| #define sCR0_GFIE (1 << 2) |
| #define sCR0_GCFGFRE (1 << 4) |
| #define sCR0_GCFGFIE (1 << 5) |
| #define sCR0_USFCFG (1 << 10) |
| #define sCR0_VMIDPNE (1 << 11) |
| #define sCR0_PTM (1 << 12) |
| #define sCR0_FB (1 << 13) |
| #define sCR0_VMID16EN (1 << 31) |
| #define sCR0_BSU_SHIFT 14 |
| #define sCR0_BSU_MASK 0x3 |
| #define ARM_SMMU_SMMU_SCR1 0x4 |
| #define SCR1_NSNUMCBO_MASK 0xFF |
| #define SCR1_NSNUMCBO_SHIFT 0x0 |
| #define SCR1_NSNUMSMRGO_MASK 0xFF00 |
| #define SCR1_NSNUMSMRGO_SHIFT 0x8 |
| |
| /* Identification registers */ |
| #define ARM_SMMU_GR0_ID0 0x20 |
| #define ARM_SMMU_GR0_ID1 0x24 |
| #define ARM_SMMU_GR0_ID2 0x28 |
| #define ARM_SMMU_GR0_ID3 0x2c |
| #define ARM_SMMU_GR0_ID4 0x30 |
| #define ARM_SMMU_GR0_ID5 0x34 |
| #define ARM_SMMU_GR0_ID6 0x38 |
| #define ARM_SMMU_GR0_ID7 0x3c |
| #define ARM_SMMU_GR0_sGFSR 0x48 |
| #define ARM_SMMU_GR0_sGFSYNR0 0x50 |
| #define ARM_SMMU_GR0_sGFSYNR1 0x54 |
| #define ARM_SMMU_GR0_sGFSYNR2 0x58 |
| |
| #define ID1_PAGESIZE (1U << 31) |
| #define ID1_NUMPAGENDXB_SHIFT 28 |
| #define ID1_NUMPAGENDXB_MASK 7 |
| #define ID1_NUMS2CB_SHIFT 16 |
| #define ID1_NUMS2CB_MASK 0xff |
| #define ID1_NUMCB_SHIFT 0 |
| #define ID1_NUMCB_MASK 0xff |
| |
| /* SMMU global address space */ |
| #define ARM_SMMU_GR0(smmu) ((smmu)->base) |
| #define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift)) |
| |
| /* Stream mapping registers */ |
| #define ARM_SMMU_GR0_SMR(n) (0x800 + (n << 2)) |
| #define SMR_VALID (1U << 31) |
| #define SMR_MASK_SHIFT 16 |
| #define SMR_ID_SHIFT 0 |
| |
| #define ARM_SMMU_GR0_S2CR(n) (0xc00 + (n << 2)) |
| #define S2CR_CBNDX_SHIFT 0 |
| #define S2CR_CBNDX_MASK 0xff |
| #define S2CR_TYPE_SHIFT 16 |
| #define S2CR_TYPE_MASK 0x3 |
| |
| #define ARM_SMMU_GR1_CBA2R(n) (0x800 + (n << 2)) |
| #define CBA2R_RW64_32BIT (0 << 0) |
| #define CBA2R_RW64_64BIT (1 << 0) |
| #define CBA2R_VMID_SHIFT 16 |
| #define CBA2R_VMID_MASK 0xffff |
| |
| #define ARM_SMMU_GR1_CBAR(n) (0x0 + (n << 2)) |
| #define CBAR_VMID_SHIFT 0 |
| #define CBAR_VMID_MASK 0xff |
| #define CBAR_S1_BPSHCFG_SHIFT 8 |
| #define CBAR_S1_BPSHCFG_MASK 3 |
| #define CBAR_S1_BPSHCFG_NSH 3 |
| #define CBAR_S1_MEMATTR_SHIFT 12 |
| #define CBAR_S1_MEMATTR_MASK 0xf |
| #define CBAR_S1_MEMATTR_WB 0xf |
| #define CBAR_TYPE_SHIFT 16 |
| #define CBAR_TYPE_MASK 0x3 |
| #define CBAR_TYPE_S2_TRANS (0 << CBAR_TYPE_SHIFT) |
| #define CBAR_TYPE_S1_TRANS_S2_BYPASS (1 << CBAR_TYPE_SHIFT) |
| #define CBAR_TYPE_S1_TRANS_S2_FAULT (2 << CBAR_TYPE_SHIFT) |
| #define CBAR_TYPE_S1_TRANS_S2_TRANS (3 << CBAR_TYPE_SHIFT) |
| #define CBAR_IRPTNDX_SHIFT 24 |
| #define CBAR_IRPTNDX_MASK 0xff |
| |
| /* Translation context bank */ |
| #define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size >> 1)) |
| #define ARM_SMMU_CB(smmu, n) ((n) * (1 << (smmu)->pgshift)) |
| |
| #define ARM_SMMU_CB_SCTLR 0x0 |
| #define ARM_SMMU_CB_ACTLR 0x4 |
| #define ARM_SMMU_CB_RESUME 0x8 |
| #define ARM_SMMU_CB_TTBCR2 0x10 |
| #define ARM_SMMU_CB_TTBR0 0x20 |
| #define ARM_SMMU_CB_TTBR1 0x28 |
| #define ARM_SMMU_CB_TTBCR 0x30 |
| #define ARM_SMMU_CB_CONTEXTIDR 0x34 |
| #define ARM_SMMU_CB_S1_MAIR0 0x38 |
| #define ARM_SMMU_CB_S1_MAIR1 0x3c |
| #define ARM_SMMU_CB_PAR 0x50 |
| #define ARM_SMMU_CB_FSR 0x58 |
| #define ARM_SMMU_CB_FAR 0x60 |
| #define ARM_SMMU_CB_FSYNR0 0x68 |
| #define ARM_SMMU_CB_S1_TLBIVA 0x600 |
| #define ARM_SMMU_CB_S1_TLBIASID 0x610 |
| #define ARM_SMMU_CB_S1_TLBIVAL 0x620 |
| #define ARM_SMMU_CB_S2_TLBIIPAS2 0x630 |
| #define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638 |
| #define ARM_SMMU_CB_ATS1PR 0x800 |
| #define ARM_SMMU_CB_ATSR 0x8f0 |
| |
| #define SCTLR_S1_ASIDPNE (1 << 12) |
| #define SCTLR_CFCFG (1 << 7) |
| #define SCTLR_CFIE (1 << 6) |
| #define SCTLR_CFRE (1 << 5) |
| #define SCTLR_E (1 << 4) |
| #define SCTLR_AFE (1 << 2) |
| #define SCTLR_TRE (1 << 1) |
| #define SCTLR_M (1 << 0) |
| |
| /* ARM LPAE configuration. */ |
| /**************************************************************/ |
| /* Register bits */ |
| #define ARM_32_LPAE_TCR_EAE (1 << 31) |
| #define ARM_64_LPAE_S2_TCR_RES1 (1 << 31) |
| |
| #define ARM_LPAE_TCR_EPD1 (1 << 23) |
| |
| #define ARM_LPAE_TCR_TG0_4K (0 << 14) |
| #define ARM_LPAE_TCR_TG0_64K (1 << 14) |
| #define ARM_LPAE_TCR_TG0_16K (2 << 14) |
| |
| #define ARM_LPAE_TCR_SH0_SHIFT 12 |
| #define ARM_LPAE_TCR_SH0_MASK 0x3 |
| #define ARM_LPAE_TCR_SH_NS 0 |
| #define ARM_LPAE_TCR_SH_OS 2 |
| #define ARM_LPAE_TCR_SH_IS 3 |
| |
| #define ARM_LPAE_TCR_ORGN0_SHIFT 10 |
| #define ARM_LPAE_TCR_IRGN0_SHIFT 8 |
| #define ARM_LPAE_TCR_RGN_MASK 0x3 |
| #define ARM_LPAE_TCR_RGN_NC 0 |
| #define ARM_LPAE_TCR_RGN_WBWA 1 |
| #define ARM_LPAE_TCR_RGN_WT 2 |
| #define ARM_LPAE_TCR_RGN_WB 3 |
| |
| #define ARM_LPAE_TCR_SL0_SHIFT 6 |
| #define ARM_LPAE_TCR_SL0_MASK 0x3 |
| |
| #define ARM_LPAE_TCR_T0SZ_SHIFT 0 |
| #define ARM_LPAE_TCR_SZ_MASK 0xf |
| |
| #define ARM_LPAE_TCR_PS_SHIFT 16 |
| #define ARM_LPAE_TCR_PS_MASK 0x7 |
| |
| #define ARM_LPAE_TCR_IPS_SHIFT 32 |
| #define ARM_LPAE_TCR_IPS_MASK 0x7 |
| |
| #define ARM_LPAE_TCR_PS_32_BIT 0x0ULL |
| #define ARM_LPAE_TCR_PS_36_BIT 0x1ULL |
| #define ARM_LPAE_TCR_PS_40_BIT 0x2ULL |
| #define ARM_LPAE_TCR_PS_42_BIT 0x3ULL |
| #define ARM_LPAE_TCR_PS_44_BIT 0x4ULL |
| #define ARM_LPAE_TCR_PS_48_BIT 0x5ULL |
| |
| #define ARM_LPAE_MAIR_ATTR_SHIFT(n) ((n) << 3) |
| #define ARM_LPAE_MAIR_ATTR_MASK 0xff |
| #define ARM_LPAE_MAIR_ATTR_DEVICE 0x04 |
| #define ARM_LPAE_MAIR_ATTR_NC 0x44 |
| #define ARM_LPAE_MAIR_ATTR_WBRWA 0xff |
| #define ARM_LPAE_MAIR_ATTR_IDX_NC 0 |
| #define ARM_LPAE_MAIR_ATTR_IDX_CACHE 1 |
| #define ARM_LPAE_MAIR_ATTR_IDX_DEV 2 |
| |
| #define TTBRn_ASID_SHIFT 48 |
| #define TTBCR2_SEP_SHIFT 15 |
| #define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT) |
| #define TTBCR2_AS (1 << 4) |
| #define TTBCR_T0SZ(ia_bits) (64 - (ia_bits)) |
| |
| #define S2CR_PRIVCFG_SHIFT 24 |
| #define S2CR_PRIVCFG_MASK 0x3 |
| |
| /**************************************************************/ |
| |
| uint16_t paxc_stream_ids[] = { 0x2000 }; |
| |
| uint16_t paxc_stream_ids_mask[] = { 0x1fff }; |
| uint16_t crmu_stream_ids[] = { CRMU_STREAM_ID }; |
| uint16_t crmu_stream_ids_mask[] = { 0x0 }; |
| |
| enum arm_smmu_s2cr_type { |
| S2CR_TYPE_TRANS, |
| S2CR_TYPE_BYPASS, |
| S2CR_TYPE_FAULT, |
| }; |
| |
| enum arm_smmu_s2cr_privcfg { |
| S2CR_PRIVCFG_DEFAULT, |
| S2CR_PRIVCFG_DIPAN, |
| S2CR_PRIVCFG_UNPRIV, |
| S2CR_PRIVCFG_PRIV, |
| }; |
| |
| struct arm_smmu_smr { |
| uint16_t mask; |
| uint16_t id; |
| uint32_t valid; |
| }; |
| |
| struct arm_smmu_s2cr { |
| int count; |
| enum arm_smmu_s2cr_type type; |
| enum arm_smmu_s2cr_privcfg privcfg; |
| uint8_t cbndx; |
| }; |
| |
| struct arm_smmu_cfg { |
| uint8_t cbndx; |
| uint8_t irptndx; |
| uint32_t cbar; |
| }; |
| |
| struct arm_smmu_device { |
| uint8_t *base; |
| uint32_t streams; |
| unsigned long size; |
| unsigned long pgshift; |
| unsigned long va_size; |
| unsigned long ipa_size; |
| unsigned long pa_size; |
| struct arm_smmu_smr smr[NUM_OF_SMRS]; |
| struct arm_smmu_s2cr s2cr[NUM_OF_SMRS]; |
| struct arm_smmu_cfg cfg[NUM_OF_SMRS]; |
| uint16_t *stream_ids; |
| uint16_t *stream_ids_mask; |
| }; |
| |
| void arm_smmu_enable_secure_client_port(void) |
| { |
| uintptr_t smmu_base = SMMU_BASE; |
| |
| mmio_clrbits_32(smmu_base, sCR0_CLIENTPD); |
| } |
| |
| void arm_smmu_reserve_secure_cntxt(void) |
| { |
| uintptr_t smmu_base = SMMU_BASE; |
| |
| mmio_clrsetbits_32(smmu_base + ARM_SMMU_SMMU_SCR1, |
| (SCR1_NSNUMSMRGO_MASK | SCR1_NSNUMCBO_MASK), |
| ((ARM_SMMU_NSNUMCBO << SCR1_NSNUMCBO_SHIFT) | |
| (ARM_SMMU_NSNUMSMRGO << SCR1_NSNUMSMRGO_SHIFT))); |
| } |
| |
| static void arm_smmu_smr_cfg(struct arm_smmu_device *smmu, uint32_t index) |
| { |
| uint32_t idx = smmu->cfg[index].cbndx; |
| struct arm_smmu_smr *smr = &smmu->smr[index]; |
| uint32_t reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT; |
| |
| if (smr->valid) |
| reg |= SMR_VALID; |
| |
| mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) + |
| ARM_SMMU_GR0_SMR(idx)), reg); |
| } |
| |
| static void arm_smmu_s2cr_cfg(struct arm_smmu_device *smmu, uint32_t index) |
| { |
| uint32_t idx = smmu->cfg[index].cbndx; |
| struct arm_smmu_s2cr *s2cr = &smmu->s2cr[index]; |
| |
| uint32_t reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT | |
| (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT | |
| (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT; |
| |
| mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) + |
| ARM_SMMU_GR0_S2CR(idx)), reg); |
| } |
| |
| static void smmu_set_pgtbl(struct arm_smmu_device *smmu, |
| enum iommu_domain dom, |
| uint64_t *pg_table_base) |
| { |
| int i, l0_index, l1_index; |
| uint64_t addr, *pte, *l0_base, *l1_base; |
| uint64_t addr_space_limit; |
| |
| if (dom == PCIE_PAXC) { |
| addr_space_limit = 0xffffffffff; |
| } else if (dom == DOMAIN_CRMU) { |
| addr_space_limit = 0xffffffff; |
| } else { |
| ERROR("dom is not supported\n"); |
| return; |
| } |
| |
| l0_base = pg_table_base; |
| /* clear L0 descriptors. */ |
| for (i = 0; i < ARM_LPAE_PGTBL_PTE_CNT; i++) |
| l0_base[i] = 0x0; |
| |
| addr = 0x0; |
| while (addr < addr_space_limit) { |
| /* find L0 pte */ |
| l0_index = ((addr >> ARM_LPAE_PTE_L0_INDEX_SHIFT) & |
| ARM_LPAE_PTE_L0_INDEX_MASK); |
| l1_base = l0_base + ((l0_index + 1) * ARM_LPAE_PGTBL_PTE_CNT); |
| |
| /* setup L0 pte if required */ |
| pte = l0_base + l0_index; |
| if (*pte == 0x0) { |
| *pte |= ((uint64_t)l1_base & ARM_LPAE_PTE_TABLE_MASK); |
| if (dom == PCIE_PAXC) |
| *pte |= ARM_LPAE_PTE_NSTABLE; |
| *pte |= ARM_LPAE_PTE_TABLE; |
| *pte |= ARM_LPAE_PTE_VALID; |
| } |
| |
| /* find L1 pte */ |
| l1_index = ((addr >> ARM_LPAE_PTE_L1_INDEX_SHIFT) & |
| ARM_LPAE_PTE_L1_INDEX_MASK); |
| pte = l1_base + l1_index; |
| |
| /* setup L1 pte */ |
| *pte = 0x0; |
| *pte |= (addr & ARM_LPAE_PTE_L1_ADDR_MASK); |
| if (addr < 0x80000000) { |
| *pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV << |
| ARM_LPAE_PTE_ATTRINDX); |
| if (dom == PCIE_PAXC) |
| *pte |= (1 << ARM_LPAE_PTE_NS); |
| } else { |
| *pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE << |
| ARM_LPAE_PTE_ATTRINDX); |
| *pte |= (1 << ARM_LPAE_PTE_NS); |
| } |
| *pte |= (ARM_LPAE_PTE_AP_EL0_RW << ARM_LPAE_PTE_AP); |
| *pte |= (ARM_LPAE_PTE_SH_INNER << ARM_LPAE_PTE_SH); |
| *pte |= (1 << ARM_LPAE_PTE_AF); |
| *pte |= ARM_LPAE_PTE_VALID; |
| |
| addr += ARM_LPAE_PTE_L1_BLOCK_SIZE; |
| } |
| } |
| |
| void arm_smmu_create_identity_map(enum iommu_domain dom) |
| { |
| struct arm_smmu_device iommu; |
| struct arm_smmu_device *smmu = &iommu; |
| uint32_t reg, reg2; |
| unsigned long long reg64; |
| uint32_t idx; |
| uint16_t asid; |
| unsigned int context_bank_index; |
| unsigned long long pg_table_base; |
| |
| smmu->base = (uint8_t *) SMMU_BASE; |
| reg = mmio_read_32((uintptr_t) (ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_ID1)); |
| smmu->pgshift = (reg & ID1_PAGESIZE) ? 16 : 12; |
| smmu->size = ARM_SMMU_RES_SIZE; |
| smmu->stream_ids = NULL; |
| |
| switch (dom) { |
| case PCIE_PAXC: |
| smmu->stream_ids = &paxc_stream_ids[0]; |
| smmu->stream_ids_mask = &paxc_stream_ids_mask[0]; |
| smmu->streams = ARRAY_SIZE(paxc_stream_ids); |
| context_bank_index = SMMU_CTX_BANK_IDX; |
| pg_table_base = ARM_LPAE_PGTBL_PHYS; |
| break; |
| case DOMAIN_CRMU: |
| smmu->stream_ids = &crmu_stream_ids[0]; |
| smmu->stream_ids_mask = &crmu_stream_ids_mask[0]; |
| smmu->streams = ARRAY_SIZE(crmu_stream_ids); |
| context_bank_index = SMMU_CTX_BANK_IDX_SECURE_CRMU; |
| pg_table_base = ARM_LPAE_PGTBL_PHYS_CRMU; |
| break; |
| default: |
| ERROR("domain not supported\n"); |
| return; |
| } |
| |
| if (smmu->streams > NUM_OF_SMRS) { |
| INFO("can not support more than %d sids\n", NUM_OF_SMRS); |
| return; |
| } |
| |
| /* set up iommu dev. */ |
| for (idx = 0; idx < smmu->streams; idx++) { |
| /* S2CR. */ |
| smmu->s2cr[idx].type = S2CR_TYPE_TRANS; |
| smmu->s2cr[idx].privcfg = S2CR_PRIVCFG_DEFAULT; |
| smmu->s2cr[idx].cbndx = context_bank_index; |
| smmu->cfg[idx].cbndx = context_bank_index; |
| smmu->cfg[idx].cbar = STG1_WITH_STG2_BYPASS << CBAR_TYPE_SHIFT; |
| arm_smmu_s2cr_cfg(smmu, idx); |
| |
| /* SMR. */ |
| smmu->smr[idx].mask = smmu->stream_ids_mask[idx]; |
| smmu->smr[idx].id = smmu->stream_ids[idx]; |
| smmu->smr[idx].valid = 1; |
| arm_smmu_smr_cfg(smmu, idx); |
| |
| /* CBA2R. 64-bit Translation */ |
| mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) + |
| ARM_SMMU_GR1_CBA2R(smmu->cfg[idx].cbndx)), |
| 0x1); |
| /* CBAR.*/ |
| reg = smmu->cfg[idx].cbar; |
| reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) | |
| (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); |
| |
| mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) + |
| ARM_SMMU_GR1_CBAR(smmu->cfg[idx].cbndx)), |
| reg); |
| |
| /* TTBCR. */ |
| reg64 = (ARM_LPAE_TCR_SH_IS << ARM_LPAE_TCR_SH0_SHIFT) | |
| (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) | |
| (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT); |
| reg64 |= ARM_LPAE_TCR_TG0_4K; |
| reg64 |= (ARM_LPAE_TCR_PS_40_BIT << ARM_LPAE_TCR_IPS_SHIFT); |
| /* ias 40 bits.*/ |
| reg64 |= TTBCR_T0SZ(40) << ARM_LPAE_TCR_T0SZ_SHIFT; |
| /* Disable speculative walks through TTBR1 */ |
| reg64 |= ARM_LPAE_TCR_EPD1; |
| reg = (uint32_t) reg64; |
| reg2 = (uint32_t) (reg64 >> 32); |
| reg2 |= TTBCR2_SEP_UPSTREAM; |
| reg2 |= TTBCR2_AS; |
| |
| mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + |
| ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + |
| ARM_SMMU_CB_TTBCR2), reg2); |
| |
| mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + |
| ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + |
| ARM_SMMU_CB_TTBCR), reg); |
| |
| /* TTBR0. */ |
| asid = smmu->cfg[idx].cbndx; |
| reg64 = pg_table_base; |
| reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT; |
| |
| mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + |
| ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + |
| ARM_SMMU_CB_TTBR0), reg64); |
| /* TTBR1. */ |
| reg64 = 0; |
| reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT; |
| |
| mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + |
| ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + |
| ARM_SMMU_CB_TTBR1), reg64); |
| /* MAIR. */ |
| reg = (ARM_LPAE_MAIR_ATTR_NC |
| << ARM_LPAE_MAIR_ATTR_SHIFT |
| (ARM_LPAE_MAIR_ATTR_IDX_NC)) | |
| (ARM_LPAE_MAIR_ATTR_WBRWA << |
| ARM_LPAE_MAIR_ATTR_SHIFT |
| (ARM_LPAE_MAIR_ATTR_IDX_CACHE)) | |
| (ARM_LPAE_MAIR_ATTR_DEVICE << |
| ARM_LPAE_MAIR_ATTR_SHIFT |
| (ARM_LPAE_MAIR_ATTR_IDX_DEV)); |
| |
| mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + |
| ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + |
| ARM_SMMU_CB_S1_MAIR0), reg); |
| |
| /* MAIR1. */ |
| reg = 0; |
| mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + |
| ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + |
| ARM_SMMU_CB_S1_MAIR1), reg); |
| /* SCTLR. */ |
| reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | SCTLR_M; |
| /* stage 1.*/ |
| reg |= SCTLR_S1_ASIDPNE; |
| mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + |
| ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + |
| ARM_SMMU_CB_SCTLR), reg); |
| } |
| smmu_set_pgtbl(smmu, dom, (uint64_t *)pg_table_base); |
| } |