aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2010-07-02 04:23:30 -0400
committerTony Lindgren <tony@atomide.com>2010-07-02 04:23:30 -0400
commitf40fd0e215b1bde4e43add1aacbe6faf6dbbea53 (patch)
tree05eeb8b7236f07303510162602afe05bfceecebe /arch/arm
parent9f2952dbcbc0a143cff19f2e44fc504901aad86f (diff)
parent1fd7f467127fcaea490451052fea22f234bbb206 (diff)
Merge branch 'v2.6.35-rc3-iommu-for-next' of git://gitorious.org/~doyu/lk/mainline into omap-for-linus
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap2/Makefile5
-rw-r--r--arch/arm/mach-omap2/iommu2.c44
-rw-r--r--arch/arm/mach-omap2/omap-iommu.c2
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h2
-rw-r--r--arch/arm/plat-omap/iommu.c27
-rw-r--r--arch/arm/plat-omap/iopgtable.h8
6 files changed, 70 insertions, 18 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index ea52b034e963..6c6d7c6f7aee 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -89,7 +89,10 @@ obj-$(CONFIG_OMAP3_EMU) += emu.o
89obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o 89obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
90mailbox_mach-objs := mailbox.o 90mailbox_mach-objs := mailbox.o
91 91
92obj-$(CONFIG_OMAP_IOMMU) := iommu2.o omap-iommu.o 92obj-$(CONFIG_OMAP_IOMMU) += iommu2.o
93
94iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o
95obj-y += $(iommu-m) $(iommu-y)
93 96
94i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o 97i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
95obj-y += $(i2c-omap-m) $(i2c-omap-y) 98obj-y += $(i2c-omap-m) $(i2c-omap-y)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index e82da680d908..14ee686b6492 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -44,9 +44,13 @@
44#define MMU_IRQ_EMUMISS (1 << 2) 44#define MMU_IRQ_EMUMISS (1 << 2)
45#define MMU_IRQ_TRANSLATIONFAULT (1 << 1) 45#define MMU_IRQ_TRANSLATIONFAULT (1 << 1)
46#define MMU_IRQ_TLBMISS (1 << 0) 46#define MMU_IRQ_TLBMISS (1 << 0)
47#define MMU_IRQ_MASK \ 47
48 (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_EMUMISS | \ 48#define __MMU_IRQ_FAULT \
49 MMU_IRQ_TRANSLATIONFAULT) 49 (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_EMUMISS | MMU_IRQ_TRANSLATIONFAULT)
50#define MMU_IRQ_MASK \
51 (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_TLBMISS)
52#define MMU_IRQ_TWL_MASK (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT)
53#define MMU_IRQ_TLB_MISS_MASK (__MMU_IRQ_FAULT | MMU_IRQ_TLBMISS)
50 54
51/* MMU_CNTL */ 55/* MMU_CNTL */
52#define MMU_CNTL_SHIFT 1 56#define MMU_CNTL_SHIFT 1
@@ -61,6 +65,26 @@
61 ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \ 65 ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \
62 ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0) 66 ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0)
63 67
68
69static void __iommu_set_twl(struct iommu *obj, bool on)
70{
71 u32 l = iommu_read_reg(obj, MMU_CNTL);
72
73 if (on)
74 iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
75 else
76 iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
77
78 l &= ~MMU_CNTL_MASK;
79 if (on)
80 l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
81 else
82 l |= (MMU_CNTL_MMU_EN);
83
84 iommu_write_reg(obj, l, MMU_CNTL);
85}
86
87
64static int omap2_iommu_enable(struct iommu *obj) 88static int omap2_iommu_enable(struct iommu *obj)
65{ 89{
66 u32 l, pa; 90 u32 l, pa;
@@ -96,13 +120,9 @@ static int omap2_iommu_enable(struct iommu *obj)
96 l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE); 120 l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
97 iommu_write_reg(obj, l, MMU_SYSCONFIG); 121 iommu_write_reg(obj, l, MMU_SYSCONFIG);
98 122
99 iommu_write_reg(obj, MMU_IRQ_MASK, MMU_IRQENABLE);
100 iommu_write_reg(obj, pa, MMU_TTB); 123 iommu_write_reg(obj, pa, MMU_TTB);
101 124
102 l = iommu_read_reg(obj, MMU_CNTL); 125 __iommu_set_twl(obj, true);
103 l &= ~MMU_CNTL_MASK;
104 l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
105 iommu_write_reg(obj, l, MMU_CNTL);
106 126
107 return 0; 127 return 0;
108} 128}
@@ -118,6 +138,11 @@ static void omap2_iommu_disable(struct iommu *obj)
118 dev_dbg(obj->dev, "%s is shutting down\n", obj->name); 138 dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
119} 139}
120 140
141static void omap2_iommu_set_twl(struct iommu *obj, bool on)
142{
143 __iommu_set_twl(obj, false);
144}
145
121static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra) 146static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
122{ 147{
123 int i; 148 int i;
@@ -147,7 +172,7 @@ static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
147 printk("\n"); 172 printk("\n");
148 173
149 iommu_write_reg(obj, stat, MMU_IRQSTATUS); 174 iommu_write_reg(obj, stat, MMU_IRQSTATUS);
150 omap2_iommu_disable(obj); 175
151 return stat; 176 return stat;
152} 177}
153 178
@@ -300,6 +325,7 @@ static const struct iommu_functions omap2_iommu_ops = {
300 325
301 .enable = omap2_iommu_enable, 326 .enable = omap2_iommu_enable,
302 .disable = omap2_iommu_disable, 327 .disable = omap2_iommu_disable,
328 .set_twl = omap2_iommu_set_twl,
303 .fault_isr = omap2_iommu_fault_isr, 329 .fault_isr = omap2_iommu_fault_isr,
304 330
305 .tlb_read_cr = omap2_tlb_read_cr, 331 .tlb_read_cr = omap2_tlb_read_cr,
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index eb9bee73e0cb..f5a1aad1a5c0 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -59,7 +59,7 @@ static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES];
59static struct iommu_device omap4_devices[] = { 59static struct iommu_device omap4_devices[] = {
60 { 60 {
61 .base = OMAP4_MMU1_BASE, 61 .base = OMAP4_MMU1_BASE,
62 .irq = INT_44XX_DUCATI_MMU_IRQ, 62 .irq = OMAP44XX_IRQ_DUCATI_MMU,
63 .pdata = { 63 .pdata = {
64 .name = "ducati", 64 .name = "ducati",
65 .nr_tlb_entries = 32, 65 .nr_tlb_entries = 32,
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 0752af9d099e..33c7d41cb6a5 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -80,6 +80,7 @@ struct iommu_functions {
80 80
81 int (*enable)(struct iommu *obj); 81 int (*enable)(struct iommu *obj);
82 void (*disable)(struct iommu *obj); 82 void (*disable)(struct iommu *obj);
83 void (*set_twl)(struct iommu *obj, bool on);
83 u32 (*fault_isr)(struct iommu *obj, u32 *ra); 84 u32 (*fault_isr)(struct iommu *obj, u32 *ra);
84 85
85 void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr); 86 void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
@@ -143,6 +144,7 @@ extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
143extern u32 iotlb_cr_to_virt(struct cr_regs *cr); 144extern u32 iotlb_cr_to_virt(struct cr_regs *cr);
144 145
145extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e); 146extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
147extern void iommu_set_twl(struct iommu *obj, bool on);
146extern void flush_iotlb_page(struct iommu *obj, u32 da); 148extern void flush_iotlb_page(struct iommu *obj, u32 da);
147extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end); 149extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
148extern void flush_iotlb_all(struct iommu *obj); 150extern void flush_iotlb_all(struct iommu *obj);
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index bc094dbacee6..a202a2ce6e3d 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -370,6 +370,23 @@ void flush_iotlb_all(struct iommu *obj)
370} 370}
371EXPORT_SYMBOL_GPL(flush_iotlb_all); 371EXPORT_SYMBOL_GPL(flush_iotlb_all);
372 372
373/**
374 * iommu_set_twl - enable/disable table walking logic
375 * @obj: target iommu
376 * @on: enable/disable
377 *
378 * Function used to enable/disable TWL. If one wants to work
379 * exclusively with locked TLB entries and receive notifications
380 * for TLB miss then call this function to disable TWL.
381 */
382void iommu_set_twl(struct iommu *obj, bool on)
383{
384 clk_enable(obj->clk);
385 arch_iommu->set_twl(obj, on);
386 clk_disable(obj->clk);
387}
388EXPORT_SYMBOL_GPL(iommu_set_twl);
389
373#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) 390#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
374 391
375ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes) 392ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes)
@@ -653,7 +670,7 @@ void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
653 if (!*iopgd) 670 if (!*iopgd)
654 goto out; 671 goto out;
655 672
656 if (*iopgd & IOPGD_TABLE) 673 if (iopgd_is_table(*iopgd))
657 iopte = iopte_offset(iopgd, da); 674 iopte = iopte_offset(iopgd, da);
658out: 675out:
659 *ppgd = iopgd; 676 *ppgd = iopgd;
@@ -670,7 +687,7 @@ static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
670 if (!*iopgd) 687 if (!*iopgd)
671 return 0; 688 return 0;
672 689
673 if (*iopgd & IOPGD_TABLE) { 690 if (iopgd_is_table(*iopgd)) {
674 int i; 691 int i;
675 u32 *iopte = iopte_offset(iopgd, da); 692 u32 *iopte = iopte_offset(iopgd, da);
676 693
@@ -745,7 +762,7 @@ static void iopgtable_clear_entry_all(struct iommu *obj)
745 if (!*iopgd) 762 if (!*iopgd)
746 continue; 763 continue;
747 764
748 if (*iopgd & IOPGD_TABLE) 765 if (iopgd_is_table(*iopgd))
749 iopte_free(iopte_offset(iopgd, 0)); 766 iopte_free(iopte_offset(iopgd, 0));
750 767
751 *iopgd = 0; 768 *iopgd = 0;
@@ -783,9 +800,11 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
783 if (!stat) 800 if (!stat)
784 return IRQ_HANDLED; 801 return IRQ_HANDLED;
785 802
803 iommu_disable(obj);
804
786 iopgd = iopgd_offset(obj, da); 805 iopgd = iopgd_offset(obj, da);
787 806
788 if (!(*iopgd & IOPGD_TABLE)) { 807 if (!iopgd_is_table(*iopgd)) {
789 dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__, 808 dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__,
790 da, iopgd, *iopgd); 809 da, iopgd, *iopgd);
791 return IRQ_NONE; 810 return IRQ_NONE;
diff --git a/arch/arm/plat-omap/iopgtable.h b/arch/arm/plat-omap/iopgtable.h
index ab23b6a140fd..c3e93bb0911f 100644
--- a/arch/arm/plat-omap/iopgtable.h
+++ b/arch/arm/plat-omap/iopgtable.h
@@ -63,6 +63,8 @@
63#define IOPGD_SECTION (2 << 0) 63#define IOPGD_SECTION (2 << 0)
64#define IOPGD_SUPER (1 << 18 | 2 << 0) 64#define IOPGD_SUPER (1 << 18 | 2 << 0)
65 65
66#define iopgd_is_table(x) (((x) & 3) == IOPGD_TABLE)
67
66#define IOPTE_SMALL (2 << 0) 68#define IOPTE_SMALL (2 << 0)
67#define IOPTE_LARGE (1 << 0) 69#define IOPTE_LARGE (1 << 0)
68 70
@@ -70,12 +72,12 @@
70#define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1)) 72#define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
71#define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da)) 73#define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da))
72 74
73#define iopte_paddr(iopgd) (*iopgd & ~((1 << 10) - 1)) 75#define iopgd_page_paddr(iopgd) (*iopgd & ~((1 << 10) - 1))
74#define iopte_vaddr(iopgd) ((u32 *)phys_to_virt(iopte_paddr(iopgd))) 76#define iopgd_page_vaddr(iopgd) ((u32 *)phys_to_virt(iopgd_page_paddr(iopgd)))
75 77
76/* to find an entry in the second-level page table. */ 78/* to find an entry in the second-level page table. */
77#define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1)) 79#define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
78#define iopte_offset(iopgd, da) (iopte_vaddr(iopgd) + iopte_index(da)) 80#define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da))
79 81
80static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa, 82static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
81 u32 flags) 83 u32 flags)