162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci// Copyright (C) 2019-2020 NVIDIA CORPORATION. All rights reserved. 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/bitfield.h> 562306a36Sopenharmony_ci#include <linux/delay.h> 662306a36Sopenharmony_ci#include <linux/of.h> 762306a36Sopenharmony_ci#include <linux/platform_device.h> 862306a36Sopenharmony_ci#include <linux/slab.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <soc/tegra/mc.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "arm-smmu.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* 1562306a36Sopenharmony_ci * Tegra194 has three ARM MMU-500 Instances. 1662306a36Sopenharmony_ci * Two of them are used together and must be programmed identically for 1762306a36Sopenharmony_ci * interleaved IOVA accesses across them and translates accesses from 1862306a36Sopenharmony_ci * non-isochronous HW devices. 1962306a36Sopenharmony_ci * Third one is used for translating accesses from isochronous HW devices. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * In addition, the SMMU driver needs to coordinate with the memory controller 2262306a36Sopenharmony_ci * driver to ensure that the right SID override is programmed for any given 2362306a36Sopenharmony_ci * memory client. This is necessary to allow for use-case such as seamlessly 2462306a36Sopenharmony_ci * handing over the display controller configuration from the firmware to the 2562306a36Sopenharmony_ci * kernel. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * This implementation supports programming of the two instances that must 2862306a36Sopenharmony_ci * be programmed identically and takes care of invoking the memory controller 2962306a36Sopenharmony_ci * driver for SID override programming after devices have been attached to an 3062306a36Sopenharmony_ci * SMMU instance. 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_ci#define MAX_SMMU_INSTANCES 2 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistruct nvidia_smmu { 3562306a36Sopenharmony_ci struct arm_smmu_device smmu; 3662306a36Sopenharmony_ci void __iomem *bases[MAX_SMMU_INSTANCES]; 3762306a36Sopenharmony_ci unsigned int num_instances; 3862306a36Sopenharmony_ci struct tegra_mc *mc; 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic inline struct nvidia_smmu *to_nvidia_smmu(struct arm_smmu_device *smmu) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci return container_of(smmu, struct nvidia_smmu, smmu); 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic inline void __iomem *nvidia_smmu_page(struct arm_smmu_device *smmu, 4762306a36Sopenharmony_ci unsigned int inst, int page) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci struct nvidia_smmu *nvidia_smmu; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci nvidia_smmu = container_of(smmu, struct nvidia_smmu, smmu); 5262306a36Sopenharmony_ci return nvidia_smmu->bases[inst] + (page << smmu->pgshift); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic u32 nvidia_smmu_read_reg(struct arm_smmu_device *smmu, 5662306a36Sopenharmony_ci int page, int offset) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci void __iomem *reg = nvidia_smmu_page(smmu, 0, page) + offset; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci return readl_relaxed(reg); 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic void nvidia_smmu_write_reg(struct arm_smmu_device *smmu, 6462306a36Sopenharmony_ci int page, int offset, u32 val) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu); 6762306a36Sopenharmony_ci unsigned int i; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci for (i = 0; i < nvidia->num_instances; i++) { 7062306a36Sopenharmony_ci void __iomem *reg = nvidia_smmu_page(smmu, i, page) + offset; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci writel_relaxed(val, reg); 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic u64 nvidia_smmu_read_reg64(struct arm_smmu_device *smmu, 7762306a36Sopenharmony_ci int page, int offset) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci void __iomem *reg = nvidia_smmu_page(smmu, 0, page) + offset; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci return readq_relaxed(reg); 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic void nvidia_smmu_write_reg64(struct arm_smmu_device *smmu, 8562306a36Sopenharmony_ci int page, int offset, u64 val) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu); 8862306a36Sopenharmony_ci unsigned int i; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci for (i = 0; i < nvidia->num_instances; i++) { 9162306a36Sopenharmony_ci void __iomem *reg = nvidia_smmu_page(smmu, i, page) + offset; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci writeq_relaxed(val, reg); 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void nvidia_smmu_tlb_sync(struct arm_smmu_device *smmu, int page, 9862306a36Sopenharmony_ci int sync, int status) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu); 10162306a36Sopenharmony_ci unsigned int delay; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci arm_smmu_writel(smmu, page, sync, 0); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci for (delay = 1; delay < TLB_LOOP_TIMEOUT; delay *= 2) { 10662306a36Sopenharmony_ci unsigned int spin_cnt; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci for (spin_cnt = TLB_SPIN_COUNT; spin_cnt > 0; spin_cnt--) { 10962306a36Sopenharmony_ci u32 val = 0; 11062306a36Sopenharmony_ci unsigned int i; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci for (i = 0; i < nvidia->num_instances; i++) { 11362306a36Sopenharmony_ci void __iomem *reg; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci reg = nvidia_smmu_page(smmu, i, page) + status; 11662306a36Sopenharmony_ci val |= readl_relaxed(reg); 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (!(val & ARM_SMMU_sTLBGSTATUS_GSACTIVE)) 12062306a36Sopenharmony_ci return; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci cpu_relax(); 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci udelay(delay); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci dev_err_ratelimited(smmu->dev, 12962306a36Sopenharmony_ci "TLB sync timed out -- SMMU may be deadlocked\n"); 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic int nvidia_smmu_reset(struct arm_smmu_device *smmu) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu); 13562306a36Sopenharmony_ci unsigned int i; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci for (i = 0; i < nvidia->num_instances; i++) { 13862306a36Sopenharmony_ci u32 val; 13962306a36Sopenharmony_ci void __iomem *reg = nvidia_smmu_page(smmu, i, ARM_SMMU_GR0) + 14062306a36Sopenharmony_ci ARM_SMMU_GR0_sGFSR; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* clear global FSR */ 14362306a36Sopenharmony_ci val = readl_relaxed(reg); 14462306a36Sopenharmony_ci writel_relaxed(val, reg); 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci return 0; 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic irqreturn_t nvidia_smmu_global_fault_inst(int irq, 15162306a36Sopenharmony_ci struct arm_smmu_device *smmu, 15262306a36Sopenharmony_ci int inst) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci u32 gfsr, gfsynr0, gfsynr1, gfsynr2; 15562306a36Sopenharmony_ci void __iomem *gr0_base = nvidia_smmu_page(smmu, inst, 0); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci gfsr = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR); 15862306a36Sopenharmony_ci if (!gfsr) 15962306a36Sopenharmony_ci return IRQ_NONE; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci gfsynr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR0); 16262306a36Sopenharmony_ci gfsynr1 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR1); 16362306a36Sopenharmony_ci gfsynr2 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR2); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci dev_err_ratelimited(smmu->dev, 16662306a36Sopenharmony_ci "Unexpected global fault, this could be serious\n"); 16762306a36Sopenharmony_ci dev_err_ratelimited(smmu->dev, 16862306a36Sopenharmony_ci "\tGFSR 0x%08x, GFSYNR0 0x%08x, GFSYNR1 0x%08x, GFSYNR2 0x%08x\n", 16962306a36Sopenharmony_ci gfsr, gfsynr0, gfsynr1, gfsynr2); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci writel_relaxed(gfsr, gr0_base + ARM_SMMU_GR0_sGFSR); 17262306a36Sopenharmony_ci return IRQ_HANDLED; 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic irqreturn_t nvidia_smmu_global_fault(int irq, void *dev) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci unsigned int inst; 17862306a36Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 17962306a36Sopenharmony_ci struct arm_smmu_device *smmu = dev; 18062306a36Sopenharmony_ci struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci for (inst = 0; inst < nvidia->num_instances; inst++) { 18362306a36Sopenharmony_ci irqreturn_t irq_ret; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci irq_ret = nvidia_smmu_global_fault_inst(irq, smmu, inst); 18662306a36Sopenharmony_ci if (irq_ret == IRQ_HANDLED) 18762306a36Sopenharmony_ci ret = IRQ_HANDLED; 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci return ret; 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic irqreturn_t nvidia_smmu_context_fault_bank(int irq, 19462306a36Sopenharmony_ci struct arm_smmu_device *smmu, 19562306a36Sopenharmony_ci int idx, int inst) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci u32 fsr, fsynr, cbfrsynra; 19862306a36Sopenharmony_ci unsigned long iova; 19962306a36Sopenharmony_ci void __iomem *gr1_base = nvidia_smmu_page(smmu, inst, 1); 20062306a36Sopenharmony_ci void __iomem *cb_base = nvidia_smmu_page(smmu, inst, smmu->numpage + idx); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR); 20362306a36Sopenharmony_ci if (!(fsr & ARM_SMMU_FSR_FAULT)) 20462306a36Sopenharmony_ci return IRQ_NONE; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0); 20762306a36Sopenharmony_ci iova = readq_relaxed(cb_base + ARM_SMMU_CB_FAR); 20862306a36Sopenharmony_ci cbfrsynra = readl_relaxed(gr1_base + ARM_SMMU_GR1_CBFRSYNRA(idx)); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci dev_err_ratelimited(smmu->dev, 21162306a36Sopenharmony_ci "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n", 21262306a36Sopenharmony_ci fsr, iova, fsynr, cbfrsynra, idx); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci writel_relaxed(fsr, cb_base + ARM_SMMU_CB_FSR); 21562306a36Sopenharmony_ci return IRQ_HANDLED; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic irqreturn_t nvidia_smmu_context_fault(int irq, void *dev) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci int idx; 22162306a36Sopenharmony_ci unsigned int inst; 22262306a36Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 22362306a36Sopenharmony_ci struct arm_smmu_device *smmu; 22462306a36Sopenharmony_ci struct iommu_domain *domain = dev; 22562306a36Sopenharmony_ci struct arm_smmu_domain *smmu_domain; 22662306a36Sopenharmony_ci struct nvidia_smmu *nvidia; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci smmu_domain = container_of(domain, struct arm_smmu_domain, domain); 22962306a36Sopenharmony_ci smmu = smmu_domain->smmu; 23062306a36Sopenharmony_ci nvidia = to_nvidia_smmu(smmu); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci for (inst = 0; inst < nvidia->num_instances; inst++) { 23362306a36Sopenharmony_ci irqreturn_t irq_ret; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci /* 23662306a36Sopenharmony_ci * Interrupt line is shared between all contexts. 23762306a36Sopenharmony_ci * Check for faults across all contexts. 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_ci for (idx = 0; idx < smmu->num_context_banks; idx++) { 24062306a36Sopenharmony_ci irq_ret = nvidia_smmu_context_fault_bank(irq, smmu, 24162306a36Sopenharmony_ci idx, inst); 24262306a36Sopenharmony_ci if (irq_ret == IRQ_HANDLED) 24362306a36Sopenharmony_ci ret = IRQ_HANDLED; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci return ret; 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic void nvidia_smmu_probe_finalize(struct arm_smmu_device *smmu, struct device *dev) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu); 25362306a36Sopenharmony_ci int err; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci err = tegra_mc_probe_device(nvidia->mc, dev); 25662306a36Sopenharmony_ci if (err < 0) 25762306a36Sopenharmony_ci dev_err(smmu->dev, "memory controller probe failed for %s: %d\n", 25862306a36Sopenharmony_ci dev_name(dev), err); 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic int nvidia_smmu_init_context(struct arm_smmu_domain *smmu_domain, 26262306a36Sopenharmony_ci struct io_pgtable_cfg *pgtbl_cfg, 26362306a36Sopenharmony_ci struct device *dev) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci struct arm_smmu_device *smmu = smmu_domain->smmu; 26662306a36Sopenharmony_ci const struct device_node *np = smmu->dev->of_node; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* 26962306a36Sopenharmony_ci * Tegra194 and Tegra234 SoCs have the erratum that causes walk cache 27062306a36Sopenharmony_ci * entries to not be invalidated correctly. The problem is that the walk 27162306a36Sopenharmony_ci * cache index generated for IOVA is not same across translation and 27262306a36Sopenharmony_ci * invalidation requests. This is leading to page faults when PMD entry 27362306a36Sopenharmony_ci * is released during unmap and populated with new PTE table during 27462306a36Sopenharmony_ci * subsequent map request. Disabling large page mappings avoids the 27562306a36Sopenharmony_ci * release of PMD entry and avoid translations seeing stale PMD entry in 27662306a36Sopenharmony_ci * walk cache. 27762306a36Sopenharmony_ci * Fix this by limiting the page mappings to PAGE_SIZE on Tegra194 and 27862306a36Sopenharmony_ci * Tegra234. 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_ci if (of_device_is_compatible(np, "nvidia,tegra234-smmu") || 28162306a36Sopenharmony_ci of_device_is_compatible(np, "nvidia,tegra194-smmu")) { 28262306a36Sopenharmony_ci smmu->pgsize_bitmap = PAGE_SIZE; 28362306a36Sopenharmony_ci pgtbl_cfg->pgsize_bitmap = smmu->pgsize_bitmap; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci return 0; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic const struct arm_smmu_impl nvidia_smmu_impl = { 29062306a36Sopenharmony_ci .read_reg = nvidia_smmu_read_reg, 29162306a36Sopenharmony_ci .write_reg = nvidia_smmu_write_reg, 29262306a36Sopenharmony_ci .read_reg64 = nvidia_smmu_read_reg64, 29362306a36Sopenharmony_ci .write_reg64 = nvidia_smmu_write_reg64, 29462306a36Sopenharmony_ci .reset = nvidia_smmu_reset, 29562306a36Sopenharmony_ci .tlb_sync = nvidia_smmu_tlb_sync, 29662306a36Sopenharmony_ci .global_fault = nvidia_smmu_global_fault, 29762306a36Sopenharmony_ci .context_fault = nvidia_smmu_context_fault, 29862306a36Sopenharmony_ci .probe_finalize = nvidia_smmu_probe_finalize, 29962306a36Sopenharmony_ci .init_context = nvidia_smmu_init_context, 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic const struct arm_smmu_impl nvidia_smmu_single_impl = { 30362306a36Sopenharmony_ci .probe_finalize = nvidia_smmu_probe_finalize, 30462306a36Sopenharmony_ci .init_context = nvidia_smmu_init_context, 30562306a36Sopenharmony_ci}; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistruct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci struct resource *res; 31062306a36Sopenharmony_ci struct device *dev = smmu->dev; 31162306a36Sopenharmony_ci struct nvidia_smmu *nvidia_smmu; 31262306a36Sopenharmony_ci struct platform_device *pdev = to_platform_device(dev); 31362306a36Sopenharmony_ci unsigned int i; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci nvidia_smmu = devm_krealloc(dev, smmu, sizeof(*nvidia_smmu), GFP_KERNEL); 31662306a36Sopenharmony_ci if (!nvidia_smmu) 31762306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci nvidia_smmu->mc = devm_tegra_memory_controller_get(dev); 32062306a36Sopenharmony_ci if (IS_ERR(nvidia_smmu->mc)) 32162306a36Sopenharmony_ci return ERR_CAST(nvidia_smmu->mc); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* Instance 0 is ioremapped by arm-smmu.c. */ 32462306a36Sopenharmony_ci nvidia_smmu->bases[0] = smmu->base; 32562306a36Sopenharmony_ci nvidia_smmu->num_instances++; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci for (i = 1; i < MAX_SMMU_INSTANCES; i++) { 32862306a36Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, i); 32962306a36Sopenharmony_ci if (!res) 33062306a36Sopenharmony_ci break; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci nvidia_smmu->bases[i] = devm_ioremap_resource(dev, res); 33362306a36Sopenharmony_ci if (IS_ERR(nvidia_smmu->bases[i])) 33462306a36Sopenharmony_ci return ERR_CAST(nvidia_smmu->bases[i]); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci nvidia_smmu->num_instances++; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (nvidia_smmu->num_instances == 1) 34062306a36Sopenharmony_ci nvidia_smmu->smmu.impl = &nvidia_smmu_single_impl; 34162306a36Sopenharmony_ci else 34262306a36Sopenharmony_ci nvidia_smmu->smmu.impl = &nvidia_smmu_impl; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci return &nvidia_smmu->smmu; 34562306a36Sopenharmony_ci} 346