aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuman Anna <s-anna@ti.com>2014-10-22 18:22:27 -0400
committerJoerg Roedel <jroedel@suse.de>2014-10-23 08:32:25 -0400
commitbd4396f09a4a9e77423e92ec9448217ab46f6edf (patch)
treeb437a750480b8a463b7e136a21d3a0dac7d555b2
parent124262a2eecc4c3e6e96e083e50ce4909b2d69d9 (diff)
iommu/omap: Consolidate OMAP IOMMU modules
The OMAP IOMMU driver was originally designed as modules, and split into a core module and a thin arch-specific module through the OMAP arch-specific struct iommu_functions, to scale for both OMAP1 and OMAP2+ IOMMU variants. The driver can only be built for OMAP2+ platforms currently, and also can only be built-in after the adaptation to generic IOMMU API. The OMAP1 variant was never added and will most probably be never added (the code for the only potential user, its parent, DSP processor has already been cleaned up). So, consolidate the OMAP2 specific omap-iommu2 module into the core OMAP IOMMU driver - this eliminates the arch-specific ops structure and simplifies the driver into a single module that only implements the generic IOMMU API's iommu_ops. The following are the main changes: - omap-iommu2 module is completely eliminated, with the common definitions moved to the internal omap-iommu.h, and the ops implementations moved into omap-iommu.c - OMAP arch-specific struct iommu_functions is also eliminated, with the ops implementations directly absorbed into the calling functions - iotlb_alloc_cr() is no longer inlined and defined only when PREFETCH_IOTLB is defined - iotlb_dump_cr() is similarly defined only when CONFIG_OMAP_IOMMU_DEBUG is defined - Elimination of the OMAP IOMMU exported functions to register the arch ops, omap_install_iommu_arch() & omap_uninstall_iommu_arch() - Any stale comments about OMAP1 are also cleaned up Signed-off-by: Suman Anna <s-anna@ti.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-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");