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>
51 * struct sprd_iommu_device - high-level sprd IOMMU device representation,
54 * @ver: sprd IOMMU IP version
60 * @iommu: IOMMU core representation
61 * @group: IOMMU group
62 * @eb: gate clock which controls IOMMU access
70 struct iommu_device iommu; member
93 writel_relaxed(val, sdev->base + reg); in sprd_iommu_write()
99 return readl_relaxed(sdev->base + reg); in sprd_iommu_read()
123 return -EINVAL; in sprd_iommu_get_version()
130 return ((domain->geometry.aperture_end - in sprd_iommu_pgt_size()
131 domain->geometry.aperture_start + 1) >> in sprd_iommu_pgt_size()
146 spin_lock_init(&dom->pgtlock); in sprd_iommu_domain_alloc()
148 dom->domain.geometry.aperture_start = 0; in sprd_iommu_domain_alloc()
149 dom->domain.geometry.aperture_end = SZ_256M - 1; in sprd_iommu_domain_alloc()
151 return &dom->domain; in sprd_iommu_domain_alloc()
163 struct sprd_iommu_device *sdev = dom->sdev; in sprd_iommu_first_vpn()
167 if (sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_first_vpn()
172 val = dom->domain.geometry.aperture_start >> SPRD_IOMMU_PAGE_SHIFT; in sprd_iommu_first_vpn()
178 struct sprd_iommu_device *sdev = dom->sdev; in sprd_iommu_vpn_range()
182 if (sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_vpn_range()
187 val = (dom->domain.geometry.aperture_end - in sprd_iommu_vpn_range()
188 dom->domain.geometry.aperture_start) >> SPRD_IOMMU_PAGE_SHIFT; in sprd_iommu_vpn_range()
194 u32 val = dom->pgt_pa >> SPRD_IOMMU_PAGE_SHIFT; in sprd_iommu_first_ppn()
195 struct sprd_iommu_device *sdev = dom->sdev; in sprd_iommu_first_ppn()
198 if (sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_first_ppn()
208 u32 val = sdev->prot_page_pa >> SPRD_IOMMU_PAGE_SHIFT; in sprd_iommu_default_ppn()
210 if (sdev->ver == SPRD_IOMMU_EX) { in sprd_iommu_default_ppn()
212 } else if (sdev->ver == SPRD_IOMMU_VAU) { in sprd_iommu_default_ppn()
223 if (sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_hw_en()
240 if (dom->sdev) { in sprd_iommu_attach_device()
242 return -EINVAL; in sprd_iommu_attach_device()
245 dom->pgt_va = dma_alloc_coherent(sdev->dev, pgt_size, &dom->pgt_pa, GFP_KERNEL); in sprd_iommu_attach_device()
246 if (!dom->pgt_va) in sprd_iommu_attach_device()
247 return -ENOMEM; in sprd_iommu_attach_device()
249 dom->sdev = sdev; in sprd_iommu_attach_device()
264 struct sprd_iommu_device *sdev = dom->sdev; in sprd_iommu_detach_device()
270 dma_free_coherent(sdev->dev, pgt_size, dom->pgt_va, dom->pgt_pa); in sprd_iommu_detach_device()
272 dom->sdev = NULL; in sprd_iommu_detach_device()
284 unsigned long start = domain->geometry.aperture_start; in sprd_iommu_map()
285 unsigned long end = domain->geometry.aperture_end; in sprd_iommu_map()
287 if (!dom->sdev) { in sprd_iommu_map()
289 return -EINVAL; in sprd_iommu_map()
293 dev_err(dom->sdev->dev, "(iova(0x%lx) + size(%zx)) are not in the range!\n", in sprd_iommu_map()
295 return -EINVAL; in sprd_iommu_map()
298 pgt_base_iova = dom->pgt_va + ((iova - start) >> SPRD_IOMMU_PAGE_SHIFT); in sprd_iommu_map()
300 spin_lock_irqsave(&dom->pgtlock, flags); in sprd_iommu_map()
305 spin_unlock_irqrestore(&dom->pgtlock, flags); in sprd_iommu_map()
317 unsigned long start = domain->geometry.aperture_start; in sprd_iommu_unmap()
318 unsigned long end = domain->geometry.aperture_end; in sprd_iommu_unmap()
321 return -EINVAL; in sprd_iommu_unmap()
323 pgt_base_iova = dom->pgt_va + ((iova - start) >> SPRD_IOMMU_PAGE_SHIFT); in sprd_iommu_unmap()
325 spin_lock_irqsave(&dom->pgtlock, flags); in sprd_iommu_unmap()
327 spin_unlock_irqrestore(&dom->pgtlock, flags); in sprd_iommu_unmap()
338 if (dom->sdev->ver == SPRD_IOMMU_EX) in sprd_iommu_sync_map()
343 /* clear IOMMU TLB buffer after page table updated */ in sprd_iommu_sync_map()
344 sprd_iommu_write(dom->sdev, reg, 0xffffffff); in sprd_iommu_sync_map()
359 unsigned long start = domain->geometry.aperture_start; in sprd_iommu_iova_to_phys()
360 unsigned long end = domain->geometry.aperture_end; in sprd_iommu_iova_to_phys()
365 spin_lock_irqsave(&dom->pgtlock, flags); in sprd_iommu_iova_to_phys()
366 pa = *(dom->pgt_va + ((iova - start) >> SPRD_IOMMU_PAGE_SHIFT)); in sprd_iommu_iova_to_phys()
367 pa = (pa << SPRD_IOMMU_PAGE_SHIFT) + ((iova - start) & (SPRD_IOMMU_PAGE_SIZE - 1)); in sprd_iommu_iova_to_phys()
368 spin_unlock_irqrestore(&dom->pgtlock, flags); in sprd_iommu_iova_to_phys()
378 if (!fwspec || fwspec->ops != &sprd_iommu_ops) in sprd_iommu_probe_device()
379 return ERR_PTR(-ENODEV); in sprd_iommu_probe_device()
383 return &sdev->iommu; in sprd_iommu_probe_device()
390 return iommu_group_ref_get(sdev->group); in sprd_iommu_device_group()
398 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 /* All the client devices are in the same iommu-group */ in sprd_iommu_probe()
485 sdev->group = iommu_group_alloc(); in sprd_iommu_probe()
486 if (IS_ERR(sdev->group)) { in sprd_iommu_probe()
487 ret = PTR_ERR(sdev->group); in sprd_iommu_probe()
491 ret = iommu_device_sysfs_add(&sdev->iommu, dev, NULL, dev_name(dev)); in sprd_iommu_probe()
495 ret = iommu_device_register(&sdev->iommu, &sprd_iommu_ops, dev); in sprd_iommu_probe()
505 dev_err(dev, "IOMMU version(%d) is invalid.\n", ret); in sprd_iommu_probe()
508 sdev->ver = ret; in sprd_iommu_probe()
515 iommu_device_unregister(&sdev->iommu); in sprd_iommu_probe()
517 iommu_device_sysfs_remove(&sdev->iommu); in sprd_iommu_probe()
519 iommu_group_put(sdev->group); in sprd_iommu_probe()
521 dma_free_coherent(sdev->dev, SPRD_IOMMU_PAGE_SIZE, sdev->prot_page_va, sdev->prot_page_pa); in sprd_iommu_probe()
529 dma_free_coherent(sdev->dev, SPRD_IOMMU_PAGE_SIZE, sdev->prot_page_va, sdev->prot_page_pa); in sprd_iommu_remove()
531 iommu_group_put(sdev->group); in sprd_iommu_remove()
532 sdev->group = NULL; in sprd_iommu_remove()
535 iommu_device_sysfs_remove(&sdev->iommu); in sprd_iommu_remove()
536 iommu_device_unregister(&sdev->iommu); in sprd_iommu_remove()
543 .name = "sprd-iommu",
552 MODULE_DESCRIPTION("IOMMU driver for Unisoc SoCs");
553 MODULE_ALIAS("platform:sprd-iommu");