Lines Matching +full:iommu +full:- +full:v1

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Unisoc IOMMU driver
11 #include <linux/dma-mapping.h>
13 #include <linux/iommu.h>
52 * struct sprd_iommu_device - high-level sprd IOMMU device representation,
55 * @ver: sprd IOMMU IP version
61 * @iommu: IOMMU core representation
62 * @group: IOMMU group
63 * @eb: gate clock which controls IOMMU access
72 struct iommu_device iommu; member
94 writel_relaxed(val, sdev->base + reg); in sprd_iommu_write()
100 return readl_relaxed(sdev->base + reg); in sprd_iommu_read()
124 return -EINVAL; in sprd_iommu_get_version()
131 return ((domain->geometry.aperture_end - in sprd_iommu_pgt_size()
132 domain->geometry.aperture_start + 1) >> in sprd_iommu_pgt_size()
144 spin_lock_init(&dom->pgtlock); in sprd_iommu_domain_alloc_paging()
146 dom->domain.geometry.aperture_start = 0; in sprd_iommu_domain_alloc_paging()
147 dom->domain.geometry.aperture_end = SZ_256M - 1; in sprd_iommu_domain_alloc_paging()
148 dom->domain.geometry.force_aperture = true; in sprd_iommu_domain_alloc_paging()
150 return &dom->domain; in sprd_iommu_domain_alloc_paging()
155 struct sprd_iommu_device *sdev = dom->sdev; in sprd_iommu_first_vpn()
159 if (sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_first_vpn()
164 val = dom->domain.geometry.aperture_start >> SPRD_IOMMU_PAGE_SHIFT; in sprd_iommu_first_vpn()
170 struct sprd_iommu_device *sdev = dom->sdev; in sprd_iommu_vpn_range()
174 if (sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_vpn_range()
179 val = (dom->domain.geometry.aperture_end - in sprd_iommu_vpn_range()
180 dom->domain.geometry.aperture_start) >> SPRD_IOMMU_PAGE_SHIFT; in sprd_iommu_vpn_range()
186 u32 val = dom->pgt_pa >> SPRD_IOMMU_PAGE_SHIFT; in sprd_iommu_first_ppn()
187 struct sprd_iommu_device *sdev = dom->sdev; in sprd_iommu_first_ppn()
190 if (sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_first_ppn()
200 u32 val = sdev->prot_page_pa >> SPRD_IOMMU_PAGE_SHIFT; in sprd_iommu_default_ppn()
202 if (sdev->ver == SPRD_IOMMU_EX) { in sprd_iommu_default_ppn()
204 } else if (sdev->ver == SPRD_IOMMU_VAU) { in sprd_iommu_default_ppn()
215 if (sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_hw_en()
230 if (!dom->sdev) in sprd_iommu_cleanup()
233 pgt_size = sprd_iommu_pgt_size(&dom->domain); in sprd_iommu_cleanup()
234 dma_free_coherent(dom->sdev->dev, pgt_size, dom->pgt_va, dom->pgt_pa); in sprd_iommu_cleanup()
235 sprd_iommu_hw_en(dom->sdev, false); in sprd_iommu_cleanup()
236 dom->sdev = NULL; in sprd_iommu_cleanup()
255 if (sdev->dom == dom) in sprd_iommu_attach_device()
259 if (!dom->pgt_va) { in sprd_iommu_attach_device()
260 dom->pgt_va = dma_alloc_coherent(sdev->dev, pgt_size, &dom->pgt_pa, GFP_KERNEL); in sprd_iommu_attach_device()
261 if (!dom->pgt_va) in sprd_iommu_attach_device()
262 return -ENOMEM; in sprd_iommu_attach_device()
264 dom->sdev = sdev; in sprd_iommu_attach_device()
267 sdev->dom = dom; in sprd_iommu_attach_device()
270 * One sprd IOMMU serves one client device only, disabled it before in sprd_iommu_attach_device()
294 unsigned long start = domain->geometry.aperture_start; in sprd_iommu_map()
295 unsigned long end = domain->geometry.aperture_end; in sprd_iommu_map()
297 if (!dom->sdev) { in sprd_iommu_map()
299 return -EINVAL; in sprd_iommu_map()
303 dev_err(dom->sdev->dev, "(iova(0x%lx) + size(%zx)) are not in the range!\n", in sprd_iommu_map()
305 return -EINVAL; in sprd_iommu_map()
308 pgt_base_iova = dom->pgt_va + ((iova - start) >> SPRD_IOMMU_PAGE_SHIFT); in sprd_iommu_map()
310 spin_lock_irqsave(&dom->pgtlock, flags); in sprd_iommu_map()
315 spin_unlock_irqrestore(&dom->pgtlock, flags); in sprd_iommu_map()
329 unsigned long start = domain->geometry.aperture_start; in sprd_iommu_unmap()
330 unsigned long end = domain->geometry.aperture_end; in sprd_iommu_unmap()
335 pgt_base_iova = dom->pgt_va + ((iova - start) >> SPRD_IOMMU_PAGE_SHIFT); in sprd_iommu_unmap()
337 spin_lock_irqsave(&dom->pgtlock, flags); in sprd_iommu_unmap()
339 spin_unlock_irqrestore(&dom->pgtlock, flags); in sprd_iommu_unmap()
350 if (dom->sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_sync_map()
355 /* clear IOMMU TLB buffer after page table updated */ in sprd_iommu_sync_map()
356 sprd_iommu_write(dom->sdev, reg, 0xffffffff); in sprd_iommu_sync_map()
372 unsigned long start = domain->geometry.aperture_start; in sprd_iommu_iova_to_phys()
373 unsigned long end = domain->geometry.aperture_end; in sprd_iommu_iova_to_phys()
378 spin_lock_irqsave(&dom->pgtlock, flags); in sprd_iommu_iova_to_phys()
379 pa = *(dom->pgt_va + ((iova - start) >> SPRD_IOMMU_PAGE_SHIFT)); in sprd_iommu_iova_to_phys()
380 pa = (pa << SPRD_IOMMU_PAGE_SHIFT) + ((iova - start) & (SPRD_IOMMU_PAGE_SIZE - 1)); in sprd_iommu_iova_to_phys()
381 spin_unlock_irqrestore(&dom->pgtlock, flags); in sprd_iommu_iova_to_phys()
390 return &sdev->iommu; in sprd_iommu_probe_device()
399 pdev = of_find_device_by_node(args->np); in sprd_iommu_of_xlate()
427 { .compatible = "sprd,iommu-v1" },
441 eb = devm_clk_get_optional(sdev->dev, NULL); in sprd_iommu_clk_enable()
448 sdev->eb = eb; in sprd_iommu_clk_enable()
454 if (sdev->eb) in sprd_iommu_clk_disable()
455 clk_disable_unprepare(sdev->eb); in sprd_iommu_clk_disable()
461 struct device *dev = &pdev->dev; in sprd_iommu_probe()
467 return -ENOMEM; in sprd_iommu_probe()
474 sdev->base = base; in sprd_iommu_probe()
476 sdev->prot_page_va = dma_alloc_coherent(dev, SPRD_IOMMU_PAGE_SIZE, in sprd_iommu_probe()
477 &sdev->prot_page_pa, GFP_KERNEL); in sprd_iommu_probe()
478 if (!sdev->prot_page_va) in sprd_iommu_probe()
479 return -ENOMEM; in sprd_iommu_probe()
482 sdev->dev = dev; in sprd_iommu_probe()
484 ret = iommu_device_sysfs_add(&sdev->iommu, dev, NULL, dev_name(dev)); in sprd_iommu_probe()
488 ret = iommu_device_register(&sdev->iommu, &sprd_iommu_ops, dev); in sprd_iommu_probe()
498 dev_err(dev, "IOMMU version(%d) is invalid.\n", ret); in sprd_iommu_probe()
501 sdev->ver = ret; in sprd_iommu_probe()
508 iommu_device_unregister(&sdev->iommu); in sprd_iommu_probe()
510 iommu_device_sysfs_remove(&sdev->iommu); in sprd_iommu_probe()
512 dma_free_coherent(sdev->dev, SPRD_IOMMU_PAGE_SIZE, sdev->prot_page_va, sdev->prot_page_pa); in sprd_iommu_probe()
520 dma_free_coherent(sdev->dev, SPRD_IOMMU_PAGE_SIZE, sdev->prot_page_va, sdev->prot_page_pa); in sprd_iommu_remove()
523 iommu_device_sysfs_remove(&sdev->iommu); in sprd_iommu_remove()
524 iommu_device_unregister(&sdev->iommu); in sprd_iommu_remove()
529 .name = "sprd-iommu",
538 MODULE_DESCRIPTION("IOMMU driver for Unisoc SoCs");
539 MODULE_ALIAS("platform:sprd-iommu");