Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 225689
b: refs/heads/master
c: 100832c
h: refs/heads/master
i:
  225687: a552156
v: v3
  • Loading branch information
Stepan Moskovchenko authored and Daniel Walker committed Dec 1, 2010
1 parent 3a4bee7 commit 0584ca2
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 08bd6839783319085ee0db4c888534e626225774
refs/heads/master: 100832c9b6adb3d63407416931caeba3f3b9a777
93 changes: 82 additions & 11 deletions trunk/arch/arm/mach-msm/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@
#include <mach/iommu_hw-8xxx.h>
#include <mach/iommu.h>

#define MRC(reg, processor, op1, crn, crm, op2) \
__asm__ __volatile__ ( \
" mrc " #processor "," #op1 ", %0," #crn "," #crm "," #op2 "\n" \
: "=r" (reg))

#define RCP15_PRRR(reg) MRC(reg, p15, 0, c10, c2, 0)
#define RCP15_NMRR(reg) MRC(reg, p15, 0, c10, c2, 1)

static int msm_iommu_tex_class[4];

DEFINE_SPINLOCK(msm_iommu_lock);

struct msm_priv {
Expand Down Expand Up @@ -98,6 +108,7 @@ static void __reset_context(void __iomem *base, int ctx)

static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
{
unsigned int prrr, nmrr;
__reset_context(base, ctx);

/* Set up HTW mode */
Expand Down Expand Up @@ -130,11 +141,11 @@ static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
/* Turn on TEX Remap */
SET_TRE(base, ctx, 1);

/* Do not configure PRRR / NMRR on the IOMMU for now. We will assume
* TEX class 0 for everything until attributes are properly worked out
*/
SET_PRRR(base, ctx, 0);
SET_NMRR(base, ctx, 0);
/* Set TEX remap attributes */
RCP15_PRRR(prrr);
RCP15_NMRR(nmrr);
SET_PRRR(base, ctx, prrr);
SET_NMRR(base, ctx, nmrr);

/* Turn on BFB prefetch */
SET_BFBDFE(base, ctx, 1);
Expand Down Expand Up @@ -304,12 +315,21 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
unsigned long *sl_table;
unsigned long *sl_pte;
unsigned long sl_offset;
unsigned int pgprot;
size_t len = 0x1000UL << order;
int ret = 0;
int ret = 0, tex, sh;

spin_lock_irqsave(&msm_iommu_lock, flags);
priv = domain->priv;

sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];

if (tex < 0 || tex > NUM_TEX_CLASS - 1) {
ret = -EINVAL;
goto fail;
}

priv = domain->priv;
if (!priv) {
ret = -EINVAL;
goto fail;
Expand All @@ -330,6 +350,18 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
goto fail;
}

if (len == SZ_16M || len == SZ_1M) {
pgprot = sh ? FL_SHARED : 0;
pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
pgprot |= tex & 0x04 ? FL_TEX0 : 0;
} else {
pgprot = sh ? SL_SHARED : 0;
pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
pgprot |= tex & 0x04 ? SL_TEX0 : 0;
}

fl_offset = FL_OFFSET(va); /* Upper 12 bits */
fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */

Expand All @@ -338,12 +370,12 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
for (i = 0; i < 16; i++)
*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
FL_SHARED;
FL_SHARED | pgprot;
}

if (len == SZ_1M)
*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE |
FL_TYPE_SECT | FL_SHARED;
FL_TYPE_SECT | FL_SHARED | pgprot;

/* Need a 2nd level table */
if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
Expand All @@ -368,14 +400,14 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,

if (len == SZ_4K)
*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 |
SL_SHARED | SL_TYPE_SMALL;
SL_SHARED | SL_TYPE_SMALL | pgprot;

if (len == SZ_64K) {
int i;

for (i = 0; i < 16; i++)
*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
SL_AP1 | SL_SHARED | SL_TYPE_LARGE;
SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
}

__flush_iotlb(domain);
Expand Down Expand Up @@ -593,8 +625,47 @@ static struct iommu_ops msm_iommu_ops = {
.domain_has_cap = msm_iommu_domain_has_cap
};

static int __init get_tex_class(int icp, int ocp, int mt, int nos)
{
int i = 0;
unsigned int prrr = 0;
unsigned int nmrr = 0;
int c_icp, c_ocp, c_mt, c_nos;

RCP15_PRRR(prrr);
RCP15_NMRR(nmrr);

for (i = 0; i < NUM_TEX_CLASS; i++) {
c_nos = PRRR_NOS(prrr, i);
c_mt = PRRR_MT(prrr, i);
c_icp = NMRR_ICP(nmrr, i);
c_ocp = NMRR_OCP(nmrr, i);

if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos)
return i;
}

return -ENODEV;
}

static void __init setup_iommu_tex_classes(void)
{
msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] =
get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1);

msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] =
get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1);

msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] =
get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1);

msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] =
get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1);
}

static int __init msm_iommu_init(void)
{
setup_iommu_tex_classes();
register_iommu(&msm_iommu_ops);
return 0;
}
Expand Down

0 comments on commit 0584ca2

Please sign in to comment.