20 #define pr_fmt(fmt) "%s(): " fmt, __func__
22 #include <linux/module.h>
25 #include <linux/slab.h>
28 #include <linux/list.h>
29 #include <linux/device.h>
34 #include <asm/cacheflush.h>
37 #define GART_IOMMU_PGSIZES (SZ_4K)
39 #define GART_REG_BASE 0x24
40 #define GART_CONFIG (0x24 - GART_REG_BASE)
41 #define GART_ENTRY_ADDR (0x28 - GART_REG_BASE)
42 #define GART_ENTRY_DATA (0x2c - GART_REG_BASE)
43 #define GART_ENTRY_PHYS_ADDR_VALID (1 << 31)
45 #define GART_PAGE_SHIFT 12
46 #define GART_PAGE_SIZE (1 << GART_PAGE_SHIFT)
47 #define GART_PAGE_MASK \
48 (~(GART_PAGE_SIZE - 1) & ~GART_ENTRY_PHYS_ADDR_VALID)
68 #define GART_PTE(_pfn) \
69 (GART_ENTRY_PHYS_ADDR_VALID | ((_pfn) << PAGE_SHIFT))
76 #define FLUSH_GART_REGS(gart) ((void)readl((gart)->regs + GART_CONFIG))
78 #define for_each_gart_pte(gart, iova) \
79 for (iova = gart->iovmm_base; \
80 iova < gart->iovmm_base + GART_PAGE_SIZE * gart->page_count; \
81 iova += GART_PAGE_SIZE)
83 static inline void gart_set_pte(
struct gart_device *gart,
93 static inline unsigned long gart_read_pte(
struct gart_device *gart,
109 gart_set_pte(gart, iova, data ? *(data++) : 0);
116 static void gart_dump_table(
struct gart_device *gart)
125 pte = gart_read_pte(gart, iova);
131 spin_unlock_irqrestore(&gart->
pte_lock, flags);
134 static inline void gart_dump_table(
struct gart_device *gart)
139 static inline bool gart_iova_range_valid(
struct gart_device *gart,
140 unsigned long iova,
size_t bytes)
142 unsigned long iova_start, iova_end, gart_start, gart_end;
145 iova_end = iova_start + bytes - 1;
149 if (iova_start < gart_start)
151 if (iova_end > gart_end)
156 static int gart_iommu_attach_dev(
struct iommu_domain *domain,
171 domain->
geometry.force_aperture =
true;
182 "%s is already attached\n", dev_name(dev));
189 dev_dbg(gart->
dev,
"Attached %s\n", dev_name(dev));
198 static void gart_iommu_detach_dev(
struct iommu_domain *domain,
210 dev_dbg(gart->
dev,
"Detached %s\n", dev_name(dev));
219 static int gart_iommu_domain_init(
struct iommu_domain *domain)
224 static void gart_iommu_domain_destroy(
struct iommu_domain *domain)
232 if (!list_empty(&gart->
client)) {
236 gart_iommu_detach_dev(domain, c->dev);
238 spin_unlock(&gart->client_lock);
249 if (!gart_iova_range_valid(gart, iova, bytes))
255 dev_err(gart->
dev,
"Invalid page: %08x\n", pa);
256 spin_unlock_irqrestore(&gart->
pte_lock, flags);
259 gart_set_pte(gart, iova,
GART_PTE(pfn));
261 spin_unlock_irqrestore(&gart->
pte_lock, flags);
265 static size_t gart_iommu_unmap(
struct iommu_domain *domain,
unsigned long iova,
271 if (!gart_iova_range_valid(gart, iova, bytes))
275 gart_set_pte(gart, iova, 0);
277 spin_unlock_irqrestore(&gart->
pte_lock, flags);
289 if (!gart_iova_range_valid(gart, iova, 0))
293 pte = gart_read_pte(gart, iova);
294 spin_unlock_irqrestore(&gart->
pte_lock, flags);
298 dev_err(gart->
dev,
"No entry for %08lx:%08x\n", iova, pa);
299 gart_dump_table(gart);
305 static int gart_iommu_domain_has_cap(
struct iommu_domain *domain,
311 static struct iommu_ops gart_iommu_ops = {
312 .domain_init = gart_iommu_domain_init,
313 .domain_destroy = gart_iommu_domain_destroy,
314 .attach_dev = gart_iommu_attach_dev,
315 .detach_dev = gart_iommu_detach_dev,
316 .map = gart_iommu_map,
317 .unmap = gart_iommu_unmap,
318 .iova_to_phys = gart_iommu_iova_to_phys,
319 .domain_has_cap = gart_iommu_domain_has_cap,
323 static int tegra_gart_suspend(
struct device *dev)
332 *(data++) = gart_read_pte(gart, iova);
333 spin_unlock_irqrestore(&gart->
pte_lock, flags);
337 static int tegra_gart_resume(
struct device *dev)
343 do_gart_setup(gart, gart->
savedata);
344 spin_unlock_irqrestore(&gart->
pte_lock, flags);
364 if (!res || !res_remap) {
365 dev_err(dev,
"GART memory aperture expected\n");
371 dev_err(dev,
"failed to allocate gart_device\n");
377 dev_err(dev,
"failed to remap GART registers\n");
385 INIT_LIST_HEAD(&gart->
client);
386 gart->
regs = gart_regs;
392 dev_err(dev,
"failed to allocate context save area\n");
397 platform_set_drvdata(pdev, gart);
398 do_gart_setup(gart, NULL);
414 struct gart_device *gart = platform_get_drvdata(pdev);
428 .suspend = tegra_gart_suspend,
429 .resume = tegra_gart_resume,
434 { .compatible =
"nvidia,tegra20-gart", },
441 .probe = tegra_gart_probe,
442 .remove = tegra_gart_remove,
445 .name =
"tegra-gart",
451 static int __devinit tegra_gart_init(
void)
457 static void __exit tegra_gart_exit(
void)