aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/iommu.c')
-rw-r--r--arch/arm/plat-omap/iommu.c58
1 files changed, 31 insertions, 27 deletions
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 1e83facb6b7..9598d40e276 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -25,6 +25,11 @@
25 25
26#include "iopgtable.h" 26#include "iopgtable.h"
27 27
28#define for_each_iotlb_cr(obj, n, __i, cr) \
29 for (__i = 0; \
30 (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \
31 __i++)
32
28/* accommodate the difference between omap1 and omap2/3 */ 33/* accommodate the difference between omap1 and omap2/3 */
29static const struct iommu_functions *arch_iommu; 34static const struct iommu_functions *arch_iommu;
30 35
@@ -211,6 +216,20 @@ static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
211 return arch_iommu->dump_cr(obj, cr, buf); 216 return arch_iommu->dump_cr(obj, cr, buf);
212} 217}
213 218
219/* only used in iotlb iteration for-loop */
220static struct cr_regs __iotlb_read_cr(struct iommu *obj, int n)
221{
222 struct cr_regs cr;
223 struct iotlb_lock l;
224
225 iotlb_lock_get(obj, &l);
226 l.vict = n;
227 iotlb_lock_set(obj, &l);
228 iotlb_read_cr(obj, &cr);
229
230 return cr;
231}
232
214/** 233/**
215 * load_iotlb_entry - Set an iommu tlb entry 234 * load_iotlb_entry - Set an iommu tlb entry
216 * @obj: target iommu 235 * @obj: target iommu
@@ -218,7 +237,6 @@ static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
218 **/ 237 **/
219int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) 238int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
220{ 239{
221 int i;
222 int err = 0; 240 int err = 0;
223 struct iotlb_lock l; 241 struct iotlb_lock l;
224 struct cr_regs *cr; 242 struct cr_regs *cr;
@@ -235,21 +253,20 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
235 goto out; 253 goto out;
236 } 254 }
237 if (!e->prsvd) { 255 if (!e->prsvd) {
238 for (i = l.base; i < obj->nr_tlb_entries; i++) { 256 int i;
239 struct cr_regs tmp; 257 struct cr_regs tmp;
240 258
241 iotlb_lock_get(obj, &l); 259 for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, tmp)
242 l.vict = i;
243 iotlb_lock_set(obj, &l);
244 iotlb_read_cr(obj, &tmp);
245 if (!iotlb_cr_valid(&tmp)) 260 if (!iotlb_cr_valid(&tmp))
246 break; 261 break;
247 } 262
248 if (i == obj->nr_tlb_entries) { 263 if (i == obj->nr_tlb_entries) {
249 dev_dbg(obj->dev, "%s: full: no entry\n", __func__); 264 dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
250 err = -EBUSY; 265 err = -EBUSY;
251 goto out; 266 goto out;
252 } 267 }
268
269 iotlb_lock_get(obj, &l);
253 } else { 270 } else {
254 l.vict = l.base; 271 l.vict = l.base;
255 iotlb_lock_set(obj, &l); 272 iotlb_lock_set(obj, &l);
@@ -285,20 +302,15 @@ EXPORT_SYMBOL_GPL(load_iotlb_entry);
285 **/ 302 **/
286void flush_iotlb_page(struct iommu *obj, u32 da) 303void flush_iotlb_page(struct iommu *obj, u32 da)
287{ 304{
288 struct iotlb_lock l;
289 int i; 305 int i;
306 struct cr_regs cr;
290 307
291 clk_enable(obj->clk); 308 clk_enable(obj->clk);
292 309
293 for (i = 0; i < obj->nr_tlb_entries; i++) { 310 for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
294 struct cr_regs cr;
295 u32 start; 311 u32 start;
296 size_t bytes; 312 size_t bytes;
297 313
298 iotlb_lock_get(obj, &l);
299 l.vict = i;
300 iotlb_lock_set(obj, &l);
301 iotlb_read_cr(obj, &cr);
302 if (!iotlb_cr_valid(&cr)) 314 if (!iotlb_cr_valid(&cr))
303 continue; 315 continue;
304 316
@@ -308,7 +320,6 @@ void flush_iotlb_page(struct iommu *obj, u32 da)
308 if ((start <= da) && (da < start + bytes)) { 320 if ((start <= da) && (da < start + bytes)) {
309 dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n", 321 dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
310 __func__, start, da, bytes); 322 __func__, start, da, bytes);
311 iotlb_load_cr(obj, &cr);
312 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); 323 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
313 } 324 }
314 } 325 }
@@ -379,26 +390,19 @@ EXPORT_SYMBOL_GPL(iommu_dump_ctx);
379static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num) 390static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num)
380{ 391{
381 int i; 392 int i;
382 struct iotlb_lock saved, l; 393 struct iotlb_lock saved;
394 struct cr_regs tmp;
383 struct cr_regs *p = crs; 395 struct cr_regs *p = crs;
384 396
385 clk_enable(obj->clk); 397 clk_enable(obj->clk);
386
387 iotlb_lock_get(obj, &saved); 398 iotlb_lock_get(obj, &saved);
388 memcpy(&l, &saved, sizeof(saved));
389 399
390 for (i = 0; i < num; i++) { 400 for_each_iotlb_cr(obj, num, i, tmp) {
391 struct cr_regs tmp;
392
393 iotlb_lock_get(obj, &l);
394 l.vict = i;
395 iotlb_lock_set(obj, &l);
396 iotlb_read_cr(obj, &tmp);
397 if (!iotlb_cr_valid(&tmp)) 401 if (!iotlb_cr_valid(&tmp))
398 continue; 402 continue;
399
400 *p++ = tmp; 403 *p++ = tmp;
401 } 404 }
405
402 iotlb_lock_set(obj, &saved); 406 iotlb_lock_set(obj, &saved);
403 clk_disable(obj->clk); 407 clk_disable(obj->clk);
404 408