2011-02-25 02:00:55

by Stepan Moskovchenko

[permalink] [raw]
Subject: [PATCH 1/4] msm: iommu: Clock control for the IOMMU driver

Add clock control to the IOMMU driver. The IOMMU bus clock
(and potentially an AXI clock) need to be on to gain access
to IOMMU registers. Actively control these clocks when
needed instead of leaving them on.

Signed-off-by: Stepan Moskovchenko <[email protected]>
---
arch/arm/mach-msm/include/mach/iommu.h | 9 ++++-
arch/arm/mach-msm/iommu.c | 58 ++++++++++++++++++++++++++++++--
2 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 296c0f1..8738a44 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#define MSM_IOMMU_H

#include <linux/interrupt.h>
+#include <linux/clk.h>

/* Sharability attributes of MSM IOMMU mappings */
#define MSM_IOMMU_ATTR_NON_SH 0x0
@@ -74,13 +75,17 @@ struct msm_iommu_ctx_dev {
* struct msm_iommu_drvdata - A single IOMMU hardware instance
* @base: IOMMU config port base address (VA)
* @irq: Interrupt number
- *
+ * @clk: The bus clock for this IOMMU hardware instance
+ * @pclk: The clock for the IOMMU bus interconnect
+ *
* A msm_iommu_drvdata holds the global driver data about a single piece
* of an IOMMU hardware instance.
*/
struct msm_iommu_drvdata {
void __iomem *base;
int irq;
+ struct clk *clk;
+ struct clk *pclk;
};

/**
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index e2d58e4..cde3cd0 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,7 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/iommu.h>
+#include <linux/clk.h>

#include <asm/cacheflush.h>
#include <asm/sizes.h>
@@ -50,6 +51,30 @@ struct msm_priv {
struct list_head list_attached;
};

+static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+ int ret;
+
+ ret = clk_enable(drvdata->pclk);
+ if (ret)
+ goto fail;
+
+ if (drvdata->clk) {
+ ret = clk_enable(drvdata->clk);
+ if (ret)
+ clk_disable(drvdata->pclk);
+ }
+fail:
+ return ret;
+}
+
+static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+ if (drvdata->clk)
+ clk_disable(drvdata->clk);
+ clk_disable(drvdata->pclk);
+}
+
static int __flush_iotlb(struct iommu_domain *domain)
{
struct msm_priv *priv = domain->priv;
@@ -77,9 +102,16 @@ static int __flush_iotlb(struct iommu_domain *domain)
BUG();

iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+ BUG_ON(!iommu_drvdata);
+
+ ret = __enable_clocks(iommu_drvdata);
+ if (ret)
+ goto fail;
+
SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
+ __disable_clocks(iommu_drvdata);
}
-
+fail:
return ret;
}

@@ -265,9 +297,14 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
goto fail;
}

+ ret = __enable_clocks(iommu_drvdata);
+ if (ret)
+ goto fail;
+
__program_context(iommu_drvdata->base, ctx_dev->num,
__pa(priv->pgtable));

+ __disable_clocks(iommu_drvdata);
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
ret = __flush_iotlb(domain);

@@ -303,7 +340,12 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
if (ret)
goto fail;

+ ret = __enable_clocks(iommu_drvdata);
+ if (ret)
+ goto fail;
+
__reset_context(iommu_drvdata->base, ctx_dev->num);
+ __disable_clocks(iommu_drvdata);
list_del_init(&ctx_drvdata->attached_elm);

fail:
@@ -532,6 +574,10 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
base = iommu_drvdata->base;
ctx = ctx_drvdata->num;

+ ret = __enable_clocks(iommu_drvdata);
+ if (ret)
+ goto fail;
+
/* Invalidate context TLB */
SET_CTX_TLBIALL(base, ctx, 0);
SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT);
@@ -547,6 +593,7 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
if (GET_FAULT(base, ctx))
ret = 0;

+ __disable_clocks(iommu_drvdata);
fail:
spin_unlock_irqrestore(&msm_iommu_lock, flags);
return ret;
@@ -590,7 +637,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
struct msm_iommu_drvdata *drvdata = dev_id;
void __iomem *base;
unsigned int fsr;
- int ncb, i;
+ int ncb, i, ret;

spin_lock(&msm_iommu_lock);

@@ -604,6 +651,10 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
pr_err("Unexpected IOMMU page fault!\n");
pr_err("base = %08x\n", (unsigned int) base);

+ ret = __enable_clocks(drvdata);
+ if (ret)
+ goto fail;
+
ncb = GET_NCB(base)+1;
for (i = 0; i < ncb; i++) {
fsr = GET_FSR(base, i);
@@ -614,6 +665,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
SET_FSR(base, i, 0x4000000F);
}
}
+ __disable_clocks(drvdata);
fail:
spin_unlock(&msm_iommu_lock);
return 0;
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


2011-02-25 02:00:53

by Stepan Moskovchenko

[permalink] [raw]
Subject: [PATCH 3/4] msm: iommu: Use ASID tagging instead of VMID tagging

Use ASID tags in the TLB instead of VMID tags in
preparation for changes to the secure environment.

Signed-off-by: Stepan Moskovchenko <[email protected]>
---
arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h | 4 +++-
arch/arm/mach-msm/iommu.c | 9 ++++-----
arch/arm/mach-msm/iommu_dev.c | 11 +++++++----
3 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
index c2c3da9..bbd397c 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -68,6 +68,7 @@ do { \
#define FL_CACHEABLE (1 << 3)
#define FL_TEX0 (1 << 12)
#define FL_OFFSET(va) (((va) & 0xFFF00000) >> 20)
+#define FL_NG (1 << 17)

/* Second-level page table bits */
#define SL_BASE_MASK_LARGE 0xFFFF0000
@@ -81,6 +82,7 @@ do { \
#define SL_CACHEABLE (1 << 3)
#define SL_TEX0 (1 << 6)
#define SL_OFFSET(va) (((va) & 0xFF000) >> 12)
+#define SL_NG (1 << 11)

/* Memory type and cache policy attributes */
#define MT_SO 0
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index cde3cd0..9c08740 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -137,7 +137,6 @@ static void __reset_context(void __iomem *base, int ctx)
SET_TLBLKCR(base, ctx, 0);
SET_PRRR(base, ctx, 0);
SET_NMRR(base, ctx, 0);
- SET_CONTEXTIDR(base, ctx, 0);
}

static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
@@ -418,11 +417,11 @@ 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 | pgprot;
+ FL_SHARED | FL_NG | pgprot;
}

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

/* Need a 2nd level table */
@@ -447,7 +446,7 @@ 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_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
SL_SHARED | SL_TYPE_SMALL | pgprot;

if (len == SZ_64K) {
@@ -455,7 +454,7 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,

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

ret = __flush_iotlb(domain);
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index 69acd1e..c1722eb 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -330,14 +330,17 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
SET_M2VCBR_N(drvdata->base, mid, 0);
SET_CBACR_N(drvdata->base, c->num, 0);

- /* Set VMID = MID */
- SET_VMID(drvdata->base, mid, mid);
+ /* Set VMID = 0 */
+ SET_VMID(drvdata->base, mid, 0);

/* Set the context number for that MID to this context */
SET_CBNDX(drvdata->base, mid, c->num);

- /* Set MID associated with this context bank */
- SET_CBVMID(drvdata->base, c->num, mid);
+ /* Set MID associated with this context bank to 0*/
+ SET_CBVMID(drvdata->base, c->num, 0);
+
+ /* Set the ASID for TLB tagging for this context */
+ SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);

/* Set security bit override to be Non-secure */
SET_NSCFG(drvdata->base, mid, 3);
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

2011-02-25 02:00:54

by Stepan Moskovchenko

[permalink] [raw]
Subject: [PATCH 4/4] msm: iommu: Remove dependency on IDR

Remove the depencency on the IOMMU IDR register, as it may
not be accessible depending on the security configuraton.
This involves moving the NCB field of IDR into the platform
data.

Signed-off-by: Stepan Moskovchenko <[email protected]>
---
arch/arm/mach-msm/devices-iommu.c | 26 +++++++++++++++++++-------
arch/arm/mach-msm/include/mach/iommu.h | 4 ++++
arch/arm/mach-msm/iommu.c | 5 ++---
arch/arm/mach-msm/iommu_dev.c | 29 +++++++++++++++++------------
4 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index af97afe..24030d0 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -280,50 +280,62 @@ static struct platform_device msm_root_iommu_dev = {

static struct msm_iommu_dev jpegd_iommu = {
.name = "jpegd",
+ .ncb = 2,
};

static struct msm_iommu_dev vpe_iommu = {
- .name = "vpe"
+ .name = "vpe",
+ .ncb = 2,
};

static struct msm_iommu_dev mdp0_iommu = {
- .name = "mdp0"
+ .name = "mdp0",
+ .ncb = 2,
};

static struct msm_iommu_dev mdp1_iommu = {
- .name = "mdp1"
+ .name = "mdp1",
+ .ncb = 2,
};

static struct msm_iommu_dev rot_iommu = {
- .name = "rot"
+ .name = "rot",
+ .ncb = 2,
};

static struct msm_iommu_dev ijpeg_iommu = {
- .name = "ijpeg"
+ .name = "ijpeg",
+ .ncb = 2,
};

static struct msm_iommu_dev vfe_iommu = {
.name = "vfe",
+ .ncb = 2,
};

static struct msm_iommu_dev vcodec_a_iommu = {
- .name = "vcodec_a"
+ .name = "vcodec_a",
+ .ncb = 2,
};

static struct msm_iommu_dev vcodec_b_iommu = {
- .name = "vcodec_b"
+ .name = "vcodec_b",
+ .ncb = 2,
};

static struct msm_iommu_dev gfx3d_iommu = {
.name = "gfx3d",
+ .ncb = 3,
};

static struct msm_iommu_dev gfx2d0_iommu = {
.name = "gfx2d0",
+ .ncb = 2,
};

static struct msm_iommu_dev gfx2d1_iommu = {
.name = "gfx2d1",
+ .ncb = 2,
};

static struct platform_device msm_device_iommu_jpegd = {
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 4dfe7ef..5c7c955 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -45,9 +45,11 @@
/**
* struct msm_iommu_dev - a single IOMMU hardware instance
* name Human-readable name given to this IOMMU HW instance
+ * ncb Number of context banks present on this IOMMU HW instance
*/
struct msm_iommu_dev {
const char *name;
+ int ncb;
};

/**
@@ -69,6 +71,7 @@ struct msm_iommu_ctx_dev {
/**
* struct msm_iommu_drvdata - A single IOMMU hardware instance
* @base: IOMMU config port base address (VA)
+ * @ncb The number of contexts on this IOMMU
* @irq: Interrupt number
* @clk: The bus clock for this IOMMU hardware instance
* @pclk: The clock for the IOMMU bus interconnect
@@ -79,6 +82,7 @@ struct msm_iommu_ctx_dev {
struct msm_iommu_drvdata {
void __iomem *base;
int irq;
+ int ncb;
struct clk *clk;
struct clk *pclk;
};
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index 9c08740..0146f519 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -636,7 +636,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
struct msm_iommu_drvdata *drvdata = dev_id;
void __iomem *base;
unsigned int fsr;
- int ncb, i, ret;
+ int i, ret;

spin_lock(&msm_iommu_lock);

@@ -654,8 +654,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
if (ret)
goto fail;

- ncb = GET_NCB(base)+1;
- for (i = 0; i < ncb; i++) {
+ for (i = 0; i < drvdata->ncb; i++) {
fsr = GET_FSR(base, i);
if (fsr) {
pr_err("Fault occurred in context %d.\n", i);
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index c1722eb..826a21d 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -85,9 +85,9 @@ fail:
}
EXPORT_SYMBOL(msm_iommu_get_ctx);

-static void msm_iommu_reset(void __iomem *base)
+static void msm_iommu_reset(void __iomem *base, int ncb)
{
- int ctx, ncb;
+ int ctx;

SET_RPUE(base, 0);
SET_RPUEIE(base, 0);
@@ -100,7 +100,6 @@ static void msm_iommu_reset(void __iomem *base)
SET_GLOBAL_TLBIALL(base, 0);
SET_RPU_ACR(base, 0);
SET_TLBLKCRWE(base, 1);
- ncb = GET_NCB(base)+1;

for (ctx = 0; ctx < ncb; ctx++) {
SET_BPRCOSH(base, ctx, 0);
@@ -136,7 +135,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
void __iomem *regs_base;
resource_size_t len;
- int ret, ncb, nm2v, irq;
+ int ret, irq, par;

if (pdev->id == -1) {
msm_iommu_root_dev = pdev;
@@ -211,10 +210,18 @@ static int msm_iommu_probe(struct platform_device *pdev)
goto fail_io;
}

- mb();
+ msm_iommu_reset(regs_base, iommu_dev->ncb);

- if (GET_IDR(regs_base) == 0) {
- pr_err("Invalid IDR value detected\n");
+ SET_M(regs_base, 0, 1);
+ SET_PAR(regs_base, 0, 0);
+ SET_V2PCFG(regs_base, 0, 1);
+ SET_V2PPR(regs_base, 0, 0);
+ par = GET_PAR(regs_base, 0);
+ SET_V2PCFG(regs_base, 0, 0);
+ SET_M(regs_base, 0, 0);
+
+ if (!par) {
+ pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
ret = -ENODEV;
goto fail_io;
}
@@ -226,17 +233,15 @@ static int msm_iommu_probe(struct platform_device *pdev)
goto fail_io;
}

- msm_iommu_reset(regs_base);
+
drvdata->pclk = iommu_pclk;
drvdata->clk = iommu_clk;
drvdata->base = regs_base;
drvdata->irq = irq;
-
- nm2v = GET_NM2VCBMT((unsigned long) regs_base);
- ncb = GET_NCB((unsigned long) regs_base);
+ drvdata->ncb = iommu_dev->ncb;

pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
- iommu_dev->name, regs_base, irq, ncb+1);
+ iommu_dev->name, regs_base, irq, iommu_dev->ncb);

platform_set_drvdata(pdev, drvdata);

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

2011-02-25 02:01:33

by Stepan Moskovchenko

[permalink] [raw]
Subject: [PATCH 2/4] msm: iommu: Rework clock logic and add IOMMU bus clock control

Clean up the clock control code in the probe calls, and add
support for controlling the clock for the IOMMU bus
interconnect. With the (proper) clock driver in place, the
clock control logic in the probe function can be made much
cleaner since it does not have to deal with the placeholder
driver anymore.

Signed-off-by: Stepan Moskovchenko <[email protected]>
---
arch/arm/mach-msm/devices-iommu.c | 5 -
arch/arm/mach-msm/include/mach/iommu.h | 5 -
arch/arm/mach-msm/iommu_dev.c | 206 +++++++++++++++++++-------------
3 files changed, 121 insertions(+), 95 deletions(-)

diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index c0206b7..af97afe 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -280,7 +280,6 @@ static struct platform_device msm_root_iommu_dev = {

static struct msm_iommu_dev jpegd_iommu = {
.name = "jpegd",
- .clk_rate = -1
};

static struct msm_iommu_dev vpe_iommu = {
@@ -305,7 +304,6 @@ static struct msm_iommu_dev ijpeg_iommu = {

static struct msm_iommu_dev vfe_iommu = {
.name = "vfe",
- .clk_rate = -1
};

static struct msm_iommu_dev vcodec_a_iommu = {
@@ -318,17 +316,14 @@ static struct msm_iommu_dev vcodec_b_iommu = {

static struct msm_iommu_dev gfx3d_iommu = {
.name = "gfx3d",
- .clk_rate = 27000000
};

static struct msm_iommu_dev gfx2d0_iommu = {
.name = "gfx2d0",
- .clk_rate = 27000000
};

static struct msm_iommu_dev gfx2d1_iommu = {
.name = "gfx2d1",
- .clk_rate = 27000000
};

static struct platform_device msm_device_iommu_jpegd = {
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 8738a44..4dfe7ef 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -45,14 +45,9 @@
/**
* struct msm_iommu_dev - a single IOMMU hardware instance
* name Human-readable name given to this IOMMU HW instance
- * clk_rate Rate to set for this IOMMU's clock, if applicable to this
- * particular IOMMU. 0 means don't set a rate.
- * -1 means it is an AXI clock with no valid rate
- *
*/
struct msm_iommu_dev {
const char *name;
- int clk_rate;
};

/**
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index b83c73b..69acd1e 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -29,6 +29,7 @@

#include <mach/iommu_hw-8xxx.h>
#include <mach/iommu.h>
+#include <mach/clk.h>

struct iommu_ctx_iter_data {
/* input */
@@ -130,117 +131,134 @@ static int msm_iommu_probe(struct platform_device *pdev)
{
struct resource *r, *r2;
struct clk *iommu_clk;
+ struct clk *iommu_pclk;
struct msm_iommu_drvdata *drvdata;
struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
void __iomem *regs_base;
resource_size_t len;
- int ret = 0, ncb, nm2v, irq;
+ int ret, ncb, nm2v, irq;

- if (pdev->id != -1) {
- drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+ if (pdev->id == -1) {
+ msm_iommu_root_dev = pdev;
+ return 0;
+ }

- if (!drvdata) {
- ret = -ENOMEM;
- goto fail;
- }
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);

- if (!iommu_dev) {
- ret = -ENODEV;
- goto fail;
- }
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (!iommu_dev) {
+ ret = -ENODEV;
+ goto fail;
+ }

- if (iommu_dev->clk_rate != 0) {
- iommu_clk = clk_get(&pdev->dev, "iommu_clk");
-
- if (IS_ERR(iommu_clk)) {
- ret = -ENODEV;
- goto fail;
- }
-
- if (iommu_dev->clk_rate > 0) {
- ret = clk_set_rate(iommu_clk,
- iommu_dev->clk_rate);
- if (ret) {
- clk_put(iommu_clk);
- goto fail;
- }
- }
-
- ret = clk_enable(iommu_clk);
- if (ret) {
- clk_put(iommu_clk);
- goto fail;
- }
+ iommu_pclk = clk_get(NULL, "smmu_pclk");
+ if (IS_ERR(iommu_pclk)) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ ret = clk_enable(iommu_pclk);
+ if (ret)
+ goto fail_enable;
+
+ iommu_clk = clk_get(&pdev->dev, "iommu_clk");
+
+ if (!IS_ERR(iommu_clk)) {
+ if (clk_get_rate(iommu_clk) == 0)
+ clk_set_min_rate(iommu_clk, 1);
+
+ ret = clk_enable(iommu_clk);
+ if (ret) {
clk_put(iommu_clk);
+ goto fail_pclk;
}
+ } else
+ iommu_clk = NULL;

- r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "physbase");
- if (!r) {
- ret = -ENODEV;
- goto fail;
- }
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");

- len = r->end - r->start + 1;
+ if (!r) {
+ ret = -ENODEV;
+ goto fail_clk;
+ }

- r2 = request_mem_region(r->start, len, r->name);
- if (!r2) {
- pr_err("Could not request memory region: "
- "start=%p, len=%d\n", (void *) r->start, len);
- ret = -EBUSY;
- goto fail;
- }
+ len = r->end - r->start + 1;

- regs_base = ioremap(r2->start, len);
+ r2 = request_mem_region(r->start, len, r->name);
+ if (!r2) {
+ pr_err("Could not request memory region: start=%p, len=%d\n",
+ (void *) r->start, len);
+ ret = -EBUSY;
+ goto fail_clk;
+ }

- if (!regs_base) {
- pr_err("Could not ioremap: start=%p, len=%d\n",
- (void *) r2->start, len);
- ret = -EBUSY;
- goto fail_mem;
- }
+ regs_base = ioremap(r2->start, len);

- irq = platform_get_irq_byname(pdev, "secure_irq");
- if (irq < 0) {
- ret = -ENODEV;
- goto fail_io;
- }
+ if (!regs_base) {
+ pr_err("Could not ioremap: start=%p, len=%d\n",
+ (void *) r2->start, len);
+ ret = -EBUSY;
+ goto fail_mem;
+ }
+
+ irq = platform_get_irq_byname(pdev, "secure_irq");
+ if (irq < 0) {
+ ret = -ENODEV;
+ goto fail_io;
+ }

- mb();
+ mb();

- if (GET_IDR(regs_base) == 0) {
- pr_err("Invalid IDR value detected\n");
- ret = -ENODEV;
- goto fail_io;
- }
+ if (GET_IDR(regs_base) == 0) {
+ pr_err("Invalid IDR value detected\n");
+ ret = -ENODEV;
+ goto fail_io;
+ }

- ret = request_irq(irq, msm_iommu_fault_handler, 0,
- "msm_iommu_secure_irpt_handler", drvdata);
- if (ret) {
- pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
- goto fail_io;
- }
+ ret = request_irq(irq, msm_iommu_fault_handler, 0,
+ "msm_iommu_secure_irpt_handler", drvdata);
+ if (ret) {
+ pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
+ goto fail_io;
+ }

- msm_iommu_reset(regs_base);
- drvdata->base = regs_base;
- drvdata->irq = irq;
+ msm_iommu_reset(regs_base);
+ drvdata->pclk = iommu_pclk;
+ drvdata->clk = iommu_clk;
+ drvdata->base = regs_base;
+ drvdata->irq = irq;

- nm2v = GET_NM2VCBMT((unsigned long) regs_base);
- ncb = GET_NCB((unsigned long) regs_base);
+ nm2v = GET_NM2VCBMT((unsigned long) regs_base);
+ ncb = GET_NCB((unsigned long) regs_base);

- pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
+ pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
iommu_dev->name, regs_base, irq, ncb+1);

- platform_set_drvdata(pdev, drvdata);
- } else
- msm_iommu_root_dev = pdev;
+ platform_set_drvdata(pdev, drvdata);

- return 0;
+ if (iommu_clk)
+ clk_disable(iommu_clk);
+
+ clk_disable(iommu_pclk);

+ return 0;
fail_io:
iounmap(regs_base);
fail_mem:
release_mem_region(r->start, len);
+fail_clk:
+ if (iommu_clk) {
+ clk_disable(iommu_clk);
+ clk_put(iommu_clk);
+ }
+fail_pclk:
+ clk_disable(iommu_pclk);
+fail_enable:
+ clk_put(iommu_pclk);
fail:
kfree(drvdata);
return ret;
@@ -252,7 +270,10 @@ static int msm_iommu_remove(struct platform_device *pdev)

drv = platform_get_drvdata(pdev);
if (drv) {
- memset(drv, 0, sizeof(struct msm_iommu_drvdata));
+ if (drv->clk)
+ clk_put(drv->clk);
+ clk_put(drv->pclk);
+ memset(drv, 0, sizeof(*drv));
kfree(drv);
platform_set_drvdata(pdev, NULL);
}
@@ -264,7 +285,7 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
struct msm_iommu_drvdata *drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
- int i, ret = 0;
+ int i, ret;
if (!c || !pdev->dev.parent) {
ret = -EINVAL;
goto fail;
@@ -288,6 +309,18 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
platform_set_drvdata(pdev, ctx_drvdata);

+ ret = clk_enable(drvdata->pclk);
+ if (ret)
+ goto fail;
+
+ if (drvdata->clk) {
+ ret = clk_enable(drvdata->clk);
+ if (ret) {
+ clk_disable(drvdata->pclk);
+ goto fail;
+ }
+ }
+
/* Program the M2V tables for this context */
for (i = 0; i < MAX_NUM_MIDS; i++) {
int mid = c->mids[i];
@@ -310,8 +343,11 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
SET_NSCFG(drvdata->base, mid, 3);
}

- pr_info("context device %s with bank index %d\n", c->name, c->num);
+ if (drvdata->clk)
+ clk_disable(drvdata->clk);
+ clk_disable(drvdata->pclk);

+ dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
return 0;
fail:
kfree(ctx_drvdata);
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

2011-02-25 07:29:15

by Trilok Soni

[permalink] [raw]
Subject: Re: [PATCH 2/4] msm: iommu: Rework clock logic and add IOMMU bus clock control

Hi Steve,

>
> /**
> diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
> index b83c73b..69acd1e 100644
> --- a/arch/arm/mach-msm/iommu_dev.c
> +++ b/arch/arm/mach-msm/iommu_dev.c
> @@ -1,4 +1,4 @@
> -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
> +/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
> *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License version 2 and
> @@ -29,6 +29,7 @@
>
> #include <mach/iommu_hw-8xxx.h>
> #include <mach/iommu.h>
> +#include <mach/clk.h>
>
> struct iommu_ctx_iter_data {
> /* input */
> @@ -130,117 +131,134 @@ static int msm_iommu_probe(struct platform_device *pdev)
> {
> struct resource *r, *r2;
> struct clk *iommu_clk;
> + struct clk *iommu_pclk;
> struct msm_iommu_drvdata *drvdata;
> struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;

const please.

> + iommu_pclk = clk_get(NULL, "smmu_pclk");
> + if (IS_ERR(iommu_pclk)) {
> + ret = -ENODEV;
> + goto fail;
> + }

I am not a big fan of this when you have the "device" around. You should just do

iommu_pclk = clk_get(&pdev->dev, NULL);

...error logic...

iommu_clk = clk_get(&pdev->dev, "iommu_clk");

...error logic...


> +
> + ret = clk_enable(iommu_pclk);
> + if (ret)
> + goto fail_enable;
> +
> + iommu_clk = clk_get(&pdev->dev, "iommu_clk");
> +
> + if (!IS_ERR(iommu_clk)) {
> + if (clk_get_rate(iommu_clk) == 0)
> + clk_set_min_rate(iommu_clk, 1);
> +
> + ret = clk_enable(iommu_clk);
> + if (ret) {
> clk_put(iommu_clk);
> + goto fail_pclk;
> }
> + } else
> + iommu_clk = NULL;
>
> - r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> - "physbase");
> - if (!r) {
> - ret = -ENODEV;
> - goto fail;
> - }
> + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
>
> - len = r->end - r->start + 1;
> + if (!r) {
> + ret = -ENODEV;
> + goto fail_clk;
> + }
>
> - r2 = request_mem_region(r->start, len, r->name);
> - if (!r2) {
> - pr_err("Could not request memory region: "
> - "start=%p, len=%d\n", (void *) r->start, len);
> - ret = -EBUSY;
> - goto fail;
> - }
> + len = r->end - r->start + 1;


resource_size please.


---Trilok Soni


--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

2011-02-25 22:10:00

by Stepan Moskovchenko

[permalink] [raw]
Subject: Re: [PATCH 2/4] msm: iommu: Rework clock logic and add IOMMU bus clock control

On 2/24/2011 11:29 PM, Trilok Soni wrote:
> Hi Steve,

Hello

>> @@ -130,117 +131,134 @@ static int msm_iommu_probe(struct platform_device *pdev)
>> {
>> struct resource *r, *r2;
>> struct clk *iommu_clk;
>> + struct clk *iommu_pclk;
>> struct msm_iommu_drvdata *drvdata;
>> struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
> const please.
>

I am not clear on what you mean. Please be more specific here.

>> + iommu_pclk = clk_get(NULL, "smmu_pclk");
>> + if (IS_ERR(iommu_pclk)) {
>> + ret = -ENODEV;
>> + goto fail;
>> + }
> I am not a big fan of this when you have the "device" around. You should just do
>
> iommu_pclk = clk_get(&pdev->dev, NULL);
>
> ...error logic...
>
> iommu_clk = clk_get(&pdev->dev, "iommu_clk");
>
> ...error logic...
>

The pclk is a "special" bus clock and does not have a specific device
instance associated with it, so passing a device would not be
appropriate in this case. I pass the device for other clocks that are
indeed associated with devices, but this is not one of them. I suppose
we could create 11 or 12 aliases for the pclk and associate it with all
the IOMMU devices, but I would prefer to avoid doing that as I believe
the current approach is cleaner.

>> - ret = -EBUSY;
>> - goto fail;
>> - }
>> + len = r->end - r->start + 1;
>
> resource_size please.
>

Ok

2011-02-28 12:13:46

by Trilok Soni

[permalink] [raw]
Subject: Re: [PATCH 2/4] msm: iommu: Rework clock logic and add IOMMU bus clock control

Hi Steve,

On 2/26/2011 3:39 AM, Stepan Moskovchenko wrote:
> On 2/24/2011 11:29 PM, Trilok Soni wrote:
>> Hi Steve,
>
> Hello
>
>>> @@ -130,117 +131,134 @@ static int msm_iommu_probe(struct platform_device *pdev)
>>> {
>>> struct resource *r, *r2;
>>> struct clk *iommu_clk;
>>> + struct clk *iommu_pclk;
>>> struct msm_iommu_drvdata *drvdata;
>>> struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
>> const please.
>>
>
> I am not clear on what you mean. Please be more specific here.

I mean

const struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;

Now I see that this change is not part of this patch so you can ignore my comment.

>
>>> + iommu_pclk = clk_get(NULL, "smmu_pclk");
>>> + if (IS_ERR(iommu_pclk)) {
>>> + ret = -ENODEV;
>>> + goto fail;
>>> + }
>> I am not a big fan of this when you have the "device" around. You should just do
>>
>> iommu_pclk = clk_get(&pdev->dev, NULL);
>>
>> ...error logic...
>>
>> iommu_clk = clk_get(&pdev->dev, "iommu_clk");
>>
>> ...error logic...
>>
>
> The pclk is a "special" bus clock and does not have a specific device instance associated with it, so passing a device would not be appropriate in this case. I pass the device for other clocks that are indeed associated with devices, but this is not one of them. I suppose we could create 11 or 12 aliases for the pclk and associate it with all the IOMMU devices, but I would prefer to avoid doing that as I believe the current approach is cleaner.

ok.

>
>>> - ret = -EBUSY;
>>> - goto fail;
>>> - }
>>> + len = r->end - r->start + 1;
>>
>> resource_size please.
>>
>
> Ok

Thanks.

---Trilok Soni

--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

2011-03-01 00:03:13

by Stepan Moskovchenko

[permalink] [raw]
Subject: [PATCH v2 2/4] msm: iommu: Rework clock logic and add IOMMU bus clock control

Clean up the clock control code in the probe calls, and add
support for controlling the clock for the IOMMU bus
interconnect. With the (proper) clock driver in place, the
clock control logic in the probe function can be made much
cleaner since it does not have to deal with the placeholder
driver anymore.

Signed-off-by: Stepan Moskovchenko <[email protected]>
---
v2: Use resource_size.

arch/arm/mach-msm/devices-iommu.c | 5 -
arch/arm/mach-msm/include/mach/iommu.h | 5 -
arch/arm/mach-msm/iommu_dev.c | 206 +++++++++++++++++++-------------
3 files changed, 121 insertions(+), 95 deletions(-)

diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index c0206b7..af97afe 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -280,7 +280,6 @@ static struct platform_device msm_root_iommu_dev = {

static struct msm_iommu_dev jpegd_iommu = {
.name = "jpegd",
- .clk_rate = -1
};

static struct msm_iommu_dev vpe_iommu = {
@@ -305,7 +304,6 @@ static struct msm_iommu_dev ijpeg_iommu = {

static struct msm_iommu_dev vfe_iommu = {
.name = "vfe",
- .clk_rate = -1
};

static struct msm_iommu_dev vcodec_a_iommu = {
@@ -318,17 +316,14 @@ static struct msm_iommu_dev vcodec_b_iommu = {

static struct msm_iommu_dev gfx3d_iommu = {
.name = "gfx3d",
- .clk_rate = 27000000
};

static struct msm_iommu_dev gfx2d0_iommu = {
.name = "gfx2d0",
- .clk_rate = 27000000
};

static struct msm_iommu_dev gfx2d1_iommu = {
.name = "gfx2d1",
- .clk_rate = 27000000
};

static struct platform_device msm_device_iommu_jpegd = {
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 8738a44..4dfe7ef 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -45,14 +45,9 @@
/**
* struct msm_iommu_dev - a single IOMMU hardware instance
* name Human-readable name given to this IOMMU HW instance
- * clk_rate Rate to set for this IOMMU's clock, if applicable to this
- * particular IOMMU. 0 means don't set a rate.
- * -1 means it is an AXI clock with no valid rate
- *
*/
struct msm_iommu_dev {
const char *name;
- int clk_rate;
};

/**
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index b83c73b..79ade0b 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -29,6 +29,7 @@

#include <mach/iommu_hw-8xxx.h>
#include <mach/iommu.h>
+#include <mach/clk.h>

struct iommu_ctx_iter_data {
/* input */
@@ -130,117 +131,134 @@ static int msm_iommu_probe(struct platform_device *pdev)
{
struct resource *r, *r2;
struct clk *iommu_clk;
+ struct clk *iommu_pclk;
struct msm_iommu_drvdata *drvdata;
struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
void __iomem *regs_base;
resource_size_t len;
- int ret = 0, ncb, nm2v, irq;
+ int ret, ncb, nm2v, irq;

- if (pdev->id != -1) {
- drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+ if (pdev->id == -1) {
+ msm_iommu_root_dev = pdev;
+ return 0;
+ }

- if (!drvdata) {
- ret = -ENOMEM;
- goto fail;
- }
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);

- if (!iommu_dev) {
- ret = -ENODEV;
- goto fail;
- }
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (!iommu_dev) {
+ ret = -ENODEV;
+ goto fail;
+ }

- if (iommu_dev->clk_rate != 0) {
- iommu_clk = clk_get(&pdev->dev, "iommu_clk");
-
- if (IS_ERR(iommu_clk)) {
- ret = -ENODEV;
- goto fail;
- }
-
- if (iommu_dev->clk_rate > 0) {
- ret = clk_set_rate(iommu_clk,
- iommu_dev->clk_rate);
- if (ret) {
- clk_put(iommu_clk);
- goto fail;
- }
- }
-
- ret = clk_enable(iommu_clk);
- if (ret) {
- clk_put(iommu_clk);
- goto fail;
- }
+ iommu_pclk = clk_get(NULL, "smmu_pclk");
+ if (IS_ERR(iommu_pclk)) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ ret = clk_enable(iommu_pclk);
+ if (ret)
+ goto fail_enable;
+
+ iommu_clk = clk_get(&pdev->dev, "iommu_clk");
+
+ if (!IS_ERR(iommu_clk)) {
+ if (clk_get_rate(iommu_clk) == 0)
+ clk_set_min_rate(iommu_clk, 1);
+
+ ret = clk_enable(iommu_clk);
+ if (ret) {
clk_put(iommu_clk);
+ goto fail_pclk;
}
+ } else
+ iommu_clk = NULL;

- r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "physbase");
- if (!r) {
- ret = -ENODEV;
- goto fail;
- }
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");

- len = r->end - r->start + 1;
+ if (!r) {
+ ret = -ENODEV;
+ goto fail_clk;
+ }

- r2 = request_mem_region(r->start, len, r->name);
- if (!r2) {
- pr_err("Could not request memory region: "
- "start=%p, len=%d\n", (void *) r->start, len);
- ret = -EBUSY;
- goto fail;
- }
+ len = resource_size(r);

- regs_base = ioremap(r2->start, len);
+ r2 = request_mem_region(r->start, len, r->name);
+ if (!r2) {
+ pr_err("Could not request memory region: start=%p, len=%d\n",
+ (void *) r->start, len);
+ ret = -EBUSY;
+ goto fail_clk;
+ }

- if (!regs_base) {
- pr_err("Could not ioremap: start=%p, len=%d\n",
- (void *) r2->start, len);
- ret = -EBUSY;
- goto fail_mem;
- }
+ regs_base = ioremap(r2->start, len);

- irq = platform_get_irq_byname(pdev, "secure_irq");
- if (irq < 0) {
- ret = -ENODEV;
- goto fail_io;
- }
+ if (!regs_base) {
+ pr_err("Could not ioremap: start=%p, len=%d\n",
+ (void *) r2->start, len);
+ ret = -EBUSY;
+ goto fail_mem;
+ }
+
+ irq = platform_get_irq_byname(pdev, "secure_irq");
+ if (irq < 0) {
+ ret = -ENODEV;
+ goto fail_io;
+ }

- mb();
+ mb();

- if (GET_IDR(regs_base) == 0) {
- pr_err("Invalid IDR value detected\n");
- ret = -ENODEV;
- goto fail_io;
- }
+ if (GET_IDR(regs_base) == 0) {
+ pr_err("Invalid IDR value detected\n");
+ ret = -ENODEV;
+ goto fail_io;
+ }

- ret = request_irq(irq, msm_iommu_fault_handler, 0,
- "msm_iommu_secure_irpt_handler", drvdata);
- if (ret) {
- pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
- goto fail_io;
- }
+ ret = request_irq(irq, msm_iommu_fault_handler, 0,
+ "msm_iommu_secure_irpt_handler", drvdata);
+ if (ret) {
+ pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
+ goto fail_io;
+ }

- msm_iommu_reset(regs_base);
- drvdata->base = regs_base;
- drvdata->irq = irq;
+ msm_iommu_reset(regs_base);
+ drvdata->pclk = iommu_pclk;
+ drvdata->clk = iommu_clk;
+ drvdata->base = regs_base;
+ drvdata->irq = irq;

- nm2v = GET_NM2VCBMT((unsigned long) regs_base);
- ncb = GET_NCB((unsigned long) regs_base);
+ nm2v = GET_NM2VCBMT((unsigned long) regs_base);
+ ncb = GET_NCB((unsigned long) regs_base);

- pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
+ pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
iommu_dev->name, regs_base, irq, ncb+1);

- platform_set_drvdata(pdev, drvdata);
- } else
- msm_iommu_root_dev = pdev;
+ platform_set_drvdata(pdev, drvdata);

- return 0;
+ if (iommu_clk)
+ clk_disable(iommu_clk);
+
+ clk_disable(iommu_pclk);

+ return 0;
fail_io:
iounmap(regs_base);
fail_mem:
release_mem_region(r->start, len);
+fail_clk:
+ if (iommu_clk) {
+ clk_disable(iommu_clk);
+ clk_put(iommu_clk);
+ }
+fail_pclk:
+ clk_disable(iommu_pclk);
+fail_enable:
+ clk_put(iommu_pclk);
fail:
kfree(drvdata);
return ret;
@@ -252,7 +270,10 @@ static int msm_iommu_remove(struct platform_device *pdev)

drv = platform_get_drvdata(pdev);
if (drv) {
- memset(drv, 0, sizeof(struct msm_iommu_drvdata));
+ if (drv->clk)
+ clk_put(drv->clk);
+ clk_put(drv->pclk);
+ memset(drv, 0, sizeof(*drv));
kfree(drv);
platform_set_drvdata(pdev, NULL);
}
@@ -264,7 +285,7 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
struct msm_iommu_drvdata *drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
- int i, ret = 0;
+ int i, ret;
if (!c || !pdev->dev.parent) {
ret = -EINVAL;
goto fail;
@@ -288,6 +309,18 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
platform_set_drvdata(pdev, ctx_drvdata);

+ ret = clk_enable(drvdata->pclk);
+ if (ret)
+ goto fail;
+
+ if (drvdata->clk) {
+ ret = clk_enable(drvdata->clk);
+ if (ret) {
+ clk_disable(drvdata->pclk);
+ goto fail;
+ }
+ }
+
/* Program the M2V tables for this context */
for (i = 0; i < MAX_NUM_MIDS; i++) {
int mid = c->mids[i];
@@ -310,8 +343,11 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
SET_NSCFG(drvdata->base, mid, 3);
}

- pr_info("context device %s with bank index %d\n", c->name, c->num);
+ if (drvdata->clk)
+ clk_disable(drvdata->clk);
+ clk_disable(drvdata->pclk);

+ dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
return 0;
fail:
kfree(ctx_drvdata);
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

2011-03-01 07:15:36

by Trilok Soni

[permalink] [raw]
Subject: Re: [PATCH v2 2/4] msm: iommu: Rework clock logic and add IOMMU bus clock control

Hi Steve,

On 3/1/2011 5:33 AM, Stepan Moskovchenko wrote:
> Clean up the clock control code in the probe calls, and add
> support for controlling the clock for the IOMMU bus
> interconnect. With the (proper) clock driver in place, the
> clock control logic in the probe function can be made much
> cleaner since it does not have to deal with the placeholder
> driver anymore.
>
> Signed-off-by: Stepan Moskovchenko <[email protected]>
> ---
> v2: Use resource_size.

Looks good to me.

Reviewed-by: Trilok Soni <[email protected]>

---Trilok Soni
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

2011-03-08 23:43:19

by David Brown

[permalink] [raw]
Subject: Re: [PATCH 1/4] msm: iommu: Clock control for the IOMMU driver

Stepan Moskovchenko (6):
msm: iommu: Clock control for the IOMMU driver
msm: iommu: Rework clock logic and add IOMMU bus clock control
msm: iommu: Use ASID tagging instead of VMID tagging
msm: iommu: Remove dependency on IDR
msm: iommu: Don't read from write-only registers
msm: iommu: Enable HTW L2 redirection on MSM8960

arch/arm/mach-msm/Kconfig | 2 +-
arch/arm/mach-msm/devices-iommu.c | 31 ++--
arch/arm/mach-msm/include/mach/iommu.h | 18 ++-
arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h | 32 +---
arch/arm/mach-msm/iommu.c | 72 +++++++--
arch/arm/mach-msm/iommu_dev.c | 230 ++++++++++++++----------
6 files changed, 232 insertions(+), 153 deletions(-)

I have pulled these changes into my MSM tree, which can be
found at

git://codeaurora.org/quic/kernel/davidb/linux-msm.git

in the for-next branch

This patch will show up in the next release of the linux-next tree
(usually sometime within the next 24 hours during the week.)

The path will hopefully also be merged in Linus' tree for the next
-rc kernel release.

Thanks,
David

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.