aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/Makefile1
-rw-r--r--drivers/iommu/omap-iommu.c263
-rw-r--r--drivers/iommu/omap-iommu.h61
-rw-r--r--drivers/iommu/omap-iommu2.c311
4 files changed, 217 insertions, 419 deletions
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 16edef74b8ee..18fa446a4ffa 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
11obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o 11obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
12obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o 12obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
13obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o 13obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
14obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o
15obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o 14obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
16obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o 15obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
17obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o 16obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index f9efa6ba99f5..91262fa2a351 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -76,53 +76,23 @@ struct iotlb_lock {
76 short vict; 76 short vict;
77}; 77};
78 78
79/* accommodate the difference between omap1 and omap2/3 */
80static const struct iommu_functions *arch_iommu;
81
82static struct platform_driver omap_iommu_driver; 79static struct platform_driver omap_iommu_driver;
83static struct kmem_cache *iopte_cachep; 80static struct kmem_cache *iopte_cachep;
84 81
85/** 82/**
86 * omap_install_iommu_arch - Install archtecure specific iommu functions
87 * @ops: a pointer to architecture specific iommu functions
88 *
89 * There are several kind of iommu algorithm(tlb, pagetable) among
90 * omap series. This interface installs such an iommu algorighm.
91 **/
92int omap_install_iommu_arch(const struct iommu_functions *ops)
93{
94 if (arch_iommu)
95 return -EBUSY;
96
97 arch_iommu = ops;
98 return 0;
99}
100EXPORT_SYMBOL_GPL(omap_install_iommu_arch);
101
102/**
103 * omap_uninstall_iommu_arch - Uninstall archtecure specific iommu functions
104 * @ops: a pointer to architecture specific iommu functions
105 *
106 * This interface uninstalls the iommu algorighm installed previously.
107 **/
108void omap_uninstall_iommu_arch(const struct iommu_functions *ops)
109{
110 if (arch_iommu != ops)
111 pr_err("%s: not your arch\n", __func__);
112
113 arch_iommu = NULL;
114}
115EXPORT_SYMBOL_GPL(omap_uninstall_iommu_arch);
116
117/**
118 * omap_iommu_save_ctx - Save registers for pm off-mode support 83 * omap_iommu_save_ctx - Save registers for pm off-mode support
119 * @dev: client device 84 * @dev: client device
120 **/ 85 **/
121void omap_iommu_save_ctx(struct device *dev) 86void omap_iommu_save_ctx(struct device *dev)
122{ 87{
123 struct omap_iommu *obj = dev_to_omap_iommu(dev); 88 struct omap_iommu *obj = dev_to_omap_iommu(dev);
89 u32 *p = obj->ctx;
90 int i;
124 91
125 arch_iommu->save_ctx(obj); 92 for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
93 p[i] = iommu_read_reg(obj, i * sizeof(u32));
94 dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
95 }
126} 96}
127EXPORT_SYMBOL_GPL(omap_iommu_save_ctx); 97EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
128 98
@@ -133,20 +103,75 @@ EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
133void omap_iommu_restore_ctx(struct device *dev) 103void omap_iommu_restore_ctx(struct device *dev)
134{ 104{
135 struct omap_iommu *obj = dev_to_omap_iommu(dev); 105 struct omap_iommu *obj = dev_to_omap_iommu(dev);
106 u32 *p = obj->ctx;
107 int i;
136 108
137 arch_iommu->restore_ctx(obj); 109 for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
110 iommu_write_reg(obj, p[i], i * sizeof(u32));
111 dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
112 }
138} 113}
139EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx); 114EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
140 115
116static void __iommu_set_twl(struct omap_iommu *obj, bool on)
117{
118 u32 l = iommu_read_reg(obj, MMU_CNTL);
119
120 if (on)
121 iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
122 else
123 iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
124
125 l &= ~MMU_CNTL_MASK;
126 if (on)
127 l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
128 else
129 l |= (MMU_CNTL_MMU_EN);
130
131 iommu_write_reg(obj, l, MMU_CNTL);
132}
133
134static int omap2_iommu_enable(struct omap_iommu *obj)
135{
136 u32 l, pa;
137
138 if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
139 return -EINVAL;
140
141 pa = virt_to_phys(obj->iopgd);
142 if (!IS_ALIGNED(pa, SZ_16K))
143 return -EINVAL;
144
145 l = iommu_read_reg(obj, MMU_REVISION);
146 dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
147 (l >> 4) & 0xf, l & 0xf);
148
149 iommu_write_reg(obj, pa, MMU_TTB);
150
151 if (obj->has_bus_err_back)
152 iommu_write_reg(obj, MMU_GP_REG_BUS_ERR_BACK_EN, MMU_GP_REG);
153
154 __iommu_set_twl(obj, true);
155
156 return 0;
157}
158
159static void omap2_iommu_disable(struct omap_iommu *obj)
160{
161 u32 l = iommu_read_reg(obj, MMU_CNTL);
162
163 l &= ~MMU_CNTL_MASK;
164 iommu_write_reg(obj, l, MMU_CNTL);
165
166 dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
167}
168
141static int iommu_enable(struct omap_iommu *obj) 169static int iommu_enable(struct omap_iommu *obj)
142{ 170{
143 int err; 171 int err;
144 struct platform_device *pdev = to_platform_device(obj->dev); 172 struct platform_device *pdev = to_platform_device(obj->dev);
145 struct iommu_platform_data *pdata = pdev->dev.platform_data; 173 struct iommu_platform_data *pdata = pdev->dev.platform_data;
146 174
147 if (!arch_iommu)
148 return -ENODEV;
149
150 if (pdata && pdata->deassert_reset) { 175 if (pdata && pdata->deassert_reset) {
151 err = pdata->deassert_reset(pdev, pdata->reset_name); 176 err = pdata->deassert_reset(pdev, pdata->reset_name);
152 if (err) { 177 if (err) {
@@ -157,7 +182,7 @@ static int iommu_enable(struct omap_iommu *obj)
157 182
158 pm_runtime_get_sync(obj->dev); 183 pm_runtime_get_sync(obj->dev);
159 184
160 err = arch_iommu->enable(obj); 185 err = omap2_iommu_enable(obj);
161 186
162 return err; 187 return err;
163} 188}
@@ -167,7 +192,7 @@ static void iommu_disable(struct omap_iommu *obj)
167 struct platform_device *pdev = to_platform_device(obj->dev); 192 struct platform_device *pdev = to_platform_device(obj->dev);
168 struct iommu_platform_data *pdata = pdev->dev.platform_data; 193 struct iommu_platform_data *pdata = pdev->dev.platform_data;
169 194
170 arch_iommu->disable(obj); 195 omap2_iommu_disable(obj);
171 196
172 pm_runtime_put_sync(obj->dev); 197 pm_runtime_put_sync(obj->dev);
173 198
@@ -182,7 +207,13 @@ void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
182{ 207{
183 BUG_ON(!cr || !e); 208 BUG_ON(!cr || !e);
184 209
185 arch_iommu->cr_to_e(cr, e); 210 e->da = cr->cam & MMU_CAM_VATAG_MASK;
211 e->pa = cr->ram & MMU_RAM_PADDR_MASK;
212 e->valid = cr->cam & MMU_CAM_V;
213 e->pgsz = cr->cam & MMU_CAM_PGSZ_MASK;
214 e->endian = cr->ram & MMU_RAM_ENDIAN_MASK;
215 e->elsz = cr->ram & MMU_RAM_ELSZ_MASK;
216 e->mixed = cr->ram & MMU_RAM_MIXED;
186} 217}
187EXPORT_SYMBOL_GPL(omap_iotlb_cr_to_e); 218EXPORT_SYMBOL_GPL(omap_iotlb_cr_to_e);
188 219
@@ -191,31 +222,46 @@ static inline int iotlb_cr_valid(struct cr_regs *cr)
191 if (!cr) 222 if (!cr)
192 return -EINVAL; 223 return -EINVAL;
193 224
194 return arch_iommu->cr_valid(cr); 225 return cr->cam & MMU_CAM_V;
195}
196
197static inline struct cr_regs *iotlb_alloc_cr(struct omap_iommu *obj,
198 struct iotlb_entry *e)
199{
200 if (!e)
201 return NULL;
202
203 return arch_iommu->alloc_cr(obj, e);
204} 226}
205 227
206static u32 iotlb_cr_to_virt(struct cr_regs *cr) 228static u32 iotlb_cr_to_virt(struct cr_regs *cr)
207{ 229{
208 return arch_iommu->cr_to_virt(cr); 230 u32 page_size = cr->cam & MMU_CAM_PGSZ_MASK;
231 u32 mask = get_cam_va_mask(cr->cam & page_size);
232
233 return cr->cam & mask;
209} 234}
210 235
211static u32 get_iopte_attr(struct iotlb_entry *e) 236static u32 get_iopte_attr(struct iotlb_entry *e)
212{ 237{
213 return arch_iommu->get_pte_attr(e); 238 u32 attr;
239
240 attr = e->mixed << 5;
241 attr |= e->endian;
242 attr |= e->elsz >> 3;
243 attr <<= (((e->pgsz == MMU_CAM_PGSZ_4K) ||
244 (e->pgsz == MMU_CAM_PGSZ_64K)) ? 0 : 6);
245 return attr;
214} 246}
215 247
216static u32 iommu_report_fault(struct omap_iommu *obj, u32 *da) 248static u32 iommu_report_fault(struct omap_iommu *obj, u32 *da)
217{ 249{
218 return arch_iommu->fault_isr(obj, da); 250 u32 status, fault_addr;
251
252 status = iommu_read_reg(obj, MMU_IRQSTATUS);
253 status &= MMU_IRQ_MASK;
254 if (!status) {
255 *da = 0;
256 return 0;
257 }
258
259 fault_addr = iommu_read_reg(obj, MMU_FAULT_AD);
260 *da = fault_addr;
261
262 iommu_write_reg(obj, status, MMU_IRQSTATUS);
263
264 return status;
219} 265}
220 266
221static void iotlb_lock_get(struct omap_iommu *obj, struct iotlb_lock *l) 267static void iotlb_lock_get(struct omap_iommu *obj, struct iotlb_lock *l)
@@ -241,31 +287,19 @@ static void iotlb_lock_set(struct omap_iommu *obj, struct iotlb_lock *l)
241 287
242static void iotlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr) 288static void iotlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
243{ 289{
244 arch_iommu->tlb_read_cr(obj, cr); 290 cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
291 cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
245} 292}
246 293
247static void iotlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr) 294static void iotlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
248{ 295{
249 arch_iommu->tlb_load_cr(obj, cr); 296 iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
297 iommu_write_reg(obj, cr->ram, MMU_RAM);
250 298
251 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); 299 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
252 iommu_write_reg(obj, 1, MMU_LD_TLB); 300 iommu_write_reg(obj, 1, MMU_LD_TLB);
253} 301}
254 302
255/**
256 * iotlb_dump_cr - Dump an iommu tlb entry into buf
257 * @obj: target iommu
258 * @cr: contents of cam and ram register
259 * @buf: output buffer
260 **/
261static inline ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr,
262 char *buf)
263{
264 BUG_ON(!cr || !buf);
265
266 return arch_iommu->dump_cr(obj, cr, buf);
267}
268
269/* only used in iotlb iteration for-loop */ 303/* only used in iotlb iteration for-loop */
270static struct cr_regs __iotlb_read_cr(struct omap_iommu *obj, int n) 304static struct cr_regs __iotlb_read_cr(struct omap_iommu *obj, int n)
271{ 305{
@@ -280,12 +314,36 @@ static struct cr_regs __iotlb_read_cr(struct omap_iommu *obj, int n)
280 return cr; 314 return cr;
281} 315}
282 316
317#ifdef PREFETCH_IOTLB
318static struct cr_regs *iotlb_alloc_cr(struct omap_iommu *obj,
319 struct iotlb_entry *e)
320{
321 struct cr_regs *cr;
322
323 if (!e)
324 return NULL;
325
326 if (e->da & ~(get_cam_va_mask(e->pgsz))) {
327 dev_err(obj->dev, "%s:\twrong alignment: %08x\n", __func__,
328 e->da);
329 return ERR_PTR(-EINVAL);
330 }
331
332 cr = kmalloc(sizeof(*cr), GFP_KERNEL);
333 if (!cr)
334 return ERR_PTR(-ENOMEM);
335
336 cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz | e->valid;
337 cr->ram = e->pa | e->endian | e->elsz | e->mixed;
338
339 return cr;
340}
341
283/** 342/**
284 * load_iotlb_entry - Set an iommu tlb entry 343 * load_iotlb_entry - Set an iommu tlb entry
285 * @obj: target iommu 344 * @obj: target iommu
286 * @e: an iommu tlb entry info 345 * @e: an iommu tlb entry info
287 **/ 346 **/
288#ifdef PREFETCH_IOTLB
289static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e) 347static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
290{ 348{
291 int err = 0; 349 int err = 0;
@@ -416,6 +474,44 @@ static void flush_iotlb_all(struct omap_iommu *obj)
416 474
417#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) 475#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
418 476
477#define pr_reg(name) \
478 do { \
479 ssize_t bytes; \
480 const char *str = "%20s: %08x\n"; \
481 const int maxcol = 32; \
482 bytes = snprintf(p, maxcol, str, __stringify(name), \
483 iommu_read_reg(obj, MMU_##name)); \
484 p += bytes; \
485 len -= bytes; \
486 if (len < maxcol) \
487 goto out; \
488 } while (0)
489
490static ssize_t
491omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
492{
493 char *p = buf;
494
495 pr_reg(REVISION);
496 pr_reg(IRQSTATUS);
497 pr_reg(IRQENABLE);
498 pr_reg(WALKING_ST);
499 pr_reg(CNTL);
500 pr_reg(FAULT_AD);
501 pr_reg(TTB);
502 pr_reg(LOCK);
503 pr_reg(LD_TLB);
504 pr_reg(CAM);
505 pr_reg(RAM);
506 pr_reg(GFLUSH);
507 pr_reg(FLUSH_ENTRY);
508 pr_reg(READ_CAM);
509 pr_reg(READ_RAM);
510 pr_reg(EMU_FAULT_AD);
511out:
512 return p - buf;
513}
514
419ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes) 515ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
420{ 516{
421 if (!obj || !buf) 517 if (!obj || !buf)
@@ -423,7 +519,7 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
423 519
424 pm_runtime_get_sync(obj->dev); 520 pm_runtime_get_sync(obj->dev);
425 521
426 bytes = arch_iommu->dump_ctx(obj, buf, bytes); 522 bytes = omap2_iommu_dump_ctx(obj, buf, bytes);
427 523
428 pm_runtime_put_sync(obj->dev); 524 pm_runtime_put_sync(obj->dev);
429 525
@@ -455,6 +551,24 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
455} 551}
456 552
457/** 553/**
554 * iotlb_dump_cr - Dump an iommu tlb entry into buf
555 * @obj: target iommu
556 * @cr: contents of cam and ram register
557 * @buf: output buffer
558 **/
559static ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr,
560 char *buf)
561{
562 char *p = buf;
563
564 /* FIXME: Need more detail analysis of cam/ram */
565 p += sprintf(p, "%08x %08x %01x\n", cr->cam, cr->ram,
566 (cr->cam & MMU_CAM_P) ? 1 : 0);
567
568 return p - buf;
569}
570
571/**
458 * omap_dump_tlb_entries - dump cr arrays to given buffer 572 * omap_dump_tlb_entries - dump cr arrays to given buffer
459 * @obj: target iommu 573 * @obj: target iommu
460 * @buf: output buffer 574 * @buf: output buffer
@@ -1008,7 +1122,6 @@ static u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa, int pgsz)
1008 e->da = da; 1122 e->da = da;
1009 e->pa = pa; 1123 e->pa = pa;
1010 e->valid = MMU_CAM_V; 1124 e->valid = MMU_CAM_V;
1011 /* FIXME: add OMAP1 support */
1012 e->pgsz = pgsz; 1125 e->pgsz = pgsz;
1013 e->endian = MMU_RAM_ENDIAN_LITTLE; 1126 e->endian = MMU_RAM_ENDIAN_LITTLE;
1014 e->elsz = MMU_RAM_ELSZ_8; 1127 e->elsz = MMU_RAM_ELSZ_8;
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 45fe67d641e2..0516e0ed77d7 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -13,10 +13,6 @@
13#ifndef _OMAP_IOMMU_H 13#ifndef _OMAP_IOMMU_H
14#define _OMAP_IOMMU_H 14#define _OMAP_IOMMU_H
15 15
16#if defined(CONFIG_ARCH_OMAP1)
17#error "iommu for this processor not implemented yet"
18#endif
19
20struct iotlb_entry { 16struct iotlb_entry {
21 u32 da; 17 u32 da;
22 u32 pa; 18 u32 pa;
@@ -68,31 +64,6 @@ struct cr_regs {
68 }; 64 };
69}; 65};
70 66
71/* architecture specific functions */
72struct iommu_functions {
73 int (*enable)(struct omap_iommu *obj);
74 void (*disable)(struct omap_iommu *obj);
75 void (*set_twl)(struct omap_iommu *obj, bool on);
76 u32 (*fault_isr)(struct omap_iommu *obj, u32 *ra);
77
78 void (*tlb_read_cr)(struct omap_iommu *obj, struct cr_regs *cr);
79 void (*tlb_load_cr)(struct omap_iommu *obj, struct cr_regs *cr);
80
81 struct cr_regs *(*alloc_cr)(struct omap_iommu *obj,
82 struct iotlb_entry *e);
83 int (*cr_valid)(struct cr_regs *cr);
84 u32 (*cr_to_virt)(struct cr_regs *cr);
85 void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
86 ssize_t (*dump_cr)(struct omap_iommu *obj, struct cr_regs *cr,
87 char *buf);
88
89 u32 (*get_pte_attr)(struct iotlb_entry *e);
90
91 void (*save_ctx)(struct omap_iommu *obj);
92 void (*restore_ctx)(struct omap_iommu *obj);
93 ssize_t (*dump_ctx)(struct omap_iommu *obj, char *buf, ssize_t len);
94};
95
96/** 67/**
97 * dev_to_omap_iommu() - retrieves an omap iommu object from a user device 68 * dev_to_omap_iommu() - retrieves an omap iommu object from a user device
98 * @dev: iommu client device 69 * @dev: iommu client device
@@ -130,6 +101,28 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
130/* 101/*
131 * MMU Register bit definitions 102 * MMU Register bit definitions
132 */ 103 */
104/* IRQSTATUS & IRQENABLE */
105#define MMU_IRQ_MULTIHITFAULT (1 << 4)
106#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
107#define MMU_IRQ_EMUMISS (1 << 2)
108#define MMU_IRQ_TRANSLATIONFAULT (1 << 1)
109#define MMU_IRQ_TLBMISS (1 << 0)
110
111#define __MMU_IRQ_FAULT \
112 (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_EMUMISS | MMU_IRQ_TRANSLATIONFAULT)
113#define MMU_IRQ_MASK \
114 (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_TLBMISS)
115#define MMU_IRQ_TWL_MASK (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT)
116#define MMU_IRQ_TLB_MISS_MASK (__MMU_IRQ_FAULT | MMU_IRQ_TLBMISS)
117
118/* MMU_CNTL */
119#define MMU_CNTL_SHIFT 1
120#define MMU_CNTL_MASK (7 << MMU_CNTL_SHIFT)
121#define MMU_CNTL_EML_TLB (1 << 3)
122#define MMU_CNTL_TWL_EN (1 << 2)
123#define MMU_CNTL_MMU_EN (1 << 1)
124
125/* CAM */
133#define MMU_CAM_VATAG_SHIFT 12 126#define MMU_CAM_VATAG_SHIFT 12
134#define MMU_CAM_VATAG_MASK \ 127#define MMU_CAM_VATAG_MASK \
135 ((~0UL >> MMU_CAM_VATAG_SHIFT) << MMU_CAM_VATAG_SHIFT) 128 ((~0UL >> MMU_CAM_VATAG_SHIFT) << MMU_CAM_VATAG_SHIFT)
@@ -141,6 +134,7 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
141#define MMU_CAM_PGSZ_4K (2 << 0) 134#define MMU_CAM_PGSZ_4K (2 << 0)
142#define MMU_CAM_PGSZ_16M (3 << 0) 135#define MMU_CAM_PGSZ_16M (3 << 0)
143 136
137/* RAM */
144#define MMU_RAM_PADDR_SHIFT 12 138#define MMU_RAM_PADDR_SHIFT 12
145#define MMU_RAM_PADDR_MASK \ 139#define MMU_RAM_PADDR_MASK \
146 ((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT) 140 ((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT)
@@ -162,6 +156,12 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
162 156
163#define MMU_GP_REG_BUS_ERR_BACK_EN 0x1 157#define MMU_GP_REG_BUS_ERR_BACK_EN 0x1
164 158
159#define get_cam_va_mask(pgsz) \
160 (((pgsz) == MMU_CAM_PGSZ_16M) ? 0xff000000 : \
161 ((pgsz) == MMU_CAM_PGSZ_1M) ? 0xfff00000 : \
162 ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \
163 ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0)
164
165/* 165/*
166 * utilities for super page(16MB, 1MB, 64KB and 4KB) 166 * utilities for super page(16MB, 1MB, 64KB and 4KB)
167 */ 167 */
@@ -197,9 +197,6 @@ omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
197extern int omap_foreach_iommu_device(void *data, 197extern int omap_foreach_iommu_device(void *data,
198 int (*fn)(struct device *, void *)); 198 int (*fn)(struct device *, void *));
199 199
200extern int omap_install_iommu_arch(const struct iommu_functions *ops);
201extern void omap_uninstall_iommu_arch(const struct iommu_functions *ops);
202
203extern ssize_t 200extern ssize_t
204omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len); 201omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len);
205extern size_t 202extern size_t
diff --git a/drivers/iommu/omap-iommu2.c b/drivers/iommu/omap-iommu2.c
deleted file mode 100644
index ce2fff37aa61..000000000000
--- a/drivers/iommu/omap-iommu2.c
+++ /dev/null
@@ -1,311 +0,0 @@
1/*
2 * omap iommu: omap2/3 architecture specific functions
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
7 * Paul Mundt and Toshihiro Kobayashi
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/err.h>
15#include <linux/device.h>
16#include <linux/io.h>
17#include <linux/jiffies.h>
18#include <linux/module.h>
19#include <linux/omap-iommu.h>
20#include <linux/slab.h>
21#include <linux/stringify.h>
22#include <linux/platform_data/iommu-omap.h>
23
24#include "omap-iommu.h"
25
26/*
27 * omap2 architecture specific register bit definitions
28 */
29/* IRQSTATUS & IRQENABLE */
30#define MMU_IRQ_MULTIHITFAULT (1 << 4)
31#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
32#define MMU_IRQ_EMUMISS (1 << 2)
33#define MMU_IRQ_TRANSLATIONFAULT (1 << 1)
34#define MMU_IRQ_TLBMISS (1 << 0)
35
36#define __MMU_IRQ_FAULT \
37 (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_EMUMISS | MMU_IRQ_TRANSLATIONFAULT)
38#define MMU_IRQ_MASK \
39 (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_TLBMISS)
40#define MMU_IRQ_TWL_MASK (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT)
41#define MMU_IRQ_TLB_MISS_MASK (__MMU_IRQ_FAULT | MMU_IRQ_TLBMISS)
42
43/* MMU_CNTL */
44#define MMU_CNTL_SHIFT 1
45#define MMU_CNTL_MASK (7 << MMU_CNTL_SHIFT)
46#define MMU_CNTL_EML_TLB (1 << 3)
47#define MMU_CNTL_TWL_EN (1 << 2)
48#define MMU_CNTL_MMU_EN (1 << 1)
49
50#define get_cam_va_mask(pgsz) \
51 (((pgsz) == MMU_CAM_PGSZ_16M) ? 0xff000000 : \
52 ((pgsz) == MMU_CAM_PGSZ_1M) ? 0xfff00000 : \
53 ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \
54 ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0)
55
56static void __iommu_set_twl(struct omap_iommu *obj, bool on)
57{
58 u32 l = iommu_read_reg(obj, MMU_CNTL);
59
60 if (on)
61 iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
62 else
63 iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
64
65 l &= ~MMU_CNTL_MASK;
66 if (on)
67 l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
68 else
69 l |= (MMU_CNTL_MMU_EN);
70
71 iommu_write_reg(obj, l, MMU_CNTL);
72}
73
74
75static int omap2_iommu_enable(struct omap_iommu *obj)
76{
77 u32 l, pa;
78
79 if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
80 return -EINVAL;
81
82 pa = virt_to_phys(obj->iopgd);
83 if (!IS_ALIGNED(pa, SZ_16K))
84 return -EINVAL;
85
86 l = iommu_read_reg(obj, MMU_REVISION);
87 dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
88 (l >> 4) & 0xf, l & 0xf);
89
90 iommu_write_reg(obj, pa, MMU_TTB);
91
92 if (obj->has_bus_err_back)
93 iommu_write_reg(obj, MMU_GP_REG_BUS_ERR_BACK_EN, MMU_GP_REG);
94
95 __iommu_set_twl(obj, true);
96
97 return 0;
98}
99
100static void omap2_iommu_disable(struct omap_iommu *obj)
101{
102 u32 l = iommu_read_reg(obj, MMU_CNTL);
103
104 l &= ~MMU_CNTL_MASK;
105 iommu_write_reg(obj, l, MMU_CNTL);
106
107 dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
108}
109
110static void omap2_iommu_set_twl(struct omap_iommu *obj, bool on)
111{
112 __iommu_set_twl(obj, false);
113}
114
115static u32 omap2_iommu_fault_isr(struct omap_iommu *obj, u32 *ra)
116{
117 u32 stat, da;
118
119 stat = iommu_read_reg(obj, MMU_IRQSTATUS);
120 stat &= MMU_IRQ_MASK;
121 if (!stat) {
122 *ra = 0;
123 return 0;
124 }
125
126 da = iommu_read_reg(obj, MMU_FAULT_AD);
127 *ra = da;
128
129 iommu_write_reg(obj, stat, MMU_IRQSTATUS);
130
131 return stat;
132}
133
134static void omap2_tlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
135{
136 cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
137 cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
138}
139
140static void omap2_tlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
141{
142 iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
143 iommu_write_reg(obj, cr->ram, MMU_RAM);
144}
145
146static u32 omap2_cr_to_virt(struct cr_regs *cr)
147{
148 u32 page_size = cr->cam & MMU_CAM_PGSZ_MASK;
149 u32 mask = get_cam_va_mask(cr->cam & page_size);
150
151 return cr->cam & mask;
152}
153
154static struct cr_regs *omap2_alloc_cr(struct omap_iommu *obj,
155 struct iotlb_entry *e)
156{
157 struct cr_regs *cr;
158
159 if (e->da & ~(get_cam_va_mask(e->pgsz))) {
160 dev_err(obj->dev, "%s:\twrong alignment: %08x\n", __func__,
161 e->da);
162 return ERR_PTR(-EINVAL);
163 }
164
165 cr = kmalloc(sizeof(*cr), GFP_KERNEL);
166 if (!cr)
167 return ERR_PTR(-ENOMEM);
168
169 cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz | e->valid;
170 cr->ram = e->pa | e->endian | e->elsz | e->mixed;
171
172 return cr;
173}
174
175static inline int omap2_cr_valid(struct cr_regs *cr)
176{
177 return cr->cam & MMU_CAM_V;
178}
179
180static u32 omap2_get_pte_attr(struct iotlb_entry *e)
181{
182 u32 attr;
183
184 attr = e->mixed << 5;
185 attr |= e->endian;
186 attr |= e->elsz >> 3;
187 attr <<= (((e->pgsz == MMU_CAM_PGSZ_4K) ||
188 (e->pgsz == MMU_CAM_PGSZ_64K)) ? 0 : 6);
189 return attr;
190}
191
192static ssize_t
193omap2_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, char *buf)
194{
195 char *p = buf;
196
197 /* FIXME: Need more detail analysis of cam/ram */
198 p += sprintf(p, "%08x %08x %01x\n", cr->cam, cr->ram,
199 (cr->cam & MMU_CAM_P) ? 1 : 0);
200
201 return p - buf;
202}
203
204#define pr_reg(name) \
205 do { \
206 ssize_t bytes; \
207 const char *str = "%20s: %08x\n"; \
208 const int maxcol = 32; \
209 bytes = snprintf(p, maxcol, str, __stringify(name), \
210 iommu_read_reg(obj, MMU_##name)); \
211 p += bytes; \
212 len -= bytes; \
213 if (len < maxcol) \
214 goto out; \
215 } while (0)
216
217static ssize_t
218omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
219{
220 char *p = buf;
221
222 pr_reg(REVISION);
223 pr_reg(IRQSTATUS);
224 pr_reg(IRQENABLE);
225 pr_reg(WALKING_ST);
226 pr_reg(CNTL);
227 pr_reg(FAULT_AD);
228 pr_reg(TTB);
229 pr_reg(LOCK);
230 pr_reg(LD_TLB);
231 pr_reg(CAM);
232 pr_reg(RAM);
233 pr_reg(GFLUSH);
234 pr_reg(FLUSH_ENTRY);
235 pr_reg(READ_CAM);
236 pr_reg(READ_RAM);
237 pr_reg(EMU_FAULT_AD);
238out:
239 return p - buf;
240}
241
242static void omap2_iommu_save_ctx(struct omap_iommu *obj)
243{
244 int i;
245 u32 *p = obj->ctx;
246
247 for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
248 p[i] = iommu_read_reg(obj, i * sizeof(u32));
249 dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
250 }
251}
252
253static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
254{
255 int i;
256 u32 *p = obj->ctx;
257
258 for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
259 iommu_write_reg(obj, p[i], i * sizeof(u32));
260 dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
261 }
262}
263
264static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
265{
266 e->da = cr->cam & MMU_CAM_VATAG_MASK;
267 e->pa = cr->ram & MMU_RAM_PADDR_MASK;
268 e->valid = cr->cam & MMU_CAM_V;
269 e->pgsz = cr->cam & MMU_CAM_PGSZ_MASK;
270 e->endian = cr->ram & MMU_RAM_ENDIAN_MASK;
271 e->elsz = cr->ram & MMU_RAM_ELSZ_MASK;
272 e->mixed = cr->ram & MMU_RAM_MIXED;
273}
274
275static const struct iommu_functions omap2_iommu_ops = {
276 .enable = omap2_iommu_enable,
277 .disable = omap2_iommu_disable,
278 .set_twl = omap2_iommu_set_twl,
279 .fault_isr = omap2_iommu_fault_isr,
280
281 .tlb_read_cr = omap2_tlb_read_cr,
282 .tlb_load_cr = omap2_tlb_load_cr,
283
284 .cr_to_e = omap2_cr_to_e,
285 .cr_to_virt = omap2_cr_to_virt,
286 .alloc_cr = omap2_alloc_cr,
287 .cr_valid = omap2_cr_valid,
288 .dump_cr = omap2_dump_cr,
289
290 .get_pte_attr = omap2_get_pte_attr,
291
292 .save_ctx = omap2_iommu_save_ctx,
293 .restore_ctx = omap2_iommu_restore_ctx,
294 .dump_ctx = omap2_iommu_dump_ctx,
295};
296
297static int __init omap2_iommu_init(void)
298{
299 return omap_install_iommu_arch(&omap2_iommu_ops);
300}
301module_init(omap2_iommu_init);
302
303static void __exit omap2_iommu_exit(void)
304{
305 omap_uninstall_iommu_arch(&omap2_iommu_ops);
306}
307module_exit(omap2_iommu_exit);
308
309MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
310MODULE_DESCRIPTION("omap iommu: omap2/3 architecture specific functions");
311MODULE_LICENSE("GPL v2");