aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt21
-rw-r--r--drivers/iommu/Kconfig6
-rw-r--r--drivers/iommu/Makefile1
-rw-r--r--drivers/iommu/of_iommu.c90
-rw-r--r--drivers/iommu/tegra-smmu.c280
-rw-r--r--include/linux/of_iommu.h21
6 files changed, 287 insertions, 132 deletions
diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
new file mode 100644
index 000000000000..89fb5434b730
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
@@ -0,0 +1,21 @@
1NVIDIA Tegra 30 IOMMU H/W, SMMU (System Memory Management Unit)
2
3Required properties:
4- compatible : "nvidia,tegra30-smmu"
5- reg : Should contain 3 register banks(address and length) for each
6 of the SMMU register blocks.
7- interrupts : Should contain MC General interrupt.
8- nvidia,#asids : # of ASIDs
9- dma-window : IOVA start address and length.
10- nvidia,ahb : phandle to the ahb bus connected to SMMU.
11
12Example:
13 smmu {
14 compatible = "nvidia,tegra30-smmu";
15 reg = <0x7000f010 0x02c
16 0x7000f1f0 0x010
17 0x7000f228 0x05c>;
18 nvidia,#asids = <4>; /* # of ASIDs */
19 dma-window = <0 0x40000000>; /* IOVA start & length */
20 nvidia,ahb = <&ahb>;
21 };
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 340893727538..9f69b561f5db 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -13,6 +13,10 @@ menuconfig IOMMU_SUPPORT
13 13
14if IOMMU_SUPPORT 14if IOMMU_SUPPORT
15 15
16config OF_IOMMU
17 def_bool y
18 depends on OF
19
16# MSM IOMMU support 20# MSM IOMMU support
17config MSM_IOMMU 21config MSM_IOMMU
18 bool "MSM IOMMU Support" 22 bool "MSM IOMMU Support"
@@ -154,7 +158,7 @@ config TEGRA_IOMMU_GART
154 158
155config TEGRA_IOMMU_SMMU 159config TEGRA_IOMMU_SMMU
156 bool "Tegra SMMU IOMMU Support" 160 bool "Tegra SMMU IOMMU Support"
157 depends on ARCH_TEGRA_3x_SOC 161 depends on ARCH_TEGRA_3x_SOC && TEGRA_AHB
158 select IOMMU_API 162 select IOMMU_API
159 help 163 help
160 Enables support for remapping discontiguous physical memory 164 Enables support for remapping discontiguous physical memory
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 76e54ef796de..14a4d5fc94fa 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -1,4 +1,5 @@
1obj-$(CONFIG_IOMMU_API) += iommu.o 1obj-$(CONFIG_IOMMU_API) += iommu.o
2obj-$(CONFIG_OF_IOMMU) += of_iommu.o
2obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o 3obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
3obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o 4obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
4obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o 5obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
new file mode 100644
index 000000000000..ee249bc959f8
--- /dev/null
+++ b/drivers/iommu/of_iommu.c
@@ -0,0 +1,90 @@
1/*
2 * OF helpers for IOMMU
3 *
4 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include <linux/export.h>
21#include <linux/limits.h>
22#include <linux/of.h>
23
24/**
25 * of_get_dma_window - Parse *dma-window property and returns 0 if found.
26 *
27 * @dn: device node
28 * @prefix: prefix for property name if any
29 * @index: index to start to parse
30 * @busno: Returns busno if supported. Otherwise pass NULL
31 * @addr: Returns address that DMA starts
32 * @size: Returns the range that DMA can handle
33 *
34 * This supports different formats flexibly. "prefix" can be
35 * configured if any. "busno" and "index" are optionally
36 * specified. Set 0(or NULL) if not used.
37 */
38int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
39 unsigned long *busno, dma_addr_t *addr, size_t *size)
40{
41 const __be32 *dma_window, *end;
42 int bytes, cur_index = 0;
43 char propname[NAME_MAX], addrname[NAME_MAX], sizename[NAME_MAX];
44
45 if (!dn || !addr || !size)
46 return -EINVAL;
47
48 if (!prefix)
49 prefix = "";
50
51 snprintf(propname, sizeof(propname), "%sdma-window", prefix);
52 snprintf(addrname, sizeof(addrname), "%s#dma-address-cells", prefix);
53 snprintf(sizename, sizeof(sizename), "%s#dma-size-cells", prefix);
54
55 dma_window = of_get_property(dn, propname, &bytes);
56 if (!dma_window)
57 return -ENODEV;
58 end = dma_window + bytes / sizeof(*dma_window);
59
60 while (dma_window < end) {
61 u32 cells;
62 const void *prop;
63
64 /* busno is one cell if supported */
65 if (busno)
66 *busno = be32_to_cpup(dma_window++);
67
68 prop = of_get_property(dn, addrname, NULL);
69 if (!prop)
70 prop = of_get_property(dn, "#address-cells", NULL);
71
72 cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn);
73 if (!cells)
74 return -EINVAL;
75 *addr = of_read_number(dma_window, cells);
76 dma_window += cells;
77
78 prop = of_get_property(dn, sizename, NULL);
79 cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn);
80 if (!cells)
81 return -EINVAL;
82 *size = of_read_number(dma_window, cells);
83 dma_window += cells;
84
85 if (cur_index++ == index)
86 break;
87 }
88 return 0;
89}
90EXPORT_SYMBOL_GPL(of_get_dma_window);
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 3f3d09d560ea..541d210cb421 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -30,12 +30,15 @@
30#include <linux/sched.h> 30#include <linux/sched.h>
31#include <linux/iommu.h> 31#include <linux/iommu.h>
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/of.h>
34#include <linux/of_iommu.h>
33 35
34#include <asm/page.h> 36#include <asm/page.h>
35#include <asm/cacheflush.h> 37#include <asm/cacheflush.h>
36 38
37#include <mach/iomap.h> 39#include <mach/iomap.h>
38#include <mach/smmu.h> 40#include <mach/smmu.h>
41#include <mach/tegra-ahb.h>
39 42
40/* bitmap of the page sizes currently supported */ 43/* bitmap of the page sizes currently supported */
41#define SMMU_IOMMU_PGSIZES (SZ_4K) 44#define SMMU_IOMMU_PGSIZES (SZ_4K)
@@ -111,12 +114,6 @@
111 114
112#define SMMU_PDE_NEXT_SHIFT 28 115#define SMMU_PDE_NEXT_SHIFT 28
113 116
114/* AHB Arbiter Registers */
115#define AHB_XBAR_CTRL 0xe0
116#define AHB_XBAR_CTRL_SMMU_INIT_DONE_DONE 1
117#define AHB_XBAR_CTRL_SMMU_INIT_DONE_SHIFT 17
118
119#define SMMU_NUM_ASIDS 4
120#define SMMU_TLB_FLUSH_VA_SECTION__MASK 0xffc00000 117#define SMMU_TLB_FLUSH_VA_SECTION__MASK 0xffc00000
121#define SMMU_TLB_FLUSH_VA_SECTION__SHIFT 12 /* right shift */ 118#define SMMU_TLB_FLUSH_VA_SECTION__SHIFT 12 /* right shift */
122#define SMMU_TLB_FLUSH_VA_GROUP__MASK 0xffffc000 119#define SMMU_TLB_FLUSH_VA_GROUP__MASK 0xffffc000
@@ -136,6 +133,7 @@
136 133
137#define SMMU_PAGE_SHIFT 12 134#define SMMU_PAGE_SHIFT 12
138#define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT) 135#define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT)
136#define SMMU_PAGE_MASK ((1 << SMMU_PAGE_SHIFT) - 1)
139 137
140#define SMMU_PDIR_COUNT 1024 138#define SMMU_PDIR_COUNT 1024
141#define SMMU_PDIR_SIZE (sizeof(unsigned long) * SMMU_PDIR_COUNT) 139#define SMMU_PDIR_SIZE (sizeof(unsigned long) * SMMU_PDIR_COUNT)
@@ -177,6 +175,8 @@
177#define SMMU_ASID_DISABLE 0 175#define SMMU_ASID_DISABLE 0
178#define SMMU_ASID_ASID(n) ((n) & ~SMMU_ASID_ENABLE(0)) 176#define SMMU_ASID_ASID(n) ((n) & ~SMMU_ASID_ENABLE(0))
179 177
178#define NUM_SMMU_REG_BANKS 3
179
180#define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1) 180#define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1)
181#define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0) 181#define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0)
182#define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1) 182#define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1)
@@ -235,14 +235,12 @@ struct smmu_as {
235 * Per SMMU device - IOMMU device 235 * Per SMMU device - IOMMU device
236 */ 236 */
237struct smmu_device { 237struct smmu_device {
238 void __iomem *regs, *regs_ahbarb; 238 void __iomem *regs[NUM_SMMU_REG_BANKS];
239 unsigned long iovmm_base; /* remappable base address */ 239 unsigned long iovmm_base; /* remappable base address */
240 unsigned long page_count; /* total remappable size */ 240 unsigned long page_count; /* total remappable size */
241 spinlock_t lock; 241 spinlock_t lock;
242 char *name; 242 char *name;
243 struct device *dev; 243 struct device *dev;
244 int num_as;
245 struct smmu_as *as; /* Run-time allocated array */
246 struct page *avp_vector_page; /* dummy page shared by all AS's */ 244 struct page *avp_vector_page; /* dummy page shared by all AS's */
247 245
248 /* 246 /*
@@ -252,29 +250,50 @@ struct smmu_device {
252 unsigned long translation_enable_1; 250 unsigned long translation_enable_1;
253 unsigned long translation_enable_2; 251 unsigned long translation_enable_2;
254 unsigned long asid_security; 252 unsigned long asid_security;
253
254 struct device_node *ahb;
255
256 int num_as;
257 struct smmu_as as[0]; /* Run-time allocated array */
255}; 258};
256 259
257static struct smmu_device *smmu_handle; /* unique for a system */ 260static struct smmu_device *smmu_handle; /* unique for a system */
258 261
259/* 262/*
260 * SMMU/AHB register accessors 263 * SMMU register accessors
261 */ 264 */
262static inline u32 smmu_read(struct smmu_device *smmu, size_t offs) 265static inline u32 smmu_read(struct smmu_device *smmu, size_t offs)
263{ 266{
264 return readl(smmu->regs + offs); 267 BUG_ON(offs < 0x10);
265} 268 if (offs < 0x3c)
266static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) 269 return readl(smmu->regs[0] + offs - 0x10);
267{ 270 BUG_ON(offs < 0x1f0);
268 writel(val, smmu->regs + offs); 271 if (offs < 0x200)
272 return readl(smmu->regs[1] + offs - 0x1f0);
273 BUG_ON(offs < 0x228);
274 if (offs < 0x284)
275 return readl(smmu->regs[2] + offs - 0x228);
276 BUG();
269} 277}
270 278
271static inline u32 ahb_read(struct smmu_device *smmu, size_t offs) 279static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs)
272{
273 return readl(smmu->regs_ahbarb + offs);
274}
275static inline void ahb_write(struct smmu_device *smmu, u32 val, size_t offs)
276{ 280{
277 writel(val, smmu->regs_ahbarb + offs); 281 BUG_ON(offs < 0x10);
282 if (offs < 0x3c) {
283 writel(val, smmu->regs[0] + offs - 0x10);
284 return;
285 }
286 BUG_ON(offs < 0x1f0);
287 if (offs < 0x200) {
288 writel(val, smmu->regs[1] + offs - 0x1f0);
289 return;
290 }
291 BUG_ON(offs < 0x228);
292 if (offs < 0x284) {
293 writel(val, smmu->regs[2] + offs - 0x228);
294 return;
295 }
296 BUG();
278} 297}
279 298
280#define VA_PAGE_TO_PA(va, page) \ 299#define VA_PAGE_TO_PA(va, page) \
@@ -370,7 +389,7 @@ static void smmu_flush_regs(struct smmu_device *smmu, int enable)
370 FLUSH_SMMU_REGS(smmu); 389 FLUSH_SMMU_REGS(smmu);
371} 390}
372 391
373static void smmu_setup_regs(struct smmu_device *smmu) 392static int smmu_setup_regs(struct smmu_device *smmu)
374{ 393{
375 int i; 394 int i;
376 u32 val; 395 u32 val;
@@ -398,10 +417,7 @@ static void smmu_setup_regs(struct smmu_device *smmu)
398 417
399 smmu_flush_regs(smmu, 1); 418 smmu_flush_regs(smmu, 1);
400 419
401 val = ahb_read(smmu, AHB_XBAR_CTRL); 420 return tegra_ahb_enable_smmu(smmu->ahb);
402 val |= AHB_XBAR_CTRL_SMMU_INIT_DONE_DONE <<
403 AHB_XBAR_CTRL_SMMU_INIT_DONE_SHIFT;
404 ahb_write(smmu, val, AHB_XBAR_CTRL);
405} 421}
406 422
407static void flush_ptc_and_tlb(struct smmu_device *smmu, 423static void flush_ptc_and_tlb(struct smmu_device *smmu,
@@ -537,33 +553,42 @@ static inline void put_signature(struct smmu_as *as,
537#endif 553#endif
538 554
539/* 555/*
540 * Caller must lock/unlock as 556 * Caller must not hold as->lock
541 */ 557 */
542static int alloc_pdir(struct smmu_as *as) 558static int alloc_pdir(struct smmu_as *as)
543{ 559{
544 unsigned long *pdir; 560 unsigned long *pdir, flags;
545 int pdn; 561 int pdn, err = 0;
546 u32 val; 562 u32 val;
547 struct smmu_device *smmu = as->smmu; 563 struct smmu_device *smmu = as->smmu;
564 struct page *page;
565 unsigned int *cnt;
548 566
549 if (as->pdir_page) 567 /*
550 return 0; 568 * do the allocation, then grab as->lock
569 */
570 cnt = devm_kzalloc(smmu->dev,
571 sizeof(cnt[0]) * SMMU_PDIR_COUNT,
572 GFP_KERNEL);
573 page = alloc_page(GFP_KERNEL | __GFP_DMA);
551 574
552 as->pte_count = devm_kzalloc(smmu->dev, 575 spin_lock_irqsave(&as->lock, flags);
553 sizeof(as->pte_count[0]) * SMMU_PDIR_COUNT, GFP_ATOMIC); 576
554 if (!as->pte_count) { 577 if (as->pdir_page) {
555 dev_err(smmu->dev, 578 /* We raced, free the redundant */
556 "failed to allocate smmu_device PTE cunters\n"); 579 err = -EAGAIN;
557 return -ENOMEM; 580 goto err_out;
558 } 581 }
559 as->pdir_page = alloc_page(GFP_ATOMIC | __GFP_DMA); 582
560 if (!as->pdir_page) { 583 if (!page || !cnt) {
561 dev_err(smmu->dev, 584 dev_err(smmu->dev, "failed to allocate at %s\n", __func__);
562 "failed to allocate smmu_device page directory\n"); 585 err = -ENOMEM;
563 devm_kfree(smmu->dev, as->pte_count); 586 goto err_out;
564 as->pte_count = NULL;
565 return -ENOMEM;
566 } 587 }
588
589 as->pdir_page = page;
590 as->pte_count = cnt;
591
567 SetPageReserved(as->pdir_page); 592 SetPageReserved(as->pdir_page);
568 pdir = page_address(as->pdir_page); 593 pdir = page_address(as->pdir_page);
569 594
@@ -579,7 +604,17 @@ static int alloc_pdir(struct smmu_as *as)
579 smmu_write(smmu, val, SMMU_TLB_FLUSH); 604 smmu_write(smmu, val, SMMU_TLB_FLUSH);
580 FLUSH_SMMU_REGS(as->smmu); 605 FLUSH_SMMU_REGS(as->smmu);
581 606
607 spin_unlock_irqrestore(&as->lock, flags);
608
582 return 0; 609 return 0;
610
611err_out:
612 spin_unlock_irqrestore(&as->lock, flags);
613
614 devm_kfree(smmu->dev, cnt);
615 if (page)
616 __free_page(page);
617 return err;
583} 618}
584 619
585static void __smmu_iommu_unmap(struct smmu_as *as, dma_addr_t iova) 620static void __smmu_iommu_unmap(struct smmu_as *as, dma_addr_t iova)
@@ -771,30 +806,28 @@ out:
771 806
772static int smmu_iommu_domain_init(struct iommu_domain *domain) 807static int smmu_iommu_domain_init(struct iommu_domain *domain)
773{ 808{
774 int i; 809 int i, err = -ENODEV;
775 unsigned long flags; 810 unsigned long flags;
776 struct smmu_as *as; 811 struct smmu_as *as;
777 struct smmu_device *smmu = smmu_handle; 812 struct smmu_device *smmu = smmu_handle;
778 813
779 /* Look for a free AS with lock held */ 814 /* Look for a free AS with lock held */
780 for (i = 0; i < smmu->num_as; i++) { 815 for (i = 0; i < smmu->num_as; i++) {
781 struct smmu_as *tmp = &smmu->as[i]; 816 as = &smmu->as[i];
782 817 if (!as->pdir_page) {
783 spin_lock_irqsave(&tmp->lock, flags); 818 err = alloc_pdir(as);
784 if (!tmp->pdir_page) { 819 if (!err)
785 as = tmp; 820 goto found;
786 goto found;
787 } 821 }
788 spin_unlock_irqrestore(&tmp->lock, flags); 822 if (err != -EAGAIN)
823 break;
789 } 824 }
790 dev_err(smmu->dev, "no free AS\n"); 825 if (i == smmu->num_as)
791 return -ENODEV; 826 dev_err(smmu->dev, "no free AS\n");
827 return err;
792 828
793found: 829found:
794 if (alloc_pdir(as) < 0) 830 spin_lock_irqsave(&smmu->lock, flags);
795 goto err_alloc_pdir;
796
797 spin_lock(&smmu->lock);
798 831
799 /* Update PDIR register */ 832 /* Update PDIR register */
800 smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID); 833 smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID);
@@ -802,17 +835,13 @@ found:
802 SMMU_MK_PDIR(as->pdir_page, as->pdir_attr), SMMU_PTB_DATA); 835 SMMU_MK_PDIR(as->pdir_page, as->pdir_attr), SMMU_PTB_DATA);
803 FLUSH_SMMU_REGS(smmu); 836 FLUSH_SMMU_REGS(smmu);
804 837
805 spin_unlock(&smmu->lock); 838 spin_unlock_irqrestore(&smmu->lock, flags);
806 839
807 spin_unlock_irqrestore(&as->lock, flags);
808 domain->priv = as; 840 domain->priv = as;
809 841
810 dev_dbg(smmu->dev, "smmu_as@%p\n", as); 842 dev_dbg(smmu->dev, "smmu_as@%p\n", as);
811 return 0;
812 843
813err_alloc_pdir: 844 return 0;
814 spin_unlock_irqrestore(&as->lock, flags);
815 return -ENODEV;
816} 845}
817 846
818static void smmu_iommu_domain_destroy(struct iommu_domain *domain) 847static void smmu_iommu_domain_destroy(struct iommu_domain *domain)
@@ -873,65 +902,73 @@ static int tegra_smmu_resume(struct device *dev)
873{ 902{
874 struct smmu_device *smmu = dev_get_drvdata(dev); 903 struct smmu_device *smmu = dev_get_drvdata(dev);
875 unsigned long flags; 904 unsigned long flags;
905 int err;
876 906
877 spin_lock_irqsave(&smmu->lock, flags); 907 spin_lock_irqsave(&smmu->lock, flags);
878 smmu_setup_regs(smmu); 908 err = smmu_setup_regs(smmu);
879 spin_unlock_irqrestore(&smmu->lock, flags); 909 spin_unlock_irqrestore(&smmu->lock, flags);
880 return 0; 910 return err;
881} 911}
882 912
883static int tegra_smmu_probe(struct platform_device *pdev) 913static int tegra_smmu_probe(struct platform_device *pdev)
884{ 914{
885 struct smmu_device *smmu; 915 struct smmu_device *smmu;
886 struct resource *regs, *regs2, *window;
887 struct device *dev = &pdev->dev; 916 struct device *dev = &pdev->dev;
888 int i, err = 0; 917 int i, asids, err = 0;
918 dma_addr_t uninitialized_var(base);
919 size_t bytes, uninitialized_var(size);
889 920
890 if (smmu_handle) 921 if (smmu_handle)
891 return -EIO; 922 return -EIO;
892 923
893 BUILD_BUG_ON(PAGE_SHIFT != SMMU_PAGE_SHIFT); 924 BUILD_BUG_ON(PAGE_SHIFT != SMMU_PAGE_SHIFT);
894 925
895 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 926 if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
896 regs2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
897 window = platform_get_resource(pdev, IORESOURCE_MEM, 2);
898 if (!regs || !regs2 || !window) {
899 dev_err(dev, "No SMMU resources\n");
900 return -ENODEV; 927 return -ENODEV;
901 }
902 928
903 smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); 929 bytes = sizeof(*smmu) + asids * sizeof(*smmu->as);
930 smmu = devm_kzalloc(dev, bytes, GFP_KERNEL);
904 if (!smmu) { 931 if (!smmu) {
905 dev_err(dev, "failed to allocate smmu_device\n"); 932 dev_err(dev, "failed to allocate smmu_device\n");
906 return -ENOMEM; 933 return -ENOMEM;
907 } 934 }
908 935
909 smmu->dev = dev; 936 for (i = 0; i < ARRAY_SIZE(smmu->regs); i++) {
910 smmu->num_as = SMMU_NUM_ASIDS; 937 struct resource *res;
911 smmu->iovmm_base = (unsigned long)window->start; 938
912 smmu->page_count = resource_size(window) >> SMMU_PAGE_SHIFT; 939 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
913 smmu->regs = devm_ioremap(dev, regs->start, resource_size(regs)); 940 if (!res)
914 smmu->regs_ahbarb = devm_ioremap(dev, regs2->start, 941 return -ENODEV;
915 resource_size(regs2)); 942 smmu->regs[i] = devm_request_and_ioremap(&pdev->dev, res);
916 if (!smmu->regs || !smmu->regs_ahbarb) { 943 if (!smmu->regs[i])
917 dev_err(dev, "failed to remap SMMU registers\n"); 944 return -EBUSY;
918 err = -ENXIO;
919 goto fail;
920 } 945 }
921 946
947 err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base, &size);
948 if (err)
949 return -ENODEV;
950
951 if (size & SMMU_PAGE_MASK)
952 return -EINVAL;
953
954 size >>= SMMU_PAGE_SHIFT;
955 if (!size)
956 return -EINVAL;
957
958 smmu->ahb = of_parse_phandle(dev->of_node, "nvidia,ahb", 0);
959 if (!smmu->ahb)
960 return -ENODEV;
961
962 smmu->dev = dev;
963 smmu->num_as = asids;
964 smmu->iovmm_base = base;
965 smmu->page_count = size;
966
922 smmu->translation_enable_0 = ~0; 967 smmu->translation_enable_0 = ~0;
923 smmu->translation_enable_1 = ~0; 968 smmu->translation_enable_1 = ~0;
924 smmu->translation_enable_2 = ~0; 969 smmu->translation_enable_2 = ~0;
925 smmu->asid_security = 0; 970 smmu->asid_security = 0;
926 971
927 smmu->as = devm_kzalloc(dev,
928 sizeof(smmu->as[0]) * smmu->num_as, GFP_KERNEL);
929 if (!smmu->as) {
930 dev_err(dev, "failed to allocate smmu_as\n");
931 err = -ENOMEM;
932 goto fail;
933 }
934
935 for (i = 0; i < smmu->num_as; i++) { 972 for (i = 0; i < smmu->num_as; i++) {
936 struct smmu_as *as = &smmu->as[i]; 973 struct smmu_as *as = &smmu->as[i];
937 974
@@ -945,57 +982,28 @@ static int tegra_smmu_probe(struct platform_device *pdev)
945 INIT_LIST_HEAD(&as->client); 982 INIT_LIST_HEAD(&as->client);
946 } 983 }
947 spin_lock_init(&smmu->lock); 984 spin_lock_init(&smmu->lock);
948 smmu_setup_regs(smmu); 985 err = smmu_setup_regs(smmu);
986 if (err)
987 return err;
949 platform_set_drvdata(pdev, smmu); 988 platform_set_drvdata(pdev, smmu);
950 989
951 smmu->avp_vector_page = alloc_page(GFP_KERNEL); 990 smmu->avp_vector_page = alloc_page(GFP_KERNEL);
952 if (!smmu->avp_vector_page) 991 if (!smmu->avp_vector_page)
953 goto fail; 992 return -ENOMEM;
954 993
955 smmu_handle = smmu; 994 smmu_handle = smmu;
956 return 0; 995 return 0;
957
958fail:
959 if (smmu->avp_vector_page)
960 __free_page(smmu->avp_vector_page);
961 if (smmu->regs)
962 devm_iounmap(dev, smmu->regs);
963 if (smmu->regs_ahbarb)
964 devm_iounmap(dev, smmu->regs_ahbarb);
965 if (smmu && smmu->as) {
966 for (i = 0; i < smmu->num_as; i++) {
967 if (smmu->as[i].pdir_page) {
968 ClearPageReserved(smmu->as[i].pdir_page);
969 __free_page(smmu->as[i].pdir_page);
970 }
971 }
972 devm_kfree(dev, smmu->as);
973 }
974 devm_kfree(dev, smmu);
975 return err;
976} 996}
977 997
978static int tegra_smmu_remove(struct platform_device *pdev) 998static int tegra_smmu_remove(struct platform_device *pdev)
979{ 999{
980 struct smmu_device *smmu = platform_get_drvdata(pdev); 1000 struct smmu_device *smmu = platform_get_drvdata(pdev);
981 struct device *dev = smmu->dev; 1001 int i;
982 1002
983 smmu_write(smmu, SMMU_CONFIG_DISABLE, SMMU_CONFIG); 1003 smmu_write(smmu, SMMU_CONFIG_DISABLE, SMMU_CONFIG);
984 platform_set_drvdata(pdev, NULL); 1004 for (i = 0; i < smmu->num_as; i++)
985 if (smmu->as) { 1005 free_pdir(&smmu->as[i]);
986 int i; 1006 __free_page(smmu->avp_vector_page);
987
988 for (i = 0; i < smmu->num_as; i++)
989 free_pdir(&smmu->as[i]);
990 devm_kfree(dev, smmu->as);
991 }
992 if (smmu->avp_vector_page)
993 __free_page(smmu->avp_vector_page);
994 if (smmu->regs)
995 devm_iounmap(dev, smmu->regs);
996 if (smmu->regs_ahbarb)
997 devm_iounmap(dev, smmu->regs_ahbarb);
998 devm_kfree(dev, smmu);
999 smmu_handle = NULL; 1007 smmu_handle = NULL;
1000 return 0; 1008 return 0;
1001} 1009}
@@ -1005,6 +1013,14 @@ const struct dev_pm_ops tegra_smmu_pm_ops = {
1005 .resume = tegra_smmu_resume, 1013 .resume = tegra_smmu_resume,
1006}; 1014};
1007 1015
1016#ifdef CONFIG_OF
1017static struct of_device_id tegra_smmu_of_match[] __devinitdata = {
1018 { .compatible = "nvidia,tegra30-smmu", },
1019 { },
1020};
1021MODULE_DEVICE_TABLE(of, tegra_smmu_of_match);
1022#endif
1023
1008static struct platform_driver tegra_smmu_driver = { 1024static struct platform_driver tegra_smmu_driver = {
1009 .probe = tegra_smmu_probe, 1025 .probe = tegra_smmu_probe,
1010 .remove = tegra_smmu_remove, 1026 .remove = tegra_smmu_remove,
@@ -1012,6 +1028,7 @@ static struct platform_driver tegra_smmu_driver = {
1012 .owner = THIS_MODULE, 1028 .owner = THIS_MODULE,
1013 .name = "tegra-smmu", 1029 .name = "tegra-smmu",
1014 .pm = &tegra_smmu_pm_ops, 1030 .pm = &tegra_smmu_pm_ops,
1031 .of_match_table = of_match_ptr(tegra_smmu_of_match),
1015 }, 1032 },
1016}; 1033};
1017 1034
@@ -1031,4 +1048,5 @@ module_exit(tegra_smmu_exit);
1031 1048
1032MODULE_DESCRIPTION("IOMMU API for SMMU in Tegra30"); 1049MODULE_DESCRIPTION("IOMMU API for SMMU in Tegra30");
1033MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); 1050MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
1051MODULE_ALIAS("platform:tegra-smmu");
1034MODULE_LICENSE("GPL v2"); 1052MODULE_LICENSE("GPL v2");
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
new file mode 100644
index 000000000000..51a560f34bca
--- /dev/null
+++ b/include/linux/of_iommu.h
@@ -0,0 +1,21 @@
1#ifndef __OF_IOMMU_H
2#define __OF_IOMMU_H
3
4#ifdef CONFIG_OF_IOMMU
5
6extern int of_get_dma_window(struct device_node *dn, const char *prefix,
7 int index, unsigned long *busno, dma_addr_t *addr,
8 size_t *size);
9
10#else
11
12static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
13 int index, unsigned long *busno, dma_addr_t *addr,
14 size_t *size)
15{
16 return -EINVAL;
17}
18
19#endif /* CONFIG_OF_IOMMU */
20
21#endif /* __OF_IOMMU_H */