1 /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License version 2 and 5 * only version 2 as published by the Free Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 * 02110-1301, USA. 16 */ 17 18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/platform_device.h> 22 #include <linux/errno.h> 23 #include <linux/io.h> 24 #include <linux/interrupt.h> 25 #include <linux/list.h> 26 #include <linux/spinlock.h> 27 #include <linux/slab.h> 28 #include <linux/iommu.h> 29 #include <linux/clk.h> 30 31 #include <asm/cacheflush.h> 32 #include <asm/sizes.h> 33 34 #include <mach/iommu_hw-8xxx.h> 35 #include <mach/iommu.h> 36 37 #define MRC(reg, processor, op1, crn, crm, op2) \ 38 __asm__ __volatile__ ( \ 39 " mrc " #processor "," #op1 ", %0," #crn "," #crm "," #op2 "\n" \ 40 : "=r" (reg)) 41 42 #define RCP15_PRRR(reg) MRC(reg, p15, 0, c10, c2, 0) 43 #define RCP15_NMRR(reg) MRC(reg, p15, 0, c10, c2, 1) 44 45 /* bitmap of the page sizes currently supported */ 46 #define MSM_IOMMU_PGSIZES (SZ_4K | SZ_64K | SZ_1M | SZ_16M) 47 48 static int msm_iommu_tex_class[4]; 49 50 DEFINE_SPINLOCK(msm_iommu_lock); 51 52 struct msm_priv { 53 unsigned long *pgtable; 54 struct list_head list_attached; 55 }; 56 57 static int __enable_clocks(struct msm_iommu_drvdata *drvdata) 58 { 59 int ret; 60 61 ret = clk_enable(drvdata->pclk); 62 if (ret) 63 goto fail; 64 65 if (drvdata->clk) { 66 ret = clk_enable(drvdata->clk); 67 if (ret) 68 clk_disable(drvdata->pclk); 69 } 70 fail: 71 return ret; 72 } 73 74 static void __disable_clocks(struct msm_iommu_drvdata *drvdata) 75 { 76 if (drvdata->clk) 77 clk_disable(drvdata->clk); 78 clk_disable(drvdata->pclk); 79 } 80 81 static int __flush_iotlb(struct iommu_domain *domain) 82 { 83 struct msm_priv *priv = domain->priv; 84 struct msm_iommu_drvdata *iommu_drvdata; 85 struct msm_iommu_ctx_drvdata *ctx_drvdata; 86 int ret = 0; 87 #ifndef CONFIG_IOMMU_PGTABLES_L2 88 unsigned long *fl_table = priv->pgtable; 89 int i; 90 91 if (!list_empty(&priv->list_attached)) { 92 dmac_flush_range(fl_table, fl_table + SZ_16K); 93 94 for (i = 0; i < NUM_FL_PTE; i++) 95 if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) { 96 void *sl_table = __va(fl_table[i] & 97 FL_BASE_MASK); 98 dmac_flush_range(sl_table, sl_table + SZ_4K); 99 } 100 } 101 #endif 102 103 list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) { 104 if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent) 105 BUG(); 106 107 iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent); 108 BUG_ON(!iommu_drvdata); 109 110 ret = __enable_clocks(iommu_drvdata); 111 if (ret) 112 goto fail; 113 114 SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0); 115 __disable_clocks(iommu_drvdata); 116 } 117 fail: 118 return ret; 119 } 120 121 static void __reset_context(void __iomem *base, int ctx) 122 { 123 SET_BPRCOSH(base, ctx, 0); 124 SET_BPRCISH(base, ctx, 0); 125 SET_BPRCNSH(base, ctx, 0); 126 SET_BPSHCFG(base, ctx, 0); 127 SET_BPMTCFG(base, ctx, 0); 128 SET_ACTLR(base, ctx, 0); 129 SET_SCTLR(base, ctx, 0); 130 SET_FSRRESTORE(base, ctx, 0); 131 SET_TTBR0(base, ctx, 0); 132 SET_TTBR1(base, ctx, 0); 133 SET_TTBCR(base, ctx, 0); 134 SET_BFBCR(base, ctx, 0); 135 SET_PAR(base, ctx, 0); 136 SET_FAR(base, ctx, 0); 137 SET_CTX_TLBIALL(base, ctx, 0); 138 SET_TLBFLPTER(base, ctx, 0); 139 SET_TLBSLPTER(base, ctx, 0); 140 SET_TLBLKCR(base, ctx, 0); 141 SET_PRRR(base, ctx, 0); 142 SET_NMRR(base, ctx, 0); 143 } 144 145 static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable) 146 { 147 unsigned int prrr, nmrr; 148 __reset_context(base, ctx); 149 150 /* Set up HTW mode */ 151 /* TLB miss configuration: perform HTW on miss */ 152 SET_TLBMCFG(base, ctx, 0x3); 153 154 /* V2P configuration: HTW for access */ 155 SET_V2PCFG(base, ctx, 0x3); 156 157 SET_TTBCR(base, ctx, 0); 158 SET_TTBR0_PA(base, ctx, (pgtable >> 14)); 159 160 /* Invalidate the TLB for this context */ 161 SET_CTX_TLBIALL(base, ctx, 0); 162 163 /* Set interrupt number to "secure" interrupt */ 164 SET_IRPTNDX(base, ctx, 0); 165 166 /* Enable context fault interrupt */ 167 SET_CFEIE(base, ctx, 1); 168 169 /* Stall access on a context fault and let the handler deal with it */ 170 SET_CFCFG(base, ctx, 1); 171 172 /* Redirect all cacheable requests to L2 slave port. */ 173 SET_RCISH(base, ctx, 1); 174 SET_RCOSH(base, ctx, 1); 175 SET_RCNSH(base, ctx, 1); 176 177 /* Turn on TEX Remap */ 178 SET_TRE(base, ctx, 1); 179 180 /* Set TEX remap attributes */ 181 RCP15_PRRR(prrr); 182 RCP15_NMRR(nmrr); 183 SET_PRRR(base, ctx, prrr); 184 SET_NMRR(base, ctx, nmrr); 185 186 /* Turn on BFB prefetch */ 187 SET_BFBDFE(base, ctx, 1); 188 189 #ifdef CONFIG_IOMMU_PGTABLES_L2 190 /* Configure page tables as inner-cacheable and shareable to reduce 191 * the TLB miss penalty. 192 */ 193 SET_TTBR0_SH(base, ctx, 1); 194 SET_TTBR1_SH(base, ctx, 1); 195 196 SET_TTBR0_NOS(base, ctx, 1); 197 SET_TTBR1_NOS(base, ctx, 1); 198 199 SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */ 200 SET_TTBR0_IRGNL(base, ctx, 1); 201 202 SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */ 203 SET_TTBR1_IRGNL(base, ctx, 1); 204 205 SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */ 206 SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */ 207 #endif 208 209 /* Enable the MMU */ 210 SET_M(base, ctx, 1); 211 } 212 213 static int msm_iommu_domain_init(struct iommu_domain *domain) 214 { 215 struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL); 216 217 if (!priv) 218 goto fail_nomem; 219 220 INIT_LIST_HEAD(&priv->list_attached); 221 priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL, 222 get_order(SZ_16K)); 223 224 if (!priv->pgtable) 225 goto fail_nomem; 226 227 memset(priv->pgtable, 0, SZ_16K); 228 domain->priv = priv; 229 return 0; 230 231 fail_nomem: 232 kfree(priv); 233 return -ENOMEM; 234 } 235 236 static void msm_iommu_domain_destroy(struct iommu_domain *domain) 237 { 238 struct msm_priv *priv; 239 unsigned long flags; 240 unsigned long *fl_table; 241 int i; 242 243 spin_lock_irqsave(&msm_iommu_lock, flags); 244 priv = domain->priv; 245 domain->priv = NULL; 246 247 if (priv) { 248 fl_table = priv->pgtable; 249 250 for (i = 0; i < NUM_FL_PTE; i++) 251 if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) 252 free_page((unsigned long) __va(((fl_table[i]) & 253 FL_BASE_MASK))); 254 255 free_pages((unsigned long)priv->pgtable, get_order(SZ_16K)); 256 priv->pgtable = NULL; 257 } 258 259 kfree(priv); 260 spin_unlock_irqrestore(&msm_iommu_lock, flags); 261 } 262 263 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) 264 { 265 struct msm_priv *priv; 266 struct msm_iommu_ctx_dev *ctx_dev; 267 struct msm_iommu_drvdata *iommu_drvdata; 268 struct msm_iommu_ctx_drvdata *ctx_drvdata; 269 struct msm_iommu_ctx_drvdata *tmp_drvdata; 270 int ret = 0; 271 unsigned long flags; 272 273 spin_lock_irqsave(&msm_iommu_lock, flags); 274 275 priv = domain->priv; 276 277 if (!priv || !dev) { 278 ret = -EINVAL; 279 goto fail; 280 } 281 282 iommu_drvdata = dev_get_drvdata(dev->parent); 283 ctx_drvdata = dev_get_drvdata(dev); 284 ctx_dev = dev->platform_data; 285 286 if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) { 287 ret = -EINVAL; 288 goto fail; 289 } 290 291 if (!list_empty(&ctx_drvdata->attached_elm)) { 292 ret = -EBUSY; 293 goto fail; 294 } 295 296 list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm) 297 if (tmp_drvdata == ctx_drvdata) { 298 ret = -EBUSY; 299 goto fail; 300 } 301 302 ret = __enable_clocks(iommu_drvdata); 303 if (ret) 304 goto fail; 305 306 __program_context(iommu_drvdata->base, ctx_dev->num, 307 __pa(priv->pgtable)); 308 309 __disable_clocks(iommu_drvdata); 310 list_add(&(ctx_drvdata->attached_elm), &priv->list_attached); 311 ret = __flush_iotlb(domain); 312 313 fail: 314 spin_unlock_irqrestore(&msm_iommu_lock, flags); 315 return ret; 316 } 317 318 static void msm_iommu_detach_dev(struct iommu_domain *domain, 319 struct device *dev) 320 { 321 struct msm_priv *priv; 322 struct msm_iommu_ctx_dev *ctx_dev; 323 struct msm_iommu_drvdata *iommu_drvdata; 324 struct msm_iommu_ctx_drvdata *ctx_drvdata; 325 unsigned long flags; 326 int ret; 327 328 spin_lock_irqsave(&msm_iommu_lock, flags); 329 priv = domain->priv; 330 331 if (!priv || !dev) 332 goto fail; 333 334 iommu_drvdata = dev_get_drvdata(dev->parent); 335 ctx_drvdata = dev_get_drvdata(dev); 336 ctx_dev = dev->platform_data; 337 338 if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) 339 goto fail; 340 341 ret = __flush_iotlb(domain); 342 if (ret) 343 goto fail; 344 345 ret = __enable_clocks(iommu_drvdata); 346 if (ret) 347 goto fail; 348 349 __reset_context(iommu_drvdata->base, ctx_dev->num); 350 __disable_clocks(iommu_drvdata); 351 list_del_init(&ctx_drvdata->attached_elm); 352 353 fail: 354 spin_unlock_irqrestore(&msm_iommu_lock, flags); 355 } 356 357 static int msm_iommu_map(struct iommu_domain *domain, unsigned long va, 358 phys_addr_t pa, size_t len, int prot) 359 { 360 struct msm_priv *priv; 361 unsigned long flags; 362 unsigned long *fl_table; 363 unsigned long *fl_pte; 364 unsigned long fl_offset; 365 unsigned long *sl_table; 366 unsigned long *sl_pte; 367 unsigned long sl_offset; 368 unsigned int pgprot; 369 int ret = 0, tex, sh; 370 371 spin_lock_irqsave(&msm_iommu_lock, flags); 372 373 sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0; 374 tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK]; 375 376 if (tex < 0 || tex > NUM_TEX_CLASS - 1) { 377 ret = -EINVAL; 378 goto fail; 379 } 380 381 priv = domain->priv; 382 if (!priv) { 383 ret = -EINVAL; 384 goto fail; 385 } 386 387 fl_table = priv->pgtable; 388 389 if (len != SZ_16M && len != SZ_1M && 390 len != SZ_64K && len != SZ_4K) { 391 pr_debug("Bad size: %d\n", len); 392 ret = -EINVAL; 393 goto fail; 394 } 395 396 if (!fl_table) { 397 pr_debug("Null page table\n"); 398 ret = -EINVAL; 399 goto fail; 400 } 401 402 if (len == SZ_16M || len == SZ_1M) { 403 pgprot = sh ? FL_SHARED : 0; 404 pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0; 405 pgprot |= tex & 0x02 ? FL_CACHEABLE : 0; 406 pgprot |= tex & 0x04 ? FL_TEX0 : 0; 407 } else { 408 pgprot = sh ? SL_SHARED : 0; 409 pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0; 410 pgprot |= tex & 0x02 ? SL_CACHEABLE : 0; 411 pgprot |= tex & 0x04 ? SL_TEX0 : 0; 412 } 413 414 fl_offset = FL_OFFSET(va); /* Upper 12 bits */ 415 fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */ 416 417 if (len == SZ_16M) { 418 int i = 0; 419 for (i = 0; i < 16; i++) 420 *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION | 421 FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT | 422 FL_SHARED | FL_NG | pgprot; 423 } 424 425 if (len == SZ_1M) 426 *fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG | 427 FL_TYPE_SECT | FL_SHARED | pgprot; 428 429 /* Need a 2nd level table */ 430 if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) { 431 unsigned long *sl; 432 sl = (unsigned long *) __get_free_pages(GFP_ATOMIC, 433 get_order(SZ_4K)); 434 435 if (!sl) { 436 pr_debug("Could not allocate second level table\n"); 437 ret = -ENOMEM; 438 goto fail; 439 } 440 441 memset(sl, 0, SZ_4K); 442 *fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE); 443 } 444 445 sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK)); 446 sl_offset = SL_OFFSET(va); 447 sl_pte = sl_table + sl_offset; 448 449 450 if (len == SZ_4K) 451 *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG | 452 SL_SHARED | SL_TYPE_SMALL | pgprot; 453 454 if (len == SZ_64K) { 455 int i; 456 457 for (i = 0; i < 16; i++) 458 *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 | 459 SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot; 460 } 461 462 ret = __flush_iotlb(domain); 463 fail: 464 spin_unlock_irqrestore(&msm_iommu_lock, flags); 465 return ret; 466 } 467 468 static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va, 469 size_t len) 470 { 471 struct msm_priv *priv; 472 unsigned long flags; 473 unsigned long *fl_table; 474 unsigned long *fl_pte; 475 unsigned long fl_offset; 476 unsigned long *sl_table; 477 unsigned long *sl_pte; 478 unsigned long sl_offset; 479 int i, ret = 0; 480 481 spin_lock_irqsave(&msm_iommu_lock, flags); 482 483 priv = domain->priv; 484 485 if (!priv) 486 goto fail; 487 488 fl_table = priv->pgtable; 489 490 if (len != SZ_16M && len != SZ_1M && 491 len != SZ_64K && len != SZ_4K) { 492 pr_debug("Bad length: %d\n", len); 493 goto fail; 494 } 495 496 if (!fl_table) { 497 pr_debug("Null page table\n"); 498 goto fail; 499 } 500 501 fl_offset = FL_OFFSET(va); /* Upper 12 bits */ 502 fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */ 503 504 if (*fl_pte == 0) { 505 pr_debug("First level PTE is 0\n"); 506 goto fail; 507 } 508 509 /* Unmap supersection */ 510 if (len == SZ_16M) 511 for (i = 0; i < 16; i++) 512 *(fl_pte+i) = 0; 513 514 if (len == SZ_1M) 515 *fl_pte = 0; 516 517 sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK)); 518 sl_offset = SL_OFFSET(va); 519 sl_pte = sl_table + sl_offset; 520 521 if (len == SZ_64K) { 522 for (i = 0; i < 16; i++) 523 *(sl_pte+i) = 0; 524 } 525 526 if (len == SZ_4K) 527 *sl_pte = 0; 528 529 if (len == SZ_4K || len == SZ_64K) { 530 int used = 0; 531 532 for (i = 0; i < NUM_SL_PTE; i++) 533 if (sl_table[i]) 534 used = 1; 535 if (!used) { 536 free_page((unsigned long)sl_table); 537 *fl_pte = 0; 538 } 539 } 540 541 ret = __flush_iotlb(domain); 542 543 fail: 544 spin_unlock_irqrestore(&msm_iommu_lock, flags); 545 546 /* the IOMMU API requires us to return how many bytes were unmapped */ 547 len = ret ? 0 : len; 548 return len; 549 } 550 551 static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain, 552 unsigned long va) 553 { 554 struct msm_priv *priv; 555 struct msm_iommu_drvdata *iommu_drvdata; 556 struct msm_iommu_ctx_drvdata *ctx_drvdata; 557 unsigned int par; 558 unsigned long flags; 559 void __iomem *base; 560 phys_addr_t ret = 0; 561 int ctx; 562 563 spin_lock_irqsave(&msm_iommu_lock, flags); 564 565 priv = domain->priv; 566 if (list_empty(&priv->list_attached)) 567 goto fail; 568 569 ctx_drvdata = list_entry(priv->list_attached.next, 570 struct msm_iommu_ctx_drvdata, attached_elm); 571 iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent); 572 573 base = iommu_drvdata->base; 574 ctx = ctx_drvdata->num; 575 576 ret = __enable_clocks(iommu_drvdata); 577 if (ret) 578 goto fail; 579 580 /* Invalidate context TLB */ 581 SET_CTX_TLBIALL(base, ctx, 0); 582 SET_V2PPR(base, ctx, va & V2Pxx_VA); 583 584 par = GET_PAR(base, ctx); 585 586 /* We are dealing with a supersection */ 587 if (GET_NOFAULT_SS(base, ctx)) 588 ret = (par & 0xFF000000) | (va & 0x00FFFFFF); 589 else /* Upper 20 bits from PAR, lower 12 from VA */ 590 ret = (par & 0xFFFFF000) | (va & 0x00000FFF); 591 592 if (GET_FAULT(base, ctx)) 593 ret = 0; 594 595 __disable_clocks(iommu_drvdata); 596 fail: 597 spin_unlock_irqrestore(&msm_iommu_lock, flags); 598 return ret; 599 } 600 601 static int msm_iommu_domain_has_cap(struct iommu_domain *domain, 602 unsigned long cap) 603 { 604 return 0; 605 } 606 607 static void print_ctx_regs(void __iomem *base, int ctx) 608 { 609 unsigned int fsr = GET_FSR(base, ctx); 610 pr_err("FAR = %08x PAR = %08x\n", 611 GET_FAR(base, ctx), GET_PAR(base, ctx)); 612 pr_err("FSR = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr, 613 (fsr & 0x02) ? "TF " : "", 614 (fsr & 0x04) ? "AFF " : "", 615 (fsr & 0x08) ? "APF " : "", 616 (fsr & 0x10) ? "TLBMF " : "", 617 (fsr & 0x20) ? "HTWDEEF " : "", 618 (fsr & 0x40) ? "HTWSEEF " : "", 619 (fsr & 0x80) ? "MHF " : "", 620 (fsr & 0x10000) ? "SL " : "", 621 (fsr & 0x40000000) ? "SS " : "", 622 (fsr & 0x80000000) ? "MULTI " : ""); 623 624 pr_err("FSYNR0 = %08x FSYNR1 = %08x\n", 625 GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx)); 626 pr_err("TTBR0 = %08x TTBR1 = %08x\n", 627 GET_TTBR0(base, ctx), GET_TTBR1(base, ctx)); 628 pr_err("SCTLR = %08x ACTLR = %08x\n", 629 GET_SCTLR(base, ctx), GET_ACTLR(base, ctx)); 630 pr_err("PRRR = %08x NMRR = %08x\n", 631 GET_PRRR(base, ctx), GET_NMRR(base, ctx)); 632 } 633 634 irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id) 635 { 636 struct msm_iommu_drvdata *drvdata = dev_id; 637 void __iomem *base; 638 unsigned int fsr; 639 int i, ret; 640 641 spin_lock(&msm_iommu_lock); 642 643 if (!drvdata) { 644 pr_err("Invalid device ID in context interrupt handler\n"); 645 goto fail; 646 } 647 648 base = drvdata->base; 649 650 pr_err("Unexpected IOMMU page fault!\n"); 651 pr_err("base = %08x\n", (unsigned int) base); 652 653 ret = __enable_clocks(drvdata); 654 if (ret) 655 goto fail; 656 657 for (i = 0; i < drvdata->ncb; i++) { 658 fsr = GET_FSR(base, i); 659 if (fsr) { 660 pr_err("Fault occurred in context %d.\n", i); 661 pr_err("Interesting registers:\n"); 662 print_ctx_regs(base, i); 663 SET_FSR(base, i, 0x4000000F); 664 } 665 } 666 __disable_clocks(drvdata); 667 fail: 668 spin_unlock(&msm_iommu_lock); 669 return 0; 670 } 671 672 static struct iommu_ops msm_iommu_ops = { 673 .domain_init = msm_iommu_domain_init, 674 .domain_destroy = msm_iommu_domain_destroy, 675 .attach_dev = msm_iommu_attach_dev, 676 .detach_dev = msm_iommu_detach_dev, 677 .map = msm_iommu_map, 678 .unmap = msm_iommu_unmap, 679 .iova_to_phys = msm_iommu_iova_to_phys, 680 .domain_has_cap = msm_iommu_domain_has_cap, 681 .pgsize_bitmap = MSM_IOMMU_PGSIZES, 682 }; 683 684 static int __init get_tex_class(int icp, int ocp, int mt, int nos) 685 { 686 int i = 0; 687 unsigned int prrr = 0; 688 unsigned int nmrr = 0; 689 int c_icp, c_ocp, c_mt, c_nos; 690 691 RCP15_PRRR(prrr); 692 RCP15_NMRR(nmrr); 693 694 for (i = 0; i < NUM_TEX_CLASS; i++) { 695 c_nos = PRRR_NOS(prrr, i); 696 c_mt = PRRR_MT(prrr, i); 697 c_icp = NMRR_ICP(nmrr, i); 698 c_ocp = NMRR_OCP(nmrr, i); 699 700 if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos) 701 return i; 702 } 703 704 return -ENODEV; 705 } 706 707 static void __init setup_iommu_tex_classes(void) 708 { 709 msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] = 710 get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1); 711 712 msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] = 713 get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1); 714 715 msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] = 716 get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1); 717 718 msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] = 719 get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1); 720 } 721 722 static int __init msm_iommu_init(void) 723 { 724 setup_iommu_tex_classes(); 725 bus_set_iommu(&platform_bus_type, &msm_iommu_ops); 726 return 0; 727 } 728 729 subsys_initcall(msm_iommu_init); 730 731 MODULE_LICENSE("GPL v2"); 732 MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>"); 733