* [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM
@ 2012-10-12 1:06 Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 1/6] ARM: OMAP3/4: iommu: migrate to hwmod framework Omar Ramirez Luna
` (10 more replies)
0 siblings, 11 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
These patches are needed for remoteproc to work on OMAP4.
Introduced iommu hwmod support for OMAP3 (iva, isp) and
OMAP4 (ipu, dsp), along with the corresponding runtime PM
and routines to deassert reset lines, enable/disable clocks
and configure sysc registers.
Although IOMMU hwmod patches were already submitted in the past,
this series adds few more changes, like:
- New reset handling.
- Save and restore context code rework.
- Device tree bindings for OMAP3 and OMAP4.
For this series I just dropped the patches already included in
mainline.
Previous work can be found at:
[v2]
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg75701.html
[v1]
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg70447.html
[old iteration without reset, save/restore and device tree]
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg60133.html
Omar Ramirez Luna (6):
ARM: OMAP3/4: iommu: migrate to hwmod framework
ARM: OMAP3/4: iommu: adapt to runtime pm
ARM: OMAP: iommu: pm runtime save and restore context
ARM: OMAP: iommu: optimize save and restore routines
ARM: OMAP: iommu: add device tree support
arm/dts: OMAP3/4: Add iommu nodes
.../devicetree/bindings/arm/omap/iommu.txt | 10 ++
arch/arm/boot/dts/omap3.dtsi | 12 +-
arch/arm/boot/dts/omap4.dtsi | 17 +-
arch/arm/mach-omap2/devices.c | 2 +-
arch/arm/mach-omap2/iommu2.c | 74 ++------
arch/arm/mach-omap2/omap-iommu.c | 176 +++++---------------
arch/arm/plat-omap/include/plat/iommu.h | 20 ++-
arch/arm/plat-omap/include/plat/iommu2.h | 4 -
drivers/iommu/omap-iommu.c | 163 ++++++++++++++----
9 files changed, 245 insertions(+), 233 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/omap/iommu.txt
--
1.7.9.5
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 1/6] ARM: OMAP3/4: iommu: migrate to hwmod framework
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
` (9 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
Use hwmod data and device attributes to build and register an
omap device for iommu driver.
- Update the naming convention in isp module.
- Remove unneeded check for number of resources, as this is now
handled by omap_device and prevents driver from loading.
- Now unused, remove platform device and resource data, handling
of sysconfig register for softreset purposes, use default
latency structure.
- Use hwmod API for reset handling.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/devices.c | 2 +-
arch/arm/mach-omap2/iommu2.c | 19 ----
arch/arm/mach-omap2/omap-iommu.c | 165 +++++++------------------------
arch/arm/plat-omap/include/plat/iommu.h | 8 +-
drivers/iommu/omap-iommu.c | 23 ++++-
5 files changed, 64 insertions(+), 153 deletions(-)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c8c2117..e084b94 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -213,7 +213,7 @@ static struct platform_device omap3isp_device = {
};
static struct omap_iommu_arch_data omap3_isp_iommu = {
- .name = "isp",
+ .name = "mmu_isp",
};
int omap3_init_camera(struct isp_platform_data *pdata)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index eefc379..35cab47 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -32,12 +32,8 @@
#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_SOFTRESET (1 << 1)
#define MMU_SYS_AUTOIDLE 1
-/* SYSSTATUS */
-#define MMU_SYS_RESETDONE 1
-
/* IRQSTATUS & IRQENABLE */
#define MMU_IRQ_MULTIHITFAULT (1 << 4)
#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -88,7 +84,6 @@ static void __iommu_set_twl(struct omap_iommu *obj, bool on)
static int omap2_iommu_enable(struct omap_iommu *obj)
{
u32 l, pa;
- unsigned long timeout;
if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
return -EINVAL;
@@ -97,20 +92,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
if (!IS_ALIGNED(pa, SZ_16K))
return -EINVAL;
- iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
-
- timeout = jiffies + msecs_to_jiffies(20);
- do {
- l = iommu_read_reg(obj, MMU_SYSSTATUS);
- if (l & MMU_SYS_RESETDONE)
- break;
- } while (!time_after(jiffies, timeout));
-
- if (!(l & MMU_SYS_RESETDONE)) {
- dev_err(obj->dev, "can't take mmu out of reset\n");
- return -ENODEV;
- }
-
l = iommu_read_reg(obj, MMU_REVISION);
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index df298d4..e400845 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -12,153 +12,64 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
#include <plat/iommu.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
#include "soc.h"
#include "common.h"
-struct iommu_device {
- resource_size_t base;
- int irq;
- struct iommu_platform_data pdata;
- struct resource res[2];
-};
-static struct iommu_device *devices;
-static int num_iommu_devices;
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct iommu_device omap3_devices[] = {
- {
- .base = 0x480bd400,
- .irq = 24 + OMAP_INTC_START,
- .pdata = {
- .name = "isp",
- .nr_tlb_entries = 8,
- .clk_name = "cam_ick",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
-#if defined(CONFIG_OMAP_IOMMU_IVA2)
- {
- .base = 0x5d000000,
- .irq = 28 + OMAP_INTC_START,
- .pdata = {
- .name = "iva2",
- .nr_tlb_entries = 32,
- .clk_name = "iva2_ck",
- .da_start = 0x11000000,
- .da_end = 0xFFFFF000,
- },
- },
-#endif
-};
-#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices)
-static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES];
-#else
-#define omap3_devices NULL
-#define NR_OMAP3_IOMMU_DEVICES 0
-#define omap3_iommu_pdev NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct iommu_device omap4_devices[] = {
- {
- .base = OMAP4_MMU1_BASE,
- .irq = 100 + OMAP44XX_IRQ_GIC_START,
- .pdata = {
- .name = "ducati",
- .nr_tlb_entries = 32,
- .clk_name = "ipu_fck",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
- {
- .base = OMAP4_MMU2_BASE,
- .irq = 28 + OMAP44XX_IRQ_GIC_START,
- .pdata = {
- .name = "tesla",
- .nr_tlb_entries = 32,
- .clk_name = "dsp_fck",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
-};
-#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
-static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES];
-#else
-#define omap4_devices NULL
-#define NR_OMAP4_IOMMU_DEVICES 0
-#define omap4_iommu_pdev NULL
-#endif
-
-static struct platform_device **omap_iommu_pdev;
-
-static int __init omap_iommu_init(void)
+static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
{
- int i, err;
- struct resource res[] = {
- { .flags = IORESOURCE_MEM },
- { .flags = IORESOURCE_IRQ },
- };
+ struct platform_device *pdev;
+ struct iommu_platform_data *pdata;
+ struct omap_mmu_dev_attr *a = (struct omap_mmu_dev_attr *)oh->dev_attr;
+ static int i;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->name = oh->name;
+ pdata->clk_name = oh->main_clk;
+ pdata->nr_tlb_entries = a->nr_tlb_entries;
+ pdata->da_start = a->da_start;
+ pdata->da_end = a->da_end;
+
+ if (oh->rst_lines_cnt == 1) {
+ pdata->reset_name = oh->rst_lines->name;
+ pdata->assert_reset = omap_device_assert_hardreset;
+ pdata->deassert_reset = omap_device_deassert_hardreset;
+ }
- if (cpu_is_omap34xx()) {
- devices = omap3_devices;
- omap_iommu_pdev = omap3_iommu_pdev;
- num_iommu_devices = NR_OMAP3_IOMMU_DEVICES;
- } else if (cpu_is_omap44xx()) {
- devices = omap4_devices;
- omap_iommu_pdev = omap4_iommu_pdev;
- num_iommu_devices = NR_OMAP4_IOMMU_DEVICES;
- } else
- return -ENODEV;
+ pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata),
+ NULL, 0, 0);
- for (i = 0; i < num_iommu_devices; i++) {
- struct platform_device *pdev;
- const struct iommu_device *d = &devices[i];
+ kfree(pdata);
- pdev = platform_device_alloc("omap-iommu", i);
- if (!pdev) {
- err = -ENOMEM;
- goto err_out;
- }
+ if (IS_ERR(pdev)) {
+ pr_err("%s: device build err: %ld\n", __func__, PTR_ERR(pdev));
+ return PTR_ERR(pdev);
+ }
- res[0].start = d->base;
- res[0].end = d->base + MMU_REG_SIZE - 1;
- res[1].start = res[1].end = d->irq;
+ i++;
- err = platform_device_add_resources(pdev, res,
- ARRAY_SIZE(res));
- if (err)
- goto err_out;
- err = platform_device_add_data(pdev, &d->pdata,
- sizeof(d->pdata));
- if (err)
- goto err_out;
- err = platform_device_add(pdev);
- if (err)
- goto err_out;
- omap_iommu_pdev[i] = pdev;
- }
return 0;
+}
-err_out:
- while (i--)
- platform_device_put(omap_iommu_pdev[i]);
- return err;
+static int __init omap_iommu_init(void)
+{
+ return omap_hwmod_for_each_by_class("mmu", omap_iommu_dev_init, NULL);
}
/* must be ready before omap3isp is probed */
subsys_initcall(omap_iommu_init);
static void __exit omap_iommu_exit(void)
{
- int i;
-
- for (i = 0; i < num_iommu_devices; i++)
- platform_device_unregister(omap_iommu_pdev[i]);
+ /* Do nothing */
}
module_exit(omap_iommu_exit);
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 68b5f03..0fa913d 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -13,6 +13,8 @@
#ifndef __MACH_IOMMU_H
#define __MACH_IOMMU_H
+#include <linux/platform_device.h>
+
struct iotlb_entry {
u32 da;
u32 pa;
@@ -119,9 +121,13 @@ struct omap_mmu_dev_attr {
struct iommu_platform_data {
const char *name;
const char *clk_name;
- const int nr_tlb_entries;
+ const char *reset_name;
+ int nr_tlb_entries;
u32 da_start;
u32 da_end;
+
+ int (*assert_reset)(struct platform_device *pdev, const char *name);
+ int (*deassert_reset)(struct platform_device *pdev, const char *name);
};
/**
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index d0b1234..c1caee4 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -125,13 +125,23 @@ EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
static int iommu_enable(struct omap_iommu *obj)
{
int err;
+ struct platform_device *pdev = to_platform_device(obj->dev);
+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
- if (!obj)
+ if (!obj || !pdata)
return -EINVAL;
if (!arch_iommu)
return -ENODEV;
+ if (pdata->deassert_reset) {
+ err = pdata->deassert_reset(pdev, pdata->reset_name);
+ if (err) {
+ dev_err(obj->dev, "deassert_reset failed: %d\n", err);
+ return err;
+ }
+ }
+
clk_enable(obj->clk);
err = arch_iommu->enable(obj);
@@ -142,7 +152,10 @@ static int iommu_enable(struct omap_iommu *obj)
static void iommu_disable(struct omap_iommu *obj)
{
- if (!obj)
+ struct platform_device *pdev = to_platform_device(obj->dev);
+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!obj || !pdata)
return;
clk_enable(obj->clk);
@@ -150,6 +163,9 @@ static void iommu_disable(struct omap_iommu *obj)
arch_iommu->disable(obj);
clk_disable(obj->clk);
+
+ if (pdata->assert_reset)
+ pdata->assert_reset(pdev, pdata->reset_name);
}
/*
@@ -913,9 +929,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
- if (pdev->num_resources != 2)
- return -EINVAL;
-
obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
if (!obj)
return -ENOMEM;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 1/6] ARM: OMAP3/4: iommu: migrate to hwmod framework
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 1/6] ARM: OMAP3/4: iommu: migrate to hwmod framework Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm Omar Ramirez Luna
` (8 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
Use hwmod data and device attributes to build and register an
omap device for iommu driver.
- Update the naming convention in isp module.
- Remove unneeded check for number of resources, as this is now
handled by omap_device and prevents driver from loading.
- Now unused, remove platform device and resource data, handling
of sysconfig register for softreset purposes, use default
latency structure.
- Use hwmod API for reset handling.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/devices.c | 2 +-
arch/arm/mach-omap2/iommu2.c | 19 ----
arch/arm/mach-omap2/omap-iommu.c | 165 +++++++------------------------
arch/arm/plat-omap/include/plat/iommu.h | 8 +-
drivers/iommu/omap-iommu.c | 23 ++++-
5 files changed, 64 insertions(+), 153 deletions(-)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c8c2117..e084b94 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -213,7 +213,7 @@ static struct platform_device omap3isp_device = {
};
static struct omap_iommu_arch_data omap3_isp_iommu = {
- .name = "isp",
+ .name = "mmu_isp",
};
int omap3_init_camera(struct isp_platform_data *pdata)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index eefc379..35cab47 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -32,12 +32,8 @@
#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_SOFTRESET (1 << 1)
#define MMU_SYS_AUTOIDLE 1
-/* SYSSTATUS */
-#define MMU_SYS_RESETDONE 1
-
/* IRQSTATUS & IRQENABLE */
#define MMU_IRQ_MULTIHITFAULT (1 << 4)
#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -88,7 +84,6 @@ static void __iommu_set_twl(struct omap_iommu *obj, bool on)
static int omap2_iommu_enable(struct omap_iommu *obj)
{
u32 l, pa;
- unsigned long timeout;
if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
return -EINVAL;
@@ -97,20 +92,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
if (!IS_ALIGNED(pa, SZ_16K))
return -EINVAL;
- iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
-
- timeout = jiffies + msecs_to_jiffies(20);
- do {
- l = iommu_read_reg(obj, MMU_SYSSTATUS);
- if (l & MMU_SYS_RESETDONE)
- break;
- } while (!time_after(jiffies, timeout));
-
- if (!(l & MMU_SYS_RESETDONE)) {
- dev_err(obj->dev, "can't take mmu out of reset\n");
- return -ENODEV;
- }
-
l = iommu_read_reg(obj, MMU_REVISION);
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index df298d4..e400845 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -12,153 +12,64 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
#include <plat/iommu.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
#include "soc.h"
#include "common.h"
-struct iommu_device {
- resource_size_t base;
- int irq;
- struct iommu_platform_data pdata;
- struct resource res[2];
-};
-static struct iommu_device *devices;
-static int num_iommu_devices;
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct iommu_device omap3_devices[] = {
- {
- .base = 0x480bd400,
- .irq = 24 + OMAP_INTC_START,
- .pdata = {
- .name = "isp",
- .nr_tlb_entries = 8,
- .clk_name = "cam_ick",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
-#if defined(CONFIG_OMAP_IOMMU_IVA2)
- {
- .base = 0x5d000000,
- .irq = 28 + OMAP_INTC_START,
- .pdata = {
- .name = "iva2",
- .nr_tlb_entries = 32,
- .clk_name = "iva2_ck",
- .da_start = 0x11000000,
- .da_end = 0xFFFFF000,
- },
- },
-#endif
-};
-#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices)
-static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES];
-#else
-#define omap3_devices NULL
-#define NR_OMAP3_IOMMU_DEVICES 0
-#define omap3_iommu_pdev NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct iommu_device omap4_devices[] = {
- {
- .base = OMAP4_MMU1_BASE,
- .irq = 100 + OMAP44XX_IRQ_GIC_START,
- .pdata = {
- .name = "ducati",
- .nr_tlb_entries = 32,
- .clk_name = "ipu_fck",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
- {
- .base = OMAP4_MMU2_BASE,
- .irq = 28 + OMAP44XX_IRQ_GIC_START,
- .pdata = {
- .name = "tesla",
- .nr_tlb_entries = 32,
- .clk_name = "dsp_fck",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
- },
-};
-#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
-static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES];
-#else
-#define omap4_devices NULL
-#define NR_OMAP4_IOMMU_DEVICES 0
-#define omap4_iommu_pdev NULL
-#endif
-
-static struct platform_device **omap_iommu_pdev;
-
-static int __init omap_iommu_init(void)
+static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
{
- int i, err;
- struct resource res[] = {
- { .flags = IORESOURCE_MEM },
- { .flags = IORESOURCE_IRQ },
- };
+ struct platform_device *pdev;
+ struct iommu_platform_data *pdata;
+ struct omap_mmu_dev_attr *a = (struct omap_mmu_dev_attr *)oh->dev_attr;
+ static int i;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->name = oh->name;
+ pdata->clk_name = oh->main_clk;
+ pdata->nr_tlb_entries = a->nr_tlb_entries;
+ pdata->da_start = a->da_start;
+ pdata->da_end = a->da_end;
+
+ if (oh->rst_lines_cnt == 1) {
+ pdata->reset_name = oh->rst_lines->name;
+ pdata->assert_reset = omap_device_assert_hardreset;
+ pdata->deassert_reset = omap_device_deassert_hardreset;
+ }
- if (cpu_is_omap34xx()) {
- devices = omap3_devices;
- omap_iommu_pdev = omap3_iommu_pdev;
- num_iommu_devices = NR_OMAP3_IOMMU_DEVICES;
- } else if (cpu_is_omap44xx()) {
- devices = omap4_devices;
- omap_iommu_pdev = omap4_iommu_pdev;
- num_iommu_devices = NR_OMAP4_IOMMU_DEVICES;
- } else
- return -ENODEV;
+ pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata),
+ NULL, 0, 0);
- for (i = 0; i < num_iommu_devices; i++) {
- struct platform_device *pdev;
- const struct iommu_device *d = &devices[i];
+ kfree(pdata);
- pdev = platform_device_alloc("omap-iommu", i);
- if (!pdev) {
- err = -ENOMEM;
- goto err_out;
- }
+ if (IS_ERR(pdev)) {
+ pr_err("%s: device build err: %ld\n", __func__, PTR_ERR(pdev));
+ return PTR_ERR(pdev);
+ }
- res[0].start = d->base;
- res[0].end = d->base + MMU_REG_SIZE - 1;
- res[1].start = res[1].end = d->irq;
+ i++;
- err = platform_device_add_resources(pdev, res,
- ARRAY_SIZE(res));
- if (err)
- goto err_out;
- err = platform_device_add_data(pdev, &d->pdata,
- sizeof(d->pdata));
- if (err)
- goto err_out;
- err = platform_device_add(pdev);
- if (err)
- goto err_out;
- omap_iommu_pdev[i] = pdev;
- }
return 0;
+}
-err_out:
- while (i--)
- platform_device_put(omap_iommu_pdev[i]);
- return err;
+static int __init omap_iommu_init(void)
+{
+ return omap_hwmod_for_each_by_class("mmu", omap_iommu_dev_init, NULL);
}
/* must be ready before omap3isp is probed */
subsys_initcall(omap_iommu_init);
static void __exit omap_iommu_exit(void)
{
- int i;
-
- for (i = 0; i < num_iommu_devices; i++)
- platform_device_unregister(omap_iommu_pdev[i]);
+ /* Do nothing */
}
module_exit(omap_iommu_exit);
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 68b5f03..0fa913d 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -13,6 +13,8 @@
#ifndef __MACH_IOMMU_H
#define __MACH_IOMMU_H
+#include <linux/platform_device.h>
+
struct iotlb_entry {
u32 da;
u32 pa;
@@ -119,9 +121,13 @@ struct omap_mmu_dev_attr {
struct iommu_platform_data {
const char *name;
const char *clk_name;
- const int nr_tlb_entries;
+ const char *reset_name;
+ int nr_tlb_entries;
u32 da_start;
u32 da_end;
+
+ int (*assert_reset)(struct platform_device *pdev, const char *name);
+ int (*deassert_reset)(struct platform_device *pdev, const char *name);
};
/**
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index d0b1234..c1caee4 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -125,13 +125,23 @@ EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
static int iommu_enable(struct omap_iommu *obj)
{
int err;
+ struct platform_device *pdev = to_platform_device(obj->dev);
+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
- if (!obj)
+ if (!obj || !pdata)
return -EINVAL;
if (!arch_iommu)
return -ENODEV;
+ if (pdata->deassert_reset) {
+ err = pdata->deassert_reset(pdev, pdata->reset_name);
+ if (err) {
+ dev_err(obj->dev, "deassert_reset failed: %d\n", err);
+ return err;
+ }
+ }
+
clk_enable(obj->clk);
err = arch_iommu->enable(obj);
@@ -142,7 +152,10 @@ static int iommu_enable(struct omap_iommu *obj)
static void iommu_disable(struct omap_iommu *obj)
{
- if (!obj)
+ struct platform_device *pdev = to_platform_device(obj->dev);
+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!obj || !pdata)
return;
clk_enable(obj->clk);
@@ -150,6 +163,9 @@ static void iommu_disable(struct omap_iommu *obj)
arch_iommu->disable(obj);
clk_disable(obj->clk);
+
+ if (pdata->assert_reset)
+ pdata->assert_reset(pdev, pdata->reset_name);
}
/*
@@ -913,9 +929,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
- if (pdev->num_resources != 2)
- return -EINVAL;
-
obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
if (!obj)
return -ENOMEM;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 1/6] ARM: OMAP3/4: iommu: migrate to hwmod framework Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
` (7 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
Use runtime PM functionality interfaced with hwmod enable/idle
functions, to replace direct clock operations and sysconfig
handling.
Dues to reset sequence, pm_runtime_put_sync must be used, to avoid
possible operations with the module under reset.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/iommu2.c | 17 -----------
arch/arm/mach-omap2/omap-iommu.c | 1 -
arch/arm/plat-omap/include/plat/iommu.h | 2 --
arch/arm/plat-omap/include/plat/iommu2.h | 2 --
drivers/iommu/omap-iommu.c | 45 +++++++++++++-----------------
5 files changed, 19 insertions(+), 48 deletions(-)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 35cab47..3e47786 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -25,15 +25,6 @@
*/
#define IOMMU_ARCH_VERSION 0x00000011
-/* SYSCONF */
-#define MMU_SYS_IDLE_SHIFT 3
-#define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
-
-#define MMU_SYS_AUTOIDLE 1
-
/* IRQSTATUS & IRQENABLE */
#define MMU_IRQ_MULTIHITFAULT (1 << 4)
#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -96,11 +87,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
- l = iommu_read_reg(obj, MMU_SYSCONFIG);
- l &= ~MMU_SYS_IDLE_MASK;
- l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
- iommu_write_reg(obj, l, MMU_SYSCONFIG);
-
iommu_write_reg(obj, pa, MMU_TTB);
__iommu_set_twl(obj, true);
@@ -114,7 +100,6 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL);
- iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
@@ -243,8 +228,6 @@ omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
char *p = buf;
pr_reg(REVISION);
- pr_reg(SYSCONFIG);
- pr_reg(SYSSTATUS);
pr_reg(IRQSTATUS);
pr_reg(IRQENABLE);
pr_reg(WALKING_ST);
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index e400845..82a422a 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -34,7 +34,6 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
return -ENOMEM;
pdata->name = oh->name;
- pdata->clk_name = oh->main_clk;
pdata->nr_tlb_entries = a->nr_tlb_entries;
pdata->da_start = a->da_start;
pdata->da_end = a->da_end;
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 0fa913d..902d193 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -30,7 +30,6 @@ struct iotlb_entry {
struct omap_iommu {
const char *name;
struct module *owner;
- struct clk *clk;
void __iomem *regbase;
struct device *dev;
void *isr_priv;
@@ -120,7 +119,6 @@ struct omap_mmu_dev_attr {
struct iommu_platform_data {
const char *name;
- const char *clk_name;
const char *reset_name;
int nr_tlb_entries;
u32 da_start;
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index d4116b5..1579694 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -19,8 +19,6 @@
* MMU Register offsets
*/
#define MMU_REVISION 0x00
-#define MMU_SYSCONFIG 0x10
-#define MMU_SYSSTATUS 0x14
#define MMU_IRQSTATUS 0x18
#define MMU_IRQENABLE 0x1c
#define MMU_WALKING_ST 0x40
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index c1caee4..37644c4 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -16,11 +16,11 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/iommu.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
#include <asm/cacheflush.h>
@@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
}
}
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
err = arch_iommu->enable(obj);
- clk_disable(obj->clk);
return err;
}
@@ -158,11 +157,9 @@ static void iommu_disable(struct omap_iommu *obj)
if (!obj || !pdata)
return;
- clk_enable(obj->clk);
-
arch_iommu->disable(obj);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
if (pdata->assert_reset)
pdata->assert_reset(pdev, pdata->reset_name);
@@ -288,7 +285,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
if (!obj || !obj->nr_tlb_entries || !e)
return -EINVAL;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &l);
if (l.base == obj->nr_tlb_entries) {
@@ -318,7 +315,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
cr = iotlb_alloc_cr(obj, e);
if (IS_ERR(cr)) {
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return PTR_ERR(cr);
}
@@ -332,7 +329,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
l.vict = l.base;
iotlb_lock_set(obj, &l);
out:
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return err;
}
@@ -362,7 +359,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
int i;
struct cr_regs cr;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
u32 start;
@@ -381,7 +378,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
}
}
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
if (i == obj->nr_tlb_entries)
dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
@@ -395,7 +392,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
{
struct iotlb_lock l;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
l.base = 0;
l.vict = 0;
@@ -403,7 +400,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
iommu_write_reg(obj, 1, MMU_GFLUSH);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
}
#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
@@ -413,11 +410,11 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
if (!obj || !buf)
return -EINVAL;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
bytes = arch_iommu->dump_ctx(obj, buf, bytes);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return bytes;
}
@@ -431,7 +428,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
struct cr_regs tmp;
struct cr_regs *p = crs;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &saved);
for_each_iotlb_cr(obj, num, i, tmp) {
@@ -441,7 +438,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
}
iotlb_lock_set(obj, &saved);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return p - crs;
}
@@ -805,9 +802,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
if (!obj->refcount)
return IRQ_NONE;
- clk_enable(obj->clk);
errs = iommu_report_fault(obj, &da);
- clk_disable(obj->clk);
if (errs == 0)
return IRQ_HANDLED;
@@ -933,10 +928,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
if (!obj)
return -ENOMEM;
- obj->clk = clk_get(&pdev->dev, pdata->clk_name);
- if (IS_ERR(obj->clk))
- goto err_clk;
-
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
obj->dev = &pdev->dev;
@@ -979,6 +970,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
goto err_irq;
platform_set_drvdata(pdev, obj);
+ pm_runtime_irq_safe(obj->dev);
+ pm_runtime_enable(obj->dev);
+
dev_info(&pdev->dev, "%s registered\n", obj->name);
return 0;
@@ -987,8 +981,6 @@ err_irq:
err_ioremap:
release_mem_region(res->start, resource_size(res));
err_mem:
- clk_put(obj->clk);
-err_clk:
kfree(obj);
return err;
}
@@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
release_mem_region(res->start, resource_size(res));
iounmap(obj->regbase);
- clk_put(obj->clk);
+ pm_runtime_disable(obj->dev);
+
dev_info(&pdev->dev, "%s removed\n", obj->name);
kfree(obj);
return 0;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
` (2 preceding siblings ...)
2012-10-12 1:06 ` [PATCH v3 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-12 7:48 ` Felipe Contreras
2012-10-12 1:06 ` [PATCH v3 3/6] ARM: OMAP: iommu: pm runtime save and restore context Omar Ramirez Luna
` (6 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
Use runtime PM functionality interfaced with hwmod enable/idle
functions, to replace direct clock operations and sysconfig
handling.
Dues to reset sequence, pm_runtime_put_sync must be used, to avoid
possible operations with the module under reset.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/iommu2.c | 17 -----------
arch/arm/mach-omap2/omap-iommu.c | 1 -
arch/arm/plat-omap/include/plat/iommu.h | 2 --
arch/arm/plat-omap/include/plat/iommu2.h | 2 --
drivers/iommu/omap-iommu.c | 45 +++++++++++++-----------------
5 files changed, 19 insertions(+), 48 deletions(-)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 35cab47..3e47786 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -25,15 +25,6 @@
*/
#define IOMMU_ARCH_VERSION 0x00000011
-/* SYSCONF */
-#define MMU_SYS_IDLE_SHIFT 3
-#define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
-
-#define MMU_SYS_AUTOIDLE 1
-
/* IRQSTATUS & IRQENABLE */
#define MMU_IRQ_MULTIHITFAULT (1 << 4)
#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -96,11 +87,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
- l = iommu_read_reg(obj, MMU_SYSCONFIG);
- l &= ~MMU_SYS_IDLE_MASK;
- l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
- iommu_write_reg(obj, l, MMU_SYSCONFIG);
-
iommu_write_reg(obj, pa, MMU_TTB);
__iommu_set_twl(obj, true);
@@ -114,7 +100,6 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL);
- iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
@@ -243,8 +228,6 @@ omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
char *p = buf;
pr_reg(REVISION);
- pr_reg(SYSCONFIG);
- pr_reg(SYSSTATUS);
pr_reg(IRQSTATUS);
pr_reg(IRQENABLE);
pr_reg(WALKING_ST);
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index e400845..82a422a 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -34,7 +34,6 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
return -ENOMEM;
pdata->name = oh->name;
- pdata->clk_name = oh->main_clk;
pdata->nr_tlb_entries = a->nr_tlb_entries;
pdata->da_start = a->da_start;
pdata->da_end = a->da_end;
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 0fa913d..902d193 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -30,7 +30,6 @@ struct iotlb_entry {
struct omap_iommu {
const char *name;
struct module *owner;
- struct clk *clk;
void __iomem *regbase;
struct device *dev;
void *isr_priv;
@@ -120,7 +119,6 @@ struct omap_mmu_dev_attr {
struct iommu_platform_data {
const char *name;
- const char *clk_name;
const char *reset_name;
int nr_tlb_entries;
u32 da_start;
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index d4116b5..1579694 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -19,8 +19,6 @@
* MMU Register offsets
*/
#define MMU_REVISION 0x00
-#define MMU_SYSCONFIG 0x10
-#define MMU_SYSSTATUS 0x14
#define MMU_IRQSTATUS 0x18
#define MMU_IRQENABLE 0x1c
#define MMU_WALKING_ST 0x40
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index c1caee4..37644c4 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -16,11 +16,11 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/iommu.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
#include <asm/cacheflush.h>
@@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
}
}
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
err = arch_iommu->enable(obj);
- clk_disable(obj->clk);
return err;
}
@@ -158,11 +157,9 @@ static void iommu_disable(struct omap_iommu *obj)
if (!obj || !pdata)
return;
- clk_enable(obj->clk);
-
arch_iommu->disable(obj);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
if (pdata->assert_reset)
pdata->assert_reset(pdev, pdata->reset_name);
@@ -288,7 +285,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
if (!obj || !obj->nr_tlb_entries || !e)
return -EINVAL;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &l);
if (l.base == obj->nr_tlb_entries) {
@@ -318,7 +315,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
cr = iotlb_alloc_cr(obj, e);
if (IS_ERR(cr)) {
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return PTR_ERR(cr);
}
@@ -332,7 +329,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
l.vict = l.base;
iotlb_lock_set(obj, &l);
out:
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return err;
}
@@ -362,7 +359,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
int i;
struct cr_regs cr;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
u32 start;
@@ -381,7 +378,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
}
}
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
if (i == obj->nr_tlb_entries)
dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
@@ -395,7 +392,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
{
struct iotlb_lock l;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
l.base = 0;
l.vict = 0;
@@ -403,7 +400,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
iommu_write_reg(obj, 1, MMU_GFLUSH);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
}
#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
@@ -413,11 +410,11 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
if (!obj || !buf)
return -EINVAL;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
bytes = arch_iommu->dump_ctx(obj, buf, bytes);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return bytes;
}
@@ -431,7 +428,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
struct cr_regs tmp;
struct cr_regs *p = crs;
- clk_enable(obj->clk);
+ pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &saved);
for_each_iotlb_cr(obj, num, i, tmp) {
@@ -441,7 +438,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
}
iotlb_lock_set(obj, &saved);
- clk_disable(obj->clk);
+ pm_runtime_put_sync(obj->dev);
return p - crs;
}
@@ -805,9 +802,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
if (!obj->refcount)
return IRQ_NONE;
- clk_enable(obj->clk);
errs = iommu_report_fault(obj, &da);
- clk_disable(obj->clk);
if (errs == 0)
return IRQ_HANDLED;
@@ -933,10 +928,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
if (!obj)
return -ENOMEM;
- obj->clk = clk_get(&pdev->dev, pdata->clk_name);
- if (IS_ERR(obj->clk))
- goto err_clk;
-
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
obj->dev = &pdev->dev;
@@ -979,6 +970,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
goto err_irq;
platform_set_drvdata(pdev, obj);
+ pm_runtime_irq_safe(obj->dev);
+ pm_runtime_enable(obj->dev);
+
dev_info(&pdev->dev, "%s registered\n", obj->name);
return 0;
@@ -987,8 +981,6 @@ err_irq:
err_ioremap:
release_mem_region(res->start, resource_size(res));
err_mem:
- clk_put(obj->clk);
-err_clk:
kfree(obj);
return err;
}
@@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
release_mem_region(res->start, resource_size(res));
iounmap(obj->regbase);
- clk_put(obj->clk);
+ pm_runtime_disable(obj->dev);
+
dev_info(&pdev->dev, "%s removed\n", obj->name);
kfree(obj);
return 0;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 3/6] ARM: OMAP: iommu: pm runtime save and restore context
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
` (3 preceding siblings ...)
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
` (5 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
Save and restore context during pm runtime transitions.
For now, the previous API for this purpose will trigger
pm runtime functions, and will be left as exported symbol
for compatibility with it's only user.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
drivers/iommu/omap-iommu.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 37644c4..875e894 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -97,7 +97,7 @@ void omap_iommu_save_ctx(struct device *dev)
{
struct omap_iommu *obj = dev_to_omap_iommu(dev);
- arch_iommu->save_ctx(obj);
+ pm_runtime_put_sync(obj->dev);
}
EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
@@ -109,7 +109,7 @@ void omap_iommu_restore_ctx(struct device *dev)
{
struct omap_iommu *obj = dev_to_omap_iommu(dev);
- arch_iommu->restore_ctx(obj);
+ pm_runtime_get_sync(obj->dev);
}
EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
@@ -1008,11 +1008,36 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
return 0;
}
+static int omap_iommu_runtime_suspend(struct device *dev)
+{
+ struct omap_iommu *obj = to_iommu(dev);
+
+ arch_iommu->save_ctx(obj);
+
+ return 0;
+}
+
+static int omap_iommu_runtime_resume(struct device *dev)
+{
+ struct omap_iommu *obj = to_iommu(dev);
+
+ arch_iommu->restore_ctx(obj);
+
+ return 0;
+}
+
+static const struct dev_pm_ops iommu_pm_ops = {
+ SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend,
+ omap_iommu_runtime_resume,
+ NULL)
+};
+
static struct platform_driver omap_iommu_driver = {
.probe = omap_iommu_probe,
.remove = __devexit_p(omap_iommu_remove),
.driver = {
.name = "omap-iommu",
+ .pm = &iommu_pm_ops,
},
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 3/6] ARM: OMAP: iommu: pm runtime save and restore context
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
` (4 preceding siblings ...)
2012-10-12 1:06 ` [PATCH v3 3/6] ARM: OMAP: iommu: pm runtime save and restore context Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 4/6] ARM: OMAP: iommu: optimize save and restore routines Omar Ramirez Luna
` (4 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
Save and restore context during pm runtime transitions.
For now, the previous API for this purpose will trigger
pm runtime functions, and will be left as exported symbol
for compatibility with it's only user.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
drivers/iommu/omap-iommu.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 37644c4..875e894 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -97,7 +97,7 @@ void omap_iommu_save_ctx(struct device *dev)
{
struct omap_iommu *obj = dev_to_omap_iommu(dev);
- arch_iommu->save_ctx(obj);
+ pm_runtime_put_sync(obj->dev);
}
EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
@@ -109,7 +109,7 @@ void omap_iommu_restore_ctx(struct device *dev)
{
struct omap_iommu *obj = dev_to_omap_iommu(dev);
- arch_iommu->restore_ctx(obj);
+ pm_runtime_get_sync(obj->dev);
}
EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
@@ -1008,11 +1008,36 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
return 0;
}
+static int omap_iommu_runtime_suspend(struct device *dev)
+{
+ struct omap_iommu *obj = to_iommu(dev);
+
+ arch_iommu->save_ctx(obj);
+
+ return 0;
+}
+
+static int omap_iommu_runtime_resume(struct device *dev)
+{
+ struct omap_iommu *obj = to_iommu(dev);
+
+ arch_iommu->restore_ctx(obj);
+
+ return 0;
+}
+
+static const struct dev_pm_ops iommu_pm_ops = {
+ SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend,
+ omap_iommu_runtime_resume,
+ NULL)
+};
+
static struct platform_driver omap_iommu_driver = {
.probe = omap_iommu_probe,
.remove = __devexit_p(omap_iommu_remove),
.driver = {
.name = "omap-iommu",
+ .pm = &iommu_pm_ops,
},
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 4/6] ARM: OMAP: iommu: optimize save and restore routines
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
` (5 preceding siblings ...)
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
` (3 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
These functions save and restore registers irrespectively of their
read or write permissions, this ends up in registers being saved
that can't be restored because of read only attributes. OTOH, so
far only 3 of them need to be saved.
In future GP_REG (which is present only on OMAP4 ipu) needs to be
saved but right now there is no API that can alter its value. Also,
protected TLB entries must be saved but this can be in a separate
patch as the original code didn't implement the loop to traverse
protected TLB entries.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/iommu2.c | 38 ++++++++++++++----------------
arch/arm/plat-omap/include/plat/iommu.h | 10 +++++++-
arch/arm/plat-omap/include/plat/iommu2.h | 2 --
drivers/iommu/omap-iommu.c | 3 +--
4 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 3e47786..cd77abb 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -19,6 +19,7 @@
#include <linux/stringify.h>
#include <plat/iommu.h>
+#include <plat/omap-pm.h>
/*
* omap2 architecture specific register bit definitions
@@ -55,20 +56,26 @@
static void __iommu_set_twl(struct omap_iommu *obj, bool on)
{
- u32 l = iommu_read_reg(obj, MMU_CNTL);
+ u32 l;
if (on)
- iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
+ l = MMU_IRQ_TWL_MASK;
else
- iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
+ l = MMU_IRQ_TLB_MISS_MASK;
+
+ iommu_write_reg(obj, l, MMU_IRQENABLE);
+ obj->context.irqen = l;
+ l = iommu_read_reg(obj, MMU_CNTL);
l &= ~MMU_CNTL_MASK;
+
if (on)
l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
else
l |= (MMU_CNTL_MMU_EN);
iommu_write_reg(obj, l, MMU_CNTL);
+ obj->context.cntl = l;
}
@@ -88,6 +95,7 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
(l >> 4) & 0xf, l & 0xf);
iommu_write_reg(obj, pa, MMU_TTB);
+ obj->context.ttb = pa;
__iommu_set_twl(obj, true);
@@ -100,6 +108,7 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL);
+ obj->context.cntl = l;
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
@@ -249,28 +258,17 @@ out:
static void omap2_iommu_save_ctx(struct omap_iommu *obj)
{
- int i;
- u32 *p = obj->ctx;
-
- for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
- p[i] = iommu_read_reg(obj, i * sizeof(u32));
- dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
- }
-
- BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+ obj->ctx_loss_cnt = omap_pm_get_dev_context_loss_count(obj->dev);
}
static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
{
- int i;
- u32 *p = obj->ctx;
-
- for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
- iommu_write_reg(obj, p[i], i * sizeof(u32));
- dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
- }
+ if (omap_pm_get_dev_context_loss_count(obj->dev) == obj->ctx_loss_cnt)
+ return;
- BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+ iommu_write_reg(obj, obj->context.ttb, MMU_TTB);
+ iommu_write_reg(obj, obj->context.irqen, MMU_IRQENABLE);
+ iommu_write_reg(obj, obj->context.cntl, MMU_CNTL);
}
static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 902d193..af14486 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -27,6 +27,13 @@ struct iotlb_entry {
};
};
+/* context registers */
+struct iommu_regs {
+ u32 irqen;
+ u32 cntl;
+ u32 ttb;
+};
+
struct omap_iommu {
const char *name;
struct module *owner;
@@ -50,7 +57,8 @@ struct omap_iommu {
struct list_head mmap;
struct mutex mmap_lock; /* protect mmap */
- void *ctx; /* iommu context: registres saved area */
+ struct iommu_regs context;
+ int ctx_loss_cnt;
u32 da_start;
u32 da_end;
};
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index 1579694..bc43d41 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -35,8 +35,6 @@
#define MMU_READ_RAM 0x6c
#define MMU_EMU_FAULT_AD 0x70
-#define MMU_REG_SIZE 256
-
/*
* MMU Register bit definitions
*/
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 875e894..e266ad7 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -924,14 +924,13 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
- obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
+ obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj)
return -ENOMEM;
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
obj->dev = &pdev->dev;
- obj->ctx = (void *)obj + sizeof(*obj);
obj->da_start = pdata->da_start;
obj->da_end = pdata->da_end;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 4/6] ARM: OMAP: iommu: optimize save and restore routines
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
` (6 preceding siblings ...)
2012-10-12 1:06 ` [PATCH v3 4/6] ARM: OMAP: iommu: optimize save and restore routines Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 5/6] ARM: OMAP: iommu: add device tree support Omar Ramirez Luna
` (2 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
These functions save and restore registers irrespectively of their
read or write permissions, this ends up in registers being saved
that can't be restored because of read only attributes. OTOH, so
far only 3 of them need to be saved.
In future GP_REG (which is present only on OMAP4 ipu) needs to be
saved but right now there is no API that can alter its value. Also,
protected TLB entries must be saved but this can be in a separate
patch as the original code didn't implement the loop to traverse
protected TLB entries.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/mach-omap2/iommu2.c | 38 ++++++++++++++----------------
arch/arm/plat-omap/include/plat/iommu.h | 10 +++++++-
arch/arm/plat-omap/include/plat/iommu2.h | 2 --
drivers/iommu/omap-iommu.c | 3 +--
4 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 3e47786..cd77abb 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -19,6 +19,7 @@
#include <linux/stringify.h>
#include <plat/iommu.h>
+#include <plat/omap-pm.h>
/*
* omap2 architecture specific register bit definitions
@@ -55,20 +56,26 @@
static void __iommu_set_twl(struct omap_iommu *obj, bool on)
{
- u32 l = iommu_read_reg(obj, MMU_CNTL);
+ u32 l;
if (on)
- iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
+ l = MMU_IRQ_TWL_MASK;
else
- iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
+ l = MMU_IRQ_TLB_MISS_MASK;
+
+ iommu_write_reg(obj, l, MMU_IRQENABLE);
+ obj->context.irqen = l;
+ l = iommu_read_reg(obj, MMU_CNTL);
l &= ~MMU_CNTL_MASK;
+
if (on)
l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
else
l |= (MMU_CNTL_MMU_EN);
iommu_write_reg(obj, l, MMU_CNTL);
+ obj->context.cntl = l;
}
@@ -88,6 +95,7 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
(l >> 4) & 0xf, l & 0xf);
iommu_write_reg(obj, pa, MMU_TTB);
+ obj->context.ttb = pa;
__iommu_set_twl(obj, true);
@@ -100,6 +108,7 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL);
+ obj->context.cntl = l;
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
@@ -249,28 +258,17 @@ out:
static void omap2_iommu_save_ctx(struct omap_iommu *obj)
{
- int i;
- u32 *p = obj->ctx;
-
- for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
- p[i] = iommu_read_reg(obj, i * sizeof(u32));
- dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
- }
-
- BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+ obj->ctx_loss_cnt = omap_pm_get_dev_context_loss_count(obj->dev);
}
static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
{
- int i;
- u32 *p = obj->ctx;
-
- for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
- iommu_write_reg(obj, p[i], i * sizeof(u32));
- dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
- }
+ if (omap_pm_get_dev_context_loss_count(obj->dev) == obj->ctx_loss_cnt)
+ return;
- BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+ iommu_write_reg(obj, obj->context.ttb, MMU_TTB);
+ iommu_write_reg(obj, obj->context.irqen, MMU_IRQENABLE);
+ iommu_write_reg(obj, obj->context.cntl, MMU_CNTL);
}
static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 902d193..af14486 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -27,6 +27,13 @@ struct iotlb_entry {
};
};
+/* context registers */
+struct iommu_regs {
+ u32 irqen;
+ u32 cntl;
+ u32 ttb;
+};
+
struct omap_iommu {
const char *name;
struct module *owner;
@@ -50,7 +57,8 @@ struct omap_iommu {
struct list_head mmap;
struct mutex mmap_lock; /* protect mmap */
- void *ctx; /* iommu context: registres saved area */
+ struct iommu_regs context;
+ int ctx_loss_cnt;
u32 da_start;
u32 da_end;
};
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index 1579694..bc43d41 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -35,8 +35,6 @@
#define MMU_READ_RAM 0x6c
#define MMU_EMU_FAULT_AD 0x70
-#define MMU_REG_SIZE 256
-
/*
* MMU Register bit definitions
*/
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 875e894..e266ad7 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -924,14 +924,13 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
- obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
+ obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj)
return -ENOMEM;
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
obj->dev = &pdev->dev;
- obj->ctx = (void *)obj + sizeof(*obj);
obj->da_start = pdata->da_start;
obj->da_end = pdata->da_end;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 5/6] ARM: OMAP: iommu: add device tree support
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
` (7 preceding siblings ...)
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 6/6] arm/dts: OMAP3/4: Add iommu nodes Omar Ramirez Luna
2012-10-16 17:22 ` [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Tony Lindgren
10 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
Adapt driver to use DT if provided.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
.../devicetree/bindings/arm/omap/iommu.txt | 10 +++
arch/arm/mach-omap2/omap-iommu.c | 4 ++
drivers/iommu/omap-iommu.c | 65 +++++++++++++++++++-
3 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/arm/omap/iommu.txt
diff --git a/Documentation/devicetree/bindings/arm/omap/iommu.txt b/Documentation/devicetree/bindings/arm/omap/iommu.txt
new file mode 100644
index 0000000..2bb780f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/iommu.txt
@@ -0,0 +1,10 @@
+* MMU (Memory Management Unit)
+
+MMU present in OMAP subsystems.
+
+Required properties:
+ compatible : should be "ti,omap3-iommu" for OMAP3 MMUs
+ compatible : should be "ti,omap4-iommu" for OMAP4 MMUs
+
+Optional properties:
+ None
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index 82a422a..4d6145d 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/slab.h>
@@ -29,6 +30,9 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
struct omap_mmu_dev_attr *a = (struct omap_mmu_dev_attr *)oh->dev_attr;
static int i;
+ if (of_have_populated_dt())
+ return 0;
+
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index e266ad7..946366f 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -21,12 +21,15 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
#include <asm/cacheflush.h>
#include <plat/iommu.h>
#include <plat/iopgtable.h>
+#include <plat/omap_device.h>
+#include <plat/omap_hwmod.h>
#define for_each_iotlb_cr(obj, n, __i, cr) \
for (__i = 0; \
@@ -916,13 +919,63 @@ static void omap_iommu_detach(struct omap_iommu *obj)
/*
* OMAP Device MMU(IOMMU) detection
*/
+static int __devinit
+iommu_add_platform_data_from_dt(struct platform_device *pdev)
+{
+ struct iommu_platform_data *pdata;
+ struct device_node *node = pdev->dev.of_node;
+ struct omap_hwmod *oh;
+ struct omap_mmu_dev_attr *a;
+ int ret = 0;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ of_property_read_string(node, "ti,hwmods", &pdata->name);
+ oh = omap_hwmod_lookup(pdata->name);
+ if (!oh) {
+ dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n", pdata->name);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ a = (struct omap_mmu_dev_attr *)oh->dev_attr;
+ pdata->nr_tlb_entries = a->nr_tlb_entries;
+ pdata->da_start = a->da_start;
+ pdata->da_end = a->da_end;
+
+ if (oh->rst_lines_cnt == 1) {
+ pdata->reset_name = oh->rst_lines->name;
+ pdata->assert_reset = omap_device_assert_hardreset;
+ pdata->deassert_reset = omap_device_deassert_hardreset;
+ }
+
+ ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+ if (ret)
+ dev_err(&pdev->dev, "Cannot add pdata for %s\n", pdata->name);
+
+out:
+ kfree(pdata);
+
+ return ret;
+}
+
static int __devinit omap_iommu_probe(struct platform_device *pdev)
{
int err = -ENODEV;
int irq;
struct omap_iommu *obj;
struct resource *res;
- struct iommu_platform_data *pdata = pdev->dev.platform_data;
+ struct iommu_platform_data *pdata;
+
+ if (of_have_populated_dt()) {
+ err = iommu_add_platform_data_from_dt(pdev);
+ if (err)
+ return err;
+ }
+
+ pdata = pdev->dev.platform_data;
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj)
@@ -1031,12 +1084,22 @@ static const struct dev_pm_ops iommu_pm_ops = {
NULL)
};
+#if defined(CONFIG_OF)
+static const struct of_device_id omap_iommu_of_match[] = {
+ { .compatible = "ti,omap3-iommu" },
+ { .compatible = "ti,omap4-iommu" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, omap_iommu_of_match);
+#endif
+
static struct platform_driver omap_iommu_driver = {
.probe = omap_iommu_probe,
.remove = __devexit_p(omap_iommu_remove),
.driver = {
.name = "omap-iommu",
.pm = &iommu_pm_ops,
+ .of_match_table = of_match_ptr(omap_iommu_of_match),
},
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 6/6] arm/dts: OMAP3/4: Add iommu nodes
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
` (8 preceding siblings ...)
2012-10-12 1:06 ` [PATCH v3 5/6] ARM: OMAP: iommu: add device tree support Omar Ramirez Luna
@ 2012-10-12 1:06 ` Omar Ramirez Luna
2012-10-16 17:22 ` [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Tony Lindgren
10 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 1:06 UTC (permalink / raw)
To: linux-arm-kernel
Add nodes for iommu DT, to interface with hwmods.
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
---
arch/arm/boot/dts/omap3.dtsi | 12 +++++++++++-
arch/arm/boot/dts/omap4.dtsi | 17 ++++++++++++++++-
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index f38ea87..c76872e 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -37,12 +37,17 @@
};
iva {
- compatible = "ti,iva2.2";
+ compatible = "ti,iva2.2", "simple-bus";
ti,hwmods = "iva";
dsp {
compatible = "ti,omap3-c64";
};
+
+ mmu_iva: mmu_iva at 5d000000 {
+ compatible = "ti,omap3-iommu";
+ ti,hwmods = "mmu_iva";
+ };
};
};
@@ -227,6 +232,11 @@
ti,hwmods = "mmc3";
};
+ mmu_isp: mmu_isp at 480bd400 {
+ compatible = "ti,omap3-iommu";
+ ti,hwmods = "mmu_isp";
+ };
+
wdt2: wdt at 48314000 {
compatible = "ti,omap3-wdt";
ti,hwmods = "wd_timer2";
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 3883f94..f084418 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -71,8 +71,23 @@
};
dsp {
- compatible = "ti,omap3-c64";
+ compatible = "ti,omap3-c64", "simple-bus";
ti,hwmods = "dsp";
+
+ mmu_dsp: mmu_dsp at 4a066000 {
+ compatible = "ti,omap4-iommu";
+ ti,hwmods = "mmu_dsp";
+ };
+ };
+
+ ipu {
+ compatible = "ti,omap4-ipu", "simple-bus";
+ ti,hwmods = "ipu";
+
+ mmu_ipu: mmu_ipu at 55082000 {
+ compatible = "ti,omap4-iommu";
+ ti,hwmods = "mmu_ipu";
+ };
};
iva {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
@ 2012-10-12 7:48 ` Felipe Contreras
2012-10-12 17:46 ` Omar Ramirez Luna
0 siblings, 1 reply; 22+ messages in thread
From: Felipe Contreras @ 2012-10-12 7:48 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Oct 12, 2012 at 3:06 AM, Omar Ramirez Luna <omar.luna@linaro.org> wrote:
> Use runtime PM functionality interfaced with hwmod enable/idle
> functions, to replace direct clock operations and sysconfig
> handling.
>
> Dues to reset sequence, pm_runtime_put_sync must be used, to avoid
> possible operations with the module under reset.
I already made most of these comments, but here they go again.
> @@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
> }
> }
>
> - clk_enable(obj->clk);
> + pm_runtime_get_sync(obj->dev);
>
> err = arch_iommu->enable(obj);
>
> - clk_disable(obj->clk);
The device will never go to sleep, until iommu_disable is called.
clk_enable -> pm_runtime_get_sync, clk_disable pm_runtime_put.
> @@ -288,7 +285,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
> if (!obj || !obj->nr_tlb_entries || !e)
> return -EINVAL;
>
> - clk_enable(obj->clk);
> + pm_runtime_get_sync(obj->dev);
>
> iotlb_lock_get(obj, &l);
> if (l.base == obj->nr_tlb_entries) {
> @@ -318,7 +315,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
>
> cr = iotlb_alloc_cr(obj, e);
> if (IS_ERR(cr)) {
> - clk_disable(obj->clk);
> + pm_runtime_put_sync(obj->dev);
> return PTR_ERR(cr);
> }
If I'm correct, the above pm_runtime_get/put are redundant, because
the count can't possibly reach 0 because of the reason I explained
before.
The same for all the cases below.
> @@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
> release_mem_region(res->start, resource_size(res));
> iounmap(obj->regbase);
>
> - clk_put(obj->clk);
> + pm_runtime_disable(obj->dev);
This will turn on the device unnecessarily, wasting power, and there's
no need for that, kfree will take care of that without resuming.
> dev_info(&pdev->dev, "%s removed\n", obj->name);
> kfree(obj);
> return 0;
Also, I still think that something like this is needed:
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -2222,8 +2222,17 @@ static struct clk cam_mclk = {
.recalc = &followparent_recalc,
};
+static struct clk cam_fck = {
+ .name = "cam_fck",
+ .ops = &clkops_omap2_iclk_dflt,
+ .parent = &l3_ick,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_CAM_SHIFT,
+ .clkdm_name = "cam_clkdm",
+ .recalc = &followparent_recalc,
+};
+
static struct clk cam_ick = {
- /* Handles both L3 and L4 clocks */
.name = "cam_ick",
.ops = &clkops_omap2_iclk_dflt,
.parent = &l4_ick,
@@ -3394,6 +3403,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK("omapdss_dss", "ick", &dss_ick_3430es2,
CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "dss_ick", &dss_ick_3430es2,
CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX),
+ CLK(NULL, "cam_fck", &cam_fck, CK_34XX | CK_36XX),
CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX),
CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX),
CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck,
CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
Cheers.
--
Felipe Contreras
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
2012-10-12 7:48 ` Felipe Contreras
@ 2012-10-12 17:46 ` Omar Ramirez Luna
2012-10-12 21:25 ` Felipe Contreras
0 siblings, 1 reply; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-12 17:46 UTC (permalink / raw)
To: linux-arm-kernel
On 12 October 2012 02:48, Felipe Contreras <felipe.contreras@gmail.com> wrote:
> I already made most of these comments, but here they go again.
I replied to all, but here it goes again:
>> @@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
>> }
>> }
>>
>> - clk_enable(obj->clk);
>> + pm_runtime_get_sync(obj->dev);
>>
>> err = arch_iommu->enable(obj);
>>
>> - clk_disable(obj->clk);
>
> The device will never go to sleep, until iommu_disable is called.
> clk_enable -> pm_runtime_get_sync, clk_disable pm_runtime_put.
Which is what you want... why would you want your iommu to be disabled
if the client of that iommu could request a translation?
Remember that these iommus, sit along of other processors not on the
main processor side. So, this code should enable it for the other
processor to use, and there is no point where the processor can say
"I'm not using it, shut it down" or "I'm using it, turn it on" in the
middle of execution, other than suspend/resume and if supported,
autosuspend.
>> @@ -288,7 +285,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
>> if (!obj || !obj->nr_tlb_entries || !e)
>> return -EINVAL;
>>
>> - clk_enable(obj->clk);
>> + pm_runtime_get_sync(obj->dev);
>>
>> iotlb_lock_get(obj, &l);
>> if (l.base == obj->nr_tlb_entries) {
>> @@ -318,7 +315,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
>>
>> cr = iotlb_alloc_cr(obj, e);
>> if (IS_ERR(cr)) {
>> - clk_disable(obj->clk);
>> + pm_runtime_put_sync(obj->dev);
>> return PTR_ERR(cr);
>> }
>
> If I'm correct, the above pm_runtime_get/put are redundant, because
> the count can't possibly reach 0 because of the reason I explained
> before.
>
> The same for all the cases below.
You can access this paths through debugfs, some of them doesn't work
if the module is not enabled first, but in future if you just want to
idle the iommu withouth freeing, these are needed to debug.
BTW, the next patch in the series: ARM: OMAP: iommu: pm runtime save
and restore context, let's you do a pm_runtime_[enable|put] through
save/restore ctx functions, which is just for compatibility on how isp
code uses the save and restore code.
>> @@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
>> release_mem_region(res->start, resource_size(res));
>> iounmap(obj->regbase);
>>
>> - clk_put(obj->clk);
>> + pm_runtime_disable(obj->dev);
>
> This will turn on the device unnecessarily, wasting power, and there's
> no need for that, kfree will take care of that without resuming.
Left aside the aesthetics of having balanced calls, the device will be
enabled if there was a pending resume to be executed, otherwise it
won't, kfree won't increment the disable_depth counter and I don't
think that freeing the pointer is enough reason to ignore
pm_runtime_disable.
> Also, I still think that something like this is needed:
...
> +static struct clk cam_fck = {
> + .name = "cam_fck",
> + .ops = &clkops_omap2_iclk_dflt,
> + .parent = &l3_ick,
> + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
a cam_fck name to enable the ick?
Cheers,
Omar
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
2012-10-12 17:46 ` Omar Ramirez Luna
@ 2012-10-12 21:25 ` Felipe Contreras
2012-10-16 1:29 ` Omar Ramirez Luna
0 siblings, 1 reply; 22+ messages in thread
From: Felipe Contreras @ 2012-10-12 21:25 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Oct 12, 2012 at 7:46 PM, Omar Ramirez Luna <omar.luna@linaro.org> wrote:
> On 12 October 2012 02:48, Felipe Contreras <felipe.contreras@gmail.com> wrote:
>> I already made most of these comments, but here they go again.
>
> I replied to all, but here it goes again:
Mostly, but not all :)
>>> @@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
>>> }
>>> }
>>>
>>> - clk_enable(obj->clk);
>>> + pm_runtime_get_sync(obj->dev);
>>>
>>> err = arch_iommu->enable(obj);
>>>
>>> - clk_disable(obj->clk);
>>
>> The device will never go to sleep, until iommu_disable is called.
>> clk_enable -> pm_runtime_get_sync, clk_disable pm_runtime_put.
>
> Which is what you want... why would you want your iommu to be disabled
> if the client of that iommu could request a translation?
That's the whole point of *dynamic* pm; _when_ the client wants to
request a translation, _then_ the device is waken up, which is what I
believe the code currently does.
After your patch, even if I don't use the camera, or the DSP, the
iommu devices will be enabled, and will be consuming energy *all the
time*. Which I don't think is what we want.
I'm not saying I have a solution, I'm simply saying that's what's
going to happen if I'm correct.
> Remember that these iommus, sit along of other processors not on the
> main processor side. So, this code should enable it for the other
> processor to use, and there is no point where the processor can say
> "I'm not using it, shut it down" or "I'm using it, turn it on" in the
> middle of execution, other than suspend/resume and if supported,
> autosuspend.
I understand, but perhaps there should be?
>>> @@ -288,7 +285,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
>>> if (!obj || !obj->nr_tlb_entries || !e)
>>> return -EINVAL;
>>>
>>> - clk_enable(obj->clk);
>>> + pm_runtime_get_sync(obj->dev);
>>>
>>> iotlb_lock_get(obj, &l);
>>> if (l.base == obj->nr_tlb_entries) {
>>> @@ -318,7 +315,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
>>>
>>> cr = iotlb_alloc_cr(obj, e);
>>> if (IS_ERR(cr)) {
>>> - clk_disable(obj->clk);
>>> + pm_runtime_put_sync(obj->dev);
>>> return PTR_ERR(cr);
>>> }
>>
>> If I'm correct, the above pm_runtime_get/put are redundant, because
>> the count can't possibly reach 0 because of the reason I explained
>> before.
>>
>> The same for all the cases below.
>
> You can access this paths through debugfs, some of them doesn't work
> if the module is not enabled first, but in future if you just want to
> idle the iommu withouth freeing, these are needed to debug.
>
> BTW, the next patch in the series: ARM: OMAP: iommu: pm runtime save
> and restore context, let's you do a pm_runtime_[enable|put] through
> save/restore ctx functions, which is just for compatibility on how isp
> code uses the save and restore code.
All right, it has been some time since I've touched pm code, so if you say so.
>>> @@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
>>> release_mem_region(res->start, resource_size(res));
>>> iounmap(obj->regbase);
>>>
>>> - clk_put(obj->clk);
>>> + pm_runtime_disable(obj->dev);
>>
>> This will turn on the device unnecessarily, wasting power, and there's
>> no need for that, kfree will take care of that without resuming.
>
> Left aside the aesthetics of having balanced calls, the device will be
> enabled if there was a pending resume to be executed, otherwise it
> won't, kfree won't increment the disable_depth counter and I don't
> think that freeing the pointer is enough reason to ignore
> pm_runtime_disable.
You are doing __pm_runtime_disable(dev, true), kfree will do
__pm_runtime_disable(dev, false), which is what we want. Both will
decrement the disable_depth.
But at least you agree that there's a chance that the device will be waken up.
>> Also, I still think that something like this is needed:
> ...
>> +static struct clk cam_fck = {
>> + .name = "cam_fck",
>> + .ops = &clkops_omap2_iclk_dflt,
>> + .parent = &l3_ick,
>> + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
>
> a cam_fck name to enable the ick?
Yeap, according to the TRM. Take a look at 12.3 Camera ISP Integration
Fig 12-50.
Cheers.
--
Felipe Contreras
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
2012-10-12 21:25 ` Felipe Contreras
@ 2012-10-16 1:29 ` Omar Ramirez Luna
2012-10-16 3:23 ` Felipe Contreras
0 siblings, 1 reply; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-16 1:29 UTC (permalink / raw)
To: linux-arm-kernel
Hi Felipe,
On 12 October 2012 16:25, Felipe Contreras <felipe.contreras@gmail.com> wrote:
>>>> @@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
>>>> }
>>>> }
>>>>
>>>> - clk_enable(obj->clk);
>>>> + pm_runtime_get_sync(obj->dev);
>>>>
>>>> err = arch_iommu->enable(obj);
>>>>
>>>> - clk_disable(obj->clk);
>>>
>>> The device will never go to sleep, until iommu_disable is called.
>>> clk_enable -> pm_runtime_get_sync, clk_disable pm_runtime_put.
>>
>> Which is what you want... why would you want your iommu to be disabled
>> if the client of that iommu could request a translation?
>
> That's the whole point of *dynamic* pm; _when_ the client wants to
> request a translation, _then_ the device is waken up, which is what I
> believe the code currently does.
No it doesn't, current code is working because the processor and the
iommu share the same clock, so enabling the processor is implicitly
guaranteeing that the iommu will be enabled. IMHO, there shouldn't be
such assumption that you can control both with the same clock.
So, once the remote processor is enabled, any "dynamic pm" from iommu
with current code has no effect because the clock was already enabled
for the processor.
> After your patch, even if I don't use the camera, or the DSP, the
> iommu devices will be enabled, and will be consuming energy *all the
> time*. Which I don't think is what we want.
Wrong, the iommu device will be enabled by pm_runtime_get_sync once
you decide to attach with iommu_attach_device, if you do not use
camera or the dsp, you won't turn ON the iommus.
On probe this patch does pm_runtime_enable, however this doesn't mean
the device is turned ON or resumed or kept ON all the time.
> I'm not saying I have a solution, I'm simply saying that's what's
> going to happen if I'm correct.
Ok, but that is not what happens here.
>> Remember that these iommus, sit along of other processors not on the
>> main processor side. So, this code should enable it for the other
>> processor to use, and there is no point where the processor can say
>> "I'm not using it, shut it down" or "I'm using it, turn it on" in the
>> middle of execution, other than suspend/resume and if supported,
>> autosuspend.
>
> I understand, but perhaps there should be?
Autosuspend is a feature missing and should handle the scenario where
the remote processor can sleep dynamically, this scenario should turn
off the iommu and the remote processor itself when there is no
workload but it depends on the remote processor activity not the iommu
activity.
>>>> @@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
>>>> release_mem_region(res->start, resource_size(res));
>>>> iounmap(obj->regbase);
>>>>
>>>> - clk_put(obj->clk);
>>>> + pm_runtime_disable(obj->dev);
>>>
>>> This will turn on the device unnecessarily, wasting power, and there's
>>> no need for that, kfree will take care of that without resuming.
>>
>> Left aside the aesthetics of having balanced calls, the device will be
>> enabled if there was a pending resume to be executed, otherwise it
>> won't, kfree won't increment the disable_depth counter and I don't
>> think that freeing the pointer is enough reason to ignore
>> pm_runtime_disable.
>
> You are doing __pm_runtime_disable(dev, true), kfree will do
> __pm_runtime_disable(dev, false), which is what we want. Both will
> decrement the disable_depth.
I'm quite confused here, could you please point me to the kfree snip
that does __pm_runtime_disable(dev, false)?
> But at least you agree that there's a chance that the device will be waken up.
Of course, if there is a pending resume to be executed, it must honor
that resume request and then turn off the device before removing the
iommu, IMHO.
>>> Also, I still think that something like this is needed:
>> ...
>>> +static struct clk cam_fck = {
>>> + .name = "cam_fck",
>>> + .ops = &clkops_omap2_iclk_dflt,
>>> + .parent = &l3_ick,
>>> + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
>>
>> a cam_fck name to enable the ick?
>
> Yeap, according to the TRM. Take a look at 12.3 Camera ISP Integration
> Fig 12-50.
What I meant is that, you are using the CM_ICLKEN to enable a clock
named "cam_fck" which has l3_ick as a parent. And that is not
consistent with what that register is meant to do, which is:
4.14.1.10 CAM_CM Registers
CM_ICKLEN_CAM
0x0: CAM_L3_ICK and CAM_L4_ICLK are disabled
0x1: CAM_L3_ICK and CAM_L4_ICLK are enabled
So, I'm complaining about the name "cam_fck", for an interface clock
with parent l3_ick. However I don't know why on section 12.3 they
refer to CAM_FCK to a l3_ick child clock.
Cheers,
Omar
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
2012-10-16 1:29 ` Omar Ramirez Luna
@ 2012-10-16 3:23 ` Felipe Contreras
2012-10-17 23:51 ` Omar Ramirez Luna
0 siblings, 1 reply; 22+ messages in thread
From: Felipe Contreras @ 2012-10-16 3:23 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
On Tue, Oct 16, 2012 at 3:29 AM, Omar Ramirez Luna <omar.luna@linaro.org> wrote:
>> After your patch, even if I don't use the camera, or the DSP, the
>> iommu devices will be enabled, and will be consuming energy *all the
>> time*. Which I don't think is what we want.
>
> Wrong, the iommu device will be enabled by pm_runtime_get_sync once
> you decide to attach with iommu_attach_device, if you do not use
> camera or the dsp, you won't turn ON the iommus.
I see, somehow I conflated the two functions.
> On probe this patch does pm_runtime_enable, however this doesn't mean
> the device is turned ON or resumed or kept ON all the time.
In fact it's the other way around; pm_runtime_enable turns off the
power (if it's ON).
>>>>> @@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
>>>>> release_mem_region(res->start, resource_size(res));
>>>>> iounmap(obj->regbase);
>>>>>
>>>>> - clk_put(obj->clk);
>>>>> + pm_runtime_disable(obj->dev);
>>>>
>>>> This will turn on the device unnecessarily, wasting power, and there's
>>>> no need for that, kfree will take care of that without resuming.
>>>
>>> Left aside the aesthetics of having balanced calls, the device will be
>>> enabled if there was a pending resume to be executed, otherwise it
>>> won't, kfree won't increment the disable_depth counter and I don't
>>> think that freeing the pointer is enough reason to ignore
>>> pm_runtime_disable.
>>
>> You are doing __pm_runtime_disable(dev, true), kfree will do
>> __pm_runtime_disable(dev, false), which is what we want. Both will
>> decrement the disable_depth.
>
> I'm quite confused here, could you please point me to the kfree snip
> that does __pm_runtime_disable(dev, false)?
Sorry, not kfree, but the device removal process:
device_del
device_pm_remove
pm_runtime_remove
__pm_runtime_disable <- HERE
bus_remove_device
device_release_driver
__device_release_driver
.remove => platform_drv_remove
.remove => omap_iommu_remove
Actually, it seems the pm is disabled _before_ omap_iommu_remove is
even called, so it's a no-op.
>> But at least you agree that there's a chance that the device will be waken up.
>
> Of course, if there is a pending resume to be executed, it must honor
> that resume request and then turn off the device before removing the
> iommu, IMHO.
Who will turn off the device afterwards?
>>>> Also, I still think that something like this is needed:
>>> ...
>>>> +static struct clk cam_fck = {
>>>> + .name = "cam_fck",
>>>> + .ops = &clkops_omap2_iclk_dflt,
>>>> + .parent = &l3_ick,
>>>> + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
>>>
>>> a cam_fck name to enable the ick?
>>
>> Yeap, according to the TRM. Take a look at 12.3 Camera ISP Integration
>> Fig 12-50.
>
> What I meant is that, you are using the CM_ICLKEN to enable a clock
> named "cam_fck" which has l3_ick as a parent. And that is not
> consistent with what that register is meant to do, which is:
>
> 4.14.1.10 CAM_CM Registers
>
> CM_ICKLEN_CAM
> 0x0: CAM_L3_ICK and CAM_L4_ICLK are disabled
> 0x1: CAM_L3_ICK and CAM_L4_ICLK are enabled
>
> So, I'm complaining about the name "cam_fck", for an interface clock
> with parent l3_ick. However I don't know why on section 12.3 they
> refer to CAM_FCK to a l3_ick child clock.
Because it's also used as a functional clock. Anyway, I don't care
much about the name of the clock, what is clear is that there's a link
missing to the l3_ick.
Cheers.
--
Felipe Contreras
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
` (9 preceding siblings ...)
2012-10-12 1:06 ` [PATCH v3 6/6] arm/dts: OMAP3/4: Add iommu nodes Omar Ramirez Luna
@ 2012-10-16 17:22 ` Tony Lindgren
2012-10-17 23:52 ` Omar Ramirez Luna
10 siblings, 1 reply; 22+ messages in thread
From: Tony Lindgren @ 2012-10-16 17:22 UTC (permalink / raw)
To: linux-arm-kernel
* Omar Ramirez Luna <omar.luna@linaro.org> [121011 18:07]:
> These patches are needed for remoteproc to work on OMAP4.
>
> Introduced iommu hwmod support for OMAP3 (iva, isp) and
> OMAP4 (ipu, dsp), along with the corresponding runtime PM
> and routines to deassert reset lines, enable/disable clocks
> and configure sysc registers.
>
> Although IOMMU hwmod patches were already submitted in the past,
> this series adds few more changes, like:
> - New reset handling.
> - Save and restore context code rework.
> - Device tree bindings for OMAP3 and OMAP4.
>
> For this series I just dropped the patches already included in
> mainline.
These will need to be rebased on omap-for-v3.8/cleanup-headers-iommu
when I have that pushed out as that removes plat/*iommu*.h files.
Regards,
Tony
> Previous work can be found at:
> [v2]
> http://www.mail-archive.com/linux-omap at vger.kernel.org/msg75701.html
> [v1]
> http://www.mail-archive.com/linux-omap at vger.kernel.org/msg70447.html
>
> [old iteration without reset, save/restore and device tree]
> http://www.mail-archive.com/linux-omap at vger.kernel.org/msg60133.html
>
> Omar Ramirez Luna (6):
> ARM: OMAP3/4: iommu: migrate to hwmod framework
> ARM: OMAP3/4: iommu: adapt to runtime pm
> ARM: OMAP: iommu: pm runtime save and restore context
> ARM: OMAP: iommu: optimize save and restore routines
> ARM: OMAP: iommu: add device tree support
> arm/dts: OMAP3/4: Add iommu nodes
>
> .../devicetree/bindings/arm/omap/iommu.txt | 10 ++
> arch/arm/boot/dts/omap3.dtsi | 12 +-
> arch/arm/boot/dts/omap4.dtsi | 17 +-
> arch/arm/mach-omap2/devices.c | 2 +-
> arch/arm/mach-omap2/iommu2.c | 74 ++------
> arch/arm/mach-omap2/omap-iommu.c | 176 +++++---------------
> arch/arm/plat-omap/include/plat/iommu.h | 20 ++-
> arch/arm/plat-omap/include/plat/iommu2.h | 4 -
> drivers/iommu/omap-iommu.c | 163 ++++++++++++++----
> 9 files changed, 245 insertions(+), 233 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/omap/iommu.txt
>
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
2012-10-16 3:23 ` Felipe Contreras
@ 2012-10-17 23:51 ` Omar Ramirez Luna
2012-10-18 4:03 ` Felipe Contreras
0 siblings, 1 reply; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-17 23:51 UTC (permalink / raw)
To: linux-arm-kernel
On 15 October 2012 22:23, Felipe Contreras <felipe.contreras@gmail.com> wrote:
>> On probe this patch does pm_runtime_enable, however this doesn't mean
>> the device is turned ON or resumed or kept ON all the time.
>
> In fact it's the other way around; pm_runtime_enable turns off the
> power (if it's ON).
pm_runtime_enable just decrements the disable_depth counter. Doesn't
turn off anything by itself.
>>>>>> @@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
>>>>>> release_mem_region(res->start, resource_size(res));
>>>>>> iounmap(obj->regbase);
>>>>>>
>>>>>> - clk_put(obj->clk);
>>>>>> + pm_runtime_disable(obj->dev);
>>>>>
>>>>> This will turn on the device unnecessarily, wasting power, and there's
>>>>> no need for that, kfree will take care of that without resuming.
>>>>
>>>> Left aside the aesthetics of having balanced calls, the device will be
>>>> enabled if there was a pending resume to be executed, otherwise it
>>>> won't, kfree won't increment the disable_depth counter and I don't
>>>> think that freeing the pointer is enough reason to ignore
>>>> pm_runtime_disable.
>>>
>>> You are doing __pm_runtime_disable(dev, true), kfree will do
>>> __pm_runtime_disable(dev, false), which is what we want. Both will
>>> decrement the disable_depth.
>>
>> I'm quite confused here, could you please point me to the kfree snip
>> that does __pm_runtime_disable(dev, false)?
>
> Sorry, not kfree, but the device removal process:
>
> device_del
> device_pm_remove
> pm_runtime_remove
> __pm_runtime_disable <- HERE
I'm not entirely convinced _iommu_ follows this path, it doesn't
create any devices nor register them... whereas mailbox does create
devices and mailbox does follow this path for the devices created
which are child devices.
So this path won't take care of the omap-iommu device pm_runtime_disable.
>>> But at least you agree that there's a chance that the device will be waken up.
>>
>> Of course, if there is a pending resume to be executed, it must honor
>> that resume request and then turn off the device before removing the
>> iommu, IMHO.
>
> Who will turn off the device afterwards?
What I meant is that omap_iommu_detach should turn off the device
before removing the iommu.
Cheers,
Omar
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM
2012-10-16 17:22 ` [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Tony Lindgren
@ 2012-10-17 23:52 ` Omar Ramirez Luna
2012-10-18 23:52 ` Tony Lindgren
0 siblings, 1 reply; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-17 23:52 UTC (permalink / raw)
To: linux-arm-kernel
On 16 October 2012 12:22, Tony Lindgren <tony@atomide.com> wrote:
> * Omar Ramirez Luna <omar.luna@linaro.org> [121011 18:07]:
>> These patches are needed for remoteproc to work on OMAP4.
>>
>> Introduced iommu hwmod support for OMAP3 (iva, isp) and
>> OMAP4 (ipu, dsp), along with the corresponding runtime PM
>> and routines to deassert reset lines, enable/disable clocks
>> and configure sysc registers.
>>
>> Although IOMMU hwmod patches were already submitted in the past,
>> this series adds few more changes, like:
>> - New reset handling.
>> - Save and restore context code rework.
>> - Device tree bindings for OMAP3 and OMAP4.
>>
>> For this series I just dropped the patches already included in
>> mainline.
>
> These will need to be rebased on omap-for-v3.8/cleanup-headers-iommu
> when I have that pushed out as that removes plat/*iommu*.h files.
Ok, will wait and rebase on top of it.
Thanks,
Omar
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
2012-10-17 23:51 ` Omar Ramirez Luna
@ 2012-10-18 4:03 ` Felipe Contreras
0 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-10-18 4:03 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Oct 18, 2012 at 1:51 AM, Omar Ramirez Luna <omar.luna@linaro.org> wrote:
> On 15 October 2012 22:23, Felipe Contreras <felipe.contreras@gmail.com> wrote:
>>> On probe this patch does pm_runtime_enable, however this doesn't mean
>>> the device is turned ON or resumed or kept ON all the time.
>>
>> In fact it's the other way around; pm_runtime_enable turns off the
>> power (if it's ON).
>
> pm_runtime_enable just decrements the disable_depth counter. Doesn't
> turn off anything by itself.
pm_runtime_enable turns on power management, without it the device
remains in whatever state it booted.
>> device_del
>> device_pm_remove
>> pm_runtime_remove
>> __pm_runtime_disable <- HERE
>
> I'm not entirely convinced _iommu_ follows this path, it doesn't
> create any devices nor register them... whereas mailbox does create
> devices and mailbox does follow this path for the devices created
> which are child devices.
>
> So this path won't take care of the omap-iommu device pm_runtime_disable.
Are you sure? What code-path calls omap_iommu_remove then?
Anyway, it was just an observation. I've seen other code do this.
--
Felipe Contreras
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM
2012-10-17 23:52 ` Omar Ramirez Luna
@ 2012-10-18 23:52 ` Tony Lindgren
2012-10-19 16:37 ` Omar Ramirez Luna
0 siblings, 1 reply; 22+ messages in thread
From: Tony Lindgren @ 2012-10-18 23:52 UTC (permalink / raw)
To: linux-arm-kernel
Omar,
* Omar Ramirez Luna <omar.luna@linaro.org> [121017 16:54]:
> On 16 October 2012 12:22, Tony Lindgren <tony@atomide.com> wrote:
>
> > These will need to be rebased on omap-for-v3.8/cleanup-headers-iommu
> > when I have that pushed out as that removes plat/*iommu*.h files.
>
> Ok, will wait and rebase on top of it.
Thanks, the related patches are now posted in thread
"[PATCH v3 0/6] omap iommu changes to remove plat includes".
Also, can you please take a look at the "Updated status of the removal
of plat headers" thread?
I've tagged you to remove the omap plat/mailbox.h :)
Regards,
Tony
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM
2012-10-18 23:52 ` Tony Lindgren
@ 2012-10-19 16:37 ` Omar Ramirez Luna
0 siblings, 0 replies; 22+ messages in thread
From: Omar Ramirez Luna @ 2012-10-19 16:37 UTC (permalink / raw)
To: linux-arm-kernel
Tony,
On 18 October 2012 18:52, Tony Lindgren <tony@atomide.com> wrote:
> Thanks, the related patches are now posted in thread
> "[PATCH v3 0/6] omap iommu changes to remove plat includes".
Ok.
> Also, can you please take a look at the "Updated status of the removal
> of plat headers" thread?
>
> I've tagged you to remove the omap plat/mailbox.h :)
Yes, got the request from Benoit too, but just now had the time to look at it.
Cheers,
Omar
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2012-10-19 16:37 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-12 1:06 [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 1/6] ARM: OMAP3/4: iommu: migrate to hwmod framework Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
2012-10-12 7:48 ` Felipe Contreras
2012-10-12 17:46 ` Omar Ramirez Luna
2012-10-12 21:25 ` Felipe Contreras
2012-10-16 1:29 ` Omar Ramirez Luna
2012-10-16 3:23 ` Felipe Contreras
2012-10-17 23:51 ` Omar Ramirez Luna
2012-10-18 4:03 ` Felipe Contreras
2012-10-12 1:06 ` [PATCH v3 3/6] ARM: OMAP: iommu: pm runtime save and restore context Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 4/6] ARM: OMAP: iommu: optimize save and restore routines Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH " Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 5/6] ARM: OMAP: iommu: add device tree support Omar Ramirez Luna
2012-10-12 1:06 ` [PATCH v3 6/6] arm/dts: OMAP3/4: Add iommu nodes Omar Ramirez Luna
2012-10-16 17:22 ` [PATCH v3 0/6] OMAP: iommu: hwmod, reset handling and runtime PM Tony Lindgren
2012-10-17 23:52 ` Omar Ramirez Luna
2012-10-18 23:52 ` Tony Lindgren
2012-10-19 16:37 ` Omar Ramirez Luna
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).